From: dkl Date: Fri, 21 Feb 2014 09:09:10 +0000 (+0800) Subject: clk: rk: fix clk dts info analysis and clk register X-Git-Tag: firefly_0821_release~6301 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=dcd6f049aacd1388957b8597032ceafb659a239a;p=firefly-linux-kernel-4.4.55.git clk: rk: fix clk dts info analysis and clk register 1. Fix the way to get info from rk clk dts. 2. Fix rk clk register. 3. Draw out rk_clk_dump_info func. 4. Add more debug. --- diff --git a/arch/arm/boot/dts/rk3188-clocks.dtsi b/arch/arm/boot/dts/rk3188-clocks.dtsi index 0097e9e23aae..4ca1c32a94cb 100755 --- a/arch/arm/boot/dts/rk3188-clocks.dtsi +++ b/arch/arm/boot/dts/rk3188-clocks.dtsi @@ -68,7 +68,6 @@ compatible = "rockchip,rk-clock-regs"; #address-cells = <1>; #size-cells = <1>; - reg = <0x0000 0x0100>; ranges; /* PLL control regs */ @@ -183,8 +182,10 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <9 5>; clocks = <&clk_core>; + clock-output-names = "clk_core"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[15:14]: reserved */ @@ -443,7 +444,9 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 6>; clocks = <&clk_hsicphy480m_mux>; + clock-output-names = "clk_hsicphy480m"; rockchip,div-type = ; + #clock-cells = <0>; }; /* reg[15:14]: reserved */ @@ -722,10 +725,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 5>; clocks = <&clk_mac_pll_mux>; + clock-output-names = "clk_mac_pll"; rockchip,clkops-idx = ; rockchip,div-type = ; - + #clock-cells = <0>; }; /* reg[15:13]: reserved */ @@ -765,15 +769,15 @@ compatible = "rockchip,rk3188-inv-con"; rockchip,bits = <7 1>; clocks = <&clk_hsadc>; - rockchip,div-type = ; - rockchip,div-relations = <1>; }; clk_hsadc_div: clk_hsadc_div { compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 8>; clocks = <&clk_hsadc_pll_mux>; + clock-output-names = "clk_hsadc_pll"; rockchip,div-type = ; + #clock-cells = <0>; }; }; @@ -846,7 +850,9 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <0 2>; clocks = <&clk_ddr>; + clock-output-names = "clk_ddr"; rockchip,div-type = ; + #clock-cells = <0>; }; /* reg[7:2]: reserved */ @@ -883,9 +889,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 8>; clocks = <&dclk_lcdc0>; + clock-output-names = "dclk_lcdc0"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; }; @@ -910,9 +918,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 8>; clocks = <&dclk_lcdc1>; + clock-output-names = "dclk_lcdc1"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; }; @@ -934,9 +944,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <1 5>; clocks = <&cif_out_pll_mux>; + clock-output-names = "cif_out_pll"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[6]: reserved */ @@ -987,9 +999,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <0 5>; clocks = <&aclk_lcdc0>; + clock-output-names = "aclk_lcdc0"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[6:5]: reserved */ @@ -1006,9 +1020,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 5>; clocks = <&aclk_lcdc1>; + clock-output-names = "aclk_lcdc1"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[14:13]: reserved */ @@ -1032,9 +1048,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <0 5>; clocks = <&clk_vepu>; + clock-output-names = "clk_vepu"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[6:5]: reserved */ @@ -1051,9 +1069,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <8 5>; clocks = <&clk_vdpu>; + clock-output-names = "clk_vdpu"; rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[14:13]: reserved */ @@ -1077,8 +1097,11 @@ compatible = "rockchip,rk3188-div-con"; rockchip,bits = <0 5>; clocks = <&clk_gpu>; + clock-output-names = "clk_gpu"; + rockchip,div-type = ; rockchip,clkops-idx = ; + #clock-cells = <0>; }; /* reg[6:5]: reserved */ diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 06c84830da83..a8feab7b79d7 100755 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 ROCKCHIP, Inc. * Author: chenxing + * Dai Kelin * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -24,88 +25,60 @@ #include "clk-pll.h" -struct rkclk_divmap_table { - u32 reg_val; - u32 div_val; +struct rkclk_muxinfo { + const char *clk_name; + struct device_node *np; + struct clk_mux *mux; + u8 parent_num; + const char **parent_names; + u32 clkops_idx; }; struct rkclk_divinfo { - struct clk_divider *div; - void __iomem *addr; - u32 shift; - u32 width; - u32 div_type; - u32 max_div; - u32 fixed_div_val; - u32 clkops_idx; - const char *clk_name; - const char *parent_name; - struct clk_div_table *div_table; - struct list_head node; -}; - -struct rkclk_muxinfo { - struct clk_mux *mux; - void __iomem *addr; - u32 shift; - u32 width; - u32 parent_num; - u32 clkops_idx; - //u8 mux_flags; - const char *clk_name; - const char **parent_names; - struct list_head node; + const char *clk_name; + struct device_node *np; + struct clk_divider *div; + u32 div_type; + const char *parent_name; + u32 clkops_idx; }; struct rkclk_fracinfo { - struct clk_hw hw; - void __iomem *addr; - u32 shift; - u32 width; - u32 frac_type; - u32 clkops_idx; - const char *clk_name; - const char *parent_name; - struct list_head node; + const char *clk_name; + struct device_node *np; + struct clk_divider *frac; + u32 frac_type; + const char *parent_name; + u32 clkops_idx; }; struct rkclk_gateinfo { - struct clk_gate *gate; - void __iomem *addr; - u32 shift; - u32 clkops_idx; - const char *clk_name; - const char *parent_name; + const char *clk_name; + struct device_node *np; + struct clk_gate *gate; + const char *parent_name; + //u32 clkops_idx; }; struct rkclk_pllinfo { - struct clk_hw hw; - void __iomem *addr; - u32 width; - const char *clk_name; - const char *parent_name; - /* - * const char **clkout_names; - */ - u32 clkops_idx; - u32 id; - struct list_head node; + const char *clk_name; + struct device_node *np; + struct clk_pll *pll; + const char *parent_name; + u32 clkops_idx; }; struct rkclk { - const char *clk_name; - u32 clk_type; - u32 flags; - /* - * store nodes creat this rkclk - * */ - struct device_node *np; - struct rkclk_pllinfo *pll_info; - struct rkclk_muxinfo *mux_info; - struct rkclk_divinfo *div_info; - struct rkclk_fracinfo *frac_info; - struct rkclk_gateinfo *gate_info; - struct list_head node; + const char *clk_name; + //struct device_node *np; + u32 clk_type; + u32 flags; + struct rkclk_muxinfo *mux_info; + struct rkclk_divinfo *div_info; + struct rkclk_fracinfo *frac_info; + struct rkclk_pllinfo *pll_info; + struct rkclk_gateinfo *gate_info; + struct list_head node; }; static DEFINE_SPINLOCK(clk_lock); @@ -117,279 +90,445 @@ LIST_HEAD(rk_clks); #define RKCLK_FRAC_TYPE (1 << 3) #define RKCLK_GATE_TYPE (1 << 4) -static int rkclk_init_muxinfo(struct device_node *np, - struct rkclk_muxinfo *mux, void __iomem *addr) +static int rkclk_init_muxinfo(struct device_node *np, void __iomem *addr) { + struct rkclk_muxinfo *muxinfo = NULL; + struct clk_mux *mux = NULL; + u32 shift, width; + u32 flags; int cnt, i, ret = 0; u8 found = 0; - struct rkclk *rkclk; - u32 flags; + struct rkclk *rkclk = NULL; - 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 - */ - ret = of_property_read_u32_index(np, "rockchip,bits", 0, &mux->shift); - if (ret != 0) - return -EINVAL; + muxinfo = kzalloc(sizeof(struct rkclk_muxinfo), GFP_KERNEL); + if (!muxinfo) { + ret = -ENOMEM; + goto out; + } - ret = of_property_read_u32(np, "rockchip,clkops-idx", &mux->clkops_idx); - if (ret != 0) - mux->clkops_idx = CLKOPS_TABLE_END; + muxinfo->mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); + if (!muxinfo->mux) { + ret = -ENOMEM; + goto out; + } + mux = muxinfo->mux; - ret = of_property_read_u32_index(np, "rockchip,bits", 1, &mux->width); + ret = of_property_read_string(np, "clock-output-names", + &muxinfo->clk_name); if (ret != 0) - return -EINVAL; - mux->addr = addr; + goto out; - ret = of_property_read_string(np, "clock-output-names", &mux->clk_name); - if (ret != 0) - return -EINVAL; + muxinfo->np = np; - /* - * Get parents' cnt - */ cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells"); - if (cnt< 0) - return -EINVAL; - - mux->parent_num = cnt; - mux->parent_names = kzalloc(cnt * sizeof(char *), GFP_KERNEL); + if (cnt < 0) { + ret = -EINVAL; + goto out; + } else { + clk_debug("%s: parent cnt = %d\n", __func__, cnt); + muxinfo->parent_num = (u8)cnt; + } - clk_debug("%s: parent cnt = %d\n", __func__, cnt); + muxinfo->parent_names = kzalloc(cnt * sizeof(char *), GFP_KERNEL); for (i = 0; i < cnt ; i++) { + muxinfo->parent_names[i] = of_clk_get_parent_name(np, i); + } + + mux->reg = addr; + + ret = of_property_read_u32_index(np, "rockchip,bits", 0, &shift); + if (ret != 0) { + goto out; + } else { + mux->shift = (u8)shift; + } - mux->parent_names[i] = of_clk_get_parent_name(np, i); + ret = of_property_read_u32_index(np, "rockchip,bits", 1, &width); + if (ret != 0) + goto out; + mux->mask = (1 << width) - 1; + + mux->flags = CLK_MUX_HIWORD_MASK; + + ret = of_property_read_u32(np, "rockchip,clkops-idx", + &muxinfo->clkops_idx); + if (ret != 0) { + muxinfo->clkops_idx = CLKOPS_TABLE_END; + ret = 0; + } + + ret = of_property_read_u32(np, "rockchip,flags", &flags); + if (ret != 0) { + flags = 0; + ret = 0; } found = 0; list_for_each_entry(rkclk, &rk_clks, node) { - if (strcmp(mux->clk_name, rkclk->clk_name) == 0) { - if (rkclk->mux_info != NULL) - clk_err("%s(%d): This clk(%s) has been used\n", - __func__, __LINE__, mux->clk_name); - clk_debug("%s: find match %s\n", __func__, rkclk->clk_name); + if (strcmp(muxinfo->clk_name, rkclk->clk_name) == 0) { + if (rkclk->mux_info != NULL) { + clk_err("%s %d:\n", __func__, __LINE__); + clk_err("This clk(%s) has been used," + "will be overwrited here!\n", + rkclk->clk_name); + } + clk_debug("%s: find match %s\n", __func__, + rkclk->clk_name); found = 1; - rkclk->mux_info = mux; + rkclk->mux_info = muxinfo; rkclk->clk_type |= RKCLK_MUX_TYPE; rkclk->flags |= flags; break; } } + if (!found) { rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); - rkclk->clk_name = mux->clk_name; - rkclk->mux_info = mux; + if (!rkclk) { + ret = -ENOMEM; + goto out; + } + rkclk->clk_name = muxinfo->clk_name; + rkclk->mux_info = muxinfo; rkclk->clk_type = RKCLK_MUX_TYPE; rkclk->flags = flags; - rkclk->np = np; clk_debug("%s: creat %s\n", __func__, rkclk->clk_name); - list_add_tail(&rkclk->node, &rk_clks); } - return 0; + +out: + if (ret) { + clk_err("%s error, ret = %d\n", __func__, ret); + if (muxinfo) { + if (muxinfo->mux) + kfree(muxinfo->mux); + kfree(muxinfo); + } + if (rkclk) + kfree(rkclk); + } + + return ret; } -static int rkclk_init_divinfo(struct device_node *np, - struct rkclk_divinfo *div, void __iomem *addr) +static int rkclk_init_divinfo(struct device_node *np, void __iomem *addr) { int cnt = 0, i = 0, ret = 0; - struct rkclk *rkclk; + struct rkclk *rkclk = NULL; u8 found = 0; + u32 flags; + u32 shift, width; + struct rkclk_divinfo *divinfo = NULL; + struct clk_divider *div = NULL; + struct clk_div_table *table; + u32 table_val, table_div; - div = kzalloc(sizeof(struct rkclk_divinfo), GFP_KERNEL); - if (!div) - return -ENOMEM; - of_property_read_u32_index(np, "rockchip,bits", 0, &div->shift); - of_property_read_u32_index(np, "rockchip,bits", 1, &div->width); - div->addr = addr; + divinfo = kzalloc(sizeof(struct rkclk_divinfo), GFP_KERNEL); + if (!divinfo) { + ret = -ENOMEM; + goto out; + } - of_property_read_u32(np, "rockchip,div-type", &div->div_type); + divinfo->div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); + if (!divinfo->div) { + ret = -ENOMEM; + goto out; + } + div = divinfo->div; - ret = of_property_read_u32(np, "rockchip,clkops-idx", &div->clkops_idx); + ret = of_property_read_string(np, "clock-output-names", + &divinfo->clk_name); if (ret != 0) - div->clkops_idx = CLKOPS_TABLE_END; + goto out; - cnt = of_property_count_strings(np, "clock-output-names"); - if (cnt <= 0) - div->clk_name = of_clk_get_parent_name(np, 0); - else { - ret = of_property_read_string(np, "clock-output-names", &div->clk_name); - if (ret != 0) - return -EINVAL; - div->parent_name = of_clk_get_parent_name(np, 0); + divinfo->parent_name = of_clk_get_parent_name(np, 0); + + divinfo->np = np; + + ret = of_property_read_u32(np, "rockchip,clkops-idx", + &divinfo->clkops_idx); + if (ret != 0) { + divinfo->clkops_idx = CLKOPS_TABLE_END; + ret = 0; } - switch (div->div_type) { + ret = of_property_read_u32(np, "rockchip,flags", &flags); + if (ret != 0) { + flags = 0; + ret = 0; + } + + ret = of_property_read_u32(np, "rockchip,div-type", &divinfo->div_type); + if (ret != 0) + goto out; + + switch (divinfo->div_type) { case CLK_DIVIDER_PLUS_ONE: case CLK_DIVIDER_ONE_BASED: case CLK_DIVIDER_POWER_OF_TWO: break; - case CLK_DIVIDER_FIXED: - of_property_read_u32_index(np, "rockchip,div-relations", 0, - &div->fixed_div_val); - clk_debug("%s:%s fixed_div = %d\n", __func__, - div->clk_name, div->fixed_div_val); - break; case CLK_DIVIDER_USER_DEFINE: of_get_property(np, "rockchip,div-relations", &cnt); + if (cnt <= 0) { + ret = -EINVAL; + goto out; + } cnt /= 4 * 2; - div->div_table = kzalloc(cnt * sizeof(struct clk_div_table), + table = kzalloc(cnt * sizeof(struct clk_div_table), GFP_KERNEL); - + if (!table) { + ret = -ENOMEM; + goto out; + } for (i = 0; i < cnt; i++) { - of_property_read_u32_index(np, "rockchip,div-relations", i * 2, - &div->div_table[i].val); - of_property_read_u32_index(np, "rockchip,div-relations", i * 2 + 1, - &div->div_table[i].div); + ret = of_property_read_u32_index(np, + "rockchip,div-relations", i * 2, + &table_val); + if (ret) + goto out; + ret = of_property_read_u32_index(np, + "rockchip,div-relations", + i * 2 + 1, &table_div); + if (ret) + goto out; + table[i].val = (unsigned int)table_val; + table[i].div = (unsigned int)table_div; clk_debug("\tGet div table %d: val=%d, div=%d\n", - i, div->div_table[i].val, - div->div_table[i].div); + i, table_val, table_div); } + div->table = table; break; default: - clk_err("%s: %s: unknown rockchip,div-type, please check dtsi\n", - __func__, div->clk_name); - break; + clk_err("%s: %s: unknown rockchip,div-type\n", __func__, + divinfo->clk_name); + ret = -EINVAL; + goto out; } + div->reg = addr; + ret = of_property_read_u32_index(np, "rockchip,bits", 0, &shift); + if (ret) + goto out; + ret = of_property_read_u32_index(np, "rockchip,bits", 1, &width); + if (ret) + goto out; + div->shift = (u8)shift; + div->width = (u8)width; + div->flags = CLK_DIVIDER_HIWORD_MASK | divinfo->div_type; + found = 0; list_for_each_entry(rkclk, &rk_clks, node) { - if (strcmp(div->clk_name, rkclk->clk_name) == 0) { - if (rkclk->div_info != NULL) - clk_err("%s(Line %d): This clk(%s) has been used\n", - __func__, __LINE__, rkclk->clk_name); - clk_debug("%s: find match %s\n", __func__, rkclk->clk_name); + if (strcmp(divinfo->clk_name, rkclk->clk_name) == 0) { + if (rkclk->div_info != NULL) { + clk_err("%s %d:\n", __func__, __LINE__); + clk_err("This clk(%s) has been used," + "will be overwrited here!\n", + rkclk->clk_name); + } + clk_debug("%s: find match %s\n", __func__, + rkclk->clk_name); found = 1; - rkclk->div_info = div; + rkclk->div_info = divinfo; rkclk->clk_type |= RKCLK_DIV_TYPE; + rkclk->flags |= flags; break; } } + if (!found) { rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); - rkclk->clk_name = div->clk_name; - rkclk->div_info = div; - rkclk->clk_type |= RKCLK_DIV_TYPE; - rkclk->np = np; + if (!rkclk) { + ret = -ENOMEM; + goto out; + } + rkclk->clk_name = divinfo->clk_name; + rkclk->div_info = divinfo; + rkclk->clk_type = RKCLK_DIV_TYPE; + rkclk->flags = flags; clk_debug("%s: creat %s\n", __func__, rkclk->clk_name); - list_add_tail(&rkclk->node, &rk_clks); } - return 0; +out: + if (ret) { + clk_err("%s error, ret = %d\n", __func__, ret); + if(table) + kfree(table); + if (divinfo) { + if (divinfo->div) + kfree(divinfo->div); + kfree(divinfo); + } + if (rkclk) + kfree(rkclk); + } + return ret; } -static int rkclk_init_fracinfo(struct device_node *np, - struct rkclk_fracinfo *frac, void __iomem *addr) +static int rkclk_init_fracinfo(struct device_node *np, void __iomem *addr) { - struct rkclk *rkclk; + struct rkclk *rkclk = NULL; u8 found = 0; int ret = 0; + struct rkclk_fracinfo *fracinfo = NULL; + struct clk_divider *frac = NULL; + u32 shift, width, flags; - frac = kzalloc(sizeof(struct rkclk_fracinfo), GFP_KERNEL); - if (!frac) - return -ENOMEM; - of_property_read_u32_index(np, "rockchip,bits", 0, &frac->shift); - of_property_read_u32_index(np, "rockchip,bits", 1, &frac->width); - frac->addr = addr; + fracinfo = kzalloc(sizeof(struct rkclk_fracinfo), GFP_KERNEL); + if (!fracinfo) { + ret = -ENOMEM; + goto out; + } - ret = of_property_read_u32(np, "rockchip,clkops-idx", &frac->clkops_idx); - if (ret != 0) - frac->clkops_idx = CLKOPS_TABLE_END; + fracinfo->frac = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); + if (!fracinfo->frac) { + ret = -ENOMEM; + goto out; + } + frac = fracinfo->frac; - frac->parent_name = of_clk_get_parent_name(np, 0); - ret = of_property_read_string(np, "clock-output-names", &frac->clk_name); + ret = of_property_read_string(np, "clock-output-names", + &fracinfo->clk_name); if (ret != 0) - return -EINVAL; + goto out; + + fracinfo->parent_name = of_clk_get_parent_name(np, 0); + fracinfo->np = np; + + ret = of_property_read_u32(np, "rockchip,clkops-idx", + &fracinfo->clkops_idx); + if (ret != 0) { + fracinfo->clkops_idx = CLKOPS_TABLE_END; + clk_err("frac node without specified ops!\n"); + ret = -EINVAL; + goto out; + } + + ret = of_property_read_u32(np, "rockchip,flags", &flags); + if (ret != 0) { + clk_debug("if not specified, frac use CLK_SET_RATE_PARENT flag " + "as default\n"); + flags = CLK_SET_RATE_PARENT; + ret = 0; + } + + frac->reg = addr; + ret = of_property_read_u32_index(np, "rockchip,bits", 0, &shift); + if (ret) + goto out; + ret = of_property_read_u32_index(np, "rockchip,bits", 1, &width); + if (ret) + goto out; + frac->shift = (u8)shift; + frac->width = (u8)width; + frac->flags = 0; found = 0; list_for_each_entry(rkclk, &rk_clks, node) { - if (strcmp(frac->clk_name, rkclk->clk_name) == 0) { - if (rkclk->frac_info != NULL) - clk_err("%s(%d): This clk(%s) has been used\n", - __func__, __LINE__, frac->clk_name); - clk_debug("%s: find match %s\n", __func__, rkclk->clk_name); + if (strcmp(fracinfo->clk_name, rkclk->clk_name) == 0) { + if (rkclk->frac_info != NULL) { + clk_err("%s %d:\n", __func__, __LINE__); + clk_err("This clk(%s) has been used," + "will be overwrited here!\n", + rkclk->clk_name); + } + clk_debug("%s: find match %s\n", __func__, + rkclk->clk_name); found = 1; - rkclk->frac_info = frac; + rkclk->frac_info = fracinfo; rkclk->clk_type |= RKCLK_FRAC_TYPE; - rkclk->flags |= CLK_SET_RATE_PARENT; + rkclk->flags |= flags; break; } } + if (!found) { rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); - rkclk->clk_name = frac->clk_name; - rkclk->frac_info = frac; + if (!rkclk) { + ret = -ENOMEM; + goto out; + } + rkclk->clk_name = fracinfo->clk_name; + rkclk->frac_info = fracinfo; rkclk->clk_type = RKCLK_FRAC_TYPE; - rkclk->flags = CLK_SET_RATE_PARENT; - rkclk->np = np; + rkclk->flags = flags; clk_debug("%s: creat %s\n", __func__, rkclk->clk_name); - list_add_tail(&rkclk->node, &rk_clks); } - return 0; + +out: + if (ret) { + clk_err("%s error, ret = %d\n", __func__, ret); + if (fracinfo) { + if (fracinfo->frac) + kfree(fracinfo->frac); + kfree(fracinfo); + } + if (rkclk) + kfree(rkclk); + } + + return ret; } static int __init rkclk_init_selcon(struct device_node *np) { struct device_node *node_con, *node; void __iomem *reg = 0; + int ret = 0; - struct rkclk_divinfo *divinfo; - struct rkclk_muxinfo *muxinfo; - struct rkclk_fracinfo *fracinfo; for_each_available_child_of_node(np, node_con) { - reg = of_iomap(node_con, 0); + clk_debug("\n"); + clk_debug("%s: reg = 0x%x\n", __func__, (u32)reg); for_each_available_child_of_node(node_con, node) { + clk_debug("\n"); + if (of_device_is_compatible(node, + "rockchip,rk3188-div-con")) + ret = rkclk_init_divinfo(node, reg); - if (of_device_is_compatible(node, "rockchip,rk3188-div-con")) - rkclk_init_divinfo(node, divinfo, reg); - - else if (of_device_is_compatible(node, "rockchip,rk3188-mux-con")) - rkclk_init_muxinfo(node, muxinfo, reg); + else if (of_device_is_compatible(node, + "rockchip,rk3188-mux-con")) + ret = rkclk_init_muxinfo(node, reg); - else if (of_device_is_compatible(node, "rockchip,rk3188-frac-con")) - rkclk_init_fracinfo(node, fracinfo, reg); + else if (of_device_is_compatible(node, + "rockchip,rk3188-frac-con")) + ret = rkclk_init_fracinfo(node, reg); - else if (of_device_is_compatible(node, "rockchip,rk3188-inv-con")) + else if (of_device_is_compatible(node, + "rockchip,rk3188-inv-con")) clk_debug("INV clk\n"); - else - clk_err("%s: unknown controler type, plz check dtsi " - "or add type support\n", __func__); - + else { + clk_err("%s: unknown controller type\n", + __func__); + ret = -EINVAL; + } } } - return 0; + + return ret; } static int __init rkclk_init_gatecon(struct device_node *np) { - struct clk_onecell_data *clk_data; struct device_node *node; - const char *clk_parent; const char *clk_name; void __iomem *reg; - void __iomem *reg_idx; int cnt; - int reg_bit; int i; struct rkclk_gateinfo *gateinfo; u8 found = 0; struct rkclk *rkclk; + int ret = 0; + struct clk_gate *gate = NULL; + for_each_available_child_of_node(np, node) { cnt = of_property_count_strings(node, "clock-output-names"); @@ -400,47 +539,62 @@ static int __init rkclk_init_gatecon(struct device_node *np) } if (cnt == 0) { - pr_info("%s: nothing to do\n", __func__); + clk_debug("%s: nothing to do\n", __func__); continue; } reg = of_iomap(node, 0); - - clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = kzalloc(cnt * sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) { - kfree(clk_data); - return -ENOMEM; - } + clk_debug("\n"); + clk_debug("%s: reg = 0x%x\n", __func__, (u32)reg); for (i = 0; i < cnt; i++) { - of_property_read_string_index(node, "clock-output-names", - i, &clk_name); + ret = of_property_read_string_index(node, + "clock-output-names", i, &clk_name); + if (ret != 0) + goto out; /* ignore empty slots */ - if (!strcmp("reserved", clk_name)) + if (!strcmp("reserved", clk_name)) { + clk_debug("do nothing for reserved clk\n"); continue; + } - clk_parent = of_clk_get_parent_name(node, i); + gateinfo = kzalloc(sizeof(struct rkclk_gateinfo), + GFP_KERNEL); + if (!gateinfo) { + ret = -ENOMEM; + goto out; + } - reg_idx = reg + (4 * (i / 16)); - reg_bit = (i % 16); + gateinfo->gate = kzalloc(sizeof(struct clk_gate), + GFP_KERNEL); + if (!gateinfo->gate) { + ret = -ENOMEM; + goto out; + } + gate = gateinfo->gate; - gateinfo = kzalloc(sizeof(struct rkclk_gateinfo), GFP_KERNEL); gateinfo->clk_name = clk_name; - gateinfo->parent_name = clk_parent; - gateinfo->addr = reg; - gateinfo->shift = reg_bit; + gateinfo->parent_name = of_clk_get_parent_name(node, i); + gateinfo->np = node; + + gate->reg = reg; + gate->bit_idx = (i % 16); + gate->flags = CLK_GATE_HIWORD_MASK | + CLK_GATE_SET_TO_DISABLE; + found = 0; list_for_each_entry(rkclk, &rk_clks, node) { if (strcmp(clk_name, rkclk->clk_name) == 0) { - if (rkclk->gate_info != NULL) - clk_err("%s(%d): This clk(%s) has been used\n", - __func__, __LINE__, clk_name); - clk_debug("%s: find match %s\n", __func__, rkclk->clk_name); + if (rkclk->gate_info != NULL) { + clk_err("%s %d:\n", __func__, + __LINE__); + clk_err("This clk(%s) has been used," + "will be overwrited here!\n", + rkclk->clk_name); + } + clk_debug("%s: find match %s\n", + __func__, rkclk->clk_name); found = 1; rkclk->gate_info = gateinfo; rkclk->clk_type |= RKCLK_GATE_TYPE; @@ -449,259 +603,331 @@ static int __init rkclk_init_gatecon(struct device_node *np) } if (!found) { rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); + if (!rkclk) { + ret = -ENOMEM; + goto out; + } rkclk->clk_name = gateinfo->clk_name; rkclk->gate_info = gateinfo; - rkclk->clk_type |= RKCLK_GATE_TYPE; - rkclk->np = node; - clk_debug("%s: creat %s\n", __func__, rkclk->clk_name); - + rkclk->clk_type = RKCLK_GATE_TYPE; + clk_debug("%s: creat %s\n", __func__, + rkclk->clk_name); list_add_tail(&rkclk->node, &rk_clks); } + +out: + if (ret) { + clk_err("%s error, ret = %d\n", __func__, ret); + if (gateinfo) { + if (gateinfo->gate) + kfree(gateinfo->gate); + kfree(gateinfo); + } + if (rkclk) + kfree(rkclk); + } } } + return 0; } static int __init rkclk_init_pllcon(struct device_node *np) { - struct rkclk_pllinfo *pllinfo; - struct device_node *node; - struct rkclk *rkclk; + struct device_node *node = NULL; + struct rkclk_pllinfo *pllinfo = NULL; void __iomem *reg; - int i = 0; - int ret = 0, clknum = 0; + struct clk_pll *pll = NULL; u8 found = 0; + int ret = 0; + struct rkclk *rkclk = NULL; + u32 flags; + u32 pll_id; + for_each_available_child_of_node(np, node) { - clknum = of_property_count_strings(node, "clock-output-names"); - if (clknum < 0) { - clk_err("%s: error in get clock-output-names numbers = %d\n", - __func__, clknum); - return -EINVAL; + pllinfo = kzalloc(sizeof(struct rkclk_pllinfo), GFP_KERNEL); + if (!pllinfo) { + ret = -ENOMEM; + goto out; } - reg = of_iomap(node, 0); - for (i = 0; i < clknum; i++) { - pllinfo = kzalloc(sizeof(struct rkclk_pllinfo), GFP_KERNEL); - if (!pllinfo) - return -ENOMEM; + pllinfo->pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL); + if (!pllinfo->pll) { + ret = -ENOMEM; + goto out; + } + pll = pllinfo->pll; - /* - * Get pll parent name - */ - pllinfo->parent_name = of_clk_get_parent_name(node, i); + pllinfo->np = node; - /* - * Get pll output name - */ - of_property_read_string_index(node, "clock-output-names", - i, &pllinfo->clk_name); + ret = of_property_read_string_index(node, "clock-output-names", + 0, &pllinfo->clk_name); + if (ret) + goto out; - pllinfo->addr = reg; + pllinfo->parent_name = of_clk_get_parent_name(node, 0); - ret = of_property_read_u32_index(node, "reg", 1, &pllinfo->width); - if (ret != 0) { - clk_err("%s: can not get reg info\n", __func__); - } + ret = of_property_read_u32(np, "rockchip,flags", &flags); + if (ret != 0) { + flags = 0; + ret = 0; + } - ret = of_property_read_u32(node, "rockchip,pll-id", &pllinfo->id); - if (ret != 0) { - clk_err("%s: can not get pll-id\n", __func__); - } + reg = of_iomap(node, 0); + if (reg == NULL) { + clk_err("%s: can not get reg addr info\n", __func__); + ret = -EINVAL; + goto out; + } else { + pll->reg = reg; + } - clk_debug("%s: parent=%s, pllname=%s, reg =%08x, id = %d, cnt=%d\n", - __func__,pllinfo->parent_name, - pllinfo->clk_name,(u32)pllinfo->addr, - pllinfo->id,pllinfo->width); + ret = of_property_read_u32_index(node, "reg", 1, &pll->width); + if (ret != 0) { + clk_err("%s: can not get reg length info\n", __func__); + goto out; + } - found = 0; - list_for_each_entry(rkclk, &rk_clks, node) { - if (strcmp(pllinfo->clk_name, rkclk->clk_name) == 0) { - if (rkclk->pll_info != NULL) - clk_err("%s(%d): This clk(%s) has been used\n", - __func__, __LINE__, pllinfo->clk_name); - clk_debug("%s: find match %s\n", __func__, rkclk->clk_name); - found = 1; - rkclk->pll_info = pllinfo; - rkclk->clk_type |= RKCLK_PLL_TYPE; - break; + ret = of_property_read_u32(node, "rockchip,pll-id", &pll_id); + if (ret != 0) { + clk_err("%s: can not get pll-id\n", __func__); + goto out; + } else { + pll->id = (u8)pll_id; + } + + clk_debug("%s: pllname=%s, parent=%s, flags=%u, " + "addr=0x%x, len=0x%x, id=%d\n", + __func__, pllinfo->clk_name, + pllinfo->parent_name, flags, + (u32)pll->reg, pll->width, pll->id); + + found = 0; + list_for_each_entry(rkclk, &rk_clks, node) { + if (strcmp(pllinfo->clk_name, rkclk->clk_name) == 0) { + if (rkclk->pll_info != NULL) { + clk_err("%s %d:\n", __func__, __LINE__); + clk_err("This clk(%s) has been used," + "will be overwrited here!\n", + rkclk->clk_name); } - } - if (!found) { - rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); - rkclk->clk_name = pllinfo->clk_name; + clk_debug("%s: find match %s\n", __func__, + rkclk->clk_name); + found = 1; rkclk->pll_info = pllinfo; rkclk->clk_type |= RKCLK_PLL_TYPE; - rkclk->np = node; + rkclk->flags |= flags; + break; + } + } - list_add_tail(&rkclk->node, &rk_clks); + if (!found) { + rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL); + if (!rkclk) { + ret = -ENOMEM; + goto out; } + rkclk->clk_name = pllinfo->clk_name; + rkclk->pll_info = pllinfo; + rkclk->clk_type = RKCLK_PLL_TYPE; + rkclk->flags = flags; + list_add_tail(&rkclk->node, &rk_clks); } } - return 0; -} +out: + if (ret) { + clk_err("%s error, ret = %d\n", __func__, ret); + if (pllinfo) { + if (pllinfo->pll) + kfree(pllinfo->pll); + kfree(pllinfo); + } + if (rkclk) + kfree(rkclk); + } -static unsigned long clk_div_special_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return parent_rate; -} -static long clk_div_special_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} -static int clk_div_special_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - return 0; + return ret; } -// 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 *clk = NULL; struct clk_mux *mux = NULL; struct clk_divider *div = NULL; struct clk_gate *gate = NULL; struct clk_pll *pll = NULL; + struct clk_divider *frac = NULL; - const struct clk_ops *rate_ops = NULL; + struct clk_hw *mux_hw = NULL; const struct clk_ops *mux_ops = NULL; + struct clk_hw *rate_hw = NULL; + const struct clk_ops *rate_ops = NULL; + struct clk_hw *gate_hw = NULL; + const struct clk_ops *gate_ops = NULL; - struct clk *clk = NULL; - const char **parent_names = NULL; - struct clk_hw *rate_hw; int parent_num; + const char **parent_names = NULL; - 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); - rate_ops = &clk_pll_ops; - pll->reg = rkclk->pll_info->addr; - //pll->shift = 0; - pll->width = rkclk->pll_info->width; - pll->id = rkclk->pll_info->id; - rate_hw = &pll->hw; + if (rkclk && rkclk->clk_name) { + clk_debug("%s: clk_name=%s, clk_type=0x%x, flags=0x%x\n", + __func__, rkclk->clk_name, rkclk->clk_type, + rkclk->flags); + } else { + clk_err("%s: rkclk or clk_name is NULL!\n", __func__); + return -EINVAL; + } - parent_num = 1; - parent_names = &rkclk->pll_info->parent_name; + if (rkclk->mux_info && rkclk->mux_info->mux) + mux = rkclk->mux_info->mux; + if (rkclk->div_info && rkclk->div_info->div) + div = rkclk->div_info->div; + if (rkclk->gate_info && rkclk->gate_info->gate) + gate = rkclk->gate_info->gate; + if (rkclk->pll_info && rkclk->pll_info->pll) + pll = rkclk->pll_info->pll; + if (rkclk->frac_info && rkclk->frac_info->frac) + frac = rkclk->frac_info->frac; + + switch (rkclk->clk_type) { + case RKCLK_MUX_TYPE: + /* only mux without specified ops will be registered here */ + if (rkclk->mux_info->clkops_idx == CLKOPS_TABLE_END) { + clk_debug("use clk_register_mux\n"); + clk = clk_register_mux_table(NULL, rkclk->clk_name, + rkclk->mux_info->parent_names, + rkclk->mux_info->parent_num, + rkclk->flags, mux->reg, mux->shift, + mux->mask, mux->flags, NULL, &clk_lock); + goto add_lookup; + } else + goto rgs_comp; + case 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, + rkclk->flags, pll->reg, pll->width, + pll->id, &clk_lock); + //kfree!!!!!!! + goto add_lookup; + case RKCLK_DIV_TYPE: + /* only div without specified ops will be registered here */ + if (rkclk->div_info->clkops_idx == CLKOPS_TABLE_END) { + clk_debug("use clk_register_divider\n"); + clk = clk_register_divider(NULL, rkclk->clk_name, + rkclk->div_info->parent_name, + rkclk->flags, div->reg, div->shift, + div->width, div->flags, &clk_lock); + goto add_lookup; + } else + goto rgs_comp; + case RKCLK_FRAC_TYPE: + if (rkclk->frac_info->clkops_idx == CLKOPS_TABLE_END) { + clk_err("frac node without specified ops!\n"); + return -EINVAL; + } else + goto rgs_comp; + case RKCLK_GATE_TYPE: + clk_debug("use clk_register_gate\n"); + clk = clk_register_gate(NULL, rkclk->clk_name, + rkclk->gate_info->parent_name, rkclk->flags, + gate->reg, gate->bit_idx, gate->flags, + &clk_lock); + goto add_lookup; + case (RKCLK_DIV_TYPE|RKCLK_PLL_TYPE): + case (RKCLK_DIV_TYPE|RKCLK_FRAC_TYPE): + case (RKCLK_PLL_TYPE|RKCLK_FRAC_TYPE): + case (RKCLK_DIV_TYPE|RKCLK_PLL_TYPE|RKCLK_FRAC_TYPE): + clk_err("Invalid rkclk type!\n"); + return -EINVAL; + default: + goto rgs_comp; + } - } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) { - div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); - 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; +rgs_comp: + clk_debug("use clk_register_composite\n"); - rate_hw = &div->hw; - rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx); + /* prepare args for clk_register_composite */ + /* prepare parent_num && parent_names + * priority: MUX > DIV=PLL=FRAC > GATE + */ + if (rkclk->clk_type & RKCLK_MUX_TYPE) { + parent_num = rkclk->mux_info->parent_num; + parent_names = rkclk->mux_info->parent_names; + } else if (rkclk->clk_type & RKCLK_DIV_TYPE ) { parent_num = 1; - parent_names = &rkclk->frac_info->parent_name; - - } 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) - rate_ops = rk_get_clkops(rkclk->div_info->clkops_idx); - else - rate_ops = &clk_divider_ops; - div->reg = rkclk->div_info->addr; - div->shift = (u8)rkclk->div_info->shift; - div->width = rkclk->div_info->width; - div->flags = CLK_DIVIDER_HIWORD_MASK | rkclk->div_info->div_type; - rate_hw = &div->hw; - if (rkclk->div_info->div_table) - div->table = rkclk->div_info->div_table; - + parent_names = &(rkclk->div_info->parent_name); + } else if (rkclk->clk_type & RKCLK_PLL_TYPE) { parent_num = 1; - parent_names = &rkclk->div_info->parent_name; - if (rkclk->clk_type != (rkclk->clk_type & CLK_DIVIDER_MASK)) { - // FIXME: fixed div add here - clk_err("%s: %d, unknown clk_type=%x\n", - __func__, __LINE__, rkclk->clk_type); - - } + parent_names = &(rkclk->pll_info->parent_name); + } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) { + parent_num = 1; + parent_names = &(rkclk->frac_info->parent_name); + } else if (rkclk->clk_type & RKCLK_GATE_TYPE) { + parent_num = 1; + parent_names = &(rkclk->gate_info->parent_name); } + /* prepare mux_hw && mux_ops */ if (rkclk->clk_type & RKCLK_MUX_TYPE) { - mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); - mux->reg = rkclk->mux_info->addr; - mux->shift = (u8)rkclk->mux_info->shift; - mux->mask = (1 << rkclk->mux_info->width) - 1; - mux->flags = CLK_MUX_HIWORD_MASK; + mux_hw = &mux->hw; mux_ops = &clk_mux_ops; - if (rkclk->mux_info->clkops_idx != CLKOPS_TABLE_END) { - rate_hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); - rate_ops = rk_get_clkops(rkclk->mux_info->clkops_idx); - } + } - parent_num = rkclk->mux_info->parent_num; - parent_names = rkclk->mux_info->parent_names; + /* prepare rate_hw && rate_ops + * priority: DIV=PLL=FRAC > MUX + */ + if (rkclk->clk_type & RKCLK_DIV_TYPE) { + rate_hw = &div->hw; + if (rkclk->div_info->clkops_idx != CLKOPS_TABLE_END) + rate_ops = rk_get_clkops(rkclk->div_info->clkops_idx); + else + rate_ops = &clk_divider_ops; + } else if (rkclk->clk_type & RKCLK_PLL_TYPE) { + rate_hw = &pll->hw; + rate_ops = &clk_pll_ops; + } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) { + rate_hw = &frac->hw; + rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx); + } else if ((rkclk->clk_type & RKCLK_MUX_TYPE) && + (rkclk->mux_info->clkops_idx != CLKOPS_TABLE_END)) { + /* when a mux node has specified clkops_idx, prepare rate_hw && + * rate_ops and use clk_register_composite to register it later. + */ + /*FIXME*/ + rate_hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL); + if (!rate_hw) { + clk_err("%s: fail to alloc rate_hw!\n", __func__); + return -ENOMEM; + } + rate_ops = rk_get_clkops(rkclk->mux_info->clkops_idx); } if (rkclk->clk_type & RKCLK_GATE_TYPE) { - gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); - gate->reg = rkclk->gate_info->addr; - gate->bit_idx = rkclk->gate_info->shift; - gate->flags = CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE; - + gate_hw = &gate->hw; + gate_ops = &clk_gate_ops; } - // 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, - 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, - 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, - 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, - rkclk->flags, pll->reg, pll->width, - pll->id, &clk_lock); - } else { - 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, - rkclk->flags); - } + clk_debug("parent_num=%d, mux_hw=%d mux_ops=%d, rate_hw=%d rate_ops=%d," + " gate_hw=%d gate_ops=%d\n", + parent_num, mux_hw?1:0, mux_ops?1:0, rate_hw?1:0, + rate_ops?1:0, gate_hw?1:0, gate_ops?1:0); + clk = clk_register_composite(NULL, rkclk->clk_name, parent_names, + parent_num, mux_hw, mux_ops, rate_hw, rate_ops, + gate_hw, gate_ops, rkclk->flags); + +add_lookup: if (clk) { clk_debug("clk name=%s, flags=0x%lx\n", clk->name, clk->flags); clk_register_clkdev(clk, rkclk->clk_name, NULL); } else { - clk_err("%s: clk(\"%s\") register clk error\n", - __func__, rkclk->clk_name); + clk_err("%s: clk(\"%s\") register clk error\n", __func__, + rkclk->clk_name); } return 0; @@ -831,11 +1057,97 @@ void rk_dump_cru(void) } printk("\n\n"); } + +void rkclk_dump_info(struct rkclk *rkclk) +{ + struct clk_mux *mux = NULL; + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + struct clk_pll *pll = NULL; + struct clk_divider *frac = NULL; + int i; + + + clk_debug("%s: clkname=%s, type=0x%x, flags=0x%x\n", + __func__, (rkclk->clk_name)?(rkclk->clk_name):NULL, + rkclk->clk_type, rkclk->flags); + + if (rkclk->mux_info && rkclk->mux_info->mux) + mux = rkclk->mux_info->mux; + if (rkclk->div_info && rkclk->div_info->div) + div = rkclk->div_info->div; + if (rkclk->pll_info && rkclk->pll_info->pll) + pll = rkclk->pll_info->pll; + if (rkclk->frac_info && rkclk->frac_info->frac) + frac = rkclk->frac_info->frac; + if (rkclk->gate_info && rkclk->gate_info->gate) + gate = rkclk->gate_info->gate; + + if (rkclk->mux_info) { + clk_debug("\t\tmux_info: name=%s, clkops_idx=%u\n", + rkclk->mux_info->clk_name, + rkclk->mux_info->clkops_idx); + for (i = 0; i < rkclk->mux_info->parent_num; i++) + clk_debug("\t\t\tparent[%d]: %s\n", i, + rkclk->mux_info->parent_names[i]); + if (mux) { + clk_debug("\t\tmux: reg=0x%x, mask=0x%x, shift=0x%x, " + "mux_flags=0x%x\n", (u32)mux->reg, + mux->mask, mux->shift, mux->flags); + } + } + if (rkclk->pll_info) { + clk_debug("\t\tpll_info: name=%s, parent=%s, clkops_idx=0x%x\n", + rkclk->pll_info->clk_name, + rkclk->pll_info->parent_name, + rkclk->pll_info->clkops_idx); + if (pll) { + clk_debug("\t\tpll: reg=0x%x, width=0x%x, id=%d\n", + (u32)pll->reg, pll->width, pll->id); + } + } + if (rkclk->div_info) { + clk_debug("\t\tdiv_info: name=%s, div_type=0x%x, parent=%s, " + "clkops_idx=%d\n", + rkclk->div_info->clk_name, + rkclk->div_info->div_type, + rkclk->div_info->parent_name, + rkclk->div_info->clkops_idx); + if (div) { + clk_debug("\t\tdiv: reg=0x%x, shift=0x%x, width=0x%x, " + "div_flags=0x%x\n", (u32)div->reg, + div->shift, div->width, div->flags); + } + } + if (rkclk->frac_info) { + clk_debug("\t\tfrac_info: name=%s, parent=%s, clkops_idx=%d\n", + rkclk->frac_info->clk_name, + rkclk->frac_info->parent_name, + rkclk->frac_info->clkops_idx); + if (frac) { + clk_debug("\t\tfrac: reg=0x%x, shift=0x%x, width=0x%x, " + "div_flags=0x%x\n", (u32)frac->reg, + frac->shift, frac->width, frac->flags); + } + } + if (rkclk->gate_info) { + clk_debug("\t\tgate_info: name=%s, parent=%s\n", + rkclk->gate_info->clk_name, + rkclk->gate_info->parent_name); + if (gate) { + clk_debug("\t\tgate: reg=0x%x, bit_idx=%d, " + "gate_flags=0x%x\n", (u32)gate->reg, + gate->bit_idx, gate->flags); + } + } +} #else -void rk_dump_cru(void){} +void rk_dump_cru(void) {} +void rkclk_dump_info(struct rkclk *rkclk) {} #endif EXPORT_SYMBOL_GPL(rk_dump_cru); + #ifdef RKCLK_TEST struct test_table { const char *name; @@ -930,11 +1242,10 @@ void rk_clk_test(void) } #else -void rk_clk_test(void){} +void rk_clk_test(void) {} #endif EXPORT_SYMBOL_GPL(rk_clk_test); - void rkclk_init_clks(struct device_node *node); static void __init rk_clk_tree_init(struct device_node *np) @@ -980,41 +1291,10 @@ static void __init rk_clk_tree_init(struct device_node *np) } } -#if 0 - list_for_each_entry(rkclk, &rk_clks, node) { - int i; - clk_debug("%s: clkname = %s; type=%d\n", - __func__, rkclk->clk_name, - rkclk->clk_type); - if (rkclk->pll_info) { - clk_debug("\t\tpll: name=%s, parent=%s\n", - rkclk->pll_info->clk_name, - rkclk->pll_info->parent_name); - } - if (rkclk->mux_info) { - for (i = 0; i < rkclk->mux_info->parent_num; i++) - clk_debug("\t\tmux name=%s, parent: %s\n", - rkclk->mux_info->clk_name, - rkclk->mux_info->parent_names[i]); - } - if (rkclk->div_info) { - clk_debug("\t\tdiv name=%s\n", - rkclk->div_info->clk_name); - } - if (rkclk->frac_info) { - clk_debug("\t\tfrac name=%s\n", - rkclk->frac_info->clk_name); - } - if (rkclk->gate_info) { - clk_debug("\t\tgate name=%s, \taddr=%08x, \tshift=%d\n", - rkclk->gate_info->clk_name, - (u32)rkclk->gate_info->addr, - rkclk->gate_info->shift); - } - } -#endif - list_for_each_entry(rkclk, &rk_clks, node) { + clk_debug("\n"); + rkclk_dump_info(rkclk); + clk_debug("\n"); rkclk_register(rkclk); } @@ -1051,16 +1331,16 @@ static void __init rk_clk_tree_init(struct device_node *np) rkclk_cache_parents(rkclk); } - rk_clk_test(); - rkclk_init_clks(node_init); + rk_clk_test(); } CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init); -/********************************** rockchip clks init****************************************/ -const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rate) +/***************************** rockchip clks init******************************/ +const char *of_clk_init_rate_get_info(struct device_node *np, + int index,u32 *rate) { struct of_phandle_args clkspec; const char *clk_name; @@ -1069,12 +1349,13 @@ const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rat if (index < 0) return NULL; - rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells", index, - &clkspec); + rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate", + "#clock-init-cells", index, &clkspec); if (rc) return NULL; - if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0) + if (of_property_read_string_index(clkspec.np, "clock-output-names", 0, + &clk_name) < 0) return NULL; *rate= clkspec.args[0]; @@ -1083,7 +1364,8 @@ const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rat return clk_name; } -const char *of_clk_init_parent_get_info(struct device_node *np, int index,const char **clk_child_name) +const char *of_clk_init_parent_get_info(struct device_node *np, int index, + const char **clk_child_name) { struct of_phandle_args clkspec; const char *clk_name; @@ -1094,12 +1376,13 @@ const char *of_clk_init_parent_get_info(struct device_node *np, int index,const if (index < 0) return NULL; - rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells", index, - &clkspec); + rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent", + "#clock-init-cells", index, &clkspec); if (rc) return NULL; - if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0) + if (of_property_read_string_index(clkspec.np, "clock-output-names", 0, + &clk_name) < 0) return NULL; @@ -1114,7 +1397,8 @@ const char *of_clk_init_parent_get_info(struct device_node *np, int index,const return NULL; } - if (of_property_read_string_index(node, "clock-output-names",0,clk_child_name) < 0) + if (of_property_read_string_index(node, "clock-output-names", 0, + clk_child_name) < 0) return NULL; of_node_put(node);//??? @@ -1136,7 +1420,8 @@ void rkclk_init_clks(struct device_node *np) const char *clk_name, *clk_parent_name; - cnt_parent = of_count_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells"); + cnt_parent = of_count_phandle_with_args(np, + "rockchip,clocks-init-parent", "#clock-init-cells"); printk("%s: cnt_parent = %d\n",__FUNCTION__,cnt_parent); @@ -1159,7 +1444,8 @@ void rkclk_init_clks(struct device_node *np) clk_parent_name); } - cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells"); + cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate", + "#clock-init-cells"); printk("%s: cnt_rate = %d\n",__FUNCTION__,cnt_rate); diff --git a/drivers/clk/rockchip/clkops-dtsi.h b/drivers/clk/rockchip/clkops-dtsi.h index 07af92b37570..0783f37523cf 100644 --- a/drivers/clk/rockchip/clkops-dtsi.h +++ b/drivers/clk/rockchip/clkops-dtsi.h @@ -10,18 +10,18 @@ /* rate_ops index */ -#define CLKOPS_RATE_MUX_DIV 0 -#define CLKOPS_RATE_EVENDIV 1 -#define CLKOPS_RATE_DCLK_LCDC 2 -#define CLKOPS_RATE_I2S_FRAC 3 -#define CLKOPS_RATE_FRAC 4 -#define CLKOPS_RATE_I2S 5 -#define CLKOPS_RATE_CIFOUT 6 -#define CLKOPS_RATE_UART 7 -#define CLKOPS_RATE_HSADC 8 -#define CLKOPS_RATE_MAC_REF 9 -#define CLKOPS_RATE_CORE 10 -#define CLKOPS_RATE_CORE_PERI 11 +#define CLKOPS_RATE_MUX_DIV 1 +#define CLKOPS_RATE_EVENDIV 2 +#define CLKOPS_RATE_DCLK_LCDC 3 +#define CLKOPS_RATE_I2S_FRAC 4 +#define CLKOPS_RATE_FRAC 5 +#define CLKOPS_RATE_I2S 6 +#define CLKOPS_RATE_CIFOUT 7 +#define CLKOPS_RATE_UART 8 +#define CLKOPS_RATE_HSADC 9 +#define CLKOPS_RATE_MAC_REF 10 +#define CLKOPS_RATE_CORE 11 +#define CLKOPS_RATE_CORE_PERI 12 #define CLKOPS_TABLE_END (~0) @@ -32,12 +32,13 @@ #define CLK_DIVIDER_ONE_BASED BIT(0) #define CLK_DIVIDER_POWER_OF_TWO BIT(1) #define CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define CLK_DIVIDER_HIWORD_MASK BIT(3) /* Rockchip special defined */ -#define CLK_DIVIDER_FIXED BIT(6) +//#define CLK_DIVIDER_FIXED BIT(6) #define CLK_DIVIDER_USER_DEFINE BIT(7) /* CLK_DIVIDER_MASK defined the bits been used above */ -#define CLK_DIVIDER_MASK (0xFF) +//#define CLK_DIVIDER_MASK (0xFF) /*