1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/arch/arm/mach-omap1/clock.c 4 * 5 * Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation 6 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> 7 * 8 * Modified to use omap shared clock framework by 9 * Tony Lindgren <tony@atomide.com> 10 */ 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> 22 23 #include <asm/mach-types.h> 24 25 #include "hardware.h" 26 #include "soc.h" 27 #include "iomap.h" 28 #include "clock.h" 29 #include "opp.h" 30 #include "sram.h" 31 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; 35 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); 42 43 /* 44 * Omap1 specific clock functions 45 */ 46 47 unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate) 48 { 49 unsigned int val = __raw_readl(clk->enable_reg); 50 return val & 1 << clk->enable_bit ? 48000000 : 12000000; 51 } 52 53 unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate) 54 { 55 u32 div = omap_readl(MOD_CONF_CTRL_1); 56 57 div = (div >> 17) & 0x7; 58 div++; 59 60 return p_rate / div; 61 } 62 63 static void omap1_clk_allow_idle(struct omap1_clk *clk) 64 { 65 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; 66 67 if (!(clk->flags & CLOCK_IDLE_CONTROL)) 68 return; 69 70 if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count)) 71 arm_idlect1_mask |= 1 << iclk->idlect_shift; 72 } 73 74 static void omap1_clk_deny_idle(struct omap1_clk *clk) 75 { 76 struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk; 77 78 if (!(clk->flags & CLOCK_IDLE_CONTROL)) 79 return; 80 81 if (iclk->no_idle_count++ == 0) 82 arm_idlect1_mask &= ~(1 << iclk->idlect_shift); 83 } 84 85 static __u16 verify_ckctl_value(__u16 newval) 86 { 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 93 * 94 * In addition following rules are enforced: 95 * LCD_CK <= TC_CK 96 * ARMPER_CK <= TC_CK 97 * 98 * However, maximum frequencies are not checked for! 99 */ 100 __u8 per_exp; 101 __u8 lcd_exp; 102 __u8 arm_exp; 103 __u8 dsp_exp; 104 __u8 tc_exp; 105 __u8 dspmmu_exp; 106 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; 113 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; 126 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; 134 135 return newval; 136 } 137 138 static int calc_dsor_exp(unsigned long rate, unsigned long realrate) 139 { 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. 143 * 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 150 */ 151 unsigned dsor_exp; 152 153 if (unlikely(realrate == 0)) 154 return -EIO; 155 156 for (dsor_exp=0; dsor_exp<4; dsor_exp++) { 157 if (realrate <= rate) 158 break; 159 160 realrate /= 2; 161 } 162 163 return dsor_exp; 164 } 165 166 unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate) 167 { 168 /* Calculate divisor encoded as 2-bit exponent */ 169 int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); 170 171 /* update locally maintained rate, required by arm_ck for omap1_show_rates() */ 172 clk->rate = p_rate / dsor; 173 return clk->rate; 174 } 175 176 static int omap1_clk_is_enabled(struct clk_hw *hw) 177 { 178 struct omap1_clk *clk = to_omap1_clk(hw); 179 bool api_ck_was_enabled = true; 180 __u32 regval32; 181 int ret; 182 183 if (!clk->ops) /* no gate -- always enabled */ 184 return 1; 185 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; 191 } 192 193 if (clk->flags & ENABLE_REG_32BIT) 194 regval32 = __raw_readl(clk->enable_reg); 195 else 196 regval32 = __raw_readw(clk->enable_reg); 197 198 ret = regval32 & (1 << clk->enable_bit); 199 200 if (!api_ck_was_enabled) 201 api_ck_p->ops->disable(api_ck_p); 202 203 return ret; 204 } 205 206 207 unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate) 208 { 209 bool api_ck_was_enabled; 210 int dsor; 211 212 /* Calculate divisor encoded as 2-bit exponent 213 * 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(). 218 */ 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); 225 226 return p_rate / dsor; 227 } 228 229 /* MPU virtual clock functions */ 230 int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) 231 { 232 /* Find the highest supported frequency <= rate and switch to it */ 233 struct mpu_rate * ptr; 234 unsigned long ref_rate; 235 236 ref_rate = ck_ref_p->rate; 237 238 for (ptr = omap1_rate_table; ptr->rate; ptr++) { 239 if (!(ptr->flags & cpu_mask)) 240 continue; 241 242 if (ptr->xtal != ref_rate) 243 continue; 244 245 /* Can check only after xtal frequency check */ 246 if (ptr->rate <= rate) 247 break; 248 } 249 250 if (!ptr->rate) 251 return -EINVAL; 252 253 /* 254 * In most cases we should not need to reprogram DPLL. 255 * Reprogramming the DPLL is tricky, it must be done from SRAM. 256 */ 257 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); 258 259 /* XXX Do we need to recalculate the tree below DPLL1 at this point? */ 260 ck_dpll1_p->rate = ptr->pll_rate; 261 262 return 0; 263 } 264 265 int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) 266 { 267 int dsor_exp; 268 u16 regval; 269 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; 275 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); 281 282 return 0; 283 } 284 285 long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, 286 unsigned long *p_rate) 287 { 288 int dsor_exp = calc_dsor_exp(rate, *p_rate); 289 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); 295 } 296 297 int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) 298 { 299 unsigned long flags; 300 int dsor_exp; 301 u16 regval; 302 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; 308 309 /* protect ARM_CKCTL register from concurrent access via clk_enable/disable() */ 310 spin_lock_irqsave(&arm_ckctl_lock, flags); 311 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); 318 319 spin_unlock_irqrestore(&arm_ckctl_lock, flags); 320 321 return 0; 322 } 323 324 long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) 325 { 326 /* Find the highest supported frequency <= rate */ 327 struct mpu_rate * ptr; 328 long highest_rate; 329 unsigned long ref_rate; 330 331 ref_rate = ck_ref_p->rate; 332 333 highest_rate = -EINVAL; 334 335 for (ptr = omap1_rate_table; ptr->rate; ptr++) { 336 if (!(ptr->flags & cpu_mask)) 337 continue; 338 339 if (ptr->xtal != ref_rate) 340 continue; 341 342 highest_rate = ptr->rate; 343 344 /* Can check only after xtal frequency check */ 345 if (ptr->rate <= rate) 346 break; 347 } 348 349 return highest_rate; 350 } 351 352 static unsigned calc_ext_dsor(unsigned long rate) 353 { 354 unsigned dsor; 355 356 /* MCLK and BCLK divisor selection is not linear: 357 * freq = 96MHz / dsor 358 * 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. 364 */ 365 for (dsor = 2; dsor < 96; ++dsor) { 366 if ((dsor & 1) && dsor > 8) 367 continue; 368 if (rate >= 96000000 / dsor) 369 break; 370 } 371 return dsor; 372 } 373 374 /* XXX Only needed on 1510 */ 375 long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) 376 { 377 return rate > 24000000 ? 48000000 : 12000000; 378 } 379 380 int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) 381 { 382 unsigned long flags; 383 unsigned int val; 384 385 if (rate == 12000000) 386 val = 0; 387 else if (rate == 48000000) 388 val = 1 << clk->enable_bit; 389 else 390 return -EINVAL; 391 392 /* protect MOD_CONF_CTRL_0 register from concurrent access via clk_enable/disable() */ 393 spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags); 394 395 val |= __raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit); 396 __raw_writel(val, clk->enable_reg); 397 398 spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags); 399 400 clk->rate = rate; 401 402 return 0; 403 } 404 405 /* External clock (MCLK & BCLK) functions */ 406 int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) 407 { 408 unsigned long flags; 409 unsigned dsor; 410 __u16 ratio_bits; 411 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; 418 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); 421 422 ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd; 423 __raw_writew(ratio_bits, clk->enable_reg); 424 425 spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags); 426 427 return 0; 428 } 429 430 static int calc_div_sossi(unsigned long rate, unsigned long p_rate) 431 { 432 int div; 433 434 /* Round towards slower frequency */ 435 div = (p_rate + rate - 1) / rate; 436 437 return --div; 438 } 439 440 long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) 441 { 442 int div; 443 444 div = calc_div_sossi(rate, *p_rate); 445 if (div < 0) 446 div = 0; 447 else if (div > 7) 448 div = 7; 449 450 return *p_rate / (div + 1); 451 } 452 453 int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate) 454 { 455 unsigned long flags; 456 u32 l; 457 int div; 458 459 div = calc_div_sossi(rate, p_rate); 460 if (div < 0 || div > 7) 461 return -EINVAL; 462 463 /* protect MOD_CONF_CTRL_1 register from concurrent access via clk_enable/disable() */ 464 spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags); 465 466 l = omap_readl(MOD_CONF_CTRL_1); 467 l &= ~(7 << 17); 468 l |= div << 17; 469 omap_writel(l, MOD_CONF_CTRL_1); 470 471 clk->rate = p_rate / (div + 1); 472 473 spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags); 474 475 return 0; 476 } 477 478 long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate) 479 { 480 return 96000000 / calc_ext_dsor(rate); 481 } 482 483 int omap1_init_ext_clk(struct omap1_clk *clk) 484 { 485 unsigned dsor; 486 __u16 ratio_bits; 487 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); 491 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; 497 498 clk-> rate = 96000000 / dsor; 499 500 return 0; 501 } 502 503 static int omap1_clk_enable(struct clk_hw *hw) 504 { 505 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw)); 506 int ret = 0; 507 508 if (parent && clk->flags & CLOCK_NO_IDLE_PARENT) 509 omap1_clk_deny_idle(parent); 510 511 if (clk->ops && !(WARN_ON(!clk->ops->enable))) 512 ret = clk->ops->enable(clk); 513 514 return ret; 515 } 516 517 static void omap1_clk_disable(struct clk_hw *hw) 518 { 519 struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw)); 520 521 if (clk->ops && !(WARN_ON(!clk->ops->disable))) 522 clk->ops->disable(clk); 523 524 if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT) 525 omap1_clk_allow_idle(parent); 526 } 527 528 static int omap1_clk_enable_generic(struct omap1_clk *clk) 529 { 530 unsigned long flags; 531 __u16 regval16; 532 __u32 regval32; 533 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; 538 } 539 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); 551 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); 560 } 561 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); 572 573 return 0; 574 } 575 576 static void omap1_clk_disable_generic(struct omap1_clk *clk) 577 { 578 unsigned long flags; 579 __u16 regval16; 580 __u32 regval32; 581 582 if (clk->enable_reg == NULL) 583 return; 584 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); 596 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); 605 } 606 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); 617 } 618 619 const struct clkops clkops_generic = { 620 .enable = omap1_clk_enable_generic, 621 .disable = omap1_clk_disable_generic, 622 }; 623 624 static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk) 625 { 626 bool api_ck_was_enabled; 627 int retval = 0; 628 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); 632 633 if (!retval) { 634 retval = omap1_clk_enable_generic(clk); 635 636 if (!api_ck_was_enabled) 637 api_ck_p->ops->disable(api_ck_p); 638 } 639 640 return retval; 641 } 642 643 static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk) 644 { 645 bool api_ck_was_enabled; 646 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; 651 652 omap1_clk_disable_generic(clk); 653 654 if (!api_ck_was_enabled) 655 api_ck_p->ops->disable(api_ck_p); 656 } 657 658 const struct clkops clkops_dspck = { 659 .enable = omap1_clk_enable_dsp_domain, 660 .disable = omap1_clk_disable_dsp_domain, 661 }; 662 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) 665 { 666 int ret; 667 struct uart_clk *uclk; 668 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); 675 } 676 677 return ret; 678 } 679 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) 682 { 683 struct uart_clk *uclk; 684 685 /* Set force idle acknowledgement mode */ 686 uclk = (struct uart_clk *)clk; 687 omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); 688 689 omap1_clk_disable_generic(clk); 690 } 691 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, 696 }; 697 698 static unsigned long omap1_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate) 699 { 700 struct omap1_clk *clk = to_omap1_clk(hw); 701 702 if (clk->recalc) 703 return clk->recalc(clk, p_rate); 704 705 return clk->rate; 706 } 707 708 static long omap1_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *p_rate) 709 { 710 struct omap1_clk *clk = to_omap1_clk(hw); 711 712 if (clk->round_rate != NULL) 713 return clk->round_rate(clk, rate, p_rate); 714 715 return omap1_clk_recalc_rate(hw, *p_rate); 716 } 717 718 static int omap1_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate) 719 { 720 struct omap1_clk *clk = to_omap1_clk(hw); 721 int ret = -EINVAL; 722 723 if (clk->set_rate) 724 ret = clk->set_rate(clk, rate, p_rate); 725 return ret; 726 } 727 728 /* 729 * Omap1 clock reset and init functions 730 */ 731 732 static int omap1_clk_init_op(struct clk_hw *hw) 733 { 734 struct omap1_clk *clk = to_omap1_clk(hw); 735 736 if (clk->init) 737 return clk->init(clk); 738 739 return 0; 740 } 741 742 #ifdef CONFIG_OMAP_RESET_CLOCKS 743 744 static void omap1_clk_disable_unused(struct clk_hw *hw) 745 { 746 struct omap1_clk *clk = to_omap1_clk(hw); 747 const char *name = clk_hw_get_name(hw); 748 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; 754 } 755 756 pr_info("Disabling unused clock \"%s\"... ", name); 757 omap1_clk_disable(hw); 758 printk(" done\n"); 759 } 760 761 #endif 762 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 770 }; 771 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, 777 }; 778 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, 790 }; 791 792 /* 793 * OMAP specific clock functions shared between omap1 and omap2 794 */ 795 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) 798 { 799 return p_rate; 800 } 801 802 /* 803 * Used for clocks that have the same value as the parent clock, 804 * divided by some factor 805 */ 806 unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate) 807 { 808 WARN_ON(!clk->fixed_div); 809 810 return p_rate / clk->fixed_div; 811 } 812 813 /* Propagate rate to children */ 814 void propagate_rate(struct omap1_clk *tclk) 815 { 816 struct clk *clkp; 817 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; 821 822 clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw)); 823 if (WARN_ON(!clkp)) 824 return; 825 826 clk_get_rate(clkp); 827 clk_put(clkp); 828 } 829 830 const struct clk_ops omap1_clk_null_ops = { 831 }; 832 833 /* 834 * Dummy clock 835 * 836 * Used for clock aliases that are needed on some OMAPs, but not others 837 */ 838 struct omap1_clk dummy_ck __refdata = { 839 .hw.init = CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0), 840 }; 841
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.