From 5e0531f6b90ac096fedaf5bd0eae0bb4e5a39da5 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Wed, 7 Sep 2022 16:11:25 +0200 Subject: spi: Add capability to perform some transfer with chipselect off Some components require a few clock cycles with chipselect off before or/and after the data transfer done with CS on. Typically IDT 801034 QUAD PCM CODEC datasheet states "Note *: CCLK should have one cycle before CS goes low, and two cycles after CS goes high". The cycles "before" are implicitely provided by all previous activity on the SPI bus. But the cycles "after" must be provided in order to terminate the SPI transfer. In order to use that kind of component, add a cs_off flag to spi_transfer struct. When this flag is set, the transfer is performed with chipselect off. This allows consummer to add a dummy transfer at the end of the transfer list which is performed with chipselect OFF, providing the required additional clock cycles. Signed-off-by: Christophe Leroy Link: https://lore.kernel.org/r/434165c46f06d802690208a11e7ea2500e8da4c7.1662558898.git.christophe.leroy@csgroup.eu Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index e6c73d5ff1a8..6e6c62c59957 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -847,6 +847,7 @@ struct spi_res { * for this transfer. If 0 the default (from @spi_device) is used. * @dummy_data: indicates transfer is dummy bytes transfer. * @cs_change: affects chipselect after this transfer completes + * @cs_off: performs the transfer with chipselect off. * @cs_change_delay: delay between cs deassert and assert when * @cs_change is set and @spi_transfer is not the last in @spi_message * @delay: delay to be introduced after this transfer before @@ -959,6 +960,7 @@ struct spi_transfer { unsigned cs_change:1; unsigned tx_nbits:3; unsigned rx_nbits:3; + unsigned cs_off:1; #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ -- cgit From 86432b7f8f92b784c2e4af5b02766fb44052abf7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 8 Sep 2022 16:05:18 +0300 Subject: spi: Group cs_change and cs_off flags together in struct spi_transfer The commit 5e0531f6b90a ("spi: Add capability to perform some transfer with chipselect off") added a new flag but squeezed it into a wrong group of struct spi_transfer members (note that SPI_NBITS_* are macros for easier interpretation of the tx_nbits and rx_nbits bitfields). Group cs_change and cs_off flags together and their doc strings. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220908130518.32186-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6e6c62c59957..19acd4c9c7e3 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -846,8 +846,8 @@ struct spi_res { * @bits_per_word: select a bits_per_word other than the device default * for this transfer. If 0 the default (from @spi_device) is used. * @dummy_data: indicates transfer is dummy bytes transfer. - * @cs_change: affects chipselect after this transfer completes * @cs_off: performs the transfer with chipselect off. + * @cs_change: affects chipselect after this transfer completes * @cs_change_delay: delay between cs deassert and assert when * @cs_change is set and @spi_transfer is not the last in @spi_message * @delay: delay to be introduced after this transfer before @@ -957,10 +957,10 @@ struct spi_transfer { struct sg_table rx_sg; unsigned dummy_data:1; + unsigned cs_off:1; unsigned cs_change:1; unsigned tx_nbits:3; unsigned rx_nbits:3; - unsigned cs_off:1; #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ -- cgit From f25723dcef4a38f6a39e17afeabd1adf6402230e Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 27 Sep 2022 13:21:14 +0200 Subject: spi: Save current RX and TX DMA devices Save the current RX and TX DMA devices to avoid having to duplicate the logic to pick them, since we'll need access to them in some more functions to fix a bug in the cache handling. Signed-off-by: Vincent Whitchurch Link: https://lore.kernel.org/r/20220927112117.77599-2-vincent.whitchurch@axis.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 19 ++++--------------- include/linux/spi/spi.h | 4 ++++ 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index c582ae4deab3..a492a2a16fed 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1147,6 +1147,8 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) } } + ctlr->cur_rx_dma_dev = rx_dev; + ctlr->cur_tx_dma_dev = tx_dev; ctlr->cur_msg_mapped = true; return 0; @@ -1154,26 +1156,13 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg) { + struct device *rx_dev = ctlr->cur_rx_dma_dev; + struct device *tx_dev = ctlr->cur_tx_dma_dev; struct spi_transfer *xfer; - struct device *tx_dev, *rx_dev; if (!ctlr->cur_msg_mapped || !ctlr->can_dma) return 0; - if (ctlr->dma_tx) - tx_dev = ctlr->dma_tx->device->dev; - else if (ctlr->dma_map_dev) - tx_dev = ctlr->dma_map_dev; - else - tx_dev = ctlr->dev.parent; - - if (ctlr->dma_rx) - rx_dev = ctlr->dma_rx->device->dev; - else if (ctlr->dma_map_dev) - rx_dev = ctlr->dma_map_dev; - else - rx_dev = ctlr->dev.parent; - list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (!ctlr->can_dma(ctlr, msg->spi, xfer)) continue; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 19acd4c9c7e3..4b4041e9895a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -378,6 +378,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * @cleanup: frees controller-specific state * @can_dma: determine whether this controller supports DMA * @dma_map_dev: device which can be used for DMA mapping + * @cur_rx_dma_dev: device which is currently used for RX DMA mapping + * @cur_tx_dma_dev: device which is currently used for TX DMA mapping * @queued: whether this controller is providing an internal message queue * @kworker: pointer to thread struct for message pump * @pump_messages: work struct for scheduling work to the message pump @@ -609,6 +611,8 @@ struct spi_controller { struct spi_device *spi, struct spi_transfer *xfer); struct device *dma_map_dev; + struct device *cur_rx_dma_dev; + struct device *cur_tx_dma_dev; /* * These hooks are for drivers that want to use the generic -- cgit