1 /* 2 * OMAP2/3/4 clockdomain framework functions 3 * 4 * Copyright (C) 2008-2010 Texas Instruments, Inc. 5 * Copyright (C) 2008-2010 Nokia Corporation 6 * 7 * Written by Paul Walmsley and Jouni Högander 8 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 #undef DEBUG 15 16 #include <linux/module.h> 17 #include <linux/kernel.h> 18 #include <linux/device.h> 19 #include <linux/list.h> 20 #include <linux/errno.h> 21 #include <linux/delay.h> 22 #include <linux/clk.h> 23 #include <linux/limits.h> 24 #include <linux/err.h> 25 26 #include <linux/io.h> 27 28 #include <linux/bitops.h> 29 30 #include "prm.h" 31 #include "prm-regbits-24xx.h" 32 #include "cm.h" 33 34 #include <plat/clock.h> 35 #include <plat/powerdomain.h> 36 #include <plat/clockdomain.h> 37 #include <plat/prcm.h> 38 39 /* clkdm_list contains all registered struct clockdomains */ 40 static LIST_HEAD(clkdm_list); 41 42 /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */ 43 static struct clkdm_autodep *autodeps; 44 45 46 /* Private functions */ 47 48 static struct clockdomain *_clkdm_lookup(const char *name) 49 { 50 struct clockdomain *clkdm, *temp_clkdm; 51 52 if (!name) 53 return NULL; 54 55 clkdm = NULL; 56 57 list_for_each_entry(temp_clkdm, &clkdm_list, node) { 58 if (!strcmp(name, temp_clkdm->name)) { 59 clkdm = temp_clkdm; 60 break; 61 } 62 } 63 64 return clkdm; 65 } 66 67 /** 68 * _clkdm_register - register a clockdomain 69 * @clkdm: struct clockdomain * to register 70 * 71 * Adds a clockdomain to the internal clockdomain list. 72 * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is 73 * already registered by the provided name, or 0 upon success. 74 */ 75 static int _clkdm_register(struct clockdomain *clkdm) 76 { 77 struct powerdomain *pwrdm; 78 79 if (!clkdm || !clkdm->name) 80 return -EINVAL; 81 82 if (!omap_chip_is(clkdm->omap_chip)) 83 return -EINVAL; 84 85 pwrdm = pwrdm_lookup(clkdm->pwrdm.name); 86 if (!pwrdm) { 87 pr_err("clockdomain: %s: powerdomain %s does not exist\n", 88 clkdm->name, clkdm->pwrdm.name); 89 return -EINVAL; 90 } 91 clkdm->pwrdm.ptr = pwrdm; 92 93 /* Verify that the clockdomain is not already registered */ 94 if (_clkdm_lookup(clkdm->name)) 95 return -EEXIST; 96 97 list_add(&clkdm->node, &clkdm_list); 98 99 pwrdm_add_clkdm(pwrdm, clkdm); 100 101 pr_debug("clockdomain: registered %s\n", clkdm->name); 102 103 return 0; 104 } 105 106 /* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */ 107 static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm, 108 struct clkdm_dep *deps) 109 { 110 struct clkdm_dep *cd; 111 112 if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip)) 113 return ERR_PTR(-EINVAL); 114 115 for (cd = deps; cd->clkdm_name; cd++) { 116 if (!omap_chip_is(cd->omap_chip)) 117 continue; 118 119 if (!cd->clkdm && cd->clkdm_name) 120 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 121 122 if (cd->clkdm == clkdm) 123 break; 124 } 125 126 if (!cd->clkdm_name) 127 return ERR_PTR(-ENOENT); 128 129 return cd; 130 } 131 132 /* 133 * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store 134 * @autodep: struct clkdm_autodep * to resolve 135 * 136 * Resolve autodep clockdomain names to clockdomain pointers via 137 * clkdm_lookup() and store the pointers in the autodep structure. An 138 * "autodep" is a clockdomain sleep/wakeup dependency that is 139 * automatically added and removed whenever clocks in the associated 140 * clockdomain are enabled or disabled (respectively) when the 141 * clockdomain is in hardware-supervised mode. Meant to be called 142 * once at clockdomain layer initialization, since these should remain 143 * fixed for a particular architecture. No return value. 144 */ 145 static void _autodep_lookup(struct clkdm_autodep *autodep) 146 { 147 struct clockdomain *clkdm; 148 149 if (!autodep) 150 return; 151 152 if (!omap_chip_is(autodep->omap_chip)) 153 return; 154 155 clkdm = clkdm_lookup(autodep->clkdm.name); 156 if (!clkdm) { 157 pr_err("clockdomain: autodeps: clockdomain %s does not exist\n", 158 autodep->clkdm.name); 159 clkdm = ERR_PTR(-ENOENT); 160 } 161 autodep->clkdm.ptr = clkdm; 162 } 163 164 /* 165 * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable 166 * @clkdm: struct clockdomain * 167 * 168 * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' 169 * in hardware-supervised mode. Meant to be called from clock framework 170 * when a clock inside clockdomain 'clkdm' is enabled. No return value. 171 */ 172 static void _clkdm_add_autodeps(struct clockdomain *clkdm) 173 { 174 struct clkdm_autodep *autodep; 175 176 if (!autodeps) 177 return; 178 179 for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { 180 if (IS_ERR(autodep->clkdm.ptr)) 181 continue; 182 183 if (!omap_chip_is(autodep->omap_chip)) 184 continue; 185 186 pr_debug("clockdomain: adding %s sleepdep/wkdep for " 187 "clkdm %s\n", autodep->clkdm.ptr->name, 188 clkdm->name); 189 190 clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr); 191 clkdm_add_wkdep(clkdm, autodep->clkdm.ptr); 192 } 193 } 194 195 /* 196 * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm 197 * @clkdm: struct clockdomain * 198 * 199 * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' 200 * in hardware-supervised mode. Meant to be called from clock framework 201 * when a clock inside clockdomain 'clkdm' is disabled. No return value. 202 */ 203 static void _clkdm_del_autodeps(struct clockdomain *clkdm) 204 { 205 struct clkdm_autodep *autodep; 206 207 if (!autodeps) 208 return; 209 210 for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { 211 if (IS_ERR(autodep->clkdm.ptr)) 212 continue; 213 214 if (!omap_chip_is(autodep->omap_chip)) 215 continue; 216 217 pr_debug("clockdomain: removing %s sleepdep/wkdep for " 218 "clkdm %s\n", autodep->clkdm.ptr->name, 219 clkdm->name); 220 221 clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr); 222 clkdm_del_wkdep(clkdm, autodep->clkdm.ptr); 223 } 224 } 225 226 /* 227 * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit 228 * @clkdm: struct clockdomain * 229 * @enable: int 0 to disable, 1 to enable 230 * 231 * Internal helper for actually switching the bit that controls hwsup 232 * idle transitions for clkdm. 233 */ 234 static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) 235 { 236 u32 bits, v; 237 238 if (cpu_is_omap24xx()) { 239 if (enable) 240 bits = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; 241 else 242 bits = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; 243 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { 244 if (enable) 245 bits = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; 246 else 247 bits = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; 248 } else { 249 BUG(); 250 } 251 252 bits = bits << __ffs(clkdm->clktrctrl_mask); 253 254 v = __raw_readl(clkdm->clkstctrl_reg); 255 v &= ~(clkdm->clktrctrl_mask); 256 v |= bits; 257 __raw_writel(v, clkdm->clkstctrl_reg); 258 259 } 260 261 /* Public functions */ 262 263 /** 264 * clkdm_init - set up the clockdomain layer 265 * @clkdms: optional pointer to an array of clockdomains to register 266 * @init_autodeps: optional pointer to an array of autodeps to register 267 * 268 * Set up internal state. If a pointer to an array of clockdomains 269 * @clkdms was supplied, loop through the list of clockdomains, 270 * register all that are available on the current platform. Similarly, 271 * if a pointer to an array of clockdomain autodependencies 272 * @init_autodeps was provided, register those. No return value. 273 */ 274 void clkdm_init(struct clockdomain **clkdms, 275 struct clkdm_autodep *init_autodeps) 276 { 277 struct clockdomain **c = NULL; 278 struct clockdomain *clkdm; 279 struct clkdm_autodep *autodep = NULL; 280 281 if (clkdms) 282 for (c = clkdms; *c; c++) 283 _clkdm_register(*c); 284 285 autodeps = init_autodeps; 286 if (autodeps) 287 for (autodep = autodeps; autodep->clkdm.ptr; autodep++) 288 _autodep_lookup(autodep); 289 290 /* 291 * Put all clockdomains into software-supervised mode; PM code 292 * should later enable hardware-supervised mode as appropriate 293 */ 294 list_for_each_entry(clkdm, &clkdm_list, node) { 295 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) 296 omap2_clkdm_wakeup(clkdm); 297 else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO) 298 omap2_clkdm_deny_idle(clkdm); 299 300 clkdm_clear_all_wkdeps(clkdm); 301 clkdm_clear_all_sleepdeps(clkdm); 302 } 303 } 304 305 /** 306 * clkdm_lookup - look up a clockdomain by name, return a pointer 307 * @name: name of clockdomain 308 * 309 * Find a registered clockdomain by its name @name. Returns a pointer 310 * to the struct clockdomain if found, or NULL otherwise. 311 */ 312 struct clockdomain *clkdm_lookup(const char *name) 313 { 314 struct clockdomain *clkdm, *temp_clkdm; 315 316 if (!name) 317 return NULL; 318 319 clkdm = NULL; 320 321 list_for_each_entry(temp_clkdm, &clkdm_list, node) { 322 if (!strcmp(name, temp_clkdm->name)) { 323 clkdm = temp_clkdm; 324 break; 325 } 326 } 327 328 return clkdm; 329 } 330 331 /** 332 * clkdm_for_each - call function on each registered clockdomain 333 * @fn: callback function * 334 * 335 * Call the supplied function @fn for each registered clockdomain. 336 * The callback function @fn can return anything but 0 to bail 337 * out early from the iterator. The callback function is called with 338 * the clkdm_mutex held, so no clockdomain structure manipulation 339 * functions should be called from the callback, although hardware 340 * clockdomain control functions are fine. Returns the last return 341 * value of the callback function, which should be 0 for success or 342 * anything else to indicate failure; or -EINVAL if the function pointer 343 * is null. 344 */ 345 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), 346 void *user) 347 { 348 struct clockdomain *clkdm; 349 int ret = 0; 350 351 if (!fn) 352 return -EINVAL; 353 354 list_for_each_entry(clkdm, &clkdm_list, node) { 355 ret = (*fn)(clkdm, user); 356 if (ret) 357 break; 358 } 359 360 return ret; 361 } 362 363 364 /** 365 * clkdm_get_pwrdm - return a ptr to the pwrdm that this clkdm resides in 366 * @clkdm: struct clockdomain * 367 * 368 * Return a pointer to the struct powerdomain that the specified clockdomain 369 * @clkdm exists in, or returns NULL if @clkdm is NULL. 370 */ 371 struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) 372 { 373 if (!clkdm) 374 return NULL; 375 376 return clkdm->pwrdm.ptr; 377 } 378 379 380 /* Hardware clockdomain control */ 381 382 /** 383 * clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 384 * @clkdm1: wake this struct clockdomain * up (dependent) 385 * @clkdm2: when this struct clockdomain * wakes up (source) 386 * 387 * When the clockdomain represented by @clkdm2 wakes up, wake up 388 * @clkdm1. Implemented in hardware on the OMAP, this feature is 389 * designed to reduce wakeup latency of the dependent clockdomain @clkdm1. 390 * Returns -EINVAL if presented with invalid clockdomain pointers, 391 * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon 392 * success. 393 */ 394 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 395 { 396 struct clkdm_dep *cd; 397 398 if (!clkdm1 || !clkdm2) 399 return -EINVAL; 400 401 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 402 if (IS_ERR(cd)) { 403 pr_debug("clockdomain: hardware cannot set/clear wake up of " 404 "%s when %s wakes up\n", clkdm1->name, clkdm2->name); 405 return PTR_ERR(cd); 406 } 407 408 if (atomic_inc_return(&cd->wkdep_usecount) == 1) { 409 pr_debug("clockdomain: hardware will wake up %s when %s wakes " 410 "up\n", clkdm1->name, clkdm2->name); 411 412 prm_set_mod_reg_bits((1 << clkdm2->dep_bit), 413 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); 414 } 415 416 return 0; 417 } 418 419 /** 420 * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1 421 * @clkdm1: wake this struct clockdomain * up (dependent) 422 * @clkdm2: when this struct clockdomain * wakes up (source) 423 * 424 * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2 425 * wakes up. Returns -EINVAL if presented with invalid clockdomain 426 * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 427 * 0 upon success. 428 */ 429 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 430 { 431 struct clkdm_dep *cd; 432 433 if (!clkdm1 || !clkdm2) 434 return -EINVAL; 435 436 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 437 if (IS_ERR(cd)) { 438 pr_debug("clockdomain: hardware cannot set/clear wake up of " 439 "%s when %s wakes up\n", clkdm1->name, clkdm2->name); 440 return PTR_ERR(cd); 441 } 442 443 if (atomic_dec_return(&cd->wkdep_usecount) == 0) { 444 pr_debug("clockdomain: hardware will no longer wake up %s " 445 "after %s wakes up\n", clkdm1->name, clkdm2->name); 446 447 prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), 448 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); 449 } 450 451 return 0; 452 } 453 454 /** 455 * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1 456 * @clkdm1: wake this struct clockdomain * up (dependent) 457 * @clkdm2: when this struct clockdomain * wakes up (source) 458 * 459 * Return 1 if a hardware wakeup dependency exists wherein @clkdm1 will be 460 * awoken when @clkdm2 wakes up; 0 if dependency is not set; -EINVAL 461 * if either clockdomain pointer is invalid; or -ENOENT if the hardware 462 * is incapable. 463 * 464 * REVISIT: Currently this function only represents software-controllable 465 * wakeup dependencies. Wakeup dependencies fixed in hardware are not 466 * yet handled here. 467 */ 468 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 469 { 470 struct clkdm_dep *cd; 471 472 if (!clkdm1 || !clkdm2) 473 return -EINVAL; 474 475 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 476 if (IS_ERR(cd)) { 477 pr_debug("clockdomain: hardware cannot set/clear wake up of " 478 "%s when %s wakes up\n", clkdm1->name, clkdm2->name); 479 return PTR_ERR(cd); 480 } 481 482 /* XXX It's faster to return the atomic wkdep_usecount */ 483 return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, 484 (1 << clkdm2->dep_bit)); 485 } 486 487 /** 488 * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm 489 * @clkdm: struct clockdomain * to remove all wakeup dependencies from 490 * 491 * Remove all inter-clockdomain wakeup dependencies that could cause 492 * @clkdm to wake. Intended to be used during boot to initialize the 493 * PRCM to a known state, after all clockdomains are put into swsup idle 494 * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or 495 * 0 upon success. 496 */ 497 int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) 498 { 499 struct clkdm_dep *cd; 500 u32 mask = 0; 501 502 if (!clkdm) 503 return -EINVAL; 504 505 for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { 506 if (!omap_chip_is(cd->omap_chip)) 507 continue; 508 509 if (!cd->clkdm && cd->clkdm_name) 510 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 511 512 /* PRM accesses are slow, so minimize them */ 513 mask |= 1 << cd->clkdm->dep_bit; 514 atomic_set(&cd->wkdep_usecount, 0); 515 } 516 517 prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP); 518 519 return 0; 520 } 521 522 /** 523 * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 524 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 525 * @clkdm2: when this struct clockdomain * is active (source) 526 * 527 * Prevent @clkdm1 from automatically going inactive (and then to 528 * retention or off) if @clkdm2 is active. Returns -EINVAL if 529 * presented with invalid clockdomain pointers or called on a machine 530 * that does not support software-configurable hardware sleep 531 * dependencies, -ENOENT if the specified dependency cannot be set in 532 * hardware, or 0 upon success. 533 */ 534 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 535 { 536 struct clkdm_dep *cd; 537 538 if (!cpu_is_omap34xx()) 539 return -EINVAL; 540 541 if (!clkdm1 || !clkdm2) 542 return -EINVAL; 543 544 cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); 545 if (IS_ERR(cd)) { 546 pr_debug("clockdomain: hardware cannot set/clear sleep " 547 "dependency affecting %s from %s\n", clkdm1->name, 548 clkdm2->name); 549 return PTR_ERR(cd); 550 } 551 552 if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { 553 pr_debug("clockdomain: will prevent %s from sleeping if %s " 554 "is active\n", clkdm1->name, clkdm2->name); 555 556 cm_set_mod_reg_bits((1 << clkdm2->dep_bit), 557 clkdm1->pwrdm.ptr->prcm_offs, 558 OMAP3430_CM_SLEEPDEP); 559 } 560 561 return 0; 562 } 563 564 /** 565 * clkdm_del_sleepdep - remove a sleep dependency from clkdm2 to clkdm1 566 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 567 * @clkdm2: when this struct clockdomain * is active (source) 568 * 569 * Allow @clkdm1 to automatically go inactive (and then to retention or 570 * off), independent of the activity state of @clkdm2. Returns -EINVAL 571 * if presented with invalid clockdomain pointers or called on a machine 572 * that does not support software-configurable hardware sleep dependencies, 573 * -ENOENT if the specified dependency cannot be cleared in hardware, or 574 * 0 upon success. 575 */ 576 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 577 { 578 struct clkdm_dep *cd; 579 580 if (!cpu_is_omap34xx()) 581 return -EINVAL; 582 583 if (!clkdm1 || !clkdm2) 584 return -EINVAL; 585 586 cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); 587 if (IS_ERR(cd)) { 588 pr_debug("clockdomain: hardware cannot set/clear sleep " 589 "dependency affecting %s from %s\n", clkdm1->name, 590 clkdm2->name); 591 return PTR_ERR(cd); 592 } 593 594 if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { 595 pr_debug("clockdomain: will no longer prevent %s from " 596 "sleeping if %s is active\n", clkdm1->name, 597 clkdm2->name); 598 599 cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), 600 clkdm1->pwrdm.ptr->prcm_offs, 601 OMAP3430_CM_SLEEPDEP); 602 } 603 604 return 0; 605 } 606 607 /** 608 * clkdm_read_sleepdep - read sleep dependency state from clkdm2 to clkdm1 609 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 610 * @clkdm2: when this struct clockdomain * is active (source) 611 * 612 * Return 1 if a hardware sleep dependency exists wherein @clkdm1 will 613 * not be allowed to automatically go inactive if @clkdm2 is active; 614 * 0 if @clkdm1's automatic power state inactivity transition is independent 615 * of @clkdm2's; -EINVAL if either clockdomain pointer is invalid or called 616 * on a machine that does not support software-configurable hardware sleep 617 * dependencies; or -ENOENT if the hardware is incapable. 618 * 619 * REVISIT: Currently this function only represents software-controllable 620 * sleep dependencies. Sleep dependencies fixed in hardware are not 621 * yet handled here. 622 */ 623 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 624 { 625 struct clkdm_dep *cd; 626 627 if (!cpu_is_omap34xx()) 628 return -EINVAL; 629 630 if (!clkdm1 || !clkdm2) 631 return -EINVAL; 632 633 cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); 634 if (IS_ERR(cd)) { 635 pr_debug("clockdomain: hardware cannot set/clear sleep " 636 "dependency affecting %s from %s\n", clkdm1->name, 637 clkdm2->name); 638 return PTR_ERR(cd); 639 } 640 641 /* XXX It's faster to return the atomic sleepdep_usecount */ 642 return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, 643 OMAP3430_CM_SLEEPDEP, 644 (1 << clkdm2->dep_bit)); 645 } 646 647 /** 648 * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm 649 * @clkdm: struct clockdomain * to remove all sleep dependencies from 650 * 651 * Remove all inter-clockdomain sleep dependencies that could prevent 652 * @clkdm from idling. Intended to be used during boot to initialize the 653 * PRCM to a known state, after all clockdomains are put into swsup idle 654 * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or 655 * 0 upon success. 656 */ 657 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) 658 { 659 struct clkdm_dep *cd; 660 u32 mask = 0; 661 662 if (!cpu_is_omap34xx()) 663 return -EINVAL; 664 665 if (!clkdm) 666 return -EINVAL; 667 668 for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { 669 if (!omap_chip_is(cd->omap_chip)) 670 continue; 671 672 if (!cd->clkdm && cd->clkdm_name) 673 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 674 675 /* PRM accesses are slow, so minimize them */ 676 mask |= 1 << cd->clkdm->dep_bit; 677 atomic_set(&cd->sleepdep_usecount, 0); 678 } 679 680 prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, 681 OMAP3430_CM_SLEEPDEP); 682 683 return 0; 684 } 685 686 /** 687 * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode 688 * @clkdm: struct clkdm * of a clockdomain 689 * 690 * Return the clockdomain @clkdm current state transition mode from the 691 * corresponding domain CM_CLKSTCTRL register. Returns -EINVAL if @clkdm 692 * is NULL or the current mode upon success. 693 */ 694 static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm) 695 { 696 u32 v; 697 698 if (!clkdm) 699 return -EINVAL; 700 701 v = __raw_readl(clkdm->clkstctrl_reg); 702 v &= clkdm->clktrctrl_mask; 703 v >>= __ffs(clkdm->clktrctrl_mask); 704 705 return v; 706 } 707 708 /** 709 * omap2_clkdm_sleep - force clockdomain sleep transition 710 * @clkdm: struct clockdomain * 711 * 712 * Instruct the CM to force a sleep transition on the specified 713 * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if 714 * clockdomain does not support software-initiated sleep; 0 upon 715 * success. 716 */ 717 int omap2_clkdm_sleep(struct clockdomain *clkdm) 718 { 719 if (!clkdm) 720 return -EINVAL; 721 722 if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) { 723 pr_debug("clockdomain: %s does not support forcing " 724 "sleep via software\n", clkdm->name); 725 return -EINVAL; 726 } 727 728 pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); 729 730 if (cpu_is_omap24xx()) { 731 732 cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, 733 clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); 734 735 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { 736 737 u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP << 738 __ffs(clkdm->clktrctrl_mask)); 739 740 u32 v = __raw_readl(clkdm->clkstctrl_reg); 741 v &= ~(clkdm->clktrctrl_mask); 742 v |= bits; 743 __raw_writel(v, clkdm->clkstctrl_reg); 744 745 } else { 746 BUG(); 747 }; 748 749 return 0; 750 } 751 752 /** 753 * omap2_clkdm_wakeup - force clockdomain wakeup transition 754 * @clkdm: struct clockdomain * 755 * 756 * Instruct the CM to force a wakeup transition on the specified 757 * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if the 758 * clockdomain does not support software-controlled wakeup; 0 upon 759 * success. 760 */ 761 int omap2_clkdm_wakeup(struct clockdomain *clkdm) 762 { 763 if (!clkdm) 764 return -EINVAL; 765 766 if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) { 767 pr_debug("clockdomain: %s does not support forcing " 768 "wakeup via software\n", clkdm->name); 769 return -EINVAL; 770 } 771 772 pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); 773 774 if (cpu_is_omap24xx()) { 775 776 cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, 777 clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); 778 779 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { 780 781 u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP << 782 __ffs(clkdm->clktrctrl_mask)); 783 784 u32 v = __raw_readl(clkdm->clkstctrl_reg); 785 v &= ~(clkdm->clktrctrl_mask); 786 v |= bits; 787 __raw_writel(v, clkdm->clkstctrl_reg); 788 789 } else { 790 BUG(); 791 }; 792 793 return 0; 794 } 795 796 /** 797 * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm 798 * @clkdm: struct clockdomain * 799 * 800 * Allow the hardware to automatically switch the clockdomain @clkdm into 801 * active or idle states, as needed by downstream clocks. If the 802 * clockdomain has any downstream clocks enabled in the clock 803 * framework, wkdep/sleepdep autodependencies are added; this is so 804 * device drivers can read and write to the device. No return value. 805 */ 806 void omap2_clkdm_allow_idle(struct clockdomain *clkdm) 807 { 808 if (!clkdm) 809 return; 810 811 if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) { 812 pr_debug("clock: automatic idle transitions cannot be enabled " 813 "on clockdomain %s\n", clkdm->name); 814 return; 815 } 816 817 pr_debug("clockdomain: enabling automatic idle transitions for %s\n", 818 clkdm->name); 819 820 /* 821 * XXX This should be removed once TI adds wakeup/sleep 822 * dependency code and data for OMAP4. 823 */ 824 if (cpu_is_omap44xx()) { 825 WARN_ONCE(1, "clockdomain: OMAP4 wakeup/sleep dependency " 826 "support is not yet implemented\n"); 827 } else { 828 if (atomic_read(&clkdm->usecount) > 0) 829 _clkdm_add_autodeps(clkdm); 830 } 831 832 _omap2_clkdm_set_hwsup(clkdm, 1); 833 834 pwrdm_clkdm_state_switch(clkdm); 835 } 836 837 /** 838 * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm 839 * @clkdm: struct clockdomain * 840 * 841 * Prevent the hardware from automatically switching the clockdomain 842 * @clkdm into inactive or idle states. If the clockdomain has 843 * downstream clocks enabled in the clock framework, wkdep/sleepdep 844 * autodependencies are removed. No return value. 845 */ 846 void omap2_clkdm_deny_idle(struct clockdomain *clkdm) 847 { 848 if (!clkdm) 849 return; 850 851 if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) { 852 pr_debug("clockdomain: automatic idle transitions cannot be " 853 "disabled on %s\n", clkdm->name); 854 return; 855 } 856 857 pr_debug("clockdomain: disabling automatic idle transitions for %s\n", 858 clkdm->name); 859 860 _omap2_clkdm_set_hwsup(clkdm, 0); 861 862 /* 863 * XXX This should be removed once TI adds wakeup/sleep 864 * dependency code and data for OMAP4. 865 */ 866 if (cpu_is_omap44xx()) { 867 WARN_ONCE(1, "clockdomain: OMAP4 wakeup/sleep dependency " 868 "support is not yet implemented\n"); 869 } else { 870 if (atomic_read(&clkdm->usecount) > 0) 871 _clkdm_del_autodeps(clkdm); 872 } 873 } 874 875 876 /* Clockdomain-to-clock framework interface code */ 877 878 /** 879 * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm 880 * @clkdm: struct clockdomain * 881 * @clk: struct clk * of the enabled downstream clock 882 * 883 * Increment the usecount of the clockdomain @clkdm and ensure that it 884 * is awake before @clk is enabled. Intended to be called by 885 * clk_enable() code. If the clockdomain is in software-supervised 886 * idle mode, force the clockdomain to wake. If the clockdomain is in 887 * hardware-supervised idle mode, add clkdm-pwrdm autodependencies, to 888 * ensure that devices in the clockdomain can be read from/written to 889 * by on-chip processors. Returns -EINVAL if passed null pointers; 890 * returns 0 upon success or if the clockdomain is in hwsup idle mode. 891 */ 892 int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) 893 { 894 int v; 895 896 /* 897 * XXX Rewrite this code to maintain a list of enabled 898 * downstream clocks for debugging purposes? 899 */ 900 901 if (!clkdm || !clk) 902 return -EINVAL; 903 904 if (atomic_inc_return(&clkdm->usecount) > 1) 905 return 0; 906 907 /* Clockdomain now has one enabled downstream clock */ 908 909 pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, 910 clk->name); 911 912 if (!clkdm->clkstctrl_reg) 913 return 0; 914 915 v = omap2_clkdm_clktrctrl_read(clkdm); 916 917 if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || 918 (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { 919 /* Disable HW transitions when we are changing deps */ 920 _omap2_clkdm_set_hwsup(clkdm, 0); 921 _clkdm_add_autodeps(clkdm); 922 _omap2_clkdm_set_hwsup(clkdm, 1); 923 } else { 924 omap2_clkdm_wakeup(clkdm); 925 } 926 927 pwrdm_wait_transition(clkdm->pwrdm.ptr); 928 pwrdm_clkdm_state_switch(clkdm); 929 930 return 0; 931 } 932 933 /** 934 * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm 935 * @clkdm: struct clockdomain * 936 * @clk: struct clk * of the disabled downstream clock 937 * 938 * Decrement the usecount of this clockdomain @clkdm when @clk is 939 * disabled. Intended to be called by clk_disable() code. If the 940 * clockdomain usecount goes to 0, put the clockdomain to sleep 941 * (software-supervised mode) or remove the clkdm autodependencies 942 * (hardware-supervised mode). Returns -EINVAL if passed null 943 * pointers; -ERANGE if the @clkdm usecount underflows and debugging 944 * is enabled; or returns 0 upon success or if the clockdomain is in 945 * hwsup idle mode. 946 */ 947 int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) 948 { 949 int v; 950 951 /* 952 * XXX Rewrite this code to maintain a list of enabled 953 * downstream clocks for debugging purposes? 954 */ 955 956 if (!clkdm || !clk) 957 return -EINVAL; 958 959 #ifdef DEBUG 960 if (atomic_read(&clkdm->usecount) == 0) { 961 WARN_ON(1); /* underflow */ 962 return -ERANGE; 963 } 964 #endif 965 966 if (atomic_dec_return(&clkdm->usecount) > 0) 967 return 0; 968 969 /* All downstream clocks of this clockdomain are now disabled */ 970 971 pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, 972 clk->name); 973 974 if (!clkdm->clkstctrl_reg) 975 return 0; 976 977 v = omap2_clkdm_clktrctrl_read(clkdm); 978 979 if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || 980 (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { 981 /* Disable HW transitions when we are changing deps */ 982 _omap2_clkdm_set_hwsup(clkdm, 0); 983 _clkdm_del_autodeps(clkdm); 984 _omap2_clkdm_set_hwsup(clkdm, 1); 985 } else { 986 omap2_clkdm_sleep(clkdm); 987 } 988 989 pwrdm_clkdm_state_switch(clkdm); 990 991 return 0; 992 } 993 994