Commit 6a8c2018 authored by Mårten Lindahl's avatar Mårten Lindahl Committed by Ulf Hansson
Browse files

mmc: dw_mmc: Allow lower TMOUT value than maximum



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: default avatarMårten Lindahl <marten.lindahl@axis.com>
Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Reviewed-by: default avatarJaehoon Chung <jh80.chung@samsung.com>
Link: https://lore.kernel.org/r/20211119155337.14341-1-marten.lindahl@axis.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 76bfc7cc
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -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);
	}