linux/arch/powerpc/kernel/idle.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Idle daemon for PowerPC.  Idle daemon will handle any action
   4 * that needs to be taken when the system becomes idle.
   5 *
   6 * Originally written by Cort Dougan (cort@cs.nmt.edu).
   7 * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
   8 * Paul Mackerras and others.
   9 *
  10 * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
  11 *
  12 * Additional shared processor, SMT, and firmware support
  13 *    Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
  14 *
  15 * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
  16 */
  17
  18#include <linux/sched.h>
  19#include <linux/kernel.h>
  20#include <linux/smp.h>
  21#include <linux/cpu.h>
  22#include <linux/sysctl.h>
  23#include <linux/tick.h>
  24
  25#include <asm/processor.h>
  26#include <asm/cputable.h>
  27#include <asm/time.h>
  28#include <asm/machdep.h>
  29#include <asm/runlatch.h>
  30#include <asm/smp.h>
  31
  32
  33unsigned long cpuidle_disable = IDLE_NO_OVERRIDE;
  34EXPORT_SYMBOL(cpuidle_disable);
  35
  36static int __init powersave_off(char *arg)
  37{
  38        ppc_md.power_save = NULL;
  39        cpuidle_disable = IDLE_POWERSAVE_OFF;
  40        return 0;
  41}
  42__setup("powersave=off", powersave_off);
  43
  44#ifdef CONFIG_HOTPLUG_CPU
  45void arch_cpu_idle_dead(void)
  46{
  47        sched_preempt_enable_no_resched();
  48        cpu_die();
  49}
  50#endif
  51
  52void arch_cpu_idle(void)
  53{
  54        ppc64_runlatch_off();
  55
  56        if (ppc_md.power_save) {
  57                ppc_md.power_save();
  58                /*
  59                 * Some power_save functions return with
  60                 * interrupts enabled, some don't.
  61                 */
  62                if (irqs_disabled())
  63                        local_irq_enable();
  64        } else {
  65                local_irq_enable();
  66                /*
  67                 * Go into low thread priority and possibly
  68                 * low power mode.
  69                 */
  70                HMT_low();
  71                HMT_very_low();
  72        }
  73
  74        HMT_medium();
  75        ppc64_runlatch_on();
  76}
  77
  78int powersave_nap;
  79
  80#ifdef CONFIG_PPC_970_NAP
  81void power4_idle(void)
  82{
  83        if (!cpu_has_feature(CPU_FTR_CAN_NAP))
  84                return;
  85
  86        if (!powersave_nap)
  87                return;
  88
  89        if (!prep_irq_for_idle())
  90                return;
  91
  92        if (cpu_has_feature(CPU_FTR_ALTIVEC))
  93                asm volatile("DSSALL ; sync" ::: "memory");
  94
  95        power4_idle_nap();
  96
  97        /*
  98         * power4_idle_nap returns with interrupts enabled (soft and hard).
  99         * to our caller with interrupts enabled (soft and hard). Our caller
 100         * can cope with either interrupts disabled or enabled upon return.
 101         */
 102}
 103#endif
 104
 105#ifdef CONFIG_SYSCTL
 106/*
 107 * Register the sysctl to set/clear powersave_nap.
 108 */
 109static struct ctl_table powersave_nap_ctl_table[] = {
 110        {
 111                .procname       = "powersave-nap",
 112                .data           = &powersave_nap,
 113                .maxlen         = sizeof(int),
 114                .mode           = 0644,
 115                .proc_handler   = proc_dointvec,
 116        },
 117        {}
 118};
 119static struct ctl_table powersave_nap_sysctl_root[] = {
 120        {
 121                .procname       = "kernel",
 122                .mode           = 0555,
 123                .child          = powersave_nap_ctl_table,
 124        },
 125        {}
 126};
 127
 128static int __init
 129register_powersave_nap_sysctl(void)
 130{
 131        register_sysctl_table(powersave_nap_sysctl_root);
 132
 133        return 0;
 134}
 135__initcall(register_powersave_nap_sysctl);
 136#endif
 137