linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay`
@ 2019-09-13 11:45 Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 01/15] spi: move `cs_change_delay` backwards compat logic outside switch Alexandru Ardelean
                   ` (15 more replies)
  0 siblings, 16 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

Initially, I started this patchset thinking: "we need a new delay for
something-something" (in case someone is curios, we need a CS-hold-time for
the first transfer, because the CS wakes a chip from sleep-mode).

Then I added the delay, and felt a bit dirty-inside about adding a new one
(just like that), and decided to look at maybe cleaning things up a bit,
and a few days later, I got here.

Full disclaimer: this patchset is not complete. It's an RFC.
It's based on top of Jonathan's `iio/togreg` branch which also includes the
ADIS driver library changes and also includes `cs_change_delay`.

I'll send a V2 patchset, which just the first 4 patches, since I feel that
those are a bit more complete.

I thought about just sending the first 4 patches on-their-own, but I
figured that the whole series (even if not complete) serves as a better
explanation about the whole "why?".

Hopefully, this can sort-of-explain things.
I'll reference this RFC on the next series.

Thanks

Alexandru Ardelean (15):
  spi: move `cs_change_delay` backwards compat logic outside switch
  spi: introduce spi_delay struct as "value + unit" &  spi_delay_exec()
  spi: make `cs_change_delay` the first user of the `spi_delay` logic
  iio: imu: adis: convert cs_change_delay to spi_delay struct
  spi: sprd: convert transfer word delay to spi_delay struct
  spi: orion: use new `word_delay` field for SPI transfers
  spi: spidev: use new `word_delay` field for spi transfers
  spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for
    spi_device
  spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec()
  spi: use new `spi_transfer_delay` helper where straightforward
  spi: tegra114: use `spi_transfer_delay` helper
  spi: spi-loopback-test: use new `delay` field
  spi: spidev: use new `delay` field for spi transfers
  spi: tegra114: change format for `spi_set_cs_timing()` function
  spi: implement SW control for CS times

 drivers/iio/imu/adis.c           |  24 ++---
 drivers/spi/spi-atmel.c          |  29 +++++-
 drivers/spi/spi-bcm63xx-hsspi.c  |   3 +-
 drivers/spi/spi-cavium.c         |   3 +-
 drivers/spi/spi-fsl-dspi.c       |   3 +-
 drivers/spi/spi-fsl-espi.c       |   3 +-
 drivers/spi/spi-fsl-spi.c        |   3 +-
 drivers/spi/spi-loopback-test.c  |  12 ++-
 drivers/spi/spi-mpc512x-psc.c    |   3 +-
 drivers/spi/spi-mpc52xx-psc.c    |   3 +-
 drivers/spi/spi-omap-100k.c      |   3 +-
 drivers/spi/spi-orion.c          |   6 +-
 drivers/spi/spi-pl022.c          |  25 +++--
 drivers/spi/spi-sc18is602.c      |   3 +-
 drivers/spi/spi-sh-hspi.c        |   3 +-
 drivers/spi/spi-sprd.c           |  11 ++-
 drivers/spi/spi-tegra114.c       |  39 +++++---
 drivers/spi/spi-tegra20-sflash.c |   2 +-
 drivers/spi/spi-topcliff-pch.c   |   7 +-
 drivers/spi/spi-txx9.c           |   3 +-
 drivers/spi/spi-xcomm.c          |   3 +-
 drivers/spi/spi.c                | 162 +++++++++++++++++++++++++------
 drivers/spi/spidev.c             |   6 +-
 include/linux/spi/spi.h          |  65 ++++++++++---
 24 files changed, 293 insertions(+), 131 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 01/15] spi: move `cs_change_delay` backwards compat logic outside switch
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 02/15] spi: introduce spi_delay struct as "value + unit" & spi_delay_exec() Alexandru Ardelean
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The `cs_change_delay` backwards compatibility value could be moved outside
of the switch statement.
The only reason to do it, is to make the next patches easier to diff.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 75ac046cae52..c90e02e6d62f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1114,16 +1114,15 @@ static void _spi_transfer_cs_change_delay(struct spi_message *msg,
 	u32 hz;
 
 	/* return early on "fast" mode - for everything but USECS */
-	if (!delay && unit != SPI_DELAY_UNIT_USECS)
+	if (!delay) {
+		if (unit == SPI_DELAY_UNIT_USECS)
+			_spi_transfer_delay_ns(10000);
 		return;
+	}
 
 	switch (unit) {
 	case SPI_DELAY_UNIT_USECS:
-		/* for compatibility use default of 10us */
-		if (!delay)
-			delay = 10000;
-		else
-			delay *= 1000;
+		delay *= 1000;
 		break;
 	case SPI_DELAY_UNIT_NSECS: /* nothing to do here */
 		break;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 02/15] spi: introduce spi_delay struct as "value + unit" & spi_delay_exec()
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 01/15] spi: move `cs_change_delay` backwards compat logic outside switch Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic Alexandru Ardelean
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

There are plenty of delays that have been introduced in SPI core. Most of
them are in micro-seconds, some need to be in nano-seconds, and some in
clock-cycles.

For some of these delays (related to transfers & CS timing) it may make
sense to have a `spi_delay` struct that abstracts these a bit.

The important element of these delays [for unification] seems to be the
`unit` of the delay.
It looks like micro-seconds is good enough for most people, but every-once
in a while, some delays seem to require other units of measurement.

This change adds the `spi_delay` struct & a `spi_delay_exec()` function
that processes a `spi_delay` object/struct to execute the delay.
It's a copy of the `cs_change_delay` mechanism, but without the default
for 10 uS.

The clock-cycle delay unit is a bit special, as it needs to be bound to an
`spi_transfer` object to execute.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi.c       | 51 +++++++++++++++++++++++++++++++++++++++++
 include/linux/spi/spi.h | 18 ++++++++++++---
 2 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c90e02e6d62f..1883de8ffa82 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1106,6 +1106,57 @@ static void _spi_transfer_delay_ns(u32 ns)
 	}
 }
 
+static int _spi_delay_to_ns(struct spi_delay *_delay, struct spi_transfer *xfer)
+{
+	u32 delay = _delay->value;
+	u32 unit = _delay->unit;
+	u32 hz;
+
+	if (!delay)
+		return 0;
+
+	switch (unit) {
+	case SPI_DELAY_UNIT_USECS:
+		delay *= 1000;
+		break;
+	case SPI_DELAY_UNIT_NSECS: /* nothing to do here */
+		break;
+	case SPI_DELAY_UNIT_SCK:
+		/* clock cycles need to be obtained from spi_transfer */
+		if (!xfer)
+			return -EINVAL;
+		/* if there is no effective speed know, then approximate
+		 * by underestimating with half the requested hz
+		 */
+		hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2;
+		if (!hz)
+			return -EINVAL;
+		delay *= DIV_ROUND_UP(1000000000, hz);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return delay;
+}
+
+int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer)
+{
+	int delay;
+
+	if (!_delay)
+		return -EINVAL;
+
+	delay = _spi_delay_to_ns(_delay, xfer);
+	if (delay < 0)
+		return delay;
+
+	_spi_transfer_delay_ns(delay);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_delay_exec);
+
 static void _spi_transfer_cs_change_delay(struct spi_message *msg,
 					  struct spi_transfer *xfer)
 {
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index af4f265d0f67..c18cfa7cda35 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -89,6 +89,21 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
 #define SPI_STATISTICS_INCREMENT_FIELD(stats, field)	\
 	SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1)
 
