aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/arch-rockchip/cru_rk3288.h8
-rw-r--r--arch/arm/include/asm/arch-rockchip/grf_rk3288.h96
-rw-r--r--arch/arm/include/asm/arch-rockchip/periph.h1
-rw-r--r--drivers/clk/rockchip/clk_rk3288.c48
-rw-r--r--drivers/pinctrl/rockchip/pinctrl_rk3288.c14
5 files changed, 167 insertions, 0 deletions
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
index 0475598..e891f20 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
@@ -75,6 +75,14 @@ enum {
MMC0_DIV_MASK = 0x3f << MMC0_DIV_SHIFT,
};
+/* CRU_CLKSEL8_CON */
+enum {
+ I2S0_FRAC_DENOM_SHIFT = 0,
+ I2S0_FRAC_DENOM_MASK = 0xffff << I2S0_FRAC_DENOM_SHIFT,
+ I2S0_FRAC_NUMER_SHIFT = 16,
+ I2S0_FRAC_NUMER_MASK = 0xffffu << I2S0_FRAC_NUMER_SHIFT,
+};
+
/* CRU_CLKSEL12_CON */
enum {
EMMC_PLL_SHIFT = 0xe,
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3288.h b/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
index c235607..7729544 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
@@ -561,6 +561,49 @@ enum {
GPIO5C0_TS0_SYNC,
};
+/* GRF_GPIO6A_IOMUX */
+enum {
+ GPIO6A7_SHIFT = 0xe,
+ GPIO6A7_MASK = 1,
+ GPIO6A7_GPIO = 0,
+ GPIO6A7_I2S_SDO3,
+
+ GPIO6A6_SHIFT = 0xc,
+ GPIO6A6_MASK = 1,
+ GPIO6A6_GPIO = 0,
+ GPIO6A6_I2S_SDO2,
+
+ GPIO6A5_SHIFT = 0xa,
+ GPIO6A5_MASK = 1,
+ GPIO6A5_GPIO = 0,
+ GPIO6A5_I2S_SDO1,
+
+ GPIO6A4_SHIFT = 8,
+ GPIO6A4_MASK = 1,
+ GPIO6A4_GPIO = 0,
+ GPIO6A4_I2S_SDO0,
+
+ GPIO6A3_SHIFT = 6,
+ GPIO6A3_MASK = 1,
+ GPIO6A3_GPIO = 0,
+ GPIO6A3_I2S_SDI,
+
+ GPIO6A2_SHIFT = 4,
+ GPIO6A2_MASK = 1,
+ GPIO6A2_GPIO = 0,
+ GPIO6A2_I2S_LRCKTX,
+
+ GPIO6A1_SHIFT = 2,
+ GPIO6A1_MASK = 1,
+ GPIO6A1_GPIO = 0,
+ GPIO6A1_I2S_LRCKRX,
+
+ GPIO6A0_SHIFT = 0,
+ GPIO6A0_MASK = 1,
+ GPIO6A0_GPIO = 0,
+ GPIO6A0_I2S_SCLK,
+};
+
/* GRF_GPIO6B_IOMUX */
enum {
GPIO6B3_SHIFT = 6,
@@ -1042,6 +1085,59 @@ enum GRF_SOC_CON8 {
RK3288_DPHY_TX0_TURNREQUEST_DIS = 0,
};
+/* GRF_IO_VSEL */
+enum {
+ GPIO1830_V18SEL_SHIFT = 9,
+ GPIO1830_V18SEL_MASK = 1,
+ GPIO1830_V18SEL_3_3V = 0,
+ GPIO1830_V18SEL_1_8V,
+
+ GPIO30_V18SEL_SHIFT = 8,
+ GPIO30_V18SEL_MASK = 1,
+ GPIO30_V18SEL_3_3V = 0,
+ GPIO30_V18SEL_1_8V,
+
+ SDCARD_V18SEL_SHIFT = 7,
+ SDCARD_V18SEL_MASK = 1,
+ SDCARD_V18SEL_3_3V = 0,
+ SDCARD_V18SEL_1_8V,
+
+ AUDIO_V18SEL_SHIFT = 6,
+ AUDIO_V18SEL_MASK = 1,
+ AUDIO_V18SEL_3_3V = 0,
+ AUDIO_V18SEL_1_8V,
+
+ BB_V18SEL_SHIFT = 5,
+ BB_V18SEL_MASK = 1,
+ BB_V18SEL_3_3V = 0,
+ BB_V18SEL_1_8V,
+
+ WIFI_V18SEL_SHIFT = 4,
+ WIFI_V18SEL_MASK = 1,
+ WIFI_V18SEL_3_3V = 0,
+ WIFI_V18SEL_1_8V,
+
+ FLASH1_V18SEL_SHIFT = 3,
+ FLASH1_V18SEL_MASK = 1,
+ FLASH1_V18SEL_3_3V = 0,
+ FLASH1_V18SEL_1_8V,
+
+ FLASH0_V18SEL_SHIFT = 2,
+ FLASH0_V18SEL_MASK = 1,
+ FLASH0_V18SEL_3_3V = 0,
+ FLASH0_V18SEL_1_8V,
+
+ DVP_V18SEL_SHIFT = 1,
+ DVP_V18SEL_MASK = 1,
+ DVP_V18SEL_3_3V = 0,
+ DVP_V18SEL_1_8V,
+
+ LCDC_V18SEL_SHIFT = 0,
+ LCDC_V18SEL_MASK = 1,
+ LCDC_V18SEL_3_3V = 0,
+ LCDC_V18SEL_1_8V,
+};
+
/* GPIO Bias settings */
enum GPIO_BIAS {
GPIO_BIAS_2MA = 0,
diff --git a/arch/arm/include/asm/arch-rockchip/periph.h b/arch/arm/include/asm/arch-rockchip/periph.h
index 514baf6..2191b7d 100644
--- a/arch/arm/include/asm/arch-rockchip/periph.h
+++ b/arch/arm/include/asm/arch-rockchip/periph.h
@@ -45,6 +45,7 @@ enum periph_id {
PERIPH_ID_HDMI,
PERIPH_ID_GMAC,
PERIPH_ID_SFC,
+ PERIPH_ID_I2S,
PERIPH_ID_COUNT,
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 4a6e5c7..930c99f 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <bitfield.h>
#include <clk-uclass.h>
+#include <div64.h>
#include <dm.h>
#include <dt-structs.h>
#include <errno.h>
@@ -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;
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
index 3e01cfd..fd19cfb 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
@@ -531,6 +531,17 @@ static void pinctrl_rk3288_hdmi_config(struct rk3288_grf *grf, int hdmi_id)
break;
}
}
+
+static void pinctrl_rk3288_i2s_config(struct rk3288_grf *grf)
+{
+ rk_setreg(&grf->gpio6a_iomux, GPIO6A4_I2S_SDO0 << GPIO6A4_SHIFT |
+ GPIO6A3_I2S_SDI << GPIO6A3_SHIFT |
+ GPIO6A2_I2S_LRCKTX << GPIO6A2_SHIFT |
+ GPIO6A1_I2S_LRCKRX << GPIO6A1_SHIFT |
+ GPIO6A0_I2S_SCLK << GPIO6A0_SHIFT);
+ rk_setreg(&grf->gpio6b_iomux, GPIO6B0_I2S_CLK << GPIO6B0_SHIFT);
+ rk_setreg(&grf->io_vsel, AUDIO_V18SEL_1_8V << AUDIO_V18SEL_SHIFT);
+}
#endif
static int rk3288_pinctrl_request(struct udevice *dev, int func, int flags)
@@ -567,6 +578,9 @@ static int rk3288_pinctrl_request(struct udevice *dev, int func, int flags)
pinctrl_rk3288_uart_config(priv->grf, func);
break;
#ifndef CONFIG_SPL_BUILD
+ case PERIPH_ID_I2S:
+ pinctrl_rk3288_i2s_config(priv->grf);
+ break;
case PERIPH_ID_LCDC0:
case PERIPH_ID_LCDC1:
pinctrl_rk3288_lcdc_config(priv->grf, func);