From 4673090895385ded057a23dcbdfff2ebe1f80f1b Mon Sep 17 00:00:00 2001 From: dkl Date: Thu, 23 Jan 2014 17:23:47 +0800 Subject: [PATCH] clk: rockchip: add clk init data and enable clk init Mainly add rk3188 clk_core\cpu_clks\peri_clks init data and apply it. --- arch/arm/boot/dts/rk3188-clocks.dtsi | 22 ++++++-- arch/arm/boot/dts/rk3188.dtsi | 14 +++-- drivers/clk/rockchip/clk-pll.c | 18 ++++--- drivers/clk/rockchip/clk.c | 78 ++++++++++++++++------------ 4 files changed, 84 insertions(+), 48 deletions(-) diff --git a/arch/arm/boot/dts/rk3188-clocks.dtsi b/arch/arm/boot/dts/rk3188-clocks.dtsi index 807503d41ae7..441cfa75abd8 100755 --- a/arch/arm/boot/dts/rk3188-clocks.dtsi +++ b/arch/arm/boot/dts/rk3188-clocks.dtsi @@ -133,18 +133,21 @@ #address-cells = <1>; #size-cells = <1>; - aclk_cpu_div: aclk_cpu_div { + aclk_cpu: aclk_cpu_div { compatible = "rockchip,rk3188-div-con"; rockchip,bits = <0 5>; - clocks = <&aclk_cpu>; + clocks = <&aclk_cpu_mux>; + clock-output-names = "aclk_cpu"; + #clock-cells = <0>; rockchip,div-type = ; + #clock-init-cells = <1>; }; - aclk_cpu: clk_cpu_mux { + aclk_cpu_mux: aclk_cpu_mux { compatible = "rockchip,rk3188-mux-con"; rockchip,bits = <5 1>; - clocks = <&clk_apll>, <&clk_gpll>; - clock-output-names = "aclk_cpu"; + clocks = <&clk_apll>, <&clk_gpll>;/*FIXME*/ + clock-output-names = "aclk_cpu_mux"; #clock-cells = <0>; #clock-init-cells = <1>; }; @@ -172,6 +175,7 @@ rockchip,flags = <(CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT)>; #clock-cells = <0>; + #clock-init-cells = <1>; }; clk_core_div: clk_core_div { @@ -218,6 +222,7 @@ rockchip,div-type = ; clock-output-names = "hclk_cpu"; #clock-cells = <0>; + #clock-init-cells = <1>; }; /* reg[11:10]: reserved */ @@ -229,6 +234,7 @@ rockchip,div-type = ; clock-output-names = "pclk_cpu"; #clock-cells = <0>; + #clock-init-cells = <1>; }; pclk_ahb2apb: pclk_ahb2apb_div { @@ -238,6 +244,7 @@ rockchip,div-type = ; clock-output-names = "pclk_ahb2apb"; #clock-cells = <0>; + #clock-init-cells = <1>; }; }; @@ -255,6 +262,7 @@ clocks = <&clk_gpll>, <&clk_cpll>; clock-output-names = "clk_i2s_pll"; #clock-cells = <0>; + #clock-init-cells = <1>; }; }; @@ -372,6 +380,7 @@ clock-output-names = "aclk_peri"; rockchip,div-type = ; #clock-cells = <0>; + #clock-init-cells = <1>; }; /* reg[7:5]: reserved */ @@ -383,6 +392,7 @@ clock-output-names = "hclk_peri"; rockchip,div-type = ; #clock-cells = <0>; + #clock-init-cells = <1>; }; /* reg[11:10]: reserved */ @@ -394,6 +404,7 @@ clock-output-names = "pclk_peri"; rockchip,div-type = ; #clock-cells = <0>; + #clock-init-cells = <1>; }; /* reg[14]: reserved */ @@ -476,6 +487,7 @@ clocks = <&clk_gpll>, <&clk_cpll>; clock-output-names = "clk_uart_pll"; #clock-cells = <0>; + #clock-init-cells = <1>; }; }; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index ec296bac577c..31822c376874 100755 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -334,15 +334,23 @@ clocks-init{ compatible = "rockchip,clocks-init"; - rockchip,clocks-init-rate =<&clk_cpll 768000000>,<&clk_gpll 594000000>; - rockchip,clocks-init-parent =<&aclk_peri_mux &clk_gpll>,<&aclk_cpu &clk_gpll>; + rockchip,clocks-init-parent = + <&clk_core &clk_apll>, <&aclk_cpu_mux &clk_gpll>,/*FIXME*/ + <&aclk_peri_mux &clk_gpll>, <&clk_i2s_pll_mux &clk_cpll>, + <&clk_uart_pll_mux &clk_gpll>; + rockchip,clocks-init-rate = + <&clk_core 792000000>, <&clk_gpll 768000000>, + <&clk_cpll 594000000>, <&aclk_cpu 192000000>, + <&hclk_cpu 96000000>, <&pclk_cpu 48000000>, + <&pclk_ahb2apb 48000000>, <&aclk_peri 192000000>, + <&hclk_peri 96000000>, <&pclk_peri 48000000>; }; fb: fb{ compatible = "rockchip,rk-fb"; rockchip,disp-mode = ; }; - + lcdc0:lcdc@1010c000 { compatible = "rockchip,rk3188-lcdc"; rockchip,prop = ; diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index eafc7cec0d28..dba8f386e367 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -369,6 +369,11 @@ static int clk_apll_set_rate(struct clk_hw *hw, unsigned long rate, goto CHANGE_APLL; } + /* In rk3188, arm_gpll and cpu_gpll share a same gate, + * and aclk_cpu selects cpu_gpll as parent, thus this + * gate must keep enabled. + */ +#if 0 if (clk_prepare(arm_gpll)) { clk_err("fail to prepare arm_gpll path\n"); clk_unprepare(arm_gpll); @@ -381,6 +386,7 @@ static int clk_apll_set_rate(struct clk_hw *hw, unsigned long rate, clk_unprepare(arm_gpll); goto CHANGE_APLL; } +#endif arm_gpll_rate = __clk_get_rate(arm_gpll); temp_div = DIV_ROUND_UP(arm_gpll_rate, __clk_get_rate(clk)); @@ -390,8 +396,8 @@ static int clk_apll_set_rate(struct clk_hw *hw, unsigned long rate, CORE_CLK_MAX_DIV); clk_debug("can't get rate %lu from arm_gpll rate %lu\n", __clk_get_rate(clk), arm_gpll_rate); - clk_disable(arm_gpll); - clk_unprepare(arm_gpll); + //clk_disable(arm_gpll); + //clk_unprepare(arm_gpll); goto CHANGE_APLL; } @@ -425,7 +431,7 @@ CHANGE_APLL: * before power down */ //FIXME - //if(!sel_gpll) + //if (!sel_gpll) cru_writel(PLL_MODE_SLOW(pll->id), CRU_MODE_CON); /* PLL power down */ @@ -456,7 +462,7 @@ CHANGE_APLL: /* PLL return from slow mode */ //FIXME - //if(!sel_gpll) + //if (!sel_gpll) cru_writel(PLL_MODE_NORM(pll->id), CRU_MODE_CON); /* reparent to apll, and set div to 1 */ @@ -477,8 +483,8 @@ CHANGE_APLL: if (sel_gpll) { sel_gpll = 0; - clk_disable(arm_gpll); - clk_unprepare(arm_gpll); + //clk_disable(arm_gpll); + //clk_unprepare(arm_gpll); } //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index ffa95223b40e..79cb6a737009 100755 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -51,7 +51,7 @@ struct rkclk_muxinfo { u32 width; u32 parent_num; u32 clkops_idx; - u32 flags; + //u8 mux_flags; const char *clk_name; const char **parent_names; struct list_head node; @@ -95,6 +95,7 @@ struct rkclk_pllinfo { struct rkclk { const char *clk_name; u32 clk_type; + u32 flags; /* * store nodes creat this rkclk * */ @@ -123,10 +124,15 @@ static int rkclk_init_muxinfo(struct device_node *np, int cnt, i, ret = 0; u8 found = 0; struct rkclk *rkclk; + u32 flags; mux = kzalloc(sizeof(struct rkclk_muxinfo), GFP_KERNEL); if (!mux) return -ENOMEM; + + ret = of_property_read_u32(np, "rockchip,flags", &flags); + if (ret != 0) + flags = 0; /* * Get control bit addr */ @@ -134,10 +140,6 @@ static int rkclk_init_muxinfo(struct device_node *np, 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; @@ -177,6 +179,7 @@ static int rkclk_init_muxinfo(struct device_node *np, found = 1; rkclk->mux_info = mux; rkclk->clk_type |= RKCLK_MUX_TYPE; + rkclk->flags |= flags; break; } } @@ -184,7 +187,8 @@ static int rkclk_init_muxinfo(struct device_node *np, rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); rkclk->clk_name = mux->clk_name; rkclk->mux_info = mux; - rkclk->clk_type |= RKCLK_MUX_TYPE; + rkclk->clk_type = RKCLK_MUX_TYPE; + rkclk->flags = flags; rkclk->np = np; clk_debug("%s: creat %s\n", __func__, rkclk->clk_name); @@ -319,6 +323,7 @@ static int rkclk_init_fracinfo(struct device_node *np, found = 1; rkclk->frac_info = frac; rkclk->clk_type |= RKCLK_FRAC_TYPE; + rkclk->flags |= CLK_SET_RATE_PARENT; break; } } @@ -326,7 +331,8 @@ static int rkclk_init_fracinfo(struct device_node *np, rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); rkclk->clk_name = frac->clk_name; rkclk->frac_info = frac; - rkclk->clk_type |= RKCLK_FRAC_TYPE; + rkclk->clk_type = RKCLK_FRAC_TYPE; + rkclk->flags = CLK_SET_RATE_PARENT; rkclk->np = np; clk_debug("%s: creat %s\n", __func__, rkclk->clk_name); @@ -577,7 +583,6 @@ static int rkclk_register(struct rkclk *rkclk) struct clk_hw *rate_hw; int parent_num; struct device_node *node = rkclk->np; - unsigned long flags = 0; clk_debug("%s >>>>>start: clk_name=%s, clk_type=%x\n", @@ -608,8 +613,6 @@ static int rkclk_register(struct rkclk *rkclk) 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) @@ -648,7 +651,6 @@ 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) { @@ -666,26 +668,26 @@ static int rkclk_register(struct rkclk *rkclk) clk = clk_register_mux(NULL, rkclk->clk_name, rkclk->mux_info->parent_names, (u8)rkclk->mux_info->parent_num, - flags, mux->reg, mux->shift, mux->mask, - 0, &clk_lock); + rkclk->flags, mux->reg, mux->shift, mux->mask, + mux->flags, &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, - flags, div->reg, div->shift, + rkclk->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, - flags, gate->reg, + rkclk->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, - flags, pll->reg, pll->width, + rkclk->flags, pll->reg, pll->width, pll->id, &clk_lock); } else { clk_debug("use clk_register_composite\n"); @@ -694,7 +696,7 @@ static int rkclk_register(struct rkclk *rkclk) mux ? &mux->hw : NULL, mux ? mux_ops : NULL, rate_hw, rate_ops, gate ? &gate->hw : NULL, gate ? &clk_gate_ops : NULL, - flags); + rkclk->flags); } if (clk) { @@ -761,6 +763,10 @@ struct test_table t_table[] = { {.name = "clk_dpll", .rate = 400000000}, {.name = "clk_cpll", .rate = 600000000}, {.name = "clk_gpll", .rate = 800000000}, + + {.name = "clk_core", .rate = 100000000}, + {.name = "clk_core", .rate = 24000000}, + {.name = "clk_core", .rate = 500000000}, }; void rk_clk_test(void) @@ -834,9 +840,8 @@ static void __init rk_clk_tree_init(struct device_node *np) 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__); + if (!node_init) { + clk_err("%s:can not get clocks-init node\n",__FUNCTION__); return; } @@ -1028,15 +1033,13 @@ void rkclk_init_clks(struct device_node *np) int i,cnt_parent,cnt_rate; u32 clk_rate; //int ret; - struct clk * clk_p,*clk_c; - - const char * clk_name,*clk_parent_name; + struct clk *clk_p, *clk_c; + const char *clk_name, *clk_parent_name; cnt_parent = of_count_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells"); - printk("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent); - + clk_debug("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent); for (i = 0; i < cnt_parent; i++) { clk_parent_name=NULL; @@ -1048,30 +1051,37 @@ void rkclk_init_clks(struct device_node *np) 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)) continue; - //clk_set_parent(clk_name, clk_parent_name); + + clk_set_parent(clk_c, clk_p); + + clk_debug("%s: set %s parent = %s\n", __FUNCTION__, 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); + clk_debug("%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); + clk_name=of_clk_init_rate_get_info(np, i, &clk_rate); if(clk_name==NULL) continue; - clk_p=clk_get(NULL,clk_name); + clk_c = clk_get(NULL, clk_name); - printk("%s: set rate %s=%x,rate=%d\n",__FUNCTION__,clk_name,(u32)clk_p,clk_rate); - - if(IS_ERR(clk_c)||(clk_rate<1*1000*1000)||(clk_rate>2000*1000*1000)) + if(IS_ERR(clk_c)) continue; - //clk_set_rate(clk_p,clk_rate); + if((clk_rate<1*MHZ)||(clk_rate>2000*MHZ)) + clk_err("warning: clk_rate < 1*MHZ or > 2000*MHZ\n"); + + clk_set_rate(clk_c, clk_rate); + + clk_debug("%s: set %s rate = %u\n", __FUNCTION__, clk_name, + clk_rate); } } -- 2.34.1