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