blob: e2c84cddec8e711d1b1b9f54051fedb0d38e737e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Simon Glasse8045012014-11-14 18:18:43 -07002/*
3 * From Coreboot file of the same name
4 *
5 * Copyright (C) 2011 The Chromium Authors.
Simon Glasse8045012014-11-14 18:18:43 -07006 */
7
8#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glasse8045012014-11-14 18:18:43 -070010#include <asm/cpu.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Simon Glasse8045012014-11-14 18:18:43 -070012#include <asm/msr.h>
13#include <asm/processor.h>
14#include <asm/turbo.h>
15
Simon Glass37e706d2017-01-16 07:04:17 -070016DECLARE_GLOBAL_DATA_PTR;
17
Bin Meng842c31e2017-08-17 01:10:42 -070018#ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
Simon Glasse8045012014-11-14 18:18:43 -070019static inline int get_global_turbo_state(void)
20{
21 return TURBO_UNKNOWN;
22}
23
24static inline void set_global_turbo_state(int state)
25{
26}
27#else
Simon Glasse8045012014-11-14 18:18:43 -070028static inline int get_global_turbo_state(void)
29{
Simon Glass37e706d2017-01-16 07:04:17 -070030 return gd->arch.turbo_state;
Simon Glasse8045012014-11-14 18:18:43 -070031}
32
33static inline void set_global_turbo_state(int state)
34{
Simon Glass37e706d2017-01-16 07:04:17 -070035 gd->arch.turbo_state = state;
Simon Glasse8045012014-11-14 18:18:43 -070036}
37#endif
38
Simon Glassec8ae8a2020-12-23 08:11:30 -070039/* gcc 7.3 does not wwant to drop strings, so use #ifdef */
40#ifndef CONFIG_TPL_BUILD
Simon Glasse8045012014-11-14 18:18:43 -070041static const char *const turbo_state_desc[] = {
42 [TURBO_UNKNOWN] = "unknown",
43 [TURBO_UNAVAILABLE] = "unavailable",
44 [TURBO_DISABLED] = "available but hidden",
45 [TURBO_ENABLED] = "available and visible"
46};
Simon Glassec8ae8a2020-12-23 08:11:30 -070047#endif
Simon Glasse8045012014-11-14 18:18:43 -070048
49/*
50 * Determine the current state of Turbo and cache it for later.
51 * Turbo is a package level config so it does not need to be
52 * enabled on every core.
53 */
54int turbo_get_state(void)
55{
56 struct cpuid_result cpuid_regs;
57 int turbo_en, turbo_cap;
58 msr_t msr;
59 int turbo_state = get_global_turbo_state();
60
61 /* Return cached state if available */
62 if (turbo_state != TURBO_UNKNOWN)
63 return turbo_state;
64
65 cpuid_regs = cpuid(CPUID_LEAF_PM);
66 turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
67
Simon Glass05e85b92019-09-25 08:56:39 -060068 msr = msr_read(MSR_IA32_MISC_ENABLE);
69 turbo_en = !(msr.hi & MISC_DISABLE_TURBO);
Simon Glasse8045012014-11-14 18:18:43 -070070
71 if (!turbo_cap && turbo_en) {
72 /* Unavailable */
73 turbo_state = TURBO_UNAVAILABLE;
74 } else if (!turbo_cap && !turbo_en) {
75 /* Available but disabled */
76 turbo_state = TURBO_DISABLED;
77 } else if (turbo_cap && turbo_en) {
78 /* Available */
79 turbo_state = TURBO_ENABLED;
80 }
81
82 set_global_turbo_state(turbo_state);
Simon Glassec8ae8a2020-12-23 08:11:30 -070083#ifndef CONFIG_TPL_BUILD
Simon Glasse8045012014-11-14 18:18:43 -070084 debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
Simon Glassec8ae8a2020-12-23 08:11:30 -070085#endif
Simon Glasse8045012014-11-14 18:18:43 -070086 return turbo_state;
87}
88
89void turbo_enable(void)
90{
91 msr_t msr;
92
93 /* Only possible if turbo is available but hidden */
94 if (turbo_get_state() == TURBO_DISABLED) {
95 /* Clear Turbo Disable bit in Misc Enables */
Simon Glass05e85b92019-09-25 08:56:39 -060096 msr = msr_read(MSR_IA32_MISC_ENABLE);
97 msr.hi &= ~MISC_DISABLE_TURBO;
98 msr_write(MSR_IA32_MISC_ENABLE, msr);
Simon Glasse8045012014-11-14 18:18:43 -070099
100 /* Update cached turbo state */
101 set_global_turbo_state(TURBO_ENABLED);
102 debug("Turbo has been enabled\n");
103 }
104}