Skip to content

Commit 8a18fda

Browse files
committed
Merge tag 'spi-fix-v6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown: "This fixes two regressions that have been bubbling along for a large part of this release. One is a revert of the multi mode support for the OMAP SPI controller, this introduced regressions on a number of systems and while there has been progress on fixing those we've not got something that works for everyone yet so let's just drop the change for now. The other is a series of fixes from David Lechner for his recent message optimisation work, this interacted badly with spi-mux which is altogether too clever with recursive use of the bus and creates situations that hadn't been considered. There are also a couple of small driver specific fixes, including one more patch from David for sleep duration calculations in the AXI driver" * tag 'spi-fix-v6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: mux: set ctlr->bits_per_word_mask spi: add defer_optimize_message controller flag spi: don't unoptimize message in spi_async() spi: omap2-mcspi: Revert multi mode support spi: davinci: Unset POWERDOWN bit when releasing resources spi: axi-spi-engine: fix sleep calculation spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
2 parents 51df8e0 + c8bd922 commit 8a18fda

File tree

7 files changed

+49
-26
lines changed

7 files changed

+49
-26
lines changed

drivers/spi/spi-axi-spi-engine.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,20 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
164164
}
165165

166166
static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry,
167-
int delay_ns, u32 sclk_hz)
167+
int delay_ns, int inst_ns, u32 sclk_hz)
168168
{
169169
unsigned int t;
170170

171-
/* negative delay indicates error, e.g. from spi_delay_to_ns() */
172-
if (delay_ns <= 0)
171+
/*
172+
* Negative delay indicates error, e.g. from spi_delay_to_ns(). And if
173+
* delay is less that the instruction execution time, there is no need
174+
* for an extra sleep instruction since the instruction execution time
175+
* will already cover the required delay.
176+
*/
177+
if (delay_ns < 0 || delay_ns <= inst_ns)
173178
return;
174179

175-
/* rounding down since executing the instruction adds a couple of ticks delay */
176-
t = DIV_ROUND_DOWN_ULL((u64)delay_ns * sclk_hz, NSEC_PER_SEC);
180+
t = DIV_ROUND_UP_ULL((u64)(delay_ns - inst_ns) * sclk_hz, NSEC_PER_SEC);
177181
while (t) {
178182
unsigned int n = min(t, 256U);
179183

@@ -220,10 +224,16 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
220224
struct spi_device *spi = msg->spi;
221225
struct spi_controller *host = spi->controller;
222226
struct spi_transfer *xfer;
223-
int clk_div, new_clk_div;
227+
int clk_div, new_clk_div, inst_ns;
224228
bool keep_cs = false;
225229
u8 bits_per_word = 0;
226230

231+
/*
232+
* Take into account instruction execution time for more accurate sleep
233+
* times, especially when the delay is small.
234+
*/
235+
inst_ns = DIV_ROUND_UP(NSEC_PER_SEC, host->max_speed_hz);
236+
227237
clk_div = 1;
228238

229239
spi_engine_program_add_cmd(p, dry,
@@ -252,7 +262,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
252262

253263
spi_engine_gen_xfer(p, dry, xfer);
254264
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer),
255-
xfer->effective_speed_hz);
265+
inst_ns, xfer->effective_speed_hz);
256266

257267
if (xfer->cs_change) {
258268
if (list_is_last(&xfer->transfer_list, &msg->transfers)) {
@@ -262,7 +272,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
262272
spi_engine_gen_cs(p, dry, spi, false);
263273

264274
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(
265-
&xfer->cs_change_delay, xfer),
275+
&xfer->cs_change_delay, xfer), inst_ns,
266276
xfer->effective_speed_hz);
267277

268278
if (!list_next_entry(xfer, transfer_list)->cs_off)

drivers/spi/spi-davinci.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
984984
return ret;
985985

986986
free_dma:
987+
/* This bit needs to be cleared to disable dpsi->clk */
988+
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
989+
987990
if (dspi->dma_rx) {
988991
dma_release_channel(dspi->dma_rx);
989992
dma_release_channel(dspi->dma_tx);
@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev)
10131016

10141017
spi_bitbang_stop(&dspi->bitbang);
10151018

