summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorJonas Bonn <jonas@norrbonn.se>2019-01-30 09:40:04 +0100
committerMark Brown <broonie@kernel.org>2019-01-31 00:02:10 +0100
commitb7bb367afa4bf9de60830683305c63030c3e581d (patch)
tree9da3b46b4f696b5cb021a71831448e38cf7a8727 /drivers/spi
parentspi: mxs: add tracing to custom .transfer_one_message callback (diff)
downloadlinux-b7bb367afa4bf9de60830683305c63030c3e581d.tar.xz
linux-b7bb367afa4bf9de60830683305c63030c3e581d.zip
spi: support inter-word delay requirement for devices
Some devices are slow and cannot keep up with the SPI bus and therefore require a short delay between words of the SPI transfer. The example of this that I'm looking at is a SAMA5D2 with a minimum SPI clock of 400kHz talking to an AVR-based SPI slave. The AVR cannot put bytes on the bus fast enough to keep up with the SoC's SPI controller even at the lowest bus speed. This patch introduces the ability to specify a required inter-word delay for SPI devices. It is up to the controller driver to configure itself accordingly in order to introduce the requested delay. Note that, for spi_transfer, there is already a field word_delay that provides similar functionality. This field, however, is specified in clock cycles (and worse, SPI controller cycles, not SCK cycles); that makes this value dependent on the master clock instead of the device clock for which the delay is intended to provide some relief. This patch leaves this old word_delay in place and provides a time-based word_delay_us alongside it; the new field fits in the struct padding so struct size is constant. There is only one in-kernel user of the word_delay field and presumably that driver could be reworked to use the time-based value instead. The time-based delay is limited to 8 bits as these delays are intended to be short. The SAMA5D2 that I've tested this on limits delays to a maximum of ~100us, which is already many word-transfer periods even at the minimum transfer speed supported by the controller. Signed-off-by: Jonas Bonn <jonas@norrbonn.se> CC: Mark Brown <broonie@kernel.org> CC: Rob Herring <robh+dt@kernel.org> CC: Mark Rutland <mark.rutland@arm.com> CC: linux-spi@vger.kernel.org CC: devicetree@vger.kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 0e0f2c62973c..2f7176f07591 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3050,6 +3050,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
* it is not set for this transfer.
* Set transfer tx_nbits and rx_nbits as single transfer default
* (SPI_NBITS_SINGLE) if it is not set for this transfer.
+ * Ensure transfer word_delay is at least as long as that required by
+ * device itself.
*/
message->frame_length = 0;
list_for_each_entry(xfer, &message->transfers, transfer_list) {
@@ -3120,6 +3122,9 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
!(spi->mode & SPI_RX_QUAD))
return -EINVAL;
}
+
+ if (xfer->word_delay_usecs < spi->word_delay_usecs)
+ xfer->word_delay_usecs = spi->word_delay_usecs;
}
message->status = -EINPROGRESS;