U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: WeiHao Li <cn.liweihao@gmail.com>
To: u-boot@lists.denx.de
Cc: antonio.borneo@foss.st.com, mk7.kang@samsung.com,
	gregkh@linuxfoundation.org, semen.protsenko@linaro.org,
	mikhail.kshevetskiy@iopsys.eu, bb@ti.com,
	justin.swartz@risingedge.co.za, lukasz.czechowski@thaumatec.com,
	robh@kernel.org, tharvey@gateworks.com,
	clement.legoffic@foss.st.com, marek.vasut@mailbox.org,
	dinesh.maniyam@altera.com, patrice.chotard@foss.st.com,
	festevam@gmail.com, jerome.forissier@linaro.org,
	quentin.schulz@cherry.de, andrew.goodbody@linaro.org,
	sumit.garg@kernel.org, ag.dev.uboot@gmail.com,
	rfried.dev@gmail.com, joe.hershberger@ni.com,
	jh80.chung@samsung.com, peng.fan@nxp.com, seanga2@gmail.com,
	lukma@denx.de, kever.yang@rock-chips.com,
	philipp.tomsich@vrull.eu, sjg@chromium.org, trini@konsulko.com,
	WeiHao Li <cn.liweihao@gmail.com>, WeiHao Li <ieiao@outlook.com>
Subject: [PATCH 06/10] clk: rockchip: rk3368: Add vop clk get/set
Date: Thu,  7 Aug 2025 15:44:14 +0800	[thread overview]
Message-ID: <20250807074419.336752-7-cn.liweihao@gmail.com> (raw)
In-Reply-To: <20250807074419.336752-1-cn.liweihao@gmail.com>

Patch get form Rockchip downstream uboot repository.

Signed-off-by: WeiHao Li <ieiao@outlook.com>
---
 .../include/asm/arch-rockchip/cru_rk3368.h    |   5 +
 .../include/asm/arch-rockchip/grf_rk3368.h    | 111 ++++++++-
 drivers/clk/rockchip/clk_rk3368.c             | 230 ++++++++++++++++++
 .../include/dt-bindings/clock/rk3368-cru.h    |   1 +
 4 files changed, 346 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
