rk3368: clk: clk_add_recalc_ddr_freq.
authorzhangqing <zhangqing@rock-chips.com>
Fri, 3 Apr 2015 13:54:08 +0000 (06:54 -0700)
committerzhangqing <zhangqing@rock-chips.com>
Fri, 3 Apr 2015 13:54:08 +0000 (06:54 -0700)
Get ddr frequency correctly.

Signed-off-by: zhangqing <zhangqing@rock-chips.com>
arch/arm/mach-rockchip/common.c
arch/arm64/boot/dts/rk3368-clocks.dtsi
drivers/clk/rockchip/clk-ops.c
include/dt-bindings/clock/rockchip.h
include/linux/rockchip/common.h

index 684180eb998889fac654ec8d34d51d884a2b94bc..84f73659517958ecd07ebaba0970592c6d069c42 100755 (executable)
@@ -277,6 +277,7 @@ void (*ddr_bandwidth_get)(struct ddr_bw_info *ddr_bw_ch0,
 int (*ddr_change_freq)(uint32_t nMHz) = NULL;
 long (*ddr_round_rate)(uint32_t nMHz) = NULL;
 void (*ddr_set_auto_self_refresh)(bool en) = NULL;
+int (*ddr_recalc_rate)(void) = NULL;
 
 extern struct ion_platform_data ion_pdata;
 extern void __init ion_reserve(struct ion_platform_data *data);
index ced3d18b012029b11b8d2cdf8bac7af650be000b..4093fa6ad188b1539049d5cfbd20a0def21d53f2 100644 (file)
                                                rockchip,flags = <(CLK_GET_RATE_NOCACHE |
                                                                        CLK_SET_RATE_NO_REPARENT)>;
                                                rockchip,clkops-idx =
-                                                       <CLKOPS_RATE_DDR_DIV4>;
+                                                       <CLKOPS_RATE_RK3368_DDR>;
                                        };
 
                                        /* 3:2 reserved */
index c303239c3f1c78993c636f59003ccb4e28e81bb1..f2cb1c6572160f45fbc9348a41b8d5665a2f9784 100644 (file)
@@ -438,7 +438,7 @@ static long clk_ddr_determine_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long clk_ddr_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *prate)
+                unsigned long *prate)
 {
        return clk_ddr_determine_rate(hw, rate, prate, NULL);
 }
@@ -836,6 +836,66 @@ const struct clk_ops clkops_rate_3368_dclk_lcdc = {
        .recalc_rate    = clk_divider_recalc_rate,
 };
 
+static unsigned long clk_rk3368_ddr_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       if (!ddr_recalc_rate)
+               return (clk_core_recalc_rate(hw, parent_rate)/2);
+       else
+               return ddr_recalc_rate();
+}
+
+static long clk_ddr_determine_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *best_parent_rate,
+                       struct clk **best_parent_p)
+{
+       long best = 0;
+
+       if (!ddr_round_rate) {
+               /* Do nothing before ddr init */
+               best = rate;
+       } else {
+               /* Func provided by ddr driver */
+               best = ddr_round_rate(rate/MHZ) * MHZ;
+       }
+       clk_debug("%s: from %lu to %lu\n", __func__, rate, best);
+       return best;
+}
+static long clk_ddr_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *prate)
+{
+       return clk_ddr_determine_rate(hw, rate, prate, NULL);
+}
+static int clk_ddr_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct clk *parent = __clk_get_parent(hw->clk);
+       struct clk *grand_p = __clk_get_parent(parent);
+
+       /* Do nothing before ddr init */
+       if (!ddr_change_freq)
+               return 0;
+       if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
+               clk_err("fail to get parent or grand_parent!\n");
+               return -EINVAL;
+       }
+       clk_debug("%s: will set rate = %lu\n", __func__, rate);
+       /* Func provided by ddr driver */
+       ddr_change_freq(rate/MHZ);
+       parent->rate = parent->ops->recalc_rate(parent->hw,
+       __clk_get_rate(grand_p));
+       return 0;
+}
+
+const struct clk_ops clkops_rate_rk3368_ddr = {
+       .recalc_rate    = clk_rk3368_ddr_recalc_rate,
+       .round_rate     = clk_ddr_round_rate,
+       .set_rate       = clk_ddr_set_rate,
+       .determine_rate = clk_ddr_determine_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},
@@ -853,6 +913,7 @@ struct clk_ops_table rk_clkops_rate_table[] = {
        {.index = CLKOPS_RATE_DDR_DIV4,         .clk_ops = NULL},
        {.index = CLKOPS_RATE_RK3368_MUX_DIV_NPLL,   .clk_ops = &clkops_rate_3368_auto_parent},
        {.index = CLKOPS_RATE_RK3368_DCLK_LCDC, .clk_ops = &clkops_rate_3368_dclk_lcdc},
+       {.index = CLKOPS_RATE_RK3368_DDR,   .clk_ops = &clkops_rate_rk3368_ddr},
        {.index = CLKOPS_RATE_I2S,              .clk_ops = NULL},
        {.index = CLKOPS_RATE_CIFOUT,           .clk_ops = NULL},
        {.index = CLKOPS_RATE_UART,             .clk_ops = NULL},
index 4f8a6d4ea601378d78f7eda1855972d476cdbfd6..a7c8c5cc42ba5a41faeb7dff788282418b81e4a8 100644 (file)
@@ -70,6 +70,7 @@
 #define CLKOPS_RATE_DDR_DIV4           19
 #define CLKOPS_RATE_RK3368_MUX_DIV_NPLL 20
 #define CLKOPS_RATE_RK3368_DCLK_LCDC   21
+#define CLKOPS_RATE_RK3368_DDR         22
 
 #define CLKOPS_TABLE_END               (~0)
 
index 34d6a928cc5bdab5e5af115b0f58426c0672f455..006d52d8df04519e59e95c679a736cbe22e85196 100644 (file)
@@ -36,6 +36,7 @@ extern void (*ddr_bandwidth_get)(struct ddr_bw_info *ddr_bw_ch0,
 extern int (*ddr_change_freq)(uint32_t mhz);
 extern long (*ddr_round_rate)(uint32_t mhz);
 extern void (*ddr_set_auto_self_refresh)(bool en);
+extern int (*ddr_recalc_rate)(void);
 
 int rockchip_cpu_kill(unsigned int cpu);
 void rockchip_cpu_die(unsigned int cpu);