Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19b7ce8b authored by Hans-Christian Egtvedt's avatar Hans-Christian Egtvedt Committed by Haavard Skinnemoen
Browse files

[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: default avatarHans-Christian Egtvedt <hcegtvedt@atmel.com>
Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 7760989e
Loading
Loading
Loading
Loading
+37 −5
Original line number Diff line number Diff line
@@ -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
+3 −2
Original line number Diff line number Diff line
@@ -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();
+2 −0
Original line number Diff line number Diff line
@@ -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 */