[U-Boot] [PATCH 1/4] rockchip: rk3288: Add i2s pinctrl and clock support

Simon Glass sjg at chromium.org
Fri Dec 28 03:15:20 UTC 2018


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 <sjg at chromium.org>
---

 .../include/asm/arch-rockchip/cru_rk3288.h    |  8 ++
 .../include/asm/arch-rockchip/grf_rk3288.h    | 96 +++++++++++++++++++
 arch/arm/include/asm/arch-rockchip/periph.h   |  1 +
 drivers/clk/rockchip/clk_rk3288.c             | 48 ++++++++++
 drivers/pinctrl/rockchip/pinctrl_rk3288.c     | 14 +++
 5 files changed, 167 insertions(+)

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
index 0475598b77b..e891f20b373 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 c235607cee5..77295446c63 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 514baf6a535..2191b7d43a8 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 4a6e5c7113d..930c99f4d9f 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 3e01cfd98f4..fd19cfb51cc 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);
-- 
2.20.1.415.g653613c723-goog



More information about the U-Boot mailing list