From: dkl Date: Fri, 17 Jan 2014 09:52:17 +0000 (+0800) Subject: rk_clk: modify clk-ops.c to reuse and fit the common clk framework. X-Git-Tag: firefly_0821_release~6386 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c37288b6f46f97cd3bed7c42b7d294b314f9dbf3;p=firefly-linux-kernel-4.4.55.git rk_clk: modify clk-ops.c to reuse and fit the common clk framework. After the .determine_rate operation was introduced, many ops and clocks can be implemented more easily by the common clock framework, and many unnessary old codes can be removed as a result. --- diff --git a/arch/arm/boot/dts/rk3188-clocks.dtsi b/arch/arm/boot/dts/rk3188-clocks.dtsi index 154a461cb430..0097acce16f7 100755 --- a/arch/arm/boot/dts/rk3188-clocks.dtsi +++ b/arch/arm/boot/dts/rk3188-clocks.dtsi @@ -276,6 +276,7 @@ clocks = <&clk_i2s_div>, <&clk_i2s_frac>, <&xin12m>; clock-output-names = "clk_i2s"; rockchip,clkops-idx = ; + rockchip,flags = ; #clock-cells = <0>; }; @@ -308,6 +309,7 @@ clocks = <&clk_spdif_div>, <&clk_spdif_frac>, <&xin12m>; clock-output-names = "clk_spdif"; rockchip,clkops-idx = ; + rockchip,flags = ; #clock-cells = <0>; }; @@ -496,6 +498,7 @@ <&xin24m>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_uart0"; #clock-cells = <0>; }; @@ -528,6 +531,7 @@ <&xin24m>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_uart1"; #clock-cells = <0>; }; @@ -560,6 +564,7 @@ <&xin24m>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_uart2"; #clock-cells = <0>; }; @@ -592,6 +597,7 @@ <&xin24m>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_uart3"; #clock-cells = <0>; }; @@ -612,7 +618,7 @@ /* numerator denominator */ rockchip,bits = <0 32>; rockchip,clkops-idx = - ; + ; #clock-cells = <0>; }; }; @@ -628,7 +634,7 @@ /* numerator denominator */ rockchip,bits = <0 32>; rockchip,clkops-idx = - ; + ; #clock-cells = <0>; }; }; @@ -644,7 +650,7 @@ /* numerator denominator */ rockchip,bits = <0 32>; rockchip,clkops-idx = - ; + ; #clock-cells = <0>; }; }; @@ -660,7 +666,7 @@ /* numerator denominator */ rockchip,bits = <0 32>; rockchip,clkops-idx = - ; + ; #clock-cells = <0>; }; }; @@ -687,6 +693,7 @@ clocks = <&clk_mac_pll_mux>, <&rmii_clkin>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_mac"; #clock-cells = <0>; }; @@ -697,6 +704,8 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 5>; clocks = <&clk_mac_pll_mux>; + rockchip,clkops-idx = + ; rockchip,div-type = ; }; @@ -727,6 +736,7 @@ <&clk_hsadc_ext>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_hsadc"; #clock-cells = <0>; }; @@ -762,7 +772,7 @@ /* numerator denominator */ rockchip,bits = <0 32>; rockchip,clkops-idx = - ; + ; #clock-cells = <0>; }; }; @@ -907,6 +917,8 @@ rockchip,bits = <1 5>; clocks = <&cif_out_pll_mux>; rockchip,div-type = ; + rockchip,clkops-idx = + ; }; /* reg[6]: reserved */ @@ -917,6 +929,7 @@ clocks = <&cif_out_pll_mux>, <&xin24m>; rockchip,clkops-idx = ; + rockchip,flags = ; clock-output-names = "clk_cif0"; #clock-cells = <0>; }; diff --git a/drivers/clk/rockchip/clk-ops.c b/drivers/clk/rockchip/clk-ops.c index bf9bc8f99b25..8527f1aa6130 100644 --- a/drivers/clk/rockchip/clk-ops.c +++ b/drivers/clk/rockchip/clk-ops.c @@ -5,18 +5,22 @@ #include #include #include -#include "clk-ops.h" #include +#include "clk-ops.h" + + + /* mux_ops */ struct clk_ops_table rk_clk_mux_ops_table[] = { {.index = CLKOPS_TABLE_END}, }; + +/* rate_ops */ #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) #define div_mask(d) ((1 << ((d)->width)) - 1) -#define MHZ (1000 * 1000) static u32 clk_gcd(u32 numerator, u32 denominator) { u32 a, b; @@ -48,7 +52,7 @@ static int clk_fracdiv_get_config(unsigned long rate_out, unsigned long rate, __func__, rate_out, rate, gcd_val); if (!gcd_val) { - clk_err("gcd=0, i2s frac div is not be supported\n"); + clk_err("gcd=0, frac div is not be supported\n"); return -EINVAL; } @@ -75,21 +79,17 @@ static int clk_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate, u32 numerator, denominator; struct clk_divider *div = to_clk_divider(hw); - struct clk *clk_parent = hw->clk->parent; + if(clk_fracdiv_get_config(rate, parent_rate, &numerator, &denominator) == 0) { - - clk_parent->ops->set_rate(clk_parent->hw, - clk_parent->parent->rate, - clk_parent->parent->rate); writel(numerator << 16 | denominator, div->reg); - clk_err("%s set rate=%lu,is ok\n", hw->clk->name, rate); - + clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate); } else { - clk_err("clk_frac_div can't get rate=%lu,%s\n", - rate, hw->clk->name); - return -ENOENT; + clk_err("clk_frac_div name=%s can't get rate=%lu\n", + hw->clk->name, rate); + return -EINVAL; } + return 0; } @@ -100,9 +100,11 @@ static unsigned long clk_fracdiv_recalc(struct clk_hw *hw, u64 rate64; struct clk_divider *div = to_clk_divider(hw); u32 numerator, denominator, reg_val; + reg_val = readl(div->reg); if (reg_val == 0) return parent_rate; + numerator = reg_val >> 16; denominator = reg_val & 0xFFFF; rate64 = (u64)parent_rate * numerator; @@ -113,172 +115,102 @@ static unsigned long clk_fracdiv_recalc(struct clk_hw *hw, numerator, denominator); return rate; } + static long clk_fracdiv_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - return rate; -} -/*************************************************************************/ -/* rate_ops */ -#define PARENTS_NUM_MAX 3 -/* - * get the best rate from array of available rates, regarding rate which is smaller than - * and most close to the set_rate as the best. - */ -static long get_best_rate(unsigned long array[],unsigned int num, int *n, long rate) -{ - int i = 0; - unsigned long best_rate = 0; - - for(i = 0; i < num; i++){ - if(array[i] == rate){ - *n = i; - return array[i]; - }else if((array[i] < rate) && (array[i] > best_rate)){ - best_rate = array[i]; - *n = i; - } - } + struct clk *clk = hw->clk; + struct clk *parent = clk->parent; + long rate_out; - if(best_rate == 0){ - clk_err("NOT array rate is <= %lu\n", rate); - }else{ - clk_debug("get the best available rate,but it != %lu you want to set!\n", rate); - } + //FIXME: now just simply return rate + /* + *frac_div request a big input rate, and its parent is always a div, + *so we set parent->parent->rate as best_parent_rate. + */ + rate_out = rate; + *prate = parent->parent->rate; - return best_rate; + return rate_out; } -static struct clk *clk_get_best_parent(struct clk_hw *hw, unsigned long rate, - unsigned int *div_out) +static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) { - struct clk *clk = hw->clk; - u32 div[PARENTS_NUM_MAX] = {0}; - unsigned long new_rate[PARENTS_NUM_MAX] = {0}; - unsigned long best_rate; - u32 i; - - memset(div, 0, sizeof(div)); - memset(new_rate, 0, sizeof(new_rate)); - - if(clk->rate == rate) - return clk->parent; - - for(i = 0; i < clk->num_parents; i++) { - new_rate[i] = clk_divider_ops.round_rate(hw, rate, - &(clk->parents[i]->rate)); - div[i] = (clk->parents[i]->rate)/new_rate[i]; - if(new_rate[i] == rate) { - *div_out = div[i]; - return clk->parents[i]; - } - } - - best_rate = get_best_rate(new_rate, PARENTS_NUM_MAX, &i, rate); - if(best_rate == 0){ - clk_err("NOT rate is good!\n"); - return NULL; - } - - *div_out = div[i]; - - return clk->parents[i]; + return clk_divider_ops.recalc_rate(hw, parent_rate); } -static long clk_div_round_rate_autosel_parents(struct clk_hw *hw, +static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk *clk = hw->clk; - struct clk *new_parent; - int new_div; - - if(clk->rate == rate) - return rate; - - new_parent = clk_get_best_parent(hw, rate, &new_div); - if(!new_parent || (new_div <= 0)){ - clk_err("%s: clk %s could not get new_parent or new_div\n", - __func__,clk->name); - return -EINVAL; - } - - return (new_parent->rate)/new_div; + return clk_divider_ops.round_rate(hw, rate, prate); } - -static int clk_div_set_rate_autosel_parents(struct clk_hw *hw, +static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - //struct clk_divider *divider = to_clk_divider(hw); - struct clk *clk = hw->clk; - struct clk *new_parent; - unsigned int new_div,old_div; - unsigned long new_rate; - int ret = 0; - u8 index; - int i; - - if(clk->rate == rate) + return clk_divider_ops.set_rate(hw, rate, parent_rate); +} + +static long clk_mux_with_div_determine_rate(struct clk_hw *div_hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_p) +{ + struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL; + int i, num_parents; + unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0; + + + parent = __clk_get_parent(clk); + if(!parent){ + best = __clk_get_rate(clk); goto out; + } - new_parent = clk_get_best_parent(hw, rate, &new_div); - if(!new_parent || (new_div == 0)){ - clk_err("%s: clk %s could not get new_parent or get " - "new_div = 0\n", __func__,clk->name); - ret = -EINVAL; + /* if NO_REPARENT flag set, pass through to current parent */ + if (clk->flags & CLK_SET_RATE_NO_REPARENT) { + best_prate = __clk_get_rate(parent); + best = clk_divider_ops.round_rate(div_hw, rate, &best_prate); goto out; } - old_div = (clk->parent->rate)/(clk->rate); + /* find the parent that can provide the fastest rate <= rate */ + num_parents = clk->num_parents; + for (i = 0; i < num_parents; i++) { + parent = clk_get_parent_by_index(clk, i); + if (!parent) + continue; - clk_debug("%s:%d: %s: %lu\n", __func__, __LINE__, - clk->parent->name, new_parent->rate); - if(new_div > old_div){ - new_rate = (clk->parent->rate)/new_div; - ret = clk_divider_ops.set_rate(hw, new_rate, - (clk->parent->rate)); - if(ret) - goto out; - } + parent_rate = __clk_get_rate(parent); + now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate); - if(clk->parent != new_parent){ - for(i=0; inum_parents; i++){ - if(new_parent == clk->parents[i]){ - index = i; - break; - } + if (now <= rate && now > best) { + best_parent = parent; + best_prate = parent_rate; + best = now; } - /* - * ret = clk->ops->set_parent(clk->hw, index); - * if(ret) - * goto out; - */ - clk_set_parent(clk, new_parent); - clk->ops->recalc_rate(clk->hw, clk->parent->rate); - } - - if(new_div <= old_div){ - new_rate = (clk->parent->rate)/new_div; - ret = clk_divider_ops.set_rate(hw, new_rate, - (clk->parent->rate)); - if(ret) - goto out; } out: - return ret; -} + if(best_prate) + *best_parent_rate = best_prate; -static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return clk_divider_ops.recalc_rate(hw, hw->clk->parent->rate); + if (best_parent) + *best_parent_p = best_parent; + + clk_debug("clk name = %s, determine rate = %lu, best = %lu\n" + "\tbest_parent name = %s, best_prate = %lu\n", + clk->name, rate, best, + __clk_get_name(*best_parent_p), *best_parent_rate); + + return best; } const struct clk_ops clkops_rate_auto_parent = { .recalc_rate = clk_divider_recalc_rate, - .round_rate = clk_div_round_rate_autosel_parents, - .set_rate = clk_div_set_rate_autosel_parents, + .round_rate = clk_divider_round_rate, + .set_rate = clk_divider_set_rate, + .determine_rate = clk_mux_with_div_determine_rate, }; static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate, @@ -300,7 +232,7 @@ static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate, static int clk_div_set_rate_even(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - return clk_divider_ops.set_rate(hw, rate, hw->clk->parent->rate); + return clk_divider_ops.set_rate(hw, rate, parent_rate); } const struct clk_ops clkops_rate_evendiv = { @@ -314,9 +246,9 @@ static long dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate, { long ret = 0; if (rate == 27 * MHZ) { - ret = clk_div_round_rate_autosel_parents(hw, rate, prate); + ret = clk_divider_round_rate(hw, rate, prate); } else { - ret = clk_div_round_rate_autosel_parents(hw, rate, prate); + ret = clk_divider_round_rate(hw, rate, prate); } return ret; } @@ -324,81 +256,17 @@ static long dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate, static int dclk_lcdc_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - return clk_div_set_rate_autosel_parents(hw, rate, parent_rate); + return clk_divider_set_rate(hw, rate, parent_rate); } const struct clk_ops clkops_rate_dclk_lcdc = { .recalc_rate = clk_divider_recalc_rate, .round_rate = dclk_lcdc_round_rate, .set_rate = dclk_lcdc_set_rate, + .determine_rate = clk_mux_with_div_determine_rate, }; -#define CIF_OUT_SRC_DIV (0x0) -#define CIF_OUT_SRC_24M (0x1) - -static unsigned long cif_out_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return hw->clk->parent->rate; -} - -static long cif_out_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk *clk = hw->clk; - struct clk *parent; - - if (rate == clk->parents[CIF_OUT_SRC_24M]->rate) { - return rate; - } else { - parent = clk->parents[CIF_OUT_SRC_DIV]; - return parent->ops->round_rate(parent->hw, rate, - &(parent->parent->rate)); - } -} - -static int cif_out_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk *clk = hw->clk; - struct clk *parent; - int ret = 0; - - if (rate == clk->parents[CIF_OUT_SRC_24M]->rate) { - parent = clk->parents[CIF_OUT_SRC_24M]; - } else { - parent = clk->parents[CIF_OUT_SRC_DIV]; - ret = parent->ops->set_rate(parent->hw, rate, - parent->parent->rate); - if (ret) - goto out; - else - parent->rate = rate; - } - - if(clk->parent != parent){ - ret = clk_set_parent(clk, parent); #if 0 - for(i=0; inum_parents; i++){ - if(parent == clk->parents[i]){ - index = i; - break; - } - } - ret = clk->ops->set_parent(clk->hw, index); -#endif - if(ret) - goto out; - } -out: - return ret; -} -const struct clk_ops clkops_rate_cif_out = { - .recalc_rate = cif_out_recalc_rate, - .round_rate = cif_out_round_rate, - .set_rate = cif_out_set_rate, -}; - static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -428,387 +296,46 @@ static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate, } return 0; } +#endif -const struct clk_ops clkops_rate_i2s_frac = { - .recalc_rate = clk_fracdiv_recalc, - .round_rate = clk_fracdiv_round_rate, - .set_rate = clk_i2s_fracdiv_set_rate, -}; -static unsigned long clk_i2s_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return hw->clk->parent->rate; -} - -static long clk_i2s_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} - -#define I2S_SRC_DIV (0x0) -#define I2S_SRC_FRAC (0x1) -#define I2S_SRC_12M (0x2) -static int clk_i2s_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int ret = -EINVAL; - u8 p_index = 0; - struct clk *parent_tmp, *parent; - struct clk *clk = hw->clk; - - - if (rate == clk->parents[I2S_SRC_12M]->rate) { - parent = clk->parents[I2S_SRC_12M]; - p_index = I2S_SRC_12M; - goto set_parent; - } - - parent_tmp = clk->parents[I2S_SRC_DIV]; - - if(parent_tmp->ops->round_rate(parent_tmp->hw, rate, - &parent_tmp->parent->rate) == rate) { - parent = clk->parents[I2S_SRC_DIV]; - p_index = I2S_SRC_DIV; - goto set; - } - - parent = clk->parents[I2S_SRC_FRAC]; - p_index = I2S_SRC_FRAC; - //ret = clk_set_rate(parent_tmp, parent_tmp->parent->rate); - ret = parent_tmp->ops->set_rate(parent_tmp->hw, - parent_tmp->parent->rate, - parent_tmp->parent->rate); - parent_tmp->rate = parent_tmp->ops->recalc_rate(parent_tmp->hw, - parent_tmp->parent->rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - -set: - clk_debug(" %s set rate=%lu parent %s(old %s)\n", - clk->name, rate, parent->name, clk->parent->name); - - ret = clk_set_rate(parent, rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - -set_parent: - clk_debug("%s: set parent\n", __func__); - if (clk->parent != parent) { - ret = clk_set_parent(clk, parent); - /* - * clk->ops->set_parent(hw, p_index); - */ - if (ret) { - clk_debug("%s can't get rate%lu,reparent err\n", - clk->name, rate); - return ret; - } - } - - return ret; -} - -const struct clk_ops clkops_rate_i2s = { - .recalc_rate = clk_i2s_recalc_rate, - .round_rate = clk_i2s_round_rate, - .set_rate = clk_i2s_set_rate, -}; -const struct clk_ops clkops_rate_hsadc_frac = { +const struct clk_ops clkops_rate_frac = { .recalc_rate = clk_fracdiv_recalc, .round_rate = clk_fracdiv_round_rate, .set_rate = clk_fracdiv_set_rate, }; - -const struct clk_ops clkops_rate_uart_frac = { +const struct clk_ops clkops_rate_i2s_frac = { .recalc_rate = clk_fracdiv_recalc, .round_rate = clk_fracdiv_round_rate, .set_rate = clk_fracdiv_set_rate, }; -static unsigned long clk_uart_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return hw->clk->parent->rate; - -} -static long clk_uart_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} - -#define UART_SRC_DIV (0x0) -#define UART_SRC_FRAC (0x1) -#define UART_SRC_24M (0x2) -static int clk_uart_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int ret = -EINVAL; - u8 p_index = 0; - struct clk *parent_tmp, *parent; - struct clk *clk = hw->clk; - - - if (rate == clk->parents[UART_SRC_24M]->rate) { - parent = clk->parents[UART_SRC_24M]; - p_index = UART_SRC_24M; - goto set_parent; - } - - parent_tmp = clk->parents[UART_SRC_DIV]; - - if(parent_tmp->ops->round_rate(parent_tmp->hw, rate, - &parent_tmp->parent->rate) == rate) { - parent = clk->parents[UART_SRC_DIV]; - p_index = UART_SRC_DIV; - goto set; - } - - parent = clk->parents[UART_SRC_FRAC]; - p_index = UART_SRC_FRAC; - /* - * ret = clk_set_rate(parent_tmp, parent_tmp->parent->rate); - */ - ret = parent_tmp->ops->set_rate(parent_tmp->hw, - parent_tmp->parent->rate, - parent_tmp->parent->rate); - parent_tmp->rate = parent_tmp->ops->recalc_rate(parent_tmp->hw, - parent_tmp->parent->rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - -set: - clk_debug(" %s set rate=%lu parent %s(old %s)\n", - clk->name, rate, parent->name, clk->parent->name); - - ret = clk_set_rate(parent, rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - -set_parent: - clk_debug("%s: set parent\n", __func__); - if (clk->parent != parent) { - ret = clk_set_parent(clk, parent); - /* - * clk->ops->set_parent(hw, p_index); - */ - if (ret) { - clk_debug("%s can't get rate%lu,reparent err\n", - clk->name, rate); - return ret; - } - } - - return ret; -} - - -const struct clk_ops clkops_rate_uart = { - .recalc_rate = clk_uart_recalc_rate, - .round_rate = clk_uart_round_rate, - .set_rate = clk_uart_set_rate, -}; - - -static unsigned long clk_hsadc_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return hw->clk->parent->rate; - -} -static long clk_hsadc_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} - -#define HSADC_SRC_DIV (0x0) -#define HSADC_SRC_FRAC (0x1) -#define HSADC_SRC_EXT (0x2) -static int clk_hsadc_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int ret = -EINVAL; - u8 p_index = 0; - struct clk *parent_tmp, *parent; - struct clk *clk = hw->clk; - - - if (rate == clk->parents[HSADC_SRC_EXT]->rate) { - parent = clk->parents[HSADC_SRC_EXT]; - p_index = HSADC_SRC_EXT; - goto set_parent; - } - - parent_tmp = clk->parents[HSADC_SRC_DIV]; - - if(parent_tmp->ops->round_rate(parent_tmp->hw, rate, - &parent_tmp->parent->rate) == rate) { - parent = clk->parents[HSADC_SRC_DIV]; - p_index = HSADC_SRC_DIV; - goto set; - } - - parent = clk->parents[HSADC_SRC_FRAC]; - p_index = HSADC_SRC_FRAC; - /* - * ret = clk_set_rate(parent_tmp, parent_tmp->parent->rate); - */ - ret = parent_tmp->ops->set_rate(parent_tmp->hw, - parent_tmp->parent->rate, - parent_tmp->parent->rate); - parent_tmp->rate = parent_tmp->ops->recalc_rate(parent_tmp->hw, - parent_tmp->parent->rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - - - -set: - clk_debug(" %s set rate=%lu parent %s(old %s)\n", - clk->name, rate, parent->name, clk->parent->name); - - ret = clk_set_rate(parent, rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - -set_parent: - clk_debug("%s: set parent\n", __func__); - if (clk->parent != parent) { - ret = clk_set_parent(clk, parent); - /* - * clk->ops->set_parent(hw, p_index); - */ - if (ret) { - clk_debug("%s can't get rate%lu,reparent err\n", - clk->name, rate); - return ret; - } - } - - return ret; -} - - -const struct clk_ops clkops_rate_hsadc = { - .recalc_rate = clk_hsadc_recalc_rate, - .round_rate = clk_hsadc_round_rate, - .set_rate = clk_hsadc_set_rate, -}; - -static unsigned long clk_mac_ref_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return hw->clk->parent->rate; - -} -static long clk_mac_ref_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} - -#define MAC_SRC_DIV (0x0) -#define RMII_CLKIN (0x1) -static int clk_mac_ref_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int ret = -EINVAL; - u8 p_index = 0; - struct clk *parent; - struct clk *clk = hw->clk; - - clk_debug("%s: rate %lu\n", __func__, rate); - - if (rate == clk->parents[RMII_CLKIN]->rate) { - parent = clk->parents[RMII_CLKIN]; - p_index = RMII_CLKIN; - goto set_parent; - } - - parent = clk->parents[MAC_SRC_DIV]; - p_index = MAC_SRC_DIV; - - clk_debug(" %s set rate=%lu parent %s(old %s)\n", - clk->name, rate, parent->name, clk->parent->name); - - /* - * ret = clk_set_rate(parent, rate); - */ - ret = parent->ops->set_rate(parent->hw, - rate, - parent->parent->rate); - parent->rate = parent->ops->recalc_rate(parent->hw, - parent->parent->rate); - //ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate); - if (ret) { - clk_debug("%s set rate%lu err\n", clk->name, rate); - return ret; - } - -set_parent: - clk_debug("%s: set parent\n", __func__); - if (clk->parent != parent) { - ret = clk_set_parent(clk, parent); - /* - * clk->ops->set_parent(hw, p_index); - */ - if (ret) { - clk_debug("%s can't get rate%lu,reparent err\n", - clk->name, rate); - return ret; - } - } - - return ret; -} - - -const struct clk_ops clkops_rate_mac_ref = { - .recalc_rate = clk_mac_ref_recalc_rate, - .round_rate = clk_mac_ref_round_rate, - .set_rate = clk_mac_ref_set_rate, -}; - - struct clk_ops_table rk_clkops_rate_table[] = { {.index = CLKOPS_RATE_MUX_DIV, .clk_ops = &clkops_rate_auto_parent}, {.index = CLKOPS_RATE_EVENDIV, .clk_ops = &clkops_rate_evendiv}, {.index = CLKOPS_RATE_DCLK_LCDC, .clk_ops = &clkops_rate_dclk_lcdc}, - {.index = CLKOPS_RATE_CIFOUT, .clk_ops = &clkops_rate_cif_out}, {.index = CLKOPS_RATE_I2S_FRAC, .clk_ops = &clkops_rate_i2s_frac}, - {.index = CLKOPS_RATE_I2S, .clk_ops = &clkops_rate_i2s}, - {.index = CLKOPS_RATE_HSADC_FRAC, .clk_ops = &clkops_rate_hsadc_frac}, - {.index = CLKOPS_RATE_UART_FRAC, .clk_ops = &clkops_rate_uart_frac}, - {.index = CLKOPS_RATE_UART, .clk_ops = &clkops_rate_uart}, - {.index = CLKOPS_RATE_HSADC, .clk_ops = &clkops_rate_hsadc}, - {.index = CLKOPS_RATE_MAC_REF, .clk_ops = &clkops_rate_mac_ref}, - - - {.index = CLKOPS_TABLE_END}, + {.index = CLKOPS_RATE_FRAC, .clk_ops = &clkops_rate_frac}, + {.index = CLKOPS_RATE_I2S, .clk_ops = NULL}, + {.index = CLKOPS_RATE_CIFOUT, .clk_ops = NULL}, + {.index = CLKOPS_RATE_UART, .clk_ops = NULL}, + {.index = CLKOPS_RATE_HSADC, .clk_ops = NULL}, + {.index = CLKOPS_RATE_MAC_REF, .clk_ops = NULL}, + {.index = CLKOPS_TABLE_END, .clk_ops = NULL}, }; -const struct clk_ops *rk_get_clkops(u32 idx) + +const struct clk_ops *rk_get_clkops(unsigned int idx) { - return rk_clkops_rate_table[idx].clk_ops; + int i = 0; + unsigned int now_idx; + + while(1){ + now_idx = rk_clkops_rate_table[i].index; + + if ((now_idx == idx) || (now_idx == CLKOPS_TABLE_END)) + return rk_clkops_rate_table[i].clk_ops; + + i++; + } } EXPORT_SYMBOL_GPL(rk_get_clkops); diff --git a/drivers/clk/rockchip/clk-ops.h b/drivers/clk/rockchip/clk-ops.h index e3bfb85ef79a..57d0b8c91e1b 100644 --- a/drivers/clk/rockchip/clk-ops.h +++ b/drivers/clk/rockchip/clk-ops.h @@ -1,12 +1,19 @@ #ifndef __RK_CLK_OPS_H #define __RK_CLK_OPS_H #include "clkops-dtsi.h" + + +#define MHZ (1000UL * 1000UL) +#define KHZ (1000UL) + struct clk_ops_table { unsigned int index; const struct clk_ops *clk_ops; }; -const struct clk_ops *rk_get_clkops(u32 idx); +const struct clk_ops *rk_get_clkops(unsigned int idx); + //#define RKCLK_DEBUG +//#define RKCLK_TEST #if defined(RKCLK_DEBUG) #define clk_debug(fmt, args...) printk(KERN_INFO "rkclk: "fmt, ##args) diff --git a/drivers/clk/rockchip/clk-pll.h b/drivers/clk/rockchip/clk-pll.h index e803b7505c62..17fe386364d6 100644 --- a/drivers/clk/rockchip/clk-pll.h +++ b/drivers/clk/rockchip/clk-pll.h @@ -5,8 +5,6 @@ #include -#define MHZ (1000UL * 1000UL) -#define KHZ (1000UL) #define CLK_LOOPS_JIFFY_REF (11996091ULL) #define CLK_LOOPS_RATE_REF (1200UL) //Mhz #define CLK_LOOPS_RECALC(rate) \ diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 5653a404065b..aa9a4f23b371 100755 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -24,8 +24,6 @@ #include "clk-pll.h" -static DEFINE_SPINLOCK(clk_lock); - struct rkclk_divmap_table { u32 reg_val; u32 div_val; @@ -53,6 +51,7 @@ struct rkclk_muxinfo { u32 width; u32 parent_num; u32 clkops_idx; + u32 flags; const char *clk_name; const char **parent_names; struct list_head node; @@ -108,8 +107,10 @@ struct rkclk { struct list_head node; }; +static DEFINE_SPINLOCK(clk_lock); LIST_HEAD(rk_clks); void __iomem *reg_start = 0; + #define RKCLK_PLL_TYPE (1 << 0) #define RKCLK_MUX_TYPE (1 << 1) #define RKCLK_DIV_TYPE (1 << 2) @@ -132,6 +133,11 @@ static int rkclk_init_muxinfo(struct device_node *np, ret = of_property_read_u32_index(np, "rockchip,bits", 0, &mux->shift); if (ret != 0) return -EINVAL; + + ret = of_property_read_u32(np, "rockchip,flags", &mux->flags); + if (ret != 0) + mux->flags = 0; + ret = of_property_read_u32(np, "rockchip,clkops-idx", &mux->clkops_idx); if (ret != 0) mux->clkops_idx = CLKOPS_TABLE_END; @@ -186,6 +192,7 @@ static int rkclk_init_muxinfo(struct device_node *np, } return 0; } + static int rkclk_init_divinfo(struct device_node *np, struct rkclk_divinfo *div, void __iomem *addr) { @@ -202,6 +209,7 @@ static int rkclk_init_divinfo(struct device_node *np, div->addr = addr; of_property_read_u32(np, "rockchip,div-type", &div->div_type); + ret = of_property_read_u32(np, "rockchip,clkops-idx", &div->clkops_idx); if (ret != 0) div->clkops_idx = CLKOPS_TABLE_END; @@ -276,6 +284,7 @@ static int rkclk_init_divinfo(struct device_node *np, } + static int rkclk_init_fracinfo(struct device_node *np, struct rkclk_fracinfo *frac, void __iomem *addr) { @@ -448,6 +457,7 @@ static int __init rkclk_init_gatecon(struct device_node *np) } return 0; } + static int __init rkclk_init_pllcon(struct device_node *np) { struct rkclk_pllinfo *pllinfo; @@ -529,27 +539,6 @@ static int __init rkclk_init_pllcon(struct device_node *np) return 0; } - -static unsigned long clk_frac_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return parent_rate; -} -static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} -static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - return 0; -} -const struct clk_ops clk_frac_ops = { - .recalc_rate = clk_frac_recalc_rate, - .round_rate = clk_frac_round_rate, - .set_rate = clk_frac_set_rate, -}; static unsigned long clk_div_special_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -565,12 +554,14 @@ static int clk_div_special_set_rate(struct clk_hw *hw, unsigned long rate, { return 0; } + // For fixed div clks and For user defined div clk const struct clk_ops clk_div_special_ops = { .recalc_rate = clk_div_special_recalc_rate, .round_rate = clk_div_special_round_rate, .set_rate = clk_div_special_set_rate, }; + static int rkclk_register(struct rkclk *rkclk) { struct clk_mux *mux = NULL; @@ -586,9 +577,11 @@ static int rkclk_register(struct rkclk *rkclk) struct clk_hw *rate_hw; int parent_num; struct device_node *node = rkclk->np; - /* Single clk */ - clk_debug("%s: %s clk_type=%x\n", __func__, - rkclk->clk_name, rkclk->clk_type); + unsigned long flags = 0; + + + clk_debug("%s >>>>>start: clk_name=%s, clk_type=%x\n", + __func__, rkclk->clk_name, rkclk->clk_type); if (rkclk->clk_type & RKCLK_PLL_TYPE) { pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL); @@ -604,19 +597,19 @@ static int rkclk_register(struct rkclk *rkclk) } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) { div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); - if (rkclk->frac_info->clkops_idx != CLKOPS_TABLE_END) - rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx); - else - rate_ops = &clk_frac_ops; div->reg = rkclk->frac_info->addr; div->shift = (u8)rkclk->frac_info->shift; div->width = rkclk->frac_info->width; div->flags = CLK_DIVIDER_HIWORD_MASK; + rate_hw = &div->hw; + rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx); parent_num = 1; parent_names = &rkclk->frac_info->parent_name; + flags |= CLK_SET_RATE_PARENT; + } else if (rkclk->clk_type & RKCLK_DIV_TYPE) { div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); if (rkclk->div_info->clkops_idx != CLKOPS_TABLE_END) @@ -655,6 +648,7 @@ static int rkclk_register(struct rkclk *rkclk) parent_num = rkclk->mux_info->parent_num; parent_names = rkclk->mux_info->parent_names; + flags |= rkclk->mux_info->flags; } if (rkclk->clk_type & RKCLK_GATE_TYPE) { @@ -668,46 +662,43 @@ static int rkclk_register(struct rkclk *rkclk) // FIXME: flag(CLK_IGNORE_UNUSED) may need an input argument if (rkclk->clk_type == RKCLK_MUX_TYPE && rkclk->mux_info->clkops_idx == CLKOPS_TABLE_END) { + clk_debug("use clk_register_mux\n"); clk = clk_register_mux(NULL, rkclk->clk_name, rkclk->mux_info->parent_names, (u8)rkclk->mux_info->parent_num, - CLK_SET_RATE_PARENT, - mux->reg, mux->shift, mux->mask, + flags, mux->reg, mux->shift, mux->mask, 0, &clk_lock); } else if (rkclk->clk_type == RKCLK_DIV_TYPE) { + clk_debug("use clk_register_divider\n"); clk = clk_register_divider(NULL, rkclk->clk_name, rkclk->div_info->parent_name, - CLK_SET_RATE_PARENT, div->reg, div->shift, + flags, div->reg, div->shift, div->width, div->flags, &clk_lock); } else if (rkclk->clk_type == RKCLK_GATE_TYPE) { + clk_debug("use clk_register_gate\n"); clk = clk_register_gate(NULL, rkclk->clk_name, rkclk->gate_info->parent_name, - CLK_IGNORE_UNUSED, gate->reg, + flags, gate->reg, gate->bit_idx, gate->flags, &clk_lock); } else if (rkclk->clk_type == RKCLK_PLL_TYPE) { + clk_debug("use rk_clk_register_pll\n"); clk = rk_clk_register_pll(NULL, rkclk->clk_name, rkclk->pll_info->parent_name, - 0, pll->reg, pll->width, pll->id, - &clk_lock); + flags, pll->reg, pll->width, + pll->id, &clk_lock); } else { - int i = 0; - clk_debug("%s: composite clk(\"%s\") parents:\n", - __func__, rkclk->clk_name); - - for (i = 0; i < parent_num; i++) { - clk_debug("\t\t%s: parent[%d]=%s\n", __func__, - i, parent_names[i]); - } - + clk_debug("use clk_register_composite\n"); clk = clk_register_composite(NULL, rkclk->clk_name, parent_names, parent_num, mux ? &mux->hw : NULL, mux ? mux_ops : NULL, rate_hw, rate_ops, gate ? &gate->hw : NULL, gate ? &clk_gate_ops : NULL, - CLK_IGNORE_UNUSED); + flags); } + if (clk) { + clk_debug("clk name=%s, flags=0x%lx\n", clk->name, clk->flags); of_clk_add_provider(node, of_clk_src_simple_get, clk); clk_register_clkdev(clk, rkclk->clk_name, NULL); } else { @@ -718,39 +709,51 @@ static int rkclk_register(struct rkclk *rkclk) return 0; } +#ifdef RKCLK_TEST struct test_table { const char *name; u32 rate; }; + struct test_table t_table[] = { {.name = "clk_gpu", .rate = 297000000}, - {.name = "dclk_lcdc0", .rate = 297000000}, - {.name = "clk_i2s", .rate = 11289600}, - {.name = "clk_spdif", .rate = 11289600}, + {.name = "dclk_lcdc0", .rate = 100000000}, + {.name = "aclk_lcdc0", .rate = 297000000}, + {.name = "clk_sdmmc", .rate = 50000000}, {.name = "clk_emmc", .rate = 50000000}, {.name = "clk_sdio", .rate = 50000000}, + + {.name = "clk_i2s_div", .rate = 300000000}, + {.name = "clk_i2s_frac",.rate = 22579200}, + {.name = "clk_i2s", .rate = 11289600}, + {.name = "clk_spdif", .rate = 11289600}, + + {.name = "cif_out_pll", .rate = 48000000}, + {.name = "clk_cif0", .rate = 12000000}, + {.name = "clk_uart0", .rate = 12288000}, + {.name = "clk_uart1", .rate = 48000000}, {.name = "clk_hsadc", .rate = 12288000}, {.name = "clk_mac", .rate = 50000000}, - {.name = "clk_cif0", .rate = 12000000}, - {.name = "aclk_lcdc0", .rate = 297000000}, - {.name = "clk_apll", .rate = 600000000}, - {.name = "clk_dpll", .rate = 600000000}, + + {.name = "clk_apll", .rate = 500000000}, + {.name = "clk_dpll", .rate = 400000000}, {.name = "clk_cpll", .rate = 600000000}, {.name = "clk_gpll", .rate = 800000000}, }; - -#ifdef RKCLK_DEBUG void rk_clk_test(void) { const char *clk_name; struct clk *clk; - u32 rate,recalc_rate,round_rate = 0; - + unsigned long rate=0, recalc_rate=0, round_rate=0, get_rate=0; u32 i = 0, j = 0; + int ret; + for (j = 0; j < ARRAY_SIZE(t_table); j++) { + clk_debug(">>>>>>test %u\n", j); + clk_name = t_table[j].name; rate = t_table[j].rate; @@ -760,55 +763,50 @@ void rk_clk_test(void) __func__, clk_name); } else clk_debug("%s: clk(\"%s\") \tclk_get success\n", - __func__, __clk_get_name(clk)); + __func__, clk_name); - /*TEST: clk_round_rate*/ - if (clk->ops->round_rate) { - round_rate = clk_round_rate(clk, rate); - clk_debug("%s: clk(\"%s\") \tclk_round_rate from %lu to %lu\n", - __func__, __clk_get_name(clk), - rate, round_rate); - } else { - clk_debug("%s: clk(\"%s\") have no round ops\n", - __func__, clk->name); - } + /* TEST: clk_round_rate */ + round_rate = clk_round_rate(clk, rate); + clk_debug("%s: clk(\"%s\") \tclk_round_rate from %lu to %lu\n", + __func__, clk_name, rate, round_rate); /* TEST: clk_set_rate */ - if (clk->ops->set_rate) { - if (0 != clk_set_rate(clk, rate)) { - clk_err("%s: clk(\"%s\") \tclk_set_rate error\n", - __func__, clk_name); - } else { - clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n", - __func__, __clk_get_name(clk)); - } + ret = clk_set_rate(clk, rate); + if (ret) { + clk_err("%s: clk(\"%s\") \tclk_set_rate error, ret=%d\n", + __func__, clk_name, ret); } else { - clk_debug("%s: clk(\"%s\") have no set ops\n", - __func__, clk->name); + clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n", + __func__, clk_name); } - /*TEST: clk_recalc_rate*/ + /* TEST: recalc_rate\clk_get_rate */ if (clk->ops->recalc_rate) { recalc_rate = clk->ops->recalc_rate(clk->hw, - clk->parent->rate); + clk->parent->rate); clk_debug("%s: clk(\"%s\") \tclk_recalc_rate %lu\n", - __func__, __clk_get_name(clk), - recalc_rate); + __func__, clk_name, recalc_rate); } else { clk_debug("%s: clk(\"%s\") have no recalc ops\n", - __func__, clk->name); + __func__, clk_name); + get_rate = clk_get_rate(clk); + clk_debug("%s: clk(\"%s\") \tclk_get_rate %lu\n", + __func__, clk_name, get_rate); } - } +#if 0 + printk("\n"); + printk("dump cru regs:"); + for (i = 0; i * 4 <= 0xf4; i++) { + if (i % 4 == 0) + printk("\n%s: \t[0x%08x]: ", + __func__, 0x20000000 + i * 4); + printk("%08x ", readl(reg_start + i * 4)); + } + printk("\n\n"); - printk("dump cru regs:\n"); - for (i = 0; i * 4 <= 0xf4; i++) { - if (i % 4 == 0) - printk("\n%s: \t[0x%08x]: ", - __func__, 0x20000000 + i * 4); - printk("%08x ", readl(reg_start + i * 4)); +#endif } - printk("\n\n"); } EXPORT_SYMBOL_GPL(rk_clk_test); @@ -816,28 +814,23 @@ EXPORT_SYMBOL_GPL(rk_clk_test); void rk_clk_test(void){}; EXPORT_SYMBOL_GPL(rk_clk_test); #endif -extern void clk_dump_tree(void); - void rkclk_init_clks(struct device_node *node); static void __init rk_clk_tree_init(struct device_node *np) { struct device_node *node; - + struct device_node *node_init; struct rkclk *rkclk; node_init=of_find_node_by_name(NULL,"clocks-init"); if(!node_init) - { - printk("%s:can not get clocks-init node\n",__FUNCTION__); + { + printk("%s:can not get clocks-init node\n",__FUNCTION__); return; } - - - for_each_available_child_of_node(np, node) { if (!ERR_PTR(of_property_match_string(node, @@ -875,7 +868,6 @@ static void __init rk_clk_tree_init(struct device_node *np) }; - #if 0 list_for_each_entry(rkclk, &rk_clks, node) { int i; @@ -909,12 +901,13 @@ static void __init rk_clk_tree_init(struct device_node *np) } } #endif + list_for_each_entry(rkclk, &rk_clks, node) { rkclk_register(rkclk); } + /* check clock parents init */ list_for_each_entry(rkclk, &rk_clks, node) { - struct clk *clk; int i = 0; const char *clk_name = rkclk->clk_name; @@ -950,9 +943,10 @@ static void __init rk_clk_tree_init(struct device_node *np) rkclk_init_clks(node_init); } -CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init); +CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init); + -/********************************** rock chip clks init****************************************/ +/********************************** rockchip clks init****************************************/ const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rate) { struct of_phandle_args clkspec; @@ -963,15 +957,15 @@ const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rat return NULL; rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells", index, - &clkspec); + &clkspec); if (rc) return NULL; if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0) return NULL; - + *rate= clkspec.args[0]; - + of_node_put(clkspec.np); return clk_name; } @@ -988,14 +982,14 @@ const char *of_clk_init_parent_get_info(struct device_node *np, int index,const return NULL; rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells", index, - &clkspec); + &clkspec); if (rc) return NULL; if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0) return NULL; - + phandle = clkspec.args[0]; of_node_put(clkspec.np); @@ -1006,21 +1000,21 @@ const char *of_clk_init_parent_get_info(struct device_node *np, int index,const if (!node) { return NULL; } - + if (of_property_read_string_index(node, "clock-output-names",0,clk_child_name) < 0) return NULL; - + of_node_put(node);//??? node=NULL; } else return NULL; - + return clk_name; } void rkclk_init_clks(struct device_node *np) -{ +{ //struct device_node *np; int i,cnt_parent,cnt_rate; u32 clk_rate; @@ -1031,36 +1025,36 @@ void rkclk_init_clks(struct device_node *np) cnt_parent = of_count_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells"); - - printk("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent); + + printk("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent); for (i = 0; i < cnt_parent; i++) { clk_parent_name=NULL; clk_name=of_clk_init_parent_get_info(np, i,&clk_parent_name); - + if(clk_name==NULL||clk_parent_name==NULL) continue; - + clk_c=clk_get(NULL,clk_name); clk_p=clk_get(NULL,clk_parent_name); printk("%s: set parent %s=%x,%s=%x\n",__FUNCTION__,clk_name,(u32)clk_c,clk_parent_name,(u32)clk_p); - if(IS_ERR(clk_c)||IS_ERR(clk_p)) + if(IS_ERR(clk_c)||IS_ERR(clk_p)) continue; //clk_set_parent(clk_name, clk_parent_name); } cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells"); - printk("%s:rate cnt=%d\n",__FUNCTION__,cnt_rate); + printk("%s:rate cnt=%d\n",__FUNCTION__,cnt_rate); for (i = 0; i < cnt_rate; i++) { clk_name=of_clk_init_rate_get_info(np, i,&clk_rate); - + if(clk_name==NULL) continue; - + clk_p=clk_get(NULL,clk_name); printk("%s: set rate %s=%x,rate=%d\n",__FUNCTION__,clk_name,(u32)clk_p,clk_rate); @@ -1068,12 +1062,8 @@ void rkclk_init_clks(struct device_node *np) if(IS_ERR(clk_c)||(clk_rate<1*1000*1000)||(clk_rate>2000*1000*1000)) continue; //clk_set_rate(clk_p,clk_rate); - - } - -} - - + } +} diff --git a/drivers/clk/rockchip/clkops-dtsi.h b/drivers/clk/rockchip/clkops-dtsi.h index 4f5c607de0f6..578e5bd81896 100644 --- a/drivers/clk/rockchip/clkops-dtsi.h +++ b/drivers/clk/rockchip/clkops-dtsi.h @@ -9,20 +9,19 @@ #define GPLL_ID 3 - /* rate_ops index */ #define CLKOPS_RATE_MUX_DIV 0 #define CLKOPS_RATE_EVENDIV 1 #define CLKOPS_RATE_DCLK_LCDC 2 -#define CLKOPS_RATE_CIFOUT 3 -#define CLKOPS_RATE_I2S_FRAC 4 +#define CLKOPS_RATE_I2S_FRAC 3 +#define CLKOPS_RATE_FRAC 4 #define CLKOPS_RATE_I2S 5 -#define CLKOPS_RATE_HSADC_FRAC 6 -#define CLKOPS_RATE_UART_FRAC 7 -#define CLKOPS_RATE_UART 8 -#define CLKOPS_RATE_HSADC 9 -#define CLKOPS_RATE_MAC_REF 10 -#define CLKOPS_TABLE_END ~0 +#define CLKOPS_RATE_CIFOUT 6 +#define CLKOPS_RATE_UART 7 +#define CLKOPS_RATE_HSADC 8 +#define CLKOPS_RATE_MAC_REF 9 +#define CLKOPS_TABLE_END (~0) + #ifndef BIT #define BIT(nr) (1 << (nr)) @@ -37,4 +36,20 @@ #define CLK_DIVIDER_USER_DEFINE BIT(7) /* CLK_DIVIDER_MASK defined the bits been used above */ #define CLK_DIVIDER_MASK (0xFF) + + +/* + * flags used across common struct clk. these flags should only affect the + * top-level framework. custom flags for dealing with hardware specifics + * belong in struct clk_foo + */ +#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */ +#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ +#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */ +#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ +#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */ +#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ +#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ +#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ + #endif /* __RK_CLKOPS_H */