diff options
Diffstat (limited to 'arch/arm/mach-shmobile/clock-sh7372.c')
-rw-r--r-- | arch/arm/mach-shmobile/clock-sh7372.c | 115 |
1 files changed, 99 insertions, 16 deletions
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 8565aefa21fd..3aa026069435 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c | |||
@@ -50,6 +50,9 @@ | |||
50 | #define SMSTPCR3 0xe615013c | 50 | #define SMSTPCR3 0xe615013c |
51 | #define SMSTPCR4 0xe6150140 | 51 | #define SMSTPCR4 0xe6150140 |
52 | 52 | ||
53 | #define FSIDIVA 0xFE1F8000 | ||
54 | #define FSIDIVB 0xFE1F8008 | ||
55 | |||
53 | /* Platforms must set frequency on their DV_CLKI pin */ | 56 | /* Platforms must set frequency on their DV_CLKI pin */ |
54 | struct clk sh7372_dv_clki_clk = { | 57 | struct clk sh7372_dv_clki_clk = { |
55 | }; | 58 | }; |
@@ -217,8 +220,7 @@ static void pllc2_disable(struct clk *clk) | |||
217 | __raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR); | 220 | __raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR); |
218 | } | 221 | } |
219 | 222 | ||
220 | static int pllc2_set_rate(struct clk *clk, | 223 | static int pllc2_set_rate(struct clk *clk, unsigned long rate) |
221 | unsigned long rate, int algo_id) | ||
222 | { | 224 | { |
223 | unsigned long value; | 225 | unsigned long value; |
224 | int idx; | 226 | int idx; |
@@ -227,21 +229,13 @@ static int pllc2_set_rate(struct clk *clk, | |||
227 | if (idx < 0) | 229 | if (idx < 0) |
228 | return idx; | 230 | return idx; |
229 | 231 | ||
230 | if (rate == clk->parent->rate) { | 232 | if (rate == clk->parent->rate) |
231 | pllc2_disable(clk); | 233 | return -EINVAL; |
232 | return 0; | ||
233 | } | ||
234 | 234 | ||
235 | value = __raw_readl(PLLC2CR) & ~(0x3f << 24); | 235 | value = __raw_readl(PLLC2CR) & ~(0x3f << 24); |
236 | 236 | ||
237 | if (value & 0x80000000) | ||
238 | pllc2_disable(clk); | ||
239 | |||
240 | __raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR); | 237 | __raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR); |
241 | 238 | ||
242 | if (value & 0x80000000) | ||
243 | return pllc2_enable(clk); | ||
244 | |||
245 | return 0; | 239 | return 0; |
246 | } | 240 | } |
247 | 241 | ||
@@ -288,6 +282,7 @@ struct clk sh7372_pllc2_clk = { | |||
288 | .ops = &pllc2_clk_ops, | 282 | .ops = &pllc2_clk_ops, |
289 | .parent = &extal1_div2_clk, | 283 | .parent = &extal1_div2_clk, |
290 | .freq_table = pllc2_freq_table, | 284 | .freq_table = pllc2_freq_table, |
285 | .nr_freqs = ARRAY_SIZE(pllc2_freq_table) - 1, | ||
291 | .parent_table = pllc2_parent, | 286 | .parent_table = pllc2_parent, |
292 | .parent_num = ARRAY_SIZE(pllc2_parent), | 287 | .parent_num = ARRAY_SIZE(pllc2_parent), |
293 | }; | 288 | }; |
@@ -417,6 +412,93 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { | |||
417 | fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), | 412 | fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), |
418 | }; | 413 | }; |
419 | 414 | ||
415 | /* FSI DIV */ | ||
416 | static unsigned long fsidiv_recalc(struct clk *clk) | ||
417 | { | ||
418 | unsigned long value; | ||
419 | |||
420 | value = __raw_readl(clk->mapping->base); | ||
421 | |||
422 | if ((value & 0x3) != 0x3) | ||
423 | return 0; | ||
424 | |||
425 | value >>= 16; | ||
426 | if (value < 2) | ||
427 | return 0; | ||
428 | |||
429 | return clk->parent->rate / value; | ||
430 | } | ||
431 | |||
432 | static long fsidiv_round_rate(struct clk *clk, unsigned long rate) | ||
433 | { | ||
434 | return clk_rate_div_range_round(clk, 2, 0xffff, rate); | ||
435 | } | ||
436 | |||
437 | static void fsidiv_disable(struct clk *clk) | ||
438 | { | ||
439 | __raw_writel(0, clk->mapping->base); | ||
440 | } | ||
441 | |||
442 | static int fsidiv_enable(struct clk *clk) | ||
443 | { | ||
444 | unsigned long value; | ||
445 | |||
446 | value = __raw_readl(clk->mapping->base) >> 16; | ||
447 | if (value < 2) | ||
448 | return -EIO; | ||
449 | |||
450 | __raw_writel((value << 16) | 0x3, clk->mapping->base); | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int fsidiv_set_rate(struct clk *clk, unsigned long rate) | ||
456 | { | ||
457 | int idx; | ||
458 | |||
459 | idx = (clk->parent->rate / rate) & 0xffff; | ||
460 | if (idx < 2) | ||
461 | return -EINVAL; | ||
462 | |||
463 | __raw_writel(idx << 16, clk->mapping->base); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static struct clk_ops fsidiv_clk_ops = { | ||
468 | .recalc = fsidiv_recalc, | ||
469 | .round_rate = fsidiv_round_rate, | ||
470 | .set_rate = fsidiv_set_rate, | ||
471 | .enable = fsidiv_enable, | ||
472 | .disable = fsidiv_disable, | ||
473 | }; | ||
474 | |||
475 | static struct clk_mapping sh7372_fsidiva_clk_mapping = { | ||
476 | .phys = FSIDIVA, | ||
477 | .len = 8, | ||
478 | }; | ||
479 | |||
480 | struct clk sh7372_fsidiva_clk = { | ||
481 | .ops = &fsidiv_clk_ops, | ||
482 | .parent = &div6_reparent_clks[DIV6_FSIA], /* late install */ | ||
483 | .mapping = &sh7372_fsidiva_clk_mapping, | ||
484 | }; | ||
485 | |||
486 | static struct clk_mapping sh7372_fsidivb_clk_mapping = { | ||
487 | .phys = FSIDIVB, | ||
488 | .len = 8, | ||
489 | }; | ||
490 | |||
491 | struct clk sh7372_fsidivb_clk = { | ||
492 | .ops = &fsidiv_clk_ops, | ||
493 | .parent = &div6_reparent_clks[DIV6_FSIB], /* late install */ | ||
494 | .mapping = &sh7372_fsidivb_clk_mapping, | ||
495 | }; | ||
496 | |||
497 | static struct clk *late_main_clks[] = { | ||
498 | &sh7372_fsidiva_clk, | ||
499 | &sh7372_fsidivb_clk, | ||
500 | }; | ||
501 | |||
420 | enum { MSTP001, | 502 | enum { MSTP001, |
421 | MSTP131, MSTP130, | 503 | MSTP131, MSTP130, |
422 | MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, | 504 | MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, |
@@ -510,8 +592,6 @@ static struct clk_lookup lookups[] = { | |||
510 | CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), | 592 | CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), |
511 | CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), | 593 | CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), |
512 | CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), | 594 | CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), |
513 | CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FSIA]), | ||
514 | CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FSIB]), | ||
515 | CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), | 595 | CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), |
516 | CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), | 596 | CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), |
517 | CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), | 597 | CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), |
@@ -548,8 +628,8 @@ static struct clk_lookup lookups[] = { | |||
548 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ | 628 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ |
549 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ | 629 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ |
550 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ | 630 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ |
551 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */ | 631 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */ |
552 | CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP323]), /* USB0 */ | 632 | CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */ |
553 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ | 633 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ |
554 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ | 634 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ |
555 | CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */ | 635 | CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */ |
@@ -585,6 +665,9 @@ void __init sh7372_clock_init(void) | |||
585 | if (!ret) | 665 | if (!ret) |
586 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); | 666 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); |
587 | 667 | ||
668 | for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) | ||
669 | ret = clk_register(late_main_clks[k]); | ||
670 | |||
588 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 671 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); |
589 | 672 | ||
590 | if (!ret) | 673 | if (!ret) |