Re: [PATCH 2/2] mmc: t210: Fix 'bad' SD-card clock when doing 400KHz card detect
On 3/27/20 7:30 AM, tomcwarren3...@gmail.com wrote: > From: Tom Warren > > 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 Reviewed-by: Jaehoon Chung 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(>clk, clock); > div = (rate + clock - 1) / clock; > + > +#if defined(CONFIG_TEGRA210) > + if (priv->mmc_id == PERIPH_ID_SDMMC1 && clock <= 40) { > + /* 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, > + ); > +#endif > debug("div = %d\n", div); > > writew(0, >reg->clkcon); >
[PATCH 2/2] mmc: t210: Fix 'bad' SD-card clock when doing 400KHz card detect
From: Tom Warren 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 --- 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(>clk, clock); div = (rate + clock - 1) / clock; + +#if defined(CONFIG_TEGRA210) + if (priv->mmc_id == PERIPH_ID_SDMMC1 && clock <= 40) { + /* 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, + ); +#endif debug("div = %d\n", div); writew(0, >reg->clkcon); -- 1.8.2.1.610.g562af5b --- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ---
[PATCH 2/2] mmc: t210: Fix 'bad' SD-card clock when doing 400KHz card detect
From: Tom Warren 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 --- 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 a4bd679..3ca947c 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(>clk, clock); div = (rate + clock - 1) / clock; + +#if defined(CONFIG_TEGRA210) + if (priv->mmc_id == PERIPH_ID_SDMMC1 && clock <= 40) { + /* 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, + ); +#endif debug("div = %d\n", div); writew(0, >reg->clkcon); -- 1.8.2.1.610.g562af5b --- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ---