blob: a41d511238dffb8e6d710034fbd59dfac7980bd3 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Simon Glass18739e22014-11-14 18:18:43 -07002/*
3 * From Coreboot file of the same name
4 *
5 * Copyright (C) 2011 The Chromium Authors.
Simon Glass18739e22014-11-14 18:18:43 -07006 */
7
8#include <common.h>
9#include <asm/cpu.h>
10#include <asm/msr.h>
11#include <asm/processor.h>
12#include <asm/turbo.h>
13
Simon Glassa0c75f92017-01-16 07:04:17 -070014DECLARE_GLOBAL_DATA_PTR;
15
Bin Meng2ddb1a12017-08-17 01:10:42 -070016#ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
Simon Glass18739e22014-11-14 18:18:43 -070017static inline int get_global_turbo_state(void)
18{
19 return TURBO_UNKNOWN;
20}
21
22static inline void set_global_turbo_state(int state)
23{
24}
25#else
Simon Glass18739e22014-11-14 18:18:43 -070026static inline int get_global_turbo_state(void)
27{
Simon Glassa0c75f92017-01-16 07:04:17 -070028 return gd->arch.turbo_state;
Simon Glass18739e22014-11-14 18:18:43 -070029}
30
31static inline void set_global_turbo_state(int state)
32{
Simon Glassa0c75f92017-01-16 07:04:17 -070033 gd->arch.turbo_state = state;
Simon Glass18739e22014-11-14 18:18:43 -070034}
35#endif
36
37static const char *const turbo_state_desc[] = {
38 [TURBO_UNKNOWN] = "unknown",
39 [TURBO_UNAVAILABLE] = "unavailable",
40 [TURBO_DISABLED] = "available but hidden",
41 [TURBO_ENABLED] = "available and visible"
42};
43
44/*
45 * Determine the current state of Turbo and cache it for later.
46 * Turbo is a package level config so it does not need to be
47 * enabled on every core.
48 */
49int turbo_get_state(void)
50{
51 struct cpuid_result cpuid_regs;
52 int turbo_en, turbo_cap;
53 msr_t msr;
54 int turbo_state = get_global_turbo_state();
55
56 /* Return cached state if available */
57 if (turbo_state != TURBO_UNKNOWN)
58 return turbo_state;
59
60 cpuid_regs = cpuid(CPUID_LEAF_PM);
61 turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
62
63 msr = msr_read(MSR_IA32_MISC_ENABLES);
64 turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
65
66 if (!turbo_cap && turbo_en) {
67 /* Unavailable */
68 turbo_state = TURBO_UNAVAILABLE;
69 } else if (!turbo_cap && !turbo_en) {
70 /* Available but disabled */
71 turbo_state = TURBO_DISABLED;
72 } else if (turbo_cap && turbo_en) {
73 /* Available */
74 turbo_state = TURBO_ENABLED;
75 }
76
77 set_global_turbo_state(turbo_state);
78 debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
79 return turbo_state;
80}
81
82void turbo_enable(void)
83{
84 msr_t msr;
85
86 /* Only possible if turbo is available but hidden */
87 if (turbo_get_state() == TURBO_DISABLED) {
88 /* Clear Turbo Disable bit in Misc Enables */
89 msr = msr_read(MSR_IA32_MISC_ENABLES);
90 msr.hi &= ~H_MISC_DISABLE_TURBO;
91 msr_write(MSR_IA32_MISC_ENABLES, msr);
92
93 /* Update cached turbo state */
94 set_global_turbo_state(TURBO_ENABLED);
95 debug("Turbo has been enabled\n");
96 }
97}