aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-03-26 23:03:03 -0500
committerPaul Mackerras <paulus@samba.org>2006-03-26 23:03:03 -0500
commita0652fc9a28c3ef8cd59264bfcb089c44d1b0e06 (patch)
treea28527b65237b3067553a993f5ad06dfb24df044 /arch/ppc/kernel
parent55aab8cd3a498201b769a19de861c77516bdfd45 (diff)
powerpc: Unify the 32 and 64 bit idle loops
This unifies the 32-bit (ARCH=ppc and ARCH=powerpc) and 64-bit idle loops. It brings over the concept of having a ppc_md.power_save function from 32-bit to ARCH=powerpc, which lets us get rid of native_idle(). With this we will also be able to simplify the idle handling for pSeries and cell. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile4
-rw-r--r--arch/ppc/kernel/entry.S8
-rw-r--r--arch/ppc/kernel/idle.c112
-rw-r--r--arch/ppc/kernel/idle_6xx.S233
-rw-r--r--arch/ppc/kernel/idle_power4.S91
5 files changed, 7 insertions, 441 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index e399bbb969a4..1b2c7458a3d0 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -8,10 +8,9 @@ extra-$(CONFIG_40x) := head_4xx.o
8extra-$(CONFIG_44x) := head_44x.o 8extra-$(CONFIG_44x) := head_44x.o
9extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o 9extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
10extra-$(CONFIG_8xx) := head_8xx.o 10extra-$(CONFIG_8xx) := head_8xx.o
11extra-$(CONFIG_6xx) += idle_6xx.o
12extra-y += vmlinux.lds 11extra-y += vmlinux.lds
13 12
14obj-y := entry.o traps.o idle.o time.o misc.o \ 13obj-y := entry.o traps.o time.o misc.o \
15 setup.o \ 14 setup.o \
16 ppc_htab.o 15 ppc_htab.o
17obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o 16obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
@@ -35,7 +34,6 @@ endif
35# These are here while we do the architecture merge 34# These are here while we do the architecture merge
36 35
37else 36else
38obj-y := idle.o
39obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o 37obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
40obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o 38obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
41obj-$(CONFIG_MODULES) += module.o 39obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 3a2815978488..fa8d49789ef1 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -135,10 +135,10 @@ transfer_to_handler:
135 mfspr r11,SPRN_HID0 135 mfspr r11,SPRN_HID0
136 mtcr r11 136 mtcr r11
137BEGIN_FTR_SECTION 137BEGIN_FTR_SECTION
138 bt- 8,power_save_6xx_restore /* Check DOZE */ 138 bt- 8,4f /* Check DOZE */
139END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE) 139END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
140BEGIN_FTR_SECTION 140BEGIN_FTR_SECTION
141 bt- 9,power_save_6xx_restore /* Check NAP */ 141 bt- 9,4f /* Check NAP */
142END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) 142END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
143#endif /* CONFIG_6xx */ 143#endif /* CONFIG_6xx */
144 .globl transfer_to_handler_cont 144 .globl transfer_to_handler_cont
@@ -157,6 +157,10 @@ transfer_to_handler_cont:
157 SYNC 157 SYNC
158 RFI /* jump to handler, enable MMU */ 158 RFI /* jump to handler, enable MMU */
159 159
160#ifdef CONFIG_6xx
1614: b power_save_6xx_restore
162#endif
163
160/* 164/*
161 * On kernel stack overflow, load up an initial stack pointer 165 * On kernel stack overflow, load up an initial stack pointer
162 * and call StackOverflow(regs), which should not return. 166 * and call StackOverflow(regs), which should not return.
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
deleted file mode 100644
index 1be3ca5bae40..000000000000
--- a/arch/ppc/kernel/idle.c
+++ /dev/null
@@ -1,112 +0,0 @@
1/*
2 * Idle daemon for PowerPC. Idle daemon will handle any action
3 * that needs to be taken when the system becomes idle.
4 *
5 * Written by Cort Dougan (cort@cs.nmt.edu). Subsequently hacked
6 * on by Tom Rini, Armin Kuster, Paul Mackerras and others.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <linux/config.h>
14#include <linux/errno.h>
15#include <linux/sched.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/smp.h>
19#include <linux/smp_lock.h>
20#include <linux/stddef.h>
21#include <linux/unistd.h>
22#include <linux/ptrace.h>
23#include <linux/slab.h>
24#include <linux/sysctl.h>
25#include <linux/cpu.h>
26
27#include <asm/pgtable.h>
28#include <asm/uaccess.h>
29#include <asm/system.h>
30#include <asm/io.h>
31#include <asm/mmu.h>
32#include <asm/cache.h>
33#include <asm/cputable.h>
34#include <asm/machdep.h>
35#include <asm/smp.h>
36
37void default_idle(void)
38{
39 void (*powersave)(void);
40
41 powersave = ppc_md.power_save;
42
43 if (!need_resched()) {
44 if (powersave != NULL)
45 powersave();
46#ifdef CONFIG_SMP
47 else {
48 set_thread_flag(TIF_POLLING_NRFLAG);
49 while (!need_resched() &&
50 !cpu_is_offline(smp_processor_id()))
51 barrier();
52 clear_thread_flag(TIF_POLLING_NRFLAG);
53 }
54#endif
55 }
56}
57
58/*
59 * The body of the idle task.
60 */
61void cpu_idle(void)
62{
63 int cpu = smp_processor_id();
64
65 for (;;) {
66 while (!need_resched()) {
67 if (ppc_md.idle != NULL)
68 ppc_md.idle();
69 else
70 default_idle();
71 }
72
73 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
74 cpu_die();
75 preempt_enable_no_resched();
76 schedule();
77 preempt_disable();
78 }
79}
80
81#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
82/*
83 * Register the sysctl to set/clear powersave_nap.
84 */
85extern int powersave_nap;
86
87static ctl_table powersave_nap_ctl_table[]={
88 {
89 .ctl_name = KERN_PPC_POWERSAVE_NAP,
90 .procname = "powersave-nap",
91 .data = &powersave_nap,
92 .maxlen = sizeof(int),
93 .mode = 0644,
94 .proc_handler = &proc_dointvec,
95 },
96 { 0, },
97};
98static ctl_table powersave_nap_sysctl_root[] = {
99 { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
100 { 0,},
101};
102
103static int __init
104register_powersave_nap_sysctl(void)
105{
106 register_sysctl_table(powersave_nap_sysctl_root, 0);
107
108 return 0;
109}
110
111__initcall(register_powersave_nap_sysctl);
112#endif
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
deleted file mode 100644
index 1a2194cf6828..000000000000
--- a/arch/ppc/kernel/idle_6xx.S
+++ /dev/null
@@ -1,233 +0,0 @@
1/*
2 * This file contains the power_save function for 6xx & 7xxx CPUs
3 * rewritten in assembler
4 *
5 * Warning ! This code assumes that if your machine has a 750fx
6 * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
7 * if this is not the case some additional changes will have to
8 * be done to check a runtime var (a bit like powersave-nap)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/config.h>
17#include <linux/threads.h>
18#include <asm/processor.h>
19#include <asm/page.h>
20#include <asm/cputable.h>
21#include <asm/thread_info.h>
22#include <asm/ppc_asm.h>
23#include <asm/asm-offsets.h>
24
25#undef DEBUG
26
27 .text
28
29/*
30 * Init idle, called at early CPU setup time from head.S for each CPU
31 * Make sure no rest of NAP mode remains in HID0, save default
32 * values for some CPU specific registers. Called with r24
33 * containing CPU number and r3 reloc offset
34 */
35_GLOBAL(init_idle_6xx)
36BEGIN_FTR_SECTION
37 mfspr r4,SPRN_HID0
38 rlwinm r4,r4,0,10,8 /* Clear NAP */
39 mtspr SPRN_HID0, r4
40 b 1f
41END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
42 blr
431:
44 slwi r5,r24,2
45 add r5,r5,r3
46BEGIN_FTR_SECTION
47 mfspr r4,SPRN_MSSCR0
48 addis r6,r5, nap_save_msscr0@ha
49 stw r4,nap_save_msscr0@l(r6)
50END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
51BEGIN_FTR_SECTION
52 mfspr r4,SPRN_HID1
53 addis r6,r5,nap_save_hid1@ha
54 stw r4,nap_save_hid1@l(r6)
55END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
56 blr
57
58/*
59 * Here is the power_save_6xx function. This could eventually be
60 * split into several functions & changing the function pointer
61 * depending on the various features.
62 */
63_GLOBAL(ppc6xx_idle)
64 /* Check if we can nap or doze, put HID0 mask in r3
65 */
66 lis r3, 0
67BEGIN_FTR_SECTION
68 lis r3,HID0_DOZE@h
69END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
70BEGIN_FTR_SECTION
71 /* We must dynamically check for the NAP feature as it
72 * can be cleared by CPU init after the fixups are done
73 */
74 lis r4,cur_cpu_spec@ha
75 lwz r4,cur_cpu_spec@l(r4)
76 lwz r4,CPU_SPEC_FEATURES(r4)
77 andi. r0,r4,CPU_FTR_CAN_NAP
78 beq 1f
79 /* Now check if user or arch enabled NAP mode */
80 lis r4,powersave_nap@ha
81 lwz r4,powersave_nap@l(r4)
82 cmpwi 0,r4,0
83 beq 1f
84 lis r3,HID0_NAP@h
851:
86END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
87 cmpwi 0,r3,0
88 beqlr
89
90 /* Clear MSR:EE */
91 mfmsr r7
92 rlwinm r0,r7,0,17,15
93 mtmsr r0
94
95 /* Check current_thread_info()->flags */
96 rlwinm r4,r1,0,0,18
97 lwz r4,TI_FLAGS(r4)
98 andi. r0,r4,_TIF_NEED_RESCHED
99 beq 1f
100 mtmsr r7 /* out of line this ? */
101 blr
1021:
103 /* Some pre-nap cleanups needed on some CPUs */
104 andis. r0,r3,HID0_NAP@h
105 beq 2f
106BEGIN_FTR_SECTION
107 /* Disable L2 prefetch on some 745x and try to ensure
108 * L2 prefetch engines are idle. As explained by errata
109 * text, we can't be sure they are, we just hope very hard
110 * that well be enough (sic !). At least I noticed Apple
111 * doesn't even bother doing the dcbf's here...
112 */
113 mfspr r4,SPRN_MSSCR0
114 rlwinm r4,r4,0,0,29
115 sync
116 mtspr SPRN_MSSCR0,r4
117 sync
118 isync
119 lis r4,KERNELBASE@h
120 dcbf 0,r4
121 dcbf 0,r4
122 dcbf 0,r4
123 dcbf 0,r4
124END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
125#ifdef DEBUG
126 lis r6,nap_enter_count@ha
127 lwz r4,nap_enter_count@l(r6)
128 addi r4,r4,1
129 stw r4,nap_enter_count@l(r6)
130#endif
1312:
132BEGIN_FTR_SECTION
133 /* Go to low speed mode on some 750FX */
134 lis r4,powersave_lowspeed@ha
135 lwz r4,powersave_lowspeed@l(r4)
136 cmpwi 0,r4,0
137 beq 1f
138 mfspr r4,SPRN_HID1
139 oris r4,r4,0x0001
140 mtspr SPRN_HID1,r4
1411:
142END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
143
144 /* Go to NAP or DOZE now */
145 mfspr r4,SPRN_HID0
146 lis r5,(HID0_NAP|HID0_SLEEP)@h
147BEGIN_FTR_SECTION
148 oris r5,r5,HID0_DOZE@h
149END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
150 andc r4,r4,r5
151 or r4,r4,r3
152BEGIN_FTR_SECTION
153 oris r4,r4,HID0_DPM@h /* that should be done once for all */
154END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
155 mtspr SPRN_HID0,r4
156BEGIN_FTR_SECTION
157 DSSALL
158 sync
159END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
160 ori r7,r7,MSR_EE /* Could be ommited (already set) */
161 oris r7,r7,MSR_POW@h
162 sync
163 isync
164 mtmsr r7
165 isync
166 sync
167 blr
168
169/*
170 * Return from NAP/DOZE mode, restore some CPU specific registers,
171 * we are called with DR/IR still off and r2 containing physical
172 * address of current.
173 */
174_GLOBAL(power_save_6xx_restore)
175 mfspr r11,SPRN_HID0
176 rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
177 cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
178BEGIN_FTR_SECTION
179 rlwinm r11,r11,0,9,7 /* Clear DOZE */
180END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
181 mtspr SPRN_HID0, r11
182
183#ifdef DEBUG
184 beq cr1,1f
185 lis r11,(nap_return_count-KERNELBASE)@ha
186 lwz r9,nap_return_count@l(r11)
187 addi r9,r9,1
188 stw r9,nap_return_count@l(r11)
1891:
190#endif
191
192 rlwinm r9,r1,0,0,18
193 tophys(r9,r9)
194 lwz r11,TI_CPU(r9)
195 slwi r11,r11,2
196 /* Todo make sure all these are in the same page
197 * and load r22 (@ha part + CPU offset) only once
198 */
199BEGIN_FTR_SECTION
200 beq cr1,1f
201 addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
202 lwz r9,nap_save_msscr0@l(r9)
203 mtspr SPRN_MSSCR0, r9
204 sync
205 isync
2061:
207END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
208BEGIN_FTR_SECTION
209 addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
210 lwz r9,nap_save_hid1@l(r9)
211 mtspr SPRN_HID1, r9
212END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
213 b transfer_to_handler_cont
214
215 .data
216
217_GLOBAL(nap_save_msscr0)
218 .space 4*NR_CPUS
219
220_GLOBAL(nap_save_hid1)
221 .space 4*NR_CPUS
222
223_GLOBAL(powersave_nap)
224 .long 0
225_GLOBAL(powersave_lowspeed)
226 .long 0
227
228#ifdef DEBUG
229_GLOBAL(nap_enter_count)
230 .space 4
231_GLOBAL(nap_return_count)
232 .space 4
233#endif
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
deleted file mode 100644
index cc0d535365cd..000000000000
--- a/arch/ppc/kernel/idle_power4.S
+++ /dev/null
@@ -1,91 +0,0 @@
1/*
2 * This file contains the power_save function for 6xx & 7xxx CPUs
3 * rewritten in assembler
4 *
5 * Warning ! This code assumes that if your machine has a 750fx
6 * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
7 * if this is not the case some additional changes will have to
8 * be done to check a runtime var (a bit like powersave-nap)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/config.h>
17#include <linux/threads.h>
18#include <asm/processor.h>
19#include <asm/page.h>
20#include <asm/cputable.h>
21#include <asm/thread_info.h>
22#include <asm/ppc_asm.h>
23#include <asm/asm-offsets.h>
24
25#undef DEBUG
26
27 .text
28
29/*
30 * Init idle, called at early CPU setup time from head.S for each CPU
31 * So nothing for now. Called with r24 containing CPU number and r3
32 * reloc offset
33 */
34 .globl init_idle_power4
35init_idle_power4:
36 blr
37
38/*
39 * Here is the power_save_6xx function. This could eventually be
40 * split into several functions & changing the function pointer
41 * depending on the various features.
42 */
43 .globl power4_idle
44power4_idle:
45BEGIN_FTR_SECTION
46 blr
47END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
48 /* We must dynamically check for the NAP feature as it
49 * can be cleared by CPU init after the fixups are done
50 */
51 lis r4,cur_cpu_spec@ha
52 lwz r4,cur_cpu_spec@l(r4)
53 lwz r4,CPU_SPEC_FEATURES(r4)
54 andi. r0,r4,CPU_FTR_CAN_NAP
55 beqlr
56 /* Now check if user or arch enabled NAP mode */
57 lis r4,powersave_nap@ha
58 lwz r4,powersave_nap@l(r4)
59 cmpwi 0,r4,0
60 beqlr
61
62 /* Clear MSR:EE */
63 mfmsr r7
64 rlwinm r0,r7,0,17,15
65 mtmsr r0
66
67 /* Check current_thread_info()->flags */
68 rlwinm r4,r1,0,0,18
69 lwz r4,TI_FLAGS(r4)
70 andi. r0,r4,_TIF_NEED_RESCHED
71 beq 1f
72 mtmsr r7 /* out of line this ? */
73 blr
741:
75 /* Go to NAP now */
76BEGIN_FTR_SECTION
77 DSSALL
78 sync
79END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
80 ori r7,r7,MSR_EE /* Could be ommited (already set) */
81 oris r7,r7,MSR_POW@h
82 sync
83 isync
84 mtmsr r7
85 isync
86 sync
87 blr
88
89 .globl powersave_nap
90powersave_nap:
91 .long 0