From: Peng Fan <van.free...@gmail.com>

Add qspi_op_wrr to support status and configuration register write in
flash devices.

Signed-off-by: Peng Fan <van.free...@gmail.com>
---
 drivers/spi/fsl_qspi.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 7e8d07e..b1d75e7 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -32,12 +32,16 @@
 #define SEQID_CHIP_ERASE       5
 #define SEQID_PP               6
 #define SEQID_RDID             7
+#define SEQID_WRR              8
+#define SEQID_RDCR             9
 
 /* Flash opcodes */
+#define OPCODE_WRR             0x01    /* Write status/config register */
 #define OPCODE_PP              0x02    /* Page program (up to 256 bytes) */
 #define OPCODE_RDSR            0x05    /* Read status register */
 #define OPCODE_WREN            0x06    /* Write enable */
 #define OPCODE_FAST_READ       0x0b    /* Read data bytes (high frequency) */
+#define OPCODE_RDCR            0x35    /* Read configuration register */
 #define OPCODE_CHIP_ERASE      0xc7    /* Erase whole flash chip */
 #define OPCODE_SE              0xd8    /* Sector erase (usually 64KiB) */
 #define OPCODE_RDID            0x9f    /* Read JEDEC ID */
@@ -189,6 +193,18 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
        qspi_write32(&regs->lut[lut_base + 2], 0);
        qspi_write32(&regs->lut[lut_base + 3], 0);
 
+       /* Write Register */
+       lut_base = SEQID_WRR * 4;
+       qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_WRR) |
+                    PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(LUT_WRITE) |
+                    PAD1(LUT_PAD1) | INSTR1(0x2));
+
+       /* Read Configuration Register */
+       lut_base = SEQID_RDCR * 4;
+       qspi_write32(&regs->lut[lut_base], OPRND0(OPCODE_RDCR) |
+                    PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(LUT_READ) |
+                    PAD1(LUT_PAD1) | INSTR1(0x1));
+
        /* Lock the LUT */
        qspi_write32(&regs->lutkey, LUT_KEY_VALUE);
        qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
@@ -352,6 +368,55 @@ static void qspi_op_read(struct fsl_qspi *qspi, u32 
*rxbuf, u32 len)
        qspi_write32(&regs->mcr, mcr_reg);
 }
 
+static void qspi_op_wrr(struct fsl_qspi *qspi, u8 *txbuf, u32 len)
+{
+       struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
+       u32 mcr_reg, data, reg, status_reg;
+       u32 to_or_from;
+
+       mcr_reg = qspi_read32(&regs->mcr);
+       qspi_write32(&regs->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
+                    QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
+       qspi_write32(&regs->rbct, QSPI_RBCT_RXBRD_USEIPS);
+
+       status_reg = 0;
+       while ((status_reg & FLASH_STATUS_WEL) != FLASH_STATUS_WEL) {
+               qspi_write32(&regs->ipcr,
+                            (SEQID_WREN << QSPI_IPCR_SEQID_SHIFT) | 0);
+               while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+                       ;
+
+               qspi_write32(&regs->ipcr,
+                            (SEQID_RDSR << QSPI_IPCR_SEQID_SHIFT) | 1);
+               while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+                       ;
+
+               reg = qspi_read32(&regs->rbsr);
+               if (reg & QSPI_RBSR_RDBFL_MASK) {
+                       status_reg = qspi_read32(&regs->rbdr[0]);
+                       status_reg = qspi_endian_xchg(status_reg);
+               }
+               qspi_write32(&regs->mcr,
+                            qspi_read32(&regs->mcr) | QSPI_MCR_CLR_RXF_MASK);
+       }
+
+       to_or_from = qspi->amba_base;
+       qspi_write32(&regs->sfar, to_or_from);
+
+       /* The max len is 2 for OPCODE_WRR */
+       data = 0;
+       memcpy(&data, txbuf, len);
+       data = qspi_endian_xchg(data);
+       qspi_write32(&regs->tbdr, data);
+
+       qspi_write32(&regs->ipcr,
+                    (SEQID_WRR << QSPI_IPCR_SEQID_SHIFT) | len);
+       while (qspi_read32(&regs->sr) & QSPI_SR_BUSY_MASK)
+               ;
+
+       qspi_write32(&regs->mcr, mcr_reg);
+}
+
 static void qspi_op_pp(struct fsl_qspi *qspi, u32 *txbuf, u32 len)
 {
        struct fsl_qspi_regs *regs = (struct fsl_qspi_regs *)qspi->reg_base;
@@ -476,11 +541,17 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
        if (dout) {
                memcpy(&txbuf, dout, 4);
-               qspi->cur_seqid = *(u8 *)dout;
+               /* extract cmd when SPI_XFER_BEGIN is set */
+               if (flags & SPI_XFER_BEGIN)
+                       qspi->cur_seqid = *(u8 *)dout;
 
                if (flags == SPI_XFER_END) {
-                       qspi->sf_addr = pp_sfaddr;
-                       qspi_op_pp(qspi, (u32 *)dout, bytes);
+                       if (qspi->cur_seqid == OPCODE_WRR) {
+                               qspi_op_wrr(qspi, (u8 *)dout, bytes);
+                       } else if (qspi->cur_seqid == OPCODE_PP) {
+                               qspi->sf_addr = pp_sfaddr;
+                               qspi_op_pp(qspi, (u32 *)dout, bytes);
+                       }
                        return 0;
                }
 
-- 
1.8.4


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to