diff options
author | Michal Suchanek <hramrach@gmail.com> | 2016-06-13 13:46:49 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-06-14 05:05:18 -0400 |
commit | 719bd6542044efd9b338a53dba1bef45f40ca169 (patch) | |
tree | 837acfe993c8949db1570b977c6dd5d2a3cb37fb | |
parent | 6d9fe44bd73d567d04d3a68a2d2fa521ab9532f2 (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.c | 10 | ||||
-rw-r--r-- | drivers/spi/spi-sun6i.c | 10 |
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 | } |