1019+
/* This bit needs to be cleared to disable dpsi->clk */
1020+
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
1021+
10161022
if (dspi->dma_rx) {
10171023
dma_release_channel(dspi->dma_rx);
10181024
dma_release_channel(dspi->dma_tx);

drivers/spi/spi-imx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
10501050
.rx_available = mx31_rx_available,
10511051
.reset = mx31_reset,
10521052
.fifo_size = 8,
1053-
.has_dmamode = true,
1053+
.has_dmamode = false,
10541054
.dynamic_burst = false,
10551055
.has_targetmode = false,
10561056
.devtype = IMX35_CSPI,

drivers/spi/spi-mux.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,14 @@ static int spi_mux_probe(struct spi_device *spi)
158158
/* supported modes are the same as our parent's */
159159
ctlr->mode_bits = spi->controller->mode_bits;
160160
ctlr->flags = spi->controller->flags;
161+
ctlr->bits_per_word_mask = spi->controller->bits_per_word_mask;
161162
ctlr->transfer_one_message = spi_mux_transfer_one_message;
162163
ctlr->setup = spi_mux_setup;
163164
ctlr->num_chipselect = mux_control_states(priv->mux);
164165
ctlr->bus_num = -1;
165166
ctlr->dev.of_node = spi->dev.of_node;
166167
ctlr->must_async = true;
168+
ctlr->defer_optimize_message = true;
167169

168170
ret = devm_spi_register_controller(&spi->dev, ctlr);
169171
if (ret)

drivers/spi/spi-omap2-mcspi.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,24 +1277,11 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
12771277

12781278
/*
12791279
* Check if this transfer contains only one word;
1280-
* OR contains 1 to 4 words, with bits_per_word == 8 and no delay between each word
1281-
* OR contains 1 to 2 words, with bits_per_word == 16 and no delay between each word
1282-
*
1283-
* If one of the two last case is true, this also change the bits_per_word of this
1284-
* transfer to make it a bit faster.
1285-
* It's not an issue to change the bits_per_word here even if the multi-mode is not
1286-
* applicable for this message, the signal on the wire will be the same.
12871280
*/
12881281
if (bits_per_word < 8 && tr->len == 1) {
12891282
/* multi-mode is applicable, only one word (1..7 bits) */
1290-
} else if (tr->word_delay.value == 0 && bits_per_word == 8 && tr->len <= 4) {
1291-
/* multi-mode is applicable, only one "bigger" word (8,16,24,32 bits) */
1292-
tr->bits_per_word = tr->len * bits_per_word;
1293-
} else if (tr->word_delay.value == 0 && bits_per_word == 16 && tr->len <= 2) {
1294-
/* multi-mode is applicable, only one "bigger" word (16,32 bits) */
1295-
tr->bits_per_word = tr->len * bits_per_word / 2;
12961283
} else if (bits_per_word >= 8 && tr->len == bits_per_word / 8) {
1297-
/* multi-mode is applicable, only one word (9..15,17..32 bits) */
1284+
/* multi-mode is applicable, only one word (8..32 bits) */
12981285
} else {
12991286
/* multi-mode is not applicable: more than one word in the transfer */
13001287
mcspi->use_multi_mode = false;

drivers/spi/spi.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,8 @@ static void __spi_unoptimize_message(struct spi_message *msg)
21512151
*/
21522152
static void spi_maybe_unoptimize_message(struct spi_message *msg)
21532153
{
2154-
if (!msg->pre_optimized && msg->optimized)
2154+
if (!msg->pre_optimized && msg->optimized &&
2155+
!msg->spi->controller->defer_optimize_message)
21552156
__spi_unoptimize_message(msg);
21562157
}
21572158

@@ -4294,6 +4295,11 @@ static int __spi_optimize_message(struct spi_device *spi,
42944295
static int spi_maybe_optimize_message(struct spi_device *spi,
42954296
struct spi_message *msg)
42964297
{
4298+
if (spi->controller->defer_optimize_message) {
4299+
msg->spi = spi;
4300+
return 0;
4301+
}
4302+
42974303
if (msg->pre_optimized)
42984304
return 0;
42994305

@@ -4324,6 +4330,13 @@ int spi_optimize_message(struct spi_device *spi, struct spi_message *msg)
43244330
{
43254331
int ret;
43264332

4333+
/*
4334+
* Pre-optimization is not supported and optimization is deferred e.g.
4335+
* when using spi-mux.
4336+
*/
4337+
if (spi->controller->defer_optimize_message)
4338+
return 0;
4339+
43274340
ret = __spi_optimize_message(spi, msg);
43284341
if (ret)
43294342
return ret;
@@ -4350,6 +4363,9 @@ EXPORT_SYMBOL_GPL(spi_optimize_message);
43504363
*/
43514364
void spi_unoptimize_message(struct spi_message *msg)
43524365
{
4366+
if (msg->spi->controller->defer_optimize_message)
4367+
return;
4368+
43534369
__spi_unoptimize_message(msg);
43544370
msg->pre_optimized = false;
43554371
}
@@ -4432,8 +4448,6 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
44324448

44334449
spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
44344450

4435-
spi_maybe_unoptimize_message(message);
4436-
44374451
return ret;
44384452
}
44394453
EXPORT_SYMBOL_GPL(spi_async);

include/linux/spi/spi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,9 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
533533
* @queue_empty: signal green light for opportunistically skipping the queue
534534
* for spi_sync transfers.
535535
* @must_async: disable all fast paths in the core
536+
* @defer_optimize_message: set to true if controller cannot pre-optimize messages
537+
* and needs to defer the optimization step until the message is actually
538+
* being transferred
536539
*
537540
* Each SPI controller can communicate with one or more @spi_device
538541
* children. These make a small bus, sharing MOSI, MISO and SCK signals
@@ -776,6 +779,7 @@ struct spi_controller {
776779
/* Flag for enabling opportunistic skipping of the queue in spi_sync */
777780
bool queue_empty;
778781
bool must_async;
782+
bool defer_optimize_message;
779783
};
780784

781785
static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)

0 commit comments

Comments
 (0)