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(-)
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