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>
10 #include <linux/rockchip/cpu.h>
15 struct clk_ops_table rk_clk_mux_ops_table[] = {
16 {.index = CLKOPS_TABLE_END},
21 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
22 #define div_mask(d) ((1 << ((d)->width)) - 1)
24 static u32 clk_gcd(u32 numerator, u32 denominator)
28 if (!numerator || !denominator)
30 if (numerator > denominator) {
46 static int clk_fracdiv_get_config(unsigned long rate_out, unsigned long rate,
47 u32 *numerator, u32 *denominator)
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);
55 clk_err("gcd=0, frac div is not be supported\n");
59 *numerator = rate_out / gcd_val;
60 *denominator = rate / gcd_val;
62 clk_debug("%s: frac_get_seting numerator=%d, denominator=%d, times=%d\n",
63 __func__, *numerator, *denominator,
64 *denominator / *numerator);
66 if (*numerator > 0xffff || *denominator > 0xffff ||
67 (*denominator / (*numerator)) < 20) {
68 clk_err("can't get a available nume and deno\n");
76 static int clk_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
77 unsigned long parent_rate)
79 u32 numerator, denominator;
80 struct clk_divider *div = to_clk_divider(hw);
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);
88 clk_err("clk_frac_div name=%s can't get rate=%lu\n",
96 static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
97 unsigned long parent_rate)
101 struct clk_divider *div = to_clk_divider(hw);
102 u32 numerator, denominator, reg_val;
104 reg_val = readl(div->reg);
108 numerator = reg_val >> 16;
109 denominator = reg_val & 0xFFFF;
110 rate64 = (u64)parent_rate * numerator;
111 do_div(rate64, denominator);
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);
119 static long clk_fracdiv_round_rate(struct clk_hw *hw, unsigned long rate,
120 unsigned long *prate)
122 struct clk *clk = hw->clk;
123 struct clk *parent = clk->parent;
126 //FIXME: now just simply return rate
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.
132 *prate = parent->parent->rate;
137 static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
138 unsigned long parent_rate)
140 return clk_divider_ops.recalc_rate(hw, parent_rate);
143 static long clk_divider_round_rate(struct clk_hw *hw,
144 unsigned long rate, unsigned long *prate)
146 return clk_divider_ops.round_rate(hw, rate, prate);
149 static int clk_divider_set_rate(struct clk_hw *hw,
150 unsigned long rate, unsigned long parent_rate)
152 return clk_divider_ops.set_rate(hw, rate, parent_rate);
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)
159 struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
161 unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
164 parent = __clk_get_parent(clk);
166 best = __clk_get_rate(clk);
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);
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);
184 parent_rate = __clk_get_rate(parent);
185 now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
187 if (now <= rate && now > best) {
188 best_parent = parent;
189 best_prate = parent_rate;
196 *best_parent_rate = best_prate;
199 *best_parent_p = best_parent;
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);
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,
216 static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate,
217 unsigned long *prate)
220 struct clk_divider *divider =to_clk_divider(hw);
221 int max_div = 1 << divider->width;
223 for (i = 1; i <= max_div; i++) {
224 if (i > 1 && (i % 2 != 0))
226 if (rate >= (*prate / i))
230 return (*prate / max_div);
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,
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)
243 struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
245 unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
248 parent = __clk_get_parent(clk);
250 best = __clk_get_rate(clk);
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);
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);
268 parent_rate = __clk_get_rate(parent);
269 now = clk_div_round_rate_even(div_hw, rate, &parent_rate);
271 if (now <= rate && now > best) {
272 best_parent = parent;
273 best_prate = parent_rate;
280 *best_parent_rate = best_prate;
283 *best_parent_p = best_parent;
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);
293 static long clk_mux_with_evendiv_round_rate(struct clk_hw *hw, unsigned long rate,
294 unsigned long *prate)
296 return clk_div_round_rate_even(hw, rate, prate);
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,
306 static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
307 unsigned long parent_rate)
309 u32 numerator, denominator;
310 struct clk_divider *div = to_clk_divider(hw);
314 if(clk_fracdiv_get_config(rate, parent_rate,
315 &numerator, &denominator) == 0) {
317 writel((numerator - 1) << 16 | denominator, div->reg);
319 writel(numerator << 16 | denominator, div->reg);
322 clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
324 clk_err("clk_frac_div name=%s can't get rate=%lu\n",
325 hw->clk->name, rate);
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,
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,
344 static unsigned long clk_core_recalc_rate(struct clk_hw *hw,
345 unsigned long parent_rate)
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.
354 struct clk *parent = __clk_get_parent(hw->clk);
356 return clk_divider_recalc_rate(hw, __clk_get_rate(parent));
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)
363 struct clk *parent = __clk_get_parent(hw->clk);
365 if (IS_ERR_OR_NULL(parent)) {
366 clk_err("fail to get parent!\n");
370 return clk_round_rate(parent, rate);
373 static long clk_core_round_rate(struct clk_hw *hw, unsigned long rate,
374 unsigned long *prate)
376 return clk_core_determine_rate(hw, rate, prate, NULL);
379 static int clk_core_set_rate(struct clk_hw *hw, unsigned long rate,
380 unsigned long parent_rate)
382 struct clk *parent = __clk_get_parent(hw->clk);
383 struct clk *grand_p = __clk_get_parent(parent);
386 if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
387 clk_err("fail to get parent or grand_parent!\n");
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));
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,
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,
413 static unsigned long clk_ddr_recalc_rate(struct clk_hw *hw,
414 unsigned long parent_rate)
416 /* Same as clk_core, we should NOT set clk_ddr's parent
417 * (dpll) rate directly as a side effect.
419 return clk_core_recalc_rate(hw, parent_rate);
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)
428 if (!ddr_round_rate) {
429 /* Do nothing before ddr init */
430 best = rate;//__clk_get_rate(hw->clk);
432 /* Func provided by ddr driver */
433 best = ddr_round_rate(rate/MHZ) * MHZ;
436 clk_debug("%s: from %lu to %lu\n", __func__, rate, best);
441 static long clk_ddr_round_rate(struct clk_hw *hw, unsigned long rate,
442 unsigned long *prate)
444 return clk_ddr_determine_rate(hw, rate, prate, NULL);
447 static int clk_ddr_set_rate(struct clk_hw *hw, unsigned long rate,
448 unsigned long parent_rate)
450 struct clk *parent = __clk_get_parent(hw->clk);
451 struct clk *grand_p = __clk_get_parent(parent);
454 /* Do nothing before ddr init */
455 if (!ddr_change_freq)
458 if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
459 clk_err("fail to get parent or grand_parent!\n");
463 clk_debug("%s: will set rate = %lu\n", __func__, rate);
465 /* Func provided by ddr driver */
466 ddr_change_freq(rate/MHZ);
468 parent->rate = parent->ops->recalc_rate(parent->hw,
469 __clk_get_rate(grand_p));
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,
481 static unsigned long clk_ddr_div2_recalc_rate(struct clk_hw *hw,
482 unsigned long parent_rate)
484 /* Same as clk_core, we should NOT set clk_ddr's parent
485 * (dpll) rate directly as a side effect.
487 struct clk *parent = __clk_get_parent(hw->clk);
489 return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/2;
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,
499 static unsigned long clk_ddr_div4_recalc_rate(struct clk_hw *hw,
500 unsigned long parent_rate)
502 /* Same as clk_core, we should NOT set clk_ddr's parent
503 * (dpll) rate directly as a side effect.
505 struct clk *parent = __clk_get_parent(hw->clk);
507 return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/4;
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,
518 static unsigned long clk_3288_i2s_recalc_rate(struct clk_hw *hw,
519 unsigned long parent_rate)
524 static long clk_3288_i2s_round_rate(struct clk_hw *hw, unsigned long rate,
525 unsigned long *prate)
530 static int clk_3288_i2s_set_rate(struct clk_hw *hw, unsigned long rate,
531 unsigned long parent_rate)
533 struct clk *parent = __clk_get_parent(hw->clk);
534 struct clk *grand_p = __clk_get_parent(parent);
537 if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
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));
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,
555 static bool usb480m_state = false;
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)
567 static long clk_3288_usb480m_round_rate(struct clk_hw *hw, unsigned long rate,
568 unsigned long *prate)
570 return clk_3288_usb480m_determine_rate(hw, rate, prate, NULL);
573 static int clk_3288_usb480m_set_rate(struct clk_hw *hw, unsigned long rate,
574 unsigned long parent_rate)
577 usb480m_state = false;
579 usb480m_state = true;
584 static unsigned long clk_3288_usb480m_recalc_rate(struct clk_hw *hw,
585 unsigned long parent_rate)
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,
600 #define RK3288_LIMIT_PLL_VIO0 (600*MHZ)
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)
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;
610 gpll_rate = __clk_get_rate(gpll);
612 if ((rate <= (297*MHZ)) && (gpll_rate%rate == 0)) {
613 *best_parent_p = gpll;
615 *best_parent_rate = gpll_rate;
617 *best_parent_p = cpll;
618 div = RK3288_LIMIT_PLL_VIO0/rate;
620 *best_parent_rate = clk_round_rate(cpll, prate);
621 best = (*best_parent_rate)/div;
627 static long clk_3288_dclk_lcdc0_round_rate(struct clk_hw *hw, unsigned long rate,
628 unsigned long *prate)
630 return clk_3288_dclk_lcdc0_determine_rate(hw, rate, prate, NULL);
633 static int clk_3288_dclk_lcdc0_set_rate(struct clk_hw *hw, unsigned long rate,
634 unsigned long parent_rate)
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;
640 struct clk *gpll = clk_get(NULL, "clk_gpll");
641 struct clk *cpll = clk_get(NULL, "clk_cpll");
643 clk_divider_ops.set_rate(hw, rate, parent_rate);
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);
651 parent = clk_get(NULL, "clk_cpll");
652 clk_set_parent(aclk_vio0, cpll);
653 clk_set_rate(aclk_vio0, __clk_get_rate(cpll));
655 clk_set_rate(hclk_vio, 100*MHZ);
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));
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,
674 #define RK3288_LIMIT_PLL_VIO1 (350*MHZ)
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)
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;
684 gpll_rate = __clk_get_rate(gpll);
686 if ((rate <= (297*MHZ)) && ((gpll_rate)%rate == 0)) {
687 *best_parent_p = gpll;
689 *best_parent_rate = gpll_rate;
691 *best_parent_p = cpll;
692 div = RK3288_LIMIT_PLL_VIO1/rate;
694 *best_parent_rate = clk_round_rate(cpll, prate);
695 best = (*best_parent_rate)/div;
701 static long clk_3288_dclk_lcdc1_round_rate(struct clk_hw *hw, unsigned long rate,
702 unsigned long *prate)
704 return clk_3288_dclk_lcdc1_determine_rate(hw, rate, prate, NULL);
707 static int clk_3288_dclk_lcdc1_set_rate(struct clk_hw *hw, unsigned long rate,
708 unsigned long parent_rate)
710 struct clk* aclk_vio1 = clk_get(NULL, "aclk_vio1");
712 struct clk *gpll = clk_get(NULL, "clk_gpll");
713 struct clk *cpll = clk_get(NULL, "clk_cpll");
715 clk_divider_ops.set_rate(hw, rate, parent_rate);
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);
723 parent = clk_get(NULL, "clk_cpll");
724 clk_set_parent(aclk_vio1, cpll);
725 clk_set_rate(aclk_vio1, __clk_get_rate(cpll));
728 if (rockchip_get_cpu_version() == 0) {
729 clk_set_parent(aclk_vio1, parent);
730 clk_set_rate(aclk_vio1, __clk_get_rate(parent));
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,
743 #define CONFIG_RK3368_MUX_NO_USE_NPLL
745 static long clk_3368_mux_div_determine_rate(struct clk_hw *div_hw,
747 unsigned long *best_parent_rate,
748 struct clk **best_parent_p)
750 struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
752 unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
754 parent = __clk_get_parent(clk);
756 best = __clk_get_rate(clk);
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);
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);
774 #ifdef CONFIG_RK3368_MUX_NO_USE_NPLL
775 if (!strcmp(__clk_get_name(parent), "clk_npll"))
778 parent_rate = __clk_get_rate(parent);
779 now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
781 if (now <= rate && now > best) {
782 best_parent = parent;
783 best_prate = parent_rate;
790 *best_parent_rate = best_prate;
793 *best_parent_p = best_parent;
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);
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,
810 #define RK3368_LIMIT_NPLL (1250*MHZ)
812 static long clk_3368_dclk_lcdc_determine_rate(struct clk_hw *hw,
814 unsigned long *best_parent_rate,
815 struct clk **best_parent_p)
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};
822 *best_parent_p = npll;
824 /* first get parent_rate from table */
825 p_prate = rk3368_pll_rates;
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;
837 /* if not suitable parent_rate found in table, then auto calc rate */
838 div = RK3368_LIMIT_NPLL/rate;
839 /* div should be even */
844 *best_parent_rate = clk_round_rate(npll, prate);
845 best = (*best_parent_rate)/div;
850 static long clk_3368_dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate,
851 unsigned long *prate)
853 return clk_3368_dclk_lcdc_determine_rate(hw, rate, prate, NULL);
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,
863 static unsigned long clk_rk3368_ddr_recalc_rate(struct clk_hw *hw,
864 unsigned long parent_rate)
866 if (!ddr_recalc_rate)
867 return (clk_core_recalc_rate(hw, parent_rate)/2);
869 return ddr_recalc_rate();
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,
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},
907 const struct clk_ops *rk_get_clkops(unsigned int idx)
910 unsigned int now_idx;
913 now_idx = rk_clkops_rate_table[i].index;
915 if ((now_idx == idx) || (now_idx == CLKOPS_TABLE_END))
916 return rk_clkops_rate_table[i].clk_ops;
921 EXPORT_SYMBOL_GPL(rk_get_clkops);