Merge git://git.denx.de/u-boot-x86
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ebf72b3..90e828a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -47,13 +47,10 @@
 	hex
 	default 0x100000
 
-config RAMTOP
-	hex
-	default 0x200000
-
 config XIP_ROM_SIZE
 	hex
-	default 0x10000
+	depends on X86_RESET_VECTOR
+	default ROM_SIZE
 
 config CPU_ADDR_BITS
 	int
@@ -69,6 +66,15 @@
 
 config SMM_TSEG_SIZE
 	hex
+
+config X86_RESET_VECTOR
+	bool
+	default n
+
+config SYS_X86_START16
+	hex
+	depends on X86_RESET_VECTOR
+	default 0xfffff800
 
 config BOARD_ROMSIZE_KB_512
 	bool
@@ -85,6 +91,7 @@
 
 choice
 	prompt "ROM chip size"
+	depends on X86_RESET_VECTOR
 	default UBOOT_ROMSIZE_KB_512 if BOARD_ROMSIZE_KB_512
 	default UBOOT_ROMSIZE_KB_1024 if BOARD_ROMSIZE_KB_1024
 	default UBOOT_ROMSIZE_KB_2048 if BOARD_ROMSIZE_KB_2048
@@ -317,6 +324,28 @@
 
 endmenu
 
+config TSC_CALIBRATION_BYPASS
+	bool "Bypass Time-Stamp Counter (TSC) calibration"
+	default n
+	help
+	  By default U-Boot automatically calibrates Time-Stamp Counter (TSC)
+	  running frequency via Model-Specific Register (MSR) and Programmable
+	  Interval Timer (PIT). If the calibration does not work on your board,
+	  select this option and provide a hardcoded TSC running frequency with
+	  CONFIG_TSC_FREQ_IN_MHZ below.
+
+	  Normally this option should be turned on in a simulation environment
+	  like qemu.
+
+config TSC_FREQ_IN_MHZ
+	int "Time-Stamp Counter (TSC) running frequency in MHz"
+	depends on TSC_CALIBRATION_BYPASS
+	default 1000
+	help
+	  The running frequency in MHz of Time-Stamp Counter (TSC).
+
+source "arch/x86/cpu/coreboot/Kconfig"
+
 source "arch/x86/cpu/ivybridge/Kconfig"
 
 source "arch/x86/cpu/queensbay/Kconfig"
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 5033d2b..62e43c0 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -17,5 +17,6 @@
 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 0000000..e0e3c64
--- /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 cfacc05..6d06d5a 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 @@
 	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 @@
 	 * 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 6a3dd93..c9983f1 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 @@
 	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 bd3558a..0edee6b 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 @@
 
 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 dca68e4..9441666 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 @@
 	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 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 	/* 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 @@
 	.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 969b07b..e925310 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -49,27 +49,6 @@
 	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 @@
 	/* 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 @@
 	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 3d7f740..6cf9654 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 @@
 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 @@
 	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 0817751..2440a97 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 @@
 	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 @@
 	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 @@
 	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 count;
 	int node;
 	int ret;
+	int rev;
 
 	microcode_read_cpu(&cpu);
 	node = 0;
@@ -147,12 +151,16 @@
 			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 b95e781..9504735 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 @@
 	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 0000000..d5a825d
--- /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 f3492c3..ab1aaaa 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 @@
 
 	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 @@
 	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 @@
 
 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 ef1916b..aed3e2b 100644
--- a/arch/x86/cpu/queensbay/fsp_support.c
+++ b/arch/x86/cpu/queensbay/fsp_support.c
@@ -231,26 +231,28 @@
 
 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 @@
 
 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_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 @@
 	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;
+	const struct hob_header *hdr;
+	struct hob_guid *guid_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))
+	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 8e97c9b..df79a39 100644
--- a/arch/x86/cpu/queensbay/tnc_dram.c
+++ b/arch/x86/cpu/queensbay/tnc_dram.c
@@ -14,17 +14,19 @@
 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 @@
 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 125782c..f51f112 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -205,6 +205,14 @@
 	/* 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
 
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 3b5d6da..97ed884 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -1,6 +1,4 @@
-dtb-y += link.dtb \
-	chromebook_link.dtb \
-	alex.dtb \
+dtb-y += chromebook_link.dtb \
 	crownbay.dtb
 
 targets += $(dtb-y)
diff --git a/arch/x86/dts/alex.dts b/arch/x86/dts/alex.dts
deleted file mode 100644
index 2f13544..0000000
--- a/arch/x86/dts/alex.dts
+++ /dev/null
@@ -1,24 +0,0 @@
-/dts-v1/;
-
-/include/ "coreboot.dtsi"
-
-/ {
-	#address-cells = <1>;
-	#size-cells = <1>;
-	model = "Google Alex";
-	compatible = "google,alex", "intel,atom-pineview";
-
-	config {
-	       silent_console = <0>;
-	};
-
-	gpio: gpio {};
-
-	serial {
-		reg = <0x3f8 8>;
-		clock-frequency = <115200>;
-	};
-
-	chosen { };
-	memory { device_type = "memory"; reg = <0 0>; };
-};
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
deleted file mode 120000
index 6f8c5cd..0000000
--- a/arch/x86/dts/chromebook_link.dts
+++ /dev/null
@@ -1 +0,0 @@
-link.dts
\ No newline at end of file
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/chromebook_link.dts
similarity index 94%
rename from arch/x86/dts/link.dts
rename to arch/x86/dts/chromebook_link.dts
index a739080..9490b16 100644
--- a/arch/x86/dts/link.dts
+++ b/arch/x86/dts/chromebook_link.dts
@@ -1,10 +1,9 @@
 /dts-v1/;
 
-/include/ "coreboot.dtsi"
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
 	model = "Google Link";
 	compatible = "google,link", "intel,celeron-ivybridge";
 
@@ -33,14 +32,10 @@
 		bank-name = "C";
 	};
 
-	serial {
-		reg = <0x3f8 8>;
-		clock-frequency = <115200>;
+	chosen {
+		stdout-path = "/serial";
 	};
 
-	chosen { };
-	memory { device_type = "memory"; reg = <0 0>; };
-
 	spd {
 		compatible = "memory-spd";
 		#address-cells = <1>;
@@ -214,9 +209,6 @@
 
 	microcode {
 		update@0 {
-#include "microcode/m12206a7_00000029.dtsi"
-		};
-		update@1 {
 #include "microcode/m12306a9_0000001b.dtsi"
 		};
 	};
diff --git a/arch/x86/dts/coreboot.dtsi b/arch/x86/dts/coreboot.dtsi
deleted file mode 100644
index 65a93ac..0000000
--- a/arch/x86/dts/coreboot.dtsi
+++ /dev/null
@@ -1,17 +0,0 @@
-/include/ "skeleton.dtsi"
-
-/ {
-	chosen {
-		stdout-path = "/serial";
-	};
-
-	serial {
-		compatible = "x86-uart";
-		reg = <0x3f8 0x10>;
-		reg-shift = <0>;
-		io-mapped = <1>;
-		multiplier = <1>;
-		baudrate = <115200>;
-		status = "disabled";
-	};
-};
diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts
index 3f43f3c..e81054e 100644
--- a/arch/x86/dts/crownbay.dts
+++ b/arch/x86/dts/crownbay.dts
@@ -6,11 +6,10 @@
 
 /dts-v1/;
 
-/include/ "coreboot.dtsi"
+/include/ "skeleton.dtsi"
+/include/ "serial.dtsi"
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
 	model = "Intel Crown Bay";
 	compatible = "intel,crownbay", "intel,queensbay";
 
@@ -32,14 +31,18 @@
 		bank-name = "B";
 	};
 
-	serial {
-		reg = <0x3f8 8>;
-		clock-frequency = <115200>;
+	chosen {
+		/*
+		 * By default the legacy superio serial port is used as the
+		 * U-Boot serial console. If we want to use UART from Topcliff
+		 * PCH as the console, change this property to &pciuart#.
+		 *
+		 * For example, stdout-path = &pciuart0 will use the first
+		 * UART on Topcliff PCH.
+		 */
+		stdout-path = "/serial";
 	};
 
-	chosen { };
-	memory { device_type = "memory"; reg = <0 0>; };
-
 	spi {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -57,4 +60,77 @@
 		};
 	};
 
