nb/sb/cpu: Drop Intel Rangeley support

Relocatable ramstage, postcar stage and C_ENVIRONMENT_BOOTBLOCK are
now mandatory features, which this platform lacks.

Change-Id: I41589118579988617677cf48af5401bc35b23e05
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36980
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
This commit is contained in:
Arthur Heymans
2019-11-19 18:37:28 +01:00
committed by Kyösti Mälkki
parent 298619f6d9
commit c2c634a089
68 changed files with 2 additions and 9280 deletions

View File

@@ -13,7 +13,6 @@ subdirs-$(CONFIG_CPU_INTEL_SOCKET_MPGA604) += socket_mPGA604
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_NEHALEM) += model_2065x
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += model_206ax
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_RANGELEY) += fsp_model_406dx
subdirs-$(CONFIG_CPU_INTEL_SLOT_1) += slot_1
subdirs-$(CONFIG_CPU_INTEL_SOCKET_LGA775) += socket_LGA775

View File

@@ -1,63 +0,0 @@
##
## This file is part of the coreboot project.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; version 2 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
config CPU_INTEL_FSP_MODEL_406DX
bool
if CPU_INTEL_FSP_MODEL_406DX
config CPU_SPECIFIC_OPTIONS
def_bool y
select PLATFORM_USES_FSP1_0
select ARCH_BOOTBLOCK_X86_32
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select MMX
select SSE2
select UDELAY_TSC
select SUPPORT_CPU_UCODE_IN_CBFS
select MICROCODE_BLOB_NOT_IN_BLOB_REPO
select PARALLEL_CPU_INIT
select TSC_SYNC_MFENCE
select TSC_MONOTONIC_TIMER
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select NO_SMM
# Microcode header files are delivered in FSP package
select USES_MICROCODE_HEADER_FILES if HAVE_FSP_BIN
choice
prompt "Rangeley CPU Stepping"
default FSP_MODEL_406DX_B0
config FSP_MODEL_406DX_A1
bool "A1"
config FSP_MODEL_406DX_B0
bool "B0"
endchoice
config BOOTBLOCK_CPU_INIT
string
default "cpu/intel/fsp_model_406dx/bootblock.c"
#set up microcode for rangeley POSTGOLD4 release
config CPU_MICROCODE_HEADER_FILES
string
default "../intel/cpu/rangeley/microcode/microcode-m01406d000e.h ../intel/cpu/rangeley/microcode/microcode-m01406d8128.h"
endif #CPU_INTEL_FSP_MODEL_406DX

View File

@@ -1,27 +0,0 @@
#
# This file is part of the coreboot project.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
ramstage-y += model_406dx_init.c
subdirs-y += ../../x86/name
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/smm
subdirs-y += ../microcode
subdirs-y += ../turbo
ramstage-y += acpi.c
CPPFLAGS_romstage += -I$(src)/cpu/intel/fsp_model_406dx

View File

