drm/rockchip: Don't change hdmi reference clock rate
[drm/drm-misc.git] / arch / arm / mach-omap1 / clock.c
blob83381e23fab983522ca01b8feffb861b02fee730
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * linux/arch/arm/mach-omap1/clock.c
5 * Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation
6 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
8 * Modified to use omap shared clock framework by
9 * Tony Lindgren <tony@atomide.com>
11 #include <linux/kernel.h>
12 #include <linux/export.h>
13 #include <linux/list.h>
14 #include <linux/errno.h>
15 #include <linux/err.h>
16 #include <linux/io.h>
17 #include <linux/clk.h>
18 #include <linux/clkdev.h>
19 #include <linux/clk-provider.h>
20 #include <linux/soc/ti/omap1-io.h>
21 #include <linux/spinlock.h>
23 #include <asm/mach-types.h>
25 #include "hardware.h"
26 #include "soc.h"
27 #include "iomap.h"
28 #include "clock.h"
29 #include "opp.h"
30 #include "sram.h"
32 __u32 arm_idlect1_mask;
33 /* provide direct internal access (not via clk API) to some clocks */
34 struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
36 /* protect registeres shared among clk_enable/disable() and clk_set_rate() operations */
37 static DEFINE_SPINLOCK(arm_ckctl_lock);
38 static DEFINE_SPINLOCK(arm_idlect2_lock);
39 static DEFINE_SPINLOCK(mod_conf_ctrl_0_lock);
40 static DEFINE_SPINLOCK(mod_conf_ctrl_1_lock);
41 static DEFINE_SPINLOCK(swd_clk_div_ctrl_sel_lock);
44 * Omap1 specific clock functions
47 unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate)
49 unsigned int val = __raw_readl(clk->enable_reg);
50 return val & 1 << clk->enable_bit ? 48000000 : 12000000;
53 unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate)
55 u32 div = omap_readl(MOD_CONF_CTRL_1);
57 div = (div >> 17) & 0x7;
58 div++;
60 return p_rate / div;
63 static void omap1_clk_allow_idle(struct omap1_clk *clk)
65 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
67 if (!(clk->flags & CLOCK_IDLE_CONTROL))
68 return;
70 if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count))
71 arm_idlect1_mask |= 1 << iclk->idlect_shift;
74 static void omap1_clk_deny_idle(struct omap1_clk *clk)
76 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
78 if (!(clk->flags & CLOCK_IDLE_CONTROL))
79 return;
81 if (iclk->no_idle_count++ == 0)
82 arm_idlect1_mask &= ~(1 << iclk->idlect_shift);
85 static __u16 verify_ckctl_value(__u16 newval)
87 /* This function checks for following limitations set
88 * by the hardware (all conditions must be true):
89 * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
90 * ARM_CK >= TC_CK
91 * DSP_CK >= TC_CK
92 * DSPMMU_CK >= TC_CK
94 * In addition following rules are enforced:
95 * LCD_CK <= TC_CK
96 * ARMPER_CK <= TC_CK
98 * However, maximum frequencies are not checked for!
100 __u8 per_exp;
101 __u8 lcd_exp;
102 __u8 arm_exp;
103 __u8 dsp_exp;
104 __u8 tc_exp;
105 __u8 dspmmu_exp;
107 per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
108 lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
109 arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
110 dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
111 tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
112 dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
114 if (dspmmu_exp < dsp_exp)
115 dspmmu_exp = dsp_exp;
116 if (dspmmu_exp > dsp_exp+1)
117 dspmmu_exp = dsp_exp+1;
118 if (tc_exp < arm_exp)
119 tc_exp = arm_exp;
120 if (tc_exp < dspmmu_exp)
121 tc_exp = dspmmu_exp;
122 if (tc_exp > lcd_exp)
123 lcd_exp = tc_exp;
124 if (tc_exp > per_exp)
125 per_exp = tc_exp;
127 newval &= 0xf000;
128 newval |= per_exp << CKCTL_PERDIV_OFFSET;
129 newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
130 newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
131 newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
132 newval |= tc_exp << CKCTL_TCDIV_OFFSET;
133 newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
135 return newval;
138 static int calc_dsor_exp(unsigned long rate, unsigned long realrate)
140 /* Note: If target frequency is too low, this function will return 4,
141 * which is invalid value. Caller must check for this value and act
142 * accordingly.
144 * Note: This function does not check for following limitations set
145 * by the hardware (all conditions must be true):
146 * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
147 * ARM_CK >= TC_CK
148 * DSP_CK >= TC_CK
149 * DSPMMU_CK >= TC_CK
151 unsigned dsor_exp;
153 if (unlikely(realrate == 0))
154 return -EIO;
156 for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
157 if (realrate <= rate)
158 break;
160 realrate /= 2;
163 return dsor_exp;
166 unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate)
168 /* Calculate divisor encoded as 2-bit exponent */
169 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
171 /* update locally maintained rate, required by arm_ck for omap1_show_rates() */
172 clk->rate = p_rate / dsor;
173 return clk->rate;
176 static int omap1_clk_is_enabled(struct clk_hw *hw)
178 struct omap1_clk *clk = to_omap1_clk(hw);
179 bool api_ck_was_enabled = true;
180 __u32 regval32;
181 int ret;
183 if (!clk->ops) /* no gate -- always enabled */
184 return 1;
186 if (clk->ops == &clkops_dspck) {
187 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
188 if (!api_ck_was_enabled)
189 if (api_ck_p->ops->enable(api_ck_p) < 0)
190 return 0;
193 if (clk->flags & ENABLE_REG_32BIT)
194 regval32 = __raw_readl(clk->enable_reg);
195 else
196 regval32 = __raw_readw(clk->enable_reg);
198 ret = regval32 & (1 << clk->enable_bit);
200 if (!api_ck_was_enabled)
201 api_ck_p->ops->disable(api_ck_p);
203 return ret;
207 unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate)
209 bool api_ck_was_enabled;
210 int dsor;
212 /* Calculate divisor encoded as 2-bit exponent
214 * The clock control bits are in DSP domain,
215 * so api_ck is needed for access.
216 * Note that DSP_CKCTL virt addr = phys addr, so
217 * we must use __raw_readw() instead of omap_readw().
219 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
220 if (!api_ck_was_enabled)
221 api_ck_p->ops->enable(api_ck_p);
222 dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
223 if (!api_ck_was_enabled)
224 api_ck_p->ops->disable(api_ck_p);
226 return p_rate / dsor;
229 /* MPU virtual clock functions */
230 int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
232 /* Find the highest supported frequency <= rate and switch to it */
233 struct mpu_rate * ptr;
234 unsigned long ref_rate;
236 ref_rate = ck_ref_p->rate;
238 for (ptr = omap1_rate_table; ptr->rate; ptr++) {
239 if (!(ptr->flags & cpu_mask))
240 continue;
242 if (ptr->xtal != ref_rate)
243 continue;
245 /* Can check only after xtal frequency check */
246 if (ptr->rate <= rate)
247 break;
250 if (!ptr->rate)
251 return -EINVAL;
254 * In most cases we should not need to reprogram DPLL.
255 * Reprogramming the DPLL is tricky, it must be done from SRAM.
257 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
259 /* XXX Do we need to recalculate the tree below DPLL1 at this point? */
260 ck_dpll1_p->rate = ptr->pll_rate;
262 return 0;
265 int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
267 int dsor_exp;
268 u16 regval;
270 dsor_exp = calc_dsor_exp(rate, p_rate);
271 if (dsor_exp > 3)
272 dsor_exp = -EINVAL;
273 if (dsor_exp < 0)
274 return dsor_exp;
276 regval = __raw_readw(DSP_CKCTL);
277 regval &= ~(3 << clk->rate_offset);
278 regval |= dsor_exp << clk->rate_offset;
279 __raw_writew(regval, DSP_CKCTL);
280 clk->rate = p_rate / (1 << dsor_exp);
282 return 0;
285 long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate,
286 unsigned long *p_rate)
288 int dsor_exp = calc_dsor_exp(rate, *p_rate);
290 if (dsor_exp < 0)
291 return dsor_exp;
292 if (dsor_exp > 3)
293 dsor_exp = 3;
294 return *p_rate / (1 << dsor_exp);
297 int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
299 unsigned long flags;
300 int dsor_exp;
301 u16 regval;
303 dsor_exp = calc_dsor_exp(rate, p_rate);
304 if (dsor_exp > 3)
305 dsor_exp = -EINVAL;
306 if (dsor_exp < 0)
307 return dsor_exp;
309 /* protect ARM_CKCTL register from concurrent access via clk_enable/disable() */
310 spin_lock_irqsave(&arm_ckctl_lock, flags);
312 regval = omap_readw(ARM_CKCTL);
313 regval &= ~(3 << clk->rate_offset);
314 regval |= dsor_exp << clk->rate_offset;
315 regval = verify_ckctl_value(regval);
316 omap_writew(regval, ARM_CKCTL);
317 clk->rate = p_rate / (1 << dsor_exp);
319 spin_unlock_irqrestore(&arm_ckctl_lock, flags);
321 return 0;
324 long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
326 /* Find the highest supported frequency <= rate */
327 struct mpu_rate * ptr;
328 long highest_rate;
329 unsigned long ref_rate;
331 ref_rate = ck_ref_p->rate;
333 highest_rate = -EINVAL;
335 for (ptr = omap1_rate_table; ptr->rate; ptr++) {
336 if (!(ptr->flags & cpu_mask))
337 continue;
339 if (ptr->xtal != ref_rate)
340 continue;
342 highest_rate = ptr->rate;
344 /* Can check only after xtal frequency check */
345 if (ptr->rate <= rate)
346 break;
349 return highest_rate;
352 static unsigned calc_ext_dsor(unsigned long rate)
354 unsigned dsor;
356 /* MCLK and BCLK divisor selection is not linear:
357 * freq = 96MHz / dsor
359 * RATIO_SEL range: dsor <-> RATIO_SEL
360 * 0..6: (RATIO_SEL+2) <-> (dsor-2)
361 * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
362 * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
363 * can not be used.
365 for (dsor = 2; dsor < 96; ++dsor) {
366 if ((dsor & 1) && dsor > 8)
367 continue;
368 if (rate >= 96000000 / dsor)
369 break;
371 return dsor;
374 /* XXX Only needed on 1510 */
375 long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
377 return rate > 24000000 ? 48000000 : 12000000;
380 int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
382 unsigned long flags;
383 unsigned int val;
385 if (rate == 12000000)
386 val = 0;
387 else if (rate == 48000000)
388 val = 1 << clk->enable_bit;
389 else
390 return -EINVAL;
392 /* protect MOD_CONF_CTRL_0 register from concurrent access via clk_enable/disable() */
393 spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
395 val |= __raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit);
396 __raw_writel(val, clk->enable_reg);
398 spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
400 clk->rate = rate;
402 return 0;
405 /* External clock (MCLK & BCLK) functions */
406 int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
408 unsigned long flags;
409 unsigned dsor;
410 __u16 ratio_bits;
412 dsor = calc_ext_dsor(rate);
413 clk->rate = 96000000 / dsor;
414 if (dsor > 8)
415 ratio_bits = ((dsor - 8) / 2 + 6) << 2;
416 else
417 ratio_bits = (dsor - 2) << 2;
419 /* protect SWD_CLK_DIV_CTRL_SEL register from concurrent access via clk_enable/disable() */
420 spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
422 ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
423 __raw_writew(ratio_bits, clk->enable_reg);
425 spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
427 return 0;
430 static int calc_div_sossi(unsigned long rate, unsigned long p_rate)
432 int div;
434 /* Round towards slower frequency */
435 div = (p_rate + rate - 1) / rate;
437 return --div;
440 long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
442 int div;
444 div = calc_div_sossi(rate, *p_rate);
445 if (div < 0)
446 div = 0;
447 else if (div > 7)
448 div = 7;
450 return *p_rate / (div + 1);
453 int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
455 unsigned long flags;
456 u32 l;
457 int div;
459 div = calc_div_sossi(rate, p_rate);
460 if (div < 0 || div > 7)
461 return -EINVAL;
463 /* protect MOD_CONF_CTRL_1 register from concurrent access via clk_enable/disable() */
464 spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
466 l = omap_readl(MOD_CONF_CTRL_1);
467 l &= ~(7 << 17);
468 l |= div << 17;
469 omap_writel(l, MOD_CONF_CTRL_1);
471 clk->rate = p_rate / (div + 1);
473 spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
475 return 0;
478 long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
480 return 96000000 / calc_ext_dsor(rate);
483 int omap1_init_ext_clk(struct omap1_clk *clk)
485 unsigned dsor;
486 __u16 ratio_bits;
488 /* Determine current rate and ensure clock is based on 96MHz APLL */
489 ratio_bits = __raw_readw(clk->enable_reg) & ~1;
490 __raw_writew(ratio_bits, clk->enable_reg);
492 ratio_bits = (ratio_bits & 0xfc) >> 2;
493 if (ratio_bits > 6)
494 dsor = (ratio_bits - 6) * 2 + 8;
495 else
496 dsor = ratio_bits + 2;
498 clk-> rate = 96000000 / dsor;
500 return 0;
503 static int omap1_clk_enable(struct clk_hw *hw)
505 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
506 int ret = 0;
508 if (parent && clk->flags & CLOCK_NO_IDLE_PARENT)
509 omap1_clk_deny_idle(parent);
511 if (clk->ops && !(WARN_ON(!clk->ops->enable)))
512 ret = clk->ops->enable(clk);
514 return ret;
517 static void omap1_clk_disable(struct clk_hw *hw)
519 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
521 if (clk->ops && !(WARN_ON(!clk->ops->disable)))
522 clk->ops->disable(clk);
524 if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT)
525 omap1_clk_allow_idle(parent);
528 static int omap1_clk_enable_generic(struct omap1_clk *clk)
530 unsigned long flags;
531 __u16 regval16;
532 __u32 regval32;
534 if (unlikely(clk->enable_reg == NULL)) {
535 printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
536 clk_hw_get_name(&clk->hw));
537 return -EINVAL;
540 /* protect clk->enable_reg from concurrent access via clk_set_rate() */
541 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
542 spin_lock_irqsave(&arm_ckctl_lock, flags);
543 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
544 spin_lock_irqsave(&arm_idlect2_lock, flags);
545 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
546 spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
547 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
548 spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
549 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
550 spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
552 if (clk->flags & ENABLE_REG_32BIT) {
553 regval32 = __raw_readl(clk->enable_reg);
554 regval32 |= (1 << clk->enable_bit);
555 __raw_writel(regval32, clk->enable_reg);
556 } else {
557 regval16 = __raw_readw(clk->enable_reg);
558 regval16 |= (1 << clk->enable_bit);
559 __raw_writew(regval16, clk->enable_reg);
562 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
563 spin_unlock_irqrestore(&arm_ckctl_lock, flags);
564 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
565 spin_unlock_irqrestore(&arm_idlect2_lock, flags);
566 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
567 spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
568 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
569 spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
570 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
571 spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
573 return 0;
576 static void omap1_clk_disable_generic(struct omap1_clk *clk)
578 unsigned long flags;
579 __u16 regval16;
580 __u32 regval32;
582 if (clk->enable_reg == NULL)
583 return;
585 /* protect clk->enable_reg from concurrent access via clk_set_rate() */
586 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
587 spin_lock_irqsave(&arm_ckctl_lock, flags);
588 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
589 spin_lock_irqsave(&arm_idlect2_lock, flags);
590 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
591 spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
592 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
593 spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
594 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
595 spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
597 if (clk->flags & ENABLE_REG_32BIT) {
598 regval32 = __raw_readl(clk->enable_reg);
599 regval32 &= ~(1 << clk->enable_bit);
600 __raw_writel(regval32, clk->enable_reg);
601 } else {
602 regval16 = __raw_readw(clk->enable_reg);
603 regval16 &= ~(1 << clk->enable_bit);
604 __raw_writew(regval16, clk->enable_reg);
607 if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
608 spin_unlock_irqrestore(&arm_ckctl_lock, flags);
609 else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
610 spin_unlock_irqrestore(&arm_idlect2_lock, flags);
611 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
612 spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
613 else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
614 spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
615 else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
616 spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
619 const struct clkops clkops_generic = {
620 .enable = omap1_clk_enable_generic,
621 .disable = omap1_clk_disable_generic,
624 static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk)
626 bool api_ck_was_enabled;
627 int retval = 0;
629 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
630 if (!api_ck_was_enabled)
631 retval = api_ck_p->ops->enable(api_ck_p);
633 if (!retval) {
634 retval = omap1_clk_enable_generic(clk);
636 if (!api_ck_was_enabled)
637 api_ck_p->ops->disable(api_ck_p);
640 return retval;
643 static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk)
645 bool api_ck_was_enabled;
647 api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
648 if (!api_ck_was_enabled)
649 if (api_ck_p->ops->enable(api_ck_p) < 0)
650 return;
652 omap1_clk_disable_generic(clk);
654 if (!api_ck_was_enabled)
655 api_ck_p->ops->disable(api_ck_p);
658 const struct clkops clkops_dspck = {
659 .enable = omap1_clk_enable_dsp_domain,
660 .disable = omap1_clk_disable_dsp_domain,
663 /* XXX SYSC register handling does not belong in the clock framework */
664 static int omap1_clk_enable_uart_functional_16xx(struct omap1_clk *clk)
666 int ret;
667 struct uart_clk *uclk;
669 ret = omap1_clk_enable_generic(clk);
670 if (ret == 0) {
671 /* Set smart idle acknowledgement mode */
672 uclk = (struct uart_clk *)clk;
673 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8,
674 uclk->sysc_addr);
677 return ret;
680 /* XXX SYSC register handling does not belong in the clock framework */
681 static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk)
683 struct uart_clk *uclk;
685 /* Set force idle acknowledgement mode */
686 uclk = (struct uart_clk *)clk;
687 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
689 omap1_clk_disable_generic(clk);
692 /* XXX SYSC register handling does not belong in the clock framework */
693 const struct clkops clkops_uart_16xx = {
694 .enable = omap1_clk_enable_uart_functional_16xx,
695 .disable = omap1_clk_disable_uart_functional_16xx,
698 static unsigned long omap1_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
700 struct omap1_clk *clk = to_omap1_clk(hw);
702 if (clk->recalc)
703 return clk->recalc(clk, p_rate);
705 return clk->rate;
708 static long omap1_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *p_rate)
710 struct omap1_clk *clk = to_omap1_clk(hw);
712 if (clk->round_rate != NULL)
713 return clk->round_rate(clk, rate, p_rate);
715 return omap1_clk_recalc_rate(hw, *p_rate);
718 static int omap1_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
720 struct omap1_clk *clk = to_omap1_clk(hw);
721 int ret = -EINVAL;
723 if (clk->set_rate)
724 ret = clk->set_rate(clk, rate, p_rate);
725 return ret;
729 * Omap1 clock reset and init functions
732 static int omap1_clk_init_op(struct clk_hw *hw)
734 struct omap1_clk *clk = to_omap1_clk(hw);
736 if (clk->init)
737 return clk->init(clk);
739 return 0;
742 #ifdef CONFIG_OMAP_RESET_CLOCKS
744 static void omap1_clk_disable_unused(struct clk_hw *hw)
746 struct omap1_clk *clk = to_omap1_clk(hw);
747 const char *name = clk_hw_get_name(hw);
749 /* Clocks in the DSP domain need api_ck. Just assume bootloader
750 * has not enabled any DSP clocks */
751 if (clk->enable_reg == DSP_IDLECT2) {
752 pr_info("Skipping reset check for DSP domain clock \"%s\"\n", name);
753 return;
756 pr_info("Disabling unused clock \"%s\"... ", name);
757 omap1_clk_disable(hw);
758 printk(" done\n");
761 #endif
763 const struct clk_ops omap1_clk_gate_ops = {
764 .enable = omap1_clk_enable,
765 .disable = omap1_clk_disable,
766 .is_enabled = omap1_clk_is_enabled,
767 #ifdef CONFIG_OMAP_RESET_CLOCKS
768 .disable_unused = omap1_clk_disable_unused,
769 #endif
772 const struct clk_ops omap1_clk_rate_ops = {
773 .recalc_rate = omap1_clk_recalc_rate,
774 .round_rate = omap1_clk_round_rate,
775 .set_rate = omap1_clk_set_rate,
776 .init = omap1_clk_init_op,
779 const struct clk_ops omap1_clk_full_ops = {
780 .enable = omap1_clk_enable,
781 .disable = omap1_clk_disable,
782 .is_enabled = omap1_clk_is_enabled,
783 #ifdef CONFIG_OMAP_RESET_CLOCKS
784 .disable_unused = omap1_clk_disable_unused,
785 #endif
786 .recalc_rate = omap1_clk_recalc_rate,
787 .round_rate = omap1_clk_round_rate,
788 .set_rate = omap1_clk_set_rate,
789 .init = omap1_clk_init_op,
793 * OMAP specific clock functions shared between omap1 and omap2
796 /* Used for clocks that always have same value as the parent clock */
797 unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate)
799 return p_rate;
803 * Used for clocks that have the same value as the parent clock,
804 * divided by some factor
806 unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate)
808 WARN_ON(!clk->fixed_div);
810 return p_rate / clk->fixed_div;
813 /* Propagate rate to children */
814 void propagate_rate(struct omap1_clk *tclk)
816 struct clk *clkp;
818 /* depend on CCF ability to recalculate new rates across whole clock subtree */
819 if (WARN_ON(!(clk_hw_get_flags(&tclk->hw) & CLK_GET_RATE_NOCACHE)))
820 return;
822 clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw));
823 if (WARN_ON(!clkp))
824 return;
826 clk_get_rate(clkp);
827 clk_put(clkp);
830 const struct clk_ops omap1_clk_null_ops = {
834 * Dummy clock
836 * Used for clock aliases that are needed on some OMAPs, but not others
838 struct omap1_clk dummy_ck __refdata = {
839 .hw.init = CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0),