summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Serbinenko <phcoder@gmail.com>2013-06-06 22:10:45 +0200
committerStefan Reinauer <stefan.reinauer@coreboot.org>2013-06-13 00:32:01 +0200
commit22dcdd914cf36ce657f5e72c975a96d577400a69 (patch)
tree6d356f4a0a3a7dbb09b5e3b91f4b19a79867841a
parent3a09179f462ad3f6111c7b8ebbad7d78534f9234 (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>
-rw-r--r--src/cpu/intel/Kconfig1
-rw-r--r--src/cpu/intel/Makefile.inc1
-rw-r--r--src/cpu/intel/model_2065x/Kconfig42
-rw-r--r--src/cpu/intel/model_2065x/Makefile.inc16
-rw-r--r--src/cpu/intel/model_2065x/acpi.c361
-rw-r--r--src/cpu/intel/model_2065x/bootblock.c121
-rw-r--r--src/cpu/intel/model_2065x/cache_as_ram.inc347
-rw-r--r--src/cpu/intel/model_2065x/chip.h37
-rw-r--r--src/cpu/intel/model_2065x/finalize.c73
-rw-r--r--src/cpu/intel/model_2065x/microcode-m9220655_00000003.h129
-rw-r--r--src/cpu/intel/model_2065x/microcode_blob.c22
-rw-r--r--src/cpu/intel/model_2065x/microcode_blob.h26
-rw-r--r--src/cpu/intel/model_2065x/model_2065x.h109
-rw-r--r--src/cpu/intel/model_2065x/model_2065x_init.c483
14 files changed, 1768 insertions, 0 deletions
diff --git a/src/cpu/intel/Kconfig b/src/cpu/intel/Kconfig
index 106ce1d0d4..2bafa498c3 100644
--- a/src/cpu/intel/Kconfig
+++ b/src/cpu/intel/Kconfig
@@ -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
diff --git a/src/cpu/intel/Makefile.inc b/src/cpu/intel/Makefile.inc
index a1733297c1..54624fb8c7 100644
--- a/src/cpu/intel/Makefile.inc
+++ b/src/cpu/intel/Makefile.inc
@@ -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
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,
+};
+