Lines Matching +full:- +full:clk
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>
19 #include <linux/clk-provider.h>
20 #include <linux/soc/ti/omap1-io.h>
23 #include <asm/mach-types.h>
33 /* provide direct internal access (not via clk API) to some clocks */
47 unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate) in omap1_uart_recalc() argument
49 unsigned int val = __raw_readl(clk->enable_reg); in omap1_uart_recalc()
50 return val & 1 << clk->enable_bit ? 48000000 : 12000000; in omap1_uart_recalc()
53 unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate) in omap1_sossi_recalc() argument
63 static void omap1_clk_allow_idle(struct omap1_clk *clk) in omap1_clk_allow_idle() argument
65 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; in omap1_clk_allow_idle()
67 if (!(clk->flags & CLOCK_IDLE_CONTROL)) in omap1_clk_allow_idle()
70 if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count)) in omap1_clk_allow_idle()
71 arm_idlect1_mask |= 1 << iclk->idlect_shift; in omap1_clk_allow_idle()
74 static void omap1_clk_deny_idle(struct omap1_clk *clk) in omap1_clk_deny_idle() argument
76 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; in omap1_clk_deny_idle()
78 if (!(clk->flags & CLOCK_IDLE_CONTROL)) in omap1_clk_deny_idle()
81 if (iclk->no_idle_count++ == 0) in omap1_clk_deny_idle()
82 arm_idlect1_mask &= ~(1 << iclk->idlect_shift); in omap1_clk_deny_idle()
154 return -EIO; in calc_dsor_exp()
166 unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate) in omap1_ckctl_recalc() argument
168 /* Calculate divisor encoded as 2-bit exponent */ in omap1_ckctl_recalc()
169 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); in omap1_ckctl_recalc()
172 clk->rate = p_rate / dsor; in omap1_ckctl_recalc()
173 return clk->rate; in omap1_ckctl_recalc()
178 struct omap1_clk *clk = to_omap1_clk(hw); in omap1_clk_is_enabled() local
183 if (!clk->ops) /* no gate -- always enabled */ in omap1_clk_is_enabled()
186 if (clk->ops == &clkops_dspck) { in omap1_clk_is_enabled()
187 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw); in omap1_clk_is_enabled()
189 if (api_ck_p->ops->enable(api_ck_p) < 0) in omap1_clk_is_enabled()
193 if (clk->flags & ENABLE_REG_32BIT) in omap1_clk_is_enabled()
194 regval32 = __raw_readl(clk->enable_reg); in omap1_clk_is_enabled()
196 regval32 = __raw_readw(clk->enable_reg); in omap1_clk_is_enabled()
198 ret = regval32 & (1 << clk->enable_bit); in omap1_clk_is_enabled()
201 api_ck_p->ops->disable(api_ck_p); in omap1_clk_is_enabled()
207 unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate) in omap1_ckctl_recalc_dsp_domain() argument
212 /* Calculate divisor encoded as 2-bit exponent in omap1_ckctl_recalc_dsp_domain()
219 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw); in omap1_ckctl_recalc_dsp_domain()
221 api_ck_p->ops->enable(api_ck_p); in omap1_ckctl_recalc_dsp_domain()
222 dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); in omap1_ckctl_recalc_dsp_domain()
224 api_ck_p->ops->disable(api_ck_p); in omap1_ckctl_recalc_dsp_domain()
230 int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) in omap1_select_table_rate() argument
236 ref_rate = ck_ref_p->rate; in omap1_select_table_rate()
238 for (ptr = omap1_rate_table; ptr->rate; ptr++) { in omap1_select_table_rate()
239 if (!(ptr->flags & cpu_mask)) in omap1_select_table_rate()
242 if (ptr->xtal != ref_rate) in omap1_select_table_rate()
246 if (ptr->rate <= rate) in omap1_select_table_rate()
250 if (!ptr->rate) in omap1_select_table_rate()
251 return -EINVAL; in omap1_select_table_rate()
257 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); in omap1_select_table_rate()
260 ck_dpll1_p->rate = ptr->pll_rate; in omap1_select_table_rate()
265 int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) in omap1_clk_set_rate_dsp_domain() argument
272 dsor_exp = -EINVAL; in omap1_clk_set_rate_dsp_domain()
277 regval &= ~(3 << clk->rate_offset); in omap1_clk_set_rate_dsp_domain()
278 regval |= dsor_exp << clk->rate_offset; in omap1_clk_set_rate_dsp_domain()
280 clk->rate = p_rate / (1 << dsor_exp); in omap1_clk_set_rate_dsp_domain()
285 long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, in omap1_clk_round_rate_ckctl_arm() argument
297 int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) in omap1_clk_set_rate_ckctl_arm() argument
305 dsor_exp = -EINVAL; in omap1_clk_set_rate_ckctl_arm()
313 regval &= ~(3 << clk->rate_offset); in omap1_clk_set_rate_ckctl_arm()
314 regval |= dsor_exp << clk->rate_offset; in omap1_clk_set_rate_ckctl_arm()
317 clk->rate = p_rate / (1 << dsor_exp); in omap1_clk_set_rate_ckctl_arm()
324 long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) in omap1_round_to_table_rate() argument
331 ref_rate = ck_ref_p->rate; in omap1_round_to_table_rate()
333 highest_rate = -EINVAL; in omap1_round_to_table_rate()
335 for (ptr = omap1_rate_table; ptr->rate; ptr++) { in omap1_round_to_table_rate()
336 if (!(ptr->flags & cpu_mask)) in omap1_round_to_table_rate()
339 if (ptr->xtal != ref_rate) in omap1_round_to_table_rate()
342 highest_rate = ptr->rate; in omap1_round_to_table_rate()
345 if (ptr->rate <= rate) in omap1_round_to_table_rate()
359 * RATIO_SEL range: dsor <-> RATIO_SEL in calc_ext_dsor()
360 * 0..6: (RATIO_SEL+2) <-> (dsor-2) in calc_ext_dsor()
361 * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6) in calc_ext_dsor()
375 long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) in omap1_round_uart_rate() argument
380 int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) in omap1_set_uart_rate() argument
388 val = 1 << clk->enable_bit; in omap1_set_uart_rate()
390 return -EINVAL; in omap1_set_uart_rate()
395 val |= __raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit); in omap1_set_uart_rate()
396 __raw_writel(val, clk->enable_reg); in omap1_set_uart_rate()
400 clk->rate = rate; in omap1_set_uart_rate()
406 int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) in omap1_set_ext_clk_rate() argument
413 clk->rate = 96000000 / dsor; in omap1_set_ext_clk_rate()
415 ratio_bits = ((dsor - 8) / 2 + 6) << 2; in omap1_set_ext_clk_rate()
417 ratio_bits = (dsor - 2) << 2; in omap1_set_ext_clk_rate()
422 ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd; in omap1_set_ext_clk_rate()
423 __raw_writew(ratio_bits, clk->enable_reg); in omap1_set_ext_clk_rate()
435 div = (p_rate + rate - 1) / rate; in calc_div_sossi()
437 return --div; in calc_div_sossi()
440 long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) in omap1_round_sossi_rate() argument
453 int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) in omap1_set_sossi_rate() argument
461 return -EINVAL; in omap1_set_sossi_rate()
471 clk->rate = p_rate / (div + 1); in omap1_set_sossi_rate()
478 long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) in omap1_round_ext_clk_rate() argument
483 int omap1_init_ext_clk(struct omap1_clk *clk) in omap1_init_ext_clk() argument
489 ratio_bits = __raw_readw(clk->enable_reg) & ~1; in omap1_init_ext_clk()
490 __raw_writew(ratio_bits, clk->enable_reg); in omap1_init_ext_clk()
494 dsor = (ratio_bits - 6) * 2 + 8; in omap1_init_ext_clk()
498 clk-> rate = 96000000 / dsor; in omap1_init_ext_clk()
505 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw)); in omap1_clk_enable() local
508 if (parent && clk->flags & CLOCK_NO_IDLE_PARENT) in omap1_clk_enable()
511 if (clk->ops && !(WARN_ON(!clk->ops->enable))) in omap1_clk_enable()
512 ret = clk->ops->enable(clk); in omap1_clk_enable()
519 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw)); in omap1_clk_disable() local
521 if (clk->ops && !(WARN_ON(!clk->ops->disable))) in omap1_clk_disable()
522 clk->ops->disable(clk); in omap1_clk_disable()
524 if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT) in omap1_clk_disable()
528 static int omap1_clk_enable_generic(struct omap1_clk *clk) in omap1_clk_enable_generic() argument
534 if (unlikely(clk->enable_reg == NULL)) { in omap1_clk_enable_generic()
536 clk_hw_get_name(&clk->hw)); in omap1_clk_enable_generic()
537 return -EINVAL; in omap1_clk_enable_generic()
540 /* protect clk->enable_reg from concurrent access via clk_set_rate() */ in omap1_clk_enable_generic()
541 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL)) in omap1_clk_enable_generic()
543 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2)) in omap1_clk_enable_generic()
545 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0)) in omap1_clk_enable_generic()
547 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1)) in omap1_clk_enable_generic()
549 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL)) in omap1_clk_enable_generic()
552 if (clk->flags & ENABLE_REG_32BIT) { in omap1_clk_enable_generic()
553 regval32 = __raw_readl(clk->enable_reg); in omap1_clk_enable_generic()
554 regval32 |= (1 << clk->enable_bit); in omap1_clk_enable_generic()
555 __raw_writel(regval32, clk->enable_reg); in omap1_clk_enable_generic()
557 regval16 = __raw_readw(clk->enable_reg); in omap1_clk_enable_generic()
558 regval16 |= (1 << clk->enable_bit); in omap1_clk_enable_generic()
559 __raw_writew(regval16, clk->enable_reg); in omap1_clk_enable_generic()
562 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL)) in omap1_clk_enable_generic()
564 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2)) in omap1_clk_enable_generic()
566 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0)) in omap1_clk_enable_generic()
568 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1)) in omap1_clk_enable_generic()
570 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL)) in omap1_clk_enable_generic()
576 static void omap1_clk_disable_generic(struct omap1_clk *clk) in omap1_clk_disable_generic() argument
582 if (clk->enable_reg == NULL) in omap1_clk_disable_generic()
585 /* protect clk->enable_reg from concurrent access via clk_set_rate() */ in omap1_clk_disable_generic()
586 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL)) in omap1_clk_disable_generic()
588 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2)) in omap1_clk_disable_generic()
590 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0)) in omap1_clk_disable_generic()
592 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1)) in omap1_clk_disable_generic()
594 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL)) in omap1_clk_disable_generic()
597 if (clk->flags & ENABLE_REG_32BIT) { in omap1_clk_disable_generic()
598 regval32 = __raw_readl(clk->enable_reg); in omap1_clk_disable_generic()
599 regval32 &= ~(1 << clk->enable_bit); in omap1_clk_disable_generic()
600 __raw_writel(regval32, clk->enable_reg); in omap1_clk_disable_generic()
602 regval16 = __raw_readw(clk->enable_reg); in omap1_clk_disable_generic()
603 regval16 &= ~(1 << clk->enable_bit); in omap1_clk_disable_generic()
604 __raw_writew(regval16, clk->enable_reg); in omap1_clk_disable_generic()
607 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL)) in omap1_clk_disable_generic()
609 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2)) in omap1_clk_disable_generic()
611 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0)) in omap1_clk_disable_generic()
613 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1)) in omap1_clk_disable_generic()
615 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL)) in omap1_clk_disable_generic()
624 static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk) in omap1_clk_enable_dsp_domain() argument
629 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw); in omap1_clk_enable_dsp_domain()
631 retval = api_ck_p->ops->enable(api_ck_p); in omap1_clk_enable_dsp_domain()
634 retval = omap1_clk_enable_generic(clk); in omap1_clk_enable_dsp_domain()
637 api_ck_p->ops->disable(api_ck_p); in omap1_clk_enable_dsp_domain()
643 static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk) in omap1_clk_disable_dsp_domain() argument
647 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw); in omap1_clk_disable_dsp_domain()
649 if (api_ck_p->ops->enable(api_ck_p) < 0) in omap1_clk_disable_dsp_domain()
652 omap1_clk_disable_generic(clk); in omap1_clk_disable_dsp_domain()
655 api_ck_p->ops->disable(api_ck_p); in omap1_clk_disable_dsp_domain()
664 static int omap1_clk_enable_uart_functional_16xx(struct omap1_clk *clk) in omap1_clk_enable_uart_functional_16xx() argument
669 ret = omap1_clk_enable_generic(clk); in omap1_clk_enable_uart_functional_16xx()
672 uclk = (struct uart_clk *)clk; in omap1_clk_enable_uart_functional_16xx()
673 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8, in omap1_clk_enable_uart_functional_16xx()
674 uclk->sysc_addr); in omap1_clk_enable_uart_functional_16xx()
681 static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk) in omap1_clk_disable_uart_functional_16xx() argument
686 uclk = (struct uart_clk *)clk; in omap1_clk_disable_uart_functional_16xx()
687 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); in omap1_clk_disable_uart_functional_16xx()
689 omap1_clk_disable_generic(clk); in omap1_clk_disable_uart_functional_16xx()
700 struct omap1_clk *clk = to_omap1_clk(hw); in omap1_clk_recalc_rate() local
702 if (clk->recalc) in omap1_clk_recalc_rate()
703 return clk->recalc(clk, p_rate); in omap1_clk_recalc_rate()
705 return clk->rate; in omap1_clk_recalc_rate()
710 struct omap1_clk *clk = to_omap1_clk(hw); in omap1_clk_round_rate() local
712 if (clk->round_rate != NULL) in omap1_clk_round_rate()
713 return clk->round_rate(clk, rate, p_rate); in omap1_clk_round_rate()
720 struct omap1_clk *clk = to_omap1_clk(hw); in omap1_clk_set_rate() local
721 int ret = -EINVAL; in omap1_clk_set_rate()
723 if (clk->set_rate) in omap1_clk_set_rate()
724 ret = clk->set_rate(clk, rate, p_rate); in omap1_clk_set_rate()
734 struct omap1_clk *clk = to_omap1_clk(hw); in omap1_clk_init_op() local
736 if (clk->init) in omap1_clk_init_op()
737 return clk->init(clk); in omap1_clk_init_op()
746 struct omap1_clk *clk = to_omap1_clk(hw); in omap1_clk_disable_unused() local
751 if (clk->enable_reg == DSP_IDLECT2) { in omap1_clk_disable_unused()
797 unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate) in followparent_recalc() argument
806 unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate) in omap_fixed_divisor_recalc() argument
808 WARN_ON(!clk->fixed_div); in omap_fixed_divisor_recalc()
810 return p_rate / clk->fixed_div; in omap_fixed_divisor_recalc()
816 struct clk *clkp; in propagate_rate()
819 if (WARN_ON(!(clk_hw_get_flags(&tclk->hw) & CLK_GET_RATE_NOCACHE))) in propagate_rate()
822 clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw)); in propagate_rate()