@@ -1,321 +0,0 @@
/*
* This file is part of the coreboot project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <types.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <arch/cpu.h>
#include <cpu/x86/msr.h>
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
#include <delay.h>
#include <device/device.h>
#include <device/pci.h>
#include "model_406dx.h"
#include "chip.h"
static int get_cores_per_package(void)
{
struct cpuinfo_x86 c;
struct cpuid_result result;
int cores = 1;
get_fms(&c, cpuid_eax(1));
if (c.x86 != 6)
return 1;
result = cpuid_ext(0xb, 1);
cores = result.ebx & 0xff;
return cores;
}
static void generate_C_state_entries(void)
{
struct cpu_info *info;
struct cpu_driver *cpu;
struct device *lapic;
struct cpu_intel_model_406dx_config *conf = NULL;
/* Find the SpeedStep CPU in the device tree using magic APIC ID */
lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
if (!lapic)
return;
conf = lapic->chip_info;
if (!conf)
return;
/* Find CPU map of supported C-states */
info = cpu_info();
if (!info)
return;
cpu = find_cpu_driver(info->cpu);
if (!cpu || !cpu->cstates)
return;
acpigen_emit_byte(0x14); /* MethodOp */
acpigen_write_len_f(); /* PkgLength */
acpigen_emit_namestring("_CST");
acpigen_emit_byte(0x00); /* No Arguments */
/* If running on AC power */
acpigen_emit_byte(0xa0); /* IfOp */
acpigen_write_len_f(); /* PkgLength */
acpigen_emit_namestring("PWRS");
acpigen_emit_byte(0xa4); /* ReturnOp */
acpigen_pop_len();
/* Else on battery power */
acpigen_emit_byte(0xa4); /* ReturnOp */
acpigen_pop_len();
}
static acpi_tstate_t tss_table_fine[] = {
{ 100, 1000, 0, 0x00, 0 },
{ 94, 940, 0, 0x1f, 0 },
{ 88, 880, 0, 0x1e, 0 },
{ 82, 820, 0, 0x1d, 0 },
{ 75, 760, 0, 0x1c, 0 },
{ 69, 700, 0, 0x1b, 0 },
{ 63, 640, 0, 0x1a, 0 },
{ 57, 580, 0, 0x19, 0 },
{ 50, 520, 0, 0x18, 0 },
{ 44, 460, 0, 0x17, 0 },
{ 38, 400, 0, 0x16, 0 },
{ 32, 340, 0, 0x15, 0 },
{ 25, 280, 0, 0x14, 0 },
{ 19, 220, 0, 0x13, 0 },
{ 13, 160, 0, 0x12, 0 },
};
static acpi_tstate_t tss_table_coarse[] = {
{ 100, 1000, 0, 0x00, 0 },
{ 88, 875, 0, 0x1f, 0 },
{ 75, 750, 0, 0x1e, 0 },
{ 63, 625, 0, 0x1d, 0 },
{ 50, 500, 0, 0x1c, 0 },
{ 38, 375, 0, 0x1b, 0 },
{ 25, 250, 0, 0x1a, 0 },
{ 13, 125, 0, 0x19, 0 },
};
static void generate_T_state_entries(int core, int cores_per_package)
{
/* Indicate SW_ALL coordination for T-states */
acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
/* Indicate FFixedHW so OS will use MSR */
acpigen_write_empty_PTC();
/* Set a T-state limit that can be modified in NVS */
acpigen_write_TPC("\\TLVL");
/*
* CPUID.(EAX=6):EAX[5] indicates support
* for extended throttle levels.
*/
if (cpuid_eax(6) & (1 << 5))
acpigen_write_TSS_package(
ARRAY_SIZE(tss_table_fine), tss_table_fine);
else
acpigen_write_TSS_package(
ARRAY_SIZE(tss_table_coarse), tss_table_coarse);
}
static int calculate_power(int tdp, int p1_ratio, int ratio)
{
u32 m;
u32 power;
/*
* M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
*
* Power = (ratio / p1_ratio) * m * tdp
*/
m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
m = (m * m) / 1000;
power = ((ratio * 100000 / p1_ratio) / 100);
power *= (m / 100) * (tdp / 1000);
power /= 1000;
return (int)power;
}
static int get_core_frequency_mhz(int ratio)
{
int fsb, core_freq;
/* Get BCLK - different SKUs can have different BCLK */
fsb = get_timer_fsb();
printk(BIOS_DEBUG, "BCLK:%d MHz ratio:%d\n", fsb, ratio);
core_freq = DIV_ROUND_CLOSEST(fsb * ratio, 100) * 100;
printk(BIOS_DEBUG, "core frequency for ratio(%d) %dMHz\n", ratio, core_freq);
return core_freq;
}
static void generate_P_state_entries(int core, int cores_per_package)
{
int ratio_min, ratio_max, ratio_turbo, ratio_step;
int coord_type, power_max, num_entries;
int ratio, power, clock, clock_max;
msr_t msr;
/* Rangeley uses hardware only control */
coord_type = HW_ALL;
/* Get bus ratio limits and calculate clock speeds */
msr = rdmsr(MSR_PLATFORM_INFO);
ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */
/* Determine if this CPU has configurable TDP */
if (cpu_config_tdp_levels()) {
/* Set max ratio to nominal TDP ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
ratio_max = msr.lo & 0xff;
} else {
/* Max Non-Turbo Ratio */
ratio_max = (msr.lo >> 8) & 0xff;
}
clock_max = get_core_frequency_mhz(ratio_max);
/* Calculate CPU TDP in mW */
msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
power_max = 2 << ((msr.lo & 0xf) - 1);
/* Write _PCT indicating use of FFixedHW */
acpigen_write_empty_PCT();
/* Write _PPC with no limit on supported P-state */
acpigen_write_PPC_NVS();
/* Write PSD indicating configured coordination type */
acpigen_write_PSD_package(core, cores_per_package, coord_type);
/* Add P-state entries in _PSS table */
acpigen_write_name("_PSS");
/* Determine ratio points */
ratio_step = PSS_RATIO_STEP;
num_entries = (ratio_max - ratio_min) / ratio_step;
while (num_entries > PSS_MAX_ENTRIES-1) {
ratio_step <<= 1;
num_entries >>= 1;
}
/* P[T] is Turbo state if enabled */
if (get_turbo_state() == TURBO_ENABLED) {
/* _PSS package count including Turbo */
acpigen_write_package(num_entries + 2);
msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
ratio_turbo = msr.lo & 0xff;
/* Add entry for Turbo ratio */
acpigen_write_PSS_package(
clock_max + 1, /*MHz*/
power_max, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio_turbo << 8, /*control*/
ratio_turbo << 8); /*status*/
} else {
/* _PSS package count without Turbo */
acpigen_write_package(num_entries + 1);
}
/* First regular entry is max non-turbo ratio */
acpigen_write_PSS_package(
clock_max, /*MHz*/
power_max, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio_max << 8, /*control*/
ratio_max << 8); /*status*/
/* Generate the remaining entries */
for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
ratio >= ratio_min; ratio -= ratio_step) {
/* Calculate power at this ratio */
power = calculate_power(power_max, ratio_max, ratio);
clock = get_core_frequency_mhz(ratio);
acpigen_write_PSS_package(
clock, /*MHz*/
power, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio << 8, /*control*/
ratio << 8); /*status*/
}
/* Fix package length */
acpigen_pop_len();
}
void generate_cpu_entries(struct device *device)
{
int coreID, cpuID, pcontrol_blk = PMB0_BASE, plen = 6;
int totalcores = dev_count_cpu();
int cores_per_package = get_cores_per_package();
int numcpus = totalcores/cores_per_package;
printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n",
numcpus, cores_per_package);
for (cpuID = 1; cpuID <= numcpus; cpuID++) {
for (coreID = 1; coreID <= cores_per_package; coreID++) {
if (coreID > 1) {
pcontrol_blk = 0;
plen = 0;
}
/* Generate processor \_PR.CPUx */
acpigen_write_processor(
(cpuID-1)*cores_per_package+coreID-1,
pcontrol_blk, plen);
/* Generate P-state tables */
generate_P_state_entries(
cpuID-1, cores_per_package);
/* Generate C-state tables */
generate_C_state_entries();
/* Generate T-state tables */
generate_T_state_entries(
cpuID-1, cores_per_package);
acpigen_pop_len();
}
}
/* PPKG is usually used for thermal management
of the first and only package. */
acpigen_write_processor_package("PPKG", 0, cores_per_package);
/* Add a method to notify processor nodes */
acpigen_write_processor_cnot(cores_per_package);
}
struct chip_operations cpu_intel_model_406dx_ops = {
CHIP_NAME("Intel Rangeley CPU")
};

