12c2e6ecfSDeepthi Dharwar /*
22c2e6ecfSDeepthi Dharwar  *  cpuidle-powernv - idle state cpuidle driver.
32c2e6ecfSDeepthi Dharwar  *  Adapted from drivers/cpuidle/cpuidle-pseries
42c2e6ecfSDeepthi Dharwar  *
52c2e6ecfSDeepthi Dharwar  */
62c2e6ecfSDeepthi Dharwar 
72c2e6ecfSDeepthi Dharwar #include <linux/kernel.h>
82c2e6ecfSDeepthi Dharwar #include <linux/module.h>
92c2e6ecfSDeepthi Dharwar #include <linux/init.h>
102c2e6ecfSDeepthi Dharwar #include <linux/moduleparam.h>
112c2e6ecfSDeepthi Dharwar #include <linux/cpuidle.h>
122c2e6ecfSDeepthi Dharwar #include <linux/cpu.h>
132c2e6ecfSDeepthi Dharwar #include <linux/notifier.h>
140d948730SPreeti U Murthy #include <linux/clockchips.h>
150888839cSPreeti U Murthy #include <linux/of.h>
1692c83ff5SPreeti U Murthy #include <linux/slab.h>
172c2e6ecfSDeepthi Dharwar 
182c2e6ecfSDeepthi Dharwar #include <asm/machdep.h>
192c2e6ecfSDeepthi Dharwar #include <asm/firmware.h>
208eb8ac89SShreyas B. Prabhu #include <asm/opal.h>
21591ac0cbSNicolas Pitre #include <asm/runlatch.h>
2209206b60SGautham R. Shenoy #include <asm/cpuidle.h>
232c2e6ecfSDeepthi Dharwar 
249e9fc6f0SGautham R. Shenoy /*
259e9fc6f0SGautham R. Shenoy  * Expose only those Hardware idle states via the cpuidle framework
269e9fc6f0SGautham R. Shenoy  * that have latency value below POWERNV_THRESHOLD_LATENCY_NS.
279e9fc6f0SGautham R. Shenoy  */
283005c597SShreyas B. Prabhu #define POWERNV_THRESHOLD_LATENCY_NS 200000
293005c597SShreyas B. Prabhu 
30ed61390bSAndrew Donnellan static struct cpuidle_driver powernv_idle_driver = {
312c2e6ecfSDeepthi Dharwar 	.name             = "powernv_idle",
322c2e6ecfSDeepthi Dharwar 	.owner            = THIS_MODULE,
332c2e6ecfSDeepthi Dharwar };
342c2e6ecfSDeepthi Dharwar 
352c2e6ecfSDeepthi Dharwar static int max_idle_state;
362c2e6ecfSDeepthi Dharwar static struct cpuidle_state *cpuidle_state_table;
373005c597SShreyas B. Prabhu 
3809206b60SGautham R. Shenoy struct stop_psscr_table {
3909206b60SGautham R. Shenoy 	u64 val;
4009206b60SGautham R. Shenoy 	u64 mask;
4109206b60SGautham R. Shenoy };
4209206b60SGautham R. Shenoy 
4309206b60SGautham R. Shenoy static struct stop_psscr_table stop_psscr_table[CPUIDLE_STATE_MAX];
443005c597SShreyas B. Prabhu 
4578eaa10fSShilpasri G Bhat static u64 snooze_timeout;
4678eaa10fSShilpasri G Bhat static bool snooze_timeout_en;
472c2e6ecfSDeepthi Dharwar 
482c2e6ecfSDeepthi Dharwar static int snooze_loop(struct cpuidle_device *dev,
492c2e6ecfSDeepthi Dharwar 			struct cpuidle_driver *drv,
502c2e6ecfSDeepthi Dharwar 			int index)
512c2e6ecfSDeepthi Dharwar {
5278eaa10fSShilpasri G Bhat 	u64 snooze_exit_time;
5378eaa10fSShilpasri G Bhat 
542c2e6ecfSDeepthi Dharwar 	local_irq_enable();
552c2e6ecfSDeepthi Dharwar 	set_thread_flag(TIF_POLLING_NRFLAG);
562c2e6ecfSDeepthi Dharwar 
5778eaa10fSShilpasri G Bhat 	snooze_exit_time = get_tb() + snooze_timeout;
58591ac0cbSNicolas Pitre 	ppc64_runlatch_off();
592c2e6ecfSDeepthi Dharwar 	while (!need_resched()) {
602c2e6ecfSDeepthi Dharwar 		HMT_low();
612c2e6ecfSDeepthi Dharwar 		HMT_very_low();
6278eaa10fSShilpasri G Bhat 		if (snooze_timeout_en && get_tb() > snooze_exit_time)
6378eaa10fSShilpasri G Bhat 			break;
642c2e6ecfSDeepthi Dharwar 	}
652c2e6ecfSDeepthi Dharwar 
662c2e6ecfSDeepthi Dharwar 	HMT_medium();
67591ac0cbSNicolas Pitre 	ppc64_runlatch_on();
682c2e6ecfSDeepthi Dharwar 	clear_thread_flag(TIF_POLLING_NRFLAG);
692c2e6ecfSDeepthi Dharwar 	smp_mb();
702c2e6ecfSDeepthi Dharwar 	return index;
712c2e6ecfSDeepthi Dharwar }
722c2e6ecfSDeepthi Dharwar 
732c2e6ecfSDeepthi Dharwar static int nap_loop(struct cpuidle_device *dev,
742c2e6ecfSDeepthi Dharwar 			struct cpuidle_driver *drv,
752c2e6ecfSDeepthi Dharwar 			int index)
762c2e6ecfSDeepthi Dharwar {
77591ac0cbSNicolas Pitre 	ppc64_runlatch_off();
782c2e6ecfSDeepthi Dharwar 	power7_idle();
79591ac0cbSNicolas Pitre 	ppc64_runlatch_on();
802c2e6ecfSDeepthi Dharwar 	return index;
812c2e6ecfSDeepthi Dharwar }
822c2e6ecfSDeepthi Dharwar 
83cc5a2f7bSpreeti /* Register for fastsleep only in oneshot mode of broadcast */
84cc5a2f7bSpreeti #ifdef CONFIG_TICK_ONESHOT
850d948730SPreeti U Murthy static int fastsleep_loop(struct cpuidle_device *dev,
860d948730SPreeti U Murthy 				struct cpuidle_driver *drv,
870d948730SPreeti U Murthy 				int index)
880d948730SPreeti U Murthy {
890d948730SPreeti U Murthy 	unsigned long old_lpcr = mfspr(SPRN_LPCR);
900d948730SPreeti U Murthy 	unsigned long new_lpcr;
910d948730SPreeti U Murthy 
920d948730SPreeti U Murthy 	if (unlikely(system_state < SYSTEM_RUNNING))
930d948730SPreeti U Murthy 		return index;
940d948730SPreeti U Murthy 
950d948730SPreeti U Murthy 	new_lpcr = old_lpcr;
969b6a68d9SMichael Neuling 	/* Do not exit powersave upon decrementer as we've setup the timer
979b6a68d9SMichael Neuling 	 * offload.
980d948730SPreeti U Murthy 	 */
999b6a68d9SMichael Neuling 	new_lpcr &= ~LPCR_PECE1;
1000d948730SPreeti U Murthy 
1010d948730SPreeti U Murthy 	mtspr(SPRN_LPCR, new_lpcr);
1020d948730SPreeti U Murthy 	power7_sleep();
1030d948730SPreeti U Murthy 
1040d948730SPreeti U Murthy 	mtspr(SPRN_LPCR, old_lpcr);
1050d948730SPreeti U Murthy 
1060d948730SPreeti U Murthy 	return index;
1070d948730SPreeti U Murthy }
108cc5a2f7bSpreeti #endif
1093005c597SShreyas B. Prabhu 
1103005c597SShreyas B. Prabhu static int stop_loop(struct cpuidle_device *dev,
1113005c597SShreyas B. Prabhu 		     struct cpuidle_driver *drv,
1123005c597SShreyas B. Prabhu 		     int index)
1133005c597SShreyas B. Prabhu {
1143005c597SShreyas B. Prabhu 	ppc64_runlatch_off();
11509206b60SGautham R. Shenoy 	power9_idle_stop(stop_psscr_table[index].val,
11609206b60SGautham R. Shenoy 			 stop_psscr_table[index].mask);
1173005c597SShreyas B. Prabhu 	ppc64_runlatch_on();
1183005c597SShreyas B. Prabhu 	return index;
1193005c597SShreyas B. Prabhu }
1203005c597SShreyas B. Prabhu 
1212c2e6ecfSDeepthi Dharwar /*
1222c2e6ecfSDeepthi Dharwar  * States for dedicated partition case.
1232c2e6ecfSDeepthi Dharwar  */
124169f3faeSShreyas B. Prabhu static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] = {
1252c2e6ecfSDeepthi Dharwar 	{ /* Snooze */
1262c2e6ecfSDeepthi Dharwar 		.name = "snooze",
1272c2e6ecfSDeepthi Dharwar 		.desc = "snooze",
1282c2e6ecfSDeepthi Dharwar 		.exit_latency = 0,
1292c2e6ecfSDeepthi Dharwar 		.target_residency = 0,
130957efcedSShreyas B. Prabhu 		.enter = snooze_loop },
1312c2e6ecfSDeepthi Dharwar };
1322c2e6ecfSDeepthi Dharwar 
13310fcca9dSSebastian Andrzej Siewior static int powernv_cpuidle_cpu_online(unsigned int cpu)
1342c2e6ecfSDeepthi Dharwar {
13510fcca9dSSebastian Andrzej Siewior 	struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
1362c2e6ecfSDeepthi Dharwar 
1372c2e6ecfSDeepthi Dharwar 	if (dev && cpuidle_get_driver()) {
1382c2e6ecfSDeepthi Dharwar 		cpuidle_pause_and_lock();
1392c2e6ecfSDeepthi Dharwar 		cpuidle_enable_device(dev);
1402c2e6ecfSDeepthi Dharwar 		cpuidle_resume_and_unlock();
14110fcca9dSSebastian Andrzej Siewior 	}
14210fcca9dSSebastian Andrzej Siewior 	return 0;
14310fcca9dSSebastian Andrzej Siewior }
1442c2e6ecfSDeepthi Dharwar 
14510fcca9dSSebastian Andrzej Siewior static int powernv_cpuidle_cpu_dead(unsigned int cpu)
14610fcca9dSSebastian Andrzej Siewior {
14710fcca9dSSebastian Andrzej Siewior 	struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
14810fcca9dSSebastian Andrzej Siewior 
14910fcca9dSSebastian Andrzej Siewior 	if (dev && cpuidle_get_driver()) {
1502c2e6ecfSDeepthi Dharwar 		cpuidle_pause_and_lock();
1512c2e6ecfSDeepthi Dharwar 		cpuidle_disable_device(dev);
1522c2e6ecfSDeepthi Dharwar 		cpuidle_resume_and_unlock();
1532c2e6ecfSDeepthi Dharwar 	}
15410fcca9dSSebastian Andrzej Siewior 	return 0;
1552c2e6ecfSDeepthi Dharwar }
1562c2e6ecfSDeepthi Dharwar 
1572c2e6ecfSDeepthi Dharwar /*
1582c2e6ecfSDeepthi Dharwar  * powernv_cpuidle_driver_init()
1592c2e6ecfSDeepthi Dharwar  */
1602c2e6ecfSDeepthi Dharwar static int powernv_cpuidle_driver_init(void)
1612c2e6ecfSDeepthi Dharwar {
1622c2e6ecfSDeepthi Dharwar 	int idle_state;
1632c2e6ecfSDeepthi Dharwar 	struct cpuidle_driver *drv = &powernv_idle_driver;
1642c2e6ecfSDeepthi Dharwar 
1652c2e6ecfSDeepthi Dharwar 	drv->state_count = 0;
1662c2e6ecfSDeepthi Dharwar 
1672c2e6ecfSDeepthi Dharwar 	for (idle_state = 0; idle_state < max_idle_state; ++idle_state) {
1682c2e6ecfSDeepthi Dharwar 		/* Is the state not enabled? */
1692c2e6ecfSDeepthi Dharwar 		if (cpuidle_state_table[idle_state].enter == NULL)
1702c2e6ecfSDeepthi Dharwar 			continue;
1712c2e6ecfSDeepthi Dharwar 
1722c2e6ecfSDeepthi Dharwar 		drv->states[drv->state_count] =	/* structure copy */
1732c2e6ecfSDeepthi Dharwar 			cpuidle_state_table[idle_state];
1742c2e6ecfSDeepthi Dharwar 
1752c2e6ecfSDeepthi Dharwar 		drv->state_count += 1;
1762c2e6ecfSDeepthi Dharwar 	}
1772c2e6ecfSDeepthi Dharwar 
178293d264fSVaidyanathan Srinivasan 	/*
179293d264fSVaidyanathan Srinivasan 	 * On the PowerNV platform cpu_present may be less than cpu_possible in
180293d264fSVaidyanathan Srinivasan 	 * cases when firmware detects the CPU, but it is not available to the
181293d264fSVaidyanathan Srinivasan 	 * OS.  If CONFIG_HOTPLUG_CPU=n, then such CPUs are not hotplugable at
182293d264fSVaidyanathan Srinivasan 	 * run time and hence cpu_devices are not created for those CPUs by the
183293d264fSVaidyanathan Srinivasan 	 * generic topology_init().
184293d264fSVaidyanathan Srinivasan 	 *
185293d264fSVaidyanathan Srinivasan 	 * drv->cpumask defaults to cpu_possible_mask in
186293d264fSVaidyanathan Srinivasan 	 * __cpuidle_driver_init().  This breaks cpuidle on PowerNV where
187293d264fSVaidyanathan Srinivasan 	 * cpu_devices are not created for CPUs in cpu_possible_mask that
188293d264fSVaidyanathan Srinivasan 	 * cannot be hot-added later at run time.
189293d264fSVaidyanathan Srinivasan 	 *
190293d264fSVaidyanathan Srinivasan 	 * Trying cpuidle_register_device() on a CPU without a cpu_device is
191293d264fSVaidyanathan Srinivasan 	 * incorrect, so pass a correct CPU mask to the generic cpuidle driver.
192293d264fSVaidyanathan Srinivasan 	 */
193293d264fSVaidyanathan Srinivasan 
194293d264fSVaidyanathan Srinivasan 	drv->cpumask = (struct cpumask *)cpu_present_mask;
195293d264fSVaidyanathan Srinivasan 
1962c2e6ecfSDeepthi Dharwar 	return 0;
1972c2e6ecfSDeepthi Dharwar }
1982c2e6ecfSDeepthi Dharwar 
1999e9fc6f0SGautham R. Shenoy static inline void add_powernv_state(int index, const char *name,
2009e9fc6f0SGautham R. Shenoy 				     unsigned int flags,
2019e9fc6f0SGautham R. Shenoy 				     int (*idle_fn)(struct cpuidle_device *,
2029e9fc6f0SGautham R. Shenoy 						    struct cpuidle_driver *,
2039e9fc6f0SGautham R. Shenoy 						    int),
2049e9fc6f0SGautham R. Shenoy 				     unsigned int target_residency,
2059e9fc6f0SGautham R. Shenoy 				     unsigned int exit_latency,
20609206b60SGautham R. Shenoy 				     u64 psscr_val, u64 psscr_mask)
2079e9fc6f0SGautham R. Shenoy {
2089e9fc6f0SGautham R. Shenoy 	strlcpy(powernv_states[index].name, name, CPUIDLE_NAME_LEN);
2099e9fc6f0SGautham R. Shenoy 	strlcpy(powernv_states[index].desc, name, CPUIDLE_NAME_LEN);
2109e9fc6f0SGautham R. Shenoy 	powernv_states[index].flags = flags;
2119e9fc6f0SGautham R. Shenoy 	powernv_states[index].target_residency = target_residency;
2129e9fc6f0SGautham R. Shenoy 	powernv_states[index].exit_latency = exit_latency;
2139e9fc6f0SGautham R. Shenoy 	powernv_states[index].enter = idle_fn;
21409206b60SGautham R. Shenoy 	stop_psscr_table[index].val = psscr_val;
21509206b60SGautham R. Shenoy 	stop_psscr_table[index].mask = psscr_mask;
2169e9fc6f0SGautham R. Shenoy }
2179e9fc6f0SGautham R. Shenoy 
2180888839cSPreeti U Murthy static int powernv_add_idle_states(void)
2190888839cSPreeti U Murthy {
2200888839cSPreeti U Murthy 	struct device_node *power_mgt;
2210888839cSPreeti U Murthy 	int nr_idle_states = 1; /* Snooze */
2220888839cSPreeti U Murthy 	int dt_idle_states;
223957efcedSShreyas B. Prabhu 	u32 latency_ns[CPUIDLE_STATE_MAX];
224957efcedSShreyas B. Prabhu 	u32 residency_ns[CPUIDLE_STATE_MAX];
225957efcedSShreyas B. Prabhu 	u32 flags[CPUIDLE_STATE_MAX];
2263005c597SShreyas B. Prabhu 	u64 psscr_val[CPUIDLE_STATE_MAX];
22709206b60SGautham R. Shenoy 	u64 psscr_mask[CPUIDLE_STATE_MAX];
2283005c597SShreyas B. Prabhu 	const char *names[CPUIDLE_STATE_MAX];
22909206b60SGautham R. Shenoy 	u32 has_stop_states = 0;
23092c83ff5SPreeti U Murthy 	int i, rc;
2310888839cSPreeti U Murthy 
2320888839cSPreeti U Murthy 	/* Currently we have snooze statically defined */
2330888839cSPreeti U Murthy 
2340888839cSPreeti U Murthy 	power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
2350888839cSPreeti U Murthy 	if (!power_mgt) {
2360888839cSPreeti U Murthy 		pr_warn("opal: PowerMgmt Node not found\n");
23792c83ff5SPreeti U Murthy 		goto out;
2380888839cSPreeti U Murthy 	}
2390888839cSPreeti U Murthy 
24070734a78SPreeti U Murthy 	/* Read values of any property to determine the num of idle states */
24170734a78SPreeti U Murthy 	dt_idle_states = of_property_count_u32_elems(power_mgt, "ibm,cpu-idle-state-flags");
24270734a78SPreeti U Murthy 	if (dt_idle_states < 0) {
24370734a78SPreeti U Murthy 		pr_warn("cpuidle-powernv: no idle states found in the DT\n");
24492c83ff5SPreeti U Murthy 		goto out;
24574aa51b5SPreeti U. Murthy 	}
24674aa51b5SPreeti U. Murthy 
247957efcedSShreyas B. Prabhu 	/*
248957efcedSShreyas B. Prabhu 	 * Since snooze is used as first idle state, max idle states allowed is
249957efcedSShreyas B. Prabhu 	 * CPUIDLE_STATE_MAX -1
250957efcedSShreyas B. Prabhu 	 */
251957efcedSShreyas B. Prabhu 	if (dt_idle_states > CPUIDLE_STATE_MAX - 1) {
252957efcedSShreyas B. Prabhu 		pr_warn("cpuidle-powernv: discovered idle states more than allowed");
253957efcedSShreyas B. Prabhu 		dt_idle_states = CPUIDLE_STATE_MAX - 1;
254957efcedSShreyas B. Prabhu 	}
255957efcedSShreyas B. Prabhu 
25670734a78SPreeti U Murthy 	if (of_property_read_u32_array(power_mgt,
25770734a78SPreeti U Murthy 			"ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
25870734a78SPreeti U Murthy 		pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n");
259957efcedSShreyas B. Prabhu 		goto out;
26070734a78SPreeti U Murthy 	}
2610888839cSPreeti U Murthy 
262957efcedSShreyas B. Prabhu 	if (of_property_read_u32_array(power_mgt,
263957efcedSShreyas B. Prabhu 		"ibm,cpu-idle-state-latencies-ns", latency_ns,
264957efcedSShreyas B. Prabhu 		dt_idle_states)) {
26592c83ff5SPreeti U Murthy 		pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n");
266957efcedSShreyas B. Prabhu 		goto out;
26792c83ff5SPreeti U Murthy 	}
2683005c597SShreyas B. Prabhu 	if (of_property_read_string_array(power_mgt,
2693005c597SShreyas B. Prabhu 		"ibm,cpu-idle-state-names", names, dt_idle_states) < 0) {
2703005c597SShreyas B. Prabhu 		pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n");
2713005c597SShreyas B. Prabhu 		goto out;
2723005c597SShreyas B. Prabhu 	}
2733005c597SShreyas B. Prabhu 
2743005c597SShreyas B. Prabhu 	/*
2753005c597SShreyas B. Prabhu 	 * If the idle states use stop instruction, probe for psscr values
27609206b60SGautham R. Shenoy 	 * and psscr mask which are necessary to specify required stop level.
2773005c597SShreyas B. Prabhu 	 */
27809206b60SGautham R. Shenoy 	has_stop_states = (flags[0] &
27909206b60SGautham R. Shenoy 			   (OPAL_PM_STOP_INST_FAST | OPAL_PM_STOP_INST_DEEP));
28009206b60SGautham R. Shenoy 	if (has_stop_states) {
2813005c597SShreyas B. Prabhu 		if (of_property_read_u64_array(power_mgt,
2823005c597SShreyas B. Prabhu 		    "ibm,cpu-idle-state-psscr", psscr_val, dt_idle_states)) {
28309206b60SGautham R. Shenoy 			pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr in DT\n");
2843005c597SShreyas B. Prabhu 			goto out;
2853005c597SShreyas B. Prabhu 		}
28692c83ff5SPreeti U Murthy 
28709206b60SGautham R. Shenoy 		if (of_property_read_u64_array(power_mgt,
28809206b60SGautham R. Shenoy 					       "ibm,cpu-idle-state-psscr-mask",
28909206b60SGautham R. Shenoy 						psscr_mask, dt_idle_states)) {
29009206b60SGautham R. Shenoy 			pr_warn("cpuidle-powernv:Missing ibm,cpu-idle-state-psscr-mask in DT\n");
29109206b60SGautham R. Shenoy 			goto out;
29209206b60SGautham R. Shenoy 		}
29309206b60SGautham R. Shenoy 	}
29409206b60SGautham R. Shenoy 
29592c83ff5SPreeti U Murthy 	rc = of_property_read_u32_array(power_mgt,
29692c83ff5SPreeti U Murthy 		"ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);
29792c83ff5SPreeti U Murthy 
2980888839cSPreeti U Murthy 	for (i = 0; i < dt_idle_states; i++) {
2999e9fc6f0SGautham R. Shenoy 		unsigned int exit_latency, target_residency;
3003005c597SShreyas B. Prabhu 		/*
3013005c597SShreyas B. Prabhu 		 * If an idle state has exit latency beyond
3023005c597SShreyas B. Prabhu 		 * POWERNV_THRESHOLD_LATENCY_NS then don't use it
3033005c597SShreyas B. Prabhu 		 * in cpu-idle.
3043005c597SShreyas B. Prabhu 		 */
3053005c597SShreyas B. Prabhu 		if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS)
3063005c597SShreyas B. Prabhu 			continue;
3079e9fc6f0SGautham R. Shenoy 		/*
3089e9fc6f0SGautham R. Shenoy 		 * Firmware passes residency and latency values in ns.
3099e9fc6f0SGautham R. Shenoy 		 * cpuidle expects it in us.
3109e9fc6f0SGautham R. Shenoy 		 */
3119e9fc6f0SGautham R. Shenoy 		exit_latency = latency_ns[i] / 1000;
3129e9fc6f0SGautham R. Shenoy 		if (!rc)
3139e9fc6f0SGautham R. Shenoy 			target_residency = residency_ns[i] / 1000;
3149e9fc6f0SGautham R. Shenoy 		else
3159e9fc6f0SGautham R. Shenoy 			target_residency = 0;
3160888839cSPreeti U Murthy 
31709206b60SGautham R. Shenoy 		if (has_stop_states) {
31809206b60SGautham R. Shenoy 			int err = validate_psscr_val_mask(&psscr_val[i],
31909206b60SGautham R. Shenoy 							  &psscr_mask[i],
32009206b60SGautham R. Shenoy 							  flags[i]);
32109206b60SGautham R. Shenoy 			if (err) {
32209206b60SGautham R. Shenoy 				report_invalid_psscr_val(psscr_val[i], err);
32309206b60SGautham R. Shenoy 				continue;
32409206b60SGautham R. Shenoy 			}
32509206b60SGautham R. Shenoy 		}
32609206b60SGautham R. Shenoy 
32792c83ff5SPreeti U Murthy 		/*
3289e9fc6f0SGautham R. Shenoy 		 * For nap and fastsleep, use default target_residency
3299e9fc6f0SGautham R. Shenoy 		 * values if f/w does not expose it.
33074aa51b5SPreeti U. Murthy 		 */
33170734a78SPreeti U Murthy 		if (flags[i] & OPAL_PM_NAP_ENABLED) {
3329e9fc6f0SGautham R. Shenoy 			if (!rc)
3339e9fc6f0SGautham R. Shenoy 				target_residency = 100;
3340888839cSPreeti U Murthy 			/* Add NAP state */
3359e9fc6f0SGautham R. Shenoy 			add_powernv_state(nr_idle_states, "Nap",
3369e9fc6f0SGautham R. Shenoy 					  CPUIDLE_FLAG_NONE, nap_loop,
33709206b60SGautham R. Shenoy 					  target_residency, exit_latency, 0, 0);
3383005c597SShreyas B. Prabhu 		} else if ((flags[i] & OPAL_PM_STOP_INST_FAST) &&
3393005c597SShreyas B. Prabhu 				!(flags[i] & OPAL_PM_TIMEBASE_STOP)) {
3409e9fc6f0SGautham R. Shenoy 			add_powernv_state(nr_idle_states, names[i],
3419e9fc6f0SGautham R. Shenoy 					  CPUIDLE_FLAG_NONE, stop_loop,
3429e9fc6f0SGautham R. Shenoy 					  target_residency, exit_latency,
34309206b60SGautham R. Shenoy 					  psscr_val[i], psscr_mask[i]);
344cc5a2f7bSpreeti 		}
345cc5a2f7bSpreeti 
346cc5a2f7bSpreeti 		/*
347cc5a2f7bSpreeti 		 * All cpuidle states with CPUIDLE_FLAG_TIMER_STOP set must come
348cc5a2f7bSpreeti 		 * within this config dependency check.
349cc5a2f7bSpreeti 		 */
350cc5a2f7bSpreeti #ifdef CONFIG_TICK_ONESHOT
351cc5a2f7bSpreeti 		if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
35270734a78SPreeti U Murthy 			flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
3539e9fc6f0SGautham R. Shenoy 			if (!rc)
3549e9fc6f0SGautham R. Shenoy 				target_residency = 300000;
3550888839cSPreeti U Murthy 			/* Add FASTSLEEP state */
3569e9fc6f0SGautham R. Shenoy 			add_powernv_state(nr_idle_states, "FastSleep",
3579e9fc6f0SGautham R. Shenoy 					  CPUIDLE_FLAG_TIMER_STOP,
3589e9fc6f0SGautham R. Shenoy 					  fastsleep_loop,
35909206b60SGautham R. Shenoy 					  target_residency, exit_latency, 0, 0);
3603005c597SShreyas B. Prabhu 		} else if ((flags[i] & OPAL_PM_STOP_INST_DEEP) &&
3613005c597SShreyas B. Prabhu 				(flags[i] & OPAL_PM_TIMEBASE_STOP)) {
3629e9fc6f0SGautham R. Shenoy 			add_powernv_state(nr_idle_states, names[i],
3639e9fc6f0SGautham R. Shenoy 					  CPUIDLE_FLAG_TIMER_STOP, stop_loop,
3649e9fc6f0SGautham R. Shenoy 					  target_residency, exit_latency,
36509206b60SGautham R. Shenoy 					  psscr_val[i], psscr_mask[i]);
3660888839cSPreeti U Murthy 		}
367cc5a2f7bSpreeti #endif
36892c83ff5SPreeti U Murthy 		nr_idle_states++;
36992c83ff5SPreeti U Murthy 	}
37092c83ff5SPreeti U Murthy out:
3710888839cSPreeti U Murthy 	return nr_idle_states;
3720888839cSPreeti U Murthy }
3730888839cSPreeti U Murthy 
3742c2e6ecfSDeepthi Dharwar /*
3752c2e6ecfSDeepthi Dharwar  * powernv_idle_probe()
3762c2e6ecfSDeepthi Dharwar  * Choose state table for shared versus dedicated partition
3772c2e6ecfSDeepthi Dharwar  */
3782c2e6ecfSDeepthi Dharwar static int powernv_idle_probe(void)
3792c2e6ecfSDeepthi Dharwar {
3802c2e6ecfSDeepthi Dharwar 	if (cpuidle_disable != IDLE_NO_OVERRIDE)
3812c2e6ecfSDeepthi Dharwar 		return -ENODEV;
3822c2e6ecfSDeepthi Dharwar 
383e4d54f71SStewart Smith 	if (firmware_has_feature(FW_FEATURE_OPAL)) {
3842c2e6ecfSDeepthi Dharwar 		cpuidle_state_table = powernv_states;
3850888839cSPreeti U Murthy 		/* Device tree can indicate more idle states */
3860888839cSPreeti U Murthy 		max_idle_state = powernv_add_idle_states();
38778eaa10fSShilpasri G Bhat 		if (max_idle_state > 1) {
38878eaa10fSShilpasri G Bhat 			snooze_timeout_en = true;
38978eaa10fSShilpasri G Bhat 			snooze_timeout = powernv_states[1].target_residency *
39078eaa10fSShilpasri G Bhat 					 tb_ticks_per_usec;
39178eaa10fSShilpasri G Bhat 		}
3922c2e6ecfSDeepthi Dharwar  	} else
3932c2e6ecfSDeepthi Dharwar  		return -ENODEV;
3942c2e6ecfSDeepthi Dharwar 
3952c2e6ecfSDeepthi Dharwar 	return 0;
3962c2e6ecfSDeepthi Dharwar }
3972c2e6ecfSDeepthi Dharwar 
3982c2e6ecfSDeepthi Dharwar static int __init powernv_processor_idle_init(void)
3992c2e6ecfSDeepthi Dharwar {
4002c2e6ecfSDeepthi Dharwar 	int retval;
4012c2e6ecfSDeepthi Dharwar 
4022c2e6ecfSDeepthi Dharwar 	retval = powernv_idle_probe();
4032c2e6ecfSDeepthi Dharwar 	if (retval)
4042c2e6ecfSDeepthi Dharwar 		return retval;
4052c2e6ecfSDeepthi Dharwar 
4062c2e6ecfSDeepthi Dharwar 	powernv_cpuidle_driver_init();
4072c2e6ecfSDeepthi Dharwar 	retval = cpuidle_register(&powernv_idle_driver, NULL);
4082c2e6ecfSDeepthi Dharwar 	if (retval) {
4092c2e6ecfSDeepthi Dharwar 		printk(KERN_DEBUG "Registration of powernv driver failed.\n");
4102c2e6ecfSDeepthi Dharwar 		return retval;
4112c2e6ecfSDeepthi Dharwar 	}
4122c2e6ecfSDeepthi Dharwar 
41310fcca9dSSebastian Andrzej Siewior 	retval = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
41410fcca9dSSebastian Andrzej Siewior 					   "cpuidle/powernv:online",
41510fcca9dSSebastian Andrzej Siewior 					   powernv_cpuidle_cpu_online, NULL);
41610fcca9dSSebastian Andrzej Siewior 	WARN_ON(retval < 0);
41710fcca9dSSebastian Andrzej Siewior 	retval = cpuhp_setup_state_nocalls(CPUHP_CPUIDLE_DEAD,
41810fcca9dSSebastian Andrzej Siewior 					   "cpuidle/powernv:dead", NULL,
41910fcca9dSSebastian Andrzej Siewior 					   powernv_cpuidle_cpu_dead);
42010fcca9dSSebastian Andrzej Siewior 	WARN_ON(retval < 0);
4212c2e6ecfSDeepthi Dharwar 	printk(KERN_DEBUG "powernv_idle_driver registered\n");
4222c2e6ecfSDeepthi Dharwar 	return 0;
4232c2e6ecfSDeepthi Dharwar }
4242c2e6ecfSDeepthi Dharwar 
4252c2e6ecfSDeepthi Dharwar device_initcall(powernv_processor_idle_init);
426