From 6a8c2018e872906dddf34da40ddcac54cd7b967f Mon Sep 17 00:00:00 2001 From: =?utf8?q?M=C3=A5rten=20Lindahl?= Date: Fri, 19 Nov 2021 16:53:37 +0100 Subject: [PATCH] mmc: dw_mmc: Allow lower TMOUT value than maximum MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The TMOUT register is always set with a full value for every transfer, which (with a 200MHz clock) will give a full DRTO of ~84 milliseconds. This is normally good enough to complete the request, but setting a full value makes it impossible to test shorter timeouts, when for example testing data read times on different SD cards. Add a function to set any value smaller than the maximum of 0xFFFFFF. Signed-off-by: MÃ¥rten Lindahl Reviewed-by: Douglas Anderson Reviewed-by: Jaehoon Chung Link: https://lore.kernel.org/r/20211119155337.14341-1-marten.lindahl@axis.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 439080fbd87d8..195f2b2434b0e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1284,6 +1284,33 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) mci_writel(host, CTYPE, (slot->ctype << slot->id)); } +static void dw_mci_set_data_timeout(struct dw_mci *host, + unsigned int timeout_ns) +{ + u32 clk_div, tmout; + u64 tmp; + + clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2; + if (clk_div == 0) + clk_div = 1; + + tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz, NSEC_PER_SEC); + tmp = DIV_ROUND_UP_ULL(tmp, clk_div); + + /* TMOUT[7:0] (RESPONSE_TIMEOUT) */ + tmout = 0xFF; /* Set maximum */ + + /* TMOUT[31:8] (DATA_TIMEOUT) */ + if (!tmp || tmp > 0xFFFFFF) + tmout |= (0xFFFFFF << 8); + else + tmout |= (tmp & 0xFFFFFF) << 8; + + mci_writel(host, TMOUT, tmout); + dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%#08x", + timeout_ns, tmout >> 8); +} + static void __dw_mci_start_request(struct dw_mci *host, struct dw_mci_slot *slot, struct mmc_command *cmd) @@ -1304,7 +1331,7 @@ static void __dw_mci_start_request(struct dw_mci *host, data = cmd->data; if (data) { - mci_writel(host, TMOUT, 0xFFFFFFFF); + dw_mci_set_data_timeout(host, data->timeout_ns); mci_writel(host, BYTCNT, data->blksz*data->blocks); mci_writel(host, BLKSIZ, data->blksz); } -- 2.30.2