[U-Boot] [PATCH v4 1/6] ARM: rockchip: rv1108: Sync clock with vendor tree

Otavio Salvador otavio at ossystems.com.br
Tue Nov 27 10:11:04 UTC 2018


Make adjustments to the rv1108 clock driver in order to align it
with the internal Rockchip version.

Signed-off-by: Otavio Salvador <otavio at ossystems.com.br>
---

Changes in v4:
- revert a wrong removal of devices

Changes in v3: None
Changes in v2: None

 .../include/asm/arch-rockchip/cru_rv1108.h    | 143 +++++-
 drivers/clk/rockchip/clk_rv1108.c             | 457 +++++++++++++++++-
 include/dt-bindings/clock/rv1108-cru.h        | 137 +++++-
 3 files changed, 706 insertions(+), 31 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
index 3cc2ed0187..4ce8caa40f 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
@@ -11,7 +11,11 @@
 #define OSC_HZ		(24 * 1000 * 1000)
 
 #define APLL_HZ		(600 * 1000000)
-#define GPLL_HZ		(594 * 1000000)
+#define GPLL_HZ		(1188 * 1000000)
+#define ACLK_PERI_HZ	(148500000)
+#define HCLK_PERI_HZ	(148500000)
+#define PCLK_PERI_HZ	(74250000)
+#define ACLK_BUS_HZ	(148500000)
 
 struct rv1108_clk_priv {
 	struct rv1108_cru *cru;
@@ -80,6 +84,11 @@ enum {
 	WORK_MODE_NORMAL	= 1,
 	DSMPD_SHIFT             = 3,
 	DSMPD_MASK		= 1 << DSMPD_SHIFT,
+	INTEGER_MODE			= 1,
+	GLOBAL_POWER_DOWN_SHIFT		= 0,
+	GLOBAL_POWER_DOWN_MASK		= 1 << GLOBAL_POWER_DOWN_SHIFT,
+	GLOBAL_POWER_DOWN		= 1,
+	GLOBAL_POWER_UP			= 0,
 
 	/* CLKSEL0_CON */
 	CORE_PLL_SEL_SHIFT	= 8,
@@ -90,11 +99,77 @@ enum {
 	CORE_CLK_DIV_SHIFT	= 0,
 	CORE_CLK_DIV_MASK	= 0x1f << CORE_CLK_DIV_SHIFT,
 
+	/* CLKSEL_CON1 */
+	PCLK_DBG_DIV_CON_SHIFT		= 4,
+	PCLK_DBG_DIV_CON_MASK		= 0xf << PCLK_DBG_DIV_CON_SHIFT,
+	ACLK_CORE_DIV_CON_SHIFT		= 0,
+	ACLK_CORE_DIV_CON_MASK		= 7 << ACLK_CORE_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON2 */
+	ACLK_BUS_PLL_SEL_SHIFT		= 8,
+	ACLK_BUS_PLL_SEL_MASK		= 3 << ACLK_BUS_PLL_SEL_SHIFT,
+	ACLK_BUS_PLL_SEL_GPLL		= 0,
+	ACLK_BUS_PLL_SEL_APLL		= 1,
+	ACLK_BUS_PLL_SEL_DPLL		= 2,
+	ACLK_BUS_DIV_CON_SHIFT		= 0,
+	ACLK_BUS_DIV_CON_MASK		= 0x1f << ACLK_BUS_DIV_CON_SHIFT,
+	ACLK_BUS_DIV_CON_WIDTH		= 5,
+
+	/* CLKSEL_CON3 */
+	PCLK_BUS_DIV_CON_SHIFT		= 8,
+	PCLK_BUS_DIV_CON_MASK		= 0x1f << PCLK_BUS_DIV_CON_SHIFT,
+	HCLK_BUS_DIV_CON_SHIFT		= 0,
+	HCLK_BUS_DIV_CON_MASK		= 0x1f,
+
+	/* CLKSEL_CON4 */
+	CLK_DDR_PLL_SEL_SHIFT		= 8,
+	CLK_DDR_PLL_SEL_MASK		= 0x3 << CLK_DDR_PLL_SEL_SHIFT,
+	CLK_DDR_DIV_CON_SHIFT		= 0,
+	CLK_DDR_DIV_CON_MASK		= 0x3 << CLK_DDR_DIV_CON_SHIFT,
+
+	/* CLKSEL_CON19 */
+	CLK_I2C1_PLL_SEL_SHIFT		= 15,
+	CLK_I2C1_PLL_SEL_MASK		= 1 << CLK_I2C1_PLL_SEL_SHIFT,
+	CLK_I2C1_PLL_SEL_DPLL		= 0,
+	CLK_I2C1_PLL_SEL_GPLL		= 1,
+	CLK_I2C1_DIV_CON_SHIFT		= 8,
+	CLK_I2C1_DIV_CON_MASK		= 0x7f << CLK_I2C1_DIV_CON_SHIFT,
+	CLK_I2C0_PLL_SEL_SHIFT		= 7,
+	CLK_I2C0_PLL_SEL_MASK		= 1 << CLK_I2C0_PLL_SEL_SHIFT,
+	CLK_I2C0_DIV_CON_SHIFT		= 0,
+	CLK_I2C0_DIV_CON_MASK		= 0x7f,
+	I2C_DIV_CON_WIDTH		= 7,
+
+	/* CLKSEL_CON20 */
+	CLK_I2C3_PLL_SEL_SHIFT		= 15,
+	CLK_I2C3_PLL_SEL_MASK		= 1 << CLK_I2C3_PLL_SEL_SHIFT,
+	CLK_I2C3_PLL_SEL_DPLL		= 0,
+	CLK_I2C3_PLL_SEL_GPLL		= 1,
+	CLK_I2C3_DIV_CON_SHIFT		= 8,
+	CLK_I2C3_DIV_CON_MASK		= 0x7f << CLK_I2C3_DIV_CON_SHIFT,
+	CLK_I2C2_PLL_SEL_SHIFT		= 7,
+	CLK_I2C2_PLL_SEL_MASK		= 1 << CLK_I2C2_PLL_SEL_SHIFT,
+	CLK_I2C2_DIV_CON_SHIFT		= 0,
+	CLK_I2C2_DIV_CON_MASK		= 0x7f,
+
 	/* CLKSEL_CON22 */
 	CLK_SARADC_DIV_CON_SHIFT= 0,
 	CLK_SARADC_DIV_CON_MASK	= GENMASK(9, 0),
 	CLK_SARADC_DIV_CON_WIDTH= 10,
 
+	/* CLKSEL_CON23 */
+	ACLK_PERI_PLL_SEL_SHIFT		= 15,
+	ACLK_PERI_PLL_SEL_MASK		= 1 << ACLK_PERI_PLL_SEL_SHIFT,
+	ACLK_PERI_PLL_SEL_GPLL		= 0,
+	ACLK_PERI_PLL_SEL_DPLL		= 1,
+	PCLK_PERI_DIV_CON_SHIFT		= 10,
+	PCLK_PERI_DIV_CON_MASK		= 0x1f << PCLK_PERI_DIV_CON_SHIFT,
+	HCLK_PERI_DIV_CON_SHIFT		= 5,
+	HCLK_PERI_DIV_CON_MASK		= 0x1f << HCLK_PERI_DIV_CON_SHIFT,
+	ACLK_PERI_DIV_CON_SHIFT		= 0,
+	ACLK_PERI_DIV_CON_MASK		= 0x1f,
+	PERI_DIV_CON_WIDTH		= 5,
+
 	/* CLKSEL24_CON */
 	MAC_PLL_SEL_SHIFT	= 12,
 	MAC_PLL_SEL_MASK	= 1 << MAC_PLL_SEL_SHIFT,
@@ -105,6 +180,16 @@ enum {
 	MAC_CLK_DIV_MASK	= 0x1f,
 	MAC_CLK_DIV_SHIFT	= 0,
 
+	/* CLKSEL25_CON */
+	EMMC_PLL_SEL_SHIFT	= 12,
+	EMMC_PLL_SEL_MASK	= 3 << EMMC_PLL_SEL_SHIFT,
+	EMMC_PLL_SEL_DPLL	= 0,
+	EMMC_PLL_SEL_GPLL,
+
+	/* CLKSEL26_CON */
+	EMMC_CLK_DIV_SHIFT	= 8,
+	EMMC_CLK_DIV_MASK	= 0xff << EMMC_CLK_DIV_SHIFT,
+
 	/* CLKSEL27_CON */
 	SFC_PLL_SEL_SHIFT	= 7,
 	SFC_PLL_SEL_MASK	= 1 << SFC_PLL_SEL_SHIFT,
@@ -112,5 +197,61 @@ enum {
 	SFC_PLL_SEL_GPLL	= 1,
 	SFC_CLK_DIV_SHIFT	= 0,
 	SFC_CLK_DIV_MASK	= 0x3f << SFC_CLK_DIV_SHIFT,
+
+	/* CLKSEL28_CON */
+	ACLK_VIO1_PLL_SEL_SHIFT		= 14,
+	ACLK_VIO1_PLL_SEL_MASK		= 3 << ACLK_VIO1_PLL_SEL_SHIFT,
+	VIO_PLL_SEL_DPLL		= 0,
+	VIO_PLL_SEL_GPLL		= 1,
+	ACLK_VIO1_CLK_DIV_SHIFT		= 8,
+	ACLK_VIO1_CLK_DIV_MASK		= 0x1f << ACLK_VIO1_CLK_DIV_SHIFT,
+	CLK_VIO_DIV_CON_WIDTH		= 5,
+	ACLK_VIO0_PLL_SEL_SHIFT		= 6,
+	ACLK_VIO0_PLL_SEL_MASK		= 3 << ACLK_VIO0_PLL_SEL_SHIFT,
+	ACLK_VIO0_CLK_DIV_SHIFT		= 0,
+	ACLK_VIO0_CLK_DIV_MASK		= 0x1f << ACLK_VIO0_CLK_DIV_SHIFT,
+
+	/* CLKSEL29_CON */
+	PCLK_VIO_CLK_DIV_SHIFT		= 8,
+	PCLK_VIO_CLK_DIV_MASK		= 0x1f << PCLK_VIO_CLK_DIV_SHIFT,
+	HCLK_VIO_CLK_DIV_SHIFT		= 0,
+	HCLK_VIO_CLK_DIV_MASK		= 0x1f << HCLK_VIO_CLK_DIV_SHIFT,
+
+	/* CLKSEL32_CON */
+	DCLK_VOP_SEL_SHIFT		= 7,
+	DCLK_VOP_SEL_MASK		= 1 << DCLK_VOP_SEL_SHIFT,
+	DCLK_VOP_SEL_HDMI		= 0,
+	DCLK_VOP_SEL_PLL		= 1,
+	DCLK_VOP_PLL_SEL_SHIFT		= 6,
+	DCLK_VOP_PLL_SEL_MASK		= 1 << DCLK_VOP_PLL_SEL_SHIFT,
+	DCLK_VOP_PLL_SEL_GPLL		= 0,
+	DCLK_VOP_PLL_SEL_DPLL		= 1,
+	DCLK_VOP_CLK_DIV_SHIFT		= 0,
+	DCLK_VOP_CLK_DIV_MASK		= 0x3f << DCLK_VOP_CLK_DIV_SHIFT,
+	DCLK_VOP_DIV_CON_WIDTH		= 6,
+
+	/* SOFTRST1_CON*/
+	DDRPHY_SRSTN_CLKDIV_REQ_SHIFT	= 0,
+	DDRPHY_SRSTN_CLKDIV_REQ		= 1,
+	DDRPHY_SRSTN_CLKDIV_DIS		= 0,
+	DDRPHY_SRSTN_CLKDIV_REQ_MASK	= 1 << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT,
+	DDRPHY_SRSTN_REQ_SHIFT		= 1,
+	DDRPHY_SRSTN_REQ		= 1,
+	DDRPHY_SRSTN_DIS		= 0,
+	DDRPHY_SRSTN_REQ_MASK		= 1 << DDRPHY_SRSTN_REQ_SHIFT,
+	DDRPHY_PSRSTN_REQ_SHIFT		= 2,
+	DDRPHY_PSRSTN_REQ		= 1,
+	DDRPHY_PSRSTN_DIS		= 0,
+	DDRPHY_PSRSTN_REQ_MASK		= 1 << DDRPHY_PSRSTN_REQ_SHIFT,
+
+	/* SOFTRST2_CON*/
+	DDRUPCTL_PSRSTN_REQ_SHIFT	= 0,
+	DDRUPCTL_PSRSTN_REQ		= 1,
+	DDRUPCTL_PSRSTN_DIS		= 0,
+	DDRUPCTL_PSRSTN_REQ_MASK	= 1 << DDRUPCTL_PSRSTN_REQ_SHIFT,
+	DDRUPCTL_NSRSTN_REQ_SHIFT	= 1,
+	DDRUPCTL_NSRSTN_REQ		= 1,
+	DDRUPCTL_NSRSTN_DIS		= 0,
+	DDRUPCTL_NSRSTN_REQ_MASK	= 1 << DDRUPCTL_NSRSTN_REQ_SHIFT,
 };
 #endif
diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c
index 1f9f534b28..3603568ee7 100644
--- a/drivers/clk/rockchip/clk_rv1108.c
+++ b/drivers/clk/rockchip/clk_rv1108.c
@@ -35,6 +35,9 @@ enum {
 			 #hz "Hz cannot be hit with PLL "\
 			 "divisors on line " __stringify(__LINE__));
 
+static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
+static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
+
 /* use integer mode */
 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
 {
@@ -57,6 +60,58 @@ static inline int rv1108_pll_id(enum rk_clk_id clk_id)
 	return id;
 }
 
+static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
+			 const struct pll_div *div)
+{
+	int pll_id = rv1108_pll_id(clk_id);
+	struct rv1108_pll *pll = &cru->pll[pll_id];
+
+	/* All PLLs have same VCO and output frequency range restrictions. */
+	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
+	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
+
+	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
+	      pll, div->fbdiv, div->refdiv, div->postdiv1,
+	      div->postdiv2, vco_hz, output_hz);
+	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
+	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
+
+	/*
+	 * When power on or changing PLL setting,
+	 * we must force PLL into slow mode to ensure output stable clock.
+	 */
+	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
+		     WORK_MODE_SLOW << WORK_MODE_SHIFT);
+
+	/* use integer mode */
+	rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
+	/* Power down */
+	rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
+
+	rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
+	rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
+		     (div->postdiv1 << POSTDIV1_SHIFT |
+		     div->postdiv2 << POSTDIV2_SHIFT |
+		     div->refdiv << REFDIV_SHIFT));
+	rk_clrsetreg(&pll->con2, FRACDIV_MASK,
+		     (div->refdiv << REFDIV_SHIFT));
+
+	/* Power Up */
+	rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
+
+	/* waiting for pll lock */
+	while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
+		udelay(1);
+
+	/*
+	 * set PLL into normal mode.
+	 */
+	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
+		     WORK_MODE_NORMAL << WORK_MODE_SHIFT);
+
+	return 0;
+}
+
 static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
 				   enum rk_clk_id clk_id)
 {
@@ -74,7 +129,7 @@ static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
 		fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
 		postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
 		postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
-		refdiv = (con1 & REFDIV_MASK) >> REFDIV_SHIFT;
+		refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
 		freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
 	} else {
 		freq = OSC_HZ;
@@ -154,6 +209,322 @@ static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
 	return rv1108_saradc_get_clk(cru);
 }
 