+/**
+ * struct spi_delay - SPI delay information
+ * @value: Value for the delay
+ * @unit: Unit for the delay
+ */
+struct spi_delay {
+#define SPI_DELAY_UNIT_USECS	0
+#define SPI_DELAY_UNIT_NSECS	1
+#define SPI_DELAY_UNIT_SCK	2
+	u16	value;
+	u8	unit;
+};
+
+extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer);
+
 /**
  * struct spi_device - Controller side proxy for an SPI slave device
  * @dev: Driver model representation of the device.
@@ -834,9 +849,6 @@ struct spi_transfer {
 	u16		delay_usecs;
 	u16		cs_change_delay;
 	u8		cs_change_delay_unit;
-#define SPI_DELAY_UNIT_USECS	0
-#define SPI_DELAY_UNIT_NSECS	1
-#define SPI_DELAY_UNIT_SCK	2
 	u32		speed_hz;
 	u16		word_delay;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 01/15] spi: move `cs_change_delay` backwards compat logic outside switch Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 02/15] spi: introduce spi_delay struct as "value + unit" & spi_delay_exec() Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-16 12:25   ` Mark Brown
  2019-09-13 11:45 ` [RFC PATCH 04/15] iio: imu: adis: convert cs_change_delay to spi_delay struct Alexandru Ardelean
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

Since the logic for `spi_delay` struct + `spi_delay_exec()` has been copied
from the `cs_change_delay` logic, it's natural to make this delay, the
first user.

The `cs_change_delay` logic requires that the default remain 10 uS, in case
it is unspecified/unconfigured. So, there is some special handling needed
to do that.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi.c       | 28 +++++++---------------------
 include/linux/spi/spi.h |  4 +---
 2 files changed, 8 insertions(+), 24 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 1883de8ffa82..d0bf0ffca042 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1160,9 +1160,9 @@ EXPORT_SYMBOL_GPL(spi_delay_exec);
 static void _spi_transfer_cs_change_delay(struct spi_message *msg,
 					  struct spi_transfer *xfer)
 {
-	u32 delay = xfer->cs_change_delay;
-	u32 unit = xfer->cs_change_delay_unit;
-	u32 hz;
+	u32 delay = xfer->cs_change_delay.value;
+	u32 unit = xfer->cs_change_delay.unit;
+	int ret;
 
 	/* return early on "fast" mode - for everything but USECS */
 	if (!delay) {
@@ -1171,27 +1171,13 @@ static void _spi_transfer_cs_change_delay(struct spi_message *msg,
 		return;
 	}
 
-	switch (unit) {
-	case SPI_DELAY_UNIT_USECS:
-		delay *= 1000;
-		break;
-	case SPI_DELAY_UNIT_NSECS: /* nothing to do here */
-		break;
-	case SPI_DELAY_UNIT_SCK:
-		/* if there is no effective speed know, then approximate
-		 * by underestimating with half the requested hz
-		 */
-		hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2;
-		delay *= DIV_ROUND_UP(1000000000, hz);
-		break;
-	default:
+	ret = spi_delay_exec(&xfer->cs_change_delay, xfer);
+	if (ret) {
 		dev_err_once(&msg->spi->dev,
 			     "Use of unsupported delay unit %i, using default of 10us\n",
-			     xfer->cs_change_delay_unit);
-		delay = 10000;
+			     unit);
+		_spi_transfer_delay_ns(10000);
 	}
-	/* now sleep for the requested amount of time */
-	_spi_transfer_delay_ns(delay);
 }
 
 /*
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index c18cfa7cda35..9ded3f44d58e 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -754,7 +754,6 @@ extern void spi_res_release(struct spi_controller *ctlr,
  * @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
- * @cs_change_delay_unit: unit of cs_change_delay
  * @delay_usecs: microseconds to delay after this transfer before
  *	(optionally) changing the chipselect status, then starting
  *	the next transfer or completing this @spi_message.
@@ -847,8 +846,7 @@ struct spi_transfer {
 	u8		bits_per_word;
 	u8		word_delay_usecs;
 	u16		delay_usecs;
-	u16		cs_change_delay;
-	u8		cs_change_delay_unit;
+	struct spi_delay	cs_change_delay;
 	u32		speed_hz;
 	u16		word_delay;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 04/15] iio: imu: adis: convert cs_change_delay to spi_delay struct
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (2 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 05/15] spi: sprd: convert transfer word delay " Alexandru Ardelean
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The ADIS library is one of the few users of the new `cs_change_delay`
parameter for an spi_transfer.

The introduction of the `spi_delay` struct, requires that the users of of
`cs_change_delay` get an update. This change updates the ADIS library.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/iio/imu/adis.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index 1631c255deab..2cd2cc2316c6 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -39,24 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
 			.len = 2,
 			.cs_change = 1,
 			.delay_usecs = adis->data->write_delay,
-			.cs_change_delay = adis->data->cs_change_delay,
-			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
+			.cs_change_delay.value = adis->data->cs_change_delay,
+			.cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
 		}, {
 			.tx_buf = adis->tx + 2,
 			.bits_per_word = 8,
 			.len = 2,
 			.cs_change = 1,
 			.delay_usecs = adis->data->write_delay,
-			.cs_change_delay = adis->data->cs_change_delay,
-			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
+			.cs_change_delay.value = adis->data->cs_change_delay,
+			.cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
 		}, {
 			.tx_buf = adis->tx + 4,
 			.bits_per_word = 8,
 			.len = 2,
 			.cs_change = 1,
 			.delay_usecs = adis->data->write_delay,
-			.cs_change_delay = adis->data->cs_change_delay,
-			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
+			.cs_change_delay.value = adis->data->cs_change_delay,
+			.cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
 		}, {
 			.tx_buf = adis->tx + 6,
 			.bits_per_word = 8,
@@ -139,16 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
 			.len = 2,
 			.cs_change = 1,
 			.delay_usecs = adis->data->write_delay,
-			.cs_change_delay = adis->data->cs_change_delay,
-			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
+			.cs_change_delay.value = adis->data->cs_change_delay,
+			.cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
 		}, {
 			.tx_buf = adis->tx + 2,
 			.bits_per_word = 8,
 			.len = 2,
 			.cs_change = 1,
 			.delay_usecs = adis->data->read_delay,
-			.cs_change_delay = adis->data->cs_change_delay,
-			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
+			.cs_change_delay.value = adis->data->cs_change_delay,
+			.cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
 		}, {
 			.tx_buf = adis->tx + 4,
 			.rx_buf = adis->rx,
@@ -156,8 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
 			.len = 2,
 			.cs_change = 1,
 			.delay_usecs = adis->data->read_delay,
-			.cs_change_delay = adis->data->cs_change_delay,
-			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
+			.cs_change_delay.value = adis->data->cs_change_delay,
+			.cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
 		}, {
 			.rx_buf = adis->rx + 2,
 			.bits_per_word = 8,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 05/15] spi: sprd: convert transfer word delay to spi_delay struct
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (3 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 04/15] iio: imu: adis: convert cs_change_delay to spi_delay struct Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 06/15] spi: orion: use new `word_delay` field for SPI transfers Alexandru Ardelean
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The Spreadtrum SPI driver is the only user of the `word_delay` field in
the `spi_transfer` struct.

This change converts the field to use the `spi_delay` struct. This also
enforces the users to specify the delay unit to be `SPI_DELAY_UNIT_SCK`.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-sprd.c  | 11 +++++++++--
 include/linux/spi/spi.h |  4 ++--
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c
index 1b7eebb72c07..5634cd3e4a8d 100644
--- a/drivers/spi/spi-sprd.c
+++ b/drivers/spi/spi-sprd.c
@@ -671,9 +671,13 @@ static void sprd_spi_set_speed(struct sprd_spi *ss, u32 speed_hz)
 
 static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t)
 {
+	struct spi_delay *d = &t->word_delay;
 	u16 word_delay, interval;
 	u32 val;
 
+	if (t->unit != SPI_DELAY_UNIT_SCK)
+		return -EINVAL;
+
 	val = readl_relaxed(ss->base + SPRD_SPI_CTL7);
 	val &= ~(SPRD_SPI_SCK_REV | SPRD_SPI_NG_TX | SPRD_SPI_NG_RX);
 	/* Set default chip selection, clock phase and clock polarity */
@@ -686,7 +690,7 @@ static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t)
 	 * formula as below per datasheet:
 	 * interval time (source clock cycles) = interval * 4 + 10.
 	 */
