1 /* 2 * OMAP powerdomain control 3 * 4 * Copyright (C) 2007-2008 Texas Instruments, Inc. 5 * Copyright (C) 2007-2008 Nokia Corporation 6 * 7 * Written by Paul Walmsley 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 #ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN 14 # define DEBUG 15 #endif 16 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/types.h> 20 #include <linux/delay.h> 21 #include <linux/spinlock.h> 22 #include <linux/list.h> 23 #include <linux/errno.h> 24 #include <linux/err.h> 25 #include <linux/io.h> 26 27 #include <asm/atomic.h> 28 29 #include "cm.h" 30 #include "cm-regbits-34xx.h" 31 #include "prm.h" 32 #include "prm-regbits-34xx.h" 33 34 #include <mach/cpu.h> 35 #include <mach/powerdomain.h> 36 #include <mach/clockdomain.h> 37 38 /* pwrdm_list contains all registered struct powerdomains */ 39 static LIST_HEAD(pwrdm_list); 40 41 /* 42 * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to 43 * protect pwrdm_clkdms[] during clkdm add/del ops 44 */ 45 static DEFINE_RWLOCK(pwrdm_rwlock); 46 47 48 /* Private functions */ 49 50 static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask) 51 { 52 u32 v; 53 54 v = prm_read_mod_reg(domain, idx); 55 v &= mask; 56 v >>= __ffs(mask); 57 58 return v; 59 } 60 61 static struct powerdomain *_pwrdm_lookup(const char *name) 62 { 63 struct powerdomain *pwrdm, *temp_pwrdm; 64 65 pwrdm = NULL; 66 67 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { 68 if (!strcmp(name, temp_pwrdm->name)) { 69 pwrdm = temp_pwrdm; 70 break; 71 } 72 } 73 74 return pwrdm; 75 } 76 77 /* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */ 78 static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm, 79 struct pwrdm_dep *deps) 80 { 81 struct pwrdm_dep *pd; 82 83 if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip)) 84 return ERR_PTR(-EINVAL); 85 86 for (pd = deps; pd; pd++) { 87 88 if (!omap_chip_is(pd->omap_chip)) 89 continue; 90 91 if (!pd->pwrdm && pd->pwrdm_name) 92 pd->pwrdm = pwrdm_lookup(pd->pwrdm_name); 93 94 if (pd->pwrdm == pwrdm) 95 break; 96 97 } 98 99 if (!pd) 100 return ERR_PTR(-ENOENT); 101 102 return pd->pwrdm; 103 } 104 105 106 /* Public functions */ 107 108 /** 109 * pwrdm_init - set up the powerdomain layer 110 * 111 * Loop through the list of powerdomains, registering all that are 112 * available on the current CPU. If pwrdm_list is supplied and not 113 * null, all of the referenced powerdomains will be registered. No 114 * return value. 115 */ 116 void pwrdm_init(struct powerdomain **pwrdm_list) 117 { 118 struct powerdomain **p = NULL; 119 120 if (pwrdm_list) 121 for (p = pwrdm_list; *p; p++) 122 pwrdm_register(*p); 123 } 124 125 /** 126 * pwrdm_register - register a powerdomain 127 * @pwrdm: struct powerdomain * to register 128 * 129 * Adds a powerdomain to the internal powerdomain list. Returns 130 * -EINVAL if given a null pointer, -EEXIST if a powerdomain is 131 * already registered by the provided name, or 0 upon success. 132 */ 133 int pwrdm_register(struct powerdomain *pwrdm) 134 { 135 unsigned long flags; 136 int ret = -EINVAL; 137 138 if (!pwrdm) 139 return -EINVAL; 140 141 if (!omap_chip_is(pwrdm->omap_chip)) 142 return -EINVAL; 143 144 write_lock_irqsave(&pwrdm_rwlock, flags); 145 if (_pwrdm_lookup(pwrdm->name)) { 146 ret = -EEXIST; 147 goto pr_unlock; 148 } 149 150 list_add(&pwrdm->node, &pwrdm_list); 151 152 pr_debug("powerdomain: registered %s\n", pwrdm->name); 153 ret = 0; 154 155 pr_unlock: 156 write_unlock_irqrestore(&pwrdm_rwlock, flags); 157 158 return ret; 159 } 160 161 /** 162 * pwrdm_unregister - unregister a powerdomain 163 * @pwrdm: struct powerdomain * to unregister 164 * 165 * Removes a powerdomain from the internal powerdomain list. Returns 166 * -EINVAL if pwrdm argument is NULL. 167 */ 168 int pwrdm_unregister(struct powerdomain *pwrdm) 169 { 170 unsigned long flags; 171 172 if (!pwrdm) 173 return -EINVAL; 174 175 write_lock_irqsave(&pwrdm_rwlock, flags); 176 list_del(&pwrdm->node); 177 write_unlock_irqrestore(&pwrdm_rwlock, flags); 178 179 pr_debug("powerdomain: unregistered %s\n", pwrdm->name); 180 181 return 0; 182 } 183 184 /** 185 * pwrdm_lookup - look up a powerdomain by name, return a pointer 186 * @name: name of powerdomain 187 * 188 * Find a registered powerdomain by its name. Returns a pointer to the 189 * struct powerdomain if found, or NULL otherwise. 190 */ 191 struct powerdomain *pwrdm_lookup(const char *name) 192 { 193 struct powerdomain *pwrdm; 194 unsigned long flags; 195 196 if (!name) 197 return NULL; 198 199 read_lock_irqsave(&pwrdm_rwlock, flags); 200 pwrdm = _pwrdm_lookup(name); 201 read_unlock_irqrestore(&pwrdm_rwlock, flags); 202 203 return pwrdm; 204 } 205 206 /** 207 * pwrdm_for_each - call function on each registered clockdomain 208 * @fn: callback function * 209 * 210 * Call the supplied function for each registered powerdomain. The 211 * callback function can return anything but 0 to bail out early from 212 * the iterator. The callback function is called with the pwrdm_rwlock 213 * held for reading, so no powerdomain structure manipulation 214 * functions should be called from the callback, although hardware 215 * powerdomain control functions are fine. Returns the last return 216 * value of the callback function, which should be 0 for success or 217 * anything else to indicate failure; or -EINVAL if the function 218 * pointer is null. 219 */ 220 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) 221 { 222 struct powerdomain *temp_pwrdm; 223 unsigned long flags; 224 int ret = 0; 225 226 if (!fn) 227 return -EINVAL; 228 229 read_lock_irqsave(&pwrdm_rwlock, flags); 230 list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { 231 ret = (*fn)(temp_pwrdm); 232 if (ret) 233 break; 234 } 235 read_unlock_irqrestore(&pwrdm_rwlock, flags); 236 237 return ret; 238 } 239 240 /** 241 * pwrdm_add_clkdm - add a clockdomain to a powerdomain 242 * @pwrdm: struct powerdomain * to add the clockdomain to 243 * @clkdm: struct clockdomain * to associate with a powerdomain 244 * 245 * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'. This 246 * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if 247 * presented with invalid pointers; -ENOMEM if memory could not be allocated; 248 * or 0 upon success. 249 */ 250 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) 251 { 252 unsigned long flags; 253 int i; 254 int ret = -EINVAL; 255 256 if (!pwrdm || !clkdm) 257 return -EINVAL; 258 259 pr_debug("powerdomain: associating clockdomain %s with powerdomain " 260 "%s\n", clkdm->name, pwrdm->name); 261 262 write_lock_irqsave(&pwrdm_rwlock, flags); 263 264 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) { 265 if (!pwrdm->pwrdm_clkdms[i]) 266 break; 267 #ifdef DEBUG 268 if (pwrdm->pwrdm_clkdms[i] == clkdm) { 269 ret = -EINVAL; 270 goto pac_exit; 271 } 272 #endif 273 } 274 275 if (i == PWRDM_MAX_CLKDMS) { 276 pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for " 277 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name); 278 WARN_ON(1); 279 ret = -ENOMEM; 280 goto pac_exit; 281 } 282 283 pwrdm->pwrdm_clkdms[i] = clkdm; 284 285 ret = 0; 286 287 pac_exit: 288 write_unlock_irqrestore(&pwrdm_rwlock, flags); 289 290 return ret; 291 } 292 293 /** 294 * pwrdm_del_clkdm - remove a clockdomain from a powerdomain 295 * @pwrdm: struct powerdomain * to add the clockdomain to 296 * @clkdm: struct clockdomain * to associate with a powerdomain 297 * 298 * Dissociate the clockdomain 'clkdm' from the powerdomain 299 * 'pwrdm'. Returns -EINVAL if presented with invalid pointers; 300 * -ENOENT if the clkdm was not associated with the powerdomain, or 0 301 * upon success. 302 */ 303 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) 304 { 305 unsigned long flags; 306 int ret = -EINVAL; 307 int i; 308 309 if (!pwrdm || !clkdm) 310 return -EINVAL; 311 312 pr_debug("powerdomain: dissociating clockdomain %s from powerdomain " 313 "%s\n", clkdm->name, pwrdm->name); 314 315 write_lock_irqsave(&pwrdm_rwlock, flags); 316 317 for (i = 0; i < PWRDM_MAX_CLKDMS; i++) 318 if (pwrdm->pwrdm_clkdms[i] == clkdm) 319 break; 320 321 if (i == PWRDM_MAX_CLKDMS) { 322 pr_debug("powerdomain: clkdm %s not associated with pwrdm " 323 "%s ?!\n", clkdm->name, pwrdm->name); 324 ret = -ENOENT; 325 goto pdc_exit; 326 } 327 328 pwrdm->pwrdm_clkdms[i] = NULL; 329 330 ret = 0; 331 332 pdc_exit: 333 write_unlock_irqrestore(&pwrdm_rwlock, flags); 334 335 return ret; 336 } 337 338 /** 339 * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm 340 * @pwrdm: struct powerdomain * to iterate over 341 * @fn: callback function * 342 * 343 * Call the supplied function for each clockdomain in the powerdomain 344 * 'pwrdm'. The callback function can return anything but 0 to bail 345 * out early from the iterator. The callback function is called with 346 * the pwrdm_rwlock held for reading, so no powerdomain structure 347 * manipulation functions should be called from the callback, although 348 * hardware powerdomain control functions are fine. Returns -EINVAL 349 * if presented with invalid pointers; or passes along the last return 350 * value of the callback function, which should be 0 for success or 351 * anything else to indicate failure. 352 */ 353 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, 354 int (*fn)(struct powerdomain *pwrdm, 355 struct clockdomain *clkdm)) 356 { 357 unsigned long flags; 358 int ret = 0; 359 int i; 360 361 if (!fn) 362 return -EINVAL; 363 364 read_lock_irqsave(&pwrdm_rwlock, flags); 365 366 for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++) 367 ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]); 368 369 read_unlock_irqrestore(&pwrdm_rwlock, flags); 370 371 return ret; 372 } 373 374 375 /** 376 * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1 377 * @pwrdm1: wake this struct powerdomain * up (dependent) 378 * @pwrdm2: when this struct powerdomain * wakes up (source) 379 * 380 * When the powerdomain represented by pwrdm2 wakes up (due to an 381 * interrupt), wake up pwrdm1. Implemented in hardware on the OMAP, 382 * this feature is designed to reduce wakeup latency of the dependent 383 * powerdomain. Returns -EINVAL if presented with invalid powerdomain 384 * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or 385 * 0 upon success. 386 */ 387 int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) 388 { 389 struct powerdomain *p; 390 391 if (!pwrdm1) 392 return -EINVAL; 393 394 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs); 395 if (IS_ERR(p)) { 396 pr_debug("powerdomain: hardware cannot set/clear wake up of " 397 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); 398 return IS_ERR(p); 399 } 400 401 pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n", 402 pwrdm1->name, pwrdm2->name); 403 404 prm_set_mod_reg_bits((1 << pwrdm2->dep_bit), 405 pwrdm1->prcm_offs, PM_WKDEP); 406 407 return 0; 408 } 409 410 /** 411 * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1 412 * @pwrdm1: wake this struct powerdomain * up (dependent) 413 * @pwrdm2: when this struct powerdomain * wakes up (source) 414 * 415 * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2 416 * wakes up. Returns -EINVAL if presented with invalid powerdomain 417 * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or 418 * 0 upon success. 419 */ 420 int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) 421 { 422 struct powerdomain *p; 423 424 if (!pwrdm1) 425 return -EINVAL; 426 427 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs); 428 if (IS_ERR(p)) { 429 pr_debug("powerdomain: hardware cannot set/clear wake up of " 430 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); 431 return IS_ERR(p); 432 } 433 434 pr_debug("powerdomain: hardware will no longer wake up %s after %s " 435 "wakes up\n", pwrdm1->name, pwrdm2->name); 436 437 prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit), 438 pwrdm1->prcm_offs, PM_WKDEP); 439 440 return 0; 441 } 442 443 /** 444 * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1 445 * @pwrdm1: wake this struct powerdomain * up (dependent) 446 * @pwrdm2: when this struct powerdomain * wakes up (source) 447 * 448 * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be 449 * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL 450 * if either powerdomain pointer is invalid; or -ENOENT if the hardware 451 * is incapable. 452 * 453 * REVISIT: Currently this function only represents software-controllable 454 * wakeup dependencies. Wakeup dependencies fixed in hardware are not 455 * yet handled here. 456 */ 457 int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) 458 { 459 struct powerdomain *p; 460 461 if (!pwrdm1) 462 return -EINVAL; 463 464 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs); 465 if (IS_ERR(p)) { 466 pr_debug("powerdomain: hardware cannot set/clear wake up of " 467 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name); 468 return IS_ERR(p); 469 } 470 471 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP, 472 (1 << pwrdm2->dep_bit)); 473 } 474 475 /** 476 * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1 477 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent) 478 * @pwrdm2: when this struct powerdomain * is active (source) 479 * 480 * Prevent pwrdm1 from automatically going inactive (and then to 481 * retention or off) if pwrdm2 is still active. Returns -EINVAL if 482 * presented with invalid powerdomain pointers or called on a machine 483 * that does not support software-configurable hardware sleep dependencies, 484 * -ENOENT if the specified dependency cannot be set in hardware, or 485 * 0 upon success. 486 */ 487 int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) 488 { 489 struct powerdomain *p; 490 491 if (!pwrdm1) 492 return -EINVAL; 493 494 if (!cpu_is_omap34xx()) 495 return -EINVAL; 496 497 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); 498 if (IS_ERR(p)) { 499 pr_debug("powerdomain: hardware cannot set/clear sleep " 500 "dependency affecting %s from %s\n", pwrdm1->name, 501 pwrdm2->name); 502 return IS_ERR(p); 503 } 504 505 pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n", 506 pwrdm1->name, pwrdm2->name); 507 508 cm_set_mod_reg_bits((1 << pwrdm2->dep_bit), 509 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP); 510 511 return 0; 512 } 513 514 /** 515 * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1 516 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent) 517 * @pwrdm2: when this struct powerdomain * is active (source) 518 * 519 * Allow pwrdm1 to automatically go inactive (and then to retention or 520 * off), independent of the activity state of pwrdm2. Returns -EINVAL 521 * if presented with invalid powerdomain pointers or called on a machine 522 * that does not support software-configurable hardware sleep dependencies, 523 * -ENOENT if the specified dependency cannot be cleared in hardware, or 524 * 0 upon success. 525 */ 526 int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) 527 { 528 struct powerdomain *p; 529 530 if (!pwrdm1) 531 return -EINVAL; 532 533 if (!cpu_is_omap34xx()) 534 return -EINVAL; 535 536 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); 537 if (IS_ERR(p)) { 538 pr_debug("powerdomain: hardware cannot set/clear sleep " 539 "dependency affecting %s from %s\n", pwrdm1->name, 540 pwrdm2->name); 541 return IS_ERR(p); 542 } 543 544 pr_debug("powerdomain: will no longer prevent %s from sleeping if " 545 "%s is active\n", pwrdm1->name, pwrdm2->name); 546 547 cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit), 548 pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP); 549 550 return 0; 551 } 552 553 /** 554 * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1 555 * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent) 556 * @pwrdm2: when this struct powerdomain * is active (source) 557 * 558 * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will 559 * not be allowed to automatically go inactive if pwrdm2 is active; 560 * 0 if pwrdm1's automatic power state inactivity transition is independent 561 * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called 562 * on a machine that does not support software-configurable hardware sleep 563 * dependencies; or -ENOENT if the hardware is incapable. 564 * 565 * REVISIT: Currently this function only represents software-controllable 566 * sleep dependencies. Sleep dependencies fixed in hardware are not 567 * yet handled here. 568 */ 569 int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2) 570 { 571 struct powerdomain *p; 572 573 if (!pwrdm1) 574 return -EINVAL; 575 576 if (!cpu_is_omap34xx()) 577 return -EINVAL; 578 579 p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs); 580 if (IS_ERR(p)) { 581 pr_debug("powerdomain: hardware cannot set/clear sleep " 582 "dependency affecting %s from %s\n", pwrdm1->name, 583 pwrdm2->name); 584 return IS_ERR(p); 585 } 586 587 return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP, 588 (1 << pwrdm2->dep_bit)); 589 } 590 591 /** 592 * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain 593 * @pwrdm: struct powerdomain * 594 * 595 * Return the number of controllable memory banks in powerdomain pwrdm, 596 * starting with 1. Returns -EINVAL if the powerdomain pointer is null. 597 */ 598 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) 599 { 600 if (!pwrdm) 601 return -EINVAL; 602 603 return pwrdm->banks; 604 } 605 606 /** 607 * pwrdm_set_next_pwrst - set next powerdomain power state 608 * @pwrdm: struct powerdomain * to set 609 * @pwrst: one of the PWRDM_POWER_* macros 610 * 611 * Set the powerdomain pwrdm's next power state to pwrst. The powerdomain 612 * may not enter this state immediately if the preconditions for this state 613 * have not been satisfied. Returns -EINVAL if the powerdomain pointer is 614 * null or if the power state is invalid for the powerdomin, or returns 0 615 * upon success. 616 */ 617 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) 618 { 619 if (!pwrdm) 620 return -EINVAL; 621 622 if (!(pwrdm->pwrsts & (1 << pwrst))) 623 return -EINVAL; 624 625 pr_debug("powerdomain: setting next powerstate for %s to %0x\n", 626 pwrdm->name, pwrst); 627 628 prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, 629 (pwrst << OMAP_POWERSTATE_SHIFT), 630 pwrdm->prcm_offs, PM_PWSTCTRL); 631 632 return 0; 633 } 634 635 /** 636 * pwrdm_read_next_pwrst - get next powerdomain power state 637 * @pwrdm: struct powerdomain * to get power state 638 * 639 * Return the powerdomain pwrdm's next power state. Returns -EINVAL 640 * if the powerdomain pointer is null or returns the next power state 641 * upon success. 642 */ 643 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) 644 { 645 if (!pwrdm) 646 return -EINVAL; 647 648 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, 649 OMAP_POWERSTATE_MASK); 650 } 651 652 /** 653 * pwrdm_read_pwrst - get current powerdomain power state 654 * @pwrdm: struct powerdomain * to get power state 655 * 656 * Return the powerdomain pwrdm's current power state. Returns -EINVAL 657 * if the powerdomain pointer is null or returns the current power state 658 * upon success. 659 */ 660 int pwrdm_read_pwrst(struct powerdomain *pwrdm) 661 { 662 if (!pwrdm) 663 return -EINVAL; 664 665 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, 666 OMAP_POWERSTATEST_MASK); 667 } 668 669 /** 670 * pwrdm_read_prev_pwrst - get previous powerdomain power state 671 * @pwrdm: struct powerdomain * to get previous power state 672 * 673 * Return the powerdomain pwrdm's previous power state. Returns -EINVAL 674 * if the powerdomain pointer is null or returns the previous power state 675 * upon success. 676 */ 677 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) 678 { 679 if (!pwrdm) 680 return -EINVAL; 681 682 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, 683 OMAP3430_LASTPOWERSTATEENTERED_MASK); 684 } 685 686 /** 687 * pwrdm_set_logic_retst - set powerdomain logic power state upon retention 688 * @pwrdm: struct powerdomain * to set 689 * @pwrst: one of the PWRDM_POWER_* macros 690 * 691 * Set the next power state that the logic portion of the powerdomain 692 * pwrdm will enter when the powerdomain enters retention. This will 693 * be either RETENTION or OFF, if supported. Returns -EINVAL if the 694 * powerdomain pointer is null or the target power state is not not 695 * supported, or returns 0 upon success. 696 */ 697 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 698 { 699 if (!pwrdm) 700 return -EINVAL; 701 702 if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst))) 703 return -EINVAL; 704 705 pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", 706 pwrdm->name, pwrst); 707 708 /* 709 * The register bit names below may not correspond to the 710 * actual names of the bits in each powerdomain's register, 711 * but the type of value returned is the same for each 712 * powerdomain. 713 */ 714 prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE, 715 (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)), 716 pwrdm->prcm_offs, PM_PWSTCTRL); 717 718 return 0; 719 } 720 721 /** 722 * pwrdm_set_mem_onst - set memory power state while powerdomain ON 723 * @pwrdm: struct powerdomain * to set 724 * @bank: memory bank number to set (0-3) 725 * @pwrst: one of the PWRDM_POWER_* macros 726 * 727 * Set the next power state that memory bank x of the powerdomain 728 * pwrdm will enter when the powerdomain enters the ON state. Bank 729 * will be a number from 0 to 3, and represents different types of 730 * memory, depending on the powerdomain. Returns -EINVAL if the 731 * powerdomain pointer is null or the target power state is not not 732 * supported for this memory bank, -EEXIST if the target memory bank 733 * does not exist or is not controllable, or returns 0 upon success. 734 */ 735 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 736 { 737 u32 m; 738 739 if (!pwrdm) 740 return -EINVAL; 741 742 if (pwrdm->banks < (bank + 1)) 743 return -EEXIST; 744 745 if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst))) 746 return -EINVAL; 747 748 pr_debug("powerdomain: setting next memory powerstate for domain %s " 749 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); 750 751 /* 752 * The register bit names below may not correspond to the 753 * actual names of the bits in each powerdomain's register, 754 * but the type of value returned is the same for each 755 * powerdomain. 756 */ 757 switch (bank) { 758 case 0: 759 m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK; 760 break; 761 case 1: 762 m = OMAP3430_L1FLATMEMONSTATE_MASK; 763 break; 764 case 2: 765 m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK; 766 break; 767 case 3: 768 m = OMAP3430_L2FLATMEMONSTATE_MASK; 769 break; 770 default: 771 WARN_ON(1); /* should never happen */ 772 return -EEXIST; 773 } 774 775 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), 776 pwrdm->prcm_offs, PM_PWSTCTRL); 777 778 return 0; 779 } 780 781 /** 782 * pwrdm_set_mem_retst - set memory power state while powerdomain in RET 783 * @pwrdm: struct powerdomain * to set 784 * @bank: memory bank number to set (0-3) 785 * @pwrst: one of the PWRDM_POWER_* macros 786 * 787 * Set the next power state that memory bank x of the powerdomain 788 * pwrdm will enter when the powerdomain enters the RETENTION state. 789 * Bank will be a number from 0 to 3, and represents different types 790 * of memory, depending on the powerdomain. pwrst will be either 791 * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain 792 * pointer is null or the target power state is not not supported for 793 * this memory bank, -EEXIST if the target memory bank does not exist 794 * or is not controllable, or returns 0 upon success. 795 */ 796 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 797 { 798 u32 m; 799 800 if (!pwrdm) 801 return -EINVAL; 802 803 if (pwrdm->banks < (bank + 1)) 804 return -EEXIST; 805 806 if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst))) 807 return -EINVAL; 808 809 pr_debug("powerdomain: setting next memory powerstate for domain %s " 810 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); 811 812 /* 813 * The register bit names below may not correspond to the 814 * actual names of the bits in each powerdomain's register, 815 * but the type of value returned is the same for each 816 * powerdomain. 817 */ 818 switch (bank) { 819 case 0: 820 m = OMAP3430_SHAREDL1CACHEFLATRETSTATE; 821 break; 822 case 1: 823 m = OMAP3430_L1FLATMEMRETSTATE; 824 break; 825 case 2: 826 m = OMAP3430_SHAREDL2CACHEFLATRETSTATE; 827 break; 828 case 3: 829 m = OMAP3430_L2FLATMEMRETSTATE; 830 break; 831 default: 832 WARN_ON(1); /* should never happen */ 833 return -EEXIST; 834 } 835 836 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, 837 PM_PWSTCTRL); 838 839 return 0; 840 } 841 842 /** 843 * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state 844 * @pwrdm: struct powerdomain * to get current logic retention power state 845 * 846 * Return the current power state that the logic portion of 847 * powerdomain pwrdm will enter 848 * Returns -EINVAL if the powerdomain pointer is null or returns the 849 * current logic retention power state upon success. 850 */ 851 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) 852 { 853 if (!pwrdm) 854 return -EINVAL; 855 856 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, 857 OMAP3430_LOGICSTATEST); 858 } 859 860 /** 861 * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state 862 * @pwrdm: struct powerdomain * to get previous logic power state 863 * 864 * Return the powerdomain pwrdm's logic power state. Returns -EINVAL 865 * if the powerdomain pointer is null or returns the previous logic 866 * power state upon success. 867 */ 868 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) 869 { 870 if (!pwrdm) 871 return -EINVAL; 872 873 /* 874 * The register bit names below may not correspond to the 875 * actual names of the bits in each powerdomain's register, 876 * but the type of value returned is the same for each 877 * powerdomain. 878 */ 879 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, 880 OMAP3430_LASTLOGICSTATEENTERED); 881 } 882 883 /** 884 * pwrdm_read_mem_pwrst - get current memory bank power state 885 * @pwrdm: struct powerdomain * to get current memory bank power state 886 * @bank: memory bank number (0-3) 887 * 888 * Return the powerdomain pwrdm's current memory power state for bank 889 * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if 890 * the target memory bank does not exist or is not controllable, or 891 * returns the current memory power state upon success. 892 */ 893 int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 894 { 895 u32 m; 896 897 if (!pwrdm) 898 return -EINVAL; 899 900 if (pwrdm->banks < (bank + 1)) 901 return -EEXIST; 902 903 /* 904 * The register bit names below may not correspond to the 905 * actual names of the bits in each powerdomain's register, 906 * but the type of value returned is the same for each 907 * powerdomain. 908 */ 909 switch (bank) { 910 case 0: 911 m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK; 912 break; 913 case 1: 914 m = OMAP3430_L1FLATMEMSTATEST_MASK; 915 break; 916 case 2: 917 m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK; 918 break; 919 case 3: 920 m = OMAP3430_L2FLATMEMSTATEST_MASK; 921 break; 922 default: 923 WARN_ON(1); /* should never happen */ 924 return -EEXIST; 925 } 926 927 return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m); 928 } 929 930 /** 931 * pwrdm_read_prev_mem_pwrst - get previous memory bank power state 932 * @pwrdm: struct powerdomain * to get previous memory bank power state 933 * @bank: memory bank number (0-3) 934 * 935 * Return the powerdomain pwrdm's previous memory power state for bank 936 * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if 937 * the target memory bank does not exist or is not controllable, or 938 * returns the previous memory power state upon success. 939 */ 940 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 941 { 942 u32 m; 943 944 if (!pwrdm) 945 return -EINVAL; 946 947 if (pwrdm->banks < (bank + 1)) 948 return -EEXIST; 949 950 /* 951 * The register bit names below may not correspond to the 952 * actual names of the bits in each powerdomain's register, 953 * but the type of value returned is the same for each 954 * powerdomain. 955 */ 956 switch (bank) { 957 case 0: 958 m = OMAP3430_LASTMEM1STATEENTERED_MASK; 959 break; 960 case 1: 961 m = OMAP3430_LASTMEM2STATEENTERED_MASK; 962 break; 963 case 2: 964 m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; 965 break; 966 case 3: 967 m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; 968 break; 969 default: 970 WARN_ON(1); /* should never happen */ 971 return -EEXIST; 972 } 973 974 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 975 OMAP3430_PM_PREPWSTST, m); 976 } 977 978 /** 979 * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm 980 * @pwrdm: struct powerdomain * to clear 981 * 982 * Clear the powerdomain's previous power state register. Clears the 983 * entire register, including logic and memory bank previous power states. 984 * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon 985 * success. 986 */ 987 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) 988 { 989 if (!pwrdm) 990 return -EINVAL; 991 992 /* 993 * XXX should get the powerdomain's current state here; 994 * warn & fail if it is not ON. 995 */ 996 997 pr_debug("powerdomain: clearing previous power state reg for %s\n", 998 pwrdm->name); 999 1000 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); 1001 1002 return 0; 1003 } 1004 1005 /** 1006 * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm 1007 * @pwrdm: struct powerdomain * 1008 * 1009 * Enable automatic context save-and-restore upon power state change 1010 * for some devices in a powerdomain. Warning: this only affects a 1011 * subset of devices in a powerdomain; check the TRM closely. Returns 1012 * -EINVAL if the powerdomain pointer is null or if the powerdomain 1013 * does not support automatic save-and-restore, or returns 0 upon 1014 * success. 1015 */ 1016 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) 1017 { 1018 if (!pwrdm) 1019 return -EINVAL; 1020 1021 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 1022 return -EINVAL; 1023 1024 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", 1025 pwrdm->name); 1026 1027 prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 1028 pwrdm->prcm_offs, PM_PWSTCTRL); 1029 1030 return 0; 1031 } 1032 1033 /** 1034 * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm 1035 * @pwrdm: struct powerdomain * 1036 * 1037 * Disable automatic context save-and-restore upon power state change 1038 * for some devices in a powerdomain. Warning: this only affects a 1039 * subset of devices in a powerdomain; check the TRM closely. Returns 1040 * -EINVAL if the powerdomain pointer is null or if the powerdomain 1041 * does not support automatic save-and-restore, or returns 0 upon 1042 * success. 1043 */ 1044 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) 1045 { 1046 if (!pwrdm) 1047 return -EINVAL; 1048 1049 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 1050 return -EINVAL; 1051 1052 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", 1053 pwrdm->name); 1054 1055 prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0, 1056 pwrdm->prcm_offs, PM_PWSTCTRL); 1057 1058 return 0; 1059 } 1060 1061 /** 1062 * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR 1063 * @pwrdm: struct powerdomain * 1064 * 1065 * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore 1066 * for some devices, or 0 if it does not. 1067 */ 1068 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) 1069 { 1070 return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0; 1071 } 1072 1073 /** 1074 * pwrdm_wait_transition - wait for powerdomain power transition to finish 1075 * @pwrdm: struct powerdomain * to wait for 1076 * 1077 * If the powerdomain pwrdm is in the process of a state transition, 1078 * spin until it completes the power transition, or until an iteration 1079 * bailout value is reached. Returns -EINVAL if the powerdomain 1080 * pointer is null, -EAGAIN if the bailout value was reached, or 1081 * returns 0 upon success. 1082 */ 1083 int pwrdm_wait_transition(struct powerdomain *pwrdm) 1084 { 1085 u32 c = 0; 1086 1087 if (!pwrdm) 1088 return -EINVAL; 1089 1090 /* 1091 * REVISIT: pwrdm_wait_transition() may be better implemented 1092 * via a callback and a periodic timer check -- how long do we expect 1093 * powerdomain transitions to take? 1094 */ 1095 1096 /* XXX Is this udelay() value meaningful? */ 1097 while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) & 1098 OMAP_INTRANSITION) && 1099 (c++ < PWRDM_TRANSITION_BAILOUT)) 1100 udelay(1); 1101 1102 if (c >= PWRDM_TRANSITION_BAILOUT) { 1103 printk(KERN_ERR "powerdomain: waited too long for " 1104 "powerdomain %s to complete transition\n", pwrdm->name); 1105 return -EAGAIN; 1106 } 1107 1108 pr_debug("powerdomain: completed transition in %d loops\n", c); 1109 1110 return 0; 1111 } 1112 1113 1114