Unverified Commit 04694e50 authored by Neil Armstrong's avatar Neil Armstrong Committed by Mark Brown
Browse files

spi: meson-spicc: move wait completion in driver to take bursts delay in account



Some delay occurs between each bursts, thus the default delay is wrong
and a timeout will occur with big enough transfers.

The solution is to handle the timeout management in the driver and
add some delay for each bursts in the timeout calculation.

Reported-by: default avatarDa Xue <da@libre.computer>
Signed-off-by: default avatarNeil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20221026-spicc-burst-delay-v1-0-1be5ffb7051a@linaro.org


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 19558350
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct meson_spicc_device {
	struct clk			*clk;
	struct spi_message		*message;
	struct spi_transfer		*xfer;
	struct completion		done;
	const struct meson_spicc_data	*data;
	u8				*tx_buf;
	u8				*rx_buf;
@@ -282,7 +283,7 @@ static irqreturn_t meson_spicc_irq(int irq, void *data)
		/* Disable all IRQs */
		writel(0, spicc->base + SPICC_INTREG);

		spi_finalize_current_transfer(spicc->master);
		complete(&spicc->done);

		return IRQ_HANDLED;
	}
@@ -386,6 +387,7 @@ static int meson_spicc_transfer_one(struct spi_master *master,
				    struct spi_transfer *xfer)
{
	struct meson_spicc_device *spicc = spi_master_get_devdata(master);
	unsigned long timeout;

	/* Store current transfer */
	spicc->xfer = xfer;
@@ -410,13 +412,29 @@ static int meson_spicc_transfer_one(struct spi_master *master,
	/* Setup burst */
	meson_spicc_setup_burst(spicc);

	/* Setup wait for completion */
	reinit_completion(&spicc->done);

	/* For each byte we wait for 8 cycles of the SPI clock */
	timeout = 8LL * MSEC_PER_SEC * xfer->len;
	do_div(timeout, xfer->speed_hz);

	/* Add 10us delay between each fifo bursts */
	timeout += ((xfer->len >> 4) * 10) / MSEC_PER_SEC;

	/* Increase it twice and add 200 ms tolerance */
	timeout += timeout + 200;

	/* Start burst */
	writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG);

	/* Enable interrupts */
	writel_relaxed(SPICC_TC_EN, spicc->base + SPICC_INTREG);

	return 1;
	if (!wait_for_completion_timeout(&spicc->done, msecs_to_jiffies(timeout)))
		return -ETIMEDOUT;

	return 0;
}

static int meson_spicc_prepare_message(struct spi_master *master,
@@ -743,6 +761,8 @@ static int meson_spicc_probe(struct platform_device *pdev)
	spicc->pdev = pdev;
	platform_set_drvdata(pdev, spicc);

	init_completion(&spicc->done);

	spicc->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(spicc->base)) {
		dev_err(&pdev->dev, "io resource mapping failed\n");