Skip to content

Commit cd595b9

Browse files
Varadarajan Narayananbroonie
authored andcommitted
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. Signed-off-by: Andy Gross <[email protected]> Signed-off-by: Abhishek Sahu <[email protected]> Signed-off-by: Varadarajan Narayanan <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 5884e17 commit cd595b9

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

drivers/spi/spi-qup.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ static void spi_qup_read_from_fifo(struct spi_qup *controller, u32 num_words)
266266
}
267267
}
268268

269-
static void spi_qup_read(struct spi_qup *controller)
269+
static void spi_qup_read(struct spi_qup *controller, u32 *opflags)
270270
{
271271
u32 remainder, words_per_block, num_words;
272272
bool is_block_mode = controller->mode == QUP_IO_M_MODE_BLOCK;
@@ -305,10 +305,12 @@ static void spi_qup_read(struct spi_qup *controller)
305305

306306
/*
307307
* Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block
308-
* mode reads, it has to be cleared again at the very end
308+
* reads, it has to be cleared again at the very end. However, be sure
309+
* to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
310+
* present and this is used to determine if transaction is complete
309311
*/
310-
if (is_block_mode && spi_qup_is_flag_set(controller,
311-
QUP_OP_MAX_INPUT_DONE_FLAG))
312+
*opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
313+
if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
312314
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
313315
controller->base + QUP_OPERATIONAL);
314316

@@ -613,7 +615,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
613615
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
614616
} else {
615617
if (opflags & QUP_OP_IN_SERVICE_FLAG)
616-
spi_qup_read(controller);
618+
spi_qup_read(controller, &opflags);
617619

618620
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
619621
spi_qup_write(controller);

0 commit comments

Comments
 (0)