diff options
author | Hans-Christian Egtvedt <hcegtvedt@atmel.com> | 2007-02-26 07:50:43 -0500 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-04-27 07:44:12 -0400 |
commit | 19b7ce8bad718a2850ea19aeb7383f1728596c24 (patch) | |
tree | 1fef17c37eaf90231a497b92dd49565e56986b6c | |
parent | 7760989e5e2900e484e9115e6e690c6ce0b0221c (diff) |
[AVR32] Put cpu in sleep 0 when idle.
This patch puts the CPU in sleep 0 when doing nothing, idle. This will
turn of the CPU clock and thus save power. The CPU is waken again when
an interrupt occurs.
Signed-off-by: Hans-Christian Egtvedt <hcegtvedt@atmel.com>
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
-rw-r--r-- | arch/avr32/kernel/entry-avr32b.S | 42 | ||||
-rw-r--r-- | arch/avr32/kernel/process.c | 5 | ||||
-rw-r--r-- | include/asm-avr32/thread_info.h | 2 |
3 files changed, 42 insertions, 7 deletions
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index eeb66792bc37..5f5f7e42f51b 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S | |||
@@ -630,9 +630,12 @@ irq_level\level: | |||
630 | rcall do_IRQ | 630 | rcall do_IRQ |
631 | 631 | ||
632 | lddsp r4, sp[REG_SR] | 632 | lddsp r4, sp[REG_SR] |
633 | andh r4, (MODE_MASK >> 16), COH | 633 | bfextu r4, r4, SYSREG_M0_OFFSET, 3 |
634 | cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET | ||
635 | breq 2f | ||
636 | cp.w r4, MODE_USER >> SYSREG_M0_OFFSET | ||
634 | #ifdef CONFIG_PREEMPT | 637 | #ifdef CONFIG_PREEMPT |
635 | brne 2f | 638 | brne 3f |
636 | #else | 639 | #else |
637 | brne 1f | 640 | brne 1f |
638 | #endif | 641 | #endif |
@@ -649,9 +652,18 @@ irq_level\level: | |||
649 | sub sp, -4 /* ignore r12_orig */ | 652 | sub sp, -4 /* ignore r12_orig */ |
650 | rete | 653 | rete |
651 | 654 | ||
655 | 2: get_thread_info r0 | ||
656 | ld.w r1, r0[TI_flags] | ||
657 | bld r1, TIF_CPU_GOING_TO_SLEEP | ||
652 | #ifdef CONFIG_PREEMPT | 658 | #ifdef CONFIG_PREEMPT |
653 | 2: | 659 | brcc 3f |
654 | get_thread_info r0 | 660 | #else |
661 | brcc 1b | ||
662 | #endif | ||
663 | sub r1, pc, . - cpu_idle_skip_sleep | ||
664 | stdsp sp[REG_PC], r1 | ||
665 | #ifdef CONFIG_PREEMPT | ||
666 | 3: get_thread_info r0 | ||
655 | ld.w r2, r0[TI_preempt_count] | 667 | ld.w r2, r0[TI_preempt_count] |
656 | cp.w r2, 0 | 668 | cp.w r2, 0 |
657 | brne 1b | 669 | brne 1b |
@@ -662,12 +674,32 @@ irq_level\level: | |||
662 | bld r4, SYSREG_GM_OFFSET | 674 | bld r4, SYSREG_GM_OFFSET |
663 | brcs 1b | 675 | brcs 1b |
664 | rcall preempt_schedule_irq | 676 | rcall preempt_schedule_irq |
665 | rjmp 1b | ||
666 | #endif | 677 | #endif |
678 | rjmp 1b | ||
667 | .endm | 679 | .endm |
668 | 680 | ||
669 | .section .irq.text,"ax",@progbits | 681 | .section .irq.text,"ax",@progbits |
670 | 682 | ||
683 | .global cpu_idle_sleep | ||
684 | cpu_idle_sleep: | ||
685 | mask_interrupts | ||
686 | get_thread_info r8 | ||
687 | ld.w r9, r8[TI_flags] | ||
688 | bld r9, TIF_NEED_RESCHED | ||
689 | brcs cpu_idle_enable_int_and_exit | ||
690 | sbr r9, TIF_CPU_GOING_TO_SLEEP | ||
691 | st.w r8[TI_flags], r9 | ||
692 | unmask_interrupts | ||
693 | sleep 0 | ||
694 | cpu_idle_skip_sleep: | ||
695 | mask_interrupts | ||
696 | ld.w r9, r8[TI_flags] | ||
697 | cbr r9, TIF_CPU_GOING_TO_SLEEP | ||
698 | st.w r8[TI_flags], r9 | ||
699 | cpu_idle_enable_int_and_exit: | ||
700 | unmask_interrupts | ||
701 | retal r12 | ||
702 | |||
671 | .global irq_level0 | 703 | .global irq_level0 |
672 | .global irq_level1 | 704 | .global irq_level1 |
673 | .global irq_level2 | 705 | .global irq_level2 |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 0b4325946a41..4f8d2d474740 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -19,6 +19,8 @@ | |||
19 | void (*pm_power_off)(void) = NULL; | 19 | void (*pm_power_off)(void) = NULL; |
20 | EXPORT_SYMBOL(pm_power_off); | 20 | EXPORT_SYMBOL(pm_power_off); |
21 | 21 | ||
22 | extern void cpu_idle_sleep(void); | ||
23 | |||
22 | /* | 24 | /* |
23 | * This file handles the architecture-dependent parts of process handling.. | 25 | * This file handles the architecture-dependent parts of process handling.. |
24 | */ | 26 | */ |
@@ -27,9 +29,8 @@ void cpu_idle(void) | |||
27 | { | 29 | { |
28 | /* endless idle loop with no priority at all */ | 30 | /* endless idle loop with no priority at all */ |
29 | while (1) { | 31 | while (1) { |
30 | /* TODO: Enter sleep mode */ | ||
31 | while (!need_resched()) | 32 | while (!need_resched()) |
32 | cpu_relax(); | 33 | cpu_idle_sleep(); |
33 | preempt_enable_no_resched(); | 34 | preempt_enable_no_resched(); |
34 | schedule(); | 35 | schedule(); |
35 | preempt_disable(); | 36 | preempt_disable(); |
diff --git a/include/asm-avr32/thread_info.h b/include/asm-avr32/thread_info.h index d1f5b35ebd54..a2e606dd4f4a 100644 --- a/include/asm-avr32/thread_info.h +++ b/include/asm-avr32/thread_info.h | |||
@@ -83,6 +83,7 @@ static inline struct thread_info *current_thread_info(void) | |||
83 | #define TIF_SINGLE_STEP 6 /* single step after next break */ | 83 | #define TIF_SINGLE_STEP 6 /* single step after next break */ |
84 | #define TIF_MEMDIE 7 | 84 | #define TIF_MEMDIE 7 |
85 | #define TIF_RESTORE_SIGMASK 8 /* restore signal mask in do_signal */ | 85 | #define TIF_RESTORE_SIGMASK 8 /* restore signal mask in do_signal */ |
86 | #define TIF_CPU_GOING_TO_SLEEP 9 /* CPU is entering sleep 0 mode */ | ||
86 | #define TIF_USERSPACE 31 /* true if FS sets userspace */ | 87 | #define TIF_USERSPACE 31 /* true if FS sets userspace */ |
87 | 88 | ||
88 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 89 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
@@ -94,6 +95,7 @@ static inline struct thread_info *current_thread_info(void) | |||
94 | #define _TIF_SINGLE_STEP (1 << TIF_SINGLE_STEP) | 95 | #define _TIF_SINGLE_STEP (1 << TIF_SINGLE_STEP) |
95 | #define _TIF_MEMDIE (1 << TIF_MEMDIE) | 96 | #define _TIF_MEMDIE (1 << TIF_MEMDIE) |
96 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) | 97 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) |
98 | #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP) | ||
97 | 99 | ||
98 | /* XXX: These two masks must never span more than 16 bits! */ | 100 | /* XXX: These two masks must never span more than 16 bits! */ |
99 | /* work to do on interrupt/exception return */ | 101 | /* work to do on interrupt/exception return */ |