diff options
-rw-r--r-- | arch/arm/mach-mx1/clock.c | 31 | ||||
-rw-r--r-- | arch/arm/mach-mx2/clock_imx27.c | 42 | ||||
-rw-r--r-- | arch/arm/mach-mx3/clock.c | 26 | ||||
-rw-r--r-- | arch/arm/plat-mxc/clock.c | 44 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/clock.h | 2 |
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 | */ | ||
97 | static 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 | |||
117 | static unsigned long clk16m_get_rate(struct clk *clk) | 90 | static 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 | ||
189 | static unsigned long system_clk_get_rate(struct clk *clk) | 162 | static 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 | ||
201 | static unsigned long mcu_clk_get_rate(struct clk *clk) | 174 | static 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 | ||
487 | static unsigned long get_mpll_clk(struct clk *clk) | 487 | static 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 | ||
511 | static struct clk mpll_clk = { | 493 | static 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 | ||
582 | static struct clk spll_clk = { | 554 | static 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 | ||
159 | static unsigned long _clk_pll_get_rate(struct clk *clk) | 159 | static 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 | ||
211 | static int _clk_usb_pll_enable(struct clk *clk) | 189 | static 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 | ||
329 | late_initcall(mxc_setup_proc_entry); | 329 | late_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 | */ | ||
341 | unsigned 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 { | |||
63 | int clk_register(struct clk *clk); | 63 | int clk_register(struct clk *clk); |
64 | void clk_unregister(struct clk *clk); | 64 | void clk_unregister(struct clk *clk); |
65 | 65 | ||
66 | unsigned 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__ */ |