diff options
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 7f3039761d9..8bf3cec98cf 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, |
@@ -112,6 +113,29 @@ static struct clk clk_video = { | |||
112 | .set_rate = set_div_rate, | 113 | .set_rate = set_div_rate, |
113 | }; | 114 | }; |
114 | 115 | ||
116 | static struct clk clk_i2s_mclk = { | ||
117 | .sw_locked = 1, | ||
118 | .enable_reg = EP93XX_SYSCON_I2SCLKDIV, | ||
119 | .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE, | ||
120 | .set_rate = set_div_rate, | ||
121 | }; | ||
122 | |||
123 | static struct clk clk_i2s_sclk = { | ||
124 | .sw_locked = 1, | ||
125 | .parent = &clk_i2s_mclk, | ||
126 | .enable_reg = EP93XX_SYSCON_I2SCLKDIV, | ||
127 | .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, | ||
128 | .set_rate = set_i2s_sclk_rate, | ||
129 | }; | ||
130 | |||
131 | static struct clk clk_i2s_lrclk = { | ||
132 | .sw_locked = 1, | ||
133 | .parent = &clk_i2s_sclk, | ||
134 | .enable_reg = EP93XX_SYSCON_I2SCLKDIV, | ||
135 | .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA, | ||
136 | .set_rate = set_i2s_lrclk_rate, | ||
137 | }; | ||
138 | |||
115 | /* DMA Clocks */ | 139 | /* DMA Clocks */ |
116 | static struct clk clk_m2p0 = { | 140 | static struct clk clk_m2p0 = { |
117 | .parent = &clk_h, | 141 | .parent = &clk_h, |
@@ -191,6 +215,9 @@ static struct clk_lookup clocks[] = { | |||
191 | INIT_CK("ep93xx-keypad", NULL, &clk_keypad), | 215 | INIT_CK("ep93xx-keypad", NULL, &clk_keypad), |
192 | INIT_CK("ep93xx-fb", NULL, &clk_video), | 216 | INIT_CK("ep93xx-fb", NULL, &clk_video), |
193 | INIT_CK("ep93xx-spi.0", NULL, &clk_spi), | 217 | INIT_CK("ep93xx-spi.0", NULL, &clk_spi), |
218 | INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk), | ||
219 | INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk), | ||
220 | INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk), | ||
194 | INIT_CK(NULL, "pwm_clk", &clk_pwm), | 221 | INIT_CK(NULL, "pwm_clk", &clk_pwm), |
195 | INIT_CK(NULL, "m2p0", &clk_m2p0), | 222 | INIT_CK(NULL, "m2p0", &clk_m2p0), |
196 | INIT_CK(NULL, "m2p1", &clk_m2p1), | 223 | INIT_CK(NULL, "m2p1", &clk_m2p1), |
@@ -401,6 +428,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate) | |||
401 | return 0; | 428 | return 0; |
402 | } | 429 | } |
403 | 430 | ||
431 | static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate) | ||
432 | { | ||
433 | unsigned val = __raw_readl(clk->enable_reg); | ||
434 | |||
435 | if (rate == clk_i2s_mclk.rate / 2) | ||
436 | ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV, | ||
437 | clk->enable_reg); | ||
438 | else if (rate == clk_i2s_mclk.rate / 4) | ||
439 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV, | ||
440 | clk->enable_reg); | ||
441 | else | ||
442 | return -EINVAL; | ||
443 | |||
444 | clk_i2s_sclk.rate = rate; | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate) | ||
449 | { | ||
450 | unsigned val = __raw_readl(clk->enable_reg) & | ||
451 | ~EP93XX_I2SCLKDIV_LRDIV_MASK; | ||
452 | |||
453 | if (rate == clk_i2s_sclk.rate / 32) | ||
454 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32, | ||
455 | clk->enable_reg); | ||
456 | else if (rate == clk_i2s_sclk.rate / 64) | ||
457 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64, | ||
458 | clk->enable_reg); | ||
459 | else if (rate == clk_i2s_sclk.rate / 128) | ||
460 | ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128, | ||
461 | clk->enable_reg); | ||
462 | else | ||
463 | return -EINVAL; | ||
464 | |||
465 | clk_i2s_lrclk.rate = rate; | ||
466 | return 0; | ||
467 | } | ||
468 | |||
404 | int clk_set_rate(struct clk *clk, unsigned long rate) | 469 | int clk_set_rate(struct clk *clk, unsigned long rate) |
405 | { | 470 | { |
406 | if (clk->set_rate) | 471 | if (clk->set_rate) |