Commit 8a18fda0 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 51df8e0c c8bd922d
...@@ -164,16 +164,20 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, ...@@ -164,16 +164,20 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
} }
static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry, static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry,
int delay_ns, u32 sclk_hz) int delay_ns, int inst_ns, u32 sclk_hz)
{ {
unsigned int t; unsigned int t;
/* negative delay indicates error, e.g. from spi_delay_to_ns() */ /*
if (delay_ns <= 0) * Negative delay indicates error, e.g. from spi_delay_to_ns(). And if
* delay is less that the instruction execution time, there is no need
* for an extra sleep instruction since the instruction execution time
* will already cover the required delay.
*/
if (delay_ns < 0 || delay_ns <= inst_ns)
return; return;
/* rounding down since executing the instruction adds a couple of ticks delay */ t = DIV_ROUND_UP_ULL((u64)(delay_ns - inst_ns) * sclk_hz, NSEC_PER_SEC);
t = DIV_ROUND_DOWN_ULL((u64)delay_ns * sclk_hz, NSEC_PER_SEC);
while (t) { while (t) {
unsigned int n = min(t, 256U); unsigned int n = min(t, 256U);
...@@ -220,10 +224,16 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry, ...@@ -220,10 +224,16 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
struct spi_device *spi = msg->spi; struct spi_device *spi = msg->spi;
struct spi_controller *host = spi->controller; struct spi_controller *host = spi->controller;
struct spi_transfer *xfer; struct spi_transfer *xfer;
int clk_div, new_clk_div; int clk_div, new_clk_div, inst_ns;
bool keep_cs = false; bool keep_cs = false;
u8 bits_per_word = 0; u8 bits_per_word = 0;
/*
* Take into account instruction execution time for more accurate sleep
* times, especially when the delay is small.
*/
inst_ns = DIV_ROUND_UP(NSEC_PER_SEC, host->max_speed_hz);
clk_div = 1; clk_div = 1;
spi_engine_program_add_cmd(p, dry, spi_engine_program_add_cmd(p, dry,
...@@ -252,7 +262,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry, ...@@ -252,7 +262,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
spi_engine_gen_xfer(p, dry, xfer); spi_engine_gen_xfer(p, dry, xfer);
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer), spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer),
xfer->effective_speed_hz); inst_ns, xfer->effective_speed_hz);
if (xfer->cs_change) { if (xfer->cs_change) {
if (list_is_last(&xfer->transfer_list, &msg->transfers)) { 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, ...@@ -262,7 +272,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
spi_engine_gen_cs(p, dry, spi, false); spi_engine_gen_cs(p, dry, spi, false);
spi_engine_gen_sleep(p, dry, spi_delay_to_ns( spi_engine_gen_sleep(p, dry, spi_delay_to_ns(
&xfer->cs_change_delay, xfer), &xfer->cs_change_delay, xfer), inst_ns,
xfer->effective_speed_hz); xfer->effective_speed_hz);
if (!list_next_entry(xfer, transfer_list)->cs_off) if (!list_next_entry(xfer, transfer_list)->cs_off)
......
...@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
return ret; return ret;
free_dma: free_dma:
/* This bit needs to be cleared to disable dpsi->clk */
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
if (dspi->dma_rx) { if (dspi->dma_rx) {
dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx); dma_release_channel(dspi->dma_tx);
...@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev) ...@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&dspi->bitbang); spi_bitbang_stop(&dspi->bitbang);
/* This bit needs to be cleared to disable dpsi->clk */
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
if (dspi->dma_rx) { if (dspi->dma_rx) {
dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx); dma_release_channel(dspi->dma_tx);
......
...@@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { ...@@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
.rx_available = mx31_rx_available, .rx_available = mx31_rx_available,
.reset = mx31_reset, .reset = mx31_reset,
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = true, .has_dmamode = false,
.dynamic_burst = false, .dynamic_burst = false,
.has_targetmode = false, .has_targetmode = false,
.devtype = IMX35_CSPI, .devtype = IMX35_CSPI,
......
...@@ -158,12 +158,14 @@ static int spi_mux_probe(struct spi_device *spi) ...@@ -158,12 +158,14 @@ static int spi_mux_probe(struct spi_device *spi)
/* supported modes are the same as our parent's */ /* supported modes are the same as our parent's */
ctlr->mode_bits = spi->controller->mode_bits; ctlr->mode_bits = spi->controller->mode_bits;
ctlr->flags = spi->controller->flags; ctlr->flags = spi->controller->flags;
ctlr->bits_per_word_mask = spi->controller->bits_per_word_mask;
ctlr->transfer_one_message = spi_mux_transfer_one_message; ctlr->transfer_one_message = spi_mux_transfer_one_message;
ctlr->setup = spi_mux_setup; ctlr->setup = spi_mux_setup;
ctlr->num_chipselect = mux_control_states(priv->mux); ctlr->num_chipselect = mux_control_states(priv->mux);
ctlr->bus_num = -1; ctlr->bus_num = -1;
ctlr->dev.of_node = spi->dev.of_node; ctlr->dev.of_node = spi->dev.of_node;
ctlr->must_async = true; ctlr->must_async = true;
ctlr->defer_optimize_message = true;
ret = devm_spi_register_controller(&spi->dev, ctlr); ret = devm_spi_register_controller(&spi->dev, ctlr);
if (ret) if (ret)
......
...@@ -1277,24 +1277,11 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, ...@@ -1277,24 +1277,11 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
/* /*
* Check if this transfer contains only one word; * Check if this transfer contains only one word;
* OR contains 1 to 4 words, with bits_per_word == 8 and no delay between each word
* OR contains 1 to 2 words, with bits_per_word == 16 and no delay between each word
*
* If one of the two last case is true, this also change the bits_per_word of this
* transfer to make it a bit faster.
* It's not an issue to change the bits_per_word here even if the multi-mode is not
* applicable for this message, the signal on the wire will be the same.
*/ */
if (bits_per_word < 8 && tr->len == 1) { if (bits_per_word < 8 && tr->len == 1) {
/* multi-mode is applicable, only one word (1..7 bits) */ /* multi-mode is applicable, only one word (1..7 bits) */
} else if (tr->word_delay.value == 0 && bits_per_word == 8 && tr->len <= 4) {
/* multi-mode is applicable, only one "bigger" word (8,16,24,32 bits) */
tr->bits_per_word = tr->len * bits_per_word;
} else if (tr->word_delay.value == 0 && bits_per_word == 16 && tr->len <= 2) {
/* multi-mode is applicable, only one "bigger" word (16,32 bits) */
tr->bits_per_word = tr->len * bits_per_word / 2;
} else if (bits_per_word >= 8 && tr->len == bits_per_word / 8) { } else if (bits_per_word >= 8 && tr->len == bits_per_word / 8) {
/* multi-mode is applicable, only one word (9..15,17..32 bits) */ /* multi-mode is applicable, only one word (8..32 bits) */
} else { } else {
/* multi-mode is not applicable: more than one word in the transfer */ /* multi-mode is not applicable: more than one word in the transfer */
mcspi->use_multi_mode = false; mcspi->use_multi_mode = false;
......
...@@ -2151,7 +2151,8 @@ static void __spi_unoptimize_message(struct spi_message *msg) ...@@ -2151,7 +2151,8 @@ static void __spi_unoptimize_message(struct spi_message *msg)
*/ */
static void spi_maybe_unoptimize_message(struct spi_message *msg) static void spi_maybe_unoptimize_message(struct spi_message *msg)
{ {
if (!msg->pre_optimized && msg->optimized) if (!msg->pre_optimized && msg->optimized &&
!msg->spi->controller->defer_optimize_message)
__spi_unoptimize_message(msg); __spi_unoptimize_message(msg);
} }
...@@ -4294,6 +4295,11 @@ static int __spi_optimize_message(struct spi_device *spi, ...@@ -4294,6 +4295,11 @@ static int __spi_optimize_message(struct spi_device *spi,
static int spi_maybe_optimize_message(struct spi_device *spi, static int spi_maybe_optimize_message(struct spi_device *spi,
struct spi_message *msg) struct spi_message *msg)
{ {
if (spi->controller->defer_optimize_message) {
msg->spi = spi;
return 0;
}
if (msg->pre_optimized) if (msg->pre_optimized)
return 0; return 0;
...@@ -4324,6 +4330,13 @@ int spi_optimize_message(struct spi_device *spi, struct spi_message *msg) ...@@ -4324,6 +4330,13 @@ int spi_optimize_message(struct spi_device *spi, struct spi_message *msg)
{ {
int ret; int ret;
/*
* Pre-optimization is not supported and optimization is deferred e.g.
* when using spi-mux.
*/
if (spi->controller->defer_optimize_message)
return 0;
ret = __spi_optimize_message(spi, msg); ret = __spi_optimize_message(spi, msg);
if (ret) if (ret)
return ret; return ret;
...@@ -4350,6 +4363,9 @@ EXPORT_SYMBOL_GPL(spi_optimize_message); ...@@ -4350,6 +4363,9 @@ EXPORT_SYMBOL_GPL(spi_optimize_message);
*/ */
void spi_unoptimize_message(struct spi_message *msg) void spi_unoptimize_message(struct spi_message *msg)
{ {
if (msg->spi->controller->defer_optimize_message)
return;
__spi_unoptimize_message(msg); __spi_unoptimize_message(msg);
msg->pre_optimized = false; msg->pre_optimized = false;
} }
...@@ -4432,8 +4448,6 @@ int spi_async(struct spi_device *spi, struct spi_message *message) ...@@ -4432,8 +4448,6 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags);
spi_maybe_unoptimize_message(message);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(spi_async); EXPORT_SYMBOL_GPL(spi_async);
......
...@@ -533,6 +533,9 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch ...@@ -533,6 +533,9 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @queue_empty: signal green light for opportunistically skipping the queue * @queue_empty: signal green light for opportunistically skipping the queue
* for spi_sync transfers. * for spi_sync transfers.
* @must_async: disable all fast paths in the core * @must_async: disable all fast paths in the core
* @defer_optimize_message: set to true if controller cannot pre-optimize messages
* and needs to defer the optimization step until the message is actually
* being transferred
* *
* Each SPI controller can communicate with one or more @spi_device * Each SPI controller can communicate with one or more @spi_device
* children. These make a small bus, sharing MOSI, MISO and SCK signals * children. These make a small bus, sharing MOSI, MISO and SCK signals
...@@ -776,6 +779,7 @@ struct spi_controller { ...@@ -776,6 +779,7 @@ struct spi_controller {
/* Flag for enabling opportunistic skipping of the queue in spi_sync */ /* Flag for enabling opportunistic skipping of the queue in spi_sync */
bool queue_empty; bool queue_empty;
bool must_async; bool must_async;
bool defer_optimize_message;
}; };
static inline void *spi_controller_get_devdata(struct spi_controller *ctlr) static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment