blob: c31f4c0e3b1d085ad861f7f0c66f956802a6dcda [file] [log] [blame]
Stefan Reinauerea37a212012-04-02 13:35:09 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauerea37a212012-04-02 13:35:09 -070015 */
16
17#include <console/console.h>
18#include <cpu/intel/turbo.h>
19#include <cpu/x86/msr.h>
20#include <arch/cpu.h>
21
Martin Rothffdee282017-06-24 13:43:40 -060022#if IS_ENABLED(CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED)
Aaron Durbinba6b07e2014-01-14 17:28:33 -060023static inline int get_global_turbo_state(void)
24{
25 return TURBO_UNKNOWN;
26}
27
28static inline void set_global_turbo_state(int state)
29{
30}
31#else
32static int g_turbo_state = TURBO_UNKNOWN;
33
34static inline int get_global_turbo_state(void)
35{
36 return g_turbo_state;
37}
38
39static inline void set_global_turbo_state(int state)
40{
41 g_turbo_state = state;
42}
43#endif
Stefan Reinauerea37a212012-04-02 13:35:09 -070044
Elyes HAOUAS6c9737b2018-07-08 12:30:02 +020045static const char *const turbo_state_desc[] = {
Stefan Reinauerea37a212012-04-02 13:35:09 -070046 [TURBO_UNKNOWN] = "unknown",
47 [TURBO_UNAVAILABLE] = "unavailable",
48 [TURBO_DISABLED] = "available but hidden",
49 [TURBO_ENABLED] = "available and visible"
50};
51
52/*
53 * Determine the current state of Turbo and cache it for later.
54 * Turbo is a package level config so it does not need to be
55 * enabled on every core.
56 */
57int get_turbo_state(void)
58{
59 struct cpuid_result cpuid_regs;
60 int turbo_en, turbo_cap;
61 msr_t msr;
Aaron Durbinba6b07e2014-01-14 17:28:33 -060062 int turbo_state = get_global_turbo_state();
Stefan Reinauerea37a212012-04-02 13:35:09 -070063
64 /* Return cached state if available */
65 if (turbo_state != TURBO_UNKNOWN)
66 return turbo_state;
67
68 cpuid_regs = cpuid(CPUID_LEAF_PM);
69 turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
70
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +020071 msr = rdmsr(IA32_MISC_ENABLE);
Stefan Reinauerea37a212012-04-02 13:35:09 -070072 turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
73
74 if (!turbo_cap && turbo_en) {
75 /* Unavailable */
76 turbo_state = TURBO_UNAVAILABLE;
77 } else if (!turbo_cap && !turbo_en) {
78 /* Available but disabled */
79 turbo_state = TURBO_DISABLED;
80 } else if (turbo_cap && turbo_en) {
81 /* Available */
82 turbo_state = TURBO_ENABLED;
83 }
84
Aaron Durbinba6b07e2014-01-14 17:28:33 -060085 set_global_turbo_state(turbo_state);
Stefan Reinauerea37a212012-04-02 13:35:09 -070086 printk(BIOS_INFO, "Turbo is %s\n", turbo_state_desc[turbo_state]);
87 return turbo_state;
88}
89
90/*
91 * Try to enable Turbo mode.
92 */
93void enable_turbo(void)
94{
95 msr_t msr;
96
97 /* Only possible if turbo is available but hidden */
98 if (get_turbo_state() == TURBO_DISABLED) {
99 /* Clear Turbo Disable bit in Misc Enables */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200100 msr = rdmsr(IA32_MISC_ENABLE);
Stefan Reinauerea37a212012-04-02 13:35:09 -0700101 msr.hi &= ~H_MISC_DISABLE_TURBO;
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200102 wrmsr(IA32_MISC_ENABLE, msr);
Stefan Reinauerea37a212012-04-02 13:35:09 -0700103
104 /* Update cached turbo state */
Aaron Durbinba6b07e2014-01-14 17:28:33 -0600105 set_global_turbo_state(TURBO_ENABLED);
Stefan Reinauerea37a212012-04-02 13:35:09 -0700106 printk(BIOS_INFO, "Turbo has been enabled\n");
107 }
108}
Subrata Banik7bde8482017-05-02 19:35:42 +0530109
110/*
111 * Try to disable Turbo mode.
112 */
113void disable_turbo(void)
114{
115 msr_t msr;
116
117 /* Set Turbo Disable bit in Misc Enables */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200118 msr = rdmsr(IA32_MISC_ENABLE);
Subrata Banik7bde8482017-05-02 19:35:42 +0530119 msr.hi |= H_MISC_DISABLE_TURBO;
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200120 wrmsr(IA32_MISC_ENABLE, msr);
Subrata Banik7bde8482017-05-02 19:35:42 +0530121
122 /* Update cached turbo state */
123 set_global_turbo_state(TURBO_UNAVAILABLE);
124 printk(BIOS_INFO, "Turbo has been disabled\n");
125}