rk_clk: modify clk-ops.c to reuse and fit the common clk framework.
authordkl <dkl@rock-chips.com>
Fri, 17 Jan 2014 09:52:17 +0000 (17:52 +0800)
committerdkl <dkl@rock-chips.com>
Fri, 17 Jan 2014 09:52:17 +0000 (17:52 +0800)
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.

arch/arm/boot/dts/rk3188-clocks.dtsi
drivers/clk/rockchip/clk-ops.c
drivers/clk/rockchip/clk-ops.h
drivers/clk/rockchip/clk-pll.h
drivers/clk/rockchip/clk.c
drivers/clk/rockchip/clkops-dtsi.h

index 154a461cb43058e27ec4f1651bf39c6f072bebd3..0097acce16f77d9f69cf43a1706d79e3bcdabaf2 100755 (executable)
                                                clocks = <&clk_i2s_div>, <&clk_i2s_frac>, <&xin12m>;
                                                clock-output-names = "clk_i2s";
                                                rockchip,clkops-idx = <CLKOPS_RATE_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                #clock-cells = <0>;
                                        };
 
                                                clocks = <&clk_spdif_div>, <&clk_spdif_frac>, <&xin12m>;
                                                clock-output-names = "clk_spdif";
                                                rockchip,clkops-idx = <CLKOPS_RATE_I2S>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                #clock-cells = <0>;
                                        };
 
                                                       <&xin24m>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_UART>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_uart0";
                                                #clock-cells = <0>;
                                        };
                                                       <&xin24m>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_UART>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_uart1";
                                                #clock-cells = <0>;
                                        };
                                                       <&xin24m>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_UART>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_uart2";
                                                #clock-cells = <0>;
                                        };
                                                       <&xin24m>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_UART>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_uart3";
                                                #clock-cells = <0>;
                                        };
                                                /* numerator    denominator */
                                                rockchip,bits = <0 32>;
                                                rockchip,clkops-idx =
-                                                       <CLKOPS_RATE_UART_FRAC>;
+                                                       <CLKOPS_RATE_FRAC>;
                                                #clock-cells = <0>;
                                        };
                                };
                                                /* numerator    denominator */
                                                rockchip,bits = <0 32>;
                                                rockchip,clkops-idx =
-                                                       <CLKOPS_RATE_UART_FRAC>;
+                                                       <CLKOPS_RATE_FRAC>;
                                                #clock-cells = <0>;
                                        };
                                };
                                                /* numerator    denominator */
                                                rockchip,bits = <0 32>;
                                                rockchip,clkops-idx =
-                                                       <CLKOPS_RATE_UART_FRAC>;
+                                                       <CLKOPS_RATE_FRAC>;
                                                #clock-cells = <0>;
                                        };
                                };
                                                /* numerator    denominator */
                                                rockchip,bits = <0 32>;
                                                rockchip,clkops-idx =
-                                                       <CLKOPS_RATE_UART_FRAC>;
+                                                       <CLKOPS_RATE_FRAC>;
                                                #clock-cells = <0>;
                                        };
                                };
                                                clocks = <&clk_mac_pll_mux>, <&rmii_clkin>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_MAC_REF>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_mac";
                                                #clock-cells = <0>;
                                        };
                                                compatible = "rockchip,rk3188-div-con";
                                                rockchip,bits = <8 5>;
                                                clocks = <&clk_mac_pll_mux>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
                                                rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
 
                                        };
                                                         <&clk_hsadc_ext>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_HSADC>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_hsadc";
                                                #clock-cells = <0>;
                                        };
                                                /* numerator    denominator */
                                                rockchip,bits = <0 32>;
                                                rockchip,clkops-idx =
-                                                       <CLKOPS_RATE_HSADC_FRAC>;
+                                                       <CLKOPS_RATE_FRAC>;
                                                #clock-cells = <0>;
                                        };
                                };
                                                rockchip,bits = <1 5>;
                                                clocks = <&cif_out_pll_mux>;
                                                rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
+                                               rockchip,clkops-idx =
+                                                       <CLKOPS_RATE_MUX_DIV>;
                                        };
 
                                        /* reg[6]: reserved */
                                                clocks = <&cif_out_pll_mux>, <&xin24m>;
                                                rockchip,clkops-idx =
                                                        <CLKOPS_RATE_CIFOUT>;
+                                               rockchip,flags = <CLK_SET_RATE_PARENT>;
                                                clock-output-names = "clk_cif0";
                                                #clock-cells = <0>;
                                        };
index bf9bc8f99b259bfe9b5df9d502ca0f998eccd503..8527f1aa61303dc2f12fca8d8e936ecbaa87e597 100644 (file)
@@ -5,18 +5,22 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk-private.h>
-#include "clk-ops.h"
 #include <linux/delay.h>
 
+#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; i<clk->num_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; i<clk->num_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);
index e3bfb85ef79a559f0e9c12a4264f3450410223ef..57d0b8c91e1b949a2e6a26b51aef6f38c9baafd5 100644 (file)
@@ -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)
index e803b7505c6287eb1952ffc28524350954c9c1bd..17fe386364d6a9078ef3382b5f64a1189b0ea048 100644 (file)
@@ -5,8 +5,6 @@
 #include <linux/delay.h>
 
 
-#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)  \
index 5653a404065bdbac9e5e9373ab7df39d2b2c4156..aa9a4f23b371723e2b38f2df4472e203df9c0ce7 100755 (executable)
@@ -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);
-                               
-       }
-       
-}
-
 
-       
+       }
 
+}
 
index 4f5c607de0f6d3e59c3287110349fc9344014e5f..578e5bd8189631b70895c2f984b81c0f4ccf234e 100644 (file)
@@ -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))
 #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 */