+static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[28]);
+	div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
+			       CLK_VIO_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[28],
+		     ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
+		     (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
+
+	return rv1108_aclk_vio1_get_clk(cru);
+}
+
+static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[28]);
+	div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
+			       CLK_VIO_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[28],
+		     ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
+		     (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
+
+	/*HCLK_VIO default div = 4*/
+	rk_clrsetreg(&cru->clksel_con[29],
+		     HCLK_VIO_CLK_DIV_MASK,
+		     3 << HCLK_VIO_CLK_DIV_SHIFT);
+	/*PCLK_VIO default div = 4*/
+	rk_clrsetreg(&cru->clksel_con[29],
+		     PCLK_VIO_CLK_DIV_MASK,
+		     3 << PCLK_VIO_CLK_DIV_SHIFT);
+
+	return rv1108_aclk_vio0_get_clk(cru);
+}
+
+static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[32]);
+	div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
+			       DCLK_VOP_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
+	assert(src_clk_div < 64);
+
+	rk_clrsetreg(&cru->clksel_con[32],
+		     DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
+		     DCLK_VOP_SEL_SHIFT,
+		     (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
+		     (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
+		     (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
+
+	return rv1108_dclk_vop_get_clk(cru);
+}
+
+static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[2]);
+	div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
+			       ACLK_BUS_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[2],
+		     ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
+		     (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
+
+	return rv1108_aclk_bus_get_clk(cru);
+}
+
+static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
+			       PERI_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
+			       PERI_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
+			       PERI_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(parent_rate, div);
+}
+
+static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
+		     (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
+		     (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
+
+	return rv1108_aclk_peri_get_clk(cru);
+}
+
+static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     HCLK_PERI_DIV_CON_MASK,
+		     (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
+
+	return rv1108_hclk_peri_get_clk(cru);
+}
+
+static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
+	assert(src_clk_div < 32);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     PCLK_PERI_DIV_CON_MASK,
+		     (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
+
+	return rv1108_pclk_peri_get_clk(cru);
+}
+
+static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
+{
+	u32 div, con;
+
+	switch (clk_id) {
+	case SCLK_I2C0_PMU:
+		con = readl(&cru->clksel_con[19]);
+		div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	case SCLK_I2C1:
+		con = readl(&cru->clksel_con[19]);
+		div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	case SCLK_I2C2:
+		con = readl(&cru->clksel_con[20]);
+		div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	case SCLK_I2C3:
+		con = readl(&cru->clksel_con[20]);
+		div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
+				       I2C_DIV_CON_WIDTH);
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
+{
+	int src_clk_div;
+
+	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
+	src_clk_div = GPLL_HZ / hz;
+	assert(src_clk_div - 1 <= 127);
+
+	switch (clk_id) {
+	case SCLK_I2C0_PMU:
+		rk_clrsetreg(&cru->clksel_con[19],
+			     CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
+			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
+		break;
+	case SCLK_I2C1:
+		rk_clrsetreg(&cru->clksel_con[19],
+			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
+			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
+		break;
+	case SCLK_I2C2:
+		rk_clrsetreg(&cru->clksel_con[20],
+			     CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
+			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
+		break;
+	case SCLK_I2C3:
+		rk_clrsetreg(&cru->clksel_con[20],
+			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
+			     (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
+			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
+		break;
+	default:
+		printf("do not support this i2c bus\n");
+		return -EINVAL;
+	}
+
+	return rv1108_i2c_get_clk(cru, clk_id);
+}
+
+static ulong rv1108_mmc_get_clk(struct clk *clk)
+{
+	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rv1108_cru *cru = priv->cru;
+	u32 div, con;
+
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+
+	con = readl(&cru->clksel_con[26]);
+	div = (con & EMMC_CLK_DIV_MASK) >> EMMC_CLK_DIV_SHIFT;
+
+
+	debug("%s id %ld get_clk %ld\n", __func__, clk->id, DIV_TO_RATE(parent_rate, div));
+
+	return DIV_TO_RATE(parent_rate, div);
+
+}
+
+static ulong rv1108_mmc_set_clk(struct clk *clk, ulong set_rate)
+{
+	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rv1108_cru *cru = priv->cru;
+	int src_clk_div;
+
+	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
+	src_clk_div = DIV_ROUND_UP(parent_rate, set_rate);
+
+	if (src_clk_div > 127) {
+		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+	}
+
+	debug("%s id %ld src_clk_div %d\n", __func__, clk->id, src_clk_div);
+
+	rk_clrsetreg(&cru->clksel_con[26],
+		     EMMC_CLK_DIV_MASK , (src_clk_div -1) << EMMC_CLK_DIV_SHIFT);
+
+	rk_clrsetreg(&cru->clksel_con[25],
+		     EMMC_PLL_SEL_MASK , EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT);
+
+	return rv1108_mmc_get_clk(clk);
+}
+
+
 static ulong rv1108_clk_get_rate(struct clk *clk)
 {
 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
@@ -163,6 +534,31 @@ static ulong rv1108_clk_get_rate(struct clk *clk)
 		return rkclk_pll_get_rate(priv->cru, clk->id);
 	case SCLK_SARADC:
 		return rv1108_saradc_get_clk(priv->cru);
+	case ACLK_VIO0:
+		return rv1108_aclk_vio0_get_clk(priv->cru);
+	case ACLK_VIO1:
+		return rv1108_aclk_vio1_get_clk(priv->cru);
+	case DCLK_VOP:
+		return rv1108_dclk_vop_get_clk(priv->cru);
+	case ACLK_PRE:
+		return rv1108_aclk_bus_get_clk(priv->cru);
+	case ACLK_PERI:
+		return rv1108_aclk_peri_get_clk(priv->cru);
+	case HCLK_PERI:
+		return rv1108_hclk_peri_get_clk(priv->cru);
+	case PCLK_PERI:
+		return rv1108_pclk_peri_get_clk(priv->cru);
+	case SCLK_I2C0_PMU:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		return rv1108_i2c_get_clk(priv->cru, clk->id);
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+	case SCLK_EMMC_SAMPLE:
+		return rv1108_mmc_get_clk(clk);
 	default:
 		return -ENOENT;
 	}
@@ -183,6 +579,39 @@ static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
 	case SCLK_SARADC:
 		new_rate = rv1108_saradc_set_clk(priv->cru, rate);
 		break;
+	case ACLK_VIO0:
+		new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
+		break;
+	case ACLK_VIO1:
+		new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
+		break;
+	case DCLK_VOP:
+		new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
+		break;
+	case ACLK_PRE:
+		new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
+		break;
+	case ACLK_PERI:
+		new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
+		break;
+	case HCLK_PERI:
+		new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
+		break;
+	case PCLK_PERI:
+		new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
+		break;
+	case SCLK_I2C0_PMU:
+	case SCLK_I2C1:
+	case SCLK_I2C2:
+	case SCLK_I2C3:
+		new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
+		break;
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case SCLK_SDMMC:
+	case SCLK_EMMC:
+		new_rate = rv1108_mmc_set_clk(clk, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -197,14 +626,34 @@ static const struct clk_ops rv1108_clk_ops = {
 
 static void rkclk_init(struct rv1108_cru *cru)
 {
-	unsigned int apll = rkclk_pll_get_rate(cru, CLK_ARM);
-	unsigned int dpll = rkclk_pll_get_rate(cru, CLK_DDR);
-	unsigned int gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
+	unsigned int apll, dpll, gpll;
+	unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
+
+	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
+	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
+	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
+	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
+	rv1108_aclk_vio0_set_clk(cru, 297000000);
+	rv1108_aclk_vio1_set_clk(cru, 297000000);
+
+	/* configure apll */
+	rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
+	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
+	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
+	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
+	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
+	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
+
+	apll = rkclk_pll_get_rate(cru, CLK_ARM);
+	dpll = rkclk_pll_get_rate(cru, CLK_DDR);
+	gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
 
 	rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
 		     0 << MAC_CLK_DIV_SHIFT);
 
 	printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
+	printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
+	       aclk_bus, aclk_peri, hclk_peri, pclk_peri);
 }
 
 static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h
index 9219a50a24..10ed9d140f 100644
--- a/include/dt-bindings/clock/rv1108-cru.h
+++ b/include/dt-bindings/clock/rv1108-cru.h
@@ -14,7 +14,6 @@
 #define ARMCLK				3
 
 /* sclk gates (special clocks) */
-#define SCLK_MAC			64
 #define SCLK_SPI0			65
 #define SCLK_NANDC			67
 #define SCLK_SDMMC			68
@@ -35,20 +34,77 @@
 #define SCLK_SDMMC_SAMPLE		84
 #define SCLK_SDIO_SAMPLE		85
 #define SCLK_EMMC_SAMPLE		86
-#define SCLK_MAC_RX			87
-#define SCLK_MAC_TX			88
-#define SCLK_MACREF			89
-#define SCLK_MACREF_OUT			90
-#define SCLK_SARADC			91
+#define SCLK_VENC_CORE			87
+#define SCLK_HEVC_CORE			88
+#define SCLK_HEVC_CABAC			89
+#define SCLK_PWM0_PMU			90
+#define SCLK_I2C0_PMU			91
+#define SCLK_WIFI			92
+#define SCLK_CIFOUT			93
+#define SCLK_MIPI_CSI_OUT		94
+#define SCLK_CIF0			95
+#define SCLK_CIF1			96
+#define SCLK_CIF2			97
+#define SCLK_CIF3			98
+#define SCLK_DSP			99
+#define SCLK_DSP_IOP			100
+#define SCLK_DSP_EPP			101
+#define SCLK_DSP_EDP			102
+#define SCLK_DSP_EDAP			103
+#define SCLK_CVBS_HOST			104
+#define SCLK_HDMI_SFR			105
+#define SCLK_HDMI_CEC			106
+#define SCLK_CRYPTO			107
+#define SCLK_SPI			108
+#define SCLK_SARADC			109
+#define SCLK_TSADC			110
+#define SCLK_MAC_PRE			111
+#define SCLK_MAC			112
+#define SCLK_MAC_RX			113
+#define SCLK_MAC_REF			114
+#define SCLK_MAC_REFOUT			115
+#define SCLK_DSP_PFM			116
+#define SCLK_RGA			117
+#define SCLK_I2C1			118
+#define SCLK_I2C2			119
+#define SCLK_I2C3			120
+#define SCLK_PWM			121
+#define SCLK_ISP			122
+#define SCLK_USBPHY			123
+#define SCLK_I2S0_SRC			124
+#define SCLK_I2S1_SRC			125
+#define SCLK_I2S2_SRC			126
+#define SCLK_UART0_SRC			127
+#define SCLK_UART1_SRC			128
+#define SCLK_UART2_SRC			129
+#define SCLK_MAC_TX			130
+#define SCLK_MACREF			131
+#define SCLK_MACREF_OUT			132
 
+#define DCLK_VOP_SRC			185
+#define DCLK_HDMIPHY			186
+#define DCLK_VOP			187
 
 /* aclk gates */
 #define ACLK_DMAC			192
 #define ACLK_PRE			193
 #define ACLK_CORE			194
 #define ACLK_ENMCORE			195
-#define ACLK_GMAC			196
-
+#define ACLK_RKVENC			196
+#define ACLK_RKVDEC			197
+#define ACLK_VPU			198
+#define ACLK_CIF0			199
+#define ACLK_VIO0			200
+#define ACLK_VIO1			201
+#define ACLK_VOP			202
+#define ACLK_IEP			203
+#define ACLK_RGA			204
+#define ACLK_ISP			205
+#define ACLK_CIF1			206
+#define ACLK_CIF2			207
+#define ACLK_CIF3			208
+#define ACLK_PERI			209
+#define ACLK_GMAC			210
 
 /* pclk gates */
 #define PCLK_GPIO1			256
@@ -67,12 +123,24 @@
 #define PCLK_PWM			269
 #define PCLK_TIMER			270
 #define PCLK_PERI			271
-#define PCLK_GMAC			272
-#define PCLK_SARADC			273
+#define PCLK_GPIO0_PMU			272
+#define PCLK_I2C0_PMU			273
+#define PCLK_PWM0_PMU			274
+#define PCLK_ISP			275
+#define PCLK_VIO			276
+#define PCLK_MIPI_DSI			277
+#define PCLK_HDMI_CTRL			278
+#define PCLK_SARADC			279
+#define PCLK_DSP_CFG			280
+#define PCLK_BUS			281
+#define PCLK_EFUSE0			282
+#define PCLK_EFUSE1			283
+#define PCLK_WDT			284
+#define PCLK_GMAC			285
 
 /* hclk gates */
 #define HCLK_I2S0_8CH			320
-#define HCLK_I2S1_8CH			321
+#define HCLK_I2S1_2CH			321
 #define HCLK_I2S2_2CH			322
 #define HCLK_NANDC			323
 #define HCLK_SDMMC			324
@@ -80,20 +148,37 @@
 #define HCLK_EMMC			326
 #define HCLK_PERI			327
 #define HCLK_SFC			328
+#define HCLK_RKVENC			329
+#define HCLK_RKVDEC			330
+#define HCLK_CIF0			331
+#define HCLK_VIO			332
+#define HCLK_VOP			333
+#define HCLK_IEP			334
+#define HCLK_RGA			335
+#define HCLK_ISP			336
+#define HCLK_CRYPTO_MST			337
+#define HCLK_CRYPTO_SLV			338
+#define HCLK_HOST0			339
+#define HCLK_OTG			340
+#define HCLK_CIF1			341
+#define HCLK_CIF2			342
+#define HCLK_CIF3			343
+#define HCLK_BUS			344
+#define HCLK_VPU			345
 
-#define CLK_NR_CLKS			(HCLK_SFC + 1)
+#define CLK_NR_CLKS			(HCLK_VPU + 1)
 
 /* reset id */
-#define SRST_CORE_PO_AD		0
+#define SRST_CORE_PO_AD			0
 #define SRST_CORE_AD			1
 #define SRST_L2_AD			2
-#define SRST_CPU_NIU_AD		3
+#define SRST_CPU_NIU_AD			3
 #define SRST_CORE_PO			4
 #define SRST_CORE			5
-#define SRST_L2			6
+#define SRST_L2				6
 #define SRST_CORE_DBG			8
 #define PRST_DBG			9
-#define RST_DAP			10
+#define RST_DAP				10
 #define PRST_DBG_NIU			11
 #define ARST_STRC_SYS_AD		15
 
@@ -160,9 +245,9 @@
 #define HRST_SYSBUS			75
 #define PRST_USBGRF			76
 
-#define ARST_PERIPH_NIU		80
-#define HRST_PERIPH_NIU		81
-#define PRST_PERIPH_NIU		82
+#define ARST_PERIPH_NIU			80
+#define HRST_PERIPH_NIU			81
+#define PRST_PERIPH_NIU			82
 #define HRST_PERIPH			83
 #define HRST_SDMMC			84
 #define HRST_SDIO			85
@@ -180,7 +265,7 @@
 #define HRST_HOST0_AUX			96
 #define HRST_HOST0_ARB			97
 #define SRST_HOST0_EHCIPHY		98
-#define SRST_HOST0_UTMI		99
+#define SRST_HOST0_UTMI			99
 #define SRST_USBPOR			100
 #define SRST_UTMI0			101
 #define SRST_UTMI1			102
@@ -227,21 +312,21 @@
 #define HRST_VPU_NIU			141
 #define ARST_VPU			142
 #define HRST_VPU			143
-#define ARST_RKVDEC_NIU		144
-#define HRST_RKVDEC_NIU		145
+#define ARST_RKVDEC_NIU			144
+#define HRST_RKVDEC_NIU			145
 #define ARST_RKVDEC			146
 #define HRST_RKVDEC			147
 #define SRST_RKVDEC_CABAC		148
 #define SRST_RKVDEC_CORE		149
-#define ARST_RKVENC_NIU		150
-#define HRST_RKVENC_NIU		151
+#define ARST_RKVENC_NIU			150
+#define HRST_RKVENC_NIU			151
 #define ARST_RKVENC			152
 #define HRST_RKVENC			153
 #define SRST_RKVENC_CORE		154
 
 #define SRST_DSP_CORE			156
 #define SRST_DSP_SYS			157
-#define SRST_DSP_GLOBAL		158
+#define SRST_DSP_GLOBAL			158
 #define SRST_DSP_OECM			159
 #define PRST_DSP_IOP_NIU		160
 #define ARST_DSP_EPP_NIU		161
@@ -259,7 +344,7 @@
 #define SRST_PMU_I2C0			173
 #define PRST_PMU_I2C0			174
 #define PRST_PMU_GPIO0			175
-#define PRST_PMU_INTMEM		176
+#define PRST_PMU_INTMEM			176
 #define PRST_PMU_PWM0			177
 #define SRST_PMU_PWM0			178
 #define PRST_PMU_GRF			179
-- 
2.19.2



More information about the U-Boot mailing list