rk_clk: modify clk-ops.c to reuse and fit the common clk framework.
[firefly-linux-kernel-4.4.55.git] / drivers / clk / rockchip / clk.c
1 /*
2  * Copyright (C) 2013 ROCKCHIP, Inc.
3  * Author: chenxing <chenxing@rock-chips.com>
4  *
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.
8  *
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.
13  *
14  */
15
16 #include <linux/clk-provider.h>
17 #include <linux/clkdev.h>
18 #include <linux/of.h>
19 #include <linux/of_address.h>
20 #include <linux/clk-private.h>
21 #include <asm/io.h>
22
23 #include "clk-ops.h"
24 #include "clk-pll.h"
25
26
27 struct rkclk_divmap_table {
28         u32             reg_val;
29         u32             div_val;
30 };
31
32 struct rkclk_divinfo {
33         struct clk_divider *div;
34         void __iomem    *addr;
35         u32             shift;
36         u32             width;
37         u32             div_type;
38         u32             max_div;
39         u32             fixed_div_val;
40         u32             clkops_idx;
41         const char      *clk_name;
42         const char      *parent_name;
43         struct clk_div_table            *div_table;
44         struct list_head                node;
45 };
46
47 struct rkclk_muxinfo {
48         struct clk_mux  *mux;
49         void __iomem    *addr;
50         u32             shift;
51         u32             width;
52         u32             parent_num;
53         u32             clkops_idx;
54         u32             flags;
55         const char      *clk_name;
56         const char      **parent_names;
57         struct list_head        node;
58 };
59
60 struct rkclk_fracinfo {
61         struct clk_hw   hw;
62         void __iomem    *addr;
63         u32             shift;
64         u32             width;
65         u32             frac_type;
66         u32             clkops_idx;
67         const char      *clk_name;
68         const char      *parent_name;
69         struct list_head        node;
70 };
71
72 struct rkclk_gateinfo {
73         struct clk_gate *gate;
74         void __iomem    *addr;
75         u32             shift;
76         u32             clkops_idx;
77         const char      *clk_name;
78         const char      *parent_name;
79 };
80
81 struct rkclk_pllinfo {
82         struct clk_hw   hw;
83         void __iomem    *addr;
84         u32             width;
85         const char      *clk_name;
86         const char      *parent_name;
87         /*
88          * const char   **clkout_names;
89          */
90         u32             clkops_idx;
91         u32             id;
92         struct list_head        node;
93 };
94
95 struct rkclk {
96         const char      *clk_name;
97         u32             clk_type;
98         /*
99          * store nodes creat this rkclk
100          * */
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;
108 };
109
110 static DEFINE_SPINLOCK(clk_lock);
111 LIST_HEAD(rk_clks);
112 void __iomem *reg_start = 0;
113
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)
119
120 static int rkclk_init_muxinfo(struct device_node *np,
121                 struct rkclk_muxinfo *mux, void __iomem *addr)
122 {
123         int cnt, i, ret = 0;
124         u8 found = 0;
125         struct rkclk *rkclk;
126
127         mux = kzalloc(sizeof(struct rkclk_muxinfo), GFP_KERNEL);
128         if (!mux)
129                 return -ENOMEM;
130         /*
131          * Get control bit addr
132          */
133         ret = of_property_read_u32_index(np, "rockchip,bits", 0, &mux->shift);
134         if (ret != 0)
135                 return -EINVAL;
136
137         ret = of_property_read_u32(np, "rockchip,flags", &mux->flags);
138         if (ret != 0)
139                 mux->flags = 0;
140
141         ret = of_property_read_u32(np, "rockchip,clkops-idx", &mux->clkops_idx);
142         if (ret != 0)
143                 mux->clkops_idx = CLKOPS_TABLE_END;
144
145         ret = of_property_read_u32_index(np, "rockchip,bits", 1, &mux->width);
146         if (ret != 0)
147                 return -EINVAL;
148         mux->addr = addr;
149
150         ret = of_property_read_string(np, "clock-output-names", &mux->clk_name);
151         if (ret != 0)
152                 return -EINVAL;
153
154         /*
155          * Get parents' cnt
156          */
157         cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells");
158         if (cnt< 0)
159                 return -EINVAL;
160
161         mux->parent_num = cnt;
162         mux->parent_names = kzalloc(cnt * sizeof(char *), GFP_KERNEL);
163
164         clk_debug("%s: parent cnt = %d\n", __func__, cnt);
165         for (i = 0; i < cnt ; i++) {
166
167                 mux->parent_names[i] = of_clk_get_parent_name(np, i);
168         }
169
170         found = 0;
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);
177                         found = 1;
178                         rkclk->mux_info = mux;
179                         rkclk->clk_type |= RKCLK_MUX_TYPE;
180                         break;
181                 }
182         }
183         if (!found) {
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;
188                 rkclk->np = np;
189                 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
190
191                 list_add_tail(&rkclk->node, &rk_clks);
192         }
193         return 0;
194 }
195
196 static int rkclk_init_divinfo(struct device_node *np,
197                 struct rkclk_divinfo *div, void __iomem *addr)
198 {
199         int cnt = 0, i = 0, ret = 0;
200         struct rkclk *rkclk;
201         u8 found = 0;
202
203         div = kzalloc(sizeof(struct rkclk_divinfo), GFP_KERNEL);
204         if (!div)
205                 return -ENOMEM;
206
207         of_property_read_u32_index(np, "rockchip,bits", 0, &div->shift);
208         of_property_read_u32_index(np, "rockchip,bits", 1, &div->width);
209         div->addr = addr;
210
211         of_property_read_u32(np, "rockchip,div-type", &div->div_type);
212
213         ret = of_property_read_u32(np, "rockchip,clkops-idx", &div->clkops_idx);
214         if (ret != 0)
215                 div->clkops_idx = CLKOPS_TABLE_END;
216
217         cnt = of_property_count_strings(np, "clock-output-names");
218         if (cnt <= 0)
219                 div->clk_name = of_clk_get_parent_name(np, 0);
220         else {
221                 ret = of_property_read_string(np, "clock-output-names", &div->clk_name);
222                 if (ret != 0)
223                         return -EINVAL;
224                 div->parent_name = of_clk_get_parent_name(np, 0);
225         }
226
227         switch (div->div_type) {
228                 case CLK_DIVIDER_PLUS_ONE:
229                 case CLK_DIVIDER_ONE_BASED:
230                 case CLK_DIVIDER_POWER_OF_TWO:
231                         break;
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);
237                         break;
238                 case CLK_DIVIDER_USER_DEFINE:
239                         of_get_property(np, "rockchip,div-relations", &cnt);
240                         cnt /= 4 * 2;
241                         div->div_table = kzalloc(cnt * sizeof(struct clk_div_table),
242                                         GFP_KERNEL);
243
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);
252                         }
253                         break;
254                 default:
255                         clk_err("%s: %s: unknown rockchip,div-type, please check dtsi\n",
256                                         __func__, div->clk_name);
257                         break;
258         }
259
260         found = 0;
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);
267                         found = 1;
268                         rkclk->div_info = div;
269                         rkclk->clk_type |= RKCLK_DIV_TYPE;
270                         break;
271                 }
272         }
273         if (!found) {
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;
278                 rkclk->np = np;
279                 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
280
281                 list_add_tail(&rkclk->node, &rk_clks);
282         }
283         return 0;
284
285
286 }
287
288 static int rkclk_init_fracinfo(struct device_node *np,
289                 struct rkclk_fracinfo *frac, void __iomem *addr)
290 {
291         struct rkclk *rkclk;
292         u8 found = 0;
293         int ret = 0;
294
295         frac = kzalloc(sizeof(struct rkclk_fracinfo), GFP_KERNEL);
296         if (!frac)
297                 return -ENOMEM;
298
299         of_property_read_u32_index(np, "rockchip,bits", 0, &frac->shift);
300         of_property_read_u32_index(np, "rockchip,bits", 1, &frac->width);
301         frac->addr = addr;
302
303         ret = of_property_read_u32(np, "rockchip,clkops-idx", &frac->clkops_idx);
304         if (ret != 0)
305                 frac->clkops_idx = CLKOPS_TABLE_END;
306
307         frac->parent_name = of_clk_get_parent_name(np, 0);
308         ret = of_property_read_string(np, "clock-output-names", &frac->clk_name);
309         if (ret != 0)
310                 return -EINVAL;
311
312         found = 0;
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);
319                         found = 1;
320                         rkclk->frac_info = frac;
321                         rkclk->clk_type |= RKCLK_FRAC_TYPE;
322                         break;
323                 }
324         }
325         if (!found) {
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;
330                 rkclk->np = np;
331                 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
332
333                 list_add_tail(&rkclk->node, &rk_clks);
334         }
335         return 0;
336 }
337
338 static int __init rkclk_init_selcon(struct device_node *np)
339 {
340         struct device_node *node_con, *node;
341         void __iomem *reg = 0;
342
343         struct rkclk_divinfo *divinfo;
344         struct rkclk_muxinfo *muxinfo;
345         struct rkclk_fracinfo *fracinfo;
346
347         for_each_available_child_of_node(np, node_con) {
348
349                 reg = of_iomap(node_con, 0);
350
351                 for_each_available_child_of_node(node_con, node) {
352
353                         if (of_device_is_compatible(node, "rockchip,rk3188-div-con"))
354                                 rkclk_init_divinfo(node, divinfo, reg);
355
356                         else if (of_device_is_compatible(node, "rockchip,rk3188-mux-con"))
357                                 rkclk_init_muxinfo(node, muxinfo, reg);
358
359                         else if (of_device_is_compatible(node, "rockchip,rk3188-frac-con"))
360                                 rkclk_init_fracinfo(node, fracinfo, reg);
361
362                         else if (of_device_is_compatible(node, "rockchip,rk3188-inv-con"))
363                                 clk_debug("INV clk\n");
364
365                         else
366                                 clk_err("%s: unknown controler type, plz check dtsi "
367                                                 "or add type support\n", __func__);
368
369                 }
370         }
371         return 0;
372 }
373
374 static int __init rkclk_init_gatecon(struct device_node *np)
375 {
376         struct clk_onecell_data *clk_data;
377         struct device_node *node;
378         const char *clk_parent;
379         const char *clk_name;
380         void __iomem *reg;
381         void __iomem *reg_idx;
382         int cnt;
383         int reg_bit;
384         int i;
385         struct rkclk_gateinfo *gateinfo;
386         u8 found = 0;
387         struct rkclk *rkclk;
388
389         for_each_available_child_of_node(np, node) {
390                 cnt = of_property_count_strings(node, "clock-output-names");
391                 if (cnt < 0) {
392                         clk_err("%s: error in clock-output-names %d\n",
393                                         __func__, cnt);
394                         continue;
395                 }
396
397                 if (cnt == 0) {
398                         pr_info("%s: nothing to do\n", __func__);
399                         continue;
400                 }
401
402                 reg = of_iomap(node, 0);
403
404                 clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
405                 if (!clk_data)
406                         return -ENOMEM;
407
408                 clk_data->clks = kzalloc(cnt * sizeof(struct clk *), GFP_KERNEL);
409                 if (!clk_data->clks) {
410                         kfree(clk_data);
411                         return -ENOMEM;
412                 }
413
414                 for (i = 0; i < cnt; i++) {
415                         of_property_read_string_index(node, "clock-output-names",
416                                         i, &clk_name);
417
418                         /* ignore empty slots */
419                         if (!strcmp("reserved", clk_name))
420                                 continue;
421
422                         clk_parent = of_clk_get_parent_name(node, i);
423
424                         reg_idx = reg + (4 * (i / 16));
425                         reg_bit = (i % 16);
426
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;
432                         found = 0;
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);
439                                         found = 1;
440                                         rkclk->gate_info = gateinfo;
441                                         rkclk->clk_type |= RKCLK_GATE_TYPE;
442                                         break;
443                                 }
444                         }
445                         if (!found) {
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;
450                                 rkclk->np = node;
451                                 clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
452
453                                 list_add_tail(&rkclk->node, &rk_clks);
454                         }
455                 }
456
457         }
458         return 0;
459 }
460
461 static int __init rkclk_init_pllcon(struct device_node *np)
462 {
463         struct rkclk_pllinfo *pllinfo;
464         struct device_node *node;
465         struct rkclk *rkclk;
466         void __iomem    *reg;
467         int i = 0;
468         int ret = 0, clknum = 0;
469         u8 found = 0;
470
471         for_each_available_child_of_node(np, node) {
472                 clknum = of_property_count_strings(node, "clock-output-names");
473                 if (clknum < 0) {
474                         clk_err("%s: error in get clock-output-names numbers = %d\n",
475                                         __func__, clknum);
476                         return -EINVAL;
477                 }
478                 reg = of_iomap(node, 0);
479                 if (reg_start == 0)
480                         reg_start = reg;
481                 for (i = 0; i < clknum; i++) {
482                         pllinfo = kzalloc(sizeof(struct rkclk_pllinfo), GFP_KERNEL);
483                         if (!pllinfo)
484                                 return -ENOMEM;
485
486                         /*
487                          * Get pll parent name
488                          */
489                         pllinfo->parent_name = of_clk_get_parent_name(node, i);
490
491                         /*
492                          * Get pll output name
493                          */
494                         of_property_read_string_index(node, "clock-output-names",
495                                         i, &pllinfo->clk_name);
496
497                         pllinfo->addr = reg;
498
499                         ret = of_property_read_u32_index(node, "reg", 1, &pllinfo->width);
500                         if (ret != 0) {
501                                 clk_err("%s: can not get reg info\n", __func__);
502                         }
503
504                         ret = of_property_read_u32(node, "rockchip,pll-id", &pllinfo->id);
505                         if (ret != 0) {
506                                 clk_err("%s: can not get pll-id\n", __func__);
507                         }
508
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);
513
514                         found = 0;
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);
521                                         found = 1;
522                                         rkclk->pll_info = pllinfo;
523                                         rkclk->clk_type |= RKCLK_PLL_TYPE;
524                                         break;
525                                 }
526                         }
527                         if (!found) {
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;
532                                 rkclk->np = node;
533
534                                 list_add_tail(&rkclk->node, &rk_clks);
535                         }
536                 }
537         }
538
539         return 0;
540 }
541
542 static unsigned long clk_div_special_recalc_rate(struct clk_hw *hw,
543                 unsigned long parent_rate)
544 {
545         return parent_rate;
546 }
547 static long clk_div_special_round_rate(struct clk_hw *hw, unsigned long rate,
548                 unsigned long *prate)
549 {
550         return rate;
551 }
552 static int clk_div_special_set_rate(struct clk_hw *hw, unsigned long rate,
553                 unsigned long parent_rate)
554 {
555         return 0;
556 }
557
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,
563 };
564
565 static int rkclk_register(struct rkclk *rkclk)
566 {
567         struct clk_mux          *mux = NULL;
568         struct clk_divider      *div = NULL;
569         struct clk_gate         *gate = NULL;
570         struct clk_pll          *pll = NULL;
571
572         const struct clk_ops    *rate_ops = NULL;
573         const struct clk_ops    *mux_ops = NULL;
574
575         struct clk              *clk = NULL;
576         const char              **parent_names = NULL;
577         struct clk_hw           *rate_hw;
578         int                     parent_num;
579         struct device_node      *node = rkclk->np;
580         unsigned long           flags = 0;
581
582
583         clk_debug("%s >>>>>start: clk_name=%s, clk_type=%x\n",
584                         __func__, rkclk->clk_name, rkclk->clk_type);
585
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;
590                 //pll->shift = 0;
591                 pll->width = rkclk->pll_info->width;
592                 pll->id = rkclk->pll_info->id;
593                 rate_hw = &pll->hw;
594
595                 parent_num = 1;
596                 parent_names = &rkclk->pll_info->parent_name;
597
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;
604
605                 rate_hw = &div->hw;
606                 rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx);
607
608                 parent_num = 1;
609                 parent_names = &rkclk->frac_info->parent_name;
610
611                 flags |= CLK_SET_RATE_PARENT;
612
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);
617                 else
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;
623                 rate_hw = &div->hw;
624                 if (rkclk->div_info->div_table)
625                         div->table = rkclk->div_info->div_table;
626
627                 parent_num = 1;
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);
633
634                 }
635         }
636
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);
647                 }
648
649                 parent_num = rkclk->mux_info->parent_num;
650                 parent_names = rkclk->mux_info->parent_names;
651                 flags |= rkclk->mux_info->flags;
652         }
653
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;
659
660         }
661
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,
670                                 0, &clk_lock);
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,
681                                 flags, gate->reg,
682                                 gate->bit_idx,
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,
689                                 pll->id, &clk_lock);
690         } else {
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,
695                                 rate_hw, rate_ops,
696                                 gate ? &gate->hw : NULL, gate ? &clk_gate_ops : NULL,
697                                 flags);
698         }
699
700         if (clk) {
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);
704         } else {
705                 clk_err("%s: clk(\"%s\") register clk error\n",
706                                 __func__, rkclk->clk_name);
707         }
708
709         return 0;
710 }
711
712 #ifdef RKCLK_TEST
713 struct test_table {
714         const char *name;
715         u32 rate;
716 };
717
718 struct test_table t_table[] = {
719         {.name = "clk_gpu",     .rate = 297000000},
720         {.name = "dclk_lcdc0",  .rate = 100000000},
721         {.name = "aclk_lcdc0",  .rate = 297000000},
722
723         {.name = "clk_sdmmc",   .rate = 50000000},
724         {.name = "clk_emmc",    .rate = 50000000},
725         {.name = "clk_sdio",    .rate = 50000000},
726
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},
731
732         {.name = "cif_out_pll", .rate = 48000000},
733         {.name = "clk_cif0",    .rate = 12000000},
734
735         {.name = "clk_uart0",   .rate = 12288000},
736         {.name = "clk_uart1",   .rate = 48000000},
737         {.name = "clk_hsadc",   .rate = 12288000},
738         {.name = "clk_mac",     .rate = 50000000},
739
740         {.name = "clk_apll",    .rate = 500000000},
741         {.name = "clk_dpll",    .rate = 400000000},
742         {.name = "clk_cpll",    .rate = 600000000},
743         {.name = "clk_gpll",    .rate = 800000000},
744 };
745
746 void rk_clk_test(void)
747 {
748         const char *clk_name;
749         struct clk *clk;
750         unsigned long rate=0, recalc_rate=0, round_rate=0, get_rate=0;
751         u32 i = 0, j = 0;
752         int ret;
753
754         for (j = 0; j < ARRAY_SIZE(t_table); j++) {
755                 clk_debug(">>>>>>test %u\n", j);
756
757                 clk_name = t_table[j].name;
758                 rate = t_table[j].rate;
759
760                 clk = clk_get(NULL, clk_name);
761                 if (IS_ERR(clk)) {
762                         clk_err("%s: clk(\"%s\") \tclk_get error\n",
763                                         __func__, clk_name);
764                 } else
765                         clk_debug("%s: clk(\"%s\") \tclk_get success\n",
766                                         __func__, clk_name);
767
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);
772
773                 /* TEST: clk_set_rate */
774                 ret = clk_set_rate(clk, rate);
775                 if (ret) {
776                         clk_err("%s: clk(\"%s\") \tclk_set_rate error, ret=%d\n",
777                                         __func__, clk_name, ret);
778                 } else {
779                         clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n",
780                                         __func__, clk_name);
781                 }
782
783                 /* TEST: recalc_rate\clk_get_rate */
784                 if (clk->ops->recalc_rate) {
785                         recalc_rate = clk->ops->recalc_rate(clk->hw,
786                                         clk->parent->rate);
787                         clk_debug("%s: clk(\"%s\") \tclk_recalc_rate %lu\n",
788                                         __func__, clk_name, recalc_rate);
789                 } else {
790                         clk_debug("%s: clk(\"%s\") have no recalc ops\n",
791                                         __func__, clk_name);
792                         get_rate = clk_get_rate(clk);
793                         clk_debug("%s: clk(\"%s\") \tclk_get_rate %lu\n",
794                                         __func__, clk_name, get_rate);
795                 }
796
797 #if 0
798                 printk("\n");
799                 printk("dump cru regs:");
800                 for (i = 0; i * 4 <= 0xf4; i++) {
801                         if (i % 4 == 0)
802                                 printk("\n%s: \t[0x%08x]: ",
803                                                 __func__, 0x20000000 + i * 4);
804                         printk("%08x ", readl(reg_start + i * 4));
805                 }
806                 printk("\n\n");
807
808 #endif
809         }
810
811 }
812 EXPORT_SYMBOL_GPL(rk_clk_test);
813 #else
814 void rk_clk_test(void){};
815 EXPORT_SYMBOL_GPL(rk_clk_test);
816 #endif
817
818 void rkclk_init_clks(struct device_node *node);
819
820 static void __init rk_clk_tree_init(struct device_node *np)
821 {
822         struct device_node *node;
823
824         struct device_node *node_init;
825         struct rkclk *rkclk;
826
827         node_init=of_find_node_by_name(NULL,"clocks-init");
828         if(!node_init)
829         {
830                 printk("%s:can not get  clocks-init node\n",__FUNCTION__);
831                 return;
832         }
833
834         for_each_available_child_of_node(np, node) {
835
836                 if (!ERR_PTR(of_property_match_string(node,
837                                                 "compatible",
838                                                 "fixed-clock"))) {
839                         continue;
840
841                 } else if (!ERR_PTR(of_property_match_string(node,
842                                                 "compatible",
843                                                 "rockchip,rk-pll-cons"))) {
844                         if (ERR_PTR(rkclk_init_pllcon(node))) {
845                                 clk_err("%s: init pll clk err\n", __func__);
846                                 return ;
847                         }
848
849                 } else if (!ERR_PTR(of_property_match_string(node,
850                                                 "compatible",
851                                                 "rockchip,rk-sel-cons"))) {
852                         if (ERR_PTR(rkclk_init_selcon(node))) {
853                                 clk_err("%s: init sel cons err\n", __func__);
854                                 return ;
855                         }
856
857                 } else if (!ERR_PTR(of_property_match_string(node,
858                                                 "compatible",
859                                                 "rockchip,rk-gate-cons"))) {
860                         if (ERR_PTR(rkclk_init_gatecon(node))) {
861                                 clk_err("%s: init gate cons err\n", __func__);
862                                 return ;
863                         }
864
865                 } else {
866                         clk_err("%s: unknown\n", __func__);
867                 }
868
869         };
870
871 #if 0
872         list_for_each_entry(rkclk, &rk_clks, node) {
873                 int i;
874                 clk_debug("%s: clkname = %s; type=%d\n",
875                                 __func__, rkclk->clk_name,
876                                 rkclk->clk_type);
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);
881                 }
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]);
887                 }
888                 if (rkclk->div_info) {
889                         clk_debug("\t\tdiv name=%s\n",
890                                         rkclk->div_info->clk_name);
891                 }
892                 if (rkclk->frac_info) {
893                         clk_debug("\t\tfrac name=%s\n",
894                                         rkclk->frac_info->clk_name);
895                 }
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);
901                 }
902         }
903 #endif
904
905         list_for_each_entry(rkclk, &rk_clks, node) {
906                 rkclk_register(rkclk);
907         }
908
909         /* check clock parents init */
910         list_for_each_entry(rkclk, &rk_clks, node) {
911                 struct clk *clk;
912                 int i = 0;
913                 const char *clk_name = rkclk->clk_name;
914                 clk = clk_get(NULL, clk_name);
915                 if (IS_ERR(clk)) {
916                         clk_err("%s: clk(\"%s\") \tclk_get error\n",
917                                         __func__, clk_name);
918                         continue;
919                 } else {
920                         clk_debug("%s: clk(\"%s\") \tclk_get success\n",
921                                         __func__, __clk_get_name(clk));
922                 }
923
924                 if (clk->parents) {
925                         for (i = 0; i < clk->num_parents; i++) {
926                                 if (clk->parents[i])
927                                         clk_debug("\t\tclk(\"%s\"): init parent:%s\n",
928                                                         clk->name,
929                                                         clk->parents[i]->name);
930                                 else {
931                                         clk->parents[i] = clk_get(NULL, clk->parent_names[i]);
932                                         clk_debug("\t\tclk(\"%s\"): init parent:%s\n",
933                                                         clk->name,
934                                                         clk->parents[i]->name);
935                                 }
936                         }
937
938                 } else {
939                         clk_debug("\t\tNOT A MUX CLK, parent num=%d\n", clk->num_parents);
940                 }
941         }
942
943         rkclk_init_clks(node_init);
944
945 }
946 CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init);
947
948
949 /********************************** rockchip clks init****************************************/
950 const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rate)
951 {
952         struct of_phandle_args clkspec;
953         const char *clk_name;
954         int rc;
955
956         if (index < 0)
957                 return NULL;
958
959         rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells", index,
960                         &clkspec);
961         if (rc)
962                 return NULL;
963
964         if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0)
965                 return NULL;
966
967         *rate= clkspec.args[0];
968
969         of_node_put(clkspec.np);
970         return clk_name;
971 }
972
973 const char *of_clk_init_parent_get_info(struct device_node *np, int index,const char **clk_child_name)
974 {
975         struct of_phandle_args clkspec;
976         const char *clk_name;
977         int rc;
978         phandle phandle;
979         struct device_node *node = NULL;
980
981         if (index < 0)
982                 return NULL;
983
984         rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells", index,
985                         &clkspec);
986         if (rc)
987                 return NULL;
988
989         if (of_property_read_string_index(clkspec.np, "clock-output-names",0,&clk_name) < 0)
990                 return NULL;
991
992
993         phandle = clkspec.args[0];
994
995         of_node_put(clkspec.np);
996
997         if (phandle) {
998
999                 node = of_find_node_by_phandle(phandle);
1000                 if (!node) {
1001                         return NULL;
1002                 }
1003
1004                 if (of_property_read_string_index(node, "clock-output-names",0,clk_child_name) < 0)
1005                         return NULL;
1006
1007                 of_node_put(node);//???
1008                 node=NULL;
1009         }
1010         else
1011                 return NULL;
1012
1013         return clk_name;
1014 }
1015
1016 void rkclk_init_clks(struct device_node *np)
1017 {
1018         //struct device_node *np;
1019         int i,cnt_parent,cnt_rate;
1020         u32 clk_rate;
1021         //int ret;
1022         struct clk * clk_p,*clk_c;
1023
1024         const char * clk_name,*clk_parent_name;
1025
1026
1027         cnt_parent = of_count_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells");
1028
1029         printk("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent);
1030
1031
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);
1035
1036                 if(clk_name==NULL||clk_parent_name==NULL)
1037                         continue;
1038
1039                 clk_c=clk_get(NULL,clk_name);
1040                 clk_p=clk_get(NULL,clk_parent_name);
1041
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))
1044                         continue;
1045                 //clk_set_parent(clk_name, clk_parent_name);
1046         }
1047
1048         cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells");
1049
1050         printk("%s:rate cnt=%d\n",__FUNCTION__,cnt_rate);
1051
1052         for (i = 0; i < cnt_rate; i++) {
1053                 clk_name=of_clk_init_rate_get_info(np, i,&clk_rate);
1054
1055                 if(clk_name==NULL)
1056                         continue;
1057
1058                 clk_p=clk_get(NULL,clk_name);
1059
1060                 printk("%s: set rate %s=%x,rate=%d\n",__FUNCTION__,clk_name,(u32)clk_p,clk_rate);
1061
1062                 if(IS_ERR(clk_c)||(clk_rate<1*1000*1000)||(clk_rate>2000*1000*1000))
1063                         continue;
1064                 //clk_set_rate(clk_p,clk_rate);
1065
1066         }
1067
1068 }
1069