[U-Boot] spi: fsl_qspi: Fix flash write issue on i.MX7ULP
diff mbox series

Message ID 1562753010-44601-1-git-send-email-ye.li@nxp.com
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series
  • [U-Boot] spi: fsl_qspi: Fix flash write issue on i.MX7ULP
Related show

Commit Message

Ye Li July 10, 2019, 10:03 a.m. UTC
The page write sequence in spi-mem is changed with orignal spi-flash. When
the max_write_size is set by driver, the orignal sequence is
  1. WREN
  2. write max_write_size data to flash
  3. wait for WIP clean
  4. back to #1 if having data remained in a page.

The new sequence is:
  1. WREN
  2. write (max_write_size - command length) data to flash
  3. back to #2 if having data remained in a page
  4. wait for WIP clean

i.MX7ULP has 64 bytes TX buffer (max_write_size), while other iMX chips
have 512 bytes (page size is 256). So when adapt qspi with the new sequence,
we have to check the WIP before each write on mx7ulp. Otherwise the WIP may set
due to previous write is not completed by flash device, then cause current
write failed.

Signed-off-by: Ye Li <ye.li@nxp.com>
---
 drivers/spi/fsl_qspi.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Comments

Jagan Teki July 15, 2019, 7:35 a.m. UTC | #1
On Wed, Jul 10, 2019 at 3:34 PM Ye Li <ye.li@nxp.com> wrote:
>
> The page write sequence in spi-mem is changed with orignal spi-flash. When
> the max_write_size is set by driver, the orignal sequence is
>   1. WREN
>   2. write max_write_size data to flash
>   3. wait for WIP clean
>   4. back to #1 if having data remained in a page.
>
> The new sequence is:
>   1. WREN
>   2. write (max_write_size - command length) data to flash
>   3. back to #2 if having data remained in a page
>   4. wait for WIP clean
>
> i.MX7ULP has 64 bytes TX buffer (max_write_size), while other iMX chips
> have 512 bytes (page size is 256). So when adapt qspi with the new sequence,
> we have to check the WIP before each write on mx7ulp. Otherwise the WIP may set
> due to previous write is not completed by flash device, then cause current
> write failed.
>
> Signed-off-by: Ye Li <ye.li@nxp.com>
> ---
>  drivers/spi/fsl_qspi.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>
> diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
> index 1598c4f..e958b6a 100644
> --- a/drivers/spi/fsl_qspi.c
> +++ b/drivers/spi/fsl_qspi.c
> @@ -29,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define OFFSET_BITS_MASK       GENMASK(23, 0)
>
>  #define FLASH_STATUS_WEL       0x02
> +#define FLASH_STATUS_WIP       0x01
>
>  /* SEQID */
>  #define SEQID_WREN             1
> @@ -634,6 +635,27 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
>                      QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
>         qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
>
> +       if (TX_BUFFER_SIZE <= 256) {

Checking macro look odd here, since the driver is already moved to dm
try driver data on effected SoC compatible or similar.

Patch
diff mbox series

diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 1598c4f..e958b6a 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -29,6 +29,7 @@  DECLARE_GLOBAL_DATA_PTR;
 #define OFFSET_BITS_MASK	GENMASK(23, 0)
 
 #define FLASH_STATUS_WEL	0x02
+#define FLASH_STATUS_WIP	0x01
 
 /* SEQID */
 #define SEQID_WREN		1
@@ -634,6 +635,27 @@  static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
 		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
+	if (TX_BUFFER_SIZE <= 256) {
+		status_reg = 0;
+		do {
+			WATCHDOG_RESET();
+
+			qspi_write32(priv->flags, &regs->ipcr,
+				     (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
+			while (qspi_read32(priv->flags, &regs->sr) & QSPI_SR_BUSY_MASK)
+				;
+
+			reg = qspi_read32(priv->flags, &regs->rbsr);
+			if (reg & QSPI_RBSR_RDBFL_MASK) {
+				status_reg = qspi_read32(priv->flags, &regs->rbdr[0]);
+				status_reg = qspi_endian_xchg(status_reg);
+			}
+			qspi_write32(priv->flags, &regs->mcr,
+				     qspi_read32(priv->flags, &regs->mcr) |
+				     QSPI_MCR_CLR_RXF_MASK);
+		} while ((status_reg & FLASH_STATUS_WIP) == FLASH_STATUS_WIP);
+	}
+
 	status_reg = 0;
 	while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
 		WATCHDOG_RESET();