blob: fd96af1d2ef0c1285a6042bfb8fdf4ed29de0e55 [file] [log] [blame]
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +05301/*
2 * cpuidle-powernv - idle state cpuidle driver.
3 * Adapted from drivers/cpuidle/cpuidle-pseries
4 *
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/moduleparam.h>
11#include <linux/cpuidle.h>
12#include <linux/cpu.h>
13#include <linux/notifier.h>
Preeti U Murthy0d948732014-02-26 05:39:06 +053014#include <linux/clockchips.h>
Preeti U Murthy08888392014-02-26 05:39:20 +053015#include <linux/of.h>
Preeti U Murthy92c83ff52015-02-18 06:34:17 +010016#include <linux/slab.h>
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053017
18#include <asm/machdep.h>
19#include <asm/firmware.h>
Shreyas B. Prabhu8eb8ac82014-12-10 00:26:51 +053020#include <asm/opal.h>
Nicolas Pitre591ac0c2014-02-17 10:59:29 -050021#include <asm/runlatch.h>
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053022
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +053023#define POWERNV_THRESHOLD_LATENCY_NS 200000
24
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053025struct cpuidle_driver powernv_idle_driver = {
26 .name = "powernv_idle",
27 .owner = THIS_MODULE,
28};
29
30static int max_idle_state;
31static struct cpuidle_state *cpuidle_state_table;
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +053032
33static u64 stop_psscr_table[CPUIDLE_STATE_MAX];
34
Gautham R. Shenoy443004a2018-05-31 17:45:09 +053035static u64 default_snooze_timeout;
Shilpasri G Bhat78eaa102015-06-18 16:53:11 +053036static bool snooze_timeout_en;
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053037
Gautham R. Shenoy443004a2018-05-31 17:45:09 +053038static u64 get_snooze_timeout(struct cpuidle_device *dev,
39 struct cpuidle_driver *drv,
40 int index)
41{
42 int i;
43
44 if (unlikely(!snooze_timeout_en))
45 return default_snooze_timeout;
46
47 for (i = index + 1; i < drv->state_count; i++) {
48 struct cpuidle_state *s = &drv->states[i];
49 struct cpuidle_state_usage *su = &dev->states_usage[i];
50
51 if (s->disabled || su->disable)
52 continue;
53
54 return s->target_residency * tb_ticks_per_usec;
55 }
56
57 return default_snooze_timeout;
58}
59
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053060static int snooze_loop(struct cpuidle_device *dev,
61 struct cpuidle_driver *drv,
62 int index)
63{
Shilpasri G Bhat78eaa102015-06-18 16:53:11 +053064 u64 snooze_exit_time;
65
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053066 local_irq_enable();
67 set_thread_flag(TIF_POLLING_NRFLAG);
68
Gautham R. Shenoy443004a2018-05-31 17:45:09 +053069 snooze_exit_time = get_tb() + get_snooze_timeout(dev, drv, index);
Nicolas Pitre591ac0c2014-02-17 10:59:29 -050070 ppc64_runlatch_off();
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053071 while (!need_resched()) {
72 HMT_low();
73 HMT_very_low();
Shilpasri G Bhat78eaa102015-06-18 16:53:11 +053074 if (snooze_timeout_en && get_tb() > snooze_exit_time)
75 break;
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053076 }
77
78 HMT_medium();
Nicolas Pitre591ac0c2014-02-17 10:59:29 -050079 ppc64_runlatch_on();
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053080 clear_thread_flag(TIF_POLLING_NRFLAG);
81 smp_mb();
82 return index;
83}
84
85static int nap_loop(struct cpuidle_device *dev,
86 struct cpuidle_driver *drv,
87 int index)
88{
Nicolas Pitre591ac0c2014-02-17 10:59:29 -050089 ppc64_runlatch_off();
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053090 power7_idle();
Nicolas Pitre591ac0c2014-02-17 10:59:29 -050091 ppc64_runlatch_on();
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +053092 return index;
93}
94
preeticc5a2f72015-06-24 01:48:01 -050095/* Register for fastsleep only in oneshot mode of broadcast */
96#ifdef CONFIG_TICK_ONESHOT
Preeti U Murthy0d948732014-02-26 05:39:06 +053097static int fastsleep_loop(struct cpuidle_device *dev,
98 struct cpuidle_driver *drv,
99 int index)
100{
101 unsigned long old_lpcr = mfspr(SPRN_LPCR);
102 unsigned long new_lpcr;
103
104 if (unlikely(system_state < SYSTEM_RUNNING))
105 return index;
106
107 new_lpcr = old_lpcr;
Michael Neuling9b6a68d2014-06-11 15:59:27 +1000108 /* Do not exit powersave upon decrementer as we've setup the timer
109 * offload.
Preeti U Murthy0d948732014-02-26 05:39:06 +0530110 */
Michael Neuling9b6a68d2014-06-11 15:59:27 +1000111 new_lpcr &= ~LPCR_PECE1;
Preeti U Murthy0d948732014-02-26 05:39:06 +0530112
113 mtspr(SPRN_LPCR, new_lpcr);
114 power7_sleep();
115
116 mtspr(SPRN_LPCR, old_lpcr);
117
118 return index;
119}
preeticc5a2f72015-06-24 01:48:01 -0500120#endif
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +0530121
122static int stop_loop(struct cpuidle_device *dev,
123 struct cpuidle_driver *drv,
124 int index)
125{
126 ppc64_runlatch_off();
127 power9_idle_stop(stop_psscr_table[index]);
128 ppc64_runlatch_on();
129 return index;
130}
131
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530132/*
133 * States for dedicated partition case.
134 */
Shreyas B. Prabhu169f3fa2016-07-08 11:50:50 +0530135static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] = {
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530136 { /* Snooze */
137 .name = "snooze",
138 .desc = "snooze",
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530139 .exit_latency = 0,
140 .target_residency = 0,
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530141 .enter = snooze_loop },
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530142};
143
Sebastian Andrzej Siewior10fcca92016-08-24 11:12:59 +0200144static int powernv_cpuidle_cpu_online(unsigned int cpu)
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530145{
Sebastian Andrzej Siewior10fcca92016-08-24 11:12:59 +0200146 struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530147
148 if (dev && cpuidle_get_driver()) {
Sebastian Andrzej Siewior10fcca92016-08-24 11:12:59 +0200149 cpuidle_pause_and_lock();
150 cpuidle_enable_device(dev);
151 cpuidle_resume_and_unlock();
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530152 }
Sebastian Andrzej Siewior10fcca92016-08-24 11:12:59 +0200153 return 0;
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530154}
155
Sebastian Andrzej Siewior10fcca92016-08-24 11:12:59 +0200156static int powernv_cpuidle_cpu_dead(unsigned int cpu)
157{
158 struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
159
160 if (dev && cpuidle_get_driver()) {
161 cpuidle_pause_and_lock();
162 cpuidle_disable_device(dev);
163 cpuidle_resume_and_unlock();
164 }
165 return 0;
166}
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530167
168/*
169 * powernv_cpuidle_driver_init()
170 */
171static int powernv_cpuidle_driver_init(void)
172{
173 int idle_state;
174 struct cpuidle_driver *drv = &powernv_idle_driver;
175
176 drv->state_count = 0;
177
178 for (idle_state = 0; idle_state < max_idle_state; ++idle_state) {
179 /* Is the state not enabled? */
180 if (cpuidle_state_table[idle_state].enter == NULL)
181 continue;
182
183 drv->states[drv->state_count] = /* structure copy */
184 cpuidle_state_table[idle_state];
185
186 drv->state_count += 1;
187 }
188
Vaidyanathan Srinivasan9e177132017-03-23 20:52:46 +0530189 /*
190 * On the PowerNV platform cpu_present may be less than cpu_possible in
191 * cases when firmware detects the CPU, but it is not available to the
192 * OS. If CONFIG_HOTPLUG_CPU=n, then such CPUs are not hotplugable at
193 * run time and hence cpu_devices are not created for those CPUs by the
194 * generic topology_init().
195 *
196 * drv->cpumask defaults to cpu_possible_mask in
197 * __cpuidle_driver_init(). This breaks cpuidle on PowerNV where
198 * cpu_devices are not created for CPUs in cpu_possible_mask that
199 * cannot be hot-added later at run time.
200 *
201 * Trying cpuidle_register_device() on a CPU without a cpu_device is
202 * incorrect, so pass a correct CPU mask to the generic cpuidle driver.
203 */
204
205 drv->cpumask = (struct cpumask *)cpu_present_mask;
206
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530207 return 0;
208}
209
Preeti U Murthy08888392014-02-26 05:39:20 +0530210static int powernv_add_idle_states(void)
211{
212 struct device_node *power_mgt;
Preeti U Murthy08888392014-02-26 05:39:20 +0530213 int nr_idle_states = 1; /* Snooze */
214 int dt_idle_states;
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530215 u32 latency_ns[CPUIDLE_STATE_MAX];
216 u32 residency_ns[CPUIDLE_STATE_MAX];
217 u32 flags[CPUIDLE_STATE_MAX];
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +0530218 u64 psscr_val[CPUIDLE_STATE_MAX];
219 const char *names[CPUIDLE_STATE_MAX];
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100220 int i, rc;
Preeti U Murthy08888392014-02-26 05:39:20 +0530221
222 /* Currently we have snooze statically defined */
223
224 power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
225 if (!power_mgt) {
226 pr_warn("opal: PowerMgmt Node not found\n");
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100227 goto out;
Preeti U Murthy08888392014-02-26 05:39:20 +0530228 }
229
Preeti U Murthy70734a72015-02-18 23:24:53 -0600230 /* Read values of any property to determine the num of idle states */
231 dt_idle_states = of_property_count_u32_elems(power_mgt, "ibm,cpu-idle-state-flags");
232 if (dt_idle_states < 0) {
233 pr_warn("cpuidle-powernv: no idle states found in the DT\n");
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100234 goto out;
Preeti U. Murthy74aa51b2014-10-14 13:23:00 +0530235 }
236
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530237 /*
238 * Since snooze is used as first idle state, max idle states allowed is
239 * CPUIDLE_STATE_MAX -1
240 */
241 if (dt_idle_states > CPUIDLE_STATE_MAX - 1) {
242 pr_warn("cpuidle-powernv: discovered idle states more than allowed");
243 dt_idle_states = CPUIDLE_STATE_MAX - 1;
244 }
245
Preeti U Murthy70734a72015-02-18 23:24:53 -0600246 if (of_property_read_u32_array(power_mgt,
247 "ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
248 pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n");
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530249 goto out;
Preeti U Murthy70734a72015-02-18 23:24:53 -0600250 }
Preeti U Murthy08888392014-02-26 05:39:20 +0530251
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530252 if (of_property_read_u32_array(power_mgt,
253 "ibm,cpu-idle-state-latencies-ns", latency_ns,
254 dt_idle_states)) {
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100255 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n");
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530256 goto out;
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100257 }
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +0530258 if (of_property_read_string_array(power_mgt,
259 "ibm,cpu-idle-state-names", names, dt_idle_states) < 0) {
260 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n");
261 goto out;
262 }
263
264 /*
265 * If the idle states use stop instruction, probe for psscr values
266 * which are necessary to specify required stop level.
267 */
268 if (flags[0] & (OPAL_PM_STOP_INST_FAST | OPAL_PM_STOP_INST_DEEP))
269 if (of_property_read_u64_array(power_mgt,
270 "ibm,cpu-idle-state-psscr", psscr_val, dt_idle_states)) {
271 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-states-psscr in DT\n");
272 goto out;
273 }
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100274
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100275 rc = of_property_read_u32_array(power_mgt,
276 "ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);
277
Preeti U Murthy08888392014-02-26 05:39:20 +0530278 for (i = 0; i < dt_idle_states; i++) {
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +0530279 /*
280 * If an idle state has exit latency beyond
281 * POWERNV_THRESHOLD_LATENCY_NS then don't use it
282 * in cpu-idle.
283 */
284 if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS)
285 continue;
Preeti U Murthy08888392014-02-26 05:39:20 +0530286
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100287 /*
288 * Cpuidle accepts exit_latency and target_residency in us.
289 * Use default target_residency values if f/w does not expose it.
Preeti U. Murthy74aa51b2014-10-14 13:23:00 +0530290 */
Preeti U Murthy70734a72015-02-18 23:24:53 -0600291 if (flags[i] & OPAL_PM_NAP_ENABLED) {
Preeti U Murthy08888392014-02-26 05:39:20 +0530292 /* Add NAP state */
293 strcpy(powernv_states[nr_idle_states].name, "Nap");
294 strcpy(powernv_states[nr_idle_states].desc, "Nap");
Daniel Lezcanob82b6cc2014-11-12 16:03:50 +0100295 powernv_states[nr_idle_states].flags = 0;
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100296 powernv_states[nr_idle_states].target_residency = 100;
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530297 powernv_states[nr_idle_states].enter = nap_loop;
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +0530298 } else if ((flags[i] & OPAL_PM_STOP_INST_FAST) &&
299 !(flags[i] & OPAL_PM_TIMEBASE_STOP)) {
300 strncpy(powernv_states[nr_idle_states].name,
301 names[i], CPUIDLE_NAME_LEN);
302 strncpy(powernv_states[nr_idle_states].desc,
303 names[i], CPUIDLE_NAME_LEN);
304 powernv_states[nr_idle_states].flags = 0;
305
306 powernv_states[nr_idle_states].enter = stop_loop;
307 stop_psscr_table[nr_idle_states] = psscr_val[i];
preeticc5a2f72015-06-24 01:48:01 -0500308 }
309
310 /*
311 * All cpuidle states with CPUIDLE_FLAG_TIMER_STOP set must come
312 * within this config dependency check.
313 */
314#ifdef CONFIG_TICK_ONESHOT
315 if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
Preeti U Murthy70734a72015-02-18 23:24:53 -0600316 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
Preeti U Murthy08888392014-02-26 05:39:20 +0530317 /* Add FASTSLEEP state */
318 strcpy(powernv_states[nr_idle_states].name, "FastSleep");
319 strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
Daniel Lezcanob82b6cc2014-11-12 16:03:50 +0100320 powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100321 powernv_states[nr_idle_states].target_residency = 300000;
Shreyas B. Prabhu957efce2016-07-08 11:50:51 +0530322 powernv_states[nr_idle_states].enter = fastsleep_loop;
Shreyas B. Prabhu3005c592016-07-08 11:50:52 +0530323 } else if ((flags[i] & OPAL_PM_STOP_INST_DEEP) &&
324 (flags[i] & OPAL_PM_TIMEBASE_STOP)) {
325 strncpy(powernv_states[nr_idle_states].name,
326 names[i], CPUIDLE_NAME_LEN);
327 strncpy(powernv_states[nr_idle_states].desc,
328 names[i], CPUIDLE_NAME_LEN);
329
330 powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
331 powernv_states[nr_idle_states].enter = stop_loop;
332 stop_psscr_table[nr_idle_states] = psscr_val[i];
Preeti U Murthy08888392014-02-26 05:39:20 +0530333 }
preeticc5a2f72015-06-24 01:48:01 -0500334#endif
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100335 powernv_states[nr_idle_states].exit_latency =
336 ((unsigned int)latency_ns[i]) / 1000;
337
338 if (!rc) {
339 powernv_states[nr_idle_states].target_residency =
340 ((unsigned int)residency_ns[i]) / 1000;
341 }
342
343 nr_idle_states++;
Preeti U Murthy08888392014-02-26 05:39:20 +0530344 }
Preeti U Murthy92c83ff52015-02-18 06:34:17 +0100345out:
Preeti U Murthy08888392014-02-26 05:39:20 +0530346 return nr_idle_states;
347}
348
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530349/*
350 * powernv_idle_probe()
351 * Choose state table for shared versus dedicated partition
352 */
353static int powernv_idle_probe(void)
354{
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530355 if (cpuidle_disable != IDLE_NO_OVERRIDE)
356 return -ENODEV;
357
Stewart Smithe4d54f72015-12-09 17:18:20 +1100358 if (firmware_has_feature(FW_FEATURE_OPAL)) {
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530359 cpuidle_state_table = powernv_states;
Preeti U Murthy08888392014-02-26 05:39:20 +0530360 /* Device tree can indicate more idle states */
361 max_idle_state = powernv_add_idle_states();
Gautham R. Shenoy443004a2018-05-31 17:45:09 +0530362 default_snooze_timeout = TICK_USEC * tb_ticks_per_usec;
363 if (max_idle_state > 1)
Shilpasri G Bhat78eaa102015-06-18 16:53:11 +0530364 snooze_timeout_en = true;
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530365 } else
366 return -ENODEV;
367
368 return 0;
369}
370
371static int __init powernv_processor_idle_init(void)
372{
373 int retval;
374
375 retval = powernv_idle_probe();
376 if (retval)
377 return retval;
378
379 powernv_cpuidle_driver_init();
380 retval = cpuidle_register(&powernv_idle_driver, NULL);
381 if (retval) {
382 printk(KERN_DEBUG "Registration of powernv driver failed.\n");
383 return retval;
384 }
385
Sebastian Andrzej Siewior10fcca92016-08-24 11:12:59 +0200386 retval = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
387 "cpuidle/powernv:online",
388 powernv_cpuidle_cpu_online, NULL);
389 WARN_ON(retval < 0);
390 retval = cpuhp_setup_state_nocalls(CPUHP_CPUIDLE_DEAD,
391 "cpuidle/powernv:dead", NULL,
392 powernv_cpuidle_cpu_dead);
393 WARN_ON(retval < 0);
Deepthi Dharwar2c2e6ec2014-01-14 16:32:40 +0530394 printk(KERN_DEBUG "powernv_idle_driver registered\n");
395 return 0;
396}
397
398device_initcall(powernv_processor_idle_init);