[1/2] mtd: spi-nor: create/Export parameter softwareseq for intel-spi driver to user
diff mbox series

Message ID 20200518175930.10948-1-danielwa@cisco.com
State New, archived
Headers show
Series
  • [1/2] mtd: spi-nor: create/Export parameter softwareseq for intel-spi driver to user
Related show

Commit Message

Daniel Walker May 18, 2020, 5:59 p.m. UTC
From: Bobby Liu <bobbliu@cisco.com>

How to use:
append softwareseq=1 while probe the driver.
example:
modprobe intel-spi writeable=1 softwareseq=1
it will let driver use software sequence to write register for opt=EN4B
by default it's 0 if not specified, driver will do usual HW cycle

Why this parameter is posted to user:
Intel PCH provides two groups of registers for SPI flash operation,
Hard Sequence registers and Software Sequence registers,
corresponding to intel_spi_hw_cycle() and intel_spi_sw_cycle()
respectively in driver code. But HW sequence register won't send EN4B
opcode to SPI flash. BIOS code use SW register to send EN4B.

On some Cisco routers, two 32M SPI flashes, which require 4-byte address mode enabled,
are physically connected to an FPGA, one flash is active and one is inactive.
When we do BIOS upgrade, we need switch to the inactive one,
but unfortunately, this one is still 3-byte address mode as default,
after we do real-time switch, we need reload SPI driver to send EN4B code to
enable 4-byte address mode.

Refering to our BIOS code, Software sequence register is processed
while sending EN4B opcode. So here we use sw_cycle in driver for EN4B as well.

Why I don't just easily use software sequence for all:
1.It will impact all flash operation, include flash W/R, high risk
2.The only SPI type I can use is INTEL_SPI_BXT according to datasheet,
  this will require using hw seq.
  I tried to specify other SPI type, it couldn't work with Intel PCH.
  If I force SW seq for all, during boot up, sw_cycle fails to read
  vendor ID.

In conclusion, I only use SW cycle for EN4B opcode to minimize impact.
It won't impact other users as well.

Why the default flash can work at 4-byte address mode:
BIOS sets 4-byte address mode for the current active SPI flash with SW seq registers.
So we don't need append softwareseq=1 for normal boot up script,
it will only be used in BIOS upgrade script.

Cc: xe-linux-external@cisco.com
Signed-off-by: Bobby Liu <bobbliu@cisco.com>
[ danielwa: edited the commit message a little. ]
Signed-off-by: Daniel Walker <danielwa@cisco.com>
---
 drivers/mtd/spi-nor/controllers/intel-spi.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Comments

Vignesh Raghavendra May 28, 2020, 10:46 a.m. UTC | #1
+Mika Westerberg original author of the driver

On 18/05/20 11:29 pm, Daniel Walker wrote:
> From: Bobby Liu <bobbliu@cisco.com>
> 
> How to use:
> append softwareseq=1 while probe the driver.
> example:
> modprobe intel-spi writeable=1 softwareseq=1
> it will let driver use software sequence to write register for opt=EN4B
> by default it's 0 if not specified, driver will do usual HW cycle
> 

Could some one from Intel please review this patch?

Regards
Vignesh

