From 3dbfe5ae614a561c3e0c2ccddd7cae0d4cd8f2c8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 27 Dec 2018 20:15:20 -0700 Subject: rockchip: rk3288: Add i2s pinctrl and clock support Add support for setting pinctrl and clock for I2S on rk3288. This allows the sound driver to operate. These settings were created by rkmux.py Signed-off-by: Simon Glass Reviewed-by: Philipp Tomsich --- drivers/clk/rockchip/clk_rk3288.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'drivers/clk/rockchip/clk_rk3288.c') diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c index 4a6e5c7113..930c99f4d9 100644 --- a/drivers/clk/rockchip/clk_rk3288.c +++ b/drivers/clk/rockchip/clk_rk3288.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -371,6 +372,50 @@ static int rockchip_vop_set_clk(struct rk3288_cru *cru, struct rk3288_grf *grf, return 0; } + +static u32 rockchip_clk_gcd(u32 a, u32 b) +{ + while (b != 0) { + int r = b; + + b = a % b; + a = r; + } + return a; +} + +static ulong rockchip_i2s_get_clk(struct rk3288_cru *cru, uint gclk_rate) +{ + unsigned long long rate; + uint val; + int n, d; + + val = readl(&cru->cru_clksel_con[8]); + n = (val & I2S0_FRAC_NUMER_MASK) >> I2S0_FRAC_NUMER_SHIFT; + d = (val & I2S0_FRAC_DENOM_MASK) >> I2S0_FRAC_DENOM_SHIFT; + + rate = (unsigned long long)gclk_rate * n; + do_div(rate, d); + + return (ulong)rate; +} + +static ulong rockchip_i2s_set_clk(struct rk3288_cru *cru, uint gclk_rate, + uint freq) +{ + int n, d; + int v; + + /* set frac divider */ + v = rockchip_clk_gcd(gclk_rate, freq); + n = gclk_rate / v; + d = freq / v; + assert(freq == gclk_rate / n * d); + writel(d << I2S0_FRAC_NUMER_SHIFT | n << I2S0_FRAC_DENOM_SHIFT, + &cru->cru_clksel_con[8]); + + return rockchip_i2s_get_clk(cru, gclk_rate); +} #endif /* CONFIG_SPL_BUILD */ static void rkclk_init(struct rk3288_cru *cru, struct rk3288_grf *grf) @@ -769,6 +814,9 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate) new_rate = rockchip_spi_set_clk(cru, gclk_rate, clk->id, rate); break; #ifndef CONFIG_SPL_BUILD + case SCLK_I2S0: + new_rate = rockchip_i2s_set_clk(cru, gclk_rate, rate); + break; case SCLK_MAC: new_rate = rockchip_mac_set_clk(priv->cru, rate); break; -- cgit