diff mbox series

[U-Boot] spi: qspi: Fix issue when booting with DDR mode

Message ID 1546850714-21142-1-git-send-email-ye.li@nxp.com
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series [U-Boot] spi: qspi: Fix issue when booting with DDR mode | expand

Commit Message

Ye Li Jan. 7, 2019, 8:45 a.m. UTC
When booting from QSPI NOR with DDR mode enabled on i.MX7D/6UL, the
FLSHCR TDH bit is set to 1 by ROM along with MCR DDR_EN bit set. But
the read/write/readid/erase operations in the driver will overwrite
the MCR register, and cause the bits like DDR_EN are cleared.
If the DDR_EN is cleared but TDH is set, there is no clk2x output for
TX data shift. So these operations above will fail.

Fix the issue in two aspects:
1. In read/write/readid/erase operations, only set useful bit to MCR,
   not overwrite the whole register.
2. Set the TDH to 1 in qspi_enable_ddr_mode, so that DDR_EN and TDH will
   be correctly set by this function.

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

Comments

Jagan Teki Feb. 9, 2019, 5:32 p.m. UTC | #1
On Mon, Jan 7, 2019 at 2:15 PM Ye Li <ye.li@nxp.com> wrote:
>
> When booting from QSPI NOR with DDR mode enabled on i.MX7D/6UL, the
> FLSHCR TDH bit is set to 1 by ROM along with MCR DDR_EN bit set. But
> the read/write/readid/erase operations in the driver will overwrite
> the MCR register, and cause the bits like DDR_EN are cleared.
> If the DDR_EN is cleared but TDH is set, there is no clk2x output for
> TX data shift. So these operations above will fail.
>
> Fix the issue in two aspects:
> 1. In read/write/readid/erase operations, only set useful bit to MCR,
>    not overwrite the whole register.
> 2. Set the TDH to 1 in qspi_enable_ddr_mode, so that DDR_EN and TDH will
>    be correctly set by this function.
>
> Signed-off-by: Ye Li <ye.li@nxp.com>
> ---
>  drivers/spi/fsl_qspi.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
> index 1598c4f..1987a72 100644
> --- a/drivers/spi/fsl_qspi.c
> +++ b/drivers/spi/fsl_qspi.c
> @@ -405,7 +405,7 @@ static inline void qspi_ahb_read(struct fsl_qspi_priv *priv, u8 *rxbuf, int len)
>
>         qspi_write32(priv->flags, &regs->mcr,
>                      QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
> -                    QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
> +                    mcr_reg);
>
>         rx_addr = (void *)(uintptr_t)(priv->cur_amba_base + priv->sf_addr);
>         /* Read out the data directly from the AHB buffer. */
> @@ -435,6 +435,12 @@ static void qspi_enable_ddr_mode(struct fsl_qspi_priv *priv)
>         reg |= BIT(29);
>
>         qspi_write32(priv->flags, &regs->mcr, reg);
> +
> +       /* Enable the TDH to 1 for i.mx6ul and mx7d, it is reserved on other platforms */
> +       reg = qspi_read32(priv->flags, &regs->flshcr);
> +       reg &= ~(BIT(17));
> +       reg |= BIT(16);

Add proper macros for these bits.
diff mbox series

Patch

diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 1598c4f..1987a72 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -405,7 +405,7 @@  static inline void qspi_ahb_read(struct fsl_qspi_priv *priv, u8 *rxbuf, int len)
 
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 
 	rx_addr = (void *)(uintptr_t)(priv->cur_amba_base + priv->sf_addr);
 	/* Read out the data directly from the AHB buffer. */
@@ -435,6 +435,12 @@  static void qspi_enable_ddr_mode(struct fsl_qspi_priv *priv)
 	reg |= BIT(29);
 
 	qspi_write32(priv->flags, &regs->mcr, reg);
+
+	/* Enable the TDH to 1 for i.mx6ul and mx7d, it is reserved on other platforms */
+	reg = qspi_read32(priv->flags, &regs->flshcr);
+	reg &= ~(BIT(17));
+	reg |= BIT(16);
+	qspi_write32(priv->flags, &regs->flshcr, reg);
 }
 
 /*
@@ -488,7 +494,7 @@  static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len)
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
 	qspi_write32(priv->flags, &regs->sfar, priv->cur_amba_base);
@@ -533,7 +539,7 @@  static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
 	qspi_write32(priv->flags, &regs->sfar, priv->cur_amba_base);
@@ -579,7 +585,7 @@  static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
 	to_or_from = priv->sf_addr + priv->cur_amba_base;
@@ -631,7 +637,7 @@  static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
 	status_reg = 0;
@@ -706,7 +712,7 @@  static void qspi_op_rdsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len)
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
 	qspi_write32(priv->flags, &regs->sfar, priv->cur_amba_base);
@@ -743,7 +749,7 @@  static void qspi_op_erase(struct fsl_qspi_priv *priv)
 	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 	qspi_write32(priv->flags, &regs->mcr,
 		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
-		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+		     mcr_reg);
 	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
 
 	to_or_from = priv->sf_addr + priv->cur_amba_base;