+	pci {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		compatible = "intel,pci";
+		device_type = "pci";
+
+		pcie@17,0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			compatible = "intel,pci";
+			device_type = "pci";
+
+			topcliff@0,0 {
+				#address-cells = <3>;
+				#size-cells = <2>;
+				compatible = "intel,pci";
+				device_type = "pci";
+
+				pciuart0: uart@a,1 {
+					compatible = "pci8086,8811.00",
+							"pci8086,8811",
+							"pciclass,070002",
+							"pciclass,0700",
+							"x86-uart";
+					reg = <0x00025100 0x0 0x0 0x0 0x0
+					       0x01025110 0x0 0x0 0x0 0x0>;
+					reg-shift = <0>;
+					clock-frequency = <1843200>;
+					current-speed = <115200>;
+				};
+
+				pciuart1: uart@a,2 {
+					compatible = "pci8086,8812.00",
+							"pci8086,8812",
+							"pciclass,070002",
+							"pciclass,0700",
+							"x86-uart";
+					reg = <0x00025200 0x0 0x0 0x0 0x0
+					       0x01025210 0x0 0x0 0x0 0x0>;
+					reg-shift = <0>;
+					clock-frequency = <1843200>;
+					current-speed = <115200>;
+				};
+
+				pciuart2: uart@a,3 {
+					compatible = "pci8086,8813.00",
+							"pci8086,8813",
+							"pciclass,070002",
+							"pciclass,0700",
+							"x86-uart";
+					reg = <0x00025300 0x0 0x0 0x0 0x0
+					       0x01025310 0x0 0x0 0x0 0x0>;
+					reg-shift = <0>;
+					clock-frequency = <1843200>;
+					current-speed = <115200>;
+				};
+
+				pciuart3: uart@a,4 {
+					compatible = "pci8086,8814.00",
+							"pci8086,8814",
+							"pciclass,070002",
+							"pciclass,0700",
+							"x86-uart";
+					reg = <0x00025400 0x0 0x0 0x0 0x0
+					       0x01025410 0x0 0x0 0x0 0x0>;
+					reg-shift = <0>;
+					clock-frequency = <1843200>;
+					current-speed = <115200>;
+				};
+			};
+		};
+	};
+
 };
diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi
new file mode 100644
index 0000000..9b097f4
--- /dev/null
+++ b/arch/x86/dts/serial.dtsi
@@ -0,0 +1,9 @@
+/ {
+	serial {
+		compatible = "x86-uart";
+		reg = <0x3f8 8>;
+		reg-shift = <0>;
+		clock-frequency = <1843200>;
+		current-speed = <115200>;
+	};
+};
diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h
index bc9b87c..b868283 100644
--- a/arch/x86/include/asm/arch-ivybridge/microcode.h
+++ b/arch/x86/include/asm/arch-ivybridge/microcode.h
@@ -7,6 +7,11 @@
 #ifndef __ASM_ARCH_MICROCODE_H
 #define __ASM_ARCH_MICROCODE_H
 
+/* Length of the public header on Intel microcode blobs */
+#define UCODE_HEADER_LEN	0x30
+
+#ifndef __ASSEMBLY__
+
 /**
  * microcode_update_intel() - Apply microcode updates
  *
@@ -16,5 +21,6 @@
  * not updates were found, -EINVAL if an update was invalid
  */
 int microcode_update_intel(void);
+#endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
index 380b64e..6cca7f5 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
+++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h
@@ -182,58 +182,19 @@
 	/* GUID specific data goes here */
 };
 
-/* Union of all the possible HOB Types */
-union hob_pointers {
-	struct hob_header	*hdr;
-	struct hob_mem_alloc	*mem_alloc;
-	struct hob_res_desc	*res_desc;
-	struct hob_guid		*guid;
-	u8			*raw;
-};
-
-/**
- * get_hob_type() - return the type of a HOB
- *
- * This macro returns the type field from the HOB header for the
- * HOB specified by hob.
- *
- * @hob:    A pointer to a HOB.
- *
- * @return: HOB type.
- */
-static inline u16 get_hob_type(union hob_pointers hob)
-{
-	return hob.hdr->type;
-}
-
-/**
- * get_hob_length() - return the length, in bytes, of a HOB
- *
- * This macro returns the len field from the HOB header for the
- * HOB specified by hob.
- *
- * @hob:    A pointer to a HOB.
- *
- * @return: HOB length.
- */
-static inline u16 get_hob_length(union hob_pointers hob)
-{
-	return hob.hdr->len;
-}
-
 /**
  * get_next_hob() - return a pointer to the next HOB in the HOB list
  *
  * This macro returns a pointer to HOB that follows the HOB specified by hob
  * in the HOB List.
  *
- * @hob:    A pointer to a HOB.
+ * @hdr:    A pointer to a HOB.
  *
  * @return: A pointer to the next HOB in the HOB list.
  */
-static inline void *get_next_hob(union hob_pointers hob)
+static inline const struct hob_header *get_next_hob(const struct hob_header *hdr)
 {
-	return (void *)(*(u8 **)&(hob) + get_hob_length(hob));
+	return (const struct hob_header *)((u32)hdr + hdr->len);
 }
 
 /**
@@ -243,14 +204,14 @@
  * HOB list.  If hob is last HOB in the HOB list, then true is returned.
  * Otherwise, false is returned.
  *
- * @hob:          A pointer to a HOB.
+ * @hdr:          A pointer to a HOB.
  *
- * @retval true:  The HOB specified by hob is the last HOB in the HOB list.
- * @retval false: The HOB specified by hob is not the last HOB in the HOB list.
+ * @retval true:  The HOB specified by hdr is the last HOB in the HOB list.
+ * @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
  */
-static inline bool end_of_hob(union hob_pointers hob)
+static inline bool end_of_hob(const struct hob_header *hdr)
 {
-	return get_hob_type(hob) == HOB_TYPE_EOH;
+	return hdr->type == HOB_TYPE_EOH;
 }
 
 /**
@@ -260,13 +221,13 @@
  * This macro returns a pointer to the data buffer in a HOB specified by hob.
  * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
  *
- * @hob:    A pointer to a HOB.
+ * @hdr:    A pointer to a HOB.
  *
  * @return: A pointer to the data buffer in a HOB.
  */
-static inline void *get_guid_hob_data(u8 *hob)
+static inline void *get_guid_hob_data(const struct hob_header *hdr)
 {
-	return (void *)(hob + sizeof(struct hob_guid));
+	return (void *)((u32)hdr + sizeof(struct hob_guid));
 }
 
 /**
@@ -276,14 +237,13 @@
  * This macro returns the size, in bytes, of the data buffer in a HOB
  * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
  *
- * @hob:    A pointer to a HOB.
+ * @hdr:    A pointer to a HOB.
  *
  * @return: The size of the data buffer.
  */
-static inline u16 get_guid_hob_data_size(u8 *hob)
+static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
 {
-	union hob_pointers hob_p = *(union hob_pointers *)hob;
-	return get_hob_length(hob_p) - sizeof(struct hob_guid);
+	return hdr->len - sizeof(struct hob_guid);
 }
 
 /* FSP specific GUID HOB definitions */
diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
index 3ae1b66..ebdbd03 100644
--- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
+++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h
@@ -145,7 +145,7 @@
  *
  * @retval:   A HOB object with matching type; Otherwise NULL.
  */
-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);
 
 /**
  * Returns the next instance of the matched GUID HOB from the starting HOB.
@@ -155,7 +155,8 @@
  *
  * @retval:   A HOB object with matching GUID; Otherwise 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);
 
 /**
  * This function retrieves a GUID HOB data buffer and size.
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 03d491a..24e3052 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -29,6 +29,19 @@
 	struct memory_area area[CONFIG_NR_DRAM_BANKS];
 };
 
+#define MAX_MTRR_REQUESTS	8
+
+/**
+ * A request for a memory region to be set up in a particular way. These
+ * requests are processed before board_init_r() is called. They are generally
+ * optional and can be ignored with some performance impact.
+ */
+struct mtrr_request {
+	int type;		/* MTRR_TYPE_... */
+	uint64_t start;
+	uint64_t size;
+};
+
 /* Architecture-specific global data */
 struct arch_global_data {
 	struct global_data *gd_addr;		/* Location of Global Data */
@@ -43,13 +56,14 @@
 	uint32_t tsc_mhz;		/* TSC frequency in MHz */
 	void *new_fdt;			/* Relocated FDT */
 	uint32_t bist;			/* Built-in self test value */
-	struct pci_controller *hose;	/* PCI hose for early use */
 	enum pei_boot_mode_t pei_boot_mode;
 	const struct pch_gpio_map *gpio_map;	/* board GPIO map */
 	struct memory_info meminfo;	/* Memory information */
 #ifdef CONFIG_HAVE_FSP
 	void	*hob_list;		/* FSP HOB list */
 #endif
+	struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
+	int mtrr_req_count;
 };
 
 #endif
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 5f05a48..3c11740 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -9,99 +9,86 @@
 #ifndef _ASM_MTRR_H
 #define _ASM_MTRR_H
 
