From: Stephen Warren Date: Wed, 19 Aug 2015 23:03:59 +0000 (-0600) Subject: ARM: tegra: fix PLLP frequency calc on T210 X-Git-Tag: v2015.10-rc4~37 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6c7dc6236a48752be548e0c6965b5a4a9076af11;p=oweals%2Fu-boot.git ARM: tegra: fix PLLP frequency calc on T210 AFAIK, for all PLLs on all Tegra SoCs, the primary PLL output frequency is (input * m) / (n * p). However, PLLP's primary output (pllP_out0) on T210 is the VCO output, and divp is not applied. pllP_out2 does have divp applied. All other pllP_outN are divided down from pllP_out0. We only support pllP_out0 in U-Boot at the time of writing. Fix clock_get_rate() to handle this special case. This corrects the returned rate for PLLP to be 408MHz rather than 204MHz. In turn, this causes high enough dividers to be calculated for the various peripheral clocks that feed off of PLLP. Without this, some peripherals failed to operate correctly. For instance, one of my SD cards worked perfectly but an older (presumably slower) card could not be read. Note that prior to commit 722e000ccd72 "Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.", the calculated PLL frequency was 816MHz since the wrong values were being extracted from the PLLP divider register. This caused overly large peripheral dividers to be calculated, which while wrong, didn't cause any correctness issues; things simply ran slower than they could. Reported-by: Thierry Reding Signed-off-by: Stephen Warren Signed-off-by: Tom Warren --- diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index f9dfcd0411..b85f63848f 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -483,7 +483,16 @@ unsigned clock_get_rate(enum clock_id clkid) * PLLU uses p_mask/p_shift for VCO on all but T210, * T210 uses normal DIVP. Handled in pllinfo table. */ - divm <<= (base >> pllinfo->p_shift) & pllinfo->p_mask; +#ifdef CONFIG_TEGRA210 + /* + * PLLP's primary output (pllP_out0) on T210 is the VCO, and divp is + * not applied. pllP_out2 does have divp applied. All other pllP_outN + * are divided down from pllP_out0. We only support pllP_out0 in + * U-Boot at the time of writing this comment. + */ + if (clkid != CLOCK_ID_PERIPH) +#endif + divm <<= (base >> pllinfo->p_shift) & pllinfo->p_mask; do_div(rate, divm); return rate; }