summaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-mxc/clock.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-01-26 15:41:16 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2009-03-13 10:33:46 +0100
commita2865197a5dad23c619c84f44b7fdf7fdbef3f9c (patch)
treee62afa2bf72a8bad1cbfd400f79b92a13617fac6 /arch/arm/plat-mxc/clock.c
parent5512e88f3a1f1b498fd07181f14596ee117b3471 (diff)
downloadlinux-a2865197a5dad23c619c84f44b7fdf7fdbef3f9c.tar.bz2
[ARM] MXC: Use a single function for decoding a PLL
We had 3 versions of this function in clock support for MX1/2/3 Use a single one instead. I picked the one from the MX3 as it seems to calculate more accurate as the other ones. Also, on MX27 and MX31 mfn can be negative, this hasn't been handled correctly on MX27 since now. This patch has been tested on MX27 and MX31 and produces the same clock frequencies for me. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/plat-mxc/clock.c')
-rw-r--r--arch/arm/plat-mxc/clock.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 0a38f0b396eb..888dd33abf76 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -328,3 +328,47 @@ static int __init mxc_setup_proc_entry(void)
late_initcall(mxc_setup_proc_entry);
#endif
+
+/*
+ * Get the resulting clock rate from a PLL register value and the input
+ * frequency. PLLs with this register layout can at least be found on
+ * MX1, MX21, MX27 and MX31
+ *
+ * mfi + mfn / (mfd + 1)
+ * f = 2 * f_ref * --------------------
+ * pd + 1
+ */
+unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq)
+{
+ long long ll;
+ int mfn_abs;
+ unsigned int mfi, mfn, mfd, pd;
+
+ mfi = (reg_val >> 10) & 0xf;
+ mfn = reg_val & 0x3ff;
+ mfd = (reg_val >> 16) & 0x3ff;
+ pd = (reg_val >> 26) & 0xf;
+
+ mfi = mfi <= 5 ? 5 : mfi;
+
+ mfn_abs = mfn;
+
+#if !defined CONFIG_ARCH_MX1 && !defined CONFIG_ARCH_MX21
+ if (mfn >= 0x200) {
+ mfn |= 0xFFFFFE00;
+ mfn_abs = -mfn;
+ }
+#endif
+
+ freq *= 2;
+ freq /= pd + 1;
+
+ ll = (unsigned long long)freq * mfn_abs;
+
+ do_div(ll, mfd + 1);
+ if (mfn < 0)
+ ll = -ll;
+ ll = (freq * mfi) + ll;
+
+ return ll;
+}