system_clock.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * File : clock.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2011-01-13 weety first version
  23. */
  24. #include <rtthread.h>
  25. #include "at91sam9g45.h"
  26. static rt_list_t clocks;
  27. struct clk {
  28. char name[32];
  29. rt_uint32_t rate_hz;
  30. struct clk *parent;
  31. rt_list_t node;
  32. };
  33. static struct clk clk32k = {
  34. "clk32k",
  35. AT91C_SLOW_CLOCK,
  36. RT_NULL,
  37. {RT_NULL, RT_NULL},
  38. };
  39. static struct clk main_clk = {
  40. "main",
  41. 0,
  42. RT_NULL,
  43. {RT_NULL, RT_NULL},
  44. };
  45. static struct clk plla = {
  46. "plla",
  47. 0,
  48. &main_clk,
  49. {RT_NULL, RT_NULL},
  50. };
  51. static struct clk mck = {
  52. "mck",
  53. 0,
  54. NULL,
  55. {RT_NULL, RT_NULL},
  56. };
  57. static struct clk upllck = {
  58. "upllck",
  59. 480*1000*1000,
  60. &main_clk,
  61. {RT_NULL, RT_NULL},
  62. };
  63. static struct clk *const standard_pmc_clocks[] = {
  64. /* four primary clocks */
  65. &clk32k,
  66. &main_clk,
  67. &plla,
  68. /* MCK */
  69. &mck
  70. };
  71. /* clocks cannot be de-registered no refcounting necessary */
  72. struct clk *clk_get(const char *id)
  73. {
  74. struct clk *clk;
  75. rt_list_t *list;
  76. for (list = (&clocks)->next; list != &clocks; list = list->next)
  77. {
  78. clk = (struct clk *)rt_list_entry(list, struct clk, node);
  79. if (rt_strcmp(id, clk->name) == 0)
  80. return clk;
  81. }
  82. return RT_NULL;
  83. }
  84. rt_uint32_t clk_get_rate(struct clk *clk)
  85. {
  86. rt_uint32_t rate;
  87. for (;;) {
  88. rate = clk->rate_hz;
  89. if (rate || !clk->parent)
  90. break;
  91. clk = clk->parent;
  92. }
  93. return rate;
  94. }
  95. static void at91_upllck_init(rt_uint32_t main_clock)
  96. {
  97. // EHCI USB use fixed 480MHz clock
  98. }
  99. static struct clk *at91_css_to_clk(unsigned long css)
  100. {
  101. switch (css) {
  102. case AT91C_PMC_CSS_SLOW_CLK:
  103. return &clk32k;
  104. case AT91C_PMC_CSS_MAIN_CLK:
  105. return &main_clk;
  106. case AT91C_PMC_CSS_PLLA_CLK:
  107. return &plla;
  108. case AT91C_PMC_CSS_UPLL_CLK:
  109. return &upllck;
  110. }
  111. return RT_NULL;
  112. }
  113. // TODO: how to auto-set register value by OSC and MCK
  114. /* Settings at 400/133MHz */
  115. // In datasheet, ATMEL says 12MHz main crystal startup time less than 2ms, so we
  116. // configure OSC startup timeout to 64*8/32768=15.6ms, should enough
  117. #define BOARD_OSCOUNT (AT91C_CKGR_OSCOUNT & (64 << 8))
  118. // MAINCK => Divider(DIVA) => PLLA(MULA, OUTA) => /1/2 Divider(PLLADIV2) => PLLACK
  119. // pls. refer to doc6438G figure 24-6 on pg294. ICPLLA in reg PMC_PLLICPR
  120. // 12MHz / 3 * (199 + 1) = 800MHz
  121. // OUTA/ICPLLA can as ICPLLA:OUTA[1]:OUTA[0] = (800-PLLAOUT(MHz))/50
  122. // PLLACOUNT field occupy bit[13:8], max value is 0x3F, then about 19.2ms
  123. #define BOARD_CKGR_PLLA (AT91C_CKGR_SRCA | AT91C_CKGR_OUTA_0)
  124. #define BOARD_PLLACOUNT (0x3F << 8)
  125. #define BOARD_MULA (AT91C_CKGR_MULA & (199 << 16))
  126. #define BOARD_DIVA (AT91C_CKGR_DIVA & 3)
  127. // Clock Source => select(CCS) => Prescaler(PRES) => Master Clock Divider(MDIV) => MCK
  128. // => Processor Clock Divider => PCK
  129. // Master clock can refer to doc6438G figure 25-2 on pg298
  130. // PLLADIV2=1(div 2, 400MHz), PRES=0(no div, 400MHz),
  131. // MDIV=3(Master Clock divided by 3, 133MHz), CSS=0(still Slow Clock)
  132. #define BOARD_PRESCALER (0x00001300) //400/133MHz
  133. #define MHz(n) ((n) * 1000 * 1000)
  134. #define OSC_FREQ MHz(12)
  135. #define PLLA_FREQ MHz(800)
  136. static void at91_plla_init(void)
  137. {
  138. rt_uint32_t pllar, mckr;
  139. // Code refer to doc6438G, 25.10 Programming Sequence
  140. /* Initialize main oscillator
  141. ****************************/
  142. // enable main OSC and wait OSC startup time timeout.
  143. AT91C_BASE_PMC->PMC_MOR = BOARD_OSCOUNT | AT91C_CKGR_MOSCEN;
  144. while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));
  145. /* Initialize PLLA, Set PLL to 800MHz and wait PLL stable */
  146. pllar = (MHz(800) - PLLA_FREQ) / MHz(50); // please refer to Table 46-15 of doc 6438G
  147. AT91C_BASE_PMC->PMC_PLLICPR = (pllar >> 2) & 1; // ICPLLA
  148. pllar = (pllar & 3) << 14; // OUTA
  149. pllar |= BOARD_DIVA; // PLLA input clock as 4MHz
  150. pllar |= BOARD_MULA; // PLLA output clock as 800MHz
  151. pllar |= BOARD_PLLACOUNT;
  152. pllar |= AT91C_CKGR_SRCA; // I don't known what means, but seems must set it
  153. AT91C_BASE_PMC->PMC_PLLAR = pllar;
  154. while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA));
  155. /* Wait for the master clock if it was already initialized */
  156. // make sure Master clock in READY status before operate it
  157. while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
  158. /* Switch to fast clock
  159. **********************/
  160. /* setup main clock divisor and prescaler, 400MHz/133MHz, but don't switch */
  161. mckr = AT91C_BASE_PMC->PMC_MCKR;
  162. if ((mckr & AT91C_PMC_MDIV) != (BOARD_PRESCALER & AT91C_PMC_MDIV))
  163. {
  164. mckr = (mckr & ~(unsigned int)AT91C_PMC_MDIV) | (BOARD_PRESCALER & AT91C_PMC_MDIV);
  165. AT91C_BASE_PMC->PMC_MCKR = mckr;
  166. while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
  167. }
  168. /* Switch to PLL + prescaler, now Switch to PLLA as source, run on the fly */
  169. if ((mckr & AT91C_PMC_CSS) != AT91C_PMC_CSS_PLLA_CLK)
  170. {
  171. mckr = (mckr & ~(unsigned int)AT91C_PMC_CSS) | AT91C_PMC_CSS_PLLA_CLK;
  172. AT91C_BASE_PMC->PMC_MCKR = mckr;
  173. while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
  174. }
  175. plla.rate_hz = PLLA_FREQ;
  176. }
  177. #define false 0
  178. #define true 1
  179. int at91_clock_init(rt_uint32_t main_clock)
  180. {
  181. unsigned tmp, freq, mckr, mdiv;
  182. int i;
  183. /*
  184. * When the bootloader initialized the main oscillator correctly,
  185. * there's no problem using the cycle counter. But if it didn't,
  186. * or when using oscillator bypass mode, we must be told the speed
  187. * of the main clock.
  188. */
  189. if (!main_clock) {
  190. do {
  191. tmp = readl(AT91C_CKGR_MCFR);
  192. } while (!(tmp & AT91C_CKGR_MAINRDY));
  193. main_clock = (tmp & AT91C_CKGR_MAINF) * (AT91C_SLOW_CLOCK / 16);
  194. }
  195. main_clk.rate_hz = main_clock;
  196. at91_plla_init();
  197. at91_upllck_init(main_clock);
  198. /*
  199. * MCK and CPU derive from one of those primary clocks.
  200. * For now, assume this parentage won't change.
  201. */
  202. mckr = readl(AT91C_PMC_MCKR);
  203. mck.parent = at91_css_to_clk(mckr & AT91C_PMC_CSS);
  204. freq = mck.parent->rate_hz;
  205. freq /= (1 << ((mckr & AT91C_PMC_PRES) >> 2)); /* prescale */
  206. mdiv = 1 << ((mckr & AT91C_PMC_MDIV) >> 8);
  207. if (mdiv == 8) mdiv = 3;
  208. freq /= mdiv; /* mdiv */
  209. if (mckr & AT91C_PMC_PLLADIV2) freq /= 2; /* plla_div2 */
  210. mck.rate_hz = freq;
  211. /* Register the PMC's standard clocks */
  212. rt_list_init(&clocks);
  213. for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
  214. rt_list_insert_after(&clocks, &standard_pmc_clocks[i]->node);
  215. rt_list_insert_after(&clocks, &upllck.node);
  216. /* MCK and CPU clock are "always on" */
  217. //clk_enable(&mck);
  218. /*rt_kprintf("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
  219. freq / 1000000, (unsigned) mck.rate_hz / 1000000,
  220. (unsigned) main_clock / 1000000,
  221. ((unsigned) main_clock % 1000000) / 1000);*///cause blocked
  222. return 0;
  223. }
  224. /**
  225. * @brief System Clock Configuration
  226. */
  227. void rt_hw_clock_init(void)
  228. {
  229. at91_clock_init(MHz(12));
  230. }