diff options
author | Ryan Mallon <ryan@bluewatersys.com> | 2010-06-08 06:01:10 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-06-09 06:12:36 -0400 |
commit | ed67ea82c0d9a163458dc6a69a7a3123db1a8b3b (patch) | |
tree | 6789785686ddf249ab813c296ade58b7b0443d33 /arch/arm/mach-ep93xx/clock.c | |
parent | e40152ee1e1c7a63f4777791863215e3faa37a86 (diff) |
EP93xx: Add i2s core support
Add core support for EP93xx i2s audio
Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'arch/arm/mach-ep93xx/clock.c')
-rw-r--r-- | arch/arm/mach-ep93xx/clock.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 5f80092b6ace..e782af18ffb7 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c | |||
@@ -43,7 +43,8 @@ static unsigned long get_uart_rate(struct clk *clk); | |||
43 | 43 | ||
44 | static int set_keytchclk_rate(struct clk *clk, unsigned long rate); | 44 | static int set_keytchclk_rate(struct clk *clk, unsigned long rate); |
45 | static int set_div_rate(struct clk *clk, unsigned long rate); | 45 | static int set_div_rate(struct clk *clk, unsigned long rate); |
46 | 46 | static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate); | |
47 | static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate); | ||
47 | 48 | ||
48 | static struct clk clk_xtali = { | 49 | static struct clk clk_xtali = { |
49 | .rate = EP93XX_EXT_CLK_RATE, | 50 | .rate = EP93XX_EXT_CLK_RATE, |
@@ -108,6 +109,29 @@ static struct clk clk_video = { | |||
108 | .set_rate = set_div_rate, | 109 | .set_rate = set_div_rate, |
109 | }; | 110 | }; |
110 | 111 | ||
112 | static struct clk clk_i2s_mclk = { | ||
113 | .sw_locked = 1, | ||
114 | .enable_reg = EP93XX_SYSCON_I2SCLKDIV, | ||
115 | .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE, | ||
116 | .set_rate = set_div_rate, | ||
117 | }; | ||
118 | |||
119 | static struct clk clk_i2s_sclk = { | ||
120 | .sw_locked = 1, | ||
121 | .parent = &clk_i2s_mclk, | ||
122 | .enable_reg = EP93XX_SYSCON_I2SCLKDIV, | ||
123 | .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, | ||
124 | .set_rate = set_i2s_sclk_rate, | ||
125 | }; | ||
126 | |||
127 | static struct clk clk_i2s_lrclk = { | ||
128 | .sw_locked = 1, | ||
129 | .parent = &clk_i2s_sclk, | ||
130 | .enable_reg = EP93XX_SYSCON_I2SCLKDIV, | ||
131 | .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, | ||
132 | .set_rate = set_i2s_lrclk_rate, | ||
133 | }; | ||
134 | |||
111 | /* DMA Clocks */ | 135 | /* DMA Clocks */ |
112 | static struct clk clk_m2p0 = { | 136 | static struct clk clk_m2p0 = { |
113 | .parent = &clk_h, | 137 | .parent = &clk_h, |
@@ -186,6 +210,9 @@ static struct clk_lookup clocks[] = { | |||
186 | INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), | 210 | INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), |
187 | INIT_CK("ep93xx-keypad", NULL, &clk_keypad), | 211 | INIT_CK("ep93xx-keypad", NULL, &clk_keypad), |
188 | INIT_CK("ep93xx-fb", NULL, &clk_video), | 212 | INIT_CK("ep93xx-fb", NULL, &clk_video), |
213 | INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk), | ||
214 | INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk), | ||
215 | INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk), | ||
189 | INIT_CK(NULL, "pwm_clk", &clk_pwm), | 216 | INIT_CK(NULL, "pwm_clk", &clk_pwm), |
190 | INIT_CK(NULL, "m2p0", &clk_m2p0), | 217 | INIT_CK(NULL, "m2p0", &clk_m2p0), |
191 | INIT_CK(NULL, "m2p1", &clk_m2p1), | 218 | INIT_CK(NULL, "m2p1", &clk_m2p1), |
@@ -396,6 +423,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate) | |||
396 | return 0; | 423 | return 0; |
397 | } | 424 | } |
398 | 425 | ||
426 | static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate) | ||
427 | { | ||
428 | unsigned val = __raw_readl(clk->enable_reg); | ||
429 | |||
430 | if (rate == clk_i2s_mclk.rate / 2) | ||
431 | ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV, | ||
432 | clk->enable_reg); | ||
433 | else if (rate == clk_i2s_mclk.rate / 4) | ||
434 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV, | ||
435 | clk->enable_reg); | ||
436 | else | ||
437 | return -EINVAL; | ||
438 | |||
439 | clk_i2s_sclk.rate = rate; | ||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate) | ||
444 | { | ||
445 | unsigned val = __raw_readl(clk->enable_reg) & | ||
446 | ~EP93XX_I2SCLKDIV_LRDIV_MASK; | ||
447 | |||
448 | if (rate == clk_i2s_sclk.rate / 32) | ||
449 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32, | ||
450 | clk->enable_reg); | ||
451 | else if (rate == clk_i2s_sclk.rate / 64) | ||
452 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64, | ||
453 | clk->enable_reg); | ||
454 | else if (rate == clk_i2s_sclk.rate / 128) | ||
455 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128, | ||
456 | clk->enable_reg); | ||
457 | else | ||
458 | return -EINVAL; | ||
459 | |||
460 | clk_i2s_lrclk.rate = rate; | ||
461 | return 0; | ||
462 | } | ||
463 | |||
399 | int clk_set_rate(struct clk *clk, unsigned long rate) | 464 | int clk_set_rate(struct clk *clk, unsigned long rate) |
400 | { | 465 | { |
401 | if (clk->set_rate) | 466 | if (clk->set_rate) |