26eea5f2105420116bb5332633d4a1385ed949d7
[deliverable/linux.git] / arch / arm / mach-shmobile / clock-r8a7740.c
1 /*
2 * R8A7740 processor support
3 *
4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
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
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <linux/init.h>
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/sh_clk.h>
24 #include <linux/clkdev.h>
25 #include <mach/common.h>
26 #include <mach/r8a7740.h>
27
28 /*
29 * | MDx | XTAL1/EXTAL1 | System | EXTALR |
30 * Clock |-------+-----------------+ clock | 32.768 | RCLK
31 * Mode | 2/1/0 | src MHz | source | KHz | source
32 * -------+-------+-----------------+-----------+--------+----------
33 * 0 | 0 0 0 | External 20~50 | XTAL1 | O | EXTALR
34 * 1 | 0 0 1 | Crystal 20~30 | XTAL1 | O | EXTALR
35 * 2 | 0 1 0 | External 40~50 | XTAL1 / 2 | O | EXTALR
36 * 3 | 0 1 1 | Crystal 40~50 | XTAL1 / 2 | O | EXTALR
37 * 4 | 1 0 0 | External 20~50 | XTAL1 | x | XTAL1 / 1024
38 * 5 | 1 0 1 | Crystal 20~30 | XTAL1 | x | XTAL1 / 1024
39 * 6 | 1 1 0 | External 40~50 | XTAL1 / 2 | x | XTAL1 / 2048
40 * 7 | 1 1 1 | Crystal 40~50 | XTAL1 / 2 | x | XTAL1 / 2048
41 */
42
43 /* CPG registers */
44 #define FRQCRA 0xe6150000
45 #define FRQCRB 0xe6150004
46 #define FRQCRC 0xe61500e0
47 #define PLLC01CR 0xe6150028
48
49 #define SUBCKCR 0xe6150080
50 #define USBCKCR 0xe615008c
51
52 #define MSTPSR0 0xe6150030
53 #define MSTPSR1 0xe6150038
54 #define MSTPSR2 0xe6150040
55 #define MSTPSR3 0xe6150048
56 #define MSTPSR4 0xe615004c
57 #define SMSTPCR0 0xe6150130
58 #define SMSTPCR1 0xe6150134
59 #define SMSTPCR2 0xe6150138
60 #define SMSTPCR3 0xe615013c
61 #define SMSTPCR4 0xe6150140
62
63 /* Fixed 32 KHz root clock from EXTALR pin */
64 static struct clk extalr_clk = {
65 .rate = 32768,
66 };
67
68 /*
69 * 25MHz default rate for the EXTAL1 root input clock.
70 * If needed, reset this with clk_set_rate() from the platform code.
71 */
72 static struct clk extal1_clk = {
73 .rate = 25000000,
74 };
75
76 /*
77 * 48MHz default rate for the EXTAL2 root input clock.
78 * If needed, reset this with clk_set_rate() from the platform code.
79 */
80 static struct clk extal2_clk = {
81 .rate = 48000000,
82 };
83
84 /*
85 * 27MHz default rate for the DV_CLKI root input clock.
86 * If needed, reset this with clk_set_rate() from the platform code.
87 */
88 static struct clk dv_clk = {
89 .rate = 27000000,
90 };
91
92 static unsigned long div_recalc(struct clk *clk)
93 {
94 return clk->parent->rate / (int)(clk->priv);
95 }
96
97 static struct sh_clk_ops div_clk_ops = {
98 .recalc = div_recalc,
99 };
100
101 /* extal1 / 2 */
102 static struct clk extal1_div2_clk = {
103 .ops = &div_clk_ops,
104 .priv = (void *)2,
105 .parent = &extal1_clk,
106 };
107
108 /* extal1 / 1024 */
109 static struct clk extal1_div1024_clk = {
110 .ops = &div_clk_ops,
111 .priv = (void *)1024,
112 .parent = &extal1_clk,
113 };
114
115 /* extal1 / 2 / 1024 */
116 static struct clk extal1_div2048_clk = {
117 .ops = &div_clk_ops,
118 .priv = (void *)1024,
119 .parent = &extal1_div2_clk,
120 };
121
122 /* extal2 / 2 */
123 static struct clk extal2_div2_clk = {
124 .ops = &div_clk_ops,
125 .priv = (void *)2,
126 .parent = &extal2_clk,
127 };
128
129 static struct sh_clk_ops followparent_clk_ops = {
130 .recalc = followparent_recalc,
131 };
132
133 /* Main clock */
134 static struct clk system_clk = {
135 .ops = &followparent_clk_ops,
136 };
137
138 static struct clk system_div2_clk = {
139 .ops = &div_clk_ops,
140 .priv = (void *)2,
141 .parent = &system_clk,
142 };
143
144 /* r_clk */
145 static struct clk r_clk = {
146 .ops = &followparent_clk_ops,
147 };
148
149 /* PLLC0/PLLC1 */
150 static unsigned long pllc01_recalc(struct clk *clk)
151 {
152 unsigned long mult = 1;
153
154 if (__raw_readl(PLLC01CR) & (1 << 14))
155 mult = ((__raw_readl(clk->enable_reg) >> 24) & 0x7f) + 1;
156
157 return clk->parent->rate * mult;
158 }
159
160 static struct sh_clk_ops pllc01_clk_ops = {
161 .recalc = pllc01_recalc,
162 };
163
164 static struct clk pllc0_clk = {
165 .ops = &pllc01_clk_ops,
166 .flags = CLK_ENABLE_ON_INIT,
167 .parent = &system_clk,
168 .enable_reg = (void __iomem *)FRQCRC,
169 };
170
171 static struct clk pllc1_clk = {
172 .ops = &pllc01_clk_ops,
173 .flags = CLK_ENABLE_ON_INIT,
174 .parent = &system_div2_clk,
175 .enable_reg = (void __iomem *)FRQCRA,
176 };
177
178 /* PLLC1 / 2 */
179 static struct clk pllc1_div2_clk = {
180 .ops = &div_clk_ops,
181 .priv = (void *)2,
182 .parent = &pllc1_clk,
183 };
184
185 /* USB clock */
186 static struct clk *usb24s_parents[] = {
187 [0] = &system_clk,
188 [1] = &extal2_clk
189 };
190
191 static int usb24s_enable(struct clk *clk)
192 {
193 __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
194
195 return 0;
196 }
197
198 static void usb24s_disable(struct clk *clk)
199 {
200 __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
201 }
202
203 static int usb24s_set_parent(struct clk *clk, struct clk *parent)
204 {
205 int i, ret;
206 u32 val;
207
208 if (!clk->parent_table || !clk->parent_num)
209 return -EINVAL;
210
211 /* Search the parent */
212 for (i = 0; i < clk->parent_num; i++)
213 if (clk->parent_table[i] == parent)
214 break;
215
216 if (i == clk->parent_num)
217 return -ENODEV;
218
219 ret = clk_reparent(clk, parent);
220 if (ret < 0)
221 return ret;
222
223 val = __raw_readl(USBCKCR);
224 val &= ~(1 << 7);
225 val |= i << 7;
226 __raw_writel(val, USBCKCR);
227
228 return 0;
229 }
230
231 static struct sh_clk_ops usb24s_clk_ops = {
232 .recalc = followparent_recalc,
233 .enable = usb24s_enable,
234 .disable = usb24s_disable,
235 .set_parent = usb24s_set_parent,
236 };
237
238 static struct clk usb24s_clk = {
239 .ops = &usb24s_clk_ops,
240 .parent_table = usb24s_parents,
241 .parent_num = ARRAY_SIZE(usb24s_parents),
242 .parent = &system_clk,
243 };
244
245 static unsigned long usb24_recalc(struct clk *clk)
246 {
247 return clk->parent->rate /
248 ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
249 };
250
251 static int usb24_set_rate(struct clk *clk, unsigned long rate)
252 {
253 u32 val;
254
255 /* closer to which ? parent->rate or parent->rate/2 */
256 val = __raw_readl(USBCKCR);
257 val &= ~(1 << 6);
258 val |= (rate > (clk->parent->rate / 4) * 3) << 6;
259 __raw_writel(val, USBCKCR);
260
261 return 0;
262 }
263
264 static struct sh_clk_ops usb24_clk_ops = {
265 .recalc = usb24_recalc,
266 .set_rate = usb24_set_rate,
267 };
268
269 static struct clk usb24_clk = {
270 .ops = &usb24_clk_ops,
271 .parent = &usb24s_clk,
272 };
273
274 struct clk *main_clks[] = {
275 &extalr_clk,
276 &extal1_clk,
277 &extal2_clk,
278 &extal1_div2_clk,
279 &extal1_div1024_clk,
280 &extal1_div2048_clk,
281 &extal2_div2_clk,
282 &dv_clk,
283 &system_clk,
284 &system_div2_clk,
285 &r_clk,
286 &pllc0_clk,
287 &pllc1_clk,
288 &pllc1_div2_clk,
289 &usb24s_clk,
290 &usb24_clk,
291 };
292
293 static void div4_kick(struct clk *clk)
294 {
295 unsigned long value;
296
297 /* set KICK bit in FRQCRB to update hardware setting */
298 value = __raw_readl(FRQCRB);
299 value |= (1 << 31);
300 __raw_writel(value, FRQCRB);
301 }
302
303 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
304 24, 32, 36, 48, 0, 72, 96, 0 };
305
306 static struct clk_div_mult_table div4_div_mult_table = {
307 .divisors = divisors,
308 .nr_divisors = ARRAY_SIZE(divisors),
309 };
310
311 static struct clk_div4_table div4_table = {
312 .div_mult_table = &div4_div_mult_table,
313 .kick = div4_kick,
314 };
315
316 enum {
317 DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
318 DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
319 DIV4_NR
320 };
321
322 struct clk div4_clks[DIV4_NR] = {
323 [DIV4_I] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
324 [DIV4_ZG] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
325 [DIV4_B] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT),
326 [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
327 [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0),
328 [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
329 [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
330 [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
331 [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0),
332 [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0),
333 [DIV4_CP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 0, 0x6fff, 0),
334 };
335
336 enum {
337 DIV6_SUB,
338 DIV6_NR
339 };
340
341 static struct clk div6_clks[DIV6_NR] = {
342 [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
343 };
344
345 enum {
346 MSTP125,
347 MSTP116, MSTP111, MSTP100, MSTP117,
348
349 MSTP230,
350 MSTP222,
351 MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
352
353 MSTP329, MSTP328, MSTP323, MSTP320,
354 MSTP314, MSTP313, MSTP312,
355 MSTP309,
356
357 MSTP416, MSTP415, MSTP407, MSTP406,
358
359 MSTP_NR
360 };
361
362 static struct clk mstp_clks[MSTP_NR] = {
363 [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
364 [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
365 [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
366 [MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 11, 0), /* TMU1 */
367 [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
368
369 [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
370 [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
371 [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
372 [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
373 [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
374 [MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
375 [MSTP202] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
376 [MSTP201] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
377 [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
378
379 [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
380 [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
381 [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
382 [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
383 [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
384 [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
385 [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
386 [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */
387
388 [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
389 [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
390 [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
391 [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
392 };
393
394 static struct clk_lookup lookups[] = {
395 /* main clocks */
396 CLKDEV_CON_ID("extalr", &extalr_clk),
397 CLKDEV_CON_ID("extal1", &extal1_clk),
398 CLKDEV_CON_ID("extal2", &extal2_clk),
399 CLKDEV_CON_ID("extal1_div2", &extal1_div2_clk),
400 CLKDEV_CON_ID("extal1_div1024", &extal1_div1024_clk),
401 CLKDEV_CON_ID("extal1_div2048", &extal1_div2048_clk),
402 CLKDEV_CON_ID("extal2_div2", &extal2_div2_clk),
403 CLKDEV_CON_ID("dv_clk", &dv_clk),
404 CLKDEV_CON_ID("system_clk", &system_clk),
405 CLKDEV_CON_ID("system_div2_clk", &system_div2_clk),
406 CLKDEV_CON_ID("r_clk", &r_clk),
407 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
408 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
409 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
410 CLKDEV_CON_ID("usb24s", &usb24s_clk),
411
412 /* DIV4 clocks */
413 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
414 CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
415 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
416 CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
417 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
418 CLKDEV_CON_ID("hpp_clk", &div4_clks[DIV4_HPP]),
419 CLKDEV_CON_ID("s_clk", &div4_clks[DIV4_S]),
420 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
421 CLKDEV_CON_ID("m3_clk", &div4_clks[DIV4_M3]),
422 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
423
424 /* DIV6 clocks */
425 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
426
427 /* MSTP32 clocks */
428 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]),
429 CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP111]),
430 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]),
431 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]),
432 CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]),
433
434 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]),
435 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]),
436 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]),
437 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
438 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
439 CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
440 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
441
442 CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
443 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
444
445 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
446 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
447 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
448 CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
449 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
450 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
451 CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
452 CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]),
453
454 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
455
456 /* ICK */
457 CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
458 CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
459 CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
460 CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
461 CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
462 };
463
464 void __init r8a7740_clock_init(u8 md_ck)
465 {
466 int k, ret = 0;
467
468 /* detect system clock parent */
469 if (md_ck & MD_CK1)
470 system_clk.parent = &extal1_div2_clk;
471 else
472 system_clk.parent = &extal1_clk;
473
474 /* detect RCLK parent */
475 switch (md_ck & (MD_CK2 | MD_CK1)) {
476 case MD_CK2 | MD_CK1:
477 r_clk.parent = &extal1_div2048_clk;
478 break;
479 case MD_CK2:
480 r_clk.parent = &extal1_div1024_clk;
481 break;
482 case MD_CK1:
483 default:
484 r_clk.parent = &extalr_clk;
485 break;
486 }
487
488 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
489 ret = clk_register(main_clks[k]);
490
491 if (!ret)
492 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
493
494 if (!ret)
495 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
496
497 if (!ret)
498 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
499
500 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
501
502 if (!ret)
503 shmobile_clk_init();
504 else
505 panic("failed to setup r8a7740 clocks\n");
506 }
This page took 0.041512 seconds and 4 git commands to generate.