xref: /openbmc/linux/drivers/idle/intel_idle.c (revision 08beb0d4)
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>
50bf5835bcSPeter 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>
56bf5835bcSPeter Zijlstra #include <asm/nospec-branch.h>
57bc83ccccSH. Peter Anvin #include <asm/mwait.h>
5814796fcaSLen Brown #include <asm/msr.h>
599f011293SChang S. Bae #include <asm/fpu/api.h>
6026717172SLen Brown 
61317e5ec3SRafael J. Wysocki #define INTEL_IDLE_VERSION "0.5.1"
6226717172SLen Brown 
6326717172SLen Brown static struct cpuidle_driver intel_idle_driver = {
6426717172SLen Brown 	.name = "intel_idle",
6526717172SLen Brown 	.owner = THIS_MODULE,
6626717172SLen Brown };
6726717172SLen Brown /* intel_idle.max_cstate=0 disables driver */
68137ecc77SLen Brown static int max_cstate = CPUIDLE_STATE_MAX - 1;
69bd446829SArtem Bityutskiy static unsigned int disabled_states_mask __read_mostly;
70bd446829SArtem Bityutskiy static unsigned int preferred_states_mask __read_mostly;
714152379aSArtem Bityutskiy static bool force_irq_on __read_mostly;
7226717172SLen Brown 
736eb0443aSRafael J. Wysocki static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
747f843dd7SRafael J. Wysocki 
757f843dd7SRafael J. Wysocki static unsigned long auto_demotion_disable_flags;
7639c184a6SArtem Bityutskiy 
7739c184a6SArtem Bityutskiy static enum {
7839c184a6SArtem Bityutskiy 	C1E_PROMOTION_PRESERVE,
7939c184a6SArtem Bityutskiy 	C1E_PROMOTION_ENABLE,
8039c184a6SArtem Bityutskiy 	C1E_PROMOTION_DISABLE
8139c184a6SArtem Bityutskiy } c1e_promotion = C1E_PROMOTION_PRESERVE;
827f843dd7SRafael J. Wysocki 
83b66b8b9aSAndi Kleen struct idle_cpu {
84b66b8b9aSAndi Kleen 	struct cpuidle_state *state_table;
8526717172SLen Brown 
8626717172SLen Brown 	/*
8714796fcaSLen Brown 	 * Hardware C-state auto-demotion may not always be optimal.
8814796fcaSLen Brown 	 * Indicate which enable bits to clear here.
8914796fcaSLen Brown 	 */
90b66b8b9aSAndi Kleen 	unsigned long auto_demotion_disable_flags;
918c058d53SLen Brown 	bool byt_auto_demotion_disable_flag;
9232e95180SLen Brown 	bool disable_promotion_to_c1e;
93bff8e60aSRafael J. Wysocki 	bool use_acpi;
94b66b8b9aSAndi Kleen };
95b66b8b9aSAndi Kleen 
967f843dd7SRafael J. Wysocki static const struct idle_cpu *icpu __initdata;
977f843dd7SRafael J. Wysocki static struct cpuidle_state *cpuidle_state_table __initdata;
9814796fcaSLen Brown 
996eb0443aSRafael J. Wysocki static unsigned int mwait_substates __initdata;
1006eb0443aSRafael J. Wysocki 
10114796fcaSLen Brown /*
102c227233aSArtem Bityutskiy  * Enable interrupts before entering the C-state. On some platforms and for
103c227233aSArtem Bityutskiy  * some C-states, this may measurably decrease interrupt latency.
104c227233aSArtem Bityutskiy  */
105c227233aSArtem Bityutskiy #define CPUIDLE_FLAG_IRQ_ENABLE		BIT(14)
106c227233aSArtem Bityutskiy 
107c227233aSArtem Bityutskiy /*
108bff8e60aSRafael J. Wysocki  * Enable this state by default even if the ACPI _CST does not list it.
109bff8e60aSRafael J. Wysocki  */
110bff8e60aSRafael J. Wysocki #define CPUIDLE_FLAG_ALWAYS_ENABLE	BIT(15)
111bff8e60aSRafael J. Wysocki 
112bff8e60aSRafael J. Wysocki /*
113bf5835bcSPeter Zijlstra  * Disable IBRS across idle (when KERNEL_IBRS), is exclusive vs IRQ_ENABLE
114bf5835bcSPeter Zijlstra  * above.
115bf5835bcSPeter Zijlstra  */
116bf5835bcSPeter Zijlstra #define CPUIDLE_FLAG_IBRS		BIT(16)
117bf5835bcSPeter Zijlstra 
118bf5835bcSPeter Zijlstra /*
1199f011293SChang S. Bae  * Initialize large xstate for the C6-state entrance.
1209f011293SChang S. Bae  */
1219f011293SChang S. Bae #define CPUIDLE_FLAG_INIT_XSTATE	BIT(17)
1229f011293SChang S. Bae 
1239f011293SChang S. Bae /*
124b1beab48SLen Brown  * MWAIT takes an 8-bit "hint" in EAX "suggesting"
125b1beab48SLen Brown  * the C-state (top nibble) and sub-state (bottom nibble)
126b1beab48SLen Brown  * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc.
127b1beab48SLen Brown  *
128b1beab48SLen Brown  * We store the hint at the top of our "flags" for each state.
129b1beab48SLen Brown  */
130b1beab48SLen Brown #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
131b1beab48SLen Brown #define MWAIT2flg(eax) ((eax & 0xFF) << 24)
132b1beab48SLen Brown 
__intel_idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index,bool irqoff)13332d4fd57SPeter Zijlstra static __always_inline int __intel_idle(struct cpuidle_device *dev,
134*08beb0d4SPeter Zijlstra 					struct cpuidle_driver *drv,
135*08beb0d4SPeter Zijlstra 					int index, bool irqoff)
13632d4fd57SPeter Zijlstra {
13732d4fd57SPeter Zijlstra 	struct cpuidle_state *state = &drv->states[index];
13832d4fd57SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
139*08beb0d4SPeter Zijlstra 	unsigned long ecx = 1*irqoff; /* break on interrupt flag */
14032d4fd57SPeter Zijlstra 
14132d4fd57SPeter Zijlstra 	mwait_idle_with_hints(eax, ecx);
14232d4fd57SPeter Zijlstra 
14332d4fd57SPeter Zijlstra 	return index;
14432d4fd57SPeter Zijlstra }
14532d4fd57SPeter Zijlstra 
14630a996fbSRafael J. Wysocki /**
14730a996fbSRafael J. Wysocki  * intel_idle - Ask the processor to enter the given idle state.
14830a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
14930a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
15030a996fbSRafael J. Wysocki  * @index: Target idle state index.
15130a996fbSRafael J. Wysocki  *
15230a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
15330a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
15430a996fbSRafael J. Wysocki  *
15530a996fbSRafael J. Wysocki  * If the local APIC timer is not known to be reliable in the target idle state,
15630a996fbSRafael J. Wysocki  * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
15730a996fbSRafael J. Wysocki  *
15830a996fbSRafael J. Wysocki  * Must be called under local_irq_disable().
15930a996fbSRafael J. Wysocki  */
intel_idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)16030a996fbSRafael J. Wysocki static __cpuidle int intel_idle(struct cpuidle_device *dev,
16130a996fbSRafael J. Wysocki 				struct cpuidle_driver *drv, int index)
16230a996fbSRafael J. Wysocki {
163*08beb0d4SPeter Zijlstra 	return __intel_idle(dev, drv, index, true);
16432d4fd57SPeter Zijlstra }
16530a996fbSRafael J. Wysocki 
intel_idle_irq(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)16632d4fd57SPeter Zijlstra static __cpuidle int intel_idle_irq(struct cpuidle_device *dev,
16732d4fd57SPeter Zijlstra 				    struct cpuidle_driver *drv, int index)
16832d4fd57SPeter Zijlstra {
169*08beb0d4SPeter Zijlstra 	return __intel_idle(dev, drv, index, false);
17030a996fbSRafael J. Wysocki }
17130a996fbSRafael J. Wysocki 
intel_idle_ibrs(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)172bf5835bcSPeter Zijlstra static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
173bf5835bcSPeter Zijlstra 				     struct cpuidle_driver *drv, int index)
174bf5835bcSPeter Zijlstra {
175bf5835bcSPeter Zijlstra 	bool smt_active = sched_smt_active();
176bf5835bcSPeter Zijlstra 	u64 spec_ctrl = spec_ctrl_current();
177bf5835bcSPeter Zijlstra 	int ret;
178bf5835bcSPeter Zijlstra 
179bf5835bcSPeter Zijlstra 	if (smt_active)
1809b461a6fSPeter Zijlstra 		native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
181bf5835bcSPeter Zijlstra 
182*08beb0d4SPeter Zijlstra 	ret = __intel_idle(dev, drv, index, true);
183bf5835bcSPeter Zijlstra 
184bf5835bcSPeter Zijlstra 	if (smt_active)
1859b461a6fSPeter Zijlstra 		native_wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl);
186bf5835bcSPeter Zijlstra 
187bf5835bcSPeter Zijlstra 	return ret;
188bf5835bcSPeter Zijlstra }
189bf5835bcSPeter Zijlstra 
intel_idle_xstate(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)1909f011293SChang S. Bae static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
1919f011293SChang S. Bae 				       struct cpuidle_driver *drv, int index)
1929f011293SChang S. Bae {
1939f011293SChang S. Bae 	fpu_idle_fpregs();
194*08beb0d4SPeter Zijlstra 	return __intel_idle(dev, drv, index, true);
1959f011293SChang S. Bae }
1969f011293SChang S. Bae 
19730a996fbSRafael J. Wysocki /**
19830a996fbSRafael J. Wysocki  * intel_idle_s2idle - Ask the processor to enter the given idle state.
19930a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
20030a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
20130a996fbSRafael J. Wysocki  * @index: Target idle state index.
20230a996fbSRafael J. Wysocki  *
20330a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
20430a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
20530a996fbSRafael J. Wysocki  *
20630a996fbSRafael J. Wysocki  * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
20730a996fbSRafael J. Wysocki  * scheduler tick and suspended scheduler clock on the target CPU.
20830a996fbSRafael J. Wysocki  */
intel_idle_s2idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)209efe97112SNeal Liu static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
21030a996fbSRafael J. Wysocki 				       struct cpuidle_driver *drv, int index)
21130a996fbSRafael J. Wysocki {
21230a996fbSRafael J. Wysocki 	unsigned long ecx = 1; /* break on interrupt flag */
2139f011293SChang S. Bae 	struct cpuidle_state *state = &drv->states[index];
2149f011293SChang S. Bae 	unsigned long eax = flg2MWAIT(state->flags);
2159f011293SChang S. Bae 
2169f011293SChang S. Bae 	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE)
2179f011293SChang S. Bae 		fpu_idle_fpregs();
21830a996fbSRafael J. Wysocki 
21930a996fbSRafael J. Wysocki 	mwait_idle_with_hints(eax, ecx);
220efe97112SNeal Liu 
221efe97112SNeal Liu 	return 0;
22230a996fbSRafael J. Wysocki }
22330a996fbSRafael J. Wysocki 
224b1beab48SLen Brown /*
22526717172SLen Brown  * States are indexed by the cstate number,
22626717172SLen Brown  * which is also the index into the MWAIT hint array.
22726717172SLen Brown  * Thus C0 is a dummy.
22826717172SLen Brown  */
229ab1a8522SRafael J. Wysocki static struct cpuidle_state nehalem_cstates[] __initdata = {
230e022e7ebSLen Brown 	{
231de09cdd0SLen Brown 		.name = "C1",
23226717172SLen Brown 		.desc = "MWAIT 0x00",
233b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
23426717172SLen Brown 		.exit_latency = 3,
23526717172SLen Brown 		.target_residency = 6,
2365fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
23728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
238e022e7ebSLen Brown 	{
239de09cdd0SLen Brown 		.name = "C1E",
24032e95180SLen Brown 		.desc = "MWAIT 0x01",
241e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
24232e95180SLen Brown 		.exit_latency = 10,
24332e95180SLen Brown 		.target_residency = 20,
2445fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
24528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
24632e95180SLen Brown 	{
247de09cdd0SLen Brown 		.name = "C3",
24826717172SLen Brown 		.desc = "MWAIT 0x10",
249b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
25026717172SLen Brown 		.exit_latency = 20,
25126717172SLen Brown 		.target_residency = 80,
2525fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
25328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
254e022e7ebSLen Brown 	{
255de09cdd0SLen Brown 		.name = "C6",
25626717172SLen Brown 		.desc = "MWAIT 0x20",
257b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
25826717172SLen Brown 		.exit_latency = 200,
25926717172SLen Brown 		.target_residency = 800,
2605fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
26128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
262e022e7ebSLen Brown 	{
263e022e7ebSLen Brown 		.enter = NULL }
26426717172SLen Brown };
26526717172SLen Brown 
266ab1a8522SRafael J. Wysocki static struct cpuidle_state snb_cstates[] __initdata = {
267e022e7ebSLen Brown 	{
268de09cdd0SLen Brown 		.name = "C1",
269d13780d4SLen Brown 		.desc = "MWAIT 0x00",
270b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
27132e95180SLen Brown 		.exit_latency = 2,
27232e95180SLen Brown 		.target_residency = 2,
2735fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
27428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
27532e95180SLen Brown 	{
276de09cdd0SLen Brown 		.name = "C1E",
27732e95180SLen Brown 		.desc = "MWAIT 0x01",
278e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
27932e95180SLen Brown 		.exit_latency = 10,
28032e95180SLen Brown 		.target_residency = 20,
2815fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
28228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
283e022e7ebSLen Brown 	{
284de09cdd0SLen Brown 		.name = "C3",
285d13780d4SLen Brown 		.desc = "MWAIT 0x10",
286b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
287d13780d4SLen Brown 		.exit_latency = 80,
288ddbd550dSLen Brown 		.target_residency = 211,
2895fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
29028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
291e022e7ebSLen Brown 	{
292de09cdd0SLen Brown 		.name = "C6",
293d13780d4SLen Brown 		.desc = "MWAIT 0x20",
294b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
295d13780d4SLen Brown 		.exit_latency = 104,
296ddbd550dSLen Brown 		.target_residency = 345,
2975fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
29828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
299e022e7ebSLen Brown 	{
300de09cdd0SLen Brown 		.name = "C7",
301d13780d4SLen Brown 		.desc = "MWAIT 0x30",
302b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
303d13780d4SLen Brown 		.exit_latency = 109,
304ddbd550dSLen Brown 		.target_residency = 345,
3055fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
30628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
307e022e7ebSLen Brown 	{
308e022e7ebSLen Brown 		.enter = NULL }
309d13780d4SLen Brown };
310d13780d4SLen Brown 
311ab1a8522SRafael J. Wysocki static struct cpuidle_state byt_cstates[] __initdata = {
312718987d6SLen Brown 	{
313de09cdd0SLen Brown 		.name = "C1",
314718987d6SLen Brown 		.desc = "MWAIT 0x00",
315b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
316718987d6SLen Brown 		.exit_latency = 1,
317718987d6SLen Brown 		.target_residency = 1,
3185fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
31928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
320718987d6SLen Brown 	{
321de09cdd0SLen Brown 		.name = "C6N",
322718987d6SLen Brown 		.desc = "MWAIT 0x58",
323b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
324d7ef7671SLen Brown 		.exit_latency = 300,
325718987d6SLen Brown 		.target_residency = 275,
3265fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
32728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
328718987d6SLen Brown 	{
329de09cdd0SLen Brown 		.name = "C6S",
330718987d6SLen Brown 		.desc = "MWAIT 0x52",
331b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
332d7ef7671SLen Brown 		.exit_latency = 500,
333718987d6SLen Brown 		.target_residency = 560,
3345fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
33528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
336718987d6SLen Brown 	{
337de09cdd0SLen Brown 		.name = "C7",
338718987d6SLen Brown 		.desc = "MWAIT 0x60",
339b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
340718987d6SLen Brown 		.exit_latency = 1200,
341d7ef7671SLen Brown 		.target_residency = 4000,
3425fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
34328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
344718987d6SLen Brown 	{
345de09cdd0SLen Brown 		.name = "C7S",
346718987d6SLen Brown 		.desc = "MWAIT 0x64",
347b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
348718987d6SLen Brown 		.exit_latency = 10000,
349718987d6SLen Brown 		.target_residency = 20000,
3505fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
35128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
352718987d6SLen Brown 	{
353718987d6SLen Brown 		.enter = NULL }
354718987d6SLen Brown };
355718987d6SLen Brown 
356ab1a8522SRafael J. Wysocki static struct cpuidle_state cht_cstates[] __initdata = {
357cab07a56SLen Brown 	{
358de09cdd0SLen Brown 		.name = "C1",
359cab07a56SLen Brown 		.desc = "MWAIT 0x00",
360cab07a56SLen Brown 		.flags = MWAIT2flg(0x00),
361cab07a56SLen Brown 		.exit_latency = 1,
362cab07a56SLen Brown 		.target_residency = 1,
363cab07a56SLen Brown 		.enter = &intel_idle,
36428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
365cab07a56SLen Brown 	{
366de09cdd0SLen Brown 		.name = "C6N",
367cab07a56SLen Brown 		.desc = "MWAIT 0x58",
368cab07a56SLen Brown 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
369cab07a56SLen Brown 		.exit_latency = 80,
370cab07a56SLen Brown 		.target_residency = 275,
371cab07a56SLen Brown 		.enter = &intel_idle,
37228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
373cab07a56SLen Brown 	{
374de09cdd0SLen Brown 		.name = "C6S",
375cab07a56SLen Brown 		.desc = "MWAIT 0x52",
376cab07a56SLen Brown 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
377cab07a56SLen Brown 		.exit_latency = 200,
378cab07a56SLen Brown 		.target_residency = 560,
379cab07a56SLen Brown 		.enter = &intel_idle,
38028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
381cab07a56SLen Brown 	{
382de09cdd0SLen Brown 		.name = "C7",
383cab07a56SLen Brown 		.desc = "MWAIT 0x60",
384cab07a56SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
385cab07a56SLen Brown 		.exit_latency = 1200,
386cab07a56SLen Brown 		.target_residency = 4000,
387cab07a56SLen Brown 		.enter = &intel_idle,
38828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
389cab07a56SLen Brown 	{
390de09cdd0SLen Brown 		.name = "C7S",
391cab07a56SLen Brown 		.desc = "MWAIT 0x64",
392cab07a56SLen Brown 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
393cab07a56SLen Brown 		.exit_latency = 10000,
394cab07a56SLen Brown 		.target_residency = 20000,
395cab07a56SLen Brown 		.enter = &intel_idle,
39628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
397cab07a56SLen Brown 	{
398cab07a56SLen Brown 		.enter = NULL }
399cab07a56SLen Brown };
400cab07a56SLen Brown 
401ab1a8522SRafael J. Wysocki static struct cpuidle_state ivb_cstates[] __initdata = {
402e022e7ebSLen Brown 	{
403de09cdd0SLen Brown 		.name = "C1",
4046edab08cSLen Brown 		.desc = "MWAIT 0x00",
405b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4066edab08cSLen Brown 		.exit_latency = 1,
4076edab08cSLen Brown 		.target_residency = 1,
4085fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
40928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
410e022e7ebSLen Brown 	{
411de09cdd0SLen Brown 		.name = "C1E",
41232e95180SLen Brown 		.desc = "MWAIT 0x01",
413e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
41432e95180SLen Brown 		.exit_latency = 10,
41532e95180SLen Brown 		.target_residency = 20,
4165fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
41728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
41832e95180SLen Brown 	{
419de09cdd0SLen Brown 		.name = "C3",
4206edab08cSLen Brown 		.desc = "MWAIT 0x10",
421b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4226edab08cSLen Brown 		.exit_latency = 59,
4236edab08cSLen Brown 		.target_residency = 156,
4245fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
42528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
426e022e7ebSLen Brown 	{
427de09cdd0SLen Brown 		.name = "C6",
4286edab08cSLen Brown 		.desc = "MWAIT 0x20",
429b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4306edab08cSLen Brown 		.exit_latency = 80,
4316edab08cSLen Brown 		.target_residency = 300,
4325fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
43328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
434e022e7ebSLen Brown 	{
435de09cdd0SLen Brown 		.name = "C7",
4366edab08cSLen Brown 		.desc = "MWAIT 0x30",
437b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
4386edab08cSLen Brown 		.exit_latency = 87,
4396edab08cSLen Brown 		.target_residency = 300,
4405fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
44128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
442e022e7ebSLen Brown 	{
443e022e7ebSLen Brown 		.enter = NULL }
4446edab08cSLen Brown };
4456edab08cSLen Brown 
446ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates[] __initdata = {
4470138d8f0SLen Brown 	{
448de09cdd0SLen Brown 		.name = "C1",
4490138d8f0SLen Brown 		.desc = "MWAIT 0x00",
450b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4510138d8f0SLen Brown 		.exit_latency = 1,
4520138d8f0SLen Brown 		.target_residency = 1,
4535fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
45428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4550138d8f0SLen Brown 	{
456de09cdd0SLen Brown 		.name = "C1E",
4570138d8f0SLen Brown 		.desc = "MWAIT 0x01",
458e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
4590138d8f0SLen Brown 		.exit_latency = 10,
4600138d8f0SLen Brown 		.target_residency = 80,
4615fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
46228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4630138d8f0SLen Brown 	{
464de09cdd0SLen Brown 		.name = "C3",
4650138d8f0SLen Brown 		.desc = "MWAIT 0x10",
466b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4670138d8f0SLen Brown 		.exit_latency = 59,
4680138d8f0SLen Brown 		.target_residency = 156,
4695fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
47028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4710138d8f0SLen Brown 	{
472de09cdd0SLen Brown 		.name = "C6",
4730138d8f0SLen Brown 		.desc = "MWAIT 0x20",
474b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4750138d8f0SLen Brown 		.exit_latency = 82,
4760138d8f0SLen Brown 		.target_residency = 300,
4775fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
47828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4790138d8f0SLen Brown 	{
4800138d8f0SLen Brown 		.enter = NULL }
4810138d8f0SLen Brown };
4820138d8f0SLen Brown 
483ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_4s[] __initdata = {
4840138d8f0SLen Brown 	{
485de09cdd0SLen Brown 		.name = "C1",
4860138d8f0SLen Brown 		.desc = "MWAIT 0x00",
487b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4880138d8f0SLen Brown 		.exit_latency = 1,
4890138d8f0SLen Brown 		.target_residency = 1,
4905fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
49128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4920138d8f0SLen Brown 	{
493de09cdd0SLen Brown 		.name = "C1E",
4940138d8f0SLen Brown 		.desc = "MWAIT 0x01",
495e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
4960138d8f0SLen Brown 		.exit_latency = 10,
4970138d8f0SLen Brown 		.target_residency = 250,
4985fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
49928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5000138d8f0SLen Brown 	{
501de09cdd0SLen Brown 		.name = "C3",
5020138d8f0SLen Brown 		.desc = "MWAIT 0x10",
503b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5040138d8f0SLen Brown 		.exit_latency = 59,
5050138d8f0SLen Brown 		.target_residency = 300,
5065fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
50728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5080138d8f0SLen Brown 	{
509de09cdd0SLen Brown 		.name = "C6",
5100138d8f0SLen Brown 		.desc = "MWAIT 0x20",
511b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5120138d8f0SLen Brown 		.exit_latency = 84,
5130138d8f0SLen Brown 		.target_residency = 400,
5145fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
51528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5160138d8f0SLen Brown 	{
5170138d8f0SLen Brown 		.enter = NULL }
5180138d8f0SLen Brown };
5190138d8f0SLen Brown 
520ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_8s[] __initdata = {
5210138d8f0SLen Brown 	{
522de09cdd0SLen Brown 		.name = "C1",
5230138d8f0SLen Brown 		.desc = "MWAIT 0x00",
524b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
5250138d8f0SLen Brown 		.exit_latency = 1,
5260138d8f0SLen Brown 		.target_residency = 1,
5275fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
52828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5290138d8f0SLen Brown 	{
530de09cdd0SLen Brown 		.name = "C1E",
5310138d8f0SLen Brown 		.desc = "MWAIT 0x01",
532e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
5330138d8f0SLen Brown 		.exit_latency = 10,
5340138d8f0SLen Brown 		.target_residency = 500,
5355fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
53628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5370138d8f0SLen Brown 	{
538de09cdd0SLen Brown 		.name = "C3",
5390138d8f0SLen Brown 		.desc = "MWAIT 0x10",
540b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5410138d8f0SLen Brown 		.exit_latency = 59,
5420138d8f0SLen Brown 		.target_residency = 600,
5435fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
54428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5450138d8f0SLen Brown 	{
546de09cdd0SLen Brown 		.name = "C6",
5470138d8f0SLen Brown 		.desc = "MWAIT 0x20",
548b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5490138d8f0SLen Brown 		.exit_latency = 88,
5500138d8f0SLen Brown 		.target_residency = 700,
5515fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
55228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5530138d8f0SLen Brown 	{
5540138d8f0SLen Brown 		.enter = NULL }
5550138d8f0SLen Brown };
5560138d8f0SLen Brown 
557ab1a8522SRafael J. Wysocki static struct cpuidle_state hsw_cstates[] __initdata = {
558e022e7ebSLen Brown 	{
559de09cdd0SLen Brown 		.name = "C1",
56085a4d2d4SLen Brown 		.desc = "MWAIT 0x00",
561b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
56285a4d2d4SLen Brown 		.exit_latency = 2,
56385a4d2d4SLen Brown 		.target_residency = 2,
5645fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
56528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
566e022e7ebSLen Brown 	{
567de09cdd0SLen Brown 		.name = "C1E",
56832e95180SLen Brown 		.desc = "MWAIT 0x01",
569e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
57032e95180SLen Brown 		.exit_latency = 10,
57132e95180SLen Brown 		.target_residency = 20,
5725fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
57328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
57432e95180SLen Brown 	{
575de09cdd0SLen Brown 		.name = "C3",
57685a4d2d4SLen Brown 		.desc = "MWAIT 0x10",
577b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
57885a4d2d4SLen Brown 		.exit_latency = 33,
57985a4d2d4SLen Brown 		.target_residency = 100,
5805fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
58128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
582e022e7ebSLen Brown 	{
583de09cdd0SLen Brown 		.name = "C6",
58485a4d2d4SLen Brown 		.desc = "MWAIT 0x20",
585b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
58685a4d2d4SLen Brown 		.exit_latency = 133,
58785a4d2d4SLen Brown 		.target_residency = 400,
5885fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
58928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
590e022e7ebSLen Brown 	{
591de09cdd0SLen Brown 		.name = "C7s",
59285a4d2d4SLen Brown 		.desc = "MWAIT 0x32",
593b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
59485a4d2d4SLen Brown 		.exit_latency = 166,
59585a4d2d4SLen Brown 		.target_residency = 500,
5965fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
59728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
598e022e7ebSLen Brown 	{
599de09cdd0SLen Brown 		.name = "C8",
60086239cebSLen Brown 		.desc = "MWAIT 0x40",
601b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
60286239cebSLen Brown 		.exit_latency = 300,
60386239cebSLen Brown 		.target_residency = 900,
6045fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
60528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
60686239cebSLen Brown 	{
607de09cdd0SLen Brown 		.name = "C9",
60886239cebSLen Brown 		.desc = "MWAIT 0x50",
609b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
61086239cebSLen Brown 		.exit_latency = 600,
61186239cebSLen Brown 		.target_residency = 1800,
6125fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
61328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
61486239cebSLen Brown 	{
615de09cdd0SLen Brown 		.name = "C10",
61686239cebSLen Brown 		.desc = "MWAIT 0x60",
617b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
61886239cebSLen Brown 		.exit_latency = 2600,
61986239cebSLen Brown 		.target_residency = 7700,
6205fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
62128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
62286239cebSLen Brown 	{
623e022e7ebSLen Brown 		.enter = NULL }
62485a4d2d4SLen Brown };
625ab1a8522SRafael J. Wysocki static struct cpuidle_state bdw_cstates[] __initdata = {
626a138b568SLen Brown 	{
627de09cdd0SLen Brown 		.name = "C1",
628a138b568SLen Brown 		.desc = "MWAIT 0x00",
629b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
630a138b568SLen Brown 		.exit_latency = 2,
631a138b568SLen Brown 		.target_residency = 2,
6325fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
63328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
634a138b568SLen Brown 	{
635de09cdd0SLen Brown 		.name = "C1E",
636a138b568SLen Brown 		.desc = "MWAIT 0x01",
637e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
638a138b568SLen Brown 		.exit_latency = 10,
639a138b568SLen Brown 		.target_residency = 20,
6405fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
64128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
642a138b568SLen Brown 	{
643de09cdd0SLen Brown 		.name = "C3",
644a138b568SLen Brown 		.desc = "MWAIT 0x10",
645b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
646a138b568SLen Brown 		.exit_latency = 40,
647a138b568SLen Brown 		.target_residency = 100,
6485fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
64928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
650a138b568SLen Brown 	{
651de09cdd0SLen Brown 		.name = "C6",
652a138b568SLen Brown 		.desc = "MWAIT 0x20",
653b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
654a138b568SLen Brown 		.exit_latency = 133,
655a138b568SLen Brown 		.target_residency = 400,
6565fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
65728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
658a138b568SLen Brown 	{
659de09cdd0SLen Brown 		.name = "C7s",
660a138b568SLen Brown 		.desc = "MWAIT 0x32",
661b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
662a138b568SLen Brown 		.exit_latency = 166,
663a138b568SLen Brown 		.target_residency = 500,
6645fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
66528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
666a138b568SLen Brown 	{
667de09cdd0SLen Brown 		.name = "C8",
668a138b568SLen Brown 		.desc = "MWAIT 0x40",
669b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
670a138b568SLen Brown 		.exit_latency = 300,
671a138b568SLen Brown 		.target_residency = 900,
6725fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
67328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
674a138b568SLen Brown 	{
675de09cdd0SLen Brown 		.name = "C9",
676a138b568SLen Brown 		.desc = "MWAIT 0x50",
677b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
678a138b568SLen Brown 		.exit_latency = 600,
679a138b568SLen Brown 		.target_residency = 1800,
6805fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
68128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
682a138b568SLen Brown 	{
683de09cdd0SLen Brown 		.name = "C10",
684a138b568SLen Brown 		.desc = "MWAIT 0x60",
685b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
686a138b568SLen Brown 		.exit_latency = 2600,
687a138b568SLen Brown 		.target_residency = 7700,
6885fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
68928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
690a138b568SLen Brown 	{
691a138b568SLen Brown 		.enter = NULL }
692a138b568SLen Brown };
69385a4d2d4SLen Brown 
694ab1a8522SRafael J. Wysocki static struct cpuidle_state skl_cstates[] __initdata = {
695493f133fSLen Brown 	{
696de09cdd0SLen Brown 		.name = "C1",
697493f133fSLen Brown 		.desc = "MWAIT 0x00",
698493f133fSLen Brown 		.flags = MWAIT2flg(0x00),
699493f133fSLen Brown 		.exit_latency = 2,
700493f133fSLen Brown 		.target_residency = 2,
701493f133fSLen Brown 		.enter = &intel_idle,
70228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
703493f133fSLen Brown 	{
704de09cdd0SLen Brown 		.name = "C1E",
705493f133fSLen Brown 		.desc = "MWAIT 0x01",
706e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
707493f133fSLen Brown 		.exit_latency = 10,
708493f133fSLen Brown 		.target_residency = 20,
709493f133fSLen Brown 		.enter = &intel_idle,
71028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
711493f133fSLen Brown 	{
712de09cdd0SLen Brown 		.name = "C3",
713493f133fSLen Brown 		.desc = "MWAIT 0x10",
714493f133fSLen Brown 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
715493f133fSLen Brown 		.exit_latency = 70,
716493f133fSLen Brown 		.target_residency = 100,
717493f133fSLen Brown 		.enter = &intel_idle,
71828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
719493f133fSLen Brown 	{
720de09cdd0SLen Brown 		.name = "C6",
721493f133fSLen Brown 		.desc = "MWAIT 0x20",
722bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
723135919a3SLen Brown 		.exit_latency = 85,
724493f133fSLen Brown 		.target_residency = 200,
725493f133fSLen Brown 		.enter = &intel_idle,
72628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
727493f133fSLen Brown 	{
728de09cdd0SLen Brown 		.name = "C7s",
729493f133fSLen Brown 		.desc = "MWAIT 0x33",
730bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
731493f133fSLen Brown 		.exit_latency = 124,
732493f133fSLen Brown 		.target_residency = 800,
733493f133fSLen Brown 		.enter = &intel_idle,
73428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
735493f133fSLen Brown 	{
736de09cdd0SLen Brown 		.name = "C8",
737493f133fSLen Brown 		.desc = "MWAIT 0x40",
738bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
739135919a3SLen Brown 		.exit_latency = 200,
740493f133fSLen Brown 		.target_residency = 800,
741493f133fSLen Brown 		.enter = &intel_idle,
74228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
743493f133fSLen Brown 	{
744de09cdd0SLen Brown 		.name = "C9",
745135919a3SLen Brown 		.desc = "MWAIT 0x50",
746bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
747135919a3SLen Brown 		.exit_latency = 480,
748135919a3SLen Brown 		.target_residency = 5000,
749135919a3SLen Brown 		.enter = &intel_idle,
75028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
751135919a3SLen Brown 	{
752de09cdd0SLen Brown 		.name = "C10",
753493f133fSLen Brown 		.desc = "MWAIT 0x60",
754bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
755493f133fSLen Brown 		.exit_latency = 890,
756493f133fSLen Brown 		.target_residency = 5000,
757493f133fSLen Brown 		.enter = &intel_idle,
75828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
759493f133fSLen Brown 	{
760493f133fSLen Brown 		.enter = NULL }
761493f133fSLen Brown };
762493f133fSLen Brown 
763ab1a8522SRafael J. Wysocki static struct cpuidle_state skx_cstates[] __initdata = {
764f9e71657SLen Brown 	{
765de09cdd0SLen Brown 		.name = "C1",
766f9e71657SLen Brown 		.desc = "MWAIT 0x00",
767c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
768f9e71657SLen Brown 		.exit_latency = 2,
769f9e71657SLen Brown 		.target_residency = 2,
770f9e71657SLen Brown 		.enter = &intel_idle,
77128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
772f9e71657SLen Brown 	{
773de09cdd0SLen Brown 		.name = "C1E",
774f9e71657SLen Brown 		.desc = "MWAIT 0x01",
775e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
776f9e71657SLen Brown 		.exit_latency = 10,
777f9e71657SLen Brown 		.target_residency = 20,
778f9e71657SLen Brown 		.enter = &intel_idle,
77928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
780f9e71657SLen Brown 	{
781de09cdd0SLen Brown 		.name = "C6",
782f9e71657SLen Brown 		.desc = "MWAIT 0x20",
783bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
784f9e71657SLen Brown 		.exit_latency = 133,
785f9e71657SLen Brown 		.target_residency = 600,
786f9e71657SLen Brown 		.enter = &intel_idle,
78728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
788f9e71657SLen Brown 	{
789f9e71657SLen Brown 		.enter = NULL }
790f9e71657SLen Brown };
791f9e71657SLen Brown 
792a472ad2bSChen Yu static struct cpuidle_state icx_cstates[] __initdata = {
793a472ad2bSChen Yu 	{
794a472ad2bSChen Yu 		.name = "C1",
795a472ad2bSChen Yu 		.desc = "MWAIT 0x00",
796c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
797a472ad2bSChen Yu 		.exit_latency = 1,
798a472ad2bSChen Yu 		.target_residency = 1,
799a472ad2bSChen Yu 		.enter = &intel_idle,
800a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
801a472ad2bSChen Yu 	{
802a472ad2bSChen Yu 		.name = "C1E",
803a472ad2bSChen Yu 		.desc = "MWAIT 0x01",
804a472ad2bSChen Yu 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
805a472ad2bSChen Yu 		.exit_latency = 4,
806a472ad2bSChen Yu 		.target_residency = 4,
807a472ad2bSChen Yu 		.enter = &intel_idle,
808a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
809a472ad2bSChen Yu 	{
810a472ad2bSChen Yu 		.name = "C6",
811a472ad2bSChen Yu 		.desc = "MWAIT 0x20",
812a472ad2bSChen Yu 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
813d484b8bfSArtem Bityutskiy 		.exit_latency = 170,
814d484b8bfSArtem Bityutskiy 		.target_residency = 600,
815a472ad2bSChen Yu 		.enter = &intel_idle,
816a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
817a472ad2bSChen Yu 	{
818a472ad2bSChen Yu 		.enter = NULL }
819a472ad2bSChen Yu };
820a472ad2bSChen Yu 
8219edf3c0fSArtem Bityutskiy /*
822d1cf8bbfSZhang Rui  * On AlderLake C1 has to be disabled if C1E is enabled, and vice versa.
823d1cf8bbfSZhang Rui  * C1E is enabled only if "C1E promotion" bit is set in MSR_IA32_POWER_CTL.
824d1cf8bbfSZhang Rui  * But in this case there is effectively no C1, because C1 requests are
825d1cf8bbfSZhang Rui  * promoted to C1E. If the "C1E promotion" bit is cleared, then both C1
826d1cf8bbfSZhang Rui  * and C1E requests end up with C1, so there is effectively no C1E.
827d1cf8bbfSZhang Rui  *
828d1cf8bbfSZhang Rui  * By default we enable C1E and disable C1 by marking it with
829d1cf8bbfSZhang Rui  * 'CPUIDLE_FLAG_UNUSABLE'.
830d1cf8bbfSZhang Rui  */
831d1cf8bbfSZhang Rui static struct cpuidle_state adl_cstates[] __initdata = {
832d1cf8bbfSZhang Rui 	{
833d1cf8bbfSZhang Rui 		.name = "C1",
834d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
835d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
836d1cf8bbfSZhang Rui 		.exit_latency = 1,
837d1cf8bbfSZhang Rui 		.target_residency = 1,
838d1cf8bbfSZhang Rui 		.enter = &intel_idle,
839d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
840d1cf8bbfSZhang Rui 	{
841d1cf8bbfSZhang Rui 		.name = "C1E",
842d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
843d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
844d1cf8bbfSZhang Rui 		.exit_latency = 2,
845d1cf8bbfSZhang Rui 		.target_residency = 4,
846d1cf8bbfSZhang Rui 		.enter = &intel_idle,
847d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
848d1cf8bbfSZhang Rui 	{
849d1cf8bbfSZhang Rui 		.name = "C6",
850d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
851d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
852d1cf8bbfSZhang Rui 		.exit_latency = 220,
853d1cf8bbfSZhang Rui 		.target_residency = 600,
854d1cf8bbfSZhang Rui 		.enter = &intel_idle,
855d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
856d1cf8bbfSZhang Rui 	{
857d1cf8bbfSZhang Rui 		.name = "C8",
858d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
859d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
860d1cf8bbfSZhang Rui 		.exit_latency = 280,
861d1cf8bbfSZhang Rui 		.target_residency = 800,
862d1cf8bbfSZhang Rui 		.enter = &intel_idle,
863d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
864d1cf8bbfSZhang Rui 	{
865d1cf8bbfSZhang Rui 		.name = "C10",
866d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
867d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
868d1cf8bbfSZhang Rui 		.exit_latency = 680,
869d1cf8bbfSZhang Rui 		.target_residency = 2000,
870d1cf8bbfSZhang Rui 		.enter = &intel_idle,
871d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
872d1cf8bbfSZhang Rui 	{
873d1cf8bbfSZhang Rui 		.enter = NULL }
874d1cf8bbfSZhang Rui };
875d1cf8bbfSZhang Rui 
876d1cf8bbfSZhang Rui static struct cpuidle_state adl_l_cstates[] __initdata = {
877d1cf8bbfSZhang Rui 	{
878d1cf8bbfSZhang Rui 		.name = "C1",
879d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
880d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
881d1cf8bbfSZhang Rui 		.exit_latency = 1,
882d1cf8bbfSZhang Rui 		.target_residency = 1,
883d1cf8bbfSZhang Rui 		.enter = &intel_idle,
884d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
885d1cf8bbfSZhang Rui 	{
886d1cf8bbfSZhang Rui 		.name = "C1E",
887d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
888d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
889d1cf8bbfSZhang Rui 		.exit_latency = 2,
890d1cf8bbfSZhang Rui 		.target_residency = 4,
891d1cf8bbfSZhang Rui 		.enter = &intel_idle,
892d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
893d1cf8bbfSZhang Rui 	{
894d1cf8bbfSZhang Rui 		.name = "C6",
895d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
896d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
897d1cf8bbfSZhang Rui 		.exit_latency = 170,
898d1cf8bbfSZhang Rui 		.target_residency = 500,
899d1cf8bbfSZhang Rui 		.enter = &intel_idle,
900d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
901d1cf8bbfSZhang Rui 	{
902d1cf8bbfSZhang Rui 		.name = "C8",
903d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
904d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
905d1cf8bbfSZhang Rui 		.exit_latency = 200,
906d1cf8bbfSZhang Rui 		.target_residency = 600,
907d1cf8bbfSZhang Rui 		.enter = &intel_idle,
908d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
909d1cf8bbfSZhang Rui 	{
910d1cf8bbfSZhang Rui 		.name = "C10",
911d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
912d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
913d1cf8bbfSZhang Rui 		.exit_latency = 230,
914d1cf8bbfSZhang Rui 		.target_residency = 700,
915d1cf8bbfSZhang Rui 		.enter = &intel_idle,
916d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
917d1cf8bbfSZhang Rui 	{
918d1cf8bbfSZhang Rui 		.enter = NULL }
919d1cf8bbfSZhang Rui };
920d1cf8bbfSZhang Rui 
921882cdb06SPeter Zijlstra static struct cpuidle_state gmt_cstates[] __initdata = {
92265c0c236SZhang Rui 	{
92365c0c236SZhang Rui 		.name = "C1",
92465c0c236SZhang Rui 		.desc = "MWAIT 0x00",
92565c0c236SZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
92665c0c236SZhang Rui 		.exit_latency = 1,
92765c0c236SZhang Rui 		.target_residency = 1,
92865c0c236SZhang Rui 		.enter = &intel_idle,
92965c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
93065c0c236SZhang Rui 	{
93165c0c236SZhang Rui 		.name = "C1E",
93265c0c236SZhang Rui 		.desc = "MWAIT 0x01",
93365c0c236SZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
93465c0c236SZhang Rui 		.exit_latency = 2,
93565c0c236SZhang Rui 		.target_residency = 4,
93665c0c236SZhang Rui 		.enter = &intel_idle,
93765c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
93865c0c236SZhang Rui 	{
93965c0c236SZhang Rui 		.name = "C6",
94065c0c236SZhang Rui 		.desc = "MWAIT 0x20",
94165c0c236SZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
94265c0c236SZhang Rui 		.exit_latency = 195,
94365c0c236SZhang Rui 		.target_residency = 585,
94465c0c236SZhang Rui 		.enter = &intel_idle,
94565c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
94665c0c236SZhang Rui 	{
94765c0c236SZhang Rui 		.name = "C8",
94865c0c236SZhang Rui 		.desc = "MWAIT 0x40",
94965c0c236SZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
95065c0c236SZhang Rui 		.exit_latency = 260,
95165c0c236SZhang Rui 		.target_residency = 1040,
95265c0c236SZhang Rui 		.enter = &intel_idle,
95365c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
95465c0c236SZhang Rui 	{
95565c0c236SZhang Rui 		.name = "C10",
95665c0c236SZhang Rui 		.desc = "MWAIT 0x60",
95765c0c236SZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
95865c0c236SZhang Rui 		.exit_latency = 660,
95965c0c236SZhang Rui 		.target_residency = 1980,
96065c0c236SZhang Rui 		.enter = &intel_idle,
96165c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
96265c0c236SZhang Rui 	{
96365c0c236SZhang Rui 		.enter = NULL }
96465c0c236SZhang Rui };
96565c0c236SZhang Rui 
9669edf3c0fSArtem Bityutskiy static struct cpuidle_state spr_cstates[] __initdata = {
9679edf3c0fSArtem Bityutskiy 	{
9689edf3c0fSArtem Bityutskiy 		.name = "C1",
9699edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x00",
9709edf3c0fSArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
9719edf3c0fSArtem Bityutskiy 		.exit_latency = 1,
9729edf3c0fSArtem Bityutskiy 		.target_residency = 1,
9739edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9749edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9759edf3c0fSArtem Bityutskiy 	{
9769edf3c0fSArtem Bityutskiy 		.name = "C1E",
9779edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x01",
9781548fac4SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
9799edf3c0fSArtem Bityutskiy 		.exit_latency = 2,
9809edf3c0fSArtem Bityutskiy 		.target_residency = 4,
9819edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9829edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9839edf3c0fSArtem Bityutskiy 	{
9849edf3c0fSArtem Bityutskiy 		.name = "C6",
9859edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x20",
9869f011293SChang S. Bae 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
9879f011293SChang S. Bae 					   CPUIDLE_FLAG_INIT_XSTATE,
9889edf3c0fSArtem Bityutskiy 		.exit_latency = 290,
9899edf3c0fSArtem Bityutskiy 		.target_residency = 800,
9909edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9919edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9929edf3c0fSArtem Bityutskiy 	{
9939edf3c0fSArtem Bityutskiy 		.enter = NULL }
9949edf3c0fSArtem Bityutskiy };
9959edf3c0fSArtem Bityutskiy 
996ab1a8522SRafael J. Wysocki static struct cpuidle_state atom_cstates[] __initdata = {
997e022e7ebSLen Brown 	{
998de09cdd0SLen Brown 		.name = "C1E",
99926717172SLen Brown 		.desc = "MWAIT 0x00",
1000b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
100132e95180SLen Brown 		.exit_latency = 10,
100232e95180SLen Brown 		.target_residency = 20,
10035fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
100428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1005e022e7ebSLen Brown 	{
1006de09cdd0SLen Brown 		.name = "C2",
100726717172SLen Brown 		.desc = "MWAIT 0x10",
1008b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10),
100926717172SLen Brown 		.exit_latency = 20,
101026717172SLen Brown 		.target_residency = 80,
10115fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
101228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1013e022e7ebSLen Brown 	{
1014de09cdd0SLen Brown 		.name = "C4",
101526717172SLen Brown 		.desc = "MWAIT 0x30",
1016b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
101726717172SLen Brown 		.exit_latency = 100,
101826717172SLen Brown 		.target_residency = 400,
10195fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
102028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1021e022e7ebSLen Brown 	{
1022de09cdd0SLen Brown 		.name = "C6",
10237fcca7d9SLen Brown 		.desc = "MWAIT 0x52",
1024b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10257fcca7d9SLen Brown 		.exit_latency = 140,
10267fcca7d9SLen Brown 		.target_residency = 560,
10275fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
102828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1029e022e7ebSLen Brown 	{
1030e022e7ebSLen Brown 		.enter = NULL }
103126717172SLen Brown };
1032ab1a8522SRafael J. Wysocki static struct cpuidle_state tangier_cstates[] __initdata = {
10335e7ec268SAndy Shevchenko 	{
1034de09cdd0SLen Brown 		.name = "C1",
10355e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x00",
10365e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x00),
10375e7ec268SAndy Shevchenko 		.exit_latency = 1,
10385e7ec268SAndy Shevchenko 		.target_residency = 4,
10395e7ec268SAndy Shevchenko 		.enter = &intel_idle,
104028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10415e7ec268SAndy Shevchenko 	{
1042de09cdd0SLen Brown 		.name = "C4",
10435e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x30",
10445e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
10455e7ec268SAndy Shevchenko 		.exit_latency = 100,
10465e7ec268SAndy Shevchenko 		.target_residency = 400,
10475e7ec268SAndy Shevchenko 		.enter = &intel_idle,
104828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10495e7ec268SAndy Shevchenko 	{
1050de09cdd0SLen Brown 		.name = "C6",
10515e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x52",
10525e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10535e7ec268SAndy Shevchenko 		.exit_latency = 140,
10545e7ec268SAndy Shevchenko 		.target_residency = 560,
10555e7ec268SAndy Shevchenko 		.enter = &intel_idle,
105628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10575e7ec268SAndy Shevchenko 	{
1058de09cdd0SLen Brown 		.name = "C7",
10595e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x60",
10605e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
10615e7ec268SAndy Shevchenko 		.exit_latency = 1200,
10625e7ec268SAndy Shevchenko 		.target_residency = 4000,
10635e7ec268SAndy Shevchenko 		.enter = &intel_idle,
106428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10655e7ec268SAndy Shevchenko 	{
1066de09cdd0SLen Brown 		.name = "C9",
10675e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x64",
10685e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
10695e7ec268SAndy Shevchenko 		.exit_latency = 10000,
10705e7ec268SAndy Shevchenko 		.target_residency = 20000,
10715e7ec268SAndy Shevchenko 		.enter = &intel_idle,
107228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10735e7ec268SAndy Shevchenko 	{
10745e7ec268SAndy Shevchenko 		.enter = NULL }
10755e7ec268SAndy Shevchenko };
1076ab1a8522SRafael J. Wysocki static struct cpuidle_state avn_cstates[] __initdata = {
1077fab04b22SLen Brown 	{
1078de09cdd0SLen Brown 		.name = "C1",
1079fab04b22SLen Brown 		.desc = "MWAIT 0x00",
1080b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
1081fab04b22SLen Brown 		.exit_latency = 2,
1082fab04b22SLen Brown 		.target_residency = 2,
10835fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
108428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1085fab04b22SLen Brown 	{
1086de09cdd0SLen Brown 		.name = "C6",
1087fab04b22SLen Brown 		.desc = "MWAIT 0x51",
1088b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED,
1089fab04b22SLen Brown 		.exit_latency = 15,
1090fab04b22SLen Brown 		.target_residency = 45,
10915fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
109228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
109388390996SJiang Liu 	{
109488390996SJiang Liu 		.enter = NULL }
1095fab04b22SLen Brown };
1096ab1a8522SRafael J. Wysocki static struct cpuidle_state knl_cstates[] __initdata = {
1097281baf7aSDasaratharaman Chandramouli 	{
1098de09cdd0SLen Brown 		.name = "C1",
1099281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x00",
1100281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x00),
1101281baf7aSDasaratharaman Chandramouli 		.exit_latency = 1,
1102281baf7aSDasaratharaman Chandramouli 		.target_residency = 2,
1103281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
110428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1105281baf7aSDasaratharaman Chandramouli 	{
1106de09cdd0SLen Brown 		.name = "C6",
1107281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x10",
1108281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
1109281baf7aSDasaratharaman Chandramouli 		.exit_latency = 120,
1110281baf7aSDasaratharaman Chandramouli 		.target_residency = 500,
1111281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
111228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1113281baf7aSDasaratharaman Chandramouli 	{
1114281baf7aSDasaratharaman Chandramouli 		.enter = NULL }
1115281baf7aSDasaratharaman Chandramouli };
111626717172SLen Brown 
1117ab1a8522SRafael J. Wysocki static struct cpuidle_state bxt_cstates[] __initdata = {
11185dcef694SLen Brown 	{
1119de09cdd0SLen Brown 		.name = "C1",
11205dcef694SLen Brown 		.desc = "MWAIT 0x00",
11215dcef694SLen Brown 		.flags = MWAIT2flg(0x00),
11225dcef694SLen Brown 		.exit_latency = 2,
11235dcef694SLen Brown 		.target_residency = 2,
11245dcef694SLen Brown 		.enter = &intel_idle,
112528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11265dcef694SLen Brown 	{
1127de09cdd0SLen Brown 		.name = "C1E",
11285dcef694SLen Brown 		.desc = "MWAIT 0x01",
1129e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11305dcef694SLen Brown 		.exit_latency = 10,
11315dcef694SLen Brown 		.target_residency = 20,
11325dcef694SLen Brown 		.enter = &intel_idle,
113328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11345dcef694SLen Brown 	{
1135de09cdd0SLen Brown 		.name = "C6",
11365dcef694SLen Brown 		.desc = "MWAIT 0x20",
11375dcef694SLen Brown 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
11385dcef694SLen Brown 		.exit_latency = 133,
11395dcef694SLen Brown 		.target_residency = 133,
11405dcef694SLen Brown 		.enter = &intel_idle,
114128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11425dcef694SLen Brown 	{
1143de09cdd0SLen Brown 		.name = "C7s",
11445dcef694SLen Brown 		.desc = "MWAIT 0x31",
11455dcef694SLen Brown 		.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
11465dcef694SLen Brown 		.exit_latency = 155,
11475dcef694SLen Brown 		.target_residency = 155,
11485dcef694SLen Brown 		.enter = &intel_idle,
114928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11505dcef694SLen Brown 	{
1151de09cdd0SLen Brown 		.name = "C8",
11525dcef694SLen Brown 		.desc = "MWAIT 0x40",
11535dcef694SLen Brown 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
11545dcef694SLen Brown 		.exit_latency = 1000,
11555dcef694SLen Brown 		.target_residency = 1000,
11565dcef694SLen Brown 		.enter = &intel_idle,
115728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11585dcef694SLen Brown 	{
1159de09cdd0SLen Brown 		.name = "C9",
11605dcef694SLen Brown 		.desc = "MWAIT 0x50",
11615dcef694SLen Brown 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
11625dcef694SLen Brown 		.exit_latency = 2000,
11635dcef694SLen Brown 		.target_residency = 2000,
11645dcef694SLen Brown 		.enter = &intel_idle,
116528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11665dcef694SLen Brown 	{
1167de09cdd0SLen Brown 		.name = "C10",
11685dcef694SLen Brown 		.desc = "MWAIT 0x60",
11695dcef694SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
11705dcef694SLen Brown 		.exit_latency = 10000,
11715dcef694SLen Brown 		.target_residency = 10000,
11725dcef694SLen Brown 		.enter = &intel_idle,
117328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11745dcef694SLen Brown 	{
11755dcef694SLen Brown 		.enter = NULL }
11765dcef694SLen Brown };
11775dcef694SLen Brown 
1178ab1a8522SRafael J. Wysocki static struct cpuidle_state dnv_cstates[] __initdata = {
11790080d65bSJacob Pan 	{
1180de09cdd0SLen Brown 		.name = "C1",
11810080d65bSJacob Pan 		.desc = "MWAIT 0x00",
11820080d65bSJacob Pan 		.flags = MWAIT2flg(0x00),
11830080d65bSJacob Pan 		.exit_latency = 2,
11840080d65bSJacob Pan 		.target_residency = 2,
11850080d65bSJacob Pan 		.enter = &intel_idle,
118628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11870080d65bSJacob Pan 	{
1188de09cdd0SLen Brown 		.name = "C1E",
11890080d65bSJacob Pan 		.desc = "MWAIT 0x01",
1190e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11910080d65bSJacob Pan 		.exit_latency = 10,
11920080d65bSJacob Pan 		.target_residency = 20,
11930080d65bSJacob Pan 		.enter = &intel_idle,
119428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11950080d65bSJacob Pan 	{
1196de09cdd0SLen Brown 		.name = "C6",
11970080d65bSJacob Pan 		.desc = "MWAIT 0x20",
11980080d65bSJacob Pan 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
11990080d65bSJacob Pan 		.exit_latency = 50,
12000080d65bSJacob Pan 		.target_residency = 500,
12010080d65bSJacob Pan 		.enter = &intel_idle,
120228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12030080d65bSJacob Pan 	{
12040080d65bSJacob Pan 		.enter = NULL }
12050080d65bSJacob Pan };
12060080d65bSJacob Pan 
12079cf93f05SArtem Bityutskiy /*
12089cf93f05SArtem Bityutskiy  * Note, depending on HW and FW revision, SnowRidge SoC may or may not support
12099cf93f05SArtem Bityutskiy  * C6, and this is indicated in the CPUID mwait leaf.
12109cf93f05SArtem Bityutskiy  */
12119cf93f05SArtem Bityutskiy static struct cpuidle_state snr_cstates[] __initdata = {
12129cf93f05SArtem Bityutskiy 	{
12139cf93f05SArtem Bityutskiy 		.name = "C1",
12149cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x00",
12159cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
12169cf93f05SArtem Bityutskiy 		.exit_latency = 2,
12179cf93f05SArtem Bityutskiy 		.target_residency = 2,
12189cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12199cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12209cf93f05SArtem Bityutskiy 	{
12219cf93f05SArtem Bityutskiy 		.name = "C1E",
12229cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x01",
12239cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
12249cf93f05SArtem Bityutskiy 		.exit_latency = 15,
12259cf93f05SArtem Bityutskiy 		.target_residency = 25,
12269cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12279cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12289cf93f05SArtem Bityutskiy 	{
12299cf93f05SArtem Bityutskiy 		.name = "C6",
12309cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x20",
12319cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
12329cf93f05SArtem Bityutskiy 		.exit_latency = 130,
12339cf93f05SArtem Bityutskiy 		.target_residency = 500,
12349cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12359cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12369cf93f05SArtem Bityutskiy 	{
12379cf93f05SArtem Bityutskiy 		.enter = NULL }
12389cf93f05SArtem Bityutskiy };
12399cf93f05SArtem Bityutskiy 
1240ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nehalem __initconst = {
1241b66b8b9aSAndi Kleen 	.state_table = nehalem_cstates,
1242b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
124332e95180SLen Brown 	.disable_promotion_to_c1e = true,
1244b66b8b9aSAndi Kleen };
1245b66b8b9aSAndi Kleen 
1246ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nhx __initconst = {
1247e6d4f08aSRafael J. Wysocki 	.state_table = nehalem_cstates,
1248e6d4f08aSRafael J. Wysocki 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
1249e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1250e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1251e6d4f08aSRafael J. Wysocki };
1252e6d4f08aSRafael J. Wysocki 
1253ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_atom __initconst = {
1254b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1255b66b8b9aSAndi Kleen };
1256b66b8b9aSAndi Kleen 
1257ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_tangier __initconst = {
12585e7ec268SAndy Shevchenko 	.state_table = tangier_cstates,
12595e7ec268SAndy Shevchenko };
12605e7ec268SAndy Shevchenko 
1261ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_lincroft __initconst = {
1262b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1263b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
1264b66b8b9aSAndi Kleen };
1265b66b8b9aSAndi Kleen 
1266ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snb __initconst = {
1267b66b8b9aSAndi Kleen 	.state_table = snb_cstates,
126832e95180SLen Brown 	.disable_promotion_to_c1e = true,
1269b66b8b9aSAndi Kleen };
1270b66b8b9aSAndi Kleen 
1271ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snx __initconst = {
1272e6d4f08aSRafael J. Wysocki 	.state_table = snb_cstates,
1273e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1274e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1275e6d4f08aSRafael J. Wysocki };
1276e6d4f08aSRafael J. Wysocki 
1277ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_byt __initconst = {
1278718987d6SLen Brown 	.state_table = byt_cstates,
1279718987d6SLen Brown 	.disable_promotion_to_c1e = true,
12808c058d53SLen Brown 	.byt_auto_demotion_disable_flag = true,
1281718987d6SLen Brown };
1282718987d6SLen Brown 
1283ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_cht __initconst = {
1284cab07a56SLen Brown 	.state_table = cht_cstates,
1285cab07a56SLen Brown 	.disable_promotion_to_c1e = true,
1286cab07a56SLen Brown 	.byt_auto_demotion_disable_flag = true,
1287cab07a56SLen Brown };
1288cab07a56SLen Brown 
1289ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivb __initconst = {
12906edab08cSLen Brown 	.state_table = ivb_cstates,
129132e95180SLen Brown 	.disable_promotion_to_c1e = true,
12926edab08cSLen Brown };
12936edab08cSLen Brown 
1294ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivt __initconst = {
12950138d8f0SLen Brown 	.state_table = ivt_cstates,
12960138d8f0SLen Brown 	.disable_promotion_to_c1e = true,
1297e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
12980138d8f0SLen Brown };
12990138d8f0SLen Brown 
1300ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsw __initconst = {
130185a4d2d4SLen Brown 	.state_table = hsw_cstates,
130232e95180SLen Brown 	.disable_promotion_to_c1e = true,
130385a4d2d4SLen Brown };
130485a4d2d4SLen Brown 
1305ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsx __initconst = {
1306e6d4f08aSRafael J. Wysocki 	.state_table = hsw_cstates,
1307e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1308e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1309e6d4f08aSRafael J. Wysocki };
1310e6d4f08aSRafael J. Wysocki 
1311ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdw __initconst = {
1312a138b568SLen Brown 	.state_table = bdw_cstates,
1313a138b568SLen Brown 	.disable_promotion_to_c1e = true,
1314a138b568SLen Brown };
1315a138b568SLen Brown 
1316ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdx __initconst = {
1317e6d4f08aSRafael J. Wysocki 	.state_table = bdw_cstates,
1318e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1319e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1320e6d4f08aSRafael J. Wysocki };
1321e6d4f08aSRafael J. Wysocki 
1322ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skl __initconst = {
1323493f133fSLen Brown 	.state_table = skl_cstates,
1324493f133fSLen Brown 	.disable_promotion_to_c1e = true,
1325493f133fSLen Brown };
1326493f133fSLen Brown 
1327ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skx __initconst = {
1328f9e71657SLen Brown 	.state_table = skx_cstates,
1329f9e71657SLen Brown 	.disable_promotion_to_c1e = true,
1330e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1331f9e71657SLen Brown };
1332493f133fSLen Brown 
1333a472ad2bSChen Yu static const struct idle_cpu idle_cpu_icx __initconst = {
1334a472ad2bSChen Yu 	.state_table = icx_cstates,
1335a472ad2bSChen Yu 	.disable_promotion_to_c1e = true,
1336a472ad2bSChen Yu 	.use_acpi = true,
1337a472ad2bSChen Yu };
1338a472ad2bSChen Yu 
1339d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl __initconst = {
1340d1cf8bbfSZhang Rui 	.state_table = adl_cstates,
1341d1cf8bbfSZhang Rui };
1342d1cf8bbfSZhang Rui 
1343d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl_l __initconst = {
1344d1cf8bbfSZhang Rui 	.state_table = adl_l_cstates,
1345d1cf8bbfSZhang Rui };
1346d1cf8bbfSZhang Rui 
1347882cdb06SPeter Zijlstra static const struct idle_cpu idle_cpu_gmt __initconst = {
1348882cdb06SPeter Zijlstra 	.state_table = gmt_cstates,
134965c0c236SZhang Rui };
135065c0c236SZhang Rui 
13519edf3c0fSArtem Bityutskiy static const struct idle_cpu idle_cpu_spr __initconst = {
13529edf3c0fSArtem Bityutskiy 	.state_table = spr_cstates,
13539edf3c0fSArtem Bityutskiy 	.disable_promotion_to_c1e = true,
13549edf3c0fSArtem Bityutskiy 	.use_acpi = true,
13559edf3c0fSArtem Bityutskiy };
13569edf3c0fSArtem Bityutskiy 
1357ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_avn __initconst = {
1358fab04b22SLen Brown 	.state_table = avn_cstates,
1359fab04b22SLen Brown 	.disable_promotion_to_c1e = true,
1360e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1361fab04b22SLen Brown };
1362fab04b22SLen Brown 
1363ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_knl __initconst = {
1364281baf7aSDasaratharaman Chandramouli 	.state_table = knl_cstates,
1365e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1366281baf7aSDasaratharaman Chandramouli };
1367281baf7aSDasaratharaman Chandramouli 
1368ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bxt __initconst = {
13695dcef694SLen Brown 	.state_table = bxt_cstates,
13705dcef694SLen Brown 	.disable_promotion_to_c1e = true,
13715dcef694SLen Brown };
13725dcef694SLen Brown 
1373ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_dnv __initconst = {
13740080d65bSJacob Pan 	.state_table = dnv_cstates,
13750080d65bSJacob Pan 	.disable_promotion_to_c1e = true,
1376e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
13770080d65bSJacob Pan };
13780080d65bSJacob Pan 
13799cf93f05SArtem Bityutskiy static const struct idle_cpu idle_cpu_snr __initconst = {
13809cf93f05SArtem Bityutskiy 	.state_table = snr_cstates,
13819cf93f05SArtem Bityutskiy 	.disable_promotion_to_c1e = true,
13829cf93f05SArtem Bityutskiy 	.use_acpi = true,
13839cf93f05SArtem Bityutskiy };
13849cf93f05SArtem Bityutskiy 
1385d5cdc3c4SMathias Krause static const struct x86_cpu_id intel_idle_ids[] __initconst = {
13864a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP,		&idle_cpu_nhx),
13874a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM,		&idle_cpu_nehalem),
13884a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G,		&idle_cpu_nehalem),
13894a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE,		&idle_cpu_nehalem),
13904a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP,		&idle_cpu_nhx),
13914a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX,		&idle_cpu_nhx),
13924a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL,	&idle_cpu_atom),
13934a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL_MID,	&idle_cpu_lincroft),
13944a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX,		&idle_cpu_nhx),
13954a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE,		&idle_cpu_snb),
13964a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X,	&idle_cpu_snx),
13974a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL,	&idle_cpu_atom),
13984a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,	&idle_cpu_byt),
13994a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID,	&idle_cpu_tangier),
14004a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,	&idle_cpu_cht),
14014a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE,		&idle_cpu_ivb),
14024a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X,		&idle_cpu_ivt),
14034a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL,		&idle_cpu_hsw),
14044a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X,		&idle_cpu_hsx),
14054a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L,		&idle_cpu_hsw),
14064a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G,		&idle_cpu_hsw),
14074a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D,	&idle_cpu_avn),
14084a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL,		&idle_cpu_bdw),
14094a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G,		&idle_cpu_bdw),
14104a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X,		&idle_cpu_bdx),
14114a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D,		&idle_cpu_bdx),
14124a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L,		&idle_cpu_skl),
14134a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE,		&idle_cpu_skl),
14144a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L,		&idle_cpu_skl),
14154a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE,		&idle_cpu_skl),
14164a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,		&idle_cpu_skx),
1417a472ad2bSChen Yu 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,		&idle_cpu_icx),
141822141d5fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,		&idle_cpu_icx),
1419d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,		&idle_cpu_adl),
1420d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,		&idle_cpu_adl_l),
1421882cdb06SPeter Zijlstra 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT,	&idle_cpu_gmt),
14229edf3c0fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,	&idle_cpu_spr),
142374528edfSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X,	&idle_cpu_spr),
14244a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,	&idle_cpu_knl),
14254a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,	&idle_cpu_knl),
14264a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	&idle_cpu_bxt),
14274a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,	&idle_cpu_bxt),
14284a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D,	&idle_cpu_dnv),
14299cf93f05SArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,	&idle_cpu_snr),
1430b66b8b9aSAndi Kleen 	{}
1431b66b8b9aSAndi Kleen };
1432b66b8b9aSAndi Kleen 
143318734958SRafael J. Wysocki static const struct x86_cpu_id intel_mwait_ids[] __initconst = {
14344a9f45a0SThomas Gleixner 	X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL),
143518734958SRafael J. Wysocki 	{}
143618734958SRafael J. Wysocki };
143718734958SRafael J. Wysocki 
intel_idle_max_cstate_reached(int cstate)1438095928aeSRafael J. Wysocki static bool __init intel_idle_max_cstate_reached(int cstate)
143918734958SRafael J. Wysocki {
144018734958SRafael J. Wysocki 	if (cstate + 1 > max_cstate) {
144118734958SRafael J. Wysocki 		pr_info("max_cstate %d reached\n", max_cstate);
144218734958SRafael J. Wysocki 		return true;
144318734958SRafael J. Wysocki 	}
144418734958SRafael J. Wysocki 	return false;
144518734958SRafael J. Wysocki }
144618734958SRafael J. Wysocki 
intel_idle_state_needs_timer_stop(struct cpuidle_state * state)14474d916140SPeter Zijlstra static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
14484d916140SPeter Zijlstra {
14494d916140SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
14504d916140SPeter Zijlstra 
14514d916140SPeter Zijlstra 	if (boot_cpu_has(X86_FEATURE_ARAT))
14524d916140SPeter Zijlstra 		return false;
14534d916140SPeter Zijlstra 
14544d916140SPeter Zijlstra 	/*
14554d916140SPeter Zijlstra 	 * Switch over to one-shot tick broadcast if the target C-state
14564d916140SPeter Zijlstra 	 * is deeper than C1.
14574d916140SPeter Zijlstra 	 */
14584d916140SPeter Zijlstra 	return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
14594d916140SPeter Zijlstra }
14604d916140SPeter Zijlstra 
146118734958SRafael J. Wysocki #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
146218734958SRafael J. Wysocki #include <acpi/processor.h>
146318734958SRafael J. Wysocki 
14644ec32d9eSRafael J. Wysocki static bool no_acpi __read_mostly;
14654ec32d9eSRafael J. Wysocki module_param(no_acpi, bool, 0444);
14664ec32d9eSRafael J. Wysocki MODULE_PARM_DESC(no_acpi, "Do not use ACPI _CST for building the idle states list");
14674ec32d9eSRafael J. Wysocki 
14683a5be9b8SRafael J. Wysocki static bool force_use_acpi __read_mostly; /* No effect if no_acpi is set. */
14693a5be9b8SRafael J. Wysocki module_param_named(use_acpi, force_use_acpi, bool, 0444);
14703a5be9b8SRafael J. Wysocki MODULE_PARM_DESC(use_acpi, "Use ACPI _CST for building the idle states list");
14713a5be9b8SRafael J. Wysocki 
1472095928aeSRafael J. Wysocki static struct acpi_processor_power acpi_state_table __initdata;
147318734958SRafael J. Wysocki 
147418734958SRafael J. Wysocki /**
147518734958SRafael J. Wysocki  * intel_idle_cst_usable - Check if the _CST information can be used.
147618734958SRafael J. Wysocki  *
147718734958SRafael J. Wysocki  * Check if all of the C-states listed by _CST in the max_cstate range are
147818734958SRafael J. Wysocki  * ACPI_CSTATE_FFH, which means that they should be entered via MWAIT.
147918734958SRafael J. Wysocki  */
intel_idle_cst_usable(void)1480095928aeSRafael J. Wysocki static bool __init intel_idle_cst_usable(void)
148118734958SRafael J. Wysocki {
148218734958SRafael J. Wysocki 	int cstate, limit;
148318734958SRafael J. Wysocki 
148418734958SRafael J. Wysocki 	limit = min_t(int, min_t(int, CPUIDLE_STATE_MAX, max_cstate + 1),
148518734958SRafael J. Wysocki 		      acpi_state_table.count);
148618734958SRafael J. Wysocki 
148718734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
148818734958SRafael J. Wysocki 		struct acpi_processor_cx *cx = &acpi_state_table.states[cstate];
148918734958SRafael J. Wysocki 
149018734958SRafael J. Wysocki 		if (cx->entry_method != ACPI_CSTATE_FFH)
149118734958SRafael J. Wysocki 			return false;
149218734958SRafael J. Wysocki 	}
149318734958SRafael J. Wysocki 
149418734958SRafael J. Wysocki 	return true;
149518734958SRafael J. Wysocki }
149618734958SRafael J. Wysocki 
intel_idle_acpi_cst_extract(void)1497095928aeSRafael J. Wysocki static bool __init intel_idle_acpi_cst_extract(void)
149818734958SRafael J. Wysocki {
149918734958SRafael J. Wysocki 	unsigned int cpu;
150018734958SRafael J. Wysocki 
15014ec32d9eSRafael J. Wysocki 	if (no_acpi) {
15024ec32d9eSRafael J. Wysocki 		pr_debug("Not allowed to use ACPI _CST\n");
15034ec32d9eSRafael J. Wysocki 		return false;
15044ec32d9eSRafael J. Wysocki 	}
15054ec32d9eSRafael J. Wysocki 
150618734958SRafael J. Wysocki 	for_each_possible_cpu(cpu) {
150718734958SRafael J. Wysocki 		struct acpi_processor *pr = per_cpu(processors, cpu);
150818734958SRafael J. Wysocki 
150918734958SRafael J. Wysocki 		if (!pr)
151018734958SRafael J. Wysocki 			continue;
151118734958SRafael J. Wysocki 
151218734958SRafael J. Wysocki 		if (acpi_processor_evaluate_cst(pr->handle, cpu, &acpi_state_table))
151318734958SRafael J. Wysocki 			continue;
151418734958SRafael J. Wysocki 
151518734958SRafael J. Wysocki 		acpi_state_table.count++;
151618734958SRafael J. Wysocki 
151718734958SRafael J. Wysocki 		if (!intel_idle_cst_usable())
151818734958SRafael J. Wysocki 			continue;
151918734958SRafael J. Wysocki 
152075af76d0SMel Gorman 		if (!acpi_processor_claim_cst_control())
152175af76d0SMel Gorman 			break;
152218734958SRafael J. Wysocki 
152318734958SRafael J. Wysocki 		return true;
152418734958SRafael J. Wysocki 	}
152518734958SRafael J. Wysocki 
152675af76d0SMel Gorman 	acpi_state_table.count = 0;
152718734958SRafael J. Wysocki 	pr_debug("ACPI _CST not found or not usable\n");
152818734958SRafael J. Wysocki 	return false;
152918734958SRafael J. Wysocki }
153018734958SRafael J. Wysocki 
intel_idle_init_cstates_acpi(struct cpuidle_driver * drv)1531095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
153218734958SRafael J. Wysocki {
153318734958SRafael J. Wysocki 	int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
153418734958SRafael J. Wysocki 
153518734958SRafael J. Wysocki 	/*
153618734958SRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
153718734958SRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
153818734958SRafael J. Wysocki 	 */
153918734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
154018734958SRafael J. Wysocki 		struct acpi_processor_cx *cx;
154118734958SRafael J. Wysocki 		struct cpuidle_state *state;
154218734958SRafael J. Wysocki 
15434e0ba557SChen Yu 		if (intel_idle_max_cstate_reached(cstate - 1))
154418734958SRafael J. Wysocki 			break;
154518734958SRafael J. Wysocki 
154618734958SRafael J. Wysocki 		cx = &acpi_state_table.states[cstate];
154718734958SRafael J. Wysocki 
154818734958SRafael J. Wysocki 		state = &drv->states[drv->state_count++];
154918734958SRafael J. Wysocki 
155018734958SRafael J. Wysocki 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate);
15510dbc0f49SWolfram Sang 		strscpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
155218734958SRafael J. Wysocki 		state->exit_latency = cx->latency;
155318734958SRafael J. Wysocki 		/*
155418734958SRafael J. Wysocki 		 * For C1-type C-states use the same number for both the exit
155518734958SRafael J. Wysocki 		 * latency and target residency, because that is the case for
155618734958SRafael J. Wysocki 		 * C1 in the majority of the static C-states tables above.
155718734958SRafael J. Wysocki 		 * For the other types of C-states, however, set the target
155818734958SRafael J. Wysocki 		 * residency to 3 times the exit latency which should lead to
155918734958SRafael J. Wysocki 		 * a reasonable balance between energy-efficiency and
156018734958SRafael J. Wysocki 		 * performance in the majority of interesting cases.
156118734958SRafael J. Wysocki 		 */
156218734958SRafael J. Wysocki 		state->target_residency = cx->latency;
156318734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C1)
156418734958SRafael J. Wysocki 			state->target_residency *= 3;
156518734958SRafael J. Wysocki 
156618734958SRafael J. Wysocki 		state->flags = MWAIT2flg(cx->address);
156718734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C2)
156818734958SRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
156918734958SRafael J. Wysocki 
15704dcb78eeSRafael J. Wysocki 		if (disabled_states_mask & BIT(cstate))
15714dcb78eeSRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_OFF;
15724dcb78eeSRafael J. Wysocki 
15736e1d2bc6SPeter Zijlstra 		if (intel_idle_state_needs_timer_stop(state))
15746e1d2bc6SPeter Zijlstra 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
15756e1d2bc6SPeter Zijlstra 
157618734958SRafael J. Wysocki 		state->enter = intel_idle;
157718734958SRafael J. Wysocki 		state->enter_s2idle = intel_idle_s2idle;
157818734958SRafael J. Wysocki 	}
157918734958SRafael J. Wysocki }
1580bff8e60aSRafael J. Wysocki 
intel_idle_off_by_default(u32 mwait_hint)1581095928aeSRafael J. Wysocki static bool __init intel_idle_off_by_default(u32 mwait_hint)
1582bff8e60aSRafael J. Wysocki {
1583bff8e60aSRafael J. Wysocki 	int cstate, limit;
1584bff8e60aSRafael J. Wysocki 
1585bff8e60aSRafael J. Wysocki 	/*
1586bff8e60aSRafael J. Wysocki 	 * If there are no _CST C-states, do not disable any C-states by
1587bff8e60aSRafael J. Wysocki 	 * default.
1588bff8e60aSRafael J. Wysocki 	 */
1589bff8e60aSRafael J. Wysocki 	if (!acpi_state_table.count)
1590bff8e60aSRafael J. Wysocki 		return false;
1591bff8e60aSRafael J. Wysocki 
1592bff8e60aSRafael J. Wysocki 	limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
1593bff8e60aSRafael J. Wysocki 	/*
1594bff8e60aSRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
1595bff8e60aSRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
1596bff8e60aSRafael J. Wysocki 	 */
1597bff8e60aSRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
1598bff8e60aSRafael J. Wysocki 		if (acpi_state_table.states[cstate].address == mwait_hint)
1599bff8e60aSRafael J. Wysocki 			return false;
1600bff8e60aSRafael J. Wysocki 	}
1601bff8e60aSRafael J. Wysocki 	return true;
1602bff8e60aSRafael J. Wysocki }
160318734958SRafael J. Wysocki #else /* !CONFIG_ACPI_PROCESSOR_CSTATE */
16043a5be9b8SRafael J. Wysocki #define force_use_acpi	(false)
16053a5be9b8SRafael J. Wysocki 
intel_idle_acpi_cst_extract(void)160618734958SRafael J. Wysocki static inline bool intel_idle_acpi_cst_extract(void) { return false; }
intel_idle_init_cstates_acpi(struct cpuidle_driver * drv)160718734958SRafael J. Wysocki static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
intel_idle_off_by_default(u32 mwait_hint)1608bff8e60aSRafael J. Wysocki static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
160918734958SRafael J. Wysocki #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */
161018734958SRafael J. Wysocki 
16116eacb15fSRafael J. Wysocki /**
16126eacb15fSRafael J. Wysocki  * ivt_idle_state_table_update - Tune the idle states table for Ivy Town.
16130138d8f0SLen Brown  *
16146eacb15fSRafael J. Wysocki  * Tune IVT multi-socket targets.
16156eacb15fSRafael J. Wysocki  * Assumption: num_sockets == (max_package_num + 1).
16160138d8f0SLen Brown  */
ivt_idle_state_table_update(void)1617095928aeSRafael J. Wysocki static void __init ivt_idle_state_table_update(void)
16180138d8f0SLen Brown {
16190138d8f0SLen Brown 	/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
16200138d8f0SLen Brown 	int cpu, package_num, num_sockets = 1;
16210138d8f0SLen Brown 
16220138d8f0SLen Brown 	for_each_online_cpu(cpu) {
16230138d8f0SLen Brown 		package_num = topology_physical_package_id(cpu);
16240138d8f0SLen Brown 		if (package_num + 1 > num_sockets) {
16250138d8f0SLen Brown 			num_sockets = package_num + 1;
16260138d8f0SLen Brown 
1627d27dca42SChristoph Jaeger 			if (num_sockets > 4) {
16280138d8f0SLen Brown 				cpuidle_state_table = ivt_cstates_8s;
16290138d8f0SLen Brown 				return;
16300138d8f0SLen Brown 			}
16310138d8f0SLen Brown 		}
1632d27dca42SChristoph Jaeger 	}
16330138d8f0SLen Brown 
16340138d8f0SLen Brown 	if (num_sockets > 2)
16350138d8f0SLen Brown 		cpuidle_state_table = ivt_cstates_4s;
1636d70e28f5SLen Brown 
16370138d8f0SLen Brown 	/* else, 1 and 2 socket systems use default ivt_cstates */
16380138d8f0SLen Brown }
16395dcef694SLen Brown 
164086e9466aSRafael J. Wysocki /**
164186e9466aSRafael J. Wysocki  * irtl_2_usec - IRTL to microseconds conversion.
164286e9466aSRafael J. Wysocki  * @irtl: IRTL MSR value.
164386e9466aSRafael J. Wysocki  *
164486e9466aSRafael J. Wysocki  * Translate the IRTL (Interrupt Response Time Limit) MSR value to microseconds.
16455dcef694SLen Brown  */
irtl_2_usec(unsigned long long irtl)164686e9466aSRafael J. Wysocki static unsigned long long __init irtl_2_usec(unsigned long long irtl)
164786e9466aSRafael J. Wysocki {
1648095928aeSRafael J. Wysocki 	static const unsigned int irtl_ns_units[] __initconst = {
1649095928aeSRafael J. Wysocki 		1, 32, 1024, 32768, 1048576, 33554432, 0, 0
1650095928aeSRafael J. Wysocki 	};
16515dcef694SLen Brown 	unsigned long long ns;
16525dcef694SLen Brown 
16533451ab3eSJan Beulich 	if (!irtl)
16543451ab3eSJan Beulich 		return 0;
16553451ab3eSJan Beulich 
1656bef45096SJan Beulich 	ns = irtl_ns_units[(irtl >> 10) & 0x7];
16575dcef694SLen Brown 
165886e9466aSRafael J. Wysocki 	return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC);
16595dcef694SLen Brown }
166086e9466aSRafael J. Wysocki 
16616eacb15fSRafael J. Wysocki /**
16626eacb15fSRafael J. Wysocki  * bxt_idle_state_table_update - Fix up the Broxton idle states table.
16635dcef694SLen Brown  *
16646eacb15fSRafael J. Wysocki  * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the
16656eacb15fSRafael J. Wysocki  * definitive maximum latency and use the same value for target_residency.
16665dcef694SLen Brown  */
bxt_idle_state_table_update(void)1667095928aeSRafael J. Wysocki static void __init bxt_idle_state_table_update(void)
16685dcef694SLen Brown {
16695dcef694SLen Brown 	unsigned long long msr;
16703451ab3eSJan Beulich 	unsigned int usec;
16715dcef694SLen Brown 
16725dcef694SLen Brown 	rdmsrl(MSR_PKGC6_IRTL, msr);
16733451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16743451ab3eSJan Beulich 	if (usec) {
16755dcef694SLen Brown 		bxt_cstates[2].exit_latency = usec;
16765dcef694SLen Brown 		bxt_cstates[2].target_residency = usec;
16775dcef694SLen Brown 	}
16785dcef694SLen Brown 
16795dcef694SLen Brown 	rdmsrl(MSR_PKGC7_IRTL, msr);
16803451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16813451ab3eSJan Beulich 	if (usec) {
16825dcef694SLen Brown 		bxt_cstates[3].exit_latency = usec;
16835dcef694SLen Brown 		bxt_cstates[3].target_residency = usec;
16845dcef694SLen Brown 	}
16855dcef694SLen Brown 
16865dcef694SLen Brown 	rdmsrl(MSR_PKGC8_IRTL, msr);
16873451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16883451ab3eSJan Beulich 	if (usec) {
16895dcef694SLen Brown 		bxt_cstates[4].exit_latency = usec;
16905dcef694SLen Brown 		bxt_cstates[4].target_residency = usec;
16915dcef694SLen Brown 	}
16925dcef694SLen Brown 
16935dcef694SLen Brown 	rdmsrl(MSR_PKGC9_IRTL, msr);
16943451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16953451ab3eSJan Beulich 	if (usec) {
16965dcef694SLen Brown 		bxt_cstates[5].exit_latency = usec;
16975dcef694SLen Brown 		bxt_cstates[5].target_residency = usec;
16985dcef694SLen Brown 	}
16995dcef694SLen Brown 
17005dcef694SLen Brown 	rdmsrl(MSR_PKGC10_IRTL, msr);
17013451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17023451ab3eSJan Beulich 	if (usec) {
17035dcef694SLen Brown 		bxt_cstates[6].exit_latency = usec;
17045dcef694SLen Brown 		bxt_cstates[6].target_residency = usec;
17055dcef694SLen Brown 	}
17065dcef694SLen Brown 
17075dcef694SLen Brown }
17086eacb15fSRafael J. Wysocki 
17096eacb15fSRafael J. Wysocki /**
17106eacb15fSRafael J. Wysocki  * sklh_idle_state_table_update - Fix up the Sky Lake idle states table.
1711d70e28f5SLen Brown  *
17126eacb15fSRafael J. Wysocki  * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled.
1713d70e28f5SLen Brown  */
sklh_idle_state_table_update(void)1714095928aeSRafael J. Wysocki static void __init sklh_idle_state_table_update(void)
1715d70e28f5SLen Brown {
1716d70e28f5SLen Brown 	unsigned long long msr;
1717d70e28f5SLen Brown 	unsigned int eax, ebx, ecx, edx;
1718d70e28f5SLen Brown 
1719d70e28f5SLen Brown 
1720d70e28f5SLen Brown 	/* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
1721d70e28f5SLen Brown 	if (max_cstate <= 7)
17220138d8f0SLen Brown 		return;
1723d70e28f5SLen Brown 
1724d70e28f5SLen Brown 	/* if PC10 not present in CPUID.MWAIT.EDX */
1725d70e28f5SLen Brown 	if ((mwait_substates & (0xF << 28)) == 0)
1726d70e28f5SLen Brown 		return;
1727d70e28f5SLen Brown 
17286cfb2374SLen Brown 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
1729d70e28f5SLen Brown 
1730d70e28f5SLen Brown 	/* PC10 is not enabled in PKG C-state limit */
1731d70e28f5SLen Brown 	if ((msr & 0xF) != 8)
1732d70e28f5SLen Brown 		return;
1733d70e28f5SLen Brown 
1734d70e28f5SLen Brown 	ecx = 0;
1735d70e28f5SLen Brown 	cpuid(7, &eax, &ebx, &ecx, &edx);
1736d70e28f5SLen Brown 
1737d70e28f5SLen Brown 	/* if SGX is present */
1738d70e28f5SLen Brown 	if (ebx & (1 << 2)) {
1739d70e28f5SLen Brown 
174032ad73dbSSean Christopherson 		rdmsrl(MSR_IA32_FEAT_CTL, msr);
1741d70e28f5SLen Brown 
1742d70e28f5SLen Brown 		/* if SGX is enabled */
1743d70e28f5SLen Brown 		if (msr & (1 << 18))
1744d70e28f5SLen Brown 			return;
1745d70e28f5SLen Brown 	}
1746d70e28f5SLen Brown 
1747ba1e78a1SRafael J. Wysocki 	skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C8-SKL */
1748ba1e78a1SRafael J. Wysocki 	skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C9-SKL */
1749d70e28f5SLen Brown }
1750d70e28f5SLen Brown 
175164233338SChen Yu /**
175264233338SChen Yu  * skx_idle_state_table_update - Adjust the Sky Lake/Cascade Lake
175364233338SChen Yu  * idle states table.
175464233338SChen Yu  */
skx_idle_state_table_update(void)175564233338SChen Yu static void __init skx_idle_state_table_update(void)
175664233338SChen Yu {
175764233338SChen Yu 	unsigned long long msr;
175864233338SChen Yu 
175964233338SChen Yu 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
176064233338SChen Yu 
176164233338SChen Yu 	/*
176264233338SChen Yu 	 * 000b: C0/C1 (no package C-state support)
176364233338SChen Yu 	 * 001b: C2
176464233338SChen Yu 	 * 010b: C6 (non-retention)
176564233338SChen Yu 	 * 011b: C6 (retention)
176664233338SChen Yu 	 * 111b: No Package C state limits.
176764233338SChen Yu 	 */
176864233338SChen Yu 	if ((msr & 0x7) < 2) {
176964233338SChen Yu 		/*
177064233338SChen Yu 		 * Uses the CC6 + PC0 latency and 3 times of
177164233338SChen Yu 		 * latency for target_residency if the PC6
177264233338SChen Yu 		 * is disabled in BIOS. This is consistent
177364233338SChen Yu 		 * with how intel_idle driver uses _CST
177464233338SChen Yu 		 * to set the target_residency.
177564233338SChen Yu 		 */
177664233338SChen Yu 		skx_cstates[2].exit_latency = 92;
177764233338SChen Yu 		skx_cstates[2].target_residency = 276;
177864233338SChen Yu 	}
177964233338SChen Yu }
178064233338SChen Yu 
1781da0e58c0SArtem Bityutskiy /**
1782d1cf8bbfSZhang Rui  * adl_idle_state_table_update - Adjust AlderLake idle states table.
1783d1cf8bbfSZhang Rui  */
adl_idle_state_table_update(void)1784d1cf8bbfSZhang Rui static void __init adl_idle_state_table_update(void)
1785d1cf8bbfSZhang Rui {
1786d1cf8bbfSZhang Rui 	/* Check if user prefers C1 over C1E. */
1787d1cf8bbfSZhang Rui 	if (preferred_states_mask & BIT(1) && !(preferred_states_mask & BIT(2))) {
1788d1cf8bbfSZhang Rui 		cpuidle_state_table[0].flags &= ~CPUIDLE_FLAG_UNUSABLE;
1789d1cf8bbfSZhang Rui 		cpuidle_state_table[1].flags |= CPUIDLE_FLAG_UNUSABLE;
1790d1cf8bbfSZhang Rui 
1791d1cf8bbfSZhang Rui 		/* Disable C1E by clearing the "C1E promotion" bit. */
1792d1cf8bbfSZhang Rui 		c1e_promotion = C1E_PROMOTION_DISABLE;
1793d1cf8bbfSZhang Rui 		return;
1794d1cf8bbfSZhang Rui 	}
1795d1cf8bbfSZhang Rui 
1796d1cf8bbfSZhang Rui 	/* Make sure C1E is enabled by default */
1797d1cf8bbfSZhang Rui 	c1e_promotion = C1E_PROMOTION_ENABLE;
1798d1cf8bbfSZhang Rui }
1799d1cf8bbfSZhang Rui 
1800d1cf8bbfSZhang Rui /**
1801da0e58c0SArtem Bityutskiy  * spr_idle_state_table_update - Adjust Sapphire Rapids idle states table.
1802da0e58c0SArtem Bityutskiy  */
spr_idle_state_table_update(void)1803da0e58c0SArtem Bityutskiy static void __init spr_idle_state_table_update(void)
1804da0e58c0SArtem Bityutskiy {
18053a9cf77bSArtem Bityutskiy 	unsigned long long msr;
18063a9cf77bSArtem Bityutskiy 
18073a9cf77bSArtem Bityutskiy 	/*
18083a9cf77bSArtem Bityutskiy 	 * By default, the C6 state assumes the worst-case scenario of package
18093a9cf77bSArtem Bityutskiy 	 * C6. However, if PC6 is disabled, we update the numbers to match
18103a9cf77bSArtem Bityutskiy 	 * core C6.
18113a9cf77bSArtem Bityutskiy 	 */
18123a9cf77bSArtem Bityutskiy 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
18133a9cf77bSArtem Bityutskiy 
18143a9cf77bSArtem Bityutskiy 	/* Limit value 2 and above allow for PC6. */
18153a9cf77bSArtem Bityutskiy 	if ((msr & 0x7) < 2) {
18163a9cf77bSArtem Bityutskiy 		spr_cstates[2].exit_latency = 190;
18173a9cf77bSArtem Bityutskiy 		spr_cstates[2].target_residency = 600;
18183a9cf77bSArtem Bityutskiy 	}
1819da0e58c0SArtem Bityutskiy }
1820da0e58c0SArtem Bityutskiy 
intel_idle_verify_cstate(unsigned int mwait_hint)18211aefbd7aSRafael J. Wysocki static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
18221aefbd7aSRafael J. Wysocki {
18231aefbd7aSRafael J. Wysocki 	unsigned int mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint) + 1;
18241aefbd7aSRafael J. Wysocki 	unsigned int num_substates = (mwait_substates >> mwait_cstate * 4) &
18251aefbd7aSRafael J. Wysocki 					MWAIT_SUBSTATE_MASK;
18261aefbd7aSRafael J. Wysocki 
18271aefbd7aSRafael J. Wysocki 	/* Ignore the C-state if there are NO sub-states in CPUID for it. */
18281aefbd7aSRafael J. Wysocki 	if (num_substates == 0)
18291aefbd7aSRafael J. Wysocki 		return false;
18301aefbd7aSRafael J. Wysocki 
18311aefbd7aSRafael J. Wysocki 	if (mwait_cstate > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
18321aefbd7aSRafael J. Wysocki 		mark_tsc_unstable("TSC halts in idle states deeper than C2");
18331aefbd7aSRafael J. Wysocki 
18341aefbd7aSRafael J. Wysocki 	return true;
18351aefbd7aSRafael J. Wysocki }
18361aefbd7aSRafael J. Wysocki 
state_update_enter_method(struct cpuidle_state * state,int cstate)18374622ba92SArjan van de Ven static void state_update_enter_method(struct cpuidle_state *state, int cstate)
18384622ba92SArjan van de Ven {
18394622ba92SArjan van de Ven 	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
18404622ba92SArjan van de Ven 		/*
18414622ba92SArjan van de Ven 		 * Combining with XSTATE with IBRS or IRQ_ENABLE flags
18424622ba92SArjan van de Ven 		 * is not currently supported but this driver.
18434622ba92SArjan van de Ven 		 */
18444622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS);
18454622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
18464622ba92SArjan van de Ven 		state->enter = intel_idle_xstate;
18477826c069SArjan van de Ven 		return;
18487826c069SArjan van de Ven 	}
18497826c069SArjan van de Ven 
18507826c069SArjan van de Ven 	if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
18514622ba92SArjan van de Ven 			   state->flags & CPUIDLE_FLAG_IBRS) {
18524622ba92SArjan van de Ven 		/*
18534622ba92SArjan van de Ven 		 * IBRS mitigation requires that C-states are entered
18544622ba92SArjan van de Ven 		 * with interrupts disabled.
18554622ba92SArjan van de Ven 		 */
18564622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
18574622ba92SArjan van de Ven 		state->enter = intel_idle_ibrs;
18587826c069SArjan van de Ven 		return;
18597826c069SArjan van de Ven 	}
18607826c069SArjan van de Ven 
18617826c069SArjan van de Ven 	if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) {
18624622ba92SArjan van de Ven 		state->enter = intel_idle_irq;
18637826c069SArjan van de Ven 		return;
18647826c069SArjan van de Ven 	}
18657826c069SArjan van de Ven 
18667826c069SArjan van de Ven 	if (force_irq_on) {
18674622ba92SArjan van de Ven 		pr_info("forced intel_idle_irq for state %d\n", cstate);
18684622ba92SArjan van de Ven 		state->enter = intel_idle_irq;
18694622ba92SArjan van de Ven 	}
18704622ba92SArjan van de Ven }
18714622ba92SArjan van de Ven 
intel_idle_init_cstates_icpu(struct cpuidle_driver * drv)1872095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
1873d70e28f5SLen Brown {
18743d3a1ae9SRafael J. Wysocki 	int cstate;
1875d70e28f5SLen Brown 
18763d3a1ae9SRafael J. Wysocki 	switch (boot_cpu_data.x86_model) {
1877db73c5a8SDave Hansen 	case INTEL_FAM6_IVYBRIDGE_X:
1878d70e28f5SLen Brown 		ivt_idle_state_table_update();
1879d70e28f5SLen Brown 		break;
1880db73c5a8SDave Hansen 	case INTEL_FAM6_ATOM_GOLDMONT:
1881f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
18825dcef694SLen Brown 		bxt_idle_state_table_update();
18835dcef694SLen Brown 		break;
1884c66f78a6SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE:
1885d70e28f5SLen Brown 		sklh_idle_state_table_update();
1886d70e28f5SLen Brown 		break;
188764233338SChen Yu 	case INTEL_FAM6_SKYLAKE_X:
188864233338SChen Yu 		skx_idle_state_table_update();
188964233338SChen Yu 		break;
1890da0e58c0SArtem Bityutskiy 	case INTEL_FAM6_SAPPHIRERAPIDS_X:
189174528edfSArtem Bityutskiy 	case INTEL_FAM6_EMERALDRAPIDS_X:
1892da0e58c0SArtem Bityutskiy 		spr_idle_state_table_update();
1893da0e58c0SArtem Bityutskiy 		break;
1894d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE:
1895d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE_L:
1896882cdb06SPeter Zijlstra 	case INTEL_FAM6_ATOM_GRACEMONT:
1897d1cf8bbfSZhang Rui 		adl_idle_state_table_update();
1898d1cf8bbfSZhang Rui 		break;
1899d70e28f5SLen Brown 	}
190046bcfad7SDeepthi Dharwar 
1901e022e7ebSLen Brown 	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
19021abffbd8SArtem Bityutskiy 		struct cpuidle_state *state;
19039f3d6dafSRafael J. Wysocki 		unsigned int mwait_hint;
190446bcfad7SDeepthi Dharwar 
190518734958SRafael J. Wysocki 		if (intel_idle_max_cstate_reached(cstate))
190618734958SRafael J. Wysocki 			break;
190718734958SRafael J. Wysocki 
19089f3d6dafSRafael J. Wysocki 		if (!cpuidle_state_table[cstate].enter &&
19099f3d6dafSRafael J. Wysocki 		    !cpuidle_state_table[cstate].enter_s2idle)
1910e022e7ebSLen Brown 			break;
1911e022e7ebSLen Brown 
19129f3d6dafSRafael J. Wysocki 		/* If marked as unusable, skip this state. */
1913ba1e78a1SRafael J. Wysocki 		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) {
1914654d08a4SJoe Perches 			pr_debug("state %s is disabled\n",
1915d70e28f5SLen Brown 				 cpuidle_state_table[cstate].name);
1916d70e28f5SLen Brown 			continue;
1917d70e28f5SLen Brown 		}
1918d70e28f5SLen Brown 
19199f3d6dafSRafael J. Wysocki 		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
19205534f446SRafael J. Wysocki 		if (!intel_idle_verify_cstate(mwait_hint))
19219f3d6dafSRafael J. Wysocki 			continue;
1922d70e28f5SLen Brown 
19239f3d6dafSRafael J. Wysocki 		/* Structure copy. */
1924bff8e60aSRafael J. Wysocki 		drv->states[drv->state_count] = cpuidle_state_table[cstate];
19251abffbd8SArtem Bityutskiy 		state = &drv->states[drv->state_count];
1926bff8e60aSRafael J. Wysocki 
19274622ba92SArjan van de Ven 		state_update_enter_method(state, cstate);
19284622ba92SArjan van de Ven 
192932d4fd57SPeter Zijlstra 
19304dcb78eeSRafael J. Wysocki 		if ((disabled_states_mask & BIT(drv->state_count)) ||
19314dcb78eeSRafael J. Wysocki 		    ((icpu->use_acpi || force_use_acpi) &&
19323a5be9b8SRafael J. Wysocki 		     intel_idle_off_by_default(mwait_hint) &&
19331abffbd8SArtem Bityutskiy 		     !(state->flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
19341abffbd8SArtem Bityutskiy 			state->flags |= CPUIDLE_FLAG_OFF;
1935bff8e60aSRafael J. Wysocki 
19361abffbd8SArtem Bityutskiy 		if (intel_idle_state_needs_timer_stop(state))
19371abffbd8SArtem Bityutskiy 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
19386e1d2bc6SPeter Zijlstra 
1939bff8e60aSRafael J. Wysocki 		drv->state_count++;
194046bcfad7SDeepthi Dharwar 	}
194146bcfad7SDeepthi Dharwar 
19428c058d53SLen Brown 	if (icpu->byt_auto_demotion_disable_flag) {
19438c058d53SLen Brown 		wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
19448c058d53SLen Brown 		wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
19458c058d53SLen Brown 	}
194646bcfad7SDeepthi Dharwar }
194746bcfad7SDeepthi Dharwar 
19486eacb15fSRafael J. Wysocki /**
19496eacb15fSRafael J. Wysocki  * intel_idle_cpuidle_driver_init - Create the list of available idle states.
19506eacb15fSRafael J. Wysocki  * @drv: cpuidle driver structure to initialize.
195118734958SRafael J. Wysocki  */
intel_idle_cpuidle_driver_init(struct cpuidle_driver * drv)19523d3a1ae9SRafael J. Wysocki static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
195318734958SRafael J. Wysocki {
195418734958SRafael J. Wysocki 	cpuidle_poll_state_init(drv);
19554dcb78eeSRafael J. Wysocki 
19564dcb78eeSRafael J. Wysocki 	if (disabled_states_mask & BIT(0))
19574dcb78eeSRafael J. Wysocki 		drv->states[0].flags |= CPUIDLE_FLAG_OFF;
19584dcb78eeSRafael J. Wysocki 
195918734958SRafael J. Wysocki 	drv->state_count = 1;
196018734958SRafael J. Wysocki 
196118734958SRafael J. Wysocki 	if (icpu)
196218734958SRafael J. Wysocki 		intel_idle_init_cstates_icpu(drv);
196318734958SRafael J. Wysocki 	else
196418734958SRafael J. Wysocki 		intel_idle_init_cstates_acpi(drv);
196518734958SRafael J. Wysocki }
196646bcfad7SDeepthi Dharwar 
auto_demotion_disable(void)19671aefbd7aSRafael J. Wysocki static void auto_demotion_disable(void)
19681aefbd7aSRafael J. Wysocki {
19691aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
19701aefbd7aSRafael J. Wysocki 
19711aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
19727f843dd7SRafael J. Wysocki 	msr_bits &= ~auto_demotion_disable_flags;
19731aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
19741aefbd7aSRafael J. Wysocki }
19751aefbd7aSRafael J. Wysocki 
c1e_promotion_enable(void)1976da0e58c0SArtem Bityutskiy static void c1e_promotion_enable(void)
1977da0e58c0SArtem Bityutskiy {
1978da0e58c0SArtem Bityutskiy 	unsigned long long msr_bits;
1979da0e58c0SArtem Bityutskiy 
1980da0e58c0SArtem Bityutskiy 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
1981da0e58c0SArtem Bityutskiy 	msr_bits |= 0x2;
1982da0e58c0SArtem Bityutskiy 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
1983da0e58c0SArtem Bityutskiy }
1984da0e58c0SArtem Bityutskiy 
c1e_promotion_disable(void)19851aefbd7aSRafael J. Wysocki static void c1e_promotion_disable(void)
19861aefbd7aSRafael J. Wysocki {
19871aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
19881aefbd7aSRafael J. Wysocki 
19891aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
19901aefbd7aSRafael J. Wysocki 	msr_bits &= ~0x2;
19911aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
19921aefbd7aSRafael J. Wysocki }
19931aefbd7aSRafael J. Wysocki 
19946eacb15fSRafael J. Wysocki /**
19956eacb15fSRafael J. Wysocki  * intel_idle_cpu_init - Register the target CPU with the cpuidle core.
19966eacb15fSRafael J. Wysocki  * @cpu: CPU to initialize.
19976eacb15fSRafael J. Wysocki  *
19986eacb15fSRafael J. Wysocki  * Register a cpuidle device object for @cpu and update its MSRs in accordance
19996eacb15fSRafael J. Wysocki  * with the processor model flags.
200026717172SLen Brown  */
intel_idle_cpu_init(unsigned int cpu)2001fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_init(unsigned int cpu)
200226717172SLen Brown {
200326717172SLen Brown 	struct cpuidle_device *dev;
200426717172SLen Brown 
200565b7f839SThomas Renninger 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
200665b7f839SThomas Renninger 	dev->cpu = cpu;
200726717172SLen Brown 
200826717172SLen Brown 	if (cpuidle_register_device(dev)) {
2009654d08a4SJoe Perches 		pr_debug("cpuidle_register_device %d failed!\n", cpu);
201026717172SLen Brown 		return -EIO;
201126717172SLen Brown 	}
201265b7f839SThomas Renninger 
20137f843dd7SRafael J. Wysocki 	if (auto_demotion_disable_flags)
2014fb1013a0SSebastian Andrzej Siewior 		auto_demotion_disable();
201526717172SLen Brown 
201639c184a6SArtem Bityutskiy 	if (c1e_promotion == C1E_PROMOTION_ENABLE)
201739c184a6SArtem Bityutskiy 		c1e_promotion_enable();
201839c184a6SArtem Bityutskiy 	else if (c1e_promotion == C1E_PROMOTION_DISABLE)
2019fb1013a0SSebastian Andrzej Siewior 		c1e_promotion_disable();
2020fb1013a0SSebastian Andrzej Siewior 
2021fb1013a0SSebastian Andrzej Siewior 	return 0;
2022fb1013a0SSebastian Andrzej Siewior }
2023fb1013a0SSebastian Andrzej Siewior 
intel_idle_cpu_online(unsigned int cpu)2024fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_online(unsigned int cpu)
2025fb1013a0SSebastian Andrzej Siewior {
2026fb1013a0SSebastian Andrzej Siewior 	struct cpuidle_device *dev;
2027fb1013a0SSebastian Andrzej Siewior 
2028dab20177SRafael J. Wysocki 	if (!boot_cpu_has(X86_FEATURE_ARAT))
2029cbd2c4c2SRafael J. Wysocki 		tick_broadcast_enable();
2030fb1013a0SSebastian Andrzej Siewior 
2031fb1013a0SSebastian Andrzej Siewior 	/*
2032fb1013a0SSebastian Andrzej Siewior 	 * Some systems can hotplug a cpu at runtime after
2033fb1013a0SSebastian Andrzej Siewior 	 * the kernel has booted, we have to initialize the
2034fb1013a0SSebastian Andrzej Siewior 	 * driver in this case
2035fb1013a0SSebastian Andrzej Siewior 	 */
2036fb1013a0SSebastian Andrzej Siewior 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
2037fb1013a0SSebastian Andrzej Siewior 	if (!dev->registered)
2038fb1013a0SSebastian Andrzej Siewior 		return intel_idle_cpu_init(cpu);
2039dbf87ab8SBartlomiej Zolnierkiewicz 
204026717172SLen Brown 	return 0;
204126717172SLen Brown }
204226717172SLen Brown 
20430755a9bdSRafael J. Wysocki /**
20440755a9bdSRafael J. Wysocki  * intel_idle_cpuidle_devices_uninit - Unregister all cpuidle devices.
20450755a9bdSRafael J. Wysocki  */
intel_idle_cpuidle_devices_uninit(void)20460755a9bdSRafael J. Wysocki static void __init intel_idle_cpuidle_devices_uninit(void)
20470755a9bdSRafael J. Wysocki {
20480755a9bdSRafael J. Wysocki 	int i;
20490755a9bdSRafael J. Wysocki 
20500755a9bdSRafael J. Wysocki 	for_each_online_cpu(i)
20510755a9bdSRafael J. Wysocki 		cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
20520755a9bdSRafael J. Wysocki }
20530755a9bdSRafael J. Wysocki 
intel_idle_init(void)205426717172SLen Brown static int __init intel_idle_init(void)
205526717172SLen Brown {
2056a6c86e33SRafael J. Wysocki 	const struct x86_cpu_id *id;
2057a6c86e33SRafael J. Wysocki 	unsigned int eax, ebx, ecx;
2058fb1013a0SSebastian Andrzej Siewior 	int retval;
205926717172SLen Brown 
2060d1896049SThomas Renninger 	/* Do not load intel_idle at all for now if idle= is passed */
2061d1896049SThomas Renninger 	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
2062d1896049SThomas Renninger 		return -ENODEV;
2063d1896049SThomas Renninger 
2064a6c86e33SRafael J. Wysocki 	if (max_cstate == 0) {
2065a6c86e33SRafael J. Wysocki 		pr_debug("disabled\n");
2066a6c86e33SRafael J. Wysocki 		return -EPERM;
2067a6c86e33SRafael J. Wysocki 	}
2068a6c86e33SRafael J. Wysocki 
2069a6c86e33SRafael J. Wysocki 	id = x86_match_cpu(intel_idle_ids);
2070a6c86e33SRafael J. Wysocki 	if (id) {
2071a6c86e33SRafael J. Wysocki 		if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
2072a6c86e33SRafael J. Wysocki 			pr_debug("Please enable MWAIT in BIOS SETUP\n");
2073a6c86e33SRafael J. Wysocki 			return -ENODEV;
2074a6c86e33SRafael J. Wysocki 		}
2075a6c86e33SRafael J. Wysocki 	} else {
2076a6c86e33SRafael J. Wysocki 		id = x86_match_cpu(intel_mwait_ids);
2077a6c86e33SRafael J. Wysocki 		if (!id)
2078a6c86e33SRafael J. Wysocki 			return -ENODEV;
2079a6c86e33SRafael J. Wysocki 	}
2080a6c86e33SRafael J. Wysocki 
2081a6c86e33SRafael J. Wysocki 	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
2082a6c86e33SRafael J. Wysocki 		return -ENODEV;
2083a6c86e33SRafael J. Wysocki 
2084a6c86e33SRafael J. Wysocki 	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
2085a6c86e33SRafael J. Wysocki 
2086a6c86e33SRafael J. Wysocki 	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
2087a6c86e33SRafael J. Wysocki 	    !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
2088a6c86e33SRafael J. Wysocki 	    !mwait_substates)
2089a6c86e33SRafael J. Wysocki 			return -ENODEV;
2090a6c86e33SRafael J. Wysocki 
2091a6c86e33SRafael J. Wysocki 	pr_debug("MWAIT substates: 0x%x\n", mwait_substates);
2092a6c86e33SRafael J. Wysocki 
2093a6c86e33SRafael J. Wysocki 	icpu = (const struct idle_cpu *)id->driver_data;
2094a6c86e33SRafael J. Wysocki 	if (icpu) {
2095a6c86e33SRafael J. Wysocki 		cpuidle_state_table = icpu->state_table;
20967f843dd7SRafael J. Wysocki 		auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
209739c184a6SArtem Bityutskiy 		if (icpu->disable_promotion_to_c1e)
209839c184a6SArtem Bityutskiy 			c1e_promotion = C1E_PROMOTION_DISABLE;
20993a5be9b8SRafael J. Wysocki 		if (icpu->use_acpi || force_use_acpi)
2100a6c86e33SRafael J. Wysocki 			intel_idle_acpi_cst_extract();
2101a6c86e33SRafael J. Wysocki 	} else if (!intel_idle_acpi_cst_extract()) {
2102a6c86e33SRafael J. Wysocki 		return -ENODEV;
2103a6c86e33SRafael J. Wysocki 	}
2104a6c86e33SRafael J. Wysocki 
2105a6c86e33SRafael J. Wysocki 	pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
2106a6c86e33SRafael J. Wysocki 		 boot_cpu_data.x86_model);
210726717172SLen Brown 
2108e9df69ccSRichard Cochran 	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
2109533da74aSRafael J. Wysocki 	if (!intel_idle_cpuidle_devices)
2110e9df69ccSRichard Cochran 		return -ENOMEM;
2111e9df69ccSRichard Cochran 
21123d3a1ae9SRafael J. Wysocki 	intel_idle_cpuidle_driver_init(&intel_idle_driver);
21133d3a1ae9SRafael J. Wysocki 
211426717172SLen Brown 	retval = cpuidle_register_driver(&intel_idle_driver);
211526717172SLen Brown 	if (retval) {
21163735d524SKonrad Rzeszutek Wilk 		struct cpuidle_driver *drv = cpuidle_get_driver();
2117654d08a4SJoe Perches 		printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
21183735d524SKonrad Rzeszutek Wilk 		       drv ? drv->name : "none");
2119fb1013a0SSebastian Andrzej Siewior 		goto init_driver_fail;
212026717172SLen Brown 	}
212126717172SLen Brown 
2122fb1013a0SSebastian Andrzej Siewior 	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
2123fb1013a0SSebastian Andrzej Siewior 				   intel_idle_cpu_online, NULL);
2124fb1013a0SSebastian Andrzej Siewior 	if (retval < 0)
2125fb1013a0SSebastian Andrzej Siewior 		goto hp_setup_fail;
212626717172SLen Brown 
212740ab82e0SRafael J. Wysocki 	pr_debug("Local APIC timer is reliable in %s\n",
2128dab20177SRafael J. Wysocki 		 boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1");
21292259a819SRichard Cochran 
213026717172SLen Brown 	return 0;
2131fb1013a0SSebastian Andrzej Siewior 
2132fb1013a0SSebastian Andrzej Siewior hp_setup_fail:
2133fb1013a0SSebastian Andrzej Siewior 	intel_idle_cpuidle_devices_uninit();
2134fb1013a0SSebastian Andrzej Siewior 	cpuidle_unregister_driver(&intel_idle_driver);
2135fb1013a0SSebastian Andrzej Siewior init_driver_fail:
2136fb1013a0SSebastian Andrzej Siewior 	free_percpu(intel_idle_cpuidle_devices);
2137fb1013a0SSebastian Andrzej Siewior 	return retval;
2138fb1013a0SSebastian Andrzej Siewior 
213926717172SLen Brown }
214002c4fae9SPaul Gortmaker device_initcall(intel_idle_init);
214126717172SLen Brown 
214202c4fae9SPaul Gortmaker /*
214302c4fae9SPaul Gortmaker  * We are not really modular, but we used to support that.  Meaning we also
214402c4fae9SPaul Gortmaker  * support "intel_idle.max_cstate=..." at boot and also a read-only export of
214502c4fae9SPaul Gortmaker  * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param
214602c4fae9SPaul Gortmaker  * is the easiest way (currently) to continue doing that.
214702c4fae9SPaul Gortmaker  */
214826717172SLen Brown module_param(max_cstate, int, 0444);
21494dcb78eeSRafael J. Wysocki /*
21504dcb78eeSRafael J. Wysocki  * The positions of the bits that are set in this number are the indices of the
21514dcb78eeSRafael J. Wysocki  * idle states to be disabled by default (as reflected by the names of the
21524dcb78eeSRafael J. Wysocki  * corresponding idle state directories in sysfs, "state0", "state1" ...
21534dcb78eeSRafael J. Wysocki  * "state<i>" ..., where <i> is the index of the given state).
21544dcb78eeSRafael J. Wysocki  */
21554dcb78eeSRafael J. Wysocki module_param_named(states_off, disabled_states_mask, uint, 0444);
21564dcb78eeSRafael J. Wysocki MODULE_PARM_DESC(states_off, "Mask of disabled idle states");
2157da0e58c0SArtem Bityutskiy /*
2158da0e58c0SArtem Bityutskiy  * Some platforms come with mutually exclusive C-states, so that if one is
2159da0e58c0SArtem Bityutskiy  * enabled, the other C-states must not be used. Example: C1 and C1E on
2160da0e58c0SArtem Bityutskiy  * Sapphire Rapids platform. This parameter allows for selecting the
2161da0e58c0SArtem Bityutskiy  * preferred C-states among the groups of mutually exclusive C-states - the
2162da0e58c0SArtem Bityutskiy  * selected C-states will be registered, the other C-states from the mutually
2163da0e58c0SArtem Bityutskiy  * exclusive group won't be registered. If the platform has no mutually
2164da0e58c0SArtem Bityutskiy  * exclusive C-states, this parameter has no effect.
2165da0e58c0SArtem Bityutskiy  */
2166da0e58c0SArtem Bityutskiy module_param_named(preferred_cstates, preferred_states_mask, uint, 0444);
2167da0e58c0SArtem Bityutskiy MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states");
21684152379aSArtem Bityutskiy /*
21694152379aSArtem Bityutskiy  * Debugging option that forces the driver to enter all C-states with
21704152379aSArtem Bityutskiy  * interrupts enabled. Does not apply to C-states with
21714152379aSArtem Bityutskiy  * 'CPUIDLE_FLAG_INIT_XSTATE' and 'CPUIDLE_FLAG_IBRS' flags.
21724152379aSArtem Bityutskiy  */
21734152379aSArtem Bityutskiy module_param(force_irq_on, bool, 0444);
2174