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