xref: /openbmc/u-boot/arch/x86/cpu/turbo.c (revision e8f80a5a)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * From Coreboot file of the same name
4  *
5  * Copyright (C) 2011 The Chromium Authors.
6  */
7 
8 #include <common.h>
9 #include <asm/cpu.h>
10 #include <asm/msr.h>
11 #include <asm/processor.h>
12 #include <asm/turbo.h>
13 
14 DECLARE_GLOBAL_DATA_PTR;
15 
16 #ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
get_global_turbo_state(void)17 static inline int get_global_turbo_state(void)
18 {
19 	return TURBO_UNKNOWN;
20 }
21 
set_global_turbo_state(int state)22 static inline void set_global_turbo_state(int state)
23 {
24 }
25 #else
get_global_turbo_state(void)26 static inline int get_global_turbo_state(void)
27 {
28 	return gd->arch.turbo_state;
29 }
30 
set_global_turbo_state(int state)31 static inline void set_global_turbo_state(int state)
32 {
33 	gd->arch.turbo_state = state;
34 }
35 #endif
36 
37 static const char *const turbo_state_desc[] = {
38 	[TURBO_UNKNOWN]		= "unknown",
39 	[TURBO_UNAVAILABLE]	= "unavailable",
40 	[TURBO_DISABLED]	= "available but hidden",
41 	[TURBO_ENABLED]		= "available and visible"
42 };
43 
44 /*
45  * Determine the current state of Turbo and cache it for later.
46  * Turbo is a package level config so it does not need to be
47  * enabled on every core.
48  */
turbo_get_state(void)49 int turbo_get_state(void)
50 {
51 	struct cpuid_result cpuid_regs;
52 	int turbo_en, turbo_cap;
53 	msr_t msr;
54 	int turbo_state = get_global_turbo_state();
55 
56 	/* Return cached state if available */
57 	if (turbo_state != TURBO_UNKNOWN)
58 		return turbo_state;
59 
60 	cpuid_regs = cpuid(CPUID_LEAF_PM);
61 	turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
62 
63 	msr = msr_read(MSR_IA32_MISC_ENABLES);
64 	turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
65 
66 	if (!turbo_cap && turbo_en) {
67 		/* Unavailable */
68 		turbo_state = TURBO_UNAVAILABLE;
69 	} else if (!turbo_cap && !turbo_en) {
70 		/* Available but disabled */
71 		turbo_state = TURBO_DISABLED;
72 	} else if (turbo_cap && turbo_en) {
73 		/* Available */
74 		turbo_state = TURBO_ENABLED;
75 	}
76 
77 	set_global_turbo_state(turbo_state);
78 	debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
79 	return turbo_state;
80 }
81 
turbo_enable(void)82 void turbo_enable(void)
83 {
84 	msr_t msr;
85 
86 	/* Only possible if turbo is available but hidden */
87 	if (turbo_get_state() == TURBO_DISABLED) {
88 		/* Clear Turbo Disable bit in Misc Enables */
89 		msr = msr_read(MSR_IA32_MISC_ENABLES);
90 		msr.hi &= ~H_MISC_DISABLE_TURBO;
91 		msr_write(MSR_IA32_MISC_ENABLES, msr);
92 
93 		/* Update cached turbo state */
94 		set_global_turbo_state(TURBO_ENABLED);
95 		debug("Turbo has been enabled\n");
96 	}
97 }
98