blob: c9b402c4dc73396f82f7a581d39631aded0cc6d3 [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
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Simon Glasse8045012014-11-14 18:18:43 -07009#include <asm/cpu.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060010#include <asm/global_data.h>
Simon Glasse8045012014-11-14 18:18:43 -070011#include <asm/msr.h>
12#include <asm/processor.h>
13#include <asm/turbo.h>
14
Simon Glass37e706d2017-01-16 07:04:17 -070015DECLARE_GLOBAL_DATA_PTR;
16
Bin Meng842c31e2017-08-17 01:10:42 -070017#ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
Simon Glasse8045012014-11-14 18:18:43 -070018static inline int get_global_turbo_state(void)
19{
20 return TURBO_UNKNOWN;
21}
22
23static inline void set_global_turbo_state(int state)
24{
25}
26#else
Simon Glasse8045012014-11-14 18:18:43 -070027static inline int get_global_turbo_state(void)
28{
Simon Glass37e706d2017-01-16 07:04:17 -070029 return gd->arch.turbo_state;
Simon Glasse8045012014-11-14 18:18:43 -070030}
31
32static inline void set_global_turbo_state(int state)
33{
Simon Glass37e706d2017-01-16 07:04:17 -070034 gd->arch.turbo_state = state;
Simon Glasse8045012014-11-14 18:18:43 -070035}
36#endif
37
Simon Glassec8ae8a2020-12-23 08:11:30 -070038/* gcc 7.3 does not wwant to drop strings, so use #ifdef */
39#ifndef CONFIG_TPL_BUILD
Simon Glasse8045012014-11-14 18:18:43 -070040static const char *const turbo_state_desc[] = {
41 [TURBO_UNKNOWN] = "unknown",
42 [TURBO_UNAVAILABLE] = "unavailable",
43 [TURBO_DISABLED] = "available but hidden",
44 [TURBO_ENABLED] = "available and visible"
45};
Simon Glassec8ae8a2020-12-23 08:11:30 -070046#endif
Simon Glasse8045012014-11-14 18:18:43 -070047
48/*
49 * Determine the current state of Turbo and cache it for later.
50 * Turbo is a package level config so it does not need to be
51 * enabled on every core.
52 */
53int turbo_get_state(void)
54{
55 struct cpuid_result cpuid_regs;
56 int turbo_en, turbo_cap;
57 msr_t msr;
58 int turbo_state = get_global_turbo_state();
59
60 /* Return cached state if available */
61 if (turbo_state != TURBO_UNKNOWN)
62 return turbo_state;
63
64 cpuid_regs = cpuid(CPUID_LEAF_PM);
65 turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
66
Simon Glass05e85b92019-09-25 08:56:39 -060067 msr = msr_read(MSR_IA32_MISC_ENABLE);
68 turbo_en = !(msr.hi & MISC_DISABLE_TURBO);
Simon Glasse8045012014-11-14 18:18:43 -070069
70 if (!turbo_cap && turbo_en) {
71 /* Unavailable */
72 turbo_state = TURBO_UNAVAILABLE;
73 } else if (!turbo_cap && !turbo_en) {
74 /* Available but disabled */
75 turbo_state = TURBO_DISABLED;
76 } else if (turbo_cap && turbo_en) {
77 /* Available */
78 turbo_state = TURBO_ENABLED;
79 }
80
81 set_global_turbo_state(turbo_state);
Simon Glassec8ae8a2020-12-23 08:11:30 -070082#ifndef CONFIG_TPL_BUILD
Simon Glasse8045012014-11-14 18:18:43 -070083 debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
Simon Glassec8ae8a2020-12-23 08:11:30 -070084#endif
Simon Glasse8045012014-11-14 18:18:43 -070085 return turbo_state;
86}
87
88void turbo_enable(void)
89{
90 msr_t msr;
91
92 /* Only possible if turbo is available but hidden */
93 if (turbo_get_state() == TURBO_DISABLED) {
94 /* Clear Turbo Disable bit in Misc Enables */
Simon Glass05e85b92019-09-25 08:56:39 -060095 msr = msr_read(MSR_IA32_MISC_ENABLE);
96 msr.hi &= ~MISC_DISABLE_TURBO;
97 msr_write(MSR_IA32_MISC_ENABLE, msr);
Simon Glasse8045012014-11-14 18:18:43 -070098
99 /* Update cached turbo state */
100 set_global_turbo_state(TURBO_ENABLED);
101 debug("Turbo has been enabled\n");
102 }
103}