clockdomain.c (38164B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * OMAP2/3/4 clockdomain framework functions 4 * 5 * Copyright (C) 2008-2011 Texas Instruments, Inc. 6 * Copyright (C) 2008-2011 Nokia Corporation 7 * 8 * Written by Paul Walmsley and Jouni Högander 9 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com> 10 */ 11#undef DEBUG 12 13#include <linux/kernel.h> 14#include <linux/device.h> 15#include <linux/list.h> 16#include <linux/errno.h> 17#include <linux/string.h> 18#include <linux/delay.h> 19#include <linux/clk.h> 20#include <linux/limits.h> 21#include <linux/err.h> 22#include <linux/clk-provider.h> 23#include <linux/cpu_pm.h> 24 25#include <linux/io.h> 26 27#include <linux/bitops.h> 28 29#include "soc.h" 30#include "clock.h" 31#include "clockdomain.h" 32#include "pm.h" 33 34/* clkdm_list contains all registered struct clockdomains */ 35static LIST_HEAD(clkdm_list); 36 37/* array of clockdomain deps to be added/removed when clkdm in hwsup mode */ 38static struct clkdm_autodep *autodeps; 39 40static struct clkdm_ops *arch_clkdm; 41void clkdm_save_context(void); 42void clkdm_restore_context(void); 43 44/* Private functions */ 45 46static struct clockdomain *_clkdm_lookup(const char *name) 47{ 48 struct clockdomain *clkdm, *temp_clkdm; 49 50 if (!name) 51 return NULL; 52 53 clkdm = NULL; 54 55 list_for_each_entry(temp_clkdm, &clkdm_list, node) { 56 if (!strcmp(name, temp_clkdm->name)) { 57 clkdm = temp_clkdm; 58 break; 59 } 60 } 61 62 return clkdm; 63} 64 65/** 66 * _clkdm_register - register a clockdomain 67 * @clkdm: struct clockdomain * to register 68 * 69 * Adds a clockdomain to the internal clockdomain list. 70 * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is 71 * already registered by the provided name, or 0 upon success. 72 */ 73static int _clkdm_register(struct clockdomain *clkdm) 74{ 75 struct powerdomain *pwrdm; 76 77 if (!clkdm || !clkdm->name) 78 return -EINVAL; 79 80 pwrdm = pwrdm_lookup(clkdm->pwrdm.name); 81 if (!pwrdm) { 82 pr_err("clockdomain: %s: powerdomain %s does not exist\n", 83 clkdm->name, clkdm->pwrdm.name); 84 return -EINVAL; 85 } 86 clkdm->pwrdm.ptr = pwrdm; 87 88 /* Verify that the clockdomain is not already registered */ 89 if (_clkdm_lookup(clkdm->name)) 90 return -EEXIST; 91 92 list_add(&clkdm->node, &clkdm_list); 93 94 pwrdm_add_clkdm(pwrdm, clkdm); 95 96 pr_debug("clockdomain: registered %s\n", clkdm->name); 97 98 return 0; 99} 100 101/* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */ 102static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm, 103 struct clkdm_dep *deps) 104{ 105 struct clkdm_dep *cd; 106 107 if (!clkdm || !deps) 108 return ERR_PTR(-EINVAL); 109 110 for (cd = deps; cd->clkdm_name; cd++) { 111 if (!cd->clkdm && cd->clkdm_name) 112 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 113 114 if (cd->clkdm == clkdm) 115 break; 116 } 117 118 if (!cd->clkdm_name) 119 return ERR_PTR(-ENOENT); 120 121 return cd; 122} 123 124/** 125 * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store 126 * @autodep: struct clkdm_autodep * to resolve 127 * 128 * Resolve autodep clockdomain names to clockdomain pointers via 129 * clkdm_lookup() and store the pointers in the autodep structure. An 130 * "autodep" is a clockdomain sleep/wakeup dependency that is 131 * automatically added and removed whenever clocks in the associated 132 * clockdomain are enabled or disabled (respectively) when the 133 * clockdomain is in hardware-supervised mode. Meant to be called 134 * once at clockdomain layer initialization, since these should remain 135 * fixed for a particular architecture. No return value. 136 * 137 * XXX autodeps are deprecated and should be removed at the earliest 138 * opportunity 139 */ 140static void _autodep_lookup(struct clkdm_autodep *autodep) 141{ 142 struct clockdomain *clkdm; 143 144 if (!autodep) 145 return; 146 147 clkdm = clkdm_lookup(autodep->clkdm.name); 148 if (!clkdm) { 149 pr_err("clockdomain: autodeps: clockdomain %s does not exist\n", 150 autodep->clkdm.name); 151 clkdm = ERR_PTR(-ENOENT); 152 } 153 autodep->clkdm.ptr = clkdm; 154} 155 156/** 157 * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms 158 * @clkdm: clockdomain that we are resolving dependencies for 159 * @clkdm_deps: ptr to array of struct clkdm_deps to resolve 160 * 161 * Iterates through @clkdm_deps, looking up the struct clockdomain named by 162 * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep. 163 * No return value. 164 */ 165static void _resolve_clkdm_deps(struct clockdomain *clkdm, 166 struct clkdm_dep *clkdm_deps) 167{ 168 struct clkdm_dep *cd; 169 170 for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) { 171 if (cd->clkdm) 172 continue; 173 cd->clkdm = _clkdm_lookup(cd->clkdm_name); 174 175 WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen", 176 clkdm->name, cd->clkdm_name); 177 } 178} 179 180/** 181 * _clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 (lockless) 182 * @clkdm1: wake this struct clockdomain * up (dependent) 183 * @clkdm2: when this struct clockdomain * wakes up (source) 184 * 185 * When the clockdomain represented by @clkdm2 wakes up, wake up 186 * @clkdm1. Implemented in hardware on the OMAP, this feature is 187 * designed to reduce wakeup latency of the dependent clockdomain @clkdm1. 188 * Returns -EINVAL if presented with invalid clockdomain pointers, 189 * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon 190 * success. 191 */ 192static int _clkdm_add_wkdep(struct clockdomain *clkdm1, 193 struct clockdomain *clkdm2) 194{ 195 struct clkdm_dep *cd; 196 int ret = 0; 197 198 if (!clkdm1 || !clkdm2) 199 return -EINVAL; 200 201 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 202 if (IS_ERR(cd)) 203 ret = PTR_ERR(cd); 204 205 if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep) 206 ret = -EINVAL; 207 208 if (ret) { 209 pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", 210 clkdm1->name, clkdm2->name); 211 return ret; 212 } 213 214 cd->wkdep_usecount++; 215 if (cd->wkdep_usecount == 1) { 216 pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n", 217 clkdm1->name, clkdm2->name); 218 219 ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2); 220 } 221 222 return ret; 223} 224 225/** 226 * _clkdm_del_wkdep - remove a wakeup dep from clkdm2 to clkdm1 (lockless) 227 * @clkdm1: wake this struct clockdomain * up (dependent) 228 * @clkdm2: when this struct clockdomain * wakes up (source) 229 * 230 * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2 231 * wakes up. Returns -EINVAL if presented with invalid clockdomain 232 * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 233 * 0 upon success. 234 */ 235static int _clkdm_del_wkdep(struct clockdomain *clkdm1, 236 struct clockdomain *clkdm2) 237{ 238 struct clkdm_dep *cd; 239 int ret = 0; 240 241 if (!clkdm1 || !clkdm2) 242 return -EINVAL; 243 244 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 245 if (IS_ERR(cd)) 246 ret = PTR_ERR(cd); 247 248 if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep) 249 ret = -EINVAL; 250 251 if (ret) { 252 pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", 253 clkdm1->name, clkdm2->name); 254 return ret; 255 } 256 257 cd->wkdep_usecount--; 258 if (cd->wkdep_usecount == 0) { 259 pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n", 260 clkdm1->name, clkdm2->name); 261 262 ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2); 263 } 264 265 return ret; 266} 267 268/** 269 * _clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 (lockless) 270 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 271 * @clkdm2: when this struct clockdomain * is active (source) 272 * 273 * Prevent @clkdm1 from automatically going inactive (and then to 274 * retention or off) if @clkdm2 is active. Returns -EINVAL if 275 * presented with invalid clockdomain pointers or called on a machine 276 * that does not support software-configurable hardware sleep 277 * dependencies, -ENOENT if the specified dependency cannot be set in 278 * hardware, or 0 upon success. 279 */ 280static int _clkdm_add_sleepdep(struct clockdomain *clkdm1, 281 struct clockdomain *clkdm2) 282{ 283 struct clkdm_dep *cd; 284 int ret = 0; 285 286 if (!clkdm1 || !clkdm2) 287 return -EINVAL; 288 289 cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); 290 if (IS_ERR(cd)) 291 ret = PTR_ERR(cd); 292 293 if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep) 294 ret = -EINVAL; 295 296 if (ret) { 297 pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", 298 clkdm1->name, clkdm2->name); 299 return ret; 300 } 301 302 cd->sleepdep_usecount++; 303 if (cd->sleepdep_usecount == 1) { 304 pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n", 305 clkdm1->name, clkdm2->name); 306 307 ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2); 308 } 309 310 return ret; 311} 312 313/** 314 * _clkdm_del_sleepdep - remove a sleep dep from clkdm2 to clkdm1 (lockless) 315 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 316 * @clkdm2: when this struct clockdomain * is active (source) 317 * 318 * Allow @clkdm1 to automatically go inactive (and then to retention or 319 * off), independent of the activity state of @clkdm2. Returns -EINVAL 320 * if presented with invalid clockdomain pointers or called on a machine 321 * that does not support software-configurable hardware sleep dependencies, 322 * -ENOENT if the specified dependency cannot be cleared in hardware, or 323 * 0 upon success. 324 */ 325static int _clkdm_del_sleepdep(struct clockdomain *clkdm1, 326 struct clockdomain *clkdm2) 327{ 328 struct clkdm_dep *cd; 329 int ret = 0; 330 331 if (!clkdm1 || !clkdm2) 332 return -EINVAL; 333 334 cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); 335 if (IS_ERR(cd)) 336 ret = PTR_ERR(cd); 337 338 if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep) 339 ret = -EINVAL; 340 341 if (ret) { 342 pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", 343 clkdm1->name, clkdm2->name); 344 return ret; 345 } 346 347 cd->sleepdep_usecount--; 348 if (cd->sleepdep_usecount == 0) { 349 pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n", 350 clkdm1->name, clkdm2->name); 351 352 ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2); 353 } 354 355 return ret; 356} 357 358/* Public functions */ 359 360/** 361 * clkdm_register_platform_funcs - register clockdomain implementation fns 362 * @co: func pointers for arch specific implementations 363 * 364 * Register the list of function pointers used to implement the 365 * clockdomain functions on different OMAP SoCs. Should be called 366 * before any other clkdm_register*() function. Returns -EINVAL if 367 * @co is null, -EEXIST if platform functions have already been 368 * registered, or 0 upon success. 369 */ 370int clkdm_register_platform_funcs(struct clkdm_ops *co) 371{ 372 if (!co) 373 return -EINVAL; 374 375 if (arch_clkdm) 376 return -EEXIST; 377 378 arch_clkdm = co; 379 380 return 0; 381}; 382 383/** 384 * clkdm_register_clkdms - register SoC clockdomains 385 * @cs: pointer to an array of struct clockdomain to register 386 * 387 * Register the clockdomains available on a particular OMAP SoC. Must 388 * be called after clkdm_register_platform_funcs(). May be called 389 * multiple times. Returns -EACCES if called before 390 * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is 391 * null; or 0 upon success. 392 */ 393int clkdm_register_clkdms(struct clockdomain **cs) 394{ 395 struct clockdomain **c = NULL; 396 397 if (!arch_clkdm) 398 return -EACCES; 399 400 if (!cs) 401 return -EINVAL; 402 403 for (c = cs; *c; c++) 404 _clkdm_register(*c); 405 406 return 0; 407} 408 409/** 410 * clkdm_register_autodeps - register autodeps (if required) 411 * @ia: pointer to a static array of struct clkdm_autodep to register 412 * 413 * Register clockdomain "automatic dependencies." These are 414 * clockdomain wakeup and sleep dependencies that are automatically 415 * added whenever the first clock inside a clockdomain is enabled, and 416 * removed whenever the last clock inside a clockdomain is disabled. 417 * These are currently only used on OMAP3 devices, and are deprecated, 418 * since they waste energy. However, until the OMAP2/3 IP block 419 * enable/disable sequence can be converted to match the OMAP4 420 * sequence, they are needed. 421 * 422 * Must be called only after all of the SoC clockdomains are 423 * registered, since the function will resolve autodep clockdomain 424 * names into clockdomain pointers. 425 * 426 * The struct clkdm_autodep @ia array must be static, as this function 427 * does not copy the array elements. 428 * 429 * Returns -EACCES if called before any clockdomains have been 430 * registered, -EINVAL if called with a null @ia argument, -EEXIST if 431 * autodeps have already been registered, or 0 upon success. 432 */ 433int clkdm_register_autodeps(struct clkdm_autodep *ia) 434{ 435 struct clkdm_autodep *a = NULL; 436 437 if (list_empty(&clkdm_list)) 438 return -EACCES; 439 440 if (!ia) 441 return -EINVAL; 442 443 if (autodeps) 444 return -EEXIST; 445 446 autodeps = ia; 447 for (a = autodeps; a->clkdm.ptr; a++) 448 _autodep_lookup(a); 449 450 return 0; 451} 452 453static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) 454{ 455 switch (cmd) { 456 case CPU_CLUSTER_PM_ENTER: 457 if (enable_off_mode) 458 clkdm_save_context(); 459 break; 460 case CPU_CLUSTER_PM_EXIT: 461 if (enable_off_mode) 462 clkdm_restore_context(); 463 break; 464 } 465 466 return NOTIFY_OK; 467} 468 469/** 470 * clkdm_complete_init - set up the clockdomain layer 471 * 472 * Put all clockdomains into software-supervised mode; PM code should 473 * later enable hardware-supervised mode as appropriate. Must be 474 * called after clkdm_register_clkdms(). Returns -EACCES if called 475 * before clkdm_register_clkdms(), or 0 upon success. 476 */ 477int clkdm_complete_init(void) 478{ 479 struct clockdomain *clkdm; 480 static struct notifier_block nb; 481 482 if (list_empty(&clkdm_list)) 483 return -EACCES; 484 485 list_for_each_entry(clkdm, &clkdm_list, node) { 486 clkdm_deny_idle(clkdm); 487 488 _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs); 489 clkdm_clear_all_wkdeps(clkdm); 490 491 _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs); 492 clkdm_clear_all_sleepdeps(clkdm); 493 } 494 495 /* Only AM43XX can lose clkdm context during rtc-ddr suspend */ 496 if (soc_is_am43xx()) { 497 nb.notifier_call = cpu_notifier; 498 cpu_pm_register_notifier(&nb); 499 } 500 501 return 0; 502} 503 504/** 505 * clkdm_lookup - look up a clockdomain by name, return a pointer 506 * @name: name of clockdomain 507 * 508 * Find a registered clockdomain by its name @name. Returns a pointer 509 * to the struct clockdomain if found, or NULL otherwise. 510 */ 511struct clockdomain *clkdm_lookup(const char *name) 512{ 513 struct clockdomain *clkdm, *temp_clkdm; 514 515 if (!name) 516 return NULL; 517 518 clkdm = NULL; 519 520 list_for_each_entry(temp_clkdm, &clkdm_list, node) { 521 if (!strcmp(name, temp_clkdm->name)) { 522 clkdm = temp_clkdm; 523 break; 524 } 525 } 526 527 return clkdm; 528} 529 530/** 531 * clkdm_for_each - call function on each registered clockdomain 532 * @fn: callback function * 533 * 534 * Call the supplied function @fn for each registered clockdomain. 535 * The callback function @fn can return anything but 0 to bail 536 * out early from the iterator. The callback function is called with 537 * the clkdm_mutex held, so no clockdomain structure manipulation 538 * functions should be called from the callback, although hardware 539 * clockdomain control functions are fine. Returns the last return 540 * value of the callback function, which should be 0 for success or 541 * anything else to indicate failure; or -EINVAL if the function pointer 542 * is null. 543 */ 544int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), 545 void *user) 546{ 547 struct clockdomain *clkdm; 548 int ret = 0; 549 550 if (!fn) 551 return -EINVAL; 552 553 list_for_each_entry(clkdm, &clkdm_list, node) { 554 ret = (*fn)(clkdm, user); 555 if (ret) 556 break; 557 } 558 559 return ret; 560} 561 562 563/** 564 * clkdm_get_pwrdm - return a ptr to the pwrdm that this clkdm resides in 565 * @clkdm: struct clockdomain * 566 * 567 * Return a pointer to the struct powerdomain that the specified clockdomain 568 * @clkdm exists in, or returns NULL if @clkdm is NULL. 569 */ 570struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) 571{ 572 if (!clkdm) 573 return NULL; 574 575 return clkdm->pwrdm.ptr; 576} 577 578 579/* Hardware clockdomain control */ 580 581/** 582 * clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 583 * @clkdm1: wake this struct clockdomain * up (dependent) 584 * @clkdm2: when this struct clockdomain * wakes up (source) 585 * 586 * When the clockdomain represented by @clkdm2 wakes up, wake up 587 * @clkdm1. Implemented in hardware on the OMAP, this feature is 588 * designed to reduce wakeup latency of the dependent clockdomain @clkdm1. 589 * Returns -EINVAL if presented with invalid clockdomain pointers, 590 * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon 591 * success. 592 */ 593int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 594{ 595 struct clkdm_dep *cd; 596 int ret; 597 598 if (!clkdm1 || !clkdm2) 599 return -EINVAL; 600 601 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 602 if (IS_ERR(cd)) 603 return PTR_ERR(cd); 604 605 pwrdm_lock(cd->clkdm->pwrdm.ptr); 606 ret = _clkdm_add_wkdep(clkdm1, clkdm2); 607 pwrdm_unlock(cd->clkdm->pwrdm.ptr); 608 609 return ret; 610} 611 612/** 613 * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1 614 * @clkdm1: wake this struct clockdomain * up (dependent) 615 * @clkdm2: when this struct clockdomain * wakes up (source) 616 * 617 * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2 618 * wakes up. Returns -EINVAL if presented with invalid clockdomain 619 * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 620 * 0 upon success. 621 */ 622int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 623{ 624 struct clkdm_dep *cd; 625 int ret; 626 627 if (!clkdm1 || !clkdm2) 628 return -EINVAL; 629 630 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 631 if (IS_ERR(cd)) 632 return PTR_ERR(cd); 633 634 pwrdm_lock(cd->clkdm->pwrdm.ptr); 635 ret = _clkdm_del_wkdep(clkdm1, clkdm2); 636 pwrdm_unlock(cd->clkdm->pwrdm.ptr); 637 638 return ret; 639} 640 641/** 642 * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1 643 * @clkdm1: wake this struct clockdomain * up (dependent) 644 * @clkdm2: when this struct clockdomain * wakes up (source) 645 * 646 * Return 1 if a hardware wakeup dependency exists wherein @clkdm1 will be 647 * awoken when @clkdm2 wakes up; 0 if dependency is not set; -EINVAL 648 * if either clockdomain pointer is invalid; or -ENOENT if the hardware 649 * is incapable. 650 * 651 * REVISIT: Currently this function only represents software-controllable 652 * wakeup dependencies. Wakeup dependencies fixed in hardware are not 653 * yet handled here. 654 */ 655int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 656{ 657 struct clkdm_dep *cd; 658 int ret = 0; 659 660 if (!clkdm1 || !clkdm2) 661 return -EINVAL; 662 663 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 664 if (IS_ERR(cd)) 665 ret = PTR_ERR(cd); 666 667 if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep) 668 ret = -EINVAL; 669 670 if (ret) { 671 pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n", 672 clkdm1->name, clkdm2->name); 673 return ret; 674 } 675 676 /* XXX It's faster to return the wkdep_usecount */ 677 return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2); 678} 679 680/** 681 * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm 682 * @clkdm: struct clockdomain * to remove all wakeup dependencies from 683 * 684 * Remove all inter-clockdomain wakeup dependencies that could cause 685 * @clkdm to wake. Intended to be used during boot to initialize the 686 * PRCM to a known state, after all clockdomains are put into swsup idle 687 * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or 688 * 0 upon success. 689 */ 690int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) 691{ 692 if (!clkdm) 693 return -EINVAL; 694 695 if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps) 696 return -EINVAL; 697 698 return arch_clkdm->clkdm_clear_all_wkdeps(clkdm); 699} 700 701/** 702 * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 703 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 704 * @clkdm2: when this struct clockdomain * is active (source) 705 * 706 * Prevent @clkdm1 from automatically going inactive (and then to 707 * retention or off) if @clkdm2 is active. Returns -EINVAL if 708 * presented with invalid clockdomain pointers or called on a machine 709 * that does not support software-configurable hardware sleep 710 * dependencies, -ENOENT if the specified dependency cannot be set in 711 * hardware, or 0 upon success. 712 */ 713int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 714{ 715 struct clkdm_dep *cd; 716 int ret; 717 718 if (!clkdm1 || !clkdm2) 719 return -EINVAL; 720 721 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 722 if (IS_ERR(cd)) 723 return PTR_ERR(cd); 724 725 pwrdm_lock(cd->clkdm->pwrdm.ptr); 726 ret = _clkdm_add_sleepdep(clkdm1, clkdm2); 727 pwrdm_unlock(cd->clkdm->pwrdm.ptr); 728 729 return ret; 730} 731 732/** 733 * clkdm_del_sleepdep - remove a sleep dependency from clkdm2 to clkdm1 734 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 735 * @clkdm2: when this struct clockdomain * is active (source) 736 * 737 * Allow @clkdm1 to automatically go inactive (and then to retention or 738 * off), independent of the activity state of @clkdm2. Returns -EINVAL 739 * if presented with invalid clockdomain pointers or called on a machine 740 * that does not support software-configurable hardware sleep dependencies, 741 * -ENOENT if the specified dependency cannot be cleared in hardware, or 742 * 0 upon success. 743 */ 744int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 745{ 746 struct clkdm_dep *cd; 747 int ret; 748 749 if (!clkdm1 || !clkdm2) 750 return -EINVAL; 751 752 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); 753 if (IS_ERR(cd)) 754 return PTR_ERR(cd); 755 756 pwrdm_lock(cd->clkdm->pwrdm.ptr); 757 ret = _clkdm_del_sleepdep(clkdm1, clkdm2); 758 pwrdm_unlock(cd->clkdm->pwrdm.ptr); 759 760 return ret; 761} 762 763/** 764 * clkdm_read_sleepdep - read sleep dependency state from clkdm2 to clkdm1 765 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent) 766 * @clkdm2: when this struct clockdomain * is active (source) 767 * 768 * Return 1 if a hardware sleep dependency exists wherein @clkdm1 will 769 * not be allowed to automatically go inactive if @clkdm2 is active; 770 * 0 if @clkdm1's automatic power state inactivity transition is independent 771 * of @clkdm2's; -EINVAL if either clockdomain pointer is invalid or called 772 * on a machine that does not support software-configurable hardware sleep 773 * dependencies; or -ENOENT if the hardware is incapable. 774 * 775 * REVISIT: Currently this function only represents software-controllable 776 * sleep dependencies. Sleep dependencies fixed in hardware are not 777 * yet handled here. 778 */ 779int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) 780{ 781 struct clkdm_dep *cd; 782 int ret = 0; 783 784 if (!clkdm1 || !clkdm2) 785 return -EINVAL; 786 787 cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); 788 if (IS_ERR(cd)) 789 ret = PTR_ERR(cd); 790 791 if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep) 792 ret = -EINVAL; 793 794 if (ret) { 795 pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n", 796 clkdm1->name, clkdm2->name); 797 return ret; 798 } 799 800 /* XXX It's faster to return the sleepdep_usecount */ 801 return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2); 802} 803 804/** 805 * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm 806 * @clkdm: struct clockdomain * to remove all sleep dependencies from 807 * 808 * Remove all inter-clockdomain sleep dependencies that could prevent 809 * @clkdm from idling. Intended to be used during boot to initialize the 810 * PRCM to a known state, after all clockdomains are put into swsup idle 811 * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or 812 * 0 upon success. 813 */ 814int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) 815{ 816 if (!clkdm) 817 return -EINVAL; 818 819 if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps) 820 return -EINVAL; 821 822 return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm); 823} 824 825/** 826 * clkdm_sleep_nolock - force clockdomain sleep transition (lockless) 827 * @clkdm: struct clockdomain * 828 * 829 * Instruct the CM to force a sleep transition on the specified 830 * clockdomain @clkdm. Only for use by the powerdomain code. Returns 831 * -EINVAL if @clkdm is NULL or if clockdomain does not support 832 * software-initiated sleep; 0 upon success. 833 */ 834int clkdm_sleep_nolock(struct clockdomain *clkdm) 835{ 836 int ret; 837 838 if (!clkdm) 839 return -EINVAL; 840 841 if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) { 842 pr_debug("clockdomain: %s does not support forcing sleep via software\n", 843 clkdm->name); 844 return -EINVAL; 845 } 846 847 if (!arch_clkdm || !arch_clkdm->clkdm_sleep) 848 return -EINVAL; 849 850 pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); 851 852 clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; 853 ret = arch_clkdm->clkdm_sleep(clkdm); 854 ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); 855 856 return ret; 857} 858 859/** 860 * clkdm_sleep - force clockdomain sleep transition 861 * @clkdm: struct clockdomain * 862 * 863 * Instruct the CM to force a sleep transition on the specified 864 * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if 865 * clockdomain does not support software-initiated sleep; 0 upon 866 * success. 867 */ 868int clkdm_sleep(struct clockdomain *clkdm) 869{ 870 int ret; 871 872 pwrdm_lock(clkdm->pwrdm.ptr); 873 ret = clkdm_sleep_nolock(clkdm); 874 pwrdm_unlock(clkdm->pwrdm.ptr); 875 876 return ret; 877} 878 879/** 880 * clkdm_wakeup_nolock - force clockdomain wakeup transition (lockless) 881 * @clkdm: struct clockdomain * 882 * 883 * Instruct the CM to force a wakeup transition on the specified 884 * clockdomain @clkdm. Only for use by the powerdomain code. Returns 885 * -EINVAL if @clkdm is NULL or if the clockdomain does not support 886 * software-controlled wakeup; 0 upon success. 887 */ 888int clkdm_wakeup_nolock(struct clockdomain *clkdm) 889{ 890 int ret; 891 892 if (!clkdm) 893 return -EINVAL; 894 895 if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) { 896 pr_debug("clockdomain: %s does not support forcing wakeup via software\n", 897 clkdm->name); 898 return -EINVAL; 899 } 900 901 if (!arch_clkdm || !arch_clkdm->clkdm_wakeup) 902 return -EINVAL; 903 904 pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); 905 906 clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; 907 ret = arch_clkdm->clkdm_wakeup(clkdm); 908 ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); 909 910 return ret; 911} 912 913/** 914 * clkdm_wakeup - force clockdomain wakeup transition 915 * @clkdm: struct clockdomain * 916 * 917 * Instruct the CM to force a wakeup transition on the specified 918 * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if the 919 * clockdomain does not support software-controlled wakeup; 0 upon 920 * success. 921 */ 922int clkdm_wakeup(struct clockdomain *clkdm) 923{ 924 int ret; 925 926 pwrdm_lock(clkdm->pwrdm.ptr); 927 ret = clkdm_wakeup_nolock(clkdm); 928 pwrdm_unlock(clkdm->pwrdm.ptr); 929 930 return ret; 931} 932 933/** 934 * clkdm_allow_idle_nolock - enable hwsup idle transitions for clkdm 935 * @clkdm: struct clockdomain * 936 * 937 * Allow the hardware to automatically switch the clockdomain @clkdm 938 * into active or idle states, as needed by downstream clocks. If the 939 * clockdomain has any downstream clocks enabled in the clock 940 * framework, wkdep/sleepdep autodependencies are added; this is so 941 * device drivers can read and write to the device. Only for use by 942 * the powerdomain code. No return value. 943 */ 944void clkdm_allow_idle_nolock(struct clockdomain *clkdm) 945{ 946 if (!clkdm) 947 return; 948 949 if (!WARN_ON(!clkdm->forcewake_count)) 950 clkdm->forcewake_count--; 951 952 if (clkdm->forcewake_count) 953 return; 954 955 if (!clkdm->usecount && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) 956 clkdm_sleep_nolock(clkdm); 957 958 if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) 959 return; 960 961 if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) 962 return; 963 964 if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle) 965 return; 966 967 pr_debug("clockdomain: enabling automatic idle transitions for %s\n", 968 clkdm->name); 969 970 clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED; 971 arch_clkdm->clkdm_allow_idle(clkdm); 972 pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); 973} 974 975/** 976 * clkdm_allow_idle - enable hwsup idle transitions for clkdm 977 * @clkdm: struct clockdomain * 978 * 979 * Allow the hardware to automatically switch the clockdomain @clkdm into 980 * active or idle states, as needed by downstream clocks. If the 981 * clockdomain has any downstream clocks enabled in the clock 982 * framework, wkdep/sleepdep autodependencies are added; this is so 983 * device drivers can read and write to the device. No return value. 984 */ 985void clkdm_allow_idle(struct clockdomain *clkdm) 986{ 987 pwrdm_lock(clkdm->pwrdm.ptr); 988 clkdm_allow_idle_nolock(clkdm); 989 pwrdm_unlock(clkdm->pwrdm.ptr); 990} 991 992/** 993 * clkdm_deny_idle - disable hwsup idle transitions for clkdm 994 * @clkdm: struct clockdomain * 995 * 996 * Prevent the hardware from automatically switching the clockdomain 997 * @clkdm into inactive or idle states. If the clockdomain has 998 * downstream clocks enabled in the clock framework, wkdep/sleepdep 999 * autodependencies are removed. Only for use by the powerdomain 1000 * code. No return value. 1001 */ 1002void clkdm_deny_idle_nolock(struct clockdomain *clkdm) 1003{ 1004 if (!clkdm) 1005 return; 1006 1007 if (clkdm->forcewake_count++) 1008 return; 1009 1010 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) 1011 clkdm_wakeup_nolock(clkdm); 1012 1013 if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) 1014 return; 1015 1016 if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) 1017 return; 1018 1019 if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle) 1020 return; 1021 1022 pr_debug("clockdomain: disabling automatic idle transitions for %s\n", 1023 clkdm->name); 1024 1025 clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; 1026 arch_clkdm->clkdm_deny_idle(clkdm); 1027 pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); 1028} 1029 1030/** 1031 * clkdm_deny_idle - disable hwsup idle transitions for clkdm 1032 * @clkdm: struct clockdomain * 1033 * 1034 * Prevent the hardware from automatically switching the clockdomain 1035 * @clkdm into inactive or idle states. If the clockdomain has 1036 * downstream clocks enabled in the clock framework, wkdep/sleepdep 1037 * autodependencies are removed. No return value. 1038 */ 1039void clkdm_deny_idle(struct clockdomain *clkdm) 1040{ 1041 pwrdm_lock(clkdm->pwrdm.ptr); 1042 clkdm_deny_idle_nolock(clkdm); 1043 pwrdm_unlock(clkdm->pwrdm.ptr); 1044} 1045 1046/** 1047 * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled? 1048 * @clkdm: struct clockdomain * 1049 * 1050 * Returns true if clockdomain @clkdm currently has 1051 * hardware-supervised idle enabled, or false if it does not or if 1052 * @clkdm is NULL. It is only valid to call this function after 1053 * clkdm_init() has been called. This function does not actually read 1054 * bits from the hardware; it instead tests an in-memory flag that is 1055 * changed whenever the clockdomain code changes the auto-idle mode. 1056 */ 1057bool clkdm_in_hwsup(struct clockdomain *clkdm) 1058{ 1059 bool ret; 1060 1061 if (!clkdm) 1062 return false; 1063 1064 ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false; 1065 1066 return ret; 1067} 1068 1069/** 1070 * clkdm_missing_idle_reporting - can @clkdm enter autoidle even if in use? 1071 * @clkdm: struct clockdomain * 1072 * 1073 * Returns true if clockdomain @clkdm has the 1074 * CLKDM_MISSING_IDLE_REPORTING flag set, or false if not or @clkdm is 1075 * null. More information is available in the documentation for the 1076 * CLKDM_MISSING_IDLE_REPORTING macro. 1077 */ 1078bool clkdm_missing_idle_reporting(struct clockdomain *clkdm) 1079{ 1080 if (!clkdm) 1081 return false; 1082 1083 return (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) ? true : false; 1084} 1085 1086/* Public autodep handling functions (deprecated) */ 1087 1088/** 1089 * clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable 1090 * @clkdm: struct clockdomain * 1091 * 1092 * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm' 1093 * in hardware-supervised mode. Meant to be called from clock framework 1094 * when a clock inside clockdomain 'clkdm' is enabled. No return value. 1095 * 1096 * XXX autodeps are deprecated and should be removed at the earliest 1097 * opportunity 1098 */ 1099void clkdm_add_autodeps(struct clockdomain *clkdm) 1100{ 1101 struct clkdm_autodep *autodep; 1102 1103 if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) 1104 return; 1105 1106 for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { 1107 if (IS_ERR(autodep->clkdm.ptr)) 1108 continue; 1109 1110 pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n", 1111 clkdm->name, autodep->clkdm.ptr->name); 1112 1113 _clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr); 1114 _clkdm_add_wkdep(clkdm, autodep->clkdm.ptr); 1115 } 1116} 1117 1118/** 1119 * clkdm_del_autodeps - remove auto sleepdeps/wkdeps from clkdm 1120 * @clkdm: struct clockdomain * 1121 * 1122 * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm' 1123 * in hardware-supervised mode. Meant to be called from clock framework 1124 * when a clock inside clockdomain 'clkdm' is disabled. No return value. 1125 * 1126 * XXX autodeps are deprecated and should be removed at the earliest 1127 * opportunity 1128 */ 1129void clkdm_del_autodeps(struct clockdomain *clkdm) 1130{ 1131 struct clkdm_autodep *autodep; 1132 1133 if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) 1134 return; 1135 1136 for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { 1137 if (IS_ERR(autodep->clkdm.ptr)) 1138 continue; 1139 1140 pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n", 1141 clkdm->name, autodep->clkdm.ptr->name); 1142 1143 _clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr); 1144 _clkdm_del_wkdep(clkdm, autodep->clkdm.ptr); 1145 } 1146} 1147 1148/* Clockdomain-to-clock/hwmod framework interface code */ 1149 1150/** 1151 * clkdm_clk_enable - add an enabled downstream clock to this clkdm 1152 * @clkdm: struct clockdomain * 1153 * @clk: struct clk * of the enabled downstream clock 1154 * 1155 * Increment the usecount of the clockdomain @clkdm and ensure that it 1156 * is awake before @clk is enabled. Intended to be called by 1157 * clk_enable() code. If the clockdomain is in software-supervised 1158 * idle mode, force the clockdomain to wake. If the clockdomain is in 1159 * hardware-supervised idle mode, add clkdm-pwrdm autodependencies, to 1160 * ensure that devices in the clockdomain can be read from/written to 1161 * by on-chip processors. Returns -EINVAL if passed null pointers; 1162 * returns 0 upon success or if the clockdomain is in hwsup idle mode. 1163 */ 1164int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *unused) 1165{ 1166 if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable) 1167 return -EINVAL; 1168 1169 pwrdm_lock(clkdm->pwrdm.ptr); 1170 1171 /* 1172 * For arch's with no autodeps, clkcm_clk_enable 1173 * should be called for every clock instance or hwmod that is 1174 * enabled, so the clkdm can be force woken up. 1175 */ 1176 clkdm->usecount++; 1177 if (clkdm->usecount > 1 && autodeps) { 1178 pwrdm_unlock(clkdm->pwrdm.ptr); 1179 return 0; 1180 } 1181 1182 arch_clkdm->clkdm_clk_enable(clkdm); 1183 pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); 1184 pwrdm_unlock(clkdm->pwrdm.ptr); 1185 1186 pr_debug("clockdomain: %s: enabled\n", clkdm->name); 1187 1188 return 0; 1189} 1190 1191/** 1192 * clkdm_clk_disable - remove an enabled downstream clock from this clkdm 1193 * @clkdm: struct clockdomain * 1194 * @clk: struct clk * of the disabled downstream clock 1195 * 1196 * Decrement the usecount of this clockdomain @clkdm when @clk is 1197 * disabled. Intended to be called by clk_disable() code. If the 1198 * clockdomain usecount goes to 0, put the clockdomain to sleep 1199 * (software-supervised mode) or remove the clkdm autodependencies 1200 * (hardware-supervised mode). Returns -EINVAL if passed null 1201 * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0 1202 * upon success or if the clockdomain is in hwsup idle mode. 1203 */ 1204int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) 1205{ 1206 if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) 1207 return -EINVAL; 1208 1209 pwrdm_lock(clkdm->pwrdm.ptr); 1210 1211 /* corner case: disabling unused clocks */ 1212 if (clk && (__clk_get_enable_count(clk) == 0) && clkdm->usecount == 0) 1213 goto ccd_exit; 1214 1215 if (clkdm->usecount == 0) { 1216 pwrdm_unlock(clkdm->pwrdm.ptr); 1217 WARN_ON(1); /* underflow */ 1218 return -ERANGE; 1219 } 1220 1221 clkdm->usecount--; 1222 if (clkdm->usecount > 0) { 1223 pwrdm_unlock(clkdm->pwrdm.ptr); 1224 return 0; 1225 } 1226 1227 arch_clkdm->clkdm_clk_disable(clkdm); 1228 pwrdm_state_switch_nolock(clkdm->pwrdm.ptr); 1229 1230 pr_debug("clockdomain: %s: disabled\n", clkdm->name); 1231 1232ccd_exit: 1233 pwrdm_unlock(clkdm->pwrdm.ptr); 1234 1235 return 0; 1236} 1237 1238/** 1239 * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm 1240 * @clkdm: struct clockdomain * 1241 * @oh: struct omap_hwmod * of the enabled downstream hwmod 1242 * 1243 * Increment the usecount of the clockdomain @clkdm and ensure that it 1244 * is awake before @oh is enabled. Intended to be called by 1245 * module_enable() code. 1246 * If the clockdomain is in software-supervised idle mode, force the 1247 * clockdomain to wake. If the clockdomain is in hardware-supervised idle 1248 * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the 1249 * clockdomain can be read from/written to by on-chip processors. 1250 * Returns -EINVAL if passed null pointers; 1251 * returns 0 upon success or if the clockdomain is in hwsup idle mode. 1252 */ 1253int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh) 1254{ 1255 /* The clkdm attribute does not exist yet prior OMAP4 */ 1256 if (cpu_is_omap24xx() || cpu_is_omap34xx()) 1257 return 0; 1258 1259 /* 1260 * XXX Rewrite this code to maintain a list of enabled 1261 * downstream hwmods for debugging purposes? 1262 */ 1263 1264 if (!oh) 1265 return -EINVAL; 1266 1267 return clkdm_clk_enable(clkdm, NULL); 1268} 1269 1270/** 1271 * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm 1272 * @clkdm: struct clockdomain * 1273 * @oh: struct omap_hwmod * of the disabled downstream hwmod 1274 * 1275 * Decrement the usecount of this clockdomain @clkdm when @oh is 1276 * disabled. Intended to be called by module_disable() code. 1277 * If the clockdomain usecount goes to 0, put the clockdomain to sleep 1278 * (software-supervised mode) or remove the clkdm autodependencies 1279 * (hardware-supervised mode). 1280 * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount 1281 * underflows; or returns 0 upon success or if the clockdomain is in hwsup 1282 * idle mode. 1283 */ 1284int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) 1285{ 1286 /* The clkdm attribute does not exist yet prior OMAP4 */ 1287 if (cpu_is_omap24xx() || cpu_is_omap34xx()) 1288 return 0; 1289 1290 if (!oh) 1291 return -EINVAL; 1292 1293 return clkdm_clk_disable(clkdm, NULL); 1294} 1295 1296/** 1297 * _clkdm_save_context - save the context for the control of this clkdm 1298 * 1299 * Due to a suspend or hibernation operation, the state of the registers 1300 * controlling this clkdm will be lost, save their context. 1301 */ 1302static int _clkdm_save_context(struct clockdomain *clkdm, void *unused) 1303{ 1304 if (!arch_clkdm || !arch_clkdm->clkdm_save_context) 1305 return -EINVAL; 1306 1307 return arch_clkdm->clkdm_save_context(clkdm); 1308} 1309 1310/** 1311 * _clkdm_restore_context - restore context for control of this clkdm 1312 * 1313 * Restore the register values for this clockdomain. 1314 */ 1315static int _clkdm_restore_context(struct clockdomain *clkdm, void *unused) 1316{ 1317 if (!arch_clkdm || !arch_clkdm->clkdm_restore_context) 1318 return -EINVAL; 1319 1320 return arch_clkdm->clkdm_restore_context(clkdm); 1321} 1322 1323/** 1324 * clkdm_save_context - Saves the context for each registered clkdm 1325 * 1326 * Save the context for each registered clockdomain. 1327 */ 1328void clkdm_save_context(void) 1329{ 1330 clkdm_for_each(_clkdm_save_context, NULL); 1331} 1332 1333/** 1334 * clkdm_restore_context - Restores the context for each registered clkdm 1335 * 1336 * Restore the context for each registered clockdomain. 1337 */ 1338void clkdm_restore_context(void) 1339{ 1340 clkdm_for_each(_clkdm_restore_context, NULL); 1341}