diff options
-rw-r--r-- | arch/powerpc/include/asm/machdep.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/paca.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc-opcode.h | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 30 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle_power7.S | 97 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 4 |
7 files changed, 139 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index e4f01915fbb0..493dbb38e1ba 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -267,6 +267,7 @@ struct machdep_calls { | |||
267 | 267 | ||
268 | extern void e500_idle(void); | 268 | extern void e500_idle(void); |
269 | extern void power4_idle(void); | 269 | extern void power4_idle(void); |
270 | extern void power7_idle(void); | ||
270 | extern void ppc6xx_idle(void); | 271 | extern void ppc6xx_idle(void); |
271 | extern void book3e_idle(void); | 272 | extern void book3e_idle(void); |
272 | 273 | ||
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index ec57540cd7af..f6da4f517fca 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -125,7 +125,7 @@ struct paca_struct { | |||
125 | struct task_struct *__current; /* Pointer to current */ | 125 | struct task_struct *__current; /* Pointer to current */ |
126 | u64 kstack; /* Saved Kernel stack addr */ | 126 | u64 kstack; /* Saved Kernel stack addr */ |
127 | u64 stab_rr; /* stab/slb round-robin counter */ | 127 | u64 stab_rr; /* stab/slb round-robin counter */ |
128 | u64 saved_r1; /* r1 save for RTAS calls */ | 128 | u64 saved_r1; /* r1 save for RTAS calls or PM */ |
129 | u64 saved_msr; /* MSR saved here by enter_rtas */ | 129 | u64 saved_msr; /* MSR saved here by enter_rtas */ |
130 | u16 trap_save; /* Used when bad stack is encountered */ | 130 | u16 trap_save; /* Used when bad stack is encountered */ |
131 | u8 soft_enabled; /* irq soft-enable flag */ | 131 | u8 soft_enabled; /* irq soft-enable flag */ |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 1255569387b6..384a96db794a 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -56,6 +56,9 @@ | |||
56 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 | 56 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 |
57 | #define PPC_INST_XXLOR 0xf0000510 | 57 | #define PPC_INST_XXLOR 0xf0000510 |
58 | 58 | ||
59 | #define PPC_INST_NAP 0x4c000364 | ||
60 | #define PPC_INST_SLEEP 0x4c0003a4 | ||
61 | |||
59 | /* macros to insert fields into opcodes */ | 62 | /* macros to insert fields into opcodes */ |
60 | #define __PPC_RA(a) (((a) & 0x1f) << 16) | 63 | #define __PPC_RA(a) (((a) & 0x1f) << 16) |
61 | #define __PPC_RB(b) (((b) & 0x1f) << 11) | 64 | #define __PPC_RB(b) (((b) & 0x1f) << 11) |
@@ -126,4 +129,7 @@ | |||
126 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ | 129 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ |
127 | VSX_XX3((t), (a), (b))) | 130 | VSX_XX3((t), (a), (b))) |
128 | 131 | ||
132 | #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) | ||
133 | #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) | ||
134 | |||
129 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ | 135 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 7c6eb4974f25..0fd6273bb8a9 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o | |||
44 | obj-$(CONFIG_PPC64) += vdso64/ | 44 | obj-$(CONFIG_PPC64) += vdso64/ |
45 | obj-$(CONFIG_ALTIVEC) += vecemu.o | 45 | obj-$(CONFIG_ALTIVEC) += vecemu.o |
46 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 46 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
47 | obj-$(CONFIG_PPC_P7_NAP) += idle_power7.o | ||
47 | obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o | 48 | obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o |
48 | obj-$(CONFIG_PPC_CLOCK) += clock.o | 49 | obj-$(CONFIG_PPC_CLOCK) += clock.o |
49 | procfs-y := proc_powerpc.o | 50 | procfs-y := proc_powerpc.o |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index e513c1d35b2a..ad06333631ac 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -37,7 +37,35 @@ | |||
37 | .globl __start_interrupts | 37 | .globl __start_interrupts |
38 | __start_interrupts: | 38 | __start_interrupts: |
39 | 39 | ||
40 | STD_EXCEPTION_PSERIES(0x100, 0x100, system_reset) | 40 | .globl system_reset_pSeries; |
41 | system_reset_pSeries: | ||
42 | HMT_MEDIUM; | ||
43 | DO_KVM 0x100; | ||
44 | SET_SCRATCH0(r13) | ||
45 | #ifdef CONFIG_PPC_P7_NAP | ||
46 | BEGIN_FTR_SECTION | ||
47 | /* Running native on arch 2.06 or later, check if we are | ||
48 | * waking up from nap. We only handle no state loss and | ||
49 | * supervisor state loss. We do -not- handle hypervisor | ||
50 | * state loss at this time. | ||
51 | */ | ||
52 | mfspr r13,SPRN_SRR1 | ||
53 | rlwinm r13,r13,47-31,30,31 | ||
54 | cmpwi cr0,r13,1 | ||
55 | bne 1f | ||
56 | b .power7_wakeup_noloss | ||
57 | 1: cmpwi cr0,r13,2 | ||
58 | bne 1f | ||
59 | b .power7_wakeup_loss | ||
60 | /* Total loss of HV state is fatal, we could try to use the | ||
61 | * PIR to locate a PACA, then use an emergency stack etc... | ||
62 | * but for now, let's just stay stuck here | ||
63 | */ | ||
64 | 1: cmpwi cr0,r13,3 | ||
65 | beq . | ||
66 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206) | ||
67 | #endif /* CONFIG_PPC_P7_NAP */ | ||
68 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD) | ||
41 | 69 | ||
42 | . = 0x200 | 70 | . = 0x200 |
43 | _machine_check_pSeries: | 71 | _machine_check_pSeries: |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S new file mode 100644 index 000000000000..f8f0bc7f1d4f --- /dev/null +++ b/arch/powerpc/kernel/idle_power7.S | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * This file contains the power_save function for 970-family CPUs. | ||
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> | ||
18 | |||
19 | #undef DEBUG | ||
20 | |||
21 | .text | ||
22 | |||
23 | _GLOBAL(power7_idle) | ||
24 | /* Now check if user or arch enabled NAP mode */ | ||
25 | LOAD_REG_ADDRBASE(r3,powersave_nap) | ||
26 | lwz r4,ADDROFF(powersave_nap)(r3) | ||
27 | cmpwi 0,r4,0 | ||
28 | beqlr | ||
29 | |||
30 | /* NAP is a state loss, we create a regs frame on the | ||
31 | * stack, fill it up with the state we care about and | ||
32 | * stick a pointer to it in PACAR1. We really only | ||
33 | * need to save PC, some CR bits and the NV GPRs, | ||
34 | * but for now an interrupt frame will do. | ||
35 | */ | ||
36 | mflr r0 | ||
37 | std r0,16(r1) | ||
38 | stdu r1,-INT_FRAME_SIZE(r1) | ||
39 | std r0,_LINK(r1) | ||
40 | std r0,_NIP(r1) | ||
41 | |||
42 | #ifndef CONFIG_SMP | ||
43 | /* Make sure FPU, VSX etc... are flushed as we may lose | ||
44 | * state when going to nap mode | ||
45 | */ | ||
46 | bl .discard_lazy_cpu_state | ||
47 | #endif /* CONFIG_SMP */ | ||
48 | |||
49 | /* Hard disable interrupts */ | ||
50 | mfmsr r9 | ||
51 | rldicl r9,r9,48,1 | ||
52 | rotldi r9,r9,16 | ||
53 | mtmsrd r9,1 /* hard-disable interrupts */ | ||
54 | li r0,0 | ||
55 | stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */ | ||
56 | stb r0,PACAHARDIRQEN(r13) | ||
57 | |||
58 | /* Continue saving state */ | ||
59 | SAVE_GPR(2, r1) | ||
60 | SAVE_NVGPRS(r1) | ||
61 | mfcr r3 | ||
62 | std r3,_CCR(r1) | ||
63 | std r9,_MSR(r1) | ||
64 | std r1,PACAR1(r13) | ||
65 | |||
66 | /* Magic NAP mode enter sequence */ | ||
67 | std r0,0(r1) | ||
68 | ptesync | ||
69 | ld r0,0(r1) | ||
70 | 1: cmp cr0,r0,r0 | ||
71 | bne 1b | ||
72 | PPC_NAP | ||
73 | b . | ||
74 | |||
75 | _GLOBAL(power7_wakeup_loss) | ||
76 | GET_PACA(r13) | ||
77 | ld r1,PACAR1(r13) | ||
78 | REST_NVGPRS(r1) | ||
79 | REST_GPR(2, r1) | ||
80 | ld r3,_CCR(r1) | ||
81 | ld r4,_MSR(r1) | ||
82 | ld r5,_NIP(r1) | ||
83 | addi r1,r1,INT_FRAME_SIZE | ||
84 | mtcr r3 | ||
85 | mtspr SPRN_SRR1,r4 | ||
86 | mtspr SPRN_SRR0,r5 | ||
87 | rfid | ||
88 | |||
89 | _GLOBAL(power7_wakeup_noloss) | ||
90 | GET_PACA(r13) | ||
91 | ld r1,PACAR1(r13) | ||
92 | ld r4,_MSR(r1) | ||
93 | ld r5,_NIP(r1) | ||
94 | addi r1,r1,INT_FRAME_SIZE | ||
95 | mtspr SPRN_SRR1,r4 | ||
96 | mtspr SPRN_SRR0,r5 | ||
97 | rfid | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index f7b07720aa30..658ffc50493d 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -147,6 +147,10 @@ config PPC_970_NAP | |||
147 | bool | 147 | bool |
148 | default n | 148 | default n |
149 | 149 | ||
150 | config PPC_P7_NAP | ||
151 | bool | ||
152 | default n | ||
153 | |||
150 | config PPC_INDIRECT_IO | 154 | config PPC_INDIRECT_IO |
151 | bool | 155 | bool |
152 | select GENERIC_IOMAP | 156 | select GENERIC_IOMAP |