aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Suchanek <hramrach@gmail.com>2016-06-13 13:46:49 -0400
committerMark Brown <broonie@kernel.org>2016-06-14 05:05:18 -0400
commit719bd6542044efd9b338a53dba1bef45f40ca169 (patch)
tree837acfe993c8949db1570b977c6dd5d2a3cb37fb
parent6d9fe44bd73d567d04d3a68a2d2fa521ab9532f2 (diff)
spi: sunxi: fix transfer timeout
The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over 1MHz SPI bus takes way longer than that. Calculate the timeout from the actual time the transfer is supposed to take and multiply by 2 for good measure. Signed-off-by: Michal Suchanek <hramrach@gmail.com> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org
-rw-r--r--drivers/spi/spi-sun4i.c10
-rw-r--r--drivers/spi/spi-sun6i.c10
2 files changed, 18 insertions, 2 deletions
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index e7e4aecb3295..cf007f3b83ec 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
173{ 173{
174 struct sun4i_spi *sspi = spi_master_get_devdata(master); 174 struct sun4i_spi *sspi = spi_master_get_devdata(master);
175 unsigned int mclk_rate, div, timeout; 175 unsigned int mclk_rate, div, timeout;
176 unsigned int start, end, tx_time;
176 unsigned int tx_len = 0; 177 unsigned int tx_len = 0;
177 int ret = 0; 178 int ret = 0;
178 u32 reg; 179 u32 reg;
@@ -286,9 +287,16 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
286 reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); 287 reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
287 sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH); 288 sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
288 289
290 tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
291 start = jiffies;
289 timeout = wait_for_completion_timeout(&sspi->done, 292 timeout = wait_for_completion_timeout(&sspi->done,
290 msecs_to_jiffies(1000)); 293 msecs_to_jiffies(tx_time));
294 end = jiffies;
291 if (!timeout) { 295 if (!timeout) {
296 dev_warn(&master->dev,
297 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
298 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
299 jiffies_to_msecs(end - start), tx_time);
292 ret = -ETIMEDOUT; 300 ret = -ETIMEDOUT;
293 goto out; 301 goto out;
294 } 302 }
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 42e2c4bd690a..7fce79a60608 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -160,6 +160,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
160{ 160{
161 struct sun6i_spi *sspi = spi_master_get_devdata(master); 161 struct sun6i_spi *sspi = spi_master_get_devdata(master);
162 unsigned int mclk_rate, div, timeout; 162 unsigned int mclk_rate, div, timeout;
163 unsigned int start, end, tx_time;
163 unsigned int tx_len = 0; 164 unsigned int tx_len = 0;
164 int ret = 0; 165 int ret = 0;
165 u32 reg; 166 u32 reg;
@@ -269,9 +270,16 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
269 reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); 270 reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
270 sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH); 271 sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
271 272
273 tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
274 start = jiffies;
272 timeout = wait_for_completion_timeout(&sspi->done, 275 timeout = wait_for_completion_timeout(&sspi->done,
273 msecs_to_jiffies(1000)); 276 msecs_to_jiffies(tx_time));
277 end = jiffies;
274 if (!timeout) { 278 if (!timeout) {
279 dev_warn(&master->dev,
280 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
281 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
282 jiffies_to_msecs(end - start), tx_time);
275 ret = -ETIMEDOUT; 283 ret = -ETIMEDOUT;
276 goto out; 284 goto out;
277 } 285 }