summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Warren <twarren@nvidia.com>2019-06-03 16:06:34 -0700
committerTom Warren <twarren@nvidia.com>2020-04-02 14:30:01 -0700
commita482f32992230d8bdae2caa72056ab7d9208d5f0 (patch)
tree02b8009a11d357044536905c5eeb79e8d1ceba3e /drivers
parent5e965e814067e7539943bbaeb47d7bf9738a701b (diff)
mmc: t210: Fix 'bad' SD-card clock when doing 400KHz card detect
According to the HW team, for some reason the normal clock select code picks what appears to be a perfectly valid 375KHz SD card clock, based on the CAR clock source and SDMMC1 controller register settings (CAR = 408MHz PLLP0 divided by 68 for 6MHz, then a SD Clock Control register divisor of 16 = 375KHz). But the resulting SD card clock, as measured by the HW team, is 700KHz, which is out-of-spec. So the WAR is to use the values given in the TRM PLLP table to generate a 400KHz SD-clock (CAR clock of 24.7MHz, SD Clock Control divisor of 62) only for SDMMC1 on T210 when the requested clock is <= 400KHz. Note that as far as I can tell, the other requests for clocks in the Tegra MMC driver result in valid SD clocks. Signed-off-by: Tom Warren <twarren@nvidia.com> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/tegra_mmc.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 73ac58c6c8..2b041562a6 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -376,6 +376,25 @@ static void tegra_mmc_change_clock(struct tegra_mmc_priv *priv, uint clock)
rate = clk_set_rate(&priv->clk, clock);
div = (rate + clock - 1) / clock;
+
+#if defined(CONFIG_TEGRA210)
+ if (priv->mmc_id == PERIPH_ID_SDMMC1 && clock <= 400000) {
+ /* clock_adjust_periph_pll_div() chooses a 'bad' clock
+ * on SDMMC1 T210, so skip it here and force a clock
+ * that's been spec'd in the table in the TRM for
+ * card-detect (400KHz).
+ */
+ uint effective_rate = clock_adjust_periph_pll_div(priv->mmc_id,
+ CLOCK_ID_PERIPH, 24727273, NULL);
+ div = 62;
+
+ debug("%s: WAR: Using SDMMC1 clock of %u, div %d to achieve %dHz card clock ...\n",
+ __func__, effective_rate, div, clock);
+ } else {
+ clock_adjust_periph_pll_div(priv->mmc_id, CLOCK_ID_PERIPH,
+ clock, &div);
+ }
+#endif
debug("div = %d\n", div);
writew(0, &priv->reg->clkcon);