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>
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
44 #define FRQCRA 0xe6150000
45 #define FRQCRB 0xe6150004
46 #define FRQCRC 0xe61500e0
47 #define PLLC01CR 0xe6150028
49 #define SUBCKCR 0xe6150080
50 #define USBCKCR 0xe615008c
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
63 /* Fixed 32 KHz root clock from EXTALR pin */
64 static struct clk extalr_clk = {
69 * 25MHz default rate for the EXTAL1 root input clock.
70 * If needed, reset this with clk_set_rate() from the platform code.
72 static struct clk extal1_clk = {
77 * 48MHz default rate for the EXTAL2 root input clock.
78 * If needed, reset this with clk_set_rate() from the platform code.
80 static struct clk extal2_clk = {
85 * 27MHz default rate for the DV_CLKI root input clock.
86 * If needed, reset this with clk_set_rate() from the platform code.
88 static struct clk dv_clk = {
92 static unsigned long div_recalc(struct clk *clk)
94 return clk->parent->rate / (int)(clk->priv);
97 static struct sh_clk_ops div_clk_ops = {
102 static struct clk extal1_div2_clk = {
105 .parent = &extal1_clk,
109 static struct clk extal1_div1024_clk = {
111 .priv = (void *)1024,
112 .parent = &extal1_clk,
115 /* extal1 / 2 / 1024 */
116 static struct clk extal1_div2048_clk = {
118 .priv = (void *)1024,
119 .parent = &extal1_div2_clk,
123 static struct clk extal2_div2_clk = {
126 .parent = &extal2_clk,
129 static struct sh_clk_ops followparent_clk_ops = {
130 .recalc = followparent_recalc,
134 static struct clk system_clk = {
135 .ops = &followparent_clk_ops,
138 static struct clk system_div2_clk = {
141 .parent = &system_clk,
145 static struct clk r_clk = {
146 .ops = &followparent_clk_ops,
150 static unsigned long pllc01_recalc(struct clk *clk)
152 unsigned long mult = 1;
154 if (__raw_readl(PLLC01CR) & (1 << 14))
155 mult = ((__raw_readl(clk->enable_reg) >> 24) & 0x7f) + 1;
157 return clk->parent->rate * mult;
160 static struct sh_clk_ops pllc01_clk_ops = {
161 .recalc = pllc01_recalc,
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,
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,
179 static struct clk pllc1_div2_clk = {
182 .parent = &pllc1_clk,
186 static struct clk *usb24s_parents[] = {
191 static int usb24s_enable(struct clk *clk)
193 __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
198 static void usb24s_disable(struct clk *clk)
200 __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
203 static int usb24s_set_parent(struct clk *clk, struct clk *parent)
208 if (!clk->parent_table || !clk->parent_num)
211 /* Search the parent */
212 for (i = 0; i < clk->parent_num; i++)
213 if (clk->parent_table[i] == parent)
216 if (i == clk->parent_num)
219 ret = clk_reparent(clk, parent);
223 val = __raw_readl(USBCKCR);
226 __raw_writel(val, USBCKCR);
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,
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,
245 static unsigned long usb24_recalc(struct clk *clk)
247 return clk->parent->rate /
248 ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
251 static int usb24_set_rate(struct clk *clk, unsigned long rate)
255 /* closer to which ? parent->rate or parent->rate/2 */
256 val = __raw_readl(USBCKCR);
258 val |= (rate > (clk->parent->rate / 4) * 3) << 6;
259 __raw_writel(val, USBCKCR);
264 static struct sh_clk_ops usb24_clk_ops = {
265 .recalc = usb24_recalc,
266 .set_rate = usb24_set_rate,
269 static struct clk usb24_clk = {
270 .ops = &usb24_clk_ops,
271 .parent = &usb24s_clk,
274 struct clk *main_clks[] = {
293 static void div4_kick(struct clk *clk)
297 /* set KICK bit in FRQCRB to update hardware setting */
298 value = __raw_readl(FRQCRB);
300 __raw_writel(value, FRQCRB);
303 static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
304 24, 32, 36, 48, 0, 72, 96, 0 };
306 static struct clk_div_mult_table div4_div_mult_table = {
307 .divisors = divisors,
308 .nr_divisors = ARRAY_SIZE(divisors),
311 static struct clk_div4_table div4_table = {
312 .div_mult_table = &div4_div_mult_table,
317 DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
318 DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
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),
341 static struct clk div6_clks[DIV6_NR] = {
342 [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
347 MSTP116, MSTP111, MSTP100, MSTP117,
351 MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
353 MSTP329, MSTP328, MSTP323, MSTP320,
354 MSTP314, MSTP313, MSTP312,
357 MSTP416, MSTP415, MSTP407, MSTP406,
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 */
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 */
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 */
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 */
394 static struct clk_lookup lookups[] = {
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),
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]),
425 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
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]),
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]),
442 CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
443 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
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]),
454 CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
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),
464 void __init r8a7740_clock_init(u8 md_ck)
468 /* detect system clock parent */
470 system_clk.parent = &extal1_div2_clk;
472 system_clk.parent = &extal1_clk;
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;
480 r_clk.parent = &extal1_div1024_clk;
484 r_clk.parent = &extalr_clk;
488 for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
489 ret = clk_register(main_clks[k]);
492 ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
495 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
498 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
500 clkdev_add_table(lookups, ARRAY_SIZE(lookups));
505 panic("failed to setup r8a7740 clocks\n");