aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile/clock-sh7372.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shmobile/clock-sh7372.c')
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c115
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 */
54struct clk sh7372_dv_clki_clk = { 57struct 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
220static int pllc2_set_rate(struct clk *clk, 223static 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 */
416static 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
432static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
433{
434 return clk_rate_div_range_round(clk, 2, 0xffff, rate);
435}
436
437static void fsidiv_disable(struct clk *clk)
438{
439 __raw_writel(0, clk->mapping->base);
440}
441
442static 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
455static 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
467static 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
475static struct clk_mapping sh7372_fsidiva_clk_mapping = {
476 .phys = FSIDIVA,
477 .len = 8,
478};
479
480struct 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
486static struct clk_mapping sh7372_fsidivb_clk_mapping = {
487 .phys = FSIDIVB,
488 .len = 8,
489};
490
491struct 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
497static struct clk *late_main_clks[] = {
498 &sh7372_fsidiva_clk,
499 &sh7372_fsidivb_clk,
500};
501
420enum { MSTP001, 502enum { 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)