aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mx1/clock.c31
-rw-r--r--arch/arm/mach-mx2/clock_imx27.c42
-rw-r--r--arch/arm/mach-mx3/clock.c26
-rw-r--r--arch/arm/plat-mxc/clock.c44
-rw-r--r--arch/arm/plat-mxc/include/mach/clock.h2
5 files changed, 57 insertions, 88 deletions
diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c
index 4bcd1ece55f5..3c464331b870 100644
--- a/arch/arm/mach-mx1/clock.c
+++ b/arch/arm/mach-mx1/clock.c
@@ -87,33 +87,6 @@ static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
87 return clk->parent->set_rate(clk->parent, rate); 87 return clk->parent->set_rate(clk->parent, rate);
88} 88}
89 89
90/*
91 * get the system pll clock in Hz
92 *
93 * mfi + mfn / (mfd +1)
94 * f = 2 * f_ref * --------------------
95 * pd + 1
96 */
97static unsigned long mx1_decode_pll(unsigned int pll, u32 f_ref)
98{
99 unsigned long long ll;
100 unsigned long quot;
101
102 u32 mfi = (pll >> 10) & 0xf;
103 u32 mfn = pll & 0x3ff;
104 u32 mfd = (pll >> 16) & 0x3ff;
105 u32 pd = (pll >> 26) & 0xf;
106
107 mfi = mfi <= 5 ? 5 : mfi;
108
109 ll = 2 * (unsigned long long)f_ref *
110 ((mfi << 16) + (mfn << 16) / (mfd + 1));
111 quot = (pd + 1) * (1 << 16);
112 ll += quot / 2;
113 do_div(ll, quot);
114 return (unsigned long)ll;
115}
116
117static unsigned long clk16m_get_rate(struct clk *clk) 90static unsigned long clk16m_get_rate(struct clk *clk)
118{ 91{
119 return 16000000; 92 return 16000000;
@@ -188,7 +161,7 @@ static struct clk prem_clk = {
188 161
189static unsigned long system_clk_get_rate(struct clk *clk) 162static unsigned long system_clk_get_rate(struct clk *clk)
190{ 163{
191 return mx1_decode_pll(__raw_readl(CCM_SPCTL0), 164 return mxc_decode_pll(__raw_readl(CCM_SPCTL0),
192 clk_get_rate(clk->parent)); 165 clk_get_rate(clk->parent));
193} 166}
194 167
@@ -200,7 +173,7 @@ static struct clk system_clk = {
200 173
201static unsigned long mcu_clk_get_rate(struct clk *clk) 174static unsigned long mcu_clk_get_rate(struct clk *clk)
202{ 175{
203 return mx1_decode_pll(__raw_readl(CCM_MPCTL0), 176 return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
204 clk_get_rate(clk->parent)); 177 clk_get_rate(clk->parent));
205} 178}
206 179
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c
index c69896d011a1..047e71e6ea9a 100644
--- a/arch/arm/mach-mx2/clock_imx27.c
+++ b/arch/arm/mach-mx2/clock_imx27.c
@@ -486,26 +486,8 @@ static struct clk ckil_clk = {
486 486
487static unsigned long get_mpll_clk(struct clk *clk) 487static unsigned long get_mpll_clk(struct clk *clk)
488{ 488{
489 uint32_t reg; 489 return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
490 unsigned long ref_clk; 490 clk_get_rate(clk->parent));
491 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
492 unsigned long long temp;
493
494 ref_clk = clk_get_rate(clk->parent);
495
496 reg = __raw_readl(CCM_MPCTL0);
497 pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
498 mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
499 mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
500 mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
501
502 mfi = (mfi <= 5) ? 5 : mfi;
503 temp = 2LL * ref_clk * mfn;
504 do_div(temp, mfd + 1);
505 temp = 2LL * ref_clk * mfi + temp;
506 do_div(temp, pdf + 1);
507
508 return (unsigned long)temp;
509} 491}
510 492
511static struct clk mpll_clk = { 493static struct clk mpll_clk = {
@@ -555,28 +537,18 @@ static unsigned long get_spll_clk(struct clk *clk)
555{ 537{
556 uint32_t reg; 538 uint32_t reg;
557 unsigned long ref_clk; 539 unsigned long ref_clk;
558 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
559 unsigned long long temp;
560 540
561 ref_clk = clk_get_rate(clk->parent); 541 ref_clk = clk_get_rate(clk->parent);
562 542
563 reg = __raw_readl(CCM_SPCTL0); 543 reg = __raw_readl(CCM_SPCTL0);
564 /*TODO: This is TO2 Bug */ 544
545 /* On TO2 we have to write the value back. Otherwise we
546 * read 0 from this register the next time.
547 */
565 if (mx27_revision() >= CHIP_REV_2_0) 548 if (mx27_revision() >= CHIP_REV_2_0)
566 __raw_writel(reg, CCM_SPCTL0); 549 __raw_writel(reg, CCM_SPCTL0);
567 550
568 pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET; 551 return mxc_decode_pll(reg, ref_clk);
569 mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
570 mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
571 mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
572
573 mfi = (mfi <= 5) ? 5 : mfi;
574 temp = 2LL * ref_clk * mfn;
575 do_div(temp, mfd + 1);
576 temp = 2LL * ref_clk * mfi + temp;
577 do_div(temp, pdf + 1);
578
579 return (unsigned long)temp;
580} 552}
581 553
582static struct clk spll_clk = { 554static struct clk spll_clk = {
diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c
index b1746aae1f89..8486ea46d6c1 100644
--- a/arch/arm/mach-mx3/clock.c
+++ b/arch/arm/mach-mx3/clock.c
@@ -158,10 +158,8 @@ static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
158 158
159static unsigned long _clk_pll_get_rate(struct clk *clk) 159static unsigned long _clk_pll_get_rate(struct clk *clk)
160{ 160{
161 long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
162 unsigned long reg, ccmr; 161 unsigned long reg, ccmr;
163 s64 temp; 162 unsigned int prcs, ref_clk;
164 unsigned int prcs;
165 163
166 ccmr = __raw_readl(MXC_CCM_CCMR); 164 ccmr = __raw_readl(MXC_CCM_CCMR);
167 prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET; 165 prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
@@ -185,27 +183,7 @@ static unsigned long _clk_pll_get_rate(struct clk *clk)
185 return 0; 183 return 0;
186 } 184 }
187 185
188 pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET; 186 return mxc_decode_pll(reg, ref_clk);
189 mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
190 mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
191 mfi = (mfi <= 5) ? 5 : mfi;
192 mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
193
194 if (mfn >= 0x200) {
195 mfn |= 0xFFFFFE00;
196 mfn_abs = -mfn;
197 }
198
199 ref_clk *= 2;
200 ref_clk /= pdf + 1;
201
202 temp = (u64) ref_clk * mfn_abs;
203 do_div(temp, mfd + 1);
204 if (mfn < 0)
205 temp = -temp;
206 temp = (ref_clk * mfi) + temp;
207
208 return temp;
209} 187}
210 188
211static int _clk_usb_pll_enable(struct clk *clk) 189static int _clk_usb_pll_enable(struct clk *clk)
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)
328 328
329late_initcall(mxc_setup_proc_entry); 329late_initcall(mxc_setup_proc_entry);
330#endif 330#endif
331
332/*
333 * Get the resulting clock rate from a PLL register value and the input
334 * frequency. PLLs with this register layout can at least be found on
335 * MX1, MX21, MX27 and MX31
336 *
337 * mfi + mfn / (mfd + 1)
338 * f = 2 * f_ref * --------------------
339 * pd + 1
340 */
341unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq)
342{
343 long long ll;
344 int mfn_abs;
345 unsigned int mfi, mfn, mfd, pd;
346
347 mfi = (reg_val >> 10) & 0xf;
348 mfn = reg_val & 0x3ff;
349 mfd = (reg_val >> 16) & 0x3ff;
350 pd = (reg_val >> 26) & 0xf;
351
352 mfi = mfi <= 5 ? 5 : mfi;
353
354 mfn_abs = mfn;
355
356#if !defined CONFIG_ARCH_MX1 && !defined CONFIG_ARCH_MX21
357 if (mfn >= 0x200) {
358 mfn |= 0xFFFFFE00;
359 mfn_abs = -mfn;
360 }
361#endif
362
363 freq *= 2;
364 freq /= pd + 1;
365
366 ll = (unsigned long long)freq * mfn_abs;
367
368 do_div(ll, mfd + 1);
369 if (mfn < 0)
370 ll = -ll;
371 ll = (freq * mfi) + ll;
372
373 return ll;
374}
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index d21f78e78819..b830655514eb 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -63,5 +63,7 @@ struct clk {
63int clk_register(struct clk *clk); 63int clk_register(struct clk *clk);
64void clk_unregister(struct clk *clk); 64void clk_unregister(struct clk *clk);
65 65
66unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
67
66#endif /* __ASSEMBLY__ */ 68#endif /* __ASSEMBLY__ */
67#endif /* __ASM_ARCH_MXC_CLOCK_H__ */ 69#endif /* __ASM_ARCH_MXC_CLOCK_H__ */