diff options
-rw-r--r-- | arch/avr32/kernel/entry-avr32b.S | 20 | ||||
-rw-r--r-- | arch/avr32/kernel/process.c | 4 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/Makefile | 2 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/pm-at32ap700x.S | 66 | ||||
-rw-r--r-- | include/asm-avr32/arch-at32ap/pm.h | 48 |
5 files changed, 117 insertions, 23 deletions
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 8cf16d7a7040..5f31702d6b1c 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S | |||
@@ -741,26 +741,6 @@ irq_level\level: | |||
741 | 741 | ||
742 | .section .irq.text,"ax",@progbits | 742 | .section .irq.text,"ax",@progbits |
743 | 743 | ||
744 | .global cpu_idle_sleep | ||
745 | cpu_idle_sleep: | ||
746 | mask_interrupts | ||
747 | get_thread_info r8 | ||
748 | ld.w r9, r8[TI_flags] | ||
749 | bld r9, TIF_NEED_RESCHED | ||
750 | brcs cpu_idle_enable_int_and_exit | ||
751 | sbr r9, TIF_CPU_GOING_TO_SLEEP | ||
752 | st.w r8[TI_flags], r9 | ||
753 | unmask_interrupts | ||
754 | sleep 0 | ||
755 | cpu_idle_skip_sleep: | ||
756 | mask_interrupts | ||
757 | ld.w r9, r8[TI_flags] | ||
758 | cbr r9, TIF_CPU_GOING_TO_SLEEP | ||
759 | st.w r8[TI_flags], r9 | ||
760 | cpu_idle_enable_int_and_exit: | ||
761 | unmask_interrupts | ||
762 | retal r12 | ||
763 | |||
764 | .global irq_level0 | 744 | .global irq_level0 |
765 | .global irq_level1 | 745 | .global irq_level1 |
766 | .global irq_level2 | 746 | .global irq_level2 |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 7f4af0b1e111..3de115462d7b 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -18,11 +18,11 @@ | |||
18 | #include <asm/sysreg.h> | 18 | #include <asm/sysreg.h> |
19 | #include <asm/ocd.h> | 19 | #include <asm/ocd.h> |
20 | 20 | ||
21 | #include <asm/arch/pm.h> | ||
22 | |||
21 | void (*pm_power_off)(void) = NULL; | 23 | void (*pm_power_off)(void) = NULL; |
22 | EXPORT_SYMBOL(pm_power_off); | 24 | EXPORT_SYMBOL(pm_power_off); |
23 | 25 | ||
24 | extern void cpu_idle_sleep(void); | ||
25 | |||
26 | /* | 26 | /* |
27 | * This file handles the architecture-dependent parts of process handling.. | 27 | * This file handles the architecture-dependent parts of process handling.. |
28 | */ | 28 | */ |
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index 5e9f8217befc..83cab2abb6c3 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o | 1 | obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o |
2 | obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o | 2 | obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o |
3 | obj-$(CONFIG_CPU_AT32AP700X) += time-tc.o | 3 | obj-$(CONFIG_CPU_AT32AP700X) += time-tc.o |
4 | obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o | 4 | obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o |
diff --git a/arch/avr32/mach-at32ap/pm-at32ap700x.S b/arch/avr32/mach-at32ap/pm-at32ap700x.S new file mode 100644 index 000000000000..949e2485e278 --- /dev/null +++ b/arch/avr32/mach-at32ap/pm-at32ap700x.S | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Low-level Power Management code. | ||
3 | * | ||
4 | * Copyright (C) 2008 Atmel Corporation | ||
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 | #include <asm/asm.h> | ||
11 | #include <asm/asm-offsets.h> | ||
12 | #include <asm/thread_info.h> | ||
13 | #include <asm/arch/pm.h> | ||
14 | |||
15 | .section .bss, "wa", @nobits | ||
16 | .global disable_idle_sleep | ||
17 | .type disable_idle_sleep, @object | ||
18 | disable_idle_sleep: | ||
19 | .int 4 | ||
20 | .size disable_idle_sleep, . - disable_idle_sleep | ||
21 | |||
22 | /* Keep this close to the irq handlers */ | ||
23 | .section .irq.text, "ax", @progbits | ||
24 | |||
25 | /* | ||
26 | * void cpu_enter_idle(void) | ||
27 | * | ||
28 | * Put the CPU into "idle" mode, in which it will consume | ||
29 | * significantly less power. | ||
30 | * | ||
31 | * If an interrupt comes along in the window between | ||
32 | * unmask_interrupts and the sleep instruction below, the | ||
33 | * interrupt code will adjust the return address so that we | ||
34 | * never execute the sleep instruction. This is required | ||
35 | * because the AP7000 doesn't unmask interrupts when entering | ||
36 | * sleep modes; later CPUs may not need this workaround. | ||
37 | */ | ||
38 | .global cpu_enter_idle | ||
39 | .type cpu_enter_idle, @function | ||
40 | cpu_enter_idle: | ||
41 | mask_interrupts | ||
42 | get_thread_info r8 | ||
43 | ld.w r9, r8[TI_flags] | ||
44 | bld r9, TIF_NEED_RESCHED | ||
45 | brcs .Lret_from_sleep | ||
46 | sbr r9, TIF_CPU_GOING_TO_SLEEP | ||
47 | st.w r8[TI_flags], r9 | ||
48 | unmask_interrupts | ||
49 | sleep CPU_SLEEP_IDLE | ||
50 | .size cpu_idle_sleep, . - cpu_idle_sleep | ||
51 | |||
52 | /* | ||
53 | * Common return path for PM functions that don't run from | ||
54 | * SRAM. | ||
55 | */ | ||
56 | .global cpu_idle_skip_sleep | ||
57 | .type cpu_idle_skip_sleep, @function | ||
58 | cpu_idle_skip_sleep: | ||
59 | mask_interrupts | ||
60 | ld.w r9, r8[TI_flags] | ||
61 | cbr r9, TIF_CPU_GOING_TO_SLEEP | ||
62 | st.w r8[TI_flags], r9 | ||
63 | .Lret_from_sleep: | ||
64 | unmask_interrupts | ||
65 | retal r12 | ||
66 | .size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep | ||
diff --git a/include/asm-avr32/arch-at32ap/pm.h b/include/asm-avr32/arch-at32ap/pm.h new file mode 100644 index 000000000000..356e43064903 --- /dev/null +++ b/include/asm-avr32/arch-at32ap/pm.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * AVR32 AP Power Management. | ||
3 | * | ||
4 | * Copyright (C) 2008 Atmel Corporation | ||
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 | #ifndef __ASM_AVR32_ARCH_PM_H | ||
11 | #define __ASM_AVR32_ARCH_PM_H | ||
12 | |||
13 | /* Possible arguments to the "sleep" instruction */ | ||
14 | #define CPU_SLEEP_IDLE 0 | ||
15 | #define CPU_SLEEP_FROZEN 1 | ||
16 | #define CPU_SLEEP_STANDBY 2 | ||
17 | #define CPU_SLEEP_STOP 3 | ||
18 | #define CPU_SLEEP_STATIC 5 | ||
19 | |||
20 | #ifndef __ASSEMBLY__ | ||
21 | extern void cpu_enter_idle(void); | ||
22 | |||
23 | extern bool disable_idle_sleep; | ||
24 | |||
25 | static inline void cpu_disable_idle_sleep(void) | ||
26 | { | ||
27 | disable_idle_sleep = true; | ||
28 | } | ||
29 | |||
30 | static inline void cpu_enable_idle_sleep(void) | ||
31 | { | ||
32 | disable_idle_sleep = false; | ||
33 | } | ||
34 | |||
35 | static inline void cpu_idle_sleep(void) | ||
36 | { | ||
37 | /* | ||
38 | * If we're using the COUNT and COMPARE registers for | ||
39 | * timekeeping, we can't use the IDLE state. | ||
40 | */ | ||
41 | if (disable_idle_sleep) | ||
42 | cpu_relax(); | ||
43 | else | ||
44 | cpu_enter_idle(); | ||
45 | } | ||
46 | #endif | ||
47 | |||
48 | #endif /* __ASM_AVR32_ARCH_PM_H */ | ||