xref: /OK3568_Linux_fs/kernel/drivers/clk/pxa/clk-pxa27x.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Marvell PXA27x family clocks
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2014 Robert Jarzmik
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Heavily inspired from former arch/arm/mach-pxa/clock.c.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun #include <linux/clk-provider.h>
10*4882a593Smuzhiyun #include <mach/pxa2xx-regs.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <linux/clk.h>
13*4882a593Smuzhiyun #include <linux/clkdev.h>
14*4882a593Smuzhiyun #include <linux/of.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <mach/smemc.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <dt-bindings/clock/pxa-clock.h>
19*4882a593Smuzhiyun #include "clk-pxa.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define KHz 1000
22*4882a593Smuzhiyun #define MHz (1000 * 1000)
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun enum {
25*4882a593Smuzhiyun 	PXA_CORE_13Mhz = 0,
26*4882a593Smuzhiyun 	PXA_CORE_RUN,
27*4882a593Smuzhiyun 	PXA_CORE_TURBO,
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun enum {
31*4882a593Smuzhiyun 	PXA_BUS_13Mhz = 0,
32*4882a593Smuzhiyun 	PXA_BUS_RUN,
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun enum {
36*4882a593Smuzhiyun 	PXA_LCD_13Mhz = 0,
37*4882a593Smuzhiyun 	PXA_LCD_RUN,
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun enum {
41*4882a593Smuzhiyun 	PXA_MEM_13Mhz = 0,
42*4882a593Smuzhiyun 	PXA_MEM_SYSTEM_BUS,
43*4882a593Smuzhiyun 	PXA_MEM_RUN,
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define PXA27x_CLKCFG(B, HT, T)			\
47*4882a593Smuzhiyun 	(CLKCFG_FCS |				\
48*4882a593Smuzhiyun 	 ((B)  ? CLKCFG_FASTBUS : 0) |		\
49*4882a593Smuzhiyun 	 ((HT) ? CLKCFG_HALFTURBO : 0) |	\
50*4882a593Smuzhiyun 	 ((T)  ? CLKCFG_TURBO : 0))
51*4882a593Smuzhiyun #define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define MDCNFG_DRAC2(mdcnfg)	(((mdcnfg) >> 21) & 0x3)
54*4882a593Smuzhiyun #define MDCNFG_DRAC0(mdcnfg)	(((mdcnfg) >> 5) & 0x3)
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun /* Define the refresh period in mSec for the SDRAM and the number of rows */
57*4882a593Smuzhiyun #define SDRAM_TREF	64	/* standard 64ms SDRAM */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static const char * const get_freq_khz[] = {
60*4882a593Smuzhiyun 	"core", "run", "cpll", "memory",
61*4882a593Smuzhiyun 	"system_bus"
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
get_sdram_rows(void)64*4882a593Smuzhiyun static int get_sdram_rows(void)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	static int sdram_rows;
67*4882a593Smuzhiyun 	unsigned int drac2 = 0, drac0 = 0;
68*4882a593Smuzhiyun 	u32 mdcnfg;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	if (sdram_rows)
71*4882a593Smuzhiyun 		return sdram_rows;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	mdcnfg = readl_relaxed(MDCNFG);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
76*4882a593Smuzhiyun 		drac2 = MDCNFG_DRAC2(mdcnfg);
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
79*4882a593Smuzhiyun 		drac0 = MDCNFG_DRAC0(mdcnfg);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	sdram_rows = 1 << (11 + max(drac0, drac2));
82*4882a593Smuzhiyun 	return sdram_rows;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
mdrefr_dri(unsigned int freq_khz)85*4882a593Smuzhiyun static u32 mdrefr_dri(unsigned int freq_khz)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	return (interval - 31) / 32;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun  * Get the clock frequency as reflected by CCSR and the turbo flag.
94*4882a593Smuzhiyun  * We assume these values have been applied via a fcs.
95*4882a593Smuzhiyun  * If info is not 0 we also display the current settings.
96*4882a593Smuzhiyun  */
pxa27x_get_clk_frequency_khz(int info)97*4882a593Smuzhiyun unsigned int pxa27x_get_clk_frequency_khz(int info)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct clk *clk;
100*4882a593Smuzhiyun 	unsigned long clks[5];
101*4882a593Smuzhiyun 	int i;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	for (i = 0; i < 5; i++) {
104*4882a593Smuzhiyun 		clk = clk_get(NULL, get_freq_khz[i]);
105*4882a593Smuzhiyun 		if (IS_ERR(clk)) {
106*4882a593Smuzhiyun 			clks[i] = 0;
107*4882a593Smuzhiyun 		} else {
108*4882a593Smuzhiyun 			clks[i] = clk_get_rate(clk);
109*4882a593Smuzhiyun 			clk_put(clk);
110*4882a593Smuzhiyun 		}
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 	if (info) {
113*4882a593Smuzhiyun 		pr_info("Run Mode clock: %ld.%02ldMHz\n",
114*4882a593Smuzhiyun 			clks[1] / 1000000, (clks[1] % 1000000) / 10000);
115*4882a593Smuzhiyun 		pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
116*4882a593Smuzhiyun 			clks[2] / 1000000, (clks[2] % 1000000) / 10000);
117*4882a593Smuzhiyun 		pr_info("Memory clock: %ld.%02ldMHz\n",
118*4882a593Smuzhiyun 			clks[3] / 1000000, (clks[3] % 1000000) / 10000);
119*4882a593Smuzhiyun 		pr_info("System bus clock: %ld.%02ldMHz\n",
120*4882a593Smuzhiyun 			clks[4] / 1000000, (clks[4] % 1000000) / 10000);
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun 	return (unsigned int)clks[0] / KHz;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
pxa27x_is_ppll_disabled(void)125*4882a593Smuzhiyun bool pxa27x_is_ppll_disabled(void)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return ccsr & (1 << CCCR_PPDIS_BIT);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun #define PXA27X_CKEN(dev_id, con_id, parents, mult_hp, div_hp,		\
133*4882a593Smuzhiyun 		    bit, is_lp, flags)					\
134*4882a593Smuzhiyun 	PXA_CKEN(dev_id, con_id, bit, parents, 1, 1, mult_hp, div_hp,	\
135*4882a593Smuzhiyun 		 is_lp,  CKEN, CKEN_ ## bit, flags)
136*4882a593Smuzhiyun #define PXA27X_PBUS_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay)	\
137*4882a593Smuzhiyun 	PXA27X_CKEN(dev_id, con_id, pxa27x_pbus_parents, mult_hp,	\
138*4882a593Smuzhiyun 		    div_hp, bit, pxa27x_is_ppll_disabled, 0)
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun PARENTS(pxa27x_pbus) = { "osc_13mhz", "ppll_312mhz" };
141*4882a593Smuzhiyun PARENTS(pxa27x_sbus) = { "system_bus", "system_bus" };
142*4882a593Smuzhiyun PARENTS(pxa27x_32Mhz_bus) = { "osc_32_768khz", "osc_32_768khz" };
143*4882a593Smuzhiyun PARENTS(pxa27x_lcd_bus) = { "lcd_base", "lcd_base" };
144*4882a593Smuzhiyun PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" };
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun #define PXA27X_CKEN_1RATE(dev_id, con_id, bit, parents, delay)		\
147*4882a593Smuzhiyun 	PXA_CKEN_1RATE(dev_id, con_id, bit, parents,			\
148*4882a593Smuzhiyun 		       CKEN, CKEN_ ## bit, 0)
149*4882a593Smuzhiyun #define PXA27X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay)	\
150*4882a593Smuzhiyun 	PXA_CKEN_1RATE(dev_id, con_id, bit, parents,			\
151*4882a593Smuzhiyun 		       CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun static struct desc_clk_cken pxa27x_clocks[] __initdata = {
154*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1),
155*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1),
156*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1),
157*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-i2s", NULL, I2S, 2, 51, 0),
158*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 19, 0),
159*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-udc", NULL, USB, 2, 13, 5),
160*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC, 2, 32, 0),
161*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-ir", "FICPCLK", FICP, 2, 13, 0),
162*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-ohci", NULL, USBHOST, 2, 13, 0),
163*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa2xx-i2c.1", NULL, PWRI2C, 1, 24, 0),
164*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-ssp.0", NULL, SSP1, 1, 24, 0),
165*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-ssp.1", NULL, SSP2, 1, 24, 0),
166*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-ssp.2", NULL, SSP3, 1, 24, 0),
167*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 24, 0),
168*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 24, 0),
169*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN(NULL, "MSLCLK", MSL, 2, 13, 0),
170*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN(NULL, "USIMCLK", USIM, 2, 13, 0),
171*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN(NULL, "MSTKCLK", MEMSTK, 2, 32, 0),
172*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN(NULL, "AC97CLK", AC97, 1, 1, 0),
173*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN(NULL, "AC97CONFCLK", AC97CONF, 1, 1, 0),
174*4882a593Smuzhiyun 	PXA27X_PBUS_CKEN(NULL, "OSTIMER0", OSTIMER, 1, 96, 0),
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	PXA27X_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
177*4882a593Smuzhiyun 			  pxa27x_32Mhz_bus_parents, 0),
178*4882a593Smuzhiyun 	PXA27X_CKEN_1RATE(NULL, "IMCLK", IM, pxa27x_sbus_parents, 0),
179*4882a593Smuzhiyun 	PXA27X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, pxa27x_lcd_bus_parents, 0),
180*4882a593Smuzhiyun 	PXA27X_CKEN_1RATE("pxa27x-camera.0", NULL, CAMERA,
181*4882a593Smuzhiyun 			  pxa27x_lcd_bus_parents, 0),
182*4882a593Smuzhiyun 	PXA27X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC,
183*4882a593Smuzhiyun 			     pxa27x_membus_parents, 0),
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /*
188*4882a593Smuzhiyun  * PXA270 definitions
189*4882a593Smuzhiyun  *
190*4882a593Smuzhiyun  * For the PXA27x:
191*4882a593Smuzhiyun  * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * A = 0 => memory controller clock from table 3-7,
194*4882a593Smuzhiyun  * A = 1 => memory controller clock = system bus clock
195*4882a593Smuzhiyun  * Run mode frequency	= 13 MHz * L
196*4882a593Smuzhiyun  * Turbo mode frequency = 13 MHz * L * N
197*4882a593Smuzhiyun  * System bus frequency = 13 MHz * L / (B + 1)
198*4882a593Smuzhiyun  *
199*4882a593Smuzhiyun  * In CCCR:
200*4882a593Smuzhiyun  * A = 1
201*4882a593Smuzhiyun  * L = 16	  oscillator to run mode ratio
202*4882a593Smuzhiyun  * 2N = 6	  2 * (turbo mode to run mode ratio)
203*4882a593Smuzhiyun  *
204*4882a593Smuzhiyun  * In CCLKCFG:
205*4882a593Smuzhiyun  * B = 1	  Fast bus mode
206*4882a593Smuzhiyun  * HT = 0	  Half-Turbo mode
207*4882a593Smuzhiyun  * T = 1	  Turbo mode
208*4882a593Smuzhiyun  *
209*4882a593Smuzhiyun  * For now, just support some of the combinations in table 3-7 of
210*4882a593Smuzhiyun  * PXA27x Processor Family Developer's Manual to simplify frequency
211*4882a593Smuzhiyun  * change sequences.
212*4882a593Smuzhiyun  */
213*4882a593Smuzhiyun static struct pxa2xx_freq pxa27x_freqs[] = {
214*4882a593Smuzhiyun 	{104000000, 104000, PXA27x_CCCR(1,  8, 2), 0, PXA27x_CLKCFG(1, 0, 1) },
215*4882a593Smuzhiyun 	{156000000, 104000, PXA27x_CCCR(1,  8, 3), 0, PXA27x_CLKCFG(1, 0, 1) },
216*4882a593Smuzhiyun 	{208000000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CLKCFG(0, 0, 1) },
217*4882a593Smuzhiyun 	{312000000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CLKCFG(1, 0, 1) },
218*4882a593Smuzhiyun 	{416000000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CLKCFG(1, 0, 1) },
219*4882a593Smuzhiyun 	{520000000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CLKCFG(1, 0, 1) },
220*4882a593Smuzhiyun 	{624000000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CLKCFG(1, 0, 1) },
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun 
clk_pxa27x_cpll_get_rate(struct clk_hw * hw,unsigned long parent_rate)223*4882a593Smuzhiyun static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
224*4882a593Smuzhiyun 	unsigned long parent_rate)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	unsigned long clkcfg;
227*4882a593Smuzhiyun 	unsigned int t, ht;
228*4882a593Smuzhiyun 	unsigned int l, L, n2, N;
229*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
232*4882a593Smuzhiyun 	t  = clkcfg & (1 << 0);
233*4882a593Smuzhiyun 	ht = clkcfg & (1 << 2);
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	l  = ccsr & CCSR_L_MASK;
236*4882a593Smuzhiyun 	n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
237*4882a593Smuzhiyun 	L  = l * parent_rate;
238*4882a593Smuzhiyun 	N  = (L * n2) / 2;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	return N;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
clk_pxa27x_cpll_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)243*4882a593Smuzhiyun static int clk_pxa27x_cpll_determine_rate(struct clk_hw *hw,
244*4882a593Smuzhiyun 					  struct clk_rate_request *req)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	return pxa2xx_determine_rate(req, pxa27x_freqs,
247*4882a593Smuzhiyun 				     ARRAY_SIZE(pxa27x_freqs));
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
clk_pxa27x_cpll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)250*4882a593Smuzhiyun static int clk_pxa27x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
251*4882a593Smuzhiyun 				    unsigned long parent_rate)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	int i;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
256*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(pxa27x_freqs); i++)
257*4882a593Smuzhiyun 		if (pxa27x_freqs[i].cpll == rate)
258*4882a593Smuzhiyun 			break;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (i >= ARRAY_SIZE(pxa27x_freqs))
261*4882a593Smuzhiyun 		return -EINVAL;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	pxa2xx_cpll_change(&pxa27x_freqs[i], mdrefr_dri, MDREFR, CCCR);
264*4882a593Smuzhiyun 	return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
268*4882a593Smuzhiyun RATE_OPS(clk_pxa27x_cpll, "cpll");
269*4882a593Smuzhiyun 
clk_pxa27x_lcd_base_get_rate(struct clk_hw * hw,unsigned long parent_rate)270*4882a593Smuzhiyun static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
271*4882a593Smuzhiyun 						  unsigned long parent_rate)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	unsigned int l, osc_forced;
274*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
275*4882a593Smuzhiyun 	unsigned long cccr = readl(CCCR);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	l  = ccsr & CCSR_L_MASK;
278*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
279*4882a593Smuzhiyun 	if (osc_forced) {
280*4882a593Smuzhiyun 		if (cccr & (1 << CCCR_LCD_26_BIT))
281*4882a593Smuzhiyun 			return parent_rate * 2;
282*4882a593Smuzhiyun 		else
283*4882a593Smuzhiyun 			return parent_rate;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if (l <= 7)
287*4882a593Smuzhiyun 		return parent_rate;
288*4882a593Smuzhiyun 	if (l <= 16)
289*4882a593Smuzhiyun 		return parent_rate / 2;
290*4882a593Smuzhiyun 	return parent_rate / 4;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
clk_pxa27x_lcd_base_get_parent(struct clk_hw * hw)293*4882a593Smuzhiyun static u8 clk_pxa27x_lcd_base_get_parent(struct clk_hw *hw)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	unsigned int osc_forced;
296*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
299*4882a593Smuzhiyun 	if (osc_forced)
300*4882a593Smuzhiyun 		return PXA_LCD_13Mhz;
301*4882a593Smuzhiyun 	else
302*4882a593Smuzhiyun 		return PXA_LCD_RUN;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun PARENTS(clk_pxa27x_lcd_base) = { "osc_13mhz", "run" };
306*4882a593Smuzhiyun MUX_RO_RATE_RO_OPS(clk_pxa27x_lcd_base, "lcd_base");
307*4882a593Smuzhiyun 
pxa27x_register_plls(void)308*4882a593Smuzhiyun static void __init pxa27x_register_plls(void)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
311*4882a593Smuzhiyun 				CLK_GET_RATE_NOCACHE,
312*4882a593Smuzhiyun 				13 * MHz);
313*4882a593Smuzhiyun 	clkdev_pxa_register(CLK_OSC32k768, "osc_32_768khz", NULL,
314*4882a593Smuzhiyun 			    clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
315*4882a593Smuzhiyun 						    CLK_GET_RATE_NOCACHE,
316*4882a593Smuzhiyun 						    32768 * KHz));
317*4882a593Smuzhiyun 	clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
318*4882a593Smuzhiyun 	clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
clk_pxa27x_core_get_parent(struct clk_hw * hw)321*4882a593Smuzhiyun static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun 	unsigned long clkcfg;
324*4882a593Smuzhiyun 	unsigned int t, ht, osc_forced;
325*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
328*4882a593Smuzhiyun 	if (osc_forced)
329*4882a593Smuzhiyun 		return PXA_CORE_13Mhz;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
332*4882a593Smuzhiyun 	t  = clkcfg & (1 << 0);
333*4882a593Smuzhiyun 	ht = clkcfg & (1 << 2);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (ht || t)
336*4882a593Smuzhiyun 		return PXA_CORE_TURBO;
337*4882a593Smuzhiyun 	return PXA_CORE_RUN;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
clk_pxa27x_core_set_parent(struct clk_hw * hw,u8 index)340*4882a593Smuzhiyun static int clk_pxa27x_core_set_parent(struct clk_hw *hw, u8 index)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	if (index > PXA_CORE_TURBO)
343*4882a593Smuzhiyun 		return -EINVAL;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	return 0;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
clk_pxa27x_core_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)350*4882a593Smuzhiyun static int clk_pxa27x_core_determine_rate(struct clk_hw *hw,
351*4882a593Smuzhiyun 					  struct clk_rate_request *req)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	return __clk_mux_determine_rate(hw, req);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
357*4882a593Smuzhiyun MUX_OPS(clk_pxa27x_core, "core", CLK_SET_RATE_PARENT);
358*4882a593Smuzhiyun 
clk_pxa27x_run_get_rate(struct clk_hw * hw,unsigned long parent_rate)359*4882a593Smuzhiyun static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
360*4882a593Smuzhiyun 					     unsigned long parent_rate)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
363*4882a593Smuzhiyun 	unsigned int n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	return (parent_rate / n2) * 2;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun PARENTS(clk_pxa27x_run) = { "cpll" };
368*4882a593Smuzhiyun RATE_RO_OPS(clk_pxa27x_run, "run");
369*4882a593Smuzhiyun 
pxa27x_register_core(void)370*4882a593Smuzhiyun static void __init pxa27x_register_core(void)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	clkdev_pxa_register(CLK_NONE, "cpll", NULL,
373*4882a593Smuzhiyun 			    clk_register_clk_pxa27x_cpll());
374*4882a593Smuzhiyun 	clkdev_pxa_register(CLK_NONE, "run", NULL,
375*4882a593Smuzhiyun 			    clk_register_clk_pxa27x_run());
376*4882a593Smuzhiyun 	clkdev_pxa_register(CLK_CORE, "core", NULL,
377*4882a593Smuzhiyun 			    clk_register_clk_pxa27x_core());
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
clk_pxa27x_system_bus_get_rate(struct clk_hw * hw,unsigned long parent_rate)380*4882a593Smuzhiyun static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw,
381*4882a593Smuzhiyun 						    unsigned long parent_rate)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	unsigned long clkcfg;
384*4882a593Smuzhiyun 	unsigned int b, osc_forced;
385*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
388*4882a593Smuzhiyun 	asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
389*4882a593Smuzhiyun 	b  = clkcfg & (1 << 3);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (osc_forced)
392*4882a593Smuzhiyun 		return parent_rate;
393*4882a593Smuzhiyun 	if (b)
394*4882a593Smuzhiyun 		return parent_rate;
395*4882a593Smuzhiyun 	else
396*4882a593Smuzhiyun 		return parent_rate / 2;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
clk_pxa27x_system_bus_get_parent(struct clk_hw * hw)399*4882a593Smuzhiyun static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	unsigned int osc_forced;
402*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
405*4882a593Smuzhiyun 	if (osc_forced)
406*4882a593Smuzhiyun 		return PXA_BUS_13Mhz;
407*4882a593Smuzhiyun 	else
408*4882a593Smuzhiyun 		return PXA_BUS_RUN;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun PARENTS(clk_pxa27x_system_bus) = { "osc_13mhz", "run" };
412*4882a593Smuzhiyun MUX_RO_RATE_RO_OPS(clk_pxa27x_system_bus, "system_bus");
413*4882a593Smuzhiyun 
clk_pxa27x_memory_get_rate(struct clk_hw * hw,unsigned long parent_rate)414*4882a593Smuzhiyun static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
415*4882a593Smuzhiyun 						unsigned long parent_rate)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun 	unsigned int a, l, osc_forced;
418*4882a593Smuzhiyun 	unsigned long cccr = readl(CCCR);
419*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
422*4882a593Smuzhiyun 	a = cccr & (1 << CCCR_A_BIT);
423*4882a593Smuzhiyun 	l  = ccsr & CCSR_L_MASK;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	if (osc_forced || a)
426*4882a593Smuzhiyun 		return parent_rate;
427*4882a593Smuzhiyun 	if (l <= 10)
428*4882a593Smuzhiyun 		return parent_rate;
429*4882a593Smuzhiyun 	if (l <= 20)
430*4882a593Smuzhiyun 		return parent_rate / 2;
431*4882a593Smuzhiyun 	return parent_rate / 4;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
clk_pxa27x_memory_get_parent(struct clk_hw * hw)434*4882a593Smuzhiyun static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	unsigned int osc_forced, a;
437*4882a593Smuzhiyun 	unsigned long cccr = readl(CCCR);
438*4882a593Smuzhiyun 	unsigned long ccsr = readl(CCSR);
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
441*4882a593Smuzhiyun 	a = cccr & (1 << CCCR_A_BIT);
442*4882a593Smuzhiyun 	if (osc_forced)
443*4882a593Smuzhiyun 		return PXA_MEM_13Mhz;
444*4882a593Smuzhiyun 	if (a)
445*4882a593Smuzhiyun 		return PXA_MEM_SYSTEM_BUS;
446*4882a593Smuzhiyun 	else
447*4882a593Smuzhiyun 		return PXA_MEM_RUN;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun PARENTS(clk_pxa27x_memory) = { "osc_13mhz", "system_bus", "run" };
451*4882a593Smuzhiyun MUX_RO_RATE_RO_OPS(clk_pxa27x_memory, "memory");
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun #define DUMMY_CLK(_con_id, _dev_id, _parent) \
454*4882a593Smuzhiyun 	{ .con_id = _con_id, .dev_id = _dev_id, .parent = _parent }
455*4882a593Smuzhiyun struct dummy_clk {
456*4882a593Smuzhiyun 	const char *con_id;
457*4882a593Smuzhiyun 	const char *dev_id;
458*4882a593Smuzhiyun 	const char *parent;
459*4882a593Smuzhiyun };
460*4882a593Smuzhiyun static struct dummy_clk dummy_clks[] __initdata = {
461*4882a593Smuzhiyun 	DUMMY_CLK(NULL, "pxa27x-gpio", "osc_32_768khz"),
462*4882a593Smuzhiyun 	DUMMY_CLK(NULL, "pxa-rtc", "osc_32_768khz"),
463*4882a593Smuzhiyun 	DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
464*4882a593Smuzhiyun 	DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
465*4882a593Smuzhiyun };
466*4882a593Smuzhiyun 
pxa27x_dummy_clocks_init(void)467*4882a593Smuzhiyun static void __init pxa27x_dummy_clocks_init(void)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun 	struct clk *clk;
470*4882a593Smuzhiyun 	struct dummy_clk *d;
471*4882a593Smuzhiyun 	const char *name;
472*4882a593Smuzhiyun 	int i;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) {
475*4882a593Smuzhiyun 		d = &dummy_clks[i];
476*4882a593Smuzhiyun 		name = d->dev_id ? d->dev_id : d->con_id;
477*4882a593Smuzhiyun 		clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1);
478*4882a593Smuzhiyun 		clk_register_clkdev(clk, d->con_id, d->dev_id);
479*4882a593Smuzhiyun 	}
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
pxa27x_base_clocks_init(void)482*4882a593Smuzhiyun static void __init pxa27x_base_clocks_init(void)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	pxa27x_register_plls();
485*4882a593Smuzhiyun 	pxa27x_register_core();
486*4882a593Smuzhiyun 	clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
487*4882a593Smuzhiyun 			    clk_register_clk_pxa27x_system_bus());
488*4882a593Smuzhiyun 	clkdev_pxa_register(CLK_NONE, "memory", NULL,
489*4882a593Smuzhiyun 			    clk_register_clk_pxa27x_memory());
490*4882a593Smuzhiyun 	clk_register_clk_pxa27x_lcd_base();
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
pxa27x_clocks_init(void)493*4882a593Smuzhiyun int __init pxa27x_clocks_init(void)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	pxa27x_base_clocks_init();
496*4882a593Smuzhiyun 	pxa27x_dummy_clocks_init();
497*4882a593Smuzhiyun 	return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks));
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
pxa27x_dt_clocks_init(struct device_node * np)500*4882a593Smuzhiyun static void __init pxa27x_dt_clocks_init(struct device_node *np)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun 	pxa27x_clocks_init();
503*4882a593Smuzhiyun 	clk_pxa_dt_common_init(np);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun CLK_OF_DECLARE(pxa_clks, "marvell,pxa270-clocks", pxa27x_dt_clocks_init);
506