Commit 1ff9cabd authored by Chen-Yu Tsai's avatar Chen-Yu Tsai Committed by Ulf Hansson

mmc: sunxi: Clarify new timing mode usage and implementation

Newer sunxi mmc controller variants support what they call the "new
timing mode". Support for this was implemented in two ways, according
to the hardware that was seen at the time.

The first type retained the old timing mode, and both the clock and mmc
controllers had switches to select which mode was used. Both switches
had to be set to the same setting. This variant was denoted with the
.has_timings_switch field in the sunxi_mmc_cfg structure. This hardware
is only seen on the A83T.

The second type did away with the old timing mode. The clock controller
no longer had the mode selection or clock delay setting bits. In some
cases the mmc controller retained its mode selection bit, but this
always needed to be set to the new mode, or instabilities would occur.
In a few cases, such as the A64 and H6 eMMC controller, the mode
selection bit is gone, but the controller still behaves like the new
timing mode, requiring the module clock to be double the card clock
in DDR transfer modes. This variant is denoted with the
.needs_new_timings field.

This patch adds more comments explaining the two fields, as well as
the possibly nonexistent mode switch in the mmc controller.

The .has_timings_switch is renamed to .ccu_has_timings_switch to clarify
its meaning.
Signed-off-by: default avatarChen-Yu Tsai <wens@csie.org>
Acked-by: default avatarMaxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent fb8bd90f
...@@ -258,11 +258,16 @@ struct sunxi_mmc_cfg { ...@@ -258,11 +258,16 @@ struct sunxi_mmc_cfg {
/* Does DATA0 needs to be masked while the clock is updated */ /* Does DATA0 needs to be masked while the clock is updated */
bool mask_data0; bool mask_data0;
/* hardware only supports new timing mode */ /*
* hardware only supports new timing mode, either due to lack of
* a mode switch in the clock controller, or the mmc controller
* is permanently configured in the new timing mode, without the
* NTSR mode switch.
*/
bool needs_new_timings; bool needs_new_timings;
/* hardware can switch between old and new timing modes */ /* clock hardware can switch between old and new timing modes */
bool has_timings_switch; bool ccu_has_timings_switch;
}; };
struct sunxi_mmc_host { struct sunxi_mmc_host {
...@@ -787,7 +792,7 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, ...@@ -787,7 +792,7 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
clock <<= 1; clock <<= 1;
} }
if (host->use_new_timings && host->cfg->has_timings_switch) { if (host->use_new_timings && host->cfg->ccu_has_timings_switch) {
ret = sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true); ret = sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true);
if (ret) { if (ret) {
dev_err(mmc_dev(mmc), dev_err(mmc_dev(mmc),
...@@ -822,6 +827,12 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, ...@@ -822,6 +827,12 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
/* update card clock rate to account for internal divider */ /* update card clock rate to account for internal divider */
rate /= div; rate /= div;
/*
* Configure the controller to use the new timing mode if needed.
* On controllers that only support the new timing mode, such as
* the eMMC controller on the A64, this register does not exist,
* and any writes to it are ignored.
*/
if (host->use_new_timings) { if (host->use_new_timings) {
/* Don't touch the delay bits */ /* Don't touch the delay bits */
rval = mmc_readl(host, REG_SD_NTSR); rval = mmc_readl(host, REG_SD_NTSR);
...@@ -1145,7 +1156,7 @@ static const struct sunxi_mmc_cfg sun8i_a83t_emmc_cfg = { ...@@ -1145,7 +1156,7 @@ static const struct sunxi_mmc_cfg sun8i_a83t_emmc_cfg = {
.idma_des_size_bits = 16, .idma_des_size_bits = 16,
.clk_delays = sunxi_mmc_clk_delays, .clk_delays = sunxi_mmc_clk_delays,
.can_calibrate = false, .can_calibrate = false,
.has_timings_switch = true, .ccu_has_timings_switch = true,
}; };
static const struct sunxi_mmc_cfg sun9i_a80_cfg = { static const struct sunxi_mmc_cfg sun9i_a80_cfg = {
...@@ -1351,7 +1362,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev) ...@@ -1351,7 +1362,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
goto error_free_host; goto error_free_host;
} }
if (host->cfg->has_timings_switch) { if (host->cfg->ccu_has_timings_switch) {
/* /*
* Supports both old and new timing modes. * Supports both old and new timing modes.
* Try setting the clk to new timing mode. * Try setting the clk to new timing mode.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment