[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221026-spicc-burst-delay-v1-0-1be5ffb7051a@linaro.org>
Date: Wed, 26 Oct 2022 09:58:28 +0200
From: Neil Armstrong <neil.armstrong@...aro.org>
To: Jerome Brunet <jbrunet@...libre.com>,
Martin Blumenstingl <martin.blumenstingl@...glemail.com>,
Mark Brown <broonie@...nel.org>,
Kevin Hilman <khilman@...libre.com>
Cc: linux-arm-kernel@...ts.infradead.org, Da Xue <da@...re.computer>,
linux-kernel@...r.kernel.org, linux-amlogic@...ts.infradead.org,
Neil Armstrong <neil.armstrong@...aro.org>,
linux-spi@...r.kernel.org
Subject: [PATCH] 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: Da Xue <da@...re.computer>
Signed-off-by: Neil Armstrong <neil.armstrong@...aro.org>
---
To: Mark Brown <broonie@...nel.org>
To: Kevin Hilman <khilman@...libre.com>
To: Jerome Brunet <jbrunet@...libre.com>
To: Martin Blumenstingl <martin.blumenstingl@...glemail.com>
Cc: linux-spi@...r.kernel.org
Cc: linux-arm-kernel@...ts.infradead.org
Cc: linux-amlogic@...ts.infradead.org
Cc: linux-kernel@...r.kernel.org
---
drivers/spi/spi-meson-spicc.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index bad201510a99..52bffab18329 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -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");
---
base-commit: 247f34f7b80357943234f93f247a1ae6b6c3a740
change-id: 20221026-spicc-burst-delay-ea0526602760
Best regards,
--
Neil Armstrong <neil.armstrong@...aro.org>
Powered by blists - more mailing lists