xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-at91/arm926ejs/clock.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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