diff options
author | Olof Johansson <olof@lixom.net> | 2007-02-04 17:36:51 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-06 22:03:22 -0500 |
commit | 1199919b69ff9559a3d3444fb5eb45b7cc48264d (patch) | |
tree | 40313402be457e274e777b385703b25fa359f9b2 | |
parent | bfed9d32d968b2054a036d419537e9e9909bb343 (diff) |
[POWERPC] pasemi: Idle loops
Powersave support on PA6T. Right now it only uses 'doze' mode, and
will default to no savings (spin).
Signed-off-by: Olof Johansson <olof@lixom.net>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/cpu_setup_pa6t.S | 44 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/Makefile | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/idle.c | 88 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/pasemi.h | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/powersave.S | 80 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/setup.c | 2 | ||||
-rw-r--r-- | include/asm-powerpc/reg.h | 1 |
9 files changed, 228 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index d2ded19e4064..8120d428ebfd 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -17,6 +17,7 @@ obj-y += vdso32/ | |||
17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 17 | obj-$(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_ppc970.o \ | 19 | paca.o cpu_setup_ppc970.o \ |
20 | cpu_setup_pa6t.o \ | ||
20 | firmware.o sysfs.o nvram_64.o | 21 | firmware.o sysfs.o nvram_64.o |
21 | obj-$(CONFIG_PPC64) += vdso64/ | 22 | obj-$(CONFIG_PPC64) += vdso64/ |
22 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o | 23 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o |
diff --git a/arch/powerpc/kernel/cpu_setup_pa6t.S b/arch/powerpc/kernel/cpu_setup_pa6t.S new file mode 100644 index 000000000000..4047be25c4d2 --- /dev/null +++ b/arch/powerpc/kernel/cpu_setup_pa6t.S | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2007 PA Semi, Inc | ||
3 | * | ||
4 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <asm/processor.h> | ||
22 | #include <asm/page.h> | ||
23 | #include <asm/cputable.h> | ||
24 | #include <asm/ppc_asm.h> | ||
25 | #include <asm/asm-offsets.h> | ||
26 | #include <asm/cache.h> | ||
27 | |||
28 | /* Right now, restore and setup are the same thing */ | ||
29 | _GLOBAL(__restore_cpu_pa6t) | ||
30 | _GLOBAL(__setup_cpu_pa6t) | ||
31 | /* Do nothing if not running in HV mode */ | ||
32 | mfmsr r0 | ||
33 | rldicl. r0,r0,4,63 | ||
34 | beqlr | ||
35 | |||
36 | mfspr r0,SPRN_HID5 | ||
37 | ori r0,r0,0x30 | ||
38 | mtspr SPRN_HID5,r0 | ||
39 | |||
40 | mfspr r0,SPRN_LPCR | ||
41 | ori r0,r0,0x7000 | ||
42 | mtspr SPRN_LPCR,r0 | ||
43 | |||
44 | blr | ||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 4939b3d56dfb..dd17dffbf058 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -43,6 +43,8 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec); | |||
43 | #ifdef CONFIG_PPC64 | 43 | #ifdef CONFIG_PPC64 |
44 | extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | 44 | extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); |
45 | extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec); | 45 | extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec); |
46 | extern void __setup_cpu_pa6t(unsigned long offset, struct cpu_spec* spec); | ||
47 | extern void __restore_cpu_pa6t(unsigned long offset, struct cpu_spec* spec); | ||
46 | extern void __restore_cpu_ppc970(void); | 48 | extern void __restore_cpu_ppc970(void); |
47 | #endif /* CONFIG_PPC64 */ | 49 | #endif /* CONFIG_PPC64 */ |
48 | 50 | ||
@@ -369,6 +371,8 @@ static struct cpu_spec cpu_specs[] = { | |||
369 | .dcache_bsize = 64, | 371 | .dcache_bsize = 64, |
370 | .num_pmcs = 6, | 372 | .num_pmcs = 6, |
371 | .pmc_type = PPC_PMC_PA6T, | 373 | .pmc_type = PPC_PMC_PA6T, |
374 | .cpu_setup = __setup_cpu_pa6t, | ||
375 | .cpu_restore = __restore_cpu_pa6t, | ||
372 | .platform = "pa6t", | 376 | .platform = "pa6t", |
373 | }, | 377 | }, |
374 | { /* default match */ | 378 | { /* default match */ |
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index 1be1a993c5f5..fe4da46074bb 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-y += setup.o pci.o time.o | 1 | obj-y += setup.o pci.o time.o idle.o powersave.o |
2 | |||
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c new file mode 100644 index 000000000000..1ca3ff381591 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/idle.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2007 PA Semi, Inc | ||
3 | * | ||
4 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #undef DEBUG | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/string.h> | ||
25 | |||
26 | #include <asm/machdep.h> | ||
27 | #include <asm/reg.h> | ||
28 | |||
29 | #include "pasemi.h" | ||
30 | |||
31 | struct sleep_mode { | ||
32 | char *name; | ||
33 | void (*entry)(void); | ||
34 | }; | ||
35 | |||
36 | static struct sleep_mode modes[] = { | ||
37 | { .name = "spin", .entry = &idle_spin }, | ||
38 | { .name = "doze", .entry = &idle_doze }, | ||
39 | }; | ||
40 | |||
41 | static int current_mode = 0; | ||
42 | |||
43 | static int pasemi_system_reset_exception(struct pt_regs *regs) | ||
44 | { | ||
45 | /* If we were woken up from power savings, we need to return | ||
46 | * to the calling function, since nip is not saved across | ||
47 | * all modes. | ||
48 | */ | ||
49 | |||
50 | if (regs->msr & SRR1_WAKEMASK) | ||
51 | regs->nip = regs->link; | ||
52 | |||
53 | switch (regs->msr & SRR1_WAKEMASK) { | ||
54 | case SRR1_WAKEEE: | ||
55 | do_IRQ(regs); | ||
56 | break; | ||
57 | case SRR1_WAKEDEC: | ||
58 | timer_interrupt(regs); | ||
59 | break; | ||
60 | default: | ||
61 | /* do system reset */ | ||
62 | return 0; | ||
63 | } | ||
64 | /* everything handled */ | ||
65 | regs->msr |= MSR_RI; | ||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | void __init pasemi_idle_init(void) | ||
70 | { | ||
71 | ppc_md.system_reset_exception = pasemi_system_reset_exception; | ||
72 | ppc_md.power_save = modes[current_mode].entry; | ||
73 | printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); | ||
74 | } | ||
75 | |||
76 | static int __init idle_param(char *p) | ||
77 | { | ||
78 | int i; | ||
79 | for (i = 0; i < sizeof(modes)/sizeof(struct sleep_mode); i++) { | ||
80 | if (!strcmp(modes[i].name, p)) { | ||
81 | current_mode = i; | ||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | early_param("idle", idle_param); | ||
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index 51c2a2397ecf..94fd00cc6a10 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h | |||
@@ -4,4 +4,11 @@ | |||
4 | extern unsigned long pas_get_boot_time(void); | 4 | extern unsigned long pas_get_boot_time(void); |
5 | extern void pas_pci_init(void); | 5 | extern void pas_pci_init(void); |
6 | 6 | ||
7 | extern void __init pasemi_idle_init(void); | ||
8 | |||
9 | /* Power savings modes, implemented in asm */ | ||
10 | extern void idle_spin(void); | ||
11 | extern void idle_doze(void); | ||
12 | |||
13 | |||
7 | #endif /* _PASEMI_PASEMI_H */ | 14 | #endif /* _PASEMI_PASEMI_H */ |
diff --git a/arch/powerpc/platforms/pasemi/powersave.S b/arch/powerpc/platforms/pasemi/powersave.S new file mode 100644 index 000000000000..6d0fba6aab17 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/powersave.S | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2007 PA Semi, Inc | ||
3 | * | ||
4 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <asm/processor.h> | ||
22 | #include <asm/page.h> | ||
23 | #include <asm/ppc_asm.h> | ||
24 | #include <asm/cputable.h> | ||
25 | #include <asm/cache.h> | ||
26 | #include <asm/thread_info.h> | ||
27 | #include <asm/asm-offsets.h> | ||
28 | |||
29 | /* Power savings opcodes since not all binutils have them at this time */ | ||
30 | #define DOZE .long 0x4c000324 | ||
31 | #define NAP .long 0x4c000364 | ||
32 | #define SLEEP .long 0x4c0003a4 | ||
33 | #define RVW .long 0x4c0003e4 | ||
34 | |||
35 | /* Common sequence to do before going to any of the | ||
36 | * powersavings modes. | ||
37 | */ | ||
38 | |||
39 | #define PRE_SLEEP_SEQUENCE \ | ||
40 | std r3,8(r1); \ | ||
41 | ptesync ; \ | ||
42 | ld r3,8(r1); \ | ||
43 | 1: cmpd r3,r3; \ | ||
44 | bne 1b | ||
45 | |||
46 | _doze: | ||
47 | PRE_SLEEP_SEQUENCE | ||
48 | DOZE | ||
49 | b . | ||
50 | |||
51 | |||
52 | _GLOBAL(idle_spin) | ||
53 | blr | ||
54 | |||
55 | _GLOBAL(idle_doze) | ||
56 | LOAD_REG_ADDR(r3, _doze) | ||
57 | b sleep_common | ||
58 | |||
59 | /* Add more modes here later */ | ||
60 | |||
61 | sleep_common: | ||
62 | mflr r0 | ||
63 | std r0, 16(r1) | ||
64 | stdu r1,-64(r1) | ||
65 | |||
66 | LOAD_REG_IMMEDIATE(r6,MSR_DR|MSR_IR|MSR_ME|MSR_EE) | ||
67 | mfmsr r4 | ||
68 | andc r5,r4,r6 | ||
69 | mtmsrd r5,0 | ||
70 | |||
71 | mtctr r3 | ||
72 | bctrl | ||
73 | |||
74 | mtmsrd r4,0 | ||
75 | |||
76 | addi r1,r1,64 | ||
77 | ld r0,16(r1) | ||
78 | mtlr r0 | ||
79 | blr | ||
80 | |||
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 4142873a87ef..f69f5e76618f 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -82,7 +82,7 @@ void __init pas_setup_arch(void) | |||
82 | conswitchp = &dummy_con; | 82 | conswitchp = &dummy_con; |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | printk(KERN_DEBUG "Using default idle loop\n"); | 85 | pasemi_idle_init(); |
86 | } | 86 | } |
87 | 87 | ||
88 | /* No legacy IO on our parts */ | 88 | /* No legacy IO on our parts */ |
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 0279d4ec5211..923df6ceaa5c 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h | |||
@@ -166,6 +166,7 @@ | |||
166 | #define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */ | 166 | #define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */ |
167 | #define SPRN_SPURR 0x134 /* Scaled PURR */ | 167 | #define SPRN_SPURR 0x134 /* Scaled PURR */ |
168 | #define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */ | 168 | #define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */ |
169 | #define SPRN_LPCR 0x13E /* LPAR Control Register */ | ||
169 | #define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */ | 170 | #define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */ |
170 | #define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */ | 171 | #define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */ |
171 | #define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */ | 172 | #define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */ |