--- /dev/null
+// 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,
+};
--- /dev/null
+/* 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