2 #include <linux/clkdev.h>
4 #include <linux/clk-provider.h>
6 #include <linux/of_address.h>
7 #include <linux/clk-private.h>
8 #include <linux/delay.h>
9 #include <linux/rockchip/common.h>
14 struct clk_ops_table rk_clk_mux_ops_table[] = {
15 {.index = CLKOPS_TABLE_END},
20 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
21 #define div_mask(d) ((1 << ((d)->width)) - 1)
23 static u32 clk_gcd(u32 numerator, u32 denominator)
27 if (!numerator || !denominator)
29 if (numerator > denominator) {
45 static int clk_fracdiv_get_config(unsigned long rate_out, unsigned long rate,
46 u32 *numerator, u32 *denominator)
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);
54 clk_err("gcd=0, frac div is not be supported\n");
58 *numerator = rate_out / gcd_val;
59 *denominator = rate / gcd_val;
61 clk_debug("%s: frac_get_seting numerator=%d, denominator=%d, times=%d\n",
62 __func__, *numerator, *denominator,
63 *denominator / *numerator);
65 if (*numerator > 0xffff || *denominator > 0xffff ||
66 (*denominator / (*numerator)) < 20) {
67 clk_err("can't get a available nume and deno\n");
75 static int clk_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
76 unsigned long parent_rate)
78 u32 numerator, denominator;
79 struct clk_divider *div = to_clk_divider(hw);
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);
87 clk_err("clk_frac_div name=%s can't get rate=%lu\n",
95 static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
96 unsigned long parent_rate)
100 struct clk_divider *div = to_clk_divider(hw);
101 u32 numerator, denominator, reg_val;
103 reg_val = readl(div->reg);
107 numerator = reg_val >> 16;
108 denominator = reg_val & 0xFFFF;
109 rate64 = (u64)parent_rate * numerator;
110 do_div(rate64, denominator);
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);
118 static long clk_fracdiv_round_rate(struct clk_hw *hw, unsigned long rate,
119 unsigned long *prate)
121 struct clk *clk = hw->clk;
122 struct clk *parent = clk->parent;
125 //FIXME: now just simply return rate
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.
131 *prate = parent->parent->rate;
136 static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
137 unsigned long parent_rate)
139 return clk_divider_ops.recalc_rate(hw, parent_rate);
142 static long clk_divider_round_rate(struct clk_hw *hw,
143 unsigned long rate, unsigned long *prate)
145 return clk_divider_ops.round_rate(hw, rate, prate);
148 static int clk_divider_set_rate(struct clk_hw *hw,
149 unsigned long rate, unsigned long parent_rate)
151 return clk_divider_ops.set_rate(hw, rate, parent_rate);
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)
158 struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
160 unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
163 parent = __clk_get_parent(clk);
165 best = __clk_get_rate(clk);
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);
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);
183 parent_rate = __clk_get_rate(parent);
184 now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
186 if (now <= rate && now > best) {
187 best_parent = parent;
188 best_prate = parent_rate;
195 *best_parent_rate = best_prate;
198 *best_parent_p = best_parent;
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);
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,
215 static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate,
216 unsigned long *prate)
219 struct clk_divider *divider =to_clk_divider(hw);
220 int max_div = 1 << divider->width;
222 for (i = 1; i <= max_div; i++) {
223 if (i > 1 && (i % 2 != 0))
225 if (rate >= (*prate / i))
229 return (*prate / max_div);
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,
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)
242 struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
244 unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
247 parent = __clk_get_parent(clk);
249 best = __clk_get_rate(clk);
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);
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);
267 parent_rate = __clk_get_rate(parent);
268 now = clk_div_round_rate_even(div_hw, rate, &parent_rate);
270 if (now <= rate && now > best) {
271 best_parent = parent;
272 best_prate = parent_rate;
279 *best_parent_rate = best_prate;
282 *best_parent_p = best_parent;
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);
292 static long clk_mux_with_evendiv_round_rate(struct clk_hw *hw, unsigned long rate,
293 unsigned long *prate)
295 return clk_div_round_rate_even(hw, rate, prate);
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,
305 static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
306 unsigned long parent_rate)
308 u32 numerator, denominator;
309 struct clk_divider *div = to_clk_divider(hw);
313 if(clk_fracdiv_get_config(rate, parent_rate,
314 &numerator, &denominator) == 0) {
316 writel((numerator - 1) << 16 | denominator, div->reg);
318 writel(numerator << 16 | denominator, div->reg);
321 clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
323 clk_err("clk_frac_div name=%s can't get rate=%lu\n",
324 hw->clk->name, rate);
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,
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,
343 static unsigned long clk_core_recalc_rate(struct clk_hw *hw,
344 unsigned long parent_rate)
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.
353 struct clk *parent = __clk_get_parent(hw->clk);
355 return clk_divider_recalc_rate(hw, __clk_get_rate(parent));
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)
362 struct clk *parent = __clk_get_parent(hw->clk);
364 if (IS_ERR_OR_NULL(parent)) {
365 clk_err("fail to get parent!\n");
369 return clk_round_rate(parent, rate);
372 static long clk_core_round_rate(struct clk_hw *hw, unsigned long rate,
373 unsigned long *prate)
375 return clk_core_determine_rate(hw, rate, prate, NULL);
378 static int clk_core_set_rate(struct clk_hw *hw, unsigned long rate,
379 unsigned long parent_rate)
381 struct clk *parent = __clk_get_parent(hw->clk);
382 struct clk *grand_p = __clk_get_parent(parent);
385 if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
386 clk_err("fail to get parent or grand_parent!\n");
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));
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,
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,
412 static unsigned long clk_ddr_recalc_rate(struct clk_hw *hw,
413 unsigned long parent_rate)
415 /* Same as clk_core, we should NOT set clk_ddr's parent
416 * (dpll) rate directly as a side effect.
418 return clk_core_recalc_rate(hw, parent_rate);
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)
427 if (!ddr_round_rate) {
428 /* Do nothing before ddr init */
429 best = rate;//__clk_get_rate(hw->clk);
431 /* Func provided by ddr driver */
432 best = ddr_round_rate(rate/MHZ) * MHZ;
435 clk_debug("%s: from %lu to %lu\n", __func__, rate, best);
440 static long clk_ddr_round_rate(struct clk_hw *hw, unsigned long rate,
441 unsigned long *prate)
443 return clk_ddr_determine_rate(hw, rate, prate, NULL);
446 static int clk_ddr_set_rate(struct clk_hw *hw, unsigned long rate,
447 unsigned long parent_rate)
449 struct clk *parent = __clk_get_parent(hw->clk);
450 struct clk *grand_p = __clk_get_parent(parent);
453 /* Do nothing before ddr init */
454 if (!ddr_change_freq)
457 if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
458 clk_err("fail to get parent or grand_parent!\n");
462 clk_debug("%s: will set rate = %lu\n", __func__, rate);
464 /* Func provided by ddr driver */
465 ddr_change_freq(rate/MHZ);
467 parent->rate = parent->ops->recalc_rate(parent->hw,
468 __clk_get_rate(grand_p));
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,
480 static unsigned long clk_ddr_div2_recalc_rate(struct clk_hw *hw,
481 unsigned long parent_rate)
483 /* Same as clk_core, we should NOT set clk_ddr's parent
484 * (dpll) rate directly as a side effect.
486 struct clk *parent = __clk_get_parent(hw->clk);
488 return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/2;
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,
498 static unsigned long clk_ddr_div4_recalc_rate(struct clk_hw *hw,
499 unsigned long parent_rate)
501 /* Same as clk_core, we should NOT set clk_ddr's parent
502 * (dpll) rate directly as a side effect.
504 struct clk *parent = __clk_get_parent(hw->clk);
506 return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/4;
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,
517 static unsigned long clk_3288_i2s_recalc_rate(struct clk_hw *hw,
518 unsigned long parent_rate)
523 static long clk_3288_i2s_round_rate(struct clk_hw *hw, unsigned long rate,
524 unsigned long *prate)
529 static int clk_3288_i2s_set_rate(struct clk_hw *hw, unsigned long rate,
530 unsigned long parent_rate)
532 struct clk *parent = __clk_get_parent(hw->clk);
533 struct clk *grand_p = __clk_get_parent(parent);
536 if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
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));
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,
554 static bool usb480m_state = false;
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)
566 static long clk_3288_usb480m_round_rate(struct clk_hw *hw, unsigned long rate,
567 unsigned long *prate)
569 return clk_3288_usb480m_determine_rate(hw, rate, prate, NULL);
572 static int clk_3288_usb480m_set_rate(struct clk_hw *hw, unsigned long rate,
573 unsigned long parent_rate)
576 usb480m_state = false;
578 usb480m_state = true;
583 static unsigned long clk_3288_usb480m_recalc_rate(struct clk_hw *hw,
584 unsigned long parent_rate)
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,
599 #define RK3288_LIMIT_PLL_VIO0 (410*MHZ)
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)
605 struct clk *gpll = clk_get(NULL, "clk_gpll");
606 struct clk *cpll = clk_get(NULL, "clk_cpll");
607 unsigned long best, div, prate;
610 if((rate <= (297*MHZ)) && ((297*MHZ)%rate == 0)) {
611 *best_parent_p = gpll;
613 *best_parent_rate = 297*MHZ;
615 *best_parent_p = cpll;
616 div = RK3288_LIMIT_PLL_VIO0/rate;
618 *best_parent_rate = clk_round_rate(cpll, prate);
619 best = (*best_parent_rate)/div;
625 static long clk_3288_dclk_lcdc0_round_rate(struct clk_hw *hw, unsigned long rate,
626 unsigned long *prate)
628 return clk_3288_dclk_lcdc0_determine_rate(hw, rate, prate, NULL);
631 static int clk_3288_dclk_lcdc0_set_rate(struct clk_hw *hw, unsigned long rate,
632 unsigned long parent_rate)
634 struct clk* aclk_vio0 = clk_get(NULL, "aclk_vio0");
635 struct clk* hclk_vio = clk_get(NULL, "hclk_vio");
638 clk_divider_ops.set_rate(hw, rate, parent_rate);
641 if(parent_rate == 297*MHZ)
642 parent = clk_get(NULL, "clk_gpll");
644 parent = clk_get(NULL, "clk_cpll");
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);
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,
660 #define RK3288_LIMIT_PLL_VIO1 (350*MHZ)
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)
666 struct clk *gpll = clk_get(NULL, "clk_gpll");
667 struct clk *cpll = clk_get(NULL, "clk_cpll");
668 unsigned long best, div, prate;
671 if((rate <= (297*MHZ)) && ((297*MHZ)%rate == 0)) {
672 *best_parent_p = gpll;
674 *best_parent_rate = 297*MHZ;
676 *best_parent_p = cpll;
677 div = RK3288_LIMIT_PLL_VIO1/rate;
679 *best_parent_rate = clk_round_rate(cpll, prate);
680 best = (*best_parent_rate)/div;
686 static long clk_3288_dclk_lcdc1_round_rate(struct clk_hw *hw, unsigned long rate,
687 unsigned long *prate)
689 return clk_3288_dclk_lcdc1_determine_rate(hw, rate, prate, NULL);
692 static int clk_3288_dclk_lcdc1_set_rate(struct clk_hw *hw, unsigned long rate,
693 unsigned long parent_rate)
695 struct clk* aclk_vio1 = clk_get(NULL, "aclk_vio1");
698 clk_divider_ops.set_rate(hw, rate, parent_rate);
701 if(parent_rate == 297*MHZ)
702 parent = clk_get(NULL, "clk_gpll");
704 parent = clk_get(NULL, "clk_cpll");
706 clk_set_parent(aclk_vio1, parent);
707 clk_set_rate(aclk_vio1, __clk_get_rate(parent));
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,
719 #define CONFIG_RK3368_MUX_NO_USE_NPLL
721 static long clk_3368_mux_div_determine_rate(struct clk_hw *div_hw,
723 unsigned long *best_parent_rate,
724 struct clk **best_parent_p)
726 struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
728 unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
730 parent = __clk_get_parent(clk);
732 best = __clk_get_rate(clk);
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);
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);
750 #ifdef CONFIG_RK3368_MUX_NO_USE_NPLL
751 if (!strcmp(__clk_get_name(parent), "clk_npll"))
754 parent_rate = __clk_get_rate(parent);
755 now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
757 if (now <= rate && now > best) {
758 best_parent = parent;
759 best_prate = parent_rate;
766 *best_parent_rate = best_prate;
769 *best_parent_p = best_parent;
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);
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,
786 #define RK3368_LIMIT_NPLL (1250*MHZ)
788 static long clk_3368_dclk_lcdc_determine_rate(struct clk_hw *hw,
790 unsigned long *best_parent_rate,
791 struct clk **best_parent_p)
793 struct clk *npll = clk_get(NULL, "clk_npll");
794 unsigned long div, prate, best;
796 *best_parent_p = npll;
798 div = RK3368_LIMIT_NPLL/rate;
799 /* div should be even */
804 *best_parent_rate = clk_round_rate(npll, prate);
805 best = (*best_parent_rate)/div;
810 static long clk_3368_dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate,
811 unsigned long *prate)
813 return clk_3368_dclk_lcdc_determine_rate(hw, rate, prate, NULL);
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,
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},
848 const struct clk_ops *rk_get_clkops(unsigned int idx)
851 unsigned int now_idx;
854 now_idx = rk_clkops_rate_table[i].index;
856 if ((now_idx == idx) || (now_idx == CLKOPS_TABLE_END))
857 return rk_clkops_rate_table[i].clk_ops;
862 EXPORT_SYMBOL_GPL(rk_get_clkops);