All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
@ 2018-02-05 11:32 Mika Westerberg
  2018-02-05 11:33 ` [PATCH v2 2/2] spi-nor: intel-spi: Explicitly mark the driver as dangerous in Kconfig Mika Westerberg
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Mika Westerberg @ 2018-02-05 11:32 UTC (permalink / raw)
  To: linux-mtd
  Cc: Cyrille Pitchen, Marek Vasut, David Woodhouse, Brian Norris,
	Boris Brezillon, Richard Weinberger, Anthony Wong, Bin Meng,
	Mika Westerberg

On many older systems using SW sequencer the PREOP_OPTYPE register
contains two preopcodes as following:

  PREOP_OPTYPE=0xf2785006

The last two bytes are the opcodes decoded to:

  0x50 - Write enable for volatile status register
  0x06 - Write enable

The former is used to modify volatile bits in the status register. For
non-volatile bits the latter is needed. Preopcodes are used in SW
sequencer to send one command "atomically" without anything else
interfering the transfer. The sequence that gets executed is:

  - Send preopcode (write enable) from PREOP_OPTYPE register
  - Send the actual SPI command
  - Poll busy bit in the status register (0x05, RDSR)

Commit 8c473dd61bb5 ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be
programmed by BIOS") enabled atomic sequence handling but because both
preopcodes are programmed, the following happens:

  if (preop >> 8)
  	val |= SSFSTS_CTL_SPOP;

Since on these systems preop >> 8 == 0x50 we end up picking volatile
write enable instead. Because of this the actual write command is pretty
much NOP unless there is a WREN latched in the chip already.

Furthermore we should not really just assume that WREN was issued in
previous call to intel_spi_write_reg() because that might not be the
case.

This updates driver to first check that the opcode is actually available
in PREOP_OPTYPE register and if not return error back to the spi-nor
core (if the controller is not locked we program it now). In addition we
save the opcode to ispi->atomic_preopcode field which is checked in next
call to intel_spi_sw_cycle() to actually enable atomic sequence using
the requested preopcode.

Fixes: 8c473dd61bb5 ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be programmed by BIOS")
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: stable@vger.kernel.org
---
Changes from v1:

  - Added atomic_preopcode field and only when it is set, enable atomic
    sequence.
  - Return -EINVAL if the requested WREN operation cannot be found from
    PREOP register instead of silently pretending it is supported.
  - Updated patch subject to match more closely what is being fixed.

 drivers/mtd/spi-nor/intel-spi.c | 76 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 67 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c
index 699951523179..8e98f4ab87c1 100644
--- a/drivers/mtd/spi-nor/intel-spi.c
+++ b/drivers/mtd/spi-nor/intel-spi.c
@@ -136,6 +136,7 @@
  * @swseq_reg: Use SW sequencer in register reads/writes
  * @swseq_erase: Use SW sequencer in erase operation
  * @erase_64k: 64k erase supported
+ * @atomic_preopcode: Holds preopcode when atomic sequence is requested
  * @opcodes: Opcodes which are supported. This are programmed by BIOS
  *           before it locks down the controller.
  */
@@ -153,6 +154,7 @@ struct intel_spi {
 	bool swseq_reg;
 	bool swseq_erase;
 	bool erase_64k;
+	u8 atomic_preopcode;
 	u8 opcodes[8];
 };
 
@@ -474,7 +476,7 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len,
 			      int optype)
 {
 	u32 val = 0, status;
-	u16 preop;
+	u8 atomic_preopcode;
 	int ret;
 
 	ret = intel_spi_opcode_index(ispi, opcode, optype);
@@ -484,17 +486,42 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len,
 	if (len > INTEL_SPI_FIFO_SZ)
 		return -EINVAL;
 
+	/*
+	 * Always clear it after each SW sequencer operation regardless
+	 * of whether it is successful or not.
+	 */
+	atomic_preopcode = ispi->atomic_preopcode;
+	ispi->atomic_preopcode = 0;
+
 	/* Only mark 'Data Cycle' bit when there is data to be transferred */
 	if (len > 0)
 		val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS;
 	val |= ret << SSFSTS_CTL_COP_SHIFT;
 	val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE;
 	val |= SSFSTS_CTL_SCGO;
-	preop = readw(ispi->sregs + PREOP_OPTYPE);
-	if (preop) {
-		val |= SSFSTS_CTL_ACS;
-		if (preop >> 8)
-			val |= SSFSTS_CTL_SPOP;
+	if (atomic_preopcode) {
+		u16 preop;
+
+		switch (optype) {
+		case OPTYPE_WRITE_NO_ADDR:
+		case OPTYPE_WRITE_WITH_ADDR:
+			/* Pick matching preopcode for the atomic sequence */
+			preop = readw(ispi->sregs + PREOP_OPTYPE);
+			if ((preop & 0xff) == atomic_preopcode)
+				; /* Do nothing */
+			else if ((preop >> 8) == atomic_preopcode)
+				val |= SSFSTS_CTL_SPOP;
+			else
+				return -EINVAL;
+
+			/* Enable atomic sequence */
+			val |= SSFSTS_CTL_ACS;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
 	}
 	writel(val, ispi->sregs + SSFSTS_CTL);
 
@@ -538,13 +565,31 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
 
 	/*
 	 * This is handled with atomic operation and preop code in Intel
-	 * controller so skip it here now. If the controller is not locked,
-	 * program the opcode to the PREOP register for later use.
+	 * controller so we only verify that it is available. If the
+	 * controller is not locked, program the opcode to the PREOP
+	 * register for later use.
+	 *
+	 * When hardware sequencer is used there is no need to program
+	 * any opcodes (it handles them automatically as part of a command).
 	 */
 	if (opcode == SPINOR_OP_WREN) {
-		if (!ispi->locked)
+		u16 preop;
+
+		if (!ispi->swseq_reg)
+			return 0;
+
+		preop = readw(ispi->sregs + PREOP_OPTYPE);
+		if ((preop & 0xff) != opcode && (preop >> 8) != opcode) {
+			if (ispi->locked)
+				return -EINVAL;
 			writel(opcode, ispi->sregs + PREOP_OPTYPE);
+		}
 
+		/*
+		 * This enables atomic sequence on next SW sycle. Will
+		 * be cleared after next operation.
+		 */
+		ispi->atomic_preopcode = opcode;
 		return 0;
 	}
 
@@ -569,6 +614,13 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 	u32 val, status;
 	ssize_t ret;
 
+	/*
+	 * Atomic sequence is not expected with HW sequencer reads. Make
+	 * sure it is cleared regardless.
+	 */
+	if (WARN_ON_ONCE(ispi->atomic_preopcode))
+		ispi->atomic_preopcode = 0;
+
 	switch (nor->read_opcode) {
 	case SPINOR_OP_READ:
 	case SPINOR_OP_READ_FAST:
@@ -627,6 +679,9 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
 	u32 val, status;
 	ssize_t ret;
 
+	/* Not needed with HW sequencer write, make sure it is cleared */
+	ispi->atomic_preopcode = 0;
+
 	while (len > 0) {
 		block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);
 
@@ -707,6 +762,9 @@ static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
 		return 0;
 	}
 
+	/* Not needed with HW sequencer erase, make sure it is cleared */
+	ispi->atomic_preopcode = 0;
+
 	while (len > 0) {
 		writel(offs, ispi->base + FADDR);
 
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] spi-nor: intel-spi: Explicitly mark the driver as dangerous in Kconfig
  2018-02-05 11:32 [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
@ 2018-02-05 11:33 ` Mika Westerberg
  2018-02-27 16:51 ` [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
  2018-05-18 20:01 ` Boris Brezillon
  2 siblings, 0 replies; 9+ messages in thread
