blob: 1f835539fda420d7f6d0005a7da502da7d42c473 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Idle daemon for PowerPC. Idle daemon will handle any action
4 * that needs to be taken when the system becomes idle.
5 *
Paul Mackerrasa0652fc2006-03-27 15:03:03 +11006 * Originally written by Cort Dougan (cort@cs.nmt.edu).
7 * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
8 * Paul Mackerras and others.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
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 *
Paul Mackerrasa0652fc2006-03-27 15:03:03 +110015 * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 */
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/smp.h>
21#include <linux/cpu.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/sysctl.h>
Tony Breeds1ad74992007-09-21 13:26:03 +100023#include <linux/tick.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <asm/processor.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/cputable.h>
27#include <asm/time.h>
Michael Ellermanfd899c02005-07-07 17:56:28 -070028#include <asm/machdep.h>
David Howellsae3a1972012-03-28 18:30:02 +010029#include <asm/runlatch.h>
Paul Mackerras2249ca92005-11-07 13:18:13 +110030#include <asm/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
Deepthi Dharwar771dae82011-11-30 02:46:31 +000033unsigned long cpuidle_disable = IDLE_NO_OVERRIDE;
34EXPORT_SYMBOL(cpuidle_disable);
35
arnd@arndb.de302eca12006-10-24 18:31:26 +020036static int __init powersave_off(char *arg)
37{
38 ppc_md.power_save = NULL;
Deepthi Dharwar771dae82011-11-30 02:46:31 +000039 cpuidle_disable = IDLE_POWERSAVE_OFF;
arnd@arndb.de302eca12006-10-24 18:31:26 +020040 return 0;
41}
42__setup("powersave=off", powersave_off);
43
Thomas Gleixner799fef02013-03-21 22:49:56 +010044void arch_cpu_idle(void)
45{
46 ppc64_runlatch_off();
Anton Blanchardddafddc2006-04-02 19:54:09 +100047
Thomas Gleixner799fef02013-03-21 22:49:56 +010048 if (ppc_md.power_save) {
49 ppc_md.power_save();
50 /*
51 * Some power_save functions return with
52 * interrupts enabled, some don't.
53 */
54 if (irqs_disabled())
Peter Zijlstra58c644b2020-11-20 11:50:35 +010055 raw_local_irq_enable();
Thomas Gleixner799fef02013-03-21 22:49:56 +010056 } else {
Peter Zijlstra58c644b2020-11-20 11:50:35 +010057 raw_local_irq_enable();
Thomas Gleixner799fef02013-03-21 22:49:56 +010058 /*
59 * Go into low thread priority and possibly
60 * low power mode.
61 */
62 HMT_low();
63 HMT_very_low();
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 }
Thomas Gleixner799fef02013-03-21 22:49:56 +010065
66 HMT_medium();
67 ppc64_runlatch_on();
Linus Torvalds1da177e2005-04-16 15:20:36 -070068}
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070int powersave_nap;
71
Nicholas Piggined0bc982019-07-11 12:24:03 +100072#ifdef CONFIG_PPC_970_NAP
73void power4_idle(void)
74{
75 if (!cpu_has_feature(CPU_FTR_CAN_NAP))
76 return;
77
78 if (!powersave_nap)
79 return;
80
81 if (!prep_irq_for_idle())
82 return;
83
84 if (cpu_has_feature(CPU_FTR_ALTIVEC))
85 asm volatile("DSSALL ; sync" ::: "memory");
86
87 power4_idle_nap();
88
89 /*
90 * power4_idle_nap returns with interrupts enabled (soft and hard).
91 * to our caller with interrupts enabled (soft and hard). Our caller
92 * can cope with either interrupts disabled or enabled upon return.
93 */
94}
95#endif
96
Linus Torvalds1da177e2005-04-16 15:20:36 -070097#ifdef CONFIG_SYSCTL
98/*
99 * Register the sysctl to set/clear powersave_nap.
100 */
Joe Perchescc293bf2013-06-13 19:37:30 -0700101static struct ctl_table powersave_nap_ctl_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 .procname = "powersave-nap",
104 .data = &powersave_nap,
105 .maxlen = sizeof(int),
106 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -0800107 .proc_handler = proc_dointvec,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 },
Eric W. Biedermanf5f10672007-02-14 00:33:46 -0800109 {}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110};
Joe Perchescc293bf2013-06-13 19:37:30 -0700111static struct ctl_table powersave_nap_sysctl_root[] = {
Eric W. Biedermanf5f10672007-02-14 00:33:46 -0800112 {
Eric W. Biedermanf5f10672007-02-14 00:33:46 -0800113 .procname = "kernel",
Alexey Dobriyanfb293ae2007-10-28 05:34:53 +1100114 .mode = 0555,
Eric W. Biedermanf5f10672007-02-14 00:33:46 -0800115 .child = powersave_nap_ctl_table,
116 },
117 {}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118};
119
120static int __init
121register_powersave_nap_sysctl(void)
122{
Eric W. Biederman0b4d4142007-02-14 00:34:09 -0800123 register_sysctl_table(powersave_nap_sysctl_root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
125 return 0;
126}
127__initcall(register_powersave_nap_sysctl);
128#endif