]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/fsl_qspi.c
am335x-fb: cosmetic: update-copyright
[u-boot] / drivers / spi / fsl_qspi.c
index e61c67b088bc7e267f44eaec916df7628b9fa5b4..0f3f7d97f0137fa7b258358119f8a0459d313a33 100644 (file)
@@ -14,6 +14,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <watchdog.h>
+#include <wait_bit.h>
 #include "fsl_qspi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -493,6 +494,8 @@ static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len)
                ;
 
        while (1) {
+               WATCHDOG_RESET();
+
                reg = qspi_read32(priv->flags, &regs->rbsr);
                if (reg & QSPI_RBSR_RDBFL_MASK) {
                        data = qspi_read32(priv->flags, &regs->rbdr[0]);
@@ -530,6 +533,8 @@ static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
 
        i = 0;
        while ((RX_BUFFER_SIZE >= len) && (len > 0)) {
+               WATCHDOG_RESET();
+
                rbsr_reg = qspi_read32(priv->flags, &regs->rbsr);
                if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
                        data = qspi_read32(priv->flags, &regs->rbdr[i]);
@@ -659,22 +664,20 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
        tx_size = (len > TX_BUFFER_SIZE) ?
                TX_BUFFER_SIZE : len;
 
-       size = tx_size / 4;
-       for (i = 0; i < size; i++) {
+       size = tx_size / 16;
+       /*
+        * There must be atleast 128bit data
+        * available in TX FIFO for any pop operation
+        */
+       if (tx_size % 16)
+               size++;
+       for (i = 0; i < size * 4; i++) {
                memcpy(&data, txbuf, 4);
                data = qspi_endian_xchg(data);
                qspi_write32(priv->flags, &regs->tbdr, data);
                txbuf += 4;
        }
 
-       size = tx_size % 4;
-       if (size) {
-               data = 0;
-               memcpy(&data, txbuf, size);
-               data = qspi_endian_xchg(data);
-               qspi_write32(priv->flags, &regs->tbdr, data);
-       }
-
        qspi_write32(priv->flags, &regs->ipcr,
                     (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size);
        while (qspi_read32(priv->flags, &regs->sr) & QSPI_SR_BUSY_MASK)
@@ -702,6 +705,8 @@ static void qspi_op_rdsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len)
                ;
 
        while (1) {
+               WATCHDOG_RESET();
+
                reg = qspi_read32(priv->flags, &regs->rbsr);
                if (reg & QSPI_RBSR_RDBFL_MASK) {
                        data = qspi_read32(priv->flags, &regs->rbdr[0]);
@@ -757,6 +762,8 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
        static u32 wr_sfaddr;
        u32 txbuf;
 
+       WATCHDOG_RESET();
+
        if (dout) {
                if (flags & SPI_XFER_BEGIN) {
                        priv->cur_seqid = *(u8 *)dout;
@@ -983,7 +990,7 @@ static int fsl_qspi_probe(struct udevice *bus)
        struct fsl_qspi_platdata *plat = dev_get_platdata(bus);
        struct fsl_qspi_priv *priv = dev_get_priv(bus);
        struct dm_spi_bus *dm_spi_bus;
-       int i;
+       int i, ret;
 
        dm_spi_bus = bus->uclass_priv;
 
@@ -1003,6 +1010,18 @@ static int fsl_qspi_probe(struct udevice *bus)
        priv->flash_num = plat->flash_num;
        priv->num_chipselect = plat->num_chipselect;
 
+       /* make sure controller is not busy anywhere */
+       ret = wait_for_bit(__func__, &priv->regs->sr,
+                          QSPI_SR_BUSY_MASK |
+                          QSPI_SR_AHB_ACC_MASK |
+                          QSPI_SR_IP_ACC_MASK,
+                          false, 100, false);
+
+       if (ret) {
+               debug("ERROR : The controller is busy\n");
+               return ret;
+       }
+
        mcr_val = qspi_read32(priv->flags, &priv->regs->mcr);
        qspi_write32(priv->flags, &priv->regs->mcr,
                     QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK |
@@ -1148,10 +1167,23 @@ static int fsl_qspi_claim_bus(struct udevice *dev)
        struct fsl_qspi_priv *priv;
        struct udevice *bus;
        struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+       int ret;
 
        bus = dev->parent;
        priv = dev_get_priv(bus);
 
+       /* make sure controller is not busy anywhere */
+       ret = wait_for_bit(__func__, &priv->regs->sr,
+                          QSPI_SR_BUSY_MASK |
+                          QSPI_SR_AHB_ACC_MASK |
+                          QSPI_SR_IP_ACC_MASK,
+                          false, 100, false);
+
+       if (ret) {
+               debug("ERROR : The controller is busy\n");
+               return ret;
+       }
+
        priv->cur_amba_base = priv->amba_base[slave_plat->cs];
 
        qspi_module_disable(priv, 0);