2 * Copyright (C) 2013 ROCKCHIP, Inc.
3 * Author: chenxing <chenxing@rock-chips.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/clk-provider.h>
17 #include <linux/clkdev.h>
19 #include <linux/of_address.h>
20 #include <linux/clk-private.h>
27 struct rkclk_divmap_table {
32 struct rkclk_divinfo {
33 struct clk_divider *div;
42 const char *parent_name;
43 struct clk_div_table *div_table;
44 struct list_head node;
47 struct rkclk_muxinfo {
56 const char **parent_names;
57 struct list_head node;
60 struct rkclk_fracinfo {
68 const char *parent_name;
69 struct list_head node;
72 struct rkclk_gateinfo {
73 struct clk_gate *gate;
78 const char *parent_name;
81 struct rkclk_pllinfo {
86 const char *parent_name;
88 * const char **clkout_names;
92 struct list_head node;
99 * store nodes creat this rkclk
101 struct device_node *np;
102 struct rkclk_pllinfo *pll_info;
103 struct rkclk_muxinfo *mux_info;
104 struct rkclk_divinfo *div_info;
105 struct rkclk_fracinfo *frac_info;
106 struct rkclk_gateinfo *gate_info;
107 struct list_head node;
110 static DEFINE_SPINLOCK(clk_lock);
112 void __iomem *reg_start = 0;
114 #define RKCLK_PLL_TYPE (1 << 0)
115 #define RKCLK_MUX_TYPE (1 << 1)
116 #define RKCLK_DIV_TYPE (1 << 2)
117 #define RKCLK_FRAC_TYPE (1 << 3)
118 #define RKCLK_GATE_TYPE (1 << 4)
120 static int rkclk_init_muxinfo(struct device_node *np,
121 struct rkclk_muxinfo *mux, void __iomem *addr)
127 mux = kzalloc(sizeof(struct rkclk_muxinfo), GFP_KERNEL);
131 * Get control bit addr
133 ret = of_property_read_u32_index(np, "rockchip,bits", 0, &mux->shift);
137 ret = of_property_read_u32(np, "rockchip,flags", &mux->flags);
141 ret = of_property_read_u32(np, "rockchip,clkops-idx", &mux->clkops_idx);
143 mux->clkops_idx = CLKOPS_TABLE_END;
145 ret = of_property_read_u32_index(np, "rockchip,bits", 1, &mux->width);
150 ret = of_property_read_string(np, "clock-output-names", &mux->clk_name);
157 cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells");
161 mux->parent_num = cnt;
162 mux->parent_names = kzalloc(cnt * sizeof(char *), GFP_KERNEL);
164 clk_debug("%s: parent cnt = %d\n", __func__, cnt);
165 for (i = 0; i < cnt ; i++) {
167 mux->parent_names[i] = of_clk_get_parent_name(np, i);
171 list_for_each_entry(rkclk, &rk_clks, node) {
172 if (strcmp(mux->clk_name, rkclk->clk_name) == 0) {
173 if (rkclk->mux_info != NULL)
174 clk_err("%s(%d): This clk(%s) has been used\n",
175 __func__, __LINE__, mux->clk_name);
176 clk_debug("%s: find match %s\n", __func__, rkclk->clk_name);
178 rkclk->mux_info = mux;
179 rkclk->clk_type |= RKCLK_MUX_TYPE;
184 rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
185 rkclk->clk_name = mux->clk_name;
186 rkclk->mux_info = mux;
187 rkclk->clk_type |= RKCLK_MUX_TYPE;
189 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
191 list_add_tail(&rkclk->node, &rk_clks);
196 static int rkclk_init_divinfo(struct device_node *np,
197 struct rkclk_divinfo *div, void __iomem *addr)
199 int cnt = 0, i = 0, ret = 0;
203 div = kzalloc(sizeof(struct rkclk_divinfo), GFP_KERNEL);
207 of_property_read_u32_index(np, "rockchip,bits", 0, &div->shift);
208 of_property_read_u32_index(np, "rockchip,bits", 1, &div->width);
211 of_property_read_u32(np, "rockchip,div-type", &div->div_type);
213 ret = of_property_read_u32(np, "rockchip,clkops-idx", &div->clkops_idx);
215 div->clkops_idx = CLKOPS_TABLE_END;
217 cnt = of_property_count_strings(np, "clock-output-names");
219 div->clk_name = of_clk_get_parent_name(np, 0);
221 ret = of_property_read_string(np, "clock-output-names", &div->clk_name);
224 div->parent_name = of_clk_get_parent_name(np, 0);
227 switch (div->div_type) {
228 case CLK_DIVIDER_PLUS_ONE:
229 case CLK_DIVIDER_ONE_BASED:
230 case CLK_DIVIDER_POWER_OF_TWO:
232 case CLK_DIVIDER_FIXED:
233 of_property_read_u32_index(np, "rockchip,div-relations", 0,
234 &div->fixed_div_val);
235 clk_debug("%s:%s fixed_div = %d\n", __func__,
236 div->clk_name, div->fixed_div_val);
238 case CLK_DIVIDER_USER_DEFINE:
239 of_get_property(np, "rockchip,div-relations", &cnt);
241 div->div_table = kzalloc(cnt * sizeof(struct clk_div_table),
244 for (i = 0; i < cnt; i++) {
245 of_property_read_u32_index(np, "rockchip,div-relations", i * 2,
246 &div->div_table[i].val);
247 of_property_read_u32_index(np, "rockchip,div-relations", i * 2 + 1,
248 &div->div_table[i].div);
249 clk_debug("\tGet div table %d: val=%d, div=%d\n",
250 i, div->div_table[i].val,
251 div->div_table[i].div);
255 clk_err("%s: %s: unknown rockchip,div-type, please check dtsi\n",
256 __func__, div->clk_name);
261 list_for_each_entry(rkclk, &rk_clks, node) {
262 if (strcmp(div->clk_name, rkclk->clk_name) == 0) {
263 if (rkclk->div_info != NULL)
264 clk_err("%s(Line %d): This clk(%s) has been used\n",
265 __func__, __LINE__, rkclk->clk_name);
266 clk_debug("%s: find match %s\n", __func__, rkclk->clk_name);
268 rkclk->div_info = div;
269 rkclk->clk_type |= RKCLK_DIV_TYPE;
274 rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
275 rkclk->clk_name = div->clk_name;
276 rkclk->div_info = div;
277 rkclk->clk_type |= RKCLK_DIV_TYPE;
279 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
281 list_add_tail(&rkclk->node, &rk_clks);
288 static int rkclk_init_fracinfo(struct device_node *np,
289 struct rkclk_fracinfo *frac, void __iomem *addr)
295 frac = kzalloc(sizeof(struct rkclk_fracinfo), GFP_KERNEL);
299 of_property_read_u32_index(np, "rockchip,bits", 0, &frac->shift);
300 of_property_read_u32_index(np, "rockchip,bits", 1, &frac->width);
303 ret = of_property_read_u32(np, "rockchip,clkops-idx", &frac->clkops_idx);
305 frac->clkops_idx = CLKOPS_TABLE_END;
307 frac->parent_name = of_clk_get_parent_name(np, 0);
308 ret = of_property_read_string(np, "clock-output-names", &frac->clk_name);
313 list_for_each_entry(rkclk, &rk_clks, node) {
314 if (strcmp(frac->clk_name, rkclk->clk_name) == 0) {
315 if (rkclk->frac_info != NULL)
316 clk_err("%s(%d): This clk(%s) has been used\n",
317 __func__, __LINE__, frac->clk_name);
318 clk_debug("%s: find match %s\n", __func__, rkclk->clk_name);
320 rkclk->frac_info = frac;
321 rkclk->clk_type |= RKCLK_FRAC_TYPE;
326 rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
327 rkclk->clk_name = frac->clk_name;
328 rkclk->frac_info = frac;
329 rkclk->clk_type |= RKCLK_FRAC_TYPE;
331 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
333 list_add_tail(&rkclk->node, &rk_clks);
338 static int __init rkclk_init_selcon(struct device_node *np)
340 struct device_node *node_con, *node;
341 void __iomem *reg = 0;
343 struct rkclk_divinfo *divinfo;
344 struct rkclk_muxinfo *muxinfo;
345 struct rkclk_fracinfo *fracinfo;
347 for_each_available_child_of_node(np, node_con) {
349 reg = of_iomap(node_con, 0);
351 for_each_available_child_of_node(node_con, node) {
353 if (of_device_is_compatible(node, "rockchip,rk3188-div-con"))
354 rkclk_init_divinfo(node, divinfo, reg);
356 else if (of_device_is_compatible(node, "rockchip,rk3188-mux-con"))
357 rkclk_init_muxinfo(node, muxinfo, reg);
359 else if (of_device_is_compatible(node, "rockchip,rk3188-frac-con"))
360 rkclk_init_fracinfo(node, fracinfo, reg);
362 else if (of_device_is_compatible(node, "rockchip,rk3188-inv-con"))
363 clk_debug("INV clk\n");
366 clk_err("%s: unknown controler type, plz check dtsi "
367 "or add type support\n", __func__);
374 static int __init rkclk_init_gatecon(struct device_node *np)
376 struct clk_onecell_data *clk_data;
377 struct device_node *node;
378 const char *clk_parent;
379 const char *clk_name;
381 void __iomem *reg_idx;
385 struct rkclk_gateinfo *gateinfo;
389 for_each_available_child_of_node(np, node) {
390 cnt = of_property_count_strings(node, "clock-output-names");
392 clk_err("%s: error in clock-output-names %d\n",
398 pr_info("%s: nothing to do\n", __func__);
402 reg = of_iomap(node, 0);
404 clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
408 clk_data->clks = kzalloc(cnt * sizeof(struct clk *), GFP_KERNEL);
409 if (!clk_data->clks) {
414 for (i = 0; i < cnt; i++) {
415 of_property_read_string_index(node, "clock-output-names",
418 /* ignore empty slots */
419 if (!strcmp("reserved", clk_name))
422 clk_parent = of_clk_get_parent_name(node, i);
424 reg_idx = reg + (4 * (i / 16));
427 gateinfo = kzalloc(sizeof(struct rkclk_gateinfo), GFP_KERNEL);
428 gateinfo->clk_name = clk_name;
429 gateinfo->parent_name = clk_parent;
430 gateinfo->addr = reg;
431 gateinfo->shift = reg_bit;
433 list_for_each_entry(rkclk, &rk_clks, node) {
434 if (strcmp(clk_name, rkclk->clk_name) == 0) {
435 if (rkclk->gate_info != NULL)
436 clk_err("%s(%d): This clk(%s) has been used\n",
437 __func__, __LINE__, clk_name);
438 clk_debug("%s: find match %s\n", __func__, rkclk->clk_name);
440 rkclk->gate_info = gateinfo;
441 rkclk->clk_type |= RKCLK_GATE_TYPE;
446 rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
447 rkclk->clk_name = gateinfo->clk_name;
448 rkclk->gate_info = gateinfo;
449 rkclk->clk_type |= RKCLK_GATE_TYPE;
451 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
453 list_add_tail(&rkclk->node, &rk_clks);
461 static int __init rkclk_init_pllcon(struct device_node *np)
463 struct rkclk_pllinfo *pllinfo;
464 struct device_node *node;
468 int ret = 0, clknum = 0;
471 for_each_available_child_of_node(np, node) {
472 clknum = of_property_count_strings(node, "clock-output-names");
474 clk_err("%s: error in get clock-output-names numbers = %d\n",
478 reg = of_iomap(node, 0);
481 for (i = 0; i < clknum; i++) {
482 pllinfo = kzalloc(sizeof(struct rkclk_pllinfo), GFP_KERNEL);
487 * Get pll parent name
489 pllinfo->parent_name = of_clk_get_parent_name(node, i);
492 * Get pll output name
494 of_property_read_string_index(node, "clock-output-names",
495 i, &pllinfo->clk_name);
499 ret = of_property_read_u32_index(node, "reg", 1, &pllinfo->width);
501 clk_err("%s: can not get reg info\n", __func__);
504 ret = of_property_read_u32(node, "rockchip,pll-id", &pllinfo->id);
506 clk_err("%s: can not get pll-id\n", __func__);
509 clk_debug("%s: parent=%s, pllname=%s, reg =%08x, id = %d, cnt=%d\n",
510 __func__,pllinfo->parent_name,
511 pllinfo->clk_name,(u32)pllinfo->addr,
512 pllinfo->id,pllinfo->width);
515 list_for_each_entry(rkclk, &rk_clks, node) {
516 if (strcmp(pllinfo->clk_name, rkclk->clk_name) == 0) {
517 if (rkclk->pll_info != NULL)
518 clk_err("%s(%d): This clk(%s) has been used\n",
519 __func__, __LINE__, pllinfo->clk_name);
520 clk_debug("%s: find match %s\n", __func__, rkclk->clk_name);
522 rkclk->pll_info = pllinfo;
523 rkclk->clk_type |= RKCLK_PLL_TYPE;
528 rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
529 rkclk->clk_name = pllinfo->clk_name;
530 rkclk->pll_info = pllinfo;
531 rkclk->clk_type |= RKCLK_PLL_TYPE;
534 list_add_tail(&rkclk->node, &rk_clks);
542 static unsigned long clk_div_special_recalc_rate(struct clk_hw *hw,
543 unsigned long parent_rate)
547 static long clk_div_special_round_rate(struct clk_hw *hw, unsigned long rate,
548 unsigned long *prate)
552 static int clk_div_special_set_rate(struct clk_hw *hw, unsigned long rate,
553 unsigned long parent_rate)
558 // For fixed div clks and For user defined div clk
559 const struct clk_ops clk_div_special_ops = {
560 .recalc_rate = clk_div_special_recalc_rate,
561 .round_rate = clk_div_special_round_rate,
562 .set_rate = clk_div_special_set_rate,
565 static int rkclk_register(struct rkclk *rkclk)
567 struct clk_mux *mux = NULL;
568 struct clk_divider *div = NULL;
569 struct clk_gate *gate = NULL;
570 struct clk_pll *pll = NULL;
572 const struct clk_ops *rate_ops = NULL;
573 const struct clk_ops *mux_ops = NULL;
575 struct clk *clk = NULL;
576 const char **parent_names = NULL;
577 struct clk_hw *rate_hw;
579 struct device_node *node = rkclk->np;
580 unsigned long flags = 0;
583 clk_debug("%s >>>>>start: clk_name=%s, clk_type=%x\n",
584 __func__, rkclk->clk_name, rkclk->clk_type);
586 if (rkclk->clk_type & RKCLK_PLL_TYPE) {
587 pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL);
588 rate_ops = &clk_pll_ops;
589 pll->reg = rkclk->pll_info->addr;
591 pll->width = rkclk->pll_info->width;
592 pll->id = rkclk->pll_info->id;
596 parent_names = &rkclk->pll_info->parent_name;
598 } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) {
599 div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
600 div->reg = rkclk->frac_info->addr;
601 div->shift = (u8)rkclk->frac_info->shift;
602 div->width = rkclk->frac_info->width;
603 div->flags = CLK_DIVIDER_HIWORD_MASK;
606 rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx);
609 parent_names = &rkclk->frac_info->parent_name;
611 flags |= CLK_SET_RATE_PARENT;
613 } else if (rkclk->clk_type & RKCLK_DIV_TYPE) {
614 div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
615 if (rkclk->div_info->clkops_idx != CLKOPS_TABLE_END)
616 rate_ops = rk_get_clkops(rkclk->div_info->clkops_idx);
618 rate_ops = &clk_divider_ops;
619 div->reg = rkclk->div_info->addr;
620 div->shift = (u8)rkclk->div_info->shift;
621 div->width = rkclk->div_info->width;
622 div->flags = CLK_DIVIDER_HIWORD_MASK | rkclk->div_info->div_type;
624 if (rkclk->div_info->div_table)
625 div->table = rkclk->div_info->div_table;
628 parent_names = &rkclk->div_info->parent_name;
629 if (rkclk->clk_type != (rkclk->clk_type & CLK_DIVIDER_MASK)) {
630 // FIXME: fixed div add here
631 clk_err("%s: %d, unknown clk_type=%x\n",
632 __func__, __LINE__, rkclk->clk_type);
637 if (rkclk->clk_type & RKCLK_MUX_TYPE) {
638 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
639 mux->reg = rkclk->mux_info->addr;
640 mux->shift = (u8)rkclk->mux_info->shift;
641 mux->mask = (1 << rkclk->mux_info->width) - 1;
642 mux->flags = CLK_MUX_HIWORD_MASK;
643 mux_ops = &clk_mux_ops;
644 if (rkclk->mux_info->clkops_idx != CLKOPS_TABLE_END) {
645 rate_hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL);
646 rate_ops = rk_get_clkops(rkclk->mux_info->clkops_idx);
649 parent_num = rkclk->mux_info->parent_num;
650 parent_names = rkclk->mux_info->parent_names;
651 flags |= rkclk->mux_info->flags;
654 if (rkclk->clk_type & RKCLK_GATE_TYPE) {
655 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
656 gate->reg = rkclk->gate_info->addr;
657 gate->bit_idx = rkclk->gate_info->shift;
658 gate->flags = CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE;
662 // FIXME: flag(CLK_IGNORE_UNUSED) may need an input argument
663 if (rkclk->clk_type == RKCLK_MUX_TYPE
664 && rkclk->mux_info->clkops_idx == CLKOPS_TABLE_END) {
665 clk_debug("use clk_register_mux\n");
666 clk = clk_register_mux(NULL, rkclk->clk_name,
667 rkclk->mux_info->parent_names,
668 (u8)rkclk->mux_info->parent_num,
669 flags, mux->reg, mux->shift, mux->mask,
671 } else if (rkclk->clk_type == RKCLK_DIV_TYPE) {
672 clk_debug("use clk_register_divider\n");
673 clk = clk_register_divider(NULL, rkclk->clk_name,
674 rkclk->div_info->parent_name,
675 flags, div->reg, div->shift,
676 div->width, div->flags, &clk_lock);
677 } else if (rkclk->clk_type == RKCLK_GATE_TYPE) {
678 clk_debug("use clk_register_gate\n");
679 clk = clk_register_gate(NULL, rkclk->clk_name,
680 rkclk->gate_info->parent_name,
683 gate->flags, &clk_lock);
684 } else if (rkclk->clk_type == RKCLK_PLL_TYPE) {
685 clk_debug("use rk_clk_register_pll\n");
686 clk = rk_clk_register_pll(NULL, rkclk->clk_name,
687 rkclk->pll_info->parent_name,
688 flags, pll->reg, pll->width,
691 clk_debug("use clk_register_composite\n");
692 clk = clk_register_composite(NULL, rkclk->clk_name,
693 parent_names, parent_num,
694 mux ? &mux->hw : NULL, mux ? mux_ops : NULL,
696 gate ? &gate->hw : NULL, gate ? &clk_gate_ops : NULL,
701 clk_debug("clk name=%s, flags=0x%lx\n", clk->name, clk->flags);
702 of_clk_add_provider(node, of_clk_src_simple_get, clk);
703 clk_register_clkdev(clk, rkclk->clk_name, NULL);
705 clk_err("%s: clk(\"%s\") register clk error\n",
706 __func__, rkclk->clk_name);
718 struct test_table t_table[] = {
719 {.name = "clk_gpu", .rate = 297000000},
720 {.name = "dclk_lcdc0", .rate = 100000000},
721 {.name = "aclk_lcdc0", .rate = 297000000},
723 {.name = "clk_sdmmc", .rate = 50000000},
724 {.name = "clk_emmc", .rate = 50000000},
725 {.name = "clk_sdio", .rate = 50000000},
727 {.name = "clk_i2s_div", .rate = 300000000},
728 {.name = "clk_i2s_frac",.rate = 22579200},
729 {.name = "clk_i2s", .rate = 11289600},
730 {.name = "clk_spdif", .rate = 11289600},
732 {.name = "cif_out_pll", .rate = 48000000},
733 {.name = "clk_cif0", .rate = 12000000},
735 {.name = "clk_uart0", .rate = 12288000},
736 {.name = "clk_uart1", .rate = 48000000},
737 {.name = "clk_hsadc", .rate = 12288000},
738 {.name = "clk_mac", .rate = 50000000},
740 {.name = "clk_apll", .rate = 500000000},
741 {.name = "clk_dpll", .rate = 400000000},
742 {.name = "clk_cpll", .rate = 600000000},
743 {.name = "clk_gpll", .rate = 800000000},
746 void rk_clk_test(void)
748 const char *clk_name;
750 unsigned long rate=0, recalc_rate=0, round_rate=0, get_rate=0;
754 for (j = 0; j < ARRAY_SIZE(t_table); j++) {
755 clk_debug(">>>>>>test %u\n", j);
757 clk_name = t_table[j].name;
758 rate = t_table[j].rate;
760 clk = clk_get(NULL, clk_name);
762 clk_err("%s: clk(\"%s\") \tclk_get error\n",
765 clk_debug("%s: clk(\"%s\") \tclk_get success\n",
768 /* TEST: clk_round_rate */
769 round_rate = clk_round_rate(clk, rate);
770 clk_debug("%s: clk(\"%s\") \tclk_round_rate from %lu to %lu\n",
771 __func__, clk_name, rate, round_rate);
773 /* TEST: clk_set_rate */
774 ret = clk_set_rate(clk, rate);
776 clk_err("%s: clk(\"%s\") \tclk_set_rate error, ret=%d\n",
777 __func__, clk_name, ret);
779 clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n",
783 /* TEST: recalc_rate\clk_get_rate */
784 if (clk->ops->recalc_rate) {
785 recalc_rate = clk->ops->recalc_rate(clk->hw,
787 clk_debug("%s: clk(\"%s\") \tclk_recalc_rate %lu\n",
788 __func__, clk_name, recalc_rate);
790 clk_debug("%s: clk(\"%s\") have no recalc ops\n",
792 get_rate = clk_get_rate(clk);
793 clk_debug("%s: clk(\"%s\") \tclk_get_rate %lu\n",
794 __func__, clk_name, get_rate);
799 printk("dump cru regs:");
800 for (i = 0; i * 4 <= 0xf4; i++) {
802 printk("\n%s: \t[0x%08x]: ",
803 __func__, 0x20000000 + i * 4);
804 printk("%08x ", readl(reg_start + i * 4));
812 EXPORT_SYMBOL_GPL(rk_clk_test);
814 void rk_clk_test(void){};
815 EXPORT_SYMBOL_GPL(rk_clk_test);
818 void rkclk_init_clks(struct device_node *node);
820 static void __init rk_clk_tree_init(struct device_node *np)
822 struct device_node *node;
824 struct device_node *node_init;
827 node_init=of_find_node_by_name(NULL,"clocks-init");
830 printk("%s:can not get clocks-init node\n",__FUNCTION__);
834 for_each_available_child_of_node(np, node) {
836 if (!ERR_PTR(of_property_match_string(node,
841 } else if (!ERR_PTR(of_property_match_string(node,
843 "rockchip,rk-pll-cons"))) {
844 if (ERR_PTR(rkclk_init_pllcon(node))) {
845 clk_err("%s: init pll clk err\n", __func__);
849 } else if (!ERR_PTR(of_property_match_string(node,
851 "rockchip,rk-sel-cons"))) {
852 if (ERR_PTR(rkclk_init_selcon(node))) {
853 clk_err("%s: init sel cons err\n", __func__);
857 } else if (!ERR_PTR(of_property_match_string(node,
859 "rockchip,rk-gate-cons"))) {
860 if (ERR_PTR(rkclk_init_gatecon(node))) {
861 clk_err("%s: init gate cons err\n", __func__);
866 clk_err("%s: unknown\n", __func__);
872 list_for_each_entry(rkclk, &rk_clks, node) {
874 clk_debug("%s: clkname = %s; type=%d\n",
875 __func__, rkclk->clk_name,
877 if (rkclk->pll_info) {
878 clk_debug("\t\tpll: name=%s, parent=%s\n",
879 rkclk->pll_info->clk_name,
880 rkclk->pll_info->parent_name);
882 if (rkclk->mux_info) {
883 for (i = 0; i < rkclk->mux_info->parent_num; i++)
884 clk_debug("\t\tmux name=%s, parent: %s\n",
885 rkclk->mux_info->clk_name,
886 rkclk->mux_info->parent_names[i]);
888 if (rkclk->div_info) {
889 clk_debug("\t\tdiv name=%s\n",
890 rkclk->div_info->clk_name);
892 if (rkclk->frac_info) {
893 clk_debug("\t\tfrac name=%s\n",
894 rkclk->frac_info->clk_name);
896 if (rkclk->gate_info) {
897 clk_debug("\t\tgate name=%s, \taddr=%08x, \tshift=%d\n",
898 rkclk->gate_info->clk_name,
899 (u32)rkclk->gate_info->addr,
900 rkclk->gate_info->shift);
905 list_for_each_entry(rkclk, &rk_clks, node) {
906 rkclk_register(rkclk);
909 /* check clock parents init */
910 list_for_each_entry(rkclk, &rk_clks, node) {
913 const char *clk_name = rkclk->clk_name;
914 clk = clk_get(NULL, clk_name);
916 clk_err("%s: clk(\"%s\") \tclk_get error\n",
920 clk_debug("%s: clk(\"%s\") \tclk_get success\n",
921 __func__, __clk_get_name(clk));
925 for (i = 0; i < clk->num_parents; i++) {
927 clk_debug("\t\tclk(\"%s\"): init parent:%s\n",
929 clk->parents[i]->name);
931 clk->parents[i] = clk_get(NULL, clk->parent_names[i]);
932 clk_debug("\t\tclk(\"%s\"): init parent:%s\n",
934 clk->parents[i]->name);
939 clk_debug("\t\tNOT A MUX CLK, parent num=%d\n", clk->num_parents);
943 rkclk_init_clks(node_init);
946 CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init);
949 /********************************** rockchip clks init****************************************/
950 const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rate)
952 struct of_phandle_args clkspec;
953 const char *clk_name;
959 rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells", index,
964 if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0)
967 *rate= clkspec.args[0];
969 of_node_put(clkspec.np);
973 const char *of_clk_init_parent_get_info(struct device_node *np, int index,const char **clk_child_name)
975 struct of_phandle_args clkspec;
976 const char *clk_name;
979 struct device_node *node = NULL;
984 rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells", index,
989 if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0)
993 phandle = clkspec.args[0];
995 of_node_put(clkspec.np);
999 node = of_find_node_by_phandle(phandle);
1004 if (of_property_read_string_index(node, "clock-output-names",0,clk_child_name) < 0)
1007 of_node_put(node);//???
1016 void rkclk_init_clks(struct device_node *np)
1018 //struct device_node *np;
1019 int i,cnt_parent,cnt_rate;
1022 struct clk * clk_p,*clk_c;
1024 const char * clk_name,*clk_parent_name;
1027 cnt_parent = of_count_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells");
1029 printk("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent);
1032 for (i = 0; i < cnt_parent; i++) {
1033 clk_parent_name=NULL;
1034 clk_name=of_clk_init_parent_get_info(np, i,&clk_parent_name);
1036 if(clk_name==NULL||clk_parent_name==NULL)
1039 clk_c=clk_get(NULL,clk_name);
1040 clk_p=clk_get(NULL,clk_parent_name);
1042 printk("%s: set parent %s=%x,%s=%x\n",__FUNCTION__,clk_name,(u32)clk_c,clk_parent_name,(u32)clk_p);
1043 if(IS_ERR(clk_c)||IS_ERR(clk_p))
1045 //clk_set_parent(clk_name, clk_parent_name);
1048 cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells");
1050 printk("%s:rate cnt=%d\n",__FUNCTION__,cnt_rate);
1052 for (i = 0; i < cnt_rate; i++) {
1053 clk_name=of_clk_init_rate_get_info(np, i,&clk_rate);
1058 clk_p=clk_get(NULL,clk_name);
1060 printk("%s: set rate %s=%x,rate=%d\n",__FUNCTION__,clk_name,(u32)clk_p,clk_rate);
1062 if(IS_ERR(clk_c)||(clk_rate<1*1000*1000)||(clk_rate>2000*1000*1000))
1064 //clk_set_rate(clk_p,clk_rate);