rockchip: clk: Add clk driver for rk3308
authorFinley Xiao <finley.xiao@rock-chips.com>
Thu, 14 Nov 2019 03:21:13 +0000 (11:21 +0800)
committerKever Yang <kever.yang@rock-chips.com>
Sun, 17 Nov 2019 09:22:53 +0000 (17:22 +0800)
Add clk controller driver for RK3308 SOC.

This patch depends on Elaine's pll patch[0].

[0]http://patchwork.ozlabs.org/patch/1183718/

Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
drivers/clk/rockchip/Makefile
drivers/clk/rockchip/clk_rk3308.c [new file with mode: 0644]
include/dt-bindings/clock/rk3308-cru.h [new file with mode: 0644]

index 8035b26136f566319c540a7890ffab4dad6d6025..4cfcf83309298b416a23bd8f95bf981f1e4c2490 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_ROCKCHIP_RK3128) += clk_rk3128.o
 obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK322X) += clk_rk322x.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
+obj-$(CONFIG_ROCKCHIP_RK3308) += clk_rk3308.o
 obj-$(CONFIG_ROCKCHIP_RK3328) += clk_rk3328.o
 obj-$(CONFIG_ROCKCHIP_RK3368) += clk_rk3368.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
diff --git a/drivers/clk/rockchip/clk_rk3308.c b/drivers/clk/rockchip/clk_rk3308.c
new file mode 100644 (file)
index 0000000..f212c5f
--- /dev/null
@@ -0,0 +1,1072 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2017-2019 Rockchip Electronics Co., Ltd
+ */
+#include <common.h>
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <div64.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/cru_rk3308.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rk3308-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+       VCO_MAX_HZ      = 3200U * 1000000,
+       VCO_MIN_HZ      = 800 * 1000000,
+       OUTPUT_MAX_HZ   = 3200U * 1000000,
+       OUTPUT_MIN_HZ   = 24 * 1000000,
+};
+
+#define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
+
+#define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)         \
+{                                                               \
+       .rate   = _rate##U,                                     \
+       .aclk_div = _aclk_div,                                  \
+       .pclk_div = _pclk_div,                                  \
+}
+
+static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
+       /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+       RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+       RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+       RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0),
+};
+
+static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = {
+       RK3308_CPUCLK_RATE(1200000000, 1, 5),
+       RK3308_CPUCLK_RATE(1008000000, 1, 5),
+       RK3308_CPUCLK_RATE(816000000, 1, 3),
+       RK3308_CPUCLK_RATE(600000000, 1, 3),
+       RK3308_CPUCLK_RATE(408000000, 1, 1),
+};
+
+static struct rockchip_pll_clock rk3308_pll_clks[] = {
+       [APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0),
+                    RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates),
+       [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8),
+                    RK3308_MODE_CON, 2, 10, 0, NULL),
+       [VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16),
+                     RK3308_MODE_CON, 4, 10, 0, NULL),
+       [VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24),
+                     RK3308_MODE_CON, 6, 10, 0, NULL),
+};
+
+static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz)
+{
+       struct rk3308_cru *cru = priv->cru;
+       const struct rockchip_cpu_rate_table *rate;
+       ulong old_rate;
+
+       rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz);
+       if (!rate) {
+               printf("%s unsupport rate\n", __func__);
+               return -EINVAL;
+       }
+
+       /*
+        * select apll as cpu/core clock pll source and
+        * set up dependent divisors for PERI and ACLK clocks.
+        * core hz : apll = 1:1
+        */
+       old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
+                                        priv->cru, APLL);
+       if (old_rate > hz) {
+               if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
+                                         priv->cru, APLL, hz))
+                       return -EINVAL;
+               rk_clrsetreg(&cru->clksel_con[0],
+                            CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+                            CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+                            rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+                            rate->pclk_div << CORE_DBG_DIV_SHIFT |
+                            CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+                            0 << CORE_DIV_CON_SHIFT);
+       } else if (old_rate < hz) {
+               rk_clrsetreg(&cru->clksel_con[0],
+                            CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+                            CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+                            rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+                            rate->pclk_div << CORE_DBG_DIV_SHIFT |
+                            CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+                            0 << CORE_DIV_CON_SHIFT);
+               if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
+                                         priv->cru, APLL, hz))
+                       return -EINVAL;
+       }
+
+       return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL);
+}
+
+static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv)
+{
+       if (!priv->dpll_hz)
+               priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+                                                     priv->cru, DPLL);
+       if (!priv->vpll0_hz)
+               priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
+                                                      priv->cru, VPLL0);
+       if (!priv->vpll1_hz)
+               priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
+                                                      priv->cru, VPLL1);
+}
+
+static ulong rk3308_i2c_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, con_id;
+
+       switch (clk->id) {
+       case SCLK_I2C0:
+               con_id = 25;
+               break;
+       case SCLK_I2C1:
+               con_id = 26;
+               break;
+       case SCLK_I2C2:
+               con_id = 27;
+               break;
+       case SCLK_I2C3:
+               con_id = 28;
+               break;
+       default:
+               printf("do not support this i2c bus\n");
+               return -EINVAL;
+       }
+
+       con = readl(&cru->clksel_con[con_id]);
+       div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+
+       return DIV_TO_RATE(priv->dpll_hz, div);
+}
+
+static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 src_clk_div, con_id;
+
+       src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+       assert(src_clk_div - 1 <= 127);
+
+       switch (clk->id) {
+       case SCLK_I2C0:
+               con_id = 25;
+               break;
+       case SCLK_I2C1:
+               con_id = 26;
+               break;
+       case SCLK_I2C2:
+               con_id = 27;
+               break;
+       case SCLK_I2C3:
+               con_id = 28;
+               break;
+       default:
+               printf("do not support this i2c bus\n");
+               return -EINVAL;
+       }
+       rk_clrsetreg(&cru->clksel_con[con_id],
+                    CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
+                    CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
+                    (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
+
+       return rk3308_i2c_get_clk(clk);
+}
+
+static ulong rk3308_mac_set_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 con = readl(&cru->clksel_con[43]);
+       ulong pll_rate;
+       u8 div;
+
+       if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0)
+               pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
+                                                priv->cru, VPLL0);
+       else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1)
+               pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
+                                                priv->cru, VPLL1);
+       else
+               pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+                                                priv->cru, DPLL);
+
+       /*default set 50MHZ for gmac*/
+       if (!hz)
+               hz = 50000000;
+
+       div = DIV_ROUND_UP(pll_rate, hz) - 1;
+       assert(div < 32);
+       rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK,
+                    div << MAC_DIV_SHIFT);
+
+       return DIV_TO_RATE(pll_rate, div);
+}
+
+static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+
+       if (hz != 2500000 && hz != 25000000) {
+               debug("Unsupported mac speed:%d\n", hz);
+               return -EINVAL;
+       }
+
+       rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK,
+                    ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT);
+
+       return 0;
+}
+
+static ulong rk3308_mmc_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, con_id;
+
+       switch (clk->id) {
+       case HCLK_SDMMC:
+       case SCLK_SDMMC:
+               con_id = 39;
+               break;
+       case HCLK_EMMC:
+       case SCLK_EMMC:
+       case SCLK_EMMC_SAMPLE:
+               con_id = 41;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       con = readl(&cru->clksel_con[con_id]);
+       div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
+
+       if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
+           == EMMC_SEL_24M)
+               return DIV_TO_RATE(OSC_HZ, div) / 2;
+       else
+               return DIV_TO_RATE(priv->vpll0_hz, div) / 2;
+}
+
+static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+       u32 con_id;
+
+       switch (clk->id) {
+       case HCLK_SDMMC:
+       case SCLK_SDMMC:
+               con_id = 39;
+               break;
+       case HCLK_EMMC:
+       case SCLK_EMMC:
+               con_id = 41;
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* Select clk_sdmmc/emmc source from VPLL0 by default */
+       /* mmc clock defaulg div 2 internal, need provide double in cru */
+       src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate);
+
+       if (src_clk_div > 127) {
+               /* use 24MHz source for 400KHz clock */
+               src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+               rk_clrsetreg(&cru->clksel_con[con_id],
+                            EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
+                            EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
+                            EMMC_SEL_24M << EMMC_PLL_SHIFT |
+                            (src_clk_div - 1) << EMMC_DIV_SHIFT);
+       } else {
+               rk_clrsetreg(&cru->clksel_con[con_id],
+                            EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
+                            EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
+                            EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
+                            (src_clk_div - 1) << EMMC_DIV_SHIFT);
+       }
+
+       return rk3308_mmc_get_clk(clk);
+}
+
+static ulong rk3308_saradc_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con;
+
+       con = readl(&cru->clksel_con[34]);
+       div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+       assert(src_clk_div - 1 <= 2047);
+
+       rk_clrsetreg(&cru->clksel_con[34],
+                    CLK_SARADC_DIV_CON_MASK,
+                    (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rk3308_saradc_get_clk(clk);
+}
+
+static ulong rk3308_tsadc_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con;
+
+       con = readl(&cru->clksel_con[33]);
+       div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+       return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+       assert(src_clk_div - 1 <= 2047);
+
+       rk_clrsetreg(&cru->clksel_con[33],
+                    CLK_SARADC_DIV_CON_MASK,
+                    (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+       return rk3308_tsadc_get_clk(clk);
+}
+
+static ulong rk3308_spi_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, con_id;
+
+       switch (clk->id) {
+       case SCLK_SPI0:
+               con_id = 30;
+               break;
+       case SCLK_SPI1:
+               con_id = 31;
+               break;
+       case SCLK_SPI2:
+               con_id = 32;
+               break;
+       default:
+               printf("do not support this spi bus\n");
+               return -EINVAL;
+       }
+
+       con = readl(&cru->clksel_con[con_id]);
+       div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
+
+       return DIV_TO_RATE(priv->dpll_hz, div);
+}
+
+static ulong rk3308_spi_set_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 src_clk_div, con_id;
+
+       src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+       assert(src_clk_div - 1 <= 127);
+
+       switch (clk->id) {
+       case SCLK_SPI0:
+               con_id = 30;
+               break;
+       case SCLK_SPI1:
+               con_id = 31;
+               break;
+       case SCLK_SPI2:
+               con_id = 32;
+               break;
+       default:
+               printf("do not support this spi bus\n");
+               return -EINVAL;
+       }
+
+       rk_clrsetreg(&cru->clksel_con[con_id],
+                    CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
+                    CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
+                    (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
+
+       return rk3308_spi_get_clk(clk);
+}
+
+static ulong rk3308_pwm_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con;
+
+       con = readl(&cru->clksel_con[29]);
+       div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
+
+       return DIV_TO_RATE(priv->dpll_hz, div);
+}
+
+static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+       assert(src_clk_div - 1 <= 127);
+
+       rk_clrsetreg(&cru->clksel_con[29],
+                    CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
+                    CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
+                    (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
+
+       return rk3308_pwm_get_clk(clk);
+}
+
+static ulong rk3308_vop_get_clk(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, pll_sel, vol_sel, con, parent;
+
+       con = readl(&cru->clksel_con[8]);
+       vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
+       pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
+       div = con & DCLK_VOP_DIV_MASK;
+
+       if (vol_sel == DCLK_VOP_SEL_24M) {
+               parent = OSC_HZ;
+       } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
+               switch (pll_sel) {
+               case DCLK_VOP_PLL_SEL_DPLL:
+                       parent = priv->dpll_hz;
+                       break;
+               case DCLK_VOP_PLL_SEL_VPLL0:
+                       parent = priv->vpll0_hz;
+                       break;
+               case DCLK_VOP_PLL_SEL_VPLL1:
+                       parent = priv->vpll0_hz;
+                       break;
+               default:
+                       printf("do not support this vop pll sel\n");
+                       return -EINVAL;
+               }
+       } else {
+               printf("do not support this vop sel\n");
+               return -EINVAL;
+       }
+
+       return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       struct rk3308_cru *cru = priv->cru;
+       ulong pll_rate, now, best_rate = 0;
+       u32 i, div, best_div = 0, best_sel = 0;
+
+       for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
+               switch (i) {
+               case DCLK_VOP_PLL_SEL_DPLL:
+                       pll_rate = priv->dpll_hz;
+                       break;
+               case DCLK_VOP_PLL_SEL_VPLL0:
+                       pll_rate = priv->vpll0_hz;
+                       break;
+               case DCLK_VOP_PLL_SEL_VPLL1:
+                       pll_rate = priv->vpll1_hz;
+                       break;
+               default:
+                       printf("do not support this vop pll sel\n");
+                       return -EINVAL;
+               }
+
+               div = DIV_ROUND_UP(pll_rate, hz);
+               if (div > 255)
+                       continue;
+               now = pll_rate / div;
+               if (abs(hz - now) < abs(hz - best_rate)) {
+                       best_rate = now;
+                       best_div = div;
+                       best_sel = i;
+               }
+               debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
+                     pll_rate, best_rate, best_div, best_sel);
+       }
+
+       if (best_rate != hz && hz == OSC_HZ) {
+               rk_clrsetreg(&cru->clksel_con[8],
+                            DCLK_VOP_SEL_MASK,
+                            DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
+       } else if (best_rate) {
+               rk_clrsetreg(&cru->clksel_con[8],
+                            DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
+                            DCLK_VOP_DIV_MASK,
+                            DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
+                            best_sel << DCLK_VOP_PLL_SEL_SHIFT |
+                            (best_div - 1) << DCLK_VOP_DIV_SHIFT);
+       } else {
+               printf("do not support this vop freq\n");
+               return -EINVAL;
+       }
+
+       return rk3308_vop_get_clk(clk);
+}
+
+static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, parent = priv->dpll_hz;
+
+       switch (clk_id) {
+       case ACLK_BUS:
+               con = readl(&cru->clksel_con[5]);
+               div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
+               break;
+       case HCLK_BUS:
+               con = readl(&cru->clksel_con[6]);
+               div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
+               break;
+       case PCLK_BUS:
+       case PCLK_WDT:
+               con = readl(&cru->clksel_con[6]);
+               div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+                               ulong hz)
+{
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+       assert(src_clk_div - 1 <= 31);
+
+       /*
+        * select dpll as pd_bus bus clock source and
+        * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+        */
+       switch (clk_id) {
+       case ACLK_BUS:
+               rk_clrsetreg(&cru->clksel_con[5],
+                            BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
+                            BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
+               break;
+       case HCLK_BUS:
+               rk_clrsetreg(&cru->clksel_con[6],
+                            BUS_HCLK_DIV_MASK,
+                            (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
+               break;
+       case PCLK_BUS:
+               rk_clrsetreg(&cru->clksel_con[6],
+                            BUS_PCLK_DIV_MASK,
+                            (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
+               break;
+       default:
+               printf("do not support this bus freq\n");
+               return -EINVAL;
+       }
+
+       return rk3308_bus_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, parent = priv->dpll_hz;
+
+       switch (clk_id) {
+       case ACLK_PERI:
+               con = readl(&cru->clksel_con[36]);
+               div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
+               break;
+       case HCLK_PERI:
+               con = readl(&cru->clksel_con[37]);
+               div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
+               break;
+       case PCLK_PERI:
+               con = readl(&cru->clksel_con[37]);
+               div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT;
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+                                ulong hz)
+{
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
+       assert(src_clk_div - 1 <= 31);
+
+       /*
+        * select dpll as pd_peri bus clock source and
+        * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+        */
+       switch (clk_id) {
+       case ACLK_PERI:
+               rk_clrsetreg(&cru->clksel_con[36],
+                            PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
+                            PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
+               break;
+       case HCLK_PERI:
+               rk_clrsetreg(&cru->clksel_con[37],
+                            PERI_HCLK_DIV_MASK,
+                            (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
+               break;
+       case PCLK_PERI:
+               rk_clrsetreg(&cru->clksel_con[37],
+                            PERI_PCLK_DIV_MASK,
+                            (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT);
+               break;
+       default:
+               printf("do not support this peri freq\n");
+               return -EINVAL;
+       }
+
+       return rk3308_peri_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, parent = priv->vpll0_hz;
+
+       switch (clk_id) {
+       case HCLK_AUDIO:
+               con = readl(&cru->clksel_con[45]);
+               div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT;
+               break;
+       case PCLK_AUDIO:
+               con = readl(&cru->clksel_con[45]);
+               div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT;
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+                                 ulong hz)
+{
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
+       assert(src_clk_div - 1 <= 31);
+
+       /*
+        * select vpll0 as audio bus clock source and
+        * set up dependent divisors for HCLK and PCLK clocks.
+        */
+       switch (clk_id) {
+       case HCLK_AUDIO:
+               rk_clrsetreg(&cru->clksel_con[45],
+                            AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK,
+                            AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT);
+               break;
+       case PCLK_AUDIO:
+               rk_clrsetreg(&cru->clksel_con[45],
+                            AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK,
+                            AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT);
+               break;
+       default:
+               printf("do not support this audio freq\n");
+               return -EINVAL;
+       }
+
+       return rk3308_peri_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
+{
+       struct rk3308_cru *cru = priv->cru;
+       u32 div, con, parent;
+
+       switch (clk_id) {
+       case SCLK_CRYPTO:
+               con = readl(&cru->clksel_con[7]);
+               div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
+               parent = priv->vpll0_hz;
+               break;
+       case SCLK_CRYPTO_APK:
+               con = readl(&cru->clksel_con[7]);
+               div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
+               parent = priv->vpll0_hz;
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
+                                  ulong hz)
+{
+       struct rk3308_cru *cru = priv->cru;
+       int src_clk_div;
+
+       src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
+       assert(src_clk_div - 1 <= 31);
+
+       /*
+        * select gpll as crypto clock source and
+        * set up dependent divisors for crypto clocks.
+        */
+       switch (clk_id) {
+       case SCLK_CRYPTO:
+               rk_clrsetreg(&cru->clksel_con[7],
+                            CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
+                            CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
+               break;
+       case SCLK_CRYPTO_APK:
+               rk_clrsetreg(&cru->clksel_con[7],
+                            CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
+                            CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
+                            (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
+               break;
+       default:
+               printf("do not support this peri freq\n");
+               return -EINVAL;
+       }
+
+       return rk3308_crypto_get_clk(priv, clk_id);
+}
+
+static ulong rk3308_clk_get_rate(struct clk *clk)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       ulong rate = 0;
+
+       debug("%s id:%ld\n", __func__, clk->id);
+
+       switch (clk->id) {
+       case PLL_APLL:
+       case ARMCLK:
+               rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
+                                            priv->cru, APLL);
+               break;
+       case PLL_DPLL:
+               rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+                                            priv->cru, DPLL);
+               break;
+       case PLL_VPLL0:
+               rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
+                                            priv->cru, VPLL0);
+               break;
+       case PLL_VPLL1:
+               rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
+                                            priv->cru, VPLL1);
+               break;
+       case HCLK_SDMMC:
+       case HCLK_EMMC:
+       case SCLK_SDMMC:
+       case SCLK_EMMC:
+       case SCLK_EMMC_SAMPLE:
+               rate = rk3308_mmc_get_clk(clk);
+               break;
+       case SCLK_I2C0:
+       case SCLK_I2C1:
+       case SCLK_I2C2:
+       case SCLK_I2C3:
+               rate = rk3308_i2c_get_clk(clk);
+               break;
+       case SCLK_SARADC:
+               rate = rk3308_saradc_get_clk(clk);
+               break;
+       case SCLK_TSADC:
+               rate = rk3308_tsadc_get_clk(clk);
+               break;
+       case SCLK_SPI0:
+       case SCLK_SPI1:
+               rate = rk3308_spi_get_clk(clk);
+               break;
+       case SCLK_PWM0:
+               rate = rk3308_pwm_get_clk(clk);
+               break;
+       case DCLK_VOP:
+               rate = rk3308_vop_get_clk(clk);
+               break;
+       case ACLK_BUS:
+       case HCLK_BUS:
+       case PCLK_BUS:
+       case PCLK_WDT:
+               rate = rk3308_bus_get_clk(priv, clk->id);
+               break;
+       case ACLK_PERI:
+       case HCLK_PERI:
+       case PCLK_PERI:
+               rate = rk3308_peri_get_clk(priv, clk->id);
+               break;
+       case HCLK_AUDIO:
+       case PCLK_AUDIO:
+               rate = rk3308_audio_get_clk(priv, clk->id);
+               break;
+       case SCLK_CRYPTO:
+       case SCLK_CRYPTO_APK:
+               rate = rk3308_crypto_get_clk(priv, clk->id);
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return rate;
+}
+
+static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+       ulong ret = 0;
+
+       debug("%s %ld %ld\n", __func__, clk->id, rate);
+
+       switch (clk->id) {
+       case PLL_DPLL:
+               ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
+                                           DPLL, rate);
+               priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
+                                                     priv->cru, DPLL);
+               break;
+       case ARMCLK:
+               if (priv->armclk_hz)
+                       rk3308_armclk_set_clk(priv, rate);
+               priv->armclk_hz = rate;
+               break;
+       case HCLK_SDMMC:
+       case HCLK_EMMC:
+       case SCLK_SDMMC:
+       case SCLK_EMMC:
+               ret = rk3308_mmc_set_clk(clk, rate);
+               break;
+       case SCLK_I2C0:
+       case SCLK_I2C1:
+       case SCLK_I2C2:
+       case SCLK_I2C3:
+               ret = rk3308_i2c_set_clk(clk, rate);
+               break;
+       case SCLK_MAC:
+               ret = rk3308_mac_set_clk(clk, rate);
+               break;
+       case SCLK_MAC_RMII:
+               ret = rk3308_mac_set_speed_clk(clk, rate);
+               break;
+       case SCLK_SARADC:
+               ret = rk3308_saradc_set_clk(clk, rate);
+               break;
+       case SCLK_TSADC:
+               ret = rk3308_tsadc_set_clk(clk, rate);
+               break;
+       case SCLK_SPI0:
+       case SCLK_SPI1:
+               ret = rk3308_spi_set_clk(clk, rate);
+               break;
+       case SCLK_PWM0:
+               ret = rk3308_pwm_set_clk(clk, rate);
+               break;
+       case DCLK_VOP:
+               ret = rk3308_vop_set_clk(clk, rate);
+               break;
+       case ACLK_BUS:
+       case HCLK_BUS:
+       case PCLK_BUS:
+               rate = rk3308_bus_set_clk(priv, clk->id, rate);
+               break;
+       case ACLK_PERI:
+       case HCLK_PERI:
+       case PCLK_PERI:
+               rate = rk3308_peri_set_clk(priv, clk->id, rate);
+               break;
+       case HCLK_AUDIO:
+       case PCLK_AUDIO:
+               rate = rk3308_audio_set_clk(priv, clk->id, rate);
+               break;
+       case SCLK_CRYPTO:
+       case SCLK_CRYPTO_APK:
+               ret = rk3308_crypto_set_clk(priv, clk->id, rate);
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return ret;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
+
+       /*
+        * If the requested parent is in the same clock-controller and
+        * the id is SCLK_MAC_SRC, switch to the internal clock.
+        */
+       if (parent->id == SCLK_MAC_SRC) {
+               debug("%s: switching RMII to SCLK_MAC\n", __func__);
+               rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
+       } else {
+               debug("%s: switching RMII to CLKIN\n", __func__);
+               rk_setreg(&priv->cru->clksel_con[43], BIT(14));
+       }
+
+       return 0;
+}
+
+static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       switch (clk->id) {
+       case SCLK_MAC:
+               return rk3308_mac_set_parent(clk, parent);
+       default:
+               break;
+       }
+
+       debug("%s: unsupported clk %ld\n", __func__, clk->id);
+       return -ENOENT;
+}
+#endif
+
+static struct clk_ops rk3308_clk_ops = {
+       .get_rate = rk3308_clk_get_rate,
+       .set_rate = rk3308_clk_set_rate,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+       .set_parent = rk3308_clk_set_parent,
+#endif
+};
+
+static void rk3308_clk_init(struct udevice *dev)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
+                                 priv->cru, APLL) != APLL_HZ) {
+               ret = rk3308_armclk_set_clk(priv, APLL_HZ);
+               if (ret < 0)
+                       printf("%s failed to set armclk rate\n", __func__);
+       }
+
+       rk3308_clk_get_pll_rate(priv);
+
+       rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
+       rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
+       rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
+
+       rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
+       rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
+       rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
+
+       rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
+       rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
+}
+
+static int rk3308_clk_probe(struct udevice *dev)
+{
+       int ret;
+
+       rk3308_clk_init(dev);
+
+       /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+       ret = clk_set_defaults(dev, 1);
+       if (ret)
+               debug("%s clk_set_defaults failed %d\n", __func__, ret);
+
+       return ret;
+}
+
+static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
+{
+       struct rk3308_clk_priv *priv = dev_get_priv(dev);
+
+       priv->cru = dev_read_addr_ptr(dev);
+
+       return 0;
+}
+
+static int rk3308_clk_bind(struct udevice *dev)
+{
+       int ret;
+       struct udevice *sys_child;
+       struct sysreset_reg *priv;
+
+       /* The reset driver does not have a device node, so bind it here */
+       ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+                                &sys_child);
+       if (ret) {
+               debug("Warning: No sysreset driver: ret=%d\n", ret);
+       } else {
+               priv = malloc(sizeof(struct sysreset_reg));
+               priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
+                                                   glb_srst_fst);
+               priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
+                                                   glb_srst_snd);
+               sys_child->priv = priv;
+       }
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+       ret = offsetof(struct rk3308_cru, softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 12);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
+       return 0;
+}
+
+static const struct udevice_id rk3308_clk_ids[] = {
+       { .compatible = "rockchip,rk3308-cru" },
+       { }
+};
+
+U_BOOT_DRIVER(rockchip_rk3308_cru) = {
+       .name           = "rockchip_rk3308_cru",
+       .id             = UCLASS_CLK,
+       .of_match       = rk3308_clk_ids,
+       .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
+       .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
+       .ops            = &rk3308_clk_ops,
+       .bind           = rk3308_clk_bind,
+       .probe          = rk3308_clk_probe,
+};
diff --git a/include/dt-bindings/clock/rk3308-cru.h b/include/dt-bindings/clock/rk3308-cru.h
new file mode 100644 (file)
index 0000000..d97840f
--- /dev/null
@@ -0,0 +1,387 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao <finley.xiao@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H
+
+/* core clocks */
+#define PLL_APLL               1
+#define PLL_DPLL               2
+#define PLL_VPLL0              3
+#define PLL_VPLL1              4
+#define ARMCLK                 5
+
+/* sclk (special clocks) */
+#define USB480M                        14
+#define SCLK_RTC32K            15
+#define SCLK_PVTM_CORE         16
+#define SCLK_UART0             17
+#define SCLK_UART1             18
+#define SCLK_UART2             19
+#define SCLK_UART3             20
+#define SCLK_UART4             21
+#define SCLK_I2C0              22
+#define SCLK_I2C1              23
+#define SCLK_I2C2              24
+#define SCLK_I2C3              25
+#define SCLK_PWM0              26
+#define SCLK_SPI0              27
+#define SCLK_SPI1              28
+#define SCLK_SPI2              29
+#define SCLK_TIMER0            30
+#define SCLK_TIMER1            31
+#define SCLK_TIMER2            32
+#define SCLK_TIMER3            33
+#define SCLK_TIMER4            34
+#define SCLK_TIMER5            35
+#define SCLK_TSADC             36
+#define SCLK_SARADC            37
+#define SCLK_OTP               38
+#define SCLK_OTP_USR           39
+#define SCLK_CPU_BOOST         40
+#define SCLK_CRYPTO            41
+#define SCLK_CRYPTO_APK                42
+#define SCLK_NANDC_DIV         43
+#define SCLK_NANDC_DIV50       44
+#define SCLK_NANDC             45
+#define SCLK_SDMMC_DIV         46
+#define SCLK_SDMMC_DIV50       47
+#define SCLK_SDMMC             48
+#define SCLK_SDMMC_DRV         49
+#define SCLK_SDMMC_SAMPLE      50
+#define SCLK_SDIO_DIV          51
+#define SCLK_SDIO_DIV50                52
+#define SCLK_SDIO              53
+#define SCLK_SDIO_DRV          54
+#define SCLK_SDIO_SAMPLE       55
+#define SCLK_EMMC_DIV          56
+#define SCLK_EMMC_DIV50                57
+#define SCLK_EMMC              58
+#define SCLK_EMMC_DRV          59
+#define SCLK_EMMC_SAMPLE       60
+#define SCLK_SFC               61
+#define SCLK_OTG_ADP           62
+#define SCLK_MAC_SRC           63
+#define SCLK_MAC               64
+#define SCLK_MAC_REF           65
+#define SCLK_MAC_RX_TX         66
+#define SCLK_MAC_RMII          67
+#define SCLK_DDR_MON_TIMER     68
+#define SCLK_DDR_MON           69
+#define SCLK_DDRCLK            70
+#define SCLK_PMU               71
+#define SCLK_USBPHY_REF                72
+#define SCLK_WIFI              73
+#define SCLK_PVTM_PMU          74
+#define SCLK_PDM               75
+#define SCLK_I2S0_8CH_TX       76
+#define SCLK_I2S0_8CH_TX_OUT   77
+#define SCLK_I2S0_8CH_RX       78
+#define SCLK_I2S0_8CH_RX_OUT   79
+#define SCLK_I2S1_8CH_TX       80
+#define SCLK_I2S1_8CH_TX_OUT   81
+#define SCLK_I2S1_8CH_RX       82
+#define SCLK_I2S1_8CH_RX_OUT   83
+#define SCLK_I2S2_8CH_TX       84
+#define SCLK_I2S2_8CH_TX_OUT   85
+#define SCLK_I2S2_8CH_RX       86
+#define SCLK_I2S2_8CH_RX_OUT   87
+#define SCLK_I2S3_8CH_TX       88
+#define SCLK_I2S3_8CH_TX_OUT   89
+#define SCLK_I2S3_8CH_RX       90
+#define SCLK_I2S3_8CH_RX_OUT   91
+#define SCLK_I2S0_2CH          92
+#define SCLK_I2S0_2CH_OUT      93
+#define SCLK_I2S1_2CH          94
+#define SCLK_I2S1_2CH_OUT      95
+#define SCLK_SPDIF_TX_DIV      96
+#define SCLK_SPDIF_TX_DIV50    97
+#define SCLK_SPDIF_TX          98
+#define SCLK_SPDIF_RX_DIV      99
+#define SCLK_SPDIF_RX_DIV50    100
+#define SCLK_SPDIF_RX          101
+#define SCLK_I2S0_8CH_TX_MUX   102
+#define SCLK_I2S0_8CH_RX_MUX   103
+#define SCLK_I2S1_8CH_TX_MUX   104
+#define SCLK_I2S1_8CH_RX_MUX   105
+#define SCLK_I2S2_8CH_TX_MUX   106
+#define SCLK_I2S2_8CH_RX_MUX   107
+#define SCLK_I2S3_8CH_TX_MUX   108
+#define SCLK_I2S3_8CH_RX_MUX   109
+#define SCLK_I2S0_8CH_TX_SRC   110
+#define SCLK_I2S0_8CH_RX_SRC   111
+#define SCLK_I2S1_8CH_TX_SRC   112
+#define SCLK_I2S1_8CH_RX_SRC   113
+#define SCLK_I2S2_8CH_TX_SRC   114
+#define SCLK_I2S2_8CH_RX_SRC   115
+#define SCLK_I2S3_8CH_TX_SRC   116
+#define SCLK_I2S3_8CH_RX_SRC   117
+#define SCLK_I2S0_2CH_SRC      118
+#define SCLK_I2S1_2CH_SRC      119
+#define SCLK_PWM1              120
+#define SCLK_PWM2              121
+#define SCLK_OWIRE             122
+
+/* dclk */
+#define DCLK_VOP               125
+
+/* aclk */
+#define ACLK_BUS_SRC           130
+#define ACLK_BUS               131
+#define ACLK_PERI_SRC          132
+#define ACLK_PERI              133
+#define ACLK_MAC               134
+#define ACLK_CRYPTO            135
+#define ACLK_VOP               136
+#define ACLK_GIC               137
+#define ACLK_DMAC0             138
+#define ACLK_DMAC1             139
+
+/* hclk */
+#define HCLK_BUS               150
+#define HCLK_PERI              151
+#define HCLK_AUDIO             152
+#define HCLK_NANDC             153
+#define HCLK_SDMMC             154
+#define HCLK_SDIO              155
+#define HCLK_EMMC              156
+#define HCLK_SFC               157
+#define HCLK_OTG               158
+#define HCLK_HOST              159
+#define HCLK_HOST_ARB          160
+#define HCLK_PDM               161
+#define HCLK_SPDIFTX           162
+#define HCLK_SPDIFRX           163
+#define HCLK_I2S0_8CH          164
+#define HCLK_I2S1_8CH          165
+#define HCLK_I2S2_8CH          166
+#define HCLK_I2S3_8CH          167
+#define HCLK_I2S0_2CH          168
+#define HCLK_I2S1_2CH          169
+#define HCLK_VAD               170
+#define HCLK_CRYPTO            171
+#define HCLK_VOP               172
+
+/* pclk */
+#define PCLK_BUS               190
+#define PCLK_DDR               191
+#define PCLK_PERI              192
+#define PCLK_PMU               193
+#define PCLK_AUDIO             194
+#define PCLK_MAC               195
+#define PCLK_ACODEC            196
+#define PCLK_UART0             197
+#define PCLK_UART1             198
+#define PCLK_UART2             199
+#define PCLK_UART3             200
+#define PCLK_UART4             201
+#define PCLK_I2C0              202
+#define PCLK_I2C1              203
+#define PCLK_I2C2              204
+#define PCLK_I2C3              205
+#define PCLK_PWM0              206
+#define PCLK_SPI0              207
+#define PCLK_SPI1              208
+#define PCLK_SPI2              209
+#define PCLK_SARADC            210
+#define PCLK_TSADC             211
+#define PCLK_TIMER             212
+#define PCLK_OTP_NS            213
+#define PCLK_WDT               214
+#define PCLK_GPIO0             215
+#define PCLK_GPIO1             216
+#define PCLK_GPIO2             217
+#define PCLK_GPIO3             218
+#define PCLK_GPIO4             219
+#define PCLK_SGRF              220
+#define PCLK_GRF               221
+#define PCLK_USBSD_DET         222
+#define PCLK_DDR_UPCTL         223
+#define PCLK_DDR_MON           224
+#define PCLK_DDRPHY            225
+#define PCLK_DDR_STDBY         226
+#define PCLK_USB_GRF           227
+#define PCLK_CRU               228
+#define PCLK_OTP_PHY           229
+#define PCLK_CPU_BOOST         230
+#define PCLK_PWM1              231
+#define PCLK_PWM2              232
+#define PCLK_CAN               233
+#define PCLK_OWIRE             234
+
+#define CLK_NR_CLKS            (PCLK_OWIRE + 1)
+
+/* soft-reset indices */
+
+/* cru_softrst_con0 */
+#define SRST_CORE0_PO          0
+#define SRST_CORE1_PO          1
+#define SRST_CORE2_PO          2
+#define SRST_CORE3_PO          3
+#define SRST_CORE0             4
+#define SRST_CORE1             5
+#define SRST_CORE2             6
+#define SRST_CORE3             7
+#define SRST_CORE0_DBG         8
+#define SRST_CORE1_DBG         9
+#define SRST_CORE2_DBG         10
+#define SRST_CORE3_DBG         11
+#define SRST_TOPDBG            12
+#define SRST_CORE_NOC          13
+#define SRST_STRC_A            14
+#define SRST_L2C               15
+
+/* cru_softrst_con1 */
+#define SRST_DAP               16
+#define SRST_CORE_PVTM         17
+#define SRST_CORE_PRF          18
+#define SRST_CORE_GRF          19
+#define SRST_DDRUPCTL          20
+#define SRST_DDRUPCTL_P                22
+#define SRST_MSCH              23
+#define SRST_DDRMON_P          25
+#define SRST_DDRSTDBY_P                26
+#define SRST_DDRSTDBY          27
+#define SRST_DDRPHY            28
+#define SRST_DDRPHY_DIV                29
+#define SRST_DDRPHY_P          30
+
+/* cru_softrst_con2 */
+#define SRST_BUS_NIU_H         32
+#define SRST_USB_NIU_P         33
+#define SRST_CRYPTO_A          34
+#define SRST_CRYPTO_H          35
+#define SRST_CRYPTO            36
+#define SRST_CRYPTO_APK                37
+#define SRST_VOP_A             38
+#define SRST_VOP_H             39
+#define SRST_VOP_D             40
+#define SRST_INTMEM_A          41
+#define SRST_ROM_H             42
+#define SRST_GIC_A             43
+#define SRST_UART0_P           44
+#define SRST_UART0             45
+#define SRST_UART1_P           46
+#define SRST_UART1             47
+
+/* cru_softrst_con3 */
+#define SRST_UART2_P           48
+#define SRST_UART2             49
+#define SRST_UART3_P           50
+#define SRST_UART3             51
+#define SRST_UART4_P           52
+#define SRST_UART4             53
+#define SRST_I2C0_P            54
+#define SRST_I2C0              55
+#define SRST_I2C1_P            56
+#define SRST_I2C1              57
+#define SRST_I2C2_P            58
+#define SRST_I2C2              59
+#define SRST_I2C3_P            60
+#define SRST_I2C3              61
+#define SRST_PWM0_P            62
+#define SRST_PWM0              63
+
+/* cru_softrst_con4 */
+#define SRST_SPI0_P            64
+#define SRST_SPI0              65
+#define SRST_SPI1_P            66
+#define SRST_SPI1              67
+#define SRST_SPI2_P            68
+#define SRST_SPI2              69
+#define SRST_SARADC_P          70
+#define SRST_TSADC_P           71
+#define SRST_TSADC             72
+#define SRST_TIMER0_P          73
+#define SRST_TIMER0            74
+#define SRST_TIMER1            75
+#define SRST_TIMER2            76
+#define SRST_TIMER3            77
+#define SRST_TIMER4            78
+#define SRST_TIMER5            79
+
+/* cru_softrst_con5 */
+#define SRST_OTP_NS_P          80
+#define SRST_OTP_NS_SBPI       81
+#define SRST_OTP_NS_USR                82
+#define SRST_OTP_PHY_P         83
+#define SRST_OTP_PHY           84
+#define SRST_GPIO0_P           86
+#define SRST_GPIO1_P           87
+#define SRST_GPIO2_P           88
+#define SRST_GPIO3_P           89
+#define SRST_GPIO4_P           90
+#define SRST_GRF_P             91
+#define SRST_USBSD_DET_P       92
+#define SRST_PMU               93
+#define SRST_PMU_PVTM          94
+#define SRST_USB_GRF_P         95
+
+/* cru_softrst_con6 */
+#define SRST_CPU_BOOST         96
+#define SRST_CPU_BOOST_P       97
+#define SRST_PWM1_P            98
+#define SRST_PWM1              99
+#define SRST_PWM2_P            100
+#define SRST_PWM2              101
+#define SRST_PERI_NIU_A                104
+#define SRST_PERI_NIU_H                105
+#define SRST_PERI_NIU_p                106
+#define SRST_USB2OTG_H         107
+#define SRST_USB2OTG           108
+#define SRST_USB2OTG_ADP       109
+#define SRST_USB2HOST_H                110
+#define SRST_USB2HOST_ARB_H    111
+
+/* cru_softrst_con7 */
+#define SRST_USB2HOST_AUX_H    112
+#define SRST_USB2HOST_EHCI     113
+#define SRST_USB2HOST          114
+#define SRST_USBPHYPOR         115
+#define SRST_UTMI0             116
+#define SRST_UTMI1             117
+#define SRST_SDIO_H            118
+#define SRST_EMMC_H            119
+#define SRST_SFC_H             120
+#define SRST_SFC               121
+#define SRST_SD_H              122
+#define SRST_NANDC_H           123
+#define SRST_NANDC_N           124
+#define SRST_MAC_A             125
+#define SRST_CAN_P             126
+#define SRST_OWIRE_P           127
+
+/* cru_softrst_con8 */
+#define SRST_AUDIO_NIU_H       128
+#define SRST_AUDIO_NIU_P       129
+#define SRST_PDM_H             130
+#define SRST_PDM_M             131
+#define SRST_SPDIFTX_H         132
+#define SRST_SPDIFTX_M         133
+#define SRST_SPDIFRX_H         134
+#define SRST_SPDIFRX_M         135
+#define SRST_I2S0_8CH_H                136
+#define SRST_I2S0_8CH_TX_M     137
+#define SRST_I2S0_8CH_RX_M     138
+#define SRST_I2S1_8CH_H                139
+#define SRST_I2S1_8CH_TX_M     140
+#define SRST_I2S1_8CH_RX_M     141
+#define SRST_I2S2_8CH_H                142
+#define SRST_I2S2_8CH_TX_M     143
+
+/* cru_softrst_con9 */
+#define SRST_I2S2_8CH_RX_M     144
+#define SRST_I2S3_8CH_H                145
+#define SRST_I2S3_8CH_TX_M     146
+#define SRST_I2S3_8CH_RX_M     147
+#define SRST_I2S0_2CH_H                148
+#define SRST_I2S0_2CH_M                149
+#define SRST_I2S1_2CH_H                150
+#define SRST_I2S1_2CH_M                151
+#define SRST_VAD_H             152
+#define SRST_ACODEC_P          153
+
+#endif