From: Mika Westerberg @ 2018-02-05 11:33 UTC (permalink / raw)
  To: linux-mtd
  Cc: Cyrille Pitchen, Marek Vasut, David Woodhouse, Brian Norris,
	Boris Brezillon, Richard Weinberger, Anthony Wong, Bin Meng,
	Mika Westerberg

The driver is not meant for normal users at all but instead such users
who really know what they are doing and are able to build their own
kernel to enable it. Mark both driver Kconfig entries as dangerous to
make sure the driver is not accidentally enabled without understanding
possible consequences in doing so.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
No changes from v1.

 drivers/mtd/spi-nor/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 89da88e59121..f480b227a6b8 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -90,7 +90,7 @@ config SPI_INTEL_SPI
 	tristate
 
 config SPI_INTEL_SPI_PCI
-	tristate "Intel PCH/PCU SPI flash PCI driver"
+	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
 	depends on X86 && PCI
 	select SPI_INTEL_SPI
 	help
@@ -106,7 +106,7 @@ config SPI_INTEL_SPI_PCI
 	  will be called intel-spi-pci.
 
 config SPI_INTEL_SPI_PLATFORM
-	tristate "Intel PCH/PCU SPI flash platform driver"
+	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
 	depends on X86
 	select SPI_INTEL_SPI
 	help
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-02-05 11:32 [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
  2018-02-05 11:33 ` [PATCH v2 2/2] spi-nor: intel-spi: Explicitly mark the driver as dangerous in Kconfig Mika Westerberg
@ 2018-02-27 16:51 ` Mika Westerberg
  2018-04-03 13:48   ` Mika Westerberg
  2018-05-18 20:01 ` Boris Brezillon
  2 siblings, 1 reply; 9+ messages in thread
From: Mika Westerberg @ 2018-02-27 16:51 UTC (permalink / raw)
  To: linux-mtd
  Cc: Cyrille Pitchen, Marek Vasut, David Woodhouse, Brian Norris,
	Boris Brezillon, Richard Weinberger, Anthony Wong, Bin Meng

On Mon, Feb 05, 2018 at 02:32:59PM +0300, Mika Westerberg wrote:
> Changes from v1:
> 
>   - Added atomic_preopcode field and only when it is set, enable atomic
>     sequence.
>   - Return -EINVAL if the requested WREN operation cannot be found from
>     PREOP register instead of silently pretending it is supported.
>   - Updated patch subject to match more closely what is being fixed.

Any comments on these two? I did the changes Cyrille asked me to do.

Thanks!

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-02-27 16:51 ` [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
@ 2018-04-03 13:48   ` Mika Westerberg
  2018-04-04  8:21     ` Marek Vasut
  0 siblings, 1 reply; 9+ messages in thread
From: Mika Westerberg @ 2018-04-03 13:48 UTC (permalink / raw)
  To: linux-mtd
  Cc: Cyrille Pitchen, Marek Vasut, David Woodhouse, Brian Norris,
	Boris Brezillon, Richard Weinberger, Anthony Wong, Bin Meng

On Tue, Feb 27, 2018 at 06:51:42PM +0200, Mika Westerberg wrote:
> On Mon, Feb 05, 2018 at 02:32:59PM +0300, Mika Westerberg wrote:
> > Changes from v1:
> > 
> >   - Added atomic_preopcode field and only when it is set, enable atomic
> >     sequence.
> >   - Return -EINVAL if the requested WREN operation cannot be found from
> >     PREOP register instead of silently pretending it is supported.
> >   - Updated patch subject to match more closely what is being fixed.
> 
> Any comments on these two? I did the changes Cyrille asked me to do.

Ping. If no comments, could someone pick these up please.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-04-03 13:48   ` Mika Westerberg
@ 2018-04-04  8:21     ` Marek Vasut
  2018-04-04 19:22       ` Boris Brezillon
  0 siblings, 1 reply; 9+ messages in thread
From: Marek Vasut @ 2018-04-04  8:21 UTC (permalink / raw)
  To: Mika Westerberg, linux-mtd
  Cc: Cyrille Pitchen, David Woodhouse, Brian Norris, Boris Brezillon,
	Richard Weinberger, Anthony Wong, Bin Meng

On 04/03/2018 03:48 PM, Mika Westerberg wrote:
> On Tue, Feb 27, 2018 at 06:51:42PM +0200, Mika Westerberg wrote:
>> On Mon, Feb 05, 2018 at 02:32:59PM +0300, Mika Westerberg wrote:
>>> Changes from v1:
>>>
>>>   - Added atomic_preopcode field and only when it is set, enable atomic
>>>     sequence.
>>>   - Return -EINVAL if the requested WREN operation cannot be found from
>>>     PREOP register instead of silently pretending it is supported.
>>>   - Updated patch subject to match more closely what is being fixed.
>>
>> Any comments on these two? I did the changes Cyrille asked me to do.
> 
> Ping. If no comments, could someone pick these up please.
> 
Reviewed-by: Marek Vasut <marek.vasut@gmail.com>

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-04-04  8:21     ` Marek Vasut
@ 2018-04-04 19:22       ` Boris Brezillon
  2018-05-18  5:20         ` Mika Westerberg
  0 siblings, 1 reply; 9+ messages in thread
From: Boris Brezillon @ 2018-04-04 19:22 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Mika Westerberg, linux-mtd, Boris Brezillon, Bin Meng,
	Richard Weinberger, Anthony Wong, Cyrille Pitchen, Brian Norris,
	David Woodhouse

On Wed, 4 Apr 2018 10:21:45 +0200
Marek Vasut <marek.vasut@gmail.com> wrote:

> On 04/03/2018 03:48 PM, Mika Westerberg wrote:
> > On Tue, Feb 27, 2018 at 06:51:42PM +0200, Mika Westerberg wrote:  
> >> On Mon, Feb 05, 2018 at 02:32:59PM +0300, Mika Westerberg wrote:  
> >>> Changes from v1:
> >>>
> >>>   - Added atomic_preopcode field and only when it is set, enable atomic
> >>>     sequence.
> >>>   - Return -EINVAL if the requested WREN operation cannot be found from
> >>>     PREOP register instead of silently pretending it is supported.
> >>>   - Updated patch subject to match more closely what is being fixed.  
> >>
> >> Any comments on these two? I did the changes Cyrille asked me to do.  
> > 
> > Ping. If no comments, could someone pick these up please.
> >   
> Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
> 

Will queue this patches to mtd/fixes just after 4.17-rc1 is out. Sorry
for the huge delay.

Regards,

Boris

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-04-04 19:22       ` Boris Brezillon
@ 2018-05-18  5:20         ` Mika Westerberg
  2018-05-18  6:53           ` Boris Brezillon
  0 siblings, 1 reply; 9+ messages in thread
From: Mika Westerberg @ 2018-05-18  5:20 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Marek Vasut, linux-mtd, Boris Brezillon, Bin Meng,
	Richard Weinberger, Anthony Wong, Cyrille Pitchen, Brian Norris,
	David Woodhouse

On Wed, Apr 04, 2018 at 09:22:38PM +0200, Boris Brezillon wrote:
> On Wed, 4 Apr 2018 10:21:45 +0200
> Marek Vasut <marek.vasut@gmail.com> wrote:
> 
> > On 04/03/2018 03:48 PM, Mika Westerberg wrote:
> > > On Tue, Feb 27, 2018 at 06:51:42PM +0200, Mika Westerberg wrote:  
> > >> On Mon, Feb 05, 2018 at 02:32:59PM +0300, Mika Westerberg wrote:  
> > >>> Changes from v1:
> > >>>
> > >>>   - Added atomic_preopcode field and only when it is set, enable atomic
> > >>>     sequence.
> > >>>   - Return -EINVAL if the requested WREN operation cannot be found from
> > >>>     PREOP register instead of silently pretending it is supported.
> > >>>   - Updated patch subject to match more closely what is being fixed.  
> > >>
> > >> Any comments on these two? I did the changes Cyrille asked me to do.  
> > > 
> > > Ping. If no comments, could someone pick these up please.
> > >   
> > Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
> > 
> 
> Will queue this patches to mtd/fixes just after 4.17-rc1 is out. Sorry
> for the huge delay.

Hi,

Did these patches end up somewhere? I can't see them in current
v4.17-rc5.

Thanks!

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-05-18  5:20         ` Mika Westerberg
@ 2018-05-18  6:53           ` Boris Brezillon
  0 siblings, 0 replies; 9+ messages in thread
From: Boris Brezillon @ 2018-05-18  6:53 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Marek Vasut, linux-mtd, Boris Brezillon, Bin Meng,
	Richard Weinberger, Anthony Wong, Cyrille Pitchen, Brian Norris,
	David Woodhouse

On Fri, 18 May 2018 08:20:17 +0300
Mika Westerberg <mika.westerberg@linux.intel.com> wrote:

> On Wed, Apr 04, 2018 at 09:22:38PM +0200, Boris Brezillon wrote:
> > On Wed, 4 Apr 2018 10:21:45 +0200
> > Marek Vasut <marek.vasut@gmail.com> wrote:
> >   
> > > On 04/03/2018 03:48 PM, Mika Westerberg wrote:  
> > > > On Tue, Feb 27, 2018 at 06:51:42PM +0200, Mika Westerberg wrote:    
> > > >> On Mon, Feb 05, 2018 at 02:32:59PM +0300, Mika Westerberg wrote:    
> > > >>> Changes from v1:
> > > >>>
> > > >>>   - Added atomic_preopcode field and only when it is set, enable atomic
> > > >>>     sequence.
> > > >>>   - Return -EINVAL if the requested WREN operation cannot be found from
> > > >>>     PREOP register instead of silently pretending it is supported.
> > > >>>   - Updated patch subject to match more closely what is being fixed.    
> > > >>
> > > >> Any comments on these two? I did the changes Cyrille asked me to do.    
> > > > 
> > > > Ping. If no comments, could someone pick these up please.
> > > >     
> > > Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
> > >   
> > 
> > Will queue this patches to mtd/fixes just after 4.17-rc1 is out. Sorry
> > for the huge delay.  
> 
> Hi,
> 
> Did these patches end up somewhere? I can't see them in current
> v4.17-rc5.

Oops, my bad. I'll queue it in spi-nor/next (it's too late for -rc6).
Sorry for the inconvenience.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling
  2018-02-05 11:32 [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
  2018-02-05 11:33 ` [PATCH v2 2/2] spi-nor: intel-spi: Explicitly mark the driver as dangerous in Kconfig Mika Westerberg
  2018-02-27 16:51 ` [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
@ 2018-05-18 20:01 ` Boris Brezillon
  2 siblings, 0 replies; 9+ messages in thread
From: Boris Brezillon @ 2018-05-18 20:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: linux-mtd, Boris Brezillon, Bin Meng, Richard Weinberger,
	Anthony Wong, Marek Vasut, Cyrille Pitchen, Brian Norris,
	David Woodhouse

On Mon,  5 Feb 2018 14:32:59 +0300
Mika Westerberg <mika.westerberg@linux.intel.com> wrote:

> On many older systems using SW sequencer the PREOP_OPTYPE register
> contains two preopcodes as following:
> 
>   PREOP_OPTYPE=0xf2785006
> 
> The last two bytes are the opcodes decoded to:
> 
>   0x50 - Write enable for volatile status register
>   0x06 - Write enable
> 
> The former is used to modify volatile bits in the status register. For
> non-volatile bits the latter is needed. Preopcodes are used in SW
> sequencer to send one command "atomically" without anything else
> interfering the transfer. The sequence that gets executed is:
> 
>   - Send preopcode (write enable) from PREOP_OPTYPE register
>   - Send the actual SPI command
>   - Poll busy bit in the status register (0x05, RDSR)
> 
> Commit 8c473dd61bb5 ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be
> programmed by BIOS") enabled atomic sequence handling but because both
> preopcodes are programmed, the following happens:
> 
>   if (preop >> 8)
>   	val |= SSFSTS_CTL_SPOP;
> 
> Since on these systems preop >> 8 == 0x50 we end up picking volatile
> write enable instead. Because of this the actual write command is pretty
> much NOP unless there is a WREN latched in the chip already.
> 
> Furthermore we should not really just assume that WREN was issued in
> previous call to intel_spi_write_reg() because that might not be the
> case.
> 
> This updates driver to first check that the opcode is actually available
> in PREOP_OPTYPE register and if not return error back to the spi-nor
> core (if the controller is not locked we program it now). In addition we
> save the opcode to ispi->atomic_preopcode field which is checked in next
> call to intel_spi_sw_cycle() to actually enable atomic sequence using
> the requested preopcode.
> 
> Fixes: 8c473dd61bb5 ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be programmed by BIOS")
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Cc: stable@vger.kernel.org

Queued to spi-nor/next.

Thanks,

Boris

> ---
> Changes from v1:
> 
>   - Added atomic_preopcode field and only when it is set, enable atomic
>     sequence.
>   - Return -EINVAL if the requested WREN operation cannot be found from
>     PREOP register instead of silently pretending it is supported.
>   - Updated patch subject to match more closely what is being fixed.
> 
>  drivers/mtd/spi-nor/intel-spi.c | 76 ++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 67 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c
> index 699951523179..8e98f4ab87c1 100644
> --- a/drivers/mtd/spi-nor/intel-spi.c
> +++ b/drivers/mtd/spi-nor/intel-spi.c
> @@ -136,6 +136,7 @@
>   * @swseq_reg: Use SW sequencer in register reads/writes
>   * @swseq_erase: Use SW sequencer in erase operation
>   * @erase_64k: 64k erase supported
> + * @atomic_preopcode: Holds preopcode when atomic sequence is requested
>   * @opcodes: Opcodes which are supported. This are programmed by BIOS
>   *           before it locks down the controller.
>   */
> @@ -153,6 +154,7 @@ struct intel_spi {
>  	bool swseq_reg;
>  	bool swseq_erase;
>  	bool erase_64k;
> +	u8 atomic_preopcode;
>  	u8 opcodes[8];
>  };
>  
> @@ -474,7 +476,7 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len,
>  			      int optype)
>  {
>  	u32 val = 0, status;
> -	u16 preop;
> +	u8 atomic_preopcode;
>  	int ret;
>  
>  	ret = intel_spi_opcode_index(ispi, opcode, optype);
> @@ -484,17 +486,42 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len,
>  	if (len > INTEL_SPI_FIFO_SZ)
>  		return -EINVAL;
>  
> +	/*
> +	 * Always clear it after each SW sequencer operation regardless
> +	 * of whether it is successful or not.
> +	 */
> +	atomic_preopcode = ispi->atomic_preopcode;
> +	ispi->atomic_preopcode = 0;
> +
>  	/* Only mark 'Data Cycle' bit when there is data to be transferred */
>  	if (len > 0)
>  		val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS;
>  	val |= ret << SSFSTS_CTL_COP_SHIFT;
>  	val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE;
>  	val |= SSFSTS_CTL_SCGO;
> -	preop = readw(ispi->sregs + PREOP_OPTYPE);
> -	if (preop) {
> -		val |= SSFSTS_CTL_ACS;
> -		if (preop >> 8)
> -			val |= SSFSTS_CTL_SPOP;
> +	if (atomic_preopcode) {
> +		u16 preop;
> +
> +		switch (optype) {
> +		case OPTYPE_WRITE_NO_ADDR:
> +		case OPTYPE_WRITE_WITH_ADDR:
> +			/* Pick matching preopcode for the atomic sequence */
> +			preop = readw(ispi->sregs + PREOP_OPTYPE);
> +			if ((preop & 0xff) == atomic_preopcode)
> +				; /* Do nothing */
> +			else if ((preop >> 8) == atomic_preopcode)
> +				val |= SSFSTS_CTL_SPOP;
> +			else
> +				return -EINVAL;
> +
> +			/* Enable atomic sequence */
> +			val |= SSFSTS_CTL_ACS;
> +			break;
> +
> +		default:
> +			return -EINVAL;
> +		}
> +
>  	}
>  	writel(val, ispi->sregs + SSFSTS_CTL);
>  
> @@ -538,13 +565,31 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
>  
>  	/*
>  	 * This is handled with atomic operation and preop code in Intel
> -	 * controller so skip it here now. If the controller is not locked,
> -	 * program the opcode to the PREOP register for later use.
> +	 * controller so we only verify that it is available. If the
> +	 * controller is not locked, program the opcode to the PREOP
> +	 * register for later use.
> +	 *
> +	 * When hardware sequencer is used there is no need to program
> +	 * any opcodes (it handles them automatically as part of a command).
>  	 */
>  	if (opcode == SPINOR_OP_WREN) {
> -		if (!ispi->locked)
> +		u16 preop;
> +
> +		if (!ispi->swseq_reg)
> +			return 0;
> +
> +		preop = readw(ispi->sregs + PREOP_OPTYPE);
> +		if ((preop & 0xff) != opcode && (preop >> 8) != opcode) {
> +			if (ispi->locked)
> +				return -EINVAL;
>  			writel(opcode, ispi->sregs + PREOP_OPTYPE);
> +		}
>  
> +		/*
> +		 * This enables atomic sequence on next SW sycle. Will
> +		 * be cleared after next operation.
> +		 */
> +		ispi->atomic_preopcode = opcode;
>  		return 0;
>  	}
>  
> @@ -569,6 +614,13 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
>  	u32 val, status;
>  	ssize_t ret;
>  
> +	/*
> +	 * Atomic sequence is not expected with HW sequencer reads. Make
> +	 * sure it is cleared regardless.
> +	 */
> +	if (WARN_ON_ONCE(ispi->atomic_preopcode))
> +		ispi->atomic_preopcode = 0;
> +
>  	switch (nor->read_opcode) {
>  	case SPINOR_OP_READ:
>  	case SPINOR_OP_READ_FAST:
> @@ -627,6 +679,9 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
>  	u32 val, status;
>  	ssize_t ret;
>  
> +	/* Not needed with HW sequencer write, make sure it is cleared */
> +	ispi->atomic_preopcode = 0;
> +
>  	while (len > 0) {
>  		block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);
>  
> @@ -707,6 +762,9 @@ static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
>  		return 0;
>  	}
>  
> +	/* Not needed with HW sequencer erase, make sure it is cleared */
> +	ispi->atomic_preopcode = 0;
> +
>  	while (len > 0) {
>  		writel(offs, ispi->base + FADDR);
>  

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-05-18 20:01 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-05 11:32 [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
2018-02-05 11:33 ` [PATCH v2 2/2] spi-nor: intel-spi: Explicitly mark the driver as dangerous in Kconfig Mika Westerberg
2018-02-27 16:51 ` [PATCH v2 1/2] spi-nor: intel-spi: Fix atomic sequence handling Mika Westerberg
2018-04-03 13:48   ` Mika Westerberg
2018-04-04  8:21     ` Marek Vasut
2018-04-04 19:22       ` Boris Brezillon
2018-05-18  5:20         ` Mika Westerberg
2018-05-18  6:53           ` Boris Brezillon
2018-05-18 20:01 ` Boris Brezillon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.