| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * From Coreboot file of the same name |
| * |
| * Copyright (C) 2011 The Chromium Authors. |
| */ |
| |
| #include <common.h> |
| #include <log.h> |
| #include <asm/cpu.h> |
| #include <asm/msr.h> |
| #include <asm/processor.h> |
| #include <asm/turbo.h> |
| |
| DECLARE_GLOBAL_DATA_PTR; |
| |
| #ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED |
| static inline int get_global_turbo_state(void) |
| { |
| return TURBO_UNKNOWN; |
| } |
| |
| static inline void set_global_turbo_state(int state) |
| { |
| } |
| #else |
| static inline int get_global_turbo_state(void) |
| { |
| return gd->arch.turbo_state; |
| } |
| |
| static inline void set_global_turbo_state(int state) |
| { |
| gd->arch.turbo_state = state; |
| } |
| #endif |
| |
| /* gcc 7.3 does not wwant to drop strings, so use #ifdef */ |
| #ifndef CONFIG_TPL_BUILD |
| static const char *const turbo_state_desc[] = { |
| [TURBO_UNKNOWN] = "unknown", |
| [TURBO_UNAVAILABLE] = "unavailable", |
| [TURBO_DISABLED] = "available but hidden", |
| [TURBO_ENABLED] = "available and visible" |
| }; |
| #endif |
| |
| /* |
| * Determine the current state of Turbo and cache it for later. |
| * Turbo is a package level config so it does not need to be |
| * enabled on every core. |
| */ |
| int turbo_get_state(void) |
| { |
| struct cpuid_result cpuid_regs; |
| int turbo_en, turbo_cap; |
| msr_t msr; |
| int turbo_state = get_global_turbo_state(); |
| |
| /* Return cached state if available */ |
| if (turbo_state != TURBO_UNKNOWN) |
| return turbo_state; |
| |
| cpuid_regs = cpuid(CPUID_LEAF_PM); |
| turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE); |
| |
| msr = msr_read(MSR_IA32_MISC_ENABLE); |
| turbo_en = !(msr.hi & MISC_DISABLE_TURBO); |
| |
| if (!turbo_cap && turbo_en) { |
| /* Unavailable */ |
| turbo_state = TURBO_UNAVAILABLE; |
| } else if (!turbo_cap && !turbo_en) { |
| /* Available but disabled */ |
| turbo_state = TURBO_DISABLED; |
| } else if (turbo_cap && turbo_en) { |
| /* Available */ |
| turbo_state = TURBO_ENABLED; |
| } |
| |
| set_global_turbo_state(turbo_state); |
| #ifndef CONFIG_TPL_BUILD |
| debug("Turbo is %s\n", turbo_state_desc[turbo_state]); |
| #endif |
| return turbo_state; |
| } |
| |
| void turbo_enable(void) |
| { |
| msr_t msr; |
| |
| /* Only possible if turbo is available but hidden */ |
| if (turbo_get_state() == TURBO_DISABLED) { |
| /* Clear Turbo Disable bit in Misc Enables */ |
| msr = msr_read(MSR_IA32_MISC_ENABLE); |
| msr.hi &= ~MISC_DISABLE_TURBO; |
| msr_write(MSR_IA32_MISC_ENABLE, msr); |
| |
| /* Update cached turbo state */ |
| set_global_turbo_state(TURBO_ENABLED); |
| debug("Turbo has been enabled\n"); |
| } |
| } |