Add support for Intel Nehalem CPU

Change-Id: I7ecc394b1e5bc0b8b85a8afac22efc0befe2d36a
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Signed-off-by: Stefan Reinauer <reinauer@google.com>
Reviewed-on: http://review.coreboot.org/3395
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Vladimir Serbinenko 2013-06-06 22:10:45 +02:00 committed by Stefan Reinauer
parent 3a09179f46
commit 22dcdd914c
14 changed files with 1768 additions and 0 deletions

View File

@ -10,6 +10,7 @@ source src/cpu/intel/model_6fx/Kconfig
source src/cpu/intel/model_1067x/Kconfig
source src/cpu/intel/model_106cx/Kconfig
source src/cpu/intel/model_206ax/Kconfig
source src/cpu/intel/model_2065x/Kconfig
source src/cpu/intel/model_f0x/Kconfig
source src/cpu/intel/model_f1x/Kconfig
source src/cpu/intel/model_f2x/Kconfig

View File

@ -15,6 +15,7 @@ subdirs-$(CONFIG_CPU_INTEL_SOCKET_MPGA603) += socket_mPGA603
subdirs-$(CONFIG_CPU_INTEL_SOCKET_MPGA604) += socket_mPGA604
subdirs-$(CONFIG_CPU_INTEL_SOCKET_PGA370) += socket_PGA370
subdirs-$(CONFIG_CPU_INTEL_SOCKET_RPGA989) += socket_rPGA989
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_NEHALEM) += model_2065x
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += model_206ax
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += model_206ax
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell

View File

@ -0,0 +1,42 @@
config CPU_INTEL_MODEL_2065X
bool
if CPU_INTEL_MODEL_2065X
config CPU_SPECIFIC_OPTIONS
def_bool y
select SMP
select SSE
select SSE2
select UDELAY_LAPIC
select SMM_TSEG
select HAVE_INIT_TIMER
select CPU_MICROCODE_IN_CBFS
#select AP_IN_SIPI_WAIT
select TSC_SYNC_MFENCE
config BOOTBLOCK_CPU_INIT
string
default "cpu/intel/model_2065x/bootblock.c"
config SERIAL_CPU_INIT
bool
default n
config SMM_TSEG_SIZE
hex
default 0x800000
config ENABLE_VMX
bool "Enable VMX for virtualization"
default n
config MICROCODE_INCLUDE_PATH
string
default "3rdparty/mainboard/lenovo/x201"
config XIP_ROM_SIZE
hex
default 0x20000
endif

View File

@ -0,0 +1,16 @@
ramstage-y += model_2065x_init.c
subdirs-y += ../../x86/name
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../intel/turbo
subdirs-y += ../../intel/microcode
subdirs-y += ../../x86/smm
ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c
cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c
cpu_incs += $(src)/cpu/intel/model_2065x/cache_as_ram.inc

View File

@ -0,0 +1,361 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 coresystems GmbH
* 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
*/
#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_2065x.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_cstate_entries(acpi_cstate_t *cstates,
int c1, int c2, int c3)
{
int length, cstate_count = 0;
/* Count number of active C-states */
if (c1 > 0)
++cstate_count;
if (c2 > 0)
++cstate_count;
if (c3 > 0)
++cstate_count;
if (!cstate_count)
return 0;
length = acpigen_write_package(cstate_count + 1);
length += acpigen_write_byte(cstate_count);
/* Add an entry if the level is enabled */
if (c1 > 0) {
cstates[c1].ctype = 1;
length += acpigen_write_CST_package_entry(&cstates[c1]);
}
if (c2 > 0) {
cstates[c2].ctype = 2;
length += acpigen_write_CST_package_entry(&cstates[c2]);
}
if (c3 > 0) {
cstates[c3].ctype = 3;
length += acpigen_write_CST_package_entry(&cstates[c3]);
}
acpigen_patch_len(length - 1);
return length;
}
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_2065x_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 */
lenif += generate_cstate_entries(cpu->cstates, conf->c1_acpower,
conf->c2_acpower, conf->c3_acpower);
acpigen_patch_len(lenif - 1);
len += lenif;
/* Else on battery power */
len += acpigen_emit_byte(0xa4); /* ReturnOp */
len += generate_cstate_entries(cpu->cstates, conf->c1_battery,
conf->c2_battery, conf->c3_battery);
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;
/* Determine P-state coordination type from MISC_PWR_MGMT[0] */
msr = rdmsr(MSR_MISC_PWR_MGMT);
if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
coord_type = SW_ANY;
else
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 * SANDYBRIDGE_BCLK + ratio_max / 3;
/* Calculate CPU TDP in mW */
power_max = 25000;
/* 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, /*control*/
ratio_turbo); /*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, /*control*/
ratio_max); /*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 * SANDYBRIDGE_BCLK + ratio / 3;
len_pss += acpigen_write_PSS_package(
clock, /*MHz*/
power, /*mW*/
PSS_LATENCY_TRANSITION, /*lat1*/
PSS_LATENCY_BUSMASTER, /*lat2*/
ratio, /*control*/
ratio); /*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_2065x_ops = {
CHIP_NAME("Intel Nehalem CPU")
};

View File

@ -0,0 +1,121 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Google Inc.
*
* 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 <cpu/intel/microcode/microcode.c>
#if CONFIG_SOUTHBRIDGE_INTEL_IBEXPEAK
#include <southbridge/intel/ibexpeak/pch.h>
#include "model_2065x.h"
#else
#error "CPU must be paired with Intel BD82X6X or C216 southbridge"
#endif
static void set_var_mtrr(
unsigned reg, unsigned base, unsigned size, unsigned type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
/* FIXME: It only support 4G less range */
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, 0xffc00000, 4*1024*1024, MTRR_TYPE_WRPROT);
enable_cache();
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
wrmsr(MTRRdefType_MSR, msr);
}
static void set_flex_ratio_to_tdp_nominal(void)
{
msr_t flex_ratio, msr;
u32 soft_reset;
u8 nominal_ratio;
/* Minimum CPU revision for configurable TDP support */
if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
return;
/* Check for Flex Ratio support */
flex_ratio = rdmsr(MSR_FLEX_RATIO);
if (!(flex_ratio.lo & FLEX_RATIO_EN))
return;
/* Check for >0 configurable TDPs */
msr = rdmsr(MSR_PLATFORM_INFO);
if (((msr.hi >> 1) & 3) == 0)
return;
/* Use nominal TDP ratio for flex ratio */
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
nominal_ratio = msr.lo & 0xff;
/* See if flex ratio is already set to nominal TDP ratio */
if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
return;
/* Set flex ratio to nominal TDP ratio */
flex_ratio.lo &= ~0xff00;
flex_ratio.lo |= nominal_ratio << 8;
flex_ratio.lo |= FLEX_RATIO_LOCK;
wrmsr(MSR_FLEX_RATIO, flex_ratio);
/* Set flex ratio in soft reset data register bits 11:6.
* RCBA region is enabled in southbridge bootblock */
soft_reset = RCBA32(SOFT_RESET_DATA);
soft_reset &= ~(0x3f << 6);
soft_reset |= (nominal_ratio & 0x3f) << 6;
RCBA32(SOFT_RESET_DATA) = soft_reset;
/* Set soft reset control to use register value */
RCBA32_OR(SOFT_RESET_CTRL, 1);
/* Issue warm reset, will be "CPU only" due to soft reset data */
outb(0x0, 0xcf9);
outb(0x6, 0xcf9);
asm("hlt");
}
static void bootblock_cpu_init(void)
{
/* Set flex ratio and reset if needed */
set_flex_ratio_to_tdp_nominal();
enable_rom_caching();
intel_update_microcode_from_cbfs();
}

View File

