diff options
-rw-r--r-- | arch/powerpc/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle_power7.S | 63 |
3 files changed, 53 insertions, 21 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index b62de43ae5f3..d660dc36831a 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -450,6 +450,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; | |||
450 | 450 | ||
451 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ | 451 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ |
452 | extern void power7_nap(void); | 452 | extern void power7_nap(void); |
453 | extern void power7_sleep(void); | ||
453 | extern void flush_instruction_cache(void); | 454 | extern void flush_instruction_cache(void); |
454 | extern void hard_reset_now(void); | 455 | extern void hard_reset_now(void); |
455 | extern void poweroff_now(void); | 456 | extern void poweroff_now(void); |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 38d507306a11..b01a9cb441e4 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -121,9 +121,10 @@ BEGIN_FTR_SECTION | |||
121 | cmpwi cr1,r13,2 | 121 | cmpwi cr1,r13,2 |
122 | /* Total loss of HV state is fatal, we could try to use the | 122 | /* Total loss of HV state is fatal, we could try to use the |
123 | * PIR to locate a PACA, then use an emergency stack etc... | 123 | * PIR to locate a PACA, then use an emergency stack etc... |
124 | * but for now, let's just stay stuck here | 124 | * OPAL v3 based powernv platforms have new idle states |
125 | * which fall in this catagory. | ||
125 | */ | 126 | */ |
126 | bgt cr1,. | 127 | bgt cr1,8f |
127 | GET_PACA(r13) | 128 | GET_PACA(r13) |
128 | 129 | ||
129 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | 130 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
@@ -141,6 +142,11 @@ BEGIN_FTR_SECTION | |||
141 | beq cr1,2f | 142 | beq cr1,2f |
142 | b .power7_wakeup_noloss | 143 | b .power7_wakeup_noloss |
143 | 2: b .power7_wakeup_loss | 144 | 2: b .power7_wakeup_loss |
145 | |||
146 | /* Fast Sleep wakeup on PowerNV */ | ||
147 | 8: GET_PACA(r13) | ||
148 | b .power7_wakeup_loss | ||
149 | |||
144 | 9: | 150 | 9: |
145 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) | 151 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) |
146 | #endif /* CONFIG_PPC_P7_NAP */ | 152 | #endif /* CONFIG_PPC_P7_NAP */ |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index 3fdef0f0c67f..14f78bec62c4 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S | |||
@@ -20,17 +20,27 @@ | |||
20 | 20 | ||
21 | #undef DEBUG | 21 | #undef DEBUG |
22 | 22 | ||
23 | .text | 23 | /* Idle state entry routines */ |
24 | 24 | ||
25 | _GLOBAL(power7_idle) | 25 | #define IDLE_STATE_ENTER_SEQ(IDLE_INST) \ |
26 | /* Now check if user or arch enabled NAP mode */ | 26 | /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \ |
27 | LOAD_REG_ADDRBASE(r3,powersave_nap) | 27 | std r0,0(r1); \ |
28 | lwz r4,ADDROFF(powersave_nap)(r3) | 28 | ptesync; \ |
29 | cmpwi 0,r4,0 | 29 | ld r0,0(r1); \ |
30 | beqlr | 30 | 1: cmp cr0,r0,r0; \ |
31 | /* fall through */ | 31 | bne 1b; \ |
32 | IDLE_INST; \ | ||
33 | b . | ||
32 | 34 | ||
33 | _GLOBAL(power7_nap) | 35 | .text |
36 | |||
37 | /* | ||
38 | * Pass requested state in r3: | ||
39 | * 0 - nap | ||
40 | * 1 - sleep | ||
41 | */ | ||
42 | _GLOBAL(power7_powersave_common) | ||
43 | /* Use r3 to pass state nap/sleep/winkle */ | ||
34 | /* NAP is a state loss, we create a regs frame on the | 44 | /* NAP is a state loss, we create a regs frame on the |
35 | * stack, fill it up with the state we care about and | 45 | * stack, fill it up with the state we care about and |
36 | * stick a pointer to it in PACAR1. We really only | 46 | * stick a pointer to it in PACAR1. We really only |
@@ -79,8 +89,8 @@ _GLOBAL(power7_nap) | |||
79 | /* Continue saving state */ | 89 | /* Continue saving state */ |
80 | SAVE_GPR(2, r1) | 90 | SAVE_GPR(2, r1) |
81 | SAVE_NVGPRS(r1) | 91 | SAVE_NVGPRS(r1) |
82 | mfcr r3 | 92 | mfcr r4 |
83 | std r3,_CCR(r1) | 93 | std r4,_CCR(r1) |
84 | std r9,_MSR(r1) | 94 | std r9,_MSR(r1) |
85 | std r1,PACAR1(r13) | 95 | std r1,PACAR1(r13) |
86 | 96 | ||
@@ -90,15 +100,30 @@ _GLOBAL(power7_enter_nap_mode) | |||
90 | li r4,KVM_HWTHREAD_IN_NAP | 100 | li r4,KVM_HWTHREAD_IN_NAP |
91 | stb r4,HSTATE_HWTHREAD_STATE(r13) | 101 | stb r4,HSTATE_HWTHREAD_STATE(r13) |
92 | #endif | 102 | #endif |
103 | cmpwi cr0,r3,1 | ||
104 | beq 2f | ||
105 | IDLE_STATE_ENTER_SEQ(PPC_NAP) | ||
106 | /* No return */ | ||
107 | 2: IDLE_STATE_ENTER_SEQ(PPC_SLEEP) | ||
108 | /* No return */ | ||
93 | 109 | ||
94 | /* Magic NAP mode enter sequence */ | 110 | _GLOBAL(power7_idle) |
95 | std r0,0(r1) | 111 | /* Now check if user or arch enabled NAP mode */ |
96 | ptesync | 112 | LOAD_REG_ADDRBASE(r3,powersave_nap) |
97 | ld r0,0(r1) | 113 | lwz r4,ADDROFF(powersave_nap)(r3) |
98 | 1: cmp cr0,r0,r0 | 114 | cmpwi 0,r4,0 |
99 | bne 1b | 115 | beqlr |
100 | PPC_NAP | 116 | /* fall through */ |
101 | b . | 117 | |
118 | _GLOBAL(power7_nap) | ||
119 | li r3,0 | ||
120 | b power7_powersave_common | ||
121 | /* No return */ | ||
122 | |||
123 | _GLOBAL(power7_sleep) | ||
124 | li r3,1 | ||
125 | b power7_powersave_common | ||
126 | /* No return */ | ||
102 | 127 | ||
103 | _GLOBAL(power7_wakeup_loss) | 128 | _GLOBAL(power7_wakeup_loss) |
104 | ld r1,PACAR1(r13) | 129 | ld r1,PACAR1(r13) |