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