1/* 2 * OMAP3/4 - specific DPLL control functions 3 * 4 * Copyright (C) 2009-2010 Texas Instruments, Inc. 5 * Copyright (C) 2009-2010 Nokia Corporation 6 * 7 * Written by Paul Walmsley 8 * Testing and integration fixes by Jouni Högander 9 * 10 * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth 11 * Menon 12 * 13 * Parts of this code are based on code written by 14 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License version 2 as 18 * published by the Free Software Foundation. 19 */ 20 21#include <linux/kernel.h> 22#include <linux/device.h> 23#include <linux/list.h> 24#include <linux/errno.h> 25#include <linux/delay.h> 26#include <linux/clk.h> 27#include <linux/io.h> 28#include <linux/bitops.h> 29#include <linux/clkdev.h> 30 31#include "clockdomain.h" 32#include "clock.h" 33 34/* CM_AUTOIDLE_PLL*.AUTO_* bit values */ 35#define DPLL_AUTOIDLE_DISABLE 0x0 36#define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1 37 38#define MAX_DPLL_WAIT_TRIES 1000000 39 40/* Private functions */ 41 42/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ 43static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits) 44{ 45 const struct dpll_data *dd; 46 u32 v; 47 48 dd = clk->dpll_data; 49 50 v = omap2_clk_readl(clk, dd->control_reg); 51 v &= ~dd->enable_mask; 52 v |= clken_bits << __ffs(dd->enable_mask); 53 omap2_clk_writel(v, clk, dd->control_reg); 54} 55 56/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ 57static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state) 58{ 59 const struct dpll_data *dd; 60 int i = 0; 61 int ret = -EINVAL; 62 const char *clk_name; 63 64 dd = clk->dpll_data; 65 clk_name = __clk_get_name(clk->hw.clk); 66 67 state <<= __ffs(dd->idlest_mask); 68 69 while (((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) 70 != state) && i < MAX_DPLL_WAIT_TRIES) { 71 i++; 72 udelay(1); 73 } 74 75 if (i == MAX_DPLL_WAIT_TRIES) { 76 printk(KERN_ERR "clock: %s failed transition to '%s'\n", 77 clk_name, (state) ? "locked" : "bypassed"); 78 } else { 79 pr_debug("clock: %s transition to '%s' in %d loops\n", 80 clk_name, (state) ? "locked" : "bypassed", i); 81 82 ret = 0; 83 } 84 85 return ret; 86} 87 88/* From 3430 TRM ES2 4.7.6.2 */ 89static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n) 90{ 91 unsigned long fint; 92 u16 f = 0; 93 94 fint = __clk_get_rate(clk->dpll_data->clk_ref) / n; 95 96 pr_debug("clock: fint is %lu\n", fint); 97 98 if (fint >= 750000 && fint <= 1000000) 99 f = 0x3; 100 else if (fint > 1000000 && fint <= 1250000) 101 f = 0x4; 102 else if (fint > 1250000 && fint <= 1500000) 103 f = 0x5; 104 else if (fint > 1500000 && fint <= 1750000) 105 f = 0x6; 106 else if (fint > 1750000 && fint <= 2100000) 107 f = 0x7; 108 else if (fint > 7500000 && fint <= 10000000) 109 f = 0xB; 110 else if (fint > 10000000 && fint <= 12500000) 111 f = 0xC; 112 else if (fint > 12500000 && fint <= 15000000) 113 f = 0xD; 114 else if (fint > 15000000 && fint <= 17500000) 115 f = 0xE; 116 else if (fint > 17500000 && fint <= 21000000) 117 f = 0xF; 118 else 119 pr_debug("clock: unknown freqsel setting for %d\n", n); 120 121 return f; 122} 123 124/* 125 * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness 126 * @clk: pointer to a DPLL struct clk 127 * 128 * Instructs a non-CORE DPLL to lock. Waits for the DPLL to report 129 * readiness before returning. Will save and restore the DPLL's 130 * autoidle state across the enable, per the CDP code. If the DPLL 131 * locked successfully, return 0; if the DPLL did not lock in the time 132 * allotted, or DPLL3 was passed in, return -EINVAL. 133 */ 134static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk) 135{ 136 const struct dpll_data *dd; 137 u8 ai; 138 u8 state = 1; 139 int r = 0; 140 141 pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk)); 142 143 dd = clk->dpll_data; 144 state <<= __ffs(dd->idlest_mask); 145 146 /* Check if already locked */ 147 if ((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) == state) 148 goto done; 149 150 ai = omap3_dpll_autoidle_read(clk); 151 152 if (ai) 153 omap3_dpll_deny_idle(clk); 154 155 _omap3_dpll_write_clken(clk, DPLL_LOCKED); 156 157 r = _omap3_wait_dpll_status(clk, 1); 158 159 if (ai) 160 omap3_dpll_allow_idle(clk); 161 162done: 163 return r; 164} 165 166/* 167 * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness 168 * @clk: pointer to a DPLL struct clk 169 * 170 * Instructs a non-CORE DPLL to enter low-power bypass mode. In 171 * bypass mode, the DPLL's rate is set equal to its parent clock's 172 * rate. Waits for the DPLL to report readiness before returning. 173 * Will save and restore the DPLL's autoidle state across the enable, 174 * per the CDP code. If the DPLL entered bypass mode successfully, 175 * return 0; if the DPLL did not enter bypass in the time allotted, or 176 * DPLL3 was passed in, or the DPLL does not support low-power bypass, 177 * return -EINVAL. 178 */ 179static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk) 180{ 181 int r; 182 u8 ai; 183 184 if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) 185 return -EINVAL; 186 187 pr_debug("clock: configuring DPLL %s for low-power bypass\n", 188 __clk_get_name(clk->hw.clk)); 189 190 ai = omap3_dpll_autoidle_read(clk); 191 192 _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS); 193 194 r = _omap3_wait_dpll_status(clk, 0); 195 196 if (ai) 197 omap3_dpll_allow_idle(clk); 198 199 return r; 200} 201 202/* 203 * _omap3_noncore_dpll_stop - instruct a DPLL to stop 204 * @clk: pointer to a DPLL struct clk 205 * 206 * Instructs a non-CORE DPLL to enter low-power stop. Will save and 207 * restore the DPLL's autoidle state across the stop, per the CDP 208 * code. If DPLL3 was passed in, or the DPLL does not support 209 * low-power stop, return -EINVAL; otherwise, return 0. 210 */ 211static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk) 212{ 213 u8 ai; 214 215 if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP))) 216 return -EINVAL; 217 218 pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk)); 219 220 ai = omap3_dpll_autoidle_read(clk); 221 222 _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP); 223 224 if (ai) 225 omap3_dpll_allow_idle(clk); 226 227 return 0; 228} 229 230/** 231 * _lookup_dco - Lookup DCO used by j-type DPLL 232 * @clk: pointer to a DPLL struct clk 233 * @dco: digital control oscillator selector 234 * @m: DPLL multiplier to set 235 * @n: DPLL divider to set 236 * 237 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)" 238 * 239 * XXX This code is not needed for 3430/AM35xx; can it be optimized 240 * out in non-multi-OMAP builds for those chips? 241 */ 242static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n) 243{ 244 unsigned long fint, clkinp; /* watch out for overflow */ 245 246 clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk)); 247 fint = (clkinp / n) * m; 248 249 if (fint < 1000000000) 250 *dco = 2; 251 else 252 *dco = 4; 253} 254 255/** 256 * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL 257 * @clk: pointer to a DPLL struct clk 258 * @sd_div: target sigma-delta divider 259 * @m: DPLL multiplier to set 260 * @n: DPLL divider to set 261 * 262 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)" 263 * 264 * XXX This code is not needed for 3430/AM35xx; can it be optimized 265 * out in non-multi-OMAP builds for those chips? 266 */ 267static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n) 268{ 269 unsigned long clkinp, sd; /* watch out for overflow */ 270 int mod1, mod2; 271 272 clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk)); 273 274 /* 275 * target sigma-delta to near 250MHz 276 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)] 277 */ 278 clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */ 279 mod1 = (clkinp * m) % (250 * n); 280 sd = (clkinp * m) / (250 * n); 281 mod2 = sd % 10; 282 sd /= 10; 283 284 if (mod1 || mod2) 285 sd++; 286 *sd_div = sd; 287} 288 289/* 290 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly 291 * @clk: struct clk * of DPLL to set 292 * @freqsel: FREQSEL value to set 293 * 294 * Program the DPLL with the last M, N values calculated, and wait for 295 * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success. 296 */ 297static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) 298{ 299 struct dpll_data *dd = clk->dpll_data; 300 u8 dco, sd_div; 301 u32 v; 302 303 /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ 304 _omap3_noncore_dpll_bypass(clk); 305 306 /* 307 * Set jitter correction. Jitter correction applicable for OMAP343X 308 * only since freqsel field is no longer present on other devices. 309 */ 310 if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) { 311 v = omap2_clk_readl(clk, dd->control_reg); 312 v &= ~dd->freqsel_mask; 313 v |= freqsel << __ffs(dd->freqsel_mask); 314 omap2_clk_writel(v, clk, dd->control_reg); 315 } 316 317 /* Set DPLL multiplier, divider */ 318 v = omap2_clk_readl(clk, dd->mult_div1_reg); 319 320 /* Handle Duty Cycle Correction */ 321 if (dd->dcc_mask) { 322 if (dd->last_rounded_rate >= dd->dcc_rate) 323 v |= dd->dcc_mask; /* Enable DCC */ 324 else 325 v &= ~dd->dcc_mask; /* Disable DCC */ 326 } 327 328 v &= ~(dd->mult_mask | dd->div1_mask); 329 v |= dd->last_rounded_m << __ffs(dd->mult_mask); 330 v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask); 331 332 /* Configure dco and sd_div for dplls that have these fields */ 333 if (dd->dco_mask) { 334 _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n); 335 v &= ~(dd->dco_mask); 336 v |= dco << __ffs(dd->dco_mask); 337 } 338 if (dd->sddiv_mask) { 339 _lookup_sddiv(clk, &sd_div, dd->last_rounded_m, 340 dd->last_rounded_n); 341 v &= ~(dd->sddiv_mask); 342 v |= sd_div << __ffs(dd->sddiv_mask); 343 } 344 345 omap2_clk_writel(v, clk, dd->mult_div1_reg); 346 347 /* Set 4X multiplier and low-power mode */ 348 if (dd->m4xen_mask || dd->lpmode_mask) { 349 v = omap2_clk_readl(clk, dd->control_reg); 350 351 if (dd->m4xen_mask) { 352 if (dd->last_rounded_m4xen) 353 v |= dd->m4xen_mask; 354 else 355 v &= ~dd->m4xen_mask; 356 } 357 358 if (dd->lpmode_mask) { 359 if (dd->last_rounded_lpmode) 360 v |= dd->lpmode_mask; 361 else 362 v &= ~dd->lpmode_mask; 363 } 364 365 omap2_clk_writel(v, clk, dd->control_reg); 366 } 367 368 /* We let the clock framework set the other output dividers later */ 369 370 /* REVISIT: Set ramp-up delay? */ 371 372 _omap3_noncore_dpll_lock(clk); 373 374 return 0; 375} 376 377/* Public functions */ 378 379/** 380 * omap3_dpll_recalc - recalculate DPLL rate 381 * @clk: DPLL struct clk 382 * 383 * Recalculate and propagate the DPLL rate. 384 */ 385unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate) 386{ 387 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 388 389 return omap2_get_dpll_rate(clk); 390} 391 392/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */ 393 394/** 395 * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode 396 * @clk: pointer to a DPLL struct clk 397 * 398 * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock. 399 * The choice of modes depends on the DPLL's programmed rate: if it is 400 * the same as the DPLL's parent clock, it will enter bypass; 401 * otherwise, it will enter lock. This code will wait for the DPLL to 402 * indicate readiness before returning, unless the DPLL takes too long 403 * to enter the target state. Intended to be used as the struct clk's 404 * enable function. If DPLL3 was passed in, or the DPLL does not 405 * support low-power stop, or if the DPLL took too long to enter 406 * bypass or lock, return -EINVAL; otherwise, return 0. 407 */ 408int omap3_noncore_dpll_enable(struct clk_hw *hw) 409{ 410 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 411 int r; 412 struct dpll_data *dd; 413 struct clk_hw *parent; 414 415 dd = clk->dpll_data; 416 if (!dd) 417 return -EINVAL; 418 419 if (clk->clkdm) { 420 r = clkdm_clk_enable(clk->clkdm, hw->clk); 421 if (r) { 422 WARN(1, 423 "%s: could not enable %s's clockdomain %s: %d\n", 424 __func__, __clk_get_name(hw->clk), 425 clk->clkdm->name, r); 426 return r; 427 } 428 } 429 430 parent = __clk_get_hw(__clk_get_parent(hw->clk)); 431 432 if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) { 433 WARN_ON(parent != __clk_get_hw(dd->clk_bypass)); 434 r = _omap3_noncore_dpll_bypass(clk); 435 } else { 436 WARN_ON(parent != __clk_get_hw(dd->clk_ref)); 437 r = _omap3_noncore_dpll_lock(clk); 438 } 439 440 return r; 441} 442 443/** 444 * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop 445 * @clk: pointer to a DPLL struct clk 446 * 447 * Instructs a non-CORE DPLL to enter low-power stop. This function is 448 * intended for use in struct clkops. No return value. 449 */ 450void omap3_noncore_dpll_disable(struct clk_hw *hw) 451{ 452 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 453 454 _omap3_noncore_dpll_stop(clk); 455 if (clk->clkdm) 456 clkdm_clk_disable(clk->clkdm, hw->clk); 457} 458 459 460/* Non-CORE DPLL rate set code */ 461 462/** 463 * omap3_noncore_dpll_determine_rate - determine rate for a DPLL 464 * @hw: pointer to the clock to determine rate for 465 * @rate: target rate for the DPLL 466 * @best_parent_rate: pointer for returning best parent rate 467 * @best_parent_clk: pointer for returning best parent clock 468 * 469 * Determines which DPLL mode to use for reaching a desired target rate. 470 * Checks whether the DPLL shall be in bypass or locked mode, and if 471 * locked, calculates the M,N values for the DPLL via round-rate. 472 * Returns a positive clock rate with success, negative error value 473 * in failure. 474 */ 475long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate, 476 unsigned long min_rate, 477 unsigned long max_rate, 478 unsigned long *best_parent_rate, 479 struct clk_hw **best_parent_clk) 480{ 481 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 482 struct dpll_data *dd; 483 484 if (!hw || !rate) 485 return -EINVAL; 486 487 dd = clk->dpll_data; 488 if (!dd) 489 return -EINVAL; 490 491 if (__clk_get_rate(dd->clk_bypass) == rate && 492 (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { 493 *best_parent_clk = __clk_get_hw(dd->clk_bypass); 494 } else { 495 rate = omap2_dpll_round_rate(hw, rate, best_parent_rate); 496 *best_parent_clk = __clk_get_hw(dd->clk_ref); 497 } 498 499 *best_parent_rate = rate; 500 501 return rate; 502} 503 504/** 505 * omap3_noncore_dpll_set_parent - set parent for a DPLL clock 506 * @hw: pointer to the clock to set parent for 507 * @index: parent index to select 508 * 509 * Sets parent for a DPLL clock. This sets the DPLL into bypass or 510 * locked mode. Returns 0 with success, negative error value otherwise. 511 */ 512int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index) 513{ 514 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 515 int ret; 516 517 if (!hw) 518 return -EINVAL; 519 520 if (index) 521 ret = _omap3_noncore_dpll_bypass(clk); 522 else 523 ret = _omap3_noncore_dpll_lock(clk); 524 525 return ret; 526} 527 528/** 529 * omap3_noncore_dpll_set_rate - set rate for a DPLL clock 530 * @hw: pointer to the clock to set parent for 531 * @rate: target rate for the clock 532 * @parent_rate: rate of the parent clock 533 * 534 * Sets rate for a DPLL clock. First checks if the clock parent is 535 * reference clock (in bypass mode, the rate of the clock can't be 536 * changed) and proceeds with the rate change operation. Returns 0 537 * with success, negative error value otherwise. 538 */ 539int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, 540 unsigned long parent_rate) 541{ 542 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 543 struct dpll_data *dd; 544 u16 freqsel = 0; 545 int ret; 546 547 if (!hw || !rate) 548 return -EINVAL; 549 550 dd = clk->dpll_data; 551 if (!dd) 552 return -EINVAL; 553 554 if (__clk_get_hw(__clk_get_parent(hw->clk)) != 555 __clk_get_hw(dd->clk_ref)) 556 return -EINVAL; 557 558 if (dd->last_rounded_rate == 0) 559 return -EINVAL; 560 561 /* Freqsel is available only on OMAP343X devices */ 562 if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) { 563 freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n); 564 WARN_ON(!freqsel); 565 } 566 567 pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__, 568 __clk_get_name(hw->clk), rate); 569 570 ret = omap3_noncore_dpll_program(clk, freqsel); 571 572 return ret; 573} 574 575/** 576 * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock 577 * @hw: pointer to the clock to set rate and parent for 578 * @rate: target rate for the DPLL 579 * @parent_rate: clock rate of the DPLL parent 580 * @index: new parent index for the DPLL, 0 - reference, 1 - bypass 581 * 582 * Sets rate and parent for a DPLL clock. If new parent is the bypass 583 * clock, only selects the parent. Otherwise proceeds with a rate 584 * change, as this will effectively also change the parent as the 585 * DPLL is put into locked mode. Returns 0 with success, negative error 586 * value otherwise. 587 */ 588int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw, 589 unsigned long rate, 590 unsigned long parent_rate, 591 u8 index) 592{ 593 int ret; 594 595 if (!hw || !rate) 596 return -EINVAL; 597 598 /* 599 * clk-ref at index[0], in which case we only need to set rate, 600 * the parent will be changed automatically with the lock sequence. 601 * With clk-bypass case we only need to change parent. 602 */ 603 if (index) 604 ret = omap3_noncore_dpll_set_parent(hw, index); 605 else 606 ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate); 607 608 return ret; 609} 610 611/* DPLL autoidle read/set code */ 612 613/** 614 * omap3_dpll_autoidle_read - read a DPLL's autoidle bits 615 * @clk: struct clk * of the DPLL to read 616 * 617 * Return the DPLL's autoidle bits, shifted down to bit 0. Returns 618 * -EINVAL if passed a null pointer or if the struct clk does not 619 * appear to refer to a DPLL. 620 */ 621u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk) 622{ 623 const struct dpll_data *dd; 624 u32 v; 625 626 if (!clk || !clk->dpll_data) 627 return -EINVAL; 628 629 dd = clk->dpll_data; 630 631 if (!dd->autoidle_reg) 632 return -EINVAL; 633 634 v = omap2_clk_readl(clk, dd->autoidle_reg); 635 v &= dd->autoidle_mask; 636 v >>= __ffs(dd->autoidle_mask); 637 638 return v; 639} 640 641/** 642 * omap3_dpll_allow_idle - enable DPLL autoidle bits 643 * @clk: struct clk * of the DPLL to operate on 644 * 645 * Enable DPLL automatic idle control. This automatic idle mode 646 * switching takes effect only when the DPLL is locked, at least on 647 * OMAP3430. The DPLL will enter low-power stop when its downstream 648 * clocks are gated. No return value. 649 */ 650void omap3_dpll_allow_idle(struct clk_hw_omap *clk) 651{ 652 const struct dpll_data *dd; 653 u32 v; 654 655 if (!clk || !clk->dpll_data) 656 return; 657 658 dd = clk->dpll_data; 659 660 if (!dd->autoidle_reg) 661 return; 662 663 /* 664 * REVISIT: CORE DPLL can optionally enter low-power bypass 665 * by writing 0x5 instead of 0x1. Add some mechanism to 666 * optionally enter this mode. 667 */ 668 v = omap2_clk_readl(clk, dd->autoidle_reg); 669 v &= ~dd->autoidle_mask; 670 v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); 671 omap2_clk_writel(v, clk, dd->autoidle_reg); 672 673} 674 675/** 676 * omap3_dpll_deny_idle - prevent DPLL from automatically idling 677 * @clk: struct clk * of the DPLL to operate on 678 * 679 * Disable DPLL automatic idle control. No return value. 680 */ 681void omap3_dpll_deny_idle(struct clk_hw_omap *clk) 682{ 683 const struct dpll_data *dd; 684 u32 v; 685 686 if (!clk || !clk->dpll_data) 687 return; 688 689 dd = clk->dpll_data; 690 691 if (!dd->autoidle_reg) 692 return; 693 694 v = omap2_clk_readl(clk, dd->autoidle_reg); 695 v &= ~dd->autoidle_mask; 696 v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); 697 omap2_clk_writel(v, clk, dd->autoidle_reg); 698 699} 700 701/* Clock control for DPLL outputs */ 702 703/* Find the parent DPLL for the given clkoutx2 clock */ 704static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw) 705{ 706 struct clk_hw_omap *pclk = NULL; 707 struct clk *parent; 708 709 /* Walk up the parents of clk, looking for a DPLL */ 710 do { 711 do { 712 parent = __clk_get_parent(hw->clk); 713 hw = __clk_get_hw(parent); 714 } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC)); 715 if (!hw) 716 break; 717 pclk = to_clk_hw_omap(hw); 718 } while (pclk && !pclk->dpll_data); 719 720 /* clk does not have a DPLL as a parent? error in the clock data */ 721 if (!pclk) { 722 WARN_ON(1); 723 return NULL; 724 } 725 726 return pclk; 727} 728 729/** 730 * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate 731 * @clk: DPLL output struct clk 732 * 733 * Using parent clock DPLL data, look up DPLL state. If locked, set our 734 * rate to the dpll_clk * 2; otherwise, just use dpll_clk. 735 */ 736unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, 737 unsigned long parent_rate) 738{ 739 const struct dpll_data *dd; 740 unsigned long rate; 741 u32 v; 742 struct clk_hw_omap *pclk = NULL; 743 744 if (!parent_rate) 745 return 0; 746 747 pclk = omap3_find_clkoutx2_dpll(hw); 748 749 if (!pclk) 750 return 0; 751 752 dd = pclk->dpll_data; 753 754 WARN_ON(!dd->enable_mask); 755 756 v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask; 757 v >>= __ffs(dd->enable_mask); 758 if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE)) 759 rate = parent_rate; 760 else 761 rate = parent_rate * 2; 762 return rate; 763} 764 765int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate, 766 unsigned long parent_rate) 767{ 768 return 0; 769} 770 771long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate, 772 unsigned long *prate) 773{ 774 const struct dpll_data *dd; 775 u32 v; 776 struct clk_hw_omap *pclk = NULL; 777 778 if (!*prate) 779 return 0; 780 781 pclk = omap3_find_clkoutx2_dpll(hw); 782 783 if (!pclk) 784 return 0; 785 786 dd = pclk->dpll_data; 787 788 /* TYPE J does not have a clkoutx2 */ 789 if (dd->flags & DPLL_J_TYPE) { 790 *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate); 791 return *prate; 792 } 793 794 WARN_ON(!dd->enable_mask); 795 796 v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask; 797 v >>= __ffs(dd->enable_mask); 798 799 /* If in bypass, the rate is fixed to the bypass rate*/ 800 if (v != OMAP3XXX_EN_DPLL_LOCKED) 801 return *prate; 802 803 if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) { 804 unsigned long best_parent; 805 806 best_parent = (rate / 2); 807 *prate = __clk_round_rate(__clk_get_parent(hw->clk), 808 best_parent); 809 } 810 811 return *prate * 2; 812} 813 814/* OMAP3/4 non-CORE DPLL clkops */ 815const struct clk_hw_omap_ops clkhwops_omap3_dpll = { 816 .allow_idle = omap3_dpll_allow_idle, 817 .deny_idle = omap3_dpll_deny_idle, 818}; 819