xref: /openbmc/u-boot/arch/x86/cpu/turbo.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
218739e2cSSimon Glass /*
318739e2cSSimon Glass  * From Coreboot file of the same name
418739e2cSSimon Glass  *
518739e2cSSimon Glass  * Copyright (C) 2011 The Chromium Authors.
618739e2cSSimon Glass  */
718739e2cSSimon Glass 
818739e2cSSimon Glass #include <common.h>
918739e2cSSimon Glass #include <asm/cpu.h>
1018739e2cSSimon Glass #include <asm/msr.h>
1118739e2cSSimon Glass #include <asm/processor.h>
1218739e2cSSimon Glass #include <asm/turbo.h>
1318739e2cSSimon Glass 
14a0c75f90SSimon Glass DECLARE_GLOBAL_DATA_PTR;
15a0c75f90SSimon Glass 
162ddb1a17SBin Meng #ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
get_global_turbo_state(void)1718739e2cSSimon Glass static inline int get_global_turbo_state(void)
1818739e2cSSimon Glass {
1918739e2cSSimon Glass 	return TURBO_UNKNOWN;
2018739e2cSSimon Glass }
2118739e2cSSimon Glass 
set_global_turbo_state(int state)2218739e2cSSimon Glass static inline void set_global_turbo_state(int state)
2318739e2cSSimon Glass {
2418739e2cSSimon Glass }
2518739e2cSSimon Glass #else
get_global_turbo_state(void)2618739e2cSSimon Glass static inline int get_global_turbo_state(void)
2718739e2cSSimon Glass {
28a0c75f90SSimon Glass 	return gd->arch.turbo_state;
2918739e2cSSimon Glass }
3018739e2cSSimon Glass 
set_global_turbo_state(int state)3118739e2cSSimon Glass static inline void set_global_turbo_state(int state)
3218739e2cSSimon Glass {
33a0c75f90SSimon Glass 	gd->arch.turbo_state = state;
3418739e2cSSimon Glass }
3518739e2cSSimon Glass #endif
3618739e2cSSimon Glass 
3718739e2cSSimon Glass static const char *const turbo_state_desc[] = {
3818739e2cSSimon Glass 	[TURBO_UNKNOWN]		= "unknown",
3918739e2cSSimon Glass 	[TURBO_UNAVAILABLE]	= "unavailable",
4018739e2cSSimon Glass 	[TURBO_DISABLED]	= "available but hidden",
4118739e2cSSimon Glass 	[TURBO_ENABLED]		= "available and visible"
4218739e2cSSimon Glass };
4318739e2cSSimon Glass 
4418739e2cSSimon Glass /*
4518739e2cSSimon Glass  * Determine the current state of Turbo and cache it for later.
4618739e2cSSimon Glass  * Turbo is a package level config so it does not need to be
4718739e2cSSimon Glass  * enabled on every core.
4818739e2cSSimon Glass  */
turbo_get_state(void)4918739e2cSSimon Glass int turbo_get_state(void)
5018739e2cSSimon Glass {
5118739e2cSSimon Glass 	struct cpuid_result cpuid_regs;
5218739e2cSSimon Glass 	int turbo_en, turbo_cap;
5318739e2cSSimon Glass 	msr_t msr;
5418739e2cSSimon Glass 	int turbo_state = get_global_turbo_state();
5518739e2cSSimon Glass 
5618739e2cSSimon Glass 	/* Return cached state if available */
5718739e2cSSimon Glass 	if (turbo_state != TURBO_UNKNOWN)
5818739e2cSSimon Glass 		return turbo_state;
5918739e2cSSimon Glass 
6018739e2cSSimon Glass 	cpuid_regs = cpuid(CPUID_LEAF_PM);
6118739e2cSSimon Glass 	turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
6218739e2cSSimon Glass 
6318739e2cSSimon Glass 	msr = msr_read(MSR_IA32_MISC_ENABLES);
6418739e2cSSimon Glass 	turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
6518739e2cSSimon Glass 
6618739e2cSSimon Glass 	if (!turbo_cap && turbo_en) {
6718739e2cSSimon Glass 		/* Unavailable */
6818739e2cSSimon Glass 		turbo_state = TURBO_UNAVAILABLE;
6918739e2cSSimon Glass 	} else if (!turbo_cap && !turbo_en) {
7018739e2cSSimon Glass 		/* Available but disabled */
7118739e2cSSimon Glass 		turbo_state = TURBO_DISABLED;
7218739e2cSSimon Glass 	} else if (turbo_cap && turbo_en) {
7318739e2cSSimon Glass 		/* Available */
7418739e2cSSimon Glass 		turbo_state = TURBO_ENABLED;
7518739e2cSSimon Glass 	}
7618739e2cSSimon Glass 
7718739e2cSSimon Glass 	set_global_turbo_state(turbo_state);
7818739e2cSSimon Glass 	debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
7918739e2cSSimon Glass 	return turbo_state;
8018739e2cSSimon Glass }
8118739e2cSSimon Glass 
turbo_enable(void)8218739e2cSSimon Glass void turbo_enable(void)
8318739e2cSSimon Glass {
8418739e2cSSimon Glass 	msr_t msr;
8518739e2cSSimon Glass 
8618739e2cSSimon Glass 	/* Only possible if turbo is available but hidden */
8718739e2cSSimon Glass 	if (turbo_get_state() == TURBO_DISABLED) {
8818739e2cSSimon Glass 		/* Clear Turbo Disable bit in Misc Enables */
8918739e2cSSimon Glass 		msr = msr_read(MSR_IA32_MISC_ENABLES);
9018739e2cSSimon Glass 		msr.hi &= ~H_MISC_DISABLE_TURBO;
9118739e2cSSimon Glass 		msr_write(MSR_IA32_MISC_ENABLES, msr);
9218739e2cSSimon Glass 
9318739e2cSSimon Glass 		/* Update cached turbo state */
9418739e2cSSimon Glass 		set_global_turbo_state(TURBO_ENABLED);
9518739e2cSSimon Glass 		debug("Turbo has been enabled\n");
9618739e2cSSimon Glass 	}
9718739e2cSSimon Glass }
98