From e3f8cdb843db8ce0b6418a01f12d5d4d2fd3e79b Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 26 Feb 2023 12:39:07 +0000 Subject: [PATCH] RK3588 support. ok patrick@ --- sys/dev/fdt/rkclock.c | 579 +++++++++++++++++++++++++++++++++-- sys/dev/fdt/rkclock_clocks.h | 80 +++++ 2 files changed, 632 insertions(+), 27 deletions(-) diff --git a/sys/dev/fdt/rkclock.c b/sys/dev/fdt/rkclock.c index b638c4a3be0..9e6458acb19 100644 --- a/sys/dev/fdt/rkclock.c +++ b/sys/dev/fdt/rkclock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rkclock.c,v 1.65 2023/02/15 14:06:43 kettenis Exp $ */ +/* $OpenBSD: rkclock.c,v 1.66 2023/02/26 12:39:07 kettenis Exp $ */ /* * Copyright (c) 2017, 2018 Mark Kettenis * @@ -187,11 +187,37 @@ #define RK3568_PMUCRU_MODE_CON 0x0080 #define RK3568_PMUCRU_CLKSEL_CON(i) (0x0100 + (i) * 4) +/* RK3588 registers */ +#define RK3588_CRU_AUPLL_CON(i) (0x00180 + (i) * 4) +#define RK3588_CRU_CPLL_CON(i) (0x001a0 + (i) * 4) +#define RK3588_CRU_GPLL_CON(i) (0x001c0 + (i) * 4) +#define RK3588_CRU_NPLL_CON(i) (0x001e0 + (i) * 4) +#define RK3588_CRU_PLL_M_MASK (0x3ff << 0) +#define RK3588_CRU_PLL_M_SHIFT 0 +#define RK3588_CRU_PLL_RESETB (1 << 13) +#define RK3588_CRU_PLL_S_MASK (0x7 << 6) +#define RK3588_CRU_PLL_S_SHIFT 6 +#define RK3588_CRU_PLL_P_MASK (0x3f << 0) +#define RK3588_CRU_PLL_P_SHIFT 0 +#define RK3588_CRU_PLL_K_MASK (0xffff << 0) +#define RK3588_CRU_PLL_K_SHIFT 0 +#define RK3588_CRU_PLL_PLL_LOCK (1 << 15) +#define RK3588_CRU_MODE_CON 0x00280 +#define RK3588_CRU_MODE_MASK 0x3 +#define RK3588_CRU_MODE_SLOW 0x0 +#define RK3588_CRU_MODE_NORMAL 0x1 + +#define RK3588_CRU_CLKSEL_CON(i) (0x00300 + (i) * 4) +#define RK3588_CRU_GATE_CON(i) (0x00800 + (i) * 4) + +#define RK3588_PHPTOPCRU_PPLL_CON(i) (0x08200 + (i) * 4) +#define RK3588_PMUCRU_CLKSEL_CON(i) (0x30300 + (i) * 4) + #include "rkclock_clocks.h" struct rkclock { uint16_t idx; - uint16_t reg; + uint32_t reg; uint16_t sel_mask; uint16_t div_mask; uint16_t parents[8]; @@ -282,6 +308,12 @@ int rk3568_pmu_set_frequency(void *, uint32_t *, uint32_t); void rk3568_pmu_enable(void *, uint32_t *, int); void rk3568_pmu_reset(void *, uint32_t *, int); +void rk3588_init(struct rkclock_softc *); +uint32_t rk3588_get_frequency(void *, uint32_t *); +int rk3588_set_frequency(void *, uint32_t *, uint32_t); +void rk3588_enable(void *, uint32_t *, int); +void rk3588_reset(void *, uint32_t *, int); + struct rkclock_compat { const char *compat; int assign; @@ -335,7 +367,13 @@ const struct rkclock_compat rkclock_compat[] = { rk3568_pmu_enable, rk3568_pmu_get_frequency, rk3568_pmu_set_frequency, NULL, rk3568_pmu_reset - } + }, + { + "rockchip,rk3588-cru", 1, rk3588_init, + rk3588_enable, rk3588_get_frequency, + rk3588_set_frequency, NULL, + rk3588_reset + }, }; int @@ -541,27 +579,33 @@ rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq) } /* - * If there is no divider, see if we have a parent with the - * right frequency. + * If there is no divider, pick the parent with the frequency + * closest to the target frequency. */ if (clk->div_mask == 0) { + /* + * Start out with the current parent. This prevents + * unnecessary switching to a different parent. + */ parent = clk->parents[mux]; - if (freq == sc->sc_cd.cd_get_frequency(sc, &parent)) - return 0; + best_freq = sc->sc_cd.cd_get_frequency(sc, &parent); + best_mux = mux; for (i = 0; i < nitems(clk->parents); i++) { if (clk->parents[i] == 0) continue; parent = clk->parents[i]; - if (freq == sc->sc_cd.cd_get_frequency(sc, &parent)) { - HWRITE4(sc, clk->reg, - clk->sel_mask << 16 | i << sel_shift); - return 0; + f = sc->sc_cd.cd_get_frequency(sc, &parent); + if ((best_freq > freq && f < best_freq) || + (f > best_freq && f <= freq)) { + best_freq = f; + best_mux = i; } } - printf("%s: 0x%08x\n", __func__, idx); - return -1; + HWRITE4(sc, clk->reg, + clk->sel_mask << 16 | best_mux << sel_shift); + return 0; } /* @@ -580,8 +624,8 @@ rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq) if (clk->parents[i] == 0) continue; f = rkclock_freq(sc, clk, i, freq); - if ((f > best_freq && f <= freq) || - (f < best_freq && f >= freq)) { + if ((best_freq > freq && f < best_freq) || + (f > best_freq && f <= freq)) { best_freq = f; best_mux = i; } @@ -2011,19 +2055,14 @@ rk3328_get_frequency(void *cookie, uint32_t *cells) switch (idx) { case RK3328_PLL_APLL: return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0)); - break; case RK3328_PLL_DPLL: return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0)); - break; case RK3328_PLL_CPLL: return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0)); - break; case RK3328_PLL_GPLL: return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0)); - break; case RK3328_PLL_NPLL: return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0)); - break; case RK3328_ARMCLK: return rk3328_get_armclk(sc); case RK3328_XIN24M: @@ -2989,7 +3028,6 @@ rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) switch (idx) { case RK3399_PLL_PPLL: return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq); - break; default: break; } @@ -3393,22 +3431,16 @@ rk3568_get_frequency(void *cookie, uint32_t *cells) switch (idx) { case RK3568_PLL_APLL: return rk3328_get_pll(sc, RK3568_CRU_APLL_CON(0)); - break; case RK3568_PLL_DPLL: return rk3328_get_pll(sc, RK3568_CRU_DPLL_CON(0)); - break; case RK3568_PLL_CPLL: return rk3328_get_pll(sc, RK3568_CRU_CPLL_CON(0)); - break; case RK3568_PLL_GPLL: return rk3328_get_pll(sc, RK3568_CRU_GPLL_CON(0)); - break; case RK3568_PLL_NPLL: return rk3328_get_pll(sc, RK3568_CRU_NPLL_CON(0)); - break; case RK3568_PLL_VPLL: return rk3328_get_pll(sc, RK3568_CRU_VPLL_CON(0)); - break; case RK3568_SCLK_GMAC0_DIV_50: idx = RK3568_SCLK_GMAC0; return rk3568_get_frequency(sc, &idx) / 50; @@ -3642,3 +3674,496 @@ rk3568_pmu_reset(void *cookie, uint32_t *cells, int on) printf("%s: 0x%08x\n", __func__, idx); } + +/* + * Rockchip RK3588 + */ + +const struct rkclock rk3588_clocks[] = { + { + RK3588_ACLK_BUS_ROOT, RK3588_CRU_CLKSEL_CON(38), + SEL(5, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART1_SRC, RK3588_CRU_CLKSEL_CON(41), + SEL(14, 14), DIV(13, 9), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART1, RK3588_CRU_CLKSEL_CON(43), + SEL(1, 0), 0, + { RK3588_CLK_UART1_SRC, RK3588_CLK_UART1_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART1, 0, 0, 0, + { RK3588_CLK_UART1 } + }, + { + RK3588_CLK_UART2_SRC, RK3588_CRU_CLKSEL_CON(43), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART2, RK3588_CRU_CLKSEL_CON(45), + SEL(1, 0), 0, + { RK3588_CLK_UART2_SRC, RK3588_CLK_UART2_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART2, 0, 0, 0, + { RK3588_CLK_UART2 } + }, + { + RK3588_CLK_UART3_SRC, RK3588_CRU_CLKSEL_CON(45), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART3, RK3588_CRU_CLKSEL_CON(47), + SEL(1, 0), 0, + { RK3588_CLK_UART3_SRC, RK3588_CLK_UART3_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART3, 0, 0, 0, + { RK3588_CLK_UART3 } + }, + { + RK3588_CLK_UART4_SRC, RK3588_CRU_CLKSEL_CON(47), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART4, RK3588_CRU_CLKSEL_CON(49), + SEL(1, 0), 0, + { RK3588_CLK_UART4_SRC, RK3588_CLK_UART4_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART4, 0, 0, 0, + { RK3588_CLK_UART4 } + }, + { + RK3588_CLK_UART5_SRC, RK3588_CRU_CLKSEL_CON(49), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART5, RK3588_CRU_CLKSEL_CON(51), + SEL(1, 0), 0, + { RK3588_CLK_UART5_SRC, RK3588_CLK_UART5_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART5, 0, 0, 0, + { RK3588_CLK_UART5 } + }, + { + RK3588_CLK_UART6_SRC, RK3588_CRU_CLKSEL_CON(51), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART6, RK3588_CRU_CLKSEL_CON(53), + SEL(1, 0), 0, + { RK3588_CLK_UART6_SRC, RK3588_CLK_UART6_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART6, 0, 0, 0, + { RK3588_CLK_UART6 } + }, + { + RK3588_CLK_UART7_SRC, RK3588_CRU_CLKSEL_CON(53), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART7, RK3588_CRU_CLKSEL_CON(55), + SEL(1, 0), 0, + { RK3588_CLK_UART7_SRC, RK3588_CLK_UART7_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART7, 0, 0, 0, + { RK3588_CLK_UART7 } + }, + { + RK3588_CLK_UART8_SRC, RK3588_CRU_CLKSEL_CON(55), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART8, RK3588_CRU_CLKSEL_CON(57), + SEL(1, 0), 0, + { RK3588_CLK_UART8_SRC, RK3588_CLK_UART8_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART8, 0, 0, 0, + { RK3588_CLK_UART8 } + }, + { + RK3588_CLK_UART9_SRC, RK3588_CRU_CLKSEL_CON(57), + SEL(7, 7), DIV(6, 2), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART9, RK3588_CRU_CLKSEL_CON(59), + SEL(1, 0), 0, + { RK3588_CLK_UART9_SRC, RK3588_CLK_UART9_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART9, 0, 0, 0, + { RK3588_CLK_UART9 } + }, + { + RK3588_ACLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165), + SEL(1, 0), 0, + { RK3588_CLK_700M_SRC, RK3588_CLK_400M_SRC, + RK3588_CLK_200M_SRC, RK3588_XIN24M } + }, + { + RK3588_ACLK_CENTER_LOW_ROOT, RK3588_CRU_CLKSEL_CON(165), + SEL(3, 2), 0, + { RK3588_CLK_500M_SRC, RK3588_CLK_250M_SRC, + RK3588_CLK_100M_SRC, RK3588_XIN24M } + }, + { + RK3588_HCLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165), + SEL(5, 4), 0, + { RK3588_CLK_400M_SRC, RK3588_CLK_200M_SRC, + RK3588_CLK_100M_SRC, RK3588_XIN24M } + }, + { + RK3588_CLK_50M_SRC, RK3588_CRU_CLKSEL_CON(0), + SEL(5, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_100M_SRC, RK3588_CRU_CLKSEL_CON(0), + SEL(11, 11), DIV(10, 6), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_150M_SRC, RK3588_CRU_CLKSEL_CON(1), + SEL(5, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_200M_SRC, RK3588_CRU_CLKSEL_CON(1), + SEL(11, 11), DIV(10, 6), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_250M_SRC, RK3588_CRU_CLKSEL_CON(2), + SEL(5, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_400M_SRC, RK3588_CRU_CLKSEL_CON(3), + SEL(11, 11), DIV(10, 6), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_500M_SRC, RK3588_CRU_CLKSEL_CON(4), + SEL(11, 11), DIV(10, 6), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_700M_SRC, RK3588_CRU_CLKSEL_CON(6), + SEL(5, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_SPLL } + }, + { + RK3588_ACLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8), + SEL(6, 5), 0, + { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL } + }, + { + RK3588_PCLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8), + SEL(8, 7), 0, + { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M } + }, + { + RK3588_ACLK_LOW_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8), + SEL(14, 14), DIV(13, 9), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL } + }, + { + RK3588_CLK_GPU_SRC, RK3588_CRU_CLKSEL_CON(158), + SEL(7, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL, + RK3588_PLL_NPLL, RK3588_PLL_SPLL } + }, + { + RK3588_CLK_GPU, 0, 0, 0, + { RK3588_CLK_GPU_SRC }, + SET_PARENT + }, + { + RK3588_ACLK_VOP_ROOT, RK3588_CRU_CLKSEL_CON(110), + SEL(7, 5), DIV(4, 0), + { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL, + RK3588_PLL_NPLL, RK3588_PLL_SPLL } + }, + { + RK3588_ACLK_VOP, 0, 0, 0, + { RK3588_ACLK_VOP_SUB_SRC }, + SET_PARENT + }, + { + RK3588_ACLK_VOP_SUB_SRC, RK3588_CRU_CLKSEL_CON(115), + SEL(9, 9), 0, + { RK3588_ACLK_VOP_ROOT, 0 /* RK3588_ACLK_VOP_DIV2_SRC */ }, + SET_PARENT + }, + { + RK3588_CLK_PMU1_50M_SRC, RK3588_PMUCRU_CLKSEL_CON(0), + 0, DIV(3, 0), + { RK3588_CLK_PMU1_400M_SRC } + }, + { + RK3588_CLK_PMU1_100M_SRC, RK3588_PMUCRU_CLKSEL_CON(0), + 0, DIV(6, 4), + { RK3588_CLK_PMU1_400M_SRC } + }, + { + RK3588_CLK_PMU1_200M_SRC, RK3588_PMUCRU_CLKSEL_CON(0), + 0, DIV(9, 7), + { RK3588_CLK_PMU1_400M_SRC } + }, + { + RK3588_CLK_PMU1_400M_SRC, RK3588_PMUCRU_CLKSEL_CON(1), + SEL(5, 5), DIV(4, 0), + { RK3588_CLK_400M_SRC, RK3588_XIN24M } + }, + { + RK3588_PCLK_PMU1_ROOT, RK3588_PMUCRU_CLKSEL_CON(1), + SEL(9, 8), 0, + { RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC, + RK3588_XIN24M } + }, + { + RK3588_PCLK_PMU0_ROOT, 0, 0, 0, + { RK3588_PCLK_PMU1_ROOT }, + SET_PARENT + }, + { + RK3588_HCLK_PMU_CM0_ROOT, RK3588_PMUCRU_CLKSEL_CON(1), + SEL(11, 10), 0, + { RK3588_CLK_PMU1_400M_SRC, RK3588_CLK_PMU1_200M_SRC, + RK3588_CLK_PMU1_100M_SRC, RK3588_XIN24M } + }, + { + RK3588_CLK_UART0_SRC, RK3588_PMUCRU_CLKSEL_CON(3), + 0, DIV(11, 7), + { RK3588_PLL_CPLL } + }, + { + RK3588_CLK_UART0, RK3588_PMUCRU_CLKSEL_CON(5), + SEL(1, 0), 0, + { RK3588_CLK_UART0_SRC, RK3588_CLK_UART0_FRAC, RK3588_XIN24M } + }, + { + RK3588_SCLK_UART0, 0, 0, 0, + { RK3588_CLK_UART0 } + }, + { + /* Sentinel */ + } +}; + +/* Certain test clocks are disabled. */ +const uint32_t rk3588_gates[78] = { + [2] = 0x00000050, + [22] = 0x00000200, + [25] = 0x00000200, + [29] = 0x00000004, + [66] = 0x00000004, +}; + +void +rk3588_init(struct rkclock_softc *sc) +{ + int i; + + /* The code below assumes all clocks are enabled. Check this!. */ + for (i = 0; i < nitems(rk3588_gates); i++) { + if (HREAD4(sc, RK3588_CRU_GATE_CON(i)) != rk3588_gates[i]) { + printf("CRU_GATE_CON%d: 0x%08x\n", i, + HREAD4(sc, RK3588_CRU_GATE_CON(i))); + } + } + + sc->sc_clocks = rk3588_clocks; +} + +int +rk3588_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) +{ + uint32_t p, m, s, k; + int mode_shift = -1; + + switch (base) { + case RK3588_CRU_AUPLL_CON(0): + mode_shift = 6; + break; + case RK3588_CRU_GPLL_CON(0): + mode_shift = 2; + break; + case RK3588_CRU_NPLL_CON(0): + mode_shift = 0; + break; + case RK3588_PHPTOPCRU_PPLL_CON(0): + mode_shift = 10; + break; + } + KASSERT(mode_shift != -1); + + /* + * It is not clear whether all combinations of the clock + * dividers result in a stable clock. Therefore this function + * only supports a limited set of PLL clock rates. + */ + switch (freq) { + case 1188000000U: + p = 2; m = 198; s = 1; k = 0; + break; + case 850000000U: + p = 3; m = 425; s = 2; k = 0; + break; + case 786432000U: + p = 2; m = 262; s = 2; k = 9437; + break; + case 100000000U: + p = 3; m = 400; s = 5; k = 0; + break; + default: + printf("%s: %u Hz\n", __func__, freq); + return -1; + } + + /* + * Select slow mode to guarantee a stable clock while we're + * adjusting the PLL. + */ + HWRITE4(sc, RK3588_CRU_MODE_CON, + (RK3588_CRU_MODE_MASK << 16 |RK3588_CRU_MODE_SLOW) << mode_shift); + + /* Power down PLL. */ + HWRITE4(sc, base + 0x0004, + RK3588_CRU_PLL_RESETB << 16 | RK3588_CRU_PLL_RESETB); + + /* Set PLL rate. */ + HWRITE4(sc, base + 0x0000, + RK3588_CRU_PLL_M_MASK << 16 | m << RK3588_CRU_PLL_M_SHIFT); + HWRITE4(sc, base + 0x0004, + RK3588_CRU_PLL_S_MASK << 16 | s << RK3588_CRU_PLL_S_SHIFT | + RK3588_CRU_PLL_P_MASK << 16 | p << RK3588_CRU_PLL_P_SHIFT); + HWRITE4(sc, base + 0x0008, + RK3588_CRU_PLL_K_MASK << 16 | k << RK3588_CRU_PLL_K_SHIFT); + + /* Power up PLL. */ + HWRITE4(sc, base + 0x0004, RK3588_CRU_PLL_RESETB << 16); + + /* Wait for PLL to stabilize. */ + while ((HREAD4(sc, base + 0x0018) & RK3588_CRU_PLL_PLL_LOCK) == 0) + delay(10); + + /* Switch back to normal mode. */ + HWRITE4(sc, RK3588_CRU_MODE_CON, + (RK3588_CRU_MODE_MASK << 16 | RK3588_CRU_MODE_NORMAL) << mode_shift); + + return 0; +} + +uint32_t +rk3588_get_pll(struct rkclock_softc *sc, bus_size_t base) +{ + uint64_t freq, frac; + uint32_t k, m, p, s; + uint32_t reg; + + reg = HREAD4(sc, base); + m = (reg & RK3588_CRU_PLL_M_MASK) >> RK3588_CRU_PLL_M_SHIFT; + reg = HREAD4(sc, base + 4); + p = (reg & RK3588_CRU_PLL_P_MASK) >> RK3588_CRU_PLL_P_SHIFT; + s = (reg & RK3588_CRU_PLL_S_MASK) >> RK3588_CRU_PLL_S_SHIFT; + reg = HREAD4(sc, base + 8); + k = (reg & RK3588_CRU_PLL_K_MASK) >> RK3588_CRU_PLL_K_SHIFT; + + freq = (24000000ULL * m) / p; + if (k) { + frac = ((24000000ULL * k) / (p * 65535)); + freq += frac; + } + + return freq >> s; +} + +uint32_t +rk3588_get_frequency(void *cookie, uint32_t *cells) +{ + struct rkclock_softc *sc = cookie; + uint32_t idx = cells[0]; + uint32_t freq; + + switch (idx) { + case RK3588_PLL_AUPLL: + return rk3588_get_pll(sc, RK3588_CRU_AUPLL_CON(0)); + case RK3588_PLL_CPLL: + return rk3588_get_pll(sc, RK3588_CRU_CPLL_CON(0)); + case RK3588_PLL_GPLL: + return rk3588_get_pll(sc, RK3588_CRU_GPLL_CON(0)); + case RK3588_PLL_NPLL: + return rk3588_get_pll(sc, RK3588_CRU_NPLL_CON(0)); + case RK3588_PLL_PPLL: + return rk3588_get_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0)); + case RK3588_PLL_SPLL: + return rkclock_external_frequency("spll"); + case RK3588_XIN24M: + return 24000000; + default: + break; + } + + freq = rkclock_get_frequency(sc, idx); + return freq; +} + +int +rk3588_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) +{ + struct rkclock_softc *sc = cookie; + uint32_t idx = cells[0]; + + switch (idx) { + case RK3588_PLL_AUPLL: + return rk3588_set_pll(sc, RK3588_CRU_AUPLL_CON(0), freq); + case RK3588_PLL_GPLL: + return rk3588_set_pll(sc, RK3588_CRU_GPLL_CON(0), freq); + case RK3588_PLL_NPLL: + return rk3588_set_pll(sc, RK3588_CRU_NPLL_CON(0), freq); + case RK3588_PLL_PPLL: + return rk3588_set_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0), freq); + default: + break; + } + + return rkclock_set_frequency(sc, idx, freq); +} + +void +rk3588_enable(void *cookie, uint32_t *cells, int on) +{ + uint32_t idx = cells[0]; + + /* All clocks are enabled upon hardware reset. */ + if (!on) { + printf("%s: 0x%08x\n", __func__, idx); + return; + } +} + +void +rk3588_reset(void *cookie, uint32_t *cells, int on) +{ + uint32_t idx = cells[0]; + + printf("%s: 0x%08x\n", __func__, idx); +} diff --git a/sys/dev/fdt/rkclock_clocks.h b/sys/dev/fdt/rkclock_clocks.h index 3df0603e7e5..ae012153442 100644 --- a/sys/dev/fdt/rkclock_clocks.h +++ b/sys/dev/fdt/rkclock_clocks.h @@ -357,3 +357,83 @@ #define RK3568_SCLK_UART0 11 #define RK3568_PCLK_I2C0 45 #define RK3568_CLK_PDPMU 49 + +/* + * RK3588 clocks. + */ +#define RK3588_PLL_AUPLL 4 +#define RK3588_PLL_CPLL 5 +#define RK3588_PLL_GPLL 6 +#define RK3588_PLL_NPLL 7 +#define RK3588_PLL_PPLL 8 + +#define RK3588_ACLK_BUS_ROOT 113 +#define RK3588_CLK_UART1_SRC 168 +#define RK3588_CLK_UART1_FRAC 169 +#define RK3588_CLK_UART1 170 +#define RK3588_SCLK_UART1 171 +#define RK3588_CLK_UART2_SRC 172 +#define RK3588_CLK_UART2_FRAC 173 +#define RK3588_CLK_UART2 174 +#define RK3588_SCLK_UART2 175 +#define RK3588_CLK_UART3_SRC 176 +#define RK3588_CLK_UART3_FRAC 177 +#define RK3588_CLK_UART3 178 +#define RK3588_SCLK_UART3 179 +#define RK3588_CLK_UART4_SRC 180 +#define RK3588_CLK_UART4_FRAC 181 +#define RK3588_CLK_UART4 182 +#define RK3588_SCLK_UART4 183 +#define RK3588_CLK_UART5_SRC 184 +#define RK3588_CLK_UART5_FRAC 185 +#define RK3588_CLK_UART5 186 +#define RK3588_SCLK_UART5 187 +#define RK3588_CLK_UART6_SRC 188 +#define RK3588_CLK_UART6_FRAC 189 +#define RK3588_CLK_UART6 190 +#define RK3588_SCLK_UART6 191 +#define RK3588_CLK_UART7_SRC 192 +#define RK3588_CLK_UART7_FRAC 193 +#define RK3588_CLK_UART7 194 +#define RK3588_SCLK_UART7 195 +#define RK3588_CLK_UART8_SRC 196 +#define RK3588_CLK_UART8_FRAC 197 +#define RK3588_CLK_UART8 198 +#define RK3588_SCLK_UART8 199 +#define RK3588_CLK_UART9_SRC 200 +#define RK3588_CLK_UART9_FRAC 201 +#define RK3588_CLK_UART9 202 +#define RK3588_SCLK_UART9 203 +#define RK3588_ACLK_CENTER_ROOT 204 +#define RK3588_ACLK_CENTER_LOW_ROOT 205 +#define RK3588_HCLK_CENTER_ROOT 206 +#define RK3588_CLK_50M_SRC 222 +#define RK3588_CLK_100M_SRC 223 +#define RK3588_CLK_150M_SRC 224 +#define RK3588_CLK_200M_SRC 225 +#define RK3588_CLK_250M_SRC 226 +#define RK3588_CLK_400M_SRC 229 +#define RK3588_CLK_500M_SRC 231 +#define RK3588_CLK_700M_SRC 234 +#define RK3588_ACLK_TOP_ROOT 256 +#define RK3588_PCLK_TOP_ROOT 257 +#define RK3588_ACLK_LOW_TOP_ROOT 258 +#define RK3588_CLK_GPU_SRC 261 +#define RK3588_CLK_GPU 262 +#define RK3588_ACLK_VOP_ROOT 600 +#define RK3588_ACLK_VOP 605 +#define RK3588_ACLK_VOP_SUB_SRC 619 +#define RK3588_CLK_PMU1_50M_SRC 639 +#define RK3588_CLK_PMU1_100M_SRC 640 +#define RK3588_CLK_PMU1_200M_SRC 641 +#define RK3588_CLK_PMU1_400M_SRC 643 +#define RK3588_PCLK_PMU1_ROOT 645 +#define RK3588_PCLK_PMU0_ROOT 646 +#define RK3588_HCLK_PMU_CM0_ROOT 647 +#define RK3588_CLK_UART0_SRC 664 +#define RK3588_CLK_UART0_FRAC 665 +#define RK3588_CLK_UART0 666 +#define RK3588_SCLK_UART0 667 + +#define RK3588_PLL_SPLL 1022 +#define RK3588_XIN24M 1023 -- 2.20.1