-/*  These are the region types  */
-#define MTRR_TYPE_UNCACHEABLE 0
-#define MTRR_TYPE_WRCOMB     1
-/*#define MTRR_TYPE_         2*/
-/*#define MTRR_TYPE_         3*/
-#define MTRR_TYPE_WRTHROUGH  4
-#define MTRR_TYPE_WRPROT     5
-#define MTRR_TYPE_WRBACK     6
-#define MTRR_NUM_TYPES       7
+/* MTRR region types */
+#define MTRR_TYPE_UNCACHEABLE	0
+#define MTRR_TYPE_WRCOMB	1
+#define MTRR_TYPE_WRTHROUGH	4
+#define MTRR_TYPE_WRPROT	5
+#define MTRR_TYPE_WRBACK	6
 
-#define MTRRcap_MSR     0x0fe
-#define MTRRdefType_MSR 0x2ff
+#define MTRR_TYPE_COUNT		7
 
-#define MTRRdefTypeEn		(1 << 11)
-#define MTRRdefTypeFixEn	(1 << 10)
+#define MTRR_CAP_MSR		0x0fe
+#define MTRR_DEF_TYPE_MSR	0x2ff
 
-#define SMRRphysBase_MSR 0x1f2
-#define SMRRphysMask_MSR 0x1f3
+#define MTRR_DEF_TYPE_EN	(1 << 11)
+#define MTRR_DEF_TYPE_FIX_EN	(1 << 10)
 
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+#define MTRR_PHYS_BASE_MSR(reg)	(0x200 + 2 * (reg))
+#define MTRR_PHYS_MASK_MSR(reg)	(0x200 + 2 * (reg) + 1)
 
-#define MTRRphysMaskValid	(1 << 11)
+#define MTRR_PHYS_MASK_VALID	(1 << 11)
 
-#define NUM_FIXED_RANGES 88
-#define RANGES_PER_FIXED_MTRR 8
-#define MTRRfix64K_00000_MSR 0x250
-#define MTRRfix16K_80000_MSR 0x258
-#define MTRRfix16K_A0000_MSR 0x259
-#define MTRRfix4K_C0000_MSR 0x268
-#define MTRRfix4K_C8000_MSR 0x269
-#define MTRRfix4K_D0000_MSR 0x26a
-#define MTRRfix4K_D8000_MSR 0x26b
-#define MTRRfix4K_E0000_MSR 0x26c
-#define MTRRfix4K_E8000_MSR 0x26d
-#define MTRRfix4K_F0000_MSR 0x26e
-#define MTRRfix4K_F8000_MSR 0x26f
+#define MTRR_BASE_TYPE_MASK	0x7
+
+/* Number of MTRRs supported */
+#define MTRR_COUNT		8
 
 #if !defined(__ASSEMBLER__)
 
-/*
- * The MTRR code has some side effects that the callers should be aware for.
- * 1. The call sequence matters. x86_setup_mtrrs() calls
- *    x86_setup_fixed_mtrrs_no_enable() then enable_fixed_mtrrs() (equivalent
- *    of x86_setup_fixed_mtrrs()) then x86_setup_var_mtrrs(). If the callers
- *    want to call the components of x86_setup_mtrrs() because of other
- *    rquirements the ordering should still preserved.
- * 2. enable_fixed_mtrr() will enable both variable and fixed MTRRs because
- *    of the nature of the global MTRR enable flag. Therefore, all direct
- *    or indirect callers of enable_fixed_mtrr() should ensure that the
- *    variable MTRR MSRs do not contain bad ranges.
- * 3. If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling
- *    the caching of the ROM. However, it is set to uncacheable (UC). It
- *    is the responsiblity of the caller to enable it by calling
- *    x86_mtrr_enable_rom_caching().
+/**
+ * Information about the previous MTRR state, set up by mtrr_open()
+ *
+ * @deftype:		Previous value of MTRR_DEF_TYPE_MSR
+ * @enable_cache:	true if cache was enabled
  */
-void x86_setup_mtrrs(void);
-/*
- * x86_setup_var_mtrrs() parameters:
- * address_bits - number of physical address bits supported by cpu
- * above4gb - 2 means dynamically detect number of variable MTRRs available.
- *            non-zero means handle memory ranges above 4GiB.
- *            0 means ignore memory ranges above 4GiB
+struct mtrr_state {
+	uint64_t deftype;
+	bool enable_cache;
+};
+
+/**
+ * mtrr_open() - Prepare to adjust MTRRs
+ *
+ * Use mtrr_open() passing in a structure - this function will init it. Then
+ * when done, pass the same structure to mtrr_close() to re-enable MTRRs and
+ * possibly the cache.
+ *
+ * @state:	Empty structure to pass in to hold settings
  */
-void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb);
-void enable_fixed_mtrr(void);
-void x86_setup_fixed_mtrrs(void);
-/* Set up fixed MTRRs but do not enable them. */
-void x86_setup_fixed_mtrrs_no_enable(void);
-int x86_mtrr_check(void);
-/* ROM caching can be used after variable MTRRs are set up. Beware that
- * enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on
- * one's IO hole size and WRCOMB resources. Be sure to check the console
- * log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. Beware that
- * on CPUs with core-scoped MTRR registers such as hyperthreaded CPUs the
- * rom caching will be disabled if all threads run the MTRR code. Therefore,
- * one needs to call x86_mtrr_enable_rom_caching() after all threads of the
- * same core have run the MTRR code. */
-#if CONFIG_CACHE_ROM
-void x86_mtrr_enable_rom_caching(void);
-void x86_mtrr_disable_rom_caching(void);
-/* Return the variable range MTRR index of the ROM cache. */
-long x86_mtrr_rom_cache_var_index(void);
-#else
-static inline void x86_mtrr_enable_rom_caching(void) {}
-static inline void x86_mtrr_disable_rom_caching(void) {}
-static inline long x86_mtrr_rom_cache_var_index(void) { return -1; }
-#endif /* CONFIG_CACHE_ROM */
+void mtrr_open(struct mtrr_state *state);
 
-#endif
+/**
+ * mtrr_open() - Clean up after adjusting MTRRs, and enable them
+ *
+ * This uses the structure containing information returned from mtrr_open().
+ *
+ * @state:	Structure from mtrr_open()
+ */
+/*  */
+void mtrr_close(struct mtrr_state *state);
+
+/**
+ * mtrr_add_request() - Add a new MTRR request
+ *
+ * This adds a request for a memory region to be set up in a particular way.
+ *
+ * @type:	Requested type (MTRR_TYPE_)
+ * @start:	Start address
+ * @size:	Size
+ */
+int mtrr_add_request(int type, uint64_t start, uint64_t size);
+
+/**
+ * mtrr_commit() - set up the MTRR registers based on current requests
+ *
+ * This sets up MTRRs for the available DRAM and the requests received so far.
+ * It must be called with caches disabled.
+ *
+ * @do_caches:	true if caches are currently on
+ */
+int mtrr_commit(bool do_caches);
 
-#if !defined(CONFIG_RAMTOP)
-# error "CONFIG_RAMTOP not defined"
 #endif
 
 #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
@@ -114,8 +101,4 @@
 
 #define CACHE_ROM_BASE	(((1 << 20) - (CONFIG_CACHE_ROM_SIZE >> 12)) << 12)
 
-#if (CONFIG_RAMTOP & (CONFIG_RAMTOP - 1)) != 0
-# error "CONFIG_RAMTOP must be a power of 2"
-#endif
-
 #endif
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index ac1a808..c30dd4c 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -29,7 +29,7 @@
  * pci_early_init_hose() - Set up PCI host before relocation
  *
  * This allocates memory for, sets up and returns the PCI hose. It can be
