aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/Makefile6
-rw-r--r--arch/powerpc/kernel/entry_32.S8
-rw-r--r--arch/powerpc/kernel/idle.c (renamed from arch/powerpc/kernel/idle_64.c)79
-rw-r--r--arch/powerpc/kernel/idle_6xx.S15
-rw-r--r--arch/powerpc/kernel/idle_power4.S15
-rw-r--r--arch/powerpc/kernel/setup_32.c7
-rw-r--r--arch/powerpc/kernel/setup_64.c6
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c2
-rw-r--r--arch/ppc/Makefile2
-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
-rw-r--r--include/asm-powerpc/machdep.h13
-rw-r--r--include/asm-powerpc/reg.h4
-rw-r--r--include/asm-ppc/machdep.h2
18 files changed, 74 insertions, 535 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 80e9fe2632b8..f2c47e907037 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,12 +12,12 @@ endif
12 12
13obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ 13obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
14 irq.o align.o signal_32.o pmc.o vdso.o \ 14 irq.o align.o signal_32.o pmc.o vdso.o \
15 init_task.o process.o systbl.o 15 init_task.o process.o systbl.o idle.o
16obj-y += vdso32/ 16obj-y += vdso32/
17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 17obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
18 signal_64.o ptrace32.o \ 18 signal_64.o ptrace32.o \
19 paca.o cpu_setup_power4.o \ 19 paca.o cpu_setup_power4.o \
20 firmware.o sysfs.o idle_64.o 20 firmware.o sysfs.o
21obj-$(CONFIG_PPC64) += vdso64/ 21obj-$(CONFIG_PPC64) += vdso64/
22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 22obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
23obj-$(CONFIG_POWER4) += idle_power4.o 23obj-$(CONFIG_POWER4) += idle_power4.o
@@ -34,6 +34,7 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o
34obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 34obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
35obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o 35obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
36obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 36obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
37obj-$(CONFIG_6xx) += idle_6xx.o
37 38
38ifeq ($(CONFIG_PPC_MERGE),y) 39ifeq ($(CONFIG_PPC_MERGE),y)
39 40
@@ -51,7 +52,6 @@ obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
51obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o 52obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
52obj-$(CONFIG_MODULES) += ppc_ksyms.o 53obj-$(CONFIG_MODULES) += ppc_ksyms.o
53obj-$(CONFIG_BOOTX_TEXT) += btext.o 54obj-$(CONFIG_BOOTX_TEXT) += btext.o
54obj-$(CONFIG_6xx) += idle_6xx.o
55obj-$(CONFIG_SMP) += smp.o 55obj-$(CONFIG_SMP) += smp.o
56obj-$(CONFIG_KPROBES) += kprobes.o 56obj-$(CONFIG_KPROBES) += kprobes.o
57obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o 57obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 4827ca1ec89b..b3a979467225 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.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/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle.c
index b879d3057ef8..e9f321d74d85 100644
--- a/arch/powerpc/kernel/idle_64.c
+++ b/arch/powerpc/kernel/idle.c
@@ -2,13 +2,17 @@
2 * Idle daemon for PowerPC. Idle daemon will handle any action 2 * Idle daemon for PowerPC. Idle daemon will handle any action
3 * that needs to be taken when the system becomes idle. 3 * that needs to be taken when the system becomes idle.
4 * 4 *
5 * Originally Written by Cort Dougan (cort@cs.nmt.edu) 5 * Originally written by Cort Dougan (cort@cs.nmt.edu).
6 * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
7 * Paul Mackerras and others.
6 * 8 *
7 * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com> 9 * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
8 * 10 *
9 * Additional shared processor, SMT, and firmware support 11 * Additional shared processor, SMT, and firmware support
10 * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com> 12 * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
11 * 13 *
14 * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
15 *
12 * This program is free software; you can redistribute it and/or 16 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 17 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 18 * as published by the Free Software Foundation; either version
@@ -29,18 +33,43 @@
29#include <asm/machdep.h> 33#include <asm/machdep.h>
30#include <asm/smp.h> 34#include <asm/smp.h>
31 35
32extern void power4_idle(void); 36#ifdef CONFIG_HOTPLUG_CPU
37#define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \
38 system_state == SYSTEM_RUNNING)
39#else
40#define cpu_should_die() 0
41#endif
33 42
34void default_idle(void) 43/*
44 * The body of the idle task.
45 */
46void cpu_idle(void)
35{ 47{
36 unsigned int cpu = smp_processor_id(); 48 if (ppc_md.idle_loop)
37 set_thread_flag(TIF_POLLING_NRFLAG); 49 ppc_md.idle_loop(); /* doesn't return */
38 50
51 set_thread_flag(TIF_POLLING_NRFLAG);
39 while (1) { 52 while (1) {
40 if (!need_resched()) { 53 ppc64_runlatch_off();
41 while (!need_resched() && !cpu_is_offline(cpu)) {
42 ppc64_runlatch_off();
43 54
55 while (!need_resched() && !cpu_should_die()) {
56 if (ppc_md.power_save) {
57 clear_thread_flag(TIF_POLLING_NRFLAG);
58 /*
59 * smp_mb is so clearing of TIF_POLLING_NRFLAG
60 * is ordered w.r.t. need_resched() test.
61 */
62 smp_mb();
63 local_irq_disable();
64
65 /* check again after disabling irqs */
66 if (!need_resched() && !cpu_should_die())
67 ppc_md.power_save();
68
69 local_irq_enable();
70 set_thread_flag(TIF_POLLING_NRFLAG);
71
72 } else {
44 /* 73 /*
45 * Go into low thread priority and possibly 74 * Go into low thread priority and possibly
46 * low power mode. 75 * low power mode.
@@ -48,46 +77,18 @@ void default_idle(void)
48 HMT_low(); 77 HMT_low();
49 HMT_very_low(); 78 HMT_very_low();
50 } 79 }
51
52 HMT_medium();
53 } 80 }
54 81
82 HMT_medium();
55 ppc64_runlatch_on(); 83 ppc64_runlatch_on();
84 if (cpu_should_die())
85 cpu_die();
56 preempt_enable_no_resched(); 86 preempt_enable_no_resched();
57 schedule(); 87 schedule();
58 preempt_disable(); 88 preempt_disable();
59 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
60 cpu_die();
61 } 89 }
62} 90}
63 91
64void native_idle(void)
65{
66 while (1) {
67 ppc64_runlatch_off();
68
69 if (!need_resched())
70 power4_idle();
71
72 if (need_resched()) {
73 ppc64_runlatch_on();
74 preempt_enable_no_resched();
75 schedule();
76 preempt_disable();
77 }
78
79 if (cpu_is_offline(smp_processor_id()) &&
80 system_state == SYSTEM_RUNNING)
81 cpu_die();
82 }
83}
84
85void cpu_idle(void)
86{
87 BUG_ON(NULL == ppc_md.idle_loop);
88 ppc_md.idle_loop();
89}
90
91int powersave_nap; 92int powersave_nap;
92 93
93#ifdef CONFIG_SYSCTL 94#ifdef CONFIG_SYSCTL
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 444fdcc769f1..1647ea361ef7 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -87,19 +87,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
87 cmpwi 0,r3,0 87 cmpwi 0,r3,0
88 beqlr 88 beqlr
89 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 */ 90 /* Some pre-nap cleanups needed on some CPUs */
104 andis. r0,r3,HID0_NAP@h 91 andis. r0,r3,HID0_NAP@h
105 beq 2f 92 beq 2f
@@ -220,8 +207,6 @@ _GLOBAL(nap_save_msscr0)
220_GLOBAL(nap_save_hid1) 207_GLOBAL(nap_save_hid1)
221 .space 4*NR_CPUS 208 .space 4*NR_CPUS
222 209
223_GLOBAL(powersave_nap)
224 .long 0
225_GLOBAL(powersave_lowspeed) 210_GLOBAL(powersave_lowspeed)
226 .long 0 211 .long 0
227 212
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index c16b4afab582..692cf2ebe0f4 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -49,21 +49,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
49 cmpwi 0,r4,0 49 cmpwi 0,r4,0
50 beqlr 50 beqlr
51 51
52 /* Clear MSR:EE */
53 mfmsr r7
54 li r4,0
55 ori r4,r4,MSR_EE
56 andc r0,r7,r4
57 mtmsrd r0
58
59 /* Check current_thread_info()->flags */
60 clrrdi r4,r1,THREAD_SHIFT
61 ld r4,TI_FLAGS(r4)
62 andi. r0,r4,_TIF_NEED_RESCHED
63 beq 1f
64 mtmsrd r7 /* out of line this ? */
65 blr
661:
67 /* Go to NAP now */ 52 /* Go to NAP now */
68BEGIN_FTR_SECTION 53BEGIN_FTR_SECTION
69 DSSALL 54 DSSALL
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 676f894c3380..e39f830317a8 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -53,9 +53,6 @@
53extern void platform_init(void); 53extern void platform_init(void);
54extern void bootx_init(unsigned long r4, unsigned long phys); 54extern void bootx_init(unsigned long r4, unsigned long phys);
55 55
56extern void ppc6xx_idle(void);
57extern void power4_idle(void);
58
59boot_infos_t *boot_infos; 56boot_infos_t *boot_infos;
60struct ide_machdep_calls ppc_ide_md; 57struct ide_machdep_calls ppc_ide_md;
61 58
@@ -194,7 +191,9 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
194 platform_init(); 191 platform_init();
195 192
196#ifdef CONFIG_6xx 193#ifdef CONFIG_6xx
197 ppc_md.power_save = ppc6xx_idle; 194 if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
195 cpu_has_feature(CPU_FTR_CAN_NAP))
196 ppc_md.power_save = ppc6xx_idle;
198#endif 197#endif
199 198
200 if (ppc_md.progress) 199 if (ppc_md.progress)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6c9b093c23a5..5b63a861ef43 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -607,12 +607,6 @@ void __init setup_arch(char **cmdline_p)
607 607
608 ppc_md.setup_arch(); 608 ppc_md.setup_arch();
609 609
610 /* Use the default idle loop if the platform hasn't provided one. */
611 if (NULL == ppc_md.idle_loop) {
612 ppc_md.idle_loop = default_idle;
613 printk(KERN_INFO "Using default idle loop\n");
614 }
615
616 paging_init(); 610 paging_init();
617 ppc64_boot_msg(0x15, "Setup Done"); 611 ppc64_boot_msg(0x15, "Setup Done");
618} 612}
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index ec5c1e10c407..137d6063182b 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -290,7 +290,7 @@ struct machdep_calls __initdata maple_md = {
290 .get_rtc_time = maple_get_rtc_time, 290 .get_rtc_time = maple_get_rtc_time,
291 .calibrate_decr = generic_calibrate_decr, 291 .calibrate_decr = generic_calibrate_decr,
292 .progress = maple_progress, 292 .progress = maple_progress,
293 .idle_loop = native_idle, 293 .power_save = power4_idle,
294#ifdef CONFIG_KEXEC 294#ifdef CONFIG_KEXEC
295 .machine_kexec = default_machine_kexec, 295 .machine_kexec = default_machine_kexec,
296 .machine_kexec_prepare = default_machine_kexec_prepare, 296 .machine_kexec_prepare = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 385aab90c4d2..c2696d00672a 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -733,7 +733,7 @@ struct machdep_calls __initdata pmac_md = {
733 .progress = udbg_progress, 733 .progress = udbg_progress,
734#ifdef CONFIG_PPC64 734#ifdef CONFIG_PPC64
735 .pci_probe_mode = pmac_pci_probe_mode, 735 .pci_probe_mode = pmac_pci_probe_mode,
736 .idle_loop = native_idle, 736 .power_save = power4_idle,
737 .enable_pmcs = power4_enable_pmcs, 737 .enable_pmcs = power4_enable_pmcs,
738#ifdef CONFIG_KEXEC 738#ifdef CONFIG_KEXEC
739 .machine_kexec = default_machine_kexec, 739 .machine_kexec = default_machine_kexec,
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 9fbdf54ba2be..cde5fa87f455 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -59,8 +59,6 @@ head-$(CONFIG_4xx) := arch/ppc/kernel/head_4xx.o
59head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o 59head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o
60head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o 60head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o
61 61
62head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o
63head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o
64head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o 62head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o
65 63
66core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \ 64core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \
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
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5348b820788c..21c8dc90d175 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -158,6 +158,12 @@ struct machdep_calls {
158 /* Idle loop for this platform, leave empty for default idle loop */ 158 /* Idle loop for this platform, leave empty for default idle loop */
159 void (*idle_loop)(void); 159 void (*idle_loop)(void);
160 160
161 /*
162 * Function for waiting for work with reduced power in idle loop;
163 * called with interrupts disabled.
164 */
165 void (*power_save)(void);
166
161 /* Function to enable performance monitor counters for this 167 /* Function to enable performance monitor counters for this
162 platform, called once per cpu. */ 168 platform, called once per cpu. */
163 void (*enable_pmcs)(void); 169 void (*enable_pmcs)(void);
@@ -170,9 +176,6 @@ struct machdep_calls {
170 May be NULL. */ 176 May be NULL. */
171 void (*init)(void); 177 void (*init)(void);
172 178
173 void (*idle)(void);
174 void (*power_save)(void);
175
176 void (*heartbeat)(void); 179 void (*heartbeat)(void);
177 unsigned long heartbeat_reset; 180 unsigned long heartbeat_reset;
178 unsigned long heartbeat_count; 181 unsigned long heartbeat_count;
@@ -242,8 +245,8 @@ struct machdep_calls {
242#endif /* CONFIG_KEXEC */ 245#endif /* CONFIG_KEXEC */
243}; 246};
244 247
245extern void default_idle(void); 248extern void power4_idle(void);
246extern void native_idle(void); 249extern void ppc6xx_idle(void);
247 250
248extern struct machdep_calls ppc_md; 251extern struct machdep_calls ppc_md;
249extern char cmd_line[COMMAND_LINE_SIZE]; 252extern char cmd_line[COMMAND_LINE_SIZE];
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 72bfe3af0460..bd467bf5cf5a 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -622,6 +622,10 @@ extern void ppc64_runlatch_off(void);
622extern unsigned long scom970_read(unsigned int address); 622extern unsigned long scom970_read(unsigned int address);
623extern void scom970_write(unsigned int address, unsigned long value); 623extern void scom970_write(unsigned int address, unsigned long value);
624 624
625#else
626#define ppc64_runlatch_on()
627#define ppc64_runlatch_off()
628
625#endif /* CONFIG_PPC64 */ 629#endif /* CONFIG_PPC64 */
626 630
627#define __get_SP() ({unsigned long sp; \ 631#define __get_SP() ({unsigned long sp; \
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index a3e8a45e45a9..ebbef64e8985 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -44,7 +44,7 @@ struct machdep_calls {
44 void (*power_off)(void); 44 void (*power_off)(void);
45 void (*halt)(void); 45 void (*halt)(void);
46 46
47 void (*idle)(void); 47 void (*idle_loop)(void);
48 void (*power_save)(void); 48 void (*power_save)(void);
49 49
50 long (*time_init)(void); /* Optional, may be NULL */ 50 long (*time_init)(void); /* Optional, may be NULL */