clock.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
  3. *
  4. * Copyright (C) 2005 David Brownell
  5. * Copyright (C) 2005 Ivan Kokshaysky
  6. * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
  7. * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <common.h>
  12. #include <asm/io.h>
  13. #include <asm/arch/hardware.h>
  14. #include <asm/arch/at91_pmc.h>
  15. #include <asm/arch/clk.h>
  16. #if !defined(CONFIG_AT91FAMILY)
  17. # error You need to define CONFIG_AT91FAMILY in your board config!
  18. #endif
  19. DECLARE_GLOBAL_DATA_PTR;
  20. static unsigned long at91_css_to_rate(unsigned long css)
  21. {
  22. switch (css) {
  23. case AT91_PMC_MCKR_CSS_SLOW:
  24. return CONFIG_SYS_AT91_SLOW_CLOCK;
  25. case AT91_PMC_MCKR_CSS_MAIN:
  26. return gd->arch.main_clk_rate_hz;
  27. case AT91_PMC_MCKR_CSS_PLLA:
  28. return gd->arch.plla_rate_hz;
  29. }
  30. return 0;
  31. }
  32. static u32 at91_pll_rate(u32 freq, u32 reg)
  33. {
  34. unsigned mul, div;
  35. div = reg & 0xff;
  36. mul = (reg >> 18) & 0x7f;
  37. if (div && mul) {
  38. freq /= div;
  39. freq *= mul + 1;
  40. } else {
  41. freq = 0;
  42. }
  43. return freq;
  44. }
  45. int at91_clock_init(unsigned long main_clock)
  46. {
  47. unsigned freq, mckr;
  48. struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
  49. #ifndef CONFIG_SYS_AT91_MAIN_CLOCK
  50. unsigned tmp;
  51. /*
  52. * When the bootloader initialized the main oscillator correctly,
  53. * there's no problem using the cycle counter. But if it didn't,
  54. * or when using oscillator bypass mode, we must be told the speed
  55. * of the main clock.
  56. */
  57. if (!main_clock) {
  58. do {
  59. tmp = readl(&pmc->mcfr);
  60. } while (!(tmp & AT91_PMC_MCFR_MAINRDY));
  61. tmp &= AT91_PMC_MCFR_MAINF_MASK;
  62. main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
  63. }
  64. #endif
  65. gd->arch.main_clk_rate_hz = main_clock;
  66. /* report if PLLA is more than mildly overclocked */
  67. gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
  68. /*
  69. * MCK and CPU derive from one of those primary clocks.
  70. * For now, assume this parentage won't change.
  71. */
  72. mckr = readl(&pmc->mckr);
  73. /* plla divisor by 2 */
  74. if (mckr & (1 << 12))
  75. gd->arch.plla_rate_hz >>= 1;
  76. gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
  77. freq = gd->arch.mck_rate_hz;
  78. /* prescale */
  79. freq >>= mckr & AT91_PMC_MCKR_PRES_MASK;
  80. switch (mckr & AT91_PMC_MCKR_MDIV_MASK) {
  81. case AT91_PMC_MCKR_MDIV_2:
  82. gd->arch.mck_rate_hz = freq / 2;
  83. break;
  84. case AT91_PMC_MCKR_MDIV_3:
  85. gd->arch.mck_rate_hz = freq / 3;
  86. break;
  87. case AT91_PMC_MCKR_MDIV_4:
  88. gd->arch.mck_rate_hz = freq / 4;
  89. break;
  90. default:
  91. break;
  92. }
  93. gd->arch.cpu_clk_rate_hz = freq;
  94. return 0;
  95. }
  96. void at91_plla_init(u32 pllar)
  97. {
  98. struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
  99. writel(pllar, &pmc->pllar);
  100. while (!(readl(&pmc->sr) & (AT91_PMC_LOCKA | AT91_PMC_MCKRDY)))
  101. ;
  102. }
  103. void at91_mck_init(u32 mckr)
  104. {
  105. struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
  106. u32 tmp;
  107. tmp = readl(&pmc->mckr);
  108. tmp &= ~(AT91_PMC_MCKR_CSS_MASK |
  109. AT91_PMC_MCKR_PRES_MASK |
  110. AT91_PMC_MCKR_MDIV_MASK |
  111. AT91_PMC_MCKR_PLLADIV_2);
  112. tmp |= mckr & (AT91_PMC_MCKR_CSS_MASK |
  113. AT91_PMC_MCKR_PRES_MASK |
  114. AT91_PMC_MCKR_MDIV_MASK |
  115. AT91_PMC_MCKR_PLLADIV_2);
  116. writel(tmp, &pmc->mckr);
  117. while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
  118. ;
  119. }
  120. void at91_periph_clk_enable(int id)
  121. {
  122. struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
  123. u32 regval;
  124. if (id > AT91_PMC_PCR_PID_MASK)
  125. return;
  126. regval = AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD_WRITE | id;
  127. writel(regval, &pmc->pcr);
  128. }
  129. void at91_periph_clk_disable(int id)
  130. {
  131. struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
  132. u32 regval;
  133. if (id > AT91_PMC_PCR_PID_MASK)
  134. return;
  135. regval = AT91_PMC_PCR_CMD_WRITE | id;
  136. writel(regval, &pmc->pcr);
  137. }