
Hi Jagan,
On 2023-01-30 15:57, Jagan Teki wrote:
Add clock driver support for Rockchip RK3588 SoC.
Signed-off-by: Elaine Zhang zhangqing@rock-chips.com Signed-off-by: Jagan Teki jagan@edgeble.ai
drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk_rk3588.c | 1996 +++++++++++++++++++++++++++++ 2 files changed, 1997 insertions(+) create mode 100644 drivers/clk/rockchip/clk_rk3588.c
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index f719f4e379..9e379cc2e3 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_ROCKCHIP_RK3328) += clk_rk3328.o obj-$(CONFIG_ROCKCHIP_RK3368) += clk_rk3368.o obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o obj-$(CONFIG_ROCKCHIP_RK3568) += clk_rk3568.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_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c new file mode 100644 index 0000000000..b87b023bd7 --- /dev/null +++ b/drivers/clk/rockchip/clk_rk3588.c @@ -0,0 +1,1996 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
- Author: Elaine Zhang zhangqing@rock-chips.com
- */
+#include <common.h> +#include <bitfield.h> +#include <clk-uclass.h> +#include <dm.h> +#include <errno.h> +#include <syscon.h> +#include <asm/arch-rockchip/cru_rk3588.h> +#include <asm/arch-rockchip/clock.h> +#include <asm/arch-rockchip/hardware.h> +#include <asm/io.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dt-bindings/clock/rockchip,rk3588-cru.h>
+DECLARE_GLOBAL_DATA_PTR;
+#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
+static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
- /* _mhz, _p, _m, _s, _k */
- RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
- RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
- RK3588_PLL_RATE(1188000000, 2, 198, 1, 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(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 rk3588_pll_clks[] = {
- [B0PLL] = PLL(pll_rk3588, PLL_B0PLL, RK3588_B0_PLL_CON(0),
RK3588_B0_PLL_MODE_CON, 0, 15, 0,
rk3588_pll_rates),
- [B1PLL] = PLL(pll_rk3588, PLL_B1PLL, RK3588_B1_PLL_CON(8),
RK3588_B1_PLL_MODE_CON, 0, 15, 0,
rk3588_pll_rates),
- [LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3588_LPLL_CON(16),
RK3588_LPLL_MODE_CON, 0, 15, 0, rk3588_pll_rates),
- [V0PLL] = PLL(pll_rk3588, PLL_V0PLL, RK3588_PLL_CON(88),
RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
- [AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3588_PLL_CON(96),
RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
- [CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3588_PLL_CON(104),
RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
- [GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3588_PLL_CON(112),
RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
- [NPLL] = PLL(pll_rk3588, PLL_NPLL, RK3588_PLL_CON(120),
RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
- [PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3588_PMU_PLL_CON(128),
RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
+};
+#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:
- */
+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 rk3588_top_get_clk(struct rk3588_clk_priv *priv, ulong clk_id) +{
- struct rk3588_cru *cru = priv->cru;
- u32 con, sel, div, rate, prate;
- switch (clk_id) {
- case ACLK_TOP_ROOT:
con = readl(&cru->clksel_con[8]);
div = (con & ACLK_TOP_ROOT_DIV_MASK) >>
ACLK_TOP_ROOT_DIV_SHIFT;
sel = (con & ACLK_TOP_ROOT_SRC_SEL_MASK) >>
ACLK_TOP_ROOT_SRC_SEL_SHIFT;
if (sel == ACLK_TOP_ROOT_SRC_SEL_CPLL)
prate = priv->cpll_hz;
else
prate = priv->cpll_hz;
Should be gpll_hz instead of cpll_hz.
return DIV_TO_RATE(prate, div);
- case ACLK_LOW_TOP_ROOT:
con = readl(&cru->clksel_con[8]);
div = (con & ACLK_LOW_TOP_ROOT_DIV_MASK) >>
ACLK_LOW_TOP_ROOT_DIV_SHIFT;
sel = (con & ACLK_LOW_TOP_ROOT_SRC_SEL_MASK) >>
ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT;
if (sel == ACLK_LOW_TOP_ROOT_SRC_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_ROOT_SEL_MASK) >> PCLK_TOP_ROOT_SEL_SHIFT;
if (sel == PCLK_TOP_ROOT_SEL_100M)
rate = 100 * MHz;
else if (sel == PCLK_TOP_ROOT_SEL_50M)
rate = 50 * MHz;
else
rate = OSC_HZ;
break;
- default:
return -ENOENT;
- }
- return rate;
+}
[...]
+static ulong rk3588_clk_get_rate(struct clk *clk) +{
- struct rk3588_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(&rk3588_pll_clks[PPLL],
priv->cru, PPLL);
- }
- switch (clk->id) {
- case PLL_LPLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[LPLL], priv->cru,
LPLL);
break;
- case PLL_B0PLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[B0PLL], priv->cru,
B0PLL);
break;
- case PLL_B1PLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[B1PLL], priv->cru,
B1PLL);
break;
- case PLL_GPLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL], priv->cru,
GPLL);
break;
- case PLL_CPLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL], priv->cru,
CPLL);
break;
- case PLL_NPLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[NPLL], priv->cru,
NPLL);
break;
- case PLL_V0PLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL], priv->cru,
V0PLL);
break;
- case PLL_AUPLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL], priv->cru,
AUPLL);
break;
- case PLL_PPLL:
rate = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL], priv->cru,
PPLL);
break;
- case ACLK_CENTER_ROOT:
- case PCLK_CENTER_ROOT:
- case HCLK_CENTER_ROOT:
- case ACLK_CENTER_LOW_ROOT:
rate = rk3588_center_get_clk(priv, clk->id);
break;
- case ACLK_TOP_ROOT:
- case PCLK_TOP_ROOT:
- case ACLK_LOW_TOP_ROOT:
rate = rk3588_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:
rate = rk3588_i2c_get_clk(priv, clk->id);
break;
- case CLK_SPI0:
- case CLK_SPI1:
- case CLK_SPI2:
- case CLK_SPI3:
- case CLK_SPI4:
rate = rk3588_spi_get_clk(priv, clk->id);
break;
- case CLK_PWM1:
- case CLK_PWM2:
- case CLK_PWM3:
- case CLK_PMU1PWM:
rate = rk3588_pwm_get_clk(priv, clk->id);
break;
- case CLK_SARADC:
- case CLK_TSADC:
rate = rk3588_adc_get_clk(priv, clk->id);
break;
- case CCLK_SRC_SDIO:
- case CCLK_EMMC:
- case BCLK_EMMC:
- case SCLK_SFC:
- case DCLK_DECOM:
rate = rk3588_mmc_get_clk(priv, clk->id);
break;
- case TCLK_WDT0:
rate = OSC_HZ;
break;
+#ifndef CONFIG_SPL_BUILD
- case CLK_AUX16M_0:
- case CLK_AUX16M_1:
rk3588_aux16m_get_clk(priv, clk->id);
This is missing "rate =" before function call.
break;
- case ACLK_VOP_ROOT:
- case ACLK_VOP:
- case ACLK_VOP_LOW_ROOT:
- case HCLK_VOP_ROOT:
rate = rk3588_aclk_vop_get_clk(priv, clk->id);
break;
- case DCLK_VOP0:
- case DCLK_VOP0_SRC:
- case DCLK_VOP1:
- case DCLK_VOP1_SRC:
- case DCLK_VOP2:
- case DCLK_VOP2_SRC:
- case DCLK_VOP3:
rate = rk3588_dclk_vop_get_clk(priv, clk->id);
break;
- case CLK_GMAC0_PTP_REF:
- case CLK_GMAC1_PTP_REF:
- case CLK_GMAC_125M:
- case CLK_GMAC_50M:
rate = rk3588_gmac_get_clk(priv, clk->id);
break;
- 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:
rate = rk3588_uart_get_rate(priv, clk->id);
break;
- case CLK_REF_PIPE_PHY0:
- case CLK_REF_PIPE_PHY1:
- case CLK_REF_PIPE_PHY2:
rate = rk3588_pciephy_get_rate(priv, clk->id);
break;
+#endif
- default:
return -ENOENT;
- }
- return rate;
+};
+static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate) +{
- struct rk3588_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;
- }
- if (!priv->ppll_hz) {
priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
priv->cru, PPLL);
- }
- switch (clk->id) {
- case PLL_CPLL:
ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
CPLL, rate);
priv->cpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL],
priv->cru, CPLL);
break;
- case PLL_GPLL:
ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
GPLL, rate);
priv->gpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL],
priv->cru, GPLL);
break;
- case PLL_NPLL:
ret = rockchip_pll_set_rate(&rk3588_pll_clks[NPLL], priv->cru,
NPLL, rate);
break;
- case PLL_V0PLL:
ret = rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL], priv->cru,
V0PLL, rate);
priv->v0pll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
priv->cru, V0PLL);
break;
- case PLL_AUPLL:
ret = rockchip_pll_set_rate(&rk3588_pll_clks[AUPLL], priv->cru,
AUPLL, rate);
priv->aupll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL],
priv->cru, AUPLL);
break;
- case PLL_PPLL:
ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
PPLL, rate);
priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
priv->cru, PPLL);
break;
- case ACLK_CENTER_ROOT:
- case PCLK_CENTER_ROOT:
- case HCLK_CENTER_ROOT:
- case ACLK_CENTER_LOW_ROOT:
ret = rk3588_center_set_clk(priv, clk->id, rate);
break;
- case ACLK_TOP_ROOT:
- case PCLK_TOP_ROOT:
- case ACLK_LOW_TOP_ROOT:
ret = rk3588_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:
ret = rk3588_i2c_set_clk(priv, clk->id, rate);
break;
- case CLK_SPI0:
- case CLK_SPI1:
- case CLK_SPI2:
- case CLK_SPI3:
- case CLK_SPI4:
ret = rk3588_spi_set_clk(priv, clk->id, rate);
break;
- case CLK_PWM1:
- case CLK_PWM2:
- case CLK_PWM3:
- case CLK_PMU1PWM:
ret = rk3588_pwm_set_clk(priv, clk->id, rate);
break;
- case CLK_SARADC:
- case CLK_TSADC:
ret = rk3588_adc_set_clk(priv, clk->id, rate);
break;
- case CCLK_SRC_SDIO:
- case CCLK_EMMC:
- case BCLK_EMMC:
- case SCLK_SFC:
- case DCLK_DECOM:
ret = rk3588_mmc_set_clk(priv, clk->id, rate);
break;
- case TCLK_WDT0:
ret = OSC_HZ;
break;
+#ifndef CONFIG_SPL_BUILD
- case CLK_AUX16M_0:
- case CLK_AUX16M_1:
rk3588_aux16m_set_clk(priv, clk->id, rate);
This is missing "ret = " before function call.
Regards, Jonas
break;
- case ACLK_VOP_ROOT:
- case ACLK_VOP:
- case ACLK_VOP_LOW_ROOT:
- case HCLK_VOP_ROOT:
ret = rk3588_aclk_vop_set_clk(priv, clk->id, rate);
break;
- case DCLK_VOP0:
- case DCLK_VOP0_SRC:
- case DCLK_VOP1:
- case DCLK_VOP1_SRC:
- case DCLK_VOP2:
- case DCLK_VOP2_SRC:
- case DCLK_VOP3:
ret = rk3588_dclk_vop_set_clk(priv, clk->id, rate);
break;
- case CLK_GMAC0_PTP_REF:
- case CLK_GMAC1_PTP_REF:
- case CLK_GMAC_125M:
- case CLK_GMAC_50M:
ret = rk3588_gmac_set_clk(priv, clk->id, rate);
break;
- 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:
ret = rk3588_uart_set_rate(priv, clk->id, rate);
break;
- case CLK_REF_PIPE_PHY0:
- case CLK_REF_PIPE_PHY1:
- case CLK_REF_PIPE_PHY2:
ret = rk3588_pciephy_set_rate(priv, clk->id, rate);
break;
+#endif
- default:
return -ENOENT;
- }
- return ret;
+};
[...]