- * called before relocation. The hose will be stored in gd->arch.hose for
+ * called before relocation. The hose will be stored in gd->hose for
  * later use, but will become invalid one DRAM is available.
  */
 int pci_early_init_hose(struct pci_controller **hosep);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 73262d7..32d7b98 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -14,6 +14,7 @@
 obj-y	+= gcc.o
 obj-y	+= init_helpers.o
 obj-y	+= interrupts.o
+obj-y += cmd_mtrr.o
 obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
 obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o
 obj-$(CONFIG_PCI) += pci_type1.o
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
index d1f8933..1d75cfc 100644
--- a/arch/x86/lib/bios.c
+++ b/arch/x86/lib/bios.c
@@ -207,12 +207,14 @@
 
 static u8 vbe_set_mode(struct vbe_mode_info *mi)
 {
-	debug("VBE: Setting VESA mode %#04x\n", mi->video_mode);
+	int video_mode = mi->video_mode;
+
+	debug("VBE: Setting VESA mode %#04x\n", video_mode);
 	/* request linear framebuffer mode */
-	mi->video_mode |= (1 << 14);
-	/* request clearing of framebuffer */
-	mi->video_mode &= ~(1 << 15);
-	realmode_interrupt(0x10, VESA_SET_MODE, mi->video_mode,
+	video_mode |= (1 << 14);
+	/* don't clear the framebuffer, we do that later */
+	video_mode |= (1 << 15);
+	realmode_interrupt(0x10, VESA_SET_MODE, video_mode,
 			   0x0000, 0x0000, 0x0000, 0x0000);
 
 	return 0;
@@ -236,6 +238,7 @@
 		return;
 	}
 
+	mode_info->video_mode &= 0x3ff;
 	vbe_set_mode(mode_info);
 }
 
@@ -262,7 +265,6 @@
 	/* Make sure the code is placed. */
 	setup_realmode_code();
 
-	disable_caches();
 	debug("Calling Option ROM at %lx, pci device %#x...", addr, num_dev);
 
 	/* Option ROM entry point is at OPROM start + 3 */
diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c
index b552fe6..a0ef037 100644
--- a/arch/x86/lib/cmd_hob.c
+++ b/arch/x86/lib/cmd_hob.c
@@ -28,20 +28,20 @@
 
 int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	union hob_pointers hob;
-	u16 type;
+	const struct hob_header *hdr;
+	uint type;
 	char *desc;
 	int i = 0;
 
-	hob.raw = (u8 *)gd->arch.hob_list;
+	hdr = gd->arch.hob_list;
 
-	printf("HOB list address: 0x%08x\n\n", (unsigned int)hob.raw);
+	printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
 
 	printf("No. | Address  | Type                | Length in Bytes\n");
 	printf("----|----------|---------------------|----------------\n");
-	while (!end_of_hob(hob)) {
-		printf("%-3d | %08x | ", i, (unsigned int)hob.raw);
-		type = get_hob_type(hob);
+	while (!end_of_hob(hdr)) {
+		printf("%-3d | %08x | ", i, (unsigned int)hdr);
+		type = hdr->type;
 		if (type == HOB_TYPE_UNUSED)
 			desc = "*Unused*";
 		else if (type == HOB_TYPE_EOH)
@@ -50,8 +50,8 @@
 			desc = hob_type[type];
 		else
 			desc = "*Invalid Type*";
-		printf("%-19s | %-15d\n", desc, get_hob_length(hob));
-		hob.raw = get_next_hob(hob);
+		printf("%-19s | %-15d\n", desc, hdr->len);
+		hdr = get_next_hob(hdr);
 		i++;
 	}
 
diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c
new file mode 100644
index 0000000..7e0506b
--- /dev/null
+++ b/arch/x86/lib/cmd_mtrr.c
@@ -0,0 +1,138 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+
+static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
+	"Uncacheable",
+	"Combine",
+	"2",
+	"3",
+	"Through",
+	"Protect",
+	"Back",
+};
+
+static int do_mtrr_list(void)
+{
+	int i;
+
+	printf("Reg Valid Write-type   %-16s %-16s %-16s\n", "Base   ||",
+	       "Mask   ||", "Size   ||");
+	for (i = 0; i < MTRR_COUNT; i++) {
+		const char *type = "Invalid";
+		uint64_t base, mask, size;
+		bool valid;
+
+		base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
+		mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
+		size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
+		size |= (1 << 12) - 1;
+		size += 1;
+		valid = mask & MTRR_PHYS_MASK_VALID;
+		type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
+		printf("%d   %-5s %-12s %016llx %016llx %016llx\n", i,
+		       valid ? "Y" : "N", type, base, mask, size);
+	}
+
+	return 0;
+}
+
+static int do_mtrr_set(uint reg, int argc, char * const argv[])
+{
+	const char *typename = argv[0];
+	struct mtrr_state state;
+	uint32_t start, size;
+	uint64_t base, mask;
+	int i, type = -1;
+	bool valid;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+	for (i = 0; i < MTRR_TYPE_COUNT; i++) {
+		if (*typename == *mtrr_type_name[i])
+			type = i;
+	}
+	if (type == -1) {
+		printf("Invalid type name %s\n", typename);
+		return CMD_RET_USAGE;
+	}
+	start = simple_strtoul(argv[1], NULL, 16);
+	size = simple_strtoul(argv[2], NULL, 16);
+
+	base = start | type;
+	valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
+	mask = ~((uint64_t)size - 1);
+	mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+	if (valid)
+		mask |= MTRR_PHYS_MASK_VALID;
+
+	printf("base=%llx, mask=%llx\n", base, mask);
+	mtrr_open(&state);
+	wrmsrl(MTRR_PHYS_BASE_MSR(reg), base);
+	wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
+	mtrr_close(&state);
+
+	return 0;
+}
+
+static int mtrr_set_valid(int reg, bool valid)
+{
+	struct mtrr_state state;
+	uint64_t mask;
+
+	mtrr_open(&state);
+	mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg));
+	if (valid)
+		mask |= MTRR_PHYS_MASK_VALID;
+	else
+		mask &= ~MTRR_PHYS_MASK_VALID;
+	wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
+	mtrr_close(&state);
+
+	return 0;
+}
+
+static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const char *cmd;
+	uint reg;
+
+	cmd = argv[1];
+	if (argc < 2 || *cmd == 'l')
+		return do_mtrr_list();
+	argc -= 2;
+	argv += 2;
+	if (argc <= 0)
+		return CMD_RET_USAGE;
+	reg = simple_strtoul(argv[0], NULL, 16);
+	if (reg >= MTRR_COUNT) {
+		printf("Invalid register number\n");
+		return CMD_RET_USAGE;
+	}
+	if (*cmd == 'e')
+		return mtrr_set_valid(reg, true);
+	else if (*cmd == 'd')
+		return mtrr_set_valid(reg, false);
+	else if (*cmd == 's')
+		return do_mtrr_set(reg, argc - 1, argv + 1);
+	else
+		return CMD_RET_USAGE;
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	mtrr,	6,	1,	do_mtrr,
+	"Use x86 memory type range registers (32-bit only)",
+	"[list]        - list current registers\n"
+	"set <reg> <type> <start> <size>   - set a register\n"
+	"\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
+	"disable <reg>      - disable a register\n"
+	"ensable <reg>      - enable a register"
+);
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index be4eb12..fc211d9 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <fdtdec.h>
 #include <spi.h>
+#include <asm/mtrr.h>
 #include <asm/sections.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -66,6 +67,13 @@
 
 int init_cache_f_r(void)
 {
+#if defined(CONFIG_X86_RESET_VECTOR) & !defined(CONFIG_HAVE_FSP)
+	int ret;
+
+	ret = mtrr_commit(false);
+	if (ret)
+		return ret;
+#endif
 	/* Initialise the CPU cache(s) */
 	return init_cache();
 }
diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c
index fb9afed..7f5ba2c 100644
--- a/arch/x86/lib/tsc_timer.c
+++ b/arch/x86/lib/tsc_timer.c
@@ -78,7 +78,7 @@
  *
  * Returns the calibration value or 0 if MSR calibration failed.
  */