-	word_delay = clamp_t(u16, t->word_delay, SPRD_SPI_MIN_DELAY_CYCLE,
+	word_delay = clamp_t(u16, d->value, SPRD_SPI_MIN_DELAY_CYCLE,
 			     SPRD_SPI_MAX_DELAY_CYCLE);
 	interval = DIV_ROUND_UP(word_delay - 10, 4);
 	ss->word_delay = interval * 4 + 10;
@@ -719,13 +723,16 @@ static int sprd_spi_setup_transfer(struct spi_device *sdev,
 	struct sprd_spi *ss = spi_controller_get_devdata(sdev->controller);
 	u8 bits_per_word = t->bits_per_word;
 	u32 val, mode = 0;
+	int ret;
 
 	ss->len = t->len;
 	ss->tx_buf = t->tx_buf;
 	ss->rx_buf = t->rx_buf;
 
 	ss->hw_mode = sdev->mode;
-	sprd_spi_init_hw(ss, t);
+	ret = sprd_spi_init_hw(ss, t);
+	if (ret)
+		return ret;
 
 	/* Set tansfer speed and valid bits */
 	sprd_spi_set_speed(ss, t->speed_hz);
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 9ded3f44d58e..16397b210e0c 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -759,7 +759,7 @@ extern void spi_res_release(struct spi_controller *ctlr,
  *	the next transfer or completing this @spi_message.
  * @word_delay_usecs: microseconds to inter word delay after each word size
  *	(set by bits_per_word) transmission.
- * @word_delay: clock cycles to inter word delay after each word size
+ * @word_delay: inter word delay to be introduced after each word size
  *	(set by bits_per_word) transmission.
  * @effective_speed_hz: the effective SCK-speed that was used to
  *      transfer this transfer. Set to 0 if the spi bus driver does
@@ -847,8 +847,8 @@ struct spi_transfer {
 	u8		word_delay_usecs;
 	u16		delay_usecs;
 	struct spi_delay	cs_change_delay;
+	struct spi_delay	word_delay;
 	u32		speed_hz;
-	u16		word_delay;
 
 	u32		effective_speed_hz;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 06/15] spi: orion: use new `word_delay` field for SPI transfers
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (4 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 05/15] spi: sprd: convert transfer word delay " Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 07/15] spi: spidev: use new `word_delay` field for spi transfers Alexandru Ardelean
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The `word_delay` field had it's type changed to `struct spi_delay`.
This allows users to specify nano-second or clock-cycle delays (if needed).

Converting to use `word_delay` is straightforward: it just uses the new
`spi_delay_exec()` routine, that handles the `unit` part.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-orion.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 6643ccdc2508..756c37e32dfe 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -467,8 +467,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 			if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0)
 				goto out;
 			count--;
-			if (xfer->word_delay_usecs)
-				udelay(xfer->word_delay_usecs);
+			spi_delay_exec(&xfer->word_delay, xfer);
 		} while (count);
 	} else if (word_len == 16) {
 		const u16 *tx = xfer->tx_buf;
@@ -478,8 +477,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 			if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0)
 				goto out;
 			count -= 2;
-			if (xfer->word_delay_usecs)
-				udelay(xfer->word_delay_usecs);
+			spi_delay_exec(&xfer->word_delay, xfer);
 		} while (count);
 	}
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 07/15] spi: spidev: use new `word_delay` field for spi transfers
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (5 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 06/15] spi: orion: use new `word_delay` field for SPI transfers Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 08/15] spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for spi_device Alexandru Ardelean
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The `word_delay` field had it's type changed to `struct spi_delay`.
This allows users to specify nano-second or clock-cycle delays (if needed).

Converting to use `word_delay` is straightforward: it's just assigning the
value to `word_delay.value` and hard-coding the `word_delay.unit` to
`SPI_DELAY_UNIT_USECS`

This keeps the uapi for spidev un-changed. Changing it can be part of
another changeset and discussion.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spidev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 255786f2e844..495319c2fa11 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -267,7 +267,8 @@ static int spidev_message(struct spidev_data *spidev,
 		k_tmp->bits_per_word = u_tmp->bits_per_word;
 		k_tmp->delay_usecs = u_tmp->delay_usecs;
 		k_tmp->speed_hz = u_tmp->speed_hz;
-		k_tmp->word_delay_usecs = u_tmp->word_delay_usecs;
+		k_tmp->word_delay.value = u_tmp->word_delay_usecs;
+		k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS;
 		if (!k_tmp->speed_hz)
 			k_tmp->speed_hz = spidev->speed_hz;
 #ifdef VERBOSE
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 08/15] spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for spi_device
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (6 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 07/15] spi: spidev: use new `word_delay` field for spi transfers Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 09/15] spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec() Alexandru Ardelean
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

This change does a conversion from the `word_delay_usecs` -> `word_delay`
for the `spi_device` struct.

This allows users to specify inter-word delays in other unit types
(nano-seconds or clock cycles), depending on how users want.

The Atmel SPI driver is the only current user of the `word_delay_usecs`
field (from the `spi_device` struct).
So, it needed a slight conversion to use the `word_delay` as an `spi_delay`
struct.

In SPI core, the only required mechanism is to update the `word_delay`
information per `spi_transfer`. This requires a bit more logic than before,
because it needs that both delays be converted to a common unit
(nano-seconds) for comparison.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-atmel.c | 26 ++++++++++++++++++++++++--
 drivers/spi/spi.c       | 24 ++++++++++++++++++++++--
 include/linux/spi/spi.h |  7 ++-----
 3 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index f00b367523cd..009bb4fb5e5f 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1172,12 +1172,31 @@ atmel_spi_pdc_interrupt(int irq, void *dev_id)
 	return ret;
 }
 
+static int atmel_word_delay_csr(struct spi_device *spi, struct atmel_spi *as)
+{
+	struct spi_delay *delay = &spi->word_delay;
+	u32 value = delay->value;
+
+	switch (delay->unit) {
+	case SPI_DELAY_UNIT_NSECS:
+		value /= 1000;
+		break;
+	case SPI_DELAY_UNIT_USECS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return (as->spi_clk / 1000000 * value) >> 5;
+}
+
 static int atmel_spi_setup(struct spi_device *spi)
 {
 	struct atmel_spi	*as;
 	struct atmel_spi_device	*asd;
 	u32			csr;
 	unsigned int		bits = spi->bits_per_word;
+	int			word_delay_csr;
 
 	as = spi_master_get_devdata(spi->master);
 
@@ -1201,11 +1220,14 @@ static int atmel_spi_setup(struct spi_device *spi)
 	 */
 	csr |= SPI_BF(DLYBS, 0);
 
+	word_delay_csr = atmel_word_delay_csr(as, spi);
+	if (word_delay_csr < 0)
+		return word_delay_csr;
+
 	/* DLYBCT adds delays between words.  This is useful for slow devices
 	 * that need a bit of time to setup the next transfer.
 	 */
-	csr |= SPI_BF(DLYBCT,
-			(as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5);
+	csr |= SPI_BF(DLYBCT, word_delay_csr);
 
 	asd = spi->controller_state;
 	if (!asd) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index d0bf0ffca042..ba8731b77753 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3159,6 +3159,26 @@ void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold,
 }
 EXPORT_SYMBOL_GPL(spi_set_cs_timing);
 
+static int _spi_xfer_word_delay_update(struct spi_transfer *xfer,
+				       struct spi_device *spi)
+{
+	int delay1, delay2;
+
+	delay1 = _spi_delay_to_ns(&xfer->word_delay, xfer);
+	if (delay1 < 0)
+		return delay1;
+
+	delay2 = _spi_delay_to_ns(&spi->word_delay, xfer);
+	if (delay2 < 0)
+		return delay2;
+
+	if (delay1 < delay2)
+		memcpy(&xfer->word_delay, &spi->word_delay,
+		       sizeof(xfer->word_delay));
+
+	return 0;
+}
+
 static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 {
 	struct spi_controller *ctlr = spi->controller;
@@ -3294,8 +3314,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 				return -EINVAL;
 		}
 
-		if (xfer->word_delay_usecs < spi->word_delay_usecs)
-			xfer->word_delay_usecs = spi->word_delay_usecs;
+		if (_spi_xfer_word_delay_update(xfer, spi))
+			return -EINVAL;
 	}
 
 	message->status = -EINPROGRESS;
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 16397b210e0c..e7ec0be16a82 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -138,7 +138,7 @@ extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer);
  *	the spi_master.
  * @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when
  *	not using a GPIO line)
- * @word_delay_usecs: microsecond delay to be inserted between consecutive
+ * @word_delay: delay to be inserted between consecutive
  *	words of a transfer
  *
  * @statistics: statistics for the spi_device
