aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ep93xx/clock.c')
-rw-r--r--arch/arm/mach-ep93xx/clock.c67
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
44static int set_keytchclk_rate(struct clk *clk, unsigned long rate); 44static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
45static int set_div_rate(struct clk *clk, unsigned long rate); 45static int set_div_rate(struct clk *clk, unsigned long rate);
46 46static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
47static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
47 48
48static struct clk clk_xtali = { 49static 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
112static 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
119static 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
127static 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 */
112static struct clk clk_m2p0 = { 136static 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
426static 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
443static 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
399int clk_set_rate(struct clk *clk, unsigned long rate) 464int clk_set_rate(struct clk *clk, unsigned long rate)
400{ 465{
401 if (clk->set_rate) 466 if (clk->set_rate)