[U-Boot] [PATCH] mtd: qspi: support read the flag status in fspi driver

Ye Li ye.li at nxp.com
Mon Jan 7 08:54:54 UTC 2019


From: Han Xu <han.xu at nxp.com>

Support to read the flag status in driver to avoid the spi-nor framework
wait_for_ready hang issue.

Signed-off-by: Han Xu <han.xu at nxp.com>
---
 drivers/spi/fsl_qspi.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 1987a72..ed0e649 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #endif
 #define SEQID_WRAR		13
 #define SEQID_RDAR		14
+#define SEQID_RDFSR		15
 
 /* QSPI CMD */
 #define QSPI_CMD_PP		0x02	/* Page program (up to 256 bytes) */
@@ -57,6 +58,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define QSPI_CMD_CHIP_ERASE	0xc7	/* Erase whole flash chip */
 #define QSPI_CMD_SE		0xd8	/* Sector erase (usually 64KiB) */
 #define QSPI_CMD_RDID		0x9f	/* Read JEDEC ID */
+#define QSPI_CMD_FLAG_SR	0x70	/* Read FLAG STATUS*/
 
 /* Used for Micron, winbond and Macronix flashes */
 #define	QSPI_CMD_WREAR		0xc5	/* EAR register write */
@@ -230,6 +232,15 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv)
 	qspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
 	qspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
 
+	/* Read Flag Status */
+	lut_base = SEQID_RDFSR * 4;
+	qspi_write32(priv->flags, &regs->lut[lut_base], OPRND0(QSPI_CMD_FLAG_SR) |
+		PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
+		PAD1(LUT_PAD1) | INSTR1(LUT_READ));
+	qspi_write32(priv->flags, &regs->lut[lut_base + 1], 0);
+	qspi_write32(priv->flags, &regs->lut[lut_base + 2], 0);
+	qspi_write32(priv->flags, &regs->lut[lut_base + 3], 0);
+
 	/* Erase a sector */
 	lut_base = SEQID_SE * 4;
 #ifdef CONFIG_SPI_FLASH_BAR
@@ -740,6 +751,40 @@ static void qspi_op_rdsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len)
 	qspi_write32(priv->flags, &regs->mcr, mcr_reg);
 }
 
+static void qspi_op_rdfsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len)
+{
+	struct fsl_qspi_regs *regs = priv->regs;
+	u32 mcr_reg, reg, data;
+
+	mcr_reg = qspi_read32(priv->flags, &regs->mcr);
+	qspi_write32(priv->flags, &regs->mcr,
+		     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+		     mcr_reg);
+	qspi_write32(priv->flags, &regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+	qspi_write32(priv->flags, &regs->sfar, priv->cur_amba_base);
+
+	qspi_write32(priv->flags, &regs->ipcr,
+		     (SEQID_RDFSR << QSPI_IPCR_SEQID_SHIFT) | 0);
+	while (qspi_read32(priv->flags, &regs->sr) & QSPI_SR_BUSY_MASK)
+		;
+
+	while (1) {
+		reg = qspi_read32(priv->flags, &regs->rbsr);
+		if (reg & QSPI_RBSR_RDBFL_MASK) {
+			data = qspi_read32(priv->flags, &regs->rbdr[0]);
+			data = qspi_endian_xchg(data);
+			memcpy(rxbuf, &data, len);
+			qspi_write32(priv->flags, &regs->mcr,
+				     qspi_read32(priv->flags, &regs->mcr) |
+				     QSPI_MCR_CLR_RXF_MASK);
+			break;
+		}
+	}
+
+	qspi_write32(priv->flags, &regs->mcr, mcr_reg);
+}
+
 static void qspi_op_erase(struct fsl_qspi_priv *priv)
 {
 	struct fsl_qspi_regs *regs = priv->regs;
@@ -825,6 +870,8 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
 			qspi_op_rdid(priv, din, bytes);
 		else if (priv->cur_seqid == QSPI_CMD_RDSR)
 			qspi_op_rdsr(priv, din, bytes);
+		else if (priv->cur_seqid == QSPI_CMD_FLAG_SR)
+			qspi_op_rdfsr(priv, din, bytes);
 #ifdef CONFIG_SPI_FLASH_BAR
 		else if ((priv->cur_seqid == QSPI_CMD_BRRD) ||
 			 (priv->cur_seqid == QSPI_CMD_RDEAR)) {
-- 
2.7.4



More information about the U-Boot mailing list