@@ -201,6 +201,17 @@
(((readl((reg_base) + CQSPI_REG_SDRAMLEVEL)) >> \
CQSPI_REG_SDRAMLEVEL_WR_LSB) & CQSPI_REG_SDRAMLEVEL_WR_MASK)
+/* Interrupt status bits */
+#define CQSPI_REG_IRQ_UNDERFLOW BIT(1)
+#define CQSPI_REG_IRQ_IND_COMP BIT(2)
+#define CQSPI_REG_IRQ_WATERMARK BIT(6)
+
+#define CQSPI_IRQ_MASK_WR (CQSPI_REG_IRQ_IND_COMP | \
+ CQSPI_REG_IRQ_WATERMARK | \
+ CQSPI_REG_IRQ_UNDERFLOW)
+
+#define CQSPI_IRQ_STATUS_MASK GENMASK(16, 0)
+
struct cadence_spi_plat {
unsigned int max_hz;
void *regbase;
@@ -31,6 +31,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/errno.h>
+#include <linux/iopoll.h>
#include <wait_bit.h>
#include <spi.h>
#include <spi-mem.h>
@@ -845,7 +846,7 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_priv *priv,
const u8 *bb_txbuf = txbuf;
void *bounce_buf = NULL;
unsigned int write_bytes;
- int ret;
+ int ret, cr;
/*
* Use bounce buffer for non 32 bit aligned txbuf to avoid data
@@ -859,9 +860,15 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_priv *priv,
bb_txbuf = bounce_buf;
}
- /* Configure the indirect read transfer bytes */
+ /* Configure the indirect write transfer bytes */
writel(n_tx, priv->regbase + CQSPI_REG_INDIRECTWRBYTES);
+ /* Clear all interrupts */
+ writel(CQSPI_IRQ_STATUS_MASK, priv->regbase + CQSPI_REG_IRQSTATUS);
+
+ /* Enable interrupt for corresponding interrupt status register bit's */
+ writel(CQSPI_IRQ_MASK_WR, priv->regbase + CQSPI_REG_IRQMASK);
+
/* Start the indirect write transfer */
writel(CQSPI_REG_INDIRECTWR_START,
priv->regbase + CQSPI_REG_INDIRECTWR);
@@ -880,9 +887,10 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_priv *priv,
bb_txbuf + rounddown(write_bytes, 4),
write_bytes % 4);
- ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_SDRAMLEVEL,
- CQSPI_REG_SDRAMLEVEL_WR_MASK <<
- CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
+ /* Wait up to Indirect Operation Complete bit to set */
+ ret = readl_poll_timeout(priv->regbase + CQSPI_REG_IRQSTATUS, cr,
+ cr & CQSPI_REG_IRQ_IND_COMP, 10);
+
if (ret) {
printf("Indirect write timed out (%i)\n", ret);
goto failwr;
@@ -900,6 +908,9 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_priv *priv,
goto failwr;
}
+ /* Disable interrupt. */
+ writel(0, priv->regbase + CQSPI_REG_IRQMASK);
+
/* Clear indirect completion status */
writel(CQSPI_REG_INDIRECTWR_DONE,
priv->regbase + CQSPI_REG_INDIRECTWR);
@@ -917,6 +928,9 @@ cadence_qspi_apb_indirect_write_execute(struct cadence_spi_priv *priv,
return 0;
failwr:
+ /* Disable interrupt. */
+ writel(0, priv->regbase + CQSPI_REG_IRQMASK);
+
/* Cancel the indirect write */
writel(CQSPI_REG_INDIRECTWR_CANCEL,
priv->regbase + CQSPI_REG_INDIRECTWR);