aboutsummaryrefslogtreecommitdiff
path: root/src/soc/intel/xeon_sp/cpx/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/xeon_sp/cpx/cpu.c')
-rw-r--r--src/soc/intel/xeon_sp/cpx/cpu.c96
1 files changed, 94 insertions, 2 deletions
diff --git a/src/soc/intel/xeon_sp/cpx/cpu.c b/src/soc/intel/xeon_sp/cpx/cpu.c
index 1c33218d76..e2724cef90 100644
--- a/src/soc/intel/xeon_sp/cpx/cpu.c
+++ b/src/soc/intel/xeon_sp/cpx/cpu.c
@@ -2,18 +2,49 @@
#include <acpi/acpigen.h>
#include <acpi/acpi.h>
+#include <assert.h>
#include <console/console.h>
#include <cpu/cpu.h>
#include <cpu/intel/microcode.h>
+#include <cpu/intel/turbo.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/mtrr.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/mp_init.h>
#include <soc/cpu.h>
+#include <soc/msr.h>
+#include <soc/soc_util.h>
+#include "chip.h"
static const void *microcode_patch;
+static const config_t *chip_config = NULL;
+
+static void xeon_configure_mca(void)
+{
+ msr_t msr;
+ struct cpuid_result cpuid_regs;
+
+ /*
+ * Check feature flag in CPUID.(EAX=1):EDX[7]==1 MCE
+ * and CPUID.(EAX=1):EDX[14]==1 MCA
+ */
+ cpuid_regs = cpuid(1);
+ if ((cpuid_regs.edx & (1 << 7 | 1 << 14)) != (1 << 7 | 1 << 14))
+ return;
+
+ msr = rdmsr(IA32_MCG_CAP);
+ if (msr.lo & IA32_MCG_CAP_CTL_P_MASK) {
+ /* Enable all error logging */
+ msr.lo = msr.hi = 0xffffffff;
+ wrmsr(IA32_MCG_CTL, msr);
+ }
+
+ mca_configure();
+}
+
+
void get_microcode_info(const void **microcode, int *parallel)
{
*microcode = intel_mp_current_microcode();
@@ -27,10 +58,28 @@ const void *intel_mp_current_microcode(void)
static void each_cpu_init(struct device *cpu)
{
+ msr_t msr;
+
printk(BIOS_SPEW, "%s dev: %s, cpu: %d, apic_id: 0x%x\n",
__func__, dev_path(cpu), cpu_index(), cpu->path.apic.apic_id);
-
setup_lapic();
+
+ /* Enable Fast Strings */
+ msr = rdmsr(IA32_MISC_ENABLE);
+ msr.lo |= FAST_STRINGS_ENABLE_BIT;
+ wrmsr(IA32_MISC_ENABLE, msr);
+ /* Enable Turbo */
+ enable_turbo();
+
+ /* Enable speed step. */
+ if (get_turbo_state() == TURBO_ENABLED) {
+ msr = rdmsr(IA32_MISC_ENABLE);
+ msr.lo |= SPEED_STEP_ENABLE_BIT;
+ wrmsr(IA32_MISC_ENABLE, msr);
+ }
+
+ /* Clear out pending MCEs */
+ xeon_configure_mca();
}
static struct device_operations cpu_dev_ops = {
@@ -47,6 +96,33 @@ static const struct cpu_driver driver __cpu_driver = {
.id_table = cpu_table,
};
+static void set_max_turbo_freq(void)
+{
+ msr_t msr, perf_ctl;
+
+ FUNC_ENTER();
+ perf_ctl.hi = 0;
+
+ /* Check for configurable TDP option */
+ if (get_turbo_state() == TURBO_ENABLED) {
+ msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else if (cpu_config_tdp_levels()) {
+ /* Set to nominal TDP ratio */
+ msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else {
+ /* Platform Info bits 15:8 give max ratio */
+ msr = rdmsr(MSR_PLATFORM_INFO);
+ perf_ctl.lo = msr.lo & 0xff00;
+ }
+ wrmsr(IA32_PERF_CTL, perf_ctl);
+
+ printk(BIOS_DEBUG, "cpu: frequency set to %d\n",
+ ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
+ FUNC_EXIT();
+}
+
/*
* Do essential initialization tasks before APs can be fired up
*/
@@ -72,10 +148,17 @@ static int get_thread_count(void)
return num_virts * CONFIG_MAX_SOCKET;
}
+static void post_mp_init(void)
+{
+ /* Set Max Ratio */
+ set_max_turbo_freq();
+}
+
static const struct mp_ops mp_ops = {
.pre_mp_init = pre_mp_init,
.get_cpu_count = get_thread_count,
- .get_microcode_info = get_microcode_info
+ .get_microcode_info = get_microcode_info,
+ .post_mp_init = post_mp_init,
};
void cpx_init_cpus(struct device *dev)
@@ -89,4 +172,13 @@ void cpx_init_cpus(struct device *dev)
if (mp_init_with_smm(dev->link_list, &mp_ops) < 0)
printk(BIOS_ERR, "MP initialization failure.\n");
+
+ /*
+ * chip_config is used in cpu device callback. Other than cpu 0,
+ * rest of the CPU devices do not have chip_info updated.
+ */
+ chip_config = dev->chip_info;
+
+ /* update numa domain for all cpu devices */
+ xeonsp_init_cpu_config();
}