diff options
Diffstat (limited to 'arch/sh/kernel/idle.c')
| -rw-r--r-- | arch/sh/kernel/idle.c | 81 | 
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c new file mode 100644 index 000000000000..fe59ccfc1152 --- /dev/null +++ b/arch/sh/kernel/idle.c @@ -0,0 +1,81 @@ +/* + * The idle loop for all SuperH platforms. + * + *  Copyright (C) 2002 - 2008  Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/pm.h> +#include <linux/tick.h> +#include <linux/preempt.h> +#include <linux/thread_info.h> +#include <linux/irqflags.h> +#include <asm/pgalloc.h> +#include <asm/system.h> +#include <asm/atomic.h> + +static int hlt_counter; +void (*pm_idle)(void); +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + +static int __init nohlt_setup(char *__unused) +{ +	hlt_counter = 1; +	return 1; +} +__setup("nohlt", nohlt_setup); + +static int __init hlt_setup(char *__unused) +{ +	hlt_counter = 0; +	return 1; +} +__setup("hlt", hlt_setup); + +static void default_idle(void) +{ +	if (!hlt_counter) { +		clear_thread_flag(TIF_POLLING_NRFLAG); +		smp_mb__after_clear_bit(); +		set_bl_bit(); +		stop_critical_timings(); + +		while (!need_resched()) +			cpu_sleep(); + +		start_critical_timings(); +		clear_bl_bit(); +		set_thread_flag(TIF_POLLING_NRFLAG); +	} else +		while (!need_resched()) +			cpu_relax(); +} + +void cpu_idle(void) +{ +	set_thread_flag(TIF_POLLING_NRFLAG); + +	/* endless idle loop with no priority at all */ +	while (1) { +		void (*idle)(void) = pm_idle; + +		if (!idle) +			idle = default_idle; + +		tick_nohz_stop_sched_tick(1); +		while (!need_resched()) +			idle(); +		tick_nohz_restart_sched_tick(); + +		preempt_enable_no_resched(); +		schedule(); +		preempt_disable(); +		check_pgt_cache(); +	} +}  | 
