UPSTREAM: clk: rockchip: rk3036: fix the FLAGs for clock mux
[firefly-linux-kernel-4.4.55.git] / drivers / clk / rk / clk-ops.c
1 #include <linux/clk.h>
2 #include <linux/clkdev.h>
3 #include <linux/io.h>
4 #include <linux/clk-provider.h>
5 #include <linux/of.h>
6 #include <linux/of_address.h>
7 #include <linux/clk-private.h>
8 #include <linux/delay.h>
9 #include <linux/rockchip/common.h>
10 #include <linux/rockchip/cpu.h>
11
12 #include "clk-ops.h"
13
14 /* mux_ops */
15 struct clk_ops_table rk_clk_mux_ops_table[] = {
16         {.index = CLKOPS_TABLE_END},
17 };
18
19
20 /* rate_ops */
21 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
22 #define div_mask(d)     ((1 << ((d)->width)) - 1)
23
24 static u32 clk_gcd(u32 numerator, u32 denominator)
25 {
26         u32 a, b;
27
28         if (!numerator || !denominator)
29                 return 0;
30         if (numerator > denominator) {
31                 a = numerator;
32                 b = denominator;
33         } else {
34                 a = denominator;
35                 b = numerator;
36         }
37         while (b != 0) {
38                 int r = b;
39                 b = a % b;
40                 a = r;
41         }
42
43         return a;
44 }
45
46 static int clk_fracdiv_get_config(unsigned long rate_out, unsigned long rate,
47                 u32 *numerator, u32 *denominator)
48 {
49         u32 gcd_val;
50         gcd_val = clk_gcd(rate, rate_out);
51         clk_debug("%s: frac_get_seting rate=%lu, parent=%lu, gcd=%d\n",
52                         __func__, rate_out, rate, gcd_val);
53
54         if (!gcd_val) {
55                 clk_err("gcd=0, frac div is not be supported\n");
56                 return -EINVAL;
57         }
58
59         *numerator = rate_out / gcd_val;
60         *denominator = rate / gcd_val;
61
62         clk_debug("%s: frac_get_seting numerator=%d, denominator=%d, times=%d\n",
63                         __func__, *numerator, *denominator,
64                         *denominator / *numerator);
65
66         if (*numerator > 0xffff || *denominator > 0xffff ||
67                         (*denominator / (*numerator)) < 20) {
68                 clk_err("can't get a available nume and deno\n");
69                 return -EINVAL;
70         }
71
72         return 0;
73
74 }
75
76 static int clk_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
77                 unsigned long parent_rate)
78 {
79         u32 numerator, denominator;
80         struct clk_divider *div = to_clk_divider(hw);
81
82
83         if(clk_fracdiv_get_config(rate, parent_rate,
84                                 &numerator, &denominator) == 0) {
85                 writel(numerator << 16 | denominator, div->reg);
86                 clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
87         } else {
88                 clk_err("clk_frac_div name=%s can't get rate=%lu\n",
89                                 hw->clk->name, rate);
90                 return -EINVAL;
91         }
92
93         return 0;
94 }
95
96 static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
97                 unsigned long parent_rate)
98 {
99         unsigned long rate;
100         u64 rate64;
101         struct clk_divider *div = to_clk_divider(hw);
102         u32 numerator, denominator, reg_val;
103
104         reg_val = readl(div->reg);
105         if (reg_val == 0)
106                 return parent_rate;
107
108         numerator = reg_val >> 16;
109         denominator = reg_val & 0xFFFF;
110         rate64 = (u64)parent_rate * numerator;
111         do_div(rate64, denominator);
112         rate = rate64;
113         clk_debug("%s: %s new clock rate is %lu, prate %lu (frac %u/%u)\n",
114                         __func__, hw->clk->name, rate, parent_rate,
115                         numerator, denominator);
116         return rate;
117 }
118
119 static long clk_fracdiv_round_rate(struct clk_hw *hw, unsigned long rate,
120                 unsigned long *prate)
121 {
122         struct clk *clk = hw->clk;
123         struct clk *parent = clk->parent;
124         long rate_out;
125
126         //FIXME: now just simply return rate
127         /*
128          *frac_div request a big input rate, and its parent is always a div,
129          *so we set parent->parent->rate as best_parent_rate.
130          */
131         rate_out = rate;
132         *prate = parent->parent->rate;
133
134         return rate_out;
135 }
136
137 static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
138                 unsigned long parent_rate)
139 {
140         return clk_divider_ops.recalc_rate(hw, parent_rate);
141 }
142
143 static long clk_divider_round_rate(struct clk_hw *hw,
144                 unsigned long rate, unsigned long *prate)
145 {
146         return clk_divider_ops.round_rate(hw, rate, prate);
147 }
148
149 static int clk_divider_set_rate(struct clk_hw *hw,
150                 unsigned long rate, unsigned long parent_rate)
151 {
152         return clk_divider_ops.set_rate(hw, rate, parent_rate);
153 }
154
155 static long clk_mux_with_div_determine_rate(struct clk_hw *div_hw, unsigned long rate,
156                 unsigned long *best_parent_rate,
157                 struct clk **best_parent_p)
158 {
159         struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
160         int i, num_parents;
161         unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
162
163
164         parent = __clk_get_parent(clk);
165         if(!parent){
166                 best = __clk_get_rate(clk);
167                 goto out;
168         }
169
170         /* if NO_REPARENT flag set, pass through to current parent */
171         if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
172                 best_prate = __clk_get_rate(parent);
173                 best = clk_divider_ops.round_rate(div_hw, rate, &best_prate);
174                 goto out;
175         }
176
177         /* find the parent that can provide the fastest rate <= rate */
178         num_parents = clk->num_parents;
179         for (i = 0; i < num_parents; i++) {
180                 parent = clk_get_parent_by_index(clk, i);
181                 if (!parent)
182                         continue;
183
184                 parent_rate = __clk_get_rate(parent);
185                 now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
186
187                 if (now <= rate && now > best) {
188                         best_parent = parent;
189                         best_prate = parent_rate;
190                         best = now;
191                 }
192         }
193
194 out:
195         if(best_prate)
196                 *best_parent_rate = best_prate;
197
198         if (best_parent)
199                 *best_parent_p = best_parent;
200
201         clk_debug("clk name = %s, determine rate = %lu, best = %lu\n"
202                         "\tbest_parent name = %s, best_prate = %lu\n",
203                         clk->name, rate, best,
204                         __clk_get_name(*best_parent_p), *best_parent_rate);
205
206         return best;
207 }
208
209 const struct clk_ops clkops_rate_auto_parent = {
210         .recalc_rate    = clk_divider_recalc_rate,
211         .round_rate     = clk_divider_round_rate,
212         .set_rate       = clk_divider_set_rate,
213         .determine_rate = clk_mux_with_div_determine_rate,
214 };
215
216 static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate,
217                 unsigned long *prate)
218 {
219         int i = 0;
220         struct clk_divider *divider =to_clk_divider(hw);
221         int max_div = 1 << divider->width;
222
223         for (i = 1; i <= max_div; i++) {
224                 if (i > 1 && (i % 2 != 0))
225                         continue;
226                 if (rate >= (*prate / i))
227                         return *prate / i;
228         }
229
230         return (*prate / max_div);
231 }
232
233 const struct clk_ops clkops_rate_evendiv = {
234         .recalc_rate    = clk_divider_recalc_rate,
235         .round_rate     = clk_div_round_rate_even,
236         .set_rate       = clk_divider_set_rate,
237 };
238
239 static long clk_mux_with_evendiv_determine_rate(struct clk_hw *div_hw, unsigned long rate,
240                 unsigned long *best_parent_rate,
241                 struct clk **best_parent_p)
242 {
243         struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
244         int i, num_parents;
245         unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
246
247
248         parent = __clk_get_parent(clk);
249         if(!parent){
250                 best = __clk_get_rate(clk);
251                 goto out;
252         }
253
254         /* if NO_REPARENT flag set, pass through to current parent */
255         if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
256                 best_prate = __clk_get_rate(parent);
257                 best = clk_div_round_rate_even(div_hw, rate, &best_prate);
258                 goto out;
259         }
260
261         /* find the parent that can provide the fastest rate <= rate */
262         num_parents = clk->num_parents;
263         for (i = 0; i < num_parents; i++) {
264                 parent = clk_get_parent_by_index(clk, i);
265                 if (!parent)
266                         continue;
267
268                 parent_rate = __clk_get_rate(parent);
269                 now = clk_div_round_rate_even(div_hw, rate, &parent_rate);
270
271                 if (now <= rate && now > best) {
272                         best_parent = parent;
273                         best_prate = parent_rate;
274                         best = now;
275                 }
276         }
277
278 out:
279         if(best_prate)
280                 *best_parent_rate = best_prate;
281
282         if (best_parent)
283                 *best_parent_p = best_parent;
284
285         clk_debug("clk name = %s, determine rate = %lu, best = %lu\n"
286                         "\tbest_parent name = %s, best_prate = %lu\n",
287                         clk->name, rate, best,
288                         __clk_get_name(*best_parent_p), *best_parent_rate);
289
290         return best;
291 }
292
293 static long clk_mux_with_evendiv_round_rate(struct clk_hw *hw, unsigned long rate,
294                 unsigned long *prate)
295 {
296         return clk_div_round_rate_even(hw, rate, prate);
297 }
298
299 const struct clk_ops clkops_rate_mux_with_evendiv = {
300         .recalc_rate    = clk_divider_recalc_rate,
301         .set_rate       = clk_divider_set_rate,
302         .round_rate     = clk_mux_with_evendiv_round_rate,
303         .determine_rate = clk_mux_with_evendiv_determine_rate,
304 };
305
306 static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
307                 unsigned long parent_rate)
308 {
309         u32 numerator, denominator;
310         struct clk_divider *div = to_clk_divider(hw);
311         int i = 10;
312
313
314         if(clk_fracdiv_get_config(rate, parent_rate,
315                                 &numerator, &denominator) == 0) {
316                 while (i--) {
317                         writel((numerator - 1) << 16 | denominator, div->reg);
318                         mdelay(1);
319                         writel(numerator << 16 | denominator, div->reg);
320                         mdelay(1);
321                 }
322                 clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
323         } else {
324                 clk_err("clk_frac_div name=%s can't get rate=%lu\n",
325                                 hw->clk->name, rate);
326                 return -EINVAL;
327         }
328
329         return 0;
330 }
331
332 const struct clk_ops clkops_rate_frac = {
333         .recalc_rate    = clk_fracdiv_recalc,
334         .round_rate     = clk_fracdiv_round_rate,
335         .set_rate       = clk_fracdiv_set_rate,
336 };
337
338 const struct clk_ops clkops_rate_i2s_frac = {
339         .recalc_rate    = clk_fracdiv_recalc,
340         .round_rate     = clk_fracdiv_round_rate,
341         .set_rate       = clk_i2s_fracdiv_set_rate,
342 };
343
344 static unsigned long clk_core_recalc_rate(struct clk_hw *hw,
345                 unsigned long parent_rate)
346 {
347         /* As parent rate could be changed in clk_core.set_rate
348          * ops, the passing_in parent_rate may not be the newest
349          * and we should use the parent->rate instead. As a side
350          * effect, we should NOT directly set clk_core's parent
351          * (apll) rate, otherwise we will get a wrong recalc rate
352          * with clk_core_recalc_rate.
353          */
354         struct clk *parent = __clk_get_parent(hw->clk);
355
356         return clk_divider_recalc_rate(hw, __clk_get_rate(parent));
357 }
358
359 static long clk_core_determine_rate(struct clk_hw *hw, unsigned long rate,
360                 unsigned long *best_parent_rate,
361                 struct clk **best_parent_p)
362 {
363         struct clk *parent = __clk_get_parent(hw->clk);
364
365         if (IS_ERR_OR_NULL(parent)) {
366                 clk_err("fail to get parent!\n");
367                 return 0;
368         }
369
370         return clk_round_rate(parent, rate);
371 }
372
373 static long clk_core_round_rate(struct clk_hw *hw, unsigned long rate,
374                 unsigned long *prate)
375 {
376         return clk_core_determine_rate(hw, rate, prate, NULL);
377 }
378
379 static int clk_core_set_rate(struct clk_hw *hw, unsigned long rate,
380                 unsigned long parent_rate)
381 {
382         struct clk *parent = __clk_get_parent(hw->clk);
383         struct clk *grand_p = __clk_get_parent(parent);
384         int ret;
385
386         if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
387                 clk_err("fail to get parent or grand_parent!\n");
388                 return -EINVAL;
389         }
390
391         ret = parent->ops->set_rate(parent->hw, rate, __clk_get_rate(grand_p));
392         parent->rate = parent->ops->recalc_rate(parent->hw,
393                         __clk_get_rate(grand_p));
394
395         return ret;
396 }
397
398 const struct clk_ops clkops_rate_core = {
399         .recalc_rate    = clk_core_recalc_rate,
400         .round_rate     = clk_core_round_rate,
401         .set_rate       = clk_core_set_rate,
402         .determine_rate = clk_core_determine_rate,
403 };
404
405 /* Clk_ops for the child clk of clk_core, for example core_periph in rk3188 */
406 const struct clk_ops clkops_rate_core_peri = {
407         .recalc_rate    = clk_divider_recalc_rate,
408         .round_rate     = clk_divider_round_rate,
409         .set_rate       = NULL,
410 };
411
412
413 static unsigned long clk_ddr_recalc_rate(struct clk_hw *hw,
414                 unsigned long parent_rate)
415 {
416         /* Same as clk_core, we should NOT set clk_ddr's parent
417          * (dpll) rate directly as a side effect.
418          */
419         return clk_core_recalc_rate(hw, parent_rate);
420 }
421
422 static long clk_ddr_determine_rate(struct clk_hw *hw, unsigned long rate,
423                 unsigned long *best_parent_rate,
424                 struct clk **best_parent_p)
425 {
426         long best = 0;
427
428         if (!ddr_round_rate) {
429                 /* Do nothing before ddr init */
430                 best = rate;//__clk_get_rate(hw->clk);
431         } else {
432                 /* Func provided by ddr driver */
433                 best = ddr_round_rate(rate/MHZ) * MHZ;
434         }
435
436         clk_debug("%s: from %lu to %lu\n", __func__, rate, best);
437
438         return best;
439 }
440
441 static long clk_ddr_round_rate(struct clk_hw *hw, unsigned long rate,
442                  unsigned long *prate)
443 {
444         return clk_ddr_determine_rate(hw, rate, prate, NULL);
445 }
446
447 static int clk_ddr_set_rate(struct clk_hw *hw, unsigned long rate,
448                 unsigned long parent_rate)
449 {
450         struct clk *parent = __clk_get_parent(hw->clk);
451         struct clk *grand_p = __clk_get_parent(parent);
452
453
454         /* Do nothing before ddr init */
455         if (!ddr_change_freq)
456                 return 0;
457
458         if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
459                 clk_err("fail to get parent or grand_parent!\n");
460                 return -EINVAL;
461         }
462
463         clk_debug("%s: will set rate = %lu\n", __func__, rate);
464
465         /* Func provided by ddr driver */
466         ddr_change_freq(rate/MHZ);
467
468         parent->rate = parent->ops->recalc_rate(parent->hw,
469                         __clk_get_rate(grand_p));
470
471         return 0;
472 }
473
474 const struct clk_ops clkops_rate_ddr = {
475         .recalc_rate    = clk_ddr_recalc_rate,
476         .round_rate     = clk_ddr_round_rate,
477         .set_rate       = clk_ddr_set_rate,
478         .determine_rate = clk_ddr_determine_rate,
479 };
480
481 static unsigned long clk_ddr_div2_recalc_rate(struct clk_hw *hw,
482                                               unsigned long parent_rate)
483 {
484         /* Same as clk_core, we should NOT set clk_ddr's parent
485          * (dpll) rate directly as a side effect.
486          */
487         struct clk *parent = __clk_get_parent(hw->clk);
488
489         return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/2;
490 }
491
492 const struct clk_ops clkops_rate_ddr_div2 = {
493         .recalc_rate    = clk_ddr_div2_recalc_rate,
494         .round_rate     = clk_ddr_round_rate,
495         .set_rate       = clk_ddr_set_rate,
496         .determine_rate = clk_ddr_determine_rate,
497 };
498
499 static unsigned long clk_ddr_div4_recalc_rate(struct clk_hw *hw,
500                                               unsigned long parent_rate)
501 {
502         /* Same as clk_core, we should NOT set clk_ddr's parent
503          * (dpll) rate directly as a side effect.
504          */
505         struct clk *parent = __clk_get_parent(hw->clk);
506
507         return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/4;
508 }
509
510 const struct clk_ops clkops_rate_ddr_div4 = {
511         .recalc_rate    = clk_ddr_div4_recalc_rate,
512         .round_rate     = clk_ddr_round_rate,
513         .set_rate       = clk_ddr_set_rate,
514         .determine_rate = clk_ddr_determine_rate,
515 };
516
517
518 static unsigned long clk_3288_i2s_recalc_rate(struct clk_hw *hw,
519                 unsigned long parent_rate)
520 {
521         return parent_rate;
522 }
523
524 static long clk_3288_i2s_round_rate(struct clk_hw *hw, unsigned long rate,
525                 unsigned long *prate)
526 {
527         return rate;
528 }
529
530 static int clk_3288_i2s_set_rate(struct clk_hw *hw, unsigned long rate,
531                 unsigned long parent_rate)
532 {
533         struct clk *parent = __clk_get_parent(hw->clk);
534         struct clk *grand_p = __clk_get_parent(parent);
535
536
537         if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
538                 return 0;
539         }
540
541         if (parent->ops->set_rate) {
542                 parent->ops->set_rate(parent->hw, rate/2, __clk_get_rate(grand_p));
543                 parent->ops->set_rate(parent->hw, rate, __clk_get_rate(grand_p));
544         }
545
546         return 0;
547 }
548
549 const struct clk_ops clkops_rate_3288_i2s = {
550         .recalc_rate    = clk_3288_i2s_recalc_rate,
551         .round_rate     = clk_3288_i2s_round_rate,
552         .set_rate       = clk_3288_i2s_set_rate,
553 };
554
555 static bool usb480m_state = false;
556
557 static long clk_3288_usb480m_determine_rate(struct clk_hw *hw, unsigned long rate,
558                 unsigned long *best_parent_rate,
559                 struct clk **best_parent_p)
560 {
561         if(rate == 0)
562                 return 0;
563         else
564                 return 480*MHZ;
565 }
566
567 static long clk_3288_usb480m_round_rate(struct clk_hw *hw, unsigned long rate,
568                 unsigned long *prate)
569 {
570         return clk_3288_usb480m_determine_rate(hw, rate, prate, NULL);
571 }
572
573 static int clk_3288_usb480m_set_rate(struct clk_hw *hw, unsigned long rate,
574                 unsigned long parent_rate)
575 {
576         if(rate == 0)
577                 usb480m_state = false;
578         else
579                 usb480m_state = true;
580
581         return 0;
582 }
583
584 static unsigned long clk_3288_usb480m_recalc_rate(struct clk_hw *hw,
585                 unsigned long parent_rate)
586 {
587         if(usb480m_state)
588                 return 480*MHZ;
589         else
590                 return 0;
591 }
592
593 const struct clk_ops clkops_rate_3288_usb480m = {
594         .determine_rate = clk_3288_usb480m_determine_rate,
595         .set_rate       = clk_3288_usb480m_set_rate,
596         .round_rate     = clk_3288_usb480m_round_rate,
597         .recalc_rate    = clk_3288_usb480m_recalc_rate,
598 };
599
600 #define RK3288_LIMIT_PLL_VIO0 (600*MHZ)
601
602 static long clk_3288_dclk_lcdc0_determine_rate(struct clk_hw *hw, unsigned long rate,
603                 unsigned long *best_parent_rate,
604                 struct clk **best_parent_p)
605 {
606         struct clk *gpll = clk_get(NULL, "clk_gpll");
607         struct clk *cpll = clk_get(NULL, "clk_cpll");
608         unsigned long best, div, prate, gpll_rate;
609
610         gpll_rate = __clk_get_rate(gpll);
611
612         if ((rate <= (297*MHZ)) && (gpll_rate%rate == 0)) {
613                 *best_parent_p = gpll;
614                 best = rate;
615                 *best_parent_rate = gpll_rate;
616         } else {
617                 *best_parent_p = cpll;
618                 div = RK3288_LIMIT_PLL_VIO0/rate;
619                 prate = div * rate;
620                 *best_parent_rate = clk_round_rate(cpll, prate);
621                 best = (*best_parent_rate)/div; 
622         }
623
624         return best;
625 }
626
627 static long clk_3288_dclk_lcdc0_round_rate(struct clk_hw *hw, unsigned long rate,
628                 unsigned long *prate)
629 {
630         return clk_3288_dclk_lcdc0_determine_rate(hw, rate, prate, NULL);
631 }
632
633 static int clk_3288_dclk_lcdc0_set_rate(struct clk_hw *hw, unsigned long rate,
634                 unsigned long parent_rate)
635 {
636         struct clk* aclk_vio0 = clk_get(NULL, "aclk_vio0");
637         struct clk* hclk_vio = clk_get(NULL, "hclk_vio");
638         struct clk *aclk_vio1;
639         struct clk* parent;
640         struct clk *gpll = clk_get(NULL, "clk_gpll");
641         struct clk *cpll = clk_get(NULL, "clk_cpll");
642
643         clk_divider_ops.set_rate(hw, rate, parent_rate);
644
645         /* set aclk_vio */
646         if (parent_rate == __clk_get_rate(gpll)) {
647                 parent = clk_get(NULL, "clk_gpll");
648                 clk_set_parent(aclk_vio0, gpll);
649                 clk_set_rate(aclk_vio0, 300*MHZ);
650         } else {
651                 parent = clk_get(NULL, "clk_cpll");
652                 clk_set_parent(aclk_vio0, cpll);
653                 clk_set_rate(aclk_vio0, __clk_get_rate(cpll));
654         }
655         clk_set_rate(hclk_vio, 100*MHZ);
656
657         /* make aclk_isp and hclk_isp share a same pll in rk3288_eco */
658         if (rockchip_get_cpu_version() > 0) {
659                 aclk_vio1 = clk_get(NULL, "aclk_vio1");
660                 clk_set_parent(aclk_vio1, parent);
661                 clk_set_rate(aclk_vio1, __clk_get_rate(parent));
662         }
663
664         return 0;
665 }
666
667 const struct clk_ops clkops_rate_3288_dclk_lcdc0 = {
668         .determine_rate = clk_3288_dclk_lcdc0_determine_rate,
669         .set_rate       = clk_3288_dclk_lcdc0_set_rate,
670         .round_rate     = clk_3288_dclk_lcdc0_round_rate,
671         .recalc_rate    = clk_divider_recalc_rate,
672 };
673
674 #define RK3288_LIMIT_PLL_VIO1 (350*MHZ)
675
676 static long clk_3288_dclk_lcdc1_determine_rate(struct clk_hw *hw, unsigned long rate,
677                 unsigned long *best_parent_rate,
678                 struct clk **best_parent_p)
679 {
680         struct clk *gpll = clk_get(NULL, "clk_gpll");
681         struct clk *cpll = clk_get(NULL, "clk_cpll");
682         unsigned long best, div, prate, gpll_rate;
683
684         gpll_rate = __clk_get_rate(gpll);
685
686         if ((rate <= (297*MHZ)) && ((gpll_rate)%rate == 0)) {
687                 *best_parent_p = gpll;
688                 best = rate;
689                 *best_parent_rate = gpll_rate;
690         } else {
691                 *best_parent_p = cpll;
692                 div = RK3288_LIMIT_PLL_VIO1/rate;
693                 prate = div * rate;
694                 *best_parent_rate = clk_round_rate(cpll, prate);
695                 best = (*best_parent_rate)/div; 
696         }
697
698         return best;
699 }
700
701 static long clk_3288_dclk_lcdc1_round_rate(struct clk_hw *hw, unsigned long rate,
702                 unsigned long *prate)
703 {
704         return clk_3288_dclk_lcdc1_determine_rate(hw, rate, prate, NULL);
705 }
706
707 static int clk_3288_dclk_lcdc1_set_rate(struct clk_hw *hw, unsigned long rate,
708                 unsigned long parent_rate)
709 {
710         struct clk* aclk_vio1 = clk_get(NULL, "aclk_vio1");
711         struct clk* parent;
712         struct clk *gpll = clk_get(NULL, "clk_gpll");
713         struct clk *cpll = clk_get(NULL, "clk_cpll");
714
715         clk_divider_ops.set_rate(hw, rate, parent_rate);
716
717         /* set aclk_vio */
718         if (parent_rate == __clk_get_rate(gpll)) {
719                 parent = clk_get(NULL, "clk_gpll");
720                 clk_set_parent(aclk_vio1, gpll);
721                 clk_set_rate(aclk_vio1, 300*MHZ);
722         } else {
723                 parent = clk_get(NULL, "clk_cpll");
724                 clk_set_parent(aclk_vio1, cpll);
725                 clk_set_rate(aclk_vio1, __clk_get_rate(cpll));
726         }
727
728         if (rockchip_get_cpu_version() == 0) {
729                 clk_set_parent(aclk_vio1, parent);
730                 clk_set_rate(aclk_vio1, __clk_get_rate(parent));
731         }
732
733         return 0;
734 }
735
736 const struct clk_ops clkops_rate_3288_dclk_lcdc1 = {
737         .determine_rate = clk_3288_dclk_lcdc1_determine_rate,
738         .set_rate       = clk_3288_dclk_lcdc1_set_rate,
739         .round_rate     = clk_3288_dclk_lcdc1_round_rate,
740         .recalc_rate    = clk_divider_recalc_rate,
741 };
742
743 #define CONFIG_RK3368_MUX_NO_USE_NPLL
744
745 static long clk_3368_mux_div_determine_rate(struct clk_hw *div_hw,
746                                             unsigned long rate,
747                                             unsigned long *best_parent_rate,
748                                             struct clk **best_parent_p)
749 {
750         struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
751         int i, num_parents;
752         unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
753
754         parent = __clk_get_parent(clk);
755         if (!parent) {
756                 best = __clk_get_rate(clk);
757                 goto out;
758         }
759
760         /* if NO_REPARENT flag set, pass through to current parent */
761         if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
762                 best_prate = __clk_get_rate(parent);
763                 best = clk_divider_ops.round_rate(div_hw, rate, &best_prate);
764                 goto out;
765         }
766
767         /* find the parent that can provide the fastest rate <= rate */
768         num_parents = clk->num_parents;
769         for (i = 0; i < num_parents; i++) {
770                 parent = clk_get_parent_by_index(clk, i);
771                 if (!parent)
772                         continue;
773
774 #ifdef CONFIG_RK3368_MUX_NO_USE_NPLL
775                 if (!strcmp(__clk_get_name(parent), "clk_npll"))
776                         continue;
777 #endif
778                 parent_rate = __clk_get_rate(parent);
779                 now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
780
781                 if (now <= rate && now > best) {
782                         best_parent = parent;
783                         best_prate = parent_rate;
784                         best = now;
785                 }
786         }
787
788 out:
789         if (best_prate)
790                 *best_parent_rate = best_prate;
791
792         if (best_parent)
793                 *best_parent_p = best_parent;
794
795         clk_debug("clk name = %s, determine rate = %lu, best = %lu\n"
796                   "\tbest_parent name = %s, best_prate = %lu\n",
797                   clk->name, rate, best,
798                   __clk_get_name(*best_parent_p), *best_parent_rate);
799
800         return best;
801 }
802
803 const struct clk_ops clkops_rate_3368_auto_parent = {
804         .recalc_rate    = clk_divider_recalc_rate,
805         .round_rate     = clk_divider_round_rate,
806         .set_rate       = clk_divider_set_rate,
807         .determine_rate = clk_3368_mux_div_determine_rate,
808 };
809
810 #define RK3368_LIMIT_NPLL (1250*MHZ)
811
812 static long clk_3368_dclk_lcdc_determine_rate(struct clk_hw *hw,
813                                               unsigned long rate,
814                                               unsigned long *best_parent_rate,
815                                               struct clk **best_parent_p)
816 {
817         struct clk *npll = clk_get(NULL, "clk_npll");
818         unsigned long div, prate, best, *p_prate;
819         static unsigned long rk3368_pll_rates[] = {1188*MHZ, 0};
820
821         if (best_parent_p)
822                 *best_parent_p = npll;
823
824         /* first get parent_rate from table */
825         p_prate = rk3368_pll_rates;
826
827         while (*p_prate) {
828                 if (!(*p_prate % (rate*2)) || (*p_prate == rate)) {
829                         clk_debug("%s: get rate from table\n", __func__);
830                         *best_parent_rate = *p_prate;
831                         best = rate;
832                         return best;
833                 }
834                 p_prate++;
835         }
836
837         /* if not suitable parent_rate found in table, then auto calc rate */
838         div = RK3368_LIMIT_NPLL/rate;
839         /* div should be even */
840         if (div % 2)
841                 div = div - 1;
842
843         prate = div * rate;
844         *best_parent_rate = clk_round_rate(npll, prate);
845         best = (*best_parent_rate)/div;
846
847         return best;
848 }
849
850 static long clk_3368_dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate,
851                                           unsigned long *prate)
852 {
853         return clk_3368_dclk_lcdc_determine_rate(hw, rate, prate, NULL);
854 }
855
856 const struct clk_ops clkops_rate_3368_dclk_lcdc = {
857         .determine_rate = clk_3368_dclk_lcdc_determine_rate,
858         .set_rate       = clk_divider_set_rate,
859         .round_rate     = clk_3368_dclk_lcdc_round_rate,
860         .recalc_rate    = clk_divider_recalc_rate,
861 };
862
863 static unsigned long clk_rk3368_ddr_recalc_rate(struct clk_hw *hw,
864                 unsigned long parent_rate)
865 {
866         if (!ddr_recalc_rate)
867                 return (clk_core_recalc_rate(hw, parent_rate)/2);
868         else
869                 return ddr_recalc_rate();
870 }
871
872 const struct clk_ops clkops_rate_rk3368_ddr = {
873         .recalc_rate    = clk_rk3368_ddr_recalc_rate,
874         .round_rate     = clk_ddr_round_rate,
875         .set_rate       = clk_ddr_set_rate,
876         .determine_rate = clk_ddr_determine_rate,
877 };
878
879
880
881 struct clk_ops_table rk_clkops_rate_table[] = {
882         {.index = CLKOPS_RATE_MUX_DIV,          .clk_ops = &clkops_rate_auto_parent},
883         {.index = CLKOPS_RATE_EVENDIV,          .clk_ops = &clkops_rate_evendiv},
884         {.index = CLKOPS_RATE_MUX_EVENDIV,      .clk_ops = &clkops_rate_mux_with_evendiv},
885         {.index = CLKOPS_RATE_I2S_FRAC,         .clk_ops = &clkops_rate_i2s_frac},
886         {.index = CLKOPS_RATE_FRAC,             .clk_ops = &clkops_rate_frac},
887         {.index = CLKOPS_RATE_CORE,             .clk_ops = &clkops_rate_core},
888         {.index = CLKOPS_RATE_CORE_CHILD,       .clk_ops = &clkops_rate_core_peri},
889         {.index = CLKOPS_RATE_DDR,              .clk_ops = &clkops_rate_ddr},
890         {.index = CLKOPS_RATE_RK3288_I2S,       .clk_ops = &clkops_rate_3288_i2s},
891         {.index = CLKOPS_RATE_RK3288_USB480M,   .clk_ops = &clkops_rate_3288_usb480m},
892         {.index = CLKOPS_RATE_RK3288_DCLK_LCDC0,.clk_ops = &clkops_rate_3288_dclk_lcdc0},
893         {.index = CLKOPS_RATE_RK3288_DCLK_LCDC1,.clk_ops = &clkops_rate_3288_dclk_lcdc1},
894         {.index = CLKOPS_RATE_DDR_DIV2,         .clk_ops = &clkops_rate_ddr_div2},
895         {.index = CLKOPS_RATE_DDR_DIV4,         .clk_ops = &clkops_rate_ddr_div4},
896         {.index = CLKOPS_RATE_RK3368_MUX_DIV_NPLL,   .clk_ops = &clkops_rate_3368_auto_parent},
897         {.index = CLKOPS_RATE_RK3368_DCLK_LCDC, .clk_ops = &clkops_rate_3368_dclk_lcdc},
898         {.index = CLKOPS_RATE_RK3368_DDR,   .clk_ops = &clkops_rate_rk3368_ddr},
899         {.index = CLKOPS_RATE_I2S,              .clk_ops = NULL},
900         {.index = CLKOPS_RATE_CIFOUT,           .clk_ops = NULL},
901         {.index = CLKOPS_RATE_UART,             .clk_ops = NULL},
902         {.index = CLKOPS_RATE_HSADC,            .clk_ops = NULL},
903         {.index = CLKOPS_RATE_MAC_REF,          .clk_ops = NULL},
904         {.index = CLKOPS_TABLE_END,             .clk_ops = NULL},
905 };
906
907 const struct clk_ops *rk_get_clkops(unsigned int idx)
908 {
909         int i = 0;
910         unsigned int now_idx;
911
912         while(1){
913                 now_idx = rk_clkops_rate_table[i].index;
914
915                 if ((now_idx == idx) || (now_idx == CLKOPS_TABLE_END))
916                         return rk_clkops_rate_table[i].clk_ops;
917
918                 i++;
919         }
920 }
921 EXPORT_SYMBOL_GPL(rk_get_clkops);