xref: /openbmc/linux/drivers/idle/intel_idle.c (revision bf5835bc)
1a61127c2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
226717172SLen Brown /*
326717172SLen Brown  * intel_idle.c - native hardware idle loop for modern Intel processors
426717172SLen Brown  *
5317e5ec3SRafael J. Wysocki  * Copyright (c) 2013 - 2020, Intel Corporation.
626717172SLen Brown  * Len Brown <len.brown@intel.com>
7317e5ec3SRafael J. Wysocki  * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
826717172SLen Brown  */
926717172SLen Brown 
1026717172SLen Brown /*
118bb2e2a8SAlexander Monakov  * intel_idle is a cpuidle driver that loads on all Intel CPUs with MWAIT
1226717172SLen Brown  * in lieu of the legacy ACPI processor_idle driver.  The intent is to
1326717172SLen Brown  * make Linux more efficient on these processors, as intel_idle knows
1426717172SLen Brown  * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
1526717172SLen Brown  */
1626717172SLen Brown 
1726717172SLen Brown /*
1826717172SLen Brown  * Design Assumptions
1926717172SLen Brown  *
2026717172SLen Brown  * All CPUs have same idle states as boot CPU
2126717172SLen Brown  *
2226717172SLen Brown  * Chipset BM_STS (bus master status) bit is a NOP
238bb2e2a8SAlexander Monakov  *	for preventing entry into deep C-states
248bb2e2a8SAlexander Monakov  *
258bb2e2a8SAlexander Monakov  * CPU will flush caches as needed when entering a C-state via MWAIT
268bb2e2a8SAlexander Monakov  *	(in contrast to entering ACPI C3, in which case the WBINVD
278bb2e2a8SAlexander Monakov  *	instruction needs to be executed to flush the caches)
2826717172SLen Brown  */
2926717172SLen Brown 
3026717172SLen Brown /*
3126717172SLen Brown  * Known limitations
3226717172SLen Brown  *
3326717172SLen Brown  * ACPI has a .suspend hack to turn off deep c-statees during suspend
3426717172SLen Brown  * to avoid complications with the lapic timer workaround.
3526717172SLen Brown  * Have not seen issues with suspend, but may need same workaround here.
3626717172SLen Brown  *
3726717172SLen Brown  */
3826717172SLen Brown 
3926717172SLen Brown /* un-comment DEBUG to enable pr_debug() statements */
40651bc581STom Rix /* #define DEBUG */
4126717172SLen Brown 
42654d08a4SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
43654d08a4SJoe Perches 
4418734958SRafael J. Wysocki #include <linux/acpi.h>
4526717172SLen Brown #include <linux/kernel.h>
4626717172SLen Brown #include <linux/cpuidle.h>
4776962caaSThomas Gleixner #include <linux/tick.h>
4826717172SLen Brown #include <trace/events/power.h>
4926717172SLen Brown #include <linux/sched.h>
50*bf5835bcSPeter Zijlstra #include <linux/sched/smt.h>
512a2d31c8SShaohua Li #include <linux/notifier.h>
522a2d31c8SShaohua Li #include <linux/cpu.h>
5302c4fae9SPaul Gortmaker #include <linux/moduleparam.h>
54b66b8b9aSAndi Kleen #include <asm/cpu_device_id.h>
55db73c5a8SDave Hansen #include <asm/intel-family.h>
56*bf5835bcSPeter Zijlstra #include <asm/nospec-branch.h>
57bc83ccccSH. Peter Anvin #include <asm/mwait.h>
5814796fcaSLen Brown #include <asm/msr.h>
5926717172SLen Brown 
60317e5ec3SRafael J. Wysocki #define INTEL_IDLE_VERSION "0.5.1"
6126717172SLen Brown 
6226717172SLen Brown static struct cpuidle_driver intel_idle_driver = {
6326717172SLen Brown 	.name = "intel_idle",
6426717172SLen Brown 	.owner = THIS_MODULE,
6526717172SLen Brown };
6626717172SLen Brown /* intel_idle.max_cstate=0 disables driver */
67137ecc77SLen Brown static int max_cstate = CPUIDLE_STATE_MAX - 1;
684dcb78eeSRafael J. Wysocki static unsigned int disabled_states_mask;
69da0e58c0SArtem Bityutskiy static unsigned int preferred_states_mask;
7026717172SLen Brown 
716eb0443aSRafael J. Wysocki static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
727f843dd7SRafael J. Wysocki 
737f843dd7SRafael J. Wysocki static unsigned long auto_demotion_disable_flags;
7439c184a6SArtem Bityutskiy 
7539c184a6SArtem Bityutskiy static enum {
7639c184a6SArtem Bityutskiy 	C1E_PROMOTION_PRESERVE,
7739c184a6SArtem Bityutskiy 	C1E_PROMOTION_ENABLE,
7839c184a6SArtem Bityutskiy 	C1E_PROMOTION_DISABLE
7939c184a6SArtem Bityutskiy } c1e_promotion = C1E_PROMOTION_PRESERVE;
807f843dd7SRafael J. Wysocki 
81b66b8b9aSAndi Kleen struct idle_cpu {
82b66b8b9aSAndi Kleen 	struct cpuidle_state *state_table;
8326717172SLen Brown 
8426717172SLen Brown 	/*
8514796fcaSLen Brown 	 * Hardware C-state auto-demotion may not always be optimal.
8614796fcaSLen Brown 	 * Indicate which enable bits to clear here.
8714796fcaSLen Brown 	 */
88b66b8b9aSAndi Kleen 	unsigned long auto_demotion_disable_flags;
898c058d53SLen Brown 	bool byt_auto_demotion_disable_flag;
9032e95180SLen Brown 	bool disable_promotion_to_c1e;
91bff8e60aSRafael J. Wysocki 	bool use_acpi;
92b66b8b9aSAndi Kleen };
93b66b8b9aSAndi Kleen 
947f843dd7SRafael J. Wysocki static const struct idle_cpu *icpu __initdata;
957f843dd7SRafael J. Wysocki static struct cpuidle_state *cpuidle_state_table __initdata;
9614796fcaSLen Brown 
976eb0443aSRafael J. Wysocki static unsigned int mwait_substates __initdata;
986eb0443aSRafael J. Wysocki 
9914796fcaSLen Brown /*
100c227233aSArtem Bityutskiy  * Enable interrupts before entering the C-state. On some platforms and for
101c227233aSArtem Bityutskiy  * some C-states, this may measurably decrease interrupt latency.
102c227233aSArtem Bityutskiy  */
103c227233aSArtem Bityutskiy #define CPUIDLE_FLAG_IRQ_ENABLE		BIT(14)
104c227233aSArtem Bityutskiy 
105c227233aSArtem Bityutskiy /*
106bff8e60aSRafael J. Wysocki  * Enable this state by default even if the ACPI _CST does not list it.
107bff8e60aSRafael J. Wysocki  */
108bff8e60aSRafael J. Wysocki #define CPUIDLE_FLAG_ALWAYS_ENABLE	BIT(15)
109bff8e60aSRafael J. Wysocki 
110bff8e60aSRafael J. Wysocki /*
111*bf5835bcSPeter Zijlstra  * Disable IBRS across idle (when KERNEL_IBRS), is exclusive vs IRQ_ENABLE
112*bf5835bcSPeter Zijlstra  * above.
113*bf5835bcSPeter Zijlstra  */
114*bf5835bcSPeter Zijlstra #define CPUIDLE_FLAG_IBRS		BIT(16)
115*bf5835bcSPeter Zijlstra 
116*bf5835bcSPeter Zijlstra /*
117b1beab48SLen Brown  * MWAIT takes an 8-bit "hint" in EAX "suggesting"
118b1beab48SLen Brown  * the C-state (top nibble) and sub-state (bottom nibble)
119b1beab48SLen Brown  * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc.
120b1beab48SLen Brown  *
121b1beab48SLen Brown  * We store the hint at the top of our "flags" for each state.
122b1beab48SLen Brown  */
123b1beab48SLen Brown #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
124b1beab48SLen Brown #define MWAIT2flg(eax) ((eax & 0xFF) << 24)
125b1beab48SLen Brown 
12632d4fd57SPeter Zijlstra static __always_inline int __intel_idle(struct cpuidle_device *dev,
12732d4fd57SPeter Zijlstra 					struct cpuidle_driver *drv, int index)
12832d4fd57SPeter Zijlstra {
12932d4fd57SPeter Zijlstra 	struct cpuidle_state *state = &drv->states[index];
13032d4fd57SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
13132d4fd57SPeter Zijlstra 	unsigned long ecx = 1; /* break on interrupt flag */
13232d4fd57SPeter Zijlstra 
13332d4fd57SPeter Zijlstra 	mwait_idle_with_hints(eax, ecx);
13432d4fd57SPeter Zijlstra 
13532d4fd57SPeter Zijlstra 	return index;
13632d4fd57SPeter Zijlstra }
13732d4fd57SPeter Zijlstra 
13830a996fbSRafael J. Wysocki /**
13930a996fbSRafael J. Wysocki  * intel_idle - Ask the processor to enter the given idle state.
14030a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
14130a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
14230a996fbSRafael J. Wysocki  * @index: Target idle state index.
14330a996fbSRafael J. Wysocki  *
14430a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
14530a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
14630a996fbSRafael J. Wysocki  *
14730a996fbSRafael J. Wysocki  * If the local APIC timer is not known to be reliable in the target idle state,
14830a996fbSRafael J. Wysocki  * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
14930a996fbSRafael J. Wysocki  *
15030a996fbSRafael J. Wysocki  * Must be called under local_irq_disable().
15130a996fbSRafael J. Wysocki  */
15230a996fbSRafael J. Wysocki static __cpuidle int intel_idle(struct cpuidle_device *dev,
15330a996fbSRafael J. Wysocki 				struct cpuidle_driver *drv, int index)
15430a996fbSRafael J. Wysocki {
15532d4fd57SPeter Zijlstra 	return __intel_idle(dev, drv, index);
15632d4fd57SPeter Zijlstra }
15730a996fbSRafael J. Wysocki 
15832d4fd57SPeter Zijlstra static __cpuidle int intel_idle_irq(struct cpuidle_device *dev,
15932d4fd57SPeter Zijlstra 				    struct cpuidle_driver *drv, int index)
16032d4fd57SPeter Zijlstra {
16132d4fd57SPeter Zijlstra 	int ret;
162c227233aSArtem Bityutskiy 
16332d4fd57SPeter Zijlstra 	raw_local_irq_enable();
16432d4fd57SPeter Zijlstra 	ret = __intel_idle(dev, drv, index);
16532d4fd57SPeter Zijlstra 	raw_local_irq_disable();
16630a996fbSRafael J. Wysocki 
16732d4fd57SPeter Zijlstra 	return ret;
16830a996fbSRafael J. Wysocki }
16930a996fbSRafael J. Wysocki 
170*bf5835bcSPeter Zijlstra static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
171*bf5835bcSPeter Zijlstra 				     struct cpuidle_driver *drv, int index)
172*bf5835bcSPeter Zijlstra {
173*bf5835bcSPeter Zijlstra 	bool smt_active = sched_smt_active();
174*bf5835bcSPeter Zijlstra 	u64 spec_ctrl = spec_ctrl_current();
175*bf5835bcSPeter Zijlstra 	int ret;
176*bf5835bcSPeter Zijlstra 
177*bf5835bcSPeter Zijlstra 	if (smt_active)
178*bf5835bcSPeter Zijlstra 		wrmsrl(MSR_IA32_SPEC_CTRL, 0);
179*bf5835bcSPeter Zijlstra 
180*bf5835bcSPeter Zijlstra 	ret = __intel_idle(dev, drv, index);
181*bf5835bcSPeter Zijlstra 
182*bf5835bcSPeter Zijlstra 	if (smt_active)
183*bf5835bcSPeter Zijlstra 		wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl);
184*bf5835bcSPeter Zijlstra 
185*bf5835bcSPeter Zijlstra 	return ret;
186*bf5835bcSPeter Zijlstra }
187*bf5835bcSPeter Zijlstra 
18830a996fbSRafael J. Wysocki /**
18930a996fbSRafael J. Wysocki  * intel_idle_s2idle - Ask the processor to enter the given idle state.
19030a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
19130a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
19230a996fbSRafael J. Wysocki  * @index: Target idle state index.
19330a996fbSRafael J. Wysocki  *
19430a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
19530a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
19630a996fbSRafael J. Wysocki  *
19730a996fbSRafael J. Wysocki  * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
19830a996fbSRafael J. Wysocki  * scheduler tick and suspended scheduler clock on the target CPU.
19930a996fbSRafael J. Wysocki  */
200efe97112SNeal Liu static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
20130a996fbSRafael J. Wysocki 				       struct cpuidle_driver *drv, int index)
20230a996fbSRafael J. Wysocki {
20330a996fbSRafael J. Wysocki 	unsigned long eax = flg2MWAIT(drv->states[index].flags);
20430a996fbSRafael J. Wysocki 	unsigned long ecx = 1; /* break on interrupt flag */
20530a996fbSRafael J. Wysocki 
20630a996fbSRafael J. Wysocki 	mwait_idle_with_hints(eax, ecx);
207efe97112SNeal Liu 
208efe97112SNeal Liu 	return 0;
20930a996fbSRafael J. Wysocki }
21030a996fbSRafael J. Wysocki 
211b1beab48SLen Brown /*
21226717172SLen Brown  * States are indexed by the cstate number,
21326717172SLen Brown  * which is also the index into the MWAIT hint array.
21426717172SLen Brown  * Thus C0 is a dummy.
21526717172SLen Brown  */
216ab1a8522SRafael J. Wysocki static struct cpuidle_state nehalem_cstates[] __initdata = {
217e022e7ebSLen Brown 	{
218de09cdd0SLen Brown 		.name = "C1",
21926717172SLen Brown 		.desc = "MWAIT 0x00",
220b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
22126717172SLen Brown 		.exit_latency = 3,
22226717172SLen Brown 		.target_residency = 6,
2235fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
22428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
225e022e7ebSLen Brown 	{
226de09cdd0SLen Brown 		.name = "C1E",
22732e95180SLen Brown 		.desc = "MWAIT 0x01",
228e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
22932e95180SLen Brown 		.exit_latency = 10,
23032e95180SLen Brown 		.target_residency = 20,
2315fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
23228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
23332e95180SLen Brown 	{
234de09cdd0SLen Brown 		.name = "C3",
23526717172SLen Brown 		.desc = "MWAIT 0x10",
236b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
23726717172SLen Brown 		.exit_latency = 20,
23826717172SLen Brown 		.target_residency = 80,
2395fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
24028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
241e022e7ebSLen Brown 	{
242de09cdd0SLen Brown 		.name = "C6",
24326717172SLen Brown 		.desc = "MWAIT 0x20",
244b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
24526717172SLen Brown 		.exit_latency = 200,
24626717172SLen Brown 		.target_residency = 800,
2475fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
24828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
249e022e7ebSLen Brown 	{
250e022e7ebSLen Brown 		.enter = NULL }
25126717172SLen Brown };
25226717172SLen Brown 
253ab1a8522SRafael J. Wysocki static struct cpuidle_state snb_cstates[] __initdata = {
254e022e7ebSLen Brown 	{
255de09cdd0SLen Brown 		.name = "C1",
256d13780d4SLen Brown 		.desc = "MWAIT 0x00",
257b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
25832e95180SLen Brown 		.exit_latency = 2,
25932e95180SLen Brown 		.target_residency = 2,
2605fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
26128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
26232e95180SLen Brown 	{
263de09cdd0SLen Brown 		.name = "C1E",
26432e95180SLen Brown 		.desc = "MWAIT 0x01",
265e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
26632e95180SLen Brown 		.exit_latency = 10,
26732e95180SLen Brown 		.target_residency = 20,
2685fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
26928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
270e022e7ebSLen Brown 	{
271de09cdd0SLen Brown 		.name = "C3",
272d13780d4SLen Brown 		.desc = "MWAIT 0x10",
273b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
274d13780d4SLen Brown 		.exit_latency = 80,
275ddbd550dSLen Brown 		.target_residency = 211,
2765fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
27728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
278e022e7ebSLen Brown 	{
279de09cdd0SLen Brown 		.name = "C6",
280d13780d4SLen Brown 		.desc = "MWAIT 0x20",
281b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
282d13780d4SLen Brown 		.exit_latency = 104,
283ddbd550dSLen Brown 		.target_residency = 345,
2845fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
28528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
286e022e7ebSLen Brown 	{
287de09cdd0SLen Brown 		.name = "C7",
288d13780d4SLen Brown 		.desc = "MWAIT 0x30",
289b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
290d13780d4SLen Brown 		.exit_latency = 109,
291ddbd550dSLen Brown 		.target_residency = 345,
2925fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
29328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
294e022e7ebSLen Brown 	{
295e022e7ebSLen Brown 		.enter = NULL }
296d13780d4SLen Brown };
297d13780d4SLen Brown 
298ab1a8522SRafael J. Wysocki static struct cpuidle_state byt_cstates[] __initdata = {
299718987d6SLen Brown 	{
300de09cdd0SLen Brown 		.name = "C1",
301718987d6SLen Brown 		.desc = "MWAIT 0x00",
302b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
303718987d6SLen Brown 		.exit_latency = 1,
304718987d6SLen Brown 		.target_residency = 1,
3055fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
30628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
307718987d6SLen Brown 	{
308de09cdd0SLen Brown 		.name = "C6N",
309718987d6SLen Brown 		.desc = "MWAIT 0x58",
310b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
311d7ef7671SLen Brown 		.exit_latency = 300,
312718987d6SLen Brown 		.target_residency = 275,
3135fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
31428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
315718987d6SLen Brown 	{
316de09cdd0SLen Brown 		.name = "C6S",
317718987d6SLen Brown 		.desc = "MWAIT 0x52",
318b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
319d7ef7671SLen Brown 		.exit_latency = 500,
320718987d6SLen Brown 		.target_residency = 560,
3215fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
32228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
323718987d6SLen Brown 	{
324de09cdd0SLen Brown 		.name = "C7",
325718987d6SLen Brown 		.desc = "MWAIT 0x60",
326b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
327718987d6SLen Brown 		.exit_latency = 1200,
328d7ef7671SLen Brown 		.target_residency = 4000,
3295fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
33028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
331718987d6SLen Brown 	{
332de09cdd0SLen Brown 		.name = "C7S",
333718987d6SLen Brown 		.desc = "MWAIT 0x64",
334b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
335718987d6SLen Brown 		.exit_latency = 10000,
336718987d6SLen Brown 		.target_residency = 20000,
3375fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
33828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
339718987d6SLen Brown 	{
340718987d6SLen Brown 		.enter = NULL }
341718987d6SLen Brown };
342718987d6SLen Brown 
343ab1a8522SRafael J. Wysocki static struct cpuidle_state cht_cstates[] __initdata = {
344cab07a56SLen Brown 	{
345de09cdd0SLen Brown 		.name = "C1",
346cab07a56SLen Brown 		.desc = "MWAIT 0x00",
347cab07a56SLen Brown 		.flags = MWAIT2flg(0x00),
348cab07a56SLen Brown 		.exit_latency = 1,
349cab07a56SLen Brown 		.target_residency = 1,
350cab07a56SLen Brown 		.enter = &intel_idle,
35128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
352cab07a56SLen Brown 	{
353de09cdd0SLen Brown 		.name = "C6N",
354cab07a56SLen Brown 		.desc = "MWAIT 0x58",
355cab07a56SLen Brown 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
356cab07a56SLen Brown 		.exit_latency = 80,
357cab07a56SLen Brown 		.target_residency = 275,
358cab07a56SLen Brown 		.enter = &intel_idle,
35928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
360cab07a56SLen Brown 	{
361de09cdd0SLen Brown 		.name = "C6S",
362cab07a56SLen Brown 		.desc = "MWAIT 0x52",
363cab07a56SLen Brown 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
364cab07a56SLen Brown 		.exit_latency = 200,
365cab07a56SLen Brown 		.target_residency = 560,
366cab07a56SLen Brown 		.enter = &intel_idle,
36728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
368cab07a56SLen Brown 	{
369de09cdd0SLen Brown 		.name = "C7",
370cab07a56SLen Brown 		.desc = "MWAIT 0x60",
371cab07a56SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
372cab07a56SLen Brown 		.exit_latency = 1200,
373cab07a56SLen Brown 		.target_residency = 4000,
374cab07a56SLen Brown 		.enter = &intel_idle,
37528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
376cab07a56SLen Brown 	{
377de09cdd0SLen Brown 		.name = "C7S",
378cab07a56SLen Brown 		.desc = "MWAIT 0x64",
379cab07a56SLen Brown 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
380cab07a56SLen Brown 		.exit_latency = 10000,
381cab07a56SLen Brown 		.target_residency = 20000,
382cab07a56SLen Brown 		.enter = &intel_idle,
38328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
384cab07a56SLen Brown 	{
385cab07a56SLen Brown 		.enter = NULL }
386cab07a56SLen Brown };
387cab07a56SLen Brown 
388ab1a8522SRafael J. Wysocki static struct cpuidle_state ivb_cstates[] __initdata = {
389e022e7ebSLen Brown 	{
390de09cdd0SLen Brown 		.name = "C1",
3916edab08cSLen Brown 		.desc = "MWAIT 0x00",
392b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
3936edab08cSLen Brown 		.exit_latency = 1,
3946edab08cSLen Brown 		.target_residency = 1,
3955fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
39628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
397e022e7ebSLen Brown 	{
398de09cdd0SLen Brown 		.name = "C1E",
39932e95180SLen Brown 		.desc = "MWAIT 0x01",
400e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
40132e95180SLen Brown 		.exit_latency = 10,
40232e95180SLen Brown 		.target_residency = 20,
4035fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
40428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
40532e95180SLen Brown 	{
406de09cdd0SLen Brown 		.name = "C3",
4076edab08cSLen Brown 		.desc = "MWAIT 0x10",
408b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4096edab08cSLen Brown 		.exit_latency = 59,
4106edab08cSLen Brown 		.target_residency = 156,
4115fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
41228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
413e022e7ebSLen Brown 	{
414de09cdd0SLen Brown 		.name = "C6",
4156edab08cSLen Brown 		.desc = "MWAIT 0x20",
416b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4176edab08cSLen Brown 		.exit_latency = 80,
4186edab08cSLen Brown 		.target_residency = 300,
4195fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
42028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
421e022e7ebSLen Brown 	{
422de09cdd0SLen Brown 		.name = "C7",
4236edab08cSLen Brown 		.desc = "MWAIT 0x30",
424b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
4256edab08cSLen Brown 		.exit_latency = 87,
4266edab08cSLen Brown 		.target_residency = 300,
4275fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
42828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
429e022e7ebSLen Brown 	{
430e022e7ebSLen Brown 		.enter = NULL }
4316edab08cSLen Brown };
4326edab08cSLen Brown 
433ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates[] __initdata = {
4340138d8f0SLen Brown 	{
435de09cdd0SLen Brown 		.name = "C1",
4360138d8f0SLen Brown 		.desc = "MWAIT 0x00",
437b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4380138d8f0SLen Brown 		.exit_latency = 1,
4390138d8f0SLen Brown 		.target_residency = 1,
4405fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
44128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4420138d8f0SLen Brown 	{
443de09cdd0SLen Brown 		.name = "C1E",
4440138d8f0SLen Brown 		.desc = "MWAIT 0x01",
445e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
4460138d8f0SLen Brown 		.exit_latency = 10,
4470138d8f0SLen Brown 		.target_residency = 80,
4485fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
44928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4500138d8f0SLen Brown 	{
451de09cdd0SLen Brown 		.name = "C3",
4520138d8f0SLen Brown 		.desc = "MWAIT 0x10",
453b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4540138d8f0SLen Brown 		.exit_latency = 59,
4550138d8f0SLen Brown 		.target_residency = 156,
4565fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
45728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4580138d8f0SLen Brown 	{
459de09cdd0SLen Brown 		.name = "C6",
4600138d8f0SLen Brown 		.desc = "MWAIT 0x20",
461b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4620138d8f0SLen Brown 		.exit_latency = 82,
4630138d8f0SLen Brown 		.target_residency = 300,
4645fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
46528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4660138d8f0SLen Brown 	{
4670138d8f0SLen Brown 		.enter = NULL }
4680138d8f0SLen Brown };
4690138d8f0SLen Brown 
470ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_4s[] __initdata = {
4710138d8f0SLen Brown 	{
472de09cdd0SLen Brown 		.name = "C1",
4730138d8f0SLen Brown 		.desc = "MWAIT 0x00",
474b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4750138d8f0SLen Brown 		.exit_latency = 1,
4760138d8f0SLen Brown 		.target_residency = 1,
4775fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
47828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4790138d8f0SLen Brown 	{
480de09cdd0SLen Brown 		.name = "C1E",
4810138d8f0SLen Brown 		.desc = "MWAIT 0x01",
482e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
4830138d8f0SLen Brown 		.exit_latency = 10,
4840138d8f0SLen Brown 		.target_residency = 250,
4855fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
48628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4870138d8f0SLen Brown 	{
488de09cdd0SLen Brown 		.name = "C3",
4890138d8f0SLen Brown 		.desc = "MWAIT 0x10",
490b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4910138d8f0SLen Brown 		.exit_latency = 59,
4920138d8f0SLen Brown 		.target_residency = 300,
4935fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
49428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4950138d8f0SLen Brown 	{
496de09cdd0SLen Brown 		.name = "C6",
4970138d8f0SLen Brown 		.desc = "MWAIT 0x20",
498b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4990138d8f0SLen Brown 		.exit_latency = 84,
5000138d8f0SLen Brown 		.target_residency = 400,
5015fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
50228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5030138d8f0SLen Brown 	{
5040138d8f0SLen Brown 		.enter = NULL }
5050138d8f0SLen Brown };
5060138d8f0SLen Brown 
507ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_8s[] __initdata = {
5080138d8f0SLen Brown 	{
509de09cdd0SLen Brown 		.name = "C1",
5100138d8f0SLen Brown 		.desc = "MWAIT 0x00",
511b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
5120138d8f0SLen Brown 		.exit_latency = 1,
5130138d8f0SLen Brown 		.target_residency = 1,
5145fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
51528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5160138d8f0SLen Brown 	{
517de09cdd0SLen Brown 		.name = "C1E",
5180138d8f0SLen Brown 		.desc = "MWAIT 0x01",
519e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
5200138d8f0SLen Brown 		.exit_latency = 10,
5210138d8f0SLen Brown 		.target_residency = 500,
5225fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
52328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5240138d8f0SLen Brown 	{
525de09cdd0SLen Brown 		.name = "C3",
5260138d8f0SLen Brown 		.desc = "MWAIT 0x10",
527b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5280138d8f0SLen Brown 		.exit_latency = 59,
5290138d8f0SLen Brown 		.target_residency = 600,
5305fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
53128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5320138d8f0SLen Brown 	{
533de09cdd0SLen Brown 		.name = "C6",
5340138d8f0SLen Brown 		.desc = "MWAIT 0x20",
535b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5360138d8f0SLen Brown 		.exit_latency = 88,
5370138d8f0SLen Brown 		.target_residency = 700,
5385fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
53928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5400138d8f0SLen Brown 	{
5410138d8f0SLen Brown 		.enter = NULL }
5420138d8f0SLen Brown };
5430138d8f0SLen Brown 
544ab1a8522SRafael J. Wysocki static struct cpuidle_state hsw_cstates[] __initdata = {
545e022e7ebSLen Brown 	{
546de09cdd0SLen Brown 		.name = "C1",
54785a4d2d4SLen Brown 		.desc = "MWAIT 0x00",
548b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
54985a4d2d4SLen Brown 		.exit_latency = 2,
55085a4d2d4SLen Brown 		.target_residency = 2,
5515fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
55228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
553e022e7ebSLen Brown 	{
554de09cdd0SLen Brown 		.name = "C1E",
55532e95180SLen Brown 		.desc = "MWAIT 0x01",
556e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
55732e95180SLen Brown 		.exit_latency = 10,
55832e95180SLen Brown 		.target_residency = 20,
5595fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
56028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
56132e95180SLen Brown 	{
562de09cdd0SLen Brown 		.name = "C3",
56385a4d2d4SLen Brown 		.desc = "MWAIT 0x10",
564b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
56585a4d2d4SLen Brown 		.exit_latency = 33,
56685a4d2d4SLen Brown 		.target_residency = 100,
5675fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
56828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
569e022e7ebSLen Brown 	{
570de09cdd0SLen Brown 		.name = "C6",
57185a4d2d4SLen Brown 		.desc = "MWAIT 0x20",
572b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
57385a4d2d4SLen Brown 		.exit_latency = 133,
57485a4d2d4SLen Brown 		.target_residency = 400,
5755fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
57628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
577e022e7ebSLen Brown 	{
578de09cdd0SLen Brown 		.name = "C7s",
57985a4d2d4SLen Brown 		.desc = "MWAIT 0x32",
580b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
58185a4d2d4SLen Brown 		.exit_latency = 166,
58285a4d2d4SLen Brown 		.target_residency = 500,
5835fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
58428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
585e022e7ebSLen Brown 	{
586de09cdd0SLen Brown 		.name = "C8",
58786239cebSLen Brown 		.desc = "MWAIT 0x40",
588b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
58986239cebSLen Brown 		.exit_latency = 300,
59086239cebSLen Brown 		.target_residency = 900,
5915fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
59228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
59386239cebSLen Brown 	{
594de09cdd0SLen Brown 		.name = "C9",
59586239cebSLen Brown 		.desc = "MWAIT 0x50",
596b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
59786239cebSLen Brown 		.exit_latency = 600,
59886239cebSLen Brown 		.target_residency = 1800,
5995fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
60028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
60186239cebSLen Brown 	{
602de09cdd0SLen Brown 		.name = "C10",
60386239cebSLen Brown 		.desc = "MWAIT 0x60",
604b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
60586239cebSLen Brown 		.exit_latency = 2600,
60686239cebSLen Brown 		.target_residency = 7700,
6075fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
60828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
60986239cebSLen Brown 	{
610e022e7ebSLen Brown 		.enter = NULL }
61185a4d2d4SLen Brown };
612ab1a8522SRafael J. Wysocki static struct cpuidle_state bdw_cstates[] __initdata = {
613a138b568SLen Brown 	{
614de09cdd0SLen Brown 		.name = "C1",
615a138b568SLen Brown 		.desc = "MWAIT 0x00",
616b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
617a138b568SLen Brown 		.exit_latency = 2,
618a138b568SLen Brown 		.target_residency = 2,
6195fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
62028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
621a138b568SLen Brown 	{
622de09cdd0SLen Brown 		.name = "C1E",
623a138b568SLen Brown 		.desc = "MWAIT 0x01",
624e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
625a138b568SLen Brown 		.exit_latency = 10,
626a138b568SLen Brown 		.target_residency = 20,
6275fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
62828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
629a138b568SLen Brown 	{
630de09cdd0SLen Brown 		.name = "C3",
631a138b568SLen Brown 		.desc = "MWAIT 0x10",
632b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
633a138b568SLen Brown 		.exit_latency = 40,
634a138b568SLen Brown 		.target_residency = 100,
6355fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
63628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
637a138b568SLen Brown 	{
638de09cdd0SLen Brown 		.name = "C6",
639a138b568SLen Brown 		.desc = "MWAIT 0x20",
640b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
641a138b568SLen Brown 		.exit_latency = 133,
642a138b568SLen Brown 		.target_residency = 400,
6435fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
64428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
645a138b568SLen Brown 	{
646de09cdd0SLen Brown 		.name = "C7s",
647a138b568SLen Brown 		.desc = "MWAIT 0x32",
648b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
649a138b568SLen Brown 		.exit_latency = 166,
650a138b568SLen Brown 		.target_residency = 500,
6515fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
65228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
653a138b568SLen Brown 	{
654de09cdd0SLen Brown 		.name = "C8",
655a138b568SLen Brown 		.desc = "MWAIT 0x40",
656b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
657a138b568SLen Brown 		.exit_latency = 300,
658a138b568SLen Brown 		.target_residency = 900,
6595fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
66028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
661a138b568SLen Brown 	{
662de09cdd0SLen Brown 		.name = "C9",
663a138b568SLen Brown 		.desc = "MWAIT 0x50",
664b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
665a138b568SLen Brown 		.exit_latency = 600,
666a138b568SLen Brown 		.target_residency = 1800,
6675fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
66828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
669a138b568SLen Brown 	{
670de09cdd0SLen Brown 		.name = "C10",
671a138b568SLen Brown 		.desc = "MWAIT 0x60",
672b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
673a138b568SLen Brown 		.exit_latency = 2600,
674a138b568SLen Brown 		.target_residency = 7700,
6755fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
67628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
677a138b568SLen Brown 	{
678a138b568SLen Brown 		.enter = NULL }
679a138b568SLen Brown };
68085a4d2d4SLen Brown 
681ab1a8522SRafael J. Wysocki static struct cpuidle_state skl_cstates[] __initdata = {
682493f133fSLen Brown 	{
683de09cdd0SLen Brown 		.name = "C1",
684493f133fSLen Brown 		.desc = "MWAIT 0x00",
685493f133fSLen Brown 		.flags = MWAIT2flg(0x00),
686493f133fSLen Brown 		.exit_latency = 2,
687493f133fSLen Brown 		.target_residency = 2,
688493f133fSLen Brown 		.enter = &intel_idle,
68928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
690493f133fSLen Brown 	{
691de09cdd0SLen Brown 		.name = "C1E",
692493f133fSLen Brown 		.desc = "MWAIT 0x01",
693e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
694493f133fSLen Brown 		.exit_latency = 10,
695493f133fSLen Brown 		.target_residency = 20,
696493f133fSLen Brown 		.enter = &intel_idle,
69728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
698493f133fSLen Brown 	{
699de09cdd0SLen Brown 		.name = "C3",
700493f133fSLen Brown 		.desc = "MWAIT 0x10",
701493f133fSLen Brown 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
702493f133fSLen Brown 		.exit_latency = 70,
703493f133fSLen Brown 		.target_residency = 100,
704493f133fSLen Brown 		.enter = &intel_idle,
70528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
706493f133fSLen Brown 	{
707de09cdd0SLen Brown 		.name = "C6",
708493f133fSLen Brown 		.desc = "MWAIT 0x20",
709*bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
710135919a3SLen Brown 		.exit_latency = 85,
711493f133fSLen Brown 		.target_residency = 200,
712493f133fSLen Brown 		.enter = &intel_idle,
71328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
714493f133fSLen Brown 	{
715de09cdd0SLen Brown 		.name = "C7s",
716493f133fSLen Brown 		.desc = "MWAIT 0x33",
717*bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
718493f133fSLen Brown 		.exit_latency = 124,
719493f133fSLen Brown 		.target_residency = 800,
720493f133fSLen Brown 		.enter = &intel_idle,
72128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
722493f133fSLen Brown 	{
723de09cdd0SLen Brown 		.name = "C8",
724493f133fSLen Brown 		.desc = "MWAIT 0x40",
725*bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
726135919a3SLen Brown 		.exit_latency = 200,
727493f133fSLen Brown 		.target_residency = 800,
728493f133fSLen Brown 		.enter = &intel_idle,
72928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
730493f133fSLen Brown 	{
731de09cdd0SLen Brown 		.name = "C9",
732135919a3SLen Brown 		.desc = "MWAIT 0x50",
733*bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
734135919a3SLen Brown 		.exit_latency = 480,
735135919a3SLen Brown 		.target_residency = 5000,
736135919a3SLen Brown 		.enter = &intel_idle,
73728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
738135919a3SLen Brown 	{
739de09cdd0SLen Brown 		.name = "C10",
740493f133fSLen Brown 		.desc = "MWAIT 0x60",
741*bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
742493f133fSLen Brown 		.exit_latency = 890,
743493f133fSLen Brown 		.target_residency = 5000,
744493f133fSLen Brown 		.enter = &intel_idle,
74528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
746493f133fSLen Brown 	{
747493f133fSLen Brown 		.enter = NULL }
748493f133fSLen Brown };
749493f133fSLen Brown 
750ab1a8522SRafael J. Wysocki static struct cpuidle_state skx_cstates[] __initdata = {
751f9e71657SLen Brown 	{
752de09cdd0SLen Brown 		.name = "C1",
753f9e71657SLen Brown 		.desc = "MWAIT 0x00",
754c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
755f9e71657SLen Brown 		.exit_latency = 2,
756f9e71657SLen Brown 		.target_residency = 2,
757f9e71657SLen Brown 		.enter = &intel_idle,
75828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
759f9e71657SLen Brown 	{
760de09cdd0SLen Brown 		.name = "C1E",
761f9e71657SLen Brown 		.desc = "MWAIT 0x01",
762e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
763f9e71657SLen Brown 		.exit_latency = 10,
764f9e71657SLen Brown 		.target_residency = 20,
765f9e71657SLen Brown 		.enter = &intel_idle,
76628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
767f9e71657SLen Brown 	{
768de09cdd0SLen Brown 		.name = "C6",
769f9e71657SLen Brown 		.desc = "MWAIT 0x20",
770*bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
771f9e71657SLen Brown 		.exit_latency = 133,
772f9e71657SLen Brown 		.target_residency = 600,
773f9e71657SLen Brown 		.enter = &intel_idle,
77428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
775f9e71657SLen Brown 	{
776f9e71657SLen Brown 		.enter = NULL }
777f9e71657SLen Brown };
778f9e71657SLen Brown 
779a472ad2bSChen Yu static struct cpuidle_state icx_cstates[] __initdata = {
780a472ad2bSChen Yu 	{
781a472ad2bSChen Yu 		.name = "C1",
782a472ad2bSChen Yu 		.desc = "MWAIT 0x00",
783c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
784a472ad2bSChen Yu 		.exit_latency = 1,
785a472ad2bSChen Yu 		.target_residency = 1,
786a472ad2bSChen Yu 		.enter = &intel_idle,
787a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
788a472ad2bSChen Yu 	{
789a472ad2bSChen Yu 		.name = "C1E",
790a472ad2bSChen Yu 		.desc = "MWAIT 0x01",
791a472ad2bSChen Yu 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
792a472ad2bSChen Yu 		.exit_latency = 4,
793a472ad2bSChen Yu 		.target_residency = 4,
794a472ad2bSChen Yu 		.enter = &intel_idle,
795a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
796a472ad2bSChen Yu 	{
797a472ad2bSChen Yu 		.name = "C6",
798a472ad2bSChen Yu 		.desc = "MWAIT 0x20",
799a472ad2bSChen Yu 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
800d484b8bfSArtem Bityutskiy 		.exit_latency = 170,
801d484b8bfSArtem Bityutskiy 		.target_residency = 600,
802a472ad2bSChen Yu 		.enter = &intel_idle,
803a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
804a472ad2bSChen Yu 	{
805a472ad2bSChen Yu 		.enter = NULL }
806a472ad2bSChen Yu };
807a472ad2bSChen Yu 
8089edf3c0fSArtem Bityutskiy /*
809d1cf8bbfSZhang Rui  * On AlderLake C1 has to be disabled if C1E is enabled, and vice versa.
810d1cf8bbfSZhang Rui  * C1E is enabled only if "C1E promotion" bit is set in MSR_IA32_POWER_CTL.
811d1cf8bbfSZhang Rui  * But in this case there is effectively no C1, because C1 requests are
812d1cf8bbfSZhang Rui  * promoted to C1E. If the "C1E promotion" bit is cleared, then both C1
813d1cf8bbfSZhang Rui  * and C1E requests end up with C1, so there is effectively no C1E.
814d1cf8bbfSZhang Rui  *
815d1cf8bbfSZhang Rui  * By default we enable C1E and disable C1 by marking it with
816d1cf8bbfSZhang Rui  * 'CPUIDLE_FLAG_UNUSABLE'.
817d1cf8bbfSZhang Rui  */
818d1cf8bbfSZhang Rui static struct cpuidle_state adl_cstates[] __initdata = {
819d1cf8bbfSZhang Rui 	{
820d1cf8bbfSZhang Rui 		.name = "C1",
821d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
822d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
823d1cf8bbfSZhang Rui 		.exit_latency = 1,
824d1cf8bbfSZhang Rui 		.target_residency = 1,
825d1cf8bbfSZhang Rui 		.enter = &intel_idle,
826d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
827d1cf8bbfSZhang Rui 	{
828d1cf8bbfSZhang Rui 		.name = "C1E",
829d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
830d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
831d1cf8bbfSZhang Rui 		.exit_latency = 2,
832d1cf8bbfSZhang Rui 		.target_residency = 4,
833d1cf8bbfSZhang Rui 		.enter = &intel_idle,
834d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
835d1cf8bbfSZhang Rui 	{
836d1cf8bbfSZhang Rui 		.name = "C6",
837d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
838d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
839d1cf8bbfSZhang Rui 		.exit_latency = 220,
840d1cf8bbfSZhang Rui 		.target_residency = 600,
841d1cf8bbfSZhang Rui 		.enter = &intel_idle,
842d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
843d1cf8bbfSZhang Rui 	{
844d1cf8bbfSZhang Rui 		.name = "C8",
845d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
846d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
847d1cf8bbfSZhang Rui 		.exit_latency = 280,
848d1cf8bbfSZhang Rui 		.target_residency = 800,
849d1cf8bbfSZhang Rui 		.enter = &intel_idle,
850d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
851d1cf8bbfSZhang Rui 	{
852d1cf8bbfSZhang Rui 		.name = "C10",
853d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
854d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
855d1cf8bbfSZhang Rui 		.exit_latency = 680,
856d1cf8bbfSZhang Rui 		.target_residency = 2000,
857d1cf8bbfSZhang Rui 		.enter = &intel_idle,
858d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
859d1cf8bbfSZhang Rui 	{
860d1cf8bbfSZhang Rui 		.enter = NULL }
861d1cf8bbfSZhang Rui };
862d1cf8bbfSZhang Rui 
863d1cf8bbfSZhang Rui static struct cpuidle_state adl_l_cstates[] __initdata = {
864d1cf8bbfSZhang Rui 	{
865d1cf8bbfSZhang Rui 		.name = "C1",
866d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
867d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
868d1cf8bbfSZhang Rui 		.exit_latency = 1,
869d1cf8bbfSZhang Rui 		.target_residency = 1,
870d1cf8bbfSZhang Rui 		.enter = &intel_idle,
871d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
872d1cf8bbfSZhang Rui 	{
873d1cf8bbfSZhang Rui 		.name = "C1E",
874d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
875d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
876d1cf8bbfSZhang Rui 		.exit_latency = 2,
877d1cf8bbfSZhang Rui 		.target_residency = 4,
878d1cf8bbfSZhang Rui 		.enter = &intel_idle,
879d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
880d1cf8bbfSZhang Rui 	{
881d1cf8bbfSZhang Rui 		.name = "C6",
882d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
883d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
884d1cf8bbfSZhang Rui 		.exit_latency = 170,
885d1cf8bbfSZhang Rui 		.target_residency = 500,
886d1cf8bbfSZhang Rui 		.enter = &intel_idle,
887d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
888d1cf8bbfSZhang Rui 	{
889d1cf8bbfSZhang Rui 		.name = "C8",
890d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
891d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
892d1cf8bbfSZhang Rui 		.exit_latency = 200,
893d1cf8bbfSZhang Rui 		.target_residency = 600,
894d1cf8bbfSZhang Rui 		.enter = &intel_idle,
895d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
896d1cf8bbfSZhang Rui 	{
897d1cf8bbfSZhang Rui 		.name = "C10",
898d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
899d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
900d1cf8bbfSZhang Rui 		.exit_latency = 230,
901d1cf8bbfSZhang Rui 		.target_residency = 700,
902d1cf8bbfSZhang Rui 		.enter = &intel_idle,
903d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
904d1cf8bbfSZhang Rui 	{
905d1cf8bbfSZhang Rui 		.enter = NULL }
906d1cf8bbfSZhang Rui };
907d1cf8bbfSZhang Rui 
908d1cf8bbfSZhang Rui /*
9099edf3c0fSArtem Bityutskiy  * On Sapphire Rapids Xeon C1 has to be disabled if C1E is enabled, and vice
9109edf3c0fSArtem Bityutskiy  * versa. On SPR C1E is enabled only if "C1E promotion" bit is set in
9119edf3c0fSArtem Bityutskiy  * MSR_IA32_POWER_CTL. But in this case there effectively no C1, because C1
9129edf3c0fSArtem Bityutskiy  * requests are promoted to C1E. If the "C1E promotion" bit is cleared, then
9139edf3c0fSArtem Bityutskiy  * both C1 and C1E requests end up with C1, so there is effectively no C1E.
9149edf3c0fSArtem Bityutskiy  *
9159edf3c0fSArtem Bityutskiy  * By default we enable C1 and disable C1E by marking it with
9169edf3c0fSArtem Bityutskiy  * 'CPUIDLE_FLAG_UNUSABLE'.
9179edf3c0fSArtem Bityutskiy  */
9189edf3c0fSArtem Bityutskiy static struct cpuidle_state spr_cstates[] __initdata = {
9199edf3c0fSArtem Bityutskiy 	{
9209edf3c0fSArtem Bityutskiy 		.name = "C1",
9219edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x00",
9229edf3c0fSArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
9239edf3c0fSArtem Bityutskiy 		.exit_latency = 1,
9249edf3c0fSArtem Bityutskiy 		.target_residency = 1,
9259edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9269edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9279edf3c0fSArtem Bityutskiy 	{
9289edf3c0fSArtem Bityutskiy 		.name = "C1E",
9299edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x01",
93003eb6522SRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE |
9319edf3c0fSArtem Bityutskiy 					   CPUIDLE_FLAG_UNUSABLE,
9329edf3c0fSArtem Bityutskiy 		.exit_latency = 2,
9339edf3c0fSArtem Bityutskiy 		.target_residency = 4,
9349edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9359edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9369edf3c0fSArtem Bityutskiy 	{
9379edf3c0fSArtem Bityutskiy 		.name = "C6",
9389edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x20",
9399edf3c0fSArtem Bityutskiy 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
9409edf3c0fSArtem Bityutskiy 		.exit_latency = 290,
9419edf3c0fSArtem Bityutskiy 		.target_residency = 800,
9429edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9439edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9449edf3c0fSArtem Bityutskiy 	{
9459edf3c0fSArtem Bityutskiy 		.enter = NULL }
9469edf3c0fSArtem Bityutskiy };
9479edf3c0fSArtem Bityutskiy 
948ab1a8522SRafael J. Wysocki static struct cpuidle_state atom_cstates[] __initdata = {
949e022e7ebSLen Brown 	{
950de09cdd0SLen Brown 		.name = "C1E",
95126717172SLen Brown 		.desc = "MWAIT 0x00",
952b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
95332e95180SLen Brown 		.exit_latency = 10,
95432e95180SLen Brown 		.target_residency = 20,
9555fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
95628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
957e022e7ebSLen Brown 	{
958de09cdd0SLen Brown 		.name = "C2",
95926717172SLen Brown 		.desc = "MWAIT 0x10",
960b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10),
96126717172SLen Brown 		.exit_latency = 20,
96226717172SLen Brown 		.target_residency = 80,
9635fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
96428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
965e022e7ebSLen Brown 	{
966de09cdd0SLen Brown 		.name = "C4",
96726717172SLen Brown 		.desc = "MWAIT 0x30",
968b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
96926717172SLen Brown 		.exit_latency = 100,
97026717172SLen Brown 		.target_residency = 400,
9715fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
97228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
973e022e7ebSLen Brown 	{
974de09cdd0SLen Brown 		.name = "C6",
9757fcca7d9SLen Brown 		.desc = "MWAIT 0x52",
976b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
9777fcca7d9SLen Brown 		.exit_latency = 140,
9787fcca7d9SLen Brown 		.target_residency = 560,
9795fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
98028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
981e022e7ebSLen Brown 	{
982e022e7ebSLen Brown 		.enter = NULL }
98326717172SLen Brown };
984ab1a8522SRafael J. Wysocki static struct cpuidle_state tangier_cstates[] __initdata = {
9855e7ec268SAndy Shevchenko 	{
986de09cdd0SLen Brown 		.name = "C1",
9875e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x00",
9885e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x00),
9895e7ec268SAndy Shevchenko 		.exit_latency = 1,
9905e7ec268SAndy Shevchenko 		.target_residency = 4,
9915e7ec268SAndy Shevchenko 		.enter = &intel_idle,
99228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
9935e7ec268SAndy Shevchenko 	{
994de09cdd0SLen Brown 		.name = "C4",
9955e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x30",
9965e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
9975e7ec268SAndy Shevchenko 		.exit_latency = 100,
9985e7ec268SAndy Shevchenko 		.target_residency = 400,
9995e7ec268SAndy Shevchenko 		.enter = &intel_idle,
100028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10015e7ec268SAndy Shevchenko 	{
1002de09cdd0SLen Brown 		.name = "C6",
10035e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x52",
10045e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10055e7ec268SAndy Shevchenko 		.exit_latency = 140,
10065e7ec268SAndy Shevchenko 		.target_residency = 560,
10075e7ec268SAndy Shevchenko 		.enter = &intel_idle,
100828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10095e7ec268SAndy Shevchenko 	{
1010de09cdd0SLen Brown 		.name = "C7",
10115e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x60",
10125e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
10135e7ec268SAndy Shevchenko 		.exit_latency = 1200,
10145e7ec268SAndy Shevchenko 		.target_residency = 4000,
10155e7ec268SAndy Shevchenko 		.enter = &intel_idle,
101628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10175e7ec268SAndy Shevchenko 	{
1018de09cdd0SLen Brown 		.name = "C9",
10195e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x64",
10205e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
10215e7ec268SAndy Shevchenko 		.exit_latency = 10000,
10225e7ec268SAndy Shevchenko 		.target_residency = 20000,
10235e7ec268SAndy Shevchenko 		.enter = &intel_idle,
102428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10255e7ec268SAndy Shevchenko 	{
10265e7ec268SAndy Shevchenko 		.enter = NULL }
10275e7ec268SAndy Shevchenko };
1028ab1a8522SRafael J. Wysocki static struct cpuidle_state avn_cstates[] __initdata = {
1029fab04b22SLen Brown 	{
1030de09cdd0SLen Brown 		.name = "C1",
1031fab04b22SLen Brown 		.desc = "MWAIT 0x00",
1032b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
1033fab04b22SLen Brown 		.exit_latency = 2,
1034fab04b22SLen Brown 		.target_residency = 2,
10355fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
103628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1037fab04b22SLen Brown 	{
1038de09cdd0SLen Brown 		.name = "C6",
1039fab04b22SLen Brown 		.desc = "MWAIT 0x51",
1040b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED,
1041fab04b22SLen Brown 		.exit_latency = 15,
1042fab04b22SLen Brown 		.target_residency = 45,
10435fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
104428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
104588390996SJiang Liu 	{
104688390996SJiang Liu 		.enter = NULL }
1047fab04b22SLen Brown };
1048ab1a8522SRafael J. Wysocki static struct cpuidle_state knl_cstates[] __initdata = {
1049281baf7aSDasaratharaman Chandramouli 	{
1050de09cdd0SLen Brown 		.name = "C1",
1051281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x00",
1052281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x00),
1053281baf7aSDasaratharaman Chandramouli 		.exit_latency = 1,
1054281baf7aSDasaratharaman Chandramouli 		.target_residency = 2,
1055281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
105628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1057281baf7aSDasaratharaman Chandramouli 	{
1058de09cdd0SLen Brown 		.name = "C6",
1059281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x10",
1060281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
1061281baf7aSDasaratharaman Chandramouli 		.exit_latency = 120,
1062281baf7aSDasaratharaman Chandramouli 		.target_residency = 500,
1063281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
106428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1065281baf7aSDasaratharaman Chandramouli 	{
1066281baf7aSDasaratharaman Chandramouli 		.enter = NULL }
1067281baf7aSDasaratharaman Chandramouli };
106826717172SLen Brown 
1069ab1a8522SRafael J. Wysocki static struct cpuidle_state bxt_cstates[] __initdata = {
10705dcef694SLen Brown 	{
1071de09cdd0SLen Brown 		.name = "C1",
10725dcef694SLen Brown 		.desc = "MWAIT 0x00",
10735dcef694SLen Brown 		.flags = MWAIT2flg(0x00),
10745dcef694SLen Brown 		.exit_latency = 2,
10755dcef694SLen Brown 		.target_residency = 2,
10765dcef694SLen Brown 		.enter = &intel_idle,
107728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10785dcef694SLen Brown 	{
1079de09cdd0SLen Brown 		.name = "C1E",
10805dcef694SLen Brown 		.desc = "MWAIT 0x01",
1081e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
10825dcef694SLen Brown 		.exit_latency = 10,
10835dcef694SLen Brown 		.target_residency = 20,
10845dcef694SLen Brown 		.enter = &intel_idle,
108528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10865dcef694SLen Brown 	{
1087de09cdd0SLen Brown 		.name = "C6",
10885dcef694SLen Brown 		.desc = "MWAIT 0x20",
10895dcef694SLen Brown 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
10905dcef694SLen Brown 		.exit_latency = 133,
10915dcef694SLen Brown 		.target_residency = 133,
10925dcef694SLen Brown 		.enter = &intel_idle,
109328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10945dcef694SLen Brown 	{
1095de09cdd0SLen Brown 		.name = "C7s",
10965dcef694SLen Brown 		.desc = "MWAIT 0x31",
10975dcef694SLen Brown 		.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
10985dcef694SLen Brown 		.exit_latency = 155,
10995dcef694SLen Brown 		.target_residency = 155,
11005dcef694SLen Brown 		.enter = &intel_idle,
110128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11025dcef694SLen Brown 	{
1103de09cdd0SLen Brown 		.name = "C8",
11045dcef694SLen Brown 		.desc = "MWAIT 0x40",
11055dcef694SLen Brown 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
11065dcef694SLen Brown 		.exit_latency = 1000,
11075dcef694SLen Brown 		.target_residency = 1000,
11085dcef694SLen Brown 		.enter = &intel_idle,
110928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11105dcef694SLen Brown 	{
1111de09cdd0SLen Brown 		.name = "C9",
11125dcef694SLen Brown 		.desc = "MWAIT 0x50",
11135dcef694SLen Brown 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
11145dcef694SLen Brown 		.exit_latency = 2000,
11155dcef694SLen Brown 		.target_residency = 2000,
11165dcef694SLen Brown 		.enter = &intel_idle,
111728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11185dcef694SLen Brown 	{
1119de09cdd0SLen Brown 		.name = "C10",
11205dcef694SLen Brown 		.desc = "MWAIT 0x60",
11215dcef694SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
11225dcef694SLen Brown 		.exit_latency = 10000,
11235dcef694SLen Brown 		.target_residency = 10000,
11245dcef694SLen Brown 		.enter = &intel_idle,
112528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11265dcef694SLen Brown 	{
11275dcef694SLen Brown 		.enter = NULL }
11285dcef694SLen Brown };
11295dcef694SLen Brown 
1130ab1a8522SRafael J. Wysocki static struct cpuidle_state dnv_cstates[] __initdata = {
11310080d65bSJacob Pan 	{
1132de09cdd0SLen Brown 		.name = "C1",
11330080d65bSJacob Pan 		.desc = "MWAIT 0x00",
11340080d65bSJacob Pan 		.flags = MWAIT2flg(0x00),
11350080d65bSJacob Pan 		.exit_latency = 2,
11360080d65bSJacob Pan 		.target_residency = 2,
11370080d65bSJacob Pan 		.enter = &intel_idle,
113828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11390080d65bSJacob Pan 	{
1140de09cdd0SLen Brown 		.name = "C1E",
11410080d65bSJacob Pan 		.desc = "MWAIT 0x01",
1142e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11430080d65bSJacob Pan 		.exit_latency = 10,
11440080d65bSJacob Pan 		.target_residency = 20,
11450080d65bSJacob Pan 		.enter = &intel_idle,
114628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11470080d65bSJacob Pan 	{
1148de09cdd0SLen Brown 		.name = "C6",
11490080d65bSJacob Pan 		.desc = "MWAIT 0x20",
11500080d65bSJacob Pan 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
11510080d65bSJacob Pan 		.exit_latency = 50,
11520080d65bSJacob Pan 		.target_residency = 500,
11530080d65bSJacob Pan 		.enter = &intel_idle,
115428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11550080d65bSJacob Pan 	{
11560080d65bSJacob Pan 		.enter = NULL }
11570080d65bSJacob Pan };
11580080d65bSJacob Pan 
11599cf93f05SArtem Bityutskiy /*
11609cf93f05SArtem Bityutskiy  * Note, depending on HW and FW revision, SnowRidge SoC may or may not support
11619cf93f05SArtem Bityutskiy  * C6, and this is indicated in the CPUID mwait leaf.
11629cf93f05SArtem Bityutskiy  */
11639cf93f05SArtem Bityutskiy static struct cpuidle_state snr_cstates[] __initdata = {
11649cf93f05SArtem Bityutskiy 	{
11659cf93f05SArtem Bityutskiy 		.name = "C1",
11669cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x00",
11679cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
11689cf93f05SArtem Bityutskiy 		.exit_latency = 2,
11699cf93f05SArtem Bityutskiy 		.target_residency = 2,
11709cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
11719cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
11729cf93f05SArtem Bityutskiy 	{
11739cf93f05SArtem Bityutskiy 		.name = "C1E",
11749cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x01",
11759cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11769cf93f05SArtem Bityutskiy 		.exit_latency = 15,
11779cf93f05SArtem Bityutskiy 		.target_residency = 25,
11789cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
11799cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
11809cf93f05SArtem Bityutskiy 	{
11819cf93f05SArtem Bityutskiy 		.name = "C6",
11829cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x20",
11839cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
11849cf93f05SArtem Bityutskiy 		.exit_latency = 130,
11859cf93f05SArtem Bityutskiy 		.target_residency = 500,
11869cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
11879cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
11889cf93f05SArtem Bityutskiy 	{
11899cf93f05SArtem Bityutskiy 		.enter = NULL }
11909cf93f05SArtem Bityutskiy };
11919cf93f05SArtem Bityutskiy 
1192ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nehalem __initconst = {
1193b66b8b9aSAndi Kleen 	.state_table = nehalem_cstates,
1194b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
119532e95180SLen Brown 	.disable_promotion_to_c1e = true,
1196b66b8b9aSAndi Kleen };
1197b66b8b9aSAndi Kleen 
1198ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nhx __initconst = {
1199e6d4f08aSRafael J. Wysocki 	.state_table = nehalem_cstates,
1200e6d4f08aSRafael J. Wysocki 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
1201e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1202e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1203e6d4f08aSRafael J. Wysocki };
1204e6d4f08aSRafael J. Wysocki 
1205ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_atom __initconst = {
1206b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1207b66b8b9aSAndi Kleen };
1208b66b8b9aSAndi Kleen 
1209ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_tangier __initconst = {
12105e7ec268SAndy Shevchenko 	.state_table = tangier_cstates,
12115e7ec268SAndy Shevchenko };
12125e7ec268SAndy Shevchenko 
1213ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_lincroft __initconst = {
1214b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1215b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
1216b66b8b9aSAndi Kleen };
1217b66b8b9aSAndi Kleen 
1218ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snb __initconst = {
1219b66b8b9aSAndi Kleen 	.state_table = snb_cstates,
122032e95180SLen Brown 	.disable_promotion_to_c1e = true,
1221b66b8b9aSAndi Kleen };
1222b66b8b9aSAndi Kleen 
1223ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snx __initconst = {
1224e6d4f08aSRafael J. Wysocki 	.state_table = snb_cstates,
1225e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1226e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1227e6d4f08aSRafael J. Wysocki };
1228e6d4f08aSRafael J. Wysocki 
1229ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_byt __initconst = {
1230718987d6SLen Brown 	.state_table = byt_cstates,
1231718987d6SLen Brown 	.disable_promotion_to_c1e = true,
12328c058d53SLen Brown 	.byt_auto_demotion_disable_flag = true,
1233718987d6SLen Brown };
1234718987d6SLen Brown 
1235ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_cht __initconst = {
1236cab07a56SLen Brown 	.state_table = cht_cstates,
1237cab07a56SLen Brown 	.disable_promotion_to_c1e = true,
1238cab07a56SLen Brown 	.byt_auto_demotion_disable_flag = true,
1239cab07a56SLen Brown };
1240cab07a56SLen Brown 
1241ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivb __initconst = {
12426edab08cSLen Brown 	.state_table = ivb_cstates,
124332e95180SLen Brown 	.disable_promotion_to_c1e = true,
12446edab08cSLen Brown };
12456edab08cSLen Brown 
1246ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivt __initconst = {
12470138d8f0SLen Brown 	.state_table = ivt_cstates,
12480138d8f0SLen Brown 	.disable_promotion_to_c1e = true,
1249e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
12500138d8f0SLen Brown };
12510138d8f0SLen Brown 
1252ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsw __initconst = {
125385a4d2d4SLen Brown 	.state_table = hsw_cstates,
125432e95180SLen Brown 	.disable_promotion_to_c1e = true,
125585a4d2d4SLen Brown };
125685a4d2d4SLen Brown 
1257ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsx __initconst = {
1258e6d4f08aSRafael J. Wysocki 	.state_table = hsw_cstates,
1259e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1260e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1261e6d4f08aSRafael J. Wysocki };
1262e6d4f08aSRafael J. Wysocki 
1263ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdw __initconst = {
1264a138b568SLen Brown 	.state_table = bdw_cstates,
1265a138b568SLen Brown 	.disable_promotion_to_c1e = true,
1266a138b568SLen Brown };
1267a138b568SLen Brown 
1268ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdx __initconst = {
1269e6d4f08aSRafael J. Wysocki 	.state_table = bdw_cstates,
1270e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1271e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1272e6d4f08aSRafael J. Wysocki };
1273e6d4f08aSRafael J. Wysocki 
1274ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skl __initconst = {
1275493f133fSLen Brown 	.state_table = skl_cstates,
1276493f133fSLen Brown 	.disable_promotion_to_c1e = true,
1277493f133fSLen Brown };
1278493f133fSLen Brown 
1279ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skx __initconst = {
1280f9e71657SLen Brown 	.state_table = skx_cstates,
1281f9e71657SLen Brown 	.disable_promotion_to_c1e = true,
1282e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1283f9e71657SLen Brown };
1284493f133fSLen Brown 
1285a472ad2bSChen Yu static const struct idle_cpu idle_cpu_icx __initconst = {
1286a472ad2bSChen Yu 	.state_table = icx_cstates,
1287a472ad2bSChen Yu 	.disable_promotion_to_c1e = true,
1288a472ad2bSChen Yu 	.use_acpi = true,
1289a472ad2bSChen Yu };
1290a472ad2bSChen Yu 
1291d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl __initconst = {
1292d1cf8bbfSZhang Rui 	.state_table = adl_cstates,
1293d1cf8bbfSZhang Rui };
1294d1cf8bbfSZhang Rui 
1295d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl_l __initconst = {
1296d1cf8bbfSZhang Rui 	.state_table = adl_l_cstates,
1297d1cf8bbfSZhang Rui };
1298d1cf8bbfSZhang Rui 
12999edf3c0fSArtem Bityutskiy static const struct idle_cpu idle_cpu_spr __initconst = {
13009edf3c0fSArtem Bityutskiy 	.state_table = spr_cstates,
13019edf3c0fSArtem Bityutskiy 	.disable_promotion_to_c1e = true,
13029edf3c0fSArtem Bityutskiy 	.use_acpi = true,
13039edf3c0fSArtem Bityutskiy };
13049edf3c0fSArtem Bityutskiy 
1305ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_avn __initconst = {
1306fab04b22SLen Brown 	.state_table = avn_cstates,
1307fab04b22SLen Brown 	.disable_promotion_to_c1e = true,
1308e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1309fab04b22SLen Brown };
1310fab04b22SLen Brown 
1311ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_knl __initconst = {
1312281baf7aSDasaratharaman Chandramouli 	.state_table = knl_cstates,
1313e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1314281baf7aSDasaratharaman Chandramouli };
1315281baf7aSDasaratharaman Chandramouli 
1316ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bxt __initconst = {
13175dcef694SLen Brown 	.state_table = bxt_cstates,
13185dcef694SLen Brown 	.disable_promotion_to_c1e = true,
13195dcef694SLen Brown };
13205dcef694SLen Brown 
1321ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_dnv __initconst = {
13220080d65bSJacob Pan 	.state_table = dnv_cstates,
13230080d65bSJacob Pan 	.disable_promotion_to_c1e = true,
1324e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
13250080d65bSJacob Pan };
13260080d65bSJacob Pan 
13279cf93f05SArtem Bityutskiy static const struct idle_cpu idle_cpu_snr __initconst = {
13289cf93f05SArtem Bityutskiy 	.state_table = snr_cstates,
13299cf93f05SArtem Bityutskiy 	.disable_promotion_to_c1e = true,
13309cf93f05SArtem Bityutskiy 	.use_acpi = true,
13319cf93f05SArtem Bityutskiy };
13329cf93f05SArtem Bityutskiy 
1333d5cdc3c4SMathias Krause static const struct x86_cpu_id intel_idle_ids[] __initconst = {
13344a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP,		&idle_cpu_nhx),
13354a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM,		&idle_cpu_nehalem),
13364a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G,		&idle_cpu_nehalem),
13374a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE,		&idle_cpu_nehalem),
13384a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP,		&idle_cpu_nhx),
13394a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX,		&idle_cpu_nhx),
13404a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL,	&idle_cpu_atom),
13414a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL_MID,	&idle_cpu_lincroft),
13424a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX,		&idle_cpu_nhx),
13434a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE,		&idle_cpu_snb),
13444a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X,	&idle_cpu_snx),
13454a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL,	&idle_cpu_atom),
13464a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,	&idle_cpu_byt),
13474a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID,	&idle_cpu_tangier),
13484a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,	&idle_cpu_cht),
13494a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE,		&idle_cpu_ivb),
13504a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X,		&idle_cpu_ivt),
13514a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL,		&idle_cpu_hsw),
13524a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X,		&idle_cpu_hsx),
13534a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L,		&idle_cpu_hsw),
13544a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G,		&idle_cpu_hsw),
13554a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D,	&idle_cpu_avn),
13564a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL,		&idle_cpu_bdw),
13574a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G,		&idle_cpu_bdw),
13584a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X,		&idle_cpu_bdx),
13594a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D,		&idle_cpu_bdx),
13604a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L,		&idle_cpu_skl),
13614a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE,		&idle_cpu_skl),
13624a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L,		&idle_cpu_skl),
13634a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE,		&idle_cpu_skl),
13644a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,		&idle_cpu_skx),
1365a472ad2bSChen Yu 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,		&idle_cpu_icx),
136622141d5fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,		&idle_cpu_icx),
1367d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,		&idle_cpu_adl),
1368d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,		&idle_cpu_adl_l),
13699edf3c0fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,	&idle_cpu_spr),
13704a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,	&idle_cpu_knl),
13714a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,	&idle_cpu_knl),
13724a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	&idle_cpu_bxt),
13734a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,	&idle_cpu_bxt),
13744a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D,	&idle_cpu_dnv),
13759cf93f05SArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,	&idle_cpu_snr),
1376b66b8b9aSAndi Kleen 	{}
1377b66b8b9aSAndi Kleen };
1378b66b8b9aSAndi Kleen 
137918734958SRafael J. Wysocki static const struct x86_cpu_id intel_mwait_ids[] __initconst = {
13804a9f45a0SThomas Gleixner 	X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL),
138118734958SRafael J. Wysocki 	{}
138218734958SRafael J. Wysocki };
138318734958SRafael J. Wysocki 
1384095928aeSRafael J. Wysocki static bool __init intel_idle_max_cstate_reached(int cstate)
138518734958SRafael J. Wysocki {
138618734958SRafael J. Wysocki 	if (cstate + 1 > max_cstate) {
138718734958SRafael J. Wysocki 		pr_info("max_cstate %d reached\n", max_cstate);
138818734958SRafael J. Wysocki 		return true;
138918734958SRafael J. Wysocki 	}
139018734958SRafael J. Wysocki 	return false;
139118734958SRafael J. Wysocki }
139218734958SRafael J. Wysocki 
13934d916140SPeter Zijlstra static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
13944d916140SPeter Zijlstra {
13954d916140SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
13964d916140SPeter Zijlstra 
13974d916140SPeter Zijlstra 	if (boot_cpu_has(X86_FEATURE_ARAT))
13984d916140SPeter Zijlstra 		return false;
13994d916140SPeter Zijlstra 
14004d916140SPeter Zijlstra 	/*
14014d916140SPeter Zijlstra 	 * Switch over to one-shot tick broadcast if the target C-state
14024d916140SPeter Zijlstra 	 * is deeper than C1.
14034d916140SPeter Zijlstra 	 */
14044d916140SPeter Zijlstra 	return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
14054d916140SPeter Zijlstra }
14064d916140SPeter Zijlstra 
140718734958SRafael J. Wysocki #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
140818734958SRafael J. Wysocki #include <acpi/processor.h>
140918734958SRafael J. Wysocki 
14104ec32d9eSRafael J. Wysocki static bool no_acpi __read_mostly;
14114ec32d9eSRafael J. Wysocki module_param(no_acpi, bool, 0444);
14124ec32d9eSRafael J. Wysocki MODULE_PARM_DESC(no_acpi, "Do not use ACPI _CST for building the idle states list");
14134ec32d9eSRafael J. Wysocki 
14143a5be9b8SRafael J. Wysocki static bool force_use_acpi __read_mostly; /* No effect if no_acpi is set. */
14153a5be9b8SRafael J. Wysocki module_param_named(use_acpi, force_use_acpi, bool, 0444);
14163a5be9b8SRafael J. Wysocki MODULE_PARM_DESC(use_acpi, "Use ACPI _CST for building the idle states list");
14173a5be9b8SRafael J. Wysocki 
1418095928aeSRafael J. Wysocki static struct acpi_processor_power acpi_state_table __initdata;
141918734958SRafael J. Wysocki 
142018734958SRafael J. Wysocki /**
142118734958SRafael J. Wysocki  * intel_idle_cst_usable - Check if the _CST information can be used.
142218734958SRafael J. Wysocki  *
142318734958SRafael J. Wysocki  * Check if all of the C-states listed by _CST in the max_cstate range are
142418734958SRafael J. Wysocki  * ACPI_CSTATE_FFH, which means that they should be entered via MWAIT.
142518734958SRafael J. Wysocki  */
1426095928aeSRafael J. Wysocki static bool __init intel_idle_cst_usable(void)
142718734958SRafael J. Wysocki {
142818734958SRafael J. Wysocki 	int cstate, limit;
142918734958SRafael J. Wysocki 
143018734958SRafael J. Wysocki 	limit = min_t(int, min_t(int, CPUIDLE_STATE_MAX, max_cstate + 1),
143118734958SRafael J. Wysocki 		      acpi_state_table.count);
143218734958SRafael J. Wysocki 
143318734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
143418734958SRafael J. Wysocki 		struct acpi_processor_cx *cx = &acpi_state_table.states[cstate];
143518734958SRafael J. Wysocki 
143618734958SRafael J. Wysocki 		if (cx->entry_method != ACPI_CSTATE_FFH)
143718734958SRafael J. Wysocki 			return false;
143818734958SRafael J. Wysocki 	}
143918734958SRafael J. Wysocki 
144018734958SRafael J. Wysocki 	return true;
144118734958SRafael J. Wysocki }
144218734958SRafael J. Wysocki 
1443095928aeSRafael J. Wysocki static bool __init intel_idle_acpi_cst_extract(void)
144418734958SRafael J. Wysocki {
144518734958SRafael J. Wysocki 	unsigned int cpu;
144618734958SRafael J. Wysocki 
14474ec32d9eSRafael J. Wysocki 	if (no_acpi) {
14484ec32d9eSRafael J. Wysocki 		pr_debug("Not allowed to use ACPI _CST\n");
14494ec32d9eSRafael J. Wysocki 		return false;
14504ec32d9eSRafael J. Wysocki 	}
14514ec32d9eSRafael J. Wysocki 
145218734958SRafael J. Wysocki 	for_each_possible_cpu(cpu) {
145318734958SRafael J. Wysocki 		struct acpi_processor *pr = per_cpu(processors, cpu);
145418734958SRafael J. Wysocki 
145518734958SRafael J. Wysocki 		if (!pr)
145618734958SRafael J. Wysocki 			continue;
145718734958SRafael J. Wysocki 
145818734958SRafael J. Wysocki 		if (acpi_processor_evaluate_cst(pr->handle, cpu, &acpi_state_table))
145918734958SRafael J. Wysocki 			continue;
146018734958SRafael J. Wysocki 
146118734958SRafael J. Wysocki 		acpi_state_table.count++;
146218734958SRafael J. Wysocki 
146318734958SRafael J. Wysocki 		if (!intel_idle_cst_usable())
146418734958SRafael J. Wysocki 			continue;
146518734958SRafael J. Wysocki 
146675af76d0SMel Gorman 		if (!acpi_processor_claim_cst_control())
146775af76d0SMel Gorman 			break;
146818734958SRafael J. Wysocki 
146918734958SRafael J. Wysocki 		return true;
147018734958SRafael J. Wysocki 	}
147118734958SRafael J. Wysocki 
147275af76d0SMel Gorman 	acpi_state_table.count = 0;
147318734958SRafael J. Wysocki 	pr_debug("ACPI _CST not found or not usable\n");
147418734958SRafael J. Wysocki 	return false;
147518734958SRafael J. Wysocki }
147618734958SRafael J. Wysocki 
1477095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
147818734958SRafael J. Wysocki {
147918734958SRafael J. Wysocki 	int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
148018734958SRafael J. Wysocki 
148118734958SRafael J. Wysocki 	/*
148218734958SRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
148318734958SRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
148418734958SRafael J. Wysocki 	 */
148518734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
148618734958SRafael J. Wysocki 		struct acpi_processor_cx *cx;
148718734958SRafael J. Wysocki 		struct cpuidle_state *state;
148818734958SRafael J. Wysocki 
14894e0ba557SChen Yu 		if (intel_idle_max_cstate_reached(cstate - 1))
149018734958SRafael J. Wysocki 			break;
149118734958SRafael J. Wysocki 
149218734958SRafael J. Wysocki 		cx = &acpi_state_table.states[cstate];
149318734958SRafael J. Wysocki 
149418734958SRafael J. Wysocki 		state = &drv->states[drv->state_count++];
149518734958SRafael J. Wysocki 
149618734958SRafael J. Wysocki 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate);
149718734958SRafael J. Wysocki 		strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
149818734958SRafael J. Wysocki 		state->exit_latency = cx->latency;
149918734958SRafael J. Wysocki 		/*
150018734958SRafael J. Wysocki 		 * For C1-type C-states use the same number for both the exit
150118734958SRafael J. Wysocki 		 * latency and target residency, because that is the case for
150218734958SRafael J. Wysocki 		 * C1 in the majority of the static C-states tables above.
150318734958SRafael J. Wysocki 		 * For the other types of C-states, however, set the target
150418734958SRafael J. Wysocki 		 * residency to 3 times the exit latency which should lead to
150518734958SRafael J. Wysocki 		 * a reasonable balance between energy-efficiency and
150618734958SRafael J. Wysocki 		 * performance in the majority of interesting cases.
150718734958SRafael J. Wysocki 		 */
150818734958SRafael J. Wysocki 		state->target_residency = cx->latency;
150918734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C1)
151018734958SRafael J. Wysocki 			state->target_residency *= 3;
151118734958SRafael J. Wysocki 
151218734958SRafael J. Wysocki 		state->flags = MWAIT2flg(cx->address);
151318734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C2)
151418734958SRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
151518734958SRafael J. Wysocki 
15164dcb78eeSRafael J. Wysocki 		if (disabled_states_mask & BIT(cstate))
15174dcb78eeSRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_OFF;
15184dcb78eeSRafael J. Wysocki 
15196e1d2bc6SPeter Zijlstra 		if (intel_idle_state_needs_timer_stop(state))
15206e1d2bc6SPeter Zijlstra 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
15216e1d2bc6SPeter Zijlstra 
152218734958SRafael J. Wysocki 		state->enter = intel_idle;
152318734958SRafael J. Wysocki 		state->enter_s2idle = intel_idle_s2idle;
152418734958SRafael J. Wysocki 	}
152518734958SRafael J. Wysocki }
1526bff8e60aSRafael J. Wysocki 
1527095928aeSRafael J. Wysocki static bool __init intel_idle_off_by_default(u32 mwait_hint)
1528bff8e60aSRafael J. Wysocki {
1529bff8e60aSRafael J. Wysocki 	int cstate, limit;
1530bff8e60aSRafael J. Wysocki 
1531bff8e60aSRafael J. Wysocki 	/*
1532bff8e60aSRafael J. Wysocki 	 * If there are no _CST C-states, do not disable any C-states by
1533bff8e60aSRafael J. Wysocki 	 * default.
1534bff8e60aSRafael J. Wysocki 	 */
1535bff8e60aSRafael J. Wysocki 	if (!acpi_state_table.count)
1536bff8e60aSRafael J. Wysocki 		return false;
1537bff8e60aSRafael J. Wysocki 
1538bff8e60aSRafael J. Wysocki 	limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
1539bff8e60aSRafael J. Wysocki 	/*
1540bff8e60aSRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
1541bff8e60aSRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
1542bff8e60aSRafael J. Wysocki 	 */
1543bff8e60aSRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
1544bff8e60aSRafael J. Wysocki 		if (acpi_state_table.states[cstate].address == mwait_hint)
1545bff8e60aSRafael J. Wysocki 			return false;
1546bff8e60aSRafael J. Wysocki 	}
1547bff8e60aSRafael J. Wysocki 	return true;
1548bff8e60aSRafael J. Wysocki }
154918734958SRafael J. Wysocki #else /* !CONFIG_ACPI_PROCESSOR_CSTATE */
15503a5be9b8SRafael J. Wysocki #define force_use_acpi	(false)
15513a5be9b8SRafael J. Wysocki 
155218734958SRafael J. Wysocki static inline bool intel_idle_acpi_cst_extract(void) { return false; }
155318734958SRafael J. Wysocki static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
1554bff8e60aSRafael J. Wysocki static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
155518734958SRafael J. Wysocki #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */
155618734958SRafael J. Wysocki 
15576eacb15fSRafael J. Wysocki /**
15586eacb15fSRafael J. Wysocki  * ivt_idle_state_table_update - Tune the idle states table for Ivy Town.
15590138d8f0SLen Brown  *
15606eacb15fSRafael J. Wysocki  * Tune IVT multi-socket targets.
15616eacb15fSRafael J. Wysocki  * Assumption: num_sockets == (max_package_num + 1).
15620138d8f0SLen Brown  */
1563095928aeSRafael J. Wysocki static void __init ivt_idle_state_table_update(void)
15640138d8f0SLen Brown {
15650138d8f0SLen Brown 	/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
15660138d8f0SLen Brown 	int cpu, package_num, num_sockets = 1;
15670138d8f0SLen Brown 
15680138d8f0SLen Brown 	for_each_online_cpu(cpu) {
15690138d8f0SLen Brown 		package_num = topology_physical_package_id(cpu);
15700138d8f0SLen Brown 		if (package_num + 1 > num_sockets) {
15710138d8f0SLen Brown 			num_sockets = package_num + 1;
15720138d8f0SLen Brown 
1573d27dca42SChristoph Jaeger 			if (num_sockets > 4) {
15740138d8f0SLen Brown 				cpuidle_state_table = ivt_cstates_8s;
15750138d8f0SLen Brown 				return;
15760138d8f0SLen Brown 			}
15770138d8f0SLen Brown 		}
1578d27dca42SChristoph Jaeger 	}
15790138d8f0SLen Brown 
15800138d8f0SLen Brown 	if (num_sockets > 2)
15810138d8f0SLen Brown 		cpuidle_state_table = ivt_cstates_4s;
1582d70e28f5SLen Brown 
15830138d8f0SLen Brown 	/* else, 1 and 2 socket systems use default ivt_cstates */
15840138d8f0SLen Brown }
15855dcef694SLen Brown 
158686e9466aSRafael J. Wysocki /**
158786e9466aSRafael J. Wysocki  * irtl_2_usec - IRTL to microseconds conversion.
158886e9466aSRafael J. Wysocki  * @irtl: IRTL MSR value.
158986e9466aSRafael J. Wysocki  *
159086e9466aSRafael J. Wysocki  * Translate the IRTL (Interrupt Response Time Limit) MSR value to microseconds.
15915dcef694SLen Brown  */
159286e9466aSRafael J. Wysocki static unsigned long long __init irtl_2_usec(unsigned long long irtl)
159386e9466aSRafael J. Wysocki {
1594095928aeSRafael J. Wysocki 	static const unsigned int irtl_ns_units[] __initconst = {
1595095928aeSRafael J. Wysocki 		1, 32, 1024, 32768, 1048576, 33554432, 0, 0
1596095928aeSRafael J. Wysocki 	};
15975dcef694SLen Brown 	unsigned long long ns;
15985dcef694SLen Brown 
15993451ab3eSJan Beulich 	if (!irtl)
16003451ab3eSJan Beulich 		return 0;
16013451ab3eSJan Beulich 
1602bef45096SJan Beulich 	ns = irtl_ns_units[(irtl >> 10) & 0x7];
16035dcef694SLen Brown 
160486e9466aSRafael J. Wysocki 	return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC);
16055dcef694SLen Brown }
160686e9466aSRafael J. Wysocki 
16076eacb15fSRafael J. Wysocki /**
16086eacb15fSRafael J. Wysocki  * bxt_idle_state_table_update - Fix up the Broxton idle states table.
16095dcef694SLen Brown  *
16106eacb15fSRafael J. Wysocki  * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the
16116eacb15fSRafael J. Wysocki  * definitive maximum latency and use the same value for target_residency.
16125dcef694SLen Brown  */
1613095928aeSRafael J. Wysocki static void __init bxt_idle_state_table_update(void)
16145dcef694SLen Brown {
16155dcef694SLen Brown 	unsigned long long msr;
16163451ab3eSJan Beulich 	unsigned int usec;
16175dcef694SLen Brown 
16185dcef694SLen Brown 	rdmsrl(MSR_PKGC6_IRTL, msr);
16193451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16203451ab3eSJan Beulich 	if (usec) {
16215dcef694SLen Brown 		bxt_cstates[2].exit_latency = usec;
16225dcef694SLen Brown 		bxt_cstates[2].target_residency = usec;
16235dcef694SLen Brown 	}
16245dcef694SLen Brown 
16255dcef694SLen Brown 	rdmsrl(MSR_PKGC7_IRTL, msr);
16263451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16273451ab3eSJan Beulich 	if (usec) {
16285dcef694SLen Brown 		bxt_cstates[3].exit_latency = usec;
16295dcef694SLen Brown 		bxt_cstates[3].target_residency = usec;
16305dcef694SLen Brown 	}
16315dcef694SLen Brown 
16325dcef694SLen Brown 	rdmsrl(MSR_PKGC8_IRTL, msr);
16333451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16343451ab3eSJan Beulich 	if (usec) {
16355dcef694SLen Brown 		bxt_cstates[4].exit_latency = usec;
16365dcef694SLen Brown 		bxt_cstates[4].target_residency = usec;
16375dcef694SLen Brown 	}
16385dcef694SLen Brown 
16395dcef694SLen Brown 	rdmsrl(MSR_PKGC9_IRTL, msr);
16403451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16413451ab3eSJan Beulich 	if (usec) {
16425dcef694SLen Brown 		bxt_cstates[5].exit_latency = usec;
16435dcef694SLen Brown 		bxt_cstates[5].target_residency = usec;
16445dcef694SLen Brown 	}
16455dcef694SLen Brown 
16465dcef694SLen Brown 	rdmsrl(MSR_PKGC10_IRTL, msr);
16473451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16483451ab3eSJan Beulich 	if (usec) {
16495dcef694SLen Brown 		bxt_cstates[6].exit_latency = usec;
16505dcef694SLen Brown 		bxt_cstates[6].target_residency = usec;
16515dcef694SLen Brown 	}
16525dcef694SLen Brown 
16535dcef694SLen Brown }
16546eacb15fSRafael J. Wysocki 
16556eacb15fSRafael J. Wysocki /**
16566eacb15fSRafael J. Wysocki  * sklh_idle_state_table_update - Fix up the Sky Lake idle states table.
1657d70e28f5SLen Brown  *
16586eacb15fSRafael J. Wysocki  * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled.
1659d70e28f5SLen Brown  */
1660095928aeSRafael J. Wysocki static void __init sklh_idle_state_table_update(void)
1661d70e28f5SLen Brown {
1662d70e28f5SLen Brown 	unsigned long long msr;
1663d70e28f5SLen Brown 	unsigned int eax, ebx, ecx, edx;
1664d70e28f5SLen Brown 
1665d70e28f5SLen Brown 
1666d70e28f5SLen Brown 	/* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
1667d70e28f5SLen Brown 	if (max_cstate <= 7)
16680138d8f0SLen Brown 		return;
1669d70e28f5SLen Brown 
1670d70e28f5SLen Brown 	/* if PC10 not present in CPUID.MWAIT.EDX */
1671d70e28f5SLen Brown 	if ((mwait_substates & (0xF << 28)) == 0)
1672d70e28f5SLen Brown 		return;
1673d70e28f5SLen Brown 
16746cfb2374SLen Brown 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
1675d70e28f5SLen Brown 
1676d70e28f5SLen Brown 	/* PC10 is not enabled in PKG C-state limit */
1677d70e28f5SLen Brown 	if ((msr & 0xF) != 8)
1678d70e28f5SLen Brown 		return;
1679d70e28f5SLen Brown 
1680d70e28f5SLen Brown 	ecx = 0;
1681d70e28f5SLen Brown 	cpuid(7, &eax, &ebx, &ecx, &edx);
1682d70e28f5SLen Brown 
1683d70e28f5SLen Brown 	/* if SGX is present */
1684d70e28f5SLen Brown 	if (ebx & (1 << 2)) {
1685d70e28f5SLen Brown 
168632ad73dbSSean Christopherson 		rdmsrl(MSR_IA32_FEAT_CTL, msr);
1687d70e28f5SLen Brown 
1688d70e28f5SLen Brown 		/* if SGX is enabled */
1689d70e28f5SLen Brown 		if (msr & (1 << 18))
1690d70e28f5SLen Brown 			return;
1691d70e28f5SLen Brown 	}
1692d70e28f5SLen Brown 
1693ba1e78a1SRafael J. Wysocki 	skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C8-SKL */
1694ba1e78a1SRafael J. Wysocki 	skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C9-SKL */
1695d70e28f5SLen Brown }
1696d70e28f5SLen Brown 
169764233338SChen Yu /**
169864233338SChen Yu  * skx_idle_state_table_update - Adjust the Sky Lake/Cascade Lake
169964233338SChen Yu  * idle states table.
170064233338SChen Yu  */
170164233338SChen Yu static void __init skx_idle_state_table_update(void)
170264233338SChen Yu {
170364233338SChen Yu 	unsigned long long msr;
170464233338SChen Yu 
170564233338SChen Yu 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
170664233338SChen Yu 
170764233338SChen Yu 	/*
170864233338SChen Yu 	 * 000b: C0/C1 (no package C-state support)
170964233338SChen Yu 	 * 001b: C2
171064233338SChen Yu 	 * 010b: C6 (non-retention)
171164233338SChen Yu 	 * 011b: C6 (retention)
171264233338SChen Yu 	 * 111b: No Package C state limits.
171364233338SChen Yu 	 */
171464233338SChen Yu 	if ((msr & 0x7) < 2) {
171564233338SChen Yu 		/*
171664233338SChen Yu 		 * Uses the CC6 + PC0 latency and 3 times of
171764233338SChen Yu 		 * latency for target_residency if the PC6
171864233338SChen Yu 		 * is disabled in BIOS. This is consistent
171964233338SChen Yu 		 * with how intel_idle driver uses _CST
172064233338SChen Yu 		 * to set the target_residency.
172164233338SChen Yu 		 */
172264233338SChen Yu 		skx_cstates[2].exit_latency = 92;
172364233338SChen Yu 		skx_cstates[2].target_residency = 276;
172464233338SChen Yu 	}
172564233338SChen Yu }
172664233338SChen Yu 
1727da0e58c0SArtem Bityutskiy /**
1728d1cf8bbfSZhang Rui  * adl_idle_state_table_update - Adjust AlderLake idle states table.
1729d1cf8bbfSZhang Rui  */
1730d1cf8bbfSZhang Rui static void __init adl_idle_state_table_update(void)
1731d1cf8bbfSZhang Rui {
1732d1cf8bbfSZhang Rui 	/* Check if user prefers C1 over C1E. */
1733d1cf8bbfSZhang Rui 	if (preferred_states_mask & BIT(1) && !(preferred_states_mask & BIT(2))) {
1734d1cf8bbfSZhang Rui 		cpuidle_state_table[0].flags &= ~CPUIDLE_FLAG_UNUSABLE;
1735d1cf8bbfSZhang Rui 		cpuidle_state_table[1].flags |= CPUIDLE_FLAG_UNUSABLE;
1736d1cf8bbfSZhang Rui 
1737d1cf8bbfSZhang Rui 		/* Disable C1E by clearing the "C1E promotion" bit. */
1738d1cf8bbfSZhang Rui 		c1e_promotion = C1E_PROMOTION_DISABLE;
1739d1cf8bbfSZhang Rui 		return;
1740d1cf8bbfSZhang Rui 	}
1741d1cf8bbfSZhang Rui 
1742d1cf8bbfSZhang Rui 	/* Make sure C1E is enabled by default */
1743d1cf8bbfSZhang Rui 	c1e_promotion = C1E_PROMOTION_ENABLE;
1744d1cf8bbfSZhang Rui }
1745d1cf8bbfSZhang Rui 
1746d1cf8bbfSZhang Rui /**
1747da0e58c0SArtem Bityutskiy  * spr_idle_state_table_update - Adjust Sapphire Rapids idle states table.
1748da0e58c0SArtem Bityutskiy  */
1749da0e58c0SArtem Bityutskiy static void __init spr_idle_state_table_update(void)
1750da0e58c0SArtem Bityutskiy {
17513a9cf77bSArtem Bityutskiy 	unsigned long long msr;
17523a9cf77bSArtem Bityutskiy 
1753da0e58c0SArtem Bityutskiy 	/* Check if user prefers C1E over C1. */
17547eac3bd3SArtem Bityutskiy 	if ((preferred_states_mask & BIT(2)) &&
17557eac3bd3SArtem Bityutskiy 	    !(preferred_states_mask & BIT(1))) {
17567eac3bd3SArtem Bityutskiy 		/* Disable C1 and enable C1E. */
1757da0e58c0SArtem Bityutskiy 		spr_cstates[0].flags |= CPUIDLE_FLAG_UNUSABLE;
1758da0e58c0SArtem Bityutskiy 		spr_cstates[1].flags &= ~CPUIDLE_FLAG_UNUSABLE;
1759da0e58c0SArtem Bityutskiy 
1760da0e58c0SArtem Bityutskiy 		/* Enable C1E using the "C1E promotion" bit. */
176139c184a6SArtem Bityutskiy 		c1e_promotion = C1E_PROMOTION_ENABLE;
1762da0e58c0SArtem Bityutskiy 	}
17633a9cf77bSArtem Bityutskiy 
17643a9cf77bSArtem Bityutskiy 	/*
17653a9cf77bSArtem Bityutskiy 	 * By default, the C6 state assumes the worst-case scenario of package
17663a9cf77bSArtem Bityutskiy 	 * C6. However, if PC6 is disabled, we update the numbers to match
17673a9cf77bSArtem Bityutskiy 	 * core C6.
17683a9cf77bSArtem Bityutskiy 	 */
17693a9cf77bSArtem Bityutskiy 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
17703a9cf77bSArtem Bityutskiy 
17713a9cf77bSArtem Bityutskiy 	/* Limit value 2 and above allow for PC6. */
17723a9cf77bSArtem Bityutskiy 	if ((msr & 0x7) < 2) {
17733a9cf77bSArtem Bityutskiy 		spr_cstates[2].exit_latency = 190;
17743a9cf77bSArtem Bityutskiy 		spr_cstates[2].target_residency = 600;
17753a9cf77bSArtem Bityutskiy 	}
1776da0e58c0SArtem Bityutskiy }
1777da0e58c0SArtem Bityutskiy 
17781aefbd7aSRafael J. Wysocki static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
17791aefbd7aSRafael J. Wysocki {
17801aefbd7aSRafael J. Wysocki 	unsigned int mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint) + 1;
17811aefbd7aSRafael J. Wysocki 	unsigned int num_substates = (mwait_substates >> mwait_cstate * 4) &
17821aefbd7aSRafael J. Wysocki 					MWAIT_SUBSTATE_MASK;
17831aefbd7aSRafael J. Wysocki 
17841aefbd7aSRafael J. Wysocki 	/* Ignore the C-state if there are NO sub-states in CPUID for it. */
17851aefbd7aSRafael J. Wysocki 	if (num_substates == 0)
17861aefbd7aSRafael J. Wysocki 		return false;
17871aefbd7aSRafael J. Wysocki 
17881aefbd7aSRafael J. Wysocki 	if (mwait_cstate > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
17891aefbd7aSRafael J. Wysocki 		mark_tsc_unstable("TSC halts in idle states deeper than C2");
17901aefbd7aSRafael J. Wysocki 
17911aefbd7aSRafael J. Wysocki 	return true;
17921aefbd7aSRafael J. Wysocki }
17931aefbd7aSRafael J. Wysocki 
1794095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
1795d70e28f5SLen Brown {
17963d3a1ae9SRafael J. Wysocki 	int cstate;
1797d70e28f5SLen Brown 
17983d3a1ae9SRafael J. Wysocki 	switch (boot_cpu_data.x86_model) {
1799db73c5a8SDave Hansen 	case INTEL_FAM6_IVYBRIDGE_X:
1800d70e28f5SLen Brown 		ivt_idle_state_table_update();
1801d70e28f5SLen Brown 		break;
1802db73c5a8SDave Hansen 	case INTEL_FAM6_ATOM_GOLDMONT:
1803f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
18045dcef694SLen Brown 		bxt_idle_state_table_update();
18055dcef694SLen Brown 		break;
1806c66f78a6SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE:
1807d70e28f5SLen Brown 		sklh_idle_state_table_update();
1808d70e28f5SLen Brown 		break;
180964233338SChen Yu 	case INTEL_FAM6_SKYLAKE_X:
181064233338SChen Yu 		skx_idle_state_table_update();
181164233338SChen Yu 		break;
1812da0e58c0SArtem Bityutskiy 	case INTEL_FAM6_SAPPHIRERAPIDS_X:
1813da0e58c0SArtem Bityutskiy 		spr_idle_state_table_update();
1814da0e58c0SArtem Bityutskiy 		break;
1815d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE:
1816d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE_L:
1817d1cf8bbfSZhang Rui 		adl_idle_state_table_update();
1818d1cf8bbfSZhang Rui 		break;
1819d70e28f5SLen Brown 	}
182046bcfad7SDeepthi Dharwar 
1821e022e7ebSLen Brown 	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
18229f3d6dafSRafael J. Wysocki 		unsigned int mwait_hint;
182346bcfad7SDeepthi Dharwar 
182418734958SRafael J. Wysocki 		if (intel_idle_max_cstate_reached(cstate))
182518734958SRafael J. Wysocki 			break;
182618734958SRafael J. Wysocki 
18279f3d6dafSRafael J. Wysocki 		if (!cpuidle_state_table[cstate].enter &&
18289f3d6dafSRafael J. Wysocki 		    !cpuidle_state_table[cstate].enter_s2idle)
1829e022e7ebSLen Brown 			break;
1830e022e7ebSLen Brown 
18319f3d6dafSRafael J. Wysocki 		/* If marked as unusable, skip this state. */
1832ba1e78a1SRafael J. Wysocki 		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) {
1833654d08a4SJoe Perches 			pr_debug("state %s is disabled\n",
1834d70e28f5SLen Brown 				 cpuidle_state_table[cstate].name);
1835d70e28f5SLen Brown 			continue;
1836d70e28f5SLen Brown 		}
1837d70e28f5SLen Brown 
18389f3d6dafSRafael J. Wysocki 		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
18399f3d6dafSRafael J. Wysocki 		if (!intel_idle_verify_cstate(mwait_hint))
18409f3d6dafSRafael J. Wysocki 			continue;
1841d70e28f5SLen Brown 
18429f3d6dafSRafael J. Wysocki 		/* Structure copy. */
1843bff8e60aSRafael J. Wysocki 		drv->states[drv->state_count] = cpuidle_state_table[cstate];
1844bff8e60aSRafael J. Wysocki 
184532d4fd57SPeter Zijlstra 		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE)
184632d4fd57SPeter Zijlstra 			drv->states[drv->state_count].enter = intel_idle_irq;
184732d4fd57SPeter Zijlstra 
1848*bf5835bcSPeter Zijlstra 		if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
1849*bf5835bcSPeter Zijlstra 		    cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IBRS) {
1850*bf5835bcSPeter Zijlstra 			WARN_ON_ONCE(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE);
1851*bf5835bcSPeter Zijlstra 			drv->states[drv->state_count].enter = intel_idle_ibrs;
1852*bf5835bcSPeter Zijlstra 		}
1853*bf5835bcSPeter Zijlstra 
18544dcb78eeSRafael J. Wysocki 		if ((disabled_states_mask & BIT(drv->state_count)) ||
18554dcb78eeSRafael J. Wysocki 		    ((icpu->use_acpi || force_use_acpi) &&
18563a5be9b8SRafael J. Wysocki 		     intel_idle_off_by_default(mwait_hint) &&
18574dcb78eeSRafael J. Wysocki 		     !(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
1858bff8e60aSRafael J. Wysocki 			drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;
1859bff8e60aSRafael J. Wysocki 
18606e1d2bc6SPeter Zijlstra 		if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count]))
18616e1d2bc6SPeter Zijlstra 			drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP;
18626e1d2bc6SPeter Zijlstra 
1863bff8e60aSRafael J. Wysocki 		drv->state_count++;
186446bcfad7SDeepthi Dharwar 	}
186546bcfad7SDeepthi Dharwar 
18668c058d53SLen Brown 	if (icpu->byt_auto_demotion_disable_flag) {
18678c058d53SLen Brown 		wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
18688c058d53SLen Brown 		wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
18698c058d53SLen Brown 	}
187046bcfad7SDeepthi Dharwar }
187146bcfad7SDeepthi Dharwar 
18726eacb15fSRafael J. Wysocki /**
18736eacb15fSRafael J. Wysocki  * intel_idle_cpuidle_driver_init - Create the list of available idle states.
18746eacb15fSRafael J. Wysocki  * @drv: cpuidle driver structure to initialize.
187518734958SRafael J. Wysocki  */
18763d3a1ae9SRafael J. Wysocki static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
187718734958SRafael J. Wysocki {
187818734958SRafael J. Wysocki 	cpuidle_poll_state_init(drv);
18794dcb78eeSRafael J. Wysocki 
18804dcb78eeSRafael J. Wysocki 	if (disabled_states_mask & BIT(0))
18814dcb78eeSRafael J. Wysocki 		drv->states[0].flags |= CPUIDLE_FLAG_OFF;
18824dcb78eeSRafael J. Wysocki 
188318734958SRafael J. Wysocki 	drv->state_count = 1;
188418734958SRafael J. Wysocki 
188518734958SRafael J. Wysocki 	if (icpu)
188618734958SRafael J. Wysocki 		intel_idle_init_cstates_icpu(drv);
188718734958SRafael J. Wysocki 	else
188818734958SRafael J. Wysocki 		intel_idle_init_cstates_acpi(drv);
188918734958SRafael J. Wysocki }
189046bcfad7SDeepthi Dharwar 
18911aefbd7aSRafael J. Wysocki static void auto_demotion_disable(void)
18921aefbd7aSRafael J. Wysocki {
18931aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
18941aefbd7aSRafael J. Wysocki 
18951aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
18967f843dd7SRafael J. Wysocki 	msr_bits &= ~auto_demotion_disable_flags;
18971aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
18981aefbd7aSRafael J. Wysocki }
18991aefbd7aSRafael J. Wysocki 
1900da0e58c0SArtem Bityutskiy static void c1e_promotion_enable(void)
1901da0e58c0SArtem Bityutskiy {
1902da0e58c0SArtem Bityutskiy 	unsigned long long msr_bits;
1903da0e58c0SArtem Bityutskiy 
1904da0e58c0SArtem Bityutskiy 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
1905da0e58c0SArtem Bityutskiy 	msr_bits |= 0x2;
1906da0e58c0SArtem Bityutskiy 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
1907da0e58c0SArtem Bityutskiy }
1908da0e58c0SArtem Bityutskiy 
19091aefbd7aSRafael J. Wysocki static void c1e_promotion_disable(void)
19101aefbd7aSRafael J. Wysocki {
19111aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
19121aefbd7aSRafael J. Wysocki 
19131aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
19141aefbd7aSRafael J. Wysocki 	msr_bits &= ~0x2;
19151aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
19161aefbd7aSRafael J. Wysocki }
19171aefbd7aSRafael J. Wysocki 
19186eacb15fSRafael J. Wysocki /**
19196eacb15fSRafael J. Wysocki  * intel_idle_cpu_init - Register the target CPU with the cpuidle core.
19206eacb15fSRafael J. Wysocki  * @cpu: CPU to initialize.
19216eacb15fSRafael J. Wysocki  *
19226eacb15fSRafael J. Wysocki  * Register a cpuidle device object for @cpu and update its MSRs in accordance
19236eacb15fSRafael J. Wysocki  * with the processor model flags.
192426717172SLen Brown  */
1925fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_init(unsigned int cpu)
192626717172SLen Brown {
192726717172SLen Brown 	struct cpuidle_device *dev;
192826717172SLen Brown 
192965b7f839SThomas Renninger 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
193065b7f839SThomas Renninger 	dev->cpu = cpu;
193126717172SLen Brown 
193226717172SLen Brown 	if (cpuidle_register_device(dev)) {
1933654d08a4SJoe Perches 		pr_debug("cpuidle_register_device %d failed!\n", cpu);
193426717172SLen Brown 		return -EIO;
193526717172SLen Brown 	}
193665b7f839SThomas Renninger 
19377f843dd7SRafael J. Wysocki 	if (auto_demotion_disable_flags)
1938fb1013a0SSebastian Andrzej Siewior 		auto_demotion_disable();
193926717172SLen Brown 
194039c184a6SArtem Bityutskiy 	if (c1e_promotion == C1E_PROMOTION_ENABLE)
194139c184a6SArtem Bityutskiy 		c1e_promotion_enable();
194239c184a6SArtem Bityutskiy 	else if (c1e_promotion == C1E_PROMOTION_DISABLE)
1943fb1013a0SSebastian Andrzej Siewior 		c1e_promotion_disable();
1944fb1013a0SSebastian Andrzej Siewior 
1945fb1013a0SSebastian Andrzej Siewior 	return 0;
1946fb1013a0SSebastian Andrzej Siewior }
1947fb1013a0SSebastian Andrzej Siewior 
1948fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_online(unsigned int cpu)
1949fb1013a0SSebastian Andrzej Siewior {
1950fb1013a0SSebastian Andrzej Siewior 	struct cpuidle_device *dev;
1951fb1013a0SSebastian Andrzej Siewior 
1952dab20177SRafael J. Wysocki 	if (!boot_cpu_has(X86_FEATURE_ARAT))
1953cbd2c4c2SRafael J. Wysocki 		tick_broadcast_enable();
1954fb1013a0SSebastian Andrzej Siewior 
1955fb1013a0SSebastian Andrzej Siewior 	/*
1956fb1013a0SSebastian Andrzej Siewior 	 * Some systems can hotplug a cpu at runtime after
1957fb1013a0SSebastian Andrzej Siewior 	 * the kernel has booted, we have to initialize the
1958fb1013a0SSebastian Andrzej Siewior 	 * driver in this case
1959fb1013a0SSebastian Andrzej Siewior 	 */
1960fb1013a0SSebastian Andrzej Siewior 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
1961fb1013a0SSebastian Andrzej Siewior 	if (!dev->registered)
1962fb1013a0SSebastian Andrzej Siewior 		return intel_idle_cpu_init(cpu);
1963dbf87ab8SBartlomiej Zolnierkiewicz 
196426717172SLen Brown 	return 0;
196526717172SLen Brown }
196626717172SLen Brown 
19670755a9bdSRafael J. Wysocki /**
19680755a9bdSRafael J. Wysocki  * intel_idle_cpuidle_devices_uninit - Unregister all cpuidle devices.
19690755a9bdSRafael J. Wysocki  */
19700755a9bdSRafael J. Wysocki static void __init intel_idle_cpuidle_devices_uninit(void)
19710755a9bdSRafael J. Wysocki {
19720755a9bdSRafael J. Wysocki 	int i;
19730755a9bdSRafael J. Wysocki 
19740755a9bdSRafael J. Wysocki 	for_each_online_cpu(i)
19750755a9bdSRafael J. Wysocki 		cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
19760755a9bdSRafael J. Wysocki }
19770755a9bdSRafael J. Wysocki 
197826717172SLen Brown static int __init intel_idle_init(void)
197926717172SLen Brown {
1980a6c86e33SRafael J. Wysocki 	const struct x86_cpu_id *id;
1981a6c86e33SRafael J. Wysocki 	unsigned int eax, ebx, ecx;
1982fb1013a0SSebastian Andrzej Siewior 	int retval;
198326717172SLen Brown 
1984d1896049SThomas Renninger 	/* Do not load intel_idle at all for now if idle= is passed */
1985d1896049SThomas Renninger 	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
1986d1896049SThomas Renninger 		return -ENODEV;
1987d1896049SThomas Renninger 
1988a6c86e33SRafael J. Wysocki 	if (max_cstate == 0) {
1989a6c86e33SRafael J. Wysocki 		pr_debug("disabled\n");
1990a6c86e33SRafael J. Wysocki 		return -EPERM;
1991a6c86e33SRafael J. Wysocki 	}
1992a6c86e33SRafael J. Wysocki 
1993a6c86e33SRafael J. Wysocki 	id = x86_match_cpu(intel_idle_ids);
1994a6c86e33SRafael J. Wysocki 	if (id) {
1995a6c86e33SRafael J. Wysocki 		if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
1996a6c86e33SRafael J. Wysocki 			pr_debug("Please enable MWAIT in BIOS SETUP\n");
1997a6c86e33SRafael J. Wysocki 			return -ENODEV;
1998a6c86e33SRafael J. Wysocki 		}
1999a6c86e33SRafael J. Wysocki 	} else {
2000a6c86e33SRafael J. Wysocki 		id = x86_match_cpu(intel_mwait_ids);
2001a6c86e33SRafael J. Wysocki 		if (!id)
2002a6c86e33SRafael J. Wysocki 			return -ENODEV;
2003a6c86e33SRafael J. Wysocki 	}
2004a6c86e33SRafael J. Wysocki 
2005a6c86e33SRafael J. Wysocki 	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
2006a6c86e33SRafael J. Wysocki 		return -ENODEV;
2007a6c86e33SRafael J. Wysocki 
2008a6c86e33SRafael J. Wysocki 	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
2009a6c86e33SRafael J. Wysocki 
2010a6c86e33SRafael J. Wysocki 	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
2011a6c86e33SRafael J. Wysocki 	    !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
2012a6c86e33SRafael J. Wysocki 	    !mwait_substates)
2013a6c86e33SRafael J. Wysocki 			return -ENODEV;
2014a6c86e33SRafael J. Wysocki 
2015a6c86e33SRafael J. Wysocki 	pr_debug("MWAIT substates: 0x%x\n", mwait_substates);
2016a6c86e33SRafael J. Wysocki 
2017a6c86e33SRafael J. Wysocki 	icpu = (const struct idle_cpu *)id->driver_data;
2018a6c86e33SRafael J. Wysocki 	if (icpu) {
2019a6c86e33SRafael J. Wysocki 		cpuidle_state_table = icpu->state_table;
20207f843dd7SRafael J. Wysocki 		auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
202139c184a6SArtem Bityutskiy 		if (icpu->disable_promotion_to_c1e)
202239c184a6SArtem Bityutskiy 			c1e_promotion = C1E_PROMOTION_DISABLE;
20233a5be9b8SRafael J. Wysocki 		if (icpu->use_acpi || force_use_acpi)
2024a6c86e33SRafael J. Wysocki 			intel_idle_acpi_cst_extract();
2025a6c86e33SRafael J. Wysocki 	} else if (!intel_idle_acpi_cst_extract()) {
2026a6c86e33SRafael J. Wysocki 		return -ENODEV;
2027a6c86e33SRafael J. Wysocki 	}
2028a6c86e33SRafael J. Wysocki 
2029a6c86e33SRafael J. Wysocki 	pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
2030a6c86e33SRafael J. Wysocki 		 boot_cpu_data.x86_model);
203126717172SLen Brown 
2032e9df69ccSRichard Cochran 	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
2033533da74aSRafael J. Wysocki 	if (!intel_idle_cpuidle_devices)
2034e9df69ccSRichard Cochran 		return -ENOMEM;
2035e9df69ccSRichard Cochran 
20363d3a1ae9SRafael J. Wysocki 	intel_idle_cpuidle_driver_init(&intel_idle_driver);
20373d3a1ae9SRafael J. Wysocki 
203826717172SLen Brown 	retval = cpuidle_register_driver(&intel_idle_driver);
203926717172SLen Brown 	if (retval) {
20403735d524SKonrad Rzeszutek Wilk 		struct cpuidle_driver *drv = cpuidle_get_driver();
2041654d08a4SJoe Perches 		printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
20423735d524SKonrad Rzeszutek Wilk 		       drv ? drv->name : "none");
2043fb1013a0SSebastian Andrzej Siewior 		goto init_driver_fail;
204426717172SLen Brown 	}
204526717172SLen Brown 
2046fb1013a0SSebastian Andrzej Siewior 	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
2047fb1013a0SSebastian Andrzej Siewior 				   intel_idle_cpu_online, NULL);
2048fb1013a0SSebastian Andrzej Siewior 	if (retval < 0)
2049fb1013a0SSebastian Andrzej Siewior 		goto hp_setup_fail;
205026717172SLen Brown 
205140ab82e0SRafael J. Wysocki 	pr_debug("Local APIC timer is reliable in %s\n",
2052dab20177SRafael J. Wysocki 		 boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1");
20532259a819SRichard Cochran 
205426717172SLen Brown 	return 0;
2055fb1013a0SSebastian Andrzej Siewior 
2056fb1013a0SSebastian Andrzej Siewior hp_setup_fail:
2057fb1013a0SSebastian Andrzej Siewior 	intel_idle_cpuidle_devices_uninit();
2058fb1013a0SSebastian Andrzej Siewior 	cpuidle_unregister_driver(&intel_idle_driver);
2059fb1013a0SSebastian Andrzej Siewior init_driver_fail:
2060fb1013a0SSebastian Andrzej Siewior 	free_percpu(intel_idle_cpuidle_devices);
2061fb1013a0SSebastian Andrzej Siewior 	return retval;
2062fb1013a0SSebastian Andrzej Siewior 
206326717172SLen Brown }
206402c4fae9SPaul Gortmaker device_initcall(intel_idle_init);
206526717172SLen Brown 
206602c4fae9SPaul Gortmaker /*
206702c4fae9SPaul Gortmaker  * We are not really modular, but we used to support that.  Meaning we also
206802c4fae9SPaul Gortmaker  * support "intel_idle.max_cstate=..." at boot and also a read-only export of
206902c4fae9SPaul Gortmaker  * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param
207002c4fae9SPaul Gortmaker  * is the easiest way (currently) to continue doing that.
207102c4fae9SPaul Gortmaker  */
207226717172SLen Brown module_param(max_cstate, int, 0444);
20734dcb78eeSRafael J. Wysocki /*
20744dcb78eeSRafael J. Wysocki  * The positions of the bits that are set in this number are the indices of the
20754dcb78eeSRafael J. Wysocki  * idle states to be disabled by default (as reflected by the names of the
20764dcb78eeSRafael J. Wysocki  * corresponding idle state directories in sysfs, "state0", "state1" ...
20774dcb78eeSRafael J. Wysocki  * "state<i>" ..., where <i> is the index of the given state).
20784dcb78eeSRafael J. Wysocki  */
20794dcb78eeSRafael J. Wysocki module_param_named(states_off, disabled_states_mask, uint, 0444);
20804dcb78eeSRafael J. Wysocki MODULE_PARM_DESC(states_off, "Mask of disabled idle states");
2081da0e58c0SArtem Bityutskiy /*
2082da0e58c0SArtem Bityutskiy  * Some platforms come with mutually exclusive C-states, so that if one is
2083da0e58c0SArtem Bityutskiy  * enabled, the other C-states must not be used. Example: C1 and C1E on
2084da0e58c0SArtem Bityutskiy  * Sapphire Rapids platform. This parameter allows for selecting the
2085da0e58c0SArtem Bityutskiy  * preferred C-states among the groups of mutually exclusive C-states - the
2086da0e58c0SArtem Bityutskiy  * selected C-states will be registered, the other C-states from the mutually
2087da0e58c0SArtem Bityutskiy  * exclusive group won't be registered. If the platform has no mutually
2088da0e58c0SArtem Bityutskiy  * exclusive C-states, this parameter has no effect.
2089da0e58c0SArtem Bityutskiy  */
2090da0e58c0SArtem Bityutskiy module_param_named(preferred_cstates, preferred_states_mask, uint, 0444);
2091da0e58c0SArtem Bityutskiy MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states");
2092