diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2012-06-12 05:35:36 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-06-20 06:27:47 -0400 |
commit | c6750acb3b54c77c011045467770d5143be749ee (patch) | |
tree | baf2f96a65ae8380be691ea62708858e1899c24d /arch | |
parent | 7d7136cabcad632a81cd568a9c1135db276fe0f2 (diff) |
ARM: shmobile: r8a7740: add HDMI clock support
It is required from sh_mobile_hdmi driver.
This patch is based on v1.0 manual
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-shmobile/clock-r8a7740.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index 26eea5f21054..b09534352f97 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #define MSTPSR2 0xe6150040 | 54 | #define MSTPSR2 0xe6150040 |
55 | #define MSTPSR3 0xe6150048 | 55 | #define MSTPSR3 0xe6150048 |
56 | #define MSTPSR4 0xe615004c | 56 | #define MSTPSR4 0xe615004c |
57 | #define HDMICKCR 0xe6150094 | ||
57 | #define SMSTPCR0 0xe6150130 | 58 | #define SMSTPCR0 0xe6150130 |
58 | #define SMSTPCR1 0xe6150134 | 59 | #define SMSTPCR1 0xe6150134 |
59 | #define SMSTPCR2 0xe6150138 | 60 | #define SMSTPCR2 0xe6150138 |
@@ -313,6 +314,79 @@ static struct clk_div4_table div4_table = { | |||
313 | .kick = div4_kick, | 314 | .kick = div4_kick, |
314 | }; | 315 | }; |
315 | 316 | ||
317 | /* DIV6 reparent */ | ||
318 | enum { | ||
319 | DIV6_HDMI, | ||
320 | DIV6_REPARENT_NR, | ||
321 | }; | ||
322 | |||
323 | static struct clk *hdmi_parent[] = { | ||
324 | [0] = &pllc1_div2_clk, | ||
325 | [1] = &system_clk, | ||
326 | [2] = &dv_clk | ||
327 | }; | ||
328 | |||
329 | static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { | ||
330 | [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, | ||
331 | hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), | ||
332 | }; | ||
333 | |||
334 | /* HDMI1/2 clock */ | ||
335 | static unsigned long hdmi12_recalc(struct clk *clk) | ||
336 | { | ||
337 | u32 val = __raw_readl(HDMICKCR); | ||
338 | int shift = (int)clk->priv; | ||
339 | |||
340 | val >>= shift; | ||
341 | val &= 0x3; | ||
342 | |||
343 | return clk->parent->rate / (1 << val); | ||
344 | }; | ||
345 | |||
346 | static int hdmi12_set_rate(struct clk *clk, unsigned long rate) | ||
347 | { | ||
348 | u32 val, mask; | ||
349 | int i, shift; | ||
350 | |||
351 | for (i = 0; i < 3; i++) | ||
352 | if (rate == clk->parent->rate / (1 << i)) | ||
353 | goto find; | ||
354 | return -ENODEV; | ||
355 | |||
356 | find: | ||
357 | shift = (int)clk->priv; | ||
358 | |||
359 | val = __raw_readl(HDMICKCR); | ||
360 | mask = ~(0x3 << shift); | ||
361 | val = (val & mask) | i << shift; | ||
362 | __raw_writel(val, HDMICKCR); | ||
363 | |||
364 | return 0; | ||
365 | }; | ||
366 | |||
367 | static struct sh_clk_ops hdmi12_clk_ops = { | ||
368 | .recalc = hdmi12_recalc, | ||
369 | .set_rate = hdmi12_set_rate, | ||
370 | }; | ||
371 | |||
372 | static struct clk hdmi1_clk = { | ||
373 | .ops = &hdmi12_clk_ops, | ||
374 | .priv = (void *)9, | ||
375 | .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ | ||
376 | }; | ||
377 | |||
378 | static struct clk hdmi2_clk = { | ||
379 | .ops = &hdmi12_clk_ops, | ||
380 | .priv = (void *)11, | ||
381 | .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ | ||
382 | }; | ||
383 | |||
384 | static struct clk *late_main_clks[] = { | ||
385 | &hdmi1_clk, | ||
386 | &hdmi2_clk, | ||
387 | }; | ||
388 | |||
389 | /* MSTP */ | ||
316 | enum { | 390 | enum { |
317 | DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, | 391 | DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, |
318 | DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, | 392 | DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, |
@@ -408,6 +482,8 @@ static struct clk_lookup lookups[] = { | |||
408 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), | 482 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), |
409 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), | 483 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), |
410 | CLKDEV_CON_ID("usb24s", &usb24s_clk), | 484 | CLKDEV_CON_ID("usb24s", &usb24s_clk), |
485 | CLKDEV_CON_ID("hdmi1", &hdmi1_clk), | ||
486 | CLKDEV_CON_ID("hdmi2", &hdmi2_clk), | ||
411 | 487 | ||
412 | /* DIV4 clocks */ | 488 | /* DIV4 clocks */ |
413 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), | 489 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), |
@@ -459,6 +535,7 @@ static struct clk_lookup lookups[] = { | |||
459 | CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), | 535 | CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), |
460 | CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), | 536 | CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), |
461 | CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), | 537 | CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), |
538 | CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), | ||
462 | }; | 539 | }; |
463 | 540 | ||
464 | void __init r8a7740_clock_init(u8 md_ck) | 541 | void __init r8a7740_clock_init(u8 md_ck) |
@@ -495,8 +572,15 @@ void __init r8a7740_clock_init(u8 md_ck) | |||
495 | ret = sh_clk_div6_register(div6_clks, DIV6_NR); | 572 | ret = sh_clk_div6_register(div6_clks, DIV6_NR); |
496 | 573 | ||
497 | if (!ret) | 574 | if (!ret) |
575 | ret = sh_clk_div6_reparent_register(div6_reparent_clks, | ||
576 | DIV6_REPARENT_NR); | ||
577 | |||
578 | if (!ret) | ||
498 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); | 579 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); |
499 | 580 | ||
581 | for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) | ||
582 | ret = clk_register(late_main_clks[k]); | ||
583 | |||
500 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 584 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); |
501 | 585 | ||
502 | if (!ret) | 586 | if (!ret) |