diff options
author | Andrew Victor <andrew@sanpeople.com> | 2006-03-22 15:14:14 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-03-22 15:14:14 -0500 |
commit | 69b648a200b27a7c8ea92993bf5b4d40e83b5403 (patch) | |
tree | 0ddc77b61b5f822424fe6dfa66a16785986d87b9 /arch | |
parent | 39806805de0314d5847bfd6d046ad7d4407ccd46 (diff) |
[ARM] 3386/1: AT91RM9200 Clock update
Patch from Andrew Victor
This patch includes a few changes to the clock support on the
AT91RM9200.
1. Added definitions for Ethernet, MMC, TWI, USARTs, and SPI peripheral
clocks.
2. Replaced some hard-coded hex values with the text definitions in
at91rm9200_sys.h.
3. If the USB96M bit is set for PLLB, then the rate of PLLB is not
affected but only the USB Host/Device clocks which are derived from it.
Issue reported by Sergei Sharonov.
Signed-off-by: Andrew Victor <andrew@sanpeople.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-at91rm9200/clock.c | 85 |
1 files changed, 73 insertions, 12 deletions
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index ec8195a2a3cc..8b95467c6d61 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c | |||
@@ -201,6 +201,54 @@ static struct clk ohci_clk = { | |||
201 | .pmc_mask = 1 << AT91_ID_UHP, | 201 | .pmc_mask = 1 << AT91_ID_UHP, |
202 | .mode = pmc_periph_mode, | 202 | .mode = pmc_periph_mode, |
203 | }; | 203 | }; |
204 | static struct clk ether_clk = { | ||
205 | .name = "ether_clk", | ||
206 | .parent = &mck, | ||
207 | .pmc_mask = 1 << AT91_ID_EMAC, | ||
208 | .mode = pmc_periph_mode, | ||
209 | }; | ||
210 | static struct clk mmc_clk = { | ||
211 | .name = "mci_clk", | ||
212 | .parent = &mck, | ||
213 | .pmc_mask = 1 << AT91_ID_MCI, | ||
214 | .mode = pmc_periph_mode, | ||
215 | }; | ||
216 | static struct clk twi_clk = { | ||
217 | .name = "twi_clk", | ||
218 | .parent = &mck, | ||
219 | .pmc_mask = 1 << AT91_ID_TWI, | ||
220 | .mode = pmc_periph_mode, | ||
221 | }; | ||
222 | static struct clk usart0_clk = { | ||
223 | .name = "usart0_clk", | ||
224 | .parent = &mck, | ||
225 | .pmc_mask = 1 << AT91_ID_US0, | ||
226 | .mode = pmc_periph_mode, | ||
227 | }; | ||
228 | static struct clk usart1_clk = { | ||
229 | .name = "usart1_clk", | ||
230 | .parent = &mck, | ||
231 | .pmc_mask = 1 << AT91_ID_US1, | ||
232 | .mode = pmc_periph_mode, | ||
233 | }; | ||
234 | static struct clk usart2_clk = { | ||
235 | .name = "usart2_clk", | ||
236 | .parent = &mck, | ||
237 | .pmc_mask = 1 << AT91_ID_US2, | ||
238 | .mode = pmc_periph_mode, | ||
239 | }; | ||
240 | static struct clk usart3_clk = { | ||
241 | .name = "usart3_clk", | ||
242 | .parent = &mck, | ||
243 | .pmc_mask = 1 << AT91_ID_US3, | ||
244 | .mode = pmc_periph_mode, | ||
245 | }; | ||
246 | static struct clk spi_clk = { | ||
247 | .name = "spi0_clk", | ||
248 | .parent = &mck, | ||
249 | .pmc_mask = 1 << AT91_ID_SPI, | ||
250 | .mode = pmc_periph_mode, | ||
251 | }; | ||
204 | 252 | ||
205 | static struct clk *const clock_list[] = { | 253 | static struct clk *const clock_list[] = { |
206 | /* four primary clocks -- MUST BE FIRST! */ | 254 | /* four primary clocks -- MUST BE FIRST! */ |
@@ -223,15 +271,18 @@ static struct clk *const clock_list[] = { | |||
223 | 271 | ||
224 | /* MCK and peripherals */ | 272 | /* MCK and peripherals */ |
225 | &mck, | 273 | &mck, |
226 | // usart0..usart3 | 274 | &usart0_clk, |
227 | // mmc | 275 | &usart1_clk, |
276 | &usart2_clk, | ||
277 | &usart3_clk, | ||
278 | &mmc_clk, | ||
228 | &udc_clk, | 279 | &udc_clk, |
229 | // i2c | 280 | &twi_clk, |
230 | // spi | 281 | &spi_clk, |
231 | // ssc0..ssc2 | 282 | // ssc0..ssc2 |
232 | // tc0..tc5 | 283 | // tc0..tc5 |
233 | &ohci_clk, | 284 | &ohci_clk, |
234 | // ether | 285 | ðer_clk, |
235 | }; | 286 | }; |
236 | 287 | ||
237 | 288 | ||
@@ -360,7 +411,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
360 | u32 pckr; | 411 | u32 pckr; |
361 | 412 | ||
362 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); | 413 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); |
363 | pckr &= 0x03; | 414 | pckr &= AT91_PMC_CSS_PLLB; /* clock selection */ |
364 | pckr |= prescale << 2; | 415 | pckr |= prescale << 2; |
365 | at91_sys_write(AT91_PMC_PCKR(clk->id), pckr); | 416 | at91_sys_write(AT91_PMC_PCKR(clk->id), pckr); |
366 | clk->rate_hz = actual; | 417 | clk->rate_hz = actual; |
@@ -440,7 +491,7 @@ static int at91_clk_show(struct seq_file *s, void *unused) | |||
440 | else | 491 | else |
441 | state = ""; | 492 | state = ""; |
442 | 493 | ||
443 | seq_printf(s, "%-10s users=%d %-3s %9ld Hz %s\n", | 494 | seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n", |
444 | clk->name, clk->users, state, clk_get_rate(clk), | 495 | clk->name, clk->users, state, clk_get_rate(clk), |
445 | clk->parent ? clk->parent->name : ""); | 496 | clk->parent ? clk->parent->name : ""); |
446 | } | 497 | } |
@@ -483,11 +534,18 @@ static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg) | |||
483 | freq *= mul + 1; | 534 | freq *= mul + 1; |
484 | } else | 535 | } else |
485 | freq = 0; | 536 | freq = 0; |
486 | if (pll == &pllb && (reg & (1 << 28))) | 537 | |
487 | freq /= 2; | ||
488 | return freq; | 538 | return freq; |
489 | } | 539 | } |
490 | 540 | ||
541 | static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg) | ||
542 | { | ||
543 | if (pll == &pllb && (reg & AT91_PMC_USB96M)) | ||
544 | return freq / 2; | ||
545 | else | ||
546 | return freq; | ||
547 | } | ||
548 | |||
491 | static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq) | 549 | static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq) |
492 | { | 550 | { |
493 | unsigned i, div = 0, mul = 0, diff = 1 << 30; | 551 | unsigned i, div = 0, mul = 0, diff = 1 << 30; |
@@ -550,8 +608,8 @@ int __init at91_clock_init(unsigned long main_clock) | |||
550 | if (!main_clock) { | 608 | if (!main_clock) { |
551 | do { | 609 | do { |
552 | tmp = at91_sys_read(AT91_CKGR_MCFR); | 610 | tmp = at91_sys_read(AT91_CKGR_MCFR); |
553 | } while (!(tmp & 0x10000)); | 611 | } while (!(tmp & AT91_PMC_MAINRDY)); |
554 | main_clock = (tmp & 0xffff) * (AT91_SLOW_CLOCK / 16); | 612 | main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16); |
555 | } | 613 | } |
556 | main_clk.rate_hz = main_clock; | 614 | main_clk.rate_hz = main_clock; |
557 | 615 | ||
@@ -566,13 +624,16 @@ int __init at91_clock_init(unsigned long main_clock) | |||
566 | * | 624 | * |
567 | * REVISIT: assumes MCK doesn't derive from PLLB! | 625 | * REVISIT: assumes MCK doesn't derive from PLLB! |
568 | */ | 626 | */ |
569 | at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | 0x10000000; | 627 | at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; |
570 | pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); | 628 | pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); |
571 | at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); | 629 | at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); |
572 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); | 630 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); |
573 | at91_sys_write(AT91_CKGR_PLLBR, 0); | 631 | at91_sys_write(AT91_CKGR_PLLBR, 0); |
574 | at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); | 632 | at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); |
575 | 633 | ||
634 | udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); | ||
635 | uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); | ||
636 | |||
576 | /* | 637 | /* |
577 | * MCK and CPU derive from one of those primary clocks. | 638 | * MCK and CPU derive from one of those primary clocks. |
578 | * For now, assume this parentage won't change. | 639 | * For now, assume this parentage won't change. |