diff options
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/clock.c | 62 |
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 | ||
65 | static LIST_HEAD(clocks); | 70 | static LIST_HEAD(clocks); |
66 | static DEFINE_SPINLOCK(clk_lock); | 71 | static 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 | } |