mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
[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>
This commit is contained in:
parent
7760989e5e
commit
19b7ce8bad
@ -630,9 +630,12 @@ irq_level\level:
|
||||
rcall do_IRQ
|
||||
|
||||
lddsp r4, sp[REG_SR]
|
||||
andh r4, (MODE_MASK >> 16), COH
|
||||
bfextu r4, r4, SYSREG_M0_OFFSET, 3
|
||||
cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
|
||||
breq 2f
|
||||
cp.w r4, MODE_USER >> SYSREG_M0_OFFSET
|
||||
#ifdef CONFIG_PREEMPT
|
||||
brne 2f
|
||||
brne 3f
|
||||
#else
|
||||
brne 1f
|
||||
#endif
|
||||
@ -649,9 +652,18 @@ irq_level\level:
|
||||
sub sp, -4 /* ignore r12_orig */
|
||||
rete
|
||||
|
||||
2: get_thread_info r0
|
||||
ld.w r1, r0[TI_flags]
|
||||
bld r1, TIF_CPU_GOING_TO_SLEEP
|
||||
#ifdef CONFIG_PREEMPT
|
||||
2:
|
||||
get_thread_info r0
|
||||
brcc 3f
|
||||
#else
|
||||
brcc 1b
|
||||
#endif
|
||||
sub r1, pc, . - cpu_idle_skip_sleep
|
||||
stdsp sp[REG_PC], r1
|
||||
#ifdef CONFIG_PREEMPT
|
||||
3: get_thread_info r0
|
||||
ld.w r2, r0[TI_preempt_count]
|
||||
cp.w r2, 0
|
||||
brne 1b
|
||||
@ -662,12 +674,32 @@ irq_level\level:
|
||||
bld r4, SYSREG_GM_OFFSET
|
||||
brcs 1b
|
||||
rcall preempt_schedule_irq
|
||||
rjmp 1b
|
||||
#endif
|
||||
rjmp 1b
|
||||
.endm
|
||||
|
||||
.section .irq.text,"ax",@progbits
|
||||
|
||||
.global cpu_idle_sleep
|
||||
cpu_idle_sleep:
|
||||
mask_interrupts
|
||||
get_thread_info r8
|
||||
ld.w r9, r8[TI_flags]
|
||||
bld r9, TIF_NEED_RESCHED
|
||||
brcs cpu_idle_enable_int_and_exit
|
||||
sbr r9, TIF_CPU_GOING_TO_SLEEP
|
||||
st.w r8[TI_flags], r9
|
||||
unmask_interrupts
|
||||
sleep 0
|
||||
cpu_idle_skip_sleep:
|
||||
mask_interrupts
|
||||
ld.w r9, r8[TI_flags]
|
||||
cbr r9, TIF_CPU_GOING_TO_SLEEP
|
||||
st.w r8[TI_flags], r9
|
||||
cpu_idle_enable_int_and_exit:
|
||||
unmask_interrupts
|
||||
retal r12
|
||||
|
||||
.global irq_level0
|
||||
.global irq_level1
|
||||
.global irq_level2
|
||||
|
@ -19,6 +19,8 @@
|
||||
void (*pm_power_off)(void) = NULL;
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
extern void cpu_idle_sleep(void);
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of process handling..
|
||||
*/
|
||||
@ -27,9 +29,8 @@ void cpu_idle(void)
|
||||
{
|
||||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
/* TODO: Enter sleep mode */
|
||||
while (!need_resched())
|
||||
cpu_relax();
|
||||
cpu_idle_sleep();
|
||||
preempt_enable_no_resched();
|
||||
schedule();
|
||||
preempt_disable();
|
||||
|
@ -83,6 +83,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||
#define TIF_SINGLE_STEP 6 /* single step after next break */
|
||||
#define TIF_MEMDIE 7
|
||||
#define TIF_RESTORE_SIGMASK 8 /* restore signal mask in do_signal */
|
||||
#define TIF_CPU_GOING_TO_SLEEP 9 /* CPU is entering sleep 0 mode */
|
||||
#define TIF_USERSPACE 31 /* true if FS sets userspace */
|
||||
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
@ -94,6 +95,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||
#define _TIF_SINGLE_STEP (1 << TIF_SINGLE_STEP)
|
||||
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
|
||||
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
|
||||
#define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
|
||||
|
||||
/* XXX: These two masks must never span more than 16 bits! */
|
||||
/* work to do on interrupt/exception return */
|
||||
|
Loading…
Reference in New Issue
Block a user