i2c: Driver to expose PowerNV platform i2c busses
[deliverable/linux.git] / arch / powerpc / kernel / idle_power7.S
CommitLineData
948cf67c 1/*
7230c564 2 * This file contains the power_save function for Power7 CPUs.
948cf67c
BH
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <linux/threads.h>
11#include <asm/processor.h>
12#include <asm/page.h>
13#include <asm/cputable.h>
14#include <asm/thread_info.h>
15#include <asm/ppc_asm.h>
16#include <asm/asm-offsets.h>
17#include <asm/ppc-opcode.h>
7230c564 18#include <asm/hw_irq.h>
f0888f70 19#include <asm/kvm_book3s_asm.h>
97eb001f 20#include <asm/opal.h>
948cf67c
BH
21
22#undef DEBUG
23
aca79d2b 24/* Idle state entry routines */
948cf67c 25
aca79d2b
VS
26#define IDLE_STATE_ENTER_SEQ(IDLE_INST) \
27 /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
28 std r0,0(r1); \
29 ptesync; \
30 ld r0,0(r1); \
311: cmp cr0,r0,r0; \
32 bne 1b; \
33 IDLE_INST; \
34 b .
948cf67c 35
aca79d2b
VS
36 .text
37
38/*
39 * Pass requested state in r3:
40 * 0 - nap
41 * 1 - sleep
8d6f7c5a
ME
42 *
43 * To check IRQ_HAPPENED in r4
44 * 0 - don't check
45 * 1 - check
aca79d2b
VS
46 */
47_GLOBAL(power7_powersave_common)
48 /* Use r3 to pass state nap/sleep/winkle */
948cf67c
BH
49 /* NAP is a state loss, we create a regs frame on the
50 * stack, fill it up with the state we care about and
51 * stick a pointer to it in PACAR1. We really only
52 * need to save PC, some CR bits and the NV GPRs,
53 * but for now an interrupt frame will do.
54 */
55 mflr r0
56 std r0,16(r1)
57 stdu r1,-INT_FRAME_SIZE(r1)
58 std r0,_LINK(r1)
59 std r0,_NIP(r1)
60
61#ifndef CONFIG_SMP
62 /* Make sure FPU, VSX etc... are flushed as we may lose
63 * state when going to nap mode
64 */
b1576fec 65 bl discard_lazy_cpu_state
948cf67c
BH
66#endif /* CONFIG_SMP */
67
68 /* Hard disable interrupts */
69 mfmsr r9
70 rldicl r9,r9,48,1
71 rotldi r9,r9,16
72 mtmsrd r9,1 /* hard-disable interrupts */
7230c564
BH
73
74 /* Check if something happened while soft-disabled */
75 lbz r0,PACAIRQHAPPENED(r13)
d6a4f709 76 andi. r0,r0,~PACA_IRQ_HARD_DIS@l
7230c564 77 beq 1f
8d6f7c5a
ME
78 cmpwi cr0,r4,0
79 beq 1f
7230c564
BH
80 addi r1,r1,INT_FRAME_SIZE
81 ld r0,16(r1)
82 mtlr r0
83 blr
84
851: /* We mark irqs hard disabled as this is the state we'll
86 * be in when returning and we need to tell arch_local_irq_restore()
87 * about it
88 */
89 li r0,PACA_IRQ_HARD_DIS
90 stb r0,PACAIRQHAPPENED(r13)
91
92 /* We haven't lost state ... yet */
948cf67c 93 li r0,0
2fde6d20 94 stb r0,PACA_NAPSTATELOST(r13)
948cf67c
BH
95
96 /* Continue saving state */
97 SAVE_GPR(2, r1)
98 SAVE_NVGPRS(r1)
aca79d2b
VS
99 mfcr r4
100 std r4,_CCR(r1)
948cf67c
BH
101 std r9,_MSR(r1)
102 std r1,PACAR1(r13)
103
1c51089f 104_GLOBAL(power7_enter_nap_mode)
9975f5e3 105#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
f0888f70
PM
106 /* Tell KVM we're napping */
107 li r4,KVM_HWTHREAD_IN_NAP
108 stb r4,HSTATE_HWTHREAD_STATE(r13)
109#endif
aca79d2b
VS
110 cmpwi cr0,r3,1
111 beq 2f
112 IDLE_STATE_ENTER_SEQ(PPC_NAP)
113 /* No return */
1142: IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
115 /* No return */
f0888f70 116
aca79d2b
VS
117_GLOBAL(power7_idle)
118 /* Now check if user or arch enabled NAP mode */
119 LOAD_REG_ADDRBASE(r3,powersave_nap)
120 lwz r4,ADDROFF(powersave_nap)(r3)
121 cmpwi 0,r4,0
122 beqlr
8d6f7c5a 123 li r3, 1
aca79d2b
VS
124 /* fall through */
125
126_GLOBAL(power7_nap)
8d6f7c5a 127 mr r4,r3
aca79d2b
VS
128 li r3,0
129 b power7_powersave_common
130 /* No return */
131
132_GLOBAL(power7_sleep)
133 li r3,1
c733cf83 134 li r4,1
aca79d2b
VS
135 b power7_powersave_common
136 /* No return */
948cf67c 137
db97efff
MS
138/*
139 * Make opal call in realmode. This is a generic function to be called
140 * from realmode from reset vector. It handles endianess.
141 *
142 * r13 - paca pointer
143 * r1 - stack pointer
144 * r3 - opal token
145 */
146opal_call_realmode:
147 mflr r12
148 std r12,_LINK(r1)
149 ld r2,PACATOC(r13)
150 /* Set opal return address */
151 LOAD_REG_ADDR(r0,return_from_opal_call)
152 mtlr r0
153 /* Handle endian-ness */
154 li r0,MSR_LE
155 mfmsr r12
156 andc r12,r12,r0
157 mtspr SPRN_HSRR1,r12
158 mr r0,r3 /* Move opal token to r0 */
159 LOAD_REG_ADDR(r11,opal)
160 ld r12,8(r11)
161 ld r2,0(r11)
162 mtspr SPRN_HSRR0,r12
163 hrfid
164
165return_from_opal_call:
166 FIXUP_ENDIAN
167 ld r0,_LINK(r1)
168 mtlr r0
169 blr
170
bbdb760d
MS
171#define CHECK_HMI_INTERRUPT \
172 mfspr r0,SPRN_SRR1; \
173BEGIN_FTR_SECTION_NESTED(66); \
174 rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \
175FTR_SECTION_ELSE_NESTED(66); \
176 rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \
177ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
178 cmpwi r0,0xa; /* Hypervisor maintenance ? */ \
179 bne 20f; \
180 /* Invoke opal call to handle hmi */ \
181 ld r2,PACATOC(r13); \
182 ld r1,PACAR1(r13); \
183 std r3,ORIG_GPR3(r1); /* Save original r3 */ \
db97efff
MS
184 li r3,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \
185 bl opal_call_realmode; \
bbdb760d
MS
186 ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \
18720: nop;
188
189
97eb001f
VS
190_GLOBAL(power7_wakeup_tb_loss)
191 ld r2,PACATOC(r13);
192 ld r1,PACAR1(r13)
193
bbdb760d
MS
194BEGIN_FTR_SECTION
195 CHECK_HMI_INTERRUPT
196END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
97eb001f 197 /* Time base re-sync */
db97efff
MS
198 li r3,OPAL_RESYNC_TIMEBASE
199 bl opal_call_realmode;
97eb001f
VS
200
201 /* TODO: Check r3 for failure */
202
203 REST_NVGPRS(r1)
204 REST_GPR(2, r1)
205 ld r3,_CCR(r1)
206 ld r4,_MSR(r1)
207 ld r5,_NIP(r1)
208 addi r1,r1,INT_FRAME_SIZE
209 mtcr r3
210 mfspr r3,SPRN_SRR1 /* Return SRR1 */
211 mtspr SPRN_SRR1,r4
212 mtspr SPRN_SRR0,r5
213 rfid
214
56548fc0
PM
215/*
216 * R3 here contains the value that will be returned to the caller
217 * of power7_nap.
218 */
948cf67c 219_GLOBAL(power7_wakeup_loss)
948cf67c 220 ld r1,PACAR1(r13)
bbdb760d
MS
221BEGIN_FTR_SECTION
222 CHECK_HMI_INTERRUPT
223END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
948cf67c
BH
224 REST_NVGPRS(r1)
225 REST_GPR(2, r1)
56548fc0 226 ld r6,_CCR(r1)
948cf67c
BH
227 ld r4,_MSR(r1)
228 ld r5,_NIP(r1)
229 addi r1,r1,INT_FRAME_SIZE
56548fc0 230 mtcr r6
948cf67c
BH
231 mtspr SPRN_SRR1,r4
232 mtspr SPRN_SRR0,r5
233 rfid
234
56548fc0
PM
235/*
236 * R3 here contains the value that will be returned to the caller
237 * of power7_nap.
238 */
948cf67c 239_GLOBAL(power7_wakeup_noloss)
2fde6d20
PM
240 lbz r0,PACA_NAPSTATELOST(r13)
241 cmpwi r0,0
b1576fec 242 bne power7_wakeup_loss
bbdb760d
MS
243BEGIN_FTR_SECTION
244 CHECK_HMI_INTERRUPT
245END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
948cf67c
BH
246 ld r1,PACAR1(r13)
247 ld r4,_MSR(r1)
248 ld r5,_NIP(r1)
249 addi r1,r1,INT_FRAME_SIZE
250 mtspr SPRN_SRR1,r4
251 mtspr SPRN_SRR0,r5
252 rfid
This page took 0.181481 seconds and 5 git commands to generate.