blob: cb748543468362e05e98a197f6fd6c86ce1bccda [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <console/console.h>
#include <device/device.h>
#include <cpu/cpu.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/intel/microcode.h>
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include "model_2065x.h"
#include "chip.h"
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/common/common.h>
#include <smp/node.h>
#include <types.h>
static void configure_thermal_target(struct device *dev)
{
struct cpu_intel_model_2065x_config *conf = dev->upstream->dev->chip_info;
msr_t msr;
/* Set TCC activation offset if supported */
msr = rdmsr(MSR_PLATFORM_INFO);
if ((msr.lo & (1 << 30)) && conf->tcc_offset) {
msr = rdmsr(MSR_TEMPERATURE_TARGET);
msr.lo &= ~(0xf << 24); /* Bits 27:24 */
msr.lo |= (conf->tcc_offset & 0xf) << 24;
wrmsr(MSR_TEMPERATURE_TARGET, msr);
}
}
static void configure_misc(void)
{
msr_t msr;
msr = rdmsr(IA32_MISC_ENABLE);
msr.lo |= (1 << 0); /* Fast String enable */
msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
wrmsr(IA32_MISC_ENABLE, msr);
/* Disable Thermal interrupts */
msr.lo = 0;
msr.hi = 0;
wrmsr(IA32_THERM_INTERRUPT, msr);
}
static void set_max_ratio(void)
{
msr_t msr, perf_ctl;
perf_ctl.hi = 0;
/* 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, "model_x065x: frequency set to %d\n",
((perf_ctl.lo >> 8) & 0xff) * IRONLAKE_BCLK);
}
static void model_2065x_init(struct device *cpu)
{
char processor_name[49];
/* Clear out pending MCEs */
/* This should only be done on a cold boot */
mca_clear_status();
/* Print processor name */
fill_processor_name(processor_name);
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
printk(BIOS_INFO, "CPU:lapic=%d, boot_cpu=%d\n", lapicid(),
boot_cpu());
/* Setup Page Attribute Tables (PAT) */
// TODO set up PAT
enable_lapic_tpr();
/* Set virtualization based on Kconfig option */
set_vmx_and_lock();
set_aesni_lock();
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
/* Thermal throttle activation offset */
configure_thermal_target(cpu);
/* Set Max Ratio */
set_max_ratio();
/* Enable Turbo */
enable_turbo();
}
/* MP initialization support. */
static void pre_mp_init(void)
{
/* Setup MTRRs based on physical address size. */
x86_setup_mtrrs_with_detect();
x86_mtrr_check();
}
static int get_cpu_count(void)
{
msr_t msr;
unsigned int num_threads;
unsigned int num_cores;
msr = rdmsr(MSR_CORE_THREAD_COUNT);
num_threads = (msr.lo >> 0) & 0xffff;
num_cores = (msr.lo >> 16) & 0xffff;
printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n",
num_cores, num_threads);
return num_threads;
}
static void get_microcode_info(const void **microcode, int *parallel)
{
*microcode = intel_microcode_find();
*parallel = !intel_ht_supported();
}
static void per_cpu_smm_trigger(void)
{
/* Relocate the SMM handler. */
smm_relocate();
/* After SMM relocation a 2nd microcode load is required. */
const void *microcode_patch = intel_microcode_find();
intel_microcode_load_unlocked(microcode_patch);
}
static void post_mp_init(void)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
global_smi_enable();
/* Lock down the SMRAM space. */
smm_lock();
}
static const struct mp_ops mp_ops = {
.pre_mp_init = pre_mp_init,
.get_cpu_count = get_cpu_count,
.get_smm_info = smm_info,
.get_microcode_info = get_microcode_info,
.pre_mp_smm_init = smm_initialize,
.per_cpu_smm_trigger = per_cpu_smm_trigger,
.relocation_handler = smm_relocation_handler,
.post_mp_init = post_mp_init,
};
void mp_init_cpus(struct bus *cpu_bus)
{
/* TODO: Handle mp_init_with_smm failure? */
mp_init_with_smm(cpu_bus, &mp_ops);
}
static struct device_operations cpu_dev_ops = {
.init = model_2065x_init,
};
/* Arrandale / Clarkdale CPU IDs */
static const struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x20650, CPUID_EXACT_MATCH_MASK },
{ X86_VENDOR_INTEL, 0x20651, CPUID_EXACT_MATCH_MASK },
{ X86_VENDOR_INTEL, 0x20652, CPUID_EXACT_MATCH_MASK },
{ X86_VENDOR_INTEL, 0x20654, CPUID_EXACT_MATCH_MASK },
{ X86_VENDOR_INTEL, 0x20655, CPUID_EXACT_MATCH_MASK },
CPU_TABLE_END
};
static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
};