Skip to content

Commit 14345c3

Browse files
fancerbroonie
authored andcommitted
spi: dw: Add poll-based SPI transfers support
A functionality of the poll-based transfer has been removed by commit 1ceb09717e98 ("spi: dw: remove cs_control and poll_mode members from chip_data") with a justification that "there is no user of one anymore". It turns out one of our DW APB SSI core is synthesized with no IRQ line attached and the only possible way of using it is to implement a poll-based SPI transfer procedure. So we have to get the removed functionality back, but with some alterations described below. First of all the poll-based transfer is activated only if the DW SPI controller doesn't have an IRQ line attached and the Linux IRQ number is initialized with the IRQ_NOTCONNECTED value. Secondly the transfer procedure is now executed with a delay performed between writer and reader methods. The delay value is calculated based on the number of data words expected to be received on the current iteration. Finally the errors status is checked on each iteration. Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Link: https://lore.kernel.org/r/20201007235511.4935-20-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 84ecaf4 commit 14345c3

1 file changed

Lines changed: 39 additions & 1 deletion

File tree

drivers/spi/spi-dw-core.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,42 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
364364
dws->transfer_handler = dw_spi_transfer_handler;
365365
}
366366

367+
/*
368+
* The iterative procedure of the poll-based transfer is simple: write as much
369+
* as possible to the Tx FIFO, wait until the pending to receive data is ready
370+
* to be read, read it from the Rx FIFO and check whether the performed
371+
* procedure has been successful.
372+
*
373+
* Note this method the same way as the IRQ-based transfer won't work well for
374+
* the SPI devices connected to the controller with native CS due to the
375+
* automatic CS assertion/de-assertion.
376+
*/
377+
static int dw_spi_poll_transfer(struct dw_spi *dws,
378+
struct spi_transfer *transfer)
379+
{
380+
struct spi_delay delay;
381+
u16 nbits;
382+
int ret;
383+
384+
delay.unit = SPI_DELAY_UNIT_SCK;
385+
nbits = dws->n_bytes * BITS_PER_BYTE;
386+
387+
do {
388+
dw_writer(dws);
389+
390+
delay.value = nbits * (dws->rx_len - dws->tx_len);
391+
spi_delay_exec(&delay, transfer);
392+
393+
dw_reader(dws);
394+
395+
ret = dw_spi_check_status(dws, true);
396+
if (ret)
397+
return ret;
398+
} while (dws->rx_len);
399+
400+
return 0;
401+
}
402+
367403
static int dw_spi_transfer_one(struct spi_controller *master,
368404
struct spi_device *spi, struct spi_transfer *transfer)
369405
{
@@ -408,6 +444,8 @@ static int dw_spi_transfer_one(struct spi_controller *master,
408444

409445
if (dws->dma_mapped)
410446
return dws->dma_ops->dma_transfer(dws, transfer);
447+
else if (dws->irq == IRQ_NOTCONNECTED)
448+
return dw_spi_poll_transfer(dws, transfer);
411449

412450
dw_spi_irq_setup(dws);
413451

@@ -817,7 +855,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
817855

818856
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
819857
master);
820-
if (ret < 0) {
858+
if (ret < 0 && ret != -ENOTCONN) {
821859
dev_err(dev, "can not get IRQ\n");
822860
goto err_free_master;
823861
}

0 commit comments

Comments
 (0)