> From: joshua stein <j...@jcs.org> > Date: Wed, 7 May 2025 21:52:21 -0500 > > Use RK3128_CRU_GLB_SOFTRST_1 to implement cpuresetfn > --- > sys/dev/fdt/rkclock.c | 590 ++++++++++++++++++++++++++++++++++- > sys/dev/fdt/rkclock_clocks.h | 52 +++ > 2 files changed, 634 insertions(+), 8 deletions(-)
This has all kinds of debug leftovers so I'm assuming this needs a bit more work before you'll ask for ok's? A few general notes: * Doesn't the cpuresetfn function provided dwdog(4) reset the board already? * You're adding a lot of #defines that aren't used. * Try to make the #defines for clock numbers in the device tree match a bit closer. So RK3128_SCLK_EMMC instead of RK3128_CLK_EMMC etc. * The get/set_peri() and get/set_mmc() functions really shouldn't be necessary if you provide the right information in the rk3128_clocks[] data structure. * There is no stupid remapping of reset IDs, so you should be able to implement rk3128_reset() in a very similar way as rk3288_reset(). > diff --git a/sys/dev/fdt/rkclock.c b/sys/dev/fdt/rkclock.c > index 35a02642e7f..a0e5659748c 100644 > --- a/sys/dev/fdt/rkclock.c > +++ b/sys/dev/fdt/rkclock.c > @@ -29,6 +29,62 @@ > #include <dev/ofw/ofw_misc.h> > #include <dev/ofw/fdt.h> > > +#define SEL(l, f) (((1 << (l - f + 1)) - 1) << f) > +#define DIV(l, f) SEL(l, f) > + > +/* RK3128 registers */ > +#define RK3128_CRU_APLL_CON(i) (0x0000 + (i) * 4) > +#define RK3128_CRU_DPLL_CON(i) (0x0010 + (i) * 4) > +#define RK3128_CRU_CPLL_CON(i) (0x0020 + (i) * 4) > +#define RK3128_CRU_GPLL_CON(i) (0x0030 + (i) * 4) > +#define RK3128_CRU_PLL_POSTDIV1_MASK SEL(14, 12) > +#define RK3128_CRU_PLL_POSTDIV1_SHIFT 12 > +#define RK3128_CRU_PLL_FBDIV_MASK SEL(11, 0) > +#define RK3128_CRU_PLL_FBDIV_SHIFT 0 > +#define RK3128_CRU_PLL_DSMPD_MASK (1 << 12) > +#define RK3128_CRU_PLL_DSMPD_SHIFT 12 > +#define RK3128_CRU_PLL_PLL_LOCK (1 << 10) > +#define RK3128_CRU_PLL_POSTDIV2_MASK SEL(8, 6) > +#define RK3128_CRU_PLL_POSTDIV2_SHIFT 6 > +#define RK3128_CRU_PLL_REFDIV_MASK SEL(5, 0) > +#define RK3128_CRU_PLL_REFDIV_SHIFT 0 > +#define RK3128_CRU_PLL_FRAC_MASK SEL(23, 0) > +#define RK3128_CRU_PLL_FRAC_SHIFT 0 > +#define RK3128_CRU_MODE_CON 0x0040 > +#define RK3128_CRU_MODE_PLL_WORK_MODE_MASK 0x3 > +#define RK3128_CRU_MODE_PLL_WORK_MODE_SLOW 0x0 > +#define RK3128_CRU_MODE_PLL_WORK_MODE_NORMAL 0x1 > +#define RK3128_CRU_CLKSEL_CON(i) (0x0044 + (i) * 4) > +#define RK3128_CRU_CPU_CLK_PLL_SEL_MASK SEL(14, 13) > +#define RK3128_CRU_CPU_CLK_PLL_SEL_SHIFT 13 > +#define RK3128_CRU_CORE_ACLK_DIV_CON_SHIFT 8 > +#define RK3128_CRU_CORE_ACLK_DIV_CON_MASK SEL(12, 8) > +#define RK3128_CRU_CORE_ACLK_DIV_CON_SHIFT 8 > +#define RK3128_CRU_CORE_CLK_PLL_SEL_MASK (1 << 7) > +#define RK3128_CRU_CORE_CLK_PLL_SEL_SHIFT 7 > +#define RK3128_CRU_CLK_CORE_DIV_CON_MASK SEL(4, 0) > +#define RK3128_CRU_CLK_CORE_DIV_CON_SHIFT 0 > +#define RK3128_CRU_PERI_PLL_SEL_MASK SEL(15, 14) > +#define RK3128_CRU_PERI_PLL_SEL_SHIFT 14 > +#define RK3128_CRU_PERI_PCLK_DIV_CON_MASK SEL(13, 12) > +#define RK3128_CRU_PERI_PCLK_DIV_CON_SHIFT 12 > +#define RK3128_CRU_CLKGATE_CON(i) (0x00d0 + (i) * 4) > +#define RK3128_CRU_GLB_SOFTRST_1 0x0100 > +#define RK3128_CRU_GLB_SRSTN_1 0xfdb9 > +#define RK3128_CRU_GLB_SOFTRST_2 0x0104 > +#define RK3128_CRU_GLB_SRSTN_2 0xeca8 > +#define RK3128_CRU_SOFTRST_CON(i) (0x0110 + (i) * 4) > +#define RK3128_EMMC_PLL_SHIFT 14 > +#define RK3128_EMMC_PLL_MASK (3 << RK3128_EMMC_PLL_SHIFT) > +#define RK3128_EMMC_DIV_SHIFT 8 > +#define RK3128_EMMC_DIV_MASK (0x3f << RK3128_EMMC_DIV_SHIFT) > +#define RK3128_MMC0_PLL_SHIFT 6 > +#define RK3128_MMC0_PLL_MASK (3 << RK3128_MMC0_PLL_SHIFT) > +#define RK3128_MMC0_DIV_SHIFT 0 > +#define RK3128_MMC0_DIV_MASK (0x3f << RK3128_MMC0_DIV_SHIFT) > +#define RK3128_MMC_SEL_GPLL 0x1 > +#define RK3128_MMC_SEL_24M 0x3 > + > /* RK3288 registers */ > #define RK3288_CRU_APLL_CON(i) (0x0000 + (i) * 4) > #define RK3288_CRU_CPLL_CON(i) (0x0020 + (i) * 4) > @@ -233,9 +289,6 @@ struct rkclock { > uint32_t flags; > }; > > -#define SEL(l, f) (((1 << (l - f + 1)) - 1) << f) > -#define DIV(l, f) SEL(l, f) > - > #define FIXED_PARENT (1 << 0) > #define SET_PARENT (1 << 1) > > @@ -261,9 +314,13 @@ struct rkclock_softc { > struct reset_device sc_rd; > }; > > +static struct rkclock_softc *the_rkclock = NULL; > + > int rkclock_match(struct device *, void *, void *); > void rkclock_attach(struct device *, struct device *, void *); > > +extern void (*cpuresetfn)(void); > + > const struct cfattach rkclock_ca = { > sizeof (struct rkclock_softc), rkclock_match, rkclock_attach > }; > @@ -272,6 +329,15 @@ struct cfdriver rkclock_cd = { > NULL, "rkclock", DV_DULL > }; > > +void rk3128_init(struct rkclock_softc *); > +uint32_t rk3128_get_frequency(void *, uint32_t *); > +int rk3128_set_frequency(void *, uint32_t *, uint32_t); > +int rk3128_set_mmc_frequency(void *, uint32_t, uint32_t, uint32_t); > +int rk3128_set_parent(void *, uint32_t *, uint32_t *); > +void rk3128_enable(void *, uint32_t *, int); > +void rk3128_reset(void *, uint32_t *, int); > +void rk3128_cpureset(void); > + > void rk3288_init(struct rkclock_softc *); > uint32_t rk3288_get_frequency(void *, uint32_t *); > int rk3288_set_frequency(void *, uint32_t *, uint32_t); > @@ -344,6 +410,12 @@ struct rkclock_compat { > }; > > const struct rkclock_compat rkclock_compat[] = { > + { > + "rockchip,rk3128-cru", NULL, 0, rk3128_init, > + rk3128_enable, rk3128_get_frequency, > + rk3128_set_frequency, rk3128_set_parent, > + rk3128_reset > + }, > { > "rockchip,rk3288-cru", NULL, 0, rk3288_init, > rk3288_enable, rk3288_get_frequency, > @@ -519,7 +591,7 @@ rkclock_div_con(struct rkclock_softc *sc, const struct > rkclock *clk, > > /* Derive maximum value from mask. */ > max_div_con = clk->div_mask >> (ffs(clk->div_mask) - 1); > - > + > parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx); > div = (parent_freq + freq - 1) / freq; > div_con = (div > 0 ? div - 1 : 0); > @@ -542,7 +614,7 @@ uint32_t > rkclock_get_frequency(struct rkclock_softc *sc, uint32_t idx) > { > const struct rkclock *clk; > - uint32_t reg, mux, div_con; > + uint32_t reg, mux, div_con, ret; > int shift; > > clk = rkclock_lookup(sc, idx); > @@ -568,7 +640,8 @@ rkclock_get_frequency(struct rkclock_softc *sc, uint32_t > idx) > return 0; > } > idx = clk->parents[mux]; > - return sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1); > + ret = sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1); > + return ret; > } > > int > @@ -582,8 +655,8 @@ rkclock_set_frequency(struct rkclock_softc *sc, uint32_t > idx, uint32_t freq) > > clk = rkclock_lookup(sc, idx); > if (clk == NULL) { > - printf("%s(%s, %u, %u)\n", __func__, sc->sc_dev.dv_xname, > - idx, freq); > + printf("%s(%s, %u, %u) failed lookup\n", __func__, > + sc->sc_dev.dv_xname, idx, freq); > return -1; > } > > @@ -696,6 +769,507 @@ rkclock_set_parent(struct rkclock_softc *sc, uint32_t > idx, uint32_t parent) > return 0; > } > > +/* > + * Rockchip RK3128 > + */ > + > +const struct rkclock rk3128_clocks[] = { > + { > + RK3128_CLK_SDMMC, RK3128_CRU_CLKSEL_CON(11), > + SEL(7, 6), DIV(5, 0), > + { RK3128_PLL_CPLL, RK3128_PLL_GPLL, RK3128_PLL_GPLL_DIV2, > + RK3128_XIN24M } > + }, > + { > + RK3128_CLK_EMMC, RK3128_CRU_CLKSEL_CON(12), > + SEL(15, 14), DIV(13, 8), > + { RK3128_PLL_CPLL, RK3128_PLL_GPLL, RK3128_PLL_GPLL_DIV2, > + RK3128_XIN24M } > + }, > + { > + RK3128_CLK_UART0, RK3128_CRU_CLKSEL_CON(13), > + SEL(12, 12), DIV(6, 0), > + { RK3128_PLL_CPLL, RK3128_PLL_GPLL, RK3128_PLL_GPLL_DIV2, > + RK3128_CLK_USB480M } > + }, > + /* RK3128_CLK_UART1 */ > + { > + RK3128_CLK_MAC, RK3128_CRU_CLKSEL_CON(5), > + SEL(7, 6), DIV(4, 0), > + { RK3128_PLL_CPLL, RK3128_PLL_GPLL, RK3128_PLL_GPLL_DIV2 } > + }, > + { > + RK3128_CLK_MAC_SRC, RK3128_CRU_CLKSEL_CON(5), > + SEL(7, 6), DIV(4, 0), > + { RK3128_PLL_CPLL, RK3128_PLL_GPLL, RK3128_PLL_GPLL_DIV2 } > + }, > + /* RK3128_PCLK_I2C0 */ > + /* RK3128_PCLK_I2C1 */ > + /* RK3128_PCLK_I2C2 */ > + /* RK3128_PCLK_I2C3 */ > + {} > +}; > + > +void > +rk3128_init(struct rkclock_softc *sc) > +{ > + int i; > + > + /* The code below assumes all clocks are enabled. Check this!. */ > + for (i = 0; i <= 10; i++) { > + if (HREAD4(sc, RK3128_CRU_CLKGATE_CON(i)) != 0x00000000) { > + printf("CRU_CLKGATE_CON%d: 0x%08x\n", i, > + HREAD4(sc, RK3128_CRU_CLKGATE_CON(i))); > + } > + } > + > + sc->sc_clocks = rk3128_clocks; > + the_rkclock = sc; > + cpuresetfn = rk3128_cpureset; > +} > + > +void > +rk3128_cpureset(void) > +{ > + if (the_rkclock == NULL) > + return; > + > + HWRITE4(the_rkclock, RK3128_CRU_GLB_SOFTRST_1, RK3128_CRU_GLB_SRSTN_1); > +} > + > +uint32_t > +rk3128_get_armclk(struct rkclock_softc *sc) > +{ > + uint32_t reg, mux, div_con, idx; > + > + reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0)); > + mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >> > + RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT; > + div_con = (reg & RK3308_CRU_CLK_CORE_DIV_CON_MASK) >> > + RK3308_CRU_CLK_CORE_DIV_CON_SHIFT; > + idx = mux ? RK3128_PLL_GPLL_DIV2 : RK3128_PLL_APLL; > + > + return rk3128_get_frequency(sc, &idx) / (div_con + 1); > +} > + > +uint32_t > +rk3128_get_pll(struct rkclock_softc *sc, bus_size_t base) > +{ > + uint32_t fbdiv, postdiv1, postdiv2, refdiv, con; > + > + con = HREAD4(sc, RK3128_CRU_MODE_CON); > + > + switch ((con >> (base >> 2)) & 0x1) { > + case 0: > + /* slow */ > + return 24000000; > + case 1: > + /* normal */ > + con = HREAD4(sc, base); > + postdiv1 = (con & RK3128_CRU_PLL_POSTDIV1_MASK) >> > + RK3128_CRU_PLL_POSTDIV1_SHIFT; > + fbdiv = (con & RK3128_CRU_PLL_FBDIV_MASK) >> > + RK3128_CRU_PLL_FBDIV_SHIFT; > + con = HREAD4(sc, base + 0x0004); > + postdiv2 = (con & RK3128_CRU_PLL_POSTDIV2_MASK) >> > + RK3128_CRU_PLL_POSTDIV2_SHIFT; > + refdiv = (con & RK3128_CRU_PLL_REFDIV_MASK) >> > + RK3128_CRU_PLL_REFDIV_SHIFT; > + return 24 * fbdiv / refdiv * postdiv1 * postdiv2 * 1000000; > + default: > + return 32768; > + } > +} > + > +int > +rk3128_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) > +{ > + uint32_t fbdiv, postdiv1, postdiv2, refdiv; > + int mode_shift; > + > + /* > + * 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. For now > + * this set covers all the CPU frequencies supported by the > + * Linux kernel. > + */ > + switch (freq) { > + case 1608000000U: > + case 1584000000U: > + case 1560000000U: > + case 1536000000U: > + case 1512000000U: > + case 1488000000U: > + case 1464000000U: > + case 1440000000U: > + case 1416000000U: > + case 1392000000U: > + case 1368000000U: > + case 1344000000U: > + case 1320000000U: > + case 1296000000U: > + case 1272000000U: > + case 1248000000U: > + case 1200000000U: > + case 1104000000U: > + postdiv1 = postdiv2 = refdiv = 1; > + break; > + case 1188000000U: > + refdiv = 2; postdiv1 = postdiv2 = 1; > + break; > + case 1100000000U: > + refdiv = 12; postdiv1 = postdiv2 = 1; > + break; > + case 1000000000U: > + refdiv = 6; postdiv1 = postdiv2 = 1; > + break; > + case 1008000000U: > + case 984000000U: > + case 960000000U: > + case 936000000U: > + case 912000000U: > + case 888000000U: > + case 864000000U: > + case 840000000U: > + case 816000000U: > + case 696000000U: > + case 624000000U: > + postdiv1 = 2; postdiv2 = refdiv = 1; > + break; > + case 900000000U: > + refdiv = 4; postdiv1 = 2; postdiv2 = 1; > + break; > + case 800000000U: > + case 700000000U: > + case 500000000U: > + refdiv = 6; postdiv1 = 2; postdiv2 = 1; > + break; > + case 600000000U: > + case 504000000U: > + postdiv1 = 3; postdiv2 = refdiv = 1; > + break; > + case 594000000U: > + refdiv = 2; postdiv1 = 2; postdiv2 = 1; > + break; > + case 408000000U: > + case 312000000U: > + postdiv1 = postdiv2 = 2; refdiv = 1; > + break; > + case 216000000U: > + postdiv1 = 4; postdiv2 = 2; refdiv = 1; > + break; > + case 96000000U: > + postdiv1 = postdiv2 = 4; refdiv = 1; > + break; > + default: > + printf("%s: %u Hz\n", __func__, freq); > + return -1; > + } > + > + /* Calculate feedback divider. */ > + fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000; > + > + printf("%s: setting 0x%lx pll to freq:%d postdiv1:%d fbdiv:%d dsmpd:%d > postdiv2:%d refdiv:%d\n", > + __func__, base, freq, postdiv1, fbdiv, 0 /* dsmpd */, postdiv2, > refdiv); > + > + /* > + * Select slow mode to guarantee a stable clock while we're > + * adjusting the PLL. > + */ > + mode_shift = base >> 2; > + HWRITE4(sc, RK3128_CRU_MODE_CON, > + (RK3128_CRU_MODE_PLL_WORK_MODE_MASK << 16 | > + RK3128_CRU_MODE_PLL_WORK_MODE_SLOW) << mode_shift); > + > + /* Set PLL rate. */ > + HWRITE4(sc, base, > + RK3128_CRU_PLL_POSTDIV1_MASK << 16 | > + postdiv1 << RK3128_CRU_PLL_POSTDIV1_SHIFT | > + RK3128_CRU_PLL_FBDIV_MASK << 16 | > + fbdiv << RK3128_CRU_PLL_FBDIV_SHIFT); > + HWRITE4(sc, base + 0x0004, > + RK3128_CRU_PLL_DSMPD_MASK << 16 | RK3128_CRU_PLL_DSMPD_MASK | > + RK3128_CRU_PLL_POSTDIV2_MASK << 16 | > + postdiv2 << RK3128_CRU_PLL_POSTDIV2_SHIFT | > + RK3128_CRU_PLL_REFDIV_MASK << 16 | > + refdiv << RK3128_CRU_PLL_REFDIV_SHIFT); > + > + /* Wait for PLL to stabilize. */ > + while ((HREAD4(sc, base + 0x0004) & RK3128_CRU_PLL_PLL_LOCK) == 0) > + delay(10); > + > + /* Switch back to normal mode. */ > + HWRITE4(sc, RK3128_CRU_MODE_CON, > + (RK3128_CRU_MODE_PLL_WORK_MODE_MASK << 16 | > + RK3128_CRU_MODE_PLL_WORK_MODE_NORMAL) << mode_shift); > + > + return 0; > +} > + > +uint32_t > +rk3128_get_mmc(struct rkclock_softc *sc, uint32_t idx) > +{ > + uint32_t reg, mux, div, gclk; > + > + switch (idx) { > + case RK3128_CLK_EMMC: > + reg = HREAD4(sc, RK3128_CRU_CLKSEL_CON(12)); > + mux = (reg & RK3128_EMMC_PLL_MASK) >> RK3128_EMMC_PLL_SHIFT; > + div = (reg & RK3128_EMMC_DIV_MASK) >> RK3128_EMMC_DIV_SHIFT; > + break; > + case RK3128_CLK_SDMMC: > + reg = HREAD4(sc, RK3128_CRU_CLKSEL_CON(11)); > + mux = (reg & RK3128_MMC0_PLL_MASK) >> RK3128_MMC0_PLL_SHIFT; > + div = (reg & RK3128_MMC0_DIV_MASK) >> RK3128_MMC0_DIV_SHIFT; > + break; > + default: > + return 0; > + } > + > + if (mux == RK3128_MMC_SEL_24M) > + return 24000000 / (div + 1); > + else { > + gclk = RK3128_PLL_GPLL; > + return rk3128_get_frequency(sc, &gclk) / (div + 1); > + } > +} > + > +int > +rk3128_set_mmc(void *cookie, uint32_t gclk_rate, uint32_t idx, uint32_t freq) > +{ > + struct rkclock_softc *sc = cookie; > + uint32_t src_clk_div; > + int mux; > + > + src_clk_div = ((gclk_rate / 2) + freq - 1) / freq; > + if (src_clk_div > 128) { > + src_clk_div = ((24000000 / 2) + freq - 1) / freq; > + mux = RK3128_MMC_SEL_24M; > + } else { > + mux = RK3128_MMC_SEL_GPLL; > + } > + > + switch (idx) { > + case RK3128_CLK_EMMC: > + HWRITE4(sc, RK3128_CRU_CLKSEL_CON(12), > + (RK3128_EMMC_PLL_MASK | RK3128_EMMC_DIV_MASK | > + mux << RK3128_EMMC_PLL_SHIFT | > + (src_clk_div - 1) << RK3128_EMMC_DIV_SHIFT) << 16 | > + mux << RK3128_EMMC_PLL_SHIFT | > + (src_clk_div - 1) << RK3128_EMMC_DIV_SHIFT); > + break; > + case RK3128_CLK_SDMMC: > + HWRITE4(sc, RK3128_CRU_CLKSEL_CON(11), > + (RK3128_MMC0_PLL_MASK | RK3128_MMC0_DIV_MASK | > + mux << RK3128_MMC0_PLL_SHIFT | > + (src_clk_div - 1) << RK3128_MMC0_DIV_SHIFT) << 16 | > + mux << RK3128_MMC0_PLL_SHIFT | > + (src_clk_div - 1) << RK3128_MMC0_DIV_SHIFT); > + break; > + default: > + return -1; > + } > + > + return 0; > +} > + > +uint32_t > +rk3128_get_peri(struct rkclock_softc *sc, uint32_t idx) > +{ > + uint32_t reg, div; > + > + switch (idx) { > + case RK3128_PCLK_I2C0: > + case RK3128_PCLK_I2C1: > + case RK3128_PCLK_I2C2: > + case RK3128_PCLK_I2C3: > + case RK3128_PCLK_PWM: > + reg = HREAD4(sc, RK3128_CRU_CLKSEL_CON(10)); > + div = (reg & RK3128_CRU_PERI_PCLK_DIV_CON_MASK) >> > + RK3128_CRU_PERI_PCLK_DIV_CON_SHIFT; > + break; > + default: > + return 0; > + } > + > + /* PERI_ACLK_HZ */ > + return 148500000 / (div + 1); > +} > + > +int > +rk3128_set_peri(struct rkclock_softc *sc, uint32_t idx, uint32_t freq) > +{ > + uint32_t src_clk_div; > + > + /* PERI_ACLK_HZ */ > + src_clk_div = 148500000 / freq; > + > + switch (idx) { > + case RK3128_PCLK_I2C0: > + case RK3128_PCLK_I2C1: > + case RK3128_PCLK_I2C2: > + case RK3128_PCLK_I2C3: > + case RK3128_PCLK_PWM: > + HWRITE4(sc, RK3128_CRU_CLKSEL_CON(10), > + ((src_clk_div - 1) << > + RK3128_CRU_PERI_PCLK_DIV_CON_SHIFT) << 16 | > + (src_clk_div - 1) << RK3128_CRU_PERI_PCLK_DIV_CON_SHIFT); > + break; > + default: > + return -1; > + } > + > + return 0; > +} > + > +uint32_t > +rk3128_get_frequency(void *cookie, uint32_t *cells) > +{ > + struct rkclock_softc *sc = cookie; > + uint32_t idx = cells[0]; > + > + switch (idx) { > + case RK3128_PLL_APLL: > + return rk3128_get_pll(sc, RK3128_CRU_APLL_CON(0)); > + case RK3128_PLL_DPLL: > + return rk3128_get_pll(sc, RK3128_CRU_DPLL_CON(0)); > + case RK3128_PLL_CPLL: > + return rk3128_get_pll(sc, RK3128_CRU_CPLL_CON(0)); > + case RK3128_PLL_GPLL: > + return rk3128_get_pll(sc, RK3128_CRU_GPLL_CON(0)); > + case RK3128_PLL_GPLL_DIV2: > + return rk3128_get_pll(sc, RK3128_CRU_GPLL_CON(0)) / 2; > + case RK3128_PLL_GPLL_DIV3: > + return rk3128_get_pll(sc, RK3128_CRU_GPLL_CON(0)) / 3; > + case RK3128_ARMCLK: > + return rk3128_get_armclk(sc); > + case RK3128_CLK_EMMC: > + case RK3128_CLK_SDMMC: > + return rk3128_get_mmc(sc, idx); > + case RK3128_PCLK_I2C0: > + case RK3128_PCLK_I2C1: > + case RK3128_PCLK_I2C2: > + case RK3128_PCLK_I2C3: > + case RK3128_PCLK_PWM: > + return rk3128_get_peri(sc, idx); > + default: > + return rkclock_get_frequency(sc, idx); > + } > +} > + > +int > +rk3128_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) > +{ > + struct rkclock_softc *sc = cookie; > + uint32_t idx = cells[0], gclk, gclk_rate; > + > + if (idx < 64) > + return 0; > + > + gclk = RK3128_PLL_GPLL; > + gclk_rate = rk3128_get_frequency(sc, &gclk); > + > + switch (idx) { > + case RK3128_CLK_EMMC: > + case RK3128_CLK_SDMMC: > + return rk3128_set_mmc(sc, gclk_rate, idx, freq); > + case RK3128_PCLK_I2C0: > + case RK3128_PCLK_I2C1: > + case RK3128_PCLK_I2C2: > + case RK3128_PCLK_I2C3: > + return rk3128_set_peri(sc, idx, freq); > + case RK3128_CLK_MAC_SRC: > + return rkclock_set_frequency(sc, idx, freq); > + default: > + printf("%s: TODO implement %d -> %d\n", __func__, idx, freq); > + break; > + } > + > + return -1; > +} > + > +void > +rk3128_enable(void *cookie, uint32_t *cells, int on) > +{ > + uint32_t idx = cells[0]; > + > + switch (idx) { > + case RK3128_CLK_SDMMC: > + case RK3128_CLK_EMMC: > + case RK3128_CLK_UART0: > + case RK3128_CLK_UART1: > + case RK3128_CLK_UART2: > + case RK3128_CLK_MAC: > + case RK3128_CLK_MAC_RX: > + case RK3128_CLK_MAC_TX: > + case RK3128_CLK_SDMMC_DRV: > + case RK3128_CLK_EMMC_DRV: > + case RK3128_CLK_SDMMC_SAMPLE: > + case RK3128_CLK_EMMC_SAMPLE: > + case RK3128_CLK_OTGPHY0: > + case RK3128_CLK_OTGPHY1: > + case RK3128_ACLK_GMAC: > + case RK3128_PCLK_I2C0: > + case RK3128_PCLK_I2C1: > + case RK3128_PCLK_I2C2: > + case RK3128_PCLK_I2C3: > + case RK3128_PCLK_TSADC: > + case RK3128_PCLK_GMAC: > + case RK3128_HCLK_SDMMC: > + case RK3128_HCLK_EMMC: > + case RK3128_HCLK_HOST2: > + /* Enabled by default. */ > + break; > + default: > + printf("%s: 0x%08x\n", __func__, idx); > + break; > + } > +} > + > +int > +rk3128_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) > +{ > + struct rkclock_softc *sc = cookie; > + > + printf("%s: %d -> %d\n", __func__, cells[0], pcells[1]); > + > + return rkclock_set_parent(sc, cells[0], pcells[1]); > +} > + > +void > +rk3128_reset(void *cookie, uint32_t *cells, int on) > +{ > + struct rkclock_softc *sc = cookie; > + uint32_t idx = cells[0]; > + uint32_t bit, mask, reg; > + > + switch (idx) { > + case RK3128_SRST_I2C0: > + reg = RK3128_CRU_SOFTRST_CON(2); > + bit = 11; > + break; > + case RK3128_SRST_GMAC: > + reg = RK3128_CRU_SOFTRST_CON(3); > + bit = 8; > + break; > + case RK3128_SRST_SDMMC: > + reg = RK3128_CRU_SOFTRST_CON(5); > + bit = 1; > + break; > + case RK3128_SRST_EMMC: > + reg = RK3128_CRU_SOFTRST_CON(5); > + bit = 3; > + break; > + default: > + printf("%s: %d\n", __func__, idx); > + return; > + } > + > + mask = (1 << bit); > + HWRITE4(sc, reg, mask << 16 | (on ? mask : 0)); > +} > + > /* > * Rockchip RK3288 > */ > diff --git a/sys/dev/fdt/rkclock_clocks.h b/sys/dev/fdt/rkclock_clocks.h > index 66a45f690c5..47339ccf247 100644 > --- a/sys/dev/fdt/rkclock_clocks.h > +++ b/sys/dev/fdt/rkclock_clocks.h > @@ -1,5 +1,57 @@ > /* Public Domain */ > > +/* > + * RK3128 clocks. > + */ > + > +#define RK3128_PLL_APLL 1 > +#define RK3128_PLL_DPLL 2 > +#define RK3128_PLL_CPLL 3 > +#define RK3128_PLL_GPLL 4 > +#define RK3128_ARMCLK 5 > +#define RK3128_PLL_GPLL_DIV2 6 > +#define RK3128_PLL_GPLL_DIV3 7 > + > +#define RK3128_CLK_SDMMC 68 > +#define RK3128_CLK_EMMC 71 > +#define RK3128_CLK_UART0 77 > +#define RK3128_CLK_UART1 78 > +#define RK3128_CLK_UART2 79 > +#define RK3128_CLK_SDMMC_DRV 114 > +#define RK3128_CLK_EMMC_DRV 117 > +#define RK3128_CLK_SDMMC_SAMPLE 118 > +#define RK3128_CLK_EMMC_SAMPLE 121 > +#define RK3128_CLK_MAC_SRC 124 > +#define RK3128_CLK_MAC 126 > +#define RK3128_CLK_MAC_RX 129 > +#define RK3128_CLK_MAC_TX 130 > +#define RK3128_CLK_OTGPHY0 142 > +#define RK3128_CLK_OTGPHY1 143 > +#define RK3128_CLK_USB480M 154 > + > +#define RK3128_ACLK_GMAC 212 > + > +#define RK3128_PCLK_I2C0 332 > +#define RK3128_PCLK_I2C1 333 > +#define RK3128_PCLK_I2C2 334 > +#define RK3128_PCLK_I2C3 335 > +#define RK3128_PCLK_TSADC 344 > +#define RK3128_PCLK_PWM 350 > +#define RK3128_PCLK_GMAC 367 > + > +#define RK3128_HCLK_SDMMC 456 > +#define RK3128_HCLK_EMMC 459 > +#define RK3128_HCLK_HOST2 473 > + > +#define RK3128_SRST_I2C0 43 > +#define RK3128_SRST_GMAC 56 > +#define RK3128_SRST_SDMMC 81 > +#define RK3128_SRST_SDIO 82 > +#define RK3128_SRST_EMMC 83 > +#define RK3128_SRST_SARADC 87 > + > +#define RK3128_XIN24M 1023 > + > /* > * RK3288 clocks. > */ > -- > 2.47.1 > >