xref: /OK3568_Linux_fs/kernel/arch/mips/ar7/clock.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
4*4882a593Smuzhiyun  * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
5*4882a593Smuzhiyun  * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/types.h>
11*4882a593Smuzhiyun #include <linux/export.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/gcd.h>
14*4882a593Smuzhiyun #include <linux/io.h>
15*4882a593Smuzhiyun #include <linux/err.h>
16*4882a593Smuzhiyun #include <linux/clk.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <asm/addrspace.h>
19*4882a593Smuzhiyun #include <asm/mach-ar7/ar7.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define BOOT_PLL_SOURCE_MASK	0x3
22*4882a593Smuzhiyun #define CPU_PLL_SOURCE_SHIFT	16
23*4882a593Smuzhiyun #define BUS_PLL_SOURCE_SHIFT	14
24*4882a593Smuzhiyun #define USB_PLL_SOURCE_SHIFT	18
25*4882a593Smuzhiyun #define DSP_PLL_SOURCE_SHIFT	22
26*4882a593Smuzhiyun #define BOOT_PLL_SOURCE_AFE	0
27*4882a593Smuzhiyun #define BOOT_PLL_SOURCE_BUS	0
28*4882a593Smuzhiyun #define BOOT_PLL_SOURCE_REF	1
29*4882a593Smuzhiyun #define BOOT_PLL_SOURCE_XTAL	2
30*4882a593Smuzhiyun #define BOOT_PLL_SOURCE_CPU	3
31*4882a593Smuzhiyun #define BOOT_PLL_BYPASS		0x00000020
32*4882a593Smuzhiyun #define BOOT_PLL_ASYNC_MODE	0x02000000
33*4882a593Smuzhiyun #define BOOT_PLL_2TO1_MODE	0x00008000
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define TNETD7200_CLOCK_ID_CPU	0
36*4882a593Smuzhiyun #define TNETD7200_CLOCK_ID_DSP	1
37*4882a593Smuzhiyun #define TNETD7200_CLOCK_ID_USB	2
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define TNETD7200_DEF_CPU_CLK	211000000
40*4882a593Smuzhiyun #define TNETD7200_DEF_DSP_CLK	125000000
41*4882a593Smuzhiyun #define TNETD7200_DEF_USB_CLK	48000000
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun struct tnetd7300_clock {
44*4882a593Smuzhiyun 	u32 ctrl;
45*4882a593Smuzhiyun #define PREDIV_MASK	0x001f0000
46*4882a593Smuzhiyun #define PREDIV_SHIFT	16
47*4882a593Smuzhiyun #define POSTDIV_MASK	0x0000001f
48*4882a593Smuzhiyun 	u32 unused1[3];
49*4882a593Smuzhiyun 	u32 pll;
50*4882a593Smuzhiyun #define MUL_MASK	0x0000f000
51*4882a593Smuzhiyun #define MUL_SHIFT	12
52*4882a593Smuzhiyun #define PLL_MODE_MASK	0x00000001
53*4882a593Smuzhiyun #define PLL_NDIV	0x00000800
54*4882a593Smuzhiyun #define PLL_DIV		0x00000002
55*4882a593Smuzhiyun #define PLL_STATUS	0x00000001
56*4882a593Smuzhiyun 	u32 unused2[3];
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun struct tnetd7300_clocks {
60*4882a593Smuzhiyun 	struct tnetd7300_clock bus;
61*4882a593Smuzhiyun 	struct tnetd7300_clock cpu;
62*4882a593Smuzhiyun 	struct tnetd7300_clock usb;
63*4882a593Smuzhiyun 	struct tnetd7300_clock dsp;
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun struct tnetd7200_clock {
67*4882a593Smuzhiyun 	u32 ctrl;
68*4882a593Smuzhiyun 	u32 unused1[3];
69*4882a593Smuzhiyun #define DIVISOR_ENABLE_MASK 0x00008000
70*4882a593Smuzhiyun 	u32 mul;
71*4882a593Smuzhiyun 	u32 prediv;
72*4882a593Smuzhiyun 	u32 postdiv;
73*4882a593Smuzhiyun 	u32 postdiv2;
74*4882a593Smuzhiyun 	u32 unused2[6];
75*4882a593Smuzhiyun 	u32 cmd;
76*4882a593Smuzhiyun 	u32 status;
77*4882a593Smuzhiyun 	u32 cmden;
78*4882a593Smuzhiyun 	u32 padding[15];
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun struct tnetd7200_clocks {
82*4882a593Smuzhiyun 	struct tnetd7200_clock cpu;
83*4882a593Smuzhiyun 	struct tnetd7200_clock dsp;
84*4882a593Smuzhiyun 	struct tnetd7200_clock usb;
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static struct clk bus_clk = {
88*4882a593Smuzhiyun 	.rate	= 125000000,
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun static struct clk cpu_clk = {
92*4882a593Smuzhiyun 	.rate	= 150000000,
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun static struct clk dsp_clk;
96*4882a593Smuzhiyun static struct clk vbus_clk;
97*4882a593Smuzhiyun 
approximate(int base,int target,int * prediv,int * postdiv,int * mul)98*4882a593Smuzhiyun static void approximate(int base, int target, int *prediv,
99*4882a593Smuzhiyun 			int *postdiv, int *mul)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	int i, j, k, freq, res = target;
102*4882a593Smuzhiyun 	for (i = 1; i <= 16; i++)
103*4882a593Smuzhiyun 		for (j = 1; j <= 32; j++)
104*4882a593Smuzhiyun 			for (k = 1; k <= 32; k++) {
105*4882a593Smuzhiyun 				freq = abs(base / j * i / k - target);
106*4882a593Smuzhiyun 				if (freq < res) {
107*4882a593Smuzhiyun 					res = freq;
108*4882a593Smuzhiyun 					*mul = i;
109*4882a593Smuzhiyun 					*prediv = j;
110*4882a593Smuzhiyun 					*postdiv = k;
111*4882a593Smuzhiyun 				}
112*4882a593Smuzhiyun 			}
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
calculate(int base,int target,int * prediv,int * postdiv,int * mul)115*4882a593Smuzhiyun static void calculate(int base, int target, int *prediv, int *postdiv,
116*4882a593Smuzhiyun 	int *mul)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	int tmp_gcd, tmp_base, tmp_freq;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	for (*prediv = 1; *prediv <= 32; (*prediv)++) {
121*4882a593Smuzhiyun 		tmp_base = base / *prediv;
122*4882a593Smuzhiyun 		tmp_gcd = gcd(target, tmp_base);
123*4882a593Smuzhiyun 		*mul = target / tmp_gcd;
124*4882a593Smuzhiyun 		*postdiv = tmp_base / tmp_gcd;
125*4882a593Smuzhiyun 		if ((*mul < 1) || (*mul >= 16))
126*4882a593Smuzhiyun 			continue;
127*4882a593Smuzhiyun 		if ((*postdiv > 0) & (*postdiv <= 32))
128*4882a593Smuzhiyun 			break;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	if (base / *prediv * *mul / *postdiv != target) {
132*4882a593Smuzhiyun 		approximate(base, target, prediv, postdiv, mul);
133*4882a593Smuzhiyun 		tmp_freq = base / *prediv * *mul / *postdiv;
134*4882a593Smuzhiyun 		printk(KERN_WARNING
135*4882a593Smuzhiyun 		       "Adjusted requested frequency %d to %d\n",
136*4882a593Smuzhiyun 		       target, tmp_freq);
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
140*4882a593Smuzhiyun 	       *prediv, *postdiv, *mul);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
tnetd7300_dsp_clock(void)143*4882a593Smuzhiyun static int tnetd7300_dsp_clock(void)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	u32 didr1, didr2;
146*4882a593Smuzhiyun 	u8 rev = ar7_chip_rev();
147*4882a593Smuzhiyun 	didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
148*4882a593Smuzhiyun 	didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
149*4882a593Smuzhiyun 	if (didr2 & (1 << 23))
150*4882a593Smuzhiyun 		return 0;
151*4882a593Smuzhiyun 	if ((rev >= 0x23) && (rev != 0x57))
152*4882a593Smuzhiyun 		return 250000000;
153*4882a593Smuzhiyun 	if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
154*4882a593Smuzhiyun 	    > 4208000)
155*4882a593Smuzhiyun 		return 250000000;
156*4882a593Smuzhiyun 	return 0;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
tnetd7300_get_clock(u32 shift,struct tnetd7300_clock * clock,u32 * bootcr,u32 bus_clock)159*4882a593Smuzhiyun static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
160*4882a593Smuzhiyun 	u32 *bootcr, u32 bus_clock)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	int product;
163*4882a593Smuzhiyun 	int base_clock = AR7_REF_CLOCK;
164*4882a593Smuzhiyun 	u32 ctrl = readl(&clock->ctrl);
165*4882a593Smuzhiyun 	u32 pll = readl(&clock->pll);
166*4882a593Smuzhiyun 	int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
167*4882a593Smuzhiyun 	int postdiv = (ctrl & POSTDIV_MASK) + 1;
168*4882a593Smuzhiyun 	int divisor = prediv * postdiv;
169*4882a593Smuzhiyun 	int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
172*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_BUS:
173*4882a593Smuzhiyun 		base_clock = bus_clock;
174*4882a593Smuzhiyun 		break;
175*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_REF:
176*4882a593Smuzhiyun 		base_clock = AR7_REF_CLOCK;
177*4882a593Smuzhiyun 		break;
178*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_XTAL:
179*4882a593Smuzhiyun 		base_clock = AR7_XTAL_CLOCK;
180*4882a593Smuzhiyun 		break;
181*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_CPU:
182*4882a593Smuzhiyun 		base_clock = cpu_clk.rate;
183*4882a593Smuzhiyun 		break;
184*4882a593Smuzhiyun 	}
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	if (*bootcr & BOOT_PLL_BYPASS)
187*4882a593Smuzhiyun 		return base_clock / divisor;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	if ((pll & PLL_MODE_MASK) == 0)
190*4882a593Smuzhiyun 		return (base_clock >> (mul / 16 + 1)) / divisor;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
193*4882a593Smuzhiyun 		product = (mul & 1) ?
194*4882a593Smuzhiyun 			(base_clock * mul) >> 1 :
195*4882a593Smuzhiyun 			(base_clock * (mul - 1)) >> 2;
196*4882a593Smuzhiyun 		return product / divisor;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	if (mul == 16)
200*4882a593Smuzhiyun 		return base_clock / divisor;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	return base_clock * mul / divisor;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
tnetd7300_set_clock(u32 shift,struct tnetd7300_clock * clock,u32 * bootcr,u32 frequency)205*4882a593Smuzhiyun static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
206*4882a593Smuzhiyun 	u32 *bootcr, u32 frequency)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	int prediv, postdiv, mul;
209*4882a593Smuzhiyun 	int base_clock = bus_clk.rate;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
212*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_BUS:
213*4882a593Smuzhiyun 		base_clock = bus_clk.rate;
214*4882a593Smuzhiyun 		break;
215*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_REF:
216*4882a593Smuzhiyun 		base_clock = AR7_REF_CLOCK;
217*4882a593Smuzhiyun 		break;
218*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_XTAL:
219*4882a593Smuzhiyun 		base_clock = AR7_XTAL_CLOCK;
220*4882a593Smuzhiyun 		break;
221*4882a593Smuzhiyun 	case BOOT_PLL_SOURCE_CPU:
222*4882a593Smuzhiyun 		base_clock = cpu_clk.rate;
223*4882a593Smuzhiyun 		break;
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	calculate(base_clock, frequency, &prediv, &postdiv, &mul);
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
229*4882a593Smuzhiyun 	mdelay(1);
230*4882a593Smuzhiyun 	writel(4, &clock->pll);
231*4882a593Smuzhiyun 	while (readl(&clock->pll) & PLL_STATUS)
232*4882a593Smuzhiyun 		;
233*4882a593Smuzhiyun 	writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
234*4882a593Smuzhiyun 	mdelay(75);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun 
tnetd7300_init_clocks(void)237*4882a593Smuzhiyun static void __init tnetd7300_init_clocks(void)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun 	u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
240*4882a593Smuzhiyun 	struct tnetd7300_clocks *clocks =
241*4882a593Smuzhiyun 					ioremap(UR8_REGS_CLOCKS,
242*4882a593Smuzhiyun 					sizeof(struct tnetd7300_clocks));
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
245*4882a593Smuzhiyun 		&clocks->bus, bootcr, AR7_AFE_CLOCK);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	if (*bootcr & BOOT_PLL_ASYNC_MODE)
248*4882a593Smuzhiyun 		cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
249*4882a593Smuzhiyun 			&clocks->cpu, bootcr, AR7_AFE_CLOCK);
250*4882a593Smuzhiyun 	else
251*4882a593Smuzhiyun 		cpu_clk.rate = bus_clk.rate;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	if (dsp_clk.rate == 250000000)
254*4882a593Smuzhiyun 		tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
255*4882a593Smuzhiyun 			bootcr, dsp_clk.rate);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	iounmap(clocks);
258*4882a593Smuzhiyun 	iounmap(bootcr);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
tnetd7200_set_clock(int base,struct tnetd7200_clock * clock,int prediv,int postdiv,int postdiv2,int mul,u32 frequency)261*4882a593Smuzhiyun static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
262*4882a593Smuzhiyun 	int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	printk(KERN_INFO
265*4882a593Smuzhiyun 		"Clocks: base = %d, frequency = %u, prediv = %d, "
266*4882a593Smuzhiyun 		"postdiv = %d, postdiv2 = %d, mul = %d\n",
267*4882a593Smuzhiyun 		base, frequency, prediv, postdiv, postdiv2, mul);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	writel(0, &clock->ctrl);
270*4882a593Smuzhiyun 	writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
271*4882a593Smuzhiyun 	writel((mul - 1) & 0xF, &clock->mul);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	while (readl(&clock->status) & 0x1)
274*4882a593Smuzhiyun 		; /* nop */
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	writel(readl(&clock->cmden) | 1, &clock->cmden);
279*4882a593Smuzhiyun 	writel(readl(&clock->cmd) | 1, &clock->cmd);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	while (readl(&clock->status) & 0x1)
282*4882a593Smuzhiyun 		; /* nop */
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	writel(readl(&clock->cmden) | 1, &clock->cmden);
287*4882a593Smuzhiyun 	writel(readl(&clock->cmd) | 1, &clock->cmd);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	while (readl(&clock->status) & 0x1)
290*4882a593Smuzhiyun 		; /* nop */
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	writel(readl(&clock->ctrl) | 1, &clock->ctrl);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun 
tnetd7200_get_clock_base(int clock_id,u32 * bootcr)295*4882a593Smuzhiyun static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun 	if (*bootcr & BOOT_PLL_ASYNC_MODE)
298*4882a593Smuzhiyun 		/* Async */
299*4882a593Smuzhiyun 		switch (clock_id) {
300*4882a593Smuzhiyun 		case TNETD7200_CLOCK_ID_DSP:
301*4882a593Smuzhiyun 			return AR7_REF_CLOCK;
302*4882a593Smuzhiyun 		default:
303*4882a593Smuzhiyun 			return AR7_AFE_CLOCK;
304*4882a593Smuzhiyun 		}
305*4882a593Smuzhiyun 	else
306*4882a593Smuzhiyun 		/* Sync */
307*4882a593Smuzhiyun 		if (*bootcr & BOOT_PLL_2TO1_MODE)
308*4882a593Smuzhiyun 			/* 2:1 */
309*4882a593Smuzhiyun 			switch (clock_id) {
310*4882a593Smuzhiyun 			case TNETD7200_CLOCK_ID_DSP:
311*4882a593Smuzhiyun 				return AR7_REF_CLOCK;
312*4882a593Smuzhiyun 			default:
313*4882a593Smuzhiyun 				return AR7_AFE_CLOCK;
314*4882a593Smuzhiyun 			}
315*4882a593Smuzhiyun 		else
316*4882a593Smuzhiyun 			/* 1:1 */
317*4882a593Smuzhiyun 			return AR7_REF_CLOCK;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 
tnetd7200_init_clocks(void)321*4882a593Smuzhiyun static void __init tnetd7200_init_clocks(void)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun 	u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4);
324*4882a593Smuzhiyun 	struct tnetd7200_clocks *clocks =
325*4882a593Smuzhiyun 					ioremap(AR7_REGS_CLOCKS,
326*4882a593Smuzhiyun 					sizeof(struct tnetd7200_clocks));
327*4882a593Smuzhiyun 	int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
328*4882a593Smuzhiyun 	int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
329*4882a593Smuzhiyun 	int usb_base, usb_mul, usb_prediv, usb_postdiv;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
332*4882a593Smuzhiyun 	dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	if (*bootcr & BOOT_PLL_ASYNC_MODE) {
335*4882a593Smuzhiyun 		printk(KERN_INFO "Clocks: Async mode\n");
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 		printk(KERN_INFO "Clocks: Setting DSP clock\n");
338*4882a593Smuzhiyun 		calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
339*4882a593Smuzhiyun 			&dsp_prediv, &dsp_postdiv, &dsp_mul);
340*4882a593Smuzhiyun 		bus_clk.rate =
341*4882a593Smuzhiyun 			((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
342*4882a593Smuzhiyun 		tnetd7200_set_clock(dsp_base, &clocks->dsp,
343*4882a593Smuzhiyun 			dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
344*4882a593Smuzhiyun 			bus_clk.rate);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 		printk(KERN_INFO "Clocks: Setting CPU clock\n");
347*4882a593Smuzhiyun 		calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
348*4882a593Smuzhiyun 			&cpu_postdiv, &cpu_mul);
349*4882a593Smuzhiyun 		cpu_clk.rate =
350*4882a593Smuzhiyun 			((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
351*4882a593Smuzhiyun 		tnetd7200_set_clock(cpu_base, &clocks->cpu,
352*4882a593Smuzhiyun 			cpu_prediv, cpu_postdiv, -1, cpu_mul,
353*4882a593Smuzhiyun 			cpu_clk.rate);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	} else
356*4882a593Smuzhiyun 		if (*bootcr & BOOT_PLL_2TO1_MODE) {
357*4882a593Smuzhiyun 			printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 			printk(KERN_INFO "Clocks: Setting CPU clock\n");
360*4882a593Smuzhiyun 			calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
361*4882a593Smuzhiyun 				&cpu_postdiv, &cpu_mul);
362*4882a593Smuzhiyun 			cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
363*4882a593Smuzhiyun 								/ cpu_postdiv;
364*4882a593Smuzhiyun 			tnetd7200_set_clock(cpu_base, &clocks->cpu,
365*4882a593Smuzhiyun 				cpu_prediv, cpu_postdiv, -1, cpu_mul,
366*4882a593Smuzhiyun 				cpu_clk.rate);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 			printk(KERN_INFO "Clocks: Setting DSP clock\n");
369*4882a593Smuzhiyun 			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
370*4882a593Smuzhiyun 				&dsp_postdiv, &dsp_mul);
371*4882a593Smuzhiyun 			bus_clk.rate = cpu_clk.rate / 2;
372*4882a593Smuzhiyun 			tnetd7200_set_clock(dsp_base, &clocks->dsp,
373*4882a593Smuzhiyun 				dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
374*4882a593Smuzhiyun 				dsp_mul * 2, bus_clk.rate);
375*4882a593Smuzhiyun 		} else {
376*4882a593Smuzhiyun 			printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 			printk(KERN_INFO "Clocks: Setting DSP clock\n");
379*4882a593Smuzhiyun 			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
380*4882a593Smuzhiyun 				&dsp_postdiv, &dsp_mul);
381*4882a593Smuzhiyun 			bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
382*4882a593Smuzhiyun 								/ dsp_postdiv;
383*4882a593Smuzhiyun 			tnetd7200_set_clock(dsp_base, &clocks->dsp,
384*4882a593Smuzhiyun 				dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
385*4882a593Smuzhiyun 				dsp_mul * 2, bus_clk.rate);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 			cpu_clk.rate = bus_clk.rate;
388*4882a593Smuzhiyun 		}
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	printk(KERN_INFO "Clocks: Setting USB clock\n");
391*4882a593Smuzhiyun 	usb_base = bus_clk.rate;
392*4882a593Smuzhiyun 	calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
393*4882a593Smuzhiyun 		&usb_postdiv, &usb_mul);
394*4882a593Smuzhiyun 	tnetd7200_set_clock(usb_base, &clocks->usb,
395*4882a593Smuzhiyun 		usb_prediv, usb_postdiv, -1, usb_mul,
396*4882a593Smuzhiyun 		TNETD7200_DEF_USB_CLK);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	dsp_clk.rate = cpu_clk.rate;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	iounmap(clocks);
401*4882a593Smuzhiyun 	iounmap(bootcr);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun /*
405*4882a593Smuzhiyun  * Linux clock API
406*4882a593Smuzhiyun  */
clk_enable(struct clk * clk)407*4882a593Smuzhiyun int clk_enable(struct clk *clk)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	return 0;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun EXPORT_SYMBOL(clk_enable);
412*4882a593Smuzhiyun 
clk_disable(struct clk * clk)413*4882a593Smuzhiyun void clk_disable(struct clk *clk)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun EXPORT_SYMBOL(clk_disable);
417*4882a593Smuzhiyun 
clk_get_rate(struct clk * clk)418*4882a593Smuzhiyun unsigned long clk_get_rate(struct clk *clk)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	if (!clk)
421*4882a593Smuzhiyun 		return 0;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return clk->rate;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun EXPORT_SYMBOL(clk_get_rate);
426*4882a593Smuzhiyun 
clk_get(struct device * dev,const char * id)427*4882a593Smuzhiyun struct clk *clk_get(struct device *dev, const char *id)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	if (!strcmp(id, "bus"))
430*4882a593Smuzhiyun 		return &bus_clk;
431*4882a593Smuzhiyun 	/* cpmac and vbus share the same rate */
432*4882a593Smuzhiyun 	if (!strcmp(id, "cpmac"))
433*4882a593Smuzhiyun 		return &vbus_clk;
434*4882a593Smuzhiyun 	if (!strcmp(id, "cpu"))
435*4882a593Smuzhiyun 		return &cpu_clk;
436*4882a593Smuzhiyun 	if (!strcmp(id, "dsp"))
437*4882a593Smuzhiyun 		return &dsp_clk;
438*4882a593Smuzhiyun 	if (!strcmp(id, "vbus"))
439*4882a593Smuzhiyun 		return &vbus_clk;
440*4882a593Smuzhiyun 	return ERR_PTR(-ENOENT);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun EXPORT_SYMBOL(clk_get);
443*4882a593Smuzhiyun 
clk_put(struct clk * clk)444*4882a593Smuzhiyun void clk_put(struct clk *clk)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun EXPORT_SYMBOL(clk_put);
448*4882a593Smuzhiyun 
ar7_init_clocks(void)449*4882a593Smuzhiyun void __init ar7_init_clocks(void)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun 	switch (ar7_chip_id()) {
452*4882a593Smuzhiyun 	case AR7_CHIP_7100:
453*4882a593Smuzhiyun 	case AR7_CHIP_7200:
454*4882a593Smuzhiyun 		tnetd7200_init_clocks();
455*4882a593Smuzhiyun 		break;
456*4882a593Smuzhiyun 	case AR7_CHIP_7300:
457*4882a593Smuzhiyun 		dsp_clk.rate = tnetd7300_dsp_clock();
458*4882a593Smuzhiyun 		tnetd7300_init_clocks();
459*4882a593Smuzhiyun 		break;
460*4882a593Smuzhiyun 	default:
461*4882a593Smuzhiyun 		break;
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 	/* adjust vbus clock rate */
464*4882a593Smuzhiyun 	vbus_clk.rate = bus_clk.rate / 2;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun /* dummy functions, should not be called */
clk_round_rate(struct clk * clk,unsigned long rate)468*4882a593Smuzhiyun long clk_round_rate(struct clk *clk, unsigned long rate)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	WARN_ON(clk);
471*4882a593Smuzhiyun 	return 0;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun EXPORT_SYMBOL(clk_round_rate);
474*4882a593Smuzhiyun 
clk_set_rate(struct clk * clk,unsigned long rate)475*4882a593Smuzhiyun int clk_set_rate(struct clk *clk, unsigned long rate)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun 	WARN_ON(clk);
478*4882a593Smuzhiyun 	return 0;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun EXPORT_SYMBOL(clk_set_rate);
481*4882a593Smuzhiyun 
clk_set_parent(struct clk * clk,struct clk * parent)482*4882a593Smuzhiyun int clk_set_parent(struct clk *clk, struct clk *parent)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	WARN_ON(clk);
485*4882a593Smuzhiyun 	return 0;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun EXPORT_SYMBOL(clk_set_parent);
488*4882a593Smuzhiyun 
clk_get_parent(struct clk * clk)489*4882a593Smuzhiyun struct clk *clk_get_parent(struct clk *clk)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun 	WARN_ON(clk);
492*4882a593Smuzhiyun 	return NULL;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun EXPORT_SYMBOL(clk_get_parent);
495