summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSuresh Gupta <suresh.gupta@nxp.com>2017-08-30 20:06:33 +0530
committerJagan Teki <jagan@amarulasolutions.com>2017-09-25 12:49:56 +0530
commit1c631da459a82f4f82a063f5b4ff339ca5384d11 (patch)
tree024549b066804b69daccbace8bd733abc1cc78b5 /drivers
parent994266bdff7903279b8e43ddbf220b04a4e1411f (diff)
spi: fsl_qspi: Add controller busy check before new spi operation
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/fsl_qspi.c28
-rw-r--r--drivers/spi/fsl_qspi.h4
2 files changed, 31 insertions, 1 deletions
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 1dfa89afc9..8753ed99f1 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -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);
diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h
index 6cb361018b..e468eb2529 100644
--- a/drivers/spi/fsl_qspi.h
+++ b/drivers/spi/fsl_qspi.h
@@ -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)