From 1c631da459a82f4f82a063f5b4ff339ca5384d11 Mon Sep 17 00:00:00 2001 From: Suresh Gupta Date: Wed, 30 Aug 2017 20:06:33 +0530 Subject: 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 Reviewed-by: Jagan Teki --- drivers/spi/fsl_qspi.c | 28 +++++++++++++++++++++++++++- drivers/spi/fsl_qspi.h | 4 ++++ 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/spi') 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 #include #include +#include #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) -- cgit