xref: /linux/arch/powerpc/platforms/powernv/idle.c (revision 09206b600c76f20984e80d99f3b5343c79332a97)
1d405a98cSShreyas B. Prabhu /*
2d405a98cSShreyas B. Prabhu  * PowerNV cpuidle code
3d405a98cSShreyas B. Prabhu  *
4d405a98cSShreyas B. Prabhu  * Copyright 2015 IBM Corp.
5d405a98cSShreyas B. Prabhu  *
6d405a98cSShreyas B. Prabhu  * This program is free software; you can redistribute it and/or
7d405a98cSShreyas B. Prabhu  * modify it under the terms of the GNU General Public License
8d405a98cSShreyas B. Prabhu  * as published by the Free Software Foundation; either version
9d405a98cSShreyas B. Prabhu  * 2 of the License, or (at your option) any later version.
10d405a98cSShreyas B. Prabhu  */
11d405a98cSShreyas B. Prabhu 
12d405a98cSShreyas B. Prabhu #include <linux/types.h>
13d405a98cSShreyas B. Prabhu #include <linux/mm.h>
14d405a98cSShreyas B. Prabhu #include <linux/slab.h>
15d405a98cSShreyas B. Prabhu #include <linux/of.h>
165703d2f4SShreyas B. Prabhu #include <linux/device.h>
175703d2f4SShreyas B. Prabhu #include <linux/cpu.h>
18d405a98cSShreyas B. Prabhu 
19d405a98cSShreyas B. Prabhu #include <asm/firmware.h>
204bece972SMichael Ellerman #include <asm/machdep.h>
21d405a98cSShreyas B. Prabhu #include <asm/opal.h>
22d405a98cSShreyas B. Prabhu #include <asm/cputhreads.h>
23d405a98cSShreyas B. Prabhu #include <asm/cpuidle.h>
24d405a98cSShreyas B. Prabhu #include <asm/code-patching.h>
25d405a98cSShreyas B. Prabhu #include <asm/smp.h>
26d405a98cSShreyas B. Prabhu 
27d405a98cSShreyas B. Prabhu #include "powernv.h"
28d405a98cSShreyas B. Prabhu #include "subcore.h"
29d405a98cSShreyas B. Prabhu 
30bcef83a0SShreyas B. Prabhu /* Power ISA 3.0 allows for stop states 0x0 - 0xF */
31bcef83a0SShreyas B. Prabhu #define MAX_STOP_STATE	0xF
32bcef83a0SShreyas B. Prabhu 
33d405a98cSShreyas B. Prabhu static u32 supported_cpuidle_states;
34d405a98cSShreyas B. Prabhu 
35bcef83a0SShreyas B. Prabhu static int pnv_save_sprs_for_deep_states(void)
36d405a98cSShreyas B. Prabhu {
37d405a98cSShreyas B. Prabhu 	int cpu;
38d405a98cSShreyas B. Prabhu 	int rc;
39d405a98cSShreyas B. Prabhu 
40d405a98cSShreyas B. Prabhu 	/*
41446957baSAdam Buchbinder 	 * hid0, hid1, hid4, hid5, hmeer and lpcr values are symmetric across
42d405a98cSShreyas B. Prabhu 	 * all cpus at boot. Get these reg values of current cpu and use the
43446957baSAdam Buchbinder 	 * same across all cpus.
44d405a98cSShreyas B. Prabhu 	 */
45d405a98cSShreyas B. Prabhu 	uint64_t lpcr_val = mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1;
46d405a98cSShreyas B. Prabhu 	uint64_t hid0_val = mfspr(SPRN_HID0);
47d405a98cSShreyas B. Prabhu 	uint64_t hid1_val = mfspr(SPRN_HID1);
48d405a98cSShreyas B. Prabhu 	uint64_t hid4_val = mfspr(SPRN_HID4);
49d405a98cSShreyas B. Prabhu 	uint64_t hid5_val = mfspr(SPRN_HID5);
50d405a98cSShreyas B. Prabhu 	uint64_t hmeer_val = mfspr(SPRN_HMEER);
51d405a98cSShreyas B. Prabhu 
52d405a98cSShreyas B. Prabhu 	for_each_possible_cpu(cpu) {
53d405a98cSShreyas B. Prabhu 		uint64_t pir = get_hard_smp_processor_id(cpu);
54d405a98cSShreyas B. Prabhu 		uint64_t hsprg0_val = (uint64_t)&paca[cpu];
55d405a98cSShreyas B. Prabhu 
56bcef83a0SShreyas B. Prabhu 		if (!cpu_has_feature(CPU_FTR_ARCH_300)) {
57d405a98cSShreyas B. Prabhu 			/*
58bcef83a0SShreyas B. Prabhu 			 * HSPRG0 is used to store the cpu's pointer to paca.
59bcef83a0SShreyas B. Prabhu 			 * Hence last 3 bits are guaranteed to be 0. Program
60bcef83a0SShreyas B. Prabhu 			 * slw to restore HSPRG0 with 63rd bit set, so that
61bcef83a0SShreyas B. Prabhu 			 * when a thread wakes up at 0x100 we can use this bit
62bcef83a0SShreyas B. Prabhu 			 * to distinguish between fastsleep and deep winkle.
63bcef83a0SShreyas B. Prabhu 			 * This is not necessary with stop/psscr since PLS
64bcef83a0SShreyas B. Prabhu 			 * field of psscr indicates which state we are waking
65bcef83a0SShreyas B. Prabhu 			 * up from.
66d405a98cSShreyas B. Prabhu 			 */
67d405a98cSShreyas B. Prabhu 			hsprg0_val |= 1;
68bcef83a0SShreyas B. Prabhu 		}
69d405a98cSShreyas B. Prabhu 		rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val);
70d405a98cSShreyas B. Prabhu 		if (rc != 0)
71d405a98cSShreyas B. Prabhu 			return rc;
72d405a98cSShreyas B. Prabhu 
73d405a98cSShreyas B. Prabhu 		rc = opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val);
74d405a98cSShreyas B. Prabhu 		if (rc != 0)
75d405a98cSShreyas B. Prabhu 			return rc;
76d405a98cSShreyas B. Prabhu 
77d405a98cSShreyas B. Prabhu 		/* HIDs are per core registers */
78d405a98cSShreyas B. Prabhu 		if (cpu_thread_in_core(cpu) == 0) {
79d405a98cSShreyas B. Prabhu 
80d405a98cSShreyas B. Prabhu 			rc = opal_slw_set_reg(pir, SPRN_HMEER, hmeer_val);
81d405a98cSShreyas B. Prabhu 			if (rc != 0)
82d405a98cSShreyas B. Prabhu 				return rc;
83d405a98cSShreyas B. Prabhu 
84d405a98cSShreyas B. Prabhu 			rc = opal_slw_set_reg(pir, SPRN_HID0, hid0_val);
85d405a98cSShreyas B. Prabhu 			if (rc != 0)
86d405a98cSShreyas B. Prabhu 				return rc;
87d405a98cSShreyas B. Prabhu 
88d405a98cSShreyas B. Prabhu 			rc = opal_slw_set_reg(pir, SPRN_HID1, hid1_val);
89d405a98cSShreyas B. Prabhu 			if (rc != 0)
90d405a98cSShreyas B. Prabhu 				return rc;
91d405a98cSShreyas B. Prabhu 
92d405a98cSShreyas B. Prabhu 			rc = opal_slw_set_reg(pir, SPRN_HID4, hid4_val);
93d405a98cSShreyas B. Prabhu 			if (rc != 0)
94d405a98cSShreyas B. Prabhu 				return rc;
95d405a98cSShreyas B. Prabhu 
96d405a98cSShreyas B. Prabhu 			rc = opal_slw_set_reg(pir, SPRN_HID5, hid5_val);
97d405a98cSShreyas B. Prabhu 			if (rc != 0)
98d405a98cSShreyas B. Prabhu 				return rc;
99d405a98cSShreyas B. Prabhu 		}
100d405a98cSShreyas B. Prabhu 	}
101d405a98cSShreyas B. Prabhu 
102d405a98cSShreyas B. Prabhu 	return 0;
103d405a98cSShreyas B. Prabhu }
104d405a98cSShreyas B. Prabhu 
105d405a98cSShreyas B. Prabhu static void pnv_alloc_idle_core_states(void)
106d405a98cSShreyas B. Prabhu {
107d405a98cSShreyas B. Prabhu 	int i, j;
108d405a98cSShreyas B. Prabhu 	int nr_cores = cpu_nr_cores();
109d405a98cSShreyas B. Prabhu 	u32 *core_idle_state;
110d405a98cSShreyas B. Prabhu 
111d405a98cSShreyas B. Prabhu 	/*
112d405a98cSShreyas B. Prabhu 	 * core_idle_state - First 8 bits track the idle state of each thread
113d405a98cSShreyas B. Prabhu 	 * of the core. The 8th bit is the lock bit. Initially all thread bits
114d405a98cSShreyas B. Prabhu 	 * are set. They are cleared when the thread enters deep idle state
115d405a98cSShreyas B. Prabhu 	 * like sleep and winkle. Initially the lock bit is cleared.
116d405a98cSShreyas B. Prabhu 	 * The lock bit has 2 purposes
117d405a98cSShreyas B. Prabhu 	 * a. While the first thread is restoring core state, it prevents
118d405a98cSShreyas B. Prabhu 	 * other threads in the core from switching to process context.
119d405a98cSShreyas B. Prabhu 	 * b. While the last thread in the core is saving the core state, it
120d405a98cSShreyas B. Prabhu 	 * prevents a different thread from waking up.
121d405a98cSShreyas B. Prabhu 	 */
122d405a98cSShreyas B. Prabhu 	for (i = 0; i < nr_cores; i++) {
123d405a98cSShreyas B. Prabhu 		int first_cpu = i * threads_per_core;
124d405a98cSShreyas B. Prabhu 		int node = cpu_to_node(first_cpu);
125d405a98cSShreyas B. Prabhu 
126d405a98cSShreyas B. Prabhu 		core_idle_state = kmalloc_node(sizeof(u32), GFP_KERNEL, node);
127d405a98cSShreyas B. Prabhu 		*core_idle_state = PNV_CORE_IDLE_THREAD_BITS;
128d405a98cSShreyas B. Prabhu 
129d405a98cSShreyas B. Prabhu 		for (j = 0; j < threads_per_core; j++) {
130d405a98cSShreyas B. Prabhu 			int cpu = first_cpu + j;
131d405a98cSShreyas B. Prabhu 
132d405a98cSShreyas B. Prabhu 			paca[cpu].core_idle_state_ptr = core_idle_state;
133d405a98cSShreyas B. Prabhu 			paca[cpu].thread_idle_state = PNV_THREAD_RUNNING;
134d405a98cSShreyas B. Prabhu 			paca[cpu].thread_mask = 1 << j;
135d405a98cSShreyas B. Prabhu 		}
136d405a98cSShreyas B. Prabhu 	}
137d405a98cSShreyas B. Prabhu 
138d405a98cSShreyas B. Prabhu 	update_subcore_sibling_mask();
139d405a98cSShreyas B. Prabhu 
140bcef83a0SShreyas B. Prabhu 	if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT)
141bcef83a0SShreyas B. Prabhu 		pnv_save_sprs_for_deep_states();
142d405a98cSShreyas B. Prabhu }
143d405a98cSShreyas B. Prabhu 
144d405a98cSShreyas B. Prabhu u32 pnv_get_supported_cpuidle_states(void)
145d405a98cSShreyas B. Prabhu {
146d405a98cSShreyas B. Prabhu 	return supported_cpuidle_states;
147d405a98cSShreyas B. Prabhu }
148d405a98cSShreyas B. Prabhu EXPORT_SYMBOL_GPL(pnv_get_supported_cpuidle_states);
149d405a98cSShreyas B. Prabhu 
1505703d2f4SShreyas B. Prabhu 
1515703d2f4SShreyas B. Prabhu static void pnv_fastsleep_workaround_apply(void *info)
1525703d2f4SShreyas B. Prabhu 
1535703d2f4SShreyas B. Prabhu {
1545703d2f4SShreyas B. Prabhu 	int rc;
1555703d2f4SShreyas B. Prabhu 	int *err = info;
1565703d2f4SShreyas B. Prabhu 
1575703d2f4SShreyas B. Prabhu 	rc = opal_config_cpu_idle_state(OPAL_CONFIG_IDLE_FASTSLEEP,
1585703d2f4SShreyas B. Prabhu 					OPAL_CONFIG_IDLE_APPLY);
1595703d2f4SShreyas B. Prabhu 	if (rc)
1605703d2f4SShreyas B. Prabhu 		*err = 1;
1615703d2f4SShreyas B. Prabhu }
1625703d2f4SShreyas B. Prabhu 
1635703d2f4SShreyas B. Prabhu /*
1645703d2f4SShreyas B. Prabhu  * Used to store fastsleep workaround state
1655703d2f4SShreyas B. Prabhu  * 0 - Workaround applied/undone at fastsleep entry/exit path (Default)
1665703d2f4SShreyas B. Prabhu  * 1 - Workaround applied once, never undone.
1675703d2f4SShreyas B. Prabhu  */
1685703d2f4SShreyas B. Prabhu static u8 fastsleep_workaround_applyonce;
1695703d2f4SShreyas B. Prabhu 
1705703d2f4SShreyas B. Prabhu static ssize_t show_fastsleep_workaround_applyonce(struct device *dev,
1715703d2f4SShreyas B. Prabhu 		struct device_attribute *attr, char *buf)
1725703d2f4SShreyas B. Prabhu {
1735703d2f4SShreyas B. Prabhu 	return sprintf(buf, "%u\n", fastsleep_workaround_applyonce);
1745703d2f4SShreyas B. Prabhu }
1755703d2f4SShreyas B. Prabhu 
1765703d2f4SShreyas B. Prabhu static ssize_t store_fastsleep_workaround_applyonce(struct device *dev,
1775703d2f4SShreyas B. Prabhu 		struct device_attribute *attr, const char *buf,
1785703d2f4SShreyas B. Prabhu 		size_t count)
1795703d2f4SShreyas B. Prabhu {
1805703d2f4SShreyas B. Prabhu 	cpumask_t primary_thread_mask;
1815703d2f4SShreyas B. Prabhu 	int err;
1825703d2f4SShreyas B. Prabhu 	u8 val;
1835703d2f4SShreyas B. Prabhu 
1845703d2f4SShreyas B. Prabhu 	if (kstrtou8(buf, 0, &val) || val != 1)
1855703d2f4SShreyas B. Prabhu 		return -EINVAL;
1865703d2f4SShreyas B. Prabhu 
1875703d2f4SShreyas B. Prabhu 	if (fastsleep_workaround_applyonce == 1)
1885703d2f4SShreyas B. Prabhu 		return count;
1895703d2f4SShreyas B. Prabhu 
1905703d2f4SShreyas B. Prabhu 	/*
1915703d2f4SShreyas B. Prabhu 	 * fastsleep_workaround_applyonce = 1 implies
1925703d2f4SShreyas B. Prabhu 	 * fastsleep workaround needs to be left in 'applied' state on all
1935703d2f4SShreyas B. Prabhu 	 * the cores. Do this by-
1945703d2f4SShreyas B. Prabhu 	 * 1. Patching out the call to 'undo' workaround in fastsleep exit path
1955703d2f4SShreyas B. Prabhu 	 * 2. Sending ipi to all the cores which have at least one online thread
1965703d2f4SShreyas B. Prabhu 	 * 3. Patching out the call to 'apply' workaround in fastsleep entry
1975703d2f4SShreyas B. Prabhu 	 * path
1985703d2f4SShreyas B. Prabhu 	 * There is no need to send ipi to cores which have all threads
1995703d2f4SShreyas B. Prabhu 	 * offlined, as last thread of the core entering fastsleep or deeper
2005703d2f4SShreyas B. Prabhu 	 * state would have applied workaround.
2015703d2f4SShreyas B. Prabhu 	 */
2025703d2f4SShreyas B. Prabhu 	err = patch_instruction(
2035703d2f4SShreyas B. Prabhu 		(unsigned int *)pnv_fastsleep_workaround_at_exit,
2045703d2f4SShreyas B. Prabhu 		PPC_INST_NOP);
2055703d2f4SShreyas B. Prabhu 	if (err) {
2065703d2f4SShreyas B. Prabhu 		pr_err("fastsleep_workaround_applyonce change failed while patching pnv_fastsleep_workaround_at_exit");
2075703d2f4SShreyas B. Prabhu 		goto fail;
2085703d2f4SShreyas B. Prabhu 	}
2095703d2f4SShreyas B. Prabhu 
2105703d2f4SShreyas B. Prabhu 	get_online_cpus();
2115703d2f4SShreyas B. Prabhu 	primary_thread_mask = cpu_online_cores_map();
2125703d2f4SShreyas B. Prabhu 	on_each_cpu_mask(&primary_thread_mask,
2135703d2f4SShreyas B. Prabhu 				pnv_fastsleep_workaround_apply,
2145703d2f4SShreyas B. Prabhu 				&err, 1);
2155703d2f4SShreyas B. Prabhu 	put_online_cpus();
2165703d2f4SShreyas B. Prabhu 	if (err) {
2175703d2f4SShreyas B. Prabhu 		pr_err("fastsleep_workaround_applyonce change failed while running pnv_fastsleep_workaround_apply");
2185703d2f4SShreyas B. Prabhu 		goto fail;
2195703d2f4SShreyas B. Prabhu 	}
2205703d2f4SShreyas B. Prabhu 
2215703d2f4SShreyas B. Prabhu 	err = patch_instruction(
2225703d2f4SShreyas B. Prabhu 		(unsigned int *)pnv_fastsleep_workaround_at_entry,
2235703d2f4SShreyas B. Prabhu 		PPC_INST_NOP);
2245703d2f4SShreyas B. Prabhu 	if (err) {
2255703d2f4SShreyas B. Prabhu 		pr_err("fastsleep_workaround_applyonce change failed while patching pnv_fastsleep_workaround_at_entry");
2265703d2f4SShreyas B. Prabhu 		goto fail;
2275703d2f4SShreyas B. Prabhu 	}
2285703d2f4SShreyas B. Prabhu 
2295703d2f4SShreyas B. Prabhu 	fastsleep_workaround_applyonce = 1;
2305703d2f4SShreyas B. Prabhu 
2315703d2f4SShreyas B. Prabhu 	return count;
2325703d2f4SShreyas B. Prabhu fail:
2335703d2f4SShreyas B. Prabhu 	return -EIO;
2345703d2f4SShreyas B. Prabhu }
2355703d2f4SShreyas B. Prabhu 
2365703d2f4SShreyas B. Prabhu static DEVICE_ATTR(fastsleep_workaround_applyonce, 0600,
2375703d2f4SShreyas B. Prabhu 			show_fastsleep_workaround_applyonce,
2385703d2f4SShreyas B. Prabhu 			store_fastsleep_workaround_applyonce);
2395703d2f4SShreyas B. Prabhu 
240*09206b60SGautham R. Shenoy /*
241*09206b60SGautham R. Shenoy  * The default stop state that will be used by ppc_md.power_save
242*09206b60SGautham R. Shenoy  * function on platforms that support stop instruction.
243*09206b60SGautham R. Shenoy  */
244*09206b60SGautham R. Shenoy u64 pnv_default_stop_val;
245*09206b60SGautham R. Shenoy u64 pnv_default_stop_mask;
246bcef83a0SShreyas B. Prabhu 
247bcef83a0SShreyas B. Prabhu /*
248bcef83a0SShreyas B. Prabhu  * Used for ppc_md.power_save which needs a function with no parameters
249bcef83a0SShreyas B. Prabhu  */
250bcef83a0SShreyas B. Prabhu static void power9_idle(void)
251d405a98cSShreyas B. Prabhu {
252*09206b60SGautham R. Shenoy 	power9_idle_stop(pnv_default_stop_val, pnv_default_stop_mask);
253bcef83a0SShreyas B. Prabhu }
254*09206b60SGautham R. Shenoy 
255bcef83a0SShreyas B. Prabhu /*
256bcef83a0SShreyas B. Prabhu  * First deep stop state. Used to figure out when to save/restore
257bcef83a0SShreyas B. Prabhu  * hypervisor context.
258bcef83a0SShreyas B. Prabhu  */
259bcef83a0SShreyas B. Prabhu u64 pnv_first_deep_stop_state = MAX_STOP_STATE;
260bcef83a0SShreyas B. Prabhu 
261bcef83a0SShreyas B. Prabhu /*
262*09206b60SGautham R. Shenoy  * psscr value and mask of the deepest stop idle state.
263*09206b60SGautham R. Shenoy  * Used when a cpu is offlined.
264c0691f9dSShreyas B. Prabhu  */
265*09206b60SGautham R. Shenoy u64 pnv_deepest_stop_psscr_val;
266*09206b60SGautham R. Shenoy u64 pnv_deepest_stop_psscr_mask;
267c0691f9dSShreyas B. Prabhu 
268c0691f9dSShreyas B. Prabhu /*
269bcef83a0SShreyas B. Prabhu  * Power ISA 3.0 idle initialization.
270bcef83a0SShreyas B. Prabhu  *
271bcef83a0SShreyas B. Prabhu  * POWER ISA 3.0 defines a new SPR Processor stop Status and Control
272bcef83a0SShreyas B. Prabhu  * Register (PSSCR) to control idle behavior.
273bcef83a0SShreyas B. Prabhu  *
274bcef83a0SShreyas B. Prabhu  * PSSCR layout:
275bcef83a0SShreyas B. Prabhu  * ----------------------------------------------------------
276bcef83a0SShreyas B. Prabhu  * | PLS | /// | SD | ESL | EC | PSLL | /// | TR | MTL | RL |
277bcef83a0SShreyas B. Prabhu  * ----------------------------------------------------------
278bcef83a0SShreyas B. Prabhu  * 0      4     41   42    43   44     48    54   56    60
279bcef83a0SShreyas B. Prabhu  *
280bcef83a0SShreyas B. Prabhu  * PSSCR key fields:
281bcef83a0SShreyas B. Prabhu  *	Bits 0:3  - Power-Saving Level Status (PLS). This field indicates the
282bcef83a0SShreyas B. Prabhu  *	lowest power-saving state the thread entered since stop instruction was
283bcef83a0SShreyas B. Prabhu  *	last executed.
284bcef83a0SShreyas B. Prabhu  *
285bcef83a0SShreyas B. Prabhu  *	Bit 41 - Status Disable(SD)
286bcef83a0SShreyas B. Prabhu  *	0 - Shows PLS entries
287bcef83a0SShreyas B. Prabhu  *	1 - PLS entries are all 0
288bcef83a0SShreyas B. Prabhu  *
289bcef83a0SShreyas B. Prabhu  *	Bit 42 - Enable State Loss
290bcef83a0SShreyas B. Prabhu  *	0 - No state is lost irrespective of other fields
291bcef83a0SShreyas B. Prabhu  *	1 - Allows state loss
292bcef83a0SShreyas B. Prabhu  *
293bcef83a0SShreyas B. Prabhu  *	Bit 43 - Exit Criterion
294bcef83a0SShreyas B. Prabhu  *	0 - Exit from power-save mode on any interrupt
295bcef83a0SShreyas B. Prabhu  *	1 - Exit from power-save mode controlled by LPCR's PECE bits
296bcef83a0SShreyas B. Prabhu  *
297bcef83a0SShreyas B. Prabhu  *	Bits 44:47 - Power-Saving Level Limit
298bcef83a0SShreyas B. Prabhu  *	This limits the power-saving level that can be entered into.
299bcef83a0SShreyas B. Prabhu  *
300bcef83a0SShreyas B. Prabhu  *	Bits 60:63 - Requested Level
301bcef83a0SShreyas B. Prabhu  *	Used to specify which power-saving level must be entered on executing
302bcef83a0SShreyas B. Prabhu  *	stop instruction
303*09206b60SGautham R. Shenoy  */
304*09206b60SGautham R. Shenoy 
305*09206b60SGautham R. Shenoy int validate_psscr_val_mask(u64 *psscr_val, u64 *psscr_mask, u32 flags)
306*09206b60SGautham R. Shenoy {
307*09206b60SGautham R. Shenoy 	int err = 0;
308*09206b60SGautham R. Shenoy 
309*09206b60SGautham R. Shenoy 	/*
310*09206b60SGautham R. Shenoy 	 * psscr_mask == 0xf indicates an older firmware.
311*09206b60SGautham R. Shenoy 	 * Set remaining fields of psscr to the default values.
312*09206b60SGautham R. Shenoy 	 * See NOTE above definition of PSSCR_HV_DEFAULT_VAL
313*09206b60SGautham R. Shenoy 	 */
314*09206b60SGautham R. Shenoy 	if (*psscr_mask == 0xf) {
315*09206b60SGautham R. Shenoy 		*psscr_val = *psscr_val | PSSCR_HV_DEFAULT_VAL;
316*09206b60SGautham R. Shenoy 		*psscr_mask = PSSCR_HV_DEFAULT_MASK;
317*09206b60SGautham R. Shenoy 		return err;
318*09206b60SGautham R. Shenoy 	}
319*09206b60SGautham R. Shenoy 
320*09206b60SGautham R. Shenoy 	/*
321*09206b60SGautham R. Shenoy 	 * New firmware is expected to set the psscr_val bits correctly.
322*09206b60SGautham R. Shenoy 	 * Validate that the following invariants are correctly maintained by
323*09206b60SGautham R. Shenoy 	 * the new firmware.
324*09206b60SGautham R. Shenoy 	 * - ESL bit value matches the EC bit value.
325*09206b60SGautham R. Shenoy 	 * - ESL bit is set for all the deep stop states.
326*09206b60SGautham R. Shenoy 	 */
327*09206b60SGautham R. Shenoy 	if (GET_PSSCR_ESL(*psscr_val) != GET_PSSCR_EC(*psscr_val)) {
328*09206b60SGautham R. Shenoy 		err = ERR_EC_ESL_MISMATCH;
329*09206b60SGautham R. Shenoy 	} else if ((flags & OPAL_PM_LOSE_FULL_CONTEXT) &&
330*09206b60SGautham R. Shenoy 		GET_PSSCR_ESL(*psscr_val) == 0) {
331*09206b60SGautham R. Shenoy 		err = ERR_DEEP_STATE_ESL_MISMATCH;
332*09206b60SGautham R. Shenoy 	}
333*09206b60SGautham R. Shenoy 
334*09206b60SGautham R. Shenoy 	return err;
335*09206b60SGautham R. Shenoy }
336*09206b60SGautham R. Shenoy 
337*09206b60SGautham R. Shenoy /*
338*09206b60SGautham R. Shenoy  * pnv_arch300_idle_init: Initializes the default idle state, first
339*09206b60SGautham R. Shenoy  *                        deep idle state and deepest idle state on
340*09206b60SGautham R. Shenoy  *                        ISA 3.0 CPUs.
341bcef83a0SShreyas B. Prabhu  *
342bcef83a0SShreyas B. Prabhu  * @np: /ibm,opal/power-mgt device node
343bcef83a0SShreyas B. Prabhu  * @flags: cpu-idle-state-flags array
344bcef83a0SShreyas B. Prabhu  * @dt_idle_states: Number of idle state entries
345bcef83a0SShreyas B. Prabhu  * Returns 0 on success
346bcef83a0SShreyas B. Prabhu  */
347dd34c74cSGautham R. Shenoy static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags,
348bcef83a0SShreyas B. Prabhu 					int dt_idle_states)
349bcef83a0SShreyas B. Prabhu {
350bcef83a0SShreyas B. Prabhu 	u64 *psscr_val = NULL;
351*09206b60SGautham R. Shenoy 	u64 *psscr_mask = NULL;
352*09206b60SGautham R. Shenoy 	u32 *residency_ns = NULL;
353*09206b60SGautham R. Shenoy 	u64 max_residency_ns = 0;
354bcef83a0SShreyas B. Prabhu 	int rc = 0, i;
355*09206b60SGautham R. Shenoy 	bool default_stop_found = false, deepest_stop_found = false;
356bcef83a0SShreyas B. Prabhu 
357*09206b60SGautham R. Shenoy 	psscr_val = kcalloc(dt_idle_states, sizeof(*psscr_val), GFP_KERNEL);
358*09206b60SGautham R. Shenoy 	psscr_mask = kcalloc(dt_idle_states, sizeof(*psscr_mask), GFP_KERNEL);
359*09206b60SGautham R. Shenoy 	residency_ns = kcalloc(dt_idle_states, sizeof(*residency_ns),
360bcef83a0SShreyas B. Prabhu 			       GFP_KERNEL);
361*09206b60SGautham R. Shenoy 
362*09206b60SGautham R. Shenoy 	if (!psscr_val || !psscr_mask || !residency_ns) {
363bcef83a0SShreyas B. Prabhu 		rc = -1;
364bcef83a0SShreyas B. Prabhu 		goto out;
365bcef83a0SShreyas B. Prabhu 	}
366*09206b60SGautham R. Shenoy 
367bcef83a0SShreyas B. Prabhu 	if (of_property_read_u64_array(np,
368bcef83a0SShreyas B. Prabhu 		"ibm,cpu-idle-state-psscr",
369bcef83a0SShreyas B. Prabhu 		psscr_val, dt_idle_states)) {
370*09206b60SGautham R. Shenoy 		pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr in DT\n");
371*09206b60SGautham R. Shenoy 		rc = -1;
372*09206b60SGautham R. Shenoy 		goto out;
373*09206b60SGautham R. Shenoy 	}
374*09206b60SGautham R. Shenoy 
375*09206b60SGautham R. Shenoy 	if (of_property_read_u64_array(np,
376*09206b60SGautham R. Shenoy 				       "ibm,cpu-idle-state-psscr-mask",
377*09206b60SGautham R. Shenoy 				       psscr_mask, dt_idle_states)) {
378*09206b60SGautham R. Shenoy 		pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr-mask in DT\n");
379*09206b60SGautham R. Shenoy 		rc = -1;
380*09206b60SGautham R. Shenoy 		goto out;
381*09206b60SGautham R. Shenoy 	}
382*09206b60SGautham R. Shenoy 
383*09206b60SGautham R. Shenoy 	if (of_property_read_u32_array(np,
384*09206b60SGautham R. Shenoy 				       "ibm,cpu-idle-state-residency-ns",
385*09206b60SGautham R. Shenoy 					residency_ns, dt_idle_states)) {
386*09206b60SGautham R. Shenoy 		pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-residency-ns in DT\n");
387bcef83a0SShreyas B. Prabhu 		rc = -1;
388bcef83a0SShreyas B. Prabhu 		goto out;
389bcef83a0SShreyas B. Prabhu 	}
390bcef83a0SShreyas B. Prabhu 
391bcef83a0SShreyas B. Prabhu 	/*
392*09206b60SGautham R. Shenoy 	 * Set pnv_first_deep_stop_state, pnv_deepest_stop_psscr_{val,mask},
393*09206b60SGautham R. Shenoy 	 * and the pnv_default_stop_{val,mask}.
394*09206b60SGautham R. Shenoy 	 *
395c0691f9dSShreyas B. Prabhu 	 * pnv_first_deep_stop_state should be set to the first stop
396c0691f9dSShreyas B. Prabhu 	 * level to cause hypervisor state loss.
397*09206b60SGautham R. Shenoy 	 *
398*09206b60SGautham R. Shenoy 	 * pnv_deepest_stop_{val,mask} should be set to values corresponding to
399*09206b60SGautham R. Shenoy 	 * the deepest stop state.
400*09206b60SGautham R. Shenoy 	 *
401*09206b60SGautham R. Shenoy 	 * pnv_default_stop_{val,mask} should be set to values corresponding to
402*09206b60SGautham R. Shenoy 	 * the shallowest (OPAL_PM_STOP_INST_FAST) loss-less stop state.
403bcef83a0SShreyas B. Prabhu 	 */
404bcef83a0SShreyas B. Prabhu 	pnv_first_deep_stop_state = MAX_STOP_STATE;
405bcef83a0SShreyas B. Prabhu 	for (i = 0; i < dt_idle_states; i++) {
406*09206b60SGautham R. Shenoy 		int err;
407bcef83a0SShreyas B. Prabhu 		u64 psscr_rl = psscr_val[i] & PSSCR_RL_MASK;
408bcef83a0SShreyas B. Prabhu 
409bcef83a0SShreyas B. Prabhu 		if ((flags[i] & OPAL_PM_LOSE_FULL_CONTEXT) &&
410bcef83a0SShreyas B. Prabhu 		     (pnv_first_deep_stop_state > psscr_rl))
411bcef83a0SShreyas B. Prabhu 			pnv_first_deep_stop_state = psscr_rl;
412c0691f9dSShreyas B. Prabhu 
413*09206b60SGautham R. Shenoy 		err = validate_psscr_val_mask(&psscr_val[i], &psscr_mask[i],
414*09206b60SGautham R. Shenoy 					      flags[i]);
415*09206b60SGautham R. Shenoy 		if (err) {
416*09206b60SGautham R. Shenoy 			report_invalid_psscr_val(psscr_val[i], err);
417*09206b60SGautham R. Shenoy 			continue;
418*09206b60SGautham R. Shenoy 		}
419*09206b60SGautham R. Shenoy 
420*09206b60SGautham R. Shenoy 		if (max_residency_ns < residency_ns[i]) {
421*09206b60SGautham R. Shenoy 			max_residency_ns = residency_ns[i];
422*09206b60SGautham R. Shenoy 			pnv_deepest_stop_psscr_val = psscr_val[i];
423*09206b60SGautham R. Shenoy 			pnv_deepest_stop_psscr_mask = psscr_mask[i];
424*09206b60SGautham R. Shenoy 			deepest_stop_found = true;
425*09206b60SGautham R. Shenoy 		}
426*09206b60SGautham R. Shenoy 
427*09206b60SGautham R. Shenoy 		if (!default_stop_found &&
428*09206b60SGautham R. Shenoy 		    (flags[i] & OPAL_PM_STOP_INST_FAST)) {
429*09206b60SGautham R. Shenoy 			pnv_default_stop_val = psscr_val[i];
430*09206b60SGautham R. Shenoy 			pnv_default_stop_mask = psscr_mask[i];
431*09206b60SGautham R. Shenoy 			default_stop_found = true;
432*09206b60SGautham R. Shenoy 		}
433*09206b60SGautham R. Shenoy 	}
434*09206b60SGautham R. Shenoy 
435*09206b60SGautham R. Shenoy 	if (!default_stop_found) {
436*09206b60SGautham R. Shenoy 		pnv_default_stop_val = PSSCR_HV_DEFAULT_VAL;
437*09206b60SGautham R. Shenoy 		pnv_default_stop_mask = PSSCR_HV_DEFAULT_MASK;
438*09206b60SGautham R. Shenoy 		pr_warn("Setting default stop psscr val=0x%016llx,mask=0x%016llx\n",
439*09206b60SGautham R. Shenoy 			pnv_default_stop_val, pnv_default_stop_mask);
440*09206b60SGautham R. Shenoy 	}
441*09206b60SGautham R. Shenoy 
442*09206b60SGautham R. Shenoy 	if (!deepest_stop_found) {
443*09206b60SGautham R. Shenoy 		pnv_deepest_stop_psscr_val = PSSCR_HV_DEFAULT_VAL;
444*09206b60SGautham R. Shenoy 		pnv_deepest_stop_psscr_mask = PSSCR_HV_DEFAULT_MASK;
445*09206b60SGautham R. Shenoy 		pr_warn("Setting default stop psscr val=0x%016llx,mask=0x%016llx\n",
446*09206b60SGautham R. Shenoy 			pnv_deepest_stop_psscr_val,
447*09206b60SGautham R. Shenoy 			pnv_deepest_stop_psscr_mask);
448bcef83a0SShreyas B. Prabhu 	}
449bcef83a0SShreyas B. Prabhu 
450bcef83a0SShreyas B. Prabhu out:
451bcef83a0SShreyas B. Prabhu 	kfree(psscr_val);
452*09206b60SGautham R. Shenoy 	kfree(psscr_mask);
453*09206b60SGautham R. Shenoy 	kfree(residency_ns);
454bcef83a0SShreyas B. Prabhu 	return rc;
455bcef83a0SShreyas B. Prabhu }
456bcef83a0SShreyas B. Prabhu 
457bcef83a0SShreyas B. Prabhu /*
458bcef83a0SShreyas B. Prabhu  * Probe device tree for supported idle states
459bcef83a0SShreyas B. Prabhu  */
460bcef83a0SShreyas B. Prabhu static void __init pnv_probe_idle_states(void)
461bcef83a0SShreyas B. Prabhu {
462bcef83a0SShreyas B. Prabhu 	struct device_node *np;
463d405a98cSShreyas B. Prabhu 	int dt_idle_states;
464bcef83a0SShreyas B. Prabhu 	u32 *flags = NULL;
465d405a98cSShreyas B. Prabhu 	int i;
466d405a98cSShreyas B. Prabhu 
467bcef83a0SShreyas B. Prabhu 	np = of_find_node_by_path("/ibm,opal/power-mgt");
468bcef83a0SShreyas B. Prabhu 	if (!np) {
469d405a98cSShreyas B. Prabhu 		pr_warn("opal: PowerMgmt Node not found\n");
470d405a98cSShreyas B. Prabhu 		goto out;
471d405a98cSShreyas B. Prabhu 	}
472bcef83a0SShreyas B. Prabhu 	dt_idle_states = of_property_count_u32_elems(np,
473d405a98cSShreyas B. Prabhu 			"ibm,cpu-idle-state-flags");
474d405a98cSShreyas B. Prabhu 	if (dt_idle_states < 0) {
475d405a98cSShreyas B. Prabhu 		pr_warn("cpuidle-powernv: no idle states found in the DT\n");
476d405a98cSShreyas B. Prabhu 		goto out;
477d405a98cSShreyas B. Prabhu 	}
478d405a98cSShreyas B. Prabhu 
479bcef83a0SShreyas B. Prabhu 	flags = kcalloc(dt_idle_states, sizeof(*flags),  GFP_KERNEL);
480bcef83a0SShreyas B. Prabhu 
481bcef83a0SShreyas B. Prabhu 	if (of_property_read_u32_array(np,
482d405a98cSShreyas B. Prabhu 			"ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
483d405a98cSShreyas B. Prabhu 		pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n");
484bcef83a0SShreyas B. Prabhu 		goto out;
485bcef83a0SShreyas B. Prabhu 	}
486bcef83a0SShreyas B. Prabhu 
487bcef83a0SShreyas B. Prabhu 	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
488dd34c74cSGautham R. Shenoy 		if (pnv_power9_idle_init(np, flags, dt_idle_states))
489bcef83a0SShreyas B. Prabhu 			goto out;
490d405a98cSShreyas B. Prabhu 	}
491d405a98cSShreyas B. Prabhu 
492d405a98cSShreyas B. Prabhu 	for (i = 0; i < dt_idle_states; i++)
493d405a98cSShreyas B. Prabhu 		supported_cpuidle_states |= flags[i];
494d405a98cSShreyas B. Prabhu 
495bcef83a0SShreyas B. Prabhu out:
496bcef83a0SShreyas B. Prabhu 	kfree(flags);
497bcef83a0SShreyas B. Prabhu }
498bcef83a0SShreyas B. Prabhu static int __init pnv_init_idle_states(void)
499bcef83a0SShreyas B. Prabhu {
500bcef83a0SShreyas B. Prabhu 
501bcef83a0SShreyas B. Prabhu 	supported_cpuidle_states = 0;
502bcef83a0SShreyas B. Prabhu 
503bcef83a0SShreyas B. Prabhu 	if (cpuidle_disable != IDLE_NO_OVERRIDE)
504bcef83a0SShreyas B. Prabhu 		goto out;
505bcef83a0SShreyas B. Prabhu 
506bcef83a0SShreyas B. Prabhu 	pnv_probe_idle_states();
507bcef83a0SShreyas B. Prabhu 
508d405a98cSShreyas B. Prabhu 	if (!(supported_cpuidle_states & OPAL_PM_SLEEP_ENABLED_ER1)) {
509d405a98cSShreyas B. Prabhu 		patch_instruction(
510d405a98cSShreyas B. Prabhu 			(unsigned int *)pnv_fastsleep_workaround_at_entry,
511d405a98cSShreyas B. Prabhu 			PPC_INST_NOP);
512d405a98cSShreyas B. Prabhu 		patch_instruction(
513d405a98cSShreyas B. Prabhu 			(unsigned int *)pnv_fastsleep_workaround_at_exit,
514d405a98cSShreyas B. Prabhu 			PPC_INST_NOP);
5155703d2f4SShreyas B. Prabhu 	} else {
5165703d2f4SShreyas B. Prabhu 		/*
5175703d2f4SShreyas B. Prabhu 		 * OPAL_PM_SLEEP_ENABLED_ER1 is set. It indicates that
5185703d2f4SShreyas B. Prabhu 		 * workaround is needed to use fastsleep. Provide sysfs
5195703d2f4SShreyas B. Prabhu 		 * control to choose how this workaround has to be applied.
5205703d2f4SShreyas B. Prabhu 		 */
5215703d2f4SShreyas B. Prabhu 		device_create_file(cpu_subsys.dev_root,
5225703d2f4SShreyas B. Prabhu 				&dev_attr_fastsleep_workaround_applyonce);
523d405a98cSShreyas B. Prabhu 	}
5245703d2f4SShreyas B. Prabhu 
525d405a98cSShreyas B. Prabhu 	pnv_alloc_idle_core_states();
5265593e303SShreyas B. Prabhu 
5275593e303SShreyas B. Prabhu 	if (supported_cpuidle_states & OPAL_PM_NAP_ENABLED)
5285593e303SShreyas B. Prabhu 		ppc_md.power_save = power7_idle;
529bcef83a0SShreyas B. Prabhu 	else if (supported_cpuidle_states & OPAL_PM_STOP_INST_FAST)
530bcef83a0SShreyas B. Prabhu 		ppc_md.power_save = power9_idle;
531bcef83a0SShreyas B. Prabhu 
532d405a98cSShreyas B. Prabhu out:
533d405a98cSShreyas B. Prabhu 	return 0;
534d405a98cSShreyas B. Prabhu }
5354bece972SMichael Ellerman machine_subsys_initcall(powernv, pnv_init_idle_states);
536