View File

@@ -1,89 +0,0 @@
/*
* This file is part of the coreboot project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdint.h>
#include <cpu/x86/cache.h>
#include <cpu/intel/microcode/microcode.c>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <arch/io.h>
#include <device/pci_ops.h>
#include <southbridge/intel/fsp_rangeley/soc.h>
#include "model_406dx.h"
/*
* check for a warm reset and do a hard reset instead.
*/
static void check_for_warm_reset(void)
{
/*
* Check if INIT# is asserted by port 0xCF9 and whether RCBA has been
* set. If either is true, then this is a warm reset so execute a
* Hard Reset
*/
if ((inb(0xcf9) == 0x04) ||
(pci_io_read_config32(SOC_LPC_DEV, RCBA)
& RCBA_ENABLE)) {
outb(0x00, 0xcf9);
outb(0x06, 0xcf9);
}
}
static void set_var_mtrr(int reg, uint32_t base, uint32_t size, int type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
msr_t basem, maskm;
basem.lo = base | type;
basem.hi = 0;
wrmsr(MTRR_PHYS_BASE(reg), basem);
maskm.lo = ~(size - 1) | MTRR_PHYS_MASK_VALID;
maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
wrmsr(MTRR_PHYS_MASK(reg), maskm);
}
static void enable_rom_caching(void)
{
msr_t msr;
disable_cache();
set_var_mtrr(1, CACHE_ROM_BASE, CACHE_ROM_SIZE, MTRR_TYPE_WRPROT);
enable_cache();
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
wrmsr(MTRR_DEF_TYPE_MSR, msr);
}
static void set_no_evict_mode_msr(void)
{
msr_t msr;
msr.hi = 0x00000000;
msr.lo = 0x00000000;
wrmsr(MSR_NO_EVICT_MODE, msr);
}
static void bootblock_cpu_init(void)
{
/* Check for Warm Reset */
check_for_warm_reset();
/* Load microcode before any caching. */
intel_update_microcode_from_cbfs();
enable_rom_caching();
set_no_evict_mode_msr();
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of the coreboot project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef CPU_FSP_MODEL406DX_CHIP_H
#define CPU_FSP_MODEL406DX_CHIP_H
/* Magic value used to locate this chip in the device tree */
#define SPEEDSTEP_APIC_MAGIC 0xACAC
struct cpu_intel_fsp_model_406dx_config {
int c1_battery; /* ACPI C1 on Battery Power */
int c2_battery; /* ACPI C2 on Battery Power */
int c3_battery; /* ACPI C3 on Battery Power */
int c1_acpower; /* ACPI C1 on AC Power */
int c2_acpower; /* ACPI C2 on AC Power */
int c3_acpower; /* ACPI C3 on AC Power */
};
#endif /* CPU_FSP_MODEL406DX_CHIP_H */

View File

@@ -1,87 +0,0 @@
/*
* This file is part of the coreboot project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _CPU_INTEL_MODEL_406DX_H
#define _CPU_INTEL_MODEL_406DX_H
#define MSR_FEATURE_CONFIG 0x13c
#define MSR_FLEX_RATIO 0x194
#define FLEX_RATIO_LOCK (1 << 20)
#define FLEX_RATIO_EN (1 << 16)
#define MSR_TEMPERATURE_TARGET 0x1a2
#define MSR_LT_LOCK_MEMORY 0x2e7
#define MSR_NO_EVICT_MODE 0x2e0
#define MSR_PIC_MSG_CONTROL 0x2e
#define MSR_PLATFORM_INFO 0xce
#define PLATFORM_INFO_SET_TDP (1 << 29)
#define MSR_PKG_CST_CONFIG_CONTROL 0xe2
#define MSR_PMG_IO_CAPTURE_BASE 0xe4
#define MSR_MISC_PWR_MGMT 0x1aa
#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0)
#define MSR_TURBO_RATIO_LIMIT 0x1ad
#define MSR_POWER_CTL 0x1fc
#define MSR_PKGC3_IRTL 0x60a
#define MSR_PKGC6_IRTL 0x60b
#define MSR_PKGC7_IRTL 0x60c
#define IRTL_VALID (1 << 15)
#define IRTL_1_NS (0 << 10)
#define IRTL_32_NS (1 << 10)
#define IRTL_1024_NS (2 << 10)
#define IRTL_32768_NS (3 << 10)
#define IRTL_1048576_NS (4 << 10)
#define IRTL_33554432_NS (5 << 10)
#define IRTL_RESPONSE_MASK (0x3ff)
/* long duration in low dword, short duration in high dword */
#define MSR_PKG_POWER_LIMIT 0x610
#define PKG_POWER_LIMIT_MASK 0x7fff
#define PKG_POWER_LIMIT_EN (1 << 15)
#define PKG_POWER_LIMIT_CLAMP (1 << 16)
#define PKG_POWER_LIMIT_TIME_SHIFT 17
#define PKG_POWER_LIMIT_TIME_MASK 0x7f
#define MSR_PP0_CURRENT_CONFIG 0x601
#define PP0_CURRENT_LIMIT (112 << 3) /* 112 A */
#define MSR_PP1_CURRENT_CONFIG 0x602
#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */
#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */
#define MSR_PKG_POWER_SKU_UNIT 0x606
#define MSR_PKG_POWER_SKU 0x614
#define MSR_PP0_POWER_LIMIT 0x638
#define MSR_PP1_POWER_LIMIT 0x640
#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
#define MSR_CONFIG_TDP_NOMINAL 0x648
#define MSR_CONFIG_TDP_LEVEL1 0x649
#define MSR_CONFIG_TDP_LEVEL2 0x64a
#define MSR_CONFIG_TDP_CONTROL 0x64b
#define MSR_TURBO_ACTIVATION_RATIO 0x64c
/* P-state configuration */
#define PSS_MAX_ENTRIES 8
#define PSS_RATIO_STEP 2
#define PSS_LATENCY_TRANSITION 10
#define PSS_LATENCY_BUSMASTER 10
#ifndef __ROMCC__
/* Lock MSRs */
void intel_model_406dx_finalize_smm(void);
int cpu_config_tdp_levels(void);
#endif
#endif /* _CPU_INTEL_MODEL_406DX_H */

View File

@@ -1,169 +0,0 @@
/*
* This file is part of the coreboot project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <console/console.h>
#include <device/pci.h>
#include <cpu/cpu.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/lapic.h>
#include <cpu/intel/microcode.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include <cpu/intel/common/common.h>
#include "model_406dx.h"
#include "chip.h"
int cpu_config_tdp_levels(void)
{
msr_t platform_info;
/* Minimum CPU revision */
if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
return 0;
/* Bits 34:33 indicate how many levels supported */
platform_info = rdmsr(MSR_PLATFORM_INFO);
return (platform_info.hi >> 1) & 3;
}
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 configure_mca(void)
{
msr_t msr;
int i;
msr.lo = msr.hi = 0;
/* This should only be done on a cold boot */
for (i = 0; i < 6; i++)
wrmsr(IA32_MC0_STATUS + (i * 4), msr);
}
/*
* Initialize any extra cores/threads in this package.
*/
static void intel_cores_init(struct device *cpu)
{
struct cpuid_result result;
unsigned int threads_per_package, threads_per_core, i;
/* Logical processors (threads) per core */
result = cpuid_ext(0xb, 0);
threads_per_core = result.ebx & 0xffff;
/* Logical processors (threads) per package */
result = cpuid_ext(0xb, 1);
threads_per_package = result.ebx & 0xffff;
/* Only initialize extra cores from BSP */
if (cpu->path.apic.apic_id)
return;
printk(BIOS_DEBUG, "CPU: %u has %u cores, %u threads per core\n",
cpu->path.apic.apic_id, threads_per_package/threads_per_core,
threads_per_core);
for (i = 1; i < threads_per_package; ++i) {
struct device_path cpu_path;
struct device *new;
/* Build the CPU device path */
cpu_path.type = DEVICE_PATH_APIC;
cpu_path.apic.apic_id =
cpu->path.apic.apic_id + i;
/* Update APIC ID if no hyperthreading */
if (threads_per_core == 1)
cpu_path.apic.apic_id <<= 1;
/* Allocate the new CPU device structure */
new = alloc_dev(cpu->bus, &cpu_path);
if (!new)
continue;
printk(BIOS_DEBUG, "CPU: %u has core %u\n",
cpu->path.apic.apic_id,
new->path.apic.apic_id);
/* Start the new CPU */
if (is_smp_boot() && !start_cpu(new)) {
/* Record the error in cpu? */
printk(BIOS_ERR, "CPU %u would not start!\n",
new->path.apic.apic_id);
}
}
}
static void model_406dx_init(struct device *cpu)
{
char processor_name[49];
/* Turn on caching if we haven't already */
x86_enable_cache();
/* Load microcode */
if (CONFIG(SUPPORT_CPU_UCODE_IN_CBFS))
intel_update_microcode_from_cbfs();
/* Clear out pending MCEs */
configure_mca();
/* Print processor name */
fill_processor_name(processor_name);
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
x86_mtrr_check();
/* Enable the local CPU APICs */
setup_lapic();
/* Set virtualization based on Kconfig option */
set_vmx_and_lock();
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
/* Start up extra cores */
intel_cores_init(cpu);
}
static struct device_operations cpu_dev_ops = {
.init = model_406dx_init,
};
static const struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x406d0 }, /* Intel Avoton/Rangeley A1 */
{ X86_VENDOR_INTEL, 0x406d8 }, /* Intel Avoton/Rangeley B0 */
{ 0, 0 },
};
static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
};