]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/fsl_qspi.c
dm: mmc: sunxi: Pass private data around explicitly
[u-boot] / drivers / spi / fsl_qspi.c
index db7ebee972f7375e7239129f7484950bc8799428..e61c67b088bc7e267f44eaec916df7628b9fa5b4 100644 (file)
@@ -44,6 +44,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #define SEQID_RDEAR            11
 #define SEQID_WREAR            12
 #endif
+#define SEQID_WRAR             13
+#define SEQID_RDAR             14
 
 /* QSPI CMD */
 #define QSPI_CMD_PP            0x02    /* Page program (up to 256 bytes) */
@@ -63,6 +65,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #define        QSPI_CMD_BRRD           0x16    /* Bank register read */
 #define        QSPI_CMD_BRWR           0x17    /* Bank register write */
 
+/* Used for Spansion S25FS-S family flash only. */
+#define QSPI_CMD_RDAR          0x65    /* Read any device register */
+#define QSPI_CMD_WRAR          0x71    /* Write any device register */
+
 /* 4-byte address QSPI CMD - used on Spansion and some Macronix flashes */
 #define QSPI_CMD_FAST_READ_4B  0x0c    /* Read data bytes (high frequency) */
 #define QSPI_CMD_PP_4B         0x12    /* Page program (up to 256 bytes) */
@@ -317,6 +323,33 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv)
                     PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
                     PAD1(LUT_PAD1) | INSTR1(LUT_WRITE));
 #endif
+
+       /*
+        * Read any device register.
+        * Used for Spansion S25FS-S family flash only.
+        */
+       lut_base = SEQID_RDAR * 4;
+       qspi_write32(priv->flags, &regs->lut[lut_base],
+                    OPRND0(QSPI_CMD_RDAR) | PAD0(LUT_PAD1) |
+                    INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+                    PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+       qspi_write32(priv->flags, &regs->lut[lut_base + 1],
+                    OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) |
+                    OPRND1(1) | PAD1(LUT_PAD1) |
+                    INSTR1(LUT_READ));
+
+       /*
+        * Write any device register.
+        * Used for Spansion S25FS-S family flash only.
+        */
+       lut_base = SEQID_WRAR * 4;
+       qspi_write32(priv->flags, &regs->lut[lut_base],
+                    OPRND0(QSPI_CMD_WRAR) | PAD0(LUT_PAD1) |
+                    INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+                    PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+       qspi_write32(priv->flags, &regs->lut[lut_base + 1],
+                    OPRND0(1) | PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
+
        /* Lock the LUT */
        qspi_write32(priv->flags, &regs->lutkey, LUT_KEY_VALUE);
        qspi_write32(priv->flags, &regs->lckcr, QSPI_LCKCR_LOCK);
@@ -353,6 +386,7 @@ static inline void qspi_ahb_read(struct fsl_qspi_priv *priv, u8 *rxbuf, int len)
 {
        struct fsl_qspi_regs *regs = priv->regs;
        u32 mcr_reg;
+       void *rx_addr = NULL;
 
        mcr_reg = qspi_read32(priv->flags, &regs->mcr);
 
@@ -360,8 +394,9 @@ static inline void qspi_ahb_read(struct fsl_qspi_priv *priv, u8 *rxbuf, int len)
                     QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK |
                     QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE);
 
+       rx_addr = (void *)(uintptr_t)(priv->cur_amba_base + priv->sf_addr);
        /* Read out the data directly from the AHB buffer. */
-       memcpy(rxbuf, (u8 *)(priv->cur_amba_base + priv->sf_addr), len);
+       memcpy(rxbuf, rx_addr, len);
 
        qspi_write32(priv->flags, &regs->mcr, mcr_reg);
 }
@@ -510,7 +545,6 @@ static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
        qspi_write32(priv->flags, &regs->mcr, mcr_reg);
 }
 
