summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-04-23 11:34:53 -0600
committerTom Rini <[email protected]>2025-04-23 11:34:53 -0600
commit6e325df4891cb9be954f1e62f16cd3096b267bdb (patch)
tree1ddf3ed2807a48df09912561867a26b18ac30f0b /drivers
parent873bca77a3dd4f6ba69c244bb1aaecb82679271f (diff)
parent1f07d257305c168551370fbaddbc2b2d83aedde4 (diff)
Merge tag 'u-boot-rockchip-20250423' of https://source.denx.de/u-boot/custodians/u-boot-rockchip
CI: https://source.denx.de/u-boot/custodians/u-boot-rockchip/-/pipelines/25909 Please pull the updates for rockchip platform: - New SoC support: RK3528, RK3576 - New Board support: rk3528 Radxa E20C, rk3576 Firefly ROC-RK3576-PC; - Add generic board for rk3288 and rk3399; - rng driver binding update; - misc updates on board level or header files;
Diffstat (limited to 'drivers')
-rw-r--r--drivers/adc/rockchip-saradc.c10
-rw-r--r--drivers/clk/rockchip/Makefile2
-rw-r--r--drivers/clk/rockchip/clk_pll.c23
-rw-r--r--drivers/clk/rockchip/clk_rk3528.c1754
-rw-r--r--drivers/clk/rockchip/clk_rk3576.c2513
-rw-r--r--drivers/misc/rockchip-otp.c15
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c1
-rw-r--r--drivers/mmc/rockchip_sdhci.c54
-rw-r--r--drivers/net/dwc_eth_qos.c8
-rw-r--r--drivers/net/dwc_eth_qos_rockchip.c292
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c63
-rw-r--r--drivers/pinctrl/rockchip/Makefile2
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rk3528.c273
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rk3576.c278
-rw-r--r--drivers/pinctrl/rockchip/pinctrl-rockchip.h3
-rw-r--r--drivers/ram/rockchip/Makefile2
-rw-r--r--drivers/ram/rockchip/sdram_rk3528.c33
-rw-r--r--drivers/ram/rockchip/sdram_rk3576.c35
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/rst-rk3528.c302
-rw-r--r--drivers/reset/rst-rk3576.c647
-rw-r--r--drivers/rng/rockchip_rng.c79
-rw-r--r--drivers/usb/gadget/Kconfig1
23 files changed, 6370 insertions, 22 deletions
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c
index 7cf9735f60d..1515951403c 100644
--- a/drivers/adc/rockchip-saradc.c
+++ b/drivers/adc/rockchip-saradc.c
@@ -339,6 +339,14 @@ static const struct rockchip_saradc_data rk3399_saradc_data = {
.stop = rockchip_saradc_stop_v1,
};
+static const struct rockchip_saradc_data rk3528_saradc_data = {
+ .num_bits = 10,
+ .num_channels = 4,
+ .clk_rate = 1000000,
+ .channel_data = rockchip_saradc_channel_data_v2,
+ .start_channel = rockchip_saradc_start_channel_v2,
+};
+
static const struct rockchip_saradc_data rk3588_saradc_data = {
.num_bits = 12,
.num_channels = 8,
@@ -354,6 +362,8 @@ static const struct udevice_id rockchip_saradc_ids[] = {
.data = (ulong)&rk3066_tsadc_data },
{ .compatible = "rockchip,rk3399-saradc",
.data = (ulong)&rk3399_saradc_data },
+ { .compatible = "rockchip,rk3528-saradc",
+ .data = (ulong)&rk3528_saradc_data },
{ .compatible = "rockchip,rk3588-saradc",
.data = (ulong)&rk3588_saradc_data },
{ }
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 9e379cc2e3b..34b63d4df34 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -15,7 +15,9 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += clk_rk3308.o
obj-$(CONFIG_ROCKCHIP_RK3328) += clk_rk3328.o
obj-$(CONFIG_ROCKCHIP_RK3368) += clk_rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3528) += clk_rk3528.o
obj-$(CONFIG_ROCKCHIP_RK3568) += clk_rk3568.o
+obj-$(CONFIG_ROCKCHIP_RK3576) += clk_rk3576.o
obj-$(CONFIG_ROCKCHIP_RK3588) += clk_rk3588.o
obj-$(CONFIG_ROCKCHIP_RV1108) += clk_rv1108.o
obj-$(CONFIG_ROCKCHIP_RV1126) += clk_rv1126.o
diff --git a/drivers/clk/rockchip/clk_pll.c b/drivers/clk/rockchip/clk_pll.c
index 44c6f14618d..9dec40b1fe8 100644
--- a/drivers/clk/rockchip/clk_pll.c
+++ b/drivers/clk/rockchip/clk_pll.c
@@ -309,9 +309,11 @@ static int rk3036_pll_set_rate(struct rockchip_pll_clock *pll,
* When power on or changing PLL setting,
* we must force PLL into slow mode to ensure output stable clock.
*/
- rk_clrsetreg(base + pll->mode_offset,
- pll->mode_mask << pll->mode_shift,
- RKCLK_PLL_MODE_SLOW << pll->mode_shift);
+ if (!(pll->pll_flags & ROCKCHIP_PLL_FIXED_MODE)) {
+ rk_clrsetreg(base + pll->mode_offset,
+ pll->mode_mask << pll->mode_shift,
+ RKCLK_PLL_MODE_SLOW << pll->mode_shift);
+ }
/* Power down */
rk_setreg(base + pll->con_offset + 0x4,
@@ -345,8 +347,11 @@ static int rk3036_pll_set_rate(struct rockchip_pll_clock *pll,
while (!(readl(base + pll->con_offset + 0x4) & (1 << pll->lock_shift)))
udelay(1);
- rk_clrsetreg(base + pll->mode_offset, pll->mode_mask << pll->mode_shift,
- RKCLK_PLL_MODE_NORMAL << pll->mode_shift);
+ if (!(pll->pll_flags & ROCKCHIP_PLL_FIXED_MODE)) {
+ rk_clrsetreg(base + pll->mode_offset,
+ pll->mode_mask << pll->mode_shift,
+ RKCLK_PLL_MODE_NORMAL << pll->mode_shift);
+ }
debug("PLL at %p: con0=%x con1= %x con2= %x mode= %x\n",
pll, readl(base + pll->con_offset),
readl(base + pll->con_offset + 0x4),
@@ -362,12 +367,18 @@ static ulong rk3036_pll_get_rate(struct rockchip_pll_clock *pll,
u32 refdiv, fbdiv, postdiv1, postdiv2, dsmpd, frac;
u32 con = 0, shift, mask;
ulong rate;
+ int mode;
con = readl(base + pll->mode_offset);
shift = pll->mode_shift;
mask = pll->mode_mask << shift;
- switch ((con & mask) >> shift) {
+ if (!(pll->pll_flags & ROCKCHIP_PLL_FIXED_MODE))
+ mode = (con & mask) >> shift;
+ else
+ mode = RKCLK_PLL_MODE_NORMAL;
+
+ switch (mode) {
case RKCLK_PLL_MODE_SLOW:
return OSC_HZ;
case RKCLK_PLL_MODE_NORMAL:
diff --git a/drivers/clk/rockchip/clk_rk3528.c b/drivers/clk/rockchip/clk_rk3528.c
new file mode 100644
index 00000000000..06f20895acc
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rk3528.c
@@ -0,0 +1,1754 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ * Author: Joseph Chen <[email protected]>
+ */
+
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rk3528.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rockchip,rk3528-cru.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
+
+/*
+ * PLL attention.
+ *
+ * [FRAC PLL]: GPLL, PPLL, DPLL
+ * - frac mode: refdiv can be 1 or 2 only
+ * - int mode: refdiv has no special limit
+ * - VCO range: [950, 3800] MHZ
+ *
+ * [INT PLL]: CPLL, APLL
+ * - int mode: refdiv can be 1 or 2 only
+ * - VCO range: [475, 1900] MHZ
+ *
+ * [PPLL]: normal mode only.
+ *
+ */
+static struct rockchip_pll_rate_table rk3528_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), /* GPLL */
+ RK3036_PLL_RATE(1092000000, 2, 91, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 42, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0), /* PPLL */
+ RK3036_PLL_RATE(996000000, 2, 83, 1, 1, 1, 0), /* CPLL */
+ RK3036_PLL_RATE(960000000, 1, 40, 1, 1, 1, 0),
+ RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
+ RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE(600000000, 1, 50, 2, 1, 1, 0),
+ RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
+ RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
+ RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
+ RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
+ RK3036_PLL_RATE(96000000, 1, 24, 3, 2, 1, 0),
+ { /* sentinel */ },
+};
+
+static struct rockchip_pll_clock rk3528_pll_clks[] = {
+ [APLL] = PLL(pll_rk3328, PLL_APLL, RK3528_PLL_CON(0),
+ RK3528_MODE_CON, 0, 10, 0, rk3528_pll_rates),
+
+ [CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3528_PLL_CON(8),
+ RK3528_MODE_CON, 2, 10, 0, rk3528_pll_rates),
+
+ [GPLL] = PLL(pll_rk3328, PLL_GPLL, RK3528_PLL_CON(24),
+ RK3528_MODE_CON, 4, 10, 0, rk3528_pll_rates),
+
+ [PPLL] = PLL(pll_rk3328, PLL_PPLL, RK3528_PCIE_PLL_CON(32),
+ RK3528_MODE_CON, 6, 10, ROCKCHIP_PLL_FIXED_MODE, rk3528_pll_rates),
+
+ [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3528_DDRPHY_PLL_CON(16),
+ RK3528_DDRPHY_MODE_CON, 0, 10, 0, rk3528_pll_rates),
+};
+
+#define RK3528_CPUCLK_RATE(_rate, _aclk_m_core, _pclk_dbg) \
+{ \
+ .rate = _rate##U, \
+ .aclk_div = (_aclk_m_core), \
+ .pclk_div = (_pclk_dbg), \
+}
+
+/* sign-off: _aclk_m_core: 550M, _pclk_dbg: 137.5M, */
+static struct rockchip_cpu_rate_table rk3528_cpu_rates[] = {
+ RK3528_CPUCLK_RATE(1896000000, 1, 13),
+ RK3528_CPUCLK_RATE(1800000000, 1, 12),
+ RK3528_CPUCLK_RATE(1704000000, 1, 11),
+ RK3528_CPUCLK_RATE(1608000000, 1, 11),
+ RK3528_CPUCLK_RATE(1512000000, 1, 11),
+ RK3528_CPUCLK_RATE(1416000000, 1, 9),
+ RK3528_CPUCLK_RATE(1296000000, 1, 8),
+ RK3528_CPUCLK_RATE(1200000000, 1, 8),
+ RK3528_CPUCLK_RATE(1188000000, 1, 8),
+ RK3528_CPUCLK_RATE(1092000000, 1, 7),
+ RK3528_CPUCLK_RATE(1008000000, 1, 6),
+ RK3528_CPUCLK_RATE(1000000000, 1, 6),
+ RK3528_CPUCLK_RATE(996000000, 1, 6),
+ RK3528_CPUCLK_RATE(960000000, 1, 6),
+ RK3528_CPUCLK_RATE(912000000, 1, 6),
+ RK3528_CPUCLK_RATE(816000000, 1, 5),
+ RK3528_CPUCLK_RATE(600000000, 1, 3),
+ RK3528_CPUCLK_RATE(594000000, 1, 3),
+ RK3528_CPUCLK_RATE(408000000, 1, 2),
+ RK3528_CPUCLK_RATE(312000000, 1, 2),
+ RK3528_CPUCLK_RATE(216000000, 1, 1),
+ RK3528_CPUCLK_RATE(96000000, 1, 0),
+};
+
+/*
+ *
+ * rational_best_approximation(31415, 10000,
+ * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+ unsigned long given_denominator,
+ unsigned long max_numerator,
+ unsigned long max_denominator,
+ unsigned long *best_numerator,
+ unsigned long *best_denominator)
+{
+ unsigned long n, d, n0, d0, n1, d1;
+
+ n = given_numerator;
+ d = given_denominator;
+ n0 = 0;
+ d1 = 0;
+ n1 = 1;
+ d0 = 1;
+ for (;;) {
+ unsigned long t, a;
+
+ if (n1 > max_numerator || d1 > max_denominator) {
+ n1 = n0;
+ d1 = d0;
+ break;
+ }
+ if (d == 0)
+ break;
+ t = d;
+ a = n / d;
+ d = n % d;
+ n = t;
+ t = n0 + a * n1;
+ n0 = n1;
+ n1 = t;
+ t = d0 + a * d1;
+ d0 = d1;
+ d1 = t;
+ }
+ *best_numerator = n1;
+ *best_denominator = d1;
+}
+
+static int rk3528_armclk_set_clk(struct rk3528_clk_priv *priv, ulong new_rate)
+{
+ const struct rockchip_cpu_rate_table *rate;
+ struct rk3528_cru *cru = priv->cru;
+ ulong old_rate;
+
+ rate = rockchip_get_cpu_settings(rk3528_cpu_rates, new_rate);
+ if (!rate) {
+ printf("%s unsupported rate\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * set up dependent divisors for DBG and ACLK clocks.
+ */
+ old_rate = rockchip_pll_get_rate(&rk3528_pll_clks[APLL], priv->cru, APLL);
+ if (old_rate > new_rate) {
+ if (rockchip_pll_set_rate(&rk3528_pll_clks[APLL],
+ priv->cru, APLL, new_rate))
+ return -EINVAL;
+
+ rk_clrsetreg(&cru->clksel_con[40], RK3528_DIV_PCLK_DBG_MASK,
+ rate->pclk_div << RK3528_DIV_PCLK_DBG_SHIFT);
+
+ rk_clrsetreg(&cru->clksel_con[39], RK3528_DIV_ACLK_M_CORE_MASK,
+ rate->aclk_div << RK3528_DIV_ACLK_M_CORE_SHIFT);
+ } else if (old_rate < new_rate) {
+ rk_clrsetreg(&cru->clksel_con[40], RK3528_DIV_PCLK_DBG_MASK,
+ rate->pclk_div << RK3528_DIV_PCLK_DBG_SHIFT);
+
+ rk_clrsetreg(&cru->clksel_con[39], RK3528_DIV_ACLK_M_CORE_MASK,
+ rate->aclk_div << RK3528_DIV_ACLK_M_CORE_SHIFT);
+
+ if (rockchip_pll_set_rate(&rk3528_pll_clks[APLL],
+ priv->cru, APLL, new_rate))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static ulong rk3528_ppll_matrix_get_rate(struct rk3528_clk_priv *priv,
+ ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, mask, shift;
+ void *reg;
+
+ switch (clk_id) {
+ case CLK_PPLL_50M_MATRIX:
+ case CLK_GMAC1_RMII_VPU:
+ mask = PCIE_CLK_MATRIX_50M_SRC_DIV_MASK;
+ shift = PCIE_CLK_MATRIX_50M_SRC_DIV_SHIFT;
+ reg = &cru->pcieclksel_con[1];
+ break;
+
+ case CLK_PPLL_100M_MATRIX:
+ mask = PCIE_CLK_MATRIX_100M_SRC_DIV_MASK;
+ shift = PCIE_CLK_MATRIX_100M_SRC_DIV_SHIFT;
+ reg = &cru->pcieclksel_con[1];
+ break;
+
+ case CLK_PPLL_125M_MATRIX:
+ case CLK_GMAC1_SRC_VPU:
+ mask = CLK_MATRIX_125M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_125M_SRC_DIV_SHIFT;
+ reg = &cru->clksel_con[60];
+ break;
+
+ case CLK_GMAC1_VPU_25M:
+ mask = CLK_MATRIX_25M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_25M_SRC_DIV_SHIFT;
+ reg = &cru->clksel_con[60];
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ div = (readl(reg) & mask) >> shift;
+
+ return DIV_TO_RATE(priv->ppll_hz, div);
+}
+
+static ulong rk3528_ppll_matrix_set_rate(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, div, mask, shift;
+ u8 is_pciecru = 0;
+
+ switch (clk_id) {
+ case CLK_PPLL_50M_MATRIX:
+ id = 1;
+ mask = PCIE_CLK_MATRIX_50M_SRC_DIV_MASK;
+ shift = PCIE_CLK_MATRIX_50M_SRC_DIV_SHIFT;
+ is_pciecru = 1;
+ break;
+
+ case CLK_PPLL_100M_MATRIX:
+ id = 1;
+ mask = PCIE_CLK_MATRIX_100M_SRC_DIV_MASK;
+ shift = PCIE_CLK_MATRIX_100M_SRC_DIV_SHIFT;
+ is_pciecru = 1;
+ break;
+
+ case CLK_PPLL_125M_MATRIX:
+ id = 60;
+ mask = CLK_MATRIX_125M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_125M_SRC_DIV_SHIFT;
+ break;
+ case CLK_GMAC1_VPU_25M:
+ id = 60;
+ mask = CLK_MATRIX_25M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_25M_SRC_DIV_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ div = DIV_ROUND_UP(priv->ppll_hz, rate);
+ if (is_pciecru)
+ rk_clrsetreg(&cru->pcieclksel_con[id], mask, (div - 1) << shift);
+ else
+ rk_clrsetreg(&cru->clksel_con[id], mask, (div - 1) << shift);
+
+ return rk3528_ppll_matrix_get_rate(priv, clk_id);
+}
+
+static ulong rk3528_cgpll_matrix_get_rate(struct rk3528_clk_priv *priv,
+ ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 sel, div, mask, shift, con;
+ u32 sel_mask = 0, sel_shift;
+ u8 is_gpll_parent = 1;
+ u8 is_halfdiv = 0;
+ ulong prate;
+
+ switch (clk_id) {
+ case CLK_MATRIX_50M_SRC:
+ con = 0;
+ mask = CLK_MATRIX_50M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_50M_SRC_DIV_SHIFT;
+ is_gpll_parent = 0;
+ break;
+
+ case CLK_MATRIX_100M_SRC:
+ con = 0;
+ mask = CLK_MATRIX_100M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_100M_SRC_DIV_SHIFT;
+ is_gpll_parent = 0;
+ break;
+
+ case CLK_MATRIX_150M_SRC:
+ con = 1;
+ mask = CLK_MATRIX_150M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_150M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_200M_SRC:
+ con = 1;
+ mask = CLK_MATRIX_200M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_200M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_250M_SRC:
+ con = 1;
+ mask = CLK_MATRIX_250M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_250M_SRC_DIV_SHIFT;
+ sel_mask = CLK_MATRIX_250M_SRC_SEL_MASK;
+ sel_shift = CLK_MATRIX_250M_SRC_SEL_SHIFT;
+ break;
+
+ case CLK_MATRIX_300M_SRC:
+ con = 2;
+ mask = CLK_MATRIX_300M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_300M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_339M_SRC:
+ con = 2;
+ mask = CLK_MATRIX_339M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_339M_SRC_DIV_SHIFT;
+ is_halfdiv = 1;
+ break;
+
+ case CLK_MATRIX_400M_SRC:
+ con = 2;
+ mask = CLK_MATRIX_400M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_400M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_500M_SRC:
+ con = 3;
+ mask = CLK_MATRIX_500M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_500M_SRC_DIV_SHIFT;
+ sel_mask = CLK_MATRIX_500M_SRC_SEL_MASK;
+ sel_shift = CLK_MATRIX_500M_SRC_SEL_SHIFT;
+ break;
+
+ case CLK_MATRIX_600M_SRC:
+ con = 4;
+ mask = CLK_MATRIX_600M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_600M_SRC_DIV_SHIFT;
+ break;
+
+ case ACLK_BUS_VOPGL_ROOT:
+ case ACLK_BUS_VOPGL_BIU:
+ con = 43;
+ mask = ACLK_BUS_VOPGL_ROOT_DIV_MASK;
+ shift = ACLK_BUS_VOPGL_ROOT_DIV_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ if (sel_mask) {
+ sel = (readl(&cru->clksel_con[con]) & sel_mask) >> sel_shift;
+ if (sel == CLK_MATRIX_250M_SRC_SEL_CLK_GPLL_MUX) // TODO
+ prate = priv->gpll_hz;
+ else
+ prate = priv->cpll_hz;
+ } else {
+ if (is_gpll_parent)
+ prate = priv->gpll_hz;
+ else
+ prate = priv->cpll_hz;
+ }
+
+ div = (readl(&cru->clksel_con[con]) & mask) >> shift;
+
+ /* NOTE: '-1' to balance the DIV_TO_RATE() 'div+1' */
+ return is_halfdiv ? DIV_TO_RATE(prate * 2, (3 + 2 * div) - 1) : DIV_TO_RATE(prate, div);
+}
+
+static ulong rk3528_cgpll_matrix_set_rate(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 sel, div, mask, shift, con;
+ u32 sel_mask = 0, sel_shift;
+ u8 is_gpll_parent = 1;
+ u8 is_halfdiv = 0;
+ ulong prate = 0;
+
+ switch (clk_id) {
+ case CLK_MATRIX_50M_SRC:
+ con = 0;
+ mask = CLK_MATRIX_50M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_50M_SRC_DIV_SHIFT;
+ is_gpll_parent = 0;
+ break;
+
+ case CLK_MATRIX_100M_SRC:
+ con = 0;
+ mask = CLK_MATRIX_100M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_100M_SRC_DIV_SHIFT;
+ is_gpll_parent = 0;
+ break;
+
+ case CLK_MATRIX_150M_SRC:
+ con = 1;
+ mask = CLK_MATRIX_150M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_150M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_200M_SRC:
+ con = 1;
+ mask = CLK_MATRIX_200M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_200M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_250M_SRC:
+ con = 1;
+ mask = CLK_MATRIX_250M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_250M_SRC_DIV_SHIFT;
+ sel_mask = CLK_MATRIX_250M_SRC_SEL_MASK;
+ sel_shift = CLK_MATRIX_250M_SRC_SEL_SHIFT;
+ break;
+
+ case CLK_MATRIX_300M_SRC:
+ con = 2;
+ mask = CLK_MATRIX_300M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_300M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_339M_SRC:
+ con = 2;
+ mask = CLK_MATRIX_339M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_339M_SRC_DIV_SHIFT;
+ is_halfdiv = 1;
+ break;
+
+ case CLK_MATRIX_400M_SRC:
+ con = 2;
+ mask = CLK_MATRIX_400M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_400M_SRC_DIV_SHIFT;
+ break;
+
+ case CLK_MATRIX_500M_SRC:
+ con = 3;
+ mask = CLK_MATRIX_500M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_500M_SRC_DIV_SHIFT;
+ sel_mask = CLK_MATRIX_500M_SRC_SEL_MASK;
+ sel_shift = CLK_MATRIX_500M_SRC_SEL_SHIFT;
+ break;
+
+ case CLK_MATRIX_600M_SRC:
+ con = 4;
+ mask = CLK_MATRIX_600M_SRC_DIV_MASK;
+ shift = CLK_MATRIX_600M_SRC_DIV_SHIFT;
+ break;
+
+ case ACLK_BUS_VOPGL_ROOT:
+ case ACLK_BUS_VOPGL_BIU:
+ con = 43;
+ mask = ACLK_BUS_VOPGL_ROOT_DIV_MASK;
+ shift = ACLK_BUS_VOPGL_ROOT_DIV_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ if (sel_mask) {
+ if (priv->gpll_hz % rate == 0) {
+ sel = CLK_MATRIX_250M_SRC_SEL_CLK_GPLL_MUX; // TODO
+ prate = priv->gpll_hz;
+ } else {
+ sel = CLK_MATRIX_250M_SRC_SEL_CLK_CPLL_MUX;
+ prate = priv->cpll_hz;
+ }
+ } else {
+ if (is_gpll_parent)
+ prate = priv->gpll_hz;
+ else
+ prate = priv->cpll_hz;
+ }
+
+ if (is_halfdiv)
+ /* NOTE: '+1' to balance the following rk_clrsetreg() 'div-1' */
+ div = DIV_ROUND_UP((prate * 2) - (3 * rate), 2 * rate) + 1;
+ else
+ div = DIV_ROUND_UP(prate, rate);
+
+ rk_clrsetreg(&cru->clksel_con[con], mask, (div - 1) << shift);
+ if (sel_mask)
+ rk_clrsetreg(&cru->clksel_con[con], sel_mask, sel << sel_shift);
+
+ return rk3528_cgpll_matrix_get_rate(priv, clk_id);
+}
+
+static ulong rk3528_i2c_get_clk(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, sel, con, mask, shift;
+ u8 is_pmucru = 0;
+ ulong rate;
+
+ switch (clk_id) {
+ case CLK_I2C0:
+ id = 79;
+ mask = CLK_I2C0_SEL_MASK;
+ shift = CLK_I2C0_SEL_SHIFT;
+ break;
+
+ case CLK_I2C1:
+ id = 79;
+ mask = CLK_I2C1_SEL_MASK;
+ shift = CLK_I2C1_SEL_SHIFT;
+ break;
+
+ case CLK_I2C2:
+ id = 0;
+ mask = CLK_I2C2_SEL_MASK;
+ shift = CLK_I2C2_SEL_SHIFT;
+ is_pmucru = 1;
+ break;
+
+ case CLK_I2C3:
+ id = 63;
+ mask = CLK_I2C3_SEL_MASK;
+ shift = CLK_I2C3_SEL_SHIFT;
+ break;
+
+ case CLK_I2C4:
+ id = 85;
+ mask = CLK_I2C4_SEL_MASK;
+ shift = CLK_I2C4_SEL_SHIFT;
+ break;
+
+ case CLK_I2C5:
+ id = 63;
+ mask = CLK_I2C5_SEL_MASK;
+ shift = CLK_I2C5_SEL_SHIFT;
+ break;
+
+ case CLK_I2C6:
+ id = 64;
+ mask = CLK_I2C6_SEL_MASK;
+ shift = CLK_I2C6_SEL_SHIFT;
+ break;
+
+ case CLK_I2C7:
+ id = 86;
+ mask = CLK_I2C7_SEL_MASK;
+ shift = CLK_I2C7_SEL_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ if (is_pmucru)
+ con = readl(&cru->pmuclksel_con[id]);
+ else
+ con = readl(&cru->clksel_con[id]);
+ sel = (con & mask) >> shift;
+ if (sel == CLK_I2C3_SEL_CLK_MATRIX_200M_SRC)
+ rate = 200 * MHz;
+ else if (sel == CLK_I2C3_SEL_CLK_MATRIX_100M_SRC)
+ rate = 100 * MHz;
+ else if (sel == CLK_I2C3_SEL_CLK_MATRIX_50M_SRC)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+
+ return rate;
+}
+
+static ulong rk3528_i2c_set_clk(struct rk3528_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, sel, mask, shift;
+ u8 is_pmucru = 0;
+
+ if (rate >= 198 * MHz)
+ sel = CLK_I2C3_SEL_CLK_MATRIX_200M_SRC;
+ else if (rate >= 99 * MHz)
+ sel = CLK_I2C3_SEL_CLK_MATRIX_100M_SRC;
+ else if (rate >= 50 * MHz)
+ sel = CLK_I2C3_SEL_CLK_MATRIX_50M_SRC;
+ else
+ sel = CLK_I2C3_SEL_XIN_OSC0_FUNC;
+
+ switch (clk_id) {
+ case CLK_I2C0:
+ id = 79;
+ mask = CLK_I2C0_SEL_MASK;
+ shift = CLK_I2C0_SEL_SHIFT;
+ break;
+
+ case CLK_I2C1:
+ id = 79;
+ mask = CLK_I2C1_SEL_MASK;
+ shift = CLK_I2C1_SEL_SHIFT;
+ break;
+
+ case CLK_I2C2:
+ id = 0;
+ mask = CLK_I2C2_SEL_MASK;
+ shift = CLK_I2C2_SEL_SHIFT;
+ is_pmucru = 1;
+ break;
+
+ case CLK_I2C3:
+ id = 63;
+ mask = CLK_I2C3_SEL_MASK;
+ shift = CLK_I2C3_SEL_SHIFT;
+ break;
+
+ case CLK_I2C4:
+ id = 85;
+ mask = CLK_I2C4_SEL_MASK;
+ shift = CLK_I2C4_SEL_SHIFT;
+ break;
+
+ case CLK_I2C5:
+ id = 63;
+ mask = CLK_I2C5_SEL_MASK;
+ shift = CLK_I2C5_SEL_SHIFT;
+ break;
+
+ case CLK_I2C6:
+ id = 64;
+ mask = CLK_I2C6_SEL_MASK;
+ shift = CLK_I2C6_SEL_SHIFT;
+ break;
+
+ case CLK_I2C7:
+ id = 86;
+ mask = CLK_I2C7_SEL_MASK;
+ shift = CLK_I2C7_SEL_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ if (is_pmucru)
+ rk_clrsetreg(&cru->pmuclksel_con[id], mask, sel << shift);
+ else
+ rk_clrsetreg(&cru->clksel_con[id], mask, sel << shift);
+
+ return rk3528_i2c_get_clk(priv, clk_id);
+}
+
+static ulong rk3528_spi_get_clk(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, sel, con, mask, shift;
+ ulong rate;
+
+ switch (clk_id) {
+ case CLK_SPI0:
+ id = 79;
+ mask = CLK_SPI0_SEL_MASK;
+ shift = CLK_SPI0_SEL_SHIFT;
+ break;
+
+ case CLK_SPI1:
+ id = 63;
+ mask = CLK_SPI1_SEL_MASK;
+ shift = CLK_SPI1_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ con = readl(&cru->clksel_con[id]);
+ sel = (con & mask) >> shift;
+ if (sel == CLK_SPI1_SEL_CLK_MATRIX_200M_SRC)
+ rate = 200 * MHz;
+ else if (sel == CLK_SPI1_SEL_CLK_MATRIX_100M_SRC)
+ rate = 100 * MHz;
+ else if (sel == CLK_SPI1_SEL_CLK_MATRIX_50M_SRC)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+
+ return rate;
+}
+
+static ulong rk3528_spi_set_clk(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, sel, mask, shift;
+
+ if (rate >= 198 * MHz)
+ sel = CLK_SPI1_SEL_CLK_MATRIX_200M_SRC;
+ else if (rate >= 99 * MHz)
+ sel = CLK_SPI1_SEL_CLK_MATRIX_100M_SRC;
+ else if (rate >= 50 * MHz)
+ sel = CLK_SPI1_SEL_CLK_MATRIX_50M_SRC;
+ else
+ sel = CLK_SPI1_SEL_XIN_OSC0_FUNC;
+
+ switch (clk_id) {
+ case CLK_SPI0:
+ id = 79;
+ mask = CLK_SPI0_SEL_MASK;
+ shift = CLK_SPI0_SEL_SHIFT;
+ break;
+
+ case CLK_SPI1:
+ id = 63;
+ mask = CLK_SPI1_SEL_MASK;
+ shift = CLK_SPI1_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[id], mask, sel << shift);
+
+ return rk3528_spi_get_clk(priv, clk_id);
+}
+
+static ulong rk3528_pwm_get_clk(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, sel, con, mask, shift;
+ ulong rate;
+
+ switch (clk_id) {
+ case CLK_PWM0:
+ id = 44;
+ mask = CLK_PWM0_SEL_MASK;
+ shift = CLK_PWM0_SEL_SHIFT;
+ break;
+
+ case CLK_PWM1:
+ id = 44;
+ mask = CLK_PWM1_SEL_MASK;
+ shift = CLK_PWM1_SEL_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ con = readl(&cru->clksel_con[id]);
+ sel = (con & mask) >> shift;
+ if (sel == CLK_PWM0_SEL_CLK_MATRIX_100M_SRC)
+ rate = 100 * MHz;
+ if (sel == CLK_PWM0_SEL_CLK_MATRIX_50M_SRC)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+
+ return rate;
+}
+
+static ulong rk3528_pwm_set_clk(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 id, sel, mask, shift;
+
+ if (rate >= 99 * MHz)
+ sel = CLK_PWM0_SEL_CLK_MATRIX_100M_SRC;
+ else if (rate >= 50 * MHz)
+ sel = CLK_PWM0_SEL_CLK_MATRIX_50M_SRC;
+ else
+ sel = CLK_PWM0_SEL_XIN_OSC0_FUNC;
+
+ switch (clk_id) {
+ case CLK_PWM0:
+ id = 44;
+ mask = CLK_PWM0_SEL_MASK;
+ shift = CLK_PWM0_SEL_SHIFT;
+ break;
+
+ case CLK_PWM1:
+ id = 44;
+ mask = CLK_PWM1_SEL_MASK;
+ shift = CLK_PWM1_SEL_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[id], mask, sel << shift);
+
+ return rk3528_pwm_get_clk(priv, clk_id);
+}
+
+static ulong rk3528_adc_get_clk(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, con;
+
+ con = readl(&cru->clksel_con[74]);
+ switch (clk_id) {
+ case CLK_SARADC:
+ div = (con & CLK_SARADC_DIV_MASK) >>
+ CLK_SARADC_DIV_SHIFT;
+ break;
+
+ case CLK_TSADC_TSEN:
+ div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
+ CLK_TSADC_TSEN_DIV_SHIFT;
+ break;
+
+ case CLK_TSADC:
+ div = (con & CLK_TSADC_DIV_MASK) >>
+ CLK_TSADC_DIV_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3528_adc_set_clk(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, mask, shift;
+
+ switch (clk_id) {
+ case CLK_SARADC:
+ mask = CLK_SARADC_DIV_MASK;
+ shift = CLK_SARADC_DIV_SHIFT;
+ break;
+
+ case CLK_TSADC_TSEN:
+ mask = CLK_TSADC_TSEN_DIV_MASK;
+ shift = CLK_TSADC_TSEN_DIV_SHIFT;
+ break;
+
+ case CLK_TSADC:
+ mask = CLK_TSADC_DIV_MASK;
+ shift = CLK_TSADC_DIV_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ rk_clrsetreg(&cru->clksel_con[74], mask, (div - 1) << shift);
+
+ return rk3528_adc_get_clk(priv, clk_id);
+}
+
+static ulong rk3528_sdmmc_get_clk(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, sel, con;
+ ulong prate;
+
+ con = readl(&cru->clksel_con[85]);
+ div = (con & CCLK_SRC_SDMMC0_DIV_MASK) >>
+ CCLK_SRC_SDMMC0_DIV_SHIFT;
+ sel = (con & CCLK_SRC_SDMMC0_SEL_MASK) >>
+ CCLK_SRC_SDMMC0_SEL_SHIFT;
+
+ if (sel == CCLK_SRC_SDMMC0_SEL_CLK_GPLL_MUX)
+ prate = priv->gpll_hz;
+ else if (sel == CCLK_SRC_SDMMC0_SEL_CLK_CPLL_MUX)
+ prate = priv->cpll_hz;
+ else
+ prate = OSC_HZ;
+
+ return DIV_TO_RATE(prate, div);
+}
+
+static ulong rk3528_sdmmc_set_clk(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, sel;
+
+ if (OSC_HZ % rate == 0) {
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ sel = CCLK_SRC_SDMMC0_SEL_XIN_OSC0_FUNC;
+ } else if ((priv->cpll_hz % rate) == 0) {
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ sel = CCLK_SRC_SDMMC0_SEL_CLK_CPLL_MUX;
+ } else {
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ sel = CCLK_SRC_SDMMC0_SEL_CLK_GPLL_MUX;
+ }
+
+ assert(div - 1 <= 63);
+ rk_clrsetreg(&cru->clksel_con[85],
+ CCLK_SRC_SDMMC0_SEL_MASK |
+ CCLK_SRC_SDMMC0_DIV_MASK,
+ sel << CCLK_SRC_SDMMC0_SEL_SHIFT |
+ (div - 1) << CCLK_SRC_SDMMC0_DIV_SHIFT);
+
+ return rk3528_sdmmc_get_clk(priv, clk_id);
+}
+
+static ulong rk3528_sfc_get_clk(struct rk3528_clk_priv *priv)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[61]);
+ div = (con & SCLK_SFC_DIV_MASK) >>
+ SCLK_SFC_DIV_SHIFT;
+ sel = (con & SCLK_SFC_SEL_MASK) >>
+ SCLK_SFC_SEL_SHIFT;
+ if (sel == SCLK_SFC_SEL_CLK_GPLL_MUX)
+ parent = priv->gpll_hz;
+ else if (sel == SCLK_SFC_SEL_CLK_CPLL_MUX)
+ parent = priv->cpll_hz;
+ else
+ parent = OSC_HZ;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3528_sfc_set_clk(struct rk3528_clk_priv *priv, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ int div, sel;
+
+ if (OSC_HZ % rate == 0) {
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ sel = SCLK_SFC_SEL_XIN_OSC0_FUNC;
+ } else if ((priv->cpll_hz % rate) == 0) {
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ sel = SCLK_SFC_SEL_CLK_CPLL_MUX;
+ } else {
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ sel = SCLK_SFC_SEL_CLK_GPLL_MUX;
+ }
+
+ assert(div - 1 <= 63);
+ rk_clrsetreg(&cru->clksel_con[61],
+ SCLK_SFC_SEL_MASK |
+ SCLK_SFC_DIV_MASK,
+ sel << SCLK_SFC_SEL_SHIFT |
+ (div - 1) << SCLK_SFC_DIV_SHIFT);
+
+ return rk3528_sfc_get_clk(priv);
+}
+
+static ulong rk3528_emmc_get_clk(struct rk3528_clk_priv *priv)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[62]);
+ div = (con & CCLK_SRC_EMMC_DIV_MASK) >>
+ CCLK_SRC_EMMC_DIV_SHIFT;
+ sel = (con & CCLK_SRC_EMMC_SEL_MASK) >>
+ CCLK_SRC_EMMC_SEL_SHIFT;
+
+ if (sel == CCLK_SRC_EMMC_SEL_CLK_GPLL_MUX)
+ parent = priv->gpll_hz;
+ else if (sel == CCLK_SRC_EMMC_SEL_CLK_CPLL_MUX)
+ parent = priv->cpll_hz;
+ else
+ parent = OSC_HZ;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3528_emmc_set_clk(struct rk3528_clk_priv *priv, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div, sel;
+
+ if (OSC_HZ % rate == 0) {
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ sel = CCLK_SRC_EMMC_SEL_XIN_OSC0_FUNC;
+ } else if ((priv->cpll_hz % rate) == 0) {
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ sel = CCLK_SRC_EMMC_SEL_CLK_CPLL_MUX;
+ } else {
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ sel = CCLK_SRC_EMMC_SEL_CLK_GPLL_MUX;
+ }
+
+ assert(div - 1 <= 63);
+ rk_clrsetreg(&cru->clksel_con[62],
+ CCLK_SRC_EMMC_SEL_MASK |
+ CCLK_SRC_EMMC_DIV_MASK,
+ sel << CCLK_SRC_EMMC_SEL_SHIFT |
+ (div - 1) << CCLK_SRC_EMMC_DIV_SHIFT);
+
+ return rk3528_emmc_get_clk(priv);
+}
+
+static ulong rk3528_dclk_vop_get_clk(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div_mask, div_shift;
+ u32 sel_mask, sel_shift;
+ u32 id, con, sel, div;
+ ulong prate;
+
+ switch (clk_id) {
+ case DCLK_VOP0:
+ id = 32;
+ sel_mask = DCLK_VOP_SRC0_SEL_MASK;
+ sel_shift = DCLK_VOP_SRC0_SEL_SHIFT;
+ /* FIXME if need src: clk_hdmiphy_pixel_io */
+ div_mask = DCLK_VOP_SRC0_DIV_MASK;
+ div_shift = DCLK_VOP_SRC0_DIV_SHIFT;
+ break;
+
+ case DCLK_VOP1:
+ id = 33;
+ sel_mask = DCLK_VOP_SRC1_SEL_MASK;
+ sel_shift = DCLK_VOP_SRC1_SEL_SHIFT;
+ div_mask = DCLK_VOP_SRC1_DIV_MASK;
+ div_shift = DCLK_VOP_SRC1_DIV_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ con = readl(&cru->clksel_con[id]);
+ div = (con & div_mask) >> div_shift;
+ sel = (con & sel_mask) >> sel_shift;
+ if (sel == DCLK_VOP_SRC_SEL_CLK_GPLL_MUX)
+ prate = priv->gpll_hz;
+ else
+ prate = priv->cpll_hz;
+
+ return DIV_TO_RATE(prate, div);
+}
+
+static ulong rk3528_dclk_vop_set_clk(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 div_mask, div_shift;
+ u32 sel_mask, sel_shift;
+ u32 id, sel, div;
+ ulong prate;
+
+ switch (clk_id) {
+ case DCLK_VOP0:
+ id = 32;
+ sel_mask = DCLK_VOP_SRC0_SEL_MASK;
+ sel_shift = DCLK_VOP_SRC0_SEL_SHIFT;
+ /* FIXME if need src: clk_hdmiphy_pixel_io */
+ div_mask = DCLK_VOP_SRC0_DIV_MASK;
+ div_shift = DCLK_VOP_SRC0_DIV_SHIFT;
+ break;
+
+ case DCLK_VOP1:
+ id = 33;
+ sel_mask = DCLK_VOP_SRC1_SEL_MASK;
+ sel_shift = DCLK_VOP_SRC1_SEL_SHIFT;
+ div_mask = DCLK_VOP_SRC1_DIV_MASK;
+ div_shift = DCLK_VOP_SRC1_DIV_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ if ((priv->gpll_hz % rate) == 0) {
+ prate = priv->gpll_hz;
+ sel = (DCLK_VOP_SRC_SEL_CLK_GPLL_MUX << sel_shift) & sel_mask;
+ } else {
+ prate = priv->cpll_hz;
+ sel = (DCLK_VOP_SRC_SEL_CLK_CPLL_MUX << sel_shift) & sel_mask;
+ }
+
+ div = ((DIV_ROUND_UP(prate, rate) - 1) << div_shift) & div_mask;
+ rk_clrsetreg(&cru->clksel_con[id], sel, div);
+
+ return rk3528_dclk_vop_get_clk(priv, clk_id);
+}
+
+static ulong rk3528_uart_get_rate(struct rk3528_clk_priv *priv, ulong clk_id)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 sel_shift, sel_mask, div_shift, div_mask;
+ u32 sel, id, con, frac_div, div;
+ ulong m, n, rate;
+
+ switch (clk_id) {
+ case SCLK_UART0:
+ id = 6;
+ sel_shift = SCLK_UART0_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART0_SRC_SEL_MASK;
+ div_shift = CLK_UART0_SRC_DIV_SHIFT;
+ div_mask = CLK_UART0_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART1:
+ id = 8;
+ sel_shift = SCLK_UART1_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART1_SRC_SEL_MASK;
+ div_shift = CLK_UART1_SRC_DIV_SHIFT;
+ div_mask = CLK_UART1_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART2:
+ id = 10;
+ sel_shift = SCLK_UART2_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART2_SRC_SEL_MASK;
+ div_shift = CLK_UART2_SRC_DIV_SHIFT;
+ div_mask = CLK_UART2_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART3:
+ id = 12;
+ sel_shift = SCLK_UART3_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART3_SRC_SEL_MASK;
+ div_shift = CLK_UART3_SRC_DIV_SHIFT;
+ div_mask = CLK_UART3_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART4:
+ id = 14;
+ sel_shift = SCLK_UART4_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART4_SRC_SEL_MASK;
+ div_shift = CLK_UART4_SRC_DIV_SHIFT;
+ div_mask = CLK_UART4_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART5:
+ id = 16;
+ sel_shift = SCLK_UART5_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART5_SRC_SEL_MASK;
+ div_shift = CLK_UART5_SRC_DIV_SHIFT;
+ div_mask = CLK_UART5_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART6:
+ id = 18;
+ sel_shift = SCLK_UART6_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART6_SRC_SEL_MASK;
+ div_shift = CLK_UART6_SRC_DIV_SHIFT;
+ div_mask = CLK_UART6_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART7:
+ id = 20;
+ sel_shift = SCLK_UART7_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART7_SRC_SEL_MASK;
+ div_shift = CLK_UART7_SRC_DIV_SHIFT;
+ div_mask = CLK_UART7_SRC_DIV_MASK;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ con = readl(&cru->clksel_con[id - 2]);
+ div = (con & div_mask) >> div_shift;
+
+ con = readl(&cru->clksel_con[id]);
+ sel = (con & sel_mask) >> sel_shift;
+
+ if (sel == SCLK_UART0_SRC_SEL_CLK_UART0_SRC) {
+ rate = DIV_TO_RATE(priv->gpll_hz, div);
+ } else if (sel == SCLK_UART0_SRC_SEL_CLK_UART0_FRAC) {
+ frac_div = readl(&cru->clksel_con[id - 1]);
+ n = (frac_div & 0xffff0000) >> 16;
+ m = frac_div & 0x0000ffff;
+ rate = DIV_TO_RATE(priv->gpll_hz, div) * n / m;
+ } else {
+ rate = OSC_HZ;
+ }
+
+ return rate;
+}
+
+static ulong rk3528_uart_set_rate(struct rk3528_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 sel_shift, sel_mask, div_shift, div_mask;
+ u32 sel, id, div;
+ ulong m = 0, n = 0, val;
+
+ if (rate == OSC_HZ) {
+ sel = SCLK_UART0_SRC_SEL_XIN_OSC0_FUNC;
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ } else if (priv->gpll_hz % rate == 0) {
+ sel = SCLK_UART0_SRC_SEL_CLK_UART0_SRC;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ } else {
+ sel = SCLK_UART0_SRC_SEL_CLK_UART0_FRAC;
+ div = 2;
+ rational_best_approximation(rate, priv->gpll_hz / div,
+ GENMASK(16 - 1, 0),
+ GENMASK(16 - 1, 0),
+ &n, &m);
+ }
+
+ switch (clk_id) {
+ case SCLK_UART0:
+ id = 6;
+ sel_shift = SCLK_UART0_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART0_SRC_SEL_MASK;
+ div_shift = CLK_UART0_SRC_DIV_SHIFT;
+ div_mask = CLK_UART0_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART1:
+ id = 8;
+ sel_shift = SCLK_UART1_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART1_SRC_SEL_MASK;
+ div_shift = CLK_UART1_SRC_DIV_SHIFT;
+ div_mask = CLK_UART1_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART2:
+ id = 10;
+ sel_shift = SCLK_UART2_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART2_SRC_SEL_MASK;
+ div_shift = CLK_UART2_SRC_DIV_SHIFT;
+ div_mask = CLK_UART2_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART3:
+ id = 12;
+ sel_shift = SCLK_UART3_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART3_SRC_SEL_MASK;
+ div_shift = CLK_UART3_SRC_DIV_SHIFT;
+ div_mask = CLK_UART3_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART4:
+ id = 14;
+ sel_shift = SCLK_UART4_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART4_SRC_SEL_MASK;
+ div_shift = CLK_UART4_SRC_DIV_SHIFT;
+ div_mask = CLK_UART4_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART5:
+ id = 16;
+ sel_shift = SCLK_UART5_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART5_SRC_SEL_MASK;
+ div_shift = CLK_UART5_SRC_DIV_SHIFT;
+ div_mask = CLK_UART5_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART6:
+ id = 18;
+ sel_shift = SCLK_UART6_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART6_SRC_SEL_MASK;
+ div_shift = CLK_UART6_SRC_DIV_SHIFT;
+ div_mask = CLK_UART6_SRC_DIV_MASK;
+ break;
+
+ case SCLK_UART7:
+ id = 20;
+ sel_shift = SCLK_UART7_SRC_SEL_SHIFT;
+ sel_mask = SCLK_UART7_SRC_SEL_MASK;
+ div_shift = CLK_UART7_SRC_DIV_SHIFT;
+ div_mask = CLK_UART7_SRC_DIV_MASK;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[id - 2], div_mask, (div - 1) << div_shift);
+ rk_clrsetreg(&cru->clksel_con[id], sel_mask, sel << sel_shift);
+ if (m && n) {
+ val = n << 16 | m;
+ writel(val, &cru->clksel_con[id - 1]);
+ }
+
+ return rk3528_uart_get_rate(priv, clk_id);
+}
+
+static ulong rk3528_clk_get_rate(struct clk *clk)
+{
+ struct rk3528_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ if (!priv->gpll_hz || !priv->cpll_hz) {
+ printf("%s: gpll=%lu, cpll=%ld\n",
+ __func__, priv->gpll_hz, priv->cpll_hz);
+ return -ENOENT;
+ }
+
+ switch (clk->id) {
+ case PLL_APLL:
+ case ARMCLK:
+ rate = rockchip_pll_get_rate(&rk3528_pll_clks[APLL], priv->cru,
+ APLL);
+ break;
+ case PLL_CPLL:
+ rate = rockchip_pll_get_rate(&rk3528_pll_clks[CPLL], priv->cru,
+ CPLL);
+ break;
+ case PLL_GPLL:
+ rate = rockchip_pll_get_rate(&rk3528_pll_clks[GPLL], priv->cru,
+ GPLL);
+ break;
+
+ case PLL_PPLL:
+ rate = rockchip_pll_get_rate(&rk3528_pll_clks[PPLL], priv->cru,
+ PPLL);
+ break;
+ case PLL_DPLL:
+ rate = rockchip_pll_get_rate(&rk3528_pll_clks[DPLL], priv->cru,
+ DPLL);
+ break;
+
+ case TCLK_EMMC:
+ case TCLK_WDT_NS:
+ rate = OSC_HZ;
+ break;
+ case CLK_I2C0:
+ case CLK_I2C1:
+ case CLK_I2C2:
+ case CLK_I2C3:
+ case CLK_I2C4:
+ case CLK_I2C5:
+ case CLK_I2C6:
+ case CLK_I2C7:
+ rate = rk3528_i2c_get_clk(priv, clk->id);
+ break;
+ case CLK_SPI0:
+ case CLK_SPI1:
+ rate = rk3528_spi_get_clk(priv, clk->id);
+ break;
+ case CLK_PWM0:
+ case CLK_PWM1:
+ rate = rk3528_pwm_get_clk(priv, clk->id);
+ break;
+ case CLK_SARADC:
+ case CLK_TSADC:
+ case CLK_TSADC_TSEN:
+ rate = rk3528_adc_get_clk(priv, clk->id);
+ break;
+ case CCLK_SRC_EMMC:
+ rate = rk3528_emmc_get_clk(priv);
+ break;
+ case HCLK_SDMMC0:
+ case CCLK_SRC_SDMMC0:
+ rate = rk3528_sdmmc_get_clk(priv, clk->id);
+ break;
+ case SCLK_SFC:
+ rate = rk3528_sfc_get_clk(priv);
+ break;
+ case DCLK_VOP0:
+ case DCLK_VOP1:
+ rate = rk3528_dclk_vop_get_clk(priv, clk->id);
+ break;
+ case DCLK_CVBS:
+ rate = rk3528_dclk_vop_get_clk(priv, DCLK_VOP1) / 4;
+ break;
+ case DCLK_4X_CVBS:
+ rate = rk3528_dclk_vop_get_clk(priv, DCLK_VOP1);
+ break;
+ case SCLK_UART0:
+ case SCLK_UART1:
+ case SCLK_UART2:
+ case SCLK_UART3:
+ case SCLK_UART4:
+ case SCLK_UART5:
+ case SCLK_UART6:
+ case SCLK_UART7:
+ rate = rk3528_uart_get_rate(priv, clk->id);
+ break;
+ case CLK_MATRIX_50M_SRC:
+ case CLK_MATRIX_100M_SRC:
+ case CLK_MATRIX_150M_SRC:
+ case CLK_MATRIX_200M_SRC:
+ case CLK_MATRIX_250M_SRC:
+ case CLK_MATRIX_300M_SRC:
+ case CLK_MATRIX_339M_SRC:
+ case CLK_MATRIX_400M_SRC:
+ case CLK_MATRIX_500M_SRC:
+ case CLK_MATRIX_600M_SRC:
+ case ACLK_BUS_VOPGL_BIU:
+ rate = rk3528_cgpll_matrix_get_rate(priv, clk->id);
+ break;
+ case CLK_PPLL_50M_MATRIX:
+ case CLK_PPLL_100M_MATRIX:
+ case CLK_PPLL_125M_MATRIX:
+ case CLK_GMAC1_VPU_25M:
+ case CLK_GMAC1_RMII_VPU:
+ case CLK_GMAC1_SRC_VPU:
+ rate = rk3528_ppll_matrix_get_rate(priv, clk->id);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+};
+
+static ulong rk3528_clk_set_rate(struct clk *clk, ulong rate)
+{
+ struct rk3528_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ if (!priv->gpll_hz) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ switch (clk->id) {
+ case PLL_APLL:
+ case ARMCLK:
+ if (priv->armclk_hz)
+ rk3528_armclk_set_clk(priv, rate);
+ priv->armclk_hz = rate;
+ break;
+ case PLL_CPLL:
+ ret = rockchip_pll_set_rate(&rk3528_pll_clks[CPLL], priv->cru,
+ CPLL, rate);
+ priv->cpll_hz = rockchip_pll_get_rate(&rk3528_pll_clks[CPLL],
+ priv->cru, CPLL);
+ break;
+ case PLL_GPLL:
+ ret = rockchip_pll_set_rate(&rk3528_pll_clks[GPLL], priv->cru,
+ GPLL, rate);
+ priv->gpll_hz = rockchip_pll_get_rate(&rk3528_pll_clks[GPLL],
+ priv->cru, GPLL);
+ break;
+ case PLL_PPLL:
+ ret = rockchip_pll_set_rate(&rk3528_pll_clks[PPLL], priv->cru,
+ PPLL, rate);
+ priv->ppll_hz = rockchip_pll_get_rate(&rk3528_pll_clks[PPLL],
+ priv->cru, PPLL);
+ break;
+ case TCLK_EMMC:
+ case TCLK_WDT_NS:
+ return (rate == OSC_HZ) ? 0 : -EINVAL;
+ case CLK_I2C0:
+ case CLK_I2C1:
+ case CLK_I2C2:
+ case CLK_I2C3:
+ case CLK_I2C4:
+ case CLK_I2C5:
+ case CLK_I2C6:
+ case CLK_I2C7:
+ ret = rk3528_i2c_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_SPI0:
+ case CLK_SPI1:
+ ret = rk3528_spi_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_PWM0:
+ case CLK_PWM1:
+ ret = rk3528_pwm_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_SARADC:
+ case CLK_TSADC:
+ case CLK_TSADC_TSEN:
+ ret = rk3528_adc_set_clk(priv, clk->id, rate);
+ break;
+ case HCLK_SDMMC0:
+ case CCLK_SRC_SDMMC0:
+ ret = rk3528_sdmmc_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_SFC:
+ ret = rk3528_sfc_set_clk(priv, rate);
+ break;
+ case CCLK_SRC_EMMC:
+ ret = rk3528_emmc_set_clk(priv, rate);
+ break;
+ case DCLK_VOP0:
+ case DCLK_VOP1:
+ ret = rk3528_dclk_vop_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_UART0:
+ case SCLK_UART1:
+ case SCLK_UART2:
+ case SCLK_UART3:
+ case SCLK_UART4:
+ case SCLK_UART5:
+ case SCLK_UART6:
+ case SCLK_UART7:
+ ret = rk3528_uart_set_rate(priv, clk->id, rate);
+ break;
+ case CLK_MATRIX_50M_SRC:
+ case CLK_MATRIX_100M_SRC:
+ case CLK_MATRIX_150M_SRC:
+ case CLK_MATRIX_200M_SRC:
+ case CLK_MATRIX_250M_SRC:
+ case CLK_MATRIX_300M_SRC:
+ case CLK_MATRIX_339M_SRC:
+ case CLK_MATRIX_400M_SRC:
+ case CLK_MATRIX_500M_SRC:
+ case CLK_MATRIX_600M_SRC:
+ case ACLK_BUS_VOPGL_BIU:
+ ret = rk3528_cgpll_matrix_set_rate(priv, clk->id, rate);
+ break;
+ case CLK_PPLL_50M_MATRIX:
+ case CLK_PPLL_100M_MATRIX:
+ case CLK_PPLL_125M_MATRIX:
+ case CLK_GMAC1_VPU_25M:
+ ret = rk3528_ppll_matrix_set_rate(priv, clk->id, rate);
+ break;
+ case CLK_GMAC1_RMII_VPU:
+ case CLK_GMAC1_SRC_VPU:
+ /* dummy set */
+ ret = rk3528_ppll_matrix_get_rate(priv, clk->id);
+ break;
+
+ /* Might occur in cru assigned-clocks, can be ignored here */
+ case ACLK_BUS_VOPGL_ROOT:
+ case BCLK_EMMC:
+ case XIN_OSC0_DIV:
+ ret = 0;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return ret;
+};
+
+static struct clk_ops rk3528_clk_ops = {
+ .get_rate = rk3528_clk_get_rate,
+ .set_rate = rk3528_clk_set_rate,
+};
+
+#ifdef CONFIG_XPL_BUILD
+
+#define COREGRF_BASE 0xff300000
+#define PVTPLL_CON0_L 0x0
+#define PVTPLL_CON0_H 0x4
+
+static int rk3528_cpu_pvtpll_set_rate(struct rk3528_clk_priv *priv, ulong rate)
+{
+ struct rk3528_cru *cru = priv->cru;
+ u32 length;
+
+ if (rate >= 1200000000)
+ length = 8;
+ else if (rate >= 1008000000)
+ length = 11;
+ else
+ length = 17;
+
+ /* set pclk dbg div to 9 */
+ rk_clrsetreg(&cru->clksel_con[40], RK3528_DIV_PCLK_DBG_MASK,
+ 9 << RK3528_DIV_PCLK_DBG_SHIFT);
+ /* set aclk_m_core div to 1 */
+ rk_clrsetreg(&cru->clksel_con[39], RK3528_DIV_ACLK_M_CORE_MASK,
+ 1 << RK3528_DIV_ACLK_M_CORE_SHIFT);
+
+ /* set ring sel = 1 */
+ writel(0x07000000 | (1 << 8), COREGRF_BASE + PVTPLL_CON0_L);
+ /* set length */
+ writel(0x007f0000 | length, COREGRF_BASE + PVTPLL_CON0_H);
+ /* enable pvtpll */
+ writel(0x00020002, COREGRF_BASE + PVTPLL_CON0_L);
+ /* start monitor */
+ writel(0x00010001, COREGRF_BASE + PVTPLL_CON0_L);
+
+ /* set core mux pvtpll */
+ writel(0x00010001, &cru->clksel_con[40]);
+ writel(0x00100010, &cru->clksel_con[39]);
+
+ /* set pclk dbg div to 8 */
+ rk_clrsetreg(&cru->clksel_con[40], RK3528_DIV_PCLK_DBG_MASK,
+ 8 << RK3528_DIV_PCLK_DBG_SHIFT);
+
+ return 0;
+}
+#endif
+
+static int rk3528_clk_init(struct rk3528_clk_priv *priv)
+{
+ int ret;
+
+ priv->sync_kernel = false;
+
+#ifdef CONFIG_XPL_BUILD
+ /*
+ * BOOTROM:
+ * CPU 1902/2(postdiv1)=546M
+ * CPLL 996/2(postdiv1)=498M
+ * GPLL 1188/2(postdiv1)=594M
+ * |-- clk_matrix_200m_src_div=1 => rate: 300M
+ * |-- clk_matrix_300m_src_div=2 => rate: 200M
+ *
+ * Avoid overclocking when change GPLL rate:
+ * Change clk_matrix_200m_src_div to 5.
+ * Change clk_matrix_300m_src_div to 3.
+ */
+ writel(0x01200120, &priv->cru->clksel_con[1]);
+ writel(0x00030003, &priv->cru->clksel_con[2]);
+
+ if (!priv->armclk_enter_hz) {
+ priv->armclk_enter_hz =
+ rockchip_pll_get_rate(&rk3528_pll_clks[APLL],
+ priv->cru, APLL);
+ priv->armclk_init_hz = priv->armclk_enter_hz;
+ }
+
+ if (priv->armclk_init_hz != APLL_HZ) {
+ ret = rk3528_armclk_set_clk(priv, APLL_HZ);
+ if (!ret)
+ priv->armclk_init_hz = APLL_HZ;
+ }
+
+ if (!rk3528_cpu_pvtpll_set_rate(priv, CPU_PVTPLL_HZ)) {
+ debug("cpu pvtpll %d KHz\n", CPU_PVTPLL_HZ / 1000);
+ priv->armclk_init_hz = CPU_PVTPLL_HZ;
+ }
+#endif
+
+ if (priv->cpll_hz != CPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rk3528_pll_clks[CPLL], priv->cru,
+ CPLL, CPLL_HZ);
+ if (!ret)
+ priv->cpll_hz = CPLL_HZ;
+ }
+
+ if (priv->gpll_hz != GPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rk3528_pll_clks[GPLL], priv->cru,
+ GPLL, GPLL_HZ);
+ if (!ret)
+ priv->gpll_hz = GPLL_HZ;
+ }
+
+ if (priv->ppll_hz != PPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rk3528_pll_clks[PPLL], priv->cru,
+ PPLL, PPLL_HZ);
+ if (!ret)
+ priv->ppll_hz = PPLL_HZ;
+ }
+
+#ifdef CONFIG_XPL_BUILD
+ /* Init to override bootrom config */
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_50M_SRC, 50000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_100M_SRC, 100000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_150M_SRC, 150000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_200M_SRC, 200000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_250M_SRC, 250000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_300M_SRC, 300000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_339M_SRC, 340000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_400M_SRC, 400000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_500M_SRC, 500000000);
+ rk3528_cgpll_matrix_set_rate(priv, CLK_MATRIX_600M_SRC, 600000000);
+ rk3528_cgpll_matrix_set_rate(priv, ACLK_BUS_VOPGL_BIU, 500000000);
+
+ /* The default rate is 100Mhz, it's not friendly for remote IR module */
+ rk3528_pwm_set_clk(priv, CLK_PWM0, 24000000);
+ rk3528_pwm_set_clk(priv, CLK_PWM1, 24000000);
+#endif
+ return 0;
+}
+
+static int rk3528_clk_probe(struct udevice *dev)
+{
+ struct rk3528_clk_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = rk3528_clk_init(priv);
+ if (ret)
+ return ret;
+
+ /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+ ret = clk_set_defaults(dev, 1);
+ if (ret)
+ debug("%s clk_set_defaults failed %d\n", __func__, ret);
+ else
+ priv->sync_kernel = true;
+
+ return 0;
+}
+
+static int rk3528_clk_ofdata_to_platdata(struct udevice *dev)
+{
+ struct rk3528_clk_priv *priv = dev_get_priv(dev);
+
+ priv->cru = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static int rk3528_clk_bind(struct udevice *dev)
+{
+ struct udevice *sys_child;
+ struct sysreset_reg *priv;
+ int ret;
+
+ /* The reset driver does not have a device node, so bind it here */
+ ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+ &sys_child);
+ if (ret) {
+ debug("Warning: No sysreset driver: ret=%d\n", ret);
+ } else {
+ priv = malloc(sizeof(struct sysreset_reg));
+ priv->glb_srst_fst_value = offsetof(struct rk3528_cru,
+ glb_srst_fst);
+ priv->glb_srst_snd_value = offsetof(struct rk3528_cru,
+ glb_srst_snd);
+ dev_set_priv(sys_child, priv);
+ }
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+ ret = offsetof(struct rk3528_cru, softrst_con[0]);
+ ret = rk3528_reset_bind_lut(dev, ret, 47);
+ if (ret)
+ debug("Warning: software reset driver bind failed\n");
+#endif
+
+ return 0;
+}
+
+static const struct udevice_id rk3528_clk_ids[] = {
+ { .compatible = "rockchip,rk3528-cru" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rk3528_cru) = {
+ .name = "rockchip_rk3528_cru",
+ .id = UCLASS_CLK,
+ .of_match = rk3528_clk_ids,
+ .priv_auto = sizeof(struct rk3528_clk_priv),
+ .of_to_plat = rk3528_clk_ofdata_to_platdata,
+ .ops = &rk3528_clk_ops,
+ .bind = rk3528_clk_bind,
+ .probe = rk3528_clk_probe,
+};
diff --git a/drivers/clk/rockchip/clk_rk3576.c b/drivers/clk/rockchip/clk_rk3576.c
new file mode 100644
index 00000000000..e84a0943a94
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rk3576.c
@@ -0,0 +1,2513 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Elaine Zhang <[email protected]>
+ */
+
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/cru_rk3576.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rockchip,rk3576-cru.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
+
+static struct rockchip_pll_rate_table rk3576_24m_pll_rates[] = {
+ /* _mhz, _p, _m, _s, _k */
+ RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
+ RK3588_PLL_RATE(1200000000, 1, 100, 1, 0),
+ RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
+ RK3588_PLL_RATE(1150000000, 3, 575, 2, 0),
+ RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
+ RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
+ RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
+ RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
+ RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
+ RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
+ RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
+ RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
+ RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
+ RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
+ RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
+ RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
+ RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
+ RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
+ { /* sentinel */ },
+};
+
+static struct rockchip_pll_clock rk3576_pll_clks[] = {
+ [BPLL] = PLL(pll_rk3588, PLL_BPLL, RK3576_PLL_CON(0),
+ RK3576_BPLL_MODE_CON0, 0, 15, 0,
+ rk3576_24m_pll_rates),
+ [LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3576_LPLL_CON(16),
+ RK3576_LPLL_MODE_CON0, 0, 15, 0, rk3576_24m_pll_rates),
+ [VPLL] = PLL(pll_rk3588, PLL_VPLL, RK3576_PLL_CON(88),
+ RK3576_LPLL_MODE_CON0, 4, 15, 0, rk3576_24m_pll_rates),
+ [AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3576_PLL_CON(96),
+ RK3576_MODE_CON0, 6, 15, 0, rk3576_24m_pll_rates),
+ [CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3576_PLL_CON(104),
+ RK3576_MODE_CON0, 8, 15, 0, rk3576_24m_pll_rates),
+ [GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3576_PLL_CON(112),
+ RK3576_MODE_CON0, 2, 15, 0, rk3576_24m_pll_rates),
+ [PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3576_PMU_PLL_CON(128),
+ RK3576_MODE_CON0, 10, 15, 0, rk3576_24m_pll_rates),
+};
+
+#ifdef CONFIG_SPL_BUILD
+#ifndef BITS_WITH_WMASK
+#define BITS_WITH_WMASK(bits, msk, shift) \
+ ((bits) << (shift)) | ((msk) << ((shift) + 16))
+#endif
+#endif
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ *
+ * rational_best_approximation(31415, 10000,
+ * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+ unsigned long given_denominator,
+ unsigned long max_numerator,
+ unsigned long max_denominator,
+ unsigned long *best_numerator,
+ unsigned long *best_denominator)
+{
+ unsigned long n, d, n0, d0, n1, d1;
+
+ n = given_numerator;
+ d = given_denominator;
+ n0 = 0;
+ d1 = 0;
+ n1 = 1;
+ d0 = 1;
+ for (;;) {
+ unsigned long t, a;
+
+ if (n1 > max_numerator || d1 > max_denominator) {
+ n1 = n0;
+ d1 = d0;
+ break;
+ }
+ if (d == 0)
+ break;
+ t = d;
+ a = n / d;
+ d = n % d;
+ n = t;
+ t = n0 + a * n1;
+ n0 = n1;
+ n1 = t;
+ t = d0 + a * d1;
+ d0 = d1;
+ d1 = t;
+ }
+ *best_numerator = n1;
+ *best_denominator = d1;
+}
+#endif
+
+static ulong rk3576_bus_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 con, sel, div, rate;
+
+ switch (clk_id) {
+ case ACLK_BUS_ROOT:
+ con = readl(&cru->clksel_con[55]);
+ sel = (con & ACLK_BUS_ROOT_SEL_MASK) >>
+ ACLK_BUS_ROOT_SEL_SHIFT;
+ div = (con & ACLK_BUS_ROOT_DIV_MASK) >>
+ ACLK_BUS_ROOT_DIV_SHIFT;
+ if (sel == ACLK_BUS_ROOT_SEL_CPLL)
+ rate = DIV_TO_RATE(priv->cpll_hz, div);
+ else
+ rate = DIV_TO_RATE(priv->gpll_hz, div);
+ break;
+ case HCLK_BUS_ROOT:
+ con = readl(&cru->clksel_con[55]);
+ sel = (con & HCLK_BUS_ROOT_SEL_MASK) >>
+ HCLK_BUS_ROOT_SEL_SHIFT;
+ if (sel == HCLK_BUS_ROOT_SEL_200M)
+ rate = 198 * MHz;
+ else if (sel == HCLK_BUS_ROOT_SEL_100M)
+ rate = 100 * MHz;
+ else if (sel == HCLK_BUS_ROOT_SEL_50M)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+ break;
+ case PCLK_BUS_ROOT:
+ con = readl(&cru->clksel_con[55]);
+ sel = (con & PCLK_BUS_ROOT_SEL_MASK) >>
+ PCLK_BUS_ROOT_SEL_SHIFT;
+ if (sel == PCLK_BUS_ROOT_SEL_100M)
+ rate = 100 * MHz;
+ else if (sel == PCLK_BUS_ROOT_SEL_50M)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+}
+
+static ulong rk3576_bus_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk, src_clk_div;
+
+ switch (clk_id) {
+ case ACLK_BUS_ROOT:
+ if (!(priv->cpll_hz % rate)) {
+ src_clk = ACLK_BUS_ROOT_SEL_CPLL;
+ src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = ACLK_BUS_ROOT_SEL_GPLL;
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ rk_clrsetreg(&cru->clksel_con[55],
+ ACLK_BUS_ROOT_SEL_MASK,
+ src_clk << ACLK_BUS_ROOT_SEL_SHIFT);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[55],
+ ACLK_BUS_ROOT_DIV_MASK |
+ ACLK_BUS_ROOT_SEL_MASK,
+ (src_clk <<
+ ACLK_BUS_ROOT_SEL_SHIFT) |
+ (src_clk_div - 1) << ACLK_BUS_ROOT_DIV_SHIFT);
+ break;
+ case HCLK_BUS_ROOT:
+ if (rate >= 198 * MHz)
+ src_clk = HCLK_BUS_ROOT_SEL_200M;
+ else if (rate >= 99 * MHz)
+ src_clk = HCLK_BUS_ROOT_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = HCLK_BUS_ROOT_SEL_50M;
+ else
+ src_clk = HCLK_BUS_ROOT_SEL_OSC;
+ rk_clrsetreg(&cru->clksel_con[55],
+ HCLK_BUS_ROOT_SEL_MASK,
+ src_clk << HCLK_BUS_ROOT_SEL_SHIFT);
+ break;
+ case PCLK_BUS_ROOT:
+ if (rate >= 99 * MHz)
+ src_clk = PCLK_BUS_ROOT_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = PCLK_BUS_ROOT_SEL_50M;
+ else
+ src_clk = PCLK_BUS_ROOT_SEL_OSC;
+ rk_clrsetreg(&cru->clksel_con[55],
+ PCLK_BUS_ROOT_SEL_MASK,
+ src_clk << PCLK_BUS_ROOT_SEL_SHIFT);
+ break;
+ default:
+ printf("do not support this center freq\n");
+ return -EINVAL;
+ }
+
+ return rk3576_bus_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_top_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 con, sel, div, rate, prate;
+
+ switch (clk_id) {
+ case ACLK_TOP:
+ con = readl(&cru->clksel_con[9]);
+ div = (con & ACLK_TOP_DIV_MASK) >>
+ ACLK_TOP_DIV_SHIFT;
+ sel = (con & ACLK_TOP_SEL_MASK) >>
+ ACLK_TOP_SEL_SHIFT;
+ if (sel == ACLK_TOP_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else if (sel == ACLK_TOP_SEL_AUPLL)
+ prate = priv->aupll_hz;
+ else
+ prate = priv->gpll_hz;
+ return DIV_TO_RATE(prate, div);
+ case ACLK_TOP_MID:
+ con = readl(&cru->clksel_con[10]);
+ div = (con & ACLK_TOP_MID_DIV_MASK) >>
+ ACLK_TOP_MID_DIV_SHIFT;
+ sel = (con & ACLK_TOP_MID_SEL_MASK) >>
+ ACLK_TOP_MID_SEL_SHIFT;
+ if (sel == ACLK_TOP_MID_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else
+ prate = priv->gpll_hz;
+ return DIV_TO_RATE(prate, div);
+ case PCLK_TOP_ROOT:
+ con = readl(&cru->clksel_con[8]);
+ sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
+ if (sel == PCLK_TOP_SEL_100M)
+ rate = 100 * MHz;
+ else if (sel == PCLK_TOP_SEL_50M)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+ break;
+ case HCLK_TOP:
+ con = readl(&cru->clksel_con[19]);
+ sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
+ if (sel == HCLK_TOP_SEL_200M)
+ rate = 200 * MHz;
+ else if (sel == HCLK_TOP_SEL_100M)
+ rate = 100 * MHz;
+ else if (sel == HCLK_TOP_SEL_50M)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+}
+
+static ulong rk3576_top_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk, src_clk_div;
+
+ switch (clk_id) {
+ case ACLK_TOP:
+ if (!(priv->cpll_hz % rate)) {
+ src_clk = ACLK_TOP_SEL_CPLL;
+ src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = ACLK_TOP_SEL_GPLL;
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[9],
+ ACLK_TOP_DIV_MASK |
+ ACLK_TOP_SEL_MASK,
+ (src_clk <<
+ ACLK_TOP_SEL_SHIFT) |
+ (src_clk_div - 1) << ACLK_TOP_SEL_SHIFT);
+ break;
+ case ACLK_TOP_MID:
+ if (!(priv->cpll_hz % rate)) {
+ src_clk = ACLK_TOP_MID_SEL_CPLL;
+ src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = ACLK_TOP_MID_SEL_GPLL;
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ rk_clrsetreg(&cru->clksel_con[10],
+ ACLK_TOP_MID_DIV_MASK |
+ ACLK_TOP_MID_SEL_MASK,
+ (ACLK_TOP_MID_SEL_GPLL <<
+ ACLK_TOP_MID_SEL_SHIFT) |
+ (src_clk_div - 1) << ACLK_TOP_MID_DIV_SHIFT);
+ break;
+ case PCLK_TOP_ROOT:
+ if (rate >= 99 * MHz)
+ src_clk = PCLK_TOP_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = PCLK_TOP_SEL_50M;
+ else
+ src_clk = PCLK_TOP_SEL_OSC;
+ rk_clrsetreg(&cru->clksel_con[8],
+ PCLK_TOP_SEL_MASK,
+ src_clk << PCLK_TOP_SEL_SHIFT);
+ break;
+ case HCLK_TOP:
+ if (rate >= 198 * MHz)
+ src_clk = HCLK_TOP_SEL_200M;
+ else if (rate >= 99 * MHz)
+ src_clk = HCLK_TOP_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = HCLK_TOP_SEL_50M;
+ else
+ src_clk = HCLK_TOP_SEL_OSC;
+ rk_clrsetreg(&cru->clksel_con[19],
+ HCLK_TOP_SEL_MASK,
+ src_clk << HCLK_TOP_SEL_SHIFT);
+ break;
+ default:
+ printf("do not support this top freq\n");
+ return -EINVAL;
+ }
+
+ return rk3576_top_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_i2c_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 sel, con;
+ ulong rate;
+
+ switch (clk_id) {
+ case CLK_I2C0:
+ con = readl(&cru->pmuclksel_con[6]);
+ sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
+ break;
+ case CLK_I2C1:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
+ break;
+ case CLK_I2C2:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
+ break;
+ case CLK_I2C3:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
+ break;
+ case CLK_I2C4:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
+ break;
+ case CLK_I2C5:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
+ break;
+ case CLK_I2C6:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
+ break;
+ case CLK_I2C7:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
+ break;
+ case CLK_I2C8:
+ con = readl(&cru->clksel_con[57]);
+ sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
+ break;
+ case CLK_I2C9:
+ con = readl(&cru->clksel_con[58]);
+ sel = (con & CLK_I2C9_SEL_MASK) >> CLK_I2C9_SEL_SHIFT;
+ break;
+
+ default:
+ return -ENOENT;
+ }
+ if (sel == CLK_I2C_SEL_200M)
+ rate = 200 * MHz;
+ else if (sel == CLK_I2C_SEL_100M)
+ rate = 100 * MHz;
+ else if (sel == CLK_I2C_SEL_50M)
+ rate = 50 * MHz;
+ else
+ rate = OSC_HZ;
+
+ return rate;
+}
+
+static ulong rk3576_i2c_set_clk(struct rk3576_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk;
+
+ if (rate >= 198 * MHz)
+ src_clk = CLK_I2C_SEL_200M;
+ else if (rate >= 99 * MHz)
+ src_clk = CLK_I2C_SEL_100M;
+ if (rate >= 50 * MHz)
+ src_clk = CLK_I2C_SEL_50M;
+ else
+ src_clk = CLK_I2C_SEL_OSC;
+
+ switch (clk_id) {
+ case CLK_I2C0:
+ rk_clrsetreg(&cru->pmuclksel_con[6], CLK_I2C0_SEL_MASK,
+ src_clk << CLK_I2C0_SEL_SHIFT);
+ break;
+ case CLK_I2C1:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C1_SEL_MASK,
+ src_clk << CLK_I2C1_SEL_SHIFT);
+ break;
+ case CLK_I2C2:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C2_SEL_MASK,
+ src_clk << CLK_I2C2_SEL_SHIFT);
+ break;
+ case CLK_I2C3:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C3_SEL_MASK,
+ src_clk << CLK_I2C3_SEL_SHIFT);
+ break;
+ case CLK_I2C4:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C4_SEL_MASK,
+ src_clk << CLK_I2C4_SEL_SHIFT);
+ break;
+ case CLK_I2C5:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C5_SEL_MASK,
+ src_clk << CLK_I2C5_SEL_SHIFT);
+ break;
+ case CLK_I2C6:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C6_SEL_MASK,
+ src_clk << CLK_I2C6_SEL_SHIFT);
+ break;
+ case CLK_I2C7:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C7_SEL_MASK,
+ src_clk << CLK_I2C7_SEL_SHIFT);
+ break;
+ case CLK_I2C8:
+ rk_clrsetreg(&cru->clksel_con[57], CLK_I2C8_SEL_MASK,
+ src_clk << CLK_I2C8_SEL_SHIFT);
+ case CLK_I2C9:
+ rk_clrsetreg(&cru->clksel_con[58], CLK_I2C9_SEL_MASK,
+ src_clk << CLK_I2C9_SEL_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rk3576_i2c_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_spi_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 sel, con;
+
+ switch (clk_id) {
+ case CLK_SPI0:
+ con = readl(&cru->clksel_con[70]);
+ sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
+ break;
+ case CLK_SPI1:
+ con = readl(&cru->clksel_con[71]);
+ sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
+ break;
+ case CLK_SPI2:
+ con = readl(&cru->clksel_con[71]);
+ sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
+ break;
+ case CLK_SPI3:
+ con = readl(&cru->clksel_con[71]);
+ sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
+ break;
+ case CLK_SPI4:
+ con = readl(&cru->clksel_con[71]);
+ sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ switch (sel) {
+ case CLK_SPI_SEL_200M:
+ return 200 * MHz;
+ case CLK_SPI_SEL_100M:
+ return 100 * MHz;
+ case CLK_SPI_SEL_50M:
+ return 50 * MHz;
+ case CLK_SPI_SEL_OSC:
+ return OSC_HZ;
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_spi_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk;
+
+ if (rate >= 198 * MHz)
+ src_clk = CLK_SPI_SEL_200M;
+ else if (rate >= 99 * MHz)
+ src_clk = CLK_SPI_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = CLK_SPI_SEL_50M;
+ else
+ src_clk = CLK_SPI_SEL_OSC;
+
+ switch (clk_id) {
+ case CLK_SPI0:
+ rk_clrsetreg(&cru->clksel_con[70],
+ CLK_SPI0_SEL_MASK,
+ src_clk << CLK_SPI0_SEL_SHIFT);
+ break;
+ case CLK_SPI1:
+ rk_clrsetreg(&cru->clksel_con[71],
+ CLK_SPI1_SEL_MASK,
+ src_clk << CLK_SPI1_SEL_SHIFT);
+ break;
+ case CLK_SPI2:
+ rk_clrsetreg(&cru->clksel_con[71],
+ CLK_SPI2_SEL_MASK,
+ src_clk << CLK_SPI2_SEL_SHIFT);
+ break;
+ case CLK_SPI3:
+ rk_clrsetreg(&cru->clksel_con[71],
+ CLK_SPI3_SEL_MASK,
+ src_clk << CLK_SPI3_SEL_SHIFT);
+ break;
+ case CLK_SPI4:
+ rk_clrsetreg(&cru->clksel_con[71],
+ CLK_SPI4_SEL_MASK,
+ src_clk << CLK_SPI4_SEL_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rk3576_spi_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_pwm_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 sel, con;
+
+ switch (clk_id) {
+ case CLK_PWM1:
+ con = readl(&cru->clksel_con[71]);
+ sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
+ break;
+ case CLK_PWM2:
+ con = readl(&cru->clksel_con[74]);
+ sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
+ break;
+ case CLK_PMU1PWM:
+ con = readl(&cru->pmuclksel_con[5]);
+ sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ switch (sel) {
+ case CLK_PWM_SEL_100M:
+ return 100 * MHz;
+ case CLK_PWM_SEL_50M:
+ return 50 * MHz;
+ case CLK_PWM_SEL_OSC:
+ return OSC_HZ;
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_pwm_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk;
+
+ if (rate >= 99 * MHz)
+ src_clk = CLK_PWM_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = CLK_PWM_SEL_50M;
+ else
+ src_clk = CLK_PWM_SEL_OSC;
+
+ switch (clk_id) {
+ case CLK_PWM1:
+ rk_clrsetreg(&cru->clksel_con[71],
+ CLK_PWM1_SEL_MASK,
+ src_clk << CLK_PWM1_SEL_SHIFT);
+ break;
+ case CLK_PWM2:
+ rk_clrsetreg(&cru->clksel_con[74],
+ CLK_PWM2_SEL_MASK,
+ src_clk << CLK_PWM2_SEL_SHIFT);
+ break;
+ case CLK_PMU1PWM:
+ rk_clrsetreg(&cru->pmuclksel_con[5],
+ CLK_PMU1PWM_SEL_MASK,
+ src_clk << CLK_PMU1PWM_SEL_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rk3576_pwm_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_adc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 div, sel, con, prate;
+
+ switch (clk_id) {
+ case CLK_SARADC:
+ con = readl(&cru->clksel_con[58]);
+ div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
+ sel = (con & CLK_SARADC_SEL_MASK) >>
+ CLK_SARADC_SEL_SHIFT;
+ if (sel == CLK_SARADC_SEL_OSC)
+ prate = OSC_HZ;
+ else
+ prate = priv->gpll_hz;
+ return DIV_TO_RATE(prate, div);
+ case CLK_TSADC:
+ con = readl(&cru->clksel_con[59]);
+ div = (con & CLK_TSADC_DIV_MASK) >>
+ CLK_TSADC_DIV_SHIFT;
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_adc_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk_div;
+
+ switch (clk_id) {
+ case CLK_SARADC:
+ if (!(OSC_HZ % rate)) {
+ src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
+ assert(src_clk_div - 1 <= 255);
+ rk_clrsetreg(&cru->clksel_con[58],
+ CLK_SARADC_SEL_MASK |
+ CLK_SARADC_DIV_MASK,
+ (CLK_SARADC_SEL_OSC <<
+ CLK_SARADC_SEL_SHIFT) |
+ (src_clk_div - 1) <<
+ CLK_SARADC_DIV_SHIFT);
+ } else {
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 255);
+ rk_clrsetreg(&cru->clksel_con[59],
+ CLK_SARADC_SEL_MASK |
+ CLK_SARADC_DIV_MASK,
+ (CLK_SARADC_SEL_GPLL <<
+ CLK_SARADC_SEL_SHIFT) |
+ (src_clk_div - 1) <<
+ CLK_SARADC_DIV_SHIFT);
+ }
+ break;
+ case CLK_TSADC:
+ src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
+ assert(src_clk_div - 1 <= 255);
+ rk_clrsetreg(&cru->clksel_con[58],
+ CLK_TSADC_DIV_MASK,
+ (src_clk_div - 1) <<
+ CLK_TSADC_DIV_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+ return rk3576_adc_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_mmc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 sel, con, prate, div = 0;
+
+ switch (clk_id) {
+ case CCLK_SRC_SDIO:
+ case HCLK_SDIO:
+ con = readl(&cru->clksel_con[104]);
+ div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
+ sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
+ CCLK_SDIO_SRC_SEL_SHIFT;
+ if (sel == CCLK_SDIO_SRC_SEL_GPLL)
+ prate = priv->gpll_hz;
+ else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ case CCLK_SRC_SDMMC0:
+ case HCLK_SDMMC0:
+ con = readl(&cru->clksel_con[105]);
+ div = (con & CCLK_SDMMC0_SRC_DIV_MASK) >> CCLK_SDMMC0_SRC_DIV_SHIFT;
+ sel = (con & CCLK_SDMMC0_SRC_SEL_MASK) >>
+ CCLK_SDMMC0_SRC_SEL_SHIFT;
+ if (sel == CCLK_SDMMC0_SRC_SEL_GPLL)
+ prate = priv->gpll_hz;
+ else if (sel == CCLK_SDMMC0_SRC_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ case CCLK_SRC_EMMC:
+ case HCLK_EMMC:
+ con = readl(&cru->clksel_con[89]);
+ div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
+ sel = (con & CCLK_EMMC_SEL_MASK) >>
+ CCLK_EMMC_SEL_SHIFT;
+ if (sel == CCLK_EMMC_SEL_GPLL)
+ prate = priv->gpll_hz;
+ else if (sel == CCLK_EMMC_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ case BCLK_EMMC:
+ con = readl(&cru->clksel_con[90]);
+ sel = (con & BCLK_EMMC_SEL_MASK) >>
+ BCLK_EMMC_SEL_SHIFT;
+ if (sel == BCLK_EMMC_SEL_200M)
+ prate = 200 * MHz;
+ else if (sel == BCLK_EMMC_SEL_100M)
+ prate = 100 * MHz;
+ else if (sel == BCLK_EMMC_SEL_50M)
+ prate = 50 * MHz;
+ else
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ case SCLK_FSPI_X2:
+ con = readl(&cru->clksel_con[89]);
+ div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
+ sel = (con & SCLK_FSPI_SEL_MASK) >>
+ SCLK_FSPI_SEL_SHIFT;
+ if (sel == SCLK_FSPI_SEL_GPLL)
+ prate = priv->gpll_hz;
+ else if (sel == SCLK_FSPI_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ case SCLK_FSPI1_X2:
+ con = readl(&cru->clksel_con[106]);
+ div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
+ sel = (con & SCLK_FSPI_SEL_MASK) >>
+ SCLK_FSPI_SEL_SHIFT;
+ if (sel == SCLK_FSPI_SEL_GPLL)
+ prate = priv->gpll_hz;
+ else if (sel == SCLK_FSPI_SEL_CPLL)
+ prate = priv->cpll_hz;
+ else
+ prate = OSC_HZ;
+ return DIV_TO_RATE(prate, div);
+ case DCLK_DECOM:
+ con = readl(&cru->clksel_con[72]);
+ div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
+ sel = (con & DCLK_DECOM_SEL_MASK) >> DCLK_DECOM_SEL_SHIFT;
+ if (sel == DCLK_DECOM_SEL_SPLL)
+ prate = priv->spll_hz;
+ else
+ prate = priv->gpll_hz;
+ return DIV_TO_RATE(prate, div);
+
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_mmc_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk, div = 0;
+
+ switch (clk_id) {
+ case CCLK_SRC_SDIO:
+ case CCLK_SRC_SDMMC0:
+ case CCLK_SRC_EMMC:
+ case SCLK_FSPI_X2:
+ case SCLK_FSPI1_X2:
+ case HCLK_SDMMC0:
+ case HCLK_EMMC:
+ case HCLK_SDIO:
+ if (!(OSC_HZ % rate)) {
+ src_clk = SCLK_FSPI_SEL_OSC;
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ } else if (!(priv->cpll_hz % rate)) {
+ src_clk = SCLK_FSPI_SEL_CPLL;
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = SCLK_FSPI_SEL_GPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ break;
+ case BCLK_EMMC:
+ if (rate >= 198 * MHz)
+ src_clk = BCLK_EMMC_SEL_200M;
+ else if (rate >= 99 * MHz)
+ src_clk = BCLK_EMMC_SEL_100M;
+ else if (rate >= 50 * MHz)
+ src_clk = BCLK_EMMC_SEL_50M;
+ else
+ src_clk = BCLK_EMMC_SEL_OSC;
+ break;
+ case DCLK_DECOM:
+ if (!(priv->spll_hz % rate)) {
+ src_clk = DCLK_DECOM_SEL_SPLL;
+ div = DIV_ROUND_UP(priv->spll_hz, rate);
+ } else {
+ src_clk = DCLK_DECOM_SEL_GPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ switch (clk_id) {
+ case CCLK_SRC_SDIO:
+ case HCLK_SDIO:
+ rk_clrsetreg(&cru->clksel_con[104],
+ CCLK_SDIO_SRC_SEL_MASK |
+ CCLK_SDIO_SRC_DIV_MASK,
+ (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
+ (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
+ break;
+ case CCLK_SRC_SDMMC0:
+ case HCLK_SDMMC0:
+ rk_clrsetreg(&cru->clksel_con[105],
+ CCLK_SDMMC0_SRC_SEL_MASK |
+ CCLK_SDMMC0_SRC_DIV_MASK,
+ (src_clk << CCLK_SDMMC0_SRC_SEL_SHIFT) |
+ (div - 1) << CCLK_SDMMC0_SRC_DIV_SHIFT);
+ break;
+ case CCLK_SRC_EMMC:
+ case HCLK_EMMC:
+ rk_clrsetreg(&cru->clksel_con[89],
+ CCLK_EMMC_DIV_MASK |
+ CCLK_EMMC_SEL_MASK,
+ (src_clk << CCLK_EMMC_SEL_SHIFT) |
+ (div - 1) << CCLK_EMMC_DIV_SHIFT);
+ break;
+ case SCLK_FSPI_X2:
+ rk_clrsetreg(&cru->clksel_con[89],
+ SCLK_FSPI_DIV_MASK |
+ SCLK_FSPI_SEL_MASK,
+ (src_clk << SCLK_FSPI_SEL_SHIFT) |
+ (div - 1) << SCLK_FSPI_DIV_SHIFT);
+ break;
+ case SCLK_FSPI1_X2:
+ rk_clrsetreg(&cru->clksel_con[106],
+ SCLK_FSPI_DIV_MASK |
+ SCLK_FSPI_SEL_MASK,
+ (src_clk << SCLK_FSPI_SEL_SHIFT) |
+ (div - 1) << SCLK_FSPI_DIV_SHIFT);
+ break;
+ case BCLK_EMMC:
+ rk_clrsetreg(&cru->clksel_con[90],
+ BCLK_EMMC_SEL_MASK,
+ src_clk << BCLK_EMMC_SEL_SHIFT);
+ break;
+ case DCLK_DECOM:
+ rk_clrsetreg(&cru->clksel_con[72],
+ DCLK_DECOM_DIV_MASK |
+ DCLK_DECOM_SEL_MASK,
+ (src_clk << DCLK_DECOM_SEL_SHIFT) |
+ (div - 1) << DCLK_DECOM_DIV_SHIFT);
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ return rk3576_mmc_get_clk(priv, clk_id);
+}
+
+#ifndef CONFIG_SPL_BUILD
+
+static ulong rk3576_aclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 div, sel, con, parent = 0;
+
+ switch (clk_id) {
+ case ACLK_VOP_ROOT:
+ case ACLK_VOP:
+ con = readl(&cru->clksel_con[144]);
+ div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
+ sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
+ if (sel == ACLK_VOP_ROOT_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
+ parent = priv->aupll_hz;
+ else if (sel == ACLK_VOP_ROOT_SEL_SPLL)
+ parent = priv->spll_hz;
+ else if (sel == ACLK_VOP_ROOT_SEL_LPLL)
+ parent = priv->lpll_hz / 2;
+ return DIV_TO_RATE(parent, div);
+ case ACLK_VO0_ROOT:
+ con = readl(&cru->clksel_con[149]);
+ div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
+ sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
+ if (sel == ACLK_VO0_ROOT_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
+ parent = priv->lpll_hz / 2;
+ else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
+ parent = priv->bpll_hz / 4;
+ return DIV_TO_RATE(parent, div);
+ case ACLK_VO1_ROOT:
+ con = readl(&cru->clksel_con[158]);
+ div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
+ sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
+ if (sel == ACLK_VO0_ROOT_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
+ parent = priv->lpll_hz / 2;
+ else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
+ parent = priv->bpll_hz / 4;
+ return DIV_TO_RATE(parent, div);
+ case HCLK_VOP_ROOT:
+ con = readl(&cru->clksel_con[144]);
+ sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
+ if (sel == HCLK_VOP_ROOT_SEL_200M)
+ return 200 * MHz;
+ else if (sel == HCLK_VOP_ROOT_SEL_100M)
+ return 100 * MHz;
+ else if (sel == HCLK_VOP_ROOT_SEL_50M)
+ return 50 * MHz;
+ else
+ return OSC_HZ;
+ case PCLK_VOP_ROOT:
+ con = readl(&cru->clksel_con[144]);
+ sel = (con & PCLK_VOP_ROOT_SEL_MASK) >> PCLK_VOP_ROOT_SEL_SHIFT;
+ if (sel == PCLK_VOP_ROOT_SEL_100M)
+ return 100 * MHz;
+ else if (sel == PCLK_VOP_ROOT_SEL_50M)
+ return 50 * MHz;
+ else
+ return OSC_HZ;
+
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_aclk_vop_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int src_clk, div;
+
+ switch (clk_id) {
+ case ACLK_VOP_ROOT:
+ case ACLK_VOP:
+ if (rate == 700 * MHz) {
+ src_clk = ACLK_VOP_ROOT_SEL_SPLL;
+ div = 1;
+ } else if (!(priv->cpll_hz % rate)) {
+ src_clk = ACLK_VOP_ROOT_SEL_CPLL;
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = ACLK_VOP_ROOT_SEL_GPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ rk_clrsetreg(&cru->clksel_con[144],
+ ACLK_VOP_ROOT_DIV_MASK |
+ ACLK_VOP_ROOT_SEL_MASK,
+ (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
+ (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
+ break;
+ case ACLK_VO0_ROOT:
+ if (!(priv->cpll_hz % rate)) {
+ src_clk = ACLK_VO0_ROOT_SEL_CPLL;
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = ACLK_VO0_ROOT_SEL_GPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ rk_clrsetreg(&cru->clksel_con[149],
+ ACLK_VO0_ROOT_DIV_MASK |
+ ACLK_VO0_ROOT_SEL_MASK,
+ (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
+ (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
+ break;
+ case ACLK_VO1_ROOT:
+ if (!(priv->cpll_hz % rate)) {
+ src_clk = ACLK_VO0_ROOT_SEL_CPLL;
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ } else {
+ src_clk = ACLK_VO0_ROOT_SEL_GPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ }
+ rk_clrsetreg(&cru->clksel_con[158],
+ ACLK_VO0_ROOT_DIV_MASK |
+ ACLK_VO0_ROOT_SEL_MASK,
+ (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
+ (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
+ break;
+ case HCLK_VOP_ROOT:
+ if (rate == 200 * MHz)
+ src_clk = HCLK_VOP_ROOT_SEL_200M;
+ else if (rate == 100 * MHz)
+ src_clk = HCLK_VOP_ROOT_SEL_100M;
+ else if (rate == 50 * MHz)
+ src_clk = HCLK_VOP_ROOT_SEL_50M;
+ else
+ src_clk = HCLK_VOP_ROOT_SEL_OSC;
+ rk_clrsetreg(&cru->clksel_con[144],
+ HCLK_VOP_ROOT_SEL_MASK,
+ src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
+ break;
+ case PCLK_VOP_ROOT:
+ if (rate == 100 * MHz)
+ src_clk = PCLK_VOP_ROOT_SEL_100M;
+ else if (rate == 50 * MHz)
+ src_clk = PCLK_VOP_ROOT_SEL_50M;
+ else
+ src_clk = PCLK_VOP_ROOT_SEL_OSC;
+ rk_clrsetreg(&cru->clksel_con[144],
+ PCLK_VOP_ROOT_SEL_MASK,
+ src_clk << PCLK_VOP_ROOT_SEL_SHIFT);
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ return rk3576_aclk_vop_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_dclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ switch (clk_id) {
+ case DCLK_VP0:
+ case DCLK_VP0_SRC:
+ con = readl(&cru->clksel_con[145]);
+ div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
+ sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
+ break;
+ case DCLK_VP1:
+ case DCLK_VP1_SRC:
+ con = readl(&cru->clksel_con[146]);
+ div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
+ sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
+ break;
+ case DCLK_VP2:
+ case DCLK_VP2_SRC:
+ con = readl(&cru->clksel_con[147]);
+ div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
+ sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (sel == DCLK_VOP_SRC_SEL_VPLL)
+ parent = priv->vpll_hz;
+ else if (sel == DCLK_VOP_SRC_SEL_BPLL)
+ parent = priv->bpll_hz / 4;
+ else if (sel == DCLK_VOP_SRC_SEL_LPLL)
+ parent = priv->lpll_hz / 2;
+ else if (sel == DCLK_VOP_SRC_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else
+ parent = priv->cpll_hz;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+#define RK3576_VOP_PLL_LIMIT_FREQ 600000000
+
+static ulong rk3576_dclk_vop_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ ulong pll_rate, now, best_rate = 0;
+ u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
+ u32 mask, div_shift, sel_shift;
+
+ switch (clk_id) {
+ case DCLK_VP0:
+ case DCLK_VP0_SRC:
+ conid = 145;
+ con = readl(&cru->clksel_con[conid]);
+ sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
+ mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
+ div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
+ sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
+ break;
+ case DCLK_VP1:
+ case DCLK_VP1_SRC:
+ conid = 146;
+ con = readl(&cru->clksel_con[conid]);
+ sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
+ mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
+ div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
+ sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
+ break;
+ case DCLK_VP2:
+ case DCLK_VP2_SRC:
+ conid = 147;
+ con = readl(&cru->clksel_con[conid]);
+ sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
+ mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
+ div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
+ sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (sel == DCLK_VOP_SRC_SEL_VPLL) {
+ pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
+ priv->cru, VPLL);
+ if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
+ div = DIV_ROUND_UP(pll_rate, rate);
+ rk_clrsetreg(&cru->clksel_con[conid],
+ mask,
+ DCLK_VOP_SRC_SEL_VPLL << sel_shift |
+ ((div - 1) << div_shift));
+ } else {
+ div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ, rate);
+ if (div % 2)
+ div = div + 1;
+ rk_clrsetreg(&cru->clksel_con[conid],
+ mask,
+ DCLK_VOP_SRC_SEL_VPLL << sel_shift |
+ ((div - 1) << div_shift));
+ rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
+ priv->cru, VPLL, div * rate);
+ priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
+ priv->cru, VPLL);
+ }
+ } else {
+ for (i = 0; i <= DCLK_VOP_SRC_SEL_LPLL; i++) {
+ switch (i) {
+ case DCLK_VOP_SRC_SEL_GPLL:
+ pll_rate = priv->gpll_hz;
+ break;
+ case DCLK_VOP_SRC_SEL_CPLL:
+ pll_rate = priv->cpll_hz;
+ break;
+ case DCLK_VOP_SRC_SEL_BPLL:
+ pll_rate = 0;
+ break;
+ case DCLK_VOP_SRC_SEL_LPLL:
+ pll_rate = 0;
+ break;
+ case DCLK_VOP_SRC_SEL_VPLL:
+ pll_rate = 0;
+ break;
+ default:
+ printf("do not support this vop pll sel\n");
+ return -EINVAL;
+ }
+
+ div = DIV_ROUND_UP(pll_rate, rate);
+ if (div > 255)
+ continue;
+ now = pll_rate / div;
+ if (abs(rate - now) < abs(rate - best_rate)) {
+ best_rate = now;
+ best_div = div;
+ best_sel = i;
+ }
+ debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
+ pll_rate, best_rate, best_div, best_sel);
+ }
+
+ if (best_rate) {
+ rk_clrsetreg(&cru->clksel_con[conid],
+ mask,
+ best_sel << sel_shift |
+ (best_div - 1) << div_shift);
+ } else {
+ printf("do not support this vop freq %lu\n", rate);
+ return -EINVAL;
+ }
+ }
+
+ return rk3576_dclk_vop_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_clk_csihost_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ switch (clk_id) {
+ case CLK_DSIHOST0:
+ con = readl(&cru->clksel_con[151]);
+ div = (con & CLK_DSIHOST0_DIV_MASK) >> CLK_DSIHOST0_DIV_SHIFT;
+ sel = (con & CLK_DSIHOST0_SEL_MASK) >> CLK_DSIHOST0_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (sel == CLK_DSIHOST0_SEL_VPLL)
+ parent = priv->vpll_hz;
+ else if (sel == CLK_DSIHOST0_SEL_BPLL)
+ parent = priv->bpll_hz / 4;
+ else if (sel == CLK_DSIHOST0_SEL_LPLL)
+ parent = priv->lpll_hz / 2;
+ else if (sel == CLK_DSIHOST0_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == CLK_DSIHOST0_SEL_SPLL)
+ parent = priv->spll_hz;
+ else
+ parent = priv->cpll_hz;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3576_clk_csihost_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ ulong pll_rate, now, best_rate = 0;
+ u32 i, con, div, best_div = 0, best_sel = 0;
+ u32 mask, div_shift, sel_shift;
+
+ switch (clk_id) {
+ case CLK_DSIHOST0:
+ con = 151;
+ mask = CLK_DSIHOST0_SEL_MASK | CLK_DSIHOST0_DIV_MASK;
+ div_shift = CLK_DSIHOST0_DIV_SHIFT;
+ sel_shift = CLK_DSIHOST0_SEL_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+ for (i = 0; i <= CLK_DSIHOST0_SEL_LPLL; i++) {
+ switch (i) {
+ case CLK_DSIHOST0_SEL_GPLL:
+ pll_rate = priv->gpll_hz;
+ break;
+ case CLK_DSIHOST0_SEL_CPLL:
+ pll_rate = priv->cpll_hz;
+ break;
+ case CLK_DSIHOST0_SEL_BPLL:
+ pll_rate = 0;
+ break;
+ case CLK_DSIHOST0_SEL_LPLL:
+ pll_rate = 0;
+ break;
+ case CLK_DSIHOST0_SEL_VPLL:
+ pll_rate = 0;
+ break;
+ case CLK_DSIHOST0_SEL_SPLL:
+ pll_rate = priv->spll_hz;
+ break;
+ default:
+ printf("do not support this vop pll sel\n");
+ return -EINVAL;
+ }
+
+ div = DIV_ROUND_UP(pll_rate, rate);
+ if (div > 255)
+ continue;
+ now = pll_rate / div;
+ if (abs(rate - now) < abs(rate - best_rate)) {
+ best_rate = now;
+ best_div = div;
+ best_sel = i;
+ }
+ debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
+ pll_rate, best_rate, best_div, best_sel);
+ }
+
+ if (best_rate) {
+ rk_clrsetreg(&cru->clksel_con[con],
+ mask,
+ best_sel << sel_shift |
+ (best_div - 1) << div_shift);
+ } else {
+ printf("do not support this vop freq %lu\n", rate);
+ return -EINVAL;
+ }
+
+ return rk3576_clk_csihost_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_dclk_ebc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+ unsigned long m = 0, n = 0;
+
+ switch (clk_id) {
+ case DCLK_EBC:
+ con = readl(&cru->clksel_con[123]);
+ div = (con & DCLK_EBC_DIV_MASK) >> DCLK_EBC_DIV_SHIFT;
+ sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
+ if (sel == DCLK_EBC_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == DCLK_EBC_SEL_VPLL)
+ parent = priv->vpll_hz;
+ else if (sel == DCLK_EBC_SEL_AUPLL)
+ parent = priv->aupll_hz;
+ else if (sel == DCLK_EBC_SEL_LPLL)
+ parent = priv->lpll_hz / 2;
+ else if (sel == DCLK_EBC_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == DCLK_EBC_SEL_FRAC_SRC)
+ parent = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC);
+ else
+ parent = OSC_HZ;
+ return DIV_TO_RATE(parent, div);
+ case DCLK_EBC_FRAC_SRC:
+ con = readl(&cru->clksel_con[123]);
+ div = readl(&cru->clksel_con[122]);
+ sel = (con & DCLK_EBC_FRAC_SRC_SEL_MASK) >> DCLK_EBC_FRAC_SRC_SEL_SHIFT;
+ if (sel == DCLK_EBC_FRAC_SRC_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == DCLK_EBC_FRAC_SRC_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == DCLK_EBC_FRAC_SRC_SEL_VPLL)
+ parent = priv->vpll_hz;
+ else if (sel == DCLK_EBC_FRAC_SRC_SEL_AUPLL)
+ parent = priv->aupll_hz;
+ else
+ parent = OSC_HZ;
+
+ n = div & CLK_UART_FRAC_NUMERATOR_MASK;
+ n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
+ m = div & CLK_UART_FRAC_DENOMINATOR_MASK;
+ m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
+ return parent * n / m;
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_dclk_ebc_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ ulong pll_rate, now, best_rate = 0;
+ u32 i, con, sel, div, best_div = 0, best_sel = 0;
+ unsigned long m = 0, n = 0, val;
+
+ switch (clk_id) {
+ case DCLK_EBC:
+ con = readl(&cru->clksel_con[123]);
+ sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
+ if (sel == DCLK_EBC_SEL_VPLL) {
+ pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
+ priv->cru, VPLL);
+ if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ &&
+ pll_rate % rate == 0) {
+ div = DIV_ROUND_UP(pll_rate, rate);
+ rk_clrsetreg(&cru->clksel_con[123],
+ DCLK_EBC_DIV_MASK,
+ (div - 1) << DCLK_EBC_DIV_SHIFT);
+ } else {
+ div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ,
+ rate);
+ if (div % 2)
+ div = div + 1;
+ rk_clrsetreg(&cru->clksel_con[123],
+ DCLK_EBC_DIV_MASK,
+ (div - 1) << DCLK_EBC_DIV_SHIFT);
+ rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
+ priv->cru,
+ VPLL, div * rate);
+ priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
+ priv->cru,
+ VPLL);
+ }
+ } else if (sel == DCLK_EBC_SEL_FRAC_SRC) {
+ rk3576_dclk_ebc_set_clk(priv, DCLK_EBC_FRAC_SRC, rate);
+ div = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC) / rate;
+ rk_clrsetreg(&cru->clksel_con[123],
+ DCLK_EBC_DIV_MASK,
+ (div - 1) << DCLK_EBC_DIV_SHIFT);
+ } else {
+ for (i = 0; i <= DCLK_EBC_SEL_LPLL; i++) {
+ switch (i) {
+ case DCLK_EBC_SEL_GPLL:
+ pll_rate = priv->gpll_hz;
+ break;
+ case DCLK_EBC_SEL_CPLL:
+ pll_rate = priv->cpll_hz;
+ break;
+ case DCLK_EBC_SEL_VPLL:
+ pll_rate = 0;
+ break;
+ case DCLK_EBC_SEL_AUPLL:
+ pll_rate = priv->aupll_hz;
+ break;
+ case DCLK_EBC_SEL_LPLL:
+ pll_rate = 0;
+ break;
+ default:
+ printf("not support ebc pll sel\n");
+ return -EINVAL;
+ }
+
+ div = DIV_ROUND_UP(pll_rate, rate);
+ if (div > 255)
+ continue;
+ now = pll_rate / div;
+ if (abs(rate - now) < abs(rate - best_rate)) {
+ best_rate = now;
+ best_div = div;
+ best_sel = i;
+ }
+ }
+
+ if (best_rate) {
+ rk_clrsetreg(&cru->clksel_con[123],
+ DCLK_EBC_DIV_MASK |
+ DCLK_EBC_SEL_MASK,
+ best_sel <<
+ DCLK_EBC_SEL_SHIFT |
+ (best_div - 1) <<
+ DCLK_EBC_DIV_SHIFT);
+ } else {
+ printf("do not support this vop freq %lu\n",
+ rate);
+ return -EINVAL;
+ }
+ }
+ break;
+ case DCLK_EBC_FRAC_SRC:
+ sel = DCLK_EBC_FRAC_SRC_SEL_GPLL;
+ div = 1;
+ rational_best_approximation(rate, priv->gpll_hz,
+ GENMASK(16 - 1, 0),
+ GENMASK(16 - 1, 0),
+ &m, &n);
+
+ if (m < 4 && m != 0) {
+ if (n % 2 == 0)
+ val = 1;
+ else
+ val = DIV_ROUND_UP(4, m);
+
+ n *= val;
+ m *= val;
+ if (n > 0xffff)
+ n = 0xffff;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[123],
+ DCLK_EBC_FRAC_SRC_SEL_MASK,
+ (sel << DCLK_EBC_FRAC_SRC_SEL_SHIFT));
+ if (m && n) {
+ val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
+ writel(val, &cru->clksel_con[122]);
+ }
+ break;
+ default:
+ return -ENOENT;
+ }
+ return rk3576_dclk_ebc_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_gmac_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 con, div, src, p_rate;
+
+ switch (clk_id) {
+ case CLK_GMAC0_PTP_REF_SRC:
+ case CLK_GMAC0_PTP_REF:
+ con = readl(&cru->clksel_con[105]);
+ div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
+ src = (con & CLK_GMAC0_PTP_SEL_MASK) >> CLK_GMAC0_PTP_SEL_SHIFT;
+ if (src == CLK_GMAC0_PTP_SEL_GPLL)
+ p_rate = priv->gpll_hz;
+ else if (src == CLK_GMAC0_PTP_SEL_CPLL)
+ p_rate = priv->cpll_hz;
+ else
+ p_rate = GMAC0_PTP_REFCLK_IN;
+ return DIV_TO_RATE(p_rate, div);
+ case CLK_GMAC1_PTP_REF_SRC:
+ case CLK_GMAC1_PTP_REF:
+ con = readl(&cru->clksel_con[104]);
+ div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
+ src = (con & CLK_GMAC1_PTP_SEL_MASK) >> CLK_GMAC1_PTP_SEL_SHIFT;
+ if (src == CLK_GMAC1_PTP_SEL_GPLL)
+ p_rate = priv->gpll_hz;
+ else if (src == CLK_GMAC1_PTP_SEL_CPLL)
+ p_rate = priv->cpll_hz;
+ else
+ p_rate = GMAC1_PTP_REFCLK_IN;
+ return DIV_TO_RATE(p_rate, div);
+ case CLK_GMAC0_125M_SRC:
+ con = readl(&cru->clksel_con[30]);
+ div = (con & CLK_GMAC0_125M_DIV_MASK) >> CLK_GMAC0_125M_DIV_SHIFT;
+ return DIV_TO_RATE(priv->cpll_hz, div);
+ case CLK_GMAC1_125M_SRC:
+ con = readl(&cru->clksel_con[31]);
+ div = (con & CLK_GMAC1_125M_DIV_MASK) >> CLK_GMAC1_125M_DIV_SHIFT;
+ return DIV_TO_RATE(priv->cpll_hz, div);
+ default:
+ return -ENOENT;
+ }
+}
+
+static ulong rk3576_gmac_set_clk(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ int div, src;
+
+ div = DIV_ROUND_UP(priv->cpll_hz, rate);
+
+ switch (clk_id) {
+ case CLK_GMAC0_PTP_REF_SRC:
+ case CLK_GMAC0_PTP_REF:
+ if (rate == GMAC0_PTP_REFCLK_IN) {
+ src = CLK_GMAC0_PTP_SEL_REFIN;
+ div = 1;
+ } else if (!(priv->gpll_hz % rate)) {
+ src = CLK_GMAC0_PTP_SEL_GPLL;
+ div = priv->gpll_hz / rate;
+ } else {
+ src = CLK_GMAC0_PTP_SEL_CPLL;
+ div = priv->cpll_hz / rate;
+ }
+ rk_clrsetreg(&cru->clksel_con[105],
+ CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
+ src << CLK_GMAC0_PTP_SEL_SHIFT |
+ (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
+ break;
+ case CLK_GMAC1_PTP_REF_SRC:
+ case CLK_GMAC1_PTP_REF:
+ if (rate == GMAC1_PTP_REFCLK_IN) {
+ src = CLK_GMAC1_PTP_SEL_REFIN;
+ div = 1;
+ } else if (!(priv->gpll_hz % rate)) {
+ src = CLK_GMAC1_PTP_SEL_GPLL;
+ div = priv->gpll_hz / rate;
+ } else {
+ src = CLK_GMAC1_PTP_SEL_CPLL;
+ div = priv->cpll_hz / rate;
+ }
+ rk_clrsetreg(&cru->clksel_con[104],
+ CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
+ src << CLK_GMAC1_PTP_SEL_SHIFT |
+ (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
+ break;
+
+ case CLK_GMAC0_125M_SRC:
+ rk_clrsetreg(&cru->clksel_con[30],
+ CLK_GMAC0_125M_DIV_MASK,
+ (div - 1) << CLK_GMAC0_125M_DIV_SHIFT);
+ break;
+ case CLK_GMAC1_125M_SRC:
+ rk_clrsetreg(&cru->clksel_con[31],
+ CLK_GMAC1_125M_DIV_MASK,
+ (div - 1) << CLK_GMAC1_125M_DIV_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rk3576_gmac_get_clk(priv, clk_id);
+}
+
+static ulong rk3576_uart_frac_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 reg, con, fracdiv, p_src, p_rate;
+ unsigned long m, n;
+
+ switch (clk_id) {
+ case CLK_UART_FRAC_0:
+ reg = 21;
+ break;
+ case CLK_UART_FRAC_1:
+ reg = 23;
+ break;
+ case CLK_UART_FRAC_2:
+ reg = 25;
+ break;
+ default:
+ return -ENOENT;
+ }
+ con = readl(&cru->clksel_con[reg + 1]);
+ p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
+ if (p_src == CLK_UART_SRC_SEL_GPLL)
+ p_rate = priv->gpll_hz;
+ else if (p_src == CLK_UART_SRC_SEL_CPLL)
+ p_rate = priv->cpll_hz;
+ else if (p_src == CLK_UART_SRC_SEL_AUPLL)
+ p_rate = priv->aupll_hz;
+ else
+ p_rate = OSC_HZ;
+
+ fracdiv = readl(&cru->clksel_con[reg]);
+ n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
+ n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
+ m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
+ m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
+ return p_rate * n / m;
+}
+
+static ulong rk3576_uart_frac_set_rate(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 reg, clk_src, p_rate;
+ unsigned long m = 0, n = 0, val;
+
+ if (priv->cpll_hz % rate == 0) {
+ clk_src = CLK_UART_SRC_SEL_CPLL;
+ p_rate = priv->cpll_hz;
+ } else if (rate == OSC_HZ) {
+ clk_src = CLK_UART_SRC_SEL_OSC;
+ p_rate = OSC_HZ;
+ } else {
+ clk_src = CLK_UART_SRC_SEL_GPLL;
+ p_rate = priv->cpll_hz;
+ }
+
+ rational_best_approximation(rate, p_rate, GENMASK(16 - 1, 0),
+ GENMASK(16 - 1, 0), &m, &n);
+
+ if (m < 4 && m != 0) {
+ if (n % 2 == 0)
+ val = 1;
+ else
+ val = DIV_ROUND_UP(4, m);
+
+ n *= val;
+ m *= val;
+ if (n > 0xffff)
+ n = 0xffff;
+ }
+
+ switch (clk_id) {
+ case CLK_UART_FRAC_0:
+ reg = 21;
+ break;
+ case CLK_UART_FRAC_1:
+ reg = 23;
+ break;
+ case CLK_UART_FRAC_2:
+ reg = 25;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[reg + 1],
+ CLK_UART_SRC_SEL_MASK,
+ (clk_src << CLK_UART_SRC_SEL_SHIFT));
+ if (m && n) {
+ val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
+ writel(val, &cru->clksel_con[reg]);
+ }
+
+ return rk3576_uart_frac_get_rate(priv, clk_id);
+}
+
+static ulong rk3576_uart_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 con, div, src, p_rate;
+
+ switch (clk_id) {
+ case SCLK_UART0:
+ con = readl(&cru->clksel_con[60]);
+ break;
+ case SCLK_UART1:
+ con = readl(&cru->pmuclksel_con[8]);
+ src = (con & CLK_UART1_SEL_MASK) >> CLK_UART1_SEL_SHIFT;
+ if (src == CLK_UART1_SEL_OSC)
+ return OSC_HZ;
+ con = readl(&cru->clksel_con[27]);
+ break;
+ case SCLK_UART2:
+ con = readl(&cru->clksel_con[61]);
+ break;
+ case SCLK_UART3:
+ con = readl(&cru->clksel_con[62]);
+ break;
+ case SCLK_UART4:
+ con = readl(&cru->clksel_con[63]);
+ break;
+ case SCLK_UART5:
+ con = readl(&cru->clksel_con[64]);
+ break;
+ case SCLK_UART6:
+ con = readl(&cru->clksel_con[65]);
+ break;
+ case SCLK_UART7:
+ con = readl(&cru->clksel_con[66]);
+ break;
+ case SCLK_UART8:
+ con = readl(&cru->clksel_con[67]);
+ break;
+ case SCLK_UART9:
+ con = readl(&cru->clksel_con[68]);
+ break;
+ case SCLK_UART10:
+ con = readl(&cru->clksel_con[69]);
+ break;
+ case SCLK_UART11:
+ con = readl(&cru->clksel_con[70]);
+ break;
+ default:
+ return -ENOENT;
+ }
+ if (clk_id == SCLK_UART1) {
+ src = (con & CLK_UART1_SRC_SEL_SHIFT) >> CLK_UART1_SRC_SEL_SHIFT;
+ div = (con & CLK_UART1_SRC_DIV_MASK) >> CLK_UART1_SRC_DIV_SHIFT;
+ } else {
+ src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
+ div = (con & CLK_UART_DIV_MASK) >> CLK_UART_DIV_SHIFT;
+ }
+ if (src == CLK_UART_SEL_GPLL)
+ p_rate = priv->gpll_hz;
+ else if (src == CLK_UART_SEL_CPLL)
+ p_rate = priv->cpll_hz;
+ else if (src == CLK_UART_SEL_AUPLL)
+ p_rate = priv->aupll_hz;
+ else if (src == CLK_UART_SEL_FRAC0)
+ p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0);
+ else if (src == CLK_UART_SEL_FRAC1)
+ p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1);
+ else if (src == CLK_UART_SEL_FRAC2)
+ p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2);
+ else
+ p_rate = OSC_HZ;
+
+ return DIV_TO_RATE(p_rate, div);
+}
+
+static ulong rk3576_uart_set_rate(struct rk3576_clk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 reg, clk_src = 0, div = 0;
+
+ if (!(priv->gpll_hz % rate)) {
+ clk_src = CLK_UART_SEL_GPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ } else if (!(priv->cpll_hz % rate)) {
+ clk_src = CLK_UART_SEL_CPLL;
+ div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0) % rate)) {
+ clk_src = CLK_UART_SEL_FRAC0;
+ div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0), rate);
+ } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1) % rate)) {
+ clk_src = CLK_UART_SEL_FRAC1;
+ div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1), rate);
+ } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2) % rate)) {
+ clk_src = CLK_UART_SEL_FRAC2;
+ div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2), rate);
+ } else if (!(OSC_HZ % rate)) {
+ clk_src = CLK_UART_SEL_OSC;
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ }
+
+ switch (clk_id) {
+ case SCLK_UART0:
+ reg = 60;
+ break;
+ case SCLK_UART1:
+ if (rate == OSC_HZ) {
+ rk_clrsetreg(&cru->pmuclksel_con[8],
+ CLK_UART1_SEL_MASK,
+ CLK_UART1_SEL_OSC << CLK_UART1_SEL_SHIFT);
+ return 0;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[27],
+ CLK_UART1_SRC_SEL_MASK | CLK_UART1_SRC_DIV_MASK,
+ (clk_src << CLK_UART1_SRC_SEL_SHIFT) |
+ ((div - 1) << CLK_UART1_SRC_DIV_SHIFT));
+ rk_clrsetreg(&cru->pmuclksel_con[8],
+ CLK_UART1_SEL_MASK,
+ CLK_UART1_SEL_TOP << CLK_UART1_SEL_SHIFT);
+ return 0;
+ case SCLK_UART2:
+ reg = 61;
+ break;
+ case SCLK_UART3:
+ reg = 62;
+ break;
+ case SCLK_UART4:
+ reg = 63;
+ break;
+ case SCLK_UART5:
+ reg = 64;
+ break;
+ case SCLK_UART6:
+ reg = 65;
+ break;
+ case SCLK_UART7:
+ reg = 66;
+ break;
+ case SCLK_UART8:
+ reg = 67;
+ break;
+ case SCLK_UART9:
+ reg = 68;
+ break;
+ case SCLK_UART10:
+ reg = 69;
+ break;
+ case SCLK_UART11:
+ reg = 70;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[reg],
+ CLK_UART_SEL_MASK |
+ CLK_UART_DIV_MASK,
+ (clk_src << CLK_UART_SEL_SHIFT) |
+ ((div - 1) << CLK_UART_DIV_SHIFT));
+
+ return rk3576_uart_get_rate(priv, clk_id);
+}
+#endif
+
+static ulong rk3576_ufs_ref_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
+{
+ struct rk3576_cru *cru = priv->cru;
+ u32 src, div;
+
+ src = readl(&cru->pmuclksel_con[3]) & 0x3;
+ div = readl(&cru->pmuclksel_con[1]) & 0xff;
+ if (src == 0)
+ return OSC_HZ;
+ else if (src == 2)
+ return priv->ppll_hz / (div + 1);
+ else
+ return 26000000;
+}
+
+static ulong rk3576_clk_get_rate(struct clk *clk)
+{
+ struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ if (!priv->gpll_hz) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ if (!priv->ppll_hz) {
+ priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
+ priv->cru, PPLL);
+ }
+
+ switch (clk->id) {
+ case PLL_LPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[LPLL], priv->cru,
+ LPLL);
+ priv->lpll_hz = rate;
+ break;
+ case PLL_BPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[BPLL], priv->cru,
+ BPLL);
+ priv->bpll_hz = rate;
+ break;
+ case PLL_GPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL], priv->cru,
+ GPLL);
+ break;
+ case PLL_CPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL], priv->cru,
+ CPLL);
+ break;
+ case PLL_VPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL], priv->cru,
+ VPLL);
+ break;
+ case PLL_AUPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL], priv->cru,
+ AUPLL);
+ break;
+ case PLL_PPLL:
+ rate = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL], priv->cru,
+ PPLL) * 2;
+ break;
+ case ACLK_BUS_ROOT:
+ case HCLK_BUS_ROOT:
+ case PCLK_BUS_ROOT:
+ rate = rk3576_bus_get_clk(priv, clk->id);
+ break;
+ case ACLK_TOP:
+ case HCLK_TOP:
+ case PCLK_TOP_ROOT:
+ case ACLK_TOP_MID:
+ rate = rk3576_top_get_clk(priv, clk->id);
+ break;
+ case CLK_I2C0:
+ case CLK_I2C1:
+ case CLK_I2C2:
+ case CLK_I2C3:
+ case CLK_I2C4:
+ case CLK_I2C5:
+ case CLK_I2C6:
+ case CLK_I2C7:
+ case CLK_I2C8:
+ case CLK_I2C9:
+ rate = rk3576_i2c_get_clk(priv, clk->id);
+ break;
+ case CLK_SPI0:
+ case CLK_SPI1:
+ case CLK_SPI2:
+ case CLK_SPI3:
+ case CLK_SPI4:
+ rate = rk3576_spi_get_clk(priv, clk->id);
+ break;
+ case CLK_PWM1:
+ case CLK_PWM2:
+ case CLK_PMU1PWM:
+ rate = rk3576_pwm_get_clk(priv, clk->id);
+ break;
+ case CLK_SARADC:
+ case CLK_TSADC:
+ rate = rk3576_adc_get_clk(priv, clk->id);
+ break;
+ case CCLK_SRC_SDIO:
+ case CCLK_SRC_SDMMC0:
+ case CCLK_SRC_EMMC:
+ case BCLK_EMMC:
+ case SCLK_FSPI_X2:
+ case SCLK_FSPI1_X2:
+ case DCLK_DECOM:
+ case HCLK_SDMMC0:
+ case HCLK_EMMC:
+ case HCLK_SDIO:
+ rate = rk3576_mmc_get_clk(priv, clk->id);
+ break;
+ case TCLK_EMMC:
+ case TCLK_WDT0:
+ rate = OSC_HZ;
+ break;
+#ifndef CONFIG_SPL_BUILD
+ case ACLK_VOP_ROOT:
+ case ACLK_VOP:
+ case ACLK_VO0_ROOT:
+ case ACLK_VO1_ROOT:
+ case HCLK_VOP_ROOT:
+ case PCLK_VOP_ROOT:
+ rate = rk3576_aclk_vop_get_clk(priv, clk->id);
+ break;
+ case DCLK_VP0:
+ case DCLK_VP0_SRC:
+ case DCLK_VP1:
+ case DCLK_VP1_SRC:
+ case DCLK_VP2:
+ case DCLK_VP2_SRC:
+ rate = rk3576_dclk_vop_get_clk(priv, clk->id);
+ break;
+ case CLK_GMAC0_PTP_REF_SRC:
+ case CLK_GMAC1_PTP_REF_SRC:
+ case CLK_GMAC0_PTP_REF:
+ case CLK_GMAC1_PTP_REF:
+ case CLK_GMAC0_125M_SRC:
+ case CLK_GMAC1_125M_SRC:
+ rate = rk3576_gmac_get_clk(priv, clk->id);
+ break;
+ case CLK_UART_FRAC_0:
+ case CLK_UART_FRAC_1:
+ case CLK_UART_FRAC_2:
+ rate = rk3576_uart_frac_get_rate(priv, clk->id);
+ break;
+ case SCLK_UART0:
+ case SCLK_UART1:
+ case SCLK_UART2:
+ case SCLK_UART3:
+ case SCLK_UART4:
+ case SCLK_UART5:
+ case SCLK_UART6:
+ case SCLK_UART7:
+ case SCLK_UART8:
+ case SCLK_UART9:
+ case SCLK_UART10:
+ case SCLK_UART11:
+ rate = rk3576_uart_get_rate(priv, clk->id);
+ break;
+ case CLK_DSIHOST0:
+ rate = rk3576_clk_csihost_get_clk(priv, clk->id);
+ break;
+ case DCLK_EBC:
+ case DCLK_EBC_FRAC_SRC:
+ rate = rk3576_dclk_ebc_get_clk(priv, clk->id);
+ break;
+#endif
+ case CLK_REF_UFS_CLKOUT:
+ case CLK_REF_OSC_MPHY:
+ rate = rk3576_ufs_ref_get_rate(priv, clk->id);
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+};
+
+static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate)
+{
+ struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ if (!priv->ppll_hz) {
+ priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
+ priv->cru, PPLL);
+ }
+ if (!priv->aupll_hz) {
+ priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
+ priv->cru, AUPLL);
+ }
+
+ switch (clk->id) {
+ case PLL_CPLL:
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
+ CPLL, rate);
+ priv->cpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL],
+ priv->cru, CPLL);
+ break;
+ case PLL_GPLL:
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
+ GPLL, rate);
+ priv->gpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL],
+ priv->cru, GPLL);
+ break;
+ case PLL_VPLL:
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[VPLL], priv->cru,
+ VPLL, rate);
+ priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
+ priv->cru, VPLL);
+ break;
+ case PLL_AUPLL:
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[AUPLL], priv->cru,
+ AUPLL, rate);
+ priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
+ priv->cru, AUPLL);
+ break;
+ case PLL_PPLL:
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[PPLL], priv->cru,
+ PPLL, rate);
+ priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
+ priv->cru, PPLL) * 2;
+ break;
+ case ACLK_BUS_ROOT:
+ case HCLK_BUS_ROOT:
+ case PCLK_BUS_ROOT:
+ ret = rk3576_bus_set_clk(priv, clk->id, rate);
+ break;
+ case ACLK_TOP:
+ case HCLK_TOP:
+ case PCLK_TOP_ROOT:
+ case ACLK_TOP_MID:
+ ret = rk3576_top_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_I2C0:
+ case CLK_I2C1:
+ case CLK_I2C2:
+ case CLK_I2C3:
+ case CLK_I2C4:
+ case CLK_I2C5:
+ case CLK_I2C6:
+ case CLK_I2C7:
+ case CLK_I2C8:
+ case CLK_I2C9:
+ ret = rk3576_i2c_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_SPI0:
+ case CLK_SPI1:
+ case CLK_SPI2:
+ case CLK_SPI3:
+ case CLK_SPI4:
+ ret = rk3576_spi_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_PWM1:
+ case CLK_PWM2:
+ case CLK_PMU1PWM:
+ ret = rk3576_pwm_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_SARADC:
+ case CLK_TSADC:
+ ret = rk3576_adc_set_clk(priv, clk->id, rate);
+ break;
+ case CCLK_SRC_SDIO:
+ case CCLK_SRC_SDMMC0:
+ case CCLK_SRC_EMMC:
+ case BCLK_EMMC:
+ case SCLK_FSPI_X2:
+ case SCLK_FSPI1_X2:
+ case DCLK_DECOM:
+ case HCLK_SDMMC0:
+ case HCLK_EMMC:
+ case HCLK_SDIO:
+ ret = rk3576_mmc_set_clk(priv, clk->id, rate);
+ break;
+ case TCLK_EMMC:
+ case TCLK_WDT0:
+ ret = OSC_HZ;
+ break;
+
+ /* Might occur in cru assigned-clocks, can be ignored here */
+ case CLK_AUDIO_FRAC_0:
+ case CLK_AUDIO_FRAC_1:
+ case CLK_AUDIO_FRAC_0_SRC:
+ case CLK_AUDIO_FRAC_1_SRC:
+ case CLK_CPLL_DIV2:
+ case CLK_CPLL_DIV4:
+ case CLK_CPLL_DIV10:
+ case FCLK_DDR_CM0_CORE:
+ case ACLK_PHP_ROOT:
+ ret = 0;
+ break;
+#ifndef CONFIG_SPL_BUILD
+ case ACLK_VOP_ROOT:
+ case ACLK_VOP:
+ case ACLK_VO0_ROOT:
+ case ACLK_VO1_ROOT:
+ case HCLK_VOP_ROOT:
+ case PCLK_VOP_ROOT:
+ ret = rk3576_aclk_vop_set_clk(priv, clk->id, rate);
+ break;
+ case DCLK_VP0:
+ case DCLK_VP0_SRC:
+ case DCLK_VP1:
+ case DCLK_VP1_SRC:
+ case DCLK_VP2:
+ case DCLK_VP2_SRC:
+ ret = rk3576_dclk_vop_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_GMAC0_PTP_REF_SRC:
+ case CLK_GMAC1_PTP_REF_SRC:
+ case CLK_GMAC0_PTP_REF:
+ case CLK_GMAC1_PTP_REF:
+ case CLK_GMAC0_125M_SRC:
+ case CLK_GMAC1_125M_SRC:
+ ret = rk3576_gmac_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_UART_FRAC_0:
+ case CLK_UART_FRAC_1:
+ case CLK_UART_FRAC_2:
+ ret = rk3576_uart_frac_set_rate(priv, clk->id, rate);
+ break;
+ case SCLK_UART0:
+ case SCLK_UART1:
+ case SCLK_UART2:
+ case SCLK_UART3:
+ case SCLK_UART4:
+ case SCLK_UART5:
+ case SCLK_UART6:
+ case SCLK_UART7:
+ case SCLK_UART8:
+ case SCLK_UART9:
+ case SCLK_UART10:
+ case SCLK_UART11:
+ ret = rk3576_uart_set_rate(priv, clk->id, rate);
+ break;
+ case CLK_DSIHOST0:
+ ret = rk3576_clk_csihost_set_clk(priv, clk->id, rate);
+ break;
+ case DCLK_EBC:
+ case DCLK_EBC_FRAC_SRC:
+ ret = rk3576_dclk_ebc_set_clk(priv, clk->id, rate);
+ break;
+#endif
+ default:
+ return -ENOENT;
+ }
+
+ return ret;
+};
+
+#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
+static int __maybe_unused rk3576_dclk_vop_set_parent(struct clk *clk,
+ struct clk *parent)
+{
+ struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rk3576_cru *cru = priv->cru;
+ u32 sel;
+ const char *clock_dev_name = parent->dev->name;
+
+ if (parent->id == PLL_VPLL)
+ sel = 2;
+ else if (parent->id == PLL_GPLL)
+ sel = 0;
+ else if (parent->id == PLL_CPLL)
+ sel = 1;
+ else if (parent->id == PLL_BPLL)
+ sel = 3;
+ else
+ sel = 4;
+
+ switch (clk->id) {
+ case DCLK_VP0_SRC:
+ rk_clrsetreg(&cru->clksel_con[145], DCLK0_VOP_SRC_SEL_MASK,
+ sel << DCLK0_VOP_SRC_SEL_SHIFT);
+ break;
+ case DCLK_VP1_SRC:
+ rk_clrsetreg(&cru->clksel_con[146], DCLK0_VOP_SRC_SEL_MASK,
+ sel << DCLK0_VOP_SRC_SEL_SHIFT);
+ break;
+ case DCLK_VP2_SRC:
+ rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SRC_SEL_MASK,
+ sel << DCLK0_VOP_SRC_SEL_SHIFT);
+ break;
+ case DCLK_VP0:
+ if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
+ sel = 1;
+ else
+ sel = 0;
+ rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SEL_MASK,
+ sel << DCLK0_VOP_SEL_SHIFT);
+ break;
+ case DCLK_VP1:
+ if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
+ sel = 1;
+ else
+ sel = 0;
+ rk_clrsetreg(&cru->clksel_con[147], DCLK1_VOP_SEL_MASK,
+ sel << DCLK1_VOP_SEL_SHIFT);
+ break;
+ case DCLK_VP2:
+ if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
+ sel = 1;
+ else
+ sel = 0;
+ rk_clrsetreg(&cru->clksel_con[147], DCLK2_VOP_SEL_MASK,
+ sel << DCLK2_VOP_SEL_SHIFT);
+ break;
+ case DCLK_EBC:
+ if (parent->id == PLL_GPLL)
+ sel = 0;
+ else if (parent->id == PLL_CPLL)
+ sel = 1;
+ else if (parent->id == PLL_VPLL)
+ sel = 2;
+ else if (parent->id == PLL_AUPLL)
+ sel = 3;
+ else if (parent->id == PLL_LPLL)
+ sel = 4;
+ else if (parent->id == DCLK_EBC_FRAC_SRC)
+ sel = 5;
+ else
+ sel = 6;
+ rk_clrsetreg(&cru->clksel_con[123], DCLK_EBC_SEL_MASK,
+ sel << DCLK_EBC_SEL_SHIFT);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int __maybe_unused rk3576_ufs_ref_set_parent(struct clk *clk,
+ struct clk *parent)
+{
+ struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rk3576_cru *cru = priv->cru;
+ u32 sel;
+ const char *clock_dev_name = parent->dev->name;
+
+ if (parent->id == CLK_REF_MPHY_26M)
+ sel = 2;
+ else if (!strcmp(clock_dev_name, "xin24m"))
+ sel = 0;
+ else
+ sel = 1;
+
+ rk_clrsetreg(&cru->pmuclksel_con[3], 0x3, sel << 0);
+ return 0;
+}
+
+static int rk3576_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ switch (clk->id) {
+ case DCLK_VP0_SRC:
+ case DCLK_VP1_SRC:
+ case DCLK_VP2_SRC:
+ case DCLK_VP0:
+ case DCLK_VP1:
+ case DCLK_VP2:
+ case DCLK_EBC:
+ return rk3576_dclk_vop_set_parent(clk, parent);
+ case CLK_REF_OSC_MPHY:
+ return rk3576_ufs_ref_set_parent(clk, parent);
+ case CLK_AUDIO_FRAC_0_SRC:
+ case CLK_AUDIO_FRAC_1_SRC:
+ /* Might occur in cru assigned-clocks, can be ignored here */
+ return 0;
+ default:
+ return -ENOENT;
+ }
+
+ return 0;
+}
+#endif
+
+static struct clk_ops rk3576_clk_ops = {
+ .get_rate = rk3576_clk_get_rate,
+ .set_rate = rk3576_clk_set_rate,
+#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
+ .set_parent = rk3576_clk_set_parent,
+#endif
+};
+
+static void rk3576_clk_init(struct rk3576_clk_priv *priv)
+{
+ int ret;
+
+ priv->spll_hz = 702000000;
+
+ if (priv->cpll_hz != CPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
+ CPLL, CPLL_HZ);
+ if (!ret)
+ priv->cpll_hz = CPLL_HZ;
+ }
+ if (priv->gpll_hz != GPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
+ GPLL, GPLL_HZ);
+ if (!ret)
+ priv->gpll_hz = GPLL_HZ;
+ }
+ rk_clrsetreg(&priv->cru->clksel_con[123],
+ DCLK_EBC_FRAC_SRC_SEL_MASK,
+ (DCLK_EBC_FRAC_SRC_SEL_GPLL <<
+ DCLK_EBC_FRAC_SRC_SEL_SHIFT));
+}
+
+static int rk3576_clk_probe(struct udevice *dev)
+{
+ struct rk3576_clk_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ priv->sync_kernel = false;
+
+#ifdef CONFIG_SPL_BUILD
+ /* relase presetn_bigcore_biu/cru/grf */
+ writel(0x1c001c00, 0x26010010);
+ /* set spll to normal mode */
+ writel(BITS_WITH_WMASK(2, 0x7U, 6),
+ RK3576_SCRU_BASE + RK3576_PLL_CON(137));
+ writel(BITS_WITH_WMASK(1, 0x3U, 0),
+ RK3576_SCRU_BASE + RK3576_MODE_CON0);
+ /* fix ppll\aupll\cpll */
+ writel(BITS_WITH_WMASK(2, 0x7U, 6),
+ RK3576_CRU_BASE + RK3576_PMU_PLL_CON(129));
+ writel(BITS_WITH_WMASK(2, 0x7U, 6),
+ RK3576_CRU_BASE + RK3576_PLL_CON(97));
+ writel(BITS_WITH_WMASK(2, 0x7U, 6),
+ RK3576_CRU_BASE + RK3576_PLL_CON(105));
+ writel(BITS_WITH_WMASK(1, 0x3U, 6),
+ RK3576_CRU_BASE + RK3576_MODE_CON0);
+ writel(BITS_WITH_WMASK(1, 0x3U, 8),
+ RK3576_CRU_BASE + RK3576_MODE_CON0);
+ /* init cci */
+ writel(0xffff0000, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
+ rockchip_pll_set_rate(&rk3576_pll_clks[BPLL], priv->cru,
+ BPLL, LPLL_HZ);
+ if (!priv->armclk_enter_hz) {
+ ret = rockchip_pll_set_rate(&rk3576_pll_clks[LPLL], priv->cru,
+ LPLL, LPLL_HZ);
+ priv->armclk_enter_hz =
+ rockchip_pll_get_rate(&rk3576_pll_clks[LPLL],
+ priv->cru, LPLL);
+ priv->armclk_init_hz = priv->armclk_enter_hz;
+ rk_clrsetreg(&priv->cru->litclksel_con[0], CLK_LITCORE_DIV_MASK,
+ 0 << CLK_LITCORE_DIV_SHIFT);
+ }
+ /* init cci */
+ writel(0xffff20cb, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
+
+ /* Change bigcore rm from 4 to 3 */
+ writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x3c);
+ writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x44);
+ writel(0x00020002, RK3576_BIGCORE_GRF_BASE + 0x38);
+ udelay(1);
+ writel(0x00020000, RK3576_BIGCORE_GRF_BASE + 0x38);
+ /* Change litcore rm from 4 to 3 */
+ writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x3c);
+ writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x44);
+ writel(0x00020002, RK3576_LITCORE_GRF_BASE + 0x38);
+ udelay(1);
+ writel(0x00020000, RK3576_LITCORE_GRF_BASE + 0x38);
+ /* Change cci rm form 4 to 3 */
+ writel(0x001c000c, RK3576_CCI_GRF_BASE + 0x54);
+#endif
+
+ rk3576_clk_init(priv);
+
+ /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+ ret = clk_set_defaults(dev, 1);
+ if (ret)
+ debug("%s clk_set_defaults failed %d\n", __func__, ret);
+ else
+ priv->sync_kernel = true;
+
+ return 0;
+}
+
+static int rk3576_clk_ofdata_to_platdata(struct udevice *dev)
+{
+ struct rk3576_clk_priv *priv = dev_get_priv(dev);
+
+ priv->cru = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static int rk3576_clk_bind(struct udevice *dev)
+{
+ int ret;
+ struct udevice *sys_child;
+ struct sysreset_reg *priv;
+
+ /* The reset driver does not have a device node, so bind it here */
+ ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+ &sys_child);
+ if (ret) {
+ debug("Warning: No sysreset driver: ret=%d\n", ret);
+ } else {
+ priv = malloc(sizeof(struct sysreset_reg));
+ priv->glb_srst_fst_value = offsetof(struct rk3576_cru,
+ glb_srst_fst);
+ priv->glb_srst_snd_value = offsetof(struct rk3576_cru,
+ glb_srsr_snd);
+ dev_set_priv(sys_child, priv);
+ }
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+ ret = offsetof(struct rk3576_cru, softrst_con[0]);
+ ret = rk3576_reset_bind_lut(dev, ret, 32776);
+ if (ret)
+ debug("Warning: software reset driver bind failed\n");
+#endif
+
+ return 0;
+}
+
+static const struct udevice_id rk3576_clk_ids[] = {
+ { .compatible = "rockchip,rk3576-cru" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rk3576_cru) = {
+ .name = "rockchip_rk3576_cru",
+ .id = UCLASS_CLK,
+ .of_match = rk3576_clk_ids,
+ .priv_auto = sizeof(struct rk3576_clk_priv),
+ .of_to_plat = rk3576_clk_ofdata_to_platdata,
+ .ops = &rk3576_clk_ops,
+ .bind = rk3576_clk_bind,
+ .probe = rk3576_clk_probe,
+};
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c
index 2123c31038f..46820425a84 100644
--- a/drivers/misc/rockchip-otp.c
+++ b/drivers/misc/rockchip-otp.c
@@ -361,6 +361,13 @@ static const struct rockchip_otp_data rk3568_data = {
.block_size = 2,
};
+static const struct rockchip_otp_data rk3576_data = {
+ .read = rockchip_rk3588_otp_read,
+ .offset = 0x700,
+ .size = 0x100,
+ .block_size = 4,
+};
+
static const struct rockchip_otp_data rk3588_data = {
.read = rockchip_rk3588_otp_read,
.offset = 0xC00,
@@ -384,10 +391,18 @@ static const struct udevice_id rockchip_otp_ids[] = {
.data = (ulong)&px30_data,
},
{
+ .compatible = "rockchip,rk3528-otp",
+ .data = (ulong)&rk3568_data,
+ },
+ {
.compatible = "rockchip,rk3568-otp",
.data = (ulong)&rk3568_data,
},
{
+ .compatible = "rockchip,rk3576-otp",
+ .data = (ulong)&rk3576_data,
+ },
+ {
.compatible = "rockchip,rk3588-otp",
.data = (ulong)&rk3588_data,
},
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index 422b8f7e4c8..7a72abaa38a 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -171,6 +171,7 @@ static int rockchip_dwmmc_bind(struct udevice *dev)
static const struct udevice_id rockchip_dwmmc_ids[] = {
{ .compatible = "rockchip,rk2928-dw-mshc" },
{ .compatible = "rockchip,rk3288-dw-mshc" },
+ { .compatible = "rockchip,rk3576-dw-mshc" },
{ }
};
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index da630b9d97a..761e3619329 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -50,6 +50,10 @@
#define DWCMSHC_EMMC_EMMC_CTRL 0x52c
#define DWCMSHC_CARD_IS_EMMC BIT(0)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
+#define DWCMSHC_EMMC_AT_CTRL 0x540
+#define EMMC_AT_CTRL_TUNE_CLK_STOP_EN BIT(16)
+#define EMMC_AT_CTRL_PRE_CHANGE_DLY 17
+#define EMMC_AT_CTRL_POST_CHANGE_DLY 19
#define DWCMSHC_EMMC_DLL_CTRL 0x800
#define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1)
#define DWCMSHC_EMMC_DLL_RXCLK 0x804
@@ -156,6 +160,9 @@ struct sdhci_data {
u32 flags;
u8 hs200_txclk_tapnum;
u8 hs400_txclk_tapnum;
+ u8 hs400_cmdout_tapnum;
+ u8 hs400_strbin_tapnum;
+ u8 ddr50_strbin_delay_num;
};
static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
@@ -323,6 +330,11 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab
udelay(1);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+ extra = 0x3 << EMMC_AT_CTRL_POST_CHANGE_DLY |
+ 0x3 << EMMC_AT_CTRL_PRE_CHANGE_DLY |
+ EMMC_AT_CTRL_TUNE_CLK_STOP_EN;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_AT_CTRL);
+
/* Init DLL settings */
extra = DWCMSHC_EMMC_DLL_START_DEFAULT << DWCMSHC_EMMC_DLL_START_POINT |
DWCMSHC_EMMC_DLL_INC_VALUE << DWCMSHC_EMMC_DLL_INC |
@@ -348,7 +360,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab
extra = DLL_CMDOUT_SRC_CLK_NEG |
DLL_CMDOUT_BOTH_CLK_EDGE |
DWCMSHC_EMMC_DLL_DLYENA |
- DLL_CMDOUT_TAPNUM_90_DEGREES |
+ data->hs400_cmdout_tapnum |
DLL_CMDOUT_TAPNUM_FROM_SW;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CMDOUT);
}
@@ -360,7 +372,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
extra = DWCMSHC_EMMC_DLL_DLYENA |
- DLL_STRBIN_TAPNUM_DEFAULT |
+ data->hs400_strbin_tapnum |
DLL_STRBIN_TAPNUM_FROM_SW;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
} else {
@@ -380,7 +392,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab
*/
extra = DWCMSHC_EMMC_DLL_DLYENA |
DLL_STRBIN_DELAY_NUM_SEL |
- DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET;
+ data->ddr50_strbin_delay_num << DLL_STRBIN_DELAY_NUM_OFFSET;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
}
@@ -647,6 +659,17 @@ static const struct sdhci_data rk3399_data = {
.set_enhanced_strobe = rk3399_sdhci_set_enhanced_strobe,
};
+static const struct sdhci_data rk3528_data = {
+ .set_ios_post = rk3568_sdhci_set_ios_post,
+ .set_clock = rk3568_sdhci_set_clock,
+ .config_dll = rk3568_sdhci_config_dll,
+ .hs200_txclk_tapnum = 0xc,
+ .hs400_txclk_tapnum = 0x6,
+ .hs400_cmdout_tapnum = 0x6,
+ .hs400_strbin_tapnum = 0x3,
+ .ddr50_strbin_delay_num = 0xa,
+};
+
static const struct sdhci_data rk3568_data = {
.set_ios_post = rk3568_sdhci_set_ios_post,
.set_clock = rk3568_sdhci_set_clock,
@@ -654,6 +677,20 @@ static const struct sdhci_data rk3568_data = {
.flags = FLAG_INVERTER_FLAG_IN_RXCLK,
.hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
.hs400_txclk_tapnum = 0x8,
+ .hs400_cmdout_tapnum = DLL_CMDOUT_TAPNUM_90_DEGREES,
+ .hs400_strbin_tapnum = DLL_STRBIN_TAPNUM_DEFAULT,
+ .ddr50_strbin_delay_num = DLL_STRBIN_DELAY_NUM_DEFAULT,
+};
+
+static const struct sdhci_data rk3576_data = {
+ .set_ios_post = rk3568_sdhci_set_ios_post,
+ .set_clock = rk3568_sdhci_set_clock,
+ .config_dll = rk3568_sdhci_config_dll,
+ .hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
+ .hs400_txclk_tapnum = 0x7,
+ .hs400_cmdout_tapnum = 0x7,
+ .hs400_strbin_tapnum = 0x5,
+ .ddr50_strbin_delay_num = 0xa,
};
static const struct sdhci_data rk3588_data = {
@@ -662,6 +699,9 @@ static const struct sdhci_data rk3588_data = {
.config_dll = rk3568_sdhci_config_dll,
.hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
.hs400_txclk_tapnum = 0x9,
+ .hs400_cmdout_tapnum = DLL_CMDOUT_TAPNUM_90_DEGREES,
+ .hs400_strbin_tapnum = DLL_STRBIN_TAPNUM_DEFAULT,
+ .ddr50_strbin_delay_num = DLL_STRBIN_DELAY_NUM_DEFAULT,
};
static const struct udevice_id sdhci_ids[] = {
@@ -670,10 +710,18 @@ static const struct udevice_id sdhci_ids[] = {
.data = (ulong)&rk3399_data,
},
{
+ .compatible = "rockchip,rk3528-dwcmshc",
+ .data = (ulong)&rk3528_data,
+ },
+ {
.compatible = "rockchip,rk3568-dwcmshc",
.data = (ulong)&rk3568_data,
},
{
+ .compatible = "rockchip,rk3576-dwcmshc",
+ .data = (ulong)&rk3576_data,
+ },
+ {
.compatible = "rockchip,rk3588-dwcmshc",
.data = (ulong)&rk3588_data,
},
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index b4ec3614696..b1bc422f791 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1612,10 +1612,18 @@ static const struct udevice_id eqos_ids[] = {
#endif
#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
{
+ .compatible = "rockchip,rk3528-gmac",
+ .data = (ulong)&eqos_rockchip_config
+ },
+ {
.compatible = "rockchip,rk3568-gmac",
.data = (ulong)&eqos_rockchip_config
},
{
+ .compatible = "rockchip,rk3576-gmac",
+ .data = (ulong)&eqos_rockchip_config
+ },
+ {
.compatible = "rockchip,rk3588-gmac",
.data = (ulong)&eqos_rockchip_config
},
diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
index f3a0f63003e..d646d3ebac8 100644
--- a/drivers/net/dwc_eth_qos_rockchip.c
+++ b/drivers/net/dwc_eth_qos_rockchip.c
@@ -50,6 +50,132 @@ struct rockchip_platform_data {
(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
+#define RK3528_VO_GRF_GMAC_CON 0x0018
+#define RK3528_VPU_GRF_GMAC_CON5 0x0018
+#define RK3528_VPU_GRF_GMAC_CON6 0x001c
+
+#define RK3528_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
+#define RK3528_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
+#define RK3528_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
+#define RK3528_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
+
+#define RK3528_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3528_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 0)
+
+#define RK3528_GMAC0_PHY_INTF_SEL_RMII GRF_BIT(1)
+#define RK3528_GMAC1_PHY_INTF_SEL_RGMII GRF_CLR_BIT(8)
+#define RK3528_GMAC1_PHY_INTF_SEL_RMII GRF_BIT(8)
+
+#define RK3528_GMAC1_CLK_SELECT_CRU GRF_CLR_BIT(12)
+#define RK3528_GMAC1_CLK_SELECT_IO GRF_BIT(12)
+
+#define RK3528_GMAC0_CLK_RMII_DIV2 GRF_BIT(3)
+#define RK3528_GMAC0_CLK_RMII_DIV20 GRF_CLR_BIT(3)
+#define RK3528_GMAC1_CLK_RMII_DIV2 GRF_BIT(10)
+#define RK3528_GMAC1_CLK_RMII_DIV20 GRF_CLR_BIT(10)
+
+#define RK3528_GMAC1_CLK_RGMII_DIV1 (GRF_CLR_BIT(11) | GRF_CLR_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV5 (GRF_BIT(11) | GRF_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV50 (GRF_BIT(11) | GRF_CLR_BIT(10))
+
+#define RK3528_GMAC0_CLK_RMII_GATE GRF_BIT(2)
+#define RK3528_GMAC0_CLK_RMII_NOGATE GRF_CLR_BIT(2)
+#define RK3528_GMAC1_CLK_RMII_GATE GRF_BIT(9)
+#define RK3528_GMAC1_CLK_RMII_NOGATE GRF_CLR_BIT(9)
+
+static int rk3528_set_to_rgmii(struct udevice *dev,
+ int tx_delay, int rx_delay)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+
+ regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC1_PHY_INTF_SEL_RGMII);
+
+ regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5,
+ DELAY_ENABLE(RK3528, tx_delay, rx_delay));
+
+ regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON6,
+ RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) |
+ RK3528_GMAC_CLK_TX_DL_CFG(tx_delay));
+
+ return 0;
+}
+
+static int rk3528_set_to_rmii(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+
+ if (data->id == 1)
+ regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC1_PHY_INTF_SEL_RMII);
+ else
+ regmap_write(data->grf, RK3528_VO_GRF_GMAC_CON,
+ RK3528_GMAC0_PHY_INTF_SEL_RMII |
+ RK3528_GMAC0_CLK_RMII_DIV2);
+
+ return 0;
+}
+
+static int rk3528_set_gmac_speed(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+ u32 val, reg;
+
+ switch (eqos->phy->speed) {
+ case SPEED_10:
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
+ val = data->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 :
+ RK3528_GMAC0_CLK_RMII_DIV20;
+ else
+ val = RK3528_GMAC1_CLK_RGMII_DIV50;
+ break;
+ case SPEED_100:
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
+ val = data->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 :
+ RK3528_GMAC0_CLK_RMII_DIV2;
+ else
+ val = RK3528_GMAC1_CLK_RGMII_DIV5;
+ break;
+ case SPEED_1000:
+ if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII)
+ val = RK3528_GMAC1_CLK_RGMII_DIV1;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg = data->id == 1 ? RK3528_VPU_GRF_GMAC_CON5 :
+ RK3528_VO_GRF_GMAC_CON;
+ regmap_write(data->grf, reg, val);
+
+ return 0;
+}
+
+static void rk3528_set_clock_selection(struct udevice *dev, bool enable)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+ u32 val;
+
+ if (data->id == 1) {
+ val = data->clock_input ? RK3528_GMAC1_CLK_SELECT_IO :
+ RK3528_GMAC1_CLK_SELECT_CRU;
+ val |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE :
+ RK3528_GMAC1_CLK_RMII_GATE;
+ regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5, val);
+ } else {
+ val = enable ? RK3528_GMAC0_CLK_RMII_NOGATE :
+ RK3528_GMAC0_CLK_RMII_GATE;
+ regmap_write(data->grf, RK3528_VO_GRF_GMAC_CON, val);
+ }
+}
+
#define RK3568_GRF_GMAC0_CON0 0x0380
#define RK3568_GRF_GMAC0_CON1 0x0384
#define RK3568_GRF_GMAC1_CON0 0x0388
@@ -134,6 +260,145 @@ static int rk3568_set_gmac_speed(struct udevice *dev)
return 0;
}
+/* VCCIO0_1_3_IOC */
+#define RK3576_VCCIO0_1_3_IOC_CON2 0x6408
+#define RK3576_VCCIO0_1_3_IOC_CON3 0x640c
+#define RK3576_VCCIO0_1_3_IOC_CON4 0x6410
+#define RK3576_VCCIO0_1_3_IOC_CON5 0x6414
+
+#define RK3576_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
+#define RK3576_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
+#define RK3576_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7)
+#define RK3576_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7)
+
+#define RK3576_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
+#define RK3576_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
+
+/* SDGMAC_GRF */
+#define RK3576_GRF_GMAC_CON0 0x0020
+#define RK3576_GRF_GMAC_CON1 0x0024
+
+#define RK3576_GMAC_RMII_MODE GRF_BIT(3)
+#define RK3576_GMAC_RGMII_MODE GRF_CLR_BIT(3)
+
+#define RK3576_GMAC_CLK_SELECT_IO GRF_BIT(7)
+#define RK3576_GMAC_CLK_SELECT_CRU GRF_CLR_BIT(7)
+
+#define RK3576_GMAC_CLK_RMII_DIV2 GRF_BIT(5)
+#define RK3576_GMAC_CLK_RMII_DIV20 GRF_CLR_BIT(5)
+
+#define RK3576_GMAC_CLK_RGMII_DIV1 \
+ (GRF_CLR_BIT(6) | GRF_CLR_BIT(5))
+#define RK3576_GMAC_CLK_RGMII_DIV5 \
+ (GRF_BIT(6) | GRF_BIT(5))
+#define RK3576_GMAC_CLK_RGMII_DIV50 \
+ (GRF_BIT(6) | GRF_CLR_BIT(5))
+
+#define RK3576_GMAC_CLK_RMII_GATE GRF_BIT(4)
+#define RK3576_GMAC_CLK_RMII_NOGATE GRF_CLR_BIT(4)
+
+static int rk3576_set_to_rgmii(struct udevice *dev,
+ int tx_delay, int rx_delay)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+ u32 offset_con;
+
+ offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 :
+ RK3576_GRF_GMAC_CON0;
+
+ regmap_write(data->grf, offset_con, RK3576_GMAC_RGMII_MODE);
+
+ offset_con = data->id == 1 ? RK3576_VCCIO0_1_3_IOC_CON4 :
+ RK3576_VCCIO0_1_3_IOC_CON2;
+
+ /* m0 && m1 delay enabled */
+ regmap_write(data->php_grf, offset_con,
+ DELAY_ENABLE(RK3576, tx_delay, rx_delay));
+ regmap_write(data->php_grf, offset_con + 0x4,
+ DELAY_ENABLE(RK3576, tx_delay, rx_delay));
+
+ /* m0 && m1 delay value */
+ regmap_write(data->php_grf, offset_con,
+ RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) |
+ RK3576_GMAC_CLK_RX_DL_CFG(rx_delay));
+ regmap_write(data->php_grf, offset_con + 0x4,
+ RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) |
+ RK3576_GMAC_CLK_RX_DL_CFG(rx_delay));
+
+ return 0;
+}
+
+static int rk3576_set_to_rmii(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+ u32 offset_con;
+
+ offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 :
+ RK3576_GRF_GMAC_CON0;
+
+ regmap_write(data->grf, offset_con, RK3576_GMAC_RMII_MODE);
+
+ return 0;
+}
+
+static int rk3576_set_gmac_speed(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+ u32 val = 0, offset_con;
+
+ switch (eqos->phy->speed) {
+ case SPEED_10:
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
+ val = RK3576_GMAC_CLK_RMII_DIV20;
+ else
+ val = RK3576_GMAC_CLK_RGMII_DIV50;
+ break;
+ case SPEED_100:
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
+ val = RK3576_GMAC_CLK_RMII_DIV2;
+ else
+ val = RK3576_GMAC_CLK_RGMII_DIV5;
+ break;
+ case SPEED_1000:
+ if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII)
+ val = RK3576_GMAC_CLK_RGMII_DIV1;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 :
+ RK3576_GRF_GMAC_CON0;
+
+ regmap_write(data->grf, offset_con, val);
+
+ return 0;
+}
+
+static void rk3576_set_clock_selection(struct udevice *dev, bool enable)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct rockchip_platform_data *data = pdata->priv_pdata;
+
+ u32 val = data->clock_input ? RK3576_GMAC_CLK_SELECT_IO :
+ RK3576_GMAC_CLK_SELECT_CRU;
+ u32 offset_con;
+
+ val |= enable ? RK3576_GMAC_CLK_RMII_NOGATE :
+ RK3576_GMAC_CLK_RMII_GATE;
+
+ offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 :
+ RK3576_GRF_GMAC_CON0;
+
+ regmap_write(data->grf, offset_con, val);
+}
+
#define RK3588_DELAY_ENABLE(id, tx, rx) \
(((tx) ? RK3588_GMAC_TXCLK_DLY_ENABLE(id) : RK3588_GMAC_TXCLK_DLY_DISABLE(id)) | \
((rx) ? RK3588_GMAC_RXCLK_DLY_ENABLE(id) : RK3588_GMAC_RXCLK_DLY_DISABLE(id)))
@@ -270,6 +535,18 @@ static void rk3588_set_clock_selection(struct udevice *dev, bool enable)
static const struct rk_gmac_ops rk_gmac_ops[] = {
{
+ .compatible = "rockchip,rk3528-gmac",
+ .set_to_rgmii = rk3528_set_to_rgmii,
+ .set_to_rmii = rk3528_set_to_rmii,
+ .set_gmac_speed = rk3528_set_gmac_speed,
+ .set_clock_selection = rk3528_set_clock_selection,
+ .regs = {
+ 0xffbd0000, /* gmac0 */
+ 0xffbe0000, /* gmac1 */
+ 0x0, /* sentinel */
+ },
+ },
+ {
.compatible = "rockchip,rk3568-gmac",
.set_to_rgmii = rk3568_set_to_rgmii,
.set_to_rmii = rk3568_set_to_rmii,
@@ -281,6 +558,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = {
},
},
{
+ .compatible = "rockchip,rk3576-gmac",
+ .set_to_rgmii = rk3576_set_to_rgmii,
+ .set_to_rmii = rk3576_set_to_rmii,
+ .set_gmac_speed = rk3576_set_gmac_speed,
+ .set_clock_selection = rk3576_set_clock_selection,
+ .regs = {
+ 0x2a220000, /* gmac0 */
+ 0x2a230000, /* gmac1 */
+ 0x0, /* sentinel */
+ },
+ },
+ {
.compatible = "rockchip,rk3588-gmac",
.set_to_rgmii = rk3588_set_to_rgmii,
.set_to_rmii = rk3588_set_to_rmii,
@@ -357,7 +646,8 @@ static int eqos_probe_resources_rk(struct udevice *dev)
goto err_free;
}
- if (device_is_compatible(dev, "rockchip,rk3588-gmac")) {
+ if (device_is_compatible(dev, "rockchip,rk3588-gmac") ||
+ device_is_compatible(dev, "rockchip,rk3576-gmac")) {
data->php_grf =
syscon_regmap_lookup_by_phandle(dev, "rockchip,php-grf");
if (IS_ERR(data->php_grf)) {
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 43f6e020a6a..88b33de1b2a 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -40,11 +40,13 @@ struct rockchip_usb2phy_port_cfg {
struct rockchip_usb2phy_cfg {
unsigned int reg;
struct usb2phy_reg clkout_ctl;
+ struct usb2phy_reg clkout_ctl_phy;
const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
};
struct rockchip_usb2phy {
struct regmap *reg_base;
+ struct regmap *phy_base;
struct clk phyclk;
const struct rockchip_usb2phy_cfg *phy_cfg;
};
@@ -165,6 +167,22 @@ static struct phy_ops rockchip_usb2phy_ops = {
.of_xlate = rockchip_usb2phy_of_xlate,
};
+static void rockchip_usb2phy_clkout_ctl(struct clk *clk, struct regmap **base,
+ const struct usb2phy_reg **clkout_ctl)
+{
+ struct udevice *parent = dev_get_parent(clk->dev);
+ struct rockchip_usb2phy *priv = dev_get_priv(parent);
+ const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg;
+
+ if (priv->phy_cfg->clkout_ctl_phy.enable) {
+ *base = priv->phy_base;
+ *clkout_ctl = &phy_cfg->clkout_ctl_phy;
+ } else {
+ *base = priv->reg_base;
+ *clkout_ctl = &phy_cfg->clkout_ctl;
+ }
+}
+
/**
* round_rate() - Adjust a rate to the exact rate a clock can provide.
* @clk: The clock to manipulate.
@@ -185,13 +203,14 @@ ulong rockchip_usb2phy_clk_round_rate(struct clk *clk, ulong rate)
*/
int rockchip_usb2phy_clk_enable(struct clk *clk)
{
- struct udevice *parent = dev_get_parent(clk->dev);
- struct rockchip_usb2phy *priv = dev_get_priv(parent);
- const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg;
+ const struct usb2phy_reg *clkout_ctl;
+ struct regmap *base;
+
+ rockchip_usb2phy_clkout_ctl(clk, &base, &clkout_ctl);
/* turn on 480m clk output if it is off */
- if (!property_enabled(priv->reg_base, &phy_cfg->clkout_ctl)) {
- property_enable(priv->reg_base, &phy_cfg->clkout_ctl, true);
+ if (!property_enabled(base, clkout_ctl)) {
+ property_enable(base, clkout_ctl, true);
/* waiting for the clk become stable */
usleep_range(1200, 1300);
@@ -208,12 +227,13 @@ int rockchip_usb2phy_clk_enable(struct clk *clk)
*/
int rockchip_usb2phy_clk_disable(struct clk *clk)
{
- struct udevice *parent = dev_get_parent(clk->dev);
- struct rockchip_usb2phy *priv = dev_get_priv(parent);
- const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg;
+ const struct usb2phy_reg *clkout_ctl;
+ struct regmap *base;
+
+ rockchip_usb2phy_clkout_ctl(clk, &base, &clkout_ctl);
/* turn off 480m clk output */
- property_enable(priv->reg_base, &phy_cfg->clkout_ctl, false);
+ property_enable(base, clkout_ctl, false);
return 0;
}
@@ -281,7 +301,10 @@ static int rockchip_usb2phy_probe(struct udevice *dev)
return ret;
}
- return 0;
+ if (priv->phy_cfg->clkout_ctl_phy.enable)
+ ret = regmap_init_mem_index(dev_ofnode(dev), &priv->phy_base, 0);
+
+ return ret;
}
static int rockchip_usb2phy_bind(struct udevice *dev)
@@ -389,6 +412,22 @@ static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = {
{ /* sentinel */ }
};
+static const struct rockchip_usb2phy_cfg rk3528_phy_cfgs[] = {
+ {
+ .reg = 0xffdf0000,
+ .clkout_ctl_phy = { 0x041c, 7, 2, 0, 0x27 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x004c, 1, 0, 2, 1 },
+ },
+ [USB2PHY_PORT_HOST] = {
+ .phy_sus = { 0x005c, 1, 0, 2, 1 },
+ }
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
{
.reg = 0xfe8a0000,
@@ -471,6 +510,10 @@ static const struct udevice_id rockchip_usb2phy_ids[] = {
.data = (ulong)&rk3399_usb2phy_cfgs,
},
{
+ .compatible = "rockchip,rk3528-usb2phy",
+ .data = (ulong)&rk3528_phy_cfgs,
+ },
+ {
.compatible = "rockchip,rk3568-usb2phy",
.data = (ulong)&rk3568_phy_cfgs,
},
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index c91f650b043..e17415e1ca6 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -14,7 +14,9 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3528) += pinctrl-rk3528.o
obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
+obj-$(CONFIG_ROCKCHIP_RK3576) += pinctrl-rk3576.o
obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3528.c b/drivers/pinctrl/rockchip/pinctrl-rk3528.c
new file mode 100644
index 00000000000..a3e1f0b2c9d
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3528.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+#include <dt-bindings/pinctrl/rockchip.h>
+
+static int rk3528_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
+ int reg, mask;
+ u8 bit;
+ u32 data, rmask;
+
+ regmap = priv->regmap_base;
+ reg = bank->iomux[iomux_num].offset;
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ mask = 0xf;
+
+ data = (mask << (bit + 16));
+ rmask = data | (data >> 16);
+ data |= (mux & mask) << bit;
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RK3528_DRV_BITS_PER_PIN 8
+#define RK3528_DRV_PINS_PER_REG 2
+#define RK3528_DRV_GPIO0_OFFSET 0x100
+#define RK3528_DRV_GPIO1_OFFSET 0x20120
+#define RK3528_DRV_GPIO2_OFFSET 0x30160
+#define RK3528_DRV_GPIO3_OFFSET 0x20190
+#define RK3528_DRV_GPIO4_OFFSET 0x101C0
+
+static void rk3528_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ *regmap = priv->regmap_base;
+
+ if (bank->bank_num == 0) {
+ *reg = RK3528_DRV_GPIO0_OFFSET;
+ } else if (bank->bank_num == 1) {
+ *reg = RK3528_DRV_GPIO1_OFFSET;
+ } else if (bank->bank_num == 2) {
+ *reg = RK3528_DRV_GPIO2_OFFSET;
+ } else if (bank->bank_num == 3) {
+ *reg = RK3528_DRV_GPIO3_OFFSET;
+ } else if (bank->bank_num == 4) {
+ *reg = RK3528_DRV_GPIO4_OFFSET;
+ } else {
+ *reg = 0;
+ debug("unsupported bank_num %d\n", bank->bank_num);
+ }
+
+ *reg += ((pin_num / RK3528_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3528_DRV_PINS_PER_REG;
+ *bit *= RK3528_DRV_BITS_PER_PIN;
+}
+
+static int rk3528_set_drive(struct rockchip_pin_bank *bank,
+ int pin_num, int strength)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data, rmask;
+ u8 bit;
+ int drv = (1 << (strength + 1)) - 1;
+
+ rk3528_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3528_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+ rmask = data | (data >> 16);
+ data |= (drv << bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RK3528_PULL_BITS_PER_PIN 2
+#define RK3528_PULL_PINS_PER_REG 8
+#define RK3528_PULL_GPIO0_OFFSET 0x200
+#define RK3528_PULL_GPIO1_OFFSET 0x20210
+#define RK3528_PULL_GPIO2_OFFSET 0x30220
+#define RK3528_PULL_GPIO3_OFFSET 0x20230
+#define RK3528_PULL_GPIO4_OFFSET 0x10240
+
+static void rk3528_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ *regmap = priv->regmap_base;
+
+ if (bank->bank_num == 0) {
+ *reg = RK3528_PULL_GPIO0_OFFSET;
+ } else if (bank->bank_num == 1) {
+ *reg = RK3528_PULL_GPIO1_OFFSET;
+ } else if (bank->bank_num == 2) {
+ *reg = RK3528_PULL_GPIO2_OFFSET;
+ } else if (bank->bank_num == 3) {
+ *reg = RK3528_PULL_GPIO3_OFFSET;
+ } else if (bank->bank_num == 4) {
+ *reg = RK3528_PULL_GPIO4_OFFSET;
+ } else {
+ *reg = 0;
+ debug("unsupported bank_num %d\n", bank->bank_num);
+ }
+
+ *reg += ((pin_num / RK3528_PULL_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3528_PULL_PINS_PER_REG;
+ *bit *= RK3528_PULL_BITS_PER_PIN;
+}
+
+static int rk3528_set_pull(struct rockchip_pin_bank *bank,
+ int pin_num, int pull)
+{
+ struct regmap *regmap;
+ int reg, ret;
+ u8 bit, type;
+ u32 data, rmask;
+
+ if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+ return -EOPNOTSUPP;
+
+ rk3528_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+ type = bank->pull_type[pin_num / 8];
+ ret = rockchip_translate_pull_value(type, pull);
+ if (ret < 0) {
+ debug("unsupported pull setting %d\n", pull);
+ return ret;
+ }
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3528_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+ rmask = data | (data >> 16);
+ data |= (ret << bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RK3528_SMT_BITS_PER_PIN 1
+#define RK3528_SMT_PINS_PER_REG 8
+#define RK3528_SMT_GPIO0_OFFSET 0x400
+#define RK3528_SMT_GPIO1_OFFSET 0x20410
+#define RK3528_SMT_GPIO2_OFFSET 0x30420
+#define RK3528_SMT_GPIO3_OFFSET 0x20430
+#define RK3528_SMT_GPIO4_OFFSET 0x10440
+
+static int rk3528_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num,
+ struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ *regmap = priv->regmap_base;
+
+ if (bank->bank_num == 0) {
+ *reg = RK3528_SMT_GPIO0_OFFSET;
+ } else if (bank->bank_num == 1) {
+ *reg = RK3528_SMT_GPIO1_OFFSET;
+ } else if (bank->bank_num == 2) {
+ *reg = RK3528_SMT_GPIO2_OFFSET;
+ } else if (bank->bank_num == 3) {
+ *reg = RK3528_SMT_GPIO3_OFFSET;
+ } else if (bank->bank_num == 4) {
+ *reg = RK3528_SMT_GPIO4_OFFSET;
+ } else {
+ *reg = 0;
+ debug("unsupported bank_num %d\n", bank->bank_num);
+ }
+
+ *reg += ((pin_num / RK3528_SMT_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3528_SMT_PINS_PER_REG;
+ *bit *= RK3528_SMT_BITS_PER_PIN;
+
+ return 0;
+}
+
+static int rk3528_set_schmitt(struct rockchip_pin_bank *bank,
+ int pin_num, int enable)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data, rmask;
+ u8 bit;
+
+ rk3528_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3528_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+ rmask = data | (data >> 16);
+ data |= (enable << bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+static struct rockchip_pin_bank rk3528_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x20020, 0x20028, 0x20030, 0x20038),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x30040, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x20060, 0x20068, 0x20070, 0),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(4, 32, "gpio4",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x10080, 0x10088, 0x10090, 0x10098),
+};
+
+static const struct rockchip_pin_ctrl rk3528_pin_ctrl = {
+ .pin_banks = rk3528_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3528_pin_banks),
+ .grf_mux_offset = 0x0,
+ .set_mux = rk3528_set_mux,
+ .set_pull = rk3528_set_pull,
+ .set_drive = rk3528_set_drive,
+ .set_schmitt = rk3528_set_schmitt,
+};
+
+static const struct udevice_id rk3528_pinctrl_ids[] = {
+ {
+ .compatible = "rockchip,rk3528-pinctrl",
+ .data = (ulong)&rk3528_pin_ctrl
+ },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rk3528_pinctrl) = {
+ .name = "rockchip_rk3528_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = rk3528_pinctrl_ids,
+ .priv_auto = sizeof(struct rockchip_pinctrl_priv),
+ .ops = &rockchip_pinctrl_ops,
+#if CONFIG_IS_ENABLED(OF_REAL)
+ .bind = dm_scan_fdt_dev,
+#endif
+ .probe = rockchip_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3576.c b/drivers/pinctrl/rockchip/pinctrl-rk3576.c
new file mode 100644
index 00000000000..66e1142ac1f
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3576.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2024 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+#include <dt-bindings/pinctrl/rockchip.h>
+
+static int rk3576_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
+ int reg, mask;
+ u8 bit;
+ u32 data, rmask;
+
+ regmap = priv->regmap_base;
+ reg = bank->iomux[iomux_num].offset;
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ mask = 0xf;
+
+ data = (mask << (bit + 16));
+ rmask = data | (data >> 16);
+ data |= (mux & mask) << bit;
+
+ if (bank->bank_num == 0 && pin >= RK_PB4 && pin <= RK_PB7)
+ reg += 0x1FF4; /* GPIO0_IOC_GPIO0B_IOMUX_SEL_H */
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RK3576_DRV_BITS_PER_PIN 4
+#define RK3576_DRV_PINS_PER_REG 4
+#define RK3576_DRV_GPIO0_AL_OFFSET 0x10
+#define RK3576_DRV_GPIO0_BH_OFFSET 0x2014
+#define RK3576_DRV_GPIO1_OFFSET 0x6020
+#define RK3576_DRV_GPIO2_OFFSET 0x6040
+#define RK3576_DRV_GPIO3_OFFSET 0x6060
+#define RK3576_DRV_GPIO4_AL_OFFSET 0x6080
+#define RK3576_DRV_GPIO4_CL_OFFSET 0xA090
+#define RK3576_DRV_GPIO4_DL_OFFSET 0xB098
+
+static void rk3576_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ *regmap = priv->regmap_base;
+ if (bank->bank_num == 0 && pin_num < 12) {
+ *reg = RK3576_DRV_GPIO0_AL_OFFSET;
+ } else if (bank->bank_num == 0) {
+ *reg = RK3576_DRV_GPIO0_BH_OFFSET - 0xc;
+ } else if (bank->bank_num == 1) {
+ *reg = RK3576_DRV_GPIO1_OFFSET;
+ } else if (bank->bank_num == 2) {
+ *reg = RK3576_DRV_GPIO2_OFFSET;
+ } else if (bank->bank_num == 3) {
+ *reg = RK3576_DRV_GPIO3_OFFSET;
+ } else if (bank->bank_num == 4 && pin_num < 16) {
+ *reg = RK3576_DRV_GPIO4_AL_OFFSET;
+ } else if (bank->bank_num == 4 && pin_num < 24) {
+ *reg = RK3576_DRV_GPIO4_CL_OFFSET - 0x10;
+ } else if (bank->bank_num == 4) {
+ *reg = RK3576_DRV_GPIO4_DL_OFFSET - 0x18;
+ } else {
+ *reg = 0;
+ debug("unsupported bank_num %d\n", bank->bank_num);
+ }
+
+ *reg += ((pin_num / RK3576_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3576_DRV_PINS_PER_REG;
+ *bit *= RK3576_DRV_BITS_PER_PIN;
+}
+
+static int rk3576_set_drive(struct rockchip_pin_bank *bank,
+ int pin_num, int strength)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data, rmask;
+ u8 bit;
+ int drv = ((strength & BIT(2)) >> 2) | ((strength & BIT(0)) << 2) | (strength & BIT(1));
+
+ rk3576_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3576_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+ rmask = data | (data >> 16);
+ data |= (drv << bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RK3576_PULL_BITS_PER_PIN 2
+#define RK3576_PULL_PINS_PER_REG 8
+#define RK3576_PULL_GPIO0_AL_OFFSET 0x20
+#define RK3576_PULL_GPIO0_BH_OFFSET 0x2028
+#define RK3576_PULL_GPIO1_OFFSET 0x6110
+#define RK3576_PULL_GPIO2_OFFSET 0x6120
+#define RK3576_PULL_GPIO3_OFFSET 0x6130
+#define RK3576_PULL_GPIO4_AL_OFFSET 0x6140
+#define RK3576_PULL_GPIO4_CL_OFFSET 0xA148
+#define RK3576_PULL_GPIO4_DL_OFFSET 0xB14C
+
+static void rk3576_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ *regmap = priv->regmap_base;
+ if (bank->bank_num == 0 && pin_num < 12) {
+ *reg = RK3576_PULL_GPIO0_AL_OFFSET;
+ } else if (bank->bank_num == 0) {
+ *reg = RK3576_PULL_GPIO0_BH_OFFSET - 0x4;
+ } else if (bank->bank_num == 1) {
+ *reg = RK3576_PULL_GPIO1_OFFSET;
+ } else if (bank->bank_num == 2) {
+ *reg = RK3576_PULL_GPIO2_OFFSET;
+ } else if (bank->bank_num == 3) {
+ *reg = RK3576_PULL_GPIO3_OFFSET;
+ } else if (bank->bank_num == 4 && pin_num < 16) {
+ *reg = RK3576_PULL_GPIO4_AL_OFFSET;
+ } else if (bank->bank_num == 4 && pin_num < 24) {
+ *reg = RK3576_PULL_GPIO4_CL_OFFSET - 0x8;
+ } else if (bank->bank_num == 4) {
+ *reg = RK3576_PULL_GPIO4_DL_OFFSET - 0xc;
+ } else {
+ *reg = 0;
+ debug("unsupported bank_num %d\n", bank->bank_num);
+ }
+
+ *reg += ((pin_num / RK3576_PULL_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3576_PULL_PINS_PER_REG;
+ *bit *= RK3576_PULL_BITS_PER_PIN;
+}
+
+static int rk3576_set_pull(struct rockchip_pin_bank *bank,
+ int pin_num, int pull)
+{
+ struct regmap *regmap;
+ int reg, ret;
+ u8 bit, type;
+ u32 data, rmask;
+
+ if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+ return -ENOTSUPP;
+
+ rk3576_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+ type = 1; /* FIXME: was always set to 1 in vendor kernel */
+ ret = rockchip_translate_pull_value(type, pull);
+ if (ret < 0) {
+ debug("unsupported pull setting %d\n", pull);
+ return ret;
+ }
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3576_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+ rmask = data | (data >> 16);
+ data |= (ret << bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RK3576_SMT_BITS_PER_PIN 1
+#define RK3576_SMT_PINS_PER_REG 8
+#define RK3576_SMT_GPIO0_AL_OFFSET 0x30
+#define RK3576_SMT_GPIO0_BH_OFFSET 0x2040
+#define RK3576_SMT_GPIO1_OFFSET 0x6210
+#define RK3576_SMT_GPIO2_OFFSET 0x6220
+#define RK3576_SMT_GPIO3_OFFSET 0x6230
+#define RK3576_SMT_GPIO4_AL_OFFSET 0x6240
+#define RK3576_SMT_GPIO4_CL_OFFSET 0xA248
+#define RK3576_SMT_GPIO4_DL_OFFSET 0xB24C
+
+static void rk3576_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num,
+ struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ *regmap = priv->regmap_base;
+ if (bank->bank_num == 0 && pin_num < 12) {
+ *reg = RK3576_SMT_GPIO0_AL_OFFSET;
+ } else if (bank->bank_num == 0) {
+ *reg = RK3576_SMT_GPIO0_BH_OFFSET - 0x4;
+ } else if (bank->bank_num == 1) {
+ *reg = RK3576_SMT_GPIO1_OFFSET;
+ } else if (bank->bank_num == 2) {
+ *reg = RK3576_SMT_GPIO2_OFFSET;
+ } else if (bank->bank_num == 3) {
+ *reg = RK3576_SMT_GPIO3_OFFSET;
+ } else if (bank->bank_num == 4 && pin_num < 16) {
+ *reg = RK3576_SMT_GPIO4_AL_OFFSET;
+ } else if (bank->bank_num == 4 && pin_num < 24) {
+ *reg = RK3576_SMT_GPIO4_CL_OFFSET - 0x8;
+ } else if (bank->bank_num == 4) {
+ *reg = RK3576_SMT_GPIO4_DL_OFFSET - 0xc;
+ } else {
+ *reg = 0;
+ debug("unsupported bank_num %d\n", bank->bank_num);
+ }
+
+ *reg += ((pin_num / RK3576_SMT_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3576_SMT_PINS_PER_REG;
+ *bit *= RK3576_SMT_BITS_PER_PIN;
+}
+
+static int rk3576_set_schmitt(struct rockchip_pin_bank *bank,
+ int pin_num, int enable)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data, rmask;
+ u8 bit;
+
+ rk3576_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3576_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+ rmask = data | (data >> 16);
+ data |= (enable << bit);
+
+ return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+static struct rockchip_pin_bank rk3576_pin_banks[] = {
+ RK3576_PIN_BANK_FLAGS(0, 32, "gpio0", IOMUX_WIDTH_4BIT,
+ 0, 0x8, 0x2004, 0x200C),
+ RK3576_PIN_BANK_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
+ 0x4020, 0x4028, 0x4030, 0x4038),
+ RK3576_PIN_BANK_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
+ 0x4040, 0x4048, 0x4050, 0x4058),
+ RK3576_PIN_BANK_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
+ 0x4060, 0x4068, 0x4070, 0x4078),
+ RK3576_PIN_BANK_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
+ 0x4080, 0x4088, 0xA390, 0xB398),
+};
+
+static const struct rockchip_pin_ctrl rk3576_pin_ctrl = {
+ .pin_banks = rk3576_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3576_pin_banks),
+ .grf_mux_offset = 0x0,
+ .set_mux = rk3576_set_mux,
+ .set_pull = rk3576_set_pull,
+ .set_drive = rk3576_set_drive,
+ .set_schmitt = rk3576_set_schmitt,
+};
+
+static const struct udevice_id rk3576_pinctrl_ids[] = {
+ {
+ .compatible = "rockchip,rk3576-pinctrl",
+ .data = (ulong)&rk3576_pin_ctrl
+ },
+ { }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3576) = {
+ .name = "rockchip_rk3576_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = rk3576_pinctrl_ids,
+ .priv_auto = sizeof(struct rockchip_pinctrl_priv),
+ .ops = &rockchip_pinctrl_ops,
+#if CONFIG_IS_ENABLED(OF_REAL)
+ .bind = dm_scan_fdt_dev,
+#endif
+ .probe = rockchip_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
index df7bc684d29..5e3c9c90760 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
@@ -458,6 +458,9 @@ struct rockchip_pin_bank {
#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
+#define RK3576_PIN_BANK_FLAGS(ID, PIN, LABEL, M, O1, O2, O3, O4) \
+ PIN_BANK_IOMUX_FLAGS_OFFSET(ID, PIN, LABEL, M, M, M, M, O1, O2, O3, O4)
+
#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P) \
PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P)
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index 36dc0500dab..fd94aad0cd4 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -13,7 +13,9 @@ obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
obj-$(CONFIG_ROCKCHIP_RK3308) = sdram_rk3308.o
obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o
obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3528) += sdram_rk3528.o
obj-$(CONFIG_ROCKCHIP_RK3568) += sdram_rk3568.o
+obj-$(CONFIG_ROCKCHIP_RK3576) += sdram_rk3576.o
obj-$(CONFIG_ROCKCHIP_RK3588) += sdram_rk3588.o
obj-$(CONFIG_ROCKCHIP_RV1126) += sdram_rv1126.o sdram_pctl_px30.o
obj-$(CONFIG_ROCKCHIP_SDRAM_COMMON) += sdram_common.o
diff --git a/drivers/ram/rockchip/sdram_rk3528.c b/drivers/ram/rockchip/sdram_rk3528.c
new file mode 100644
index 00000000000..89d325bea66
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_rk3528.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright Contributors to the U-Boot project.
+
+#include <dm.h>
+#include <ram.h>
+#include <asm/arch-rockchip/sdram.h>
+
+#define PMUGRF_BASE 0xff370000
+#define OS_REG18_REG 0x248
+
+static int rk3528_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+ info->base = CFG_SYS_SDRAM_BASE;
+ info->size = rockchip_sdram_size(PMUGRF_BASE + OS_REG18_REG);
+
+ return 0;
+}
+
+static struct ram_ops rk3528_dmc_ops = {
+ .get_info = rk3528_dmc_get_info,
+};
+
+static const struct udevice_id rk3528_dmc_ids[] = {
+ { .compatible = "rockchip,rk3528-dmc" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rk3528_dmc) = {
+ .name = "rockchip_rk3528_dmc",
+ .id = UCLASS_RAM,
+ .of_match = rk3528_dmc_ids,
+ .ops = &rk3528_dmc_ops,
+};
diff --git a/drivers/ram/rockchip/sdram_rk3576.c b/drivers/ram/rockchip/sdram_rk3576.c
new file mode 100644
index 00000000000..5a66032ef8f
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_rk3576.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2024 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dm.h>
+#include <ram.h>
+#include <asm/arch-rockchip/sdram.h>
+
+#define PMU1GRF_BASE 0x26026000
+#define OS_REG2_REG 0x208
+
+static int rk3576_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+ info->base = CFG_SYS_SDRAM_BASE;
+ info->size = rockchip_sdram_size(PMU1GRF_BASE + OS_REG2_REG);
+
+ return 0;
+}
+
+static struct ram_ops rk3576_dmc_ops = {
+ .get_info = rk3576_dmc_get_info,
+};
+
+static const struct udevice_id rk3576_dmc_ids[] = {
+ { .compatible = "rockchip,rk3576-dmc" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rk3576_dmc) = {
+ .name = "rockchip_rk3576_dmc",
+ .id = UCLASS_RAM,
+ .of_match = rk3576_dmc_ids,
+ .ops = &rk3576_dmc_ops,
+};
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index b9494396013..1dd3cd99a14 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -17,7 +17,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o
obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o
-obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o rst-rk3588.o
+obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o rst-rk3528.o rst-rk3576.o rst-rk3588.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o
diff --git a/drivers/reset/rst-rk3528.c b/drivers/reset/rst-rk3528.c
new file mode 100644
index 00000000000..f6e760d468d
--- /dev/null
+++ b/drivers/reset/rst-rk3528.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ * Based on Sebastian Reichel's implementation for RK3588
+ */
+
+#include <dm.h>
+#include <asm/arch-rockchip/clock.h>
+#include <dt-bindings/reset/rockchip,rk3528-cru.h>
+
+/* 0xFF4A0000 + 0x0A00 */
+#define RK3528_CRU_RESET_OFFSET(id, reg, bit) [id] = (0 + reg * 16 + bit)
+
+/* mapping table for reset ID to register offset */
+static const int rk3528_register_offset[] = {
+ /* CRU_SOFTRST_CON03 */
+ RK3528_CRU_RESET_OFFSET(SRST_CORE0_PO, 3, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE1_PO, 3, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE2_PO, 3, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE3_PO, 3, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE0, 3, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE1, 3, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE2, 3, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE3, 3, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_NL2, 3, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE_BIU, 3, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE_CRYPTO, 3, 10),
+
+ /* CRU_SOFTRST_CON05 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_DBG, 5, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_POT_DBG, 5, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_NT_DBG, 5, 15),
+
+ /* CRU_SOFTRST_CON06 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_CORE_GRF, 6, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DAPLITE_BIU, 6, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CPU_BIU, 6, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_REF_PVTPLL_CORE, 6, 7),
+
+ /* CRU_SOFTRST_CON08 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_BUS_VOPGL_BIU, 8, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_A_BUS_H_BIU, 8, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_A_SYSMEM_BIU, 8, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_A_BUS_BIU, 8, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_H_BUS_BIU, 8, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_P_BUS_BIU, 8, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DFT2APB, 8, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_P_BUS_GRF, 8, 15),
+
+ /* CRU_SOFTRST_CON09 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_BUS_M_BIU, 9, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_A_GIC, 9, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_A_SPINLOCK, 9, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_A_DMAC, 9, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_P_TIMER, 9, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER0, 9, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER1, 9, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER2, 9, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER3, 9, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER4, 9, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER5, 9, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_P_JDBCK_DAP, 9, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_JDBCK_DAP, 9, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_P_WDT_NS, 9, 15),
+
+ /* CRU_SOFTRST_CON10 */
+ RK3528_CRU_RESET_OFFSET(SRST_T_WDT_NS, 10, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_H_TRNG_NS, 10, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART0, 10, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART0, 10, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_PKA_CRYPTO, 10, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_A_CRYPTO, 10, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_H_CRYPTO, 10, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DMA2DDR, 10, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_A_DMA2DDR, 10, 14),
+
+ /* CRU_SOFTRST_CON11 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_PWM0, 11, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_PWM0, 11, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_P_PWM1, 11, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_PWM1, 11, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_P_SCR, 11, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_A_DCF, 11, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_P_INTMUX, 11, 12),
+
+ /* CRU_SOFTRST_CON25 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_VPU_BIU, 25, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_H_VPU_BIU, 25, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VPU_BIU, 25, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_A_VPU, 25, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_H_VPU, 25, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CRU_PCIE, 25, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VPU_GRF, 25, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SFC, 25, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_S_SFC, 25, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_C_EMMC, 25, 15),
+
+ /* CRU_SOFTRST_CON26 */
+ RK3528_CRU_RESET_OFFSET(SRST_H_EMMC, 26, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_A_EMMC, 26, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_B_EMMC, 26, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_T_EMMC, 26, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_GPIO1, 26, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_DB_GPIO1, 26, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_A_VPU_L_BIU, 26, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VPU_IOC, 26, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SAI_I2S0, 26, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_M_SAI_I2S0, 26, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SAI_I2S2, 26, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_M_SAI_I2S2, 26, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_ACODEC, 26, 13),
+
+ /* CRU_SOFTRST_CON27 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_GPIO3, 27, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_DB_GPIO3, 27, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_P_SPI1, 27, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_SPI1, 27, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART2, 27, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART2, 27, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART5, 27, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART5, 27, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART6, 27, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART6, 27, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART7, 27, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART7, 27, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C3, 27, 15),
+
+ /* CRU_SOFTRST_CON28 */
+ RK3528_CRU_RESET_OFFSET(SRST_I2C3, 28, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C5, 28, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_I2C5, 28, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C6, 28, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_I2C6, 28, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_A_MAC, 28, 5),
+
+ /* CRU_SOFTRST_CON30 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_PCIE, 30, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_PCIE_PIPE_PHY, 30, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_PCIE_POWER_UP, 30, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_PCIE_PHY, 30, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_PIPE_GRF, 30, 7),
+
+ /* CRU_SOFTRST_CON32 */
+ RK3528_CRU_RESET_OFFSET(SRST_H_SDIO0, 32, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SDIO1, 32, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_TS_0, 32, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_TS_1, 32, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CAN2, 32, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_CAN2, 32, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CAN3, 32, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_CAN3, 32, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_P_SARADC, 32, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_SARADC, 32, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_SARADC_PHY, 32, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_P_TSADC, 32, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_TSADC, 32, 15),
+
+ /* CRU_SOFTRST_CON33 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_USB3OTG, 33, 1),
+
+ /* CRU_SOFTRST_CON34 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_GPU_BIU, 34, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_GPU_BIU, 34, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_A_GPU, 34, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_REF_PVTPLL_GPU, 34, 9),
+
+ /* CRU_SOFTRST_CON36 */
+ RK3528_CRU_RESET_OFFSET(SRST_H_RKVENC_BIU, 36, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_A_RKVENC_BIU, 36, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_P_RKVENC_BIU, 36, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_H_RKVENC, 36, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_A_RKVENC, 36, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE_RKVENC, 36, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SAI_I2S1, 36, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_M_SAI_I2S1, 36, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C1, 36, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_I2C1, 36, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C0, 36, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_I2C0, 36, 14),
+
+ /* CRU_SOFTRST_CON37 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_SPI0, 37, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_SPI0, 37, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_GPIO4, 37, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_DB_GPIO4, 37, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_P_RKVENC_IOC, 37, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SPDIF, 37, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_M_SPDIF, 37, 15),
+
+ /* CRU_SOFTRST_CON38 */
+ RK3528_CRU_RESET_OFFSET(SRST_H_PDM, 38, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_M_PDM, 38, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART1, 38, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART1, 38, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART3, 38, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART3, 38, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_P_RKVENC_GRF, 38, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CAN0, 38, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_CAN0, 38, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CAN1, 38, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_CAN1, 38, 10),
+
+ /* CRU_SOFTRST_CON39 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_VO_BIU, 39, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_H_VO_BIU, 39, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VO_BIU, 39, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_H_RGA2E, 39, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_A_RGA2E, 39, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE_RGA2E, 39, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_H_VDPP, 39, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_A_VDPP, 39, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_CORE_VDPP, 39, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VO_GRF, 39, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_P_CRU, 39, 15),
+
+ /* CRU_SOFTRST_CON40 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_VOP_BIU, 40, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_H_VOP, 40, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_D_VOP0, 40, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_D_VOP1, 40, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_A_VOP, 40, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_P_HDMI, 40, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_HDMI, 40, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_P_HDMIPHY, 40, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_H_HDCP_KEY, 40, 15),
+
+ /* CRU_SOFTRST_CON41 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_HDCP, 41, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_H_HDCP, 41, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_P_HDCP, 41, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_H_CVBS, 41, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_D_CVBS_VOP, 41, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_D_4X_CVBS_VOP, 41, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER, 41, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_H_JPEG_DECODER, 41, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_A_VO_L_BIU, 41, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_A_MAC_VO, 41, 10),
+
+ /* CRU_SOFTRST_CON42 */
+ RK3528_CRU_RESET_OFFSET(SRST_A_JPEG_BIU, 42, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SAI_I2S3, 42, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_M_SAI_I2S3, 42, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_MACPHY, 42, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VCDCPHY, 42, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_P_GPIO2, 42, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_DB_GPIO2, 42, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_VO_IOC, 42, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_H_SDMMC0, 42, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_P_OTPC_NS, 42, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_SBPI_OTPC_NS, 42, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_USER_OTPC_NS, 42, 13),
+
+ /* CRU_SOFTRST_CON43 */
+ RK3528_CRU_RESET_OFFSET(SRST_HDMIHDP0, 43, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_H_USBHOST, 43, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_H_USBHOST_ARB, 43, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_HOST_UTMI, 43, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_UART4, 43, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_S_UART4, 43, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C4, 43, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_I2C4, 43, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_P_I2C7, 43, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_I2C7, 43, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_P_USBPHY, 43, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_USBPHY_POR, 43, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_USBPHY_OTG, 43, 15),
+
+ /* CRU_SOFTRST_CON44 */
+ RK3528_CRU_RESET_OFFSET(SRST_USBPHY_HOST, 44, 0),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDRPHY_CRU, 44, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_H_RKVDEC_BIU, 44, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_A_RKVDEC_BIU, 44, 7),
+ RK3528_CRU_RESET_OFFSET(SRST_A_RKVDEC, 44, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_H_RKVDEC, 44, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_HEVC_CA_RKVDEC, 44, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_REF_PVTPLL_RKVDEC, 44, 12),
+
+ /* CRU_SOFTRST_CON45 */
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDR_BIU, 45, 1),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDRC, 45, 2),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDRMON, 45, 3),
+ RK3528_CRU_RESET_OFFSET(SRST_TIMER_DDRMON, 45, 4),
+ RK3528_CRU_RESET_OFFSET(SRST_P_MSCH_BIU, 45, 5),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDR_GRF, 45, 6),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDR_HWLP, 45, 8),
+ RK3528_CRU_RESET_OFFSET(SRST_P_DDRPHY, 45, 9),
+ RK3528_CRU_RESET_OFFSET(SRST_MSCH_BIU, 45, 10),
+ RK3528_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL, 45, 11),
+ RK3528_CRU_RESET_OFFSET(SRST_DDR_UPCTL, 45, 12),
+ RK3528_CRU_RESET_OFFSET(SRST_DDRMON, 45, 13),
+ RK3528_CRU_RESET_OFFSET(SRST_A_DDR_SCRAMBLE, 45, 14),
+ RK3528_CRU_RESET_OFFSET(SRST_A_SPLIT, 45, 15),
+
+ /* CRU_SOFTRST_CON46 */
+ RK3528_CRU_RESET_OFFSET(SRST_DDR_PHY, 46, 0),
+};
+
+int rk3528_reset_bind_lut(struct udevice *pdev, u32 reg_offset, u32 reg_number)
+{
+ return rockchip_reset_bind_lut(pdev, rk3528_register_offset,
+ reg_offset, reg_number);
+}
diff --git a/drivers/reset/rst-rk3576.c b/drivers/reset/rst-rk3576.c
new file mode 100644
index 00000000000..a6b83a2fd74
--- /dev/null
+++ b/drivers/reset/rst-rk3576.c
@@ -0,0 +1,647 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 Collabora Ltd.
+ * Author: Detlev Casanova <[email protected]>
+ * Based on Sebastian Reichel's implementation for RK3588
+ */
+
+#include <dm.h>
+#include <asm/arch-rockchip/clock.h>
+#include <dt-bindings/reset/rockchip,rk3576-cru.h>
+
+/* 0x27200000 + 0x0A00 */
+#define RK3576_CRU_RESET_OFFSET(id, reg, bit) [id] = (0 + (reg) * 16 + (bit))
+/* 0x27208000 + 0x0A00 */
+#define RK3576_PHPCRU_RESET_OFFSET(id, reg, bit) [id] = (0x8000 * 4 + (reg) * 16 + (bit))
+/* 0x27210000 + 0x0A00 */
+#define RK3576_SECURENSCRU_RESET_OFFSET(id, reg, bit) [id] = (0x10000 * 4 + (reg) * 16 + (bit))
+/* 0x27220000 + 0x0A00 */
+#define RK3576_PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x20000 * 4 + (reg) * 16 + (bit))
+
+/* mapping table for reset ID to register offset */
+static const int rk3576_register_offset[] = {
+ /* SOFTRST_CON01 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_TOP_BIU, 1, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_TOP_BIU, 1, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_TOP_MID_BIU, 1, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SECURE_HIGH_BIU, 1, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_TOP_BIU, 1, 14),
+
+ /* SOFTRST_CON02 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_VO0VOP_CHANNEL_BIU, 2, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VO0VOP_CHANNEL_BIU, 2, 1),
+
+ /* SOFTRST_CON06 */
+ RK3576_CRU_RESET_OFFSET(SRST_BISRINTF, 6, 2),
+
+ /* SOFTRST_CON07 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_AUDIO_BIU, 7, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_H_ASRC_2CH_0, 7, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_H_ASRC_2CH_1, 7, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_H_ASRC_4CH_0, 7, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_ASRC_4CH_1, 7, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_ASRC_2CH_0, 7, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_ASRC_2CH_1, 7, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_ASRC_4CH_0, 7, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_ASRC_4CH_1, 7, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI0_8CH, 7, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI0_8CH, 7, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_RX0, 7, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_RX0, 7, 15),
+
+ /* SOFTRST_CON08 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_RX1, 8, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_RX1, 8, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI1_8CH, 8, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI1_8CH, 8, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI2_2CH, 8, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI2_2CH, 8, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI3_2CH, 8, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI3_2CH, 8, 14),
+
+ /* SOFTRST_CON09 */
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI4_2CH, 9, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI4_2CH, 9, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_H_ACDCDIG_DSM, 9, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_M_ACDCDIG_DSM, 9, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_PDM1, 9, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_PDM1, 9, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_M_PDM1, 9, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_TX0, 9, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_TX0, 9, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_TX1, 9, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_TX1, 9, 12),
+
+ /* SOFTRST_CON11 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_BUS_BIU, 11, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_BUS_BIU, 11, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CRU, 11, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_CAN0, 11, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_CAN0, 11, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_CAN1, 11, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_CAN1, 11, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_INTMUX2BUS, 11, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VCCIO_IOC, 11, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_H_BUS_BIU, 11, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_KEY_SHIFT, 11, 15),
+
+ /* SOFTRST_CON12 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C1, 12, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C2, 12, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C3, 12, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C4, 12, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C5, 12, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C6, 12, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C7, 12, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C8, 12, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_I2C9, 12, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_P_WDT_BUSMCU, 12, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_T_WDT_BUSMCU, 12, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_A_GIC, 12, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C1, 12, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C2, 12, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C3, 12, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C4, 12, 15),
+
+ /* SOFTRST_CON13 */
+ RK3576_CRU_RESET_OFFSET(SRST_I2C5, 13, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C6, 13, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C7, 13, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C8, 13, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_I2C9, 13, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SARADC, 13, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_SARADC, 13, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_TSADC, 13, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_TSADC, 13, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART0, 13, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART2, 13, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART3, 13, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART4, 13, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART5, 13, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART6, 13, 15),
+
+ /* SOFTRST_CON14 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART7, 14, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART8, 14, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART9, 14, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART10, 14, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UART11, 14, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART0, 14, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART2, 14, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART3, 14, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART4, 14, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART5, 14, 15),
+
+ /* SOFTRST_CON15 */
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART6, 15, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART7, 15, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART8, 15, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART9, 15, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART10, 15, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_S_UART11, 15, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SPI0, 15, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SPI1, 15, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SPI2, 15, 15),
+
+ /* SOFTRST_CON16 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_SPI3, 16, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SPI4, 16, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_SPI0, 16, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_SPI1, 16, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_SPI2, 16, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_SPI3, 16, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_SPI4, 16, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_P_WDT0, 16, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_T_WDT0, 16, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SYS_GRF, 16, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PWM1, 16, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_PWM1, 16, 11),
+
+ /* SOFTRST_CON17 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_BUSTIMER0, 17, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_BUSTIMER1, 17, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER0, 17, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER1, 17, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER2, 17, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER3, 17, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER4, 17, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER5, 17, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_P_BUSIOC, 17, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_P_MAILBOX0, 17, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GPIO1, 17, 15),
+
+ /* SOFTRST_CON18 */
+ RK3576_CRU_RESET_OFFSET(SRST_GPIO1, 18, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GPIO2, 18, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_GPIO2, 18, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GPIO3, 18, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_GPIO3, 18, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GPIO4, 18, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_GPIO4, 18, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DECOM, 18, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DECOM, 18, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_D_DECOM, 18, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER6, 18, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER7, 18, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER8, 18, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER9, 18, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER10, 18, 15),
+
+ /* SOFTRST_CON19 */
+ RK3576_CRU_RESET_OFFSET(SRST_TIMER11, 19, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DMAC0, 19, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DMAC1, 19, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DMAC2, 19, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SPINLOCK, 19, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_REF_PVTPLL_BUS, 19, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_I3C0, 19, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_I3C1, 19, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_H_BUS_CM0_BIU, 19, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_F_BUS_CM0_CORE, 19, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_T_BUS_CM0_JTAG, 19, 13),
+
+ /* SOFTRST_CON20 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_INTMUX2PMU, 20, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_INTMUX2DDR, 20, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PVTPLL_BUS, 20, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PWM2, 20, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_PWM2, 20, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_FREQ_PWM1, 20, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_COUNTER_PWM1, 20, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_I3C0, 20, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_I3C1, 20, 13),
+
+ /* SOFTRST_CON21 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH0, 21, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_BIU, 21, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH0, 21, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH0, 21, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_BIU, 21, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_DFI_CH0, 21, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_MON_CH0, 21, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_HWLP_CH0, 21, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH1, 21, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_HWLP_CH1, 21, 15),
+
+ /* SOFTRST_CON22 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH1, 22, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH1, 22, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_DFI_CH1, 22, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH0, 22, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH1, 22, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_MON_CH1, 22, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_SCRAMBLE_CH0, 22, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_SCRAMBLE_CH1, 22, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_P_AHB2APB, 22, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_AHB2APB, 22, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_H_DDR_BIU, 22, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_F_DDR_CM0_CORE, 22, 15),
+
+ /* SOFTRST_CON23 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH0, 23, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH1, 23, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_TIMER0, 23, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_TIMER1, 23, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_T_WDT_DDR, 23, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_P_WDT, 23, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_TIMER, 23, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_T_DDR_CM0_JTAG, 23, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DDR_GRF, 23, 11),
+
+ /* SOFTRST_CON25 */
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH0, 25, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_0_CH0, 25, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_1_CH0, 25, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_2_CH0, 25, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_3_CH0, 25, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_4_CH0, 25, 6),
+
+ /* SOFTRST_CON26 */
+ RK3576_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH1, 26, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_0_CH1, 26, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_1_CH1, 26, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_2_CH1, 26, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_3_CH1, 26, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_4_CH1, 26, 6),
+
+ /* SOFTRST_CON27 */
+ RK3576_CRU_RESET_OFFSET(SRST_REF_PVTPLL_DDR, 27, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PVTPLL_DDR, 27, 1),
+
+ /* SOFTRST_CON28 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKNN0, 28, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKNN0_BIU, 28, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_L_RKNN0_BIU, 28, 12),
+
+ /* SOFTRST_CON29 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKNN1, 29, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKNN1_BIU, 29, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_L_RKNN1_BIU, 29, 3),
+
+ /* SOFTRST_CON31 */
+ RK3576_CRU_RESET_OFFSET(SRST_NPU_DAP, 31, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_L_NPUSUBSYS_BIU, 31, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_NPUTOP_BIU, 31, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_NPU_TIMER, 31, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_NPUTIMER0, 31, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_NPUTIMER1, 31, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_P_NPU_WDT, 31, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_T_NPU_WDT, 31, 15),
+
+ /* SOFTRST_CON32 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKNN_CBUF, 32, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RVCORE0, 32, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_NPU_GRF, 32, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PVTPLL_NPU, 32, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_NPU_PVTPLL, 32, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_H_NPU_CM0_BIU, 32, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_F_NPU_CM0_CORE, 32, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_T_NPU_CM0_JTAG, 32, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKNNTOP_BIU, 32, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_H_RKNN_CBUF, 32, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_RKNNTOP_BIU, 32, 13),
+
+ /* SOFTRST_CON33 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_NVM_BIU, 33, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_NVM_BIU, 33, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_S_FSPI, 33, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_H_FSPI, 33, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_C_EMMC, 33, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_H_EMMC, 33, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_A_EMMC, 33, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_B_EMMC, 33, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_T_EMMC, 33, 12),
+
+ /* SOFTRST_CON34 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_GRF, 34, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PHP_BIU, 34, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_PHP_BIU, 34, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PCIE0, 34, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_PCIE0_POWER_UP, 34, 15),
+
+ /* SOFTRST_CON35 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_USB3OTG1, 35, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_MMU0, 35, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SLV_MMU0, 35, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_A_MMU1, 35, 14),
+
+ /* SOFTRST_CON36 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_SLV_MMU1, 36, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PCIE1, 36, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_PCIE1_POWER_UP, 36, 9),
+
+ /* SOFTRST_CON37 */
+ RK3576_CRU_RESET_OFFSET(SRST_RXOOB0, 37, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_RXOOB1, 37, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_PMALIVE0, 37, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_PMALIVE1, 37, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SATA0, 37, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SATA1, 37, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_ASIC1, 37, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_ASIC0, 37, 7),
+
+ /* SOFTRST_CON40 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_CSIDPHY1, 40, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_SCAN_CSIDPHY1, 40, 3),
+
+ /* SOFTRST_CON42 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_SDGMAC_GRF, 42, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SDGMAC_BIU, 42, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SDGMAC_BIU, 42, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SDGMAC_BIU, 42, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_GMAC0, 42, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_A_GMAC1, 42, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GMAC0, 42, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GMAC1, 42, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SDIO, 42, 12),
+
+ /* SOFTRST_CON43 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_SDMMC0, 43, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_S_FSPI1, 43, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_H_FSPI1, 43, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DSMC_BIU, 43, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DSMC, 43, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DSMC, 43, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_H_HSGPIO, 43, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_HSGPIO, 43, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_A_HSGPIO, 43, 13),
+
+ /* SOFTRST_CON45 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_RKVDEC, 45, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_H_RKVDEC_BIU, 45, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RKVDEC_BIU, 45, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_RKVDEC_HEVC_CA, 45, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_RKVDEC_CORE, 45, 9),
+
+ /* SOFTRST_CON47 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_USB_BIU, 47, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_P_USBUFS_BIU, 47, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_USB3OTG0, 47, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_UFS_BIU, 47, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_A_MMU2, 47, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_A_SLV_MMU2, 47, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_A_UFS_SYS, 47, 15),
+
+ /* SOFTRST_CON48 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_UFS, 48, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_USBUFS_GRF, 48, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_UFS_GRF, 48, 2),
+
+ /* SOFTRST_CON49 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_VPU_BIU, 49, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_JPEG_BIU, 49, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RGA_BIU, 49, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VDPP_BIU, 49, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_A_EBC_BIU, 49, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_RGA2E_0, 49, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RGA2E_0, 49, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_CORE_RGA2E_0, 49, 15),
+
+ /* SOFTRST_CON50 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_JPEG, 50, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_H_JPEG, 50, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VDPP, 50, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VDPP, 50, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_CORE_VDPP, 50, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_H_RGA2E_1, 50, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_RGA2E_1, 50, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_CORE_RGA2E_1, 50, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_EBC, 50, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_A_EBC, 50, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_D_EBC, 50, 12),
+
+ /* SOFTRST_CON51 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_VEPU0_BIU, 51, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VEPU0_BIU, 51, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VEPU0, 51, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VEPU0, 51, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_VEPU0_CORE, 51, 6),
+
+ /* SOFTRST_CON53 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_VI_BIU, 53, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VI_BIU, 53, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VI_BIU, 53, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_D_VICAP, 53, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VICAP, 53, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VICAP, 53, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_ISP0, 53, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_ISP0_VICAP, 53, 11),
+
+ /* SOFTRST_CON54 */
+ RK3576_CRU_RESET_OFFSET(SRST_CORE_VPSS, 54, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CSI_HOST_0, 54, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CSI_HOST_1, 54, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CSI_HOST_2, 54, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CSI_HOST_3, 54, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CSI_HOST_4, 54, 8),
+
+ /* SOFTRST_CON59 */
+ RK3576_CRU_RESET_OFFSET(SRST_CIFIN, 59, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_VICAP_I0CLK, 59, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_VICAP_I1CLK, 59, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_VICAP_I2CLK, 59, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_VICAP_I3CLK, 59, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_VICAP_I4CLK, 59, 5),
+
+ /* SOFTRST_CON61 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_VOP_BIU, 61, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VOP2_BIU, 61, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VOP_BIU, 61, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VOP_BIU, 61, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VOP, 61, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VOP, 61, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_D_VP0, 61, 13),
+
+ /* SOFTRST_CON62 */
+ RK3576_CRU_RESET_OFFSET(SRST_D_VP1, 62, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_D_VP2, 62, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VOP2_BIU, 62, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VOPGRF, 62, 3),
+
+ /* SOFTRST_CON63 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_VO0_BIU, 63, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VO0_BIU, 63, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_A_HDCP0_BIU, 63, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VO0_GRF, 63, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_A_HDCP0, 63, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_HDCP0, 63, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_HDCP0, 63, 14),
+
+ /* SOFTRST_CON64 */
+ RK3576_CRU_RESET_OFFSET(SRST_P_DSIHOST0, 64, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_DSIHOST0, 64, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_P_HDMITX0, 64, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_HDMITX0_REF, 64, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_EDP0, 64, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_EDP0_24M, 64, 14),
+
+ /* SOFTRST_CON65 */
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI5_8CH, 65, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI5_8CH, 65, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI6_8CH, 65, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI6_8CH, 65, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_TX2, 65, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_TX2, 65, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_RX2, 65, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_RX2, 65, 15),
+
+ /* SOFTRST_CON66 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI8_8CH, 66, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI8_8CH, 66, 2),
+
+ /* SOFTRST_CON67 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_VO1_BIU, 67, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VO1_BIU, 67, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI7_8CH, 67, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI7_8CH, 67, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_TX3, 67, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_TX4, 67, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SPDIF_TX5, 67, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_TX3, 67, 14),
+
+ /* SOFTRST_CON68 */
+ RK3576_CRU_RESET_OFFSET(SRST_DP0, 68, 0),
+ RK3576_CRU_RESET_OFFSET(SRST_P_VO1_GRF, 68, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_A_HDCP1_BIU, 68, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_HDCP1, 68, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_H_HDCP1, 68, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_HDCP1, 68, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_H_SAI9_8CH, 68, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SAI9_8CH, 68, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_TX4, 68, 12),
+ RK3576_CRU_RESET_OFFSET(SRST_M_SPDIF_TX5, 68, 13),
+
+ /* SOFTRST_CON69 */
+ RK3576_CRU_RESET_OFFSET(SRST_GPU, 69, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_S_GPU_BIU, 69, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_M0_GPU_BIU, 69, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GPU_BIU, 69, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_GPU_GRF, 69, 13),
+ RK3576_CRU_RESET_OFFSET(SRST_GPU_PVTPLL, 69, 14),
+ RK3576_CRU_RESET_OFFSET(SRST_P_PVTPLL_GPU, 69, 15),
+
+ /* SOFTRST_CON72 */
+ RK3576_CRU_RESET_OFFSET(SRST_A_CENTER_BIU, 72, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DMA2DDR, 72, 5),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM, 72, 6),
+ RK3576_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM_BIU, 72, 7),
+ RK3576_CRU_RESET_OFFSET(SRST_H_CENTER_BIU, 72, 8),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CENTER_GRF, 72, 9),
+ RK3576_CRU_RESET_OFFSET(SRST_P_DMA2DDR, 72, 10),
+ RK3576_CRU_RESET_OFFSET(SRST_P_SHAREMEM, 72, 11),
+ RK3576_CRU_RESET_OFFSET(SRST_P_CENTER_BIU, 72, 12),
+
+ /* SOFTRST_CON75 */
+ RK3576_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY0, 75, 1),
+
+ /* SOFTRST_CON78 */
+ RK3576_CRU_RESET_OFFSET(SRST_DP0_PIXELCLK, 78, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_PHY_DP0_TX, 78, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_DP1_PIXELCLK, 78, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_DP2_PIXELCLK, 78, 4),
+
+ /* SOFTRST_CON79 */
+ RK3576_CRU_RESET_OFFSET(SRST_H_VEPU1_BIU, 79, 1),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VEPU1_BIU, 79, 2),
+ RK3576_CRU_RESET_OFFSET(SRST_H_VEPU1, 79, 3),
+ RK3576_CRU_RESET_OFFSET(SRST_A_VEPU1, 79, 4),
+ RK3576_CRU_RESET_OFFSET(SRST_VEPU1_CORE, 79, 5),
+
+ /* PPLL_SOFTRST_CON00 */
+ RK3576_PHPCRU_RESET_OFFSET(SRST_P_PHPPHY_CRU, 0, 1),
+ RK3576_PHPCRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CHIP_TOP, 0, 3),
+ RK3576_PHPCRU_RESET_OFFSET(SRST_P_PCIE2_COMBOPHY0, 0, 5),
+ RK3576_PHPCRU_RESET_OFFSET(SRST_P_PCIE2_COMBOPHY0_GRF, 0, 6),
+ RK3576_PHPCRU_RESET_OFFSET(SRST_P_PCIE2_COMBOPHY1, 0, 7),
+ RK3576_PHPCRU_RESET_OFFSET(SRST_P_PCIE2_COMBOPHY1_GRF, 0, 8),
+
+ /* PPLL_SOFTRST_CON01 */
+ RK3576_PHPCRU_RESET_OFFSET(SRST_PCIE0_PIPE_PHY, 1, 5),
+ RK3576_PHPCRU_RESET_OFFSET(SRST_PCIE1_PIPE_PHY, 1, 8),
+
+ /* SECURENS_SOFTRST_CON00 */
+ RK3576_SECURENSCRU_RESET_OFFSET(SRST_H_CRYPTO_NS, 0, 3),
+ RK3576_SECURENSCRU_RESET_OFFSET(SRST_H_TRNG_NS, 0, 4),
+ RK3576_SECURENSCRU_RESET_OFFSET(SRST_P_OTPC_NS, 0, 8),
+ RK3576_SECURENSCRU_RESET_OFFSET(SRST_OTPC_NS, 0, 9),
+
+ /* PMU1_SOFTRST_CON00 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_HDPTX_GRF, 0, 0),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_HDPTX_APB, 0, 1),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY, 0, 2),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_DCPHY_GRF, 0, 3),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_BOT0_APB2ASB, 0, 4),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_BOT1_APB2ASB, 0, 5),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_USB2DEBUG, 0, 6),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_CSIPHY_GRF, 0, 7),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_CSIPHY, 0, 8),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_USBPHY_GRF_0, 0, 9),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_USBPHY_GRF_1, 0, 10),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_USBDP_GRF, 0, 11),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_USBDPPHY, 0, 12),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY_INIT, 0, 15),
+
+ /* PMU1_SOFTRST_CON01 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY_CMN, 1, 0),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY_LANE, 1, 1),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY_PCS, 1, 2),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY, 1, 3),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY, 1, 4),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_SCAN_CSIPHY, 1, 5),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_VCCIO6_IOC, 1, 6),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_0, 1, 7),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_1, 1, 8),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_HDPTX_INIT, 1, 9),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_HDPTX_CMN, 1, 10),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_HDPTX_LANE, 1, 11),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_HDMITXHDP, 1, 13),
+
+ /* PMU1_SOFTRST_CON02 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_MPHY_INIT, 2, 0),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_MPHY_GRF, 2, 1),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_VCCIO7_IOC, 2, 3),
+
+ /* PMU1_SOFTRST_CON03 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_H_PMU1_BIU, 3, 9),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_NIU, 3, 10),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_H_PMU_CM0_BIU, 3, 11),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_PMU_CM0_CORE, 3, 12),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_PMU_CM0_JTAG, 3, 13),
+
+ /* PMU1_SOFTRST_CON04 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_CRU_PMU1, 4, 1),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_GRF, 4, 3),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_IOC, 4, 4),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU1WDT, 4, 5),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_T_PMU1WDT, 4, 6),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMUTIMER, 4, 7),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_PMUTIMER0, 4, 9),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_PMUTIMER1, 4, 10),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU1PWM, 4, 11),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_PMU1PWM, 4, 12),
+
+ /* PMU1_SOFTRST_CON05 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_I2C0, 5, 1),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_I2C0, 5, 2),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_S_UART1, 5, 5),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_UART1, 5, 6),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_PDM0, 5, 13),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_H_PDM0, 5, 15),
+
+ /* PMU1_SOFTRST_CON06 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_M_PDM0, 6, 0),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_H_VAD, 6, 1),
+
+ /* PMU1_SOFTRST_CON07 */
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU0GRF, 7, 4),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_PMU0IOC, 7, 5),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_P_GPIO0, 7, 6),
+ RK3576_PMU1CRU_RESET_OFFSET(SRST_DB_GPIO0, 7, 7),
+};
+
+int rk3576_reset_bind_lut(struct udevice *pdev, u32 reg_offset, u32 reg_number)
+{
+ return rockchip_reset_bind_lut(pdev, rk3576_register_offset,
+ reg_offset, reg_number);
+}
diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c
index 2426648fbd5..d854ea90044 100644
--- a/drivers/rng/rockchip_rng.c
+++ b/drivers/rng/rockchip_rng.c
@@ -70,6 +70,27 @@
#define TRNG_v1_VERSION_CODE 0x46BC
/* end of TRNG V1 register define */
+/* start of RKRNG register define */
+#define RKRNG_CTRL 0x0010
+#define RKRNG_CTRL_INST_REQ BIT(0)
+#define RKRNG_CTRL_RESEED_REQ BIT(1)
+#define RKRNG_CTRL_TEST_REQ BIT(2)
+#define RKRNG_CTRL_SW_DRNG_REQ BIT(3)
+#define RKRNG_CTRL_SW_TRNG_REQ BIT(4)
+
+#define RKRNG_STATE 0x0014
+#define RKRNG_STATE_INST_ACK BIT(0)
+#define RKRNG_STATE_RESEED_ACK BIT(1)
+#define RKRNG_STATE_TEST_ACK BIT(2)
+#define RKRNG_STATE_SW_DRNG_ACK BIT(3)
+#define RKRNG_STATE_SW_TRNG_ACK BIT(4)
+
+/* DRNG_DATA_0 ~ DNG_DATA_7 */
+#define RKRNG_DRNG_DATA_0 0x0070
+#define RKRNG_DRNG_DATA_7 0x008C
+
+/* end of RKRNG register define */
+
#define RK_RNG_TIME_OUT 50000 /* max 50ms */
#define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos))
@@ -228,6 +249,49 @@ exit:
return retval;
}
+static int rkrng_init(struct udevice *dev)
+{
+ struct rk_rng_plat *pdata = dev_get_priv(dev);
+ u32 reg = 0;
+
+ rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
+
+ reg = trng_read(pdata, RKRNG_STATE);
+ trng_write(pdata, RKRNG_STATE, reg);
+
+ return 0;
+}
+
+static int rkrng_rng_read(struct udevice *dev, void *data, size_t len)
+{
+ struct rk_rng_plat *pdata = dev_get_priv(dev);
+ u32 reg = 0;
+ int retval;
+
+ if (len > RK_HW_RNG_MAX)
+ return -EINVAL;
+
+ reg = RKRNG_CTRL_SW_DRNG_REQ;
+
+ rk_clrsetreg(pdata->base + RKRNG_CTRL, 0xffff, reg);
+
+ retval = readl_poll_timeout(pdata->base + RKRNG_STATE, reg,
+ (reg & RKRNG_STATE_SW_DRNG_ACK),
+ RK_RNG_TIME_OUT);
+ if (retval)
+ goto exit;
+
+ trng_write(pdata, RKRNG_STATE, reg);
+
+ rk_rng_read_regs(pdata->base + RKRNG_DRNG_DATA_0, data, len);
+
+exit:
+ /* close TRNG */
+ rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
+
+ return retval;
+}
+
static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
{
unsigned char *buf = data;
@@ -295,6 +359,11 @@ static const struct rk_rng_soc_data rk_trngv1_soc_data = {
.rk_rng_read = rk_trngv1_rng_read,
};
+static const struct rk_rng_soc_data rkrng_soc_data = {
+ .rk_rng_init = rkrng_init,
+ .rk_rng_read = rkrng_rng_read,
+};
+
static const struct dm_rng_ops rockchip_rng_ops = {
.read = rockchip_rng_read,
};
@@ -313,13 +382,21 @@ static const struct udevice_id rockchip_rng_match[] = {
.data = (ulong)&rk_cryptov1_soc_data,
},
{
+ .compatible = "rockchip,rk3568-rng",
+ .data = (ulong)&rk_cryptov2_soc_data,
+ },
+ {
.compatible = "rockchip,cryptov2-rng",
.data = (ulong)&rk_cryptov2_soc_data,
},
{
- .compatible = "rockchip,trngv1",
+ .compatible = "rockchip,rk3588-rng",
.data = (ulong)&rk_trngv1_soc_data,
},
+ {
+ .compatible = "rockchip,rkrng",
+ .data = (ulong)&rkrng_soc_data,
+ },
{},
};
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c815764c2bc..46a83141481 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -85,6 +85,7 @@ config USB_GADGET_PRODUCT_NUM
default 0x330e if ROCKCHIP_RK3308
default 0x350a if ROCKCHIP_RK3568
default 0x350b if ROCKCHIP_RK3588
+ default 0x350c if ROCKCHIP_RK3528
default 0x0
help
Product ID of the USB device emulated, reported to the host device.