Commit 8a18fda0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -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,
				 int delay_ns, u32 sclk_hz)
				 int delay_ns, int inst_ns, u32 sclk_hz)
{
	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;

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

@@ -220,10 +224,16 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
	struct spi_device *spi = msg->spi;
	struct spi_controller *host = spi->controller;
	struct spi_transfer *xfer;
	int clk_div, new_clk_div;
	int clk_div, new_clk_div, inst_ns;
	bool keep_cs = false;
	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;

	spi_engine_program_add_cmd(p, 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_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 (list_is_last(&xfer->transfer_list, &msg->transfers)) {
@@ -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_sleep(p, dry, spi_delay_to_ns(
					&xfer->cs_change_delay, xfer),
					&xfer->cs_change_delay, xfer), inst_ns,
					xfer->effective_speed_hz);

				if (!list_next_entry(xfer, transfer_list)->cs_off)
+6 −0
Original line number Diff line number Diff line
@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
	return ret;

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) {
		dma_release_channel(dspi->dma_rx);
		dma_release_channel(dspi->dma_tx);
@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev)

	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) {
		dma_release_channel(dspi->dma_rx);
		dma_release_channel(dspi->dma_tx);
+1 −1
Original line number Diff line number Diff line
@@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
	.rx_available = mx31_rx_available,
	.reset = mx31_reset,
	.fifo_size = 8,
	.has_dmamode = true,
	.has_dmamode = false,
	.dynamic_burst = false,
	.has_targetmode = false,
	.devtype = IMX35_CSPI,
+2 −0
Original line number Diff line number Diff line
@@ -158,12 +158,14 @@ static int spi_mux_probe(struct spi_device *spi)
	/* supported modes are the same as our parent's */
	ctlr->mode_bits = spi->controller->mode_bits;
	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->setup = spi_mux_setup;
	ctlr->num_chipselect = mux_control_states(priv->mux);
	ctlr->bus_num = -1;
	ctlr->dev.of_node = spi->dev.of_node;
	ctlr->must_async = true;
	ctlr->defer_optimize_message = true;

	ret = devm_spi_register_controller(&spi->dev, ctlr);
	if (ret)
+1 −14
Original line number Diff line number Diff line
@@ -1277,24 +1277,11 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,

		/*
		 * 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) {
			/* 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) {
			/* multi-mode is applicable, only one word (9..15,17..32 bits) */
			/* multi-mode is applicable, only one word (8..32 bits) */
		} else {
			/* multi-mode is not applicable: more than one word in the transfer */
			mcspi->use_multi_mode = false;
Loading