Skip to content

Commit

Permalink
spi: meson-spicc: move wait completion in driver to take bursts delay…
Browse files Browse the repository at this point in the history
… 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: Da Xue <da@libre.computer>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20221026-spicc-burst-delay-v1-0-1be5ffb7051a@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Neil Armstrong authored and Mark Brown committed Oct 26, 2022
1 parent 1955835 commit 04694e5
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions drivers/spi/spi-meson-spicc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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");
Expand Down

0 comments on commit 04694e5

Please sign in to comment.