@@ -188,7 +188,7 @@ struct spi_device {
 	const char		*driver_override;
 	int			cs_gpio;	/* LEGACY: chip select gpio */
 	struct gpio_desc	*cs_gpiod;	/* chip select gpio desc */
-	uint8_t			word_delay_usecs; /* inter-word delay */
+	struct spi_delay	word_delay; /* inter-word delay */
 
 	/* the statistics */
 	struct spi_statistics	statistics;
@@ -757,8 +757,6 @@ extern void spi_res_release(struct spi_controller *ctlr,
  * @delay_usecs: microseconds to delay after this transfer before
  *	(optionally) changing the chipselect status, then starting
  *	the next transfer or completing this @spi_message.
- * @word_delay_usecs: microseconds to inter word delay after each word size
- *	(set by bits_per_word) transmission.
  * @word_delay: inter word delay to be introduced after each word size
  *	(set by bits_per_word) transmission.
  * @effective_speed_hz: the effective SCK-speed that was used to
@@ -844,7 +842,6 @@ struct spi_transfer {
 #define	SPI_NBITS_DUAL		0x02 /* 2bits transfer */
 #define	SPI_NBITS_QUAD		0x04 /* 4bits transfer */
 	u8		bits_per_word;
-	u8		word_delay_usecs;
 	u16		delay_usecs;
 	struct spi_delay	cs_change_delay;
 	struct spi_delay	word_delay;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 09/15] spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec()
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (7 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 08/15] spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for spi_device Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 10/15] spi: use new `spi_transfer_delay` helper where straightforward Alexandru Ardelean
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The change introduces the `delay` field to the `spi_transfer` struct as an
`struct spi_delay` type.
This intends to eventually replace `delay_usecs`.

But, since there are many users of `delay_usecs`, this needs some
intermediate work.
A helper called `spi_transfer_delay()` is also added, which maintains
backwards compatibility with `delay_usecs`, by assigning the value to
`delay` if non-zero.
This should maintain backwards compatibility with current users of
`udelay_usecs`.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi.c       |  6 +++---
 include/linux/spi/spi.h | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index ba8731b77753..c55d55acbbb0 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1238,8 +1238,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
 		if (msg->status != -EINPROGRESS)
 			goto out;
 
-		if (xfer->delay_usecs)
-			_spi_transfer_delay_ns(xfer->delay_usecs * 1000);
+		spi_transfer_delay(xfer);
 
 		if (xfer->cs_change) {
 			if (list_is_last(&xfer->transfer_list,
@@ -2904,10 +2903,11 @@ struct spi_replaced_transfers *spi_replace_transfers(
 		/* add to list */
 		list_add(&xfer->transfer_list, rxfer->replaced_after);
 
-		/* clear cs_change and delay_usecs for all but the last */
+		/* clear cs_change and delay for all but the last */
 		if (i) {
 			xfer->cs_change = false;
 			xfer->delay_usecs = 0;
+			xfer->delay.value = 0;
 		}
 	}
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index e7ec0be16a82..c7f90a0129be 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -754,6 +754,9 @@ extern void spi_res_release(struct spi_controller *ctlr,
  * @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
+ *	(optionally) changing the chipselect status, then starting
+ *	the next transfer or completing this @spi_message.
  * @delay_usecs: microseconds to delay after this transfer before
  *	(optionally) changing the chipselect status, then starting
  *	the next transfer or completing this @spi_message.
@@ -843,6 +846,7 @@ struct spi_transfer {
 #define	SPI_NBITS_QUAD		0x04 /* 4bits transfer */
 	u8		bits_per_word;
 	u16		delay_usecs;
+	struct spi_delay	delay;
 	struct spi_delay	cs_change_delay;
 	struct spi_delay	word_delay;
 	u32		speed_hz;
@@ -942,6 +946,20 @@ spi_transfer_del(struct spi_transfer *t)
 	list_del(&t->transfer_list);
 }
 
+static inline int
+spi_transfer_delay(struct spi_transfer *t)
+{
+	struct spi_delay d;
+
+	if (t->delay_usecs) {
+		d.value = t->delay_usecs;
+		d.unit = SPI_DELAY_UNIT_USECS;
+		return spi_delay_exec(&d, NULL);
+	}
+
+	return spi_delay_exec(&t->delay, t);
+}
+
 /**
  * spi_message_init_with_transfers - Initialize spi_message and append transfers
  * @m: spi_message to be initialized
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 10/15] spi: use new `spi_transfer_delay` helper where straightforward
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (8 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 09/15] spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec() Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 11/15] spi: tegra114: use `spi_transfer_delay` helper Alexandru Ardelean
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

For many places in the spi drivers, using the new `spi_transfer_delay`
helper is straightforward.
It's just replacing:
```
  if (t->delay_usecs)
     udelay(t->delay_usecs);
```
with `spi_transfer_delay(t)` which handles both `delay_usecs` and the new
`delay` field.

This change replaces in all places (in the spi drivers)  where this change
is simple.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-atmel.c          |  3 +--
 drivers/spi/spi-bcm63xx-hsspi.c  |  3 +--
 drivers/spi/spi-cavium.c         |  3 +--
 drivers/spi/spi-fsl-dspi.c       |  3 +--
 drivers/spi/spi-fsl-espi.c       |  3 +--
 drivers/spi/spi-fsl-spi.c        |  3 +--
 drivers/spi/spi-mpc512x-psc.c    |  3 +--
 drivers/spi/spi-mpc52xx-psc.c    |  3 +--
 drivers/spi/spi-omap-100k.c      |  3 +--
 drivers/spi/spi-pl022.c          | 25 +++++++++++--------------
 drivers/spi/spi-sc18is602.c      |  3 +--
 drivers/spi/spi-sh-hspi.c        |  3 +--
 drivers/spi/spi-tegra20-sflash.c |  2 +-
 drivers/spi/spi-topcliff-pch.c   |  7 +------
 drivers/spi/spi-txx9.c           |  3 +--
 drivers/spi/spi-xcomm.c          |  3 +--
 16 files changed, 26 insertions(+), 47 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 009bb4fb5e5f..f51af930c7a4 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1389,8 +1389,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 		&& as->use_pdc)
 		atmel_spi_dma_unmap_xfer(master, xfer);
 
-	if (xfer->delay_usecs)
-		udelay(xfer->delay_usecs);
+	spi_transfer_delay(xfer);
 
 	if (xfer->cs_change) {
 		if (list_is_last(&xfer->transfer_list,
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index 9a06ffdb73b8..d9f5c241e2aa 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -291,8 +291,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
 
 		msg->actual_length += t->len;
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		if (t->cs_change)
 			bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);
diff --git a/drivers/spi/spi-cavium.c b/drivers/spi/spi-cavium.c
index 5aaf21582cb5..db7f5f94c525 100644
--- a/drivers/spi/spi-cavium.c
+++ b/drivers/spi/spi-cavium.c
@@ -119,8 +119,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
 			*rx_buf++ = (u8)v;
 		}
 
-	if (xfer->delay_usecs)
-		udelay(xfer->delay_usecs);
+	spi_transfer_delay(xfer);
 
 	return xfer->len;
 }
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 53335ccc98f6..0b761352c16a 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -752,8 +752,7 @@ static int dspi_transfer_one_message(struct spi_master *master,
 			dspi->waitflags = 0;
 		}
 
-		if (transfer->delay_usecs)
-			udelay(transfer->delay_usecs);
+		spi_transfer_delay(transfer);
 	}
 
 out:
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index f20326714b9d..a3af12127c40 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -427,8 +427,7 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
 
 	ret = fsl_espi_bufs(spi, trans);
 
-	if (trans->delay_usecs)
-		udelay(trans->delay_usecs);
+	spi_transfer_delay(trans);
 
 	return ret;
 }
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 1d9b33aa1a3b..9352b127d5b8 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -417,8 +417,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
 		}
 		m->actual_length += t->len;
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		if (cs_change) {
 			ndelay(nsecs);
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index a337b842ae8c..329bbdd1f15f 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -311,8 +311,7 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
 			break;
 		m->actual_length += t->len;
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		if (cs_change)
 			mpc512x_psc_spi_deactivate_cs(spi);
diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c
index c7e478b9b586..dd79d7fd3687 100644
--- a/drivers/spi/spi-mpc52xx-psc.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -234,8 +234,7 @@ static void mpc52xx_psc_spi_work(struct work_struct *work)
 				break;
 			m->actual_length += t->len;
 
-			if (t->delay_usecs)
-				udelay(t->delay_usecs);
+			spi_transfer_delay(t);
 
 			if (cs_change)
 				mpc52xx_psc_spi_deactivate_cs(spi);
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
index b955ca8796d2..eb5b51bd5126 100644
--- a/drivers/spi/spi-omap-100k.c
+++ b/drivers/spi/spi-omap-100k.c
@@ -321,8 +321,7 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
 			}
 		}
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		/* ignore the "leave it on after last xfer" hint */
 
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 7fedea67159c..42cf800073e4 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -485,12 +485,11 @@ static void giveback(struct pl022 *pl022)
 					struct spi_transfer, transfer_list);
 
 	/* Delay if requested before any change in chip select */
-	if (last_transfer->delay_usecs)
-		/*
-		 * FIXME: This runs in interrupt context.
-		 * Is this really smart?
-		 */
-		udelay(last_transfer->delay_usecs);
+	/*
+	 * FIXME: This runs in interrupt context.
+	 * Is this really smart?
+	 */
+	spi_transfer_delay(last_transfer);
 
 	if (!last_transfer->cs_change) {
 		struct spi_message *next_msg;
@@ -1401,12 +1400,11 @@ static void pump_transfers(unsigned long data)
 		previous = list_entry(transfer->transfer_list.prev,
 					struct spi_transfer,
 					transfer_list);
-		if (previous->delay_usecs)
-			/*
-			 * FIXME: This runs in interrupt context.
-			 * Is this really smart?
-			 */
-			udelay(previous->delay_usecs);
+		/*
+		 * FIXME: This runs in interrupt context.
+		 * Is this really smart?
+		 */
+		spi_transfer_delay(previous);
 
 		/* Reselect chip select only if cs_change was requested */
 		if (previous->cs_change)
@@ -1520,8 +1518,7 @@ static void do_polling_transfer(struct pl022 *pl022)
 			previous =
 			    list_entry(transfer->transfer_list.prev,
 				       struct spi_transfer, transfer_list);
-			if (previous->delay_usecs)
-				udelay(previous->delay_usecs);
+			spi_transfer_delay(previous);
 			if (previous->cs_change)
 				pl022_cs_control(pl022, SSP_CHIP_SELECT);
 		} else {
diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c
index 11acddc83304..13cb992df712 100644
--- a/drivers/spi/spi-sc18is602.c
+++ b/drivers/spi/spi-sc18is602.c
@@ -211,8 +211,7 @@ static int sc18is602_transfer_one(struct spi_master *master,
 		}
 		status = 0;
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 	}
 	m->status = status;
 	spi_finalize_current_message(master);
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 7f73f91d412a..4edad22c222e 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -190,8 +190,7 @@ static int hspi_transfer_one_message(struct spi_controller *ctlr,
 
 		msg->actual_length += t->len;
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		if (cs_change) {
 			ndelay(nsecs);
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index cd714a4f52c6..00593096cfed 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -344,7 +344,7 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master,
 		if (xfer->cs_change && xfer->delay_usecs) {
 			tegra_sflash_writel(tsd, tsd->def_command_reg,
 					SPI_COMMAND);
-			udelay(xfer->delay_usecs);
+			spi_transfer_delay(xfer);
 		}
 	}
 	ret = 0;
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index f88cbb94ce12..645b086eece8 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1229,12 +1229,7 @@ static void pch_spi_process_messages(struct work_struct *pwork)
 			"%s:data->current_msg->actual_length=%d\n",
 			__func__, data->current_msg->actual_length);
 
-		/* check for delay */
-		if (data->cur_trans->delay_usecs) {
-			dev_dbg(&data->master->dev, "%s:delay in usec=%d\n",
-				__func__, data->cur_trans->delay_usecs);
-			udelay(data->cur_trans->delay_usecs);
-		}
+		spi_transfer_delay(data->cur_trans);
 
 		spin_lock(&data->lock);
 
diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c
index 51759d3fd45f..65aa736783ae 100644
--- a/drivers/spi/spi-txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -248,8 +248,7 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
 			len -= count * wsize;
 		}
 		m->actual_length += t->len;
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		if (!cs_change)
 			continue;
diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c
index a3496c46cc1b..3aaae32b0384 100644
--- a/drivers/spi/spi-xcomm.c
+++ b/drivers/spi/spi-xcomm.c
@@ -188,8 +188,7 @@ static int spi_xcomm_transfer_one(struct spi_master *master,
 		}
 		status = 0;
 
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
+		spi_transfer_delay(t);
 
 		is_first = false;
 	}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 11/15] spi: tegra114: use `spi_transfer_delay` helper
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (9 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 10/15] spi: use new `spi_transfer_delay` helper where straightforward Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 12/15] spi: spi-loopback-test: use new `delay` field Alexandru Ardelean
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The tegra114 driver has a weird/separate `tegra_spi_transfer_delay()`
function that does 2 delays: one mdelay() and one udelay().