index 29f90454d4..8178d4e013 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
@@ -150,6 +150,11 @@ enum {
 	DCLK_VOP_DIV_SHIFT		= 0,
 	DCLK_VOP_DIV_MASK		= GENMASK(7, 0),
 
+	/* CLKSEL21_CON */
+	HCLK_VOP_DIV_SHIFT		= 0,
+	HCLK_VOP_DIV_MASK		= GENMASK(5, 0),
+	HCLK_VOP_DIV_WIDTH		= 5,
+
 	/* CLKSEL_CON25 */
 	CLK_SARADC_DIV_CON_SHIFT	= 8,
 	CLK_SARADC_DIV_CON_MASK		= GENMASK(15, 8),
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3368.h b/arch/arm/include/asm/arch-rockchip/grf_rk3368.h
index 0079d20078..ef6cd167e2 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3368.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3368.h
@@ -77,11 +77,99 @@ struct rk3368_grf {
 	u32 soc_con15;
 	u32 soc_con16;
 	u32 soc_con17;
-	u32 reserved5[0x6e];
+	u32 reserved5[0xe];
+	u32 soc_status0;
+	u32 soc_status1;
+	u32 soc_status2;
+	u32 soc_status3;
+	u32 soc_status4;
+	u32 soc_status5;
+	u32 soc_status6;
+	u32 soc_status7;
+	u32 soc_status8;
+	u32 soc_status9;
+	u32 soc_status10;
+	u32 soc_status11;
+	u32 soc_status12;
+	u32 soc_status13;
+	u32 soc_status14;
+	u32 soc_status15;
+	u32 reserved6[0x10];
+	u32 cpu_con0;
+	u32 cpu_con1;
+	u32 cpu_con2;
+	u32 cpu_con3;
+	u32 reserved7[0x4];
+	u32 cpu_status0;
+	u32 cpu_status1;
+	u32 reserved8[0x6];
+	u32 cci_status0;
+	u32 cci_status1;
+	u32 cci_status2;
+	u32 cci_status3;
+	u32 cci_status4;
+	u32 cci_status5;
+	u32 cci_status6;
+	u32 cci_status7;
+	u32 cci_status8;
+	u32 cci_status9;
+	u32 cci_status10;
+	u32 cci_status11;
+	u32 cci_status12;
+	u32 cci_status13;
+	u32 cci_status14;
+	u32 cci_status15;
+	u32 reserved9[0x20];
 	u32 ddrc0_con0;
+	u32 reserved10[0x1f];
+	u32 sig_detect_con;
+	u32 reserved11[0x3];
+	u32 sig_detect_status;
+	u32 reserved12[0x3];
+	u32 sig_detect_clr;
+	u32 reserved13[0x17];
+	u32 uoc0_con0;
+	u32 reserved14[0x5];
+	u32 uoc1_con1;
+	u32 uoc1_con2;
+	u32 uoc1_con3;
+	u32 uoc1_con4;
+	u32 uoc1_con5;
+	u32 reserved15[0x3];
+	u32 uoc3_con0;
+	u32 uoc3_con1;
+	u32 uoc4_con0;
+	u32 uoc4_con1;
+	u32 reserved16[0xe];
+	u32 usbphy_con0;
+	u32 usbphy_con1;
+	u32 usbphy_con2;
+	u32 usbphy_con3;
+	u32 usbphy_con4;
+	u32 usbphy_con5;
+	u32 usbphy_con6;
+	u32 usbphy_con7;
+	u32 usbphy_con8;
+	u32 usbphy_con9;
+	u32 usbphy_con10;
+	u32 usbphy_con11;
+	u32 usbphy_con12;
+	u32 usbphy_con13;
+	u32 usbphy_con14;
+	u32 usbphy_con15;
+	u32 reserved17[0x10];
+	u32 pvtm_con0;
+	u32 pvtm_con1;
+	u32 pvtm_con2;
+	u32 pvtm_status0;
+	u32 pvtm_status1;
+	u32 pvtm_status2;
+	u32 reserved18[0x3a];
+	u32 io_vsel;
 };
 check_member(rk3368_grf, soc_con17, 0x444);
 check_member(rk3368_grf, ddrc0_con0, 0x600);
+check_member(rk3368_grf, io_vsel, 0x900);
 
 struct rk3368_pmu_grf {
 	u32 gpio0a_iomux;
@@ -104,6 +192,27 @@ struct rk3368_pmu_grf {
 check_member(rk3368_pmu_grf, gpio0h_sr, 0x34);
 check_member(rk3368_pmu_grf, os_reg[0], 0x200);
 
+/* GRF_SOC_CON7 */
+enum {
+	RK3368_DPHY_TX0_RXMODE_SHIFT = 6,
+	RK3368_DPHY_TX0_RXMODE_MASK =
+	   0x1 << RK3368_DPHY_TX0_RXMODE_SHIFT,
+	RK3368_DPHY_TX0_RXMODE_EN = 1,
+	RK3368_DPHY_TX0_RXMODE_DIS = 0,
+
+	RK3368_DPHY_TX0_TXSTOPMODE_SHIFT = 7,
+	RK3368_DPHY_TX0_TXSTOPMODE_MASK =
+	   0xf << RK3368_DPHY_TX0_TXSTOPMODE_SHIFT,
+	RK3368_DPHY_TX0_TXSTOPMODE_EN = 0xf,
+	RK3368_DPHY_TX0_TXSTOPMODE_DIS = 0,
+
+	RK3368_DPHY_TX0_TURNDISABLE_SHIFT = 5,
+	RK3368_DPHY_TX0_TURNDISABLE_MASK =
+	   0x1 << RK3368_DPHY_TX0_TURNDISABLE_SHIFT,
+	RK3368_DPHY_TX0_TURNDISABLE_EN = 1,
+	RK3368_DPHY_TX0_TURNDISABLE_DIS = 0,
+};
+
 /*GRF_SOC_CON11/12/13*/
 enum {
 	MCU_SRAM_BASE_BIT27_BIT12_SHIFT	= 0,
diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c
index 2a20c8b50f..17707600ee 100644
--- a/drivers/clk/rockchip/clk_rk3368.c
+++ b/drivers/clk/rockchip/clk_rk3368.c
@@ -31,9 +31,27 @@ struct rk3368_clk_plat {
 #endif
 
 struct pll_div {
+	ulong rate;
 	u32 nr;
 	u32 nf;
 	u32 no;
+	u32 nb;
+};
+
+#define RK3368_PLL_RATE(_rate, _nr, _nf, _no, _nb)	\
+{							\
+	.rate	= _rate##U,				\
+	.nr = _nr,					\
+	.nf = _nf,					\
+	.no = _no,					\
+	.nb = _nb,					\
+}
+
+static struct pll_div rk3368_pll_rates[] = {
+	/* _mhz,  _nr, _nf, _no, _nb */
+	RK3368_PLL_RATE(594000000, 1, 99, 4, 16),
+	RK3368_PLL_RATE(424200000, 5, 707, 8, 0),
+	RK3368_PLL_RATE(410000000, 3, 205, 4, 16),
 };
 
 #define OSC_HZ		(24 * 1000 * 1000)
@@ -41,6 +59,7 @@ struct pll_div {
 #define APLL_B_HZ	(816 * 1000 * 1000)
 #define GPLL_HZ		(576 * 1000 * 1000)
 #define CPLL_HZ		(400 * 1000 * 1000)
+#define NPLL_HZ		(594 * 1000 * 1000)
 
 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
 
@@ -61,6 +80,105 @@ static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6);
 
 static ulong rk3368_clk_get_rate(struct clk *clk);
 
+#define VCO_MAX_KHZ	2200000
+#define VCO_MIN_KHZ	440000
+#define FREF_MAX_KHZ	2200000
+#define FREF_MIN_KHZ	269
+#define PLL_LIMIT_FREQ	400000000
+
+struct pll_div *rkclk_get_pll_config(ulong freq_hz)
+{
+	unsigned int rate_count = ARRAY_SIZE(rk3368_pll_rates);
+	int i;
+
+	for (i = 0; i < rate_count; i++) {
+		if (freq_hz == rk3368_pll_rates[i].rate)
+			return &rk3368_pll_rates[i];
+	}
+	return NULL;
+}
+
+static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div)
+{
+	struct pll_div *best_div = NULL;
+	uint ref_khz = OSC_HZ / 1000, nr, nf = 0;
+	uint fref_khz;
+	uint diff_khz, best_diff_khz;
+	const uint max_nr = 1 << 6, max_nf = 1 << 12, max_no = 1 << 4;
+	uint vco_khz;
+	uint no = 1;
+	uint freq_khz = freq_hz / 1000;
+
+	if (!freq_hz) {
+		printf("%s: the frequency can not be 0 Hz\n", __func__);
+		return -EINVAL;
+	}
+
+	no = DIV_ROUND_UP(VCO_MIN_KHZ, freq_khz);
+	if (ext_div) {
+		*ext_div = DIV_ROUND_UP(PLL_LIMIT_FREQ, freq_hz);
+		no = DIV_ROUND_UP(no, *ext_div);
+	}
+
+	best_div = rkclk_get_pll_config(freq_hz * (*ext_div));
+	if (best_div) {
+		div->nr = best_div->nr;
+		div->nf = best_div->nf;
+		div->no = best_div->no;
+		div->nb = best_div->nb;
+		return 0;
+	}
+
+	/* only even divisors (and 1) are supported */
+	if (no > 1)
+		no = DIV_ROUND_UP(no, 2) * 2;
+
+	vco_khz = freq_khz * no;
+	if (ext_div)
+		vco_khz *= *ext_div;
+
+	if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ || no > max_no) {
+		printf("%s: Cannot find out VCO for Frequency (%luHz).\n",
+		       __func__, freq_hz);
+		return -1;
+	}
+
+	div->no = no;
+
+	best_diff_khz = vco_khz;
+	for (nr = 1; nr < max_nr && best_diff_khz; nr++) {
+		fref_khz = ref_khz / nr;
+		if (fref_khz < FREF_MIN_KHZ)
+			break;
+		if (fref_khz > FREF_MAX_KHZ)
+			continue;
+
+		nf = vco_khz / fref_khz;
+		if (nf >= max_nf)
+			continue;
+		diff_khz = vco_khz - nf * fref_khz;
+		if (nf + 1 < max_nf && diff_khz > fref_khz / 2) {
+			nf++;
+			diff_khz = fref_khz - diff_khz;
+		}
+
+		if (diff_khz >= best_diff_khz)
+			continue;
+
+		best_diff_khz = diff_khz;
+		div->nr = nr;
+		div->nf = nf;
+	}
+
+	if (best_diff_khz > 4 * 1000) {
+		printf("%s:Fail to match output freq %lu,best_is %u Hz\n",
+		       __func__, freq_hz, best_diff_khz * 1000);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /* Get pll rate by id */
 static uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru,
 				   enum rk3368_pll_id pll_id)
@@ -525,6 +643,104 @@ static ulong rk3368_bus_set_clk(struct rk3368_cru *cru,
 	}
 	return rk3368_bus_get_clk(cru, clk_id);
 }
+
+static ulong rk3368_vop_get_clk(struct rk3368_cru *cru,  int clk_id)
+{
+	u32 div, con, parent, sel;
+
+	switch (clk_id) {
+	case DCLK_VOP:
+		con = readl(&cru->clksel_con[20]);
+		div = con & DCLK_VOP_DIV_MASK;
+		parent = rkclk_pll_get_rate(cru, NPLL);
+		break;
+	case ACLK_VOP:
+		con = readl(&cru->clksel_con[19]);
+		div = con & ACLK_VOP_DIV_MASK;
+		sel =  (con & (ACLK_VOP_PLL_SEL_MASK <<
+			ACLK_VOP_PLL_SEL_SHIFT)) >>
+			ACLK_VOP_PLL_SEL_SHIFT;
+		if (sel == ACLK_VOP_PLL_SEL_CPLL)
+			parent = rkclk_pll_get_rate(cru, CPLL);
+		else if (ACLK_VOP_PLL_SEL_GPLL)
+			parent = rkclk_pll_get_rate(cru, GPLL);
+		else
+			parent = 480000000;
+		break;
+	case HCLK_VOP:
+		parent = rk3368_vop_get_clk(cru, ACLK_VOP);
+		con = readl(&cru->clksel_con[21]);
+		div = con & HCLK_VOP_DIV_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3368_vop_set_clk(struct rk3368_cru *cru, int clk_id, uint hz)
+{
+	struct pll_div npll_config = {0};
+	u32 lcdc_div;
+	int ret;
+
+	switch (clk_id) {
+	case DCLK_VOP:
+		if (!(NPLL_HZ % hz)) {
+			rkclk_set_pll(cru, NPLL, rkclk_get_pll_config(NPLL_HZ));
+			lcdc_div = NPLL_HZ / hz;
+		} else {
+			ret = pll_para_config(hz, &npll_config, &lcdc_div);
+			if (ret)
+				return ret;
+
+			rkclk_set_pll(cru, NPLL, &npll_config);
+		}
+		/* vop dclk source clk: npll,dclk_div: 1 */
+		rk_clrsetreg(&cru->clksel_con[20],
+			     (DCLK_VOP_PLL_SEL_MASK << DCLK_VOP_PLL_SEL_SHIFT) |
+			     (DCLK_VOP_DIV_MASK << DCLK_VOP_DIV_SHIFT),
+			     (DCLK_VOP_PLL_SEL_NPLL << DCLK_VOP_PLL_SEL_SHIFT) |
+			     (lcdc_div - 1) << DCLK_VOP_DIV_SHIFT);
+		break;
+	case ACLK_VOP:
+		if ((rkclk_pll_get_rate(cru, CPLL) % hz) == 0) {
+			lcdc_div = rkclk_pll_get_rate(cru, CPLL) / hz;
+			rk_clrsetreg(&cru->clksel_con[19],
+				     (ACLK_VOP_PLL_SEL_MASK <<
+				     ACLK_VOP_PLL_SEL_SHIFT) |
+				     (ACLK_VOP_DIV_MASK <<
+				     ACLK_VOP_DIV_SHIFT),
+				     (ACLK_VOP_PLL_SEL_CPLL <<
+				     ACLK_VOP_PLL_SEL_SHIFT) |
+				     (lcdc_div - 1) <<
+				     ACLK_VOP_DIV_SHIFT);
+		} else {
+			lcdc_div = rkclk_pll_get_rate(cru, GPLL) / hz;
+			rk_clrsetreg(&cru->clksel_con[19],
+				     (ACLK_VOP_PLL_SEL_MASK <<
+				     ACLK_VOP_PLL_SEL_SHIFT) |
+				     (ACLK_VOP_DIV_MASK <<
+				     ACLK_VOP_DIV_SHIFT),
+				     (ACLK_VOP_PLL_SEL_GPLL <<
+				     ACLK_VOP_PLL_SEL_SHIFT) |
+				     (lcdc_div - 1) <<
+				     ACLK_VOP_DIV_SHIFT);
+		}
+		break;
+	case HCLK_VOP:
+		lcdc_div = rk3368_vop_get_clk(cru, ACLK_VOP) / hz;
+		rk_clrsetreg(&cru->clksel_con[21],
+			     HCLK_VOP_DIV_MASK,
+			     (lcdc_div - 1) << HCLK_VOP_DIV_SHIFT);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return rk3368_vop_get_clk(cru, clk_id);
+}
 #endif
 
 static ulong rk3368_clk_get_rate(struct clk *clk)
@@ -565,6 +781,13 @@ static ulong rk3368_clk_get_rate(struct clk *clk)
 	case SCLK_SARADC:
 		rate = rk3368_saradc_get_clk(priv->cru);
 		break;
+#if !IS_ENABLED(CONFIG_XPL_BUILD)
+	case ACLK_VOP:
+	case DCLK_VOP:
+	case HCLK_VOP:
+		rate = rk3368_vop_get_clk(priv->cru, clk->id);
+		break;
+#endif
 	default:
 		return -ENOENT;
 	}
@@ -609,6 +832,13 @@ static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
 	case SCLK_SARADC:
 		ret =  rk3368_saradc_set_clk(priv->cru, rate);
 		break;
+#if !defined(CONFIG_XPL_BUILD)
+	case ACLK_VOP:
+	case DCLK_VOP:
+	case HCLK_VOP:
+		ret = rk3368_vop_set_clk(priv->cru, clk->id, rate);
+		break;
+#endif
 	default:
 		return -ENOENT;
 	}
diff --git a/dts/upstream/include/dt-bindings/clock/rk3368-cru.h b/dts/upstream/include/dt-bindings/clock/rk3368-cru.h
index ebae3cbf81..b951e29069 100644
--- a/dts/upstream/include/dt-bindings/clock/rk3368-cru.h
+++ b/dts/upstream/include/dt-bindings/clock/rk3368-cru.h
@@ -72,6 +72,7 @@
 #define SCLK_SFC		126
 #define SCLK_MAC		127
 #define SCLK_MACREF_OUT		128
+#define SCLK_MIPIDSI_24M	129
 #define SCLK_TIMER10		133
 #define SCLK_TIMER11		134
 #define SCLK_TIMER12		135
-- 
2.39.5


  parent reply	other threads:[~2025-08-07  8:27 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-07  7:44 [PATCH 00/10] Add RK3368 YMD8_MB board support WeiHao Li
2025-08-07  7:44 ` [PATCH 01/10] clk: rockchip: rk3368: fix gmac clock error WeiHao Li
2025-08-07  7:44 ` [PATCH 02/10] mmc: rockchip: fix clock get wrong index WeiHao Li
2025-08-12 17:49   ` Jonas Karlman
2025-08-13  0:24     ` 李维豪
2025-08-07  7:44 ` [PATCH 03/10] net: rockchip: rk3368: add set_to_rmii WeiHao Li
2025-08-07  7:44 ` [PATCH 04/10] clk: rockchip: rk3368: Add bus clk get/set WeiHao Li
2025-08-07  7:44 ` [PATCH 05/10] clk: rockchip: rk3368: Adjust pll clk get WeiHao Li
2025-08-07  7:44 ` WeiHao Li [this message]
2025-08-07  7:44 ` [PATCH 07/10] video: rockchip: vop add bridge support WeiHao Li
2025-08-07  7:44 ` [PATCH 08/10] video: rockchip: add rk3368 vop support WeiHao Li
2025-08-07  7:44 ` [PATCH 09/10] video: panel: add rm72014 panel support WeiHao Li
2025-08-07  7:44 ` [PATCH 10/10] board: rockchip: add rk3368 ymd8_mb support WeiHao Li
2025-08-11 15:01   ` Quentin Schulz
2025-08-12  1:25     ` 李维豪
2025-08-12  8:11       ` Quentin Schulz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250807074419.336752-7-cn.liweihao@gmail.com \
    --to=cn.liweihao@gmail.com \
    --cc=ag.dev.uboot@gmail.com \
    --cc=andrew.goodbody@linaro.org \
    --cc=antonio.borneo@foss.st.com \
    --cc=bb@ti.com \
    --cc=clement.legoffic@foss.st.com \
    --cc=dinesh.maniyam@altera.com \
    --cc=festevam@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=ieiao@outlook.com \
    --cc=jerome.forissier@linaro.org \
    --cc=jh80.chung@samsung.com \
    --cc=joe.hershberger@ni.com \
    --cc=justin.swartz@risingedge.co.za \
    --cc=kever.yang@rock-chips.com \
    --cc=lukasz.czechowski@thaumatec.com \
    --cc=lukma@denx.de \
    --cc=marek.vasut@mailbox.org \
    --cc=mikhail.kshevetskiy@iopsys.eu \
    --cc=mk7.kang@samsung.com \
    --cc=patrice.chotard@foss.st.com \
    --cc=peng.fan@nxp.com \
    --cc=philipp.tomsich@vrull.eu \
    --cc=quentin.schulz@cherry.de \
    --cc=rfried.dev@gmail.com \
    --cc=robh@kernel.org \
    --cc=seanga2@gmail.com \
    --cc=semen.protsenko@linaro.org \
    --cc=sjg@chromium.org \
    --cc=sumit.garg@kernel.org \
    --cc=tharvey@gateworks.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox