cpu/intel: Add fsp version of model 406dx (Rangeley / Atom C2000)
This adds the CPU initialization pieces for Intel's Atom C2000 processor (Formerly Rangeley). Change-Id: I77d69f42c959bbc294784f044b7b0dcc2e30f30c Signed-off-by: Martin Roth <gaumless@gmail.com> Reviewed-on: http://review.coreboot.org/6368 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
This commit is contained in:
parent
ddf54b1c8b
commit
09670265b6
|
@ -11,6 +11,7 @@ source src/cpu/intel/model_1067x/Kconfig
|
||||||
source src/cpu/intel/model_106cx/Kconfig
|
source src/cpu/intel/model_106cx/Kconfig
|
||||||
source src/cpu/intel/model_206ax/Kconfig
|
source src/cpu/intel/model_206ax/Kconfig
|
||||||
source src/cpu/intel/fsp_model_206ax/Kconfig
|
source src/cpu/intel/fsp_model_206ax/Kconfig
|
||||||
|
source src/cpu/intel/fsp_model_406dx/Kconfig
|
||||||
source src/cpu/intel/model_2065x/Kconfig
|
source src/cpu/intel/model_2065x/Kconfig
|
||||||
source src/cpu/intel/model_f0x/Kconfig
|
source src/cpu/intel/model_f0x/Kconfig
|
||||||
source src/cpu/intel/model_f1x/Kconfig
|
source src/cpu/intel/model_f1x/Kconfig
|
||||||
|
|
|
@ -23,6 +23,7 @@ subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE_NATIVE) += model_206ax
|
||||||
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell
|
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell
|
||||||
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_SANDYBRIDGE) += fsp_model_206ax
|
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_SANDYBRIDGE) += fsp_model_206ax
|
||||||
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_IVYBRIDGE) += fsp_model_206ax
|
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_IVYBRIDGE) += fsp_model_206ax
|
||||||
|
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_RANGELEY) += fsp_model_406dx
|
||||||
subdirs-$(CONFIG_CPU_INTEL_SLOT_2) += slot_2
|
subdirs-$(CONFIG_CPU_INTEL_SLOT_2) += slot_2
|
||||||
subdirs-$(CONFIG_CPU_INTEL_SLOT_1) += slot_1
|
subdirs-$(CONFIG_CPU_INTEL_SLOT_1) += slot_1
|
||||||
subdirs-$(CONFIG_CPU_INTEL_SOCKET_LGA771) += socket_LGA771
|
subdirs-$(CONFIG_CPU_INTEL_SOCKET_LGA771) += socket_LGA771
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
##
|
||||||
|
## This file is part of the coreboot project.
|
||||||
|
##
|
||||||
|
## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
|
||||||
|
##
|
||||||
|
## 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.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License
|
||||||
|
## along with this program; if not, write to the Free Software
|
||||||
|
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
##
|
||||||
|
|
||||||
|
config CPU_INTEL_FSP_MODEL_406DX
|
||||||
|
bool
|
||||||
|
|
||||||
|
if CPU_INTEL_FSP_MODEL_406DX
|
||||||
|
|
||||||
|
config CPU_SPECIFIC_OPTIONS
|
||||||
|
def_bool y
|
||||||
|
select PLATFORM_USES_FSP
|
||||||
|
select ARCH_BOOTBLOCK_X86_32
|
||||||
|
select ARCH_ROMSTAGE_X86_32
|
||||||
|
select ARCH_RAMSTAGE_X86_32
|
||||||
|
select SMP
|
||||||
|
select SSE2
|
||||||
|
select UDELAY_LAPIC
|
||||||
|
select SUPPORT_CPU_UCODE_IN_CBFS if HAVE_FSP_BIN
|
||||||
|
select PARALLEL_CPU_INIT
|
||||||
|
select TSC_SYNC_MFENCE
|
||||||
|
select LAPIC_MONOTONIC_TIMER
|
||||||
|
select BROKEN_CAR_MIGRATE
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
config ENABLE_VMX
|
||||||
|
bool "Enable VMX for virtualization"
|
||||||
|
default n
|
||||||
|
|
||||||
|
config CPU_MICROCODE_CBFS_LOC
|
||||||
|
hex
|
||||||
|
depends on SUPPORT_CPU_UCODE_IN_CBFS
|
||||||
|
default 0xfff60040
|
||||||
|
|
||||||
|
config CPU_MICROCODE_CBFS_LEN
|
||||||
|
hex
|
||||||
|
depends on SUPPORT_CPU_UCODE_IN_CBFS
|
||||||
|
default 0x14400 if FSP_MODEL_406DX_A1
|
||||||
|
default 0x14800 if FSP_MODEL_406DX_B0
|
||||||
|
|
||||||
|
config MICROCODE_INCLUDE_PATH
|
||||||
|
string "Location of the intel microcode patches"
|
||||||
|
default "../intel/cpu/rangeley/microcode"
|
||||||
|
|
||||||
|
endif #CPU_INTEL_FSP_MODEL_406DX
|
|
@ -0,0 +1,31 @@
|
||||||
|
#
|
||||||
|
# This file is part of the coreboot project.
|
||||||
|
#
|
||||||
|
# Copyrignt (C) 2014 Sage Electronic Engineering, LLC.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
ramstage-y += model_406dx_init.c
|
||||||
|
subdirs-y += ../../x86/name
|
||||||
|
|
||||||
|
ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c
|
||||||
|
|
||||||
|
cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_MICROCODE_INCLUDE_PATH),)
|
||||||
|
ifneq ($(wildcard $(shell readlink -f "$(top)/$(CONFIG_MICROCODE_INCLUDE_PATH)")),)
|
||||||
|
CPPFLAGS_common += -I$(CONFIG_MICROCODE_INCLUDE_PATH)
|
||||||
|
endif
|
||||||
|
endif
|
|
@ -0,0 +1,320 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 coresystems GmbH
|
||||||
|
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
|
||||||
|
* Copyright (C) 2013 Sage Electronic Engineering, LLC.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.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 <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 int generate_C_state_entries(void)
|
||||||
|
{
|
||||||
|
struct cpu_info *info;
|
||||||
|
struct cpu_driver *cpu;
|
||||||
|
int len, lenif;
|
||||||
|
device_t 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 0;
|
||||||
|
conf = lapic->chip_info;
|
||||||
|
if (!conf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Find CPU map of supported C-states */
|
||||||
|
info = cpu_info();
|
||||||
|
if (!info)
|
||||||
|
return 0;
|
||||||
|
cpu = find_cpu_driver(info->cpu);
|
||||||
|
if (!cpu || !cpu->cstates)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = acpigen_emit_byte(0x14); /* MethodOp */
|
||||||
|
len += acpigen_write_len_f(); /* PkgLength */
|
||||||
|
len += acpigen_emit_namestring("_CST");
|
||||||
|
len += acpigen_emit_byte(0x00); /* No Arguments */
|
||||||
|
|
||||||
|
/* If running on AC power */
|
||||||
|
len += acpigen_emit_byte(0xa0); /* IfOp */
|
||||||
|
lenif = acpigen_write_len_f(); /* PkgLength */
|
||||||
|
lenif += acpigen_emit_namestring("PWRS");
|
||||||
|
lenif += acpigen_emit_byte(0xa4); /* ReturnOp */
|
||||||
|
acpigen_patch_len(lenif - 1);
|
||||||
|
len += lenif;
|
||||||
|
|
||||||
|
/* Else on battery power */
|
||||||
|
len += acpigen_emit_byte(0xa4); /* ReturnOp */
|
||||||
|
acpigen_patch_len(len - 1);
|
||||||
|
return 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 int generate_T_state_entries(int core, int cores_per_package)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Indicate SW_ALL coordination for T-states */
|
||||||
|
len = acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
|
||||||
|
|
||||||
|
/* Indicate FFixedHW so OS will use MSR */
|
||||||
|
len += acpigen_write_empty_PTC();
|
||||||
|
|
||||||
|
/* Set a T-state limit that can be modified in NVS */
|
||||||
|
len += acpigen_write_TPC("\\TLVL");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CPUID.(EAX=6):EAX[5] indicates support
|
||||||
|
* for extended throttle levels.
|
||||||
|
*/
|
||||||
|
if (cpuid_eax(6) & (1 << 5))
|
||||||
|
len += acpigen_write_TSS_package(
|
||||||
|
ARRAY_SIZE(tss_table_fine), tss_table_fine);
|
||||||
|
else
|
||||||
|
len += acpigen_write_TSS_package(
|
||||||
|
ARRAY_SIZE(tss_table_coarse), tss_table_coarse);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 generate_P_state_entries(int core, int cores_per_package)
|
||||||
|
{
|
||||||
|
int len, len_pss;
|
||||||
|
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 = ratio_max * RANGELEY_BCLK;
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
len = acpigen_write_empty_PCT();
|
||||||
|
|
||||||
|
/* Write _PPC with no limit on supported P-state */
|
||||||
|
len += acpigen_write_PPC_NVS();
|
||||||
|
|
||||||
|
/* Write PSD indicating configured coordination type */
|
||||||
|
len += acpigen_write_PSD_package(core, cores_per_package, coord_type);
|
||||||
|
|
||||||
|
/* Add P-state entries in _PSS table */
|
||||||
|
len += 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 */
|
||||||
|
len_pss = acpigen_write_package(num_entries + 2);
|
||||||
|
|
||||||
|
msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
|
||||||
|
ratio_turbo = msr.lo & 0xff;
|
||||||
|
|
||||||
|
/* Add entry for Turbo ratio */
|
||||||
|
len_pss += 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 */
|
||||||
|
len_pss = acpigen_write_package(num_entries + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First regular entry is max non-turbo ratio */
|
||||||
|
len_pss += 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 = ratio * RANGELEY_BCLK;
|
||||||
|
|
||||||
|
len_pss += 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 */
|
||||||
|
len_pss--;
|
||||||
|
acpigen_patch_len(len_pss);
|
||||||
|
|
||||||
|
return len + len_pss;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_cpu_entries(void)
|
||||||
|
{
|
||||||
|
int len_pr;
|
||||||
|
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 */
|
||||||
|
len_pr = acpigen_write_processor(
|
||||||
|
(cpuID-1)*cores_per_package+coreID-1,
|
||||||
|
pcontrol_blk, plen);
|
||||||
|
|
||||||
|
/* Generate P-state tables */
|
||||||
|
len_pr += generate_P_state_entries(
|
||||||
|
cpuID-1, cores_per_package);
|
||||||
|
|
||||||
|
/* Generate C-state tables */
|
||||||
|
len_pr += generate_C_state_entries();
|
||||||
|
|
||||||
|
/* Generate T-state tables */
|
||||||
|
len_pr += generate_T_state_entries(
|
||||||
|
cpuID-1, cores_per_package);
|
||||||
|
|
||||||
|
len_pr--;
|
||||||
|
acpigen_patch_len(len_pr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct chip_operations cpu_intel_model_406dx_ops = {
|
||||||
|
CHIP_NAME("Intel Rangeley CPU")
|
||||||
|
};
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* These devices are created at runtime */
|
||||||
|
External (\_PR.CPU0, DeviceObj)
|
||||||
|
External (\_PR.CPU1, DeviceObj)
|
||||||
|
External (\_PR.CPU2, DeviceObj)
|
||||||
|
External (\_PR.CPU3, DeviceObj)
|
||||||
|
External (\_PR.CPU4, DeviceObj)
|
||||||
|
External (\_PR.CPU5, DeviceObj)
|
||||||
|
External (\_PR.CPU6, DeviceObj)
|
||||||
|
External (\_PR.CPU7, DeviceObj)
|
||||||
|
|
||||||
|
/* Notify OS to re-read CPU tables, assuming ^2 CPU count */
|
||||||
|
Method (PNOT)
|
||||||
|
{
|
||||||
|
If (LGreaterEqual (\PCNT, 2)) {
|
||||||
|
Notify (\_PR.CPU0, 0x81) // _CST
|
||||||
|
Notify (\_PR.CPU1, 0x81) // _CST
|
||||||
|
}
|
||||||
|
If (LGreaterEqual (\PCNT, 4)) {
|
||||||
|
Notify (\_PR.CPU2, 0x81) // _CST
|
||||||
|
Notify (\_PR.CPU3, 0x81) // _CST
|
||||||
|
}
|
||||||
|
If (LGreaterEqual (\PCNT, 8)) {
|
||||||
|
Notify (\_PR.CPU4, 0x81) // _CST
|
||||||
|
Notify (\_PR.CPU5, 0x81) // _CST
|
||||||
|
Notify (\_PR.CPU6, 0x81) // _CST
|
||||||
|
Notify (\_PR.CPU7, 0x81) // _CST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */
|
||||||
|
Method (PPCN)
|
||||||
|
{
|
||||||
|
If (LGreaterEqual (\PCNT, 2)) {
|
||||||
|
Notify (\_PR.CPU0, 0x80) // _PPC
|
||||||
|
Notify (\_PR.CPU1, 0x80) // _PPC
|
||||||
|
}
|
||||||
|
If (LGreaterEqual (\PCNT, 4)) {
|
||||||
|
Notify (\_PR.CPU2, 0x80) // _PPC
|
||||||
|
Notify (\_PR.CPU3, 0x80) // _PPC
|
||||||
|
}
|
||||||
|
If (LGreaterEqual (\PCNT, 8)) {
|
||||||
|
Notify (\_PR.CPU4, 0x80) // _PPC
|
||||||
|
Notify (\_PR.CPU5, 0x80) // _PPC
|
||||||
|
Notify (\_PR.CPU6, 0x80) // _PPC
|
||||||
|
Notify (\_PR.CPU7, 0x80) // _PPC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */
|
||||||
|
Method (TNOT)
|
||||||
|
{
|
||||||
|
If (LGreaterEqual (\PCNT, 2)) {
|
||||||
|
Notify (\_PR.CPU0, 0x82) // _TPC
|
||||||
|
Notify (\_PR.CPU1, 0x82) // _TPC
|
||||||
|
}
|
||||||
|
If (LGreaterEqual (\PCNT, 4)) {
|
||||||
|
Notify (\_PR.CPU2, 0x82) // _TPC
|
||||||
|
Notify (\_PR.CPU3, 0x82) // _TPC
|
||||||
|
}
|
||||||
|
If (LGreaterEqual (\PCNT, 8)) {
|
||||||
|
Notify (\_PR.CPU4, 0x82) // _TPC
|
||||||
|
Notify (\_PR.CPU5, 0x82) // _TPC
|
||||||
|
Notify (\_PR.CPU6, 0x82) // _TPC
|
||||||
|
Notify (\_PR.CPU7, 0x82) // _TPC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a package containing enabled processor entries */
|
||||||
|
Method (PPKG)
|
||||||
|
{
|
||||||
|
If (LGreaterEqual (\PCNT, 8)) {
|
||||||
|
Return (Package() {\_PR.CPU0, \_PR.CPU1, \_PR.CPU2, \_PR.CPU3,
|
||||||
|
\_PR.CPU4, \_PR.CPU5, \_PR.CPU6, \_PR.CPU7})
|
||||||
|
} ElseIf (LGreaterEqual (\PCNT, 4)) {
|
||||||
|
Return (Package() {\_PR.CPU0, \_PR.CPU1, \_PR.CPU2, \_PR.CPU3})
|
||||||
|
} ElseIf (LGreaterEqual (\PCNT, 2)) {
|
||||||
|
Return (Package() {\_PR.CPU0, \_PR.CPU1})
|
||||||
|
} Else {
|
||||||
|
Return (Package() {\_PR.CPU0})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Google Inc.
|
||||||
|
* Copyright (C) 2013-2014 Sage Electronic Engineering LLC.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
#include <cpu/x86/cache.h>
|
||||||
|
#include <cpu/x86/msr.h>
|
||||||
|
#include <cpu/x86/mtrr.h>
|
||||||
|
#include <arch/io.h>
|
||||||
|
#include <reset.h>
|
||||||
|
#include <src/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)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_CPU_ADDR_BITS
|
||||||
|
#error "CONFIG_CPU_ADDR_BITS must be set."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
|
||||||
|
msr_t basem, maskm;
|
||||||
|
basem.lo = base | type;
|
||||||
|
basem.hi = 0;
|
||||||
|
wrmsr(MTRRphysBase_MSR(reg), basem);
|
||||||
|
maskm.lo = ~(size - 1) | MTRRphysMaskValid;
|
||||||
|
maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
|
||||||
|
wrmsr(MTRRphysMask_MSR(reg), maskm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enable_rom_caching(void)
|
||||||
|
{
|
||||||
|
msr_t msr;
|
||||||
|
|
||||||
|
disable_cache();
|
||||||
|
set_var_mtrr(1, 0xffffffff - CACHE_ROM_SIZE + 1,
|
||||||
|
CACHE_ROM_SIZE, MTRR_TYPE_WRPROT);
|
||||||
|
enable_cache();
|
||||||
|
|
||||||
|
/* Enable Variable MTRRs */
|
||||||
|
msr.hi = 0x00000000;
|
||||||
|
msr.lo = 0x00000800;
|
||||||
|
wrmsr(MTRRdefType_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();
|
||||||
|
enable_rom_caching();
|
||||||
|
set_no_evict_mode_msr();
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Magic value used to locate this chip in the device tree */
|
||||||
|
#define SPEEDSTEP_APIC_MAGIC 0xACAC
|
||||||
|
|
||||||
|
struct cpu_intel_fsp_model_406dx_config {
|
||||||
|
u8 pstate_coord_type; /* Processor Coordination Type */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.
|
||||||
|
* Copyright (C) 2014 Sage Electronic Engineering, LLC
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned microcode[] = {
|
||||||
|
#if IS_ENABLED(CONFIG_FSP_MODEL_406DX_A1)
|
||||||
|
/* Size is 0x14400 */
|
||||||
|
#include <microcode-m01406d000e.h>
|
||||||
|
#elif IS_ENABLED(CONFIG_FSP_MODEL_406DX_B0)
|
||||||
|
/* Size is 0x14800 */
|
||||||
|
#include <microcode-m01406d811d.h>
|
||||||
|
#endif
|
||||||
|
};
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
|
||||||
|
* Copyright (C) 2013 Sage Electronic Engineering, LLC.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CPU_INTEL_MODEL_406DX_H
|
||||||
|
#define _CPU_INTEL_MODEL_406DX_H
|
||||||
|
|
||||||
|
/* Rangeley bus clock is fixed at 100MHz */
|
||||||
|
#define RANGELEY_BCLK 100
|
||||||
|
|
||||||
|
#define IA32_FEATURE_CONTROL 0x3a
|
||||||
|
#define CPUID_VMX (1 << 5)
|
||||||
|
#define CPUID_SMX (1 << 6)
|
||||||
|
#define MSR_FEATURE_CONFIG 0x13c
|
||||||
|
#define MSR_FLEX_RATIO 0x194
|
||||||
|
#define FLEX_RATIO_LOCK (1 << 20)
|
||||||
|
#define FLEX_RATIO_EN (1 << 16)
|
||||||
|
#define IA32_PLATFORM_DCA_CAP 0x1f8
|
||||||
|
#define IA32_MISC_ENABLE 0x1a0
|
||||||
|
#define MSR_TEMPERATURE_TARGET 0x1a2
|
||||||
|
#define IA32_PERF_CTL 0x199
|
||||||
|
#define IA32_THERM_INTERRUPT 0x19b
|
||||||
|
#define IA32_ENERGY_PERFORMANCE_BIAS 0x1b0
|
||||||
|
#define ENERGY_POLICY_PERFORMANCE 0
|
||||||
|
#define ENERGY_POLICY_NORMAL 6
|
||||||
|
#define ENERGY_POLICY_POWERSAVE 15
|
||||||
|
#define IA32_PACKAGE_THERM_INTERRUPT 0x1b2
|
||||||
|
#define MSR_LT_LOCK_MEMORY 0x2e7
|
||||||
|
#define IA32_MC0_STATUS 0x401
|
||||||
|
|
||||||
|
#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_PMG_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__
|
||||||
|
#ifdef __SMM__
|
||||||
|
/* Lock MSRs */
|
||||||
|
void intel_model_406dx_finalize_smm(void);
|
||||||
|
#else
|
||||||
|
int cpu_config_tdp_levels(void);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2009 coresystems GmbH
|
||||||
|
* Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
|
||||||
|
* Copyright (C) 2014 Sage Electronic Engineering, LLC.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <device/device.h>
|
||||||
|
#include <device/pci.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arch/acpi.h>
|
||||||
|
#include <cpu/cpu.h>
|
||||||
|
#include <cpu/x86/mtrr.h>
|
||||||
|
#include <cpu/x86/msr.h>
|
||||||
|
#include <cpu/x86/lapic.h>
|
||||||
|
#include <cpu/intel/speedstep.h>
|
||||||
|
#include <cpu/intel/turbo.h>
|
||||||
|
#include <cpu/x86/cache.h>
|
||||||
|
#include <cpu/x86/name.h>
|
||||||
|
#include <pc80/mc146818rtc.h>
|
||||||
|
#include "model_406dx.h"
|
||||||
|
#include "chip.h"
|
||||||
|
|
||||||
|
static void enable_vmx(void)
|
||||||
|
{
|
||||||
|
struct cpuid_result regs;
|
||||||
|
msr_t msr;
|
||||||
|
int enable = CONFIG_ENABLE_VMX;
|
||||||
|
|
||||||
|
regs = cpuid(1);
|
||||||
|
/* Check that the VMX is supported before reading or writing the MSR. */
|
||||||
|
if (!((regs.ecx & CPUID_VMX) || (regs.ecx & CPUID_SMX)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
msr = rdmsr(IA32_FEATURE_CONTROL);
|
||||||
|
|
||||||
|
if (msr.lo & (1 << 0)) {
|
||||||
|
printk(BIOS_ERR, "VMX is locked, so %s will do nothing\n", __func__);
|
||||||
|
/* VMX locked. If we set it again we get an illegal
|
||||||
|
* instruction
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The IA32_FEATURE_CONTROL MSR may initialize with random values.
|
||||||
|
* It must be cleared regardless of VMX config setting.
|
||||||
|
*/
|
||||||
|
msr.hi = msr.lo = 0;
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "%s VMX\n", enable ? "Enabling" : "Disabling");
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
msr.lo |= (1 << 2);
|
||||||
|
if (regs.ecx & CPUID_SMX)
|
||||||
|
msr.lo |= (1 << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wrmsr(IA32_FEATURE_CONTROL, msr);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(device_t cpu)
|
||||||
|
{
|
||||||
|
struct cpuid_result result;
|
||||||
|
unsigned 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;
|
||||||
|
device_t 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);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_SMP) && CONFIG_MAX_CPUS > 1
|
||||||
|
/* Start the new cpu */
|
||||||
|
if (!start_cpu(new)) {
|
||||||
|
/* Record the error in cpu? */
|
||||||
|
printk(BIOS_ERR, "CPU %u would not start!\n",
|
||||||
|
new->path.apic.apic_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void model_406dx_init(device_t cpu)
|
||||||
|
{
|
||||||
|
char processor_name[49];
|
||||||
|
|
||||||
|
/* Turn on caching if we haven't already */
|
||||||
|
x86_enable_cache();
|
||||||
|
|
||||||
|
/* 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();
|
||||||
|
|
||||||
|
/* Enable virtualization */
|
||||||
|
enable_vmx();
|
||||||
|
|
||||||
|
/* 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 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,
|
||||||
|
};
|
Loading…
Reference in New Issue