> Why this parameter is posted to user:
> Intel PCH provides two groups of registers for SPI flash operation,
> Hard Sequence registers and Software Sequence registers,
> corresponding to intel_spi_hw_cycle() and intel_spi_sw_cycle()
> respectively in driver code. But HW sequence register won't send EN4B
> opcode to SPI flash. BIOS code use SW register to send EN4B.
> 
> On some Cisco routers, two 32M SPI flashes, which require 4-byte address mode enabled,
> are physically connected to an FPGA, one flash is active and one is inactive.
> When we do BIOS upgrade, we need switch to the inactive one,
> but unfortunately, this one is still 3-byte address mode as default,
> after we do real-time switch, we need reload SPI driver to send EN4B code to
> enable 4-byte address mode.
> 
> Refering to our BIOS code, Software sequence register is processed
> while sending EN4B opcode. So here we use sw_cycle in driver for EN4B as well.
> 
> Why I don't just easily use software sequence for all:
> 1.It will impact all flash operation, include flash W/R, high risk
> 2.The only SPI type I can use is INTEL_SPI_BXT according to datasheet,
>   this will require using hw seq.
>   I tried to specify other SPI type, it couldn't work with Intel PCH.
>   If I force SW seq for all, during boot up, sw_cycle fails to read
>   vendor ID.
> 
> In conclusion, I only use SW cycle for EN4B opcode to minimize impact.
> It won't impact other users as well.
> 
> Why the default flash can work at 4-byte address mode:
> BIOS sets 4-byte address mode for the current active SPI flash with SW seq registers.
> So we don't need append softwareseq=1 for normal boot up script,
> it will only be used in BIOS upgrade script.
> 
> Cc: xe-linux-external@cisco.com
> Signed-off-by: Bobby Liu <bobbliu@cisco.com>
> [ danielwa: edited the commit message a little. ]
> Signed-off-by: Daniel Walker <danielwa@cisco.com>
> ---
>  drivers/mtd/spi-nor/controllers/intel-spi.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
> index 61d2a0ad2131..e5a3d51a2e4d 100644
> --- a/drivers/mtd/spi-nor/controllers/intel-spi.c
> +++ b/drivers/mtd/spi-nor/controllers/intel-spi.c
> @@ -163,6 +163,10 @@ static bool writeable;
>  module_param(writeable, bool, 0);
>  MODULE_PARM_DESC(writeable, "Enable write access to SPI flash chip (default=0)");
>  
> +static bool softwareseq;
> +module_param(softwareseq, bool, 0);
> +MODULE_PARM_DESC(softwareseq, "Use software sequence for register write (default=0)");
> +
>  static void intel_spi_dump_regs(struct intel_spi *ispi)
>  {
>  	u32 value;
> @@ -619,6 +623,18 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
>  	if (ret)
>  		return ret;
>  
> +	/*
> +	 * Intel Skylake will not send EN4B to SPI flash if we use HW sequence
> +	 * Here export one interface "softwareseq" to OS,
> +	 * let driver user decide if use SW sequence or not
> +	 */
> +	if (opcode == SPINOR_OP_EN4B && softwareseq) {
> +	    dev_info(ispi->dev,
> +		"Write register opcode is SPINOR_OP_EN4B, do SW cycle\n");
> +	    return intel_spi_sw_cycle(ispi, opcode, len,
> +		OPTYPE_WRITE_NO_ADDR);
> +	}
> +
>  	if (ispi->swseq_reg)
>  		return intel_spi_sw_cycle(ispi, opcode, len,
>  					  OPTYPE_WRITE_NO_ADDR);
>
Mika Westerberg May 29, 2020, 5:36 a.m. UTC | #2
Hi,

I wonder if we can "generalize" this a bit and use SW sequencer to run
commands HW sequencer does not support? The BIOS can then setup the
allowed SW sequencer opcodes and lock the thing down if needed.

There are couple of other commands related to FSR register where this
could be useful.

On Thu, May 28, 2020 at 04:16:38PM +0530, Vignesh Raghavendra wrote:
> +Mika Westerberg original author of the driver
> 
> On 18/05/20 11:29 pm, Daniel Walker wrote:
> > From: Bobby Liu <bobbliu@cisco.com>
> > 
> > How to use:
> > append softwareseq=1 while probe the driver.
> > example:
> > modprobe intel-spi writeable=1 softwareseq=1
> > it will let driver use software sequence to write register for opt=EN4B
> > by default it's 0 if not specified, driver will do usual HW cycle
> > 
> 
> Could some one from Intel please review this patch?
> 
> Regards
> Vignesh
> 
> > Why this parameter is posted to user:
> > Intel PCH provides two groups of registers for SPI flash operation,
> > Hard Sequence registers and Software Sequence registers,
> > corresponding to intel_spi_hw_cycle() and intel_spi_sw_cycle()
> > respectively in driver code. But HW sequence register won't send EN4B
> > opcode to SPI flash. BIOS code use SW register to send EN4B.
> > 
> > On some Cisco routers, two 32M SPI flashes, which require 4-byte address mode enabled,
> > are physically connected to an FPGA, one flash is active and one is inactive.
> > When we do BIOS upgrade, we need switch to the inactive one,
> > but unfortunately, this one is still 3-byte address mode as default,
> > after we do real-time switch, we need reload SPI driver to send EN4B code to
> > enable 4-byte address mode.
> > 
> > Refering to our BIOS code, Software sequence register is processed
> > while sending EN4B opcode. So here we use sw_cycle in driver for EN4B as well.
> > 
> > Why I don't just easily use software sequence for all:
> > 1.It will impact all flash operation, include flash W/R, high risk
> > 2.The only SPI type I can use is INTEL_SPI_BXT according to datasheet,
> >   this will require using hw seq.
> >   I tried to specify other SPI type, it couldn't work with Intel PCH.
> >   If I force SW seq for all, during boot up, sw_cycle fails to read
> >   vendor ID.
> > 
> > In conclusion, I only use SW cycle for EN4B opcode to minimize impact.
> > It won't impact other users as well.
> > 
> > Why the default flash can work at 4-byte address mode:
> > BIOS sets 4-byte address mode for the current active SPI flash with SW seq registers.
> > So we don't need append softwareseq=1 for normal boot up script,
> > it will only be used in BIOS upgrade script.
> > 
> > Cc: xe-linux-external@cisco.com
> > Signed-off-by: Bobby Liu <bobbliu@cisco.com>
> > [ danielwa: edited the commit message a little. ]
> > Signed-off-by: Daniel Walker <danielwa@cisco.com>
> > ---
> >  drivers/mtd/spi-nor/controllers/intel-spi.c | 16 ++++++++++++++++
> >  1 file changed, 16 insertions(+)
> > 
> > diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
> > index 61d2a0ad2131..e5a3d51a2e4d 100644
> > --- a/drivers/mtd/spi-nor/controllers/intel-spi.c
> > +++ b/drivers/mtd/spi-nor/controllers/intel-spi.c
> > @@ -163,6 +163,10 @@ static bool writeable;
> >  module_param(writeable, bool, 0);
> >  MODULE_PARM_DESC(writeable, "Enable write access to SPI flash chip (default=0)");
> >  
> > +static bool softwareseq;
> > +module_param(softwareseq, bool, 0);
> > +MODULE_PARM_DESC(softwareseq, "Use software sequence for register write (default=0)");
> > +
> >  static void intel_spi_dump_regs(struct intel_spi *ispi)
> >  {
> >  	u32 value;
> > @@ -619,6 +623,18 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
> >  	if (ret)
> >  		return ret;
> >  
> > +	/*
> > +	 * Intel Skylake will not send EN4B to SPI flash if we use HW sequence
> > +	 * Here export one interface "softwareseq" to OS,
> > +	 * let driver user decide if use SW sequence or not
> > +	 */
> > +	if (opcode == SPINOR_OP_EN4B && softwareseq) {
> > +	    dev_info(ispi->dev,
> > +		"Write register opcode is SPINOR_OP_EN4B, do SW cycle\n");
> > +	    return intel_spi_sw_cycle(ispi, opcode, len,
> > +		OPTYPE_WRITE_NO_ADDR);
> > +	}
> > +
> >  	if (ispi->swseq_reg)
> >  		return intel_spi_sw_cycle(ispi, opcode, len,
> >  					  OPTYPE_WRITE_NO_ADDR);
> >

Patch
diff mbox series

diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
index 61d2a0ad2131..e5a3d51a2e4d 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi.c
+++ b/drivers/mtd/spi-nor/controllers/intel-spi.c
@@ -163,6 +163,10 @@  static bool writeable;
 module_param(writeable, bool, 0);
 MODULE_PARM_DESC(writeable, "Enable write access to SPI flash chip (default=0)");
 
+static bool softwareseq;
+module_param(softwareseq, bool, 0);
+MODULE_PARM_DESC(softwareseq, "Use software sequence for register write (default=0)");
+
 static void intel_spi_dump_regs(struct intel_spi *ispi)
 {
 	u32 value;
@@ -619,6 +623,18 @@  static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
 	if (ret)
 		return ret;
 
+	/*
+	 * Intel Skylake will not send EN4B to SPI flash if we use HW sequence
+	 * Here export one interface "softwareseq" to OS,
+	 * let driver user decide if use SW sequence or not
+	 */
+	if (opcode == SPINOR_OP_EN4B && softwareseq) {
+	    dev_info(ispi->dev,
+		"Write register opcode is SPINOR_OP_EN4B, do SW cycle\n");
+	    return intel_spi_sw_cycle(ispi, opcode, len,
+		OPTYPE_WRITE_NO_ADDR);
+	}
+
 	if (ispi->swseq_reg)
 		return intel_spi_sw_cycle(ispi, opcode, len,
 					  OPTYPE_WRITE_NO_ADDR);