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