Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/mach-omap1/clock.c
0004  *
0005  *  Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation
0006  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
0007  *
0008  *  Modified to use omap shared clock framework by
0009  *  Tony Lindgren <tony@atomide.com>
0010  */
0011 #include <linux/kernel.h>
0012 #include <linux/export.h>
0013 #include <linux/list.h>
0014 #include <linux/errno.h>
0015 #include <linux/err.h>
0016 #include <linux/io.h>
0017 #include <linux/clk.h>
0018 #include <linux/clkdev.h>
0019 #include <linux/clk-provider.h>
0020 #include <linux/soc/ti/omap1-io.h>
0021 #include <linux/spinlock.h>
0022 
0023 #include <asm/mach-types.h>
0024 
0025 #include "hardware.h"
0026 #include "soc.h"
0027 #include "iomap.h"
0028 #include "clock.h"
0029 #include "opp.h"
0030 #include "sram.h"
0031 
0032 __u32 arm_idlect1_mask;
0033 /* provide direct internal access (not via clk API) to some clocks */
0034 struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
0035 
0036 /* protect registeres shared among clk_enable/disable() and clk_set_rate() operations */
0037 static DEFINE_SPINLOCK(arm_ckctl_lock);
0038 static DEFINE_SPINLOCK(arm_idlect2_lock);
0039 static DEFINE_SPINLOCK(mod_conf_ctrl_0_lock);
0040 static DEFINE_SPINLOCK(mod_conf_ctrl_1_lock);
0041 static DEFINE_SPINLOCK(swd_clk_div_ctrl_sel_lock);
0042 
0043 /*
0044  * Omap1 specific clock functions
0045  */
0046 
0047 unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate)
0048 {
0049     unsigned int val = __raw_readl(clk->enable_reg);
0050     return val & 1 << clk->enable_bit ? 48000000 : 12000000;
0051 }
0052 
0053 unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate)
0054 {
0055     u32 div = omap_readl(MOD_CONF_CTRL_1);
0056 
0057     div = (div >> 17) & 0x7;
0058     div++;
0059 
0060     return p_rate / div;
0061 }
0062 
0063 static void omap1_clk_allow_idle(struct omap1_clk *clk)
0064 {
0065     struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
0066 
0067     if (!(clk->flags & CLOCK_IDLE_CONTROL))
0068         return;
0069 
0070     if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count))
0071         arm_idlect1_mask |= 1 << iclk->idlect_shift;
0072 }
0073 
0074 static void omap1_clk_deny_idle(struct omap1_clk *clk)
0075 {
0076     struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
0077 
0078     if (!(clk->flags & CLOCK_IDLE_CONTROL))
0079         return;
0080 
0081     if (iclk->no_idle_count++ == 0)
0082         arm_idlect1_mask &= ~(1 << iclk->idlect_shift);
0083 }
0084 
0085 static __u16 verify_ckctl_value(__u16 newval)
0086 {
0087     /* This function checks for following limitations set
0088      * by the hardware (all conditions must be true):
0089      * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
0090      * ARM_CK >= TC_CK
0091      * DSP_CK >= TC_CK
0092      * DSPMMU_CK >= TC_CK
0093      *
0094      * In addition following rules are enforced:
0095      * LCD_CK <= TC_CK
0096      * ARMPER_CK <= TC_CK
0097      *
0098      * However, maximum frequencies are not checked for!
0099      */
0100     __u8 per_exp;
0101     __u8 lcd_exp;
0102     __u8 arm_exp;
0103     __u8 dsp_exp;
0104     __u8 tc_exp;
0105     __u8 dspmmu_exp;
0106 
0107     per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
0108     lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
0109     arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
0110     dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
0111     tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
0112     dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
0113 
0114     if (dspmmu_exp < dsp_exp)
0115         dspmmu_exp = dsp_exp;
0116     if (dspmmu_exp > dsp_exp+1)
0117         dspmmu_exp = dsp_exp+1;
0118     if (tc_exp < arm_exp)
0119         tc_exp = arm_exp;
0120     if (tc_exp < dspmmu_exp)
0121         tc_exp = dspmmu_exp;
0122     if (tc_exp > lcd_exp)
0123         lcd_exp = tc_exp;
0124     if (tc_exp > per_exp)
0125         per_exp = tc_exp;
0126 
0127     newval &= 0xf000;
0128     newval |= per_exp << CKCTL_PERDIV_OFFSET;
0129     newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
0130     newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
0131     newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
0132     newval |= tc_exp << CKCTL_TCDIV_OFFSET;
0133     newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
0134 
0135     return newval;
0136 }
0137 
0138 static int calc_dsor_exp(unsigned long rate, unsigned long realrate)
0139 {
0140     /* Note: If target frequency is too low, this function will return 4,
0141      * which is invalid value. Caller must check for this value and act
0142      * accordingly.
0143      *
0144      * Note: This function does not check for following limitations set
0145      * by the hardware (all conditions must be true):
0146      * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
0147      * ARM_CK >= TC_CK
0148      * DSP_CK >= TC_CK
0149      * DSPMMU_CK >= TC_CK
0150      */
0151     unsigned  dsor_exp;
0152 
0153     if (unlikely(realrate == 0))
0154         return -EIO;
0155 
0156     for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
0157         if (realrate <= rate)
0158             break;
0159 
0160         realrate /= 2;
0161     }
0162 
0163     return dsor_exp;
0164 }
0165 
0166 unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate)
0167 {
0168     /* Calculate divisor encoded as 2-bit exponent */
0169     int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
0170 
0171     /* update locally maintained rate, required by arm_ck for omap1_show_rates() */
0172     clk->rate = p_rate / dsor;
0173     return clk->rate;
0174 }
0175 
0176 static int omap1_clk_is_enabled(struct clk_hw *hw)
0177 {
0178     struct omap1_clk *clk = to_omap1_clk(hw);
0179     bool api_ck_was_enabled = true;
0180     __u32 regval32;
0181     int ret;
0182 
0183     if (!clk->ops)  /* no gate -- always enabled */
0184         return 1;
0185 
0186     if (clk->ops == &clkops_dspck) {
0187         api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
0188         if (!api_ck_was_enabled)
0189             if (api_ck_p->ops->enable(api_ck_p) < 0)
0190                 return 0;
0191     }
0192 
0193     if (clk->flags & ENABLE_REG_32BIT)
0194         regval32 = __raw_readl(clk->enable_reg);
0195     else
0196         regval32 = __raw_readw(clk->enable_reg);
0197 
0198     ret = regval32 & (1 << clk->enable_bit);
0199 
0200     if (!api_ck_was_enabled)
0201         api_ck_p->ops->disable(api_ck_p);
0202 
0203     return ret;
0204 }
0205 
0206 
0207 unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate)
0208 {
0209     bool api_ck_was_enabled;
0210     int dsor;
0211 
0212     /* Calculate divisor encoded as 2-bit exponent
0213      *
0214      * The clock control bits are in DSP domain,
0215      * so api_ck is needed for access.
0216      * Note that DSP_CKCTL virt addr = phys addr, so
0217      * we must use __raw_readw() instead of omap_readw().
0218      */
0219     api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
0220     if (!api_ck_was_enabled)
0221         api_ck_p->ops->enable(api_ck_p);
0222     dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
0223     if (!api_ck_was_enabled)
0224         api_ck_p->ops->disable(api_ck_p);
0225 
0226     return p_rate / dsor;
0227 }
0228 
0229 /* MPU virtual clock functions */
0230 int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0231 {
0232     /* Find the highest supported frequency <= rate and switch to it */
0233     struct mpu_rate * ptr;
0234     unsigned long ref_rate;
0235 
0236     ref_rate = ck_ref_p->rate;
0237 
0238     for (ptr = omap1_rate_table; ptr->rate; ptr++) {
0239         if (!(ptr->flags & cpu_mask))
0240             continue;
0241 
0242         if (ptr->xtal != ref_rate)
0243             continue;
0244 
0245         /* Can check only after xtal frequency check */
0246         if (ptr->rate <= rate)
0247             break;
0248     }
0249 
0250     if (!ptr->rate)
0251         return -EINVAL;
0252 
0253     /*
0254      * In most cases we should not need to reprogram DPLL.
0255      * Reprogramming the DPLL is tricky, it must be done from SRAM.
0256      */
0257     omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
0258 
0259     /* XXX Do we need to recalculate the tree below DPLL1 at this point? */
0260     ck_dpll1_p->rate = ptr->pll_rate;
0261 
0262     return 0;
0263 }
0264 
0265 int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0266 {
0267     int dsor_exp;
0268     u16 regval;
0269 
0270     dsor_exp = calc_dsor_exp(rate, p_rate);
0271     if (dsor_exp > 3)
0272         dsor_exp = -EINVAL;
0273     if (dsor_exp < 0)
0274         return dsor_exp;
0275 
0276     regval = __raw_readw(DSP_CKCTL);
0277     regval &= ~(3 << clk->rate_offset);
0278     regval |= dsor_exp << clk->rate_offset;
0279     __raw_writew(regval, DSP_CKCTL);
0280     clk->rate = p_rate / (1 << dsor_exp);
0281 
0282     return 0;
0283 }
0284 
0285 long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate,
0286                     unsigned long *p_rate)
0287 {
0288     int dsor_exp = calc_dsor_exp(rate, *p_rate);
0289 
0290     if (dsor_exp < 0)
0291         return dsor_exp;
0292     if (dsor_exp > 3)
0293         dsor_exp = 3;
0294     return *p_rate / (1 << dsor_exp);
0295 }
0296 
0297 int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0298 {
0299     unsigned long flags;
0300     int dsor_exp;
0301     u16 regval;
0302 
0303     dsor_exp = calc_dsor_exp(rate, p_rate);
0304     if (dsor_exp > 3)
0305         dsor_exp = -EINVAL;
0306     if (dsor_exp < 0)
0307         return dsor_exp;
0308 
0309     /* protect ARM_CKCTL register from concurrent access via clk_enable/disable() */
0310     spin_lock_irqsave(&arm_ckctl_lock, flags);
0311 
0312     regval = omap_readw(ARM_CKCTL);
0313     regval &= ~(3 << clk->rate_offset);
0314     regval |= dsor_exp << clk->rate_offset;
0315     regval = verify_ckctl_value(regval);
0316     omap_writew(regval, ARM_CKCTL);
0317     clk->rate = p_rate / (1 << dsor_exp);
0318 
0319     spin_unlock_irqrestore(&arm_ckctl_lock, flags);
0320 
0321     return 0;
0322 }
0323 
0324 long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
0325 {
0326     /* Find the highest supported frequency <= rate */
0327     struct mpu_rate * ptr;
0328     long highest_rate;
0329     unsigned long ref_rate;
0330 
0331     ref_rate = ck_ref_p->rate;
0332 
0333     highest_rate = -EINVAL;
0334 
0335     for (ptr = omap1_rate_table; ptr->rate; ptr++) {
0336         if (!(ptr->flags & cpu_mask))
0337             continue;
0338 
0339         if (ptr->xtal != ref_rate)
0340             continue;
0341 
0342         highest_rate = ptr->rate;
0343 
0344         /* Can check only after xtal frequency check */
0345         if (ptr->rate <= rate)
0346             break;
0347     }
0348 
0349     return highest_rate;
0350 }
0351 
0352 static unsigned calc_ext_dsor(unsigned long rate)
0353 {
0354     unsigned dsor;
0355 
0356     /* MCLK and BCLK divisor selection is not linear:
0357      * freq = 96MHz / dsor
0358      *
0359      * RATIO_SEL range: dsor <-> RATIO_SEL
0360      * 0..6: (RATIO_SEL+2) <-> (dsor-2)
0361      * 6..48:  (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
0362      * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
0363      * can not be used.
0364      */
0365     for (dsor = 2; dsor < 96; ++dsor) {
0366         if ((dsor & 1) && dsor > 8)
0367             continue;
0368         if (rate >= 96000000 / dsor)
0369             break;
0370     }
0371     return dsor;
0372 }
0373 
0374 /* XXX Only needed on 1510 */
0375 long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
0376 {
0377     return rate > 24000000 ? 48000000 : 12000000;
0378 }
0379 
0380 int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0381 {
0382     unsigned long flags;
0383     unsigned int val;
0384 
0385     if (rate == 12000000)
0386         val = 0;
0387     else if (rate == 48000000)
0388         val = 1 << clk->enable_bit;
0389     else
0390         return -EINVAL;
0391 
0392     /* protect MOD_CONF_CTRL_0 register from concurrent access via clk_enable/disable() */
0393     spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
0394 
0395     val |= __raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit);
0396     __raw_writel(val, clk->enable_reg);
0397 
0398     spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
0399 
0400     clk->rate = rate;
0401 
0402     return 0;
0403 }
0404 
0405 /* External clock (MCLK & BCLK) functions */
0406 int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0407 {
0408     unsigned long flags;
0409     unsigned dsor;
0410     __u16 ratio_bits;
0411 
0412     dsor = calc_ext_dsor(rate);
0413     clk->rate = 96000000 / dsor;
0414     if (dsor > 8)
0415         ratio_bits = ((dsor - 8) / 2 + 6) << 2;
0416     else
0417         ratio_bits = (dsor - 2) << 2;
0418 
0419     /* protect SWD_CLK_DIV_CTRL_SEL register from concurrent access via clk_enable/disable() */
0420     spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
0421 
0422     ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
0423     __raw_writew(ratio_bits, clk->enable_reg);
0424 
0425     spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
0426 
0427     return 0;
0428 }
0429 
0430 static int calc_div_sossi(unsigned long rate, unsigned long p_rate)
0431 {
0432     int div;
0433 
0434     /* Round towards slower frequency */
0435     div = (p_rate + rate - 1) / rate;
0436 
0437     return --div;
0438 }
0439 
0440 long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
0441 {
0442     int div;
0443 
0444     div = calc_div_sossi(rate, *p_rate);
0445     if (div < 0)
0446         div = 0;
0447     else if (div > 7)
0448         div = 7;
0449 
0450     return *p_rate / (div + 1);
0451 }
0452 
0453 int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0454 {
0455     unsigned long flags;
0456     u32 l;
0457     int div;
0458 
0459     div = calc_div_sossi(rate, p_rate);
0460     if (div < 0 || div > 7)
0461         return -EINVAL;
0462 
0463     /* protect MOD_CONF_CTRL_1 register from concurrent access via clk_enable/disable() */
0464     spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
0465 
0466     l = omap_readl(MOD_CONF_CTRL_1);
0467     l &= ~(7 << 17);
0468     l |= div << 17;
0469     omap_writel(l, MOD_CONF_CTRL_1);
0470 
0471     clk->rate = p_rate / (div + 1);
0472 
0473     spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
0474 
0475     return 0;
0476 }
0477 
0478 long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
0479 {
0480     return 96000000 / calc_ext_dsor(rate);
0481 }
0482 
0483 int omap1_init_ext_clk(struct omap1_clk *clk)
0484 {
0485     unsigned dsor;
0486     __u16 ratio_bits;
0487 
0488     /* Determine current rate and ensure clock is based on 96MHz APLL */
0489     ratio_bits = __raw_readw(clk->enable_reg) & ~1;
0490     __raw_writew(ratio_bits, clk->enable_reg);
0491 
0492     ratio_bits = (ratio_bits & 0xfc) >> 2;
0493     if (ratio_bits > 6)
0494         dsor = (ratio_bits - 6) * 2 + 8;
0495     else
0496         dsor = ratio_bits + 2;
0497 
0498     clk-> rate = 96000000 / dsor;
0499 
0500     return 0;
0501 }
0502 
0503 static int omap1_clk_enable(struct clk_hw *hw)
0504 {
0505     struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
0506     int ret = 0;
0507 
0508     if (parent && clk->flags & CLOCK_NO_IDLE_PARENT)
0509         omap1_clk_deny_idle(parent);
0510 
0511     if (clk->ops && !(WARN_ON(!clk->ops->enable)))
0512         ret = clk->ops->enable(clk);
0513 
0514     return ret;
0515 }
0516 
0517 static void omap1_clk_disable(struct clk_hw *hw)
0518 {
0519     struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
0520 
0521     if (clk->ops && !(WARN_ON(!clk->ops->disable)))
0522         clk->ops->disable(clk);
0523 
0524     if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT)
0525         omap1_clk_allow_idle(parent);
0526 }
0527 
0528 static int omap1_clk_enable_generic(struct omap1_clk *clk)
0529 {
0530     unsigned long flags;
0531     __u16 regval16;
0532     __u32 regval32;
0533 
0534     if (unlikely(clk->enable_reg == NULL)) {
0535         printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
0536                clk_hw_get_name(&clk->hw));
0537         return -EINVAL;
0538     }
0539 
0540     /* protect clk->enable_reg from concurrent access via clk_set_rate() */
0541     if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
0542         spin_lock_irqsave(&arm_ckctl_lock, flags);
0543     else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
0544         spin_lock_irqsave(&arm_idlect2_lock, flags);
0545     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
0546         spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
0547     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
0548         spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
0549     else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
0550         spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
0551 
0552     if (clk->flags & ENABLE_REG_32BIT) {
0553         regval32 = __raw_readl(clk->enable_reg);
0554         regval32 |= (1 << clk->enable_bit);
0555         __raw_writel(regval32, clk->enable_reg);
0556     } else {
0557         regval16 = __raw_readw(clk->enable_reg);
0558         regval16 |= (1 << clk->enable_bit);
0559         __raw_writew(regval16, clk->enable_reg);
0560     }
0561 
0562     if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
0563         spin_unlock_irqrestore(&arm_ckctl_lock, flags);
0564     else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
0565         spin_unlock_irqrestore(&arm_idlect2_lock, flags);
0566     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
0567         spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
0568     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
0569         spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
0570     else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
0571         spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
0572 
0573     return 0;
0574 }
0575 
0576 static void omap1_clk_disable_generic(struct omap1_clk *clk)
0577 {
0578     unsigned long flags;
0579     __u16 regval16;
0580     __u32 regval32;
0581 
0582     if (clk->enable_reg == NULL)
0583         return;
0584 
0585     /* protect clk->enable_reg from concurrent access via clk_set_rate() */
0586     if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
0587         spin_lock_irqsave(&arm_ckctl_lock, flags);
0588     else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
0589         spin_lock_irqsave(&arm_idlect2_lock, flags);
0590     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
0591         spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
0592     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
0593         spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
0594     else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
0595         spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
0596 
0597     if (clk->flags & ENABLE_REG_32BIT) {
0598         regval32 = __raw_readl(clk->enable_reg);
0599         regval32 &= ~(1 << clk->enable_bit);
0600         __raw_writel(regval32, clk->enable_reg);
0601     } else {
0602         regval16 = __raw_readw(clk->enable_reg);
0603         regval16 &= ~(1 << clk->enable_bit);
0604         __raw_writew(regval16, clk->enable_reg);
0605     }
0606 
0607     if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
0608         spin_unlock_irqrestore(&arm_ckctl_lock, flags);
0609     else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
0610         spin_unlock_irqrestore(&arm_idlect2_lock, flags);
0611     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
0612         spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
0613     else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
0614         spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
0615     else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
0616         spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
0617 }
0618 
0619 const struct clkops clkops_generic = {
0620     .enable     = omap1_clk_enable_generic,
0621     .disable    = omap1_clk_disable_generic,
0622 };
0623 
0624 static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk)
0625 {
0626     bool api_ck_was_enabled;
0627     int retval = 0;
0628 
0629     api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
0630     if (!api_ck_was_enabled)
0631         retval = api_ck_p->ops->enable(api_ck_p);
0632 
0633     if (!retval) {
0634         retval = omap1_clk_enable_generic(clk);
0635 
0636         if (!api_ck_was_enabled)
0637             api_ck_p->ops->disable(api_ck_p);
0638     }
0639 
0640     return retval;
0641 }
0642 
0643 static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk)
0644 {
0645     bool api_ck_was_enabled;
0646 
0647     api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
0648     if (!api_ck_was_enabled)
0649         if (api_ck_p->ops->enable(api_ck_p) < 0)
0650             return;
0651 
0652     omap1_clk_disable_generic(clk);
0653 
0654     if (!api_ck_was_enabled)
0655         api_ck_p->ops->disable(api_ck_p);
0656 }
0657 
0658 const struct clkops clkops_dspck = {
0659     .enable     = omap1_clk_enable_dsp_domain,
0660     .disable    = omap1_clk_disable_dsp_domain,
0661 };
0662 
0663 /* XXX SYSC register handling does not belong in the clock framework */
0664 static int omap1_clk_enable_uart_functional_16xx(struct omap1_clk *clk)
0665 {
0666     int ret;
0667     struct uart_clk *uclk;
0668 
0669     ret = omap1_clk_enable_generic(clk);
0670     if (ret == 0) {
0671         /* Set smart idle acknowledgement mode */
0672         uclk = (struct uart_clk *)clk;
0673         omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8,
0674                 uclk->sysc_addr);
0675     }
0676 
0677     return ret;
0678 }
0679 
0680 /* XXX SYSC register handling does not belong in the clock framework */
0681 static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk)
0682 {
0683     struct uart_clk *uclk;
0684 
0685     /* Set force idle acknowledgement mode */
0686     uclk = (struct uart_clk *)clk;
0687     omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
0688 
0689     omap1_clk_disable_generic(clk);
0690 }
0691 
0692 /* XXX SYSC register handling does not belong in the clock framework */
0693 const struct clkops clkops_uart_16xx = {
0694     .enable     = omap1_clk_enable_uart_functional_16xx,
0695     .disable    = omap1_clk_disable_uart_functional_16xx,
0696 };
0697 
0698 static unsigned long omap1_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
0699 {
0700     struct omap1_clk *clk = to_omap1_clk(hw);
0701 
0702     if (clk->recalc)
0703         return clk->recalc(clk, p_rate);
0704 
0705     return clk->rate;
0706 }
0707 
0708 static long omap1_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *p_rate)
0709 {
0710     struct omap1_clk *clk = to_omap1_clk(hw);
0711 
0712     if (clk->round_rate != NULL)
0713         return clk->round_rate(clk, rate, p_rate);
0714 
0715     return omap1_clk_recalc_rate(hw, *p_rate);
0716 }
0717 
0718 static int omap1_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
0719 {
0720     struct omap1_clk *clk = to_omap1_clk(hw);
0721     int  ret = -EINVAL;
0722 
0723     if (clk->set_rate)
0724         ret = clk->set_rate(clk, rate, p_rate);
0725     return ret;
0726 }
0727 
0728 /*
0729  * Omap1 clock reset and init functions
0730  */
0731 
0732 static int omap1_clk_init_op(struct clk_hw *hw)
0733 {
0734     struct omap1_clk *clk = to_omap1_clk(hw);
0735 
0736     if (clk->init)
0737         return clk->init(clk);
0738 
0739     return 0;
0740 }
0741 
0742 #ifdef CONFIG_OMAP_RESET_CLOCKS
0743 
0744 static void omap1_clk_disable_unused(struct clk_hw *hw)
0745 {
0746     struct omap1_clk *clk = to_omap1_clk(hw);
0747     const char *name = clk_hw_get_name(hw);
0748 
0749     /* Clocks in the DSP domain need api_ck. Just assume bootloader
0750      * has not enabled any DSP clocks */
0751     if (clk->enable_reg == DSP_IDLECT2) {
0752         pr_info("Skipping reset check for DSP domain clock \"%s\"\n", name);
0753         return;
0754     }
0755 
0756     pr_info("Disabling unused clock \"%s\"... ", name);
0757     omap1_clk_disable(hw);
0758     printk(" done\n");
0759 }
0760 
0761 #endif
0762 
0763 const struct clk_ops omap1_clk_gate_ops = {
0764     .enable     = omap1_clk_enable,
0765     .disable    = omap1_clk_disable,
0766     .is_enabled = omap1_clk_is_enabled,
0767 #ifdef CONFIG_OMAP_RESET_CLOCKS
0768     .disable_unused = omap1_clk_disable_unused,
0769 #endif
0770 };
0771 
0772 const struct clk_ops omap1_clk_rate_ops = {
0773     .recalc_rate    = omap1_clk_recalc_rate,
0774     .round_rate = omap1_clk_round_rate,
0775     .set_rate   = omap1_clk_set_rate,
0776     .init       = omap1_clk_init_op,
0777 };
0778 
0779 const struct clk_ops omap1_clk_full_ops = {
0780     .enable     = omap1_clk_enable,
0781     .disable    = omap1_clk_disable,
0782     .is_enabled = omap1_clk_is_enabled,
0783 #ifdef CONFIG_OMAP_RESET_CLOCKS
0784     .disable_unused = omap1_clk_disable_unused,
0785 #endif
0786     .recalc_rate    = omap1_clk_recalc_rate,
0787     .round_rate = omap1_clk_round_rate,
0788     .set_rate   = omap1_clk_set_rate,
0789     .init       = omap1_clk_init_op,
0790 };
0791 
0792 /*
0793  * OMAP specific clock functions shared between omap1 and omap2
0794  */
0795 
0796 /* Used for clocks that always have same value as the parent clock */
0797 unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate)
0798 {
0799     return p_rate;
0800 }
0801 
0802 /*
0803  * Used for clocks that have the same value as the parent clock,
0804  * divided by some factor
0805  */
0806 unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate)
0807 {
0808     WARN_ON(!clk->fixed_div);
0809 
0810     return p_rate / clk->fixed_div;
0811 }
0812 
0813 /* Propagate rate to children */
0814 void propagate_rate(struct omap1_clk *tclk)
0815 {
0816     struct clk *clkp;
0817 
0818     /* depend on CCF ability to recalculate new rates across whole clock subtree */
0819     if (WARN_ON(!(clk_hw_get_flags(&tclk->hw) & CLK_GET_RATE_NOCACHE)))
0820         return;
0821 
0822     clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw));
0823     if (WARN_ON(!clkp))
0824         return;
0825 
0826     clk_get_rate(clkp);
0827     clk_put(clkp);
0828 }
0829 
0830 const struct clk_ops omap1_clk_null_ops = {
0831 };
0832 
0833 /*
0834  * Dummy clock
0835  *
0836  * Used for clock aliases that are needed on some OMAPs, but not others
0837  */
0838 struct omap1_clk dummy_ck __refdata = {
0839     .hw.init    = CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0),
0840 };