summaryrefslogtreecommitdiffstats
path: root/arch/x86/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r--arch/x86/cpu/Makefile1
-rw-r--r--arch/x86/cpu/coreboot/Kconfig15
-rw-r--r--arch/x86/cpu/coreboot/coreboot.c22
-rw-r--r--arch/x86/cpu/coreboot/pci.c30
-rw-r--r--arch/x86/cpu/coreboot/timestamp.c33
-rw-r--r--arch/x86/cpu/ivybridge/car.S74
-rw-r--r--arch/x86/cpu/ivybridge/cpu.c27
-rw-r--r--arch/x86/cpu/ivybridge/gma.c16
-rw-r--r--arch/x86/cpu/ivybridge/microcode_intel.c26
-rw-r--r--arch/x86/cpu/ivybridge/sdram.c10
-rw-r--r--arch/x86/cpu/mtrr.c81
-rw-r--r--arch/x86/cpu/pci.c11
-rw-r--r--arch/x86/cpu/queensbay/fsp_support.c95
-rw-r--r--arch/x86/cpu/queensbay/tnc_dram.c39
-rw-r--r--arch/x86/cpu/start.S8
15 files changed, 353 insertions, 135 deletions
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 5033d2b757..62e43c04e5 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += lapic.o
+obj-y += mtrr.o
obj-$(CONFIG_PCI) += pci.o
obj-y += turbo.o
diff --git a/arch/x86/cpu/coreboot/Kconfig b/arch/x86/cpu/coreboot/Kconfig
new file mode 100644
index 0000000000..e0e3c64506
--- /dev/null
+++ b/arch/x86/cpu/coreboot/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_COREBOOT
+
+config SYS_COREBOOT
+ bool
+ default y
+
+config CBMEM_CONSOLE
+ bool
+ default y
+
+config VIDEO_COREBOOT
+ bool
+ default y
+
+endif
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index cfacc05875..6d06d5af19 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -15,6 +15,7 @@
#include <asm/cache.h>
#include <asm/cpu.h>
#include <asm/io.h>
+#include <asm/mtrr.h>
#include <asm/arch/tables.h>
#include <asm/arch/sysinfo.h>
#include <asm/arch/timestamp.h>
@@ -64,11 +65,6 @@ int board_eth_init(bd_t *bis)
return pci_eth_init(bis);
}
-#define MTRR_TYPE_WP 5
-#define MTRRcap_MSR 0xfe
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
void board_final_cleanup(void)
{
/* Un-cache the ROM so the kernel has one
@@ -77,15 +73,17 @@ void board_final_cleanup(void)
* Coreboot should have assigned this to the
* top available variable MTRR.
*/
- u8 top_mtrr = (native_read_msr(MTRRcap_MSR) & 0xff) - 1;
- u8 top_type = native_read_msr(MTRRphysBase_MSR(top_mtrr)) & 0xff;
+ u8 top_mtrr = (native_read_msr(MTRR_CAP_MSR) & 0xff) - 1;
+ u8 top_type = native_read_msr(MTRR_PHYS_BASE_MSR(top_mtrr)) & 0xff;
/* Make sure this MTRR is the correct Write-Protected type */
- if (top_type == MTRR_TYPE_WP) {
- disable_caches();
- wrmsrl(MTRRphysBase_MSR(top_mtrr), 0);
- wrmsrl(MTRRphysMask_MSR(top_mtrr), 0);
- enable_caches();
+ if (top_type == MTRR_TYPE_WRPROT) {
+ struct mtrr_state state;
+
+ mtrr_open(&state);
+ wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0);
+ wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0);
+ mtrr_close(&state);
}
/* Issue SMI to Coreboot to lock down ME and registers */
diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c
index 6a3dd93914..c9983f1588 100644
--- a/arch/x86/cpu/coreboot/pci.c
+++ b/arch/x86/cpu/coreboot/pci.c
@@ -13,6 +13,8 @@
#include <pci.h>
#include <asm/pci.h>
+DECLARE_GLOBAL_DATA_PTR;
+
static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
struct pci_config_table *table)
{
@@ -35,7 +37,31 @@ void board_pci_setup_hose(struct pci_controller *hose)
hose->first_busno = 0;
hose->last_busno = 0;
- pci_set_region(hose->regions + 0, 0x0, 0x0, 0xffffffff,
+ /* PCI memory space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_PCI_MEM_BUS,
+ CONFIG_PCI_MEM_PHYS,
+ CONFIG_PCI_MEM_SIZE,
PCI_REGION_MEM);
- hose->region_count = 1;
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 1,
+ CONFIG_PCI_IO_BUS,
+ CONFIG_PCI_IO_PHYS,
+ CONFIG_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ pci_set_region(hose->regions + 2,
+ CONFIG_PCI_PREF_BUS,
+ CONFIG_PCI_PREF_PHYS,
+ CONFIG_PCI_PREF_SIZE,
+ PCI_REGION_PREFETCH);
+
+ pci_set_region(hose->regions + 3,
+ 0,
+ 0,
+ gd->ram_size,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ hose->region_count = 4;
}
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c
index bd3558a021..0edee6bd2c 100644
--- a/arch/x86/cpu/coreboot/timestamp.c
+++ b/arch/x86/cpu/coreboot/timestamp.c
@@ -3,18 +3,7 @@
*
* 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
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
@@ -38,9 +27,27 @@ static struct timestamp_table *ts_table __attribute__((section(".data")));
void timestamp_init(void)
{
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+ uint64_t base_time;
+#endif
+
ts_table = lib_sysinfo.tstamp_table;
#ifdef CONFIG_SYS_X86_TSC_TIMER
- timer_set_base(ts_table->base_time);
+ /*
+ * If coreboot is built with CONFIG_COLLECT_TIMESTAMPS, use the value
+ * of base_time in coreboot's timestamp table as our timer base,
+ * otherwise TSC counter value will be used.
+ *
+ * Sometimes even coreboot is built with CONFIG_COLLECT_TIMESTAMPS,
+ * the value of base_time in the timestamp table is still zero, so
+ * we must exclude this case too (this is currently seen on booting
+ * coreboot in qemu)
+ */
+ if (ts_table && ts_table->base_time)
+ base_time = ts_table->base_time;
+ else
+ base_time = rdtsc();
+ timer_set_base(base_time);
#endif
timestamp_add_now(TS_U_BOOT_INITTED);
}
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S
index dca68e4144..9441666f5a 100644
--- a/arch/x86/cpu/ivybridge/car.S
+++ b/arch/x86/cpu/ivybridge/car.S
@@ -12,9 +12,11 @@
*/
#include <common.h>
+#include <asm/msr-index.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor-flags.h>
+#include <asm/arch/microcode.h>
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
@@ -45,6 +47,14 @@ car_init:
movl $0xFEE00300, %esi
movl %eax, (%esi)
+ /* TODO: Load microcode later - the 'no eviction' mode breaks this */
+ movl $MSR_IA32_UCODE_WRITE, %ecx
+ xorl %edx, %edx
+ movl $_dt_ucode_base_size, %eax
+ movl (%eax), %eax
+ addl $UCODE_HEADER_LEN, %eax
+ wrmsr
+
post_code(POST_CAR_SIPI)
/* Zero out all fixed range and variable range MTRRs */
movl $mtrr_table, %esi
@@ -61,7 +71,7 @@ clear_mtrrs:
post_code(POST_CAR_MTRR)
/* Configure the default memory type to uncacheable */
- movl $MTRRdefType_MSR, %ecx
+ movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
@@ -76,16 +86,16 @@ clear_mtrrs:
post_code(POST_CAR_BASE_ADDRESS)
/* Set Cache-as-RAM mask */
movl $(MTRR_PHYS_MASK_MSR(0)), %ecx
- movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
+ movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
post_code(POST_CAR_MASK)
/* Enable MTRR */
- movl $MTRRdefType_MSR, %ecx
+ movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
- orl $MTRRdefTypeEn, %eax
+ orl $MTRR_DEF_TYPE_EN, %eax
wrmsr
/* Enable cache (CR0.CD = 0, CR0.NW = 0) */
@@ -130,7 +140,7 @@ clear_mtrrs:
movl $MTRR_PHYS_MASK_MSR(1), %ecx
movl $CPU_PHYSMASK_HI, %edx
- movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
+ movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
wrmsr
post_code(POST_CAR_ROM_CACHE)
@@ -141,7 +151,7 @@ clear_mtrrs:
xorl %edx, %edx
wrmsr
movl $MTRR_PHYS_MASK_MSR(2), %ecx
- movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
+ movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
#endif
@@ -163,6 +173,52 @@ wait_for_sipi:
/* return */
jmp car_init_ret
+.globl car_uninit
+car_uninit:
+ /* Disable cache */
+ movl %cr0, %eax
+ orl $X86_CR0_CD, %eax
+ movl %eax, %cr0
+
+ /* Disable MTRRs */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ andl $(~MTRR_DEF_TYPE_EN), %eax
+ wrmsr
+
+ /* 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
+
+#ifdef CONFIG_CACHE_MRC_BIN
+ /* Clear the MTRR that was used to cache MRC */
+ xorl %eax, %eax
+ xorl %edx, %edx
+ movl $MTRR_PHYS_BASE_MSR(2), %ecx
+ wrmsr
+ movl $MTRR_PHYS_MASK_MSR(2), %ecx
+ wrmsr
+#endif
+
+ /* Enable MTRRs */
+ movl $MTRR_DEF_TYPE_MSR, %ecx
+ rdmsr
+ orl $MTRR_DEF_TYPE_EN, %eax
+ wrmsr
+
+ invd
+
+ ret
+
mtrr_table:
/* Fixed MTRRs */
.word 0x250, 0x258, 0x259
@@ -176,3 +232,9 @@ mtrr_table:
.word 0x20C, 0x20D, 0x20E, 0x20F
.word 0x210, 0x211, 0x212, 0x213
mtrr_table_end:
+
+ .align 4
+_dt_ucode_base_size:
+ /* These next two fields are filled in by ifdtool */
+ .long 0 /* microcode base */
+ .long 0 /* microcode size */
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index 969b07b059..e9253100f6 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -49,27 +49,6 @@ static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
}
-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 */
- wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
- wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
- (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
-}
-
-static void enable_rom_caching(void)
-{
- disable_caches();
- set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
- enable_caches();
-
- /* Enable Variable MTRRs */
- wrmsr(MTRRdefType_MSR, 0x800, 0);
-}
-
static int set_flex_ratio_to_tdp_nominal(void)
{
msr_t flex_ratio, msr;
@@ -165,10 +144,6 @@ int arch_cpu_init(void)
/* This is already done in start.S, but let's do it in C */
enable_port80_on_lpc(hose, PCH_LPC_DEV);
- /* already done in car.S */
- if (false)
- enable_rom_caching();
-
set_spi_speed();
/*
@@ -288,7 +263,7 @@ int print_cpuinfo(void)
enable_lapic();
ret = microcode_update_intel();
- if (ret && ret != -ENOENT && ret != -EEXIST)
+ if (ret)
return ret;
/* Enable upper 128bytes of CMOS */
diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c
index 3d7f740273..6cf9654e02 100644
--- a/arch/x86/cpu/ivybridge/gma.c
+++ b/arch/x86/cpu/ivybridge/gma.c
@@ -12,9 +12,11 @@
#include <fdtdec.h>
#include <pci_rom.h>
#include <asm/io.h>
+#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/pch.h>
#include <asm/arch/sandybridge.h>
+#include <linux/kconfig.h>
struct gt_powermeter {
u16 reg;
@@ -730,7 +732,11 @@ static int int15_handler(void)
int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
const void *blob, int node)
{
+#ifdef CONFIG_VIDEO
+ ulong start;
+#endif
void *gtt_bar;
+ ulong base;
u32 reg32;
int ret;
@@ -739,14 +745,22 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
pci_write_config32(dev, PCI_COMMAND, reg32);
+ /* Use write-combining for the graphics memory, 256MB */
+ base = pci_read_bar32(hose, dev, 2);
+ mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20);
+ mtrr_commit(true);
+
gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0);
debug("GT bar %p\n", gtt_bar);
ret = gma_pm_init_pre_vbios(gtt_bar);
if (ret)
return ret;
+#ifdef CONFIG_VIDEO
+ start = get_timer(0);
ret = pci_run_vga_bios(dev, int15_handler, false);
-
+ debug("BIOS ran in %lums\n", get_timer(start));
+#endif
/* Post VBIOS init */
ret = gma_pm_init_post_vbios(gtt_bar, blob, node);
if (ret)
diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c
index 08177510ab..2440a97c48 100644
--- a/arch/x86/cpu/ivybridge/microcode_intel.c
+++ b/arch/x86/cpu/ivybridge/microcode_intel.c
@@ -13,7 +13,9 @@
#include <libfdt.h>
#include <asm/cpu.h>
#include <asm/msr.h>
+#include <asm/msr-index.h>
#include <asm/processor.h>
+#include <asm/arch/microcode.h>
/**
* struct microcode_update - standard microcode header from Intel
@@ -40,8 +42,8 @@ static int microcode_decode_node(const void *blob, int node,
update->data = fdt_getprop(blob, node, "data", &update->size);
if (!update->data)
return -EINVAL;
- update->data += 48;
- update->size -= 48;
+ update->data += UCODE_HEADER_LEN;
+ update->size -= UCODE_HEADER_LEN;
update->header_version = fdtdec_get_int(blob, node,
"intel,header-version", 0);
@@ -71,15 +73,16 @@ static inline uint32_t microcode_read_rev(void)
asm volatile (
"xorl %%eax, %%eax\n"
"xorl %%edx, %%edx\n"
- "movl $0x8b, %%ecx\n"
+ "movl %2, %%ecx\n"
"wrmsr\n"
"movl $0x01, %%eax\n"
"cpuid\n"
- "movl $0x8b, %%ecx\n"
+ "movl %2, %%ecx\n"
"rdmsr\n"
: /* outputs */
"=a" (low), "=d" (high)
: /* inputs */
+ "i" (MSR_IA32_UCODE_REV)
: /* clobbers */
"ebx", "ecx"
);
@@ -94,9 +97,9 @@ static void microcode_read_cpu(struct microcode_update *cpu)
struct cpuid_result result;
uint32_t low, high;
- wrmsr(0x8b, 0, 0);
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
result = cpuid(1);
- rdmsr(0x8b, low, cpu->update_revision);
+ rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision);
x86_model = (result.eax >> 4) & 0x0f;
x86_family = (result.eax >> 8) & 0x0f;
cpu->processor_signature = result.eax;
@@ -120,6 +123,7 @@ int microcode_update_intel(void)
int count;
int node;
int ret;
+ int rev;
microcode_read_cpu(&cpu);
node = 0;
@@ -147,12 +151,16 @@ int microcode_update_intel(void)
skipped++;
continue;
}
- ret = microcode_read_rev();
- wrmsr(0x79, (ulong)update.data, 0);
+ wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0);
+ rev = microcode_read_rev();
debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
- microcode_read_rev(), update.date_code & 0xffff,
+ rev, update.date_code & 0xffff,
(update.date_code >> 24) & 0xff,
(update.date_code >> 16) & 0xff);
+ if (update.update_revision != rev) {
+ printf("Microcode update failed\n");
+ return -EFAULT;
+ }
count++;
} while (1);
}
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index b95e781bbf..95047359ff 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -17,6 +17,7 @@
#include <asm/processor.h>
#include <asm/gpio.h>
#include <asm/global_data.h>
+#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/me.h>
#include <asm/arch/pei_data.h>
@@ -430,6 +431,15 @@ static int sdram_find(pci_dev_t dev)
add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28);
add_memory_area(info, (4 << 28) + (2 << 20), tseg_base);
add_memory_area(info, 1ULL << 32, touud);
+
+ /* Add MTRRs for memory */
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
+ mtrr_add_request(MTRR_TYPE_WRBACK, 2ULL << 30, 512 << 20);
+ mtrr_add_request(MTRR_TYPE_WRBACK, 0xaULL << 28, 256 << 20);
+ mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base, 16 << 20);
+ mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base + (16 << 20),
+ 32 << 20);
+
/*
* If >= 4GB installed then memory from TOLUD to 4GB
* is remapped above TOM, TOUUD will account for both
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c
new file mode 100644
index 0000000000..d5a825d181
--- /dev/null
+++ b/arch/x86/cpu/mtrr.c
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Memory Type Range Regsters - these are used to tell the CPU whether
+ * memory is cacheable and if so the cache write mode to use.
+ *
+ * These can speed up booting. See the mtrr command.
+ *
+ * Reference: Intel Architecture Software Developer's Manual, Volume 3:
+ * System Programming
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+
+/* Prepare to adjust MTRRs */
+void mtrr_open(struct mtrr_state *state)
+{
+ state->enable_cache = dcache_status();
+
+ if (state->enable_cache)
+ disable_caches();
+ state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
+ wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
+}
+
+/* Clean up after adjusting MTRRs, and enable them */
+void mtrr_close(struct mtrr_state *state)
+{
+ wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
+ if (state->enable_cache)
+ enable_caches();
+}
+
+int mtrr_commit(bool do_caches)
+{
+ struct mtrr_request *req = gd->arch.mtrr_req;
+ struct mtrr_state state;
+ uint64_t mask;
+ int i;
+
+ mtrr_open(&state);
+ for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
+ mask = ~(req->size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type);
+ wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID);
+ }
+
+ /* Clear the ones that are unused */
+ for (; i < MTRR_COUNT; i++)
+ wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
+ mtrr_close(&state);
+
+ return 0;
+}
+
+int mtrr_add_request(int type, uint64_t start, uint64_t size)
+{
+ struct mtrr_request *req;
+ uint64_t mask;
+
+ if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
+ return -ENOSPC;
+ req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
+ req->type = type;
+ req->start = start;
+ req->size = size;
+ debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1,
+ req->type, req->start, req->size);
+ mask = ~(req->size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ mask |= MTRR_PHYS_MASK_VALID;
+ debug(" %016llx %016llx\n", req->start | req->type, mask);
+
+ return 0;
+}
diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c
index f3492c3851..ab1aaaa059 100644
--- a/arch/x86/cpu/pci.c
+++ b/arch/x86/cpu/pci.c
@@ -15,6 +15,8 @@
#include <pci.h>
#include <asm/pci.h>
+DECLARE_GLOBAL_DATA_PTR;
+
static struct pci_controller x86_hose;
int pci_early_init_hose(struct pci_controller **hosep)
@@ -27,7 +29,8 @@ int pci_early_init_hose(struct pci_controller **hosep)
board_pci_setup_hose(hose);
pci_setup_type1(hose);
- gd->arch.hose = hose;
+ hose->last_busno = pci_hose_scan(hose);
+ gd->hose = hose;
*hosep = hose;
return 0;
@@ -48,7 +51,7 @@ void pci_init_board(void)
struct pci_controller *hose = &x86_hose;
/* Stop using the early hose */
- gd->arch.hose = NULL;
+ gd->hose = NULL;
board_pci_setup_hose(hose);
pci_setup_type1(hose);
@@ -61,8 +64,8 @@ void pci_init_board(void)
static struct pci_controller *get_hose(void)
{
- if (gd->arch.hose)
- return gd->arch.hose;
+ if (gd->hose)
+ return gd->hose;
return pci_bus_to_hose(0);
}
diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c
index ef1916b2e7..aed3e2b300 100644
--- a/arch/x86/cpu/queensbay/fsp_support.c
+++ b/arch/x86/cpu/queensbay/fsp_support.c
@@ -231,26 +231,28 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
u32 fsp_get_usable_lowmem_top(const void *hob_list)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u32 top;
/* Get the HOB list for processing */
- hob.raw = (void *)hob_list;
+ hdr = hob_list;
/* * Collect memory ranges */
top = FSP_LOWMEM_BASE;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_SYS_MEM) {
- phys_start = hob.res_desc->phys_start;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM) {
+ phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= FSP_LOWMEM_BASE &&
phys_start < (phys_addr_t)FSP_HIGHMEM_BASE)
- top += (u32)(hob.res_desc->len);
+ top += (u32)(res_desc->len);
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return top;
@@ -258,25 +260,27 @@ u32 fsp_get_usable_lowmem_top(const void *hob_list)
u64 fsp_get_usable_highmem_top(const void *hob_list)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u64 top;
/* Get the HOB list for processing */
- hob.raw = (void *)hob_list;
+ hdr = hob_list;
/* Collect memory ranges */
top = FSP_HIGHMEM_BASE;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_SYS_MEM) {
- phys_start = hob.res_desc->phys_start;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM) {
+ phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE)
- top += (u32)(hob.res_desc->len);
+ top += (u32)(res_desc->len);
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return top;
@@ -285,24 +289,26 @@ u64 fsp_get_usable_highmem_top(const void *hob_list)
u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len,
struct efi_guid *guid)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
/* Get the HOB list for processing */
- hob.raw = (void *)hob_list;
+ hdr = hob_list;
/* Collect memory ranges */
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_MEM_RESERVED) {
- if (compare_guid(&hob.res_desc->owner, guid)) {
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_MEM_RESERVED) {
+ if (compare_guid(&res_desc->owner, guid)) {
if (len)
- *len = (u32)(hob.res_desc->len);
+ *len = (u32)(res_desc->len);
- return (u64)(hob.res_desc->phys_start);
+ return (u64)(res_desc->phys_start);
}
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return 0;
@@ -336,44 +342,45 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
return base;
}
-void *fsp_get_next_hob(u16 type, const void *hob_list)
+const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list)
{
- union hob_pointers hob;
+ const struct hob_header *hdr;
- assert(hob_list != NULL);
-
- hob.raw = (u8 *)hob_list;
+ hdr = hob_list;
/* Parse the HOB list until end of list or matching type is found */
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == type)
- return hob.raw;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == type)
+ return hdr;
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
return NULL;
}
-void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list)
+const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
+ const void *hob_list)
{
- union hob_pointers hob;
-
- hob.raw = (u8 *)hob_list;
- while ((hob.raw = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
- hob.raw)) != NULL) {
- if (compare_guid(guid, &hob.guid->name))
+ const struct hob_header *hdr;
+ struct hob_guid *guid_hob;
+
+ hdr = hob_list;
+ while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
+ hdr)) != NULL) {
+ guid_hob = (struct hob_guid *)hdr;
+ if (compare_guid(guid, &(guid_hob->name)))
break;
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
- return hob.raw;
+ return hdr;
}
void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
struct efi_guid *guid)
{
- u8 *guid_hob;
+ const struct hob_header *guid_hob;
guid_hob = fsp_get_next_guid_hob(guid, hob_list);
if (guid_hob == NULL) {
diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c
index 8e97c9b82a..df79a39dd8 100644
--- a/arch/x86/cpu/queensbay/tnc_dram.c
+++ b/arch/x86/cpu/queensbay/tnc_dram.c
@@ -14,17 +14,19 @@ DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
phys_size_t ram_size = 0;
- union hob_pointers hob;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
- hob.raw = gd->arch.hob_list;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- if (hob.res_desc->type == RES_SYS_MEM ||
- hob.res_desc->type == RES_MEM_RESERVED) {
- ram_size += hob.res_desc->len;
+ hdr = gd->arch.hob_list;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ if (res_desc->type == RES_SYS_MEM ||
+ res_desc->type == RES_MEM_RESERVED) {
+ ram_size += res_desc->len;
}
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
}
gd->ram_size = ram_size;
@@ -55,22 +57,23 @@ ulong board_get_usable_ram_top(ulong total_size)
unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
{
unsigned num_entries = 0;
+ const struct hob_header *hdr;
+ struct hob_res_desc *res_desc;
- union hob_pointers hob;
+ hdr = gd->arch.hob_list;
- hob.raw = gd->arch.hob_list;
+ while (!end_of_hob(hdr)) {
+ if (hdr->type == HOB_TYPE_RES_DESC) {
+ res_desc = (struct hob_res_desc *)hdr;
+ entries[num_entries].addr = res_desc->phys_start;
+ entries[num_entries].size = res_desc->len;
- while (!end_of_hob(hob)) {
- if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
- entries[num_entries].addr = hob.res_desc->phys_start;
- entries[num_entries].size = hob.res_desc->len;
-
- if (hob.res_desc->type == RES_SYS_MEM)
+ if (res_desc->type == RES_SYS_MEM)
entries[num_entries].type = E820_RAM;
- else if (hob.res_desc->type == RES_MEM_RESERVED)
+ else if (res_desc->type == RES_MEM_RESERVED)
entries[num_entries].type = E820_RESERVED;
}
- hob.raw = get_next_hob(hob);
+ hdr = get_next_hob(hdr);
num_entries++;
}
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 125782cf27..f51f1121d0 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -205,6 +205,14 @@ board_init_f_r_trampoline:
/* Setup global descriptor table so gd->xyz works */
call setup_gdt
+ /* Set if we need to disable CAR */
+.weak car_uninit
+ movl $car_uninit, %eax
+ cmpl $0, %eax
+ jz 1f
+
+ call car_uninit
+1:
/* Re-enter U-Boot by calling board_init_f_r */
call board_init_f_r
OpenPOWER on IntegriCloud