diff mbox

[U-Boot] ARM: tegra: fix PLLP frequency calc on T210

Message ID 1440025439-3578-1-git-send-email-swarren@wwwdotorg.org
State Accepted
Delegated to: Tom Warren
Headers show

Commit Message

Stephen Warren Aug. 19, 2015, 11:03 p.m. UTC
From: Stephen Warren <swarren@nvidia.com>

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 <treding@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/mach-tegra/clock.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index f9dfcd04115a..b85f63848f2c 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;
 }