aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/powerdomain.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r--arch/arm/mach-omap2/powerdomain.c506
1 files changed, 215 insertions, 291 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 6527ec30dc17..9af08473bf10 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -2,7 +2,7 @@
2 * OMAP powerdomain control 2 * OMAP powerdomain control
3 * 3 *
4 * Copyright (C) 2007-2008 Texas Instruments, Inc. 4 * Copyright (C) 2007-2008 Texas Instruments, Inc.
5 * Copyright (C) 2007-2009 Nokia Corporation 5 * Copyright (C) 2007-2011 Nokia Corporation
6 * 6 *
7 * Written by Paul Walmsley 7 * Written by Paul Walmsley
8 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com> 8 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -15,71 +15,39 @@
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 <trace/events/power.h>
26 23
27#include <asm/atomic.h> 24#include "cm2xxx_3xxx.h"
28 25#include "prcm44xx.h"
29#include "cm.h" 26#include "cm44xx.h"
30#include "cm-regbits-34xx.h" 27#include "prm2xxx_3xxx.h"
31#include "cm-regbits-44xx.h" 28#include "prm44xx.h"
32#include "prm.h"
33#include "prm-regbits-34xx.h"
34#include "prm-regbits-44xx.h"
35 29
30#include <asm/cpu.h>
36#include <plat/cpu.h> 31#include <plat/cpu.h>
37#include <plat/powerdomain.h> 32#include "powerdomain.h"
38#include <plat/clockdomain.h> 33#include "clockdomain.h"
39#include <plat/prcm.h> 34#include <plat/prcm.h>
40 35
41#include "pm.h" 36#include "pm.h"
42 37
38#define PWRDM_TRACE_STATES_FLAG (1<<31)
39
43enum { 40enum {
44 PWRDM_STATE_NOW = 0, 41 PWRDM_STATE_NOW = 0,
45 PWRDM_STATE_PREV, 42 PWRDM_STATE_PREV,
46}; 43};
47 44
48/* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */
49static u16 pwrstctrl_reg_offs;
50
51/* Variable holding value of the CPU dependent PWRSTST Register Offset */
52static 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 45
80/* pwrdm_list contains all registered struct powerdomains */ 46/* pwrdm_list contains all registered struct powerdomains */
81static LIST_HEAD(pwrdm_list); 47static LIST_HEAD(pwrdm_list);
82 48
49static struct pwrdm_ops *arch_pwrdm;
50
83/* Private functions */ 51/* Private functions */
84 52
85static struct powerdomain *_pwrdm_lookup(const char *name) 53static struct powerdomain *_pwrdm_lookup(const char *name)
@@ -110,12 +78,19 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
110{ 78{
111 int i; 79 int i;
112 80
113 if (!pwrdm) 81 if (!pwrdm || !pwrdm->name)
114 return -EINVAL; 82 return -EINVAL;
115 83
116 if (!omap_chip_is(pwrdm->omap_chip)) 84 if (!omap_chip_is(pwrdm->omap_chip))
117 return -EINVAL; 85 return -EINVAL;
118 86
87 if (cpu_is_omap44xx() &&
88 pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
89 pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
90 pwrdm->name);
91 return -EINVAL;
92 }
93
119 if (_pwrdm_lookup(pwrdm->name)) 94 if (_pwrdm_lookup(pwrdm->name))
120 return -EEXIST; 95 return -EEXIST;
121 96
@@ -160,8 +135,7 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
160static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) 135static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
161{ 136{
162 137
163 int prev; 138 int prev, state, trace_state = 0;
164 int state;
165 139
166 if (pwrdm == NULL) 140 if (pwrdm == NULL)
167 return -EINVAL; 141 return -EINVAL;
@@ -178,6 +152,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
178 pwrdm->state_counter[prev]++; 152 pwrdm->state_counter[prev]++;
179 if (prev == PWRDM_POWER_RET) 153 if (prev == PWRDM_POWER_RET)
180 _update_logic_membank_counters(pwrdm); 154 _update_logic_membank_counters(pwrdm);
155 /*
156 * If the power domain did not hit the desired state,
157 * generate a trace event with both the desired and hit states
158 */
159 if (state != prev) {
160 trace_state = (PWRDM_TRACE_STATES_FLAG |
161 ((state & OMAP_POWERSTATE_MASK) << 8) |
162 ((prev & OMAP_POWERSTATE_MASK) << 0));
163 trace_power_domain_target(pwrdm->name, trace_state,
164 smp_processor_id());
165 }
181 break; 166 break;
182 default: 167 default:
183 return -EINVAL; 168 return -EINVAL;
@@ -211,6 +196,7 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
211/** 196/**
212 * pwrdm_init - set up the powerdomain layer 197 * pwrdm_init - set up the powerdomain layer
213 * @pwrdm_list: array of struct powerdomain pointers to register 198 * @pwrdm_list: array of struct powerdomain pointers to register
199 * @custom_funcs: func pointers for arch specific implementations
214 * 200 *
215 * Loop through the array of powerdomains @pwrdm_list, registering all 201 * Loop through the array of powerdomains @pwrdm_list, registering all
216 * that are available on the current CPU. If pwrdm_list is supplied 202 * that are available on the current CPU. If pwrdm_list is supplied
@@ -218,21 +204,14 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
218 * registered. No return value. XXX pwrdm_list is not really a 204 * registered. No return value. XXX pwrdm_list is not really a
219 * "list"; it is an array. Rename appropriately. 205 * "list"; it is an array. Rename appropriately.
220 */ 206 */
221void pwrdm_init(struct powerdomain **pwrdm_list) 207void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs)
222{ 208{
223 struct powerdomain **p = NULL; 209 struct powerdomain **p = NULL;
224 210
225 if (cpu_is_omap24xx() || cpu_is_omap34xx()) { 211 if (!custom_funcs)
226 pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL; 212 WARN(1, "powerdomain: No custom pwrdm functions registered\n");
227 pwrstst_reg_offs = OMAP2_PM_PWSTST; 213 else
228 } else if (cpu_is_omap44xx()) { 214 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 215
237 if (pwrdm_list) { 216 if (pwrdm_list) {
238 for (p = pwrdm_list; *p; p++) 217 for (p = pwrdm_list; *p; p++)
@@ -431,6 +410,8 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
431 */ 410 */
432int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) 411int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
433{ 412{
413 int ret = -EINVAL;
414
434 if (!pwrdm) 415 if (!pwrdm)
435 return -EINVAL; 416 return -EINVAL;
436 417
@@ -440,11 +421,15 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
440 pr_debug("powerdomain: setting next powerstate for %s to %0x\n", 421 pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
441 pwrdm->name, pwrst); 422 pwrdm->name, pwrst);
442 423
443 prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, 424 if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
444 (pwrst << OMAP_POWERSTATE_SHIFT), 425 /* Trace the pwrdm desired target state */
445 pwrdm->prcm_offs, pwrstctrl_reg_offs); 426 trace_power_domain_target(pwrdm->name, pwrst,
427 smp_processor_id());
428 /* Program the pwrdm desired target state */
429 ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
430 }
446 431
447 return 0; 432 return ret;
448} 433}
449 434
450/** 435/**
@@ -457,11 +442,15 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
457 */ 442 */
458int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) 443int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
459{ 444{
445 int ret = -EINVAL;
446
460 if (!pwrdm) 447 if (!pwrdm)
461 return -EINVAL; 448 return -EINVAL;
462 449
463 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 450 if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst)
464 pwrstctrl_reg_offs, OMAP_POWERSTATE_MASK); 451 ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
452
453 return ret;
465} 454}
466 455
467/** 456/**
@@ -474,11 +463,15 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
474 */ 463 */
475int pwrdm_read_pwrst(struct powerdomain *pwrdm) 464int pwrdm_read_pwrst(struct powerdomain *pwrdm)
476{ 465{
466 int ret = -EINVAL;
467
477 if (!pwrdm) 468 if (!pwrdm)
478 return -EINVAL; 469 return -EINVAL;
479 470
480 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 471 if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst)
481 pwrstst_reg_offs, OMAP_POWERSTATEST_MASK); 472 ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm);
473
474 return ret;
482} 475}
483 476
484/** 477/**
@@ -491,11 +484,15 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
491 */ 484 */
492int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) 485int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
493{ 486{
487 int ret = -EINVAL;
488
494 if (!pwrdm) 489 if (!pwrdm)
495 return -EINVAL; 490 return -EINVAL;
496 491
497 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST, 492 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst)
498 OMAP3430_LASTPOWERSTATEENTERED_MASK); 493 ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm);
494
495 return ret;
499} 496}
500 497
501/** 498/**
@@ -511,7 +508,7 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
511 */ 508 */
512int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 509int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
513{ 510{
514 u32 v; 511 int ret = -EINVAL;
515 512
516 if (!pwrdm) 513 if (!pwrdm)
517 return -EINVAL; 514 return -EINVAL;
@@ -522,17 +519,10 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
522 pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n", 519 pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
523 pwrdm->name, pwrst); 520 pwrdm->name, pwrst);
524 521
525 /* 522 if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst)
526 * The register bit names below may not correspond to the 523 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 524
535 return 0; 525 return ret;
536} 526}
537 527
538/** 528/**
@@ -552,7 +542,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
552 */ 542 */
553int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 543int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
554{ 544{
555 u32 m; 545 int ret = -EINVAL;
556 546
557 if (!pwrdm) 547 if (!pwrdm)
558 return -EINVAL; 548 return -EINVAL;
@@ -566,37 +556,10 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
566 pr_debug("powerdomain: setting next memory powerstate for domain %s " 556 pr_debug("powerdomain: setting next memory powerstate for domain %s "
567 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst); 557 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
568 558
569 /* 559 if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
570 * The register bit names below may not correspond to the 560 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 561
596 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), 562 return ret;
597 pwrdm->prcm_offs, pwrstctrl_reg_offs);
598
599 return 0;
600} 563}
601 564
602/** 565/**
@@ -617,7 +580,7 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
617 */ 580 */
618int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst) 581int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
619{ 582{
620 u32 m; 583 int ret = -EINVAL;
621 584
622 if (!pwrdm) 585 if (!pwrdm)
623 return -EINVAL; 586 return -EINVAL;
@@ -631,37 +594,10 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
631 pr_debug("powerdomain: setting next memory powerstate for domain %s " 594 pr_debug("powerdomain: setting next memory powerstate for domain %s "
632 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst); 595 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
633 596
634 /* 597 if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst)
635 * The register bit names below may not correspond to the 598 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 599
664 return 0; 600 return ret;
665} 601}
666 602
667/** 603/**
@@ -675,11 +611,15 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
675 */ 611 */
676int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) 612int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
677{ 613{
614 int ret = -EINVAL;
615
678 if (!pwrdm) 616 if (!pwrdm)
679 return -EINVAL; 617 return -EINVAL;
680 618
681 return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstst_reg_offs, 619 if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst)
682 OMAP3430_LOGICSTATEST_MASK); 620 ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
621
622 return ret;
683} 623}
684 624
685/** 625/**
@@ -692,17 +632,15 @@ int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
692 */ 632 */
693int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) 633int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
694{ 634{
635 int ret = -EINVAL;
636
695 if (!pwrdm) 637 if (!pwrdm)
696 return -EINVAL; 638 return -EINVAL;
697 639
698 /* 640 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst)
699 * The register bit names below may not correspond to the 641 ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm);
700 * actual names of the bits in each powerdomain's register, 642
701 * but the type of value returned is the same for each 643 return ret;
702 * powerdomain.
703 */
704 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
705 OMAP3430_LASTLOGICSTATEENTERED_MASK);
706} 644}
707 645
708/** 646/**
@@ -715,17 +653,15 @@ int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
715 */ 653 */
716int pwrdm_read_logic_retst(struct powerdomain *pwrdm) 654int pwrdm_read_logic_retst(struct powerdomain *pwrdm)
717{ 655{
656 int ret = -EINVAL;
657
718 if (!pwrdm) 658 if (!pwrdm)
719 return -EINVAL; 659 return -EINVAL;
720 660
721 /* 661 if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst)
722 * The register bit names below may not correspond to the 662 ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm);
723 * actual names of the bits in each powerdomain's register, 663
724 * but the type of value returned is the same for each 664 return ret;
725 * powerdomain.
726 */
727 return prm_read_mod_bits_shift(pwrdm->prcm_offs, pwrstctrl_reg_offs,
728 OMAP3430_LOGICSTATEST_MASK);
729} 665}
730 666
731/** 667/**
@@ -740,46 +676,21 @@ int pwrdm_read_logic_retst(struct powerdomain *pwrdm)
740 */ 676 */
741int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 677int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
742{ 678{
743 u32 m; 679 int ret = -EINVAL;
744 680
745 if (!pwrdm) 681 if (!pwrdm)
746 return -EINVAL; 682 return ret;
747 683
748 if (pwrdm->banks < (bank + 1)) 684 if (pwrdm->banks < (bank + 1))
749 return -EEXIST; 685 return ret;
750 686
751 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) 687 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
752 bank = 1; 688 bank = 1;
753 689
754 /* 690 if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_pwrst)
755 * The register bit names below may not correspond to the 691 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 692
781 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 693 return ret;
782 pwrstst_reg_offs, m);
783} 694}
784 695
785/** 696/**
@@ -795,43 +706,21 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
795 */ 706 */
796int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 707int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
797{ 708{
798 u32 m; 709 int ret = -EINVAL;
799 710
800 if (!pwrdm) 711 if (!pwrdm)
801 return -EINVAL; 712 return ret;
802 713
803 if (pwrdm->banks < (bank + 1)) 714 if (pwrdm->banks < (bank + 1))
804 return -EEXIST; 715 return ret;
805 716
806 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK) 717 if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
807 bank = 1; 718 bank = 1;
808 719
809 /* 720 if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_mem_pwrst)
810 * The register bit names below may not correspond to the 721 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 722
833 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 723 return ret;
834 OMAP3430_PM_PREPWSTST, m);
835} 724}
836 725
837/** 726/**
@@ -846,43 +735,18 @@ int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
846 */ 735 */
847int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) 736int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
848{ 737{
849 u32 m; 738 int ret = -EINVAL;
850 739
851 if (!pwrdm) 740 if (!pwrdm)
852 return -EINVAL; 741 return ret;
853 742
854 if (pwrdm->banks < (bank + 1)) 743 if (pwrdm->banks < (bank + 1))
855 return -EEXIST; 744 return ret;
856 745
857 /* 746 if (arch_pwrdm && arch_pwrdm->pwrdm_read_mem_retst)
858 * The register bit names below may not correspond to the 747 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 748
884 return prm_read_mod_bits_shift(pwrdm->prcm_offs, 749 return ret;
885 pwrstctrl_reg_offs, m);
886} 750}
887 751
888/** 752/**
@@ -896,8 +760,10 @@ int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
896 */ 760 */
897int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) 761int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
898{ 762{
763 int ret = -EINVAL;
764
899 if (!pwrdm) 765 if (!pwrdm)
900 return -EINVAL; 766 return ret;
901 767
902 /* 768 /*
903 * XXX should get the powerdomain's current state here; 769 * XXX should get the powerdomain's current state here;
@@ -907,9 +773,10 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
907 pr_debug("powerdomain: clearing previous power state reg for %s\n", 773 pr_debug("powerdomain: clearing previous power state reg for %s\n",
908 pwrdm->name); 774 pwrdm->name);
909 775
910 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); 776 if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst)
777 ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm);
911 778
912 return 0; 779 return ret;
913} 780}
914 781
915/** 782/**
@@ -925,19 +792,21 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
925 */ 792 */
926int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) 793int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
927{ 794{
795 int ret = -EINVAL;
796
928 if (!pwrdm) 797 if (!pwrdm)
929 return -EINVAL; 798 return ret;
930 799
931 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 800 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
932 return -EINVAL; 801 return ret;
933 802
934 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", 803 pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
935 pwrdm->name); 804 pwrdm->name);
936 805
937 prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 806 if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar)
938 pwrdm->prcm_offs, pwrstctrl_reg_offs); 807 ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm);
939 808
940 return 0; 809 return ret;
941} 810}
942 811
943/** 812/**
@@ -953,19 +822,21 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
953 */ 822 */
954int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) 823int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
955{ 824{
825 int ret = -EINVAL;
826
956 if (!pwrdm) 827 if (!pwrdm)
957 return -EINVAL; 828 return ret;
958 829
959 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR)) 830 if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
960 return -EINVAL; 831 return ret;
961 832
962 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", 833 pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
963 pwrdm->name); 834 pwrdm->name);
964 835
965 prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0, 836 if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar)
966 pwrdm->prcm_offs, pwrstctrl_reg_offs); 837 ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm);
967 838
968 return 0; 839 return ret;
969} 840}
970 841
971/** 842/**
@@ -992,6 +863,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
992 */ 863 */
993int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) 864int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
994{ 865{
866 int ret = -EINVAL;
867
995 if (!pwrdm) 868 if (!pwrdm)
996 return -EINVAL; 869 return -EINVAL;
997 870
@@ -1001,11 +874,10 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
1001 pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", 874 pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
1002 pwrdm->name); 875 pwrdm->name);
1003 876
1004 prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, 877 if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
1005 (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), 878 ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
1006 pwrdm->prcm_offs, pwrstctrl_reg_offs);
1007 879
1008 return 0; 880 return ret;
1009} 881}
1010 882
1011/** 883/**
@@ -1020,32 +892,15 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
1020 */ 892 */
1021int pwrdm_wait_transition(struct powerdomain *pwrdm) 893int pwrdm_wait_transition(struct powerdomain *pwrdm)
1022{ 894{
1023 u32 c = 0; 895 int ret = -EINVAL;
1024 896
1025 if (!pwrdm) 897 if (!pwrdm)
1026 return -EINVAL; 898 return -EINVAL;
1027 899
1028 /* 900 if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
1029 * REVISIT: pwrdm_wait_transition() may be better implemented 901 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 902
1048 return 0; 903 return ret;
1049} 904}
1050 905
1051int pwrdm_state_switch(struct powerdomain *pwrdm) 906int pwrdm_state_switch(struct powerdomain *pwrdm)
@@ -1075,3 +930,72 @@ int pwrdm_post_transition(void)
1075 return 0; 930 return 0;
1076} 931}
1077 932
933/**
934 * pwrdm_get_context_loss_count - get powerdomain's context loss count
935 * @pwrdm: struct powerdomain * to wait for
936 *
937 * Context loss count is the sum of powerdomain off-mode counter, the
938 * logic off counter and the per-bank memory off counter. Returns 0
939 * (and WARNs) upon error, otherwise, returns the context loss count.
940 */
941u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
942{
943 int i, count;
944
945 if (!pwrdm) {
946 WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
947 return 0;
948 }
949
950 count = pwrdm->state_counter[PWRDM_POWER_OFF];
951 count += pwrdm->ret_logic_off_counter;
952
953 for (i = 0; i < pwrdm->banks; i++)
954 count += pwrdm->ret_mem_off_counter[i];
955
956 pr_debug("powerdomain: %s: context loss count = %u\n",
957 pwrdm->name, count);
958
959 return count;
960}
961
962/**
963 * pwrdm_can_ever_lose_context - can this powerdomain ever lose context?
964 * @pwrdm: struct powerdomain *
965 *
966 * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain
967 * can lose either memory or logic context or if @pwrdm is invalid, or
968 * returns 0 otherwise. This function is not concerned with how the
969 * powerdomain registers are programmed (i.e., to go off or not); it's
970 * concerned with whether it's ever possible for this powerdomain to
971 * go off while some other part of the chip is active. This function
972 * assumes that every powerdomain can go to either ON or INACTIVE.
973 */
974bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
975{
976 int i;
977
978 if (IS_ERR_OR_NULL(pwrdm)) {
979 pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
980 __func__);
981 return 1;
982 }
983
984 if (pwrdm->pwrsts & PWRSTS_OFF)
985 return 1;
986
987 if (pwrdm->pwrsts & PWRSTS_RET) {
988 if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF)
989 return 1;
990
991 for (i = 0; i < pwrdm->banks; i++)
992 if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF)
993 return 1;
994 }
995
996 for (i = 0; i < pwrdm->banks; i++)
997 if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF)
998 return 1;
999
1000 return 0;
1001}