aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91/clock.c
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2009-06-26 10:36:57 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-06-27 06:05:20 -0400
commit2ef9df7ada6b6dd53446a994ef6e3a6ad5a300ef (patch)
treeaed60121be40c93aa8a8a4e46248032f8a4d885e /arch/arm/mach-at91/clock.c
parent7c6425a0404399ba78852ef4108007ecf51ef3dc (diff)
[ARM] 5569/1: at91: Support for at91sam9g45: clocks management
Add the at91sam9g45 series support to the AT91 generic clock file. This takes care of the particularities of the PMC for this series. It also takes advantage of the management by functionalities of those PLLs and clocks. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-at91/clock.c')
-rw-r--r--arch/arm/mach-at91/clock.c62
1 files changed, 52 insertions, 10 deletions
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index bac578fe0d3d..6396680271e8 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -47,20 +47,25 @@
47 * Chips have some kind of clocks : group them by functionality 47 * Chips have some kind of clocks : group them by functionality
48 */ 48 */
49#define cpu_has_utmi() ( cpu_is_at91cap9() \ 49#define cpu_has_utmi() ( cpu_is_at91cap9() \
50 || cpu_is_at91sam9rl()) 50 || cpu_is_at91sam9rl() \
51 || cpu_is_at91sam9g45())
51 52
52#define cpu_has_800M_plla() (cpu_is_at91sam9g20()) 53#define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \
54 || cpu_is_at91sam9g45())
53 55
54#define cpu_has_pllb() (!cpu_is_at91sam9rl()) 56#define cpu_has_300M_plla() (0)
55 57
56#define cpu_has_upll() (0) 58#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
59 || cpu_is_at91sam9g45()))
60
61#define cpu_has_upll() (cpu_is_at91sam9g45())
57 62
58/* USB host HS & FS */ 63/* USB host HS & FS */
59#define cpu_has_uhp() (!cpu_is_at91sam9rl()) 64#define cpu_has_uhp() (!cpu_is_at91sam9rl())
60 65
61/* USB device FS only */ 66/* USB device FS only */
62#define cpu_has_udpfs() (!cpu_is_at91sam9rl()) 67#define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \
63 68 || cpu_is_at91sam9g45()))
64 69
65static LIST_HEAD(clocks); 70static LIST_HEAD(clocks);
66static DEFINE_SPINLOCK(clk_lock); 71static DEFINE_SPINLOCK(clk_lock);
@@ -133,6 +138,13 @@ static void pmc_uckr_mode(struct clk *clk, int is_on)
133{ 138{
134 unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR); 139 unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
135 140
141 if (cpu_is_at91sam9g45()) {
142 if (is_on)
143 uckr |= AT91_PMC_BIASEN;
144 else
145 uckr &= ~AT91_PMC_BIASEN;
146 }
147
136 if (is_on) { 148 if (is_on) {
137 is_on = AT91_PMC_LOCKU; 149 is_on = AT91_PMC_LOCKU;
138 at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask); 150 at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask);
@@ -310,6 +322,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
310 unsigned long flags; 322 unsigned long flags;
311 unsigned prescale; 323 unsigned prescale;
312 unsigned long actual; 324 unsigned long actual;
325 unsigned long prev = ULONG_MAX;
313 326
314 if (!clk_is_programmable(clk)) 327 if (!clk_is_programmable(clk))
315 return -EINVAL; 328 return -EINVAL;
@@ -317,8 +330,16 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
317 330
318 actual = clk->parent->rate_hz; 331 actual = clk->parent->rate_hz;
319 for (prescale = 0; prescale < 7; prescale++) { 332 for (prescale = 0; prescale < 7; prescale++) {
320 if (actual && actual <= rate) 333 if (actual > rate)
334 prev = actual;
335
336 if (actual && actual <= rate) {
337 if ((prev - rate) < (rate - actual)) {
338 actual = prev;
339 prescale--;
340 }
321 break; 341 break;
342 }
322 actual >>= 1; 343 actual >>= 1;
323 } 344 }
324 345
@@ -373,6 +394,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
373 return -EBUSY; 394 return -EBUSY;
374 if (!clk_is_primary(parent) || !clk_is_programmable(clk)) 395 if (!clk_is_primary(parent) || !clk_is_programmable(clk))
375 return -EINVAL; 396 return -EINVAL;
397
398 if (cpu_is_at91sam9rl() && parent->id == AT91_PMC_CSS_PLLB)
399 return -EINVAL;
400
376 spin_lock_irqsave(&clk_lock, flags); 401 spin_lock_irqsave(&clk_lock, flags);
377 402
378 clk->rate_hz = parent->rate_hz; 403 clk->rate_hz = parent->rate_hz;
@@ -637,6 +662,7 @@ int __init at91_clock_init(unsigned long main_clock)
637{ 662{
638 unsigned tmp, freq, mckr; 663 unsigned tmp, freq, mckr;
639 int i; 664 int i;
665 int pll_overclock = false;
640 666
641 /* 667 /*
642 * When the bootloader initialized the main oscillator correctly, 668 * When the bootloader initialized the main oscillator correctly,
@@ -654,12 +680,25 @@ int __init at91_clock_init(unsigned long main_clock)
654 680
655 /* report if PLLA is more than mildly overclocked */ 681 /* report if PLLA is more than mildly overclocked */
656 plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR)); 682 plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
657 if ((!cpu_has_800M_plla() && plla.rate_hz > 209000000) 683 if (cpu_has_300M_plla()) {
658 || (cpu_has_800M_plla() && plla.rate_hz > 800000000)) 684 if (plla.rate_hz > 300000000)
685 pll_overclock = true;
686 } else if (cpu_has_800M_plla()) {
687 if (plla.rate_hz > 800000000)
688 pll_overclock = true;
689 } else {
690 if (plla.rate_hz > 209000000)
691 pll_overclock = true;
692 }
693 if (pll_overclock)
659 pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); 694 pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
660 695
696 if (cpu_is_at91sam9g45()) {
697 mckr = at91_sys_read(AT91_PMC_MCKR);
698 plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12)); /* plla divisor by 2 */
699 }
661 700
662 if (cpu_has_upll() && !cpu_has_pllb()) { 701 if (!cpu_has_pllb() && cpu_has_upll()) {
663 /* setup UTMI clock as the fourth primary clock 702 /* setup UTMI clock as the fourth primary clock
664 * (instead of pllb) */ 703 * (instead of pllb) */
665 utmi_clk.type |= CLK_TYPE_PRIMARY; 704 utmi_clk.type |= CLK_TYPE_PRIMARY;
@@ -701,6 +740,9 @@ int __init at91_clock_init(unsigned long main_clock)
701 freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ 740 freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */
702 if (mckr & AT91_PMC_PDIV) 741 if (mckr & AT91_PMC_PDIV)
703 freq /= 2; /* processor clock division */ 742 freq /= 2; /* processor clock division */
743 } else if (cpu_is_at91sam9g45()) {
744 mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ?
745 freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
704 } else { 746 } else {
705 mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ 747 mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
706 } 748 }