xref: /aosp_15_r20/external/coreboot/src/cpu/intel/turbo/turbo.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <cpu/cpu.h>
5 #include <cpu/intel/turbo.h>
6 #include <cpu/x86/msr.h>
7 
8 #if CONFIG(CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED)
get_global_turbo_state(void)9 static inline int get_global_turbo_state(void)
10 {
11 	return TURBO_UNKNOWN;
12 }
13 
set_global_turbo_state(int state)14 static inline void set_global_turbo_state(int state)
15 {
16 }
17 #else
18 static int g_turbo_state = TURBO_UNKNOWN;
19 
get_global_turbo_state(void)20 static inline int get_global_turbo_state(void)
21 {
22 	return g_turbo_state;
23 }
24 
set_global_turbo_state(int state)25 static inline void set_global_turbo_state(int state)
26 {
27 	g_turbo_state = state;
28 }
29 #endif
30 
31 static const char *const turbo_state_desc[] = {
32 	[TURBO_UNKNOWN]		= "unknown",
33 	[TURBO_UNAVAILABLE]	= "unavailable",
34 	[TURBO_DISABLED]	= "available but hidden",
35 	[TURBO_ENABLED]		= "available and visible"
36 };
37 
38 /*
39  * Try to update the global Turbo state.
40  */
update_turbo_state(void)41 static int update_turbo_state(void)
42 {
43 	struct cpuid_result cpuid_regs;
44 	int turbo_en, turbo_cap;
45 	msr_t msr;
46 	int turbo_state = get_global_turbo_state();
47 
48 	cpuid_regs = cpuid(CPUID_LEAF_PM);
49 	turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
50 
51 	msr = rdmsr(IA32_MISC_ENABLE);
52 	turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
53 
54 	if (!turbo_cap && turbo_en) {
55 		/* Unavailable */
56 		turbo_state = TURBO_UNAVAILABLE;
57 	} else if (!turbo_cap && !turbo_en) {
58 		/* Available but disabled */
59 		turbo_state = TURBO_DISABLED;
60 	} else if (turbo_cap && turbo_en) {
61 		/* Available */
62 		turbo_state = TURBO_ENABLED;
63 	}
64 
65 	set_global_turbo_state(turbo_state);
66 	printk(BIOS_INFO, "Turbo is %s\n", turbo_state_desc[turbo_state]);
67 
68 	return turbo_state;
69 }
70 
71 /*
72  * Determine the current state of Turbo and cache it for later. Turbo is package
73  * level config so it does not need to be enabled on every core.
74  */
get_turbo_state(void)75 int get_turbo_state(void)
76 {
77 	int turbo_state = get_global_turbo_state();
78 
79 	/* Return cached state if available */
80 	if (turbo_state == TURBO_UNKNOWN)
81 		turbo_state = update_turbo_state();
82 
83 	return turbo_state;
84 }
85 
86 /*
87  * Try to enable Turbo mode.
88  */
enable_turbo(void)89 void enable_turbo(void)
90 {
91 	msr_t msr;
92 
93 	/* Only possible if turbo is available but hidden */
94 	if (get_turbo_state() == TURBO_DISABLED) {
95 		/* Clear Turbo Disable bit in Misc Enables */
96 		msr = rdmsr(IA32_MISC_ENABLE);
97 		msr.hi &= ~H_MISC_DISABLE_TURBO;
98 		wrmsr(IA32_MISC_ENABLE, msr);
99 
100 		/* Update cached turbo state */
101 		update_turbo_state();
102 	}
103 }
104 
105 /*
106  * Try to disable Turbo mode.
107  */
disable_turbo(void)108 void disable_turbo(void)
109 {
110 	msr_t msr;
111 
112 	/* Only possible if turbo is available and visible */
113 	if (get_turbo_state() == TURBO_ENABLED) {
114 		/* Set Turbo Disable bit in Misc Enables */
115 		msr = rdmsr(IA32_MISC_ENABLE);
116 		msr.hi |= H_MISC_DISABLE_TURBO;
117 		wrmsr(IA32_MISC_ENABLE, msr);
118 
119 		/* Update cached turbo state */
120 		update_turbo_state();
121 	}
122 }
123