1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2005 David Brownell
5*4882a593Smuzhiyun * Copyright (C) 2005 Ivan Kokshaysky
6*4882a593Smuzhiyun * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun #include <asm/arch/hardware.h>
14*4882a593Smuzhiyun #include <asm/arch/at91_pmc.h>
15*4882a593Smuzhiyun #include <asm/arch/clk.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #if !defined(CONFIG_AT91FAMILY)
18*4882a593Smuzhiyun # error You need to define CONFIG_AT91FAMILY in your board config!
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define EN_PLLB_TIMEOUT 500
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
24*4882a593Smuzhiyun
at91_css_to_rate(unsigned long css)25*4882a593Smuzhiyun static unsigned long at91_css_to_rate(unsigned long css)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun switch (css) {
28*4882a593Smuzhiyun case AT91_PMC_MCKR_CSS_SLOW:
29*4882a593Smuzhiyun return CONFIG_SYS_AT91_SLOW_CLOCK;
30*4882a593Smuzhiyun case AT91_PMC_MCKR_CSS_MAIN:
31*4882a593Smuzhiyun return gd->arch.main_clk_rate_hz;
32*4882a593Smuzhiyun case AT91_PMC_MCKR_CSS_PLLA:
33*4882a593Smuzhiyun return gd->arch.plla_rate_hz;
34*4882a593Smuzhiyun case AT91_PMC_MCKR_CSS_PLLB:
35*4882a593Smuzhiyun return gd->arch.pllb_rate_hz;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun return 0;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #ifdef CONFIG_USB_ATMEL
at91_pll_calc(unsigned main_freq,unsigned out_freq)42*4882a593Smuzhiyun static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun unsigned i, div = 0, mul = 0, diff = 1 << 30;
45*4882a593Smuzhiyun unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* PLL output max 240 MHz (or 180 MHz per errata) */
48*4882a593Smuzhiyun if (out_freq > 240000000)
49*4882a593Smuzhiyun goto fail;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun for (i = 1; i < 256; i++) {
52*4882a593Smuzhiyun int diff1;
53*4882a593Smuzhiyun unsigned input, mul1;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /*
56*4882a593Smuzhiyun * PLL input between 1MHz and 32MHz per spec, but lower
57*4882a593Smuzhiyun * frequences seem necessary in some cases so allow 100K.
58*4882a593Smuzhiyun * Warning: some newer products need 2MHz min.
59*4882a593Smuzhiyun */
60*4882a593Smuzhiyun input = main_freq / i;
61*4882a593Smuzhiyun #if defined(CONFIG_AT91SAM9G20)
62*4882a593Smuzhiyun if (input < 2000000)
63*4882a593Smuzhiyun continue;
64*4882a593Smuzhiyun #endif
65*4882a593Smuzhiyun if (input < 100000)
66*4882a593Smuzhiyun continue;
67*4882a593Smuzhiyun if (input > 32000000)
68*4882a593Smuzhiyun continue;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun mul1 = out_freq / input;
71*4882a593Smuzhiyun #if defined(CONFIG_AT91SAM9G20)
72*4882a593Smuzhiyun if (mul > 63)
73*4882a593Smuzhiyun continue;
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun if (mul1 > 2048)
76*4882a593Smuzhiyun continue;
77*4882a593Smuzhiyun if (mul1 < 2)
78*4882a593Smuzhiyun goto fail;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun diff1 = out_freq - input * mul1;
81*4882a593Smuzhiyun if (diff1 < 0)
82*4882a593Smuzhiyun diff1 = -diff1;
83*4882a593Smuzhiyun if (diff > diff1) {
84*4882a593Smuzhiyun diff = diff1;
85*4882a593Smuzhiyun div = i;
86*4882a593Smuzhiyun mul = mul1;
87*4882a593Smuzhiyun if (diff == 0)
88*4882a593Smuzhiyun break;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun if (i == 256 && diff > (out_freq >> 5))
92*4882a593Smuzhiyun goto fail;
93*4882a593Smuzhiyun return ret | ((mul - 1) << 16) | div;
94*4882a593Smuzhiyun fail:
95*4882a593Smuzhiyun return 0;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun
at91_pll_rate(u32 freq,u32 reg)99*4882a593Smuzhiyun static u32 at91_pll_rate(u32 freq, u32 reg)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun unsigned mul, div;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun div = reg & 0xff;
104*4882a593Smuzhiyun mul = (reg >> 16) & 0x7ff;
105*4882a593Smuzhiyun if (div && mul) {
106*4882a593Smuzhiyun freq /= div;
107*4882a593Smuzhiyun freq *= mul + 1;
108*4882a593Smuzhiyun } else
109*4882a593Smuzhiyun freq = 0;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return freq;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
at91_clock_init(unsigned long main_clock)114*4882a593Smuzhiyun int at91_clock_init(unsigned long main_clock)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun unsigned freq, mckr;
117*4882a593Smuzhiyun at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
118*4882a593Smuzhiyun #ifndef CONFIG_SYS_AT91_MAIN_CLOCK
119*4882a593Smuzhiyun unsigned tmp;
120*4882a593Smuzhiyun /*
121*4882a593Smuzhiyun * When the bootloader initialized the main oscillator correctly,
122*4882a593Smuzhiyun * there's no problem using the cycle counter. But if it didn't,
123*4882a593Smuzhiyun * or when using oscillator bypass mode, we must be told the speed
124*4882a593Smuzhiyun * of the main clock.
125*4882a593Smuzhiyun */
126*4882a593Smuzhiyun if (!main_clock) {
127*4882a593Smuzhiyun do {
128*4882a593Smuzhiyun tmp = readl(&pmc->mcfr);
129*4882a593Smuzhiyun } while (!(tmp & AT91_PMC_MCFR_MAINRDY));
130*4882a593Smuzhiyun tmp &= AT91_PMC_MCFR_MAINF_MASK;
131*4882a593Smuzhiyun main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun #endif
134*4882a593Smuzhiyun gd->arch.main_clk_rate_hz = main_clock;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /* report if PLLA is more than mildly overclocked */
137*4882a593Smuzhiyun gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun #ifdef CONFIG_USB_ATMEL
140*4882a593Smuzhiyun /*
141*4882a593Smuzhiyun * USB clock init: choose 48 MHz PLLB value,
142*4882a593Smuzhiyun * disable 48MHz clock during usb peripheral suspend.
143*4882a593Smuzhiyun *
144*4882a593Smuzhiyun * REVISIT: assumes MCK doesn't derive from PLLB!
145*4882a593Smuzhiyun */
146*4882a593Smuzhiyun gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
147*4882a593Smuzhiyun AT91_PMC_PLLBR_USBDIV_2;
148*4882a593Smuzhiyun gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
149*4882a593Smuzhiyun gd->arch.at91_pllb_usb_init);
150*4882a593Smuzhiyun #endif
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /*
153*4882a593Smuzhiyun * MCK and CPU derive from one of those primary clocks.
154*4882a593Smuzhiyun * For now, assume this parentage won't change.
155*4882a593Smuzhiyun */
156*4882a593Smuzhiyun mckr = readl(&pmc->mckr);
157*4882a593Smuzhiyun #if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
158*4882a593Smuzhiyun || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
159*4882a593Smuzhiyun /* plla divisor by 2 */
160*4882a593Smuzhiyun gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12));
161*4882a593Smuzhiyun #endif
162*4882a593Smuzhiyun gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
163*4882a593Smuzhiyun freq = gd->arch.mck_rate_hz;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun #if defined(CONFIG_AT91SAM9X5)
166*4882a593Smuzhiyun /* different in prescale on at91sam9x5 */
167*4882a593Smuzhiyun freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4));
168*4882a593Smuzhiyun #else
169*4882a593Smuzhiyun freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
170*4882a593Smuzhiyun #endif
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun #if defined(CONFIG_AT91SAM9G20)
173*4882a593Smuzhiyun /* mdiv ; (x >> 7) = ((x >> 8) * 2) */
174*4882a593Smuzhiyun gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
175*4882a593Smuzhiyun freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq;
176*4882a593Smuzhiyun if (mckr & AT91_PMC_MCKR_MDIV_MASK)
177*4882a593Smuzhiyun freq /= 2; /* processor clock division */
178*4882a593Smuzhiyun #elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \
179*4882a593Smuzhiyun || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5)
180*4882a593Smuzhiyun /* mdiv <==> divisor
181*4882a593Smuzhiyun * 0 <==> 1
182*4882a593Smuzhiyun * 1 <==> 2
183*4882a593Smuzhiyun * 2 <==> 4
184*4882a593Smuzhiyun * 3 <==> 3
185*4882a593Smuzhiyun */
186*4882a593Smuzhiyun gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ==
187*4882a593Smuzhiyun (AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4)
188*4882a593Smuzhiyun ? freq / 3
189*4882a593Smuzhiyun : freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
190*4882a593Smuzhiyun #else
191*4882a593Smuzhiyun gd->arch.mck_rate_hz = freq /
192*4882a593Smuzhiyun (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
193*4882a593Smuzhiyun #endif
194*4882a593Smuzhiyun gd->arch.cpu_clk_rate_hz = freq;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun return 0;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #if !defined(AT91_PLL_LOCK_TIMEOUT)
200*4882a593Smuzhiyun #define AT91_PLL_LOCK_TIMEOUT 1000000
201*4882a593Smuzhiyun #endif
202*4882a593Smuzhiyun
at91_plla_init(u32 pllar)203*4882a593Smuzhiyun void at91_plla_init(u32 pllar)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun writel(pllar, &pmc->pllar);
208*4882a593Smuzhiyun while (!(readl(&pmc->sr) & AT91_PMC_LOCKA))
209*4882a593Smuzhiyun ;
210*4882a593Smuzhiyun }
at91_pllb_init(u32 pllbr)211*4882a593Smuzhiyun void at91_pllb_init(u32 pllbr)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun writel(pllbr, &pmc->pllbr);
216*4882a593Smuzhiyun while (!(readl(&pmc->sr) & AT91_PMC_LOCKB))
217*4882a593Smuzhiyun ;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
at91_mck_init(u32 mckr)220*4882a593Smuzhiyun void at91_mck_init(u32 mckr)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
223*4882a593Smuzhiyun u32 tmp;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun tmp = readl(&pmc->mckr);
226*4882a593Smuzhiyun tmp &= ~AT91_PMC_MCKR_PRES_MASK;
227*4882a593Smuzhiyun tmp |= mckr & AT91_PMC_MCKR_PRES_MASK;
228*4882a593Smuzhiyun writel(tmp, &pmc->mckr);
229*4882a593Smuzhiyun while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
230*4882a593Smuzhiyun ;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun tmp = readl(&pmc->mckr);
233*4882a593Smuzhiyun tmp &= ~AT91_PMC_MCKR_MDIV_MASK;
234*4882a593Smuzhiyun tmp |= mckr & AT91_PMC_MCKR_MDIV_MASK;
235*4882a593Smuzhiyun writel(tmp, &pmc->mckr);
236*4882a593Smuzhiyun while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
237*4882a593Smuzhiyun ;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun tmp = readl(&pmc->mckr);
240*4882a593Smuzhiyun tmp &= ~AT91_PMC_MCKR_PLLADIV_MASK;
241*4882a593Smuzhiyun tmp |= mckr & AT91_PMC_MCKR_PLLADIV_MASK;
242*4882a593Smuzhiyun writel(tmp, &pmc->mckr);
243*4882a593Smuzhiyun while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
244*4882a593Smuzhiyun ;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun tmp = readl(&pmc->mckr);
247*4882a593Smuzhiyun tmp &= ~AT91_PMC_MCKR_CSS_MASK;
248*4882a593Smuzhiyun tmp |= mckr & AT91_PMC_MCKR_CSS_MASK;
249*4882a593Smuzhiyun writel(tmp, &pmc->mckr);
250*4882a593Smuzhiyun while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
251*4882a593Smuzhiyun ;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
at91_pllb_clk_enable(u32 pllbr)254*4882a593Smuzhiyun int at91_pllb_clk_enable(u32 pllbr)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
257*4882a593Smuzhiyun ulong start_time, tmp_time;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun start_time = get_timer(0);
260*4882a593Smuzhiyun writel(pllbr, &pmc->pllbr);
261*4882a593Smuzhiyun while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) {
262*4882a593Smuzhiyun tmp_time = get_timer(0);
263*4882a593Smuzhiyun if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) {
264*4882a593Smuzhiyun printf("ERROR: failed to enable PLLB\n");
265*4882a593Smuzhiyun return -1;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return 0;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
at91_pllb_clk_disable(void)272*4882a593Smuzhiyun int at91_pllb_clk_disable(void)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
275*4882a593Smuzhiyun ulong start_time, tmp_time;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun start_time = get_timer(0);
278*4882a593Smuzhiyun writel(0, &pmc->pllbr);
279*4882a593Smuzhiyun while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) {
280*4882a593Smuzhiyun tmp_time = get_timer(0);
281*4882a593Smuzhiyun if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) {
282*4882a593Smuzhiyun printf("ERROR: failed to disable PLLB\n");
283*4882a593Smuzhiyun return -1;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun }
289