summaryrefslogtreecommitdiff
path: root/arch/x86/cpu/turbo.c
diff options
context:
space:
mode:
authorTom Rini <trini@ti.com>2014-12-01 15:24:07 -0500
committerTom Rini <trini@ti.com>2014-12-01 15:24:07 -0500
commitf4e7e2d12164c3235c3f5e19a68a503623029d35 (patch)
treedea8bdf2bf2a50f561c165b5bbd4e1195ab01994 /arch/x86/cpu/turbo.c
parent9e374e7b729dc9f68be89cd3e3b1d4d48c768ecf (diff)
parent908ec6e4d1d12f746cb9b7cc73430a268ceb2c92 (diff)
downloadu-boot-imx-f4e7e2d12164c3235c3f5e19a68a503623029d35.zip
u-boot-imx-f4e7e2d12164c3235c3f5e19a68a503623029d35.tar.gz
u-boot-imx-f4e7e2d12164c3235c3f5e19a68a503623029d35.tar.bz2
Merge git://git.denx.de/u-boot-x86
Diffstat (limited to 'arch/x86/cpu/turbo.c')
-rw-r--r--arch/x86/cpu/turbo.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/arch/x86/cpu/turbo.c b/arch/x86/cpu/turbo.c
new file mode 100644
index 0000000..254d0de
--- /dev/null
+++ b/arch/x86/cpu/turbo.c
@@ -0,0 +1,98 @@
+/*
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2011 The Chromium Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/cpu.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/turbo.h>
+
+#if CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+static inline int get_global_turbo_state(void)
+{
+ return TURBO_UNKNOWN;
+}
+
+static inline void set_global_turbo_state(int state)
+{
+}
+#else
+static int g_turbo_state = TURBO_UNKNOWN;
+
+static inline int get_global_turbo_state(void)
+{
+ return g_turbo_state;
+}
+
+static inline void set_global_turbo_state(int state)
+{
+ g_turbo_state = state;
+}
+#endif
+
+static const char *const turbo_state_desc[] = {
+ [TURBO_UNKNOWN] = "unknown",
+ [TURBO_UNAVAILABLE] = "unavailable",
+ [TURBO_DISABLED] = "available but hidden",
+ [TURBO_ENABLED] = "available and visible"
+};
+
+/*
+ * Determine the current state of Turbo and cache it for later.
+ * Turbo is a package level config so it does not need to be
+ * enabled on every core.
+ */
+int turbo_get_state(void)
+{
+ struct cpuid_result cpuid_regs;
+ int turbo_en, turbo_cap;
+ msr_t msr;
+ int turbo_state = get_global_turbo_state();
+
+ /* Return cached state if available */
+ if (turbo_state != TURBO_UNKNOWN)
+ return turbo_state;
+
+ cpuid_regs = cpuid(CPUID_LEAF_PM);
+ turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
+
+ msr = msr_read(MSR_IA32_MISC_ENABLES);
+ turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
+
+ if (!turbo_cap && turbo_en) {
+ /* Unavailable */
+ turbo_state = TURBO_UNAVAILABLE;
+ } else if (!turbo_cap && !turbo_en) {
+ /* Available but disabled */
+ turbo_state = TURBO_DISABLED;
+ } else if (turbo_cap && turbo_en) {
+ /* Available */
+ turbo_state = TURBO_ENABLED;
+ }
+
+ set_global_turbo_state(turbo_state);
+ debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
+ return turbo_state;
+}
+
+void turbo_enable(void)
+{
+ msr_t msr;
+
+ /* Only possible if turbo is available but hidden */
+ if (turbo_get_state() == TURBO_DISABLED) {
+ /* Clear Turbo Disable bit in Misc Enables */
+ msr = msr_read(MSR_IA32_MISC_ENABLES);
+ msr.hi &= ~H_MISC_DISABLE_TURBO;
+ msr_write(MSR_IA32_MISC_ENABLES, msr);
+
+ /* Update cached turbo state */
+ set_global_turbo_state(TURBO_ENABLED);
+ debug("Turbo has been enabled\n");
+ }
+}