diff options
author | Vladimir Serbinenko <phcoder@gmail.com> | 2013-06-06 22:10:45 +0200 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2013-06-13 00:32:01 +0200 |
commit | 22dcdd914cf36ce657f5e72c975a96d577400a69 (patch) | |
tree | 6d356f4a0a3a7dbb09b5e3b91f4b19a79867841a /src/cpu/intel/model_2065x | |
parent | 3a09179f462ad3f6111c7b8ebbad7d78534f9234 (diff) |
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>
Diffstat (limited to 'src/cpu/intel/model_2065x')
-rw-r--r-- | src/cpu/intel/model_2065x/Kconfig | 42 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/Makefile.inc | 16 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/acpi.c | 361 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/bootblock.c | 121 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/cache_as_ram.inc | 347 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/chip.h | 37 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/finalize.c | 73 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/microcode-m9220655_00000003.h | 129 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/microcode_blob.c | 22 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/microcode_blob.h | 26 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/model_2065x.h | 109 | ||||
-rw-r--r-- | src/cpu/intel/model_2065x/model_2065x_init.c | 483 |
12 files changed, 1766 insertions, 0 deletions
diff --git a/src/cpu/intel/model_2065x/Kconfig b/src/cpu/intel/model_2065x/Kconfig new file mode 100644 index 0000000000..019309d0e8 --- /dev/null +++ b/src/cpu/intel/model_2065x/Kconfig @@ -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 diff --git a/src/cpu/intel/model_2065x/Makefile.inc b/src/cpu/intel/model_2065x/Makefile.inc new file mode 100644 index 0000000000..963fb1b3e3 --- /dev/null +++ b/src/cpu/intel/model_2065x/Makefile.inc @@ -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 diff --git a/src/cpu/intel/model_2065x/acpi.c b/src/cpu/intel/model_2065x/acpi.c new file mode 100644 index 0000000000..848381297e --- /dev/null +++ b/src/cpu/intel/model_2065x/acpi.c @@ -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") +}; diff --git a/src/cpu/intel/model_2065x/bootblock.c b/src/cpu/intel/model_2065x/bootblock.c new file mode 100644 index 0000000000..3bd087141d --- /dev/null +++ b/src/cpu/intel/model_2065x/bootblock.c @@ -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(); +} diff --git a/src/cpu/intel/model_2065x/cache_as_ram.inc b/src/cpu/intel/model_2065x/cache_as_ram.inc new file mode 100644 index 0000000000..db0eaaebbe --- /dev/null +++ b/src/cpu/intel/model_2065x/cache_as_ram.inc @@ -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: + diff --git a/src/cpu/intel/model_2065x/chip.h b/src/cpu/intel/model_2065x/chip.h new file mode 100644 index 0000000000..2c38033785 --- /dev/null +++ b/src/cpu/intel/model_2065x/chip.h @@ -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 */ +}; diff --git a/src/cpu/intel/model_2065x/finalize.c b/src/cpu/intel/model_2065x/finalize.c new file mode 100644 index 0000000000..b37a84cfe7 --- /dev/null +++ b/src/cpu/intel/model_2065x/finalize.c @@ -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); +} diff --git a/src/cpu/intel/model_2065x/microcode-m9220655_00000003.h b/src/cpu/intel/model_2065x/microcode-m9220655_00000003.h new file mode 100644 index 0000000000..2eb6cca96e --- /dev/null +++ b/src/cpu/intel/model_2065x/microcode-m9220655_00000003.h @@ -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, diff --git a/src/cpu/intel/model_2065x/microcode_blob.c b/src/cpu/intel/model_2065x/microcode_blob.c new file mode 100644 index 0000000000..c2538e8ede --- /dev/null +++ b/src/cpu/intel/model_2065x/microcode_blob.c @@ -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" +}; diff --git a/src/cpu/intel/model_2065x/microcode_blob.h b/src/cpu/intel/model_2065x/microcode_blob.h new file mode 100644 index 0000000000..1da40d94bc --- /dev/null +++ b/src/cpu/intel/model_2065x/microcode_blob.h @@ -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, diff --git a/src/cpu/intel/model_2065x/model_2065x.h b/src/cpu/intel/model_2065x/model_2065x.h new file mode 100644 index 0000000000..18a45d8b14 --- /dev/null +++ b/src/cpu/intel/model_2065x/model_2065x.h @@ -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 diff --git a/src/cpu/intel/model_2065x/model_2065x_init.c b/src/cpu/intel/model_2065x/model_2065x_init.c new file mode 100644 index 0000000000..bdbddfba34 --- /dev/null +++ b/src/cpu/intel/model_2065x/model_2065x_init.c @@ -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, +}; + |