ipq806x: fix spi read issues observed with SMP enabled

This change is fixing the issues observed when booting from NOR flash
with SMP enabled.

Error logs below:
building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of
xref (0 dead, 0 orphan) found.
m25p80 spi32766.0: SPI transfer failed: -110
spi_master spi32766: failed to transfer one message from queue
jffs2: Write of 873 bytes at 0x019001e8 failed. returned 0, retlen 792

Patch is cherry-picked from here:
https://www.codeaurora.org/cgit/quic/qsdk/oss/kernel/linux-msm/commit/drivers/spi/spi-qup.c?h=coconut_20140924&id=4faba89e3ffbb1c5f6232651375b9b3212b50f02

More details in the patch file.

Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>

SVN-Revision: 44518
lede-17.01
John Crispin 2015-02-24 11:59:41 +00:00
parent 1175e83f50
commit a45a5f7cf0
1 changed files with 56 additions and 0 deletions

View File

@ -0,0 +1,56 @@
From 4faba89e3ffbb1c5f6232651375b9b3212b50f02 Mon Sep 17 00:00:00 2001
From: Andy Gross <agross@codeaurora.org>
Date: Thu, 15 Jan 2015 17:56:02 -0800
Subject: [PATCH] spi: qup: Ensure done detection
This patch fixes an issue where a SPI transaction has completed, but the done
condition is missed. This occurs because at the time of interrupt the
MAX_INPUT_DONE_FLAG is not asserted. However, in the process of reading blocks
of data from the FIFO, the last portion of data comes in.
The opflags read at the beginning of the irq handler no longer matches the
current opflag state. To get around this condition, the block read function
should update the opflags so that done detection is correct after the return.
Change-Id: If109e0eeb432f96000d765c4b34dbb2269f8093f
Signed-off-by: Andy Gross <agross@codeaurora.org>
---
drivers/spi/spi-qup.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -298,7 +298,7 @@ static void spi_qup_fifo_write(struct sp
}
static void spi_qup_block_read(struct spi_qup *controller,
- struct spi_transfer *xfer)
+ struct spi_transfer *xfer, u32 *opflags)
{
u32 data;
u32 reads_per_blk = controller->in_blk_sz >> 2;
@@ -327,10 +327,12 @@ static void spi_qup_block_read(struct sp
/*
* Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block
- * reads, it has to be cleared again at the very end
+ * reads, it has to be cleared again at the very end. However, be sure
+ * to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
+ * present and this is used to determine if transaction is complete
*/
- if (readl_relaxed(controller->base + QUP_OPERATIONAL) &
- QUP_OP_MAX_INPUT_DONE_FLAG)
+ *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
+ if (*opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
controller->base + QUP_OPERATIONAL);
@@ -633,7 +635,7 @@ static irqreturn_t spi_qup_qup_irq(int i
if (!controller->use_dma) {
if (opflags & QUP_OP_IN_SERVICE_FLAG) {
if (opflags & QUP_OP_IN_BLOCK_READ_REQ)
- spi_qup_block_read(controller, xfer);
+ spi_qup_block_read(controller, xfer, &opflags);
else
spi_qup_fifo_read(controller, xfer);
}