-static unsigned long try_msr_calibrate_tsc(void)
+static unsigned long __maybe_unused try_msr_calibrate_tsc(void)
 {
 	u32 lo, hi, ratio, freq_id, freq;
 	unsigned long res;
@@ -199,7 +199,7 @@
 #define MAX_QUICK_PIT_MS 50
 #define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
 
-static unsigned long quick_pit_calibrate(void)
+static unsigned long __maybe_unused quick_pit_calibrate(void)
 {
 	int i;
 	u64 tsc, delta;
@@ -306,6 +306,9 @@
 	if (gd->arch.tsc_mhz)
 		return gd->arch.tsc_mhz;
 
+#ifdef CONFIG_TSC_CALIBRATION_BYPASS
+	fast_calibrate = CONFIG_TSC_FREQ_IN_MHZ;
+#else
 	fast_calibrate = try_msr_calibrate_tsc();
 	if (!fast_calibrate) {
 
@@ -313,6 +316,7 @@
 		if (!fast_calibrate)
 			panic("TSC frequency is ZERO");
 	}
+#endif
 
 	gd->arch.tsc_mhz = fast_calibrate;
 	return fast_calibrate;
diff --git a/board/coreboot/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig
index 6ca6ced..981de1f 100644
--- a/board/coreboot/coreboot/Kconfig
+++ b/board/coreboot/coreboot/Kconfig
@@ -9,7 +9,32 @@
 config SYS_SOC
 	default "coreboot"
 
+comment "coreboot-specific options"
+
 config SYS_CONFIG_NAME
-	default "coreboot"
+	string "Board configuration file"
+	default "chromebook_link"
+	help
+	  This option selects the board configuration file in include/configs/
+	  directory to be used to build U-Boot for coreboot.
+
+config DEFAULT_DEVICE_TREE
+	string "Board Device Tree Source (dts) file"
+	default "chromebook_link"
+	help
+	  This option selects the board Device Tree Source (dts) file in
+	  arch/x86/dts/ directory to be used to build U-Boot for coreboot.
+
+config SYS_CAR_ADDR
+	hex "Board specific Cache-As-RAM (CAR) address"
+	default 0x19200000
+	help
+	  This option specifies the board specific Cache-As-RAM (CAR) address.
+
+config SYS_CAR_SIZE
+	hex "Board specific Cache-As-RAM (CAR) size"
+	default 0x4000
+	help
+	  This option specifies the board specific Cache-As-RAM (CAR) size.
 
 endif
diff --git a/board/coreboot/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS
index 6ce66f5..2736aa0 100644
--- a/board/coreboot/coreboot/MAINTAINERS
+++ b/board/coreboot/coreboot/MAINTAINERS
@@ -2,5 +2,5 @@
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	board/coreboot/coreboot/
-F:	include/configs/coreboot.h
+F:	include/configs/chromebook_link.h
 F:	configs/coreboot-x86_defconfig
diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c
index 154faf6..e076ea6 100644
--- a/board/coreboot/coreboot/coreboot.c
+++ b/board/coreboot/coreboot/coreboot.c
@@ -10,8 +10,10 @@
 
 int arch_early_init_r(void)
 {
+#ifdef CONFIG_CROS_EC
 	if (cros_ec_board_init())
 		return -1;
+#endif
 
 	return 0;
 }
diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig
index 7f79fd2..33a31f3 100644
--- a/board/google/chromebook_link/Kconfig
+++ b/board/google/chromebook_link/Kconfig
@@ -14,6 +14,7 @@
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select X86_RESET_VECTOR
 	select CPU_INTEL_SOCKET_RPGA989
 	select NORTHBRIDGE_INTEL_IVYBRIDGE
 	select SOUTHBRIDGE_INTEL_C216
@@ -29,4 +30,12 @@
 	bool "Enable early post to Chrome OS EC"
 	default y
 
+config SYS_CAR_ADDR
+	hex
+	default 0xff7e0000
+
+config SYS_CAR_SIZE
+	hex
+	default 0x20000
+
 endif
diff --git a/board/intel/crownbay/Kconfig b/board/intel/crownbay/Kconfig
index 4709f9b..762663a 100644
--- a/board/intel/crownbay/Kconfig
+++ b/board/intel/crownbay/Kconfig
@@ -14,6 +14,7 @@
 
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
+	select X86_RESET_VECTOR
 	select INTEL_QUEENSBAY
 	select BOARD_ROMSIZE_KB_1024
 
diff --git a/common/board_f.c b/common/board_f.c
index cfd77f8..3a4b32c 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -985,6 +985,11 @@
 	INIT_FUNC_WATCHDOG_RESET
 	reloc_fdt,
 	setup_reloc,
+#ifdef CONFIG_X86
+	copy_uboot_to_ram,
+	clear_bss,
+	do_elf_reloc_fixups,
+#endif
 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
 	jump_to_copy,
 #endif
@@ -1044,9 +1049,6 @@
  */
 static init_fnc_t init_sequence_f_r[] = {
 	init_cache_f_r,
-	copy_uboot_to_ram,
-	clear_bss,
-	do_elf_reloc_fixups,
 
 	NULL,
 };
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig
index b83803e..e956835 100644
--- a/configs/chromebook_link_defconfig
+++ b/configs/chromebook_link_defconfig
@@ -6,5 +6,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
 CONFIG_HAVE_MRC=y
 CONFIG_SMM_TSEG_SIZE=0x800000
+CONFIG_VIDEO_X86=y
 CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
 CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig
index 6249db7..3cc034a 100644
--- a/configs/coreboot-x86_defconfig
+++ b/configs/coreboot-x86_defconfig
@@ -2,4 +2,3 @@
 CONFIG_X86=y
 CONFIG_TARGET_COREBOOT=y
 CONFIG_OF_CONTROL=y
-CONFIG_DEFAULT_DEVICE_TREE="link"
diff --git a/doc/README.x86 b/doc/README.x86
index 5fab044..7df8cc5 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -32,6 +32,21 @@
 $ make coreboot-x86_defconfig
 $ make all
 
+Note this default configuration will build a U-Boot payload for the Link board.
+To build a coreboot payload against another board, you can change the build
+configuration during the 'make menuconfig' process.
+
+x86 architecture  --->
+	...
+	(chromebook_link) Board configuration file
+	(chromebook_link) Board Device Tree Source (dts) file
+	(0x19200000) Board specific Cache-As-RAM (CAR) address
+	(0x4000) Board specific Cache-As-RAM (CAR) size
+
+Change the 'Board configuration file' and 'Board Device Tree Source (dts) file'
+to point to a new board. You can also change the Cache-As-RAM (CAR) related
+settings here if the default values do not fit your new board.
+
 Building ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
 little bit tricky, as generally it requires several binary blobs which are not
 shipped in the U-Boot source tree. Due to this reason, the u-boot.rom build is
@@ -88,11 +103,31 @@
 Rename the first one to fsp.bin and second one to cmc.bin and put them in the
 board directory.
 
-Now you can build U-Boot and obtaim u-boot.rom
+Now you can build U-Boot and obtain u-boot.rom
 
 $ make crownbay_defconfig
 $ make all
 
+Test with coreboot
+------------------
+For testing U-Boot as the coreboot payload, there are things that need be paid
+attention to. coreboot supports loading an ELF executable and a 32-bit plain
+binary, as well as other supported payloads. With the default configuration,
+U-Boot is set up to use a separate Device Tree Blob (dtb). As of today, the
+generated u-boot-dtb.bin needs to be packaged by the cbfstool utility (a tool
+provided by coreboot) manually as coreboot's 'make menuconfig' does not provide
+this capability yet. The command is as follows:
+
+# in the coreboot root directory
+$ ./build/util/cbfstool/cbfstool build/coreboot.rom add-flat-binary \
+  -f u-boot-dtb.bin -n fallback/payload -c lzma -l 0x1110000 -e 0x1110015
+
+Make sure 0x1110000 matches CONFIG_SYS_TEXT_BASE and 0x1110015 matches the
+symbol address of _start (in arch/x86/cpu/start.S).
+
+If you want to use ELF as the coreboot payload, change U-Boot configuration to
+use CONFIG_OF_EMBED.
+
 CPU Microcode
 -------------
 Modern CPU usually requires a special bit stream called microcode [5] to be
@@ -106,13 +141,29 @@
 Device Tree
 -----------
 x86 uses device tree to configure the board thus requires CONFIG_OF_CONTROL to
-be turned on. Not every device on the board is configured via devie tree, but
+be turned on. Not every device on the board is configured via device tree, but
 more and more devices will be added as time goes by. Check out the directory
 arch/x86/dts/ for these device tree source files.
 
+Useful Commands
+---------------
+
+In keeping with the U-Boot philosophy of providing functions to check and
+adjust internal settings, there are several x86-specific commands that may be
+useful:
+
+hob  - Display information about Firmware Support Package (FSP) Hand-off
+	 Block. This is only available on platforms which use FSP, mostly
+	 Atom.
+iod  - Display I/O memory
+iow  - Write I/O memory
+mtrr - List and set the Memory Type Range Registers (MTRR). These are used to
+	 tell the CPU whether memory is cacheable and if so the cache write
+	 mode to use. U-Boot sets up some reasonable values but you can
+	 adjust then with this command.
+
 TODO List
 ---------
-- MTRR support (for performance)
 - Audio
 - Chrome OS verified boot
 - SMI and ACPI support, to provide platform info and facilities to Linux
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3daf73c..83fd9a0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -19,6 +19,8 @@
 #include <asm/io.h>
 #include <pci.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define PCI_HOSE_OP(rw, size, type)					\
 int pci_hose_##rw##_config_##size(struct pci_controller *hose,		\
 				  pci_dev_t dev,			\
@@ -123,6 +125,14 @@
 
 static struct pci_controller* hose_head;
 
+struct pci_controller *pci_get_hose_head(void)
+{
+	if (gd->hose)
+		return gd->hose;
+
+	return hose_head;
+}
+
 void pci_register_hose(struct pci_controller* hose)
 {
 	struct pci_controller **phose = &hose_head;
@@ -139,7 +149,7 @@
 {
 	struct pci_controller *hose;
 
-	for (hose = hose_head; hose; hose = hose->next) {
+	for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 		if (bus >= hose->first_busno && bus <= hose->last_busno)
 			return hose;
 	}
@@ -152,7 +162,7 @@
 {
 	struct pci_controller *hose;
 
-	for (hose = hose_head; hose; hose = hose->next) {
+	for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 		if (hose->cfg_addr == cfg_addr)
 			return hose;
 	}
@@ -162,7 +172,7 @@
 
 int pci_last_busno(void)
 {
-	struct pci_controller *hose = hose_head;
+	struct pci_controller *hose = pci_get_hose_head();
 
 	if (!hose)
 		return -1;
@@ -181,7 +191,7 @@
 	pci_dev_t bdf;
 	int i, bus, found_multi = 0;
 
-	for (hose = hose_head; hose; hose = hose->next) {
+	for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 #ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
 		for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
 #else
@@ -233,7 +243,7 @@
 
 pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
 {
-	static struct pci_device_id ids[2] = {{}, {0, 0}};
+	struct pci_device_id ids[2] = { {}, {0, 0} };
 
 	ids[0].vendor = vendor;
 	ids[0].device = device;
@@ -709,11 +719,10 @@
 int pci_hose_scan(struct pci_controller *hose)
 {
 #if defined(CONFIG_PCI_BOOTDELAY)
-	static int pcidelay_done;
 	char *s;
 	int i;
 
-	if (!pcidelay_done) {
+	if (!gd->pcidelay_done) {
 		/* wait "pcidelay" ms (if defined)... */
 		s = getenv("pcidelay");
 		if (s) {
@@ -721,7 +730,7 @@
 			for (i = 0; i < val; i++)
 				udelay(1000);
 		}
-		pcidelay_done = 1;
+		gd->pcidelay_done = 1;
 	}
 #endif /* CONFIG_PCI_BOOTDELAY */
 
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index af6a3ae..7d25cc9 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -156,6 +156,8 @@
 
 	target = (void *)PCI_VGA_RAM_IMAGE_START;
 	if (target != rom_header) {
+		ulong start = get_timer(0);
+
 		debug("Copying VGA ROM Image from %p to %p, 0x%x bytes\n",
 		      rom_header, target, rom_size);
 		memcpy(target, rom_header, rom_size);
@@ -163,6 +165,7 @@
 			printf("VGA ROM copy failed\n");
 			return -EFAULT;
 		}
+		debug("Copy took %lums\n", get_timer(start));
 	}
 	*ram_headerp = target;
 
@@ -205,7 +208,7 @@
 	gdev->vprBase = vesa->phys_base_ptr;
 	gdev->cprBase = vesa->phys_base_ptr;
 
-	return 0;
+	return gdev->winSizeX ? 0 : -ENOSYS;
 #else
 	return -ENOSYS;
 #endif
@@ -244,7 +247,7 @@
 		defined(CONFIG_FRAMEBUFFER_VESA_MODE)
 	vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
 #endif
-	debug("Selected vesa mode %d\b", vesa_mode);
+	debug("Selected vesa mode %#x\n", vesa_mode);
 	if (emulate) {
 #ifdef CONFIG_BIOSEMU
 		BE_VGAInfo *info;
@@ -272,7 +275,7 @@
 		return -ENOSYS;
 #endif
 	}
-	debug("Final vesa mode %d\n", mode_info.video_mode);
+	debug("Final vesa mode %#x\n", mode_info.video_mode);
 
 	return 0;
 }
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index a03ad5f..f9e05ad 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -458,6 +458,7 @@
 				      unsigned int *index,
 				      unsigned int *lanes)
 {
+	struct fdt_pci_addr addr;
 	pci_dev_t bdf;
 	int err;
 
@@ -469,7 +470,7 @@
 
 	*lanes = err;
 
-	err = fdtdec_pci_get_bdf(fdt, node, &bdf);
+	err = fdtdec_get_pci_bdf(fdt, node, &addr, &bdf);
 	if (err < 0) {
 		error("failed to parse \"reg\" property");
 		return err;
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index af5beba..70c9462 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -289,7 +289,38 @@
 	struct ns16550_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
+	/* try Processor Local Bus device first */
 	addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+#ifdef CONFIG_PCI
+	if (addr == FDT_ADDR_T_NONE) {
+		/* then try pci device */
+		struct fdt_pci_addr pci_addr;
+		u32 bar;
+		int ret;
+
+		/* we prefer to use a memory-mapped register */
+		ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset,
+					  FDT_PCI_SPACE_MEM32, "reg",
+					  &pci_addr);
+		if (ret) {
+			/* try if there is any i/o-mapped register */
+			ret = fdtdec_get_pci_addr(gd->fdt_blob,
+						  dev->of_offset,
+						  FDT_PCI_SPACE_IO,
+						  "reg", &pci_addr);
+			if (ret)
+				return ret;
+		}
+
+		ret = fdtdec_get_pci_bar32(gd->fdt_blob, dev->of_offset,
+					   &pci_addr, &bar);
+		if (ret)
+			return ret;
+
+		addr = bar;
+	}
+#endif
+
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_x86.c b/drivers/serial/serial_x86.c
index e81e035..4bf6062 100644
--- a/drivers/serial/serial_x86.c
+++ b/drivers/serial/serial_x86.c
@@ -6,9 +6,12 @@
 
 #include <common.h>
 #include <dm.h>
+#include <fdtdec.h>
 #include <ns16550.h>
 #include <serial.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 static const struct udevice_id x86_serial_ids[] = {
 	{ .compatible = "x86-uart" },
 	{ }
@@ -22,10 +25,13 @@
 	ret = ns16550_serial_ofdata_to_platdata(dev);
 	if (ret)
 		return ret;
-	plat->clock = 1843200;
+
+	plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+				     "clock-frequency", 1843200);
 
 	return 0;
 }
+
 U_BOOT_DRIVER(serial_ns16550) = {
 	.name	= "serial_x86",
 	.id	= UCLASS_SERIAL,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e69de29..fdbf3f6 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -0,0 +1,8 @@
+config VIDEO_X86
+	bool "Enable x86 video driver support"
+	depends on X86
+	default n
+	help
+	  Turn on this option to enable a very simple driver which uses vesa
+	  to discover the video mode and then provides a frame buffer for use
+	  by U-Boot.
diff --git a/drivers/video/x86_fb.c b/drivers/video/x86_fb.c
index 8743a8c..6641033 100644
--- a/drivers/video/x86_fb.c
+++ b/drivers/video/x86_fb.c
@@ -32,6 +32,7 @@
 	sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
 		bits_per_pixel);
 	printf("%s\n", gdev->modeIdent);
+	debug("Frame buffer at %x\n", gdev->frameAdrs);
 
 	return (void *)gdev;
 }
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 9c5a1e1..3d14d5f1 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -91,6 +91,12 @@
 	unsigned long malloc_limit;	/* limit address */
 	unsigned long malloc_ptr;	/* current address */
 #endif
+#ifdef CONFIG_PCI
+	struct pci_controller *hose;	/* PCI hose for early use */
+#endif
+#ifdef CONFIG_PCI_BOOTDELAY
+	int pcidelay_done;
+#endif
 	struct udevice *cur_serial_dev;	/* current serial device */
 	struct arch_global_data arch;	/* architecture-specific data */
 } gd_t;
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h
index 8930210..7e6d239 100644
--- a/include/configs/chromebook_link.h
+++ b/include/configs/chromebook_link.h
@@ -15,15 +15,12 @@
 
 #include <configs/x86-common.h>
 
-#define CONFIG_SYS_CAR_ADDR			0xff7e0000
-#define CONFIG_SYS_CAR_SIZE			(128 * 1024)
+
 #define CONFIG_SYS_MONITOR_LEN			(1 << 20)
+
 #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE		0x4000
-#define CONFIG_SYS_X86_START16			0xfffff800
 #define CONFIG_BOARD_EARLY_INIT_F
-#define CONFIG_DISPLAY_CPUINFO
 
-#define CONFIG_X86_RESET_VECTOR
 #define CONFIG_NR_DRAM_BANKS			8
 #define CONFIG_X86_MRC_ADDR			0xfffa0000
 #define CONFIG_CACHE_MRC_SIZE_KB		512
@@ -41,7 +38,6 @@
 
 #define CONFIG_X86_OPTION_ROM_FILE		pci8086,0166.bin
 #define CONFIG_X86_OPTION_ROM_ADDR		0xfff90000
-#define CONFIG_VIDEO_X86
 
 #define CONFIG_PCI_MEM_BUS	0xe0000000
 #define CONFIG_PCI_MEM_PHYS	CONFIG_PCI_MEM_BUS
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
deleted file mode 100644
index 990a2d1..0000000
--- a/include/configs/coreboot.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (C) Copyright 2008
- * Graeme Russ, graeme.russ@gmail.com.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/*
- * board/config.h - configuration options, board specific
- */
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-#include <configs/x86-common.h>
-
-/*
- * High Level Configuration Options
- * (easy to change)
- */
-#define CONFIG_SYS_COREBOOT
-#define CONFIG_LAST_STAGE_INIT
-#define CONFIG_SYS_EARLY_PCI_INIT
-
-#define CONFIG_SYS_CAR_ADDR			0x19200000
-#define CONFIG_SYS_CAR_SIZE			(16 * 1024)
-#define CONFIG_SYS_MONITOR_LEN			(256 * 1024)
-
-#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
-#define CONFIG_TRACE_EARLY
-#define CONFIG_TRACE_EARLY_ADDR		0x01400000
-
-#define CONFIG_BOOTSTAGE
-#define CONFIG_BOOTSTAGE_REPORT
-#define CONFIG_BOOTSTAGE_FDT
-#define CONFIG_CMD_BOOTSTAGE
-/* Place to stash bootstage data from first-stage U-Boot */
-#define CONFIG_BOOTSTAGE_STASH		0x0110f000
-#define CONFIG_BOOTSTAGE_STASH_SIZE	0x7fc
-#define CONFIG_BOOTSTAGE_USER_COUNT	60
-
-#define CONFIG_SCSI_DEV_LIST		{PCI_VENDOR_ID_INTEL, \
-			PCI_DEVICE_ID_INTEL_NM10_AHCI},	      \
-	{PCI_VENDOR_ID_INTEL,		\
-			PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \
-	{PCI_VENDOR_ID_INTEL, \
-			PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_SERIES6}, \
-	{PCI_VENDOR_ID_INTEL,		\
-			PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}
-
-#define CONFIG_X86_SERIAL
-
-#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
-					"stdout=vga,serial,cbmem\0" \
-					"stderr=vga,serial,cbmem\0"
-
-#define CONFIG_CBMEM_CONSOLE
-
-#define CONFIG_VIDEO_COREBOOT
-
-#define CONFIG_NR_DRAM_BANKS			4
-
-#define CONFIG_TRACE
-#define CONFIG_CMD_TRACE
-#define CONFIG_TRACE_BUFFER_SIZE	(16 << 20)
-
-#define CONFIG_BOOTDELAY	2
-
-#define CONFIG_CROS_EC
-#define CONFIG_CROS_EC_LPC
-#define CONFIG_CMD_CROS_EC
-#define CONFIG_ARCH_EARLY_INIT_R
-
-#endif	/* __CONFIG_H */
diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h
index eadb339..b927b1c 100644
--- a/include/configs/crownbay.h
+++ b/include/configs/crownbay.h
@@ -14,10 +14,8 @@
 #include <configs/x86-common.h>
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
-#define CONFIG_SYS_X86_START16		0xfffff800
 #define CONFIG_BOARD_EARLY_INIT_F
 
-#define CONFIG_X86_RESET_VECTOR
 #define CONFIG_NR_DRAM_BANKS		1
 
 #define CONFIG_X86_SERIAL
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 5effa24..75af750 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -15,6 +15,7 @@
  */
 
 #include <libfdt.h>
+#include <pci.h>
 
 /*
  * A typedef for a physical address. Note that fdt data is always big
@@ -50,6 +51,49 @@
 	fdt_addr_t end;
 };
 
+enum fdt_pci_space {
+	FDT_PCI_SPACE_CONFIG = 0,
+	FDT_PCI_SPACE_IO = 0x01000000,
+	FDT_PCI_SPACE_MEM32 = 0x02000000,
+	FDT_PCI_SPACE_MEM64 = 0x03000000,
+	FDT_PCI_SPACE_MEM32_PREF = 0x42000000,
+	FDT_PCI_SPACE_MEM64_PREF = 0x43000000,
+};
+
+#define FDT_PCI_ADDR_CELLS	3
+#define FDT_PCI_SIZE_CELLS	2
+#define FDT_PCI_REG_SIZE	\
+	((FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS) * sizeof(u32))
+
+/*
+ * The Open Firmware spec defines PCI physical address as follows:
+ *
+ *          bits# 31 .... 24 23 .... 16 15 .... 08 07 .... 00
+ *
+ * phys.hi  cell:  npt000ss   bbbbbbbb   dddddfff   rrrrrrrr
+ * phys.mid cell:  hhhhhhhh   hhhhhhhh   hhhhhhhh   hhhhhhhh
+ * phys.lo  cell:  llllllll   llllllll   llllllll   llllllll
+ *
+ * where:
+ *
+ * n:        is 0 if the address is relocatable, 1 otherwise
+ * p:        is 1 if addressable region is prefetchable, 0 otherwise
+ * t:        is 1 if the address is aliased (for non-relocatable I/O) below 1MB
+ *           (for Memory), or below 64KB (for relocatable I/O)
+ * ss:       is the space code, denoting the address space
+ * bbbbbbbb: is the 8-bit Bus Number
+ * ddddd:    is the 5-bit Device Number
+ * fff:      is the 3-bit Function Number
+ * rrrrrrrr: is the 8-bit Register Number
+ * hhhhhhhh: is a 32-bit unsigned number
+ * llllllll: is a 32-bit unsigned number
+ */
+struct fdt_pci_addr {
+	u32	phys_hi;
+	u32	phys_mid;
+	u32	phys_lo;
+};
+
 /**
  * Compute the size of a resource.
  *
@@ -258,6 +302,60 @@
 		const char *prop_name, fdt_size_t *sizep);
 
 /**
+ * Look at an address property in a node and return the pci address which
+ * corresponds to the given type in the form of fdt_pci_addr.
+ * The property must hold one fdt_pci_addr with a lengh.
+ *
+ * @param blob		FDT blob
+ * @param node		node to examine
+ * @param type		pci address type (FDT_PCI_SPACE_xxx)
+ * @param prop_name	name of property to find
+ * @param addr		returns pci address in the form of fdt_pci_addr
+ * @return 0 if ok, negative on error
+ */
+int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
+		const char *prop_name, struct fdt_pci_addr *addr);
+
+/**
+ * Look at the compatible property of a device node that represents a PCI
+ * device and extract pci vendor id and device id from it.
+ *
+ * @param blob		FDT blob
+ * @param node		node to examine
+ * @param vendor	vendor id of the pci device
+ * @param device	device id of the pci device
+ * @return 0 if ok, negative on error
+ */
+int fdtdec_get_pci_vendev(const void *blob, int node,
+		u16 *vendor, u16 *device);
+
+/**
+ * Look at the pci address of a device node that represents a PCI device
+ * and parse the bus, device and function number from it.
+ *
+ * @param blob		FDT blob
+ * @param node		node to examine
+ * @param addr		pci address in the form of fdt_pci_addr
+ * @param bdf		returns bus, device, function triplet
+ * @return 0 if ok, negative on error
+ */
+int fdtdec_get_pci_bdf(const void *blob, int node,
+		struct fdt_pci_addr *addr, pci_dev_t *bdf);
+
+/**
+ * Look at the pci address of a device node that represents a PCI device
+ * and return base address of the pci device's registers.
+ *
+ * @param blob		FDT blob
+ * @param node		node to examine
+ * @param addr		pci address in the form of fdt_pci_addr
+ * @param bar		returns base address of the pci device's registers
+ * @return 0 if ok, negative on error
+ */
+int fdtdec_get_pci_bar32(const void *blob, int node,
+		struct fdt_pci_addr *addr, u32 *bar);
+
+/**
  * Look up a 32-bit integer property in a node and return it. The property
  * must have at least 4 bytes of data. The value of the first cell is
  * returned.
@@ -683,17 +781,6 @@
 			   struct fdt_resource *res);
 
 /**
- * Look at the reg property of a device node that represents a PCI device
- * and parse the bus, device and function number from it.
- *
- * @param fdt		FDT blob
- * @param node		node to examine
- * @param bdf		returns bus, device, function triplet
- * @return 0 if ok, negative on error
- */
-int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf);
-
-/**
  * Decode a named region within a memory bank of a given type.
  *
  * This function handles selection of a memory region. The region is
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 745b390..487122e 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -126,6 +126,163 @@
 	return fdtdec_get_addr_size(blob, node, prop_name, NULL);
 }
 
+#ifdef CONFIG_PCI
+int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
+		const char *prop_name, struct fdt_pci_addr *addr)
+{
+	const u32 *cell;
+	int len;
+	int ret = -ENOENT;
+
+	debug("%s: %s: ", __func__, prop_name);
+
+	/*
+	 * If we follow the pci bus bindings strictly, we should check
+	 * the value of the node's parent node's #address-cells and
+	 * #size-cells. They need to be 3 and 2 accordingly. However,
+	 * for simplicity we skip the check here.
+	 */
+	cell = fdt_getprop(blob, node, prop_name, &len);
+	if (!cell)
+		goto fail;
+
+	if ((len % FDT_PCI_REG_SIZE) == 0) {
+		int num = len / FDT_PCI_REG_SIZE;
+		int i;
+
+		for (i = 0; i < num; i++) {
+			debug("pci address #%d: %08lx %08lx %08lx\n", i,
+			      (ulong)fdt_addr_to_cpu(cell[0]),
+			      (ulong)fdt_addr_to_cpu(cell[1]),
+			      (ulong)fdt_addr_to_cpu(cell[2]));
+			if ((fdt_addr_to_cpu(*cell) & type) == type) {
+				addr->phys_hi = fdt_addr_to_cpu(cell[0]);
+				addr->phys_mid = fdt_addr_to_cpu(cell[1]);
+				addr->phys_lo = fdt_addr_to_cpu(cell[2]);
+				break;
+			} else {
+				cell += (FDT_PCI_ADDR_CELLS +
+					 FDT_PCI_SIZE_CELLS);
+			}
+		}
+
+		if (i == num)
+			goto fail;
+
+		return 0;
+	} else {
+		ret = -EINVAL;
+	}
+
+fail:
+	debug("(not found)\n");
+	return ret;
+}
+
+int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
+{
+	const char *list, *end;
+	int len;
+
+	list = fdt_getprop(blob, node, "compatible", &len);
+	if (!list)
+		return -ENOENT;
+
+	end = list + len;
+	while (list < end) {
+		char *s;
+
+		len = strlen(list);
+		if (len >= strlen("pciVVVV,DDDD")) {
+			s = strstr(list, "pci");
+
+			/*
+			 * check if the string is something like pciVVVV,DDDD.RR
+			 * or just pciVVVV,DDDD
+			 */
+			if (s && s[7] == ',' &&
+			    (s[12] == '.' || s[12] == 0)) {
+				s += 3;
+				*vendor = simple_strtol(s, NULL, 16);
+
+				s += 5;
+				*device = simple_strtol(s, NULL, 16);
+
+				return 0;
+			}
+		} else {
+			list += (len + 1);
+		}
+	}
+
+	return -ENOENT;
+}
+
+int fdtdec_get_pci_bdf(const void *blob, int node,
+		struct fdt_pci_addr *addr, pci_dev_t *bdf)
+{
+	u16 dt_vendor, dt_device, vendor, device;
+	int ret;
+
+	/* get vendor id & device id from the compatible string */
+	ret = fdtdec_get_pci_vendev(blob, node, &dt_vendor, &dt_device);
+	if (ret)
+		return ret;
+
+	/* extract the bdf from fdt_pci_addr */
+	*bdf = addr->phys_hi & 0xffff00;
+
+	/* read vendor id & device id based on bdf */
+	pci_read_config_word(*bdf, PCI_VENDOR_ID, &vendor);
+	pci_read_config_word(*bdf, PCI_DEVICE_ID, &device);
+
+	/*
+	 * Note there are two places in the device tree to fully describe
+	 * a pci device: one is via compatible string with a format of
+	 * "pciVVVV,DDDD" and the other one is the bdf numbers encoded in
+	 * the device node's reg address property. We read the vendor id
+	 * and device id based on bdf and compare the values with the
+	 * "VVVV,DDDD". If they are the same, then we are good to use bdf
+	 * to read device's bar. But if they are different, we have to rely
+	 * on the vendor id and device id extracted from the compatible
+	 * string and locate the real bdf by pci_find_device(). This is
+	 * because normally we may only know device's device number and
+	 * function number when writing device tree. The bus number is
+	 * dynamically assigned during the pci enumeration process.
+	 */
+	if ((dt_vendor != vendor) || (dt_device != device)) {
+		*bdf = pci_find_device(dt_vendor, dt_device, 0);
+		if (*bdf == -1)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
+int fdtdec_get_pci_bar32(const void *blob, int node,
+		struct fdt_pci_addr *addr, u32 *bar)
+{
+	pci_dev_t bdf;
+	int barnum;
+	int ret;
+
+	/* get pci devices's bdf */
+	ret = fdtdec_get_pci_bdf(blob, node, addr, &bdf);
+	if (ret)
+		return ret;
+
+	/* extract the bar number from fdt_pci_addr */
+	barnum = addr->phys_hi & 0xff;
+	if ((barnum < PCI_BASE_ADDRESS_0) || (barnum > PCI_CARDBUS_CIS))
+		return -EINVAL;
+
+	barnum = (barnum - PCI_BASE_ADDRESS_0) / 4;
+	*bar = pci_read_bar32(pci_bus_to_hose(PCI_BUS(bdf)), bdf, barnum);
+
+	return 0;
+}
+#endif
+
 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
 		uint64_t default_val)
 {
@@ -795,20 +952,6 @@
 	return fdt_get_resource(fdt, node, property, index, res);
 }
 
-int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf)
-{
-	const fdt32_t *prop;
-	int len;
-
-	prop = fdt_getprop(fdt, node, "reg", &len);
-	if (!prop)
-		return len;
-
-	*bdf = fdt32_to_cpu(*prop) & 0xffffff;
-
-	return 0;
-}
-
 int fdtdec_decode_memory_region(const void *blob, int config_node,
 				const char *mem_type, const char *suffix,
 				fdt_addr_t *basep, fdt_size_t *sizep)
diff --git a/tools/ifdtool.c b/tools/ifdtool.c
index fe8366b..590ccc9 100644
--- a/tools/ifdtool.c
+++ b/tools/ifdtool.c
@@ -788,9 +788,9 @@
 			      fdt_strerror(data_size));
 			return -ENOENT;
 		}
-		offset = ucode_ptr - uboot->addr;
+		offset = (uint32_t)(ucode_ptr + size);
 		ptr = (void *)image + offset;
-		ptr[0] = uboot->addr + (data - image);
+		ptr[0] = (data - image) - size;
 		ptr[1] = data_size;
 		debug("Wrote microcode pointer at %x: addr=%x, size=%x\n",
 		      ucode_ptr, ptr[0], ptr[1]);