-#ifndef CONFIG_SYS_FSL_QSPI_AHB
 /* If not use AHB read, read data from ip interface */
 static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
 {
@@ -518,6 +552,12 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
        u32 mcr_reg, data;
        int i, size;
        u32 to_or_from;
+       u32 seqid;
+
+       if (priv->cur_seqid == QSPI_CMD_RDAR)
+               seqid = SEQID_RDAR;
+       else
+               seqid = SEQID_FAST_READ;
 
        mcr_reg = qspi_read32(priv->flags, &regs->mcr);
        qspi_write32(priv->flags, &regs->mcr,
@@ -536,7 +576,7 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
                        RX_BUFFER_SIZE : len;
 
                qspi_write32(priv->flags, &regs->ipcr,
-                            (SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) |
+                            (seqid << QSPI_IPCR_SEQID_SHIFT) |
                             size);
                while (qspi_read32(priv->flags, &regs->sr) & QSPI_SR_BUSY_MASK)
                        ;
@@ -548,7 +588,10 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
                while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
                        data = qspi_read32(priv->flags, &regs->rbdr[i]);
                        data = qspi_endian_xchg(data);
-                       memcpy(rxbuf, &data, 4);
+                       if (size < 4)
+                               memcpy(rxbuf, &data, size);
+                       else
+                               memcpy(rxbuf, &data, 4);
                        rxbuf++;
                        size -= 4;
                        i++;
@@ -560,7 +603,6 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
 
        qspi_write32(priv->flags, &regs->mcr, mcr_reg);
 }
-#endif
 
 static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
 {
@@ -601,6 +643,8 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
 
        /* Default is page programming */
        seqid = SEQID_PP;
+       if (priv->cur_seqid == QSPI_CMD_WRAR)
+               seqid = SEQID_WRAR;
 #ifdef CONFIG_SPI_FLASH_BAR
        if (priv->cur_seqid == QSPI_CMD_BRWR)
                seqid = SEQID_BRWR;
@@ -725,13 +769,15 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
                        return 0;
                }
 
-               if (priv->cur_seqid == QSPI_CMD_FAST_READ) {
+               if (priv->cur_seqid == QSPI_CMD_FAST_READ ||
+                   priv->cur_seqid == QSPI_CMD_RDAR) {
                        priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
                } else if ((priv->cur_seqid == QSPI_CMD_SE) ||
                           (priv->cur_seqid == QSPI_CMD_BE_4K)) {
                        priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
                        qspi_op_erase(priv);
-               } else if (priv->cur_seqid == QSPI_CMD_PP) {
+               } else if (priv->cur_seqid == QSPI_CMD_PP ||
+                          priv->cur_seqid == QSPI_CMD_WRAR) {
                        wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
                } else if ((priv->cur_seqid == QSPI_CMD_BRWR) ||
                         (priv->cur_seqid == QSPI_CMD_WREAR)) {
@@ -748,6 +794,8 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
 #else
                        qspi_op_read(priv, din, bytes);
 #endif
+               } else if (priv->cur_seqid == QSPI_CMD_RDAR) {
+                       qspi_op_read(priv, din, bytes);
                } else if (priv->cur_seqid == QSPI_CMD_RDID)
                        qspi_op_rdid(priv, din, bytes);
                else if (priv->cur_seqid == QSPI_CMD_RDSR)
@@ -817,6 +865,7 @@ static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave)
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int mode)
 {
+       u32 mcr_val;
        struct fsl_qspi *qspi;
        struct fsl_qspi_regs *regs;
        u32 total_size;
@@ -848,8 +897,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
        qspi->slave.max_write_size = TX_BUFFER_SIZE;
 
+       mcr_val = qspi_read32(qspi->priv.flags, &regs->mcr);
        qspi_write32(qspi->priv.flags, &regs->mcr,
-                    QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
+                    QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK |
+                    (mcr_val & QSPI_MCR_END_CFD_MASK));
 
        qspi_cfg_smpr(&qspi->priv,
                      ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK |
@@ -927,6 +978,7 @@ static int fsl_qspi_child_pre_probe(struct udevice *dev)
 
 static int fsl_qspi_probe(struct udevice *bus)
 {
+       u32 mcr_val;
        u32 amba_size_per_chip;
        struct fsl_qspi_platdata *plat = dev_get_platdata(bus);
        struct fsl_qspi_priv *priv = dev_get_priv(bus);
@@ -951,8 +1003,10 @@ static int fsl_qspi_probe(struct udevice *bus)
        priv->flash_num = plat->flash_num;
        priv->num_chipselect = plat->num_chipselect;
 
+       mcr_val = qspi_read32(priv->flags, &priv->regs->mcr);
        qspi_write32(priv->flags, &priv->regs->mcr,
-                    QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK);
+                    QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK |
+                    (mcr_val & QSPI_MCR_END_CFD_MASK));
 
        qspi_cfg_smpr(priv, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK |
                QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0);
@@ -983,8 +1037,11 @@ static int fsl_qspi_probe(struct udevice *bus)
         * setting the size of these devices to 0.  This would ensure
         * that the complete memory map is assigned to only one flash device.
         */
-       qspi_write32(priv->flags, &priv->regs->sfa1ad, priv->amba_base[1]);
+       qspi_write32(priv->flags, &priv->regs->sfa1ad,
+                    priv->amba_base[0] + amba_size_per_chip);
        switch (priv->num_chipselect) {
+       case 1:
+               break;
        case 2:
                qspi_write32(priv->flags, &priv->regs->sfa2ad,
                             priv->amba_base[1]);
@@ -1024,7 +1081,7 @@ static int fsl_qspi_ofdata_to_platdata(struct udevice *bus)
        struct fdt_resource res_regs, res_mem;
        struct fsl_qspi_platdata *plat = bus->platdata;
        const void *blob = gd->fdt_blob;
-       int node = bus->of_offset;
+       int node = dev_of_offset(bus);
        int ret, flash_num = 0, subnode;
 
        if (fdtdec_get_bool(blob, node, "big-endian"))
@@ -1044,7 +1101,7 @@ static int fsl_qspi_ofdata_to_platdata(struct udevice *bus)
        }
 
        /* Count flash numbers */
-       fdt_for_each_subnode(blob, subnode, node)
+       fdt_for_each_subnode(subnode, blob, node)
                ++flash_num;
 
        if (flash_num == 0) {