This was introduced via commit f4fade12d506e14867a2b0a5e2f7aaf227297d8b
("spi/tegra114: Correct support for cs_change").

There doesn't seem to be a mention in that commit message to suggest a
specific need/use-case for having the 2 delay calls.
For the most part, udelay() should be sufficient.

This change replaces it with the new `spi_transfer_delay()`, which should
do the same thing.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-tegra114.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 39374c2edcf3..5ac2ceb234fc 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -984,17 +984,6 @@ static int tegra_spi_setup(struct spi_device *spi)
 	return 0;
 }
 
-static void tegra_spi_transfer_delay(int delay)
-{
-	if (!delay)
-		return;
-
-	if (delay >= 1000)
-		mdelay(delay / 1000);
-
-	udelay(delay % 1000);
-}
-
 static void tegra_spi_transfer_end(struct spi_device *spi)
 {
 	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
@@ -1098,7 +1087,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
 complete_xfer:
 		if (ret < 0 || skip) {
 			tegra_spi_transfer_end(spi);
-			tegra_spi_transfer_delay(xfer->delay_usecs);
+			spi_transfer_delay(xfer);
 			goto exit;
 		} else if (list_is_last(&xfer->transfer_list,
 					&msg->transfers)) {
@@ -1106,11 +1095,11 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
 				tspi->cs_control = spi;
 			else {
 				tegra_spi_transfer_end(spi);
-				tegra_spi_transfer_delay(xfer->delay_usecs);
+				spi_transfer_delay(xfer);
 			}
 		} else if (xfer->cs_change) {
 			tegra_spi_transfer_end(spi);
-			tegra_spi_transfer_delay(xfer->delay_usecs);
+			spi_transfer_delay(xfer);
 		}
 
 	}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 12/15] spi: spi-loopback-test: use new `delay` field
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (10 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 11/15] spi: tegra114: use `spi_transfer_delay` helper Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 13/15] spi: spidev: use new `delay` field for spi transfers Alexandru Ardelean
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

This change replaces the use of the `delay_usecs` field with the new
`delay` field. The code/test still uses micro-seconds, but they are now
configured and used via the `struct spi_delay` format of the `delay` field.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-loopback-test.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c
index 6f18d4952767..b6d79cd156fb 100644
--- a/drivers/spi/spi-loopback-test.c
+++ b/drivers/spi/spi-loopback-test.c
@@ -298,12 +298,18 @@ static struct spi_test spi_tests[] = {
 			{
 				.tx_buf = TX(0),
 				.rx_buf = RX(0),
-				.delay_usecs = 1000,
+				.delay = {
+					.value = 1000,
+					.unit = SPI_DELAY_UNIT_USECS,
+				},
 			},
 			{
 				.tx_buf = TX(0),
 				.rx_buf = RX(0),
-				.delay_usecs = 1000,
+				.delay = {
+					.value = 1000,
+					.unit = SPI_DELAY_UNIT_USECS,
+				},
 			},
 		},
 	},
@@ -537,7 +543,7 @@ static int spi_test_check_elapsed_time(struct spi_device *spi,
 		unsigned long long nbits = (unsigned long long)BITS_PER_BYTE *
 					   xfer->len;
 
-		delay_usecs += xfer->delay_usecs;
+		delay_usecs += xfer->delay.value;
 		if (!xfer->speed_hz)
 			continue;
 		estimated_time += div_u64(nbits * NSEC_PER_SEC, xfer->speed_hz);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 13/15] spi: spidev: use new `delay` field for spi transfers
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (11 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 12/15] spi: spi-loopback-test: use new `delay` field Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 14/15] spi: tegra114: change format for `spi_set_cs_timing()` function Alexandru Ardelean
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The `delay` field has type `struct spi_delay`.
This allows users to specify nano-second or clock-cycle delays (if needed).

