With tuning sequences, we will want to associate the busy timeout with the struct mci_data, so add a timeout_ns member to it like Linux does.
Signed-off-by: Ahmad Fatoum <a.fat...@pengutronix.de> --- drivers/mci/sdhci.c | 17 +++++++---------- drivers/mci/sdhci.h | 23 ++++++++++++++++++++++- include/mci.h | 1 + 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c index d0caee22f2f7..84acb3d163b5 100644 --- a/drivers/mci/sdhci.c +++ b/drivers/mci/sdhci.c @@ -813,11 +813,10 @@ void sdhci_enable_clk(struct sdhci *host, u16 clk) int sdhci_wait_idle(struct sdhci *host, struct mci_cmd *cmd, struct mci_data *data) { u32 mask; - unsigned timeout_ms; + ktime_t timeout_ns; int ret; mask = SDHCI_CMD_INHIBIT_CMD; - timeout_ms = SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_MS; if (data || (cmd && (cmd->resp_type & MMC_RSP_BUSY))) mask |= SDHCI_CMD_INHIBIT_DATA; @@ -825,12 +824,10 @@ int sdhci_wait_idle(struct sdhci *host, struct mci_cmd *cmd, struct mci_data *da if (cmd && cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) mask &= ~SDHCI_CMD_INHIBIT_DATA; - if (cmd && cmd->busy_timeout != 0) - timeout_ms = cmd->busy_timeout; + timeout_ns = sdhci_compute_timeout(cmd, data, SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_NS); - ret = wait_on_timeout(timeout_ms * MSECOND, + ret = wait_on_timeout(timeout_ns, !(sdhci_read32(host, SDHCI_PRESENT_STATE) & mask)); - if (ret) { dev_err(sdhci_dev(host), "SDHCI timeout while waiting for idle\n"); @@ -843,19 +840,19 @@ int sdhci_wait_idle(struct sdhci *host, struct mci_cmd *cmd, struct mci_data *da int sdhci_wait_idle_data(struct sdhci *host, struct mci_cmd *cmd) { u32 mask; - unsigned timeout_ms; + unsigned timeout_ns; int ret; mask = SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA; - timeout_ms = SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_MS; + timeout_ns = SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_NS; if (cmd && cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) mask &= ~SDHCI_CMD_INHIBIT_DATA; if (cmd && cmd->busy_timeout != 0) - timeout_ms = cmd->busy_timeout; + timeout_ns = cmd->busy_timeout; - ret = wait_on_timeout(timeout_ms * MSECOND, + ret = wait_on_timeout(timeout_ns, !(sdhci_read32(host, SDHCI_PRESENT_STATE) & mask)); if (ret) { diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index d3b681153134..61058ca030a8 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -3,9 +3,11 @@ #define __MCI_SDHCI_H #include <pbl.h> +#include <mci.h> #include <dma.h> #include <linux/iopoll.h> #include <linux/sizes.h> +#include <linux/ktime.h> #define SDHCI_DMA_ADDRESS 0x00 #define SDHCI_BLOCK_SIZE__BLOCK_COUNT 0x04 @@ -201,7 +203,7 @@ #define SDHCI_MAX_DIV_SPEC_200 256 #define SDHCI_MAX_DIV_SPEC_300 2046 -#define SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_MS 10 +#define SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_NS (10 * NSEC_PER_MSEC) struct sdhci { u32 (*read32)(struct sdhci *host, int reg); @@ -352,4 +354,23 @@ void sdhci_set_bus_width(struct sdhci *host, int width); #define sdhci_read32_poll_timeout(sdhci, reg, val, cond, timeout_us) \ read_poll_timeout(sdhci_read32, val, cond, timeout_us, sdhci, reg) +/** + * sdhci_compute_timeout() - compute suitable timeout for operation + * @cmd: MCI command being sent, can be NULL + * @data: MCI data being sent, can be NULL + * @default_timeout: fallback value + * + * Return: the number of nanoseconds to wait. + */ +static inline ktime_t sdhci_compute_timeout(struct mci_cmd *cmd, struct mci_data *data, + ktime_t default_timeout) +{ + if (data && data->timeout_ns != 0) + return data->timeout_ns; + else if (cmd && cmd->busy_timeout != 0) + return cmd->busy_timeout * (u64)NSEC_PER_MSEC; + else + return SDHCI_CMD_DEFAULT_BUSY_TIMEOUT_NS; +} + #endif /* __MCI_SDHCI_H */ diff --git a/include/mci.h b/include/mci.h index 56527f956802..d3b855f530fc 100644 --- a/include/mci.h +++ b/include/mci.h @@ -513,6 +513,7 @@ struct mci_data { unsigned flags; /**< refer MMC_DATA_* to define direction */ unsigned blocks; /**< block count to handle in this command */ unsigned blocksize; /**< block size in bytes (mostly 512) */ + unsigned timeout_ns; /**< data timeout in ns */ }; enum mci_timing { -- 2.39.5