drivers: spi: Use timeout for transfer completion

Instead of waiting forever for the SPI transfer to complete, let's use
a timeout value and bail out if elapsed. The timeout value logic is,

xfer_len/frequency + tolerance

Tolerance value can be modified using a Kconfig symbol,
CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE. It defaults to 200ms.

Fixes: #33192

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
This commit is contained in:
Manivannan Sadhasivam 2021-03-11 11:01:42 +05:30 committed by Christopher Friedt
parent a95457a984
commit fa2d1ea422
2 changed files with 20 additions and 2 deletions

View file

@ -31,6 +31,12 @@ config SPI_INIT_PRIORITY
help
Device driver initialization priority.
config SPI_COMPLETION_TIMEOUT_TOLERANCE
int "Completion timeout tolerance (ms)"
default 200
help
The tolerance value in ms for the SPI completion timeout logic.
module = SPI
module-str = spi
source "subsys/logging/Kconfig.template.log_config"

View file

@ -112,13 +112,25 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
static inline int spi_context_wait_for_completion(struct spi_context *ctx)
{
int status = 0;
uint32_t timeout_ms;
timeout_ms = MAX(ctx->tx_len, ctx->rx_len) * 8 * 1000 /
ctx->config->frequency;
timeout_ms += CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE;
#ifdef CONFIG_SPI_ASYNC
if (!ctx->asynchronous) {
k_sem_take(&ctx->sync, K_FOREVER);
if (k_sem_take(&ctx->sync, K_MSEC(timeout_ms))) {
LOG_ERR("Timeout waiting for transfer complete");
return -ETIMEDOUT;
}
status = ctx->sync_status;
}
#else
k_sem_take(&ctx->sync, K_FOREVER);
if (k_sem_take(&ctx->sync, K_MSEC(timeout_ms))) {
LOG_ERR("Timeout waiting for transfer complete");
return -ETIMEDOUT;
}
status = ctx->sync_status;
#endif /* CONFIG_SPI_ASYNC */