0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0034 struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
0035
0036
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
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
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
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
0141
0142
0143
0144
0145
0146
0147
0148
0149
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
0169 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
0170
0171
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)
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
0213
0214
0215
0216
0217
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
0230 int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
0231 {
0232
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
0246 if (ptr->rate <= rate)
0247 break;
0248 }
0249
0250 if (!ptr->rate)
0251 return -EINVAL;
0252
0253
0254
0255
0256
0257 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
0258
0259
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
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
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
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
0357
0358
0359
0360
0361
0362
0363
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
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
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
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
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
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
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
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
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
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
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
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
0681 static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk)
0682 {
0683 struct uart_clk *uclk;
0684
0685
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
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
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
0750
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
0794
0795
0796
0797 unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate)
0798 {
0799 return p_rate;
0800 }
0801
0802
0803
0804
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
0814 void propagate_rate(struct omap1_clk *tclk)
0815 {
0816 struct clk *clkp;
0817
0818
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
0835
0836
0837
0838 struct omap1_clk dummy_ck __refdata = {
0839 .hw.init = CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0),
0840 };