diff options
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
| -rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 441 |
1 files changed, 152 insertions, 289 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 6527ec30dc1..eaed0df1669 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c | |||
| @@ -15,27 +15,19 @@ | |||
| 15 | #undef DEBUG | 15 | #undef DEBUG |
| 16 | 16 | ||
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/spinlock.h> | ||
| 22 | #include <linux/list.h> | 19 | #include <linux/list.h> |
| 23 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
| 24 | #include <linux/err.h> | 21 | #include <linux/string.h> |
| 25 | #include <linux/io.h> | 22 | #include "cm2xxx_3xxx.h" |
| 26 | 23 | #include "prcm44xx.h" | |
| 27 | #include <asm/atomic.h> | 24 | #include "cm44xx.h" |
| 28 | 25 | #include "prm2xxx_3xxx.h" | |
| 29 | #include "cm.h" | 26 | #include "prm44xx.h" |
| 30 | #include "cm-regbits-34xx.h" | ||
| 31 | #include "cm-regbits-44xx.h" | ||
| 32 | #include "prm.h" | ||
| 33 | #include "prm-regbits-34xx.h" | ||
| 34 | #include "prm-regbits-44xx.h" | ||
| 35 | 27 | ||
| 36 | #include <plat/cpu.h> | 28 | #include <plat/cpu.h> |
| 37 | #include <plat/powerdomain.h> | 29 | #include "powerdomain.h" |
| 38 | #include <plat/clockdomain.h> | 30 | #include "clockdomain.h" |
| 39 | #include <plat/prcm.h> | 31 | #include <plat/prcm.h> |
| 40 | 32 | ||
| 41 | #include "pm.h" | 33 | #include "pm.h" |
| @@ -45,41 +37,12 @@ enum { | |||
| 45 | PWRDM_STATE_PREV, | 37 | PWRDM_STATE_PREV, |
| 46 | }; | 38 | }; |
| 47 | 39 | ||
| 48 | /* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */ | ||
| 49 | static u16 pwrstctrl_reg_offs; | ||
| 50 | |||
| 51 | /* Variable holding value of the CPU dependent PWRSTST Register Offset */ | ||
| 52 | static u16 pwrstst_reg_offs; | ||
| 53 | |||
| 54 | /* OMAP3 and OMAP4 specific register bit initialisations | ||
| 55 | * Notice that the names here are not according to each power | ||
| 56 | * domain but the bit mapping used applies to all of them | ||
| 57 | */ | ||
| 58 | |||
| 59 | /* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */ | ||
| 60 | #define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK | ||
| 61 | #define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK | ||
| 62 | #define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK | ||
| 63 | #define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK | ||
| 64 | #define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK | ||
| 65 | |||
| 66 | /* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */ | ||
| 67 | #define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE_MASK | ||
| 68 | #define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE_MASK | ||
| 69 | #define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE_MASK | ||
| 70 | #define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE_MASK | ||
| 71 | #define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK | ||
| 72 | |||
| 73 | /* OMAP3 and OMAP4 Memory Status bits */ | ||
| 74 | #define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK | ||
| 75 | #define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK | ||
| 76 | #define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK | ||
| 77 | #define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK | ||
| 78 | #define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK | ||
| 79 | 40 | ||
| 80 | /* pwrdm_list contains all registered struct powerdomains */ | 41 | /* pwrdm_list contains all registered struct powerdomains */ |
| 81 | static LIST_HEAD(pwrdm_list); | 42 | static LIST_HEAD(pwrdm_list); |
| 82 | 43 | ||
| 44 | static struct pwrdm_ops *arch_pwrdm; | ||
| 45 | |||
| 83 | /* Private functions */ | 46 | /* Private functions */ |
| 84 | 47 | ||
| 85 | static struct powerdomain *_pwrdm_lookup(const char *name) | 48 | static struct powerdomain *_pwrdm_lookup(const char *name) |
| @@ -110,12 +73,19 @@ static int _pwrdm_register(struct powerdomain *pwrdm) | |||
| 110 | { | 73 | { |
| 111 | int i; | 74 | int i; |
| 112 | 75 | ||
| 113 | if (!pwrdm) | 76 | if (!pwrdm || !pwrdm->name) |
| 114 | return -EINVAL; | 77 | return -EINVAL; |
| 115 | 78 | ||
| 116 | if (!omap_chip_is(pwrdm->omap_chip)) | 79 | if (!omap_chip_is(pwrdm->omap_chip)) |
| 117 | return -EINVAL; | 80 | return -EINVAL; |
| 118 | 81 | ||
| 82 | if (cpu_is_omap44xx() && | ||
| 83 | pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) { | ||
| 84 | pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n", | ||
| 85 | pwrdm->name); | ||
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 88 | |||
| 119 | if (_pwrdm_lookup(pwrdm->name)) | 89 | if (_pwrdm_lookup(pwrdm->name)) |
| 120 | return -EEXIST; | 90 | return -EEXIST; |
| 121 | 91 | ||
| @@ -211,6 +181,7 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) | |||
| 211 | /** | 181 | /** |
| 212 | * pwrdm_init - set up the powerdomain layer | 182 | * pwrdm_init - set up the powerdomain layer |
| 213 | * @pwrdm_list: array of struct powerdomain pointers to register | 183 | * @pwrdm_list: array of struct powerdomain pointers to register |
| 184 | * @custom_funcs: func pointers for arch specfic implementations | ||
| 214 | * | 185 | * |
| 215 | * Loop through the array of powerdomains @pwrdm_list, registering all | 186 | * Loop through the array of powerdomains @pwrdm_list, registering all |
| 216 | * that are available on the current CPU. If pwrdm_list is supplied | 187 | * that are available on the current CPU. If pwrdm_list is supplied |
| @@ -218,21 +189,14 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) | |||
| 218 | * registered. No return value. XXX pwrdm_list is not really a | 189 | * registered. No return value. XXX pwrdm_list is not really a |
| 219 | * "list"; it is an array. Rename appropriately. | 190 | * "list"; it is an array. Rename appropriately. |
| 220 | */ | 191 | */ |
| 221 | void pwrdm_init(struct powerdomain **pwrdm_list) | 192 | void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs) |
| 222 | { | 193 | { |
| 223 | struct powerdomain **p = NULL; | 194 | struct powerdomain **p = NULL; |
| 224 | 195 | ||
| 225 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | 196 | if (!custom_funcs) |
| 226 | pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL; | 197 | WARN(1, "powerdomain: No custom pwrdm functions registered\n"); |
| 227 | pwrstst_reg_offs = OMAP2_PM_PWSTST; | 198 | else |
| 228 | } else if (cpu_is_omap44xx()) { | 199 | arch_pwrdm = custom_funcs; |
| 229 | pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL; | ||
| 230 | pwrstst_reg_offs = OMAP4_PM_PWSTST; | ||
| 231 | } else { | ||
| 232 | printk(KERN_ERR "Power Domain struct not supported for " \ | ||
| 233 | "this CPU\n"); | ||
| 234 | return; | ||
| 235 | } | ||
| 236 | 200 | ||
| 237 | if (pwrdm_list) { | 201 | if (pwrdm_list) { |
| 238 | for (p = pwrdm_list; *p; p++) | 202 | for (p = pwrdm_list; *p; p++) |
| @@ -431,6 +395,8 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) | |||
| 431 | */ | 395 | */ |
| 432 | int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | 396 | int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) |
| 433 | { | 397 | { |
| 398 | int ret = -EINVAL; | ||
| 399 | |||
| 434 | if (!pwrdm) | 400 | if (!pwrdm) |
| 435 | return -EINVAL; | 401 | return -EINVAL; |
| 436 | 402 | ||
| @@ -440,11 +406,10 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |||
| 440 | pr_debug("powerdomain: setting next powerstate for %s to %0x\n", | 406 | pr_debug("powerdomain: setting next powerstate for %s to %0x\n", |
| 441 | pwrdm->name, pwrst); | 407 | pwrdm->name, pwrst); |
| 442 | 408 | ||
| 443 | prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, | 409 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) |
| 444 | (pwrst << OMAP_POWERSTATE_SHIFT), | 410 | ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst); |
| 445 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
| 446 | 411 | ||
| 447 | return 0; | 412 | return ret; |
| 448 | } | 413 | } |
| 449 | 414 | ||
| 450 | /** | 415 | /** |
| @@ -457,11 +422,15 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |||
| 457 | */ | 422 | */ |
| 458 | int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | 423 | int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) |
| 459 | { | 424 | { |
| 425 | int ret = -EINVAL; | ||
| 426 | |||
| 460 | if (!pwrdm) | 427 | if (!pwrdm) |
| 461 | return -EINVAL; | 428 | return -EINVAL; |
| 462 | 429 | ||
| 463 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 430 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst) |
| 464 | pwrstctrl_reg_offs, OMAP_POWERSTATE_MASK); | 431 | ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm); |
| 432 | |||
| 433 | return ret; | ||
| 465 | } | 434 | } |
| 466 | 435 | ||
| 467 | /** | 436 | /** |
| @@ -474,11 +443,15 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | |||
| 474 | */ | 443 | */ |
| 475 | int pwrdm_read_pwrst(struct powerdomain *pwrdm) | 444 | int pwrdm_read_pwrst(struct powerdomain *pwrdm) |
| 476 | { | 445 | { |
| 446 | int ret = -EINVAL; | ||
| 447 | |||
| 477 | if (!pwrdm) | 448 | if (!pwrdm) |
| 478 | return -EINVAL; | 449 | return -EINVAL; |
| 479 | 450 | ||
| 480 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 451 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst) |
| 481 | pwrstst_reg_offs, OMAP_POWERSTATEST_MASK); | 452 | ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm); |
| 453 | |||
| 454 | return ret; | ||
| 482 | } | 455 | } |
| 483 | 456 | ||
| 484 | /** | 457 | /** |
| @@ -491,11 +464,15 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm) | |||
| 491 | */ | 464 | */ |
| 492 | int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | 465 | int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) |
| 493 | { | 466 | { |
| 467 | int ret = -EINVAL; | ||
| 468 | |||
| 494 | if (!pwrdm) | 469 | if (!pwrdm) |
| 495 | return -EINVAL; | 470 | return -EINVAL; |
| 496 | 471 | ||
| 497 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, | 472 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst) |
| 498 | OMAP3430_LASTPOWERSTATEENTERED_MASK); | 473 | ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm); |
| 474 | |||
| 475 | return ret; | ||
| 499 | } | 476 | } |
| 500 | 477 | ||
| 501 | /** | 478 | /** |
| @@ -511,7 +488,7 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | |||
| 511 | */ | 488 | */ |
| 512 | int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | 489 | int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) |
| 513 | { | 490 | { |
| 514 | u32 v; | 491 | int ret = -EINVAL; |
| 515 | 492 | ||
| 516 | if (!pwrdm) | 493 | if (!pwrdm) |
| 517 | return -EINVAL; | 494 | return -EINVAL; |
| @@ -522,17 +499,10 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | |||
| 522 | pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", | 499 | pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", |
| 523 | pwrdm->name, pwrst); | 500 | pwrdm->name, pwrst); |
| 524 | 501 | ||
| 525 | /* | 502 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst) |
| 526 | * The register bit names below may not correspond to the | 503 | ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, pwrst); |
| 527 | * actual names of the bits in each powerdomain's register, | ||
| 528 | * but the type of value returned is the same for each | ||
| 529 | * powerdomain. | ||
| 530 | */ | ||
| 531 | v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK); | ||
| 532 | prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v, | ||
| 533 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
| 534 | 504 | ||
| 535 | return 0; | 505 | return ret; |
| 536 | } | 506 | } |
| 537 | 507 | ||
| 538 | /** | 508 | /** |
| @@ -552,7 +522,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) | |||
| 552 | */ | 522 | */ |
| 553 | int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | 523 | int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) |
| 554 | { | 524 | { |
| 555 | u32 m; | 525 | int ret = -EINVAL; |
| 556 | 526 | ||
| 557 | if (!pwrdm) | 527 | if (!pwrdm) |
| 558 | return -EINVAL; | 528 | return -EINVAL; |
| @@ -566,37 +536,10 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
| 566 | pr_debug("powerdomain: setting next memory powerstate for domain %s " | 536 | pr_debug("powerdomain: setting next memory powerstate for domain %s " |
| 567 | "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); | 537 | "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); |
| 568 | 538 | ||
| 569 | /* | 539 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst) |
| 570 | * The register bit names below may not correspond to the | 540 | ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst); |
| 571 | * actual names of the bits in each powerdomain's register, | ||
| 572 | * but the type of value returned is the same for each | ||
| 573 | * powerdomain. | ||
| 574 | */ | ||
| 575 | switch (bank) { | ||
| 576 | case 0: | ||
| 577 | m = OMAP_MEM0_ONSTATE_MASK; | ||
| 578 | break; | ||
| 579 | case 1: | ||
| 580 | m = OMAP_MEM1_ONSTATE_MASK; | ||
| 581 | break; | ||
| 582 | case 2: | ||
| 583 | m = OMAP_MEM2_ONSTATE_MASK; | ||
| 584 | break; | ||
| 585 | case 3: | ||
| 586 | m = OMAP_MEM3_ONSTATE_MASK; | ||
| 587 | break; | ||
| 588 | case 4: | ||
| 589 | m = OMAP_MEM4_ONSTATE_MASK; | ||
| 590 | break; | ||
| 591 | default: | ||
| 592 | WARN_ON(1); /* should never happen */ | ||
| 593 | return -EEXIST; | ||
| 594 | } | ||
| 595 | 541 | ||
| 596 | prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), | 542 | return ret; |
| 597 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | 543 | } |
| 601 | 544 | ||
| 602 | /** | 545 | /** |
| @@ -617,7 +560,7 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
| 617 | */ | 560 | */ |
| 618 | int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | 561 | int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) |
| 619 | { | 562 | { |
| 620 | u32 m; | 563 | int ret = -EINVAL; |
| 621 | 564 | ||
| 622 | if (!pwrdm) | 565 | if (!pwrdm) |
| 623 | return -EINVAL; | 566 | return -EINVAL; |
| @@ -631,37 +574,10 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
| 631 | pr_debug("powerdomain: setting next memory powerstate for domain %s " | 574 | pr_debug("powerdomain: setting next memory powerstate for domain %s " |
| 632 | "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); | 575 | "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); |
| 633 | 576 | ||
| 634 | /* | 577 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst) |
| 635 | * The register bit names below may not correspond to the | 578 | ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst); |
| 636 | * actual names of the bits in each powerdomain's register, | ||
| 637 | * but the type of value returned is the same for each | ||
| 638 | * powerdomain. | ||
| 639 | */ | ||
| 640 | switch (bank) { | ||
| 641 | case 0: | ||
| 642 | m = OMAP_MEM0_RETSTATE_MASK; | ||
| 643 | break; | ||
| 644 | case 1: | ||
| 645 | m = OMAP_MEM1_RETSTATE_MASK; | ||
| 646 | break; | ||
| 647 | case 2: | ||
| 648 | m = OMAP_MEM2_RETSTATE_MASK; | ||
| 649 | break; | ||
| 650 | case 3: | ||
| 651 | m = OMAP_MEM3_RETSTATE_MASK; | ||
| 652 | break; | ||
| 653 | case 4: | ||
| 654 | m = OMAP_MEM4_RETSTATE_MASK; | ||
| 655 | break; | ||
| 656 | default: | ||
| 657 | WARN_ON(1); /* should never happen */ | ||
| 658 | return -EEXIST; | ||
| 659 | } | ||
| 660 | |||
| 661 | prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, | ||
| 662 | pwrstctrl_reg_offs); | ||
| 663 | 579 | ||
| 664 | return 0; | 580 | return ret; |
| 665 | } | 581 | } |
| 666 | 582 | ||
| 667 | /** | 583 | /** |
| @@ -675,11 +591,15 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) | |||
| 675 | */ | 591 | */ |
| 676 | int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | 592 | int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) |
| 677 | { | 593 | { |
| 594 | int ret = -EINVAL; | ||
| 595 | |||
| 678 | if (!pwrdm) | 596 | if (!pwrdm) |
| 679 | return -EINVAL; | 597 | return -EINVAL; |
| 680 | 598 | ||
| 681 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstst_reg_offs, | 599 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst) |
| 682 | OMAP3430_LOGICSTATEST_MASK); | 600 | ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm); |
| 601 | |||
| 602 | return ret; | ||
| 683 | } | 603 | } |
| 684 | 604 | ||
| 685 | /** | 605 | /** |
| @@ -692,17 +612,15 @@ int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) | |||
| 692 | */ | 612 | */ |
| 693 | int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | 613 | int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) |
| 694 | { | 614 | { |
| 615 | int ret = -EINVAL; | ||
| 616 | |||
| 695 | if (!pwrdm) | 617 | if (!pwrdm) |
| 696 | return -EINVAL; | 618 | return -EINVAL; |
| 697 | 619 | ||
| 698 | /* | 620 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst) |
| 699 | * The register bit names below may not correspond to the | 621 | ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm); |
| 700 | * actual names of the bits in each powerdomain's register, | 622 | |
| 701 | * but the type of value returned is the same for each | 623 | return ret; |
| 702 | * powerdomain. | ||
| 703 | */ | ||
| 704 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, | ||
| 705 | OMAP3430_LASTLOGICSTATEENTERED_MASK); | ||
| 706 | } | 624 | } |
| 707 | 625 | ||
| 708 | /** | 626 | /** |
| @@ -715,17 +633,15 @@ int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | |||
| 715 | */ | 633 | */ |
| 716 | int pwrdm_read_logic_retst(struct powerdomain *pwrdm) | 634 | int pwrdm_read_logic_retst(struct powerdomain *pwrdm) |
| 717 | { | 635 | { |
| 636 | int ret = -EINVAL; | ||
| 637 | |||
| 718 | if (!pwrdm) | 638 | if (!pwrdm) |
| 719 | return -EINVAL; | 639 | return -EINVAL; |
| 720 | 640 | ||
| 721 | /* | 641 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst) |
| 722 | * The register bit names below may not correspond to the | 642 | ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm); |
| 723 | * actual names of the bits in each powerdomain's register, | 643 | |
| 724 | * but the type of value returned is the same for each | 644 | return ret; |
| 725 | * powerdomain. | ||
| 726 | */ | ||
| 727 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstctrl_reg_offs, | ||
| 728 | OMAP3430_LOGICSTATEST_MASK); | ||
| 729 | } | 645 | } |
| 730 | 646 | ||
| 731 | /** | 647 | /** |
| @@ -740,46 +656,21 @@ int pwrdm_read_logic_retst(struct powerdomain *pwrdm) | |||
| 740 | */ | 656 | */ |
| 741 | int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | 657 | int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
| 742 | { | 658 | { |
| 743 | u32 m; | 659 | int ret = -EINVAL; |
| 744 | 660 | ||
| 745 | if (!pwrdm) | 661 | if (!pwrdm) |
| 746 | return -EINVAL; | 662 | return ret; |
| 747 | 663 | ||
| 748 | if (pwrdm->banks < (bank + 1)) | 664 | if (pwrdm->banks < (bank + 1)) |
| 749 | return -EEXIST; | 665 | return ret; |
| 750 | 666 | ||
| 751 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) | 667 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) |
| 752 | bank = 1; | 668 | bank = 1; |
| 753 | 669 | ||
| 754 | /* | 670 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst) |
| 755 | * The register bit names below may not correspond to the | 671 | ret = arch_pwrdm->pwrdm_read_mem_pwrst(pwrdm, bank); |
| 756 | * actual names of the bits in each powerdomain's register, | ||
| 757 | * but the type of value returned is the same for each | ||
| 758 | * powerdomain. | ||
| 759 | */ | ||
| 760 | switch (bank) { | ||
| 761 | case 0: | ||
| 762 | m = OMAP_MEM0_STATEST_MASK; | ||
| 763 | break; | ||
| 764 | case 1: | ||
| 765 | m = OMAP_MEM1_STATEST_MASK; | ||
| 766 | break; | ||
| 767 | case 2: | ||
| 768 | m = OMAP_MEM2_STATEST_MASK; | ||
| 769 | break; | ||
| 770 | case 3: | ||
| 771 | m = OMAP_MEM3_STATEST_MASK; | ||
| 772 | break; | ||
| 773 | case 4: | ||
| 774 | m = OMAP_MEM4_STATEST_MASK; | ||
| 775 | break; | ||
| 776 | default: | ||
| 777 | WARN_ON(1); /* should never happen */ | ||
| 778 | return -EEXIST; | ||
| 779 | } | ||
| 780 | 672 | ||
| 781 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 673 | return ret; |
| 782 | pwrstst_reg_offs, m); | ||
| 783 | } | 674 | } |
| 784 | 675 | ||
| 785 | /** | 676 | /** |
| @@ -795,43 +686,21 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | |||
| 795 | */ | 686 | */ |
| 796 | int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | 687 | int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
| 797 | { | 688 | { |
| 798 | u32 m; | 689 | int ret = -EINVAL; |
| 799 | 690 | ||
| 800 | if (!pwrdm) | 691 | if (!pwrdm) |
| 801 | return -EINVAL; | 692 | return ret; |
| 802 | 693 | ||
| 803 | if (pwrdm->banks < (bank + 1)) | 694 | if (pwrdm->banks < (bank + 1)) |
| 804 | return -EEXIST; | 695 | return ret; |
| 805 | 696 | ||
| 806 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) | 697 | if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) |
| 807 | bank = 1; | 698 | bank = 1; |
| 808 | 699 | ||
| 809 | /* | 700 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst) |
| 810 | * The register bit names below may not correspond to the | 701 | ret = arch_pwrdm->pwrdm_read_prev_mem_pwrst(pwrdm, bank); |
| 811 | * actual names of the bits in each powerdomain's register, | ||
| 812 | * but the type of value returned is the same for each | ||
| 813 | * powerdomain. | ||
| 814 | */ | ||
| 815 | switch (bank) { | ||
| 816 | case 0: | ||
| 817 | m = OMAP3430_LASTMEM1STATEENTERED_MASK; | ||
| 818 | break; | ||
| 819 | case 1: | ||
| 820 | m = OMAP3430_LASTMEM2STATEENTERED_MASK; | ||
| 821 | break; | ||
| 822 | case 2: | ||
| 823 | m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK; | ||
| 824 | break; | ||
| 825 | case 3: | ||
| 826 | m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK; | ||
| 827 | break; | ||
| 828 | default: | ||
| 829 | WARN_ON(1); /* should never happen */ | ||
| 830 | return -EEXIST; | ||
| 831 | } | ||
| 832 | 702 | ||
| 833 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 703 | return ret; |
| 834 | OMAP3430_PM_PREPWSTST, m); | ||
| 835 | } | 704 | } |
| 836 | 705 | ||
| 837 | /** | 706 | /** |
| @@ -846,43 +715,18 @@ int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) | |||
| 846 | */ | 715 | */ |
| 847 | int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | 716 | int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) |
| 848 | { | 717 | { |
| 849 | u32 m; | 718 | int ret = -EINVAL; |
| 850 | 719 | ||
| 851 | if (!pwrdm) | 720 | if (!pwrdm) |
| 852 | return -EINVAL; | 721 | return ret; |
| 853 | 722 | ||
| 854 | if (pwrdm->banks < (bank + 1)) | 723 | if (pwrdm->banks < (bank + 1)) |
| 855 | return -EEXIST; | 724 | return ret; |
| 856 | 725 | ||
| 857 | /* | 726 | if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst) |
| 858 | * The register bit names below may not correspond to the | 727 | ret = arch_pwrdm->pwrdm_read_mem_retst(pwrdm, bank); |
| 859 | * actual names of the bits in each powerdomain's register, | ||
| 860 | * but the type of value returned is the same for each | ||
| 861 | * powerdomain. | ||
| 862 | */ | ||
| 863 | switch (bank) { | ||
| 864 | case 0: | ||
| 865 | m = OMAP_MEM0_RETSTATE_MASK; | ||
| 866 | break; | ||
| 867 | case 1: | ||
| 868 | m = OMAP_MEM1_RETSTATE_MASK; | ||
| 869 | break; | ||
| 870 | case 2: | ||
| 871 | m = OMAP_MEM2_RETSTATE_MASK; | ||
| 872 | break; | ||
| 873 | case 3: | ||
| 874 | m = OMAP_MEM3_RETSTATE_MASK; | ||
| 875 | break; | ||
| 876 | case 4: | ||
| 877 | m = OMAP_MEM4_RETSTATE_MASK; | ||
| 878 | break; | ||
| 879 | default: | ||
| 880 | WARN_ON(1); /* should never happen */ | ||
| 881 | return -EEXIST; | ||
| 882 | } | ||
| 883 | 728 | ||
| 884 | return prm_read_mod_bits_shift(pwrdm->prcm_offs, | 729 | return ret; |
| 885 | pwrstctrl_reg_offs, m); | ||
| 886 | } | 730 | } |
| 887 | 731 | ||
| 888 | /** | 732 | /** |
| @@ -896,8 +740,10 @@ int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | |||
| 896 | */ | 740 | */ |
| 897 | int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | 741 | int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) |
| 898 | { | 742 | { |
| 743 | int ret = -EINVAL; | ||
| 744 | |||
| 899 | if (!pwrdm) | 745 | if (!pwrdm) |
| 900 | return -EINVAL; | 746 | return ret; |
| 901 | 747 | ||
| 902 | /* | 748 | /* |
| 903 | * XXX should get the powerdomain's current state here; | 749 | * XXX should get the powerdomain's current state here; |
| @@ -907,9 +753,10 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | |||
| 907 | pr_debug("powerdomain: clearing previous power state reg for %s\n", | 753 | pr_debug("powerdomain: clearing previous power state reg for %s\n", |
| 908 | pwrdm->name); | 754 | pwrdm->name); |
| 909 | 755 | ||
| 910 | prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); | 756 | if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst) |
| 757 | ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm); | ||
| 911 | 758 | ||
| 912 | return 0; | 759 | return ret; |
| 913 | } | 760 | } |
| 914 | 761 | ||
| 915 | /** | 762 | /** |
| @@ -925,19 +772,21 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | |||
| 925 | */ | 772 | */ |
| 926 | int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | 773 | int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) |
| 927 | { | 774 | { |
| 775 | int ret = -EINVAL; | ||
| 776 | |||
| 928 | if (!pwrdm) | 777 | if (!pwrdm) |
| 929 | return -EINVAL; | 778 | return ret; |
| 930 | 779 | ||
| 931 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) | 780 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) |
| 932 | return -EINVAL; | 781 | return ret; |
| 933 | 782 | ||
| 934 | pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", | 783 | pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", |
| 935 | pwrdm->name); | 784 | pwrdm->name); |
| 936 | 785 | ||
| 937 | prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | 786 | if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar) |
| 938 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | 787 | ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm); |
| 939 | 788 | ||
| 940 | return 0; | 789 | return ret; |
| 941 | } | 790 | } |
| 942 | 791 | ||
| 943 | /** | 792 | /** |
| @@ -953,19 +802,21 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | |||
| 953 | */ | 802 | */ |
| 954 | int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) | 803 | int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) |
| 955 | { | 804 | { |
| 805 | int ret = -EINVAL; | ||
| 806 | |||
| 956 | if (!pwrdm) | 807 | if (!pwrdm) |
| 957 | return -EINVAL; | 808 | return ret; |
| 958 | 809 | ||
| 959 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) | 810 | if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) |
| 960 | return -EINVAL; | 811 | return ret; |
| 961 | 812 | ||
| 962 | pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", | 813 | pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", |
| 963 | pwrdm->name); | 814 | pwrdm->name); |
| 964 | 815 | ||
| 965 | prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0, | 816 | if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar) |
| 966 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | 817 | ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm); |
| 967 | 818 | ||
| 968 | return 0; | 819 | return ret; |
| 969 | } | 820 | } |
| 970 | 821 | ||
| 971 | /** | 822 | /** |
| @@ -992,6 +843,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) | |||
| 992 | */ | 843 | */ |
| 993 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | 844 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) |
| 994 | { | 845 | { |
| 846 | int ret = -EINVAL; | ||
| 847 | |||
| 995 | if (!pwrdm) | 848 | if (!pwrdm) |
| 996 | return -EINVAL; | 849 | return -EINVAL; |
| 997 | 850 | ||
| @@ -1001,11 +854,10 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | |||
| 1001 | pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", | 854 | pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", |
| 1002 | pwrdm->name); | 855 | pwrdm->name); |
| 1003 | 856 | ||
| 1004 | prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, | 857 | if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange) |
| 1005 | (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), | 858 | ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); |
| 1006 | pwrdm->prcm_offs, pwrstctrl_reg_offs); | ||
| 1007 | 859 | ||
| 1008 | return 0; | 860 | return ret; |
| 1009 | } | 861 | } |
| 1010 | 862 | ||
| 1011 | /** | 863 | /** |
| @@ -1020,32 +872,15 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) | |||
| 1020 | */ | 872 | */ |
| 1021 | int pwrdm_wait_transition(struct powerdomain *pwrdm) | 873 | int pwrdm_wait_transition(struct powerdomain *pwrdm) |
| 1022 | { | 874 | { |
| 1023 | u32 c = 0; | 875 | int ret = -EINVAL; |
| 1024 | 876 | ||
| 1025 | if (!pwrdm) | 877 | if (!pwrdm) |
| 1026 | return -EINVAL; | 878 | return -EINVAL; |
| 1027 | 879 | ||
| 1028 | /* | 880 | if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition) |
| 1029 | * REVISIT: pwrdm_wait_transition() may be better implemented | 881 | ret = arch_pwrdm->pwrdm_wait_transition(pwrdm); |
| 1030 | * via a callback and a periodic timer check -- how long do we expect | ||
| 1031 | * powerdomain transitions to take? | ||
| 1032 | */ | ||
| 1033 | |||
| 1034 | /* XXX Is this udelay() value meaningful? */ | ||
| 1035 | while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) & | ||
| 1036 | OMAP_INTRANSITION_MASK) && | ||
| 1037 | (c++ < PWRDM_TRANSITION_BAILOUT)) | ||
| 1038 | udelay(1); | ||
| 1039 | |||
| 1040 | if (c > PWRDM_TRANSITION_BAILOUT) { | ||
| 1041 | printk(KERN_ERR "powerdomain: waited too long for " | ||
| 1042 | "powerdomain %s to complete transition\n", pwrdm->name); | ||
| 1043 | return -EAGAIN; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | pr_debug("powerdomain: completed transition in %d loops\n", c); | ||
| 1047 | 882 | ||
| 1048 | return 0; | 883 | return ret; |
| 1049 | } | 884 | } |
| 1050 | 885 | ||
| 1051 | int pwrdm_state_switch(struct powerdomain *pwrdm) | 886 | int pwrdm_state_switch(struct powerdomain *pwrdm) |
| @@ -1075,3 +910,31 @@ int pwrdm_post_transition(void) | |||
| 1075 | return 0; | 910 | return 0; |
| 1076 | } | 911 | } |
| 1077 | 912 | ||
| 913 | /** | ||
| 914 | * pwrdm_get_context_loss_count - get powerdomain's context loss count | ||
| 915 | * @pwrdm: struct powerdomain * to wait for | ||
| 916 | * | ||
| 917 | * Context loss count is the sum of powerdomain off-mode counter, the | ||
| 918 | * logic off counter and the per-bank memory off counter. Returns 0 | ||
| 919 | * (and WARNs) upon error, otherwise, returns the context loss count. | ||
| 920 | */ | ||
| 921 | u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm) | ||
| 922 | { | ||
| 923 | int i, count; | ||
| 924 | |||
| 925 | if (!pwrdm) { | ||
| 926 | WARN(1, "powerdomain: %s: pwrdm is null\n", __func__); | ||
| 927 | return 0; | ||
| 928 | } | ||
| 929 | |||
| 930 | count = pwrdm->state_counter[PWRDM_POWER_OFF]; | ||
| 931 | count += pwrdm->ret_logic_off_counter; | ||
| 932 | |||
| 933 | for (i = 0; i < pwrdm->banks; i++) | ||
| 934 | count += pwrdm->ret_mem_off_counter[i]; | ||
| 935 | |||
| 936 | pr_debug("powerdomain: %s: context loss count = %u\n", | ||
| 937 | pwrdm->name, count); | ||
| 938 | |||
| 939 | return count; | ||
| 940 | } | ||
