xref: /openbmc/linux/arch/arm/mach-ep93xx/clock.c (revision fd589a8f)
1 /*
2  * arch/arm/mach-ep93xx/clock.c
3  * Clock control for Cirrus EP93xx chips.
4  *
5  * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or (at
10  * your option) any later version.
11  */
12 
13 #include <linux/kernel.h>
14 #include <linux/clk.h>
15 #include <linux/err.h>
16 #include <linux/module.h>
17 #include <linux/string.h>
18 #include <linux/io.h>
19 
20 #include <asm/clkdev.h>
21 #include <asm/div64.h>
22 #include <mach/hardware.h>
23 
24 
25 struct clk {
26 	unsigned long	rate;
27 	int		users;
28 	int		sw_locked;
29 	void __iomem	*enable_reg;
30 	u32		enable_mask;
31 
32 	unsigned long	(*get_rate)(struct clk *clk);
33 	int		(*set_rate)(struct clk *clk, unsigned long rate);
34 };
35 
36 
37 static unsigned long get_uart_rate(struct clk *clk);
38 
39 static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
40 
41 
42 static struct clk clk_uart1 = {
43 	.sw_locked	= 1,
44 	.enable_reg	= EP93XX_SYSCON_DEVCFG,
45 	.enable_mask	= EP93XX_SYSCON_DEVCFG_U1EN,
46 	.get_rate	= get_uart_rate,
47 };
48 static struct clk clk_uart2 = {
49 	.sw_locked	= 1,
50 	.enable_reg	= EP93XX_SYSCON_DEVCFG,
51 	.enable_mask	= EP93XX_SYSCON_DEVCFG_U2EN,
52 	.get_rate	= get_uart_rate,
53 };
54 static struct clk clk_uart3 = {
55 	.sw_locked	= 1,
56 	.enable_reg	= EP93XX_SYSCON_DEVCFG,
57 	.enable_mask	= EP93XX_SYSCON_DEVCFG_U3EN,
58 	.get_rate	= get_uart_rate,
59 };
60 static struct clk clk_pll1;
61 static struct clk clk_f;
62 static struct clk clk_h;
63 static struct clk clk_p;
64 static struct clk clk_pll2;
65 static struct clk clk_usb_host = {
66 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
67 	.enable_mask	= EP93XX_SYSCON_PWRCNT_USH_EN,
68 };
69 static struct clk clk_keypad = {
70 	.sw_locked	= 1,
71 	.enable_reg	= EP93XX_SYSCON_KEYTCHCLKDIV,
72 	.enable_mask	= EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
73 	.set_rate	= set_keytchclk_rate,
74 };
75 static struct clk clk_pwm = {
76 	.rate		= EP93XX_EXT_CLK_RATE,
77 };
78 
79 /* DMA Clocks */
80 static struct clk clk_m2p0 = {
81 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
82 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P0,
83 };
84 static struct clk clk_m2p1 = {
85 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
86 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P1,
87 };
88 static struct clk clk_m2p2 = {
89 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
90 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P2,
91 };
92 static struct clk clk_m2p3 = {
93 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
94 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P3,
95 };
96 static struct clk clk_m2p4 = {
97 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
98 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P4,
99 };
100 static struct clk clk_m2p5 = {
101 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
102 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P5,
103 };
104 static struct clk clk_m2p6 = {
105 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
106 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P6,
107 };
108 static struct clk clk_m2p7 = {
109 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
110 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P7,
111 };
112 static struct clk clk_m2p8 = {
113 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
114 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P8,
115 };
116 static struct clk clk_m2p9 = {
117 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
118 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P9,
119 };
120 static struct clk clk_m2m0 = {
121 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
122 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2M0,
123 };
124 static struct clk clk_m2m1 = {
125 	.enable_reg	= EP93XX_SYSCON_PWRCNT,
126 	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2M1,
127 };
128 
129 #define INIT_CK(dev,con,ck)					\
130 	{ .dev_id = dev, .con_id = con, .clk = ck }
131 
132 static struct clk_lookup clocks[] = {
133 	INIT_CK("apb:uart1",		NULL,		&clk_uart1),
134 	INIT_CK("apb:uart2",		NULL,		&clk_uart2),
135 	INIT_CK("apb:uart3",		NULL,		&clk_uart3),
136 	INIT_CK(NULL,			"pll1",		&clk_pll1),
137 	INIT_CK(NULL,			"fclk",		&clk_f),
138 	INIT_CK(NULL,			"hclk",		&clk_h),
139 	INIT_CK(NULL,			"pclk",		&clk_p),
140 	INIT_CK(NULL,			"pll2",		&clk_pll2),
141 	INIT_CK("ep93xx-ohci",		NULL,		&clk_usb_host),
142 	INIT_CK("ep93xx-keypad",	NULL,		&clk_keypad),
143 	INIT_CK(NULL,			"pwm_clk",	&clk_pwm),
144 	INIT_CK(NULL,			"m2p0",		&clk_m2p0),
145 	INIT_CK(NULL,			"m2p1",		&clk_m2p1),
146 	INIT_CK(NULL,			"m2p2",		&clk_m2p2),
147 	INIT_CK(NULL,			"m2p3",		&clk_m2p3),
148 	INIT_CK(NULL,			"m2p4",		&clk_m2p4),
149 	INIT_CK(NULL,			"m2p5",		&clk_m2p5),
150 	INIT_CK(NULL,			"m2p6",		&clk_m2p6),
151 	INIT_CK(NULL,			"m2p7",		&clk_m2p7),
152 	INIT_CK(NULL,			"m2p8",		&clk_m2p8),
153 	INIT_CK(NULL,			"m2p9",		&clk_m2p9),
154 	INIT_CK(NULL,			"m2m0",		&clk_m2m0),
155 	INIT_CK(NULL,			"m2m1",		&clk_m2m1),
156 };
157 
158 
159 int clk_enable(struct clk *clk)
160 {
161 	if (!clk->users++ && clk->enable_reg) {
162 		u32 value;
163 
164 		value = __raw_readl(clk->enable_reg);
165 		value |= clk->enable_mask;
166 		if (clk->sw_locked)
167 			ep93xx_syscon_swlocked_write(value, clk->enable_reg);
168 		else
169 			__raw_writel(value, clk->enable_reg);
170 	}
171 
172 	return 0;
173 }
174 EXPORT_SYMBOL(clk_enable);
175 
176 void clk_disable(struct clk *clk)
177 {
178 	if (!--clk->users && clk->enable_reg) {
179 		u32 value;
180 
181 		value = __raw_readl(clk->enable_reg);
182 		value &= ~clk->enable_mask;
183 		if (clk->sw_locked)
184 			ep93xx_syscon_swlocked_write(value, clk->enable_reg);
185 		else
186 			__raw_writel(value, clk->enable_reg);
187 	}
188 }
189 EXPORT_SYMBOL(clk_disable);
190 
191 static unsigned long get_uart_rate(struct clk *clk)
192 {
193 	u32 value;
194 
195 	value = __raw_readl(EP93XX_SYSCON_PWRCNT);
196 	if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
197 		return EP93XX_EXT_CLK_RATE;
198 	else
199 		return EP93XX_EXT_CLK_RATE / 2;
200 }
201 
202 unsigned long clk_get_rate(struct clk *clk)
203 {
204 	if (clk->get_rate)
205 		return clk->get_rate(clk);
206 
207 	return clk->rate;
208 }
209 EXPORT_SYMBOL(clk_get_rate);
210 
211 static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
212 {
213 	u32 val;
214 	u32 div_bit;
215 
216 	val = __raw_readl(clk->enable_reg);
217 
218 	/*
219 	 * The Key Matrix and ADC clocks are configured using the same
220 	 * System Controller register.  The clock used will be either
221 	 * 1/4 or 1/16 the external clock rate depending on the
222 	 * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
223 	 * bit being set or cleared.
224 	 */
225 	div_bit = clk->enable_mask >> 15;
226 
227 	if (rate == EP93XX_KEYTCHCLK_DIV4)
228 		val |= div_bit;
229 	else if (rate == EP93XX_KEYTCHCLK_DIV16)
230 		val &= ~div_bit;
231 	else
232 		return -EINVAL;
233 
234 	ep93xx_syscon_swlocked_write(val, clk->enable_reg);
235 	clk->rate = rate;
236 	return 0;
237 }
238 
239 int clk_set_rate(struct clk *clk, unsigned long rate)
240 {
241 	if (clk->set_rate)
242 		return clk->set_rate(clk, rate);
243 
244 	return -EINVAL;
245 }
246 EXPORT_SYMBOL(clk_set_rate);
247 
248 
249 static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
250 static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
251 static char pclk_divisors[] = { 1, 2, 4, 8 };
252 
253 /*
254  * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
255  */
256 static unsigned long calc_pll_rate(u32 config_word)
257 {
258 	unsigned long long rate;
259 	int i;
260 
261 	rate = EP93XX_EXT_CLK_RATE;
262 	rate *= ((config_word >> 11) & 0x1f) + 1;		/* X1FBD */
263 	rate *= ((config_word >> 5) & 0x3f) + 1;		/* X2FBD */
264 	do_div(rate, (config_word & 0x1f) + 1);			/* X2IPD */
265 	for (i = 0; i < ((config_word >> 16) & 3); i++)		/* PS */
266 		rate >>= 1;
267 
268 	return (unsigned long)rate;
269 }
270 
271 static void __init ep93xx_dma_clock_init(void)
272 {
273 	clk_m2p0.rate = clk_h.rate;
274 	clk_m2p1.rate = clk_h.rate;
275 	clk_m2p2.rate = clk_h.rate;
276 	clk_m2p3.rate = clk_h.rate;
277 	clk_m2p4.rate = clk_h.rate;
278 	clk_m2p5.rate = clk_h.rate;
279 	clk_m2p6.rate = clk_h.rate;
280 	clk_m2p7.rate = clk_h.rate;
281 	clk_m2p8.rate = clk_h.rate;
282 	clk_m2p9.rate = clk_h.rate;
283 	clk_m2m0.rate = clk_h.rate;
284 	clk_m2m1.rate = clk_h.rate;
285 }
286 
287 static int __init ep93xx_clock_init(void)
288 {
289 	u32 value;
290 	int i;
291 
292 	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
293 	if (!(value & 0x00800000)) {			/* PLL1 bypassed?  */
294 		clk_pll1.rate = EP93XX_EXT_CLK_RATE;
295 	} else {
296 		clk_pll1.rate = calc_pll_rate(value);
297 	}
298 	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
299 	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
300 	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
301 	ep93xx_dma_clock_init();
302 
303 	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
304 	if (!(value & 0x00080000)) {			/* PLL2 bypassed?  */
305 		clk_pll2.rate = EP93XX_EXT_CLK_RATE;
306 	} else if (value & 0x00040000) {		/* PLL2 enabled?  */
307 		clk_pll2.rate = calc_pll_rate(value);
308 	} else {
309 		clk_pll2.rate = 0;
310 	}
311 	clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
312 
313 	printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
314 		clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
315 	printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
316 		clk_f.rate / 1000000, clk_h.rate / 1000000,
317 		clk_p.rate / 1000000);
318 
319 	for (i = 0; i < ARRAY_SIZE(clocks); i++)
320 		clkdev_add(&clocks[i]);
321 	return 0;
322 }
323 arch_initcall(ep93xx_clock_init);
324