Skip to content

Commit 6c613f6

Browse files
commodobroonie
authored andcommitted
spi: core,atmel: convert word_delay_usecs -> word_delay for spi_device
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent ec3fa72 commit 6c613f6

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

drivers/spi/spi-atmel.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,12 +1149,31 @@ atmel_spi_pdc_interrupt(int irq, void *dev_id)
11491149
return ret;
11501150
}
11511151

1152+
static int atmel_word_delay_csr(struct spi_device *spi, struct atmel_spi *as)
1153+
{
1154+
struct spi_delay *delay = &spi->word_delay;
1155+
u32 value = delay->value;
1156+
1157+
switch (delay->unit) {
1158+
case SPI_DELAY_UNIT_NSECS:
1159+
value /= 1000;
1160+
break;
1161+
case SPI_DELAY_UNIT_USECS:
1162+
break;
1163+
default:
1164+
return -EINVAL;
1165+
}
1166+
1167+
return (as->spi_clk / 1000000 * value) >> 5;
1168+
}
1169+
11521170
static int atmel_spi_setup(struct spi_device *spi)
11531171
{
11541172
struct atmel_spi *as;
11551173
struct atmel_spi_device *asd;
11561174
u32 csr;
11571175
unsigned int bits = spi->bits_per_word;
1176+
int word_delay_csr;
11581177

11591178
as = spi_master_get_devdata(spi->master);
11601179

@@ -1178,11 +1197,14 @@ static int atmel_spi_setup(struct spi_device *spi)
11781197
*/
11791198
csr |= SPI_BF(DLYBS, 0);
11801199

1200+
word_delay_csr = atmel_word_delay_csr(spi, as);
1201+
if (word_delay_csr < 0)
1202+
return word_delay_csr;
1203+
11811204
/* DLYBCT adds delays between words. This is useful for slow devices
11821205
* that need a bit of time to setup the next transfer.
11831206
*/
1184-
csr |= SPI_BF(DLYBCT,
1185-
(as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5);
1207+
csr |= SPI_BF(DLYBCT, word_delay_csr);
11861208

11871209
asd = spi->controller_state;
11881210
if (!asd) {

drivers/spi/spi.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3281,6 +3281,26 @@ void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold,
32813281
}
32823282
EXPORT_SYMBOL_GPL(spi_set_cs_timing);
32833283

3284+
static int _spi_xfer_word_delay_update(struct spi_transfer *xfer,
3285+
struct spi_device *spi)
3286+
{
3287+
int delay1, delay2;
3288+
3289+
delay1 = _spi_delay_to_ns(&xfer->word_delay, xfer);
3290+
if (delay1 < 0)
3291+
return delay1;
3292+
3293+
delay2 = _spi_delay_to_ns(&spi->word_delay, xfer);
3294+
if (delay2 < 0)
3295+
return delay2;
3296+
3297+
if (delay1 < delay2)
3298+
memcpy(&xfer->word_delay, &spi->word_delay,
3299+
sizeof(xfer->word_delay));
3300+
3301+
return 0;
3302+
}
3303+
32843304
static int __spi_validate(struct spi_device *spi, struct spi_message *message)
32853305
{
32863306
struct spi_controller *ctlr = spi->controller;
@@ -3416,8 +3436,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
34163436
return -EINVAL;
34173437
}
34183438

3419-
if (xfer->word_delay_usecs < spi->word_delay_usecs)
3420-
xfer->word_delay_usecs = spi->word_delay_usecs;
3439+
if (_spi_xfer_word_delay_update(xfer, spi))
3440+
return -EINVAL;
34213441
}
34223442

34233443
message->status = -EINPROGRESS;

include/linux/spi/spi.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer);
139139
* the spi_master.
140140
* @cs_gpiod: gpio descriptor of the chipselect line (optional, NULL when
141141
* not using a GPIO line)
142-
* @word_delay_usecs: microsecond delay to be inserted between consecutive
142+
* @word_delay: delay to be inserted between consecutive
143143
* words of a transfer
144144
*
145145
* @statistics: statistics for the spi_device
@@ -189,7 +189,7 @@ struct spi_device {
189189
const char *driver_override;
190190
int cs_gpio; /* LEGACY: chip select gpio */
191191
struct gpio_desc *cs_gpiod; /* chip select gpio desc */
192-
uint8_t word_delay_usecs; /* inter-word delay */
192+
struct spi_delay word_delay; /* inter-word delay */
193193

194194
/* the statistics */
195195
struct spi_statistics statistics;
@@ -781,8 +781,6 @@ extern void spi_res_release(struct spi_controller *ctlr,
781781
* @delay_usecs: microseconds to delay after this transfer before
782782
* (optionally) changing the chipselect status, then starting
783783
* the next transfer or completing this @spi_message.
784-
* @word_delay_usecs: microseconds to inter word delay after each word size
785-
* (set by bits_per_word) transmission.
786784
* @word_delay: inter word delay to be introduced after each word size
787785
* (set by bits_per_word) transmission.
788786
* @effective_speed_hz: the effective SCK-speed that was used to
@@ -897,7 +895,6 @@ struct spi_transfer {
897895
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
898896
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
899897
u8 bits_per_word;
900-
u8 word_delay_usecs;
901898
u16 delay_usecs;
902899
struct spi_delay cs_change_delay;
903900
struct spi_delay word_delay;

0 commit comments

Comments
 (0)