@ -0,0 +1,347 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
* Copyright (C) 2007-2008 coresystems GmbH
*
* 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 <cpu/x86/stack.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>
#include <cbmem.h>
#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
/* Cache 4GB - MRC_SIZE_KB for MRC */
#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1)
#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES)
#define CACHE_MRC_MASK (~CACHE_MRC_BYTES)
#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1)
#define NoEvictMod_MSR 0x2e0
/* Save the BIST result. */
movl %eax, %ebp
cache_as_ram:
post_code(0x20)
/* Send INIT IPI to all excluding ourself. */
movl $0x000C4500, %eax
movl $0xFEE00300, %esi
movl %eax, (%esi)
/* All CPUs need to be in Wait for SIPI state */
wait_for_sipi:
movl (%esi), %eax
bt $12, %eax
jc wait_for_sipi
post_code(0x21)
/* Zero out all fixed range and variable range MTRRs. */
movl $mtrr_table, %esi
movl $((mtrr_table_end - mtrr_table) / 2), %edi
xorl %eax, %eax
xorl %edx, %edx
clear_mtrrs:
movw (%esi), %bx
movzx %bx, %ecx
wrmsr
add $2, %esi
dec %edi
jnz clear_mtrrs
post_code(0x22)
/* Configure the default memory type to uncacheable. */
movl $MTRRdefType_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
post_code(0x23)
/* Set Cache-as-RAM base address. */
movl $(MTRRphysBase_MSR(0)), %ecx
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
xorl %edx, %edx
wrmsr
post_code(0x24)
/* Set Cache-as-RAM mask. */
movl $(MTRRphysMask_MSR(0)), %ecx
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
post_code(0x25)
/* Enable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
wrmsr
/* Enable cache (CR0.CD = 0, CR0.NW = 0). */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
invd
movl %eax, %cr0
/* enable the 'no eviction' mode */
movl $NoEvictMod_MSR, %ecx
rdmsr
orl $1, %eax
andl $~2, %eax
wrmsr
/* Clear the cache memory region. This will also fill up the cache */
movl $CACHE_AS_RAM_BASE, %esi
movl %esi, %edi
movl $(CACHE_AS_RAM_SIZE / 4), %ecx
// movl $0x23322332, %eax
xorl %eax, %eax
rep stosl
/* enable the 'no eviction run' state */
movl $NoEvictMod_MSR, %ecx
rdmsr
orl $3, %eax
wrmsr
post_code(0x26)
/* Enable Cache-as-RAM mode by disabling cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
/* Enable cache for our code in Flash because we do XIP here */
movl $MTRRphysBase_MSR(1), %ecx
xorl %edx, %edx
/*
* IMPORTANT: The following calculation _must_ be done at runtime. See
* http://www.coreboot.org/pipermail/coreboot/2010-October/060855.html
*/
movl $copy_and_run, %eax
andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr
movl $MTRRphysMask_MSR(1), %ecx
movl $CPU_PHYSMASK_HI, %edx
movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
wrmsr
post_code(0x27)
#if CONFIG_CACHE_MRC_BIN
/* Enable caching for ram init code to run faster */
movl $MTRRphysBase_MSR(2), %ecx
movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
xorl %edx, %edx
wrmsr
movl $MTRRphysMask_MSR(2), %ecx
movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
#endif
post_code(0x28)
/* Enable cache. */
movl %cr0, %eax
andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
movl %eax, %cr0
/* Set up the stack pointer below MRC variable space. */
movl $(CACHE_AS_RAM_SIZE + CACHE_AS_RAM_BASE - \
CONFIG_DCACHE_RAM_MRC_VAR_SIZE - 4 - 4096), %eax
movl %eax, %esp
/* Restore the BIST result. */
movl %ebp, %eax
movl %esp, %ebp
pushl %eax
before_romstage:
post_code(0x29)
/* Call romstage.c main function. */
call main
post_code(0x2f)
/* Copy global variable space (for USBDEBUG) to memory */
#if CONFIG_USBDEBUG
cld
movl $(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE - 24), %esi
movl $(CONFIG_RAMTOP - 24), %edi
movl $24, %ecx
rep movsb
#endif
post_code(0x30)
/* Disable cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
post_code(0x31)
/* Disable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
andl $(~MTRRdefTypeEn), %eax
wrmsr
post_code(0x31)
/* Disable the no eviction run state */
movl $NoEvictMod_MSR, %ecx
rdmsr
andl $~2, %eax
wrmsr
invd
/* Disable the no eviction mode */
rdmsr
andl $~1, %eax
wrmsr
#if CONFIG_CACHE_MRC_BIN
/* Clear MTRR that was used to cache MRC */
xorl %eax, %eax
xorl %edx, %edx
movl $MTRRphysBase_MSR(2), %ecx
wrmsr
movl $MTRRphysMask_MSR(2), %ecx
wrmsr
#endif
post_code(0x33)
/* Enable cache. */
movl %cr0, %eax
andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
movl %eax, %cr0
post_code(0x36)
/* Disable cache. */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
movl %eax, %cr0
post_code(0x38)
/* Enable Write Back and Speculative Reads for the first MB
* and coreboot_ram.
*/
movl $MTRRphysBase_MSR(0), %ecx
movl $(0x00000000 | MTRR_TYPE_WRBACK), %eax
xorl %edx, %edx
wrmsr
movl $MTRRphysMask_MSR(0), %ecx
movl $(~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx // 36bit address space
wrmsr
#if CONFIG_CACHE_ROM_SIZE
/* Enable Caching and speculative Reads for the
* complete ROM now that we actually have RAM.
*/
movl $MTRRphysBase_MSR(1), %ecx
movl $(CACHE_ROM_BASE | MTRR_TYPE_WRPROT), %eax
xorl %edx, %edx
wrmsr
movl $MTRRphysMask_MSR(1), %ecx
movl $(~(CONFIG_CACHE_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
#endif
post_code(0x39)
/* And enable cache again after setting MTRRs. */
movl %cr0, %eax
andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
movl %eax, %cr0
post_code(0x3a)
/* Enable MTRR. */
movl $MTRRdefType_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
wrmsr
post_code(0x3b)
/* Invalidate the cache again. */
invd
post_code(0x3c)
#if CONFIG_HAVE_ACPI_RESUME
movl CBMEM_BOOT_MODE, %eax
cmpl $0x2, %eax // Resume?
jne __acpi_resume_backup_done
/* copy 1MB - 64K to high tables ram_base to prevent memory corruption
* through stage 2. We could keep stuff like stack and heap in high
* tables memory completely, but that's a wonderful clean up task for
* another day.
*/
cld
movl $CONFIG_RAMBASE, %esi
movl CBMEM_RESUME_BACKUP, %edi
movl $HIGH_MEMORY_SAVE / 4, %ecx
rep movsl
__acpi_resume_backup_done:
#endif
post_code(0x3d)
__main:
post_code(POST_PREPARE_RAMSTAGE)
cld /* Clear direction flag. */
movl $ROMSTAGE_STACK, %esp
movl %esp, %ebp
call copy_and_run
.Lhlt:
post_code(POST_DEAD_CODE)
hlt
jmp .Lhlt
mtrr_table:
.word 0x02FF
/* Fixed MTRRs */
.word 0x250, 0x258, 0x259
.word 0x268, 0x269, 0x26A
.word 0x26B, 0x26C, 0x26D
.word 0x26E, 0x26F
/* Variable MTRRs */
.word 0x200, 0x201, 0x202, 0x203
.word 0x204, 0x205, 0x206, 0x207
.word 0x208, 0x209, 0x20A, 0x20B
.word 0x20C, 0x20D, 0x20E, 0x20F
mtrr_table_end:

View File

@ -0,0 +1,37 @@
/*
* 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_model_2065x_config {
u8 disable_acpi; /* Do not generate CPU ACPI tables */
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 */
int tcc_offset; /* TCC Activation Offset */
};

View File

@ -0,0 +1,73 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 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
*/
#include <stdint.h>
#include <stdlib.h>
#include <cpu/cpu.h>
#include <cpu/x86/msr.h>
#include <cpu/intel/speedstep.h>
#include "model_2065x.h"
static void msr_set_bit(unsigned reg, unsigned bit)
{
msr_t msr = rdmsr(reg);
if (bit < 32) {
if (msr.lo & (1 << bit))
return;
msr.lo |= 1 << bit;
} else {
if (msr.hi & (1 << (bit - 32)))
return;
msr.hi |= 1 << (bit - 32);
}
wrmsr(reg, msr);
}
void intel_model_2065x_finalize_smm(void)
{
msr_set_bit(MSR_PMG_CST_CONFIG_CONTROL, 15);
/* Lock AES-NI only if supported */
if (cpuid_ecx(1) & (1 << 25))
msr_set_bit(MSR_FEATURE_CONFIG, 0);
#ifdef LOCK_POWER_CONTROL_REGISTERS
/*
* Lock the power control registers.
*
* These registers can be left unlocked if modifying power
* limits from the OS is desirable. Modifying power limits
* from the OS can be especially useful for experimentation
* during early phases of system bringup while the thermal
* power envelope is being proven.
*/
msr_set_bit(MSR_PP0_CURRENT_CONFIG, 31);
msr_set_bit(MSR_PP1_CURRENT_CONFIG, 31);
msr_set_bit(MSR_PKG_POWER_LIMIT, 63);
msr_set_bit(MSR_PP0_POWER_LIMIT, 31);
msr_set_bit(MSR_PP1_POWER_LIMIT, 31);
#endif
msr_set_bit(MSR_MISC_PWR_MGMT, 22);
msr_set_bit(MSR_LT_LOCK_MEMORY, 0);
}

View File

@ -0,0 +1,129 @@
/* m9220655_00000003.inc */
0x00000001, 0x00000003, 0x09012011, 0x00020655,
0xc50abfd4, 0x00000001, 0x00000092, 0x000007d0,
0x00000800, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x000000a1, 0x00020001, 0x00000003,
0x00000000, 0x00000000, 0x20110831, 0x000001a1,
0x00000001, 0x00020655, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xc3323f9e, 0xa2912832, 0xa7a30a2e, 0x9e75a181,
0x840159be, 0xd1c7dbb0, 0x921c5cf7, 0xb323111b,
0x5d5f57b5, 0x9926d84a, 0xdaaf70e7, 0x91786b18,
0x82da740d, 0xae90be68, 0x8b6a07cf, 0xc2c37ebc,
0xde451f9c, 0x7a1444c0, 0xce6700b1, 0x5c29e58a,
0x12eb603f, 0xaaf6cb53, 0xd807a1c9, 0xf51ed696,
0x90d9e2c3, 0x641bff09, 0x732ab820, 0xfef7aa2f,
0x8f518e1d, 0xf0d8c4d9, 0x73aefe19, 0xf6d7ae12,
0xd50a095b, 0xdf21cbb8, 0x4b81ff9a, 0xe1a6d1f8,
0xbe78b0de, 0xda86826f, 0xc4f9c057, 0x306f1761,
0x7aae81f0, 0xdbab0ae2, 0x789ec0ff, 0xbaacd096,
0x68fa4733, 0x2f3fd406, 0xd287247f, 0x79eefe4c,
0x6f674a41, 0xd6948ad8, 0x90388682, 0x5a4bf35d,
0xadab41ff, 0x89e9dc62, 0xb2eccfee, 0xd4d52153,
0x34301d19, 0x8a2f38a6, 0x35b05e56, 0x482f029a,
0x296cb5a3, 0xce64f437, 0xae1dfa06, 0xb9f29132,
0x1960a103, 0x70bb6f46, 0x152a5d83, 0x171a19d9,
0xac9aa4b7, 0x54b719f7, 0x5b781cb1, 0xaea548bb,
0x00000011, 0x649668c5, 0xd3d4e73c, 0x0d7eee17,
0xc8a4d8f1, 0xa531e67c, 0x0d4e93f9, 0x109a2c8e,
0xb3a120eb, 0x1cb99ad0, 0xdf7fffa7, 0xcd22ae67,
0xbe6f61df, 0x1fff8bc4, 0x7d413494, 0xbbc77986,
0x4648fad1, 0x05a0b769, 0x14a2f426, 0x39081a28,
0x343c7600, 0x3a9d78ed, 0xa8bcbbb1, 0x1128500a,
0xb1f08088, 0x16f1cc2e, 0x187920e4, 0x7bd8c616,
0x416a91ac, 0x2d156cd1, 0xd23473e7, 0xf326b7ff,
0x991a226f, 0xf1a4f527, 0xe758dc3f, 0x20f89a4a,
0x9f84858c, 0x9c5bde06, 0x839ea7e7, 0x42cfa525,
0x869950f9, 0x48e6318f, 0x44314d3e, 0xc946335f,
0x9439e0ba, 0x16bef497, 0x5dfeb355, 0x062e96dc,
0x0c5b3442, 0x2317678c, 0x0688e8b9, 0x698df73a,
0xd87f7a27, 0xc63a05b7, 0xb77b7ed1, 0xee993117,
0xbffab1d3, 0x455c43b5, 0x5363cb6c, 0x9361cabc,
0xd5bc2e2b, 0xb0079b02, 0x5b371608, 0x8228cc3c,
0x97c217b0, 0xef92660a, 0x99e15bc3, 0x610d1881,
0xa84efd04, 0x35f287c9, 0xc02cbf49, 0xdc291d6f,
0x7d603a19, 0x420b25dc, 0x6d24d532, 0xf8c2d4b6,
0x67104704, 0x7ae246b3, 0x24f07636, 0xf88808a0,
0xcdcf7aed, 0xa78611a3, 0x9dafdde7, 0x5def0b11,
0xb39ca9d7, 0xd0de1c2a, 0xe6e8cc61, 0x9824df50,
0x501ef8c9, 0x5bb94ee7, 0x9d75a287, 0xc5b37ebc,
0x8b7175f8, 0xe9bd1024, 0xc4e004c2, 0xb626e586,
0xf71c129d, 0xe5562dd2, 0xd1d9c514, 0xaa69cd52,
0x7ec85bfb, 0x1d6d69da, 0xbd735ff0, 0x496b0cc3,
0xea10aa85, 0xd968b670, 0xe4674e6b, 0xd7725f8c,
0xc845a270, 0x15d4b857, 0x0a130ca8, 0x707de71f,
0x0cf7ba9f, 0xb46fbb4d, 0xc9631c72, 0xe0b4abcd,
0x0b364ef1, 0xa390747a, 0x5945a462, 0xe0756457,
0x5f79663c, 0x7418e5be, 0xc7ac38f4, 0x24aceecd,
0xae762e2b, 0x04c63655, 0x2807f3ba, 0x8a9fdee2,
0x4705e3b9, 0x0be41abf, 0x360a2475, 0x2188e84c,
0x6724fa71, 0x0d80d39f, 0x06be8e55, 0xd49f817a,
0x518f531d, 0x02775181, 0xbd1f8af9, 0x70c91b1f,
0x67d619f2, 0x0e2f44b0, 0xde3a57b2, 0x0b96a208,
0x86dbafdf, 0xd81a43ca, 0x894241a6, 0x453cd6c0,
0x801398e5, 0x8dc7e734, 0x64f5f2f0, 0x023fe4ad,
0x808b3fbe, 0x677dec2d, 0xc75aa416, 0x8d4a51c1,
0xcb46efb4, 0x26af2486, 0xf28d384f, 0x1f74bbaa,
0xb35dbfec, 0xa4acc70a, 0xd0c8ff4b, 0xf40e3136,
0x24f08d6d, 0xf4a5792f, 0x3423ebc0, 0x47f54044,
0x42939e1e, 0x3768fe97, 0x0890f228, 0xfe48104e,
0xd095804b, 0xde7a40cb, 0xc8ed5843, 0x04cc48c5,
0xa68d1936, 0x554d336f, 0x19cc9df7, 0xf2b5b0cc,
0xf88858c2, 0x6bef0f07, 0xcff53326, 0xfbebbb76,
0x63afbd06, 0x6d4b7c27, 0xdd5c8b52, 0x792f665e,
0x44e8bc2d, 0x53522507, 0xf5971875, 0xef44f472,
0x0ab3bc03, 0x068d792f, 0x86745dc4, 0xc0e63ca0,
0xfddb054d, 0x46c23e3c, 0xc8184e1a, 0xb7e77cc7,
0x59e90ac1, 0xd836bf58, 0xb220f287, 0x3c3a2e8f,
0xa28a7e28, 0x99a249ec, 0xd2a6641c, 0x24adeb4a,
0x2bbf323a, 0x618dee6e, 0x093e831a, 0x3f4d3194,
0xa166732a, 0x0a80f2f3, 0x8f2f80de, 0xc4d2b7ea,
0x17f9e541, 0x1059766d, 0xc2f7e49d, 0x666bb0a3,
0xfe8eb21f, 0xa68c8c87, 0x30efe1af, 0x15763eab,
0x1d18c1f0, 0xcf1907ee, 0xd478498e, 0xb8041744,
0x1bd93f4b, 0x6bca9af1, 0xa54694db, 0xaccd6971,
0x92af5474, 0x194c5290, 0xc573b14f, 0xe4d74f3c,
0xaa128d24, 0xe50848a2, 0xa5001983, 0x9fc5c01f,
0x495687cb, 0x7795998b, 0xcba451a5, 0x67c54058,
0x3585e4cc, 0x07eaf375, 0xa1bef51d, 0x730960a4,
0xc217f8f0, 0xe5779a63, 0x237b7f2f, 0x6d868035,
0x70987ef1, 0x1ab1e989, 0xf1727403, 0x94cd3133,
0xbe827fc7, 0x19e198d1, 0xf8f8a4dd, 0x0bdfc02e,
0x788737f9, 0xf554a473, 0x22488c80, 0x4397d132,
0x5602e73a, 0x4cbdf8b7, 0x14929ba4, 0xc49645d8,
0x3a724eb1, 0x44134eef, 0x534f26fc, 0x2c9a2bcf,
0xc329abc2, 0x79a52a91, 0xc4d8ecb2, 0x4f29e89b,
0x08e3bc45, 0x02c7516b, 0xe4f79884, 0x21dc828a,
0xb22adc25, 0xad6b4194, 0xc2e88ec8, 0xab76a868,
0x3049d043, 0x9781e3b5, 0xa56602b8, 0xb844a1cf,
0xd0c2f155, 0xfff59242, 0x7c0b1be7, 0x20c337ee,
0x6eeedede, 0x3d544527, 0x4fa08565, 0x78035c9f,
0x5ab9652f, 0x1679da28, 0x1d59380f, 0xfd693582,
0x6647c152, 0xa494f5b7, 0x1e5a44e5, 0x49515666,
0x80ad6e9f, 0x2857b798, 0x21c78a9c, 0xde2536d4,
0x8cd0c906, 0x0e101e47, 0xb56139d8, 0x5f29407b,
0xd86efa56, 0x60c1f662, 0x387dbee9, 0xd57f4fae,
0xe27b9e73, 0x5e4d81b9, 0x2761f882, 0x923b00c9,
0xf1d1ee2e, 0xbec5a579, 0xa90ebc17, 0x686554a2,
0xa83f71fd, 0x8eb862bc, 0xdfd0bb6f, 0x1ac1a2bb,
0x74d53b49, 0xda9430c4, 0x09797597, 0x35d8f250,
0x8d33fb7b, 0x21ec9ecd, 0x6bd9041c, 0xf858aae6,
0x3bb472b5, 0xf43a3d7e, 0x8ced914f, 0x5f5d9ce5,
0xc0e27757, 0x6afee8ff, 0x45bd08fc, 0x74402451,
0x5d1e3aff, 0xfe1e6e53, 0xcaf73401, 0x035d5585,
0xb77a8af9, 0xc869836f, 0x72e43074, 0xf784f07b,
0x17cf17fd, 0x5785c5c9, 0xa761ee5e, 0xaede1773,
0xc58bab5a, 0x8fb77743, 0xc20c974e, 0x9f72ce11,
0xdfdf11f8, 0x0153fda9, 0x87d08d4d, 0x8a8d163c,
0x2f346fc4, 0x4aabbd39, 0x9866fbe8, 0x4fbc185a,
0xc30ea07b, 0xc6e2c2e2, 0x6d9bcc5b, 0x292524ac,
0xaad044e9, 0xd6fcd72b, 0x755b2c1b, 0xbc5f83ee,
0xbb041dfd, 0x87eefef9, 0x68cdbb47, 0xf423fd81,
0x1c106165, 0x35b223a3, 0x4212e6b7, 0x0868b1b0,
0x5288c578, 0x108d97ff, 0x1962e7b9, 0x73d366ec,
0x8c851ca9, 0x1705746d, 0xc1a261ae, 0xd685b108,
0x42a77adc, 0x2c454ffe, 0x33b19c19, 0xefae69ca,
0xa6ae093b, 0x6fdfb131, 0xb6fbe5d9, 0xe872ca64,
0xecd6df71, 0xe133acfc, 0x3d16c48b, 0x240a15a8,

View File

@ -0,0 +1,22 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 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
*/
unsigned microcode[] = {
#include "microcode_blob.h"
};

View File

@ -0,0 +1,26 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Google Inc.
*
* 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 "microcode-m9220655_00000003.h"
/* Dummy terminator */
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,

View File

@ -0,0 +1,109 @@
/*
* 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
*/
#ifndef _CPU_INTEL_MODEL_2065X_H
#define _CPU_INTEL_MODEL_2065X_H
/* SandyBridge/IvyBridge bus clock is fixed at 100MHz */
#define SANDYBRIDGE_BCLK 133
#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_PIC_MSG_CONTROL 0x2e
#define MSR_PLATFORM_INFO 0xce
#define PLATFORM_INFO_SET_TDP (1 << 29)
#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 16
#define PSS_RATIO_STEP 1
#define PSS_LATENCY_TRANSITION 10
#define PSS_LATENCY_BUSMASTER 10
#ifdef __SMM__
/* Lock MSRs */
void intel_model_2065x_finalize_smm(void);
#else
/* Configure power limits for turbo mode */
void set_power_limits(u8 power_limit_1_time);
int cpu_config_tdp_levels(void);
#endif
#endif

View File

@ -0,0 +1,483 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* 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
*/
#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/microcode.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 <usbdebug.h>
#include "model_2065x.h"
#include "chip.h"
/*
* List of suported C-states in this processor
*
* Latencies are typical worst-case package exit time in uS
* taken from the SandyBridge BIOS specification.
*/
static acpi_cstate_t cstate_map[] = {
{ /* 0: C0 */
},{ /* 1: C1 */
.latency = 1,
.power = 1000,
.resource = {
.addrl = 0x00, /* MWAIT State 0 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 2: C1E */
.latency = 1,
.power = 1000,
.resource = {
.addrl = 0x01, /* MWAIT State 0 Sub-state 1 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 3: C3 */
.latency = 63,
.power = 500,
.resource = {
.addrl = 0x10, /* MWAIT State 1 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 4: C6 */
.latency = 87,
.power = 350,
.resource = {
.addrl = 0x20, /* MWAIT State 2 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 5: C7 */
.latency = 90,
.power = 200,
.resource = {
.addrl = 0x30, /* MWAIT State 3 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ /* 6: C7S */
.latency = 90,
.power = 200,
.resource = {
.addrl = 0x31, /* MWAIT State 3 Sub-state 1 */
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
}
},
{ 0 }
};
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");
/* Even though the Intel manual says you must set the lock bit in addition
* to the VMX bit in order for VMX to work, it is incorrect. Thus we leave
* it unlocked for the OS to manage things itself. This is good for a few
* reasons:
* - No need to reflash the bios just to toggle the lock bit.
* - The VMX bits really really should match each other across cores, so
* hard locking it on one while another has the opposite setting can
* easily lead to crashes as code using VMX migrates between them.
* - Vendors that want to "upsell" from a bios that disables+locks to
* one that doesn't is sleazy.
* By leaving this to the OS (e.g. Linux), people can do exactly what they
* want on the fly, and do it correctly (e.g. across multiple cores).
*/
if (enable) {
msr.lo |= (1 << 2);
if (regs.ecx & CPUID_SMX)
msr.lo |= (1 << 1);
}
wrmsr(IA32_FEATURE_CONTROL, msr);
}
/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
static const u8 power_limit_time_sec_to_msr[] = {
[0] = 0x00,
[1] = 0x0a,
[2] = 0x0b,
[3] = 0x4b,
[4] = 0x0c,
[5] = 0x2c,
[6] = 0x4c,
[7] = 0x6c,
[8] = 0x0d,
[10] = 0x2d,
[12] = 0x4d,
[14] = 0x6d,
[16] = 0x0e,
[20] = 0x2e,
[24] = 0x4e,
[28] = 0x6e,
[32] = 0x0f,
[40] = 0x2f,
[48] = 0x4f,
[56] = 0x6f,
[64] = 0x10,
[80] = 0x30,
[96] = 0x50,
[112] = 0x70,
[128] = 0x11,
};
/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
static const u8 power_limit_time_msr_to_sec[] = {
[0x00] = 0,
[0x0a] = 1,
[0x0b] = 2,
[0x4b] = 3,
[0x0c] = 4,
[0x2c] = 5,
[0x4c] = 6,
[0x6c] = 7,
[0x0d] = 8,
[0x2d] = 10,
[0x4d] = 12,
[0x6d] = 14,
[0x0e] = 16,
[0x2e] = 20,
[0x4e] = 24,
[0x6e] = 28,
[0x0f] = 32,
[0x2f] = 40,
[0x4f] = 48,
[0x6f] = 56,
[0x10] = 64,
[0x30] = 80,
[0x50] = 96,
[0x70] = 112,
[0x11] = 128,
};
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_thermal_target(void)
{
struct cpu_intel_model_2065x_config *conf;
device_t lapic;
msr_t msr;
/* Find pointer to CPU configuration */
lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
if (!lapic || !lapic->chip_info)
return;
conf = lapic->chip_info;
/* Set TCC activaiton 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);
#ifdef DISABLED
/* Enable package critical interrupt only */
msr.lo = 1 << 4;
msr.hi = 0;
wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
#endif
}
static void enable_lapic_tpr(void)
{
msr_t msr;
msr = rdmsr(MSR_PIC_MSG_CONTROL);
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
wrmsr(MSR_PIC_MSG_CONTROL, msr);
}
static void set_max_ratio(void)
{
msr_t msr, perf_ctl;
perf_ctl.hi = 0;
/* Check for configurable TDP option */
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, "model_x06ax: frequency set to %d\n",
((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK);
}
static void set_energy_perf_bias(u8 policy)
{
#ifdef DISABLED
msr_t msr;
/* Energy Policy is bits 3:0 */
msr = rdmsr(IA32_ENERGY_PERFORMANCE_BIAS);
msr.lo &= ~0xf;
msr.lo |= policy & 0xf;
wrmsr(IA32_ENERGY_PERFORMANCE_BIAS, msr);
printk(BIOS_DEBUG, "model_x06ax: energy policy set to %u\n",
policy);
#endif
}
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 < 7; i++)
wrmsr(IA32_MC0_STATUS + (i * 4), msr);
}
#if CONFIG_USBDEBUG
static unsigned ehci_debug_addr;
#endif
/*
* 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 & 1) + ((i & 2) << 1);
/* 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 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_2065x_init(device_t cpu)
{
char processor_name[49];
struct cpuid_result cpuid_regs;
/* Turn on caching if we haven't already */
x86_enable_cache();
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);
printk(BIOS_INFO, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid (), boot_cpu ());
#if CONFIG_USBDEBUG
// Is this caution really needed?
if(!ehci_debug_addr)
ehci_debug_addr = get_ehci_debug();
set_ehci_debug(0);
#endif
/* Setup MTRRs based on physical address size */
cpuid_regs = cpuid(0x80000008);
x86_setup_fixed_mtrrs();
x86_setup_var_mtrrs(cpuid_regs.eax & 0xff, 2);
x86_mtrr_check();
/* Setup Page Attribute Tables (PAT) */
// TODO set up PAT
#if CONFIG_USBDEBUG
set_ehci_debug(ehci_debug_addr);
#endif
/* Enable the local cpu apics */
enable_lapic_tpr();
setup_lapic();
/* Enable virtualization if enabled in CMOS */
enable_vmx();
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
/* Thermal throttle activation offset */
configure_thermal_target();
/* Set energy policy */
set_energy_perf_bias(ENERGY_POLICY_NORMAL);
/* Set Max Ratio */
set_max_ratio();
/* Enable Turbo */
enable_turbo();
/* Start up extra cores */
intel_cores_init(cpu);
}
static struct device_operations cpu_dev_ops = {
.init = model_2065x_init,
};
static struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x20655 }, /* Intel Nehalem */
{ 0, 0 },
};
static const struct cpu_driver driver __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
.cstates = cstate_map,
};