aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/rockchip/rk3399/clock.c44
-rw-r--r--src/soc/rockchip/rk3399/include/soc/clock.h1
-rw-r--r--src/soc/rockchip/rk3399/include/soc/grf.h15
3 files changed, 58 insertions, 2 deletions
diff --git a/src/soc/rockchip/rk3399/clock.c b/src/soc/rockchip/rk3399/clock.c
index ba66230e23..6d40cd2578 100644
--- a/src/soc/rockchip/rk3399/clock.c
+++ b/src/soc/rockchip/rk3399/clock.c
@@ -686,6 +686,50 @@ uint32_t rkclk_i2c_clock_for_bus(unsigned bus)
return freq;
}
+static u32 clk_gcd(u32 a, u32 b)
+{
+ while (b != 0) {
+ int r = b;
+ b = a % b;
+ a = r;
+ }
+ return a;
+}
+
+void rkclk_configure_i2s(unsigned int hz)
+{
+ int n, d;
+ int v;
+
+ /**
+ * clk_i2s0_sel: divider ouput from fraction
+ * clk_i2s0_pll_sel source clock: cpll
+ * clk_i2s0_div_con: 1 (div+1)
+ */
+ write32(&cru_ptr->clksel_con[28],
+ RK_CLRSETBITS(3 << 8 | 1 << 7 | 0x7f << 0,
+ 1 << 8 | 0 << 7 | 0 << 0));
+
+ /* make sure and enable i2s0 path gates */
+ write32(&cru_ptr->clkgate_con[8],
+ RK_CLRBITS(1 << 12 | 1 << 5 | 1 << 4 | 1 << 3));
+
+ /* set frac divider */
+ v = clk_gcd(CPLL_HZ, hz);
+ n = (CPLL_HZ / v) & (0xffff);
+ d = (hz / v) & (0xffff);
+ assert(hz == CPLL_HZ / n * d);
+ write32(&cru_ptr->clksel_con[96], d << 16 | n);
+
+ /**
+ * clk_i2sout_sel clk_i2s
+ * clk_i2s_ch_sel: clk_i2s0
+ */
+ write32(&cru_ptr->clksel_con[31],
+ RK_CLRSETBITS(1 << 2 | 3 << 0,
+ 0 << 2 | 0 << 0));
+}
+
void rkclk_configure_saradc(unsigned int hz)
{
int src_clk_div;
diff --git a/src/soc/rockchip/rk3399/include/soc/clock.h b/src/soc/rockchip/rk3399/include/soc/clock.h
index 286abec06f..806e1ce348 100644
--- a/src/soc/rockchip/rk3399/include/soc/clock.h
+++ b/src/soc/rockchip/rk3399/include/soc/clock.h
@@ -107,6 +107,7 @@ int rkclk_configure_vop_dclk(u32 vop_id, u32 dclk_hz);
void rkclk_configure_cpu(enum apll_l_frequencies apll_l_freq);
void rkclk_configure_ddr(unsigned int hz);
void rkclk_configure_emmc(void);
+void rkclk_configure_i2s(unsigned int hz);
void rkclk_configure_saradc(unsigned int hz);
void rkclk_configure_spi(unsigned int bus, unsigned int hz);
void rkclk_configure_tsadc(unsigned int hz);
diff --git a/src/soc/rockchip/rk3399/include/soc/grf.h b/src/soc/rockchip/rk3399/include/soc/grf.h
index aec9248fd6..c0d6900cfd 100644
--- a/src/soc/rockchip/rk3399/include/soc/grf.h
+++ b/src/soc/rockchip/rk3399/include/soc/grf.h
@@ -131,8 +131,14 @@ struct rk3399_grf_regs {
u32 gpio3a_iomux;
u32 gpio3b_iomux;
u32 gpio3c_iomux;
- u32 gpio3d_iomux;
- u32 gpio4a_iomux;
+ union {
+ u32 iomux_i2s0;
+ u32 gpio3d_iomux;
+ };
+ union {
+ u32 iomux_i2sclk;
+ u32 gpio4a_iomux;
+ };
union {
u32 iomux_sdmmc;
u32 iomux_uart2a;
@@ -346,6 +352,11 @@ static struct rk3399_pmusgrf_regs * const rk3399_pmusgrf = (void *)PMUSGRF_BASE;
1 << 4 | 1 << 2 | 1 << 0)
#define IOMUX_I2C0_SCL RK_CLRSETBITS(3 << 0, 2 << 0)
#define IOMUX_I2C0_SDA RK_CLRSETBITS(3 << 14, 2 << 14)
+
+#define IOMUX_I2S0 RK_SETBITS(1 << 14 | 1 << 12 | 1 << 10 | 1 << 8 |\
+ 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0)
+#define IOMUX_I2SCLK RK_SETBITS(1 << 0)
+
#define IOMUX_PWM_0 RK_SETBITS(1 << 4)
#define IOMUX_PWM_1 RK_SETBITS(1 << 12)
#define IOMUX_PWM_2 RK_SETBITS(1 << 6)