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