Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Idle daemon for PowerPC.  Idle daemon will handle any action
0004  * that needs to be taken when the system becomes idle.
0005  *
0006  * Originally written by Cort Dougan (cort@cs.nmt.edu).
0007  * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
0008  * Paul Mackerras and others.
0009  *
0010  * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
0011  *
0012  * Additional shared processor, SMT, and firmware support
0013  *    Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
0014  *
0015  * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
0016  */
0017 
0018 #include <linux/sched.h>
0019 #include <linux/kernel.h>
0020 #include <linux/smp.h>
0021 #include <linux/cpu.h>
0022 #include <linux/sysctl.h>
0023 #include <linux/tick.h>
0024 
0025 #include <asm/processor.h>
0026 #include <asm/cputable.h>
0027 #include <asm/time.h>
0028 #include <asm/machdep.h>
0029 #include <asm/runlatch.h>
0030 #include <asm/smp.h>
0031 
0032 
0033 unsigned long cpuidle_disable = IDLE_NO_OVERRIDE;
0034 EXPORT_SYMBOL(cpuidle_disable);
0035 
0036 static int __init powersave_off(char *arg)
0037 {
0038     ppc_md.power_save = NULL;
0039     cpuidle_disable = IDLE_POWERSAVE_OFF;
0040     return 1;
0041 }
0042 __setup("powersave=off", powersave_off);
0043 
0044 void arch_cpu_idle(void)
0045 {
0046     ppc64_runlatch_off();
0047 
0048     if (ppc_md.power_save) {
0049         ppc_md.power_save();
0050         /*
0051          * Some power_save functions return with
0052          * interrupts enabled, some don't.
0053          */
0054         if (irqs_disabled())
0055             raw_local_irq_enable();
0056     } else {
0057         raw_local_irq_enable();
0058         /*
0059          * Go into low thread priority and possibly
0060          * low power mode.
0061          */
0062         HMT_low();
0063         HMT_very_low();
0064     }
0065 
0066     HMT_medium();
0067     ppc64_runlatch_on();
0068 }
0069 
0070 int powersave_nap;
0071 
0072 #ifdef CONFIG_PPC_970_NAP
0073 void power4_idle(void)
0074 {
0075     if (!cpu_has_feature(CPU_FTR_CAN_NAP))
0076         return;
0077 
0078     if (!powersave_nap)
0079         return;
0080 
0081     if (!prep_irq_for_idle())
0082         return;
0083 
0084     if (cpu_has_feature(CPU_FTR_ALTIVEC))
0085         asm volatile(PPC_DSSALL " ; sync" ::: "memory");
0086 
0087     power4_idle_nap();
0088 
0089     /*
0090      * power4_idle_nap returns with interrupts enabled (soft and hard).
0091      * to our caller with interrupts enabled (soft and hard). Our caller
0092      * can cope with either interrupts disabled or enabled upon return.
0093      */
0094 }
0095 #endif
0096 
0097 #ifdef CONFIG_SYSCTL
0098 /*
0099  * Register the sysctl to set/clear powersave_nap.
0100  */
0101 static struct ctl_table powersave_nap_ctl_table[] = {
0102     {
0103         .procname   = "powersave-nap",
0104         .data       = &powersave_nap,
0105         .maxlen     = sizeof(int),
0106         .mode       = 0644,
0107         .proc_handler   = proc_dointvec,
0108     },
0109     {}
0110 };
0111 static struct ctl_table powersave_nap_sysctl_root[] = {
0112     {
0113         .procname   = "kernel",
0114         .mode       = 0555,
0115         .child      = powersave_nap_ctl_table,
0116     },
0117     {}
0118 };
0119 
0120 static int __init
0121 register_powersave_nap_sysctl(void)
0122 {
0123     register_sysctl_table(powersave_nap_sysctl_root);
0124 
0125     return 0;
0126 }
0127 __initcall(register_powersave_nap_sysctl);
0128 #endif