xref: /openbmc/u-boot/arch/arm/mach-at91/arm920t/clock.c (revision 620118403e1521b4c883848a84d2fb68e3fa1aa0)
1*62011840SMasahiro Yamada /*
2*62011840SMasahiro Yamada  * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
3*62011840SMasahiro Yamada  *
4*62011840SMasahiro Yamada  * Copyright (C) 2011 Andreas Bießmann
5*62011840SMasahiro Yamada  * Copyright (C) 2005 David Brownell
6*62011840SMasahiro Yamada  * Copyright (C) 2005 Ivan Kokshaysky
7*62011840SMasahiro Yamada  * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
8*62011840SMasahiro Yamada  *
9*62011840SMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
10*62011840SMasahiro Yamada  */
11*62011840SMasahiro Yamada #include <common.h>
12*62011840SMasahiro Yamada #include <asm/io.h>
13*62011840SMasahiro Yamada #include <asm/arch/hardware.h>
14*62011840SMasahiro Yamada #include <asm/arch/at91_pmc.h>
15*62011840SMasahiro Yamada #include <asm/arch/clk.h>
16*62011840SMasahiro Yamada 
17*62011840SMasahiro Yamada #if !defined(CONFIG_AT91FAMILY)
18*62011840SMasahiro Yamada # error You need to define CONFIG_AT91FAMILY in your board config!
19*62011840SMasahiro Yamada #endif
20*62011840SMasahiro Yamada 
21*62011840SMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
22*62011840SMasahiro Yamada 
23*62011840SMasahiro Yamada static unsigned long at91_css_to_rate(unsigned long css)
24*62011840SMasahiro Yamada {
25*62011840SMasahiro Yamada 	switch (css) {
26*62011840SMasahiro Yamada 	case AT91_PMC_MCKR_CSS_SLOW:
27*62011840SMasahiro Yamada 		return CONFIG_SYS_AT91_SLOW_CLOCK;
28*62011840SMasahiro Yamada 	case AT91_PMC_MCKR_CSS_MAIN:
29*62011840SMasahiro Yamada 		return gd->arch.main_clk_rate_hz;
30*62011840SMasahiro Yamada 	case AT91_PMC_MCKR_CSS_PLLA:
31*62011840SMasahiro Yamada 		return gd->arch.plla_rate_hz;
32*62011840SMasahiro Yamada 	case AT91_PMC_MCKR_CSS_PLLB:
33*62011840SMasahiro Yamada 		return gd->arch.pllb_rate_hz;
34*62011840SMasahiro Yamada 	}
35*62011840SMasahiro Yamada 
36*62011840SMasahiro Yamada 	return 0;
37*62011840SMasahiro Yamada }
38*62011840SMasahiro Yamada 
39*62011840SMasahiro Yamada #ifdef CONFIG_USB_ATMEL
40*62011840SMasahiro Yamada static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
41*62011840SMasahiro Yamada {
42*62011840SMasahiro Yamada 	unsigned i, div = 0, mul = 0, diff = 1 << 30;
43*62011840SMasahiro Yamada 	unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
44*62011840SMasahiro Yamada 
45*62011840SMasahiro Yamada 	/* PLL output max 240 MHz (or 180 MHz per errata) */
46*62011840SMasahiro Yamada 	if (out_freq > 240000000)
47*62011840SMasahiro Yamada 		goto fail;
48*62011840SMasahiro Yamada 
49*62011840SMasahiro Yamada 	for (i = 1; i < 256; i++) {
50*62011840SMasahiro Yamada 		int diff1;
51*62011840SMasahiro Yamada 		unsigned input, mul1;
52*62011840SMasahiro Yamada 
53*62011840SMasahiro Yamada 		/*
54*62011840SMasahiro Yamada 		 * PLL input between 1MHz and 32MHz per spec, but lower
55*62011840SMasahiro Yamada 		 * frequences seem necessary in some cases so allow 100K.
56*62011840SMasahiro Yamada 		 * Warning: some newer products need 2MHz min.
57*62011840SMasahiro Yamada 		 */
58*62011840SMasahiro Yamada 		input = main_freq / i;
59*62011840SMasahiro Yamada 		if (input < 100000)
60*62011840SMasahiro Yamada 			continue;
61*62011840SMasahiro Yamada 		if (input > 32000000)
62*62011840SMasahiro Yamada 			continue;
63*62011840SMasahiro Yamada 
64*62011840SMasahiro Yamada 		mul1 = out_freq / input;
65*62011840SMasahiro Yamada 		if (mul1 > 2048)
66*62011840SMasahiro Yamada 			continue;
67*62011840SMasahiro Yamada 		if (mul1 < 2)
68*62011840SMasahiro Yamada 			goto fail;
69*62011840SMasahiro Yamada 
70*62011840SMasahiro Yamada 		diff1 = out_freq - input * mul1;
71*62011840SMasahiro Yamada 		if (diff1 < 0)
72*62011840SMasahiro Yamada 			diff1 = -diff1;
73*62011840SMasahiro Yamada 		if (diff > diff1) {
74*62011840SMasahiro Yamada 			diff = diff1;
75*62011840SMasahiro Yamada 			div = i;
76*62011840SMasahiro Yamada 			mul = mul1;
77*62011840SMasahiro Yamada 			if (diff == 0)
78*62011840SMasahiro Yamada 				break;
79*62011840SMasahiro Yamada 		}
80*62011840SMasahiro Yamada 	}
81*62011840SMasahiro Yamada 	if (i == 256 && diff > (out_freq >> 5))
82*62011840SMasahiro Yamada 		goto fail;
83*62011840SMasahiro Yamada 	return ret | ((mul - 1) << 16) | div;
84*62011840SMasahiro Yamada fail:
85*62011840SMasahiro Yamada 	return 0;
86*62011840SMasahiro Yamada }
87*62011840SMasahiro Yamada #endif
88*62011840SMasahiro Yamada 
89*62011840SMasahiro Yamada static u32 at91_pll_rate(u32 freq, u32 reg)
90*62011840SMasahiro Yamada {
91*62011840SMasahiro Yamada 	unsigned mul, div;
92*62011840SMasahiro Yamada 
93*62011840SMasahiro Yamada 	div = reg & 0xff;
94*62011840SMasahiro Yamada 	mul = (reg >> 16) & 0x7ff;
95*62011840SMasahiro Yamada 	if (div && mul) {
96*62011840SMasahiro Yamada 		freq /= div;
97*62011840SMasahiro Yamada 		freq *= mul + 1;
98*62011840SMasahiro Yamada 	} else
99*62011840SMasahiro Yamada 		freq = 0;
100*62011840SMasahiro Yamada 
101*62011840SMasahiro Yamada 	return freq;
102*62011840SMasahiro Yamada }
103*62011840SMasahiro Yamada 
104*62011840SMasahiro Yamada int at91_clock_init(unsigned long main_clock)
105*62011840SMasahiro Yamada {
106*62011840SMasahiro Yamada 	unsigned freq, mckr;
107*62011840SMasahiro Yamada 	at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
108*62011840SMasahiro Yamada #ifndef CONFIG_SYS_AT91_MAIN_CLOCK
109*62011840SMasahiro Yamada 	unsigned tmp;
110*62011840SMasahiro Yamada 	/*
111*62011840SMasahiro Yamada 	 * When the bootloader initialized the main oscillator correctly,
112*62011840SMasahiro Yamada 	 * there's no problem using the cycle counter.  But if it didn't,
113*62011840SMasahiro Yamada 	 * or when using oscillator bypass mode, we must be told the speed
114*62011840SMasahiro Yamada 	 * of the main clock.
115*62011840SMasahiro Yamada 	 */
116*62011840SMasahiro Yamada 	if (!main_clock) {
117*62011840SMasahiro Yamada 		do {
118*62011840SMasahiro Yamada 			tmp = readl(&pmc->mcfr);
119*62011840SMasahiro Yamada 		} while (!(tmp & AT91_PMC_MCFR_MAINRDY));
120*62011840SMasahiro Yamada 		tmp &= AT91_PMC_MCFR_MAINF_MASK;
121*62011840SMasahiro Yamada 		main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
122*62011840SMasahiro Yamada 	}
123*62011840SMasahiro Yamada #endif
124*62011840SMasahiro Yamada 	gd->arch.main_clk_rate_hz = main_clock;
125*62011840SMasahiro Yamada 
126*62011840SMasahiro Yamada 	/* report if PLLA is more than mildly overclocked */
127*62011840SMasahiro Yamada 	gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
128*62011840SMasahiro Yamada 
129*62011840SMasahiro Yamada #ifdef CONFIG_USB_ATMEL
130*62011840SMasahiro Yamada 	/*
131*62011840SMasahiro Yamada 	 * USB clock init:  choose 48 MHz PLLB value,
132*62011840SMasahiro Yamada 	 * disable 48MHz clock during usb peripheral suspend.
133*62011840SMasahiro Yamada 	 *
134*62011840SMasahiro Yamada 	 * REVISIT:  assumes MCK doesn't derive from PLLB!
135*62011840SMasahiro Yamada 	 */
136*62011840SMasahiro Yamada 	gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
137*62011840SMasahiro Yamada 			     AT91_PMC_PLLBR_USBDIV_2;
138*62011840SMasahiro Yamada 	gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
139*62011840SMasahiro Yamada 					      gd->arch.at91_pllb_usb_init);
140*62011840SMasahiro Yamada #endif
141*62011840SMasahiro Yamada 
142*62011840SMasahiro Yamada 	/*
143*62011840SMasahiro Yamada 	 * MCK and CPU derive from one of those primary clocks.
144*62011840SMasahiro Yamada 	 * For now, assume this parentage won't change.
145*62011840SMasahiro Yamada 	 */
146*62011840SMasahiro Yamada 	mckr = readl(&pmc->mckr);
147*62011840SMasahiro Yamada 	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
148*62011840SMasahiro Yamada 	freq = gd->arch.mck_rate_hz;
149*62011840SMasahiro Yamada 
150*62011840SMasahiro Yamada 	freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2));	/* prescale */
151*62011840SMasahiro Yamada 	/* mdiv */
152*62011840SMasahiro Yamada 	gd->arch.mck_rate_hz = freq /
153*62011840SMasahiro Yamada 			(1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
154*62011840SMasahiro Yamada 	gd->arch.cpu_clk_rate_hz = freq;
155*62011840SMasahiro Yamada 
156*62011840SMasahiro Yamada 	return 0;
157*62011840SMasahiro Yamada }
158