Lines Matching +full:clk +full:- +full:out +full:- +full:frequency
1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/arch/arm/mach-omap1/clock.c
5 * Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation
17 #include <linux/clk.h>
20 #include <asm/mach-types.h>
31 struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
41 unsigned long omap1_uart_recalc(struct clk *clk) in omap1_uart_recalc() argument
43 unsigned int val = __raw_readl(clk->enable_reg); in omap1_uart_recalc()
44 return val & clk->enable_bit ? 48000000 : 12000000; in omap1_uart_recalc()
47 unsigned long omap1_sossi_recalc(struct clk *clk) in omap1_sossi_recalc() argument
54 return clk->parent->rate / div; in omap1_sossi_recalc()
57 static void omap1_clk_allow_idle(struct clk *clk) in omap1_clk_allow_idle() argument
59 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; in omap1_clk_allow_idle()
61 if (!(clk->flags & CLOCK_IDLE_CONTROL)) in omap1_clk_allow_idle()
64 if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count)) in omap1_clk_allow_idle()
65 arm_idlect1_mask |= 1 << iclk->idlect_shift; in omap1_clk_allow_idle()
68 static void omap1_clk_deny_idle(struct clk *clk) in omap1_clk_deny_idle() argument
70 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; in omap1_clk_deny_idle()
72 if (!(clk->flags & CLOCK_IDLE_CONTROL)) in omap1_clk_deny_idle()
75 if (iclk->no_idle_count++ == 0) in omap1_clk_deny_idle()
76 arm_idlect1_mask &= ~(1 << iclk->idlect_shift); in omap1_clk_deny_idle()
132 static int calc_dsor_exp(struct clk *clk, unsigned long rate) in calc_dsor_exp() argument
134 /* Note: If target frequency is too low, this function will return 4, in calc_dsor_exp()
146 struct clk * parent; in calc_dsor_exp()
149 parent = clk->parent; in calc_dsor_exp()
151 return -EIO; in calc_dsor_exp()
153 realrate = parent->rate; in calc_dsor_exp()
164 unsigned long omap1_ckctl_recalc(struct clk *clk) in omap1_ckctl_recalc() argument
166 /* Calculate divisor encoded as 2-bit exponent */ in omap1_ckctl_recalc()
167 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); in omap1_ckctl_recalc()
169 return clk->parent->rate / dsor; in omap1_ckctl_recalc()
172 unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk) in omap1_ckctl_recalc_dsp_domain() argument
176 /* Calculate divisor encoded as 2-bit exponent in omap1_ckctl_recalc_dsp_domain()
184 dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); in omap1_ckctl_recalc_dsp_domain()
187 return clk->parent->rate / dsor; in omap1_ckctl_recalc_dsp_domain()
191 int omap1_select_table_rate(struct clk *clk, unsigned long rate) in omap1_select_table_rate() argument
193 /* Find the highest supported frequency <= rate and switch to it */ in omap1_select_table_rate()
197 ref_rate = ck_ref_p->rate; in omap1_select_table_rate()
199 for (ptr = omap1_rate_table; ptr->rate; ptr++) { in omap1_select_table_rate()
200 if (!(ptr->flags & cpu_mask)) in omap1_select_table_rate()
203 if (ptr->xtal != ref_rate) in omap1_select_table_rate()
206 /* Can check only after xtal frequency check */ in omap1_select_table_rate()
207 if (ptr->rate <= rate) in omap1_select_table_rate()
211 if (!ptr->rate) in omap1_select_table_rate()
212 return -EINVAL; in omap1_select_table_rate()
218 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); in omap1_select_table_rate()
221 ck_dpll1_p->rate = ptr->pll_rate; in omap1_select_table_rate()
226 int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate) in omap1_clk_set_rate_dsp_domain() argument
231 dsor_exp = calc_dsor_exp(clk, rate); in omap1_clk_set_rate_dsp_domain()
233 dsor_exp = -EINVAL; in omap1_clk_set_rate_dsp_domain()
238 regval &= ~(3 << clk->rate_offset); in omap1_clk_set_rate_dsp_domain()
239 regval |= dsor_exp << clk->rate_offset; in omap1_clk_set_rate_dsp_domain()
241 clk->rate = clk->parent->rate / (1 << dsor_exp); in omap1_clk_set_rate_dsp_domain()
246 long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate) in omap1_clk_round_rate_ckctl_arm() argument
248 int dsor_exp = calc_dsor_exp(clk, rate); in omap1_clk_round_rate_ckctl_arm()
253 return clk->parent->rate / (1 << dsor_exp); in omap1_clk_round_rate_ckctl_arm()
256 int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate) in omap1_clk_set_rate_ckctl_arm() argument
261 dsor_exp = calc_dsor_exp(clk, rate); in omap1_clk_set_rate_ckctl_arm()
263 dsor_exp = -EINVAL; in omap1_clk_set_rate_ckctl_arm()
268 regval &= ~(3 << clk->rate_offset); in omap1_clk_set_rate_ckctl_arm()
269 regval |= dsor_exp << clk->rate_offset; in omap1_clk_set_rate_ckctl_arm()
272 clk->rate = clk->parent->rate / (1 << dsor_exp); in omap1_clk_set_rate_ckctl_arm()
276 long omap1_round_to_table_rate(struct clk *clk, unsigned long rate) in omap1_round_to_table_rate() argument
278 /* Find the highest supported frequency <= rate */ in omap1_round_to_table_rate()
283 ref_rate = ck_ref_p->rate; in omap1_round_to_table_rate()
285 highest_rate = -EINVAL; in omap1_round_to_table_rate()
287 for (ptr = omap1_rate_table; ptr->rate; ptr++) { in omap1_round_to_table_rate()
288 if (!(ptr->flags & cpu_mask)) in omap1_round_to_table_rate()
291 if (ptr->xtal != ref_rate) in omap1_round_to_table_rate()
294 highest_rate = ptr->rate; in omap1_round_to_table_rate()
296 /* Can check only after xtal frequency check */ in omap1_round_to_table_rate()
297 if (ptr->rate <= rate) in omap1_round_to_table_rate()
311 * RATIO_SEL range: dsor <-> RATIO_SEL in calc_ext_dsor()
312 * 0..6: (RATIO_SEL+2) <-> (dsor-2) in calc_ext_dsor()
313 * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6) in calc_ext_dsor()
327 int omap1_set_uart_rate(struct clk *clk, unsigned long rate) in omap1_set_uart_rate() argument
331 val = __raw_readl(clk->enable_reg); in omap1_set_uart_rate()
333 val &= ~(1 << clk->enable_bit); in omap1_set_uart_rate()
335 val |= (1 << clk->enable_bit); in omap1_set_uart_rate()
337 return -EINVAL; in omap1_set_uart_rate()
338 __raw_writel(val, clk->enable_reg); in omap1_set_uart_rate()
339 clk->rate = rate; in omap1_set_uart_rate()
345 int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate) in omap1_set_ext_clk_rate() argument
351 clk->rate = 96000000 / dsor; in omap1_set_ext_clk_rate()
353 ratio_bits = ((dsor - 8) / 2 + 6) << 2; in omap1_set_ext_clk_rate()
355 ratio_bits = (dsor - 2) << 2; in omap1_set_ext_clk_rate()
357 ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd; in omap1_set_ext_clk_rate()
358 __raw_writew(ratio_bits, clk->enable_reg); in omap1_set_ext_clk_rate()
363 int omap1_set_sossi_rate(struct clk *clk, unsigned long rate) in omap1_set_sossi_rate() argument
369 p_rate = clk->parent->rate; in omap1_set_sossi_rate()
370 /* Round towards slower frequency */ in omap1_set_sossi_rate()
371 div = (p_rate + rate - 1) / rate; in omap1_set_sossi_rate()
372 div--; in omap1_set_sossi_rate()
374 return -EINVAL; in omap1_set_sossi_rate()
381 clk->rate = p_rate / (div + 1); in omap1_set_sossi_rate()
386 long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate) in omap1_round_ext_clk_rate() argument
391 void omap1_init_ext_clk(struct clk *clk) in omap1_init_ext_clk() argument
397 ratio_bits = __raw_readw(clk->enable_reg) & ~1; in omap1_init_ext_clk()
398 __raw_writew(ratio_bits, clk->enable_reg); in omap1_init_ext_clk()
402 dsor = (ratio_bits - 6) * 2 + 8; in omap1_init_ext_clk()
406 clk-> rate = 96000000 / dsor; in omap1_init_ext_clk()
409 int omap1_clk_enable(struct clk *clk) in omap1_clk_enable() argument
413 if (clk->usecount++ == 0) { in omap1_clk_enable()
414 if (clk->parent) { in omap1_clk_enable()
415 ret = omap1_clk_enable(clk->parent); in omap1_clk_enable()
419 if (clk->flags & CLOCK_NO_IDLE_PARENT) in omap1_clk_enable()
420 omap1_clk_deny_idle(clk->parent); in omap1_clk_enable()
423 ret = clk->ops->enable(clk); in omap1_clk_enable()
425 if (clk->parent) in omap1_clk_enable()
426 omap1_clk_disable(clk->parent); in omap1_clk_enable()
433 clk->usecount--; in omap1_clk_enable()
437 void omap1_clk_disable(struct clk *clk) in omap1_clk_disable() argument
439 if (clk->usecount > 0 && !(--clk->usecount)) { in omap1_clk_disable()
440 clk->ops->disable(clk); in omap1_clk_disable()
441 if (likely(clk->parent)) { in omap1_clk_disable()
442 omap1_clk_disable(clk->parent); in omap1_clk_disable()
443 if (clk->flags & CLOCK_NO_IDLE_PARENT) in omap1_clk_disable()
444 omap1_clk_allow_idle(clk->parent); in omap1_clk_disable()
449 static int omap1_clk_enable_generic(struct clk *clk) in omap1_clk_enable_generic() argument
454 if (unlikely(clk->enable_reg == NULL)) { in omap1_clk_enable_generic()
456 clk->name); in omap1_clk_enable_generic()
457 return -EINVAL; in omap1_clk_enable_generic()
460 if (clk->flags & ENABLE_REG_32BIT) { in omap1_clk_enable_generic()
461 regval32 = __raw_readl(clk->enable_reg); in omap1_clk_enable_generic()
462 regval32 |= (1 << clk->enable_bit); in omap1_clk_enable_generic()
463 __raw_writel(regval32, clk->enable_reg); in omap1_clk_enable_generic()
465 regval16 = __raw_readw(clk->enable_reg); in omap1_clk_enable_generic()
466 regval16 |= (1 << clk->enable_bit); in omap1_clk_enable_generic()
467 __raw_writew(regval16, clk->enable_reg); in omap1_clk_enable_generic()
473 static void omap1_clk_disable_generic(struct clk *clk) in omap1_clk_disable_generic() argument
478 if (clk->enable_reg == NULL) in omap1_clk_disable_generic()
481 if (clk->flags & ENABLE_REG_32BIT) { in omap1_clk_disable_generic()
482 regval32 = __raw_readl(clk->enable_reg); in omap1_clk_disable_generic()
483 regval32 &= ~(1 << clk->enable_bit); in omap1_clk_disable_generic()
484 __raw_writel(regval32, clk->enable_reg); in omap1_clk_disable_generic()
486 regval16 = __raw_readw(clk->enable_reg); in omap1_clk_disable_generic()
487 regval16 &= ~(1 << clk->enable_bit); in omap1_clk_disable_generic()
488 __raw_writew(regval16, clk->enable_reg); in omap1_clk_disable_generic()
497 static int omap1_clk_enable_dsp_domain(struct clk *clk) in omap1_clk_enable_dsp_domain() argument
503 retval = omap1_clk_enable_generic(clk); in omap1_clk_enable_dsp_domain()
510 static void omap1_clk_disable_dsp_domain(struct clk *clk) in omap1_clk_disable_dsp_domain() argument
513 omap1_clk_disable_generic(clk); in omap1_clk_disable_dsp_domain()
524 static int omap1_clk_enable_uart_functional_16xx(struct clk *clk) in omap1_clk_enable_uart_functional_16xx() argument
529 ret = omap1_clk_enable_generic(clk); in omap1_clk_enable_uart_functional_16xx()
532 uclk = (struct uart_clk *)clk; in omap1_clk_enable_uart_functional_16xx()
533 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8, in omap1_clk_enable_uart_functional_16xx()
534 uclk->sysc_addr); in omap1_clk_enable_uart_functional_16xx()
541 static void omap1_clk_disable_uart_functional_16xx(struct clk *clk) in omap1_clk_disable_uart_functional_16xx() argument
546 uclk = (struct uart_clk *)clk; in omap1_clk_disable_uart_functional_16xx()
547 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); in omap1_clk_disable_uart_functional_16xx()
549 omap1_clk_disable_generic(clk); in omap1_clk_disable_uart_functional_16xx()
558 long omap1_clk_round_rate(struct clk *clk, unsigned long rate) in omap1_clk_round_rate() argument
560 if (clk->round_rate != NULL) in omap1_clk_round_rate()
561 return clk->round_rate(clk, rate); in omap1_clk_round_rate()
563 return clk->rate; in omap1_clk_round_rate()
566 int omap1_clk_set_rate(struct clk *clk, unsigned long rate) in omap1_clk_set_rate() argument
568 int ret = -EINVAL; in omap1_clk_set_rate()
570 if (clk->set_rate) in omap1_clk_set_rate()
571 ret = clk->set_rate(clk, rate); in omap1_clk_set_rate()
581 void omap1_clk_disable_unused(struct clk *clk) in omap1_clk_disable_unused() argument
587 if (clk->enable_reg == DSP_IDLECT2) { in omap1_clk_disable_unused()
589 clk->name); in omap1_clk_disable_unused()
594 if (clk->flags & ENABLE_REG_32BIT) in omap1_clk_disable_unused()
595 regval32 = __raw_readl(clk->enable_reg); in omap1_clk_disable_unused()
597 regval32 = __raw_readw(clk->enable_reg); in omap1_clk_disable_unused()
599 if ((regval32 & (1 << clk->enable_bit)) == 0) in omap1_clk_disable_unused()
602 printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name); in omap1_clk_disable_unused()
603 clk->ops->disable(clk); in omap1_clk_disable_unused()
610 int clk_enable(struct clk *clk) in clk_enable() argument
615 if (clk == NULL || IS_ERR(clk)) in clk_enable()
616 return -EINVAL; in clk_enable()
619 ret = omap1_clk_enable(clk); in clk_enable()
626 void clk_disable(struct clk *clk) in clk_disable() argument
630 if (clk == NULL || IS_ERR(clk)) in clk_disable()
634 if (clk->usecount == 0) { in clk_disable()
636 clk->name); in clk_disable()
638 goto out; in clk_disable()
641 omap1_clk_disable(clk); in clk_disable()
643 out: in clk_disable()
648 unsigned long clk_get_rate(struct clk *clk) in clk_get_rate() argument
653 if (clk == NULL || IS_ERR(clk)) in clk_get_rate()
657 ret = clk->rate; in clk_get_rate()
665 * Optional clock functions defined in include/linux/clk.h
668 long clk_round_rate(struct clk *clk, unsigned long rate) in clk_round_rate() argument
673 if (clk == NULL || IS_ERR(clk)) in clk_round_rate()
677 ret = omap1_clk_round_rate(clk, rate); in clk_round_rate()
684 int clk_set_rate(struct clk *clk, unsigned long rate) in clk_set_rate() argument
687 int ret = -EINVAL; in clk_set_rate()
689 if (clk == NULL || IS_ERR(clk)) in clk_set_rate()
693 ret = omap1_clk_set_rate(clk, rate); in clk_set_rate()
695 propagate_rate(clk); in clk_set_rate()
702 int clk_set_parent(struct clk *clk, struct clk *parent) in clk_set_parent() argument
706 return -EINVAL; in clk_set_parent()
710 struct clk *clk_get_parent(struct clk *clk) in clk_get_parent() argument
712 return clk->parent; in clk_get_parent()
721 unsigned long followparent_recalc(struct clk *clk) in followparent_recalc() argument
723 return clk->parent->rate; in followparent_recalc()
730 unsigned long omap_fixed_divisor_recalc(struct clk *clk) in omap_fixed_divisor_recalc() argument
732 WARN_ON(!clk->fixed_div); in omap_fixed_divisor_recalc()
734 return clk->parent->rate / clk->fixed_div; in omap_fixed_divisor_recalc()
737 void clk_reparent(struct clk *child, struct clk *parent) in clk_reparent()
739 list_del_init(&child->sibling); in clk_reparent()
741 list_add(&child->sibling, &parent->children); in clk_reparent()
742 child->parent = parent; in clk_reparent()
749 void propagate_rate(struct clk *tclk) in propagate_rate()
751 struct clk *clkp; in propagate_rate()
753 list_for_each_entry(clkp, &tclk->children, sibling) { in propagate_rate()
754 if (clkp->recalc) in propagate_rate()
755 clkp->rate = clkp->recalc(clkp); in propagate_rate()
763 * recalculate_root_clocks - recalculate and propagate all root clocks
771 struct clk *clkp; in recalculate_root_clocks()
774 if (clkp->recalc) in recalculate_root_clocks()
775 clkp->rate = clkp->recalc(clkp); in recalculate_root_clocks()
781 * clk_preinit - initialize any fields in the struct clk before clk init
782 * @clk: struct clk * to initialize
784 * Initialize any struct clk fields needed before normal clk initialization
787 void clk_preinit(struct clk *clk) in clk_preinit() argument
789 INIT_LIST_HEAD(&clk->children); in clk_preinit()
792 int clk_register(struct clk *clk) in clk_register() argument
794 if (clk == NULL || IS_ERR(clk)) in clk_register()
795 return -EINVAL; in clk_register()
798 * trap out already registered clocks in clk_register()
800 if (clk->node.next || clk->node.prev) in clk_register()
804 if (clk->parent) in clk_register()
805 list_add(&clk->sibling, &clk->parent->children); in clk_register()
807 list_add(&clk->sibling, &root_clks); in clk_register()
809 list_add(&clk->node, &clocks); in clk_register()
810 if (clk->init) in clk_register()
811 clk->init(clk); in clk_register()
818 void clk_unregister(struct clk *clk) in clk_unregister() argument
820 if (clk == NULL || IS_ERR(clk)) in clk_unregister()
824 list_del(&clk->sibling); in clk_unregister()
825 list_del(&clk->node); in clk_unregister()
832 struct clk *clkp; in clk_enable_init_clocks()
835 if (clkp->flags & ENABLE_ON_INIT) in clk_enable_init_clocks()
840 * omap_clk_get_by_name - locate OMAP struct clk by its name
841 * @name: name of the struct clk to locate
843 * Locate an OMAP struct clk by its name. Assumes that struct clk
845 * struct clk if found.
847 struct clk *omap_clk_get_by_name(const char *name) in omap_clk_get_by_name()
849 struct clk *c; in omap_clk_get_by_name()
850 struct clk *ret = NULL; in omap_clk_get_by_name()
855 if (!strcmp(c->name, name)) { in omap_clk_get_by_name()
868 struct clk *c; in omap_clk_enable_autoidle_all()
874 if (c->ops->allow_idle) in omap_clk_enable_autoidle_all()
875 c->ops->allow_idle(c); in omap_clk_enable_autoidle_all()
884 struct clk *c; in omap_clk_disable_autoidle_all()
890 if (c->ops->deny_idle) in omap_clk_disable_autoidle_all()
891 c->ops->deny_idle(c); in omap_clk_disable_autoidle_all()
901 static int clkll_enable_null(struct clk *clk) in clkll_enable_null() argument
906 static void clkll_disable_null(struct clk *clk) in clkll_disable_null() argument
920 struct clk dummy_ck = {
935 struct clk *ck; in clk_disable_unused()
942 if (ck->ops == &clkops_null) in clk_disable_unused()
945 if (ck->usecount > 0 || !ck->enable_reg) in clk_disable_unused()
970 struct clk *c; in debug_clock_show()
971 struct clk *pa; in debug_clock_show()
974 seq_printf(s, "%-30s %-30s %-10s %s\n", in debug_clock_show()
975 "clock-name", "parent-name", "rate", "use-count"); in debug_clock_show()
978 pa = c->parent; in debug_clock_show()
979 seq_printf(s, "%-30s %-30s %-10lu %d\n", in debug_clock_show()
980 c->name, pa ? pa->name : "none", c->rate, in debug_clock_show()
981 c->usecount); in debug_clock_show()
990 static void clk_debugfs_register_one(struct clk *c) in clk_debugfs_register_one()
993 struct clk *pa = c->parent; in clk_debugfs_register_one()
995 d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root); in clk_debugfs_register_one()
996 c->dent = d; in clk_debugfs_register_one()
998 debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount); in clk_debugfs_register_one()
999 debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate); in clk_debugfs_register_one()
1000 debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags); in clk_debugfs_register_one()
1003 static void clk_debugfs_register(struct clk *c) in clk_debugfs_register()
1005 struct clk *pa = c->parent; in clk_debugfs_register()
1007 if (pa && !pa->dent) in clk_debugfs_register()
1010 if (!c->dent) in clk_debugfs_register()
1016 struct clk *c; in clk_debugfs_init()