Converting to use `delay` is straightforward: it's just assigning the
value to `delay.value` and hard-coding the `delay.unit` to
`SPI_DELAY_UNIT_USECS`.

This keeps the uapi for spidev un-changed. Changing it can be part of
another changeset and discussion.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spidev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 495319c2fa11..6b6afd27f4a1 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -265,7 +265,8 @@ static int spidev_message(struct spidev_data *spidev,
 		k_tmp->tx_nbits = u_tmp->tx_nbits;
 		k_tmp->rx_nbits = u_tmp->rx_nbits;
 		k_tmp->bits_per_word = u_tmp->bits_per_word;
-		k_tmp->delay_usecs = u_tmp->delay_usecs;
+		k_tmp->delay.value = u_tmp->delay_usecs;
+		k_tmp->delay.unit = SPI_DELAY_UNIT_USECS;
 		k_tmp->speed_hz = u_tmp->speed_hz;
 		k_tmp->word_delay.value = u_tmp->word_delay_usecs;
 		k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 14/15] spi: tegra114: change format for `spi_set_cs_timing()` function
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (12 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 13/15] spi: spidev: use new `delay` field for spi transfers Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-13 11:45 ` [RFC PATCH 15/15] spi: implement SW control for CS times Alexandru Ardelean
  2019-09-15 10:22 ` [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Jonathan Cameron
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

The initial version of `spi_set_cs_timing()` was implemented with
consideration only for clock-cycles as delay.

For cases like `CS setup` time, it's sometimes needed that micro-seconds
(or nano-seconds) are required, or sometimes even longer delays, for cases
where the device needs a little longer to start transferring that after CS
is asserted.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi-tegra114.c | 22 ++++++++++++++++++++--
 drivers/spi/spi.c          | 16 ++++++++++------
 include/linux/spi/spi.h    |  9 ++++++---
 3 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 5ac2ceb234fc..d8db4af08fff 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -723,15 +723,31 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
 	dma_release_channel(dma_chan);
 }
 
-static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly,
-				       u8 hold_dly, u8 inactive_dly)
+static int tegra_spi_set_hw_cs_timing(struct spi_device *spi,
+				      struct spi_delay *setup,
+				      struct spi_delay *hold,
+				      struct spi_delay *inactive)
 {
 	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
+	u8 setup_dly, hold_dly, inactive_dly;
 	u32 setup_hold;
 	u32 spi_cs_timing;
 	u32 inactive_cycles;
 	u8 cs_state;
 
+	if ((setup && setup->unit != SPI_DELAY_UNIT_SCK) ||
+	    (hold && hold->unit != SPI_DELAY_UNIT_SCK) ||
+	    (inactive && inactive != SPI_DELAY_UNIT_SCK)) {
+		dev_err(&spi->dev,
+			"Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n",
+			SPI_DELAY_UNIT_SCK);
+		return -EINVAL;
+	}
+
+	setup_dly = setup ? setup->value : 0;
+	hold_dly = hold ? hold->value : 0;
+	inactive_dly = inactive ? inactive->value : 0;
+
 	setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES);
 	hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES);
 	if (setup_dly && hold_dly) {
@@ -758,6 +774,8 @@ static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly,
 		tspi->spi_cs_timing2 = spi_cs_timing;
 		tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2);
 	}
+
+	return 0;
 }
 
 static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c55d55acbbb0..54d00c0a26d2 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3147,15 +3147,19 @@ EXPORT_SYMBOL_GPL(spi_setup);
 /**
  * spi_set_cs_timing - configure CS setup, hold, and inactive delays
  * @spi: the device that requires specific CS timing configuration
- * @setup: CS setup time in terms of clock count
- * @hold: CS hold time in terms of clock count
- * @inactive_dly: CS inactive delay between transfers in terms of clock count
+ * @setup: CS setup time specified via @spi_delay
+ * @hold: CS hold time specified via @spi_delay
+ * @inactive: CS inactive delay between transfers specified via @spi_delay
+ *
+ * Return: zero on success, else a negative error code.
  */
