spi: fsl_qspi: Add controller busy check before new spi operation
authorSuresh Gupta <suresh.gupta@nxp.com>
Wed, 30 Aug 2017 14:36:33 +0000 (20:06 +0530)
committerJagan Teki <jagan@amarulasolutions.com>
Mon, 25 Sep 2017 07:19:56 +0000 (12:49 +0530)
It is recommended to check either controller is free to take
new spi action. The IP_ACC and AHB_ACC bits indicates that
the controller is busy in IP or AHB mode respectively.
And the BUSY bit indicates that controller is currently
busy handling a transaction to an external flash device

Signed-off-by: Suresh Gupta <suresh.gupta@nxp.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
drivers/spi/fsl_qspi.c
drivers/spi/fsl_qspi.h

index 1dfa89a..8753ed9 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;
@@ -991,7 +992,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;
 
@@ -1011,6 +1012,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 |
@@ -1156,10 +1169,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);
index 6cb3610..e468eb2 100644 (file)
@@ -105,6 +105,10 @@ struct fsl_qspi_regs {
 #define QSPI_RBCT_RXBRD_SHIFT          8
 #define QSPI_RBCT_RXBRD_USEIPS         (1 << QSPI_RBCT_RXBRD_SHIFT)
 
+#define QSPI_SR_AHB_ACC_SHIFT          2
+#define QSPI_SR_AHB_ACC_MASK           (1 << QSPI_SR_AHB_ACC_SHIFT)
+#define QSPI_SR_IP_ACC_SHIFT           1
+#define QSPI_SR_IP_ACC_MASK            (1 << QSPI_SR_IP_ACC_SHIFT)
 #define QSPI_SR_BUSY_SHIFT             0
 #define QSPI_SR_BUSY_MASK              (1 << QSPI_SR_BUSY_SHIFT)