diff options
Diffstat (limited to 'arch/arm/mach-at91/clock.c')
-rw-r--r-- | arch/arm/mach-at91/clock.c | 88 |
1 files changed, 65 insertions, 23 deletions
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 61873f3aa92d..a5291e0e7004 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c | |||
@@ -47,26 +47,38 @@ | |||
47 | /* | 47 | /* |
48 | * Chips have some kind of clocks : group them by functionality | 48 | * Chips have some kind of clocks : group them by functionality |
49 | */ | 49 | */ |
50 | #define cpu_has_utmi() ( cpu_is_at91cap9() \ | 50 | #define cpu_has_utmi() ( cpu_is_at91sam9rl() \ |
51 | || cpu_is_at91sam9rl() \ | 51 | || cpu_is_at91sam9g45() \ |
52 | || cpu_is_at91sam9g45()) | 52 | || cpu_is_at91sam9x5()) |
53 | 53 | ||
54 | #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ | 54 | #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ |
55 | || cpu_is_at91sam9g45()) | 55 | || cpu_is_at91sam9g45() \ |
56 | || cpu_is_at91sam9x5()) | ||
56 | 57 | ||
57 | #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) | 58 | #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) |
58 | 59 | ||
59 | #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ | 60 | #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ |
60 | || cpu_is_at91sam9g45())) | 61 | || cpu_is_at91sam9g45() \ |
62 | || cpu_is_at91sam9x5())) | ||
61 | 63 | ||
62 | #define cpu_has_upll() (cpu_is_at91sam9g45()) | 64 | #define cpu_has_upll() (cpu_is_at91sam9g45() \ |
65 | || cpu_is_at91sam9x5()) | ||
63 | 66 | ||
64 | /* USB host HS & FS */ | 67 | /* USB host HS & FS */ |
65 | #define cpu_has_uhp() (!cpu_is_at91sam9rl()) | 68 | #define cpu_has_uhp() (!cpu_is_at91sam9rl()) |
66 | 69 | ||
67 | /* USB device FS only */ | 70 | /* USB device FS only */ |
68 | #define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \ | 71 | #define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \ |
69 | || cpu_is_at91sam9g45())) | 72 | || cpu_is_at91sam9g45() \ |
73 | || cpu_is_at91sam9x5())) | ||
74 | |||
75 | #define cpu_has_plladiv2() (cpu_is_at91sam9g45() \ | ||
76 | || cpu_is_at91sam9x5()) | ||
77 | |||
78 | #define cpu_has_mdiv3() (cpu_is_at91sam9g45() \ | ||
79 | || cpu_is_at91sam9x5()) | ||
80 | |||
81 | #define cpu_has_alt_prescaler() (cpu_is_at91sam9x5()) | ||
70 | 82 | ||
71 | static LIST_HEAD(clocks); | 83 | static LIST_HEAD(clocks); |
72 | static DEFINE_SPINLOCK(clk_lock); | 84 | static DEFINE_SPINLOCK(clk_lock); |
@@ -139,13 +151,6 @@ static void pmc_uckr_mode(struct clk *clk, int is_on) | |||
139 | { | 151 | { |
140 | unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR); | 152 | unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR); |
141 | 153 | ||
142 | if (cpu_is_at91sam9g45()) { | ||
143 | if (is_on) | ||
144 | uckr |= AT91_PMC_BIASEN; | ||
145 | else | ||
146 | uckr &= ~AT91_PMC_BIASEN; | ||
147 | } | ||
148 | |||
149 | if (is_on) { | 154 | if (is_on) { |
150 | is_on = AT91_PMC_LOCKU; | 155 | is_on = AT91_PMC_LOCKU; |
151 | at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask); | 156 | at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask); |
@@ -210,11 +215,24 @@ static struct clk __init *at91_css_to_clk(unsigned long css) | |||
210 | return &utmi_clk; | 215 | return &utmi_clk; |
211 | else if (cpu_has_pllb()) | 216 | else if (cpu_has_pllb()) |
212 | return &pllb; | 217 | return &pllb; |
218 | break; | ||
219 | /* alternate PMC: can use master clock */ | ||
220 | case AT91_PMC_CSS_MASTER: | ||
221 | return &mck; | ||
213 | } | 222 | } |
214 | 223 | ||
215 | return NULL; | 224 | return NULL; |
216 | } | 225 | } |
217 | 226 | ||
227 | static int pmc_prescaler_divider(u32 reg) | ||
228 | { | ||
229 | if (cpu_has_alt_prescaler()) { | ||
230 | return 1 << ((reg & AT91_PMC_ALT_PRES) >> PMC_ALT_PRES_OFFSET); | ||
231 | } else { | ||
232 | return 1 << ((reg & AT91_PMC_PRES) >> PMC_PRES_OFFSET); | ||
233 | } | ||
234 | } | ||
235 | |||
218 | static void __clk_enable(struct clk *clk) | 236 | static void __clk_enable(struct clk *clk) |
219 | { | 237 | { |
220 | if (clk->parent) | 238 | if (clk->parent) |
@@ -316,12 +334,22 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
316 | { | 334 | { |
317 | unsigned long flags; | 335 | unsigned long flags; |
318 | unsigned prescale; | 336 | unsigned prescale; |
337 | unsigned long prescale_offset, css_mask; | ||
319 | unsigned long actual; | 338 | unsigned long actual; |
320 | 339 | ||
321 | if (!clk_is_programmable(clk)) | 340 | if (!clk_is_programmable(clk)) |
322 | return -EINVAL; | 341 | return -EINVAL; |
323 | if (clk->users) | 342 | if (clk->users) |
324 | return -EBUSY; | 343 | return -EBUSY; |
344 | |||
345 | if (cpu_has_alt_prescaler()) { | ||
346 | prescale_offset = PMC_ALT_PRES_OFFSET; | ||
347 | css_mask = AT91_PMC_ALT_PCKR_CSS; | ||
348 | } else { | ||
349 | prescale_offset = PMC_PRES_OFFSET; | ||
350 | css_mask = AT91_PMC_CSS; | ||
351 | } | ||
352 | |||
325 | spin_lock_irqsave(&clk_lock, flags); | 353 | spin_lock_irqsave(&clk_lock, flags); |
326 | 354 | ||
327 | actual = clk->parent->rate_hz; | 355 | actual = clk->parent->rate_hz; |
@@ -330,8 +358,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
330 | u32 pckr; | 358 | u32 pckr; |
331 | 359 | ||
332 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); | 360 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); |
333 | pckr &= AT91_PMC_CSS; /* clock selection */ | 361 | pckr &= css_mask; /* keep clock selection */ |
334 | pckr |= prescale << 2; | 362 | pckr |= prescale << prescale_offset; |
335 | at91_sys_write(AT91_PMC_PCKR(clk->id), pckr); | 363 | at91_sys_write(AT91_PMC_PCKR(clk->id), pckr); |
336 | clk->rate_hz = actual; | 364 | clk->rate_hz = actual; |
337 | break; | 365 | break; |
@@ -378,11 +406,17 @@ static void __init init_programmable_clock(struct clk *clk) | |||
378 | { | 406 | { |
379 | struct clk *parent; | 407 | struct clk *parent; |
380 | u32 pckr; | 408 | u32 pckr; |
409 | unsigned int css_mask; | ||
410 | |||
411 | if (cpu_has_alt_prescaler()) | ||
412 | css_mask = AT91_PMC_ALT_PCKR_CSS; | ||
413 | else | ||
414 | css_mask = AT91_PMC_CSS; | ||
381 | 415 | ||
382 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); | 416 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); |
383 | parent = at91_css_to_clk(pckr & AT91_PMC_CSS); | 417 | parent = at91_css_to_clk(pckr & css_mask); |
384 | clk->parent = parent; | 418 | clk->parent = parent; |
385 | clk->rate_hz = parent->rate_hz / (1 << ((pckr & AT91_PMC_PRES) >> 2)); | 419 | clk->rate_hz = parent->rate_hz / pmc_prescaler_divider(pckr); |
386 | } | 420 | } |
387 | 421 | ||
388 | #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ | 422 | #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ |
@@ -602,8 +636,6 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock) | |||
602 | cpu_is_at91sam9g10()) { | 636 | cpu_is_at91sam9g10()) { |
603 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; | 637 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; |
604 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; | 638 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; |
605 | } else if (cpu_is_at91cap9()) { | ||
606 | uhpck.pmc_mask = AT91CAP9_PMC_UHP; | ||
607 | } | 639 | } |
608 | at91_sys_write(AT91_CKGR_PLLBR, 0); | 640 | at91_sys_write(AT91_CKGR_PLLBR, 0); |
609 | 641 | ||
@@ -666,7 +698,7 @@ int __init at91_clock_init(unsigned long main_clock) | |||
666 | if (pll_overclock) | 698 | if (pll_overclock) |
667 | pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); | 699 | pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); |
668 | 700 | ||
669 | if (cpu_is_at91sam9g45()) { | 701 | if (cpu_has_plladiv2()) { |
670 | mckr = at91_sys_read(AT91_PMC_MCKR); | 702 | mckr = at91_sys_read(AT91_PMC_MCKR); |
671 | plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12)); /* plla divisor by 2 */ | 703 | plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12)); /* plla divisor by 2 */ |
672 | } | 704 | } |
@@ -688,6 +720,10 @@ int __init at91_clock_init(unsigned long main_clock) | |||
688 | * (obtain the USB High Speed 480 MHz when input is 12 MHz) | 720 | * (obtain the USB High Speed 480 MHz when input is 12 MHz) |
689 | */ | 721 | */ |
690 | utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz; | 722 | utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz; |
723 | |||
724 | /* UTMI bias and PLL are managed at the same time */ | ||
725 | if (cpu_has_upll()) | ||
726 | utmi_clk.pmc_mask |= AT91_PMC_BIASEN; | ||
691 | } | 727 | } |
692 | 728 | ||
693 | /* | 729 | /* |
@@ -706,7 +742,7 @@ int __init at91_clock_init(unsigned long main_clock) | |||
706 | mckr = at91_sys_read(AT91_PMC_MCKR); | 742 | mckr = at91_sys_read(AT91_PMC_MCKR); |
707 | mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS); | 743 | mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS); |
708 | freq = mck.parent->rate_hz; | 744 | freq = mck.parent->rate_hz; |
709 | freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2)); /* prescale */ | 745 | freq /= pmc_prescaler_divider(mckr); /* prescale */ |
710 | if (cpu_is_at91rm9200()) { | 746 | if (cpu_is_at91rm9200()) { |
711 | mck.rate_hz = freq / (1 + ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ | 747 | mck.rate_hz = freq / (1 + ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ |
712 | } else if (cpu_is_at91sam9g20()) { | 748 | } else if (cpu_is_at91sam9g20()) { |
@@ -714,13 +750,19 @@ int __init at91_clock_init(unsigned long main_clock) | |||
714 | freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ | 750 | freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ |
715 | if (mckr & AT91_PMC_PDIV) | 751 | if (mckr & AT91_PMC_PDIV) |
716 | freq /= 2; /* processor clock division */ | 752 | freq /= 2; /* processor clock division */ |
717 | } else if (cpu_is_at91sam9g45()) { | 753 | } else if (cpu_has_mdiv3()) { |
718 | mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ? | 754 | mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ? |
719 | freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ | 755 | freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ |
720 | } else { | 756 | } else { |
721 | mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ | 757 | mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ |
722 | } | 758 | } |
723 | 759 | ||
760 | if (cpu_has_alt_prescaler()) { | ||
761 | /* Programmable clocks can use MCK */ | ||
762 | mck.type |= CLK_TYPE_PRIMARY; | ||
763 | mck.id = 4; | ||
764 | } | ||
765 | |||
724 | /* Register the PMC's standard clocks */ | 766 | /* Register the PMC's standard clocks */ |
725 | for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++) | 767 | for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++) |
726 | at91_clk_add(standard_pmc_clocks[i]); | 768 | at91_clk_add(standard_pmc_clocks[i]); |