[PATCH 2/2] mmc: t210: Fix 'bad' SD-card clock when doing 400KHz card detect
Jaehoon Chung
jh80.chung at samsung.com
Thu Apr 2 03:59:26 CEST 2020
On 3/27/20 7:30 AM, tomcwarren3959 at gmail.com wrote:
> From: Tom Warren <twarren at nvidia.com>
>
> 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 at nvidia.com>
Reviewed-by: Jaehoon Chung <jh80.chung at samsung.com>
Best Regards,
Jaehoon Chung
> ---
> Changes for v2:
> - None
>
> arch/arm/include/asm/arch-tegra/tegra_mmc.h | 2 +-
> drivers/mmc/tegra_mmc.c | 18 ++++++++++++++++++
> 2 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> index a8bfa46..70dcf4a 100644
> --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
> @@ -130,9 +130,9 @@ struct tegra_mmc {
> /* SDMMC1/3 settings from SDMMCx Initialization Sequence of TRM */
> #define MEMCOMP_PADCTRL_VREF 7
> #define AUTO_CAL_ENABLE (1 << 29)
> -#if defined(CONFIG_TEGRA210)
> #define AUTO_CAL_ACTIVE (1 << 31)
> #define AUTO_CAL_START (1 << 31)
> +#if defined(CONFIG_TEGRA210)
> #define AUTO_CAL_PD_OFFSET (0x7D << 8)
> #define AUTO_CAL_PU_OFFSET (0 << 0)
> #define IO_TRIM_BYPASS_MASK (1 << 2)
> diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
> index 73ac58c..03110ba 100644
> --- a/drivers/mmc/tegra_mmc.c
> +++ b/drivers/mmc/tegra_mmc.c
> @@ -376,6 +376,24 @@ 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);
>
More information about the U-Boot
mailing list