Home | History | Annotate | Download | only in cpu
      1 // SPDX-License-Identifier: GPL-2.0
      2 /*
      3  * From Coreboot file of the same name
      4  *
      5  * Copyright (C) 2011 The Chromium Authors.
      6  */
      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 
     14 DECLARE_GLOBAL_DATA_PTR;
     15 
     16 #ifdef CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
     17 static inline int get_global_turbo_state(void)
     18 {
     19 	return TURBO_UNKNOWN;
     20 }
     21 
     22 static inline void set_global_turbo_state(int state)
     23 {
     24 }
     25 #else
     26 static inline int get_global_turbo_state(void)
     27 {
     28 	return gd->arch.turbo_state;
     29 }
     30 
     31 static inline void set_global_turbo_state(int state)
     32 {
     33 	gd->arch.turbo_state = state;
     34 }
     35 #endif
     36 
     37 static 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  */
     49 int 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 
     82 void 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 }
     98