|
@@ -43,7 +43,8 @@ static unsigned long get_uart_rate(struct clk *clk);
|
|
|
|
|
|
static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
|
|
|
static int set_div_rate(struct clk *clk, unsigned long rate);
|
|
|
-
|
|
|
+static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
|
|
|
+static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
|
|
|
|
|
|
static struct clk clk_xtali = {
|
|
|
.rate = EP93XX_EXT_CLK_RATE,
|
|
@@ -112,6 +113,29 @@ static struct clk clk_video = {
|
|
|
.set_rate = set_div_rate,
|
|
|
};
|
|
|
|
|
|
+static struct clk clk_i2s_mclk = {
|
|
|
+ .sw_locked = 1,
|
|
|
+ .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
|
|
|
+ .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
|
|
|
+ .set_rate = set_div_rate,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk clk_i2s_sclk = {
|
|
|
+ .sw_locked = 1,
|
|
|
+ .parent = &clk_i2s_mclk,
|
|
|
+ .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
|
|
|
+ .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
|
|
|
+ .set_rate = set_i2s_sclk_rate,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk clk_i2s_lrclk = {
|
|
|
+ .sw_locked = 1,
|
|
|
+ .parent = &clk_i2s_sclk,
|
|
|
+ .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
|
|
|
+ .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
|
|
|
+ .set_rate = set_i2s_lrclk_rate,
|
|
|
+};
|
|
|
+
|
|
|
/* DMA Clocks */
|
|
|
static struct clk clk_m2p0 = {
|
|
|
.parent = &clk_h,
|
|
@@ -191,6 +215,9 @@ static struct clk_lookup clocks[] = {
|
|
|
INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
|
|
|
INIT_CK("ep93xx-fb", NULL, &clk_video),
|
|
|
INIT_CK("ep93xx-spi.0", NULL, &clk_spi),
|
|
|
+ INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk),
|
|
|
+ INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk),
|
|
|
+ INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk),
|
|
|
INIT_CK(NULL, "pwm_clk", &clk_pwm),
|
|
|
INIT_CK(NULL, "m2p0", &clk_m2p0),
|
|
|
INIT_CK(NULL, "m2p1", &clk_m2p1),
|
|
@@ -401,6 +428,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ unsigned val = __raw_readl(clk->enable_reg);
|
|
|
+
|
|
|
+ if (rate == clk_i2s_mclk.rate / 2)
|
|
|
+ ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV,
|
|
|
+ clk->enable_reg);
|
|
|
+ else if (rate == clk_i2s_mclk.rate / 4)
|
|
|
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV,
|
|
|
+ clk->enable_reg);
|
|
|
+ else
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ clk_i2s_sclk.rate = rate;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ unsigned val = __raw_readl(clk->enable_reg) &
|
|
|
+ ~EP93XX_I2SCLKDIV_LRDIV_MASK;
|
|
|
+
|
|
|
+ if (rate == clk_i2s_sclk.rate / 32)
|
|
|
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32,
|
|
|
+ clk->enable_reg);
|
|
|
+ else if (rate == clk_i2s_sclk.rate / 64)
|
|
|
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64,
|
|
|
+ clk->enable_reg);
|
|
|
+ else if (rate == clk_i2s_sclk.rate / 128)
|
|
|
+ ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128,
|
|
|
+ clk->enable_reg);
|
|
|
+ else
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ clk_i2s_lrclk.rate = rate;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int clk_set_rate(struct clk *clk, unsigned long rate)
|
|
|
{
|
|
|
if (clk->set_rate)
|