xref: /openbmc/linux/drivers/idle/intel_idle.c (revision 0fac214b)
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 
13332d4fd57SPeter Zijlstra static __always_inline int __intel_idle(struct cpuidle_device *dev,
13432d4fd57SPeter Zijlstra 					struct cpuidle_driver *drv, int index)
13532d4fd57SPeter Zijlstra {
13632d4fd57SPeter Zijlstra 	struct cpuidle_state *state = &drv->states[index];
13732d4fd57SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
13832d4fd57SPeter Zijlstra 	unsigned long ecx = 1; /* break on interrupt flag */
13932d4fd57SPeter Zijlstra 
14032d4fd57SPeter Zijlstra 	mwait_idle_with_hints(eax, ecx);
14132d4fd57SPeter Zijlstra 
14232d4fd57SPeter Zijlstra 	return index;
14332d4fd57SPeter Zijlstra }
14432d4fd57SPeter Zijlstra 
14530a996fbSRafael J. Wysocki /**
14630a996fbSRafael J. Wysocki  * intel_idle - Ask the processor to enter the given idle state.
14730a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
14830a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
14930a996fbSRafael J. Wysocki  * @index: Target idle state index.
15030a996fbSRafael J. Wysocki  *
15130a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
15230a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
15330a996fbSRafael J. Wysocki  *
15430a996fbSRafael J. Wysocki  * If the local APIC timer is not known to be reliable in the target idle state,
15530a996fbSRafael J. Wysocki  * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
15630a996fbSRafael J. Wysocki  *
15730a996fbSRafael J. Wysocki  * Must be called under local_irq_disable().
15830a996fbSRafael J. Wysocki  */
15930a996fbSRafael J. Wysocki static __cpuidle int intel_idle(struct cpuidle_device *dev,
16030a996fbSRafael J. Wysocki 				struct cpuidle_driver *drv, int index)
16130a996fbSRafael J. Wysocki {
16232d4fd57SPeter Zijlstra 	return __intel_idle(dev, drv, index);
16332d4fd57SPeter Zijlstra }
16430a996fbSRafael J. Wysocki 
16532d4fd57SPeter Zijlstra static __cpuidle int intel_idle_irq(struct cpuidle_device *dev,
16632d4fd57SPeter Zijlstra 				    struct cpuidle_driver *drv, int index)
16732d4fd57SPeter Zijlstra {
16832d4fd57SPeter Zijlstra 	int ret;
169c227233aSArtem Bityutskiy 
17032d4fd57SPeter Zijlstra 	raw_local_irq_enable();
17132d4fd57SPeter Zijlstra 	ret = __intel_idle(dev, drv, index);
1726d9c7f51SPeter Zijlstra 	raw_local_irq_disable();
17330a996fbSRafael J. Wysocki 
17432d4fd57SPeter Zijlstra 	return ret;
17530a996fbSRafael J. Wysocki }
17630a996fbSRafael J. Wysocki 
177bf5835bcSPeter Zijlstra static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
178bf5835bcSPeter Zijlstra 				     struct cpuidle_driver *drv, int index)
179bf5835bcSPeter Zijlstra {
180bf5835bcSPeter Zijlstra 	bool smt_active = sched_smt_active();
181bf5835bcSPeter Zijlstra 	u64 spec_ctrl = spec_ctrl_current();
182bf5835bcSPeter Zijlstra 	int ret;
183bf5835bcSPeter Zijlstra 
184bf5835bcSPeter Zijlstra 	if (smt_active)
1859b461a6fSPeter Zijlstra 		native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
186bf5835bcSPeter Zijlstra 
187bf5835bcSPeter Zijlstra 	ret = __intel_idle(dev, drv, index);
188bf5835bcSPeter Zijlstra 
189bf5835bcSPeter Zijlstra 	if (smt_active)
1909b461a6fSPeter Zijlstra 		native_wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl);
191bf5835bcSPeter Zijlstra 
192bf5835bcSPeter Zijlstra 	return ret;
193bf5835bcSPeter Zijlstra }
194bf5835bcSPeter Zijlstra 
1959f011293SChang S. Bae static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
1969f011293SChang S. Bae 				       struct cpuidle_driver *drv, int index)
1979f011293SChang S. Bae {
1989f011293SChang S. Bae 	fpu_idle_fpregs();
1999f011293SChang S. Bae 	return __intel_idle(dev, drv, index);
2009f011293SChang S. Bae }
2019f011293SChang S. Bae 
2022f3d08f0SArjan van de Ven static __always_inline int __intel_idle_hlt(struct cpuidle_device *dev,
2032f3d08f0SArjan van de Ven 					struct cpuidle_driver *drv, int index)
2042f3d08f0SArjan van de Ven {
2052f3d08f0SArjan van de Ven 	raw_safe_halt();
2062f3d08f0SArjan van de Ven 	raw_local_irq_disable();
2072f3d08f0SArjan van de Ven 	return index;
2082f3d08f0SArjan van de Ven }
2092f3d08f0SArjan van de Ven 
2102f3d08f0SArjan van de Ven /**
2112f3d08f0SArjan van de Ven  * intel_idle_hlt - Ask the processor to enter the given idle state using hlt.
2122f3d08f0SArjan van de Ven  * @dev: cpuidle device of the target CPU.
2132f3d08f0SArjan van de Ven  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
2142f3d08f0SArjan van de Ven  * @index: Target idle state index.
2152f3d08f0SArjan van de Ven  *
2162f3d08f0SArjan van de Ven  * Use the HLT instruction to notify the processor that the CPU represented by
2172f3d08f0SArjan van de Ven  * @dev is idle and it can try to enter the idle state corresponding to @index.
2182f3d08f0SArjan van de Ven  *
2192f3d08f0SArjan van de Ven  * Must be called under local_irq_disable().
2202f3d08f0SArjan van de Ven  */
2212f3d08f0SArjan van de Ven static __cpuidle int intel_idle_hlt(struct cpuidle_device *dev,
2222f3d08f0SArjan van de Ven 				struct cpuidle_driver *drv, int index)
2232f3d08f0SArjan van de Ven {
2242f3d08f0SArjan van de Ven 	return __intel_idle_hlt(dev, drv, index);
2252f3d08f0SArjan van de Ven }
2262f3d08f0SArjan van de Ven 
2272f3d08f0SArjan van de Ven static __cpuidle int intel_idle_hlt_irq_on(struct cpuidle_device *dev,
2282f3d08f0SArjan van de Ven                                    struct cpuidle_driver *drv, int index)
2292f3d08f0SArjan van de Ven {
2302f3d08f0SArjan van de Ven        int ret;
2312f3d08f0SArjan van de Ven 
2322f3d08f0SArjan van de Ven        raw_local_irq_enable();
2332f3d08f0SArjan van de Ven        ret = __intel_idle_hlt(dev, drv, index);
2342f3d08f0SArjan van de Ven        raw_local_irq_disable();
2352f3d08f0SArjan van de Ven 
2362f3d08f0SArjan van de Ven        return ret;
2372f3d08f0SArjan van de Ven }
2382f3d08f0SArjan van de Ven 
23930a996fbSRafael J. Wysocki /**
24030a996fbSRafael J. Wysocki  * intel_idle_s2idle - Ask the processor to enter the given idle state.
24130a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
24230a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
24330a996fbSRafael J. Wysocki  * @index: Target idle state index.
24430a996fbSRafael J. Wysocki  *
24530a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
24630a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
24730a996fbSRafael J. Wysocki  *
24830a996fbSRafael J. Wysocki  * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
24930a996fbSRafael J. Wysocki  * scheduler tick and suspended scheduler clock on the target CPU.
25030a996fbSRafael J. Wysocki  */
251efe97112SNeal Liu static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
25230a996fbSRafael J. Wysocki 				       struct cpuidle_driver *drv, int index)
25330a996fbSRafael J. Wysocki {
25430a996fbSRafael J. Wysocki 	unsigned long ecx = 1; /* break on interrupt flag */
2559f011293SChang S. Bae 	struct cpuidle_state *state = &drv->states[index];
2569f011293SChang S. Bae 	unsigned long eax = flg2MWAIT(state->flags);
2579f011293SChang S. Bae 
2589f011293SChang S. Bae 	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE)
2599f011293SChang S. Bae 		fpu_idle_fpregs();
26030a996fbSRafael J. Wysocki 
26130a996fbSRafael J. Wysocki 	mwait_idle_with_hints(eax, ecx);
262efe97112SNeal Liu 
263efe97112SNeal Liu 	return 0;
26430a996fbSRafael J. Wysocki }
26530a996fbSRafael J. Wysocki 
266b1beab48SLen Brown /*
26726717172SLen Brown  * States are indexed by the cstate number,
26826717172SLen Brown  * which is also the index into the MWAIT hint array.
26926717172SLen Brown  * Thus C0 is a dummy.
27026717172SLen Brown  */
271ab1a8522SRafael J. Wysocki static struct cpuidle_state nehalem_cstates[] __initdata = {
272e022e7ebSLen Brown 	{
273de09cdd0SLen Brown 		.name = "C1",
27426717172SLen Brown 		.desc = "MWAIT 0x00",
275b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
27626717172SLen Brown 		.exit_latency = 3,
27726717172SLen Brown 		.target_residency = 6,
2785fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
27928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
280e022e7ebSLen Brown 	{
281de09cdd0SLen Brown 		.name = "C1E",
28232e95180SLen Brown 		.desc = "MWAIT 0x01",
283e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
28432e95180SLen Brown 		.exit_latency = 10,
28532e95180SLen Brown 		.target_residency = 20,
2865fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
28728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
28832e95180SLen Brown 	{
289de09cdd0SLen Brown 		.name = "C3",
29026717172SLen Brown 		.desc = "MWAIT 0x10",
291b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
29226717172SLen Brown 		.exit_latency = 20,
29326717172SLen Brown 		.target_residency = 80,
2945fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
29528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
296e022e7ebSLen Brown 	{
297de09cdd0SLen Brown 		.name = "C6",
29826717172SLen Brown 		.desc = "MWAIT 0x20",
299b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
30026717172SLen Brown 		.exit_latency = 200,
30126717172SLen Brown 		.target_residency = 800,
3025fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
30328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
304e022e7ebSLen Brown 	{
305e022e7ebSLen Brown 		.enter = NULL }
30626717172SLen Brown };
30726717172SLen Brown 
308ab1a8522SRafael J. Wysocki static struct cpuidle_state snb_cstates[] __initdata = {
309e022e7ebSLen Brown 	{
310de09cdd0SLen Brown 		.name = "C1",
311d13780d4SLen Brown 		.desc = "MWAIT 0x00",
312b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
31332e95180SLen Brown 		.exit_latency = 2,
31432e95180SLen Brown 		.target_residency = 2,
3155fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
31628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
31732e95180SLen Brown 	{
318de09cdd0SLen Brown 		.name = "C1E",
31932e95180SLen Brown 		.desc = "MWAIT 0x01",
320e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
32132e95180SLen Brown 		.exit_latency = 10,
32232e95180SLen Brown 		.target_residency = 20,
3235fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
32428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
325e022e7ebSLen Brown 	{
326de09cdd0SLen Brown 		.name = "C3",
327d13780d4SLen Brown 		.desc = "MWAIT 0x10",
328b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
329d13780d4SLen Brown 		.exit_latency = 80,
330ddbd550dSLen Brown 		.target_residency = 211,
3315fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
33228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
333e022e7ebSLen Brown 	{
334de09cdd0SLen Brown 		.name = "C6",
335d13780d4SLen Brown 		.desc = "MWAIT 0x20",
336b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
337d13780d4SLen Brown 		.exit_latency = 104,
338ddbd550dSLen Brown 		.target_residency = 345,
3395fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
34028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
341e022e7ebSLen Brown 	{
342de09cdd0SLen Brown 		.name = "C7",
343d13780d4SLen Brown 		.desc = "MWAIT 0x30",
344b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
345d13780d4SLen Brown 		.exit_latency = 109,
346ddbd550dSLen Brown 		.target_residency = 345,
3475fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
34828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
349e022e7ebSLen Brown 	{
350e022e7ebSLen Brown 		.enter = NULL }
351d13780d4SLen Brown };
352d13780d4SLen Brown 
353ab1a8522SRafael J. Wysocki static struct cpuidle_state byt_cstates[] __initdata = {
354718987d6SLen Brown 	{
355de09cdd0SLen Brown 		.name = "C1",
356718987d6SLen Brown 		.desc = "MWAIT 0x00",
357b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
358718987d6SLen Brown 		.exit_latency = 1,
359718987d6SLen Brown 		.target_residency = 1,
3605fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
36128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
362718987d6SLen Brown 	{
363de09cdd0SLen Brown 		.name = "C6N",
364718987d6SLen Brown 		.desc = "MWAIT 0x58",
365b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
366d7ef7671SLen Brown 		.exit_latency = 300,
367718987d6SLen Brown 		.target_residency = 275,
3685fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
36928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
370718987d6SLen Brown 	{
371de09cdd0SLen Brown 		.name = "C6S",
372718987d6SLen Brown 		.desc = "MWAIT 0x52",
373b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
374d7ef7671SLen Brown 		.exit_latency = 500,
375718987d6SLen Brown 		.target_residency = 560,
3765fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
37728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
378718987d6SLen Brown 	{
379de09cdd0SLen Brown 		.name = "C7",
380718987d6SLen Brown 		.desc = "MWAIT 0x60",
381b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
382718987d6SLen Brown 		.exit_latency = 1200,
383d7ef7671SLen Brown 		.target_residency = 4000,
3845fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
38528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
386718987d6SLen Brown 	{
387de09cdd0SLen Brown 		.name = "C7S",
388718987d6SLen Brown 		.desc = "MWAIT 0x64",
389b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
390718987d6SLen Brown 		.exit_latency = 10000,
391718987d6SLen Brown 		.target_residency = 20000,
3925fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
39328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
394718987d6SLen Brown 	{
395718987d6SLen Brown 		.enter = NULL }
396718987d6SLen Brown };
397718987d6SLen Brown 
398ab1a8522SRafael J. Wysocki static struct cpuidle_state cht_cstates[] __initdata = {
399cab07a56SLen Brown 	{
400de09cdd0SLen Brown 		.name = "C1",
401cab07a56SLen Brown 		.desc = "MWAIT 0x00",
402cab07a56SLen Brown 		.flags = MWAIT2flg(0x00),
403cab07a56SLen Brown 		.exit_latency = 1,
404cab07a56SLen Brown 		.target_residency = 1,
405cab07a56SLen Brown 		.enter = &intel_idle,
40628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
407cab07a56SLen Brown 	{
408de09cdd0SLen Brown 		.name = "C6N",
409cab07a56SLen Brown 		.desc = "MWAIT 0x58",
410cab07a56SLen Brown 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
411cab07a56SLen Brown 		.exit_latency = 80,
412cab07a56SLen Brown 		.target_residency = 275,
413cab07a56SLen Brown 		.enter = &intel_idle,
41428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
415cab07a56SLen Brown 	{
416de09cdd0SLen Brown 		.name = "C6S",
417cab07a56SLen Brown 		.desc = "MWAIT 0x52",
418cab07a56SLen Brown 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
419cab07a56SLen Brown 		.exit_latency = 200,
420cab07a56SLen Brown 		.target_residency = 560,
421cab07a56SLen Brown 		.enter = &intel_idle,
42228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
423cab07a56SLen Brown 	{
424de09cdd0SLen Brown 		.name = "C7",
425cab07a56SLen Brown 		.desc = "MWAIT 0x60",
426cab07a56SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
427cab07a56SLen Brown 		.exit_latency = 1200,
428cab07a56SLen Brown 		.target_residency = 4000,
429cab07a56SLen Brown 		.enter = &intel_idle,
43028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
431cab07a56SLen Brown 	{
432de09cdd0SLen Brown 		.name = "C7S",
433cab07a56SLen Brown 		.desc = "MWAIT 0x64",
434cab07a56SLen Brown 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
435cab07a56SLen Brown 		.exit_latency = 10000,
436cab07a56SLen Brown 		.target_residency = 20000,
437cab07a56SLen Brown 		.enter = &intel_idle,
43828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
439cab07a56SLen Brown 	{
440cab07a56SLen Brown 		.enter = NULL }
441cab07a56SLen Brown };
442cab07a56SLen Brown 
443ab1a8522SRafael J. Wysocki static struct cpuidle_state ivb_cstates[] __initdata = {
444e022e7ebSLen Brown 	{
445de09cdd0SLen Brown 		.name = "C1",
4466edab08cSLen Brown 		.desc = "MWAIT 0x00",
447b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4486edab08cSLen Brown 		.exit_latency = 1,
4496edab08cSLen Brown 		.target_residency = 1,
4505fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
45128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
452e022e7ebSLen Brown 	{
453de09cdd0SLen Brown 		.name = "C1E",
45432e95180SLen Brown 		.desc = "MWAIT 0x01",
455e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
45632e95180SLen Brown 		.exit_latency = 10,
45732e95180SLen Brown 		.target_residency = 20,
4585fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
45928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
46032e95180SLen Brown 	{
461de09cdd0SLen Brown 		.name = "C3",
4626edab08cSLen Brown 		.desc = "MWAIT 0x10",
463b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4646edab08cSLen Brown 		.exit_latency = 59,
4656edab08cSLen Brown 		.target_residency = 156,
4665fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
46728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
468e022e7ebSLen Brown 	{
469de09cdd0SLen Brown 		.name = "C6",
4706edab08cSLen Brown 		.desc = "MWAIT 0x20",
471b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4726edab08cSLen Brown 		.exit_latency = 80,
4736edab08cSLen Brown 		.target_residency = 300,
4745fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
47528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
476e022e7ebSLen Brown 	{
477de09cdd0SLen Brown 		.name = "C7",
4786edab08cSLen Brown 		.desc = "MWAIT 0x30",
479b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
4806edab08cSLen Brown 		.exit_latency = 87,
4816edab08cSLen Brown 		.target_residency = 300,
4825fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
48328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
484e022e7ebSLen Brown 	{
485e022e7ebSLen Brown 		.enter = NULL }
4866edab08cSLen Brown };
4876edab08cSLen Brown 
488ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates[] __initdata = {
4890138d8f0SLen Brown 	{
490de09cdd0SLen Brown 		.name = "C1",
4910138d8f0SLen Brown 		.desc = "MWAIT 0x00",
492b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4930138d8f0SLen Brown 		.exit_latency = 1,
4940138d8f0SLen Brown 		.target_residency = 1,
4955fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
49628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4970138d8f0SLen Brown 	{
498de09cdd0SLen Brown 		.name = "C1E",
4990138d8f0SLen Brown 		.desc = "MWAIT 0x01",
500e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
5010138d8f0SLen Brown 		.exit_latency = 10,
5020138d8f0SLen Brown 		.target_residency = 80,
5035fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
50428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5050138d8f0SLen Brown 	{
506de09cdd0SLen Brown 		.name = "C3",
5070138d8f0SLen Brown 		.desc = "MWAIT 0x10",
508b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5090138d8f0SLen Brown 		.exit_latency = 59,
5100138d8f0SLen Brown 		.target_residency = 156,
5115fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
51228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5130138d8f0SLen Brown 	{
514de09cdd0SLen Brown 		.name = "C6",
5150138d8f0SLen Brown 		.desc = "MWAIT 0x20",
516b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5170138d8f0SLen Brown 		.exit_latency = 82,
5180138d8f0SLen Brown 		.target_residency = 300,
5195fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
52028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5210138d8f0SLen Brown 	{
5220138d8f0SLen Brown 		.enter = NULL }
5230138d8f0SLen Brown };
5240138d8f0SLen Brown 
525ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_4s[] __initdata = {
5260138d8f0SLen Brown 	{
527de09cdd0SLen Brown 		.name = "C1",
5280138d8f0SLen Brown 		.desc = "MWAIT 0x00",
529b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
5300138d8f0SLen Brown 		.exit_latency = 1,
5310138d8f0SLen Brown 		.target_residency = 1,
5325fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
53328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5340138d8f0SLen Brown 	{
535de09cdd0SLen Brown 		.name = "C1E",
5360138d8f0SLen Brown 		.desc = "MWAIT 0x01",
537e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
5380138d8f0SLen Brown 		.exit_latency = 10,
5390138d8f0SLen Brown 		.target_residency = 250,
5405fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
54128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5420138d8f0SLen Brown 	{
543de09cdd0SLen Brown 		.name = "C3",
5440138d8f0SLen Brown 		.desc = "MWAIT 0x10",
545b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5460138d8f0SLen Brown 		.exit_latency = 59,
5470138d8f0SLen Brown 		.target_residency = 300,
5485fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
54928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5500138d8f0SLen Brown 	{
551de09cdd0SLen Brown 		.name = "C6",
5520138d8f0SLen Brown 		.desc = "MWAIT 0x20",
553b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5540138d8f0SLen Brown 		.exit_latency = 84,
5550138d8f0SLen Brown 		.target_residency = 400,
5565fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
55728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5580138d8f0SLen Brown 	{
5590138d8f0SLen Brown 		.enter = NULL }
5600138d8f0SLen Brown };
5610138d8f0SLen Brown 
562ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_8s[] __initdata = {
5630138d8f0SLen Brown 	{
564de09cdd0SLen Brown 		.name = "C1",
5650138d8f0SLen Brown 		.desc = "MWAIT 0x00",
566b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
5670138d8f0SLen Brown 		.exit_latency = 1,
5680138d8f0SLen Brown 		.target_residency = 1,
5695fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
57028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5710138d8f0SLen Brown 	{
572de09cdd0SLen Brown 		.name = "C1E",
5730138d8f0SLen Brown 		.desc = "MWAIT 0x01",
574e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
5750138d8f0SLen Brown 		.exit_latency = 10,
5760138d8f0SLen Brown 		.target_residency = 500,
5775fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
57828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5790138d8f0SLen Brown 	{
580de09cdd0SLen Brown 		.name = "C3",
5810138d8f0SLen Brown 		.desc = "MWAIT 0x10",
582b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5830138d8f0SLen Brown 		.exit_latency = 59,
5840138d8f0SLen Brown 		.target_residency = 600,
5855fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
58628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5870138d8f0SLen Brown 	{
588de09cdd0SLen Brown 		.name = "C6",
5890138d8f0SLen Brown 		.desc = "MWAIT 0x20",
590b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5910138d8f0SLen Brown 		.exit_latency = 88,
5920138d8f0SLen Brown 		.target_residency = 700,
5935fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
59428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5950138d8f0SLen Brown 	{
5960138d8f0SLen Brown 		.enter = NULL }
5970138d8f0SLen Brown };
5980138d8f0SLen Brown 
599ab1a8522SRafael J. Wysocki static struct cpuidle_state hsw_cstates[] __initdata = {
600e022e7ebSLen Brown 	{
601de09cdd0SLen Brown 		.name = "C1",
60285a4d2d4SLen Brown 		.desc = "MWAIT 0x00",
603b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
60485a4d2d4SLen Brown 		.exit_latency = 2,
60585a4d2d4SLen Brown 		.target_residency = 2,
6065fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
60728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
608e022e7ebSLen Brown 	{
609de09cdd0SLen Brown 		.name = "C1E",
61032e95180SLen Brown 		.desc = "MWAIT 0x01",
611e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
61232e95180SLen Brown 		.exit_latency = 10,
61332e95180SLen Brown 		.target_residency = 20,
6145fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
61528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
61632e95180SLen Brown 	{
617de09cdd0SLen Brown 		.name = "C3",
61885a4d2d4SLen Brown 		.desc = "MWAIT 0x10",
619b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
62085a4d2d4SLen Brown 		.exit_latency = 33,
62185a4d2d4SLen Brown 		.target_residency = 100,
6225fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
62328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
624e022e7ebSLen Brown 	{
625de09cdd0SLen Brown 		.name = "C6",
62685a4d2d4SLen Brown 		.desc = "MWAIT 0x20",
627b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
62885a4d2d4SLen Brown 		.exit_latency = 133,
62985a4d2d4SLen Brown 		.target_residency = 400,
6305fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
63128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
632e022e7ebSLen Brown 	{
633de09cdd0SLen Brown 		.name = "C7s",
63485a4d2d4SLen Brown 		.desc = "MWAIT 0x32",
635b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
63685a4d2d4SLen Brown 		.exit_latency = 166,
63785a4d2d4SLen Brown 		.target_residency = 500,
6385fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
63928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
640e022e7ebSLen Brown 	{
641de09cdd0SLen Brown 		.name = "C8",
64286239cebSLen Brown 		.desc = "MWAIT 0x40",
643b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
64486239cebSLen Brown 		.exit_latency = 300,
64586239cebSLen Brown 		.target_residency = 900,
6465fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
64728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
64886239cebSLen Brown 	{
649de09cdd0SLen Brown 		.name = "C9",
65086239cebSLen Brown 		.desc = "MWAIT 0x50",
651b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
65286239cebSLen Brown 		.exit_latency = 600,
65386239cebSLen Brown 		.target_residency = 1800,
6545fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
65528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
65686239cebSLen Brown 	{
657de09cdd0SLen Brown 		.name = "C10",
65886239cebSLen Brown 		.desc = "MWAIT 0x60",
659b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
66086239cebSLen Brown 		.exit_latency = 2600,
66186239cebSLen Brown 		.target_residency = 7700,
6625fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
66328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
66486239cebSLen Brown 	{
665e022e7ebSLen Brown 		.enter = NULL }
66685a4d2d4SLen Brown };
667ab1a8522SRafael J. Wysocki static struct cpuidle_state bdw_cstates[] __initdata = {
668a138b568SLen Brown 	{
669de09cdd0SLen Brown 		.name = "C1",
670a138b568SLen Brown 		.desc = "MWAIT 0x00",
671b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
672a138b568SLen Brown 		.exit_latency = 2,
673a138b568SLen Brown 		.target_residency = 2,
6745fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
67528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
676a138b568SLen Brown 	{
677de09cdd0SLen Brown 		.name = "C1E",
678a138b568SLen Brown 		.desc = "MWAIT 0x01",
679e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
680a138b568SLen Brown 		.exit_latency = 10,
681a138b568SLen Brown 		.target_residency = 20,
6825fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
68328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
684a138b568SLen Brown 	{
685de09cdd0SLen Brown 		.name = "C3",
686a138b568SLen Brown 		.desc = "MWAIT 0x10",
687b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
688a138b568SLen Brown 		.exit_latency = 40,
689a138b568SLen Brown 		.target_residency = 100,
6905fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
69128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
692a138b568SLen Brown 	{
693de09cdd0SLen Brown 		.name = "C6",
694a138b568SLen Brown 		.desc = "MWAIT 0x20",
695b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
696a138b568SLen Brown 		.exit_latency = 133,
697a138b568SLen Brown 		.target_residency = 400,
6985fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
69928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
700a138b568SLen Brown 	{
701de09cdd0SLen Brown 		.name = "C7s",
702a138b568SLen Brown 		.desc = "MWAIT 0x32",
703b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
704a138b568SLen Brown 		.exit_latency = 166,
705a138b568SLen Brown 		.target_residency = 500,
7065fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
70728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
708a138b568SLen Brown 	{
709de09cdd0SLen Brown 		.name = "C8",
710a138b568SLen Brown 		.desc = "MWAIT 0x40",
711b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
712a138b568SLen Brown 		.exit_latency = 300,
713a138b568SLen Brown 		.target_residency = 900,
7145fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
71528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
716a138b568SLen Brown 	{
717de09cdd0SLen Brown 		.name = "C9",
718a138b568SLen Brown 		.desc = "MWAIT 0x50",
719b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
720a138b568SLen Brown 		.exit_latency = 600,
721a138b568SLen Brown 		.target_residency = 1800,
7225fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
72328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
724a138b568SLen Brown 	{
725de09cdd0SLen Brown 		.name = "C10",
726a138b568SLen Brown 		.desc = "MWAIT 0x60",
727b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
728a138b568SLen Brown 		.exit_latency = 2600,
729a138b568SLen Brown 		.target_residency = 7700,
7305fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
73128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
732a138b568SLen Brown 	{
733a138b568SLen Brown 		.enter = NULL }
734a138b568SLen Brown };
73585a4d2d4SLen Brown 
736ab1a8522SRafael J. Wysocki static struct cpuidle_state skl_cstates[] __initdata = {
737493f133fSLen Brown 	{
738de09cdd0SLen Brown 		.name = "C1",
739493f133fSLen Brown 		.desc = "MWAIT 0x00",
740493f133fSLen Brown 		.flags = MWAIT2flg(0x00),
741493f133fSLen Brown 		.exit_latency = 2,
742493f133fSLen Brown 		.target_residency = 2,
743493f133fSLen Brown 		.enter = &intel_idle,
74428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
745493f133fSLen Brown 	{
746de09cdd0SLen Brown 		.name = "C1E",
747493f133fSLen Brown 		.desc = "MWAIT 0x01",
748e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
749493f133fSLen Brown 		.exit_latency = 10,
750493f133fSLen Brown 		.target_residency = 20,
751493f133fSLen Brown 		.enter = &intel_idle,
75228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
753493f133fSLen Brown 	{
754de09cdd0SLen Brown 		.name = "C3",
755493f133fSLen Brown 		.desc = "MWAIT 0x10",
756493f133fSLen Brown 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
757493f133fSLen Brown 		.exit_latency = 70,
758493f133fSLen Brown 		.target_residency = 100,
759493f133fSLen Brown 		.enter = &intel_idle,
76028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
761493f133fSLen Brown 	{
762de09cdd0SLen Brown 		.name = "C6",
763493f133fSLen Brown 		.desc = "MWAIT 0x20",
764bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
765135919a3SLen Brown 		.exit_latency = 85,
766493f133fSLen Brown 		.target_residency = 200,
767493f133fSLen Brown 		.enter = &intel_idle,
76828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
769493f133fSLen Brown 	{
770de09cdd0SLen Brown 		.name = "C7s",
771493f133fSLen Brown 		.desc = "MWAIT 0x33",
772bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
773493f133fSLen Brown 		.exit_latency = 124,
774493f133fSLen Brown 		.target_residency = 800,
775493f133fSLen Brown 		.enter = &intel_idle,
77628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
777493f133fSLen Brown 	{
778de09cdd0SLen Brown 		.name = "C8",
779493f133fSLen Brown 		.desc = "MWAIT 0x40",
780bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
781135919a3SLen Brown 		.exit_latency = 200,
782493f133fSLen Brown 		.target_residency = 800,
783493f133fSLen Brown 		.enter = &intel_idle,
78428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
785493f133fSLen Brown 	{
786de09cdd0SLen Brown 		.name = "C9",
787135919a3SLen Brown 		.desc = "MWAIT 0x50",
788bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
789135919a3SLen Brown 		.exit_latency = 480,
790135919a3SLen Brown 		.target_residency = 5000,
791135919a3SLen Brown 		.enter = &intel_idle,
79228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
793135919a3SLen Brown 	{
794de09cdd0SLen Brown 		.name = "C10",
795493f133fSLen Brown 		.desc = "MWAIT 0x60",
796bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
797493f133fSLen Brown 		.exit_latency = 890,
798493f133fSLen Brown 		.target_residency = 5000,
799493f133fSLen Brown 		.enter = &intel_idle,
80028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
801493f133fSLen Brown 	{
802493f133fSLen Brown 		.enter = NULL }
803493f133fSLen Brown };
804493f133fSLen Brown 
805ab1a8522SRafael J. Wysocki static struct cpuidle_state skx_cstates[] __initdata = {
806f9e71657SLen Brown 	{
807de09cdd0SLen Brown 		.name = "C1",
808f9e71657SLen Brown 		.desc = "MWAIT 0x00",
809c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
810f9e71657SLen Brown 		.exit_latency = 2,
811f9e71657SLen Brown 		.target_residency = 2,
812f9e71657SLen Brown 		.enter = &intel_idle,
81328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
814f9e71657SLen Brown 	{
815de09cdd0SLen Brown 		.name = "C1E",
816f9e71657SLen Brown 		.desc = "MWAIT 0x01",
817e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
818f9e71657SLen Brown 		.exit_latency = 10,
819f9e71657SLen Brown 		.target_residency = 20,
820f9e71657SLen Brown 		.enter = &intel_idle,
82128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
822f9e71657SLen Brown 	{
823de09cdd0SLen Brown 		.name = "C6",
824f9e71657SLen Brown 		.desc = "MWAIT 0x20",
825bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
826f9e71657SLen Brown 		.exit_latency = 133,
827f9e71657SLen Brown 		.target_residency = 600,
828f9e71657SLen Brown 		.enter = &intel_idle,
82928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
830f9e71657SLen Brown 	{
831f9e71657SLen Brown 		.enter = NULL }
832f9e71657SLen Brown };
833f9e71657SLen Brown 
834a472ad2bSChen Yu static struct cpuidle_state icx_cstates[] __initdata = {
835a472ad2bSChen Yu 	{
836a472ad2bSChen Yu 		.name = "C1",
837a472ad2bSChen Yu 		.desc = "MWAIT 0x00",
838c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
839a472ad2bSChen Yu 		.exit_latency = 1,
840a472ad2bSChen Yu 		.target_residency = 1,
841a472ad2bSChen Yu 		.enter = &intel_idle,
842a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
843a472ad2bSChen Yu 	{
844a472ad2bSChen Yu 		.name = "C1E",
845a472ad2bSChen Yu 		.desc = "MWAIT 0x01",
846a472ad2bSChen Yu 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
847a472ad2bSChen Yu 		.exit_latency = 4,
848a472ad2bSChen Yu 		.target_residency = 4,
849a472ad2bSChen Yu 		.enter = &intel_idle,
850a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
851a472ad2bSChen Yu 	{
852a472ad2bSChen Yu 		.name = "C6",
853a472ad2bSChen Yu 		.desc = "MWAIT 0x20",
854a472ad2bSChen Yu 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
855d484b8bfSArtem Bityutskiy 		.exit_latency = 170,
856d484b8bfSArtem Bityutskiy 		.target_residency = 600,
857a472ad2bSChen Yu 		.enter = &intel_idle,
858a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
859a472ad2bSChen Yu 	{
860a472ad2bSChen Yu 		.enter = NULL }
861a472ad2bSChen Yu };
862a472ad2bSChen Yu 
8639edf3c0fSArtem Bityutskiy /*
864d1cf8bbfSZhang Rui  * On AlderLake C1 has to be disabled if C1E is enabled, and vice versa.
865d1cf8bbfSZhang Rui  * C1E is enabled only if "C1E promotion" bit is set in MSR_IA32_POWER_CTL.
866d1cf8bbfSZhang Rui  * But in this case there is effectively no C1, because C1 requests are
867d1cf8bbfSZhang Rui  * promoted to C1E. If the "C1E promotion" bit is cleared, then both C1
868d1cf8bbfSZhang Rui  * and C1E requests end up with C1, so there is effectively no C1E.
869d1cf8bbfSZhang Rui  *
870d1cf8bbfSZhang Rui  * By default we enable C1E and disable C1 by marking it with
871d1cf8bbfSZhang Rui  * 'CPUIDLE_FLAG_UNUSABLE'.
872d1cf8bbfSZhang Rui  */
873d1cf8bbfSZhang Rui static struct cpuidle_state adl_cstates[] __initdata = {
874d1cf8bbfSZhang Rui 	{
875d1cf8bbfSZhang Rui 		.name = "C1",
876d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
877d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
878d1cf8bbfSZhang Rui 		.exit_latency = 1,
879d1cf8bbfSZhang Rui 		.target_residency = 1,
880d1cf8bbfSZhang Rui 		.enter = &intel_idle,
881d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
882d1cf8bbfSZhang Rui 	{
883d1cf8bbfSZhang Rui 		.name = "C1E",
884d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
885d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
886d1cf8bbfSZhang Rui 		.exit_latency = 2,
887d1cf8bbfSZhang Rui 		.target_residency = 4,
888d1cf8bbfSZhang Rui 		.enter = &intel_idle,
889d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
890d1cf8bbfSZhang Rui 	{
891d1cf8bbfSZhang Rui 		.name = "C6",
892d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
893d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
894d1cf8bbfSZhang Rui 		.exit_latency = 220,
895d1cf8bbfSZhang Rui 		.target_residency = 600,
896d1cf8bbfSZhang Rui 		.enter = &intel_idle,
897d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
898d1cf8bbfSZhang Rui 	{
899d1cf8bbfSZhang Rui 		.name = "C8",
900d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
901d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
902d1cf8bbfSZhang Rui 		.exit_latency = 280,
903d1cf8bbfSZhang Rui 		.target_residency = 800,
904d1cf8bbfSZhang Rui 		.enter = &intel_idle,
905d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
906d1cf8bbfSZhang Rui 	{
907d1cf8bbfSZhang Rui 		.name = "C10",
908d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
909d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
910d1cf8bbfSZhang Rui 		.exit_latency = 680,
911d1cf8bbfSZhang Rui 		.target_residency = 2000,
912d1cf8bbfSZhang Rui 		.enter = &intel_idle,
913d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
914d1cf8bbfSZhang Rui 	{
915d1cf8bbfSZhang Rui 		.enter = NULL }
916d1cf8bbfSZhang Rui };
917d1cf8bbfSZhang Rui 
918d1cf8bbfSZhang Rui static struct cpuidle_state adl_l_cstates[] __initdata = {
919d1cf8bbfSZhang Rui 	{
920d1cf8bbfSZhang Rui 		.name = "C1",
921d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
922d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
923d1cf8bbfSZhang Rui 		.exit_latency = 1,
924d1cf8bbfSZhang Rui 		.target_residency = 1,
925d1cf8bbfSZhang Rui 		.enter = &intel_idle,
926d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
927d1cf8bbfSZhang Rui 	{
928d1cf8bbfSZhang Rui 		.name = "C1E",
929d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
930d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
931d1cf8bbfSZhang Rui 		.exit_latency = 2,
932d1cf8bbfSZhang Rui 		.target_residency = 4,
933d1cf8bbfSZhang Rui 		.enter = &intel_idle,
934d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
935d1cf8bbfSZhang Rui 	{
936d1cf8bbfSZhang Rui 		.name = "C6",
937d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
938d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
939d1cf8bbfSZhang Rui 		.exit_latency = 170,
940d1cf8bbfSZhang Rui 		.target_residency = 500,
941d1cf8bbfSZhang Rui 		.enter = &intel_idle,
942d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
943d1cf8bbfSZhang Rui 	{
944d1cf8bbfSZhang Rui 		.name = "C8",
945d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
946d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
947d1cf8bbfSZhang Rui 		.exit_latency = 200,
948d1cf8bbfSZhang Rui 		.target_residency = 600,
949d1cf8bbfSZhang Rui 		.enter = &intel_idle,
950d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
951d1cf8bbfSZhang Rui 	{
952d1cf8bbfSZhang Rui 		.name = "C10",
953d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
954d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
955d1cf8bbfSZhang Rui 		.exit_latency = 230,
956d1cf8bbfSZhang Rui 		.target_residency = 700,
957d1cf8bbfSZhang Rui 		.enter = &intel_idle,
958d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
959d1cf8bbfSZhang Rui 	{
960d1cf8bbfSZhang Rui 		.enter = NULL }
961d1cf8bbfSZhang Rui };
962d1cf8bbfSZhang Rui 
96365c0c236SZhang Rui static struct cpuidle_state adl_n_cstates[] __initdata = {
96465c0c236SZhang Rui 	{
96565c0c236SZhang Rui 		.name = "C1",
96665c0c236SZhang Rui 		.desc = "MWAIT 0x00",
96765c0c236SZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
96865c0c236SZhang Rui 		.exit_latency = 1,
96965c0c236SZhang Rui 		.target_residency = 1,
97065c0c236SZhang Rui 		.enter = &intel_idle,
97165c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
97265c0c236SZhang Rui 	{
97365c0c236SZhang Rui 		.name = "C1E",
97465c0c236SZhang Rui 		.desc = "MWAIT 0x01",
97565c0c236SZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
97665c0c236SZhang Rui 		.exit_latency = 2,
97765c0c236SZhang Rui 		.target_residency = 4,
97865c0c236SZhang Rui 		.enter = &intel_idle,
97965c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
98065c0c236SZhang Rui 	{
98165c0c236SZhang Rui 		.name = "C6",
98265c0c236SZhang Rui 		.desc = "MWAIT 0x20",
98365c0c236SZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
98465c0c236SZhang Rui 		.exit_latency = 195,
98565c0c236SZhang Rui 		.target_residency = 585,
98665c0c236SZhang Rui 		.enter = &intel_idle,
98765c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
98865c0c236SZhang Rui 	{
98965c0c236SZhang Rui 		.name = "C8",
99065c0c236SZhang Rui 		.desc = "MWAIT 0x40",
99165c0c236SZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
99265c0c236SZhang Rui 		.exit_latency = 260,
99365c0c236SZhang Rui 		.target_residency = 1040,
99465c0c236SZhang Rui 		.enter = &intel_idle,
99565c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
99665c0c236SZhang Rui 	{
99765c0c236SZhang Rui 		.name = "C10",
99865c0c236SZhang Rui 		.desc = "MWAIT 0x60",
99965c0c236SZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
100065c0c236SZhang Rui 		.exit_latency = 660,
100165c0c236SZhang Rui 		.target_residency = 1980,
100265c0c236SZhang Rui 		.enter = &intel_idle,
100365c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
100465c0c236SZhang Rui 	{
100565c0c236SZhang Rui 		.enter = NULL }
100665c0c236SZhang Rui };
100765c0c236SZhang Rui 
10089edf3c0fSArtem Bityutskiy static struct cpuidle_state spr_cstates[] __initdata = {
10099edf3c0fSArtem Bityutskiy 	{
10109edf3c0fSArtem Bityutskiy 		.name = "C1",
10119edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x00",
10129edf3c0fSArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
10139edf3c0fSArtem Bityutskiy 		.exit_latency = 1,
10149edf3c0fSArtem Bityutskiy 		.target_residency = 1,
10159edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
10169edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
10179edf3c0fSArtem Bityutskiy 	{
10189edf3c0fSArtem Bityutskiy 		.name = "C1E",
10199edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x01",
10201548fac4SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
10219edf3c0fSArtem Bityutskiy 		.exit_latency = 2,
10229edf3c0fSArtem Bityutskiy 		.target_residency = 4,
10239edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
10249edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
10259edf3c0fSArtem Bityutskiy 	{
10269edf3c0fSArtem Bityutskiy 		.name = "C6",
10279edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x20",
10289f011293SChang S. Bae 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
10299f011293SChang S. Bae 					   CPUIDLE_FLAG_INIT_XSTATE,
10309edf3c0fSArtem Bityutskiy 		.exit_latency = 290,
10319edf3c0fSArtem Bityutskiy 		.target_residency = 800,
10329edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
10339edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
10349edf3c0fSArtem Bityutskiy 	{
10359edf3c0fSArtem Bityutskiy 		.enter = NULL }
10369edf3c0fSArtem Bityutskiy };
10379edf3c0fSArtem Bityutskiy 
1038ab1a8522SRafael J. Wysocki static struct cpuidle_state atom_cstates[] __initdata = {
1039e022e7ebSLen Brown 	{
1040de09cdd0SLen Brown 		.name = "C1E",
104126717172SLen Brown 		.desc = "MWAIT 0x00",
1042b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
104332e95180SLen Brown 		.exit_latency = 10,
104432e95180SLen Brown 		.target_residency = 20,
10455fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
104628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1047e022e7ebSLen Brown 	{
1048de09cdd0SLen Brown 		.name = "C2",
104926717172SLen Brown 		.desc = "MWAIT 0x10",
1050b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10),
105126717172SLen Brown 		.exit_latency = 20,
105226717172SLen Brown 		.target_residency = 80,
10535fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
105428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1055e022e7ebSLen Brown 	{
1056de09cdd0SLen Brown 		.name = "C4",
105726717172SLen Brown 		.desc = "MWAIT 0x30",
1058b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
105926717172SLen Brown 		.exit_latency = 100,
106026717172SLen Brown 		.target_residency = 400,
10615fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
106228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1063e022e7ebSLen Brown 	{
1064de09cdd0SLen Brown 		.name = "C6",
10657fcca7d9SLen Brown 		.desc = "MWAIT 0x52",
1066b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10677fcca7d9SLen Brown 		.exit_latency = 140,
10687fcca7d9SLen Brown 		.target_residency = 560,
10695fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
107028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1071e022e7ebSLen Brown 	{
1072e022e7ebSLen Brown 		.enter = NULL }
107326717172SLen Brown };
1074ab1a8522SRafael J. Wysocki static struct cpuidle_state tangier_cstates[] __initdata = {
10755e7ec268SAndy Shevchenko 	{
1076de09cdd0SLen Brown 		.name = "C1",
10775e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x00",
10785e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x00),
10795e7ec268SAndy Shevchenko 		.exit_latency = 1,
10805e7ec268SAndy Shevchenko 		.target_residency = 4,
10815e7ec268SAndy Shevchenko 		.enter = &intel_idle,
108228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10835e7ec268SAndy Shevchenko 	{
1084de09cdd0SLen Brown 		.name = "C4",
10855e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x30",
10865e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
10875e7ec268SAndy Shevchenko 		.exit_latency = 100,
10885e7ec268SAndy Shevchenko 		.target_residency = 400,
10895e7ec268SAndy Shevchenko 		.enter = &intel_idle,
109028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10915e7ec268SAndy Shevchenko 	{
1092de09cdd0SLen Brown 		.name = "C6",
10935e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x52",
10945e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10955e7ec268SAndy Shevchenko 		.exit_latency = 140,
10965e7ec268SAndy Shevchenko 		.target_residency = 560,
10975e7ec268SAndy Shevchenko 		.enter = &intel_idle,
109828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10995e7ec268SAndy Shevchenko 	{
1100de09cdd0SLen Brown 		.name = "C7",
11015e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x60",
11025e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
11035e7ec268SAndy Shevchenko 		.exit_latency = 1200,
11045e7ec268SAndy Shevchenko 		.target_residency = 4000,
11055e7ec268SAndy Shevchenko 		.enter = &intel_idle,
110628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11075e7ec268SAndy Shevchenko 	{
1108de09cdd0SLen Brown 		.name = "C9",
11095e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x64",
11105e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
11115e7ec268SAndy Shevchenko 		.exit_latency = 10000,
11125e7ec268SAndy Shevchenko 		.target_residency = 20000,
11135e7ec268SAndy Shevchenko 		.enter = &intel_idle,
111428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11155e7ec268SAndy Shevchenko 	{
11165e7ec268SAndy Shevchenko 		.enter = NULL }
11175e7ec268SAndy Shevchenko };
1118ab1a8522SRafael J. Wysocki static struct cpuidle_state avn_cstates[] __initdata = {
1119fab04b22SLen Brown 	{
1120de09cdd0SLen Brown 		.name = "C1",
1121fab04b22SLen Brown 		.desc = "MWAIT 0x00",
1122b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
1123fab04b22SLen Brown 		.exit_latency = 2,
1124fab04b22SLen Brown 		.target_residency = 2,
11255fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
112628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1127fab04b22SLen Brown 	{
1128de09cdd0SLen Brown 		.name = "C6",
1129fab04b22SLen Brown 		.desc = "MWAIT 0x51",
1130b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED,
1131fab04b22SLen Brown 		.exit_latency = 15,
1132fab04b22SLen Brown 		.target_residency = 45,
11335fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
113428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
113588390996SJiang Liu 	{
113688390996SJiang Liu 		.enter = NULL }
1137fab04b22SLen Brown };
1138ab1a8522SRafael J. Wysocki static struct cpuidle_state knl_cstates[] __initdata = {
1139281baf7aSDasaratharaman Chandramouli 	{
1140de09cdd0SLen Brown 		.name = "C1",
1141281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x00",
1142281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x00),
1143281baf7aSDasaratharaman Chandramouli 		.exit_latency = 1,
1144281baf7aSDasaratharaman Chandramouli 		.target_residency = 2,
1145281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
114628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1147281baf7aSDasaratharaman Chandramouli 	{
1148de09cdd0SLen Brown 		.name = "C6",
1149281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x10",
1150281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
1151281baf7aSDasaratharaman Chandramouli 		.exit_latency = 120,
1152281baf7aSDasaratharaman Chandramouli 		.target_residency = 500,
1153281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
115428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1155281baf7aSDasaratharaman Chandramouli 	{
1156281baf7aSDasaratharaman Chandramouli 		.enter = NULL }
1157281baf7aSDasaratharaman Chandramouli };
115826717172SLen Brown 
1159ab1a8522SRafael J. Wysocki static struct cpuidle_state bxt_cstates[] __initdata = {
11605dcef694SLen Brown 	{
1161de09cdd0SLen Brown 		.name = "C1",
11625dcef694SLen Brown 		.desc = "MWAIT 0x00",
11635dcef694SLen Brown 		.flags = MWAIT2flg(0x00),
11645dcef694SLen Brown 		.exit_latency = 2,
11655dcef694SLen Brown 		.target_residency = 2,
11665dcef694SLen Brown 		.enter = &intel_idle,
116728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11685dcef694SLen Brown 	{
1169de09cdd0SLen Brown 		.name = "C1E",
11705dcef694SLen Brown 		.desc = "MWAIT 0x01",
1171e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11725dcef694SLen Brown 		.exit_latency = 10,
11735dcef694SLen Brown 		.target_residency = 20,
11745dcef694SLen Brown 		.enter = &intel_idle,
117528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11765dcef694SLen Brown 	{
1177de09cdd0SLen Brown 		.name = "C6",
11785dcef694SLen Brown 		.desc = "MWAIT 0x20",
11795dcef694SLen Brown 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
11805dcef694SLen Brown 		.exit_latency = 133,
11815dcef694SLen Brown 		.target_residency = 133,
11825dcef694SLen Brown 		.enter = &intel_idle,
118328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11845dcef694SLen Brown 	{
1185de09cdd0SLen Brown 		.name = "C7s",
11865dcef694SLen Brown 		.desc = "MWAIT 0x31",
11875dcef694SLen Brown 		.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
11885dcef694SLen Brown 		.exit_latency = 155,
11895dcef694SLen Brown 		.target_residency = 155,
11905dcef694SLen Brown 		.enter = &intel_idle,
119128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11925dcef694SLen Brown 	{
1193de09cdd0SLen Brown 		.name = "C8",
11945dcef694SLen Brown 		.desc = "MWAIT 0x40",
11955dcef694SLen Brown 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
11965dcef694SLen Brown 		.exit_latency = 1000,
11975dcef694SLen Brown 		.target_residency = 1000,
11985dcef694SLen Brown 		.enter = &intel_idle,
119928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12005dcef694SLen Brown 	{
1201de09cdd0SLen Brown 		.name = "C9",
12025dcef694SLen Brown 		.desc = "MWAIT 0x50",
12035dcef694SLen Brown 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
12045dcef694SLen Brown 		.exit_latency = 2000,
12055dcef694SLen Brown 		.target_residency = 2000,
12065dcef694SLen Brown 		.enter = &intel_idle,
120728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12085dcef694SLen Brown 	{
1209de09cdd0SLen Brown 		.name = "C10",
12105dcef694SLen Brown 		.desc = "MWAIT 0x60",
12115dcef694SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
12125dcef694SLen Brown 		.exit_latency = 10000,
12135dcef694SLen Brown 		.target_residency = 10000,
12145dcef694SLen Brown 		.enter = &intel_idle,
121528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12165dcef694SLen Brown 	{
12175dcef694SLen Brown 		.enter = NULL }
12185dcef694SLen Brown };
12195dcef694SLen Brown 
1220ab1a8522SRafael J. Wysocki static struct cpuidle_state dnv_cstates[] __initdata = {
12210080d65bSJacob Pan 	{
1222de09cdd0SLen Brown 		.name = "C1",
12230080d65bSJacob Pan 		.desc = "MWAIT 0x00",
12240080d65bSJacob Pan 		.flags = MWAIT2flg(0x00),
12250080d65bSJacob Pan 		.exit_latency = 2,
12260080d65bSJacob Pan 		.target_residency = 2,
12270080d65bSJacob Pan 		.enter = &intel_idle,
122828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12290080d65bSJacob Pan 	{
1230de09cdd0SLen Brown 		.name = "C1E",
12310080d65bSJacob Pan 		.desc = "MWAIT 0x01",
1232e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
12330080d65bSJacob Pan 		.exit_latency = 10,
12340080d65bSJacob Pan 		.target_residency = 20,
12350080d65bSJacob Pan 		.enter = &intel_idle,
123628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12370080d65bSJacob Pan 	{
1238de09cdd0SLen Brown 		.name = "C6",
12390080d65bSJacob Pan 		.desc = "MWAIT 0x20",
12400080d65bSJacob Pan 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
12410080d65bSJacob Pan 		.exit_latency = 50,
12420080d65bSJacob Pan 		.target_residency = 500,
12430080d65bSJacob Pan 		.enter = &intel_idle,
124428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12450080d65bSJacob Pan 	{
12460080d65bSJacob Pan 		.enter = NULL }
12470080d65bSJacob Pan };
12480080d65bSJacob Pan 
12499cf93f05SArtem Bityutskiy /*
12509cf93f05SArtem Bityutskiy  * Note, depending on HW and FW revision, SnowRidge SoC may or may not support
12519cf93f05SArtem Bityutskiy  * C6, and this is indicated in the CPUID mwait leaf.
12529cf93f05SArtem Bityutskiy  */
12539cf93f05SArtem Bityutskiy static struct cpuidle_state snr_cstates[] __initdata = {
12549cf93f05SArtem Bityutskiy 	{
12559cf93f05SArtem Bityutskiy 		.name = "C1",
12569cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x00",
12579cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
12589cf93f05SArtem Bityutskiy 		.exit_latency = 2,
12599cf93f05SArtem Bityutskiy 		.target_residency = 2,
12609cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12619cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12629cf93f05SArtem Bityutskiy 	{
12639cf93f05SArtem Bityutskiy 		.name = "C1E",
12649cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x01",
12659cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
12669cf93f05SArtem Bityutskiy 		.exit_latency = 15,
12679cf93f05SArtem Bityutskiy 		.target_residency = 25,
12689cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12699cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12709cf93f05SArtem Bityutskiy 	{
12719cf93f05SArtem Bityutskiy 		.name = "C6",
12729cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x20",
12739cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
12749cf93f05SArtem Bityutskiy 		.exit_latency = 130,
12759cf93f05SArtem Bityutskiy 		.target_residency = 500,
12769cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12779cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12789cf93f05SArtem Bityutskiy 	{
12799cf93f05SArtem Bityutskiy 		.enter = NULL }
12809cf93f05SArtem Bityutskiy };
12819cf93f05SArtem Bityutskiy 
12822f3d08f0SArjan van de Ven static struct cpuidle_state vmguest_cstates[] __initdata = {
12832f3d08f0SArjan van de Ven 	{
12842f3d08f0SArjan van de Ven 		.name = "C1",
12852f3d08f0SArjan van de Ven 		.desc = "HLT",
12862f3d08f0SArjan van de Ven 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
12872f3d08f0SArjan van de Ven 		.exit_latency = 5,
12882f3d08f0SArjan van de Ven 		.target_residency = 10,
12892f3d08f0SArjan van de Ven 		.enter = &intel_idle_hlt, },
12902f3d08f0SArjan van de Ven 	{
1291*0fac214bSArjan van de Ven 		.name = "C1L",
1292*0fac214bSArjan van de Ven 		.desc = "Long HLT",
1293*0fac214bSArjan van de Ven 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TLB_FLUSHED,
1294*0fac214bSArjan van de Ven 		.exit_latency = 5,
1295*0fac214bSArjan van de Ven 		.target_residency = 200,
1296*0fac214bSArjan van de Ven 		.enter = &intel_idle_hlt, },
1297*0fac214bSArjan van de Ven 	{
12982f3d08f0SArjan van de Ven 		.enter = NULL }
12992f3d08f0SArjan van de Ven };
13002f3d08f0SArjan van de Ven 
1301ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nehalem __initconst = {
1302b66b8b9aSAndi Kleen 	.state_table = nehalem_cstates,
1303b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
130432e95180SLen Brown 	.disable_promotion_to_c1e = true,
1305b66b8b9aSAndi Kleen };
1306b66b8b9aSAndi Kleen 
1307ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nhx __initconst = {
1308e6d4f08aSRafael J. Wysocki 	.state_table = nehalem_cstates,
1309e6d4f08aSRafael J. Wysocki 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
1310e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1311e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1312e6d4f08aSRafael J. Wysocki };
1313e6d4f08aSRafael J. Wysocki 
1314ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_atom __initconst = {
1315b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1316b66b8b9aSAndi Kleen };
1317b66b8b9aSAndi Kleen 
1318ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_tangier __initconst = {
13195e7ec268SAndy Shevchenko 	.state_table = tangier_cstates,
13205e7ec268SAndy Shevchenko };
13215e7ec268SAndy Shevchenko 
1322ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_lincroft __initconst = {
1323b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1324b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
1325b66b8b9aSAndi Kleen };
1326b66b8b9aSAndi Kleen 
1327ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snb __initconst = {
1328b66b8b9aSAndi Kleen 	.state_table = snb_cstates,
132932e95180SLen Brown 	.disable_promotion_to_c1e = true,
1330b66b8b9aSAndi Kleen };
1331b66b8b9aSAndi Kleen 
1332ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snx __initconst = {
1333e6d4f08aSRafael J. Wysocki 	.state_table = snb_cstates,
1334e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1335e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1336e6d4f08aSRafael J. Wysocki };
1337e6d4f08aSRafael J. Wysocki 
1338ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_byt __initconst = {
1339718987d6SLen Brown 	.state_table = byt_cstates,
1340718987d6SLen Brown 	.disable_promotion_to_c1e = true,
13418c058d53SLen Brown 	.byt_auto_demotion_disable_flag = true,
1342718987d6SLen Brown };
1343718987d6SLen Brown 
1344ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_cht __initconst = {
1345cab07a56SLen Brown 	.state_table = cht_cstates,
1346cab07a56SLen Brown 	.disable_promotion_to_c1e = true,
1347cab07a56SLen Brown 	.byt_auto_demotion_disable_flag = true,
1348cab07a56SLen Brown };
1349cab07a56SLen Brown 
1350ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivb __initconst = {
13516edab08cSLen Brown 	.state_table = ivb_cstates,
135232e95180SLen Brown 	.disable_promotion_to_c1e = true,
13536edab08cSLen Brown };
13546edab08cSLen Brown 
1355ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivt __initconst = {
13560138d8f0SLen Brown 	.state_table = ivt_cstates,
13570138d8f0SLen Brown 	.disable_promotion_to_c1e = true,
1358e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
13590138d8f0SLen Brown };
13600138d8f0SLen Brown 
1361ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsw __initconst = {
136285a4d2d4SLen Brown 	.state_table = hsw_cstates,
136332e95180SLen Brown 	.disable_promotion_to_c1e = true,
136485a4d2d4SLen Brown };
136585a4d2d4SLen Brown 
1366ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsx __initconst = {
1367e6d4f08aSRafael J. Wysocki 	.state_table = hsw_cstates,
1368e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1369e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1370e6d4f08aSRafael J. Wysocki };
1371e6d4f08aSRafael J. Wysocki 
1372ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdw __initconst = {
1373a138b568SLen Brown 	.state_table = bdw_cstates,
1374a138b568SLen Brown 	.disable_promotion_to_c1e = true,
1375a138b568SLen Brown };
1376a138b568SLen Brown 
1377ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdx __initconst = {
1378e6d4f08aSRafael J. Wysocki 	.state_table = bdw_cstates,
1379e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1380e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1381e6d4f08aSRafael J. Wysocki };
1382e6d4f08aSRafael J. Wysocki 
1383ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skl __initconst = {
1384493f133fSLen Brown 	.state_table = skl_cstates,
1385493f133fSLen Brown 	.disable_promotion_to_c1e = true,
1386493f133fSLen Brown };
1387493f133fSLen Brown 
1388ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skx __initconst = {
1389f9e71657SLen Brown 	.state_table = skx_cstates,
1390f9e71657SLen Brown 	.disable_promotion_to_c1e = true,
1391e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1392f9e71657SLen Brown };
1393493f133fSLen Brown 
1394a472ad2bSChen Yu static const struct idle_cpu idle_cpu_icx __initconst = {
1395a472ad2bSChen Yu 	.state_table = icx_cstates,
1396a472ad2bSChen Yu 	.disable_promotion_to_c1e = true,
1397a472ad2bSChen Yu 	.use_acpi = true,
1398a472ad2bSChen Yu };
1399a472ad2bSChen Yu 
1400d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl __initconst = {
1401d1cf8bbfSZhang Rui 	.state_table = adl_cstates,
1402d1cf8bbfSZhang Rui };
1403d1cf8bbfSZhang Rui 
1404d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl_l __initconst = {
1405d1cf8bbfSZhang Rui 	.state_table = adl_l_cstates,
1406d1cf8bbfSZhang Rui };
1407d1cf8bbfSZhang Rui 
140865c0c236SZhang Rui static const struct idle_cpu idle_cpu_adl_n __initconst = {
140965c0c236SZhang Rui 	.state_table = adl_n_cstates,
141065c0c236SZhang Rui };
141165c0c236SZhang Rui 
14129edf3c0fSArtem Bityutskiy static const struct idle_cpu idle_cpu_spr __initconst = {
14139edf3c0fSArtem Bityutskiy 	.state_table = spr_cstates,
14149edf3c0fSArtem Bityutskiy 	.disable_promotion_to_c1e = true,
14159edf3c0fSArtem Bityutskiy 	.use_acpi = true,
14169edf3c0fSArtem Bityutskiy };
14179edf3c0fSArtem Bityutskiy 
1418ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_avn __initconst = {
1419fab04b22SLen Brown 	.state_table = avn_cstates,
1420fab04b22SLen Brown 	.disable_promotion_to_c1e = true,
1421e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1422fab04b22SLen Brown };
1423fab04b22SLen Brown 
1424ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_knl __initconst = {
1425281baf7aSDasaratharaman Chandramouli 	.state_table = knl_cstates,
1426e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1427281baf7aSDasaratharaman Chandramouli };
1428281baf7aSDasaratharaman Chandramouli 
1429ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bxt __initconst = {
14305dcef694SLen Brown 	.state_table = bxt_cstates,
14315dcef694SLen Brown 	.disable_promotion_to_c1e = true,
14325dcef694SLen Brown };
14335dcef694SLen Brown 
1434ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_dnv __initconst = {
14350080d65bSJacob Pan 	.state_table = dnv_cstates,
14360080d65bSJacob Pan 	.disable_promotion_to_c1e = true,
1437e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
14380080d65bSJacob Pan };
14390080d65bSJacob Pan 
14409cf93f05SArtem Bityutskiy static const struct idle_cpu idle_cpu_snr __initconst = {
14419cf93f05SArtem Bityutskiy 	.state_table = snr_cstates,
14429cf93f05SArtem Bityutskiy 	.disable_promotion_to_c1e = true,
14439cf93f05SArtem Bityutskiy 	.use_acpi = true,
14449cf93f05SArtem Bityutskiy };
14459cf93f05SArtem Bityutskiy 
1446d5cdc3c4SMathias Krause static const struct x86_cpu_id intel_idle_ids[] __initconst = {
14474a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP,		&idle_cpu_nhx),
14484a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM,		&idle_cpu_nehalem),
14494a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G,		&idle_cpu_nehalem),
14504a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE,		&idle_cpu_nehalem),
14514a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP,		&idle_cpu_nhx),
14524a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX,		&idle_cpu_nhx),
14534a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL,	&idle_cpu_atom),
14544a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL_MID,	&idle_cpu_lincroft),
14554a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX,		&idle_cpu_nhx),
14564a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE,		&idle_cpu_snb),
14574a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X,	&idle_cpu_snx),
14584a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL,	&idle_cpu_atom),
14594a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,	&idle_cpu_byt),
14604a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID,	&idle_cpu_tangier),
14614a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,	&idle_cpu_cht),
14624a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE,		&idle_cpu_ivb),
14634a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X,		&idle_cpu_ivt),
14644a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL,		&idle_cpu_hsw),
14654a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X,		&idle_cpu_hsx),
14664a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L,		&idle_cpu_hsw),
14674a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G,		&idle_cpu_hsw),
14684a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D,	&idle_cpu_avn),
14694a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL,		&idle_cpu_bdw),
14704a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G,		&idle_cpu_bdw),
14714a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X,		&idle_cpu_bdx),
14724a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D,		&idle_cpu_bdx),
14734a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L,		&idle_cpu_skl),
14744a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE,		&idle_cpu_skl),
14754a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L,		&idle_cpu_skl),
14764a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE,		&idle_cpu_skl),
14774a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,		&idle_cpu_skx),
1478a472ad2bSChen Yu 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,		&idle_cpu_icx),
147922141d5fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,		&idle_cpu_icx),
1480d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,		&idle_cpu_adl),
1481d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,		&idle_cpu_adl_l),
148265c0c236SZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N,		&idle_cpu_adl_n),
14839edf3c0fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,	&idle_cpu_spr),
148474528edfSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X,	&idle_cpu_spr),
14854a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,	&idle_cpu_knl),
14864a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,	&idle_cpu_knl),
14874a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	&idle_cpu_bxt),
14884a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,	&idle_cpu_bxt),
14894a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D,	&idle_cpu_dnv),
14909cf93f05SArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,	&idle_cpu_snr),
1491b66b8b9aSAndi Kleen 	{}
1492b66b8b9aSAndi Kleen };
1493b66b8b9aSAndi Kleen 
149418734958SRafael J. Wysocki static const struct x86_cpu_id intel_mwait_ids[] __initconst = {
14954a9f45a0SThomas Gleixner 	X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL),
149618734958SRafael J. Wysocki 	{}
149718734958SRafael J. Wysocki };
149818734958SRafael J. Wysocki 
1499095928aeSRafael J. Wysocki static bool __init intel_idle_max_cstate_reached(int cstate)
150018734958SRafael J. Wysocki {
150118734958SRafael J. Wysocki 	if (cstate + 1 > max_cstate) {
150218734958SRafael J. Wysocki 		pr_info("max_cstate %d reached\n", max_cstate);
150318734958SRafael J. Wysocki 		return true;
150418734958SRafael J. Wysocki 	}
150518734958SRafael J. Wysocki 	return false;
150618734958SRafael J. Wysocki }
150718734958SRafael J. Wysocki 
15084d916140SPeter Zijlstra static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
15094d916140SPeter Zijlstra {
15104d916140SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
15114d916140SPeter Zijlstra 
15124d916140SPeter Zijlstra 	if (boot_cpu_has(X86_FEATURE_ARAT))
15134d916140SPeter Zijlstra 		return false;
15144d916140SPeter Zijlstra 
15154d916140SPeter Zijlstra 	/*
15164d916140SPeter Zijlstra 	 * Switch over to one-shot tick broadcast if the target C-state
15174d916140SPeter Zijlstra 	 * is deeper than C1.
15184d916140SPeter Zijlstra 	 */
15194d916140SPeter Zijlstra 	return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
15204d916140SPeter Zijlstra }
15214d916140SPeter Zijlstra 
152218734958SRafael J. Wysocki #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
152318734958SRafael J. Wysocki #include <acpi/processor.h>
152418734958SRafael J. Wysocki 
15254ec32d9eSRafael J. Wysocki static bool no_acpi __read_mostly;
15264ec32d9eSRafael J. Wysocki module_param(no_acpi, bool, 0444);
15274ec32d9eSRafael J. Wysocki MODULE_PARM_DESC(no_acpi, "Do not use ACPI _CST for building the idle states list");
15284ec32d9eSRafael J. Wysocki 
15293a5be9b8SRafael J. Wysocki static bool force_use_acpi __read_mostly; /* No effect if no_acpi is set. */
15303a5be9b8SRafael J. Wysocki module_param_named(use_acpi, force_use_acpi, bool, 0444);
15313a5be9b8SRafael J. Wysocki MODULE_PARM_DESC(use_acpi, "Use ACPI _CST for building the idle states list");
15323a5be9b8SRafael J. Wysocki 
1533095928aeSRafael J. Wysocki static struct acpi_processor_power acpi_state_table __initdata;
153418734958SRafael J. Wysocki 
153518734958SRafael J. Wysocki /**
153618734958SRafael J. Wysocki  * intel_idle_cst_usable - Check if the _CST information can be used.
153718734958SRafael J. Wysocki  *
153818734958SRafael J. Wysocki  * Check if all of the C-states listed by _CST in the max_cstate range are
153918734958SRafael J. Wysocki  * ACPI_CSTATE_FFH, which means that they should be entered via MWAIT.
154018734958SRafael J. Wysocki  */
1541095928aeSRafael J. Wysocki static bool __init intel_idle_cst_usable(void)
154218734958SRafael J. Wysocki {
154318734958SRafael J. Wysocki 	int cstate, limit;
154418734958SRafael J. Wysocki 
154518734958SRafael J. Wysocki 	limit = min_t(int, min_t(int, CPUIDLE_STATE_MAX, max_cstate + 1),
154618734958SRafael J. Wysocki 		      acpi_state_table.count);
154718734958SRafael J. Wysocki 
154818734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
154918734958SRafael J. Wysocki 		struct acpi_processor_cx *cx = &acpi_state_table.states[cstate];
155018734958SRafael J. Wysocki 
155118734958SRafael J. Wysocki 		if (cx->entry_method != ACPI_CSTATE_FFH)
155218734958SRafael J. Wysocki 			return false;
155318734958SRafael J. Wysocki 	}
155418734958SRafael J. Wysocki 
155518734958SRafael J. Wysocki 	return true;
155618734958SRafael J. Wysocki }
155718734958SRafael J. Wysocki 
1558095928aeSRafael J. Wysocki static bool __init intel_idle_acpi_cst_extract(void)
155918734958SRafael J. Wysocki {
156018734958SRafael J. Wysocki 	unsigned int cpu;
156118734958SRafael J. Wysocki 
15624ec32d9eSRafael J. Wysocki 	if (no_acpi) {
15634ec32d9eSRafael J. Wysocki 		pr_debug("Not allowed to use ACPI _CST\n");
15644ec32d9eSRafael J. Wysocki 		return false;
15654ec32d9eSRafael J. Wysocki 	}
15664ec32d9eSRafael J. Wysocki 
156718734958SRafael J. Wysocki 	for_each_possible_cpu(cpu) {
156818734958SRafael J. Wysocki 		struct acpi_processor *pr = per_cpu(processors, cpu);
156918734958SRafael J. Wysocki 
157018734958SRafael J. Wysocki 		if (!pr)
157118734958SRafael J. Wysocki 			continue;
157218734958SRafael J. Wysocki 
157318734958SRafael J. Wysocki 		if (acpi_processor_evaluate_cst(pr->handle, cpu, &acpi_state_table))
157418734958SRafael J. Wysocki 			continue;
157518734958SRafael J. Wysocki 
157618734958SRafael J. Wysocki 		acpi_state_table.count++;
157718734958SRafael J. Wysocki 
157818734958SRafael J. Wysocki 		if (!intel_idle_cst_usable())
157918734958SRafael J. Wysocki 			continue;
158018734958SRafael J. Wysocki 
158175af76d0SMel Gorman 		if (!acpi_processor_claim_cst_control())
158275af76d0SMel Gorman 			break;
158318734958SRafael J. Wysocki 
158418734958SRafael J. Wysocki 		return true;
158518734958SRafael J. Wysocki 	}
158618734958SRafael J. Wysocki 
158775af76d0SMel Gorman 	acpi_state_table.count = 0;
158818734958SRafael J. Wysocki 	pr_debug("ACPI _CST not found or not usable\n");
158918734958SRafael J. Wysocki 	return false;
159018734958SRafael J. Wysocki }
159118734958SRafael J. Wysocki 
1592095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
159318734958SRafael J. Wysocki {
159418734958SRafael J. Wysocki 	int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
159518734958SRafael J. Wysocki 
159618734958SRafael J. Wysocki 	/*
159718734958SRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
159818734958SRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
159918734958SRafael J. Wysocki 	 */
160018734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
160118734958SRafael J. Wysocki 		struct acpi_processor_cx *cx;
160218734958SRafael J. Wysocki 		struct cpuidle_state *state;
160318734958SRafael J. Wysocki 
16044e0ba557SChen Yu 		if (intel_idle_max_cstate_reached(cstate - 1))
160518734958SRafael J. Wysocki 			break;
160618734958SRafael J. Wysocki 
160718734958SRafael J. Wysocki 		cx = &acpi_state_table.states[cstate];
160818734958SRafael J. Wysocki 
160918734958SRafael J. Wysocki 		state = &drv->states[drv->state_count++];
161018734958SRafael J. Wysocki 
161118734958SRafael J. Wysocki 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate);
16120dbc0f49SWolfram Sang 		strscpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
161318734958SRafael J. Wysocki 		state->exit_latency = cx->latency;
161418734958SRafael J. Wysocki 		/*
161518734958SRafael J. Wysocki 		 * For C1-type C-states use the same number for both the exit
161618734958SRafael J. Wysocki 		 * latency and target residency, because that is the case for
161718734958SRafael J. Wysocki 		 * C1 in the majority of the static C-states tables above.
161818734958SRafael J. Wysocki 		 * For the other types of C-states, however, set the target
161918734958SRafael J. Wysocki 		 * residency to 3 times the exit latency which should lead to
162018734958SRafael J. Wysocki 		 * a reasonable balance between energy-efficiency and
162118734958SRafael J. Wysocki 		 * performance in the majority of interesting cases.
162218734958SRafael J. Wysocki 		 */
162318734958SRafael J. Wysocki 		state->target_residency = cx->latency;
162418734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C1)
162518734958SRafael J. Wysocki 			state->target_residency *= 3;
162618734958SRafael J. Wysocki 
162718734958SRafael J. Wysocki 		state->flags = MWAIT2flg(cx->address);
162818734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C2)
162918734958SRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
163018734958SRafael J. Wysocki 
16314dcb78eeSRafael J. Wysocki 		if (disabled_states_mask & BIT(cstate))
16324dcb78eeSRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_OFF;
16334dcb78eeSRafael J. Wysocki 
16346e1d2bc6SPeter Zijlstra 		if (intel_idle_state_needs_timer_stop(state))
16356e1d2bc6SPeter Zijlstra 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
16366e1d2bc6SPeter Zijlstra 
163718734958SRafael J. Wysocki 		state->enter = intel_idle;
163818734958SRafael J. Wysocki 		state->enter_s2idle = intel_idle_s2idle;
163918734958SRafael J. Wysocki 	}
164018734958SRafael J. Wysocki }
1641bff8e60aSRafael J. Wysocki 
1642095928aeSRafael J. Wysocki static bool __init intel_idle_off_by_default(u32 mwait_hint)
1643bff8e60aSRafael J. Wysocki {
1644bff8e60aSRafael J. Wysocki 	int cstate, limit;
1645bff8e60aSRafael J. Wysocki 
1646bff8e60aSRafael J. Wysocki 	/*
1647bff8e60aSRafael J. Wysocki 	 * If there are no _CST C-states, do not disable any C-states by
1648bff8e60aSRafael J. Wysocki 	 * default.
1649bff8e60aSRafael J. Wysocki 	 */
1650bff8e60aSRafael J. Wysocki 	if (!acpi_state_table.count)
1651bff8e60aSRafael J. Wysocki 		return false;
1652bff8e60aSRafael J. Wysocki 
1653bff8e60aSRafael J. Wysocki 	limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
1654bff8e60aSRafael J. Wysocki 	/*
1655bff8e60aSRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
1656bff8e60aSRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
1657bff8e60aSRafael J. Wysocki 	 */
1658bff8e60aSRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
1659bff8e60aSRafael J. Wysocki 		if (acpi_state_table.states[cstate].address == mwait_hint)
1660bff8e60aSRafael J. Wysocki 			return false;
1661bff8e60aSRafael J. Wysocki 	}
1662bff8e60aSRafael J. Wysocki 	return true;
1663bff8e60aSRafael J. Wysocki }
166418734958SRafael J. Wysocki #else /* !CONFIG_ACPI_PROCESSOR_CSTATE */
16653a5be9b8SRafael J. Wysocki #define force_use_acpi	(false)
16663a5be9b8SRafael J. Wysocki 
166718734958SRafael J. Wysocki static inline bool intel_idle_acpi_cst_extract(void) { return false; }
166818734958SRafael J. Wysocki static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
1669bff8e60aSRafael J. Wysocki static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
167018734958SRafael J. Wysocki #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */
167118734958SRafael J. Wysocki 
16726eacb15fSRafael J. Wysocki /**
16736eacb15fSRafael J. Wysocki  * ivt_idle_state_table_update - Tune the idle states table for Ivy Town.
16740138d8f0SLen Brown  *
16756eacb15fSRafael J. Wysocki  * Tune IVT multi-socket targets.
16766eacb15fSRafael J. Wysocki  * Assumption: num_sockets == (max_package_num + 1).
16770138d8f0SLen Brown  */
1678095928aeSRafael J. Wysocki static void __init ivt_idle_state_table_update(void)
16790138d8f0SLen Brown {
16800138d8f0SLen Brown 	/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
16810138d8f0SLen Brown 	int cpu, package_num, num_sockets = 1;
16820138d8f0SLen Brown 
16830138d8f0SLen Brown 	for_each_online_cpu(cpu) {
16840138d8f0SLen Brown 		package_num = topology_physical_package_id(cpu);
16850138d8f0SLen Brown 		if (package_num + 1 > num_sockets) {
16860138d8f0SLen Brown 			num_sockets = package_num + 1;
16870138d8f0SLen Brown 
1688d27dca42SChristoph Jaeger 			if (num_sockets > 4) {
16890138d8f0SLen Brown 				cpuidle_state_table = ivt_cstates_8s;
16900138d8f0SLen Brown 				return;
16910138d8f0SLen Brown 			}
16920138d8f0SLen Brown 		}
1693d27dca42SChristoph Jaeger 	}
16940138d8f0SLen Brown 
16950138d8f0SLen Brown 	if (num_sockets > 2)
16960138d8f0SLen Brown 		cpuidle_state_table = ivt_cstates_4s;
1697d70e28f5SLen Brown 
16980138d8f0SLen Brown 	/* else, 1 and 2 socket systems use default ivt_cstates */
16990138d8f0SLen Brown }
17005dcef694SLen Brown 
170186e9466aSRafael J. Wysocki /**
170286e9466aSRafael J. Wysocki  * irtl_2_usec - IRTL to microseconds conversion.
170386e9466aSRafael J. Wysocki  * @irtl: IRTL MSR value.
170486e9466aSRafael J. Wysocki  *
170586e9466aSRafael J. Wysocki  * Translate the IRTL (Interrupt Response Time Limit) MSR value to microseconds.
17065dcef694SLen Brown  */
170786e9466aSRafael J. Wysocki static unsigned long long __init irtl_2_usec(unsigned long long irtl)
170886e9466aSRafael J. Wysocki {
1709095928aeSRafael J. Wysocki 	static const unsigned int irtl_ns_units[] __initconst = {
1710095928aeSRafael J. Wysocki 		1, 32, 1024, 32768, 1048576, 33554432, 0, 0
1711095928aeSRafael J. Wysocki 	};
17125dcef694SLen Brown 	unsigned long long ns;
17135dcef694SLen Brown 
17143451ab3eSJan Beulich 	if (!irtl)
17153451ab3eSJan Beulich 		return 0;
17163451ab3eSJan Beulich 
1717bef45096SJan Beulich 	ns = irtl_ns_units[(irtl >> 10) & 0x7];
17185dcef694SLen Brown 
171986e9466aSRafael J. Wysocki 	return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC);
17205dcef694SLen Brown }
172186e9466aSRafael J. Wysocki 
17226eacb15fSRafael J. Wysocki /**
17236eacb15fSRafael J. Wysocki  * bxt_idle_state_table_update - Fix up the Broxton idle states table.
17245dcef694SLen Brown  *
17256eacb15fSRafael J. Wysocki  * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the
17266eacb15fSRafael J. Wysocki  * definitive maximum latency and use the same value for target_residency.
17275dcef694SLen Brown  */
1728095928aeSRafael J. Wysocki static void __init bxt_idle_state_table_update(void)
17295dcef694SLen Brown {
17305dcef694SLen Brown 	unsigned long long msr;
17313451ab3eSJan Beulich 	unsigned int usec;
17325dcef694SLen Brown 
17335dcef694SLen Brown 	rdmsrl(MSR_PKGC6_IRTL, msr);
17343451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17353451ab3eSJan Beulich 	if (usec) {
17365dcef694SLen Brown 		bxt_cstates[2].exit_latency = usec;
17375dcef694SLen Brown 		bxt_cstates[2].target_residency = usec;
17385dcef694SLen Brown 	}
17395dcef694SLen Brown 
17405dcef694SLen Brown 	rdmsrl(MSR_PKGC7_IRTL, msr);
17413451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17423451ab3eSJan Beulich 	if (usec) {
17435dcef694SLen Brown 		bxt_cstates[3].exit_latency = usec;
17445dcef694SLen Brown 		bxt_cstates[3].target_residency = usec;
17455dcef694SLen Brown 	}
17465dcef694SLen Brown 
17475dcef694SLen Brown 	rdmsrl(MSR_PKGC8_IRTL, msr);
17483451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17493451ab3eSJan Beulich 	if (usec) {
17505dcef694SLen Brown 		bxt_cstates[4].exit_latency = usec;
17515dcef694SLen Brown 		bxt_cstates[4].target_residency = usec;
17525dcef694SLen Brown 	}
17535dcef694SLen Brown 
17545dcef694SLen Brown 	rdmsrl(MSR_PKGC9_IRTL, msr);
17553451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17563451ab3eSJan Beulich 	if (usec) {
17575dcef694SLen Brown 		bxt_cstates[5].exit_latency = usec;
17585dcef694SLen Brown 		bxt_cstates[5].target_residency = usec;
17595dcef694SLen Brown 	}
17605dcef694SLen Brown 
17615dcef694SLen Brown 	rdmsrl(MSR_PKGC10_IRTL, msr);
17623451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17633451ab3eSJan Beulich 	if (usec) {
17645dcef694SLen Brown 		bxt_cstates[6].exit_latency = usec;
17655dcef694SLen Brown 		bxt_cstates[6].target_residency = usec;
17665dcef694SLen Brown 	}
17675dcef694SLen Brown 
17685dcef694SLen Brown }
17696eacb15fSRafael J. Wysocki 
17706eacb15fSRafael J. Wysocki /**
17716eacb15fSRafael J. Wysocki  * sklh_idle_state_table_update - Fix up the Sky Lake idle states table.
1772d70e28f5SLen Brown  *
17736eacb15fSRafael J. Wysocki  * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled.
1774d70e28f5SLen Brown  */
1775095928aeSRafael J. Wysocki static void __init sklh_idle_state_table_update(void)
1776d70e28f5SLen Brown {
1777d70e28f5SLen Brown 	unsigned long long msr;
1778d70e28f5SLen Brown 	unsigned int eax, ebx, ecx, edx;
1779d70e28f5SLen Brown 
1780d70e28f5SLen Brown 
1781d70e28f5SLen Brown 	/* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
1782d70e28f5SLen Brown 	if (max_cstate <= 7)
17830138d8f0SLen Brown 		return;
1784d70e28f5SLen Brown 
1785d70e28f5SLen Brown 	/* if PC10 not present in CPUID.MWAIT.EDX */
1786d70e28f5SLen Brown 	if ((mwait_substates & (0xF << 28)) == 0)
1787d70e28f5SLen Brown 		return;
1788d70e28f5SLen Brown 
17896cfb2374SLen Brown 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
1790d70e28f5SLen Brown 
1791d70e28f5SLen Brown 	/* PC10 is not enabled in PKG C-state limit */
1792d70e28f5SLen Brown 	if ((msr & 0xF) != 8)
1793d70e28f5SLen Brown 		return;
1794d70e28f5SLen Brown 
1795d70e28f5SLen Brown 	ecx = 0;
1796d70e28f5SLen Brown 	cpuid(7, &eax, &ebx, &ecx, &edx);
1797d70e28f5SLen Brown 
1798d70e28f5SLen Brown 	/* if SGX is present */
1799d70e28f5SLen Brown 	if (ebx & (1 << 2)) {
1800d70e28f5SLen Brown 
180132ad73dbSSean Christopherson 		rdmsrl(MSR_IA32_FEAT_CTL, msr);
1802d70e28f5SLen Brown 
1803d70e28f5SLen Brown 		/* if SGX is enabled */
1804d70e28f5SLen Brown 		if (msr & (1 << 18))
1805d70e28f5SLen Brown 			return;
1806d70e28f5SLen Brown 	}
1807d70e28f5SLen Brown 
1808ba1e78a1SRafael J. Wysocki 	skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C8-SKL */
1809ba1e78a1SRafael J. Wysocki 	skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C9-SKL */
1810d70e28f5SLen Brown }
1811d70e28f5SLen Brown 
181264233338SChen Yu /**
181364233338SChen Yu  * skx_idle_state_table_update - Adjust the Sky Lake/Cascade Lake
181464233338SChen Yu  * idle states table.
181564233338SChen Yu  */
181664233338SChen Yu static void __init skx_idle_state_table_update(void)
181764233338SChen Yu {
181864233338SChen Yu 	unsigned long long msr;
181964233338SChen Yu 
182064233338SChen Yu 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
182164233338SChen Yu 
182264233338SChen Yu 	/*
182364233338SChen Yu 	 * 000b: C0/C1 (no package C-state support)
182464233338SChen Yu 	 * 001b: C2
182564233338SChen Yu 	 * 010b: C6 (non-retention)
182664233338SChen Yu 	 * 011b: C6 (retention)
182764233338SChen Yu 	 * 111b: No Package C state limits.
182864233338SChen Yu 	 */
182964233338SChen Yu 	if ((msr & 0x7) < 2) {
183064233338SChen Yu 		/*
183164233338SChen Yu 		 * Uses the CC6 + PC0 latency and 3 times of
183264233338SChen Yu 		 * latency for target_residency if the PC6
183364233338SChen Yu 		 * is disabled in BIOS. This is consistent
183464233338SChen Yu 		 * with how intel_idle driver uses _CST
183564233338SChen Yu 		 * to set the target_residency.
183664233338SChen Yu 		 */
183764233338SChen Yu 		skx_cstates[2].exit_latency = 92;
183864233338SChen Yu 		skx_cstates[2].target_residency = 276;
183964233338SChen Yu 	}
184064233338SChen Yu }
184164233338SChen Yu 
1842da0e58c0SArtem Bityutskiy /**
1843d1cf8bbfSZhang Rui  * adl_idle_state_table_update - Adjust AlderLake idle states table.
1844d1cf8bbfSZhang Rui  */
1845d1cf8bbfSZhang Rui static void __init adl_idle_state_table_update(void)
1846d1cf8bbfSZhang Rui {
1847d1cf8bbfSZhang Rui 	/* Check if user prefers C1 over C1E. */
1848d1cf8bbfSZhang Rui 	if (preferred_states_mask & BIT(1) && !(preferred_states_mask & BIT(2))) {
1849d1cf8bbfSZhang Rui 		cpuidle_state_table[0].flags &= ~CPUIDLE_FLAG_UNUSABLE;
1850d1cf8bbfSZhang Rui 		cpuidle_state_table[1].flags |= CPUIDLE_FLAG_UNUSABLE;
1851d1cf8bbfSZhang Rui 
1852d1cf8bbfSZhang Rui 		/* Disable C1E by clearing the "C1E promotion" bit. */
1853d1cf8bbfSZhang Rui 		c1e_promotion = C1E_PROMOTION_DISABLE;
1854d1cf8bbfSZhang Rui 		return;
1855d1cf8bbfSZhang Rui 	}
1856d1cf8bbfSZhang Rui 
1857d1cf8bbfSZhang Rui 	/* Make sure C1E is enabled by default */
1858d1cf8bbfSZhang Rui 	c1e_promotion = C1E_PROMOTION_ENABLE;
1859d1cf8bbfSZhang Rui }
1860d1cf8bbfSZhang Rui 
1861d1cf8bbfSZhang Rui /**
1862da0e58c0SArtem Bityutskiy  * spr_idle_state_table_update - Adjust Sapphire Rapids idle states table.
1863da0e58c0SArtem Bityutskiy  */
1864da0e58c0SArtem Bityutskiy static void __init spr_idle_state_table_update(void)
1865da0e58c0SArtem Bityutskiy {
18663a9cf77bSArtem Bityutskiy 	unsigned long long msr;
18673a9cf77bSArtem Bityutskiy 
18683a9cf77bSArtem Bityutskiy 	/*
18693a9cf77bSArtem Bityutskiy 	 * By default, the C6 state assumes the worst-case scenario of package
18703a9cf77bSArtem Bityutskiy 	 * C6. However, if PC6 is disabled, we update the numbers to match
18713a9cf77bSArtem Bityutskiy 	 * core C6.
18723a9cf77bSArtem Bityutskiy 	 */
18733a9cf77bSArtem Bityutskiy 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
18743a9cf77bSArtem Bityutskiy 
18753a9cf77bSArtem Bityutskiy 	/* Limit value 2 and above allow for PC6. */
18763a9cf77bSArtem Bityutskiy 	if ((msr & 0x7) < 2) {
18773a9cf77bSArtem Bityutskiy 		spr_cstates[2].exit_latency = 190;
18783a9cf77bSArtem Bityutskiy 		spr_cstates[2].target_residency = 600;
18793a9cf77bSArtem Bityutskiy 	}
1880da0e58c0SArtem Bityutskiy }
1881da0e58c0SArtem Bityutskiy 
18821aefbd7aSRafael J. Wysocki static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
18831aefbd7aSRafael J. Wysocki {
18841aefbd7aSRafael J. Wysocki 	unsigned int mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint) + 1;
18851aefbd7aSRafael J. Wysocki 	unsigned int num_substates = (mwait_substates >> mwait_cstate * 4) &
18861aefbd7aSRafael J. Wysocki 					MWAIT_SUBSTATE_MASK;
18871aefbd7aSRafael J. Wysocki 
18881aefbd7aSRafael J. Wysocki 	/* Ignore the C-state if there are NO sub-states in CPUID for it. */
18891aefbd7aSRafael J. Wysocki 	if (num_substates == 0)
18901aefbd7aSRafael J. Wysocki 		return false;
18911aefbd7aSRafael J. Wysocki 
18921aefbd7aSRafael J. Wysocki 	if (mwait_cstate > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
18931aefbd7aSRafael J. Wysocki 		mark_tsc_unstable("TSC halts in idle states deeper than C2");
18941aefbd7aSRafael J. Wysocki 
18951aefbd7aSRafael J. Wysocki 	return true;
18961aefbd7aSRafael J. Wysocki }
18971aefbd7aSRafael J. Wysocki 
18984622ba92SArjan van de Ven static void state_update_enter_method(struct cpuidle_state *state, int cstate)
18994622ba92SArjan van de Ven {
19002f3d08f0SArjan van de Ven 	if (state->enter == intel_idle_hlt) {
19012f3d08f0SArjan van de Ven 		if (force_irq_on) {
19022f3d08f0SArjan van de Ven 			pr_info("forced intel_idle_irq for state %d\n", cstate);
19032f3d08f0SArjan van de Ven 			state->enter = intel_idle_hlt_irq_on;
19042f3d08f0SArjan van de Ven 		}
19052f3d08f0SArjan van de Ven 		return;
19062f3d08f0SArjan van de Ven 	}
19072f3d08f0SArjan van de Ven 	if (state->enter == intel_idle_hlt_irq_on)
19082f3d08f0SArjan van de Ven 		return; /* no update scenarios */
19092f3d08f0SArjan van de Ven 
19104622ba92SArjan van de Ven 	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
19114622ba92SArjan van de Ven 		/*
19124622ba92SArjan van de Ven 		 * Combining with XSTATE with IBRS or IRQ_ENABLE flags
19134622ba92SArjan van de Ven 		 * is not currently supported but this driver.
19144622ba92SArjan van de Ven 		 */
19154622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS);
19164622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
19174622ba92SArjan van de Ven 		state->enter = intel_idle_xstate;
19187826c069SArjan van de Ven 		return;
19197826c069SArjan van de Ven 	}
19207826c069SArjan van de Ven 
19217826c069SArjan van de Ven 	if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
19224622ba92SArjan van de Ven 			   state->flags & CPUIDLE_FLAG_IBRS) {
19234622ba92SArjan van de Ven 		/*
19244622ba92SArjan van de Ven 		 * IBRS mitigation requires that C-states are entered
19254622ba92SArjan van de Ven 		 * with interrupts disabled.
19264622ba92SArjan van de Ven 		 */
19274622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
19284622ba92SArjan van de Ven 		state->enter = intel_idle_ibrs;
19297826c069SArjan van de Ven 		return;
19307826c069SArjan van de Ven 	}
19317826c069SArjan van de Ven 
19327826c069SArjan van de Ven 	if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) {
19334622ba92SArjan van de Ven 		state->enter = intel_idle_irq;
19347826c069SArjan van de Ven 		return;
19357826c069SArjan van de Ven 	}
19367826c069SArjan van de Ven 
19377826c069SArjan van de Ven 	if (force_irq_on) {
19384622ba92SArjan van de Ven 		pr_info("forced intel_idle_irq for state %d\n", cstate);
19394622ba92SArjan van de Ven 		state->enter = intel_idle_irq;
19404622ba92SArjan van de Ven 	}
19414622ba92SArjan van de Ven }
19424622ba92SArjan van de Ven 
19432f3d08f0SArjan van de Ven /*
19442f3d08f0SArjan van de Ven  * For mwait based states, we want to verify the cpuid data to see if the state
19452f3d08f0SArjan van de Ven  * is actually supported by this specific CPU.
19462f3d08f0SArjan van de Ven  * For non-mwait based states, this check should be skipped.
19472f3d08f0SArjan van de Ven  */
19482f3d08f0SArjan van de Ven static bool should_verify_mwait(struct cpuidle_state *state)
19492f3d08f0SArjan van de Ven {
19502f3d08f0SArjan van de Ven 	if (state->enter == intel_idle_hlt)
19512f3d08f0SArjan van de Ven 		return false;
19522f3d08f0SArjan van de Ven 	if (state->enter == intel_idle_hlt_irq_on)
19532f3d08f0SArjan van de Ven 		return false;
19542f3d08f0SArjan van de Ven 
19552f3d08f0SArjan van de Ven 	return true;
19562f3d08f0SArjan van de Ven }
19572f3d08f0SArjan van de Ven 
1958095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
1959d70e28f5SLen Brown {
19603d3a1ae9SRafael J. Wysocki 	int cstate;
1961d70e28f5SLen Brown 
19623d3a1ae9SRafael J. Wysocki 	switch (boot_cpu_data.x86_model) {
1963db73c5a8SDave Hansen 	case INTEL_FAM6_IVYBRIDGE_X:
1964d70e28f5SLen Brown 		ivt_idle_state_table_update();
1965d70e28f5SLen Brown 		break;
1966db73c5a8SDave Hansen 	case INTEL_FAM6_ATOM_GOLDMONT:
1967f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
19685dcef694SLen Brown 		bxt_idle_state_table_update();
19695dcef694SLen Brown 		break;
1970c66f78a6SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE:
1971d70e28f5SLen Brown 		sklh_idle_state_table_update();
1972d70e28f5SLen Brown 		break;
197364233338SChen Yu 	case INTEL_FAM6_SKYLAKE_X:
197464233338SChen Yu 		skx_idle_state_table_update();
197564233338SChen Yu 		break;
1976da0e58c0SArtem Bityutskiy 	case INTEL_FAM6_SAPPHIRERAPIDS_X:
197774528edfSArtem Bityutskiy 	case INTEL_FAM6_EMERALDRAPIDS_X:
1978da0e58c0SArtem Bityutskiy 		spr_idle_state_table_update();
1979da0e58c0SArtem Bityutskiy 		break;
1980d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE:
1981d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE_L:
198265c0c236SZhang Rui 	case INTEL_FAM6_ALDERLAKE_N:
1983d1cf8bbfSZhang Rui 		adl_idle_state_table_update();
1984d1cf8bbfSZhang Rui 		break;
1985d70e28f5SLen Brown 	}
198646bcfad7SDeepthi Dharwar 
1987e022e7ebSLen Brown 	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
19881abffbd8SArtem Bityutskiy 		struct cpuidle_state *state;
19899f3d6dafSRafael J. Wysocki 		unsigned int mwait_hint;
199046bcfad7SDeepthi Dharwar 
199118734958SRafael J. Wysocki 		if (intel_idle_max_cstate_reached(cstate))
199218734958SRafael J. Wysocki 			break;
199318734958SRafael J. Wysocki 
19949f3d6dafSRafael J. Wysocki 		if (!cpuidle_state_table[cstate].enter &&
19959f3d6dafSRafael J. Wysocki 		    !cpuidle_state_table[cstate].enter_s2idle)
1996e022e7ebSLen Brown 			break;
1997e022e7ebSLen Brown 
19989f3d6dafSRafael J. Wysocki 		/* If marked as unusable, skip this state. */
1999ba1e78a1SRafael J. Wysocki 		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) {
2000654d08a4SJoe Perches 			pr_debug("state %s is disabled\n",
2001d70e28f5SLen Brown 				 cpuidle_state_table[cstate].name);
2002d70e28f5SLen Brown 			continue;
2003d70e28f5SLen Brown 		}
2004d70e28f5SLen Brown 
20059f3d6dafSRafael J. Wysocki 		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
20062f3d08f0SArjan van de Ven 		if (should_verify_mwait(&cpuidle_state_table[cstate]) && !intel_idle_verify_cstate(mwait_hint))
20079f3d6dafSRafael J. Wysocki 			continue;
2008d70e28f5SLen Brown 
20099f3d6dafSRafael J. Wysocki 		/* Structure copy. */
2010bff8e60aSRafael J. Wysocki 		drv->states[drv->state_count] = cpuidle_state_table[cstate];
20111abffbd8SArtem Bityutskiy 		state = &drv->states[drv->state_count];
2012bff8e60aSRafael J. Wysocki 
20134622ba92SArjan van de Ven 		state_update_enter_method(state, cstate);
20144622ba92SArjan van de Ven 
201532d4fd57SPeter Zijlstra 
20164dcb78eeSRafael J. Wysocki 		if ((disabled_states_mask & BIT(drv->state_count)) ||
20174dcb78eeSRafael J. Wysocki 		    ((icpu->use_acpi || force_use_acpi) &&
20183a5be9b8SRafael J. Wysocki 		     intel_idle_off_by_default(mwait_hint) &&
20191abffbd8SArtem Bityutskiy 		     !(state->flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
20201abffbd8SArtem Bityutskiy 			state->flags |= CPUIDLE_FLAG_OFF;
2021bff8e60aSRafael J. Wysocki 
20221abffbd8SArtem Bityutskiy 		if (intel_idle_state_needs_timer_stop(state))
20231abffbd8SArtem Bityutskiy 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
20246e1d2bc6SPeter Zijlstra 
2025bff8e60aSRafael J. Wysocki 		drv->state_count++;
202646bcfad7SDeepthi Dharwar 	}
202746bcfad7SDeepthi Dharwar 
20288c058d53SLen Brown 	if (icpu->byt_auto_demotion_disable_flag) {
20298c058d53SLen Brown 		wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
20308c058d53SLen Brown 		wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
20318c058d53SLen Brown 	}
203246bcfad7SDeepthi Dharwar }
203346bcfad7SDeepthi Dharwar 
20346eacb15fSRafael J. Wysocki /**
20356eacb15fSRafael J. Wysocki  * intel_idle_cpuidle_driver_init - Create the list of available idle states.
20366eacb15fSRafael J. Wysocki  * @drv: cpuidle driver structure to initialize.
203718734958SRafael J. Wysocki  */
20383d3a1ae9SRafael J. Wysocki static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
203918734958SRafael J. Wysocki {
204018734958SRafael J. Wysocki 	cpuidle_poll_state_init(drv);
20414dcb78eeSRafael J. Wysocki 
20424dcb78eeSRafael J. Wysocki 	if (disabled_states_mask & BIT(0))
20434dcb78eeSRafael J. Wysocki 		drv->states[0].flags |= CPUIDLE_FLAG_OFF;
20444dcb78eeSRafael J. Wysocki 
204518734958SRafael J. Wysocki 	drv->state_count = 1;
204618734958SRafael J. Wysocki 
204718734958SRafael J. Wysocki 	if (icpu)
204818734958SRafael J. Wysocki 		intel_idle_init_cstates_icpu(drv);
204918734958SRafael J. Wysocki 	else
205018734958SRafael J. Wysocki 		intel_idle_init_cstates_acpi(drv);
205118734958SRafael J. Wysocki }
205246bcfad7SDeepthi Dharwar 
20531aefbd7aSRafael J. Wysocki static void auto_demotion_disable(void)
20541aefbd7aSRafael J. Wysocki {
20551aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
20561aefbd7aSRafael J. Wysocki 
20571aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
20587f843dd7SRafael J. Wysocki 	msr_bits &= ~auto_demotion_disable_flags;
20591aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
20601aefbd7aSRafael J. Wysocki }
20611aefbd7aSRafael J. Wysocki 
2062da0e58c0SArtem Bityutskiy static void c1e_promotion_enable(void)
2063da0e58c0SArtem Bityutskiy {
2064da0e58c0SArtem Bityutskiy 	unsigned long long msr_bits;
2065da0e58c0SArtem Bityutskiy 
2066da0e58c0SArtem Bityutskiy 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
2067da0e58c0SArtem Bityutskiy 	msr_bits |= 0x2;
2068da0e58c0SArtem Bityutskiy 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
2069da0e58c0SArtem Bityutskiy }
2070da0e58c0SArtem Bityutskiy 
20711aefbd7aSRafael J. Wysocki static void c1e_promotion_disable(void)
20721aefbd7aSRafael J. Wysocki {
20731aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
20741aefbd7aSRafael J. Wysocki 
20751aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
20761aefbd7aSRafael J. Wysocki 	msr_bits &= ~0x2;
20771aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
20781aefbd7aSRafael J. Wysocki }
20791aefbd7aSRafael J. Wysocki 
20806eacb15fSRafael J. Wysocki /**
20816eacb15fSRafael J. Wysocki  * intel_idle_cpu_init - Register the target CPU with the cpuidle core.
20826eacb15fSRafael J. Wysocki  * @cpu: CPU to initialize.
20836eacb15fSRafael J. Wysocki  *
20846eacb15fSRafael J. Wysocki  * Register a cpuidle device object for @cpu and update its MSRs in accordance
20856eacb15fSRafael J. Wysocki  * with the processor model flags.
208626717172SLen Brown  */
2087fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_init(unsigned int cpu)
208826717172SLen Brown {
208926717172SLen Brown 	struct cpuidle_device *dev;
209026717172SLen Brown 
209165b7f839SThomas Renninger 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
209265b7f839SThomas Renninger 	dev->cpu = cpu;
209326717172SLen Brown 
209426717172SLen Brown 	if (cpuidle_register_device(dev)) {
2095654d08a4SJoe Perches 		pr_debug("cpuidle_register_device %d failed!\n", cpu);
209626717172SLen Brown 		return -EIO;
209726717172SLen Brown 	}
209865b7f839SThomas Renninger 
20997f843dd7SRafael J. Wysocki 	if (auto_demotion_disable_flags)
2100fb1013a0SSebastian Andrzej Siewior 		auto_demotion_disable();
210126717172SLen Brown 
210239c184a6SArtem Bityutskiy 	if (c1e_promotion == C1E_PROMOTION_ENABLE)
210339c184a6SArtem Bityutskiy 		c1e_promotion_enable();
210439c184a6SArtem Bityutskiy 	else if (c1e_promotion == C1E_PROMOTION_DISABLE)
2105fb1013a0SSebastian Andrzej Siewior 		c1e_promotion_disable();
2106fb1013a0SSebastian Andrzej Siewior 
2107fb1013a0SSebastian Andrzej Siewior 	return 0;
2108fb1013a0SSebastian Andrzej Siewior }
2109fb1013a0SSebastian Andrzej Siewior 
2110fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_online(unsigned int cpu)
2111fb1013a0SSebastian Andrzej Siewior {
2112fb1013a0SSebastian Andrzej Siewior 	struct cpuidle_device *dev;
2113fb1013a0SSebastian Andrzej Siewior 
2114dab20177SRafael J. Wysocki 	if (!boot_cpu_has(X86_FEATURE_ARAT))
2115cbd2c4c2SRafael J. Wysocki 		tick_broadcast_enable();
2116fb1013a0SSebastian Andrzej Siewior 
2117fb1013a0SSebastian Andrzej Siewior 	/*
2118fb1013a0SSebastian Andrzej Siewior 	 * Some systems can hotplug a cpu at runtime after
2119fb1013a0SSebastian Andrzej Siewior 	 * the kernel has booted, we have to initialize the
2120fb1013a0SSebastian Andrzej Siewior 	 * driver in this case
2121fb1013a0SSebastian Andrzej Siewior 	 */
2122fb1013a0SSebastian Andrzej Siewior 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
2123fb1013a0SSebastian Andrzej Siewior 	if (!dev->registered)
2124fb1013a0SSebastian Andrzej Siewior 		return intel_idle_cpu_init(cpu);
2125dbf87ab8SBartlomiej Zolnierkiewicz 
212626717172SLen Brown 	return 0;
212726717172SLen Brown }
212826717172SLen Brown 
21290755a9bdSRafael J. Wysocki /**
21300755a9bdSRafael J. Wysocki  * intel_idle_cpuidle_devices_uninit - Unregister all cpuidle devices.
21310755a9bdSRafael J. Wysocki  */
21320755a9bdSRafael J. Wysocki static void __init intel_idle_cpuidle_devices_uninit(void)
21330755a9bdSRafael J. Wysocki {
21340755a9bdSRafael J. Wysocki 	int i;
21350755a9bdSRafael J. Wysocki 
21360755a9bdSRafael J. Wysocki 	for_each_online_cpu(i)
21370755a9bdSRafael J. Wysocki 		cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
21380755a9bdSRafael J. Wysocki }
21390755a9bdSRafael J. Wysocki 
2140*0fac214bSArjan van de Ven /*
2141*0fac214bSArjan van de Ven  * Match up the latency and break even point of the bare metal (cpu based)
2142*0fac214bSArjan van de Ven  * states with the deepest VM available state.
2143*0fac214bSArjan van de Ven  *
2144*0fac214bSArjan van de Ven  * We only want to do this for the deepest state, the ones that has
2145*0fac214bSArjan van de Ven  * the TLB_FLUSHED flag set on the .
2146*0fac214bSArjan van de Ven  *
2147*0fac214bSArjan van de Ven  * All our short idle states are dominated by vmexit/vmenter latencies,
2148*0fac214bSArjan van de Ven  * not the underlying hardware latencies so we keep our values for these.
2149*0fac214bSArjan van de Ven  */
2150*0fac214bSArjan van de Ven static void matchup_vm_state_with_baremetal(void)
2151*0fac214bSArjan van de Ven {
2152*0fac214bSArjan van de Ven 	int cstate;
2153*0fac214bSArjan van de Ven 
2154*0fac214bSArjan van de Ven 	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
2155*0fac214bSArjan van de Ven 		int matching_cstate;
2156*0fac214bSArjan van de Ven 
2157*0fac214bSArjan van de Ven 		if (intel_idle_max_cstate_reached(cstate))
2158*0fac214bSArjan van de Ven 			break;
2159*0fac214bSArjan van de Ven 
2160*0fac214bSArjan van de Ven 		if (!cpuidle_state_table[cstate].enter)
2161*0fac214bSArjan van de Ven 			break;
2162*0fac214bSArjan van de Ven 
2163*0fac214bSArjan van de Ven 		if (!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_TLB_FLUSHED))
2164*0fac214bSArjan van de Ven 			continue;
2165*0fac214bSArjan van de Ven 
2166*0fac214bSArjan van de Ven 		for (matching_cstate = 0; matching_cstate < CPUIDLE_STATE_MAX; ++matching_cstate) {
2167*0fac214bSArjan van de Ven 			if (!icpu->state_table[matching_cstate].enter)
2168*0fac214bSArjan van de Ven 				break;
2169*0fac214bSArjan van de Ven 			if (icpu->state_table[matching_cstate].exit_latency > cpuidle_state_table[cstate].exit_latency) {
2170*0fac214bSArjan van de Ven 				cpuidle_state_table[cstate].exit_latency = icpu->state_table[matching_cstate].exit_latency;
2171*0fac214bSArjan van de Ven 				cpuidle_state_table[cstate].target_residency = icpu->state_table[matching_cstate].target_residency;
2172*0fac214bSArjan van de Ven 			}
2173*0fac214bSArjan van de Ven 		}
2174*0fac214bSArjan van de Ven 
2175*0fac214bSArjan van de Ven 	}
2176*0fac214bSArjan van de Ven }
2177*0fac214bSArjan van de Ven 
2178*0fac214bSArjan van de Ven 
21792f3d08f0SArjan van de Ven static int __init intel_idle_vminit(const struct x86_cpu_id *id)
21802f3d08f0SArjan van de Ven {
21812f3d08f0SArjan van de Ven 	int retval;
21822f3d08f0SArjan van de Ven 
21832f3d08f0SArjan van de Ven 	cpuidle_state_table = vmguest_cstates;
21842f3d08f0SArjan van de Ven 
21852f3d08f0SArjan van de Ven 	icpu = (const struct idle_cpu *)id->driver_data;
21862f3d08f0SArjan van de Ven 
21872f3d08f0SArjan van de Ven 	pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
21882f3d08f0SArjan van de Ven 		 boot_cpu_data.x86_model);
21892f3d08f0SArjan van de Ven 
21902f3d08f0SArjan van de Ven 	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
21912f3d08f0SArjan van de Ven 	if (!intel_idle_cpuidle_devices)
21922f3d08f0SArjan van de Ven 		return -ENOMEM;
21932f3d08f0SArjan van de Ven 
2194*0fac214bSArjan van de Ven 	/*
2195*0fac214bSArjan van de Ven 	 * We don't know exactly what the host will do when we go idle, but as a worst estimate
2196*0fac214bSArjan van de Ven 	 * we can assume that the exit latency of the deepest host state will be hit for our
2197*0fac214bSArjan van de Ven 	 * deep (long duration) guest idle state.
2198*0fac214bSArjan van de Ven 	 * The same logic applies to the break even point for the long duration guest idle state.
2199*0fac214bSArjan van de Ven 	 * So lets copy these two properties from the table we found for the host CPU type.
2200*0fac214bSArjan van de Ven 	 */
2201*0fac214bSArjan van de Ven 	matchup_vm_state_with_baremetal();
2202*0fac214bSArjan van de Ven 
22032f3d08f0SArjan van de Ven 	intel_idle_cpuidle_driver_init(&intel_idle_driver);
22042f3d08f0SArjan van de Ven 
22052f3d08f0SArjan van de Ven 	retval = cpuidle_register_driver(&intel_idle_driver);
22062f3d08f0SArjan van de Ven 	if (retval) {
22072f3d08f0SArjan van de Ven 		struct cpuidle_driver *drv = cpuidle_get_driver();
22082f3d08f0SArjan van de Ven 		printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
22092f3d08f0SArjan van de Ven 		       drv ? drv->name : "none");
22102f3d08f0SArjan van de Ven 		goto init_driver_fail;
22112f3d08f0SArjan van de Ven 	}
22122f3d08f0SArjan van de Ven 
22132f3d08f0SArjan van de Ven 	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
22142f3d08f0SArjan van de Ven 				   intel_idle_cpu_online, NULL);
22152f3d08f0SArjan van de Ven 	if (retval < 0)
22162f3d08f0SArjan van de Ven 		goto hp_setup_fail;
22172f3d08f0SArjan van de Ven 
22182f3d08f0SArjan van de Ven 	return 0;
22192f3d08f0SArjan van de Ven hp_setup_fail:
22202f3d08f0SArjan van de Ven 	intel_idle_cpuidle_devices_uninit();
22212f3d08f0SArjan van de Ven 	cpuidle_unregister_driver(&intel_idle_driver);
22222f3d08f0SArjan van de Ven init_driver_fail:
22232f3d08f0SArjan van de Ven 	free_percpu(intel_idle_cpuidle_devices);
22242f3d08f0SArjan van de Ven 	return retval;
22252f3d08f0SArjan van de Ven }
22262f3d08f0SArjan van de Ven 
222726717172SLen Brown static int __init intel_idle_init(void)
222826717172SLen Brown {
2229a6c86e33SRafael J. Wysocki 	const struct x86_cpu_id *id;
2230a6c86e33SRafael J. Wysocki 	unsigned int eax, ebx, ecx;
2231fb1013a0SSebastian Andrzej Siewior 	int retval;
223226717172SLen Brown 
2233d1896049SThomas Renninger 	/* Do not load intel_idle at all for now if idle= is passed */
2234d1896049SThomas Renninger 	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
2235d1896049SThomas Renninger 		return -ENODEV;
2236d1896049SThomas Renninger 
2237a6c86e33SRafael J. Wysocki 	if (max_cstate == 0) {
2238a6c86e33SRafael J. Wysocki 		pr_debug("disabled\n");
2239a6c86e33SRafael J. Wysocki 		return -EPERM;
2240a6c86e33SRafael J. Wysocki 	}
2241a6c86e33SRafael J. Wysocki 
2242a6c86e33SRafael J. Wysocki 	id = x86_match_cpu(intel_idle_ids);
2243a6c86e33SRafael J. Wysocki 	if (id) {
2244a6c86e33SRafael J. Wysocki 		if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
22452f3d08f0SArjan van de Ven 			if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
22462f3d08f0SArjan van de Ven 				return intel_idle_vminit(id);
2247a6c86e33SRafael J. Wysocki 			pr_debug("Please enable MWAIT in BIOS SETUP\n");
2248a6c86e33SRafael J. Wysocki 			return -ENODEV;
2249a6c86e33SRafael J. Wysocki 		}
2250a6c86e33SRafael J. Wysocki 	} else {
2251a6c86e33SRafael J. Wysocki 		id = x86_match_cpu(intel_mwait_ids);
2252a6c86e33SRafael J. Wysocki 		if (!id)
2253a6c86e33SRafael J. Wysocki 			return -ENODEV;
2254a6c86e33SRafael J. Wysocki 	}
2255a6c86e33SRafael J. Wysocki 
2256a6c86e33SRafael J. Wysocki 	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
2257a6c86e33SRafael J. Wysocki 		return -ENODEV;
2258a6c86e33SRafael J. Wysocki 
2259a6c86e33SRafael J. Wysocki 	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
2260a6c86e33SRafael J. Wysocki 
2261a6c86e33SRafael J. Wysocki 	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
2262a6c86e33SRafael J. Wysocki 	    !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
2263a6c86e33SRafael J. Wysocki 	    !mwait_substates)
2264a6c86e33SRafael J. Wysocki 			return -ENODEV;
2265a6c86e33SRafael J. Wysocki 
2266a6c86e33SRafael J. Wysocki 	pr_debug("MWAIT substates: 0x%x\n", mwait_substates);
2267a6c86e33SRafael J. Wysocki 
2268a6c86e33SRafael J. Wysocki 	icpu = (const struct idle_cpu *)id->driver_data;
2269a6c86e33SRafael J. Wysocki 	if (icpu) {
2270a6c86e33SRafael J. Wysocki 		cpuidle_state_table = icpu->state_table;
22717f843dd7SRafael J. Wysocki 		auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
227239c184a6SArtem Bityutskiy 		if (icpu->disable_promotion_to_c1e)
227339c184a6SArtem Bityutskiy 			c1e_promotion = C1E_PROMOTION_DISABLE;
22743a5be9b8SRafael J. Wysocki 		if (icpu->use_acpi || force_use_acpi)
2275a6c86e33SRafael J. Wysocki 			intel_idle_acpi_cst_extract();
2276a6c86e33SRafael J. Wysocki 	} else if (!intel_idle_acpi_cst_extract()) {
2277a6c86e33SRafael J. Wysocki 		return -ENODEV;
2278a6c86e33SRafael J. Wysocki 	}
2279a6c86e33SRafael J. Wysocki 
2280a6c86e33SRafael J. Wysocki 	pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
2281a6c86e33SRafael J. Wysocki 		 boot_cpu_data.x86_model);
228226717172SLen Brown 
2283e9df69ccSRichard Cochran 	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
2284533da74aSRafael J. Wysocki 	if (!intel_idle_cpuidle_devices)
2285e9df69ccSRichard Cochran 		return -ENOMEM;
2286e9df69ccSRichard Cochran 
22873d3a1ae9SRafael J. Wysocki 	intel_idle_cpuidle_driver_init(&intel_idle_driver);
22883d3a1ae9SRafael J. Wysocki 
228926717172SLen Brown 	retval = cpuidle_register_driver(&intel_idle_driver);
229026717172SLen Brown 	if (retval) {
22913735d524SKonrad Rzeszutek Wilk 		struct cpuidle_driver *drv = cpuidle_get_driver();
2292654d08a4SJoe Perches 		printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
22933735d524SKonrad Rzeszutek Wilk 		       drv ? drv->name : "none");
2294fb1013a0SSebastian Andrzej Siewior 		goto init_driver_fail;
229526717172SLen Brown 	}
229626717172SLen Brown 
2297fb1013a0SSebastian Andrzej Siewior 	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
2298fb1013a0SSebastian Andrzej Siewior 				   intel_idle_cpu_online, NULL);
2299fb1013a0SSebastian Andrzej Siewior 	if (retval < 0)
2300fb1013a0SSebastian Andrzej Siewior 		goto hp_setup_fail;
230126717172SLen Brown 
230240ab82e0SRafael J. Wysocki 	pr_debug("Local APIC timer is reliable in %s\n",
2303dab20177SRafael J. Wysocki 		 boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1");
23042259a819SRichard Cochran 
230526717172SLen Brown 	return 0;
2306fb1013a0SSebastian Andrzej Siewior 
2307fb1013a0SSebastian Andrzej Siewior hp_setup_fail:
2308fb1013a0SSebastian Andrzej Siewior 	intel_idle_cpuidle_devices_uninit();
2309fb1013a0SSebastian Andrzej Siewior 	cpuidle_unregister_driver(&intel_idle_driver);
2310fb1013a0SSebastian Andrzej Siewior init_driver_fail:
2311fb1013a0SSebastian Andrzej Siewior 	free_percpu(intel_idle_cpuidle_devices);
2312fb1013a0SSebastian Andrzej Siewior 	return retval;
2313fb1013a0SSebastian Andrzej Siewior 
231426717172SLen Brown }
231502c4fae9SPaul Gortmaker device_initcall(intel_idle_init);
231626717172SLen Brown 
231702c4fae9SPaul Gortmaker /*
231802c4fae9SPaul Gortmaker  * We are not really modular, but we used to support that.  Meaning we also
231902c4fae9SPaul Gortmaker  * support "intel_idle.max_cstate=..." at boot and also a read-only export of
232002c4fae9SPaul Gortmaker  * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param
232102c4fae9SPaul Gortmaker  * is the easiest way (currently) to continue doing that.
232202c4fae9SPaul Gortmaker  */
232326717172SLen Brown module_param(max_cstate, int, 0444);
23244dcb78eeSRafael J. Wysocki /*
23254dcb78eeSRafael J. Wysocki  * The positions of the bits that are set in this number are the indices of the
23264dcb78eeSRafael J. Wysocki  * idle states to be disabled by default (as reflected by the names of the
23274dcb78eeSRafael J. Wysocki  * corresponding idle state directories in sysfs, "state0", "state1" ...
23284dcb78eeSRafael J. Wysocki  * "state<i>" ..., where <i> is the index of the given state).
23294dcb78eeSRafael J. Wysocki  */
23304dcb78eeSRafael J. Wysocki module_param_named(states_off, disabled_states_mask, uint, 0444);
23314dcb78eeSRafael J. Wysocki MODULE_PARM_DESC(states_off, "Mask of disabled idle states");
2332da0e58c0SArtem Bityutskiy /*
2333da0e58c0SArtem Bityutskiy  * Some platforms come with mutually exclusive C-states, so that if one is
2334da0e58c0SArtem Bityutskiy  * enabled, the other C-states must not be used. Example: C1 and C1E on
2335da0e58c0SArtem Bityutskiy  * Sapphire Rapids platform. This parameter allows for selecting the
2336da0e58c0SArtem Bityutskiy  * preferred C-states among the groups of mutually exclusive C-states - the
2337da0e58c0SArtem Bityutskiy  * selected C-states will be registered, the other C-states from the mutually
2338da0e58c0SArtem Bityutskiy  * exclusive group won't be registered. If the platform has no mutually
2339da0e58c0SArtem Bityutskiy  * exclusive C-states, this parameter has no effect.
2340da0e58c0SArtem Bityutskiy  */
2341da0e58c0SArtem Bityutskiy module_param_named(preferred_cstates, preferred_states_mask, uint, 0444);
2342da0e58c0SArtem Bityutskiy MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states");
23434152379aSArtem Bityutskiy /*
23444152379aSArtem Bityutskiy  * Debugging option that forces the driver to enter all C-states with
23454152379aSArtem Bityutskiy  * interrupts enabled. Does not apply to C-states with
23464152379aSArtem Bityutskiy  * 'CPUIDLE_FLAG_INIT_XSTATE' and 'CPUIDLE_FLAG_IBRS' flags.
23474152379aSArtem Bityutskiy  */
23484152379aSArtem Bityutskiy module_param(force_irq_on, bool, 0444);
2349