From: dkl Date: Wed, 5 Nov 2014 02:02:06 +0000 (+0800) Subject: rk3368: add support for rk3368 clocks X-Git-Tag: firefly_0821_release~4158^2~577 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=da14b4e6b78762962063a13e9de5aac1c47e1bbd;p=firefly-linux-kernel-4.4.55.git rk3368: add support for rk3368 clocks 1. Add clkops_rate_ddr_div4 ops 2. Add clk_pll_ops_3368_apllb && &clk_pll_ops_3368_aplll ops 3. Add some rk3368 clock macros 4. Add "rkclk_init_special_regs" type clk to handle clock with register not in CRU --- diff --git a/drivers/clk/rockchip/clk-ops.c b/drivers/clk/rockchip/clk-ops.c index 197051dec37e..226541849d31 100644 --- a/drivers/clk/rockchip/clk-ops.c +++ b/drivers/clk/rockchip/clk-ops.c @@ -494,6 +494,24 @@ const struct clk_ops clkops_rate_ddr_div2 = { .determine_rate = clk_ddr_determine_rate, }; +static unsigned long clk_ddr_div4_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + /* Same as clk_core, we should NOT set clk_ddr's parent + * (dpll) rate directly as a side effect. + */ + struct clk *parent = __clk_get_parent(hw->clk); + + return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/4; +} + +const struct clk_ops clkops_rate_ddr_div4 = { + .recalc_rate = clk_ddr_div4_recalc_rate, + .round_rate = clk_ddr_round_rate, + .set_rate = clk_ddr_set_rate, + .determine_rate = clk_ddr_determine_rate, +}; + static unsigned long clk_3288_i2s_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -710,7 +728,8 @@ struct clk_ops_table rk_clkops_rate_table[] = { {.index = CLKOPS_RATE_RK3288_USB480M, .clk_ops = &clkops_rate_3288_usb480m}, {.index = CLKOPS_RATE_RK3288_DCLK_LCDC0,.clk_ops = &clkops_rate_3288_dclk_lcdc0}, {.index = CLKOPS_RATE_RK3288_DCLK_LCDC1,.clk_ops = &clkops_rate_3288_dclk_lcdc1}, - {.index = CLKOPS_RATE_DDR_DIV2, .clk_ops = &clkops_rate_ddr_div2}, + {.index = CLKOPS_RATE_DDR_DIV2, .clk_ops = &clkops_rate_ddr_div2}, + {.index = CLKOPS_RATE_DDR_DIV4, .clk_ops = &clkops_rate_ddr_div4}, {.index = CLKOPS_RATE_I2S, .clk_ops = NULL}, {.index = CLKOPS_RATE_CIFOUT, .clk_ops = NULL}, {.index = CLKOPS_RATE_UART, .clk_ops = NULL}, diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index ce8496577766..42dfef328454 100755 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -235,6 +235,10 @@ static const struct pll_clk_set rk312xplus_pll_com_table[] = { _RK3036_PLL_SET_CLKS(400000, 6, 400, 2, 2, 1, 0), }; +static const struct apll_clk_set rk3368_apll_table[] = { + /* _RK3368_APLL_SET_CLKS(); */ +}; + static void pll_wait_lock(struct clk_hw *hw) { struct clk_pll *pll = to_clk_pll(hw); @@ -1775,6 +1779,442 @@ static const struct clk_ops clk_pll_ops_312xplus = { .set_rate = clk_cpll_set_rate_312xplus, }; +static long clk_pll_round_rate_3368_apll(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk *parent = __clk_get_parent(hw->clk); + + if (parent && (rate == __clk_get_rate(parent))) { + clk_debug("pll %s round rate=%lu equal to parent rate\n", + __clk_get_name(hw->clk), rate); + return rate; + } + + return (apll_get_best_set(rate, rk3368_apll_table)->rate); +} + +/* 1: use, 0: no use */ +#define RK3368_APLLB_USE_GPLL 1 + +/* when define 1, we will set div to make rate change gently, but it will cost + more time */ +#define RK3368_APLLB_DIV_MORE 1 + +static int clk_pll_set_rate_3368_apllb(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct clk *clk = hw->clk; + struct clk *arm_gpll = __clk_lookup("clk_gpll"); + unsigned long arm_gpll_rate, temp_rate, old_rate; + const struct apll_clk_set *ps; + u32 temp_div; + unsigned long flags; + int sel_gpll = 0; + + +#if !RK3368_APLLB_USE_GPLL + goto CHANGE_APLL; +#endif + + /* prepare arm_gpll before reparent clk_core to it */ + if (!arm_gpll) { + clk_err("clk arm_gpll is NULL!\n"); + goto CHANGE_APLL; + } + + arm_gpll_rate = __clk_get_rate(arm_gpll); + old_rate = __clk_get_rate(clk); + + temp_rate = (old_rate > rate) ? old_rate : rate; + temp_div = DIV_ROUND_UP(arm_gpll_rate, temp_rate); + + if (temp_div > RK3368_CORE_CLK_MAX_DIV) { + clk_debug("temp_div %d > max_div %d\n", temp_div, + RK3368_CORE_CLK_MAX_DIV); + clk_debug("can't get rate %lu from arm_gpll rate %lu\n", + __clk_get_rate(clk), arm_gpll_rate); + goto CHANGE_APLL; + } + +#if 0 + if (clk_prepare(arm_gpll)) { + clk_err("fail to prepare arm_gpll path\n"); + clk_unprepare(arm_gpll); + goto CHANGE_APLL; + } + + if (clk_enable(arm_gpll)) { + clk_err("fail to enable arm_gpll path\n"); + clk_disable(arm_gpll); + clk_unprepare(arm_gpll); + goto CHANGE_APLL; + } +#endif + + local_irq_save(flags); + + /* select gpll */ +#if RK3368_APLLB_DIV_MORE + if (temp_div == 1) { + /* when old_rate/2 < (old_rate-arm_gpll_rate), + we can set div to make rate change more gently */ + if (old_rate > (2*arm_gpll_rate)) { + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(0)); + } else { + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(0)); + } + } else { + cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(0)); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(0)); + } +#else + cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(0)); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(0)); +#endif + + sel_gpll = 1; + + smp_wmb(); + + local_irq_restore(flags); + + clk_debug("temp select arm_gpll path, get rate %lu\n", + arm_gpll_rate/temp_div); + clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate, + temp_div); + +CHANGE_APLL: + ps = apll_get_best_set(rate, rk3368_apll_table); + clk_debug("apll will set rate %lu\n", ps->rate); + clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n", + ps->pllcon0, ps->pllcon1, ps->pllcon2, + ps->clksel0, ps->clksel1); + + local_irq_save(flags); + + /* If core src don't select gpll, apll need to enter slow mode + * before reset + */ + if (!sel_gpll) + cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), + pll->mode_offset); + + /* PLL enter reset */ + cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3)); + + cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0)); + cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1)); + cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2)); + + udelay(5); + + /* return from rest */ + cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3)); + + /* wating lock state */ + udelay(ps->rst_dly); + pll_wait_lock(hw); + + if (rate >= __clk_get_rate(hw->clk)) { + cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(0)); + cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(1)); + } + + /* PLL return from slow mode */ + if (!sel_gpll) + cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), + pll->mode_offset); + + /* reparent to apll, and set div to 1 */ + if (sel_gpll) { +#if RK3368_APLLB_DIV_MORE + if (temp_div == 1) { + /* when rate/2 < (old_rate-arm_gpll_rate), + we can set div to make rate change more gently */ + if (rate > (2*arm_gpll_rate)) { + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(0)); + } else { + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(0)); + } + } else { + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(0)); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(0)); + } +#else + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(0)); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(0)); +#endif + } + + if (rate < __clk_get_rate(hw->clk)) { + cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(0)); + cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(1)); + } + + smp_wmb(); + + local_irq_restore(flags); + + if (sel_gpll) { + sel_gpll = 0; + /* clk_disable(arm_gpll); + clk_unprepare(arm_gpll); */ + } + + clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n", + ps->rate, + cru_readl(pll->reg + RK3188_PLL_CON(0)), + cru_readl(pll->reg + RK3188_PLL_CON(1)), + cru_readl(pll->reg + RK3188_PLL_CON(2)), + cru_readl(pll->reg + RK3188_PLL_CON(3)), + cru_readl(RK3368_CRU_CLKSELS_CON(0)), + cru_readl(RK3368_CRU_CLKSELS_CON(1))); + + return 0; +} + +static const struct clk_ops clk_pll_ops_3368_apllb = { + .recalc_rate = clk_pll_recalc_rate_3188plus, + .round_rate = clk_pll_round_rate_3368_apll, + .set_rate = clk_pll_set_rate_3368_apllb, +}; + +/* 1: use, 0: no use */ +#define RK3368_APLLL_USE_GPLL 1 + +/* when define 1, we will set div to make rate change gently, but it will cost + more time */ +#define RK3368_APLLL_DIV_MORE 1 + +static int clk_pll_set_rate_3368_aplll(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pll *pll = to_clk_pll(hw); + struct clk *clk = hw->clk; + struct clk *arm_gpll = __clk_lookup("clk_gpll"); + unsigned long arm_gpll_rate, temp_rate, old_rate; + const struct apll_clk_set *ps; + u32 temp_div; + unsigned long flags; + int sel_gpll = 0; + + +#if !RK3368_APLLL_USE_GPLL + goto CHANGE_APLL; +#endif + + /* prepare arm_gpll before reparent clk_core to it */ + if (!arm_gpll) { + clk_err("clk arm_gpll is NULL!\n"); + goto CHANGE_APLL; + } + + arm_gpll_rate = __clk_get_rate(arm_gpll); + old_rate = __clk_get_rate(clk); + + temp_rate = (old_rate > rate) ? old_rate : rate; + temp_div = DIV_ROUND_UP(arm_gpll_rate, temp_rate); + + if (temp_div > RK3368_CORE_CLK_MAX_DIV) { + clk_debug("temp_div %d > max_div %d\n", temp_div, + RK3368_CORE_CLK_MAX_DIV); + clk_debug("can't get rate %lu from arm_gpll rate %lu\n", + __clk_get_rate(clk), arm_gpll_rate); + goto CHANGE_APLL; + } + +#if 0 + if (clk_prepare(arm_gpll)) { + clk_err("fail to prepare arm_gpll path\n"); + clk_unprepare(arm_gpll); + goto CHANGE_APLL; + } + + if (clk_enable(arm_gpll)) { + clk_err("fail to enable arm_gpll path\n"); + clk_disable(arm_gpll); + clk_unprepare(arm_gpll); + goto CHANGE_APLL; + } +#endif + + local_irq_save(flags); + + /* select gpll */ +#if RK3368_APLLL_DIV_MORE + if (temp_div == 1) { + /* when old_rate/2 < (old_rate-arm_gpll_rate), + we can set div to make rate change more gently */ + if (old_rate > (2*arm_gpll_rate)) { + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(2)); + } else { + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(2)); + } + } else { + cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(2)); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(2)); + } +#else + cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(2)); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL, + RK3368_CRU_CLKSELS_CON(2)); +#endif + + sel_gpll = 1; + + smp_wmb(); + + local_irq_restore(flags); + + clk_debug("temp select arm_gpll path, get rate %lu\n", + arm_gpll_rate/temp_div); + clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate, + temp_div); + +CHANGE_APLL: + ps = apll_get_best_set(rate, rk3368_apll_table); + clk_debug("apll will set rate %lu\n", ps->rate); + clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n", + ps->pllcon0, ps->pllcon1, ps->pllcon2, + ps->clksel0, ps->clksel1); + + local_irq_save(flags); + + /* If core src don't select gpll, apll need to enter slow mode + * before reset + */ + if (!sel_gpll) + cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), + pll->mode_offset); + + /* PLL enter reset */ + cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3)); + + cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0)); + cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1)); + cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2)); + + udelay(5); + + /* return from rest */ + cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3)); + + /* wating lock state */ + udelay(ps->rst_dly); + pll_wait_lock(hw); + + if (rate >= __clk_get_rate(hw->clk)) { + cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(2)); + cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(3)); + } + + /* PLL return from slow mode */ + if (!sel_gpll) + cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), + pll->mode_offset); + + /* reparent to apll, and set div to 1 */ + if (sel_gpll) { +#if RK3368_APLLL_DIV_MORE + if (temp_div == 1) { + /* when rate/2 < (old_rate-arm_gpll_rate), + we can set div to make rate change more gently */ + if (rate > (2*arm_gpll_rate)) { + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2)); + udelay(10); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(2)); + } else { + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(2)); + } + } else { + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(2)); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(2)); + } +#else + cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL, + RK3368_CRU_CLKSELS_CON(2)); + cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(2)); +#endif + } + + if (rate < __clk_get_rate(hw->clk)) { + cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(2)); + cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(3)); + } + + smp_wmb(); + + local_irq_restore(flags); + + if (sel_gpll) { + sel_gpll = 0; + /* clk_disable(arm_gpll); + clk_unprepare(arm_gpll); */ + } + + clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n", + ps->rate, + cru_readl(pll->reg + RK3188_PLL_CON(0)), + cru_readl(pll->reg + RK3188_PLL_CON(1)), + cru_readl(pll->reg + RK3188_PLL_CON(2)), + cru_readl(pll->reg + RK3188_PLL_CON(3)), + cru_readl(RK3368_CRU_CLKSELS_CON(2)), + cru_readl(RK3368_CRU_CLKSELS_CON(3))); + + return 0; +} + +static const struct clk_ops clk_pll_ops_3368_aplll = { + .recalc_rate = clk_pll_recalc_rate_3188plus, + .round_rate = clk_pll_round_rate_3368_apll, + .set_rate = clk_pll_set_rate_3368_aplll, +}; + const struct clk_ops *rk_get_pll_ops(u32 pll_flags) { switch (pll_flags) { @@ -1805,6 +2245,12 @@ const struct clk_ops *rk_get_pll_ops(u32 pll_flags) case CLK_PLL_312XPLUS: return &clk_pll_ops_312xplus; + case CLK_PLL_3368_APLLB: + return &clk_pll_ops_3368_apllb; + + case CLK_PLL_3368_APLLL: + return &clk_pll_ops_3368_aplll; + default: clk_err("%s: unknown pll_flags!\n", __func__); return NULL; diff --git a/drivers/clk/rockchip/clk-pll.h b/drivers/clk/rockchip/clk-pll.h index df41b57644fe..3ecc178a5903 100755 --- a/drivers/clk/rockchip/clk-pll.h +++ b/drivers/clk/rockchip/clk-pll.h @@ -403,6 +403,45 @@ .pllcon2 = RK3036_PLL_SET_FRAC(_frac), \ } +/***************************RK3368 PLL**************************************/ +/*******************CLKSEL0/2 BITS***************************/ +#define RK3368_CORE_SEL_PLL_W_MSK (1 << 23) +#define RK3368_CORE_SEL_APLL (0 << 7) +#define RK3368_CORE_SEL_GPLL (1 << 7) + +#define RK3368_CORE_CLK_SHIFT 0 +#define RK3368_CORE_CLK_WIDTH 5 +#define RK3368_CORE_CLK_DIV(i) \ + CLK_DIV_PLUS_ONE_SET(i, RK3368_CORE_CLK_SHIFT, RK3368_CORE_CLK_WIDTH) +#define RK3368_CORE_CLK_MAX_DIV (2<> 1),\ + .rst_dly = ((nr*500)/24+1),\ + .clksel0 = RK3368_ACLKM_CORE_DIV(aclkm_div),\ + .clksel1 = RK3368_ATCLK_CORE_DIV(atclk_div) | RK3368_PCLK_DBG_DIV(pclk_dbg_div) \ +} + struct pll_clk_set { unsigned long rate; u32 pllcon0; diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index aaad37e87a7e..5880b5367efb 100755 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -1050,6 +1050,31 @@ out: return ret; } +static int __init rkclk_init_special_regs(struct device_node *np) +{ + struct device_node *node; + const char *compatible; + void __iomem *reg = 0; + int ret = 0; + + + for_each_available_child_of_node(np, node) { + clk_debug("\n"); + of_property_read_string(node, "compatible", &compatible); + if (strcmp(compatible, "rockchip,rk3188-mux-con") == 0) { + reg = of_iomap(node, 0); + ret = rkclk_init_muxinfo(node, reg); + if (ret != 0) { + clk_err("%s: init mux con err\n", __func__); + goto out; + } + } + } + +out: + return ret; +} + static int __init rkclk_init_pd(struct device_node *np) { struct device_node *node = NULL; @@ -1839,22 +1864,27 @@ static void __init rk_clk_tree_init(struct device_node *np) if (strcmp(compatible, "rockchip,rk-fixed-rate-cons") == 0) { if (rkclk_init_fixed_rate(node) != 0) { clk_err("%s: init fixed_rate err\n", __func__); - return ; + return; } } else if (strcmp(compatible, "rockchip,rk-fixed-factor-cons") == 0) { if (rkclk_init_fixed_factor(node) != 0) { clk_err("%s: init fixed_factor err\n", __func__); - return ; + return; } } else if (strcmp(compatible, "rockchip,rk-clock-regs") == 0) { if (rkclk_init_regcon(node) != 0) { clk_err("%s: init reg cons err\n", __func__); - return ; + return; } } else if (strcmp(compatible, "rockchip,rk-pd-cons") == 0) { if (rkclk_init_pd(node) != 0) { clk_err("%s: init pd err\n", __func__); - return ; + return; + } + } else if (strcmp(compatible, "rockchip,rk-clock-special-regs") == 0) { + if (rkclk_init_special_regs(node) != 0) { + clk_err("%s: init special reg err\n", __func__); + return; } } else { clk_err("%s: unknown\n", __func__); diff --git a/include/dt-bindings/clock/rockchip,rk3368.h b/include/dt-bindings/clock/rockchip,rk3368.h new file mode 100644 index 000000000000..728ec589f579 --- /dev/null +++ b/include/dt-bindings/clock/rockchip,rk3368.h @@ -0,0 +1,8 @@ +#ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H +#define _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H + +#include "rockchip.h" + +/* reset id */ + +#endif /* _DT_BINDINGS_CLOCK_ROCKCHIP_RK3368_H */ diff --git a/include/dt-bindings/clock/rockchip.h b/include/dt-bindings/clock/rockchip.h index 5c1234e967e3..c6d25f6aca0f 100644 --- a/include/dt-bindings/clock/rockchip.h +++ b/include/dt-bindings/clock/rockchip.h @@ -43,6 +43,8 @@ #define CLK_PLL_3036_APLL BIT(6) #define CLK_PLL_3036PLUS_AUTO BIT(7) #define CLK_PLL_312XPLUS BIT(8) +#define CLK_PLL_3368_APLLB BIT(9) +#define CLK_PLL_3368_APLLL BIT(10) /* rate_ops index */ @@ -64,6 +66,7 @@ #define CLKOPS_RATE_RK3288_DCLK_LCDC0 16 #define CLKOPS_RATE_RK3288_DCLK_LCDC1 17 #define CLKOPS_RATE_DDR_DIV2 18 +#define CLKOPS_RATE_DDR_DIV4 19 #define CLKOPS_TABLE_END (~0) /* pd id */ diff --git a/include/linux/rockchip/cru.h b/include/linux/rockchip/cru.h index 871ba05175f8..c3e2e63fd64a 100755 --- a/include/linux/rockchip/cru.h +++ b/include/linux/rockchip/cru.h @@ -241,4 +241,15 @@ enum rk312x_cru_clk_gate { RK312X_CLKGATE_PCLK_UART1, RK312X_CLKGATE_PCLK_UART2, }; + +/*************************RK3368********************************/ + +/*******************CRU OFFSET*********************/ +#define RK3368_CRU_CLKSEL_CON 0x100 +#define RK3368_CRU_CLKGATE_CON 0x200 + +#define RK3368_PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4)) +#define RK3368_CRU_CLKSELS_CON(i) (RK3368_CRU_CLKSEL_CON + ((i) * 4)) +#define RK3368_CRU_CLKGATES_CON(i) (RK3368_CRU_CLKGATE_CON + ((i) * 4)) + #endif