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

Reply via email to