-void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold,
-		       u8 inactive_dly)
+int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup,
+		      struct spi_delay *hold, struct spi_delay *inactive)
 {
 	if (spi->controller->set_cs_timing)
-		spi->controller->set_cs_timing(spi, setup, hold, inactive_dly);
+		return spi->controller->set_cs_timing(spi, setup, hold,
+						      inactive);
+	return -ENOTSUPP;
 }
 EXPORT_SYMBOL_GPL(spi_set_cs_timing);
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index c7f90a0129be..292e752ce34a 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -517,8 +517,8 @@ struct spi_controller {
 	 * to configure specific CS timing through spi_set_cs_timing() after
 	 * spi_setup().
 	 */
-	void (*set_cs_timing)(struct spi_device *spi, u8 setup_clk_cycles,
-			      u8 hold_clk_cycles, u8 inactive_clk_cycles);
+	int (*set_cs_timing)(struct spi_device *spi, struct spi_delay *setup,
+			     struct spi_delay *hold, struct spi_delay *inactive);
 
 	/* bidirectional bulk transfers
 	 *
@@ -1007,7 +1007,10 @@ static inline void spi_message_free(struct spi_message *m)
 	kfree(m);
 }
 
-extern void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, u8 inactive_dly);
+extern int spi_set_cs_timing(struct spi_device *spi,
+			     struct spi_delay *setup,
+			     struct spi_delay *hold,
+			     struct spi_delay *inactive);
 
 extern int spi_setup(struct spi_device *spi);
 extern int spi_async(struct spi_device *spi, struct spi_message *message);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 15/15] spi: implement SW control for CS times
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (13 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 14/15] spi: tegra114: change format for `spi_set_cs_timing()` function Alexandru Ardelean
@ 2019-09-13 11:45 ` Alexandru Ardelean
  2019-09-15 10:22 ` [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Jonathan Cameron
  15 siblings, 0 replies; 23+ messages in thread
From: Alexandru Ardelean @ 2019-09-13 11:45 UTC (permalink / raw)
  To: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list
  Cc: jic23, broonie, f.fainelli, linus.walleij, orsonzhai,
	baolin.wang, zhang.lyra, Alexandru Ardelean

This change implements CS control for setup, hold & inactive delays.

The `cs_setup` delay is completely new, and can help with cases where
asserting the CS, also brings the device out of power-sleep, where there
needs to be a longer (than usual), before transferring data.

The `cs_hold` time can overlap with the `delay` (or `delay_usecs`) from an
SPI transfer. The main difference is that `cs_hold` implies that CS will be
de-asserted.

The `cs_inactive` delay does not have a clear use-case yet. It has been
implemented mostly because the `spi_set_cs_timing()` function implements
it. To some degree, this could overlap or replace `cs_change_delay`, but
this will require more consideration/investigation in the future.

All these delays have been added to the `spi_controller` struct, as they
would typically be configured by calling `spi_set_cs_timing()` after an
`spi_setup()` call.

Software-mode for CS control, implies that the `set_cs_timing()` hook has
not been provided for the `spi_controller` object.

Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
 drivers/spi/spi.c       | 50 ++++++++++++++++++++++++++++++++++++++++-
 include/linux/spi/spi.h |  5 +++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 54d00c0a26d2..acbbfee837ed 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -775,6 +775,15 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
 
 static void spi_set_cs(struct spi_device *spi, bool enable)
 {
+	bool enable1 = enable;
+
+	if (!spi->controller->set_cs_timing) {
+		if (enable1)
+			spi_delay_exec(&spi->controller->cs_setup, NULL);
+		else
+			spi_delay_exec(&spi->controller->cs_hold, NULL);
+	}
+
 	if (spi->mode & SPI_CS_HIGH)
 		enable = !enable;
 
@@ -800,6 +809,11 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
 	} else if (spi->controller->set_cs) {
 		spi->controller->set_cs(spi, !enable);
 	}
+
+	if (!spi->controller->set_cs_timing) {
+		if (!enable1)
+			spi_delay_exec(&spi->controller->cs_inactive, NULL);
+	}
 }
 
 #ifdef CONFIG_HAS_DMA
@@ -3144,6 +3158,11 @@ int spi_setup(struct spi_device *spi)
 }
 EXPORT_SYMBOL_GPL(spi_setup);
 
+static inline bool _spi_delay_clock_cycles(struct spi_delay *d)
+{
+	return d && d->unit == SPI_DELAY_UNIT_SCK;
+}
+
 /**
  * spi_set_cs_timing - configure CS setup, hold, and inactive delays
  * @spi: the device that requires specific CS timing configuration
@@ -3156,10 +3175,39 @@ EXPORT_SYMBOL_GPL(spi_setup);
 int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup,
 		      struct spi_delay *hold, struct spi_delay *inactive)
 {
+	size_t len;
+
 	if (spi->controller->set_cs_timing)
 		return spi->controller->set_cs_timing(spi, setup, hold,
 						      inactive);
-	return -ENOTSUPP;
+
+	if (_spi_delay_clock_cycles(setup) ||
+	    _spi_delay_clock_cycles(hold) ||
+	    _spi_delay_clock_cycles(inactive)) {
+		dev_err(&spi->dev,
+			"Clock-cycle delays for CS not supported in SW mode\n");
+		return -ENOTSUPP;
+	}
+
+	len = sizeof(struct spi_delay);
+
+	/* copy delays to controller */
+	if (setup)
+		memcpy(&spi->controller->cs_setup, setup, len);
+	else
+		memset(&spi->controller->cs_setup, 0, len);
+
+	if (hold)
+		memcpy(&spi->controller->cs_hold, hold, len);
+	else
+		memset(&spi->controller->cs_hold, 0, len);
+
+	if (inactive)
+		memcpy(&spi->controller->cs_inactive, inactive, len);
+	else
+		memset(&spi->controller->cs_inactive, 0, len);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(spi_set_cs_timing);
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 292e752ce34a..def49a76299f 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -602,6 +602,11 @@ struct spi_controller {
 	/* Optimized handlers for SPI memory-like operations. */
 	const struct spi_controller_mem_ops *mem_ops;
 
+	/* CS delays */
+	struct spi_delay	cs_setup;
+	struct spi_delay	cs_hold;
+	struct spi_delay	cs_inactive;
+
 	/* gpio chip select */
 	int			*cs_gpios;
 	struct gpio_desc	**cs_gpiods;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay`
  2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
                   ` (14 preceding siblings ...)
  2019-09-13 11:45 ` [RFC PATCH 15/15] spi: implement SW control for CS times Alexandru Ardelean
@ 2019-09-15 10:22 ` Jonathan Cameron
  15 siblings, 0 replies; 23+ messages in thread
From: Jonathan Cameron @ 2019-09-15 10:22 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list, broonie, f.fainelli,
	linus.walleij, orsonzhai, baolin.wang, zhang.lyra

On Fri, 13 Sep 2019 14:45:35 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> Initially, I started this patchset thinking: "we need a new delay for
> something-something" (in case someone is curios, we need a CS-hold-time for
> the first transfer, because the CS wakes a chip from sleep-mode).
> 
> Then I added the delay, and felt a bit dirty-inside about adding a new one
> (just like that), and decided to look at maybe cleaning things up a bit,
> and a few days later, I got here.
> 
> Full disclaimer: this patchset is not complete. It's an RFC.
> It's based on top of Jonathan's `iio/togreg` branch which also includes the
> ADIS driver library changes and also includes `cs_change_delay`.
> 
> I'll send a V2 patchset, which just the first 4 patches, since I feel that
> those are a bit more complete.
> 
> I thought about just sending the first 4 patches on-their-own, but I
> figured that the whole series (even if not complete) serves as a better
> explanation about the whole "why?".
> 
> Hopefully, this can sort-of-explain things.
> I'll reference this RFC on the next series.

General approach looks sensible to me. Over to SPI specialists on
whether this is a sensible bit of unification to do.

Jonathan

> 
> Thanks
> 
> Alexandru Ardelean (15):
>   spi: move `cs_change_delay` backwards compat logic outside switch
>   spi: introduce spi_delay struct as "value + unit" &  spi_delay_exec()
>   spi: make `cs_change_delay` the first user of the `spi_delay` logic
>   iio: imu: adis: convert cs_change_delay to spi_delay struct
>   spi: sprd: convert transfer word delay to spi_delay struct
>   spi: orion: use new `word_delay` field for SPI transfers
>   spi: spidev: use new `word_delay` field for spi transfers
>   spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for
>     spi_device
>   spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec()
>   spi: use new `spi_transfer_delay` helper where straightforward
>   spi: tegra114: use `spi_transfer_delay` helper
>   spi: spi-loopback-test: use new `delay` field
>   spi: spidev: use new `delay` field for spi transfers
>   spi: tegra114: change format for `spi_set_cs_timing()` function
>   spi: implement SW control for CS times
> 
>  drivers/iio/imu/adis.c           |  24 ++---
>  drivers/spi/spi-atmel.c          |  29 +++++-
>  drivers/spi/spi-bcm63xx-hsspi.c  |   3 +-
>  drivers/spi/spi-cavium.c         |   3 +-
>  drivers/spi/spi-fsl-dspi.c       |   3 +-
>  drivers/spi/spi-fsl-espi.c       |   3 +-
>  drivers/spi/spi-fsl-spi.c        |   3 +-
>  drivers/spi/spi-loopback-test.c  |  12 ++-
>  drivers/spi/spi-mpc512x-psc.c    |   3 +-
>  drivers/spi/spi-mpc52xx-psc.c    |   3 +-
>  drivers/spi/spi-omap-100k.c      |   3 +-
>  drivers/spi/spi-orion.c          |   6 +-
>  drivers/spi/spi-pl022.c          |  25 +++--
>  drivers/spi/spi-sc18is602.c      |   3 +-
>  drivers/spi/spi-sh-hspi.c        |   3 +-
>  drivers/spi/spi-sprd.c           |  11 ++-
>  drivers/spi/spi-tegra114.c       |  39 +++++---
>  drivers/spi/spi-tegra20-sflash.c |   2 +-
>  drivers/spi/spi-topcliff-pch.c   |   7 +-
>  drivers/spi/spi-txx9.c           |   3 +-
>  drivers/spi/spi-xcomm.c          |   3 +-
>  drivers/spi/spi.c                | 162 +++++++++++++++++++++++++------
>  drivers/spi/spidev.c             |   6 +-
>  include/linux/spi/spi.h          |  65 ++++++++++---
>  24 files changed, 293 insertions(+), 131 deletions(-)
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-13 11:45 ` [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic Alexandru Ardelean
@ 2019-09-16 12:25   ` Mark Brown
  2019-09-16 12:37     ` Ardelean, Alexandru
  0 siblings, 1 reply; 23+ messages in thread
From: Mark Brown @ 2019-09-16 12:25 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-spi, linux-iio, linux-arm-kernel, linux-tegra,
	linux-kernel, bcm-kernel-feedback-list, jic23, f.fainelli,
	linus.walleij, orsonzhai, baolin.wang, zhang.lyra

[-- Attachment #1: Type: text/plain, Size: 224 bytes --]

On Fri, Sep 13, 2019 at 02:45:38PM +0300, Alexandru Ardelean wrote:

> -	u16		cs_change_delay;
> -	u8		cs_change_delay_unit;
> +	struct spi_delay	cs_change_delay;

This breaks the build as there is a user of this interface.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-16 12:25   ` Mark Brown
@ 2019-09-16 12:37     ` Ardelean, Alexandru
  2019-09-16 12:47       ` Mark Brown
  0 siblings, 1 reply; 23+ messages in thread
From: Ardelean, Alexandru @ 2019-09-16 12:37 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, baolin.wang, bcm-kernel-feedback-list, linux-iio,
	linux-tegra, linus.walleij, jic23, linux-kernel,
	linux-arm-kernel, f.fainelli, orsonzhai, zhang.lyra

On Mon, 2019-09-16 at 13:25 +0100, Mark Brown wrote:
> [External]
> 
> On Fri, Sep 13, 2019 at 02:45:38PM +0300, Alexandru Ardelean wrote:
> 
> > -	u16		cs_change_delay;
> > -	u8		cs_change_delay_unit;
> > +	struct spi_delay	cs_change_delay;
> 
> This breaks the build as there is a user of this interface.


Ack.
Jonathan pointed this out.
There's a V3 that changes both this and it's user (in IIO).

V3:
https://lore.kernel.org/linux-iio/20190916071024.21447-1-alexandru.ardelean@analog.com/T/#t

V2:
https://lore.kernel.org/linux-iio/20190913115549.3823-1-alexandru.ardelean@analog.com/T/#t

[ archive is from the IIO list ]

Well, I'm hoping you are referring to the same user.

On a general note: I apologise for the amount of noise/spam I am doing here. Still adjusting to how to do things/changes
that touch 2 subsystems, especially when trees are not quite in-sync.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-16 12:37     ` Ardelean, Alexandru
@ 2019-09-16 12:47       ` Mark Brown
  2019-09-16 13:04         ` Ardelean, Alexandru
  0 siblings, 1 reply; 23+ messages in thread
From: Mark Brown @ 2019-09-16 12:47 UTC (permalink / raw)
  To: Ardelean, Alexandru
  Cc: linux-spi, baolin.wang, bcm-kernel-feedback-list, linux-iio,
	linux-tegra, linus.walleij, jic23, linux-kernel,
	linux-arm-kernel, f.fainelli, orsonzhai, zhang.lyra

[-- Attachment #1: Type: text/plain, Size: 285 bytes --]

On Mon, Sep 16, 2019 at 12:37:12PM +0000, Ardelean, Alexandru wrote:

> > This breaks the build as there is a user of this interface.

> Ack.
> Jonathan pointed this out.
> There's a V3 that changes both this and it's user (in IIO).

That v3 seems to be a small subset of this series?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-16 12:47       ` Mark Brown
@ 2019-09-16 13:04         ` Ardelean, Alexandru
  2019-09-16 13:43           ` Mark Brown
  0 siblings, 1 reply; 23+ messages in thread
From: Ardelean, Alexandru @ 2019-09-16 13:04 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, baolin.wang, bcm-kernel-feedback-list, linux-iio,
	linux-tegra, linus.walleij, jic23, linux-kernel,
	linux-arm-kernel, f.fainelli, orsonzhai, zhang.lyra

On Mon, 2019-09-16 at 13:47 +0100, Mark Brown wrote:
> [External]
> 
> On Mon, Sep 16, 2019 at 12:37:12PM +0000, Ardelean, Alexandru wrote:
> 
> > > This breaks the build as there is a user of this interface.
> > Ack.
> > Jonathan pointed this out.
> > There's a V3 that changes both this and it's user (in IIO).
> 
> That v3 seems to be a small subset of this series?

Ack.
V3 is the first 4 patches from this series.
Well, patches 3 & 4 are squashed.

I am 100% convinced that the entire series is a good idea.
In the sense that a `struct spi_delay` may be a good idea, but at the same time, it may be un-needed.

All I wanted to do, was to add another delay somewhere, and got lost in the rework of current delays.
I thought about proposing just the first 4 patches [on their own], but I thought that showing the current series as-is
now, may be a good idea as well [to gather some feedback].

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-16 13:04         ` Ardelean, Alexandru
@ 2019-09-16 13:43           ` Mark Brown
  2019-09-17  6:05             ` Ardelean, Alexandru
  0 siblings, 1 reply; 23+ messages in thread
From: Mark Brown @ 2019-09-16 13:43 UTC (permalink / raw)
  To: Ardelean, Alexandru
  Cc: linux-spi, baolin.wang, bcm-kernel-feedback-list, linux-iio,
	linux-tegra, linus.walleij, jic23, linux-kernel,
	linux-arm-kernel, f.fainelli, orsonzhai, zhang.lyra

[-- Attachment #1: Type: text/plain, Size: 1044 bytes --]

On Mon, Sep 16, 2019 at 01:04:42PM +0000, Ardelean, Alexandru wrote:
> On Mon, 2019-09-16 at 13:47 +0100, Mark Brown wrote:

> > That v3 seems to be a small subset of this series?

> Ack.
> V3 is the first 4 patches from this series.
> Well, patches 3 & 4 are squashed.

> I am 100% convinced that the entire series is a good idea.
> In the sense that a `struct spi_delay` may be a good idea, but at the same time, it may be un-needed.

> All I wanted to do, was to add another delay somewhere, and got lost in the rework of current delays.
> I thought about proposing just the first 4 patches [on their own], but I thought that showing the current series as-is
> now, may be a good idea as well [to gather some feedback].

I think it makes more sense to review as a whole series rather than only
a part of the conversion, it doesn't really help to only do part of it.

Please fix your mail client to word wrap within paragraphs at something
substantially less than 80 columns.  Doing this makes your messages much
easier to read and reply to.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic
  2019-09-16 13:43           ` Mark Brown
@ 2019-09-17  6:05             ` Ardelean, Alexandru
  0 siblings, 0 replies; 23+ messages in thread
From: Ardelean, Alexandru @ 2019-09-17  6:05 UTC (permalink / raw)
  To: broonie
  Cc: linux-spi, baolin.wang, bcm-kernel-feedback-list, linux-iio,
	linux-tegra, linus.walleij, jic23, linux-kernel,
	linux-arm-kernel, f.fainelli, orsonzhai, zhang.lyra

On Mon, 2019-09-16 at 14:43 +0100, Mark Brown wrote:
> [External]
> 
> On Mon, Sep 16, 2019 at 01:04:42PM +0000, Ardelean, Alexandru wrote:
> > On Mon, 2019-09-16 at 13:47 +0100, Mark Brown wrote:
> > > That v3 seems to be a small subset of this series?
> > Ack.
> > V3 is the first 4 patches from this series.
> > Well, patches 3 & 4 are squashed.
> > I am 100% convinced that the entire series is a good idea.

Something happened here to the "not" word.
Probably got lost in an alternate dimension  ¯\_(ツ)_/¯ .

Was supposed to be:
"I am not 100% convinced that the entire series is a good idea."


> > In the sense that a `struct spi_delay` may be a good idea, but at the
> > same time, it may be un-needed.
> > All I wanted to do, was to add another delay somewhere, and got lost in
> > the rework of current delays.
> > I thought about proposing just the first 4 patches [on their own], but
> > I thought that showing the current series as-is
> > now, may be a good idea as well [to gather some feedback].
> 
> I think it makes more sense to review as a whole series rather than only
> a part of the conversion, it doesn't really help to only do part of it.
> 
> Please fix your mail client to word wrap within paragraphs at something
> substantially less than 80 columns.  Doing this makes your messages much
> easier to read and reply to.

Ack.
Problem is: I have to re-setup my email client every now-n-then since the
work-email server has some issues with Linux email clients.
And I sometimes forget to configure this.
[ Exchange does not always get along well with non-Outlook clients ]

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2019-09-17  6:05 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-13 11:45 [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 01/15] spi: move `cs_change_delay` backwards compat logic outside switch Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 02/15] spi: introduce spi_delay struct as "value + unit" & spi_delay_exec() Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 03/15] spi: make `cs_change_delay` the first user of the `spi_delay` logic Alexandru Ardelean
2019-09-16 12:25   ` Mark Brown
2019-09-16 12:37     ` Ardelean, Alexandru
2019-09-16 12:47       ` Mark Brown
2019-09-16 13:04         ` Ardelean, Alexandru
2019-09-16 13:43           ` Mark Brown
2019-09-17  6:05             ` Ardelean, Alexandru
2019-09-13 11:45 ` [RFC PATCH 04/15] iio: imu: adis: convert cs_change_delay to spi_delay struct Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 05/15] spi: sprd: convert transfer word delay " Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 06/15] spi: orion: use new `word_delay` field for SPI transfers Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 07/15] spi: spidev: use new `word_delay` field for spi transfers Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 08/15] spi: core,atmel: convert `word_delay_usecs` -> `word_delay` for spi_device Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 09/15] spi: introduce `delay` field for `spi_transfer` + spi_transfer_exec() Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 10/15] spi: use new `spi_transfer_delay` helper where straightforward Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 11/15] spi: tegra114: use `spi_transfer_delay` helper Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 12/15] spi: spi-loopback-test: use new `delay` field Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 13/15] spi: spidev: use new `delay` field for spi transfers Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 14/15] spi: tegra114: change format for `spi_set_cs_timing()` function Alexandru Ardelean
2019-09-13 11:45 ` [RFC PATCH 15/15] spi: implement SW control for CS times Alexandru Ardelean
2019-09-15 10:22 ` [RFC PATCH 00/15] Unify SPI delays into an `struct spi_delay` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).