serial: pxa: fine-tune clk useage
[linux/fpc-iii.git] / arch / arm / mach-shmobile / clock-r8a7740.c
blobeac49d59782f3a66df3de2994f2d95e8a66b2c10
1 /*
2 * R8A7740 processor support
4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
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
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.
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
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>
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
43 /* CPG registers */
44 #define FRQCRA IOMEM(0xe6150000)
45 #define FRQCRB IOMEM(0xe6150004)
46 #define VCLKCR1 IOMEM(0xE6150008)
47 #define VCLKCR2 IOMEM(0xE615000c)
48 #define FRQCRC IOMEM(0xe61500e0)
49 #define FSIACKCR IOMEM(0xe6150018)
50 #define PLLC01CR IOMEM(0xe6150028)
52 #define SUBCKCR IOMEM(0xe6150080)
53 #define USBCKCR IOMEM(0xe615008c)
55 #define MSTPSR0 IOMEM(0xe6150030)
56 #define MSTPSR1 IOMEM(0xe6150038)
57 #define MSTPSR2 IOMEM(0xe6150040)
58 #define MSTPSR3 IOMEM(0xe6150048)
59 #define MSTPSR4 IOMEM(0xe615004c)
60 #define FSIBCKCR IOMEM(0xe6150090)
61 #define HDMICKCR IOMEM(0xe6150094)
62 #define SMSTPCR0 IOMEM(0xe6150130)
63 #define SMSTPCR1 IOMEM(0xe6150134)
64 #define SMSTPCR2 IOMEM(0xe6150138)
65 #define SMSTPCR3 IOMEM(0xe615013c)
66 #define SMSTPCR4 IOMEM(0xe6150140)
68 #define FSIDIVA IOMEM(0xFE1F8000)
69 #define FSIDIVB IOMEM(0xFE1F8008)
71 /* Fixed 32 KHz root clock from EXTALR pin */
72 static struct clk extalr_clk = {
73 .rate = 32768,
77 * 25MHz default rate for the EXTAL1 root input clock.
78 * If needed, reset this with clk_set_rate() from the platform code.
80 static struct clk extal1_clk = {
81 .rate = 25000000,
85 * 48MHz default rate for the EXTAL2 root input clock.
86 * If needed, reset this with clk_set_rate() from the platform code.
88 static struct clk extal2_clk = {
89 .rate = 48000000,
93 * 27MHz default rate for the DV_CLKI root input clock.
94 * If needed, reset this with clk_set_rate() from the platform code.
96 static struct clk dv_clk = {
97 .rate = 27000000,
100 static unsigned long div_recalc(struct clk *clk)
102 return clk->parent->rate / (int)(clk->priv);
105 static struct sh_clk_ops div_clk_ops = {
106 .recalc = div_recalc,
109 /* extal1 / 2 */
110 static struct clk extal1_div2_clk = {
111 .ops = &div_clk_ops,
112 .priv = (void *)2,
113 .parent = &extal1_clk,
116 /* extal1 / 1024 */
117 static struct clk extal1_div1024_clk = {
118 .ops = &div_clk_ops,
119 .priv = (void *)1024,
120 .parent = &extal1_clk,
123 /* extal1 / 2 / 1024 */
124 static struct clk extal1_div2048_clk = {
125 .ops = &div_clk_ops,
126 .priv = (void *)1024,
127 .parent = &extal1_div2_clk,
130 /* extal2 / 2 */
131 static struct clk extal2_div2_clk = {
132 .ops = &div_clk_ops,
133 .priv = (void *)2,
134 .parent = &extal2_clk,
137 static struct sh_clk_ops followparent_clk_ops = {
138 .recalc = followparent_recalc,
141 /* Main clock */
142 static struct clk system_clk = {
143 .ops = &followparent_clk_ops,
146 static struct clk system_div2_clk = {
147 .ops = &div_clk_ops,
148 .priv = (void *)2,
149 .parent = &system_clk,
152 /* r_clk */
153 static struct clk r_clk = {
154 .ops = &followparent_clk_ops,
157 /* PLLC0/PLLC1 */
158 static unsigned long pllc01_recalc(struct clk *clk)
160 unsigned long mult = 1;
162 if (__raw_readl(PLLC01CR) & (1 << 14))
163 mult = ((__raw_readl(clk->enable_reg) >> 24) & 0x7f) + 1;
165 return clk->parent->rate * mult;
168 static struct sh_clk_ops pllc01_clk_ops = {
169 .recalc = pllc01_recalc,
172 static struct clk pllc0_clk = {
173 .ops = &pllc01_clk_ops,
174 .flags = CLK_ENABLE_ON_INIT,
175 .parent = &system_clk,
176 .enable_reg = (void __iomem *)FRQCRC,
179 static struct clk pllc1_clk = {
180 .ops = &pllc01_clk_ops,
181 .flags = CLK_ENABLE_ON_INIT,
182 .parent = &system_div2_clk,
183 .enable_reg = (void __iomem *)FRQCRA,
186 /* PLLC1 / 2 */
187 static struct clk pllc1_div2_clk = {
188 .ops = &div_clk_ops,
189 .priv = (void *)2,
190 .parent = &pllc1_clk,
193 /* USB clock */
195 * USBCKCR is controlling usb24 clock
196 * bit[7] : parent clock
197 * bit[6] : clock divide rate
198 * And this bit[7] is used as a "usb24s" from other devices.
199 * (Video clock / Sub clock / SPU clock)
200 * You can controll this clock as a below.
202 * struct clk *usb24 = clk_get(dev, "usb24");
203 * struct clk *usb24s = clk_get(NULL, "usb24s");
204 * struct clk *system = clk_get(NULL, "system_clk");
205 * int rate = clk_get_rate(system);
207 * clk_set_parent(usb24s, system); // for bit[7]
208 * clk_set_rate(usb24, rate / 2); // for bit[6]
210 static struct clk *usb24s_parents[] = {
211 [0] = &system_clk,
212 [1] = &extal2_clk
215 static int usb24s_enable(struct clk *clk)
217 __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
219 return 0;
222 static void usb24s_disable(struct clk *clk)
224 __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
227 static int usb24s_set_parent(struct clk *clk, struct clk *parent)
229 int i, ret;
230 u32 val;
232 if (!clk->parent_table || !clk->parent_num)
233 return -EINVAL;
235 /* Search the parent */
236 for (i = 0; i < clk->parent_num; i++)
237 if (clk->parent_table[i] == parent)
238 break;
240 if (i == clk->parent_num)
241 return -ENODEV;
243 ret = clk_reparent(clk, parent);
244 if (ret < 0)
245 return ret;
247 val = __raw_readl(USBCKCR);
248 val &= ~(1 << 7);
249 val |= i << 7;
250 __raw_writel(val, USBCKCR);
252 return 0;
255 static struct sh_clk_ops usb24s_clk_ops = {
256 .recalc = followparent_recalc,
257 .enable = usb24s_enable,
258 .disable = usb24s_disable,
259 .set_parent = usb24s_set_parent,
262 static struct clk usb24s_clk = {
263 .ops = &usb24s_clk_ops,
264 .parent_table = usb24s_parents,
265 .parent_num = ARRAY_SIZE(usb24s_parents),
266 .parent = &system_clk,
269 static unsigned long usb24_recalc(struct clk *clk)
271 return clk->parent->rate /
272 ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
275 static int usb24_set_rate(struct clk *clk, unsigned long rate)
277 u32 val;
279 /* closer to which ? parent->rate or parent->rate/2 */
280 val = __raw_readl(USBCKCR);
281 val &= ~(1 << 6);
282 val |= (rate > (clk->parent->rate / 4) * 3) << 6;
283 __raw_writel(val, USBCKCR);
285 return 0;
288 static struct sh_clk_ops usb24_clk_ops = {
289 .recalc = usb24_recalc,
290 .set_rate = usb24_set_rate,
293 static struct clk usb24_clk = {
294 .ops = &usb24_clk_ops,
295 .parent = &usb24s_clk,
298 /* External FSIACK/FSIBCK clock */
299 static struct clk fsiack_clk = {
302 static struct clk fsibck_clk = {
305 struct clk *main_clks[] = {
306 &extalr_clk,
307 &extal1_clk,
308 &extal2_clk,
309 &extal1_div2_clk,
310 &extal1_div1024_clk,
311 &extal1_div2048_clk,
312 &extal2_div2_clk,
313 &dv_clk,
314 &system_clk,
315 &system_div2_clk,
316 &r_clk,
317 &pllc0_clk,
318 &pllc1_clk,
319 &pllc1_div2_clk,
320 &usb24s_clk,
321 &usb24_clk,
322 &fsiack_clk,
323 &fsibck_clk,
326 static void div4_kick(struct clk *clk)
328 unsigned long value;
330 /* set KICK bit in FRQCRB to update hardware setting */
331 value = __raw_readl(FRQCRB);
332 value |= (1 << 31);
333 __raw_writel(value, FRQCRB);
336 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
337 24, 32, 36, 48, 0, 72, 96, 0 };
339 static struct clk_div_mult_table div4_div_mult_table = {
340 .divisors = divisors,
341 .nr_divisors = ARRAY_SIZE(divisors),
344 static struct clk_div4_table div4_table = {
345 .div_mult_table = &div4_div_mult_table,
346 .kick = div4_kick,
349 /* DIV6 reparent */
350 enum {
351 DIV6_HDMI,
352 DIV6_VCLK1, DIV6_VCLK2,
353 DIV6_FSIA, DIV6_FSIB,
354 DIV6_REPARENT_NR,
357 static struct clk *hdmi_parent[] = {
358 [0] = &pllc1_div2_clk,
359 [1] = &system_clk,
360 [2] = &dv_clk
363 static struct clk *vclk_parents[8] = {
364 [0] = &pllc1_div2_clk,
365 [2] = &dv_clk,
366 [3] = &usb24s_clk,
367 [4] = &extal1_div2_clk,
368 [5] = &extalr_clk,
371 static struct clk *fsia_parents[] = {
372 [0] = &pllc1_div2_clk,
373 [1] = &fsiack_clk, /* external clock */
376 static struct clk *fsib_parents[] = {
377 [0] = &pllc1_div2_clk,
378 [1] = &fsibck_clk, /* external clock */
381 static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
382 [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
383 hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
384 [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
385 vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
386 [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
387 vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
388 [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
389 fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
390 [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
391 fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
394 /* HDMI1/2 clock */
395 static unsigned long hdmi12_recalc(struct clk *clk)
397 u32 val = __raw_readl(HDMICKCR);
398 int shift = (int)clk->priv;
400 val >>= shift;
401 val &= 0x3;
403 return clk->parent->rate / (1 << val);
406 static int hdmi12_set_rate(struct clk *clk, unsigned long rate)
408 u32 val, mask;
409 int i, shift;
411 for (i = 0; i < 3; i++)
412 if (rate == clk->parent->rate / (1 << i))
413 goto find;
414 return -ENODEV;
416 find:
417 shift = (int)clk->priv;
419 val = __raw_readl(HDMICKCR);
420 mask = ~(0x3 << shift);
421 val = (val & mask) | i << shift;
422 __raw_writel(val, HDMICKCR);
424 return 0;
427 static struct sh_clk_ops hdmi12_clk_ops = {
428 .recalc = hdmi12_recalc,
429 .set_rate = hdmi12_set_rate,
432 static struct clk hdmi1_clk = {
433 .ops = &hdmi12_clk_ops,
434 .priv = (void *)9,
435 .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */
438 static struct clk hdmi2_clk = {
439 .ops = &hdmi12_clk_ops,
440 .priv = (void *)11,
441 .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */
444 static struct clk *late_main_clks[] = {
445 &hdmi1_clk,
446 &hdmi2_clk,
449 /* FSI DIV */
450 enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR };
452 static struct clk fsidivs[] = {
453 [FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]),
454 [FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]),
457 /* MSTP */
458 enum {
459 DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
460 DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
461 DIV4_NR
464 struct clk div4_clks[DIV4_NR] = {
465 [DIV4_I] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
466 [DIV4_ZG] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
467 [DIV4_B] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT),
468 [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
469 [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0),
470 [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
471 [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
472 [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
473 [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0),
474 [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0),
475 [DIV4_CP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 0, 0x6fff, 0),
478 enum {
479 DIV6_SUB,
480 DIV6_NR
483 static struct clk div6_clks[DIV6_NR] = {
484 [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
487 enum {
488 MSTP128, MSTP127, MSTP125,
489 MSTP116, MSTP111, MSTP100, MSTP117,
491 MSTP230,
492 MSTP222,
493 MSTP218, MSTP217, MSTP216, MSTP214,
494 MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
496 MSTP329, MSTP328, MSTP323, MSTP320,
497 MSTP314, MSTP313, MSTP312,
498 MSTP309,
500 MSTP416, MSTP415, MSTP407, MSTP406,
502 MSTP_NR
505 static struct clk mstp_clks[MSTP_NR] = {
506 [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */
507 [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */
508 [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
509 [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
510 [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
511 [MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 11, 0), /* TMU1 */
512 [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
514 [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
515 [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
516 [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */
517 [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */
518 [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */
519 [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */
520 [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
521 [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
522 [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
523 [MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
524 [MSTP202] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
525 [MSTP201] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
526 [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
528 [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
529 [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
530 [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
531 [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
532 [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
533 [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
534 [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
535 [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */
537 [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
538 [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
539 [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
540 [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
543 static struct clk_lookup lookups[] = {
544 /* main clocks */
545 CLKDEV_CON_ID("extalr", &extalr_clk),
546 CLKDEV_CON_ID("extal1", &extal1_clk),
547 CLKDEV_CON_ID("extal2", &extal2_clk),
548 CLKDEV_CON_ID("extal1_div2", &extal1_div2_clk),
549 CLKDEV_CON_ID("extal1_div1024", &extal1_div1024_clk),
550 CLKDEV_CON_ID("extal1_div2048", &extal1_div2048_clk),
551 CLKDEV_CON_ID("extal2_div2", &extal2_div2_clk),
552 CLKDEV_CON_ID("dv_clk", &dv_clk),
553 CLKDEV_CON_ID("system_clk", &system_clk),
554 CLKDEV_CON_ID("system_div2_clk", &system_div2_clk),
555 CLKDEV_CON_ID("r_clk", &r_clk),
556 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
557 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
558 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
559 CLKDEV_CON_ID("usb24s", &usb24s_clk),
560 CLKDEV_CON_ID("hdmi1", &hdmi1_clk),
561 CLKDEV_CON_ID("hdmi2", &hdmi2_clk),
562 CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]),
563 CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]),
564 CLKDEV_CON_ID("fsiack", &fsiack_clk),
565 CLKDEV_CON_ID("fsibck", &fsibck_clk),
567 /* DIV4 clocks */
568 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
569 CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
570 CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
571 CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
572 CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
573 CLKDEV_CON_ID("hpp_clk", &div4_clks[DIV4_HPP]),
574 CLKDEV_CON_ID("s_clk", &div4_clks[DIV4_S]),
575 CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
576 CLKDEV_CON_ID("m3_clk", &div4_clks[DIV4_M3]),
577 CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
579 /* DIV6 clocks */
580 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
582 /* MSTP32 clocks */
583 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]),
584 CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP111]),
585 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]),
586 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]),
587 CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]),
588 CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]),
589 CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]),
591 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]),
592 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]),
593 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]),
594 CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
595 CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
596 CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
597 CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
598 CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]),
599 CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]),
600 CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]),
601 CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
602 CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
603 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
605 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
606 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
607 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
608 CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
609 CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
610 CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
611 CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
612 CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]),
614 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
616 /* ICK */
617 CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
618 CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
619 CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
620 CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
621 CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
622 CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
624 CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
625 CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
626 CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
627 CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
628 CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
629 CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
632 void __init r8a7740_clock_init(u8 md_ck)
634 int k, ret = 0;
636 /* detect system clock parent */
637 if (md_ck & MD_CK1)
638 system_clk.parent = &extal1_div2_clk;
639 else
640 system_clk.parent = &extal1_clk;
642 /* detect RCLK parent */
643 switch (md_ck & (MD_CK2 | MD_CK1)) {
644 case MD_CK2 | MD_CK1:
645 r_clk.parent = &extal1_div2048_clk;
646 break;
647 case MD_CK2:
648 r_clk.parent = &extal1_div1024_clk;
649 break;
650 case MD_CK1:
651 default:
652 r_clk.parent = &extalr_clk;
653 break;
656 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
657 ret = clk_register(main_clks[k]);
659 if (!ret)
660 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
662 if (!ret)
663 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
665 if (!ret)
666 ret = sh_clk_div6_reparent_register(div6_reparent_clks,
667 DIV6_REPARENT_NR);
669 if (!ret)
670 ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
672 for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
673 ret = clk_register(late_main_clks[k]);
675 if (!ret)
676 ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR);
678 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
680 if (!ret)
681 shmobile_clk_init();
682 else
683 panic("failed to setup r8a7740 clocks\n");