xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-at91/arm920t/clock.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2011 Andreas Bießmann
5*4882a593Smuzhiyun  * Copyright (C) 2005 David Brownell
6*4882a593Smuzhiyun  * Copyright (C) 2005 Ivan Kokshaysky
7*4882a593Smuzhiyun  * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
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 (input < 100000)
62*4882a593Smuzhiyun 			continue;
63*4882a593Smuzhiyun 		if (input > 32000000)
64*4882a593Smuzhiyun 			continue;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 		mul1 = out_freq / input;
67*4882a593Smuzhiyun 		if (mul1 > 2048)
68*4882a593Smuzhiyun 			continue;
69*4882a593Smuzhiyun 		if (mul1 < 2)
70*4882a593Smuzhiyun 			goto fail;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 		diff1 = out_freq - input * mul1;
73*4882a593Smuzhiyun 		if (diff1 < 0)
74*4882a593Smuzhiyun 			diff1 = -diff1;
75*4882a593Smuzhiyun 		if (diff > diff1) {
76*4882a593Smuzhiyun 			diff = diff1;
77*4882a593Smuzhiyun 			div = i;
78*4882a593Smuzhiyun 			mul = mul1;
79*4882a593Smuzhiyun 			if (diff == 0)
80*4882a593Smuzhiyun 				break;
81*4882a593Smuzhiyun 		}
82*4882a593Smuzhiyun 	}
83*4882a593Smuzhiyun 	if (i == 256 && diff > (out_freq >> 5))
84*4882a593Smuzhiyun 		goto fail;
85*4882a593Smuzhiyun 	return ret | ((mul - 1) << 16) | div;
86*4882a593Smuzhiyun fail:
87*4882a593Smuzhiyun 	return 0;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun 
at91_pll_rate(u32 freq,u32 reg)91*4882a593Smuzhiyun static u32 at91_pll_rate(u32 freq, u32 reg)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	unsigned mul, div;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	div = reg & 0xff;
96*4882a593Smuzhiyun 	mul = (reg >> 16) & 0x7ff;
97*4882a593Smuzhiyun 	if (div && mul) {
98*4882a593Smuzhiyun 		freq /= div;
99*4882a593Smuzhiyun 		freq *= mul + 1;
100*4882a593Smuzhiyun 	} else
101*4882a593Smuzhiyun 		freq = 0;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	return freq;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
at91_clock_init(unsigned long main_clock)106*4882a593Smuzhiyun int at91_clock_init(unsigned long main_clock)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	unsigned freq, mckr;
109*4882a593Smuzhiyun 	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
110*4882a593Smuzhiyun #ifndef CONFIG_SYS_AT91_MAIN_CLOCK
111*4882a593Smuzhiyun 	unsigned tmp;
112*4882a593Smuzhiyun 	/*
113*4882a593Smuzhiyun 	 * When the bootloader initialized the main oscillator correctly,
114*4882a593Smuzhiyun 	 * there's no problem using the cycle counter.  But if it didn't,
115*4882a593Smuzhiyun 	 * or when using oscillator bypass mode, we must be told the speed
116*4882a593Smuzhiyun 	 * of the main clock.
117*4882a593Smuzhiyun 	 */
118*4882a593Smuzhiyun 	if (!main_clock) {
119*4882a593Smuzhiyun 		do {
120*4882a593Smuzhiyun 			tmp = readl(&pmc->mcfr);
121*4882a593Smuzhiyun 		} while (!(tmp & AT91_PMC_MCFR_MAINRDY));
122*4882a593Smuzhiyun 		tmp &= AT91_PMC_MCFR_MAINF_MASK;
123*4882a593Smuzhiyun 		main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun #endif
126*4882a593Smuzhiyun 	gd->arch.main_clk_rate_hz = main_clock;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	/* report if PLLA is more than mildly overclocked */
129*4882a593Smuzhiyun 	gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun #ifdef CONFIG_USB_ATMEL
132*4882a593Smuzhiyun 	/*
133*4882a593Smuzhiyun 	 * USB clock init:  choose 48 MHz PLLB value,
134*4882a593Smuzhiyun 	 * disable 48MHz clock during usb peripheral suspend.
135*4882a593Smuzhiyun 	 *
136*4882a593Smuzhiyun 	 * REVISIT:  assumes MCK doesn't derive from PLLB!
137*4882a593Smuzhiyun 	 */
138*4882a593Smuzhiyun 	gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
139*4882a593Smuzhiyun 			     AT91_PMC_PLLBR_USBDIV_2;
140*4882a593Smuzhiyun 	gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
141*4882a593Smuzhiyun 					      gd->arch.at91_pllb_usb_init);
142*4882a593Smuzhiyun #endif
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/*
145*4882a593Smuzhiyun 	 * MCK and CPU derive from one of those primary clocks.
146*4882a593Smuzhiyun 	 * For now, assume this parentage won't change.
147*4882a593Smuzhiyun 	 */
148*4882a593Smuzhiyun 	mckr = readl(&pmc->mckr);
149*4882a593Smuzhiyun 	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
150*4882a593Smuzhiyun 	freq = gd->arch.mck_rate_hz;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2));	/* prescale */
153*4882a593Smuzhiyun 	/* mdiv */
154*4882a593Smuzhiyun 	gd->arch.mck_rate_hz = freq /
155*4882a593Smuzhiyun 			(1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
156*4882a593Smuzhiyun 	gd->arch.cpu_clk_rate_hz = freq;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	return 0;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
at91_pllb_clk_enable(u32 pllbr)161*4882a593Smuzhiyun int at91_pllb_clk_enable(u32 pllbr)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
164*4882a593Smuzhiyun 	ulong start_time, tmp_time;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	start_time = get_timer(0);
167*4882a593Smuzhiyun 	writel(pllbr, &pmc->pllbr);
168*4882a593Smuzhiyun 	while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) {
169*4882a593Smuzhiyun 		tmp_time = get_timer(0);
170*4882a593Smuzhiyun 		if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) {
171*4882a593Smuzhiyun 			printf("ERROR: failed to enable PLLB\n");
172*4882a593Smuzhiyun 			return -1;
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
at91_pllb_clk_disable(void)179*4882a593Smuzhiyun int at91_pllb_clk_disable(void)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
182*4882a593Smuzhiyun 	ulong start_time, tmp_time;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	start_time = get_timer(0);
185*4882a593Smuzhiyun 	writel(0, &pmc->pllbr);
186*4882a593Smuzhiyun 	while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) {
187*4882a593Smuzhiyun 		tmp_time = get_timer(0);
188*4882a593Smuzhiyun 		if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) {
189*4882a593Smuzhiyun 			printf("ERROR: failed to disable PLLB\n");
190*4882a593Smuzhiyun 			return -1;
191*4882a593Smuzhiyun 		}
192*4882a593Smuzhiyun 	}
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	return 0;
195*4882a593Smuzhiyun }
196