Add support for Intel Turbo Boost feature
[coreboot.git] / src / cpu / intel / turbo / turbo.c
1 /*
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19  * MA 02110-1301 USA
20  */
21
22 #include <console/console.h>
23 #include <cpu/intel/turbo.h>
24 #include <cpu/x86/msr.h>
25 #include <arch/cpu.h>
26
27 static int turbo_state = TURBO_UNKNOWN;
28
29 static const char *turbo_state_desc[] = {
30         [TURBO_UNKNOWN]         = "unknown",
31         [TURBO_UNAVAILABLE]     = "unavailable",
32         [TURBO_DISABLED]        = "available but hidden",
33         [TURBO_ENABLED]         = "available and visible"
34 };
35
36 /*
37  * Determine the current state of Turbo and cache it for later.
38  * Turbo is a package level config so it does not need to be
39  * enabled on every core.
40  */
41 int get_turbo_state(void)
42 {
43         struct cpuid_result cpuid_regs;
44         int turbo_en, turbo_cap;
45         msr_t msr;
46
47         /* Return cached state if available */
48         if (turbo_state != TURBO_UNKNOWN)
49                 return turbo_state;
50
51         cpuid_regs = cpuid(CPUID_LEAF_PM);
52         turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
53
54         msr = rdmsr(MSR_IA32_MISC_ENABLES);
55         turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
56
57         if (!turbo_cap && turbo_en) {
58                 /* Unavailable */
59                 turbo_state = TURBO_UNAVAILABLE;
60         } else if (!turbo_cap && !turbo_en) {
61                 /* Available but disabled */
62                 turbo_state = TURBO_DISABLED;
63         } else if (turbo_cap && turbo_en) {
64                 /* Available */
65                 turbo_state = TURBO_ENABLED;
66         }
67
68         printk(BIOS_INFO, "Turbo is %s\n", turbo_state_desc[turbo_state]);
69         return turbo_state;
70 }
71
72 /*
73  * Try to enable Turbo mode.
74  */
75 void enable_turbo(void)
76 {
77         msr_t msr;
78
79         /* Only possible if turbo is available but hidden */
80         if (get_turbo_state() == TURBO_DISABLED) {
81                 /* Clear Turbo Disable bit in Misc Enables */
82                 msr = rdmsr(MSR_IA32_MISC_ENABLES);
83                 msr.hi &= ~H_MISC_DISABLE_TURBO;
84                 wrmsr(MSR_IA32_MISC_ENABLES, msr);
85
86                 /* Update cached turbo state */
87                 turbo_state = TURBO_ENABLED;
88                 printk(BIOS_INFO, "Turbo has been enabled\n");
89         }
90 }