Merge git://git.denx.de/u-boot-x86
diff --git a/Makefile b/Makefile
index a7dce06..b6f83a5 100644
--- a/Makefile
+++ b/Makefile
@@ -1035,8 +1035,8 @@
 IFDTOOL_FLAGS += -w $(CONFIG_CMC_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_CMC_FILE)
 endif
 
-ifneq ($(CONFIG_X86_OPTION_ROM_ADDR),)
-IFDTOOL_FLAGS += -w $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILE)
+ifneq ($(CONFIG_HAVE_VGA_BIOS),)
+IFDTOOL_FLAGS += -w $(CONFIG_VGA_BIOS_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_VGA_BIOS_FILE)
 endif
 
 quiet_cmd_ifdtool = IFDTOOL $@
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 20083e6..cbbaa4f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -69,6 +69,21 @@
 	bool
 	default n
 
+config RESET_SEG_START
+	hex
+	depends on X86_RESET_VECTOR
+	default 0xffff0000
+
+config RESET_SEG_SIZE
+	hex
+	depends on X86_RESET_VECTOR
+	default 0x10000
+
+config RESET_VEC_LOC
+	hex
+	depends on X86_RESET_VECTOR
+	default 0xfffffff0
+
 config SYS_X86_START16
 	hex
 	depends on X86_RESET_VECTOR
@@ -173,14 +188,6 @@
 	  to work correctly. It is not exhaustive but can save time by
 	  detecting obvious failures.
 
-config MARK_GRAPHICS_MEM_WRCOMB
-	bool "Mark graphics memory as write-combining"
-	default n
-	help
-	  The graphics performance may increase if the graphics
-	  memory is set as write-combining cache type. This option
-	  enables marking the graphics memory as write-combining.
-
 config HAVE_FSP
 	bool "Add an Firmware Support Package binary"
 	help
@@ -220,17 +227,6 @@
 	  Stack top address which is used in FspInit after DRAM is ready and
 	  CAR is disabled.
 
-config MAX_CPUS
-        int "Maximum number of CPUs permitted"
-        default 4
-        help
-          When using multi-CPU chips it is possible for U-Boot to start up
-          more than one CPU. The stack memory used by all of these CPUs is
-          pre-allocated so at present U-Boot wants to know the maximum
-          number of CPUs that may be present. Set this to at least as high
-          as the number of CPUs in your system (it uses about 4KB of RAM for
-          each CPU).
-
 config SMP
 	bool "Enable Symmetric Multiprocessing"
 	default n
@@ -241,8 +237,21 @@
 	  only one CPU will be enabled regardless of the number of CPUs
 	  available.
 
+config MAX_CPUS
+	int "Maximum number of CPUs permitted"
+	depends on SMP
+	default 4
+	help
+	  When using multi-CPU chips it is possible for U-Boot to start up
+	  more than one CPU. The stack memory used by all of these CPUs is
+	  pre-allocated so at present U-Boot wants to know the maximum
+	  number of CPUs that may be present. Set this to at least as high
+	  as the number of CPUs in your system (it uses about 4KB of RAM for
+	  each CPU).
+
 config AP_STACK_SIZE
 	hex
+	depends on SMP
 	default 0x1000
 	help
 	  Each additional CPU started by U-Boot requires its own stack. This
@@ -270,6 +279,28 @@
 	help
 	  The running frequency in MHz of Time-Stamp Counter (TSC).
 
+config HAVE_VGA_BIOS
+	bool "Add a VGA BIOS image"
+	help
+	  Select this option if you have a VGA BIOS image that you would
+	  like to add to your ROM.
+
+config VGA_BIOS_FILE
+	string "VGA BIOS image filename"
+	depends on HAVE_VGA_BIOS
+	default "vga.bin"
+	help
+	  The filename of the VGA BIOS image in the board directory.
+
+config VGA_BIOS_ADDR
+	hex "VGA BIOS image location"
+	depends on HAVE_VGA_BIOS
+	default 0xfff90000
+	help
+	  The location of VGA BIOS image in the SPI flash. For example, base
+	  address of 0xfff90000 indicates that the image will be put at offset
+	  0x90000 from the beginning of a 1MB flash device.
+
 menu "System tables"
 
 config GENERATE_PIRQ_TABLE
@@ -296,6 +327,15 @@
 
 	  For more information, see http://simplefirmware.org
 
+config GENERATE_MP_TABLE
+	bool "Generate an MP (Multi-Processor) table"
+	default n
+	help
+	  Generate an MP (Multi-Processor) table for this board. The MP table
+	  provides a way for the operating system to support for symmetric
+	  multiprocessing as well as symmetric I/O interrupt handling with
+	  the local APIC and I/O APIC.
+
 endmenu
 
 config MAX_PIRQ_LINKS
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 7ff05e6..8a8e63e 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -10,7 +10,7 @@
 
 extra-y	= start.o
 obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
-obj-y	+= interrupts.o cpu.o call64.o
+obj-y	+= interrupts.o cpu.o cpu_x86.o call64.o
 
 obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
@@ -19,7 +19,7 @@
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
 obj-$(CONFIG_INTEL_QUARK) += quark/
 obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
-obj-y += irq.o lapic.o
+obj-y += irq.o lapic.o ioapic.o
 obj-$(CONFIG_SMP) += mp_init.o
 obj-y += mtrr.o
 obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile
index c78b644..5be5491 100644
--- a/arch/x86/cpu/baytrail/Makefile
+++ b/arch/x86/cpu/baytrail/Makefile
@@ -7,5 +7,4 @@
 obj-y += cpu.o
 obj-y += early_uart.o
 obj-y += fsp_configs.o
-obj-y += pci.o
 obj-y += valleyview.o
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 1d48206..a011730 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -10,79 +10,11 @@
 #include <cpu.h>
 #include <dm.h>
 #include <asm/cpu.h>
+#include <asm/cpu_x86.h>
 #include <asm/lapic.h>
-#include <asm/mp.h>
 #include <asm/msr.h>
 #include <asm/turbo.h>
 
-#ifdef CONFIG_SMP
-static int enable_smis(struct udevice *cpu, void *unused)
-{
-	return 0;
-}
-
-static struct mp_flight_record mp_steps[] = {
-	MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
-	/* Wait for APs to finish initialization before proceeding. */
-	MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
-};
-
-static int detect_num_cpus(void)
-{
-	int ecx = 0;
-
-	/*
-	 * Use the algorithm described in Intel 64 and IA-32 Architectures
-	 * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
-	 * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
-	 * of CPUID Extended Topology Leaf.
-	 */
-	while (1) {
-		struct cpuid_result leaf_b;
-
-		leaf_b = cpuid_ext(0xb, ecx);
-
-		/*
-		 * Bay Trail doesn't have hyperthreading so just determine the
-		 * number of cores by from level type (ecx[15:8] == * 2)
-		 */
-		if ((leaf_b.ecx & 0xff00) == 0x0200)
-			return leaf_b.ebx & 0xffff;
-		ecx++;
-	}
-}
-
-static int baytrail_init_cpus(void)
-{
-	struct mp_params mp_params;
-
-	lapic_setup();
-
-	mp_params.num_cpus = detect_num_cpus();
-	mp_params.parallel_microcode_load = 0,
-	mp_params.flight_plan = &mp_steps[0];
-	mp_params.num_records = ARRAY_SIZE(mp_steps);
-	mp_params.microcode_pointer = 0;
-
-	if (mp_init(&mp_params)) {
-		printf("Warning: MP init failure\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-#endif
-
-int x86_init_cpus(void)
-{
-#ifdef CONFIG_SMP
-	debug("Init additional CPUs\n");
-	baytrail_init_cpus();
-#endif
-
-	return 0;
-}
-
 static void set_max_freq(void)
 {
 	msr_t perf_ctl;
@@ -175,19 +107,38 @@
 	return 0;
 }
 
-static int cpu_x86_baytrail_bind(struct udevice *dev)
+static int baytrail_get_count(struct udevice *dev)
 {
-	struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+	int ecx = 0;
 
-	plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
-				      "intel,apic-id", -1);
+	/*
+	 * Use the algorithm described in Intel 64 and IA-32 Architectures
+	 * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
+	 * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
+	 * of CPUID Extended Topology Leaf.
+	 */
+	while (1) {
+		struct cpuid_result leaf_b;
+
+		leaf_b = cpuid_ext(0xb, ecx);
+
+		/*
+		 * Bay Trail doesn't have hyperthreading so just determine the
+		 * number of cores by from level type (ecx[15:8] == * 2)
+		 */
+		if ((leaf_b.ecx & 0xff00) == 0x0200)
+			return leaf_b.ebx & 0xffff;
+
+		ecx++;
+	}
 
 	return 0;
 }
 
 static const struct cpu_ops cpu_x86_baytrail_ops = {
-	.get_desc	= x86_cpu_get_desc,
+	.get_desc	= cpu_x86_get_desc,
 	.get_info	= baytrail_get_info,
+	.get_count	= baytrail_get_count,
 };
 
 static const struct udevice_id cpu_x86_baytrail_ids[] = {
@@ -199,7 +150,7 @@
 	.name		= "cpu_x86_baytrail",
 	.id		= UCLASS_CPU,
 	.of_match	= cpu_x86_baytrail_ids,
-	.bind		= cpu_x86_baytrail_bind,
+	.bind		= cpu_x86_bind,
 	.probe		= cpu_x86_baytrail_probe,
 	.ops		= &cpu_x86_baytrail_ops,
 };
diff --git a/arch/x86/cpu/baytrail/pci.c b/arch/x86/cpu/baytrail/pci.c
deleted file mode 100644
index 48409de..0000000
--- a/arch/x86/cpu/baytrail/pci.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <pci.h>
-#include <asm/pci.h>
-#include <asm/fsp/fsp_support.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-void board_pci_setup_hose(struct pci_controller *hose)
-{
-	hose->first_busno = 0;
-	hose->last_busno = 0;
-
-	/* PCI memory space */
-	pci_set_region(hose->regions + 0,
-		       CONFIG_PCI_MEM_BUS,
-		       CONFIG_PCI_MEM_PHYS,
-		       CONFIG_PCI_MEM_SIZE,
-		       PCI_REGION_MEM);
-
-	/* 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 < 0x80000000 ? gd->ram_size : 0x80000000,
-		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
-
-	hose->region_count = 4;
-}
diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk
index 4c4d0c7..1263221 100644
--- a/arch/x86/cpu/config.mk
+++ b/arch/x86/cpu/config.mk
@@ -10,8 +10,8 @@
 PLATFORM_CPPFLAGS += -D__I386__
 
 # DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
-LDPPFLAGS += -DRESET_SEG_START=0xffff0000
-LDPPFLAGS += -DRESET_SEG_SIZE=0x10000
-LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0
+LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
+LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE)
+LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
 LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16)
 LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)"
diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c
index 67eb14c..41e29a6 100644
--- a/arch/x86/cpu/coreboot/pci.c
+++ b/arch/x86/cpu/coreboot/pci.c
@@ -11,29 +11,7 @@
 
 #include <common.h>
 #include <dm.h>
-#include <errno.h>
 #include <pci.h>
-#include <asm/io.h>
-#include <asm/pci.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static const struct dm_pci_ops pci_x86_ops = {
-	.read_config	= pci_x86_read_config,
-	.write_config	= pci_x86_write_config,
-};
-
-static const struct udevice_id pci_x86_ids[] = {
-	{ .compatible = "pci-x86" },
-	{ }
-};
-
-U_BOOT_DRIVER(pci_x86_drv) = {
-	.name		= "pci_x86",
-	.id		= UCLASS_PCI,
-	.of_match	= pci_x86_ids,
-	.ops		= &pci_x86_ops,
-};
 
 static const struct udevice_id generic_pch_ids[] = {
 	{ .compatible = "intel,pch" },
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index bb4a110..af927b9 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -21,12 +21,15 @@
 
 #include <common.h>
 #include <command.h>
-#include <cpu.h>
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <asm/control_regs.h>
 #include <asm/cpu.h>
+#include <asm/lapic.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
 #include <asm/post.h>
 #include <asm/processor.h>
 #include <asm/processor-flags.h>
@@ -164,6 +167,26 @@
 	load_fs(X86_GDT_ENTRY_32BIT_FS);
 }
 
+#ifdef CONFIG_HAVE_FSP
+/*
+ * Setup FSP execution environment GDT
+ *
+ * Per Intel FSP external architecture specification, before calling any FSP
+ * APIs, we need make sure the system is in flat 32-bit mode and both the code
+ * and data selectors should have full 4GB access range. Here we reuse the one
+ * we used in arch/x86/cpu/start16.S, and reload the segement registers.
+ */
+void setup_fsp_gdt(void)
+{
+	load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4);
+	load_ds(X86_GDT_ENTRY_32BIT_DS);
+	load_ss(X86_GDT_ENTRY_32BIT_DS);
+	load_es(X86_GDT_ENTRY_32BIT_DS);
+	load_fs(X86_GDT_ENTRY_32BIT_DS);
+	load_gs(X86_GDT_ENTRY_32BIT_DS);
+}
+#endif
+
 int __weak x86_cleanup_before_linux(void)
 {
 #ifdef CONFIG_BOOTSTAGE_STASH
@@ -330,6 +353,28 @@
 
 		gd->arch.has_mtrr = has_mtrr();
 	}
+	/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
+	gd->pci_ram_top = 0x80000000U;
+
+	/* Configure fixed range MTRRs for some legacy regions */
+	if (gd->arch.has_mtrr) {
+		u64 mtrr_cap;
+
+		mtrr_cap = native_read_msr(MTRR_CAP_MSR);
+		if (mtrr_cap & MTRR_CAP_FIX) {
+			/* Mark the VGA RAM area as uncacheable */
+			native_write_msr(MTRR_FIX_16K_A0000_MSR, 0, 0);
+
+			/* Mark the PCI ROM area as uncacheable */
+			native_write_msr(MTRR_FIX_4K_C0000_MSR, 0, 0);
+			native_write_msr(MTRR_FIX_4K_C8000_MSR, 0, 0);
+			native_write_msr(MTRR_FIX_4K_D0000_MSR, 0, 0);
+			native_write_msr(MTRR_FIX_4K_D8000_MSR, 0, 0);
+
+			/* Enable the fixed range MTRRs */
+			msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
+		}
+	}
 
 	return 0;
 }
@@ -520,16 +565,6 @@
 	return ptr;
 }
 
-int x86_cpu_get_desc(struct udevice *dev, char *buf, int size)
-{
-	if (size < CPU_MAX_NAME_LEN)
-		return -ENOSPC;
-
-	cpu_get_name(buf);
-
-	return 0;
-}
-
 int default_print_cpuinfo(void)
 {
 	printf("CPU: %s, vendor %s, device %xh\n",
@@ -613,8 +648,43 @@
 }
 #endif
 
+#ifdef CONFIG_SMP
+static int enable_smis(struct udevice *cpu, void *unused)
+{
+	return 0;
+}
+
+static struct mp_flight_record mp_steps[] = {
+	MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
+	/* Wait for APs to finish initialization before proceeding */
+	MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
+};
+
+static int x86_mp_init(void)
+{
+	struct mp_params mp_params;
+
+	mp_params.parallel_microcode_load = 0,
+	mp_params.flight_plan = &mp_steps[0];
+	mp_params.num_records = ARRAY_SIZE(mp_steps);
+	mp_params.microcode_pointer = 0;
+
+	if (mp_init(&mp_params)) {
+		printf("Warning: MP init failure\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+#endif
+
 __weak int x86_init_cpus(void)
 {
+#ifdef CONFIG_SMP
+	debug("Init additional CPUs\n");
+	x86_mp_init();
+#endif
+
 	return 0;
 }
 
@@ -622,19 +692,3 @@
 {
 	return x86_init_cpus();
 }
-
-static const struct cpu_ops cpu_x86_ops = {
-	.get_desc	= x86_cpu_get_desc,
-};
-
-static const struct udevice_id cpu_x86_ids[] = {
-	{ .compatible = "cpu-x86" },
-	{ }
-};
-
-U_BOOT_DRIVER(cpu_x86_drv) = {
-	.name		= "cpu_x86",
-	.id		= UCLASS_CPU,
-	.of_match	= cpu_x86_ids,
-	.ops		= &cpu_x86_ops,
-};
diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c
new file mode 100644
index 0000000..0941041
--- /dev/null
+++ b/arch/x86/cpu/cpu_x86.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/cpu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int cpu_x86_bind(struct udevice *dev)
+{
+	struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+	plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+				      "intel,apic-id", -1);
+
+	return 0;
+}
+
+int cpu_x86_get_desc(struct udevice *dev, char *buf, int size)
+{
+	if (size < CPU_MAX_NAME_LEN)
+		return -ENOSPC;
+
+	cpu_get_name(buf);
+
+	return 0;
+}
+
+static int cpu_x86_get_count(struct udevice *dev)
+{
+	int node, cpu;
+	int num = 0;
+
+	node = fdt_path_offset(gd->fdt_blob, "/cpus");
+	if (node < 0)
+		return -ENOENT;
+
+	for (cpu = fdt_first_subnode(gd->fdt_blob, node);
+	     cpu >= 0;
+	     cpu = fdt_next_subnode(gd->fdt_blob, cpu)) {
+		const char *device_type;
+
+		device_type = fdt_getprop(gd->fdt_blob, cpu,
+					  "device_type", NULL);
+		if (!device_type)
+			continue;
+		if (strcmp(device_type, "cpu") == 0)
+			num++;
+	}
+
+	return num;
+}
+
+static const struct cpu_ops cpu_x86_ops = {
+	.get_desc	= cpu_x86_get_desc,
+	.get_count	= cpu_x86_get_count,
+};
+
+static const struct udevice_id cpu_x86_ids[] = {
+	{ .compatible = "cpu-x86" },
+	{ }
+};
+
+U_BOOT_DRIVER(cpu_x86_drv) = {
+	.name		= "cpu_x86",
+	.id		= UCLASS_CPU,
+	.of_match	= cpu_x86_ids,
+	.bind		= cpu_x86_bind,
+	.ops		= &cpu_x86_ops,
+};
diff --git a/arch/x86/cpu/ioapic.c b/arch/x86/cpu/ioapic.c
new file mode 100644
index 0000000..112a9c6
--- /dev/null
+++ b/arch/x86/cpu/ioapic.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
+
+u32 io_apic_read(u32 reg)
+{
+	writel(reg, IO_APIC_INDEX);
+	return readl(IO_APIC_DATA);
+}
+
+void io_apic_write(u32 reg, u32 val)
+{
+	writel(reg, IO_APIC_INDEX);
+	writel(val, IO_APIC_DATA);
+}
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
index 74b89ad..97dd000 100644
--- a/arch/x86/cpu/irq.c
+++ b/arch/x86/cpu/irq.c
@@ -58,17 +58,28 @@
 		writeb(irq, irq_router.ibase + LINK_N2V(link, base));
 }
 
-static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus,
-				 u8 device, u8 func, u8 pin, u8 pirq)
+static struct irq_info *check_dup_entry(struct irq_info *slot_base,
+					int entry_num, int bus, int device)
 {
-	struct irq_info *slot = *slotp;
+	struct irq_info *slot = slot_base;
+	int i;
 
+	for (i = 0; i < entry_num; i++) {
+		if (slot->bus == bus && slot->devfn == (device << 3))
+			break;
+		slot++;
+	}
+
+	return (i == entry_num) ? NULL : slot;
+}
+
+static inline void fill_irq_info(struct irq_info *slot, int bus, int device,
+				 int pin, int pirq)
+{
 	slot->bus = bus;
-	slot->devfn = (device << 3) | func;
+	slot->devfn = (device << 3) | 0;
 	slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base);
 	slot->irq[pin - 1].bitmap = irq_router.irq_mask;
-	(*entries)++;
-	(*slotp)++;
 }
 
 __weak void cpu_irq_init(void)
@@ -84,7 +95,7 @@
 	int len, count;
 	const u32 *cell;
 	struct irq_routing_table *rt;
-	struct irq_info *slot;
+	struct irq_info *slot, *slot_base;
 	int irq_entries = 0;
 	int i;
 	int ret;
@@ -161,13 +172,13 @@
 	/* Populate the PIRQ table fields */
 	rt->signature = PIRQ_SIGNATURE;
 	rt->version = PIRQ_VERSION;
-	rt->rtr_bus = 0;
+	rt->rtr_bus = PCI_BUS(irq_router.bdf);
 	rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) |
 			PCI_FUNC(irq_router.bdf);
 	rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
 	rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;
 
-	slot = rt->slots;
+	slot_base = rt->slots;
 
 	/* Now fill in the irq_info entries in the PIRQ table */
 	for (i = 0; i < count; i++) {
@@ -181,9 +192,44 @@
 		      i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
 		      PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
 		      'A' + pr.pirq);
-		fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf),
-			      PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf),
+
+		slot = check_dup_entry(slot_base, irq_entries,
+				       PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
+		if (slot) {
+			debug("found entry for bus %d device %d, ",
+			      PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
+
+			if (slot->irq[pr.pin - 1].link) {
+				debug("skipping\n");
+
+				/*
+				 * Sanity test on the routed PIRQ pin
+				 *
+				 * If they don't match, show a warning to tell
+				 * there might be something wrong with the PIRQ
+				 * routing information in the device tree.
+				 */
+				if (slot->irq[pr.pin - 1].link !=
+					LINK_N2V(pr.pirq, irq_router.link_base))
+					debug("WARNING: Inconsistent PIRQ routing information\n");
+
+				cell += sizeof(struct pirq_routing) /
+					sizeof(u32);
+				continue;
+			} else {
+				debug("writing INT%c\n", 'A' + pr.pin - 1);
+				fill_irq_info(slot, PCI_BUS(pr.bdf),
+					      PCI_DEV(pr.bdf), pr.pin, pr.pirq);
+				cell += sizeof(struct pirq_routing) /
+					sizeof(u32);
+				continue;
+			}
+		}
+
+		slot = slot_base + irq_entries;
+		fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
 			      pr.pin, pr.pirq);
+		irq_entries++;
 		cell += sizeof(struct pirq_routing) / sizeof(u32);
 	}
 
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig
index e4595be..0e249a4 100644
--- a/arch/x86/cpu/ivybridge/Kconfig
+++ b/arch/x86/cpu/ivybridge/Kconfig
@@ -95,7 +95,6 @@
 	select ARCH_BOOTBLOCK_X86_32
 	select ARCH_ROMSTAGE_X86_32
 	select ARCH_RAMSTAGE_X86_32
-	select SMP
 	select SSE2
 	select UDELAY_LAPIC
 	select CPU_MICROCODE_IN_CBFS
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index 8b08c40..fd7db97 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -13,12 +13,12 @@
 #include <asm/acpi.h>
 #include <asm/cpu.h>
 #include <asm/lapic.h>
-#include <asm/lapic_def.h>
 #include <asm/msr.h>
 #include <asm/mtrr.h>
 #include <asm/processor.h>
 #include <asm/speedstep.h>
 #include <asm/turbo.h>
+#include <asm/arch/bd82x6x.h>
 #include <asm/arch/model_206ax.h>
 
 static void enable_vmx(void)
diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c
index 4690603..30d2313 100644
--- a/arch/x86/cpu/lapic.c
+++ b/arch/x86/cpu/lapic.c
@@ -8,50 +8,153 @@
  */
 
 #include <common.h>
-#include <asm/msr.h>
 #include <asm/io.h>
 #include <asm/lapic.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
 #include <asm/post.h>
 
+unsigned long lapic_read(unsigned long reg)
+{
+	return readl(LAPIC_DEFAULT_BASE + reg);
+}
+
+#define xchg(ptr, v)	((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+						    sizeof(*(ptr))))
+
+struct __xchg_dummy	{ unsigned long a[100]; };
+#define __xg(x)		((struct __xchg_dummy *)(x))
+
+/*
+ * Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
+ *
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ *         but generally the primitive is invalid, *ptr is output argument.
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+				   int size)
+{
+	switch (size) {
+	case 1:
+		__asm__ __volatile__("xchgb %b0,%1"
+			: "=q" (x)
+			: "m" (*__xg(ptr)), "0" (x)
+			: "memory");
+		break;
+	case 2:
+		__asm__ __volatile__("xchgw %w0,%1"
+			: "=r" (x)
+			: "m" (*__xg(ptr)), "0" (x)
+			: "memory");
+		break;
+	case 4:
+		__asm__ __volatile__("xchgl %0,%1"
+			: "=r" (x)
+			: "m" (*__xg(ptr)), "0" (x)
+			: "memory");
+		break;
+	}
+
+	return x;
+}
+
+void lapic_write(unsigned long reg, unsigned long v)
+{
+	(void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
+}
+
+void enable_lapic(void)
+{
+	msr_t msr;
+
+	msr = msr_read(MSR_IA32_APICBASE);
+	msr.hi &= 0xffffff00;
+	msr.lo |= MSR_IA32_APICBASE_ENABLE;
+	msr.lo &= ~MSR_IA32_APICBASE_BASE;
+	msr.lo |= LAPIC_DEFAULT_BASE;
+	msr_write(MSR_IA32_APICBASE, msr);
+}
+
+void disable_lapic(void)
+{
+	msr_t msr;
+
+	msr = msr_read(MSR_IA32_APICBASE);
+	msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
+	msr_write(MSR_IA32_APICBASE, msr);
+}
+
+unsigned long lapicid(void)
+{
+	return lapic_read(LAPIC_ID) >> 24;
+}
+
+static void lapic_wait_icr_idle(void)
+{
+	do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
+}
+
+int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
+{
+	int timeout;
+	unsigned long status;
+	int result;
+
+	lapic_wait_icr_idle();
+	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+	lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
+
+	timeout = 0;
+	do {
+		status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
+	} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
+
+	result = -1;
+	if (status == LAPIC_ICR_RR_VALID) {
+		*pvalue = lapic_read(LAPIC_RRR);
+		result = 0;
+	}
+
+	return result;
+}
+
 void lapic_setup(void)
 {
-#if NEED_LAPIC == 1
+#ifdef CONFIG_SMP
 	/* Only Pentium Pro and later have those MSR stuff */
 	debug("Setting up local apic: ");
 
 	/* Enable the local apic */
 	enable_lapic();
 
-	/*
-	 * Set Task Priority to 'accept all'.
-	 */
-	lapic_write_around(LAPIC_TASKPRI,
-			   lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
+	/* Set Task Priority to 'accept all' */
+	lapic_write(LAPIC_TASKPRI,
+		    lapic_read(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
 
 	/* Put the local apic in virtual wire mode */
-	lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
-				~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
-	lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
-			~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
-			  LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
-			  LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
-			  LAPIC_DELIVERY_MODE_MASK)) |
-			(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
-			 LAPIC_DELIVERY_MODE_EXTINT));
-	lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
-			~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
-			  LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
-			  LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
-			  LAPIC_DELIVERY_MODE_MASK)) |
-		(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
-			LAPIC_DELIVERY_MODE_NMI));
+	lapic_write(LAPIC_SPIV, (lapic_read(LAPIC_SPIV) &
+		    ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
+	lapic_write(LAPIC_LVT0, (lapic_read(LAPIC_LVT0) &
+		    ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
+		    LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
+		    LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
+		    LAPIC_DELIVERY_MODE_MASK)) |
+		    (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
+		    LAPIC_DELIVERY_MODE_EXTINT));
+	lapic_write(LAPIC_LVT1, (lapic_read(LAPIC_LVT1) &
+		    ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
+		    LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
+		    LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
+		    LAPIC_DELIVERY_MODE_MASK)) |
+		    (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
+		    LAPIC_DELIVERY_MODE_NMI));
 
 	debug("apic_id: 0x%02lx, ", lapicid());
-#else /* !NEED_LLAPIC */
+#else /* !CONFIG_SMP */
 	/* Only Pentium Pro and later have those MSR stuff */
 	debug("Disabling local apic: ");
 	disable_lapic();
-#endif /* !NEED_LAPIC */
+#endif /* CONFIG_SMP */
 	debug("done.\n");
 	post_code(POST_LAPIC);
 }
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c
index ac5753a..e686b28 100644
--- a/arch/x86/cpu/mp_init.c
+++ b/arch/x86/cpu/mp_init.c
@@ -16,12 +16,17 @@
 #include <asm/interrupt.h>
 #include <asm/lapic.h>
 #include <asm/mp.h>
+#include <asm/msr.h>
 #include <asm/mtrr.h>
+#include <asm/processor.h>
 #include <asm/sipi.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 #include <linux/linkage.h>
 
+/* Total CPUs include BSP */
+static int num_cpus;
+
 /* This also needs to match the sipi.S assembly code for saved MSR encoding */
 struct saved_msr {
 	uint32_t index;
@@ -56,6 +61,13 @@
 	atomic_set(b, 1);
 }
 
+static inline void stop_this_cpu(void)
+{
+	/* Called by an AP when it is ready to halt and wait for a new task */
+	for (;;)
+		cpu_hlt();
+}
+
 /* Returns 1 if timeout waiting for APs. 0 if target APs found */
 static int wait_for_aps(atomic_t *val, int target, int total_delay,
 			int delay_step)
@@ -314,9 +326,9 @@
 	}
 
 	/* Send INIT IPI to all but self */
-	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
-	lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
-			   LAPIC_DM_INIT);
+	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+	lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+		    LAPIC_DM_INIT);
 	debug("Waiting for 10ms after sending INIT.\n");
 	mdelay(10);
 
@@ -331,9 +343,9 @@
 		}
 	}
 
-	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
-	lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
-			   LAPIC_DM_STARTUP | sipi_vector);
+	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+	lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+		    LAPIC_DM_STARTUP | sipi_vector);
 	debug("Waiting for 1st SIPI to complete...");
 	if (apic_wait_timeout(10000, 50)) {
 		debug("timed out.\n");
@@ -356,9 +368,9 @@
 		}
 	}
 
-	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
-	lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
-			   LAPIC_DM_STARTUP | sipi_vector);
+	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+	lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+		    LAPIC_DM_STARTUP | sipi_vector);
 	debug("Waiting for 2nd SIPI to complete...");
 	if (apic_wait_timeout(10000, 50)) {
 		debug("timed out.\n");
@@ -383,7 +395,7 @@
 	int ret = 0;
 	const int timeout_us = 100000;
 	const int step_us = 100;
-	int num_aps = mp_params->num_cpus - 1;
+	int num_aps = num_cpus - 1;
 
 	for (i = 0; i < mp_params->num_records; i++) {
 		struct mp_flight_record *rec = &mp_params->flight_plan[i];
@@ -415,7 +427,7 @@
 	cpu_get_name(processor_name);
 	debug("CPU: %s.\n", processor_name);
 
-	enable_lapic();
+	lapic_setup();
 
 	apic_id = lapicid();
 	ret = find_cpu_by_apid_id(apic_id, devp);
@@ -451,7 +463,16 @@
 		return -1;
 	}
 
-	ret = check_cpu_devices(p->num_cpus);
+	num_cpus = cpu_get_count(cpu);
+	if (num_cpus < 0) {
+		debug("Cannot get number of CPUs: err=%d\n", num_cpus);
+		return num_cpus;
+	}
+
+	if (num_cpus < 2)
+		debug("Warning: Only 1 CPU is detected\n");
+
+	ret = check_cpu_devices(num_cpus);
 	if (ret)
 		debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
 
@@ -471,7 +492,7 @@
 	wbinvd();
 
 	/* Start the APs providing number of APs and the cpus_entered field */
-	num_aps = p->num_cpus - 1;
+	num_aps = num_cpus - 1;
 	ret = start_aps(num_aps, ap_count);
 	if (ret) {
 		mdelay(1000);
diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig
index 397e599..fbf85f2 100644
--- a/arch/x86/cpu/queensbay/Kconfig
+++ b/arch/x86/cpu/queensbay/Kconfig
@@ -38,4 +38,8 @@
 	  The default base address of 0xfffb0000 indicates that the binary must
 	  be located at offset 0xb0000 from the beginning of a 1MB flash device.
 
+config CPU_ADDR_BITS
+	int
+	default 32
+
 endif
diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c
index 873de7b..d27b2d9 100644
--- a/arch/x86/cpu/queensbay/tnc.c
+++ b/arch/x86/cpu/queensbay/tnc.c
@@ -69,17 +69,18 @@
 	 * Route TunnelCreek PCI device interrupt pin to PIRQ
 	 *
 	 * Since PCIe downstream ports received INTx are routed to PIRQ
-	 * A/B/C/D directly and not configurable, we route internal PCI
-	 * device's INTx to PIRQ E/F/G/H.
+	 * A/B/C/D directly and not configurable, we have to route PCIe
+	 * root ports' INTx to PIRQ A/B/C/D as well. For other devices
+	 * on TunneCreek, route them to PIRQ E/F/G/H.
 	 */
 	writew(PIRQE, &rcba->d02ir);
 	writew(PIRQF, &rcba->d03ir);
 	writew(PIRQG, &rcba->d27ir);
 	writew(PIRQH, &rcba->d31ir);
-	writew(PIRQE, &rcba->d23ir);
-	writew(PIRQF, &rcba->d24ir);
-	writew(PIRQG, &rcba->d25ir);
-	writew(PIRQH, &rcba->d26ir);
+	writew(PIRQA, &rcba->d23ir);
+	writew(PIRQB, &rcba->d24ir);
+	writew(PIRQC, &rcba->d25ir);
+	writew(PIRQD, &rcba->d26ir);
 }
 
 int arch_misc_init(void)
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 2e5f9da..00e585e 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -116,12 +116,16 @@
 	rep	stosb
 
 #ifdef CONFIG_HAVE_FSP
+	test	%esi, %esi
+	jz	skip_hob
+
 	/* Store HOB list */
 	movl	%esp, %edx
 	addl	$GD_HOB_LIST, %edx
 	movl	%esi, (%edx)
-#endif
 
+skip_hob:
+#endif
 	/* Setup first parameter to setup_gdt, pointer to global_data */
 	movl	%esp, %eax
 
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
index 826e2b4..5eb17f1 100644
--- a/arch/x86/cpu/start16.S
+++ b/arch/x86/cpu/start16.S
@@ -71,11 +71,12 @@
 	 */
 gdt_ptr:
 	.word	0x1f		/* limit (31 bytes = 4 GDT entries - 1) */
-	.long	BOOT_SEG + gdt	/* base */
+	.long	BOOT_SEG + gdt_rom	/* base */
 
 	/* Some CPUs are picky about GDT alignment... */
 	.align	16
-gdt:
+.globl gdt_rom
+gdt_rom:
 	/*
 	 * The GDT table ...
 	 *
diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts
index d68efda..60da1f5 100644
--- a/arch/x86/dts/crownbay.dts
+++ b/arch/x86/dts/crownbay.dts
@@ -10,6 +10,7 @@
 
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
+/include/ "rtc.dtsi"
 
 / {
 	model = "Intel Crown Bay";
@@ -23,6 +24,26 @@
 		silent_console = <0>;
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "cpu-x86";
+			reg = <0>;
+			intel,apic-id = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "cpu-x86";
+			reg = <1>;
+			intel,apic-id = <1>;
+		};
+
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
@@ -148,10 +169,22 @@
 				/* TunnelCreek PCI devices */
 				PCI_BDF(0, 2, 0) INTA PIRQE
 				PCI_BDF(0, 3, 0) INTA PIRQF
-				PCI_BDF(0, 23, 0) INTA PIRQE
-				PCI_BDF(0, 24, 0) INTA PIRQF
-				PCI_BDF(0, 25, 0) INTA PIRQG
-				PCI_BDF(0, 26, 0) INTA PIRQH
+				PCI_BDF(0, 23, 0) INTA PIRQA
+				PCI_BDF(0, 23, 0) INTB PIRQB
+				PCI_BDF(0, 23, 0) INTC PIRQC
+				PCI_BDF(0, 23, 0) INTD PIRQD
+				PCI_BDF(0, 24, 0) INTA PIRQB
+				PCI_BDF(0, 24, 0) INTB PIRQC
+				PCI_BDF(0, 24, 0) INTC PIRQD
+				PCI_BDF(0, 24, 0) INTD PIRQA
+				PCI_BDF(0, 25, 0) INTA PIRQC
+				PCI_BDF(0, 25, 0) INTB PIRQD
+				PCI_BDF(0, 25, 0) INTC PIRQA
+				PCI_BDF(0, 25, 0) INTD PIRQB
+				PCI_BDF(0, 26, 0) INTA PIRQD
+				PCI_BDF(0, 26, 0) INTB PIRQA
+				PCI_BDF(0, 26, 0) INTC PIRQB
+				PCI_BDF(0, 26, 0) INTD PIRQC
 				PCI_BDF(0, 27, 0) INTA PIRQG
 				/*
 				 * Topcliff PCI devices
@@ -159,29 +192,29 @@
 				 * Note on the Crown Bay board, Topcliff chipset
 				 * is connected to TunnelCreek PCIe port 0, so
 				 * its bus number is 1 for its PCIe port and 2
-				 * for its PCI devices per U-Boot currnet PCI
+				 * for its PCI devices per U-Boot current PCI
 				 * bus enumeration algorithm.
 				 */
 				PCI_BDF(1, 0, 0) INTA PIRQA
 				PCI_BDF(2, 0, 1) INTA PIRQA
 				PCI_BDF(2, 0, 2) INTA PIRQA
-				PCI_BDF(2, 2, 0) INTB PIRQB
-				PCI_BDF(2, 2, 1) INTB PIRQB
-				PCI_BDF(2, 2, 2) INTB PIRQB
-				PCI_BDF(2, 2, 3) INTB PIRQB
-				PCI_BDF(2, 2, 4) INTB PIRQB
+				PCI_BDF(2, 2, 0) INTB PIRQD
+				PCI_BDF(2, 2, 1) INTB PIRQD
+				PCI_BDF(2, 2, 2) INTB PIRQD
+				PCI_BDF(2, 2, 3) INTB PIRQD
+				PCI_BDF(2, 2, 4) INTB PIRQD
 				PCI_BDF(2, 4, 0) INTC PIRQC
 				PCI_BDF(2, 4, 1) INTC PIRQC
-				PCI_BDF(2, 6, 0) INTD PIRQD
+				PCI_BDF(2, 6, 0) INTD PIRQB
 				PCI_BDF(2, 8, 0) INTA PIRQA
 				PCI_BDF(2, 8, 1) INTA PIRQA
 				PCI_BDF(2, 8, 2) INTA PIRQA
 				PCI_BDF(2, 8, 3) INTA PIRQA
-				PCI_BDF(2, 10, 0) INTB PIRQB
-				PCI_BDF(2, 10, 1) INTB PIRQB
-				PCI_BDF(2, 10, 2) INTB PIRQB
-				PCI_BDF(2, 10, 3) INTB PIRQB
-				PCI_BDF(2, 10, 4) INTB PIRQB
+				PCI_BDF(2, 10, 0) INTB PIRQD
+				PCI_BDF(2, 10, 1) INTB PIRQD
+				PCI_BDF(2, 10, 2) INTB PIRQD
+				PCI_BDF(2, 10, 3) INTB PIRQD
+				PCI_BDF(2, 10, 4) INTB PIRQD
 				PCI_BDF(2, 12, 0) INTC PIRQC
 				PCI_BDF(2, 12, 1) INTC PIRQC
 				PCI_BDF(2, 12, 2) INTC PIRQC
diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index bd21bfb..0e59b18 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -111,6 +111,16 @@
 
 	};
 
+	pci {
+		compatible = "intel,pci-baytrail", "pci-x86";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		u-boot,dm-pre-reloc;
+		ranges = <0x02000000 0x0 0xd0000000 0xd0000000 0 0x10000000
+			0x42000000 0x0 0xc0000000 0xc0000000 0 0x10000000
+			0x01000000 0x0 0x2000 0x2000 0 0xe000>;
+	};
+
 	spi {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/x86/dts/rtc.dtsi b/arch/x86/dts/rtc.dtsi
new file mode 100644
index 0000000..93dacd7
--- /dev/null
+++ b/arch/x86/dts/rtc.dtsi
@@ -0,0 +1,6 @@
+/ {
+	rtc {
+		compatible = "motorola,mc146818";
+		reg = <0x70 2>;
+	};
+};
diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
index 5ae32f7..7786493 100644
--- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
+++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
@@ -16,7 +16,19 @@
 		   const void *blob, int node);
 int bd82x6x_init(void);
 
-struct x86_cpu_priv;
+/**
+ * struct x86_cpu_priv - Information about a single CPU
+ *
+ * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
+ * just a number representing the CPU core
+ *
+ * TODO: Move this to driver model once lifecycle is understood
+ */
+struct x86_cpu_priv {
+	int apic_id;
+	int start_err;
+};
+
 int model_206ax_init(struct x86_cpu_priv *cpu);
 
 #endif
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index ebc74ad..08284ee 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -197,20 +197,6 @@
 char *cpu_get_name(char *name);
 
 /**
- *
-* x86_cpu_get_desc() - Get a description string for an x86 CPU
-*
-* This uses cpu_get_name() and is suitable to use as the get_desc() method for
-* the CPU uclass.
-*
-* @dev:		Device to check (UCLASS_CPU)
-* @buf:		Buffer to place string
-* @size:	Size of string space
-* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
-*/
-int x86_cpu_get_desc(struct udevice *dev, char *buf, int size);
-
-/**
  * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
  *
  * The kernel is uncompressed and the 64-bit entry point is expected to be
diff --git a/arch/x86/include/asm/cpu_x86.h b/arch/x86/include/asm/cpu_x86.h
new file mode 100644
index 0000000..1940480
--- /dev/null
+++ b/arch/x86/include/asm/cpu_x86.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_CPU_X86_H
+#define _ASM_CPU_X86_H
+
+/**
+ * cpu_x86_bind() - Bind an x86 CPU with the driver
+ *
+ * This updates cpu device's platform data with information from device tree,
+ * like the processor local apic id.
+ *
+ * @dev:	Device to check (UCLASS_CPU)
+ * @return	0 always
+ */
+int cpu_x86_bind(struct udevice *dev);
+
+/**
+ * cpu_x86_get_desc() - Get a description string for an x86 CPU
+ *
+ * This uses cpu_get_name() and is suitable to use as the get_desc() method for
+ * the CPU uclass.
+ *
+ * @dev:	Device to check (UCLASS_CPU)
+ * @buf:	Buffer to place string
+ * @size:	Size of string space
+ * @return:	0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
+
+#endif /* _ASM_CPU_X86_H */
diff --git a/arch/x86/include/asm/ioapic.h b/arch/x86/include/asm/ioapic.h
index 699160f..77c443e 100644
--- a/arch/x86/include/asm/ioapic.h
+++ b/arch/x86/include/asm/ioapic.h
@@ -10,29 +10,33 @@
 #define __ASM_IOAPIC_H
 
 #define IO_APIC_ADDR		0xfec00000
-#define IO_APIC_INDEX		IO_APIC_ADDR
+
+/* Direct addressed register */
+#define IO_APIC_INDEX		(IO_APIC_ADDR + 0x00)
 #define IO_APIC_DATA		(IO_APIC_ADDR + 0x10)
-#define IO_APIC_INTERRUPTS	24
 
-#define ALL		(0xff << 24)
-#define NONE		0
-#define DISABLED	(1 << 16)
-#define ENABLED		(0 << 16)
-#define TRIGGER_EDGE	(0 << 15)
-#define TRIGGER_LEVEL	(1 << 15)
-#define POLARITY_HIGH	(0 << 13)
-#define POLARITY_LOW	(1 << 13)
-#define PHYSICAL_DEST	(0 << 11)
-#define LOGICAL_DEST	(1 << 11)
-#define ExtINT		(7 << 8)
-#define NMI		(4 << 8)
-#define SMI		(2 << 8)
-#define INT		(1 << 8)
+/* Indirect addressed register offset */
+#define IO_APIC_ID		0x00
+#define IO_APIC_VER		0x01
 
-u32 io_apic_read(u32 ioapic_base, u32 reg);
-void io_apic_write(u32 ioapic_base, u32 reg, u32 value);
-void set_ioapic_id(u32 ioapic_base, u8 ioapic_id);
-void setup_ioapic(u32 ioapic_base, u8 ioapic_id);
-void clear_ioapic(u32 ioapic_base);
+/**
+ * io_apic_read() - Read I/O APIC register
+ *
+ * This routine reads I/O APIC indirect addressed register.
+ *
+ * @reg:	address of indirect addressed register
+ * @return:	register value to read
+ */
+u32 io_apic_read(u32 reg);
+
+/**
+ * io_apic_write() - Write I/O APIC register
+ *
+ * This routine writes I/O APIC indirect addressed register.
+ *
+ * @reg:	address of indirect addressed register
+ * @val:	register value to write
+ */
+void io_apic_write(u32 reg, u32 val);
 
 #endif
diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h
index 0a7f443..bc2b2d1 100644
--- a/arch/x86/include/asm/lapic.h
+++ b/arch/x86/include/asm/lapic.h
@@ -1,5 +1,5 @@
 /*
- * From Coreboot file of same name
+ * From coreboot file of same name
  *
  * Copyright (C) 2014 Google, Inc
  *
@@ -9,171 +9,70 @@
 #ifndef _ARCH_ASM_LAPIC_H
 #define _ARCH_ASM_LAPIC_H
 
-#include <asm/io.h>
-#include <asm/lapic_def.h>
-#include <asm/msr.h>
-#include <asm/processor.h>
+#define LAPIC_DEFAULT_BASE		0xfee00000
 
-/* See if I need to initialize the local apic */
-#if CONFIG_SMP || CONFIG_IOAPIC
-#  define NEED_LAPIC 1
-#else
-#  define NEED_LAPIC 0
-#endif
+#define LAPIC_ID			0x020
+#define LAPIC_LVR			0x030
 
-static inline __attribute__((always_inline))
-		unsigned long lapic_read(unsigned long reg)
-{
-	return readl(LAPIC_DEFAULT_BASE + reg);
-}
+#define LAPIC_TASKPRI			0x080
+#define LAPIC_TPRI_MASK			0xff
 
-static inline __attribute__((always_inline))
-		void lapic_write(unsigned long reg, unsigned long val)
-{
-	writel(val, LAPIC_DEFAULT_BASE + reg);
-}
+#define LAPIC_RRR			0x0c0
 
-static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
-{
-	do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
-}
+#define LAPIC_SPIV			0x0f0
+#define LAPIC_SPIV_ENABLE		0x100
 
-static inline void enable_lapic(void)
-{
-	msr_t msr;
+#define LAPIC_ICR			0x300
+#define LAPIC_DEST_SELF			0x40000
+#define LAPIC_DEST_ALLINC		0x80000
+#define LAPIC_DEST_ALLBUT		0xc0000
+#define LAPIC_ICR_RR_MASK		0x30000
+#define LAPIC_ICR_RR_INVALID		0x00000
+#define LAPIC_ICR_RR_INPROG		0x10000
+#define LAPIC_ICR_RR_VALID		0x20000
+#define LAPIC_INT_LEVELTRIG		0x08000
+#define LAPIC_INT_ASSERT		0x04000
+#define LAPIC_ICR_BUSY			0x01000
+#define LAPIC_DEST_LOGICAL		0x00800
+#define LAPIC_DM_FIXED			0x00000
+#define LAPIC_DM_LOWEST			0x00100
+#define LAPIC_DM_SMI			0x00200
+#define LAPIC_DM_REMRD			0x00300
+#define LAPIC_DM_NMI			0x00400
+#define LAPIC_DM_INIT			0x00500
+#define LAPIC_DM_STARTUP		0x00600
+#define LAPIC_DM_EXTINT			0x00700
+#define LAPIC_VECTOR_MASK		0x000ff
 
-	msr = msr_read(LAPIC_BASE_MSR);
-	msr.hi &= 0xffffff00;
-	msr.lo |= LAPIC_BASE_MSR_ENABLE;
-	msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
-	msr.lo |= LAPIC_DEFAULT_BASE;
-	msr_write(LAPIC_BASE_MSR, msr);
-}
+#define LAPIC_ICR2			0x310
+#define GET_LAPIC_DEST_FIELD(x)		(((x) >> 24) & 0xff)
+#define SET_LAPIC_DEST_FIELD(x)		((x) << 24)
 
-static inline void disable_lapic(void)
-{
-	msr_t msr;
+#define LAPIC_LVT0			0x350
+#define LAPIC_LVT1			0x360
+#define LAPIC_LVT_MASKED		(1 << 16)
+#define LAPIC_LVT_LEVEL_TRIGGER		(1 << 15)
+#define LAPIC_LVT_REMOTE_IRR		(1 << 14)
+#define LAPIC_INPUT_POLARITY		(1 << 13)
+#define LAPIC_SEND_PENDING		(1 << 12)
+#define LAPIC_LVT_RESERVED_1		(1 << 11)
+#define LAPIC_DELIVERY_MODE_MASK	(7 << 8)
+#define LAPIC_DELIVERY_MODE_FIXED	(0 << 8)
+#define LAPIC_DELIVERY_MODE_NMI		(4 << 8)
+#define LAPIC_DELIVERY_MODE_EXTINT	(7 << 8)
 
-	msr = msr_read(LAPIC_BASE_MSR);
-	msr.lo &= ~(1 << 11);
-	msr_write(LAPIC_BASE_MSR, msr);
-}
+unsigned long lapic_read(unsigned long reg);
 
-static inline __attribute__((always_inline)) unsigned long lapicid(void)
-{
-	return lapic_read(LAPIC_ID) >> 24;
-}
+void lapic_write(unsigned long reg, unsigned long v);
 
-#if !CONFIG_AP_IN_SIPI_WAIT
-/* If we need to go back to sipi wait, we use the long non-inlined version of
- * this function in lapic_cpu_init.c
- */
-static inline __attribute__((always_inline)) void stop_this_cpu(void)
-{
-	/* Called by an AP when it is ready to halt and wait for a new task */
-	for (;;)
-		cpu_hlt();
-}
-#else
-void stop_this_cpu(void);
-#endif
+void enable_lapic(void);
 
-#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
-							sizeof(*(ptr))))
+void disable_lapic(void);
 
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
+unsigned long lapicid(void);
 
-/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
- * Note 2: xchg has side effect, so that attribute volatile is necessary,
- *	  but generally the primitive is invalid, *ptr is output argument. --ANK
- */
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
-				   int size)
-{
-	switch (size) {
-	case 1:
-		__asm__ __volatile__("xchgb %b0,%1"
-			: "=q" (x)
-			: "m" (*__xg(ptr)), "0" (x)
-			: "memory");
-		break;
-	case 2:
-		__asm__ __volatile__("xchgw %w0,%1"
-			: "=r" (x)
-			: "m" (*__xg(ptr)), "0" (x)
-			: "memory");
-		break;
-	case 4:
-		__asm__ __volatile__("xchgl %0,%1"
-			: "=r" (x)
-			: "m" (*__xg(ptr)), "0" (x)
-			: "memory");
-		break;
-	}
-
-	return x;
-}
-
-static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
-{
-	(void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
-}
-
-
-#ifdef X86_GOOD_APIC
-# define FORCE_READ_AROUND_WRITE 0
-# define lapic_read_around(x) lapic_read(x)
-# define lapic_write_around(x, y) lapic_write((x), (y))
-#else
-# define FORCE_READ_AROUND_WRITE 1
-# define lapic_read_around(x) lapic_read(x)
-# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
-#endif
-
-static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
-{
-	int timeout;
-	unsigned long status;
-	int result;
-	lapic_wait_icr_idle();
-	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
-	lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
-	timeout = 0;
-	do {
-		status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
-	} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
-
-	result = -1;
-	if (status == LAPIC_ICR_RR_VALID) {
-		*pvalue = lapic_read(LAPIC_RRR);
-		result = 0;
-	}
-	return result;
-}
-
+int lapic_remote_read(int apicid, int reg, unsigned long *pvalue);
 
 void lapic_setup(void);
 
-#if CONFIG_SMP
-struct device;
-int start_cpu(struct device *cpu);
-#endif /* CONFIG_SMP */
-
-int boot_cpu(void);
-
-/**
- * struct x86_cpu_priv - Information about a single CPU
- *
- * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
- * just a number representing the CPU core
- *
- * TODO: Move this to driver model once lifecycle is understood
- */
-struct x86_cpu_priv {
-	int apic_id;
-	int start_err;
-};
-
 #endif
diff --git a/arch/x86/include/asm/lapic_def.h b/arch/x86/include/asm/lapic_def.h
deleted file mode 100644
index 722cead..0000000
--- a/arch/x86/include/asm/lapic_def.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Taken from the Coreboot file of the same name
- *
- * (C) Copyright 2014 Google, Inc
- *
- * SPDX-License-Identifier:	GPL-2.0
- */
-
-#ifndef _ASM_LAPIC_DEF_H
-#define _ASM_LAPIC_DEF_H
-
-#define LAPIC_BASE_MSR			0x1B
-#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR	(1 << 8)
-#define LAPIC_BASE_MSR_ENABLE		(1 << 11)
-#define LAPIC_BASE_MSR_ADDR_MASK	0xFFFFF000
-
-#define LOCAL_APIC_ADDR			0xfee00000
-#define LAPIC_DEFAULT_BASE		LOCAL_APIC_ADDR
-
-#define LAPIC_ID			0x020
-#define LAPIC_LVR			0x030
-#define LAPIC_TASKPRI			0x80
-#define LAPIC_TPRI_MASK			0xFF
-#define LAPIC_ARBID			0x090
-#define LAPIC_RRR			0x0C0
-#define LAPIC_SVR			0x0f0
-#define LAPIC_SPIV			0x0f0
-#define LAPIC_SPIV_ENABLE		0x100
-#define LAPIC_ESR			0x280
-#define LAPIC_ESR_SEND_CS		0x00001
-#define LAPIC_ESR_RECV_CS		0x00002
-#define LAPIC_ESR_SEND_ACC		0x00004
-#define LAPIC_ESR_RECV_ACC		0x00008
-#define LAPIC_ESR_SENDILL		0x00020
-#define LAPIC_ESR_RECVILL		0x00040
-#define LAPIC_ESR_ILLREGA		0x00080
-#define LAPIC_ICR			0x300
-#define LAPIC_DEST_SELF			0x40000
-#define LAPIC_DEST_ALLINC		0x80000
-#define LAPIC_DEST_ALLBUT		0xC0000
-#define LAPIC_ICR_RR_MASK		0x30000
-#define LAPIC_ICR_RR_INVALID		0x00000
-#define LAPIC_ICR_RR_INPROG		0x10000
-#define LAPIC_ICR_RR_VALID		0x20000
-#define LAPIC_INT_LEVELTRIG		0x08000
-#define LAPIC_INT_ASSERT		0x04000
-#define LAPIC_ICR_BUSY			0x01000
-#define LAPIC_DEST_LOGICAL		0x00800
-#define LAPIC_DM_FIXED			0x00000
-#define LAPIC_DM_LOWEST			0x00100
-#define LAPIC_DM_SMI			0x00200
-#define LAPIC_DM_REMRD			0x00300
-#define LAPIC_DM_NMI			0x00400
-#define LAPIC_DM_INIT			0x00500
-#define LAPIC_DM_STARTUP		0x00600
-#define LAPIC_DM_EXTINT			0x00700
-#define LAPIC_VECTOR_MASK		0x000FF
-#define LAPIC_ICR2			0x310
-#define GET_LAPIC_DEST_FIELD(x)		(((x) >> 24) & 0xFF)
-#define SET_LAPIC_DEST_FIELD(x)		((x) << 24)
-#define LAPIC_LVTT			0x320
-#define LAPIC_LVTPC			0x340
-#define LAPIC_LVT0			0x350
-#define LAPIC_LVT_TIMER_BASE_MASK	(0x3 << 18)
-#define GET_LAPIC_TIMER_BASE(x)		(((x) >> 18) & 0x3)
-#define SET_LAPIC_TIMER_BASE(x)		(((x) << 18))
-#define LAPIC_TIMER_BASE_CLKIN		0x0
-#define LAPIC_TIMER_BASE_TMBASE		0x1
-#define LAPIC_TIMER_BASE_DIV		0x2
-#define LAPIC_LVT_TIMER_PERIODIC	(1 << 17)
-#define LAPIC_LVT_MASKED		(1 << 16)
-#define LAPIC_LVT_LEVEL_TRIGGER		(1 << 15)
-#define LAPIC_LVT_REMOTE_IRR		(1 << 14)
-#define LAPIC_INPUT_POLARITY		(1 << 13)
-#define LAPIC_SEND_PENDING		(1 << 12)
-#define LAPIC_LVT_RESERVED_1		(1 << 11)
-#define LAPIC_DELIVERY_MODE_MASK	(7 << 8)
-#define LAPIC_DELIVERY_MODE_FIXED	(0 << 8)
-#define LAPIC_DELIVERY_MODE_NMI		(4 << 8)
-#define LAPIC_DELIVERY_MODE_EXTINT	(7 << 8)
-#define GET_LAPIC_DELIVERY_MODE(x)	(((x) >> 8) & 0x7)
-#define SET_LAPIC_DELIVERY_MODE(x, y)	(((x) & ~0x700)|((y) << 8))
-#define LAPIC_MODE_FIXED		0x0
-#define LAPIC_MODE_NMI			0x4
-#define LAPIC_MODE_EXINT		0x7
-#define LAPIC_LVT1			0x360
-#define LAPIC_LVTERR			0x370
-#define LAPIC_TMICT			0x380
-#define LAPIC_TMCCT			0x390
-#define LAPIC_TDCR			0x3E0
-#define LAPIC_TDR_DIV_TMBASE		(1 << 2)
-#define LAPIC_TDR_DIV_1			0xB
-#define LAPIC_TDR_DIV_2			0x0
-#define LAPIC_TDR_DIV_4			0x1
-#define LAPIC_TDR_DIV_8			0x2
-#define LAPIC_TDR_DIV_16		0x3
-#define LAPIC_TDR_DIV_32		0x8
-#define LAPIC_TDR_DIV_64		0x9
-#define LAPIC_TDR_DIV_128		0xA
-
-#endif
diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h
index c0930fd..2e6c312 100644
--- a/arch/x86/include/asm/mp.h
+++ b/arch/x86/include/asm/mp.h
@@ -59,7 +59,6 @@
  * SMM support.
  */
 struct mp_params {
-	int num_cpus; /* Total cpus include BSP */
 	int parallel_microcode_load;
 	const void *microcode_pointer;
 	/* Flight plan  for APs and BSP */
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
new file mode 100644
index 0000000..efa9231
--- /dev/null
+++ b/arch/x86/include/asm/mpspec.h
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Adapted from coreboot src/arch/x86/include/arch/smp/mpspec.h
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_MPSPEC_H
+#define __ASM_MPSPEC_H
+
+/*
+ * Structure definitions for SMP machines following the
+ * Intel MultiProcessor Specification 1.4
+ */
+
+#define MPSPEC_V14	4
+
+#define MPF_SIGNATURE	"_MP_"
+
+struct mp_floating_table {
+	char mpf_signature[4];	/* "_MP_" */
+	u32 mpf_physptr;	/* Configuration table address */
+	u8 mpf_length;		/* Our length (paragraphs) */
+	u8 mpf_spec;		/* Specification version */
+	u8 mpf_checksum;	/* Checksum (makes sum 0) */
+	u8 mpf_feature1;	/* Predefined or Unique configuration? */
+	u8 mpf_feature2;	/* Bit7 set for IMCR/PIC */
+	u8 mpf_feature3;	/* Unused (0) */
+	u8 mpf_feature4;	/* Unused (0) */
+	u8 mpf_feature5;	/* Unused (0) */
+};
+
+#define MPC_SIGNATURE	"PCMP"
+
+struct mp_config_table {
+	char mpc_signature[4];	/* "PCMP" */
+	u16 mpc_length;		/* Size of table */
+	u8 mpc_spec;		/* Specification version */
+	u8 mpc_checksum;	/* Checksum (makes sum 0) */
+	char mpc_oem[8];	/* OEM ID */
+	char mpc_product[12];	/* Product ID */
+	u32 mpc_oemptr;		/* OEM table address */
+	u16 mpc_oemsize;	/* OEM table size */
+	u16 mpc_entry_count;	/* Number of entries in the table */
+	u32 mpc_lapic;		/* Local APIC address */
+	u16 mpe_length;		/* Extended table size */
+	u8 mpe_checksum;	/* Extended table checksum */
+	u8 reserved;
+};
+
+/* Base MP configuration table entry types */
+
+enum mp_base_config_entry_type {
+	MP_PROCESSOR,
+	MP_BUS,
+	MP_IOAPIC,
+	MP_INTSRC,
+	MP_LINTSRC
+};
+
+#define MPC_CPU_EN	(1 << 0)
+#define MPC_CPU_BP	(1 << 1)
+
+struct mpc_config_processor {
+	u8 mpc_type;
+	u8 mpc_apicid;
+	u8 mpc_apicver;
+	u8 mpc_cpuflag;
+	u32 mpc_cpusignature;
+	u32 mpc_cpufeature;
+	u32 mpc_reserved[2];
+};
+
+#define BUSTYPE_CBUS	"CBUS  "
+#define BUSTYPE_CBUSII	"CBUSII"
+#define BUSTYPE_EISA	"EISA  "
+#define BUSTYPE_FUTURE	"FUTURE"
+#define BUSTYPE_INTERN	"INTERN"
+#define BUSTYPE_ISA	"ISA   "
+#define BUSTYPE_MBI	"MBI   "
+#define BUSTYPE_MBII	"MBII  "
+#define BUSTYPE_MCA	"MCA   "
+#define BUSTYPE_MPI	"MPI   "
+#define BUSTYPE_MPSA	"MPSA  "
+#define BUSTYPE_NUBUS	"NUBUS "
+#define BUSTYPE_PCI	"PCI   "
+#define BUSTYPE_PCMCIA	"PCMCIA"
+#define BUSTYPE_TC	"TC    "
+#define BUSTYPE_VL	"VL    "
+#define BUSTYPE_VME	"VME   "
+#define BUSTYPE_XPRESS	"XPRESS"
+
+struct mpc_config_bus {
+	u8 mpc_type;
+	u8 mpc_busid;
+	u8 mpc_bustype[6];
+};
+
+#define MPC_APIC_USABLE	(1 << 0)
+
+struct mpc_config_ioapic {
+	u8 mpc_type;
+	u8 mpc_apicid;
+	u8 mpc_apicver;
+	u8 mpc_flags;
+	u32 mpc_apicaddr;
+};
+
+enum mp_irq_source_types {
+	MP_INT,
+	MP_NMI,
+	MP_SMI,
+	MP_EXTINT
+};
+
+#define MP_IRQ_POLARITY_DEFAULT	0x0
+#define MP_IRQ_POLARITY_HIGH	0x1
+#define MP_IRQ_POLARITY_LOW	0x3
+#define MP_IRQ_POLARITY_MASK	0x3
+#define MP_IRQ_TRIGGER_DEFAULT	0x0
+#define MP_IRQ_TRIGGER_EDGE	0x4
+#define MP_IRQ_TRIGGER_LEVEL	0xc
+#define MP_IRQ_TRIGGER_MASK	0xc
+
+#define MP_APIC_ALL		0xff
+
+struct mpc_config_intsrc {
+	u8 mpc_type;
+	u8 mpc_irqtype;
+	u16 mpc_irqflag;
+	u8 mpc_srcbus;
+	u8 mpc_srcbusirq;
+	u8 mpc_dstapic;
+	u8 mpc_dstirq;
+};
+
+struct mpc_config_lintsrc {
+	u8 mpc_type;
+	u8 mpc_irqtype;
+	u16 mpc_irqflag;
+	u8 mpc_srcbusid;
+	u8 mpc_srcbusirq;
+	u8 mpc_destapic;
+	u8 mpc_destlint;
+};
+
+/* Extended MP configuration table entry types */
+
+enum mp_ext_config_entry_type {
+	MPE_SYSTEM_ADDRESS_SPACE = 128,
+	MPE_BUS_HIERARCHY,
+	MPE_COMPAT_ADDRESS_SPACE
+};
+
+struct mp_ext_config {
+	u8 mpe_type;
+	u8 mpe_length;
+};
+
+#define ADDRESS_TYPE_IO		0
+#define ADDRESS_TYPE_MEM	1
+#define ADDRESS_TYPE_PREFETCH	2
+
+struct mp_ext_system_address_space {
+	u8 mpe_type;
+	u8 mpe_length;
+	u8 mpe_busid;
+	u8 mpe_addr_type;
+	u32 mpe_addr_base_low;
+	u32 mpe_addr_base_high;
+	u32 mpe_addr_length_low;
+	u32 mpe_addr_length_high;
+};
+
+#define BUS_SUBTRACTIVE_DECODE	(1 << 0)
+
+struct mp_ext_bus_hierarchy {
+	u8 mpe_type;
+	u8 mpe_length;
+	u8 mpe_busid;
+	u8 mpe_bus_info;
+	u8 mpe_parent_busid;
+	u8 reserved[3];
+};
+
+#define ADDRESS_RANGE_ADD	0
+#define ADDRESS_RANGE_SUBTRACT	1
+
+/*
+ * X100 - X3FF
+ * X500 - X7FF
+ * X900 - XBFF
+ * XD00 - XFFF
+ */
+#define RANGE_LIST_IO_ISA	0
+/*
+ * X3B0 - X3BB
+ * X3C0 - X3DF
+ * X7B0 - X7BB
+ * X7C0 - X7DF
+ * XBB0 - XBBB
+ * XBC0 - XBDF
+ * XFB0 - XFBB
+ * XFC0 - XCDF
+ */
+#define RANGE_LIST_IO_VGA	1
+
+struct mp_ext_compat_address_space {
+	u8 mpe_type;
+	u8 mpe_length;
+	u8 mpe_busid;
+	u8 mpe_addr_modifier;
+	u32 mpe_range_list;
+};
+
+/**
+ * mp_next_mpc_entry() - Compute MP configuration table end to be used as
+ *                       next base table entry start address
+ *
+ * This computes the end address of current MP configuration table, without
+ * counting any extended configuration table entry.
+ *
+ * @mc:		configuration table header address
+ * @return:	configuration table end address
+ */
+static inline u32 mp_next_mpc_entry(struct mp_config_table *mc)
+{
+	return (u32)mc + mc->mpc_length;
+}
+
+/**
+ * mp_add_mpc_entry() - Add a base MP configuration table entry
+ *
+ * This adds the base MP configuration table entry size with
+ * added base table entry length and increases entry count by 1.
+ *
+ * @mc:		configuration table header address
+ * @length:	length of the added table entry
+ */
+static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length)
+{
+	mc->mpc_length += length;
+	mc->mpc_entry_count++;
+}
+
+/**
+ * mp_next_mpe_entry() - Compute MP configuration table end to be used as
+ *                       next extended table entry start address
+ *
+ * This computes the end address of current MP configuration table,
+ * including any extended configuration table entry.
+ *
+ * @mc:		configuration table header address
+ * @return:	configuration table end address
+ */
+static inline u32 mp_next_mpe_entry(struct mp_config_table *mc)
+{
+	return (u32)mc + mc->mpc_length + mc->mpe_length;
+}
+
+/**
+ * mp_add_mpe_entry() - Add an extended MP configuration table entry
+ *
+ * This adds the extended MP configuration table entry size with
+ * added extended table entry length.
+ *
+ * @mc:		configuration table header address
+ * @mpe:	extended table entry base address
+ */
+static inline void mp_add_mpe_entry(struct mp_config_table *mc,
+				    struct mp_ext_config *mpe)
+{
+	mc->mpe_length += mpe->mpe_length;
+}
+
+/**
+ * mp_write_floating_table() - Write the MP floating table
+ *
+ * This writes the MP floating table, and points MP configuration table
+ * to its end address so that MP configuration table follows immediately
+ * after the floating table.
+ *
+ * @mf:		MP floating table base address
+ * @return:	MP configuration table header address
+ */
+struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf);
+
+/**
+ * mp_config_table_init() - Initialize the MP configuration table header
+ *
+ * This populates the MP configuration table header with valid bits.
+ *
+ * @mc:		MP configuration table header address
+ */
+void mp_config_table_init(struct mp_config_table *mc);
+
+/**
+ * mp_write_processor() - Write a processor entry
+ *
+ * This writes a processor entry to the configuration table.
+ *
+ * @mc:		MP configuration table header address
+ */
+void mp_write_processor(struct mp_config_table *mc);
+
+/**
+ * mp_write_bus() - Write a bus entry
+ *
+ * This writes a bus entry to the configuration table.
+ *
+ * @mc:		MP configuration table header address
+ * @id:		bus id
+ * @bustype:	bus type name
+ */
+void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype);
+
+/**
+ * mp_write_ioapic() - Write an I/O APIC entry
+ *
+ * This writes an I/O APIC entry to the configuration table.
+ *
+ * @mc:		MP configuration table header address
+ * @id:		I/O APIC id
+ * @ver:	I/O APIC version
+ * @apicaddr:	I/O APIC address
+ */
+void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr);
+
+/**
+ * mp_write_intsrc() - Write an I/O interrupt assignment entry
+ *
+ * This writes an I/O interrupt assignment entry to the configuration table.
+ *
+ * @mc:		MP configuration table header address
+ * @irqtype:	IRQ type (INT/NMI/SMI/ExtINT)
+ * @irqflag:	IRQ flag (level/trigger)
+ * @srcbus:	source bus id where the interrupt comes from
+ * @srcbusirq:	IRQ number mapped on the source bus
+ * @dstapic:	destination I/O APIC id where the interrupt goes to
+ * @dstirq:	destination I/O APIC pin where the interrupt goes to
+ */
+void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+		     int srcbus, int srcbusirq, int dstapic, int dstirq);
+
+/**
+ * mp_write_pci_intsrc() - Write a PCI interrupt assignment entry
+ *
+ * This writes a PCI interrupt assignment entry to the configuration table.
+ *
+ * @mc:		MP configuration table header address
+ * @irqtype:	IRQ type (INT/NMI/SMI/ExtINT)
+ * @srcbus:	PCI bus number where the interrupt comes from
+ * @dev:	device number on the PCI bus
+ * @pin:	PCI interrupt pin (INT A/B/C/D)
+ * @dstapic:	destination I/O APIC id where the interrupt goes to
+ * @dstirq:	destination I/O APIC pin where the interrupt goes to
+ */
+void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
+			 int srcbus, int dev, int pin, int dstapic, int dstirq);
+
+/**
+ * mp_write_lintsrc() - Write a local interrupt assignment entry
+ *
+ * This writes a local interrupt assignment entry to the configuration table.
+ *
+ * @mc:		MP configuration table header address
+ * @irqtype:	IRQ type (INT/NMI/SMI/ExtINT)
+ * @irqflag:	IRQ flag (level/trigger)
+ * @srcbus:	PCI bus number where the interrupt comes from
+ * @srcbusirq:	IRQ number mapped on the source bus
+ * @dstapic:	destination local APIC id where the interrupt goes to
+ * @destlint:	destination local APIC pin where the interrupt goes to
+ */
+void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+		      int srcbus, int srcbusirq, int destapic, int destlint);
+
+
+/**
+ * mp_write_address_space() - Write a system address space entry
+ *
+ * This writes a system address space entry to the configuration table.
+ *
+ * @mc:			MP configuration table header address
+ * @busid:		bus id for the bus where system address space is mapped
+ * @addr_type:		system address type
+ * @addr_base_low:	starting address low
+ * @addr_base_high:	starting address high
+ * @addr_length_low:	address length low
+ * @addr_length_high:	address length high
+ */
+void mp_write_address_space(struct mp_config_table *mc,
+			    int busid, int addr_type,
+			    u32 addr_base_low, u32 addr_base_high,
+			    u32 addr_length_low, u32 addr_length_high);
+
+/**
+ * mp_write_bus_hierarchy() - Write a bus hierarchy descriptor entry
+ *
+ * This writes a bus hierarchy descriptor entry to the configuration table.
+ *
+ * @mc:			MP configuration table header address
+ * @busid:		bus id
+ * @bus_info:		bit0 indicates if the bus is a subtractive decode bus
+ * @parent_busid:	parent bus id
+ */
+void mp_write_bus_hierarchy(struct mp_config_table *mc,
+			    int busid, int bus_info, int parent_busid);
+
+/**
+ * mp_write_compat_address_space() - Write a compat bus address space entry
+ *
+ * This writes a compatibility bus address space modifier entry to the
+ * configuration table.
+ *
+ * @mc:			MP configuration table header address
+ * @busid:		bus id
+ * @addr_modifier:	add or subtract to predefined address range list
+ * @range_list:		list of predefined address space ranges
+ */
+void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
+				   int addr_modifier, u32 range_list);
+
+/**
+ * mptable_finalize() - Finalize the MP table
+ *
+ * This finalizes the MP table by calculating required checksums.
+ *
+ * @mc:		MP configuration table header address
+ * @return:	MP table end address
+ */
+u32 mptable_finalize(struct mp_config_table *mc);
+
+/**
+ * write_mp_table() - Write MP table
+ *
+ * This writes MP table at a given address.
+ *
+ * @addr:	start address to write MP table
+ * @return:	end address of MP table
+ */
+u32 write_mp_table(u32 addr);
+
+#endif /* __ASM_MPSPEC_H */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 3ad617c..70762ee 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -21,6 +21,11 @@
 #define MTRR_CAP_MSR		0x0fe
 #define MTRR_DEF_TYPE_MSR	0x2ff
 
+#define MTRR_CAP_SMRR		(1 << 11)
+#define MTRR_CAP_WC		(1 << 10)
+#define MTRR_CAP_FIX		(1 << 8)
+#define MTRR_CAP_VCNT_MASK	0xff
+
 #define MTRR_DEF_TYPE_EN	(1 << 11)
 #define MTRR_DEF_TYPE_FIX_EN	(1 << 10)
 
@@ -38,17 +43,17 @@
 #define RANGES_PER_FIXED_MTRR	8
 #define NUM_FIXED_RANGES	(NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR)
 
-#define MTRR_FIX_64K_00000_MSR 0x250
-#define MTRR_FIX_16K_80000_MSR 0x258
-#define MTRR_FIX_16K_A0000_MSR 0x259
-#define MTRR_FIX_4K_C0000_MSR 0x268
-#define MTRR_FIX_4K_C8000_MSR 0x269
-#define MTRR_FIX_4K_D0000_MSR 0x26a
-#define MTRR_FIX_4K_D8000_MSR 0x26b
-#define MTRR_FIX_4K_E0000_MSR 0x26c
-#define MTRR_FIX_4K_E8000_MSR 0x26d
-#define MTRR_FIX_4K_F0000_MSR 0x26e
-#define MTRR_FIX_4K_F8000_MSR 0x26f
+#define MTRR_FIX_64K_00000_MSR	0x250
+#define MTRR_FIX_16K_80000_MSR	0x258
+#define MTRR_FIX_16K_A0000_MSR	0x259
+#define MTRR_FIX_4K_C0000_MSR	0x268
+#define MTRR_FIX_4K_C8000_MSR	0x269
+#define MTRR_FIX_4K_D0000_MSR	0x26a
+#define MTRR_FIX_4K_D8000_MSR	0x26b
+#define MTRR_FIX_4K_E0000_MSR	0x26c
+#define MTRR_FIX_4K_E8000_MSR	0x26d
+#define MTRR_FIX_4K_F0000_MSR	0x26e
+#define MTRR_FIX_4K_F8000_MSR	0x26f
 
 #if !defined(__ASSEMBLER__)
 
diff --git a/arch/x86/include/asm/tables.h b/arch/x86/include/asm/tables.h
index 8146ba3..0aa6d9b 100644
--- a/arch/x86/include/asm/tables.h
+++ b/arch/x86/include/asm/tables.h
@@ -28,6 +28,20 @@
 u8 table_compute_checksum(void *v, int len);
 
 /**
+ * table_fill_string() - Fill a string with pad in the configuration table
+ *
+ * This fills a string in the configuration table. It copies number of bytes
+ * from the source string, and if source string length is shorter than the
+ * required size to copy, pad the table string with the given pad character.
+ *
+ * @dest:	where to fill a string
+ * @src:	where to copy from
+ * @n:		number of bytes to copy
+ * @pad:	character to pad the remaining bytes
+ */
+void table_fill_string(char *dest, const char *src, size_t n, char pad);
+
+/**
  * write_tables() - Write x86 configuration tables
  *
  * This writes x86 configuration tables, including PIRQ routing table,
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index d1d21ed..4dae365 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -8,12 +8,19 @@
 #ifndef _U_BOOT_I386_H_
 #define _U_BOOT_I386_H_	1
 
+extern char gdt_rom[];
+
 /* cpu/.../cpu.c */
 int arch_cpu_init(void);
 int x86_cpu_init_f(void);
 int cpu_init_f(void);
 void init_gd(gd_t *id, u64 *gdt_addr);
 void setup_gdt(gd_t *id, u64 *gdt_addr);
+/*
+ * Setup FSP execution environment GDT to use the one we used in
+ * arch/x86/cpu/start16.S and reload the segment registers.
+ */
+void setup_fsp_gdt(void);
 int init_cache(void);
 int cleanup_before_linux(void);
 
@@ -49,6 +56,9 @@
 /* arch/x86/lib/... */
 int video_bios_init(void);
 
+/* arch/x86/lib/fsp/... */
+int x86_fsp_init(void);
+
 void	board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
 void	board_init_f_r(void) __attribute__ ((noreturn));
 
diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
index 8e7dd42..bf351ed 100644
--- a/arch/x86/include/asm/zimage.h
+++ b/arch/x86/include/asm/zimage.h
@@ -38,5 +38,6 @@
 				ulong *load_addressp);
 int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
 		 unsigned long initrd_addr, unsigned long initrd_size);
+void setup_video(struct screen_info *screen_info);
 
 #endif
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 70ad19b..43489fd 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -15,6 +15,7 @@
 obj-y	+= init_helpers.o
 obj-y	+= interrupts.o
 obj-y	+= lpc-uclass.o
+obj-y	+= mpspec.o
 obj-y += cmd_mtrr.o
 obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
 obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o
diff --git a/arch/x86/lib/bios_asm.S b/arch/x86/lib/bios_asm.S
index 4faa70e..9dbf969 100644
--- a/arch/x86/lib/bios_asm.S
+++ b/arch/x86/lib/bios_asm.S
@@ -246,6 +246,9 @@
 	push	%fs
 	push	%gs
 
+	/* Save real mode SS */
+	movw	%ss, %cs:__realmode_ss
+
 	/* Clear DF to not break ABI assumptions */
 	cld
 
@@ -258,12 +261,29 @@
 
 	enter_protected_mode
 
+	/*
+	 * Now we are in protected mode. We need compute the right ESP based
+	 * on saved real mode SS otherwise interrupt_handler() won't get
+	 * correct parameters from the stack.
+	 */
+	movzwl	%cs:__realmode_ss, %ecx
+	shll	$4, %ecx
+	addl	%ecx, %esp
+
 	/* Call the C interrupt handler */
 	movl	$interrupt_handler, %eax
 	call	*%eax
 
+	/* Restore real mode ESP based on saved SS */
+	movzwl	%cs:__realmode_ss, %ecx
+	shll	$4, %ecx
+	subl	%ecx, %esp
+
 	enter_real_mode
 
+	/* Restore real mode SS */
+	movw	%cs:__realmode_ss, %ss
+
 	/*
 	 * Restore all registers, including those manipulated by the C
 	 * handler
@@ -276,6 +296,9 @@
 	popal
 	iret
 
+__realmode_ss = PTR_TO_REAL_MODE(.)
+	.word	0
+
 	.globl asm_realmode_code_size
 asm_realmode_code_size:
 	.long  . - asm_realmode_code
diff --git a/arch/x86/lib/bios_interrupts.c b/arch/x86/lib/bios_interrupts.c
index 290990a..47d9f59 100644
--- a/arch/x86/lib/bios_interrupts.c
+++ b/arch/x86/lib/bios_interrupts.c
@@ -161,15 +161,7 @@
 		bus = M.x86.R_EBX >> 8;
 		reg = M.x86.R_EDI;
 		dev = PCI_BDF(bus, devfn >> 3, devfn & 7);
-		if (!dev) {
-			debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func,
-			      bus, devfn);
-			/* Or are we supposed to return PCIBIOS_NODEV? */
-			M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
-			M.x86.R_EAX |= PCIBIOS_BADREG;
-			retval = 0;
-			return retval;
-		}
+
 		switch (func) {
 		case 0xb108: /* Read Config Byte */
 			byte = x86_pci_read_config8(dev, reg);
diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c
index 7e0506b..f632f49 100644
--- a/arch/x86/lib/cmd_mtrr.c
+++ b/arch/x86/lib/cmd_mtrr.c
@@ -37,7 +37,8 @@
 		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);
+		       valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
+		       mask & ~MTRR_PHYS_MASK_VALID, size);
 	}
 
 	return 0;
diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp/fsp_car.S
index 5e09568..afbf3f9 100644
--- a/arch/x86/lib/fsp/fsp_car.S
+++ b/arch/x86/lib/fsp/fsp_car.S
@@ -56,28 +56,10 @@
 
 	/* stack grows down from top of CAR */
 	movl	%edx, %esp
+	subl	$4, %esp
 
-	/*
-	 * TODO:
-	 *
-	 * According to FSP architecture spec, the fsp_init() will not return
-	 * to its caller, instead it requires the bootloader to provide a
-	 * so-called continuation function to pass into the FSP as a parameter
-	 * of fsp_init, and fsp_init() will call that continuation function
-	 * directly.
-	 *
-	 * The call to fsp_init() may need to be moved out of the car_init()
-	 * to cpu_init_f() with the help of some inline assembly codes.
-	 * Note there is another issue that fsp_init() will setup another stack
-	 * using the fsp_init parameter stack_top after DRAM is initialized,
-	 * which means any data on the previous stack (on the CAR) gets lost
-	 * (ie: U-Boot global_data). FSP is supposed to support such scenario,
-	 * however it does not work. This should be revisited in the future.
-	 */
-	movl	$CONFIG_FSP_TEMP_RAM_ADDR, %eax
-	xorl	%edx, %edx
-	xorl	%ecx, %ecx
-	call	fsp_init
+	xor	%esi, %esi
+	jmp	car_init_done
 
 .global fsp_init_done
 fsp_init_done:
@@ -86,6 +68,8 @@
 	 * Save eax to esi temporarily.
 	 */
 	movl	%eax, %esi
+
+car_init_done:
 	/*
 	 * Re-initialize the ebp (BIST) to zero, as we already reach here
 	 * which means we passed BIST testing before.
diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c
index 001494d..5b25632 100644
--- a/arch/x86/lib/fsp/fsp_common.c
+++ b/arch/x86/lib/fsp/fsp_common.c
@@ -46,3 +46,11 @@
 
 	return;
 }
+
+int x86_fsp_init(void)
+{
+	if (!gd->arch.hob_list)
+		fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, NULL);
+
+	return 0;
+}
diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index 5809235..4585166 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -173,6 +173,9 @@
 
 	post_code(POST_PRE_MRC);
 
+	/* Load GDT for FSP */
+	setup_fsp_gdt();
+
 	/*
 	 * Use ASM code to ensure the register value in EAX & ECX
 	 * will be passed into BlContinuationFunc
diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c
new file mode 100644
index 0000000..f16fbcb
--- /dev/null
+++ b/arch/x86/lib/mpspec.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * Adapted from coreboot src/arch/x86/boot/mpspec.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/cpu.h>
+#include <asm/irq.h>
+#include <asm/ioapic.h>
+#include <asm/lapic.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <dm/uclass-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf)
+{
+	u32 mc;
+
+	memcpy(mf->mpf_signature, MPF_SIGNATURE, 4);
+	mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table);
+	mf->mpf_length = 1;
+	mf->mpf_spec = MPSPEC_V14;
+	mf->mpf_checksum = 0;
+	/* We don't use the default configuration table */
+	mf->mpf_feature1 = 0;
+	/* Indicate that virtual wire mode is always implemented */
+	mf->mpf_feature2 = 0;
+	mf->mpf_feature3 = 0;
+	mf->mpf_feature4 = 0;
+	mf->mpf_feature5 = 0;
+	mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16);
+
+	mc = (u32)mf + sizeof(struct mp_floating_table);
+	return (struct mp_config_table *)mc;
+}
+
+void mp_config_table_init(struct mp_config_table *mc)
+{
+	memcpy(mc->mpc_signature, MPC_SIGNATURE, 4);
+	mc->mpc_length = sizeof(struct mp_config_table);
+	mc->mpc_spec = MPSPEC_V14;
+	mc->mpc_checksum = 0;
+	mc->mpc_oemptr = 0;
+	mc->mpc_oemsize = 0;
+	mc->mpc_entry_count = 0;
+	mc->mpc_lapic = LAPIC_DEFAULT_BASE;
+	mc->mpe_length = 0;
+	mc->mpe_checksum = 0;
+	mc->reserved = 0;
+
+	/* The oem/product id fields are exactly 8/12 bytes long */
+	table_fill_string(mc->mpc_oem, CONFIG_SYS_VENDOR, 8, ' ');
+	table_fill_string(mc->mpc_product, CONFIG_SYS_BOARD, 12, ' ');
+}
+
+void mp_write_processor(struct mp_config_table *mc)
+{
+	struct mpc_config_processor *mpc;
+	struct udevice *dev;
+	u8 boot_apicid, apicver;
+	u32 cpusignature, cpufeature;
+	struct cpuid_result result;
+
+	boot_apicid = lapicid();
+	apicver = lapic_read(LAPIC_LVR) & 0xff;
+	result = cpuid(1);
+	cpusignature = result.eax;
+	cpufeature = result.edx;
+
+	for (uclass_find_first_device(UCLASS_CPU, &dev);
+	     dev;
+	     uclass_find_next_device(&dev)) {
+		struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+		u8 cpuflag = MPC_CPU_EN;
+
+		if (!device_active(dev))
+			continue;
+
+		mpc = (struct mpc_config_processor *)mp_next_mpc_entry(mc);
+		mpc->mpc_type = MP_PROCESSOR;
+		mpc->mpc_apicid = plat->cpu_id;
+		mpc->mpc_apicver = apicver;
+		if (boot_apicid == plat->cpu_id)
+			cpuflag |= MPC_CPU_BP;
+		mpc->mpc_cpuflag = cpuflag;
+		mpc->mpc_cpusignature = cpusignature;
+		mpc->mpc_cpufeature = cpufeature;
+		mpc->mpc_reserved[0] = 0;
+		mpc->mpc_reserved[1] = 0;
+		mp_add_mpc_entry(mc, sizeof(*mpc));
+	}
+}
+
+void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype)
+{
+	struct mpc_config_bus *mpc;
+
+	mpc = (struct mpc_config_bus *)mp_next_mpc_entry(mc);
+	mpc->mpc_type = MP_BUS;
+	mpc->mpc_busid = id;
+	memcpy(mpc->mpc_bustype, bustype, 6);
+	mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr)
+{
+	struct mpc_config_ioapic *mpc;
+
+	mpc = (struct mpc_config_ioapic *)mp_next_mpc_entry(mc);
+	mpc->mpc_type = MP_IOAPIC;
+	mpc->mpc_apicid = id;
+	mpc->mpc_apicver = ver;
+	mpc->mpc_flags = MPC_APIC_USABLE;
+	mpc->mpc_apicaddr = apicaddr;
+	mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+		     int srcbus, int srcbusirq, int dstapic, int dstirq)
+{
+	struct mpc_config_intsrc *mpc;
+
+	mpc = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
+	mpc->mpc_type = MP_INTSRC;
+	mpc->mpc_irqtype = irqtype;
+	mpc->mpc_irqflag = irqflag;
+	mpc->mpc_srcbus = srcbus;
+	mpc->mpc_srcbusirq = srcbusirq;
+	mpc->mpc_dstapic = dstapic;
+	mpc->mpc_dstirq = dstirq;
+	mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
+			 int srcbus, int dev, int pin, int dstapic, int dstirq)
+{
+	u8 srcbusirq = (dev << 2) | (pin - 1);
+
+	mp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW,
+			srcbus, srcbusirq, dstapic, dstirq);
+}
+
+void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
+		      int srcbus, int srcbusirq, int destapic, int destlint)
+{
+	struct mpc_config_lintsrc *mpc;
+
+	mpc = (struct mpc_config_lintsrc *)mp_next_mpc_entry(mc);
+	mpc->mpc_type = MP_LINTSRC;
+	mpc->mpc_irqtype = irqtype;
+	mpc->mpc_irqflag = irqflag;
+	mpc->mpc_srcbusid = srcbus;
+	mpc->mpc_srcbusirq = srcbusirq;
+	mpc->mpc_destapic = destapic;
+	mpc->mpc_destlint = destlint;
+	mp_add_mpc_entry(mc, sizeof(*mpc));
+}
+
+void mp_write_address_space(struct mp_config_table *mc,
+			    int busid, int addr_type,
+			    u32 addr_base_low, u32 addr_base_high,
+			    u32 addr_length_low, u32 addr_length_high)
+{
+	struct mp_ext_system_address_space *mpe;
+
+	mpe = (struct mp_ext_system_address_space *)mp_next_mpe_entry(mc);
+	mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
+	mpe->mpe_length = sizeof(*mpe);
+	mpe->mpe_busid = busid;
+	mpe->mpe_addr_type = addr_type;
+	mpe->mpe_addr_base_low = addr_base_low;
+	mpe->mpe_addr_base_high = addr_base_high;
+	mpe->mpe_addr_length_low = addr_length_low;
+	mpe->mpe_addr_length_high = addr_length_high;
+	mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
+}
+
+void mp_write_bus_hierarchy(struct mp_config_table *mc,
+			    int busid, int bus_info, int parent_busid)
+{
+	struct mp_ext_bus_hierarchy *mpe;
+
+	mpe = (struct mp_ext_bus_hierarchy *)mp_next_mpe_entry(mc);
+	mpe->mpe_type = MPE_BUS_HIERARCHY;
+	mpe->mpe_length = sizeof(*mpe);
+	mpe->mpe_busid = busid;
+	mpe->mpe_bus_info = bus_info;
+	mpe->mpe_parent_busid = parent_busid;
+	mpe->reserved[0] = 0;
+	mpe->reserved[1] = 0;
+	mpe->reserved[2] = 0;
+	mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
+}
+
+void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
+				   int addr_modifier, u32 range_list)
+{
+	struct mp_ext_compat_address_space *mpe;
+
+	mpe = (struct mp_ext_compat_address_space *)mp_next_mpe_entry(mc);
+	mpe->mpe_type = MPE_COMPAT_ADDRESS_SPACE;
+	mpe->mpe_length = sizeof(*mpe);
+	mpe->mpe_busid = busid;
+	mpe->mpe_addr_modifier = addr_modifier;
+	mpe->mpe_range_list = range_list;
+	mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
+}
+
+u32 mptable_finalize(struct mp_config_table *mc)
+{
+	u32 end;
+
+	mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc),
+						  mc->mpe_length);
+	mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length);
+	end = mp_next_mpe_entry(mc);
+
+	debug("Write the MP table at: %x - %x\n", (u32)mc, end);
+
+	return end;
+}
+
+static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa,
+				       int apicid, int external_int2)
+{
+	int i;
+
+	mp_write_intsrc(mc, external_int2 ? MP_INT : MP_EXTINT,
+			MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+			bus_isa, 0, apicid, 0);
+	mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+			bus_isa, 1, apicid, 1);
+	mp_write_intsrc(mc, external_int2 ? MP_EXTINT : MP_INT,
+			MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+			bus_isa, 0, apicid, 2);
+
+	for (i = 3; i < 16; i++)
+		mp_write_intsrc(mc, MP_INT,
+				MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+				bus_isa, i, apicid, i);
+}
+
+/*
+ * Check duplicated I/O interrupt assignment table entry, to make sure
+ * there is only one entry with the given bus, device and interrupt pin.
+ */
+static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base,
+			    int entry_num, int bus, int device, int pin)
+{
+	struct mpc_config_intsrc *intsrc = intsrc_base;
+	int i;
+
+	for (i = 0; i < entry_num; i++) {
+		if (intsrc->mpc_srcbus == bus &&
+		    intsrc->mpc_srcbusirq == ((device << 2) | (pin - 1)))
+			break;
+		intsrc++;
+	}
+
+	return (i == entry_num) ? false : true;
+}
+
+static int mptable_add_intsrc(struct mp_config_table *mc,
+			      int bus_isa, int apicid)
+{
+	struct mpc_config_intsrc *intsrc_base;
+	int intsrc_entries = 0;
+	const void *blob = gd->fdt_blob;
+	int node;
+	int len, count;
+	const u32 *cell;
+	int i;
+
+	/* Legacy Interrupts */
+	debug("Writing ISA IRQs\n");
+	mptable_add_isa_interrupts(mc, bus_isa, apicid, 0);
+
+	/* Get I/O interrupt information from device tree */
+	node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER);
+	if (node < 0) {
+		debug("%s: Cannot find irq router node\n", __func__);
+		return -ENOENT;
+	}
+
+	cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
+	if (!cell)
+		return -ENOENT;
+
+	if ((len % sizeof(struct pirq_routing)) == 0)
+		count = len / sizeof(struct pirq_routing);
+	else
+		return -EINVAL;
+
+	intsrc_base = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
+
+	for (i = 0; i < count; i++) {
+		struct pirq_routing pr;
+
+		pr.bdf = fdt_addr_to_cpu(cell[0]);
+		pr.pin = fdt_addr_to_cpu(cell[1]);
+		pr.pirq = fdt_addr_to_cpu(cell[2]);
+
+		if (check_dup_entry(intsrc_base, intsrc_entries,
+				    PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) {
+			debug("found entry for bus %d device %d INT%c, skipping\n",
+			      PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
+			      'A' + pr.pin - 1);
+			cell += sizeof(struct pirq_routing) / sizeof(u32);
+			continue;
+		}
+
+		/* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */
+		mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf),
+				    PCI_DEV(pr.bdf), pr.pin, apicid,
+				    pr.pirq + 16);
+		intsrc_entries++;
+		cell += sizeof(struct pirq_routing) / sizeof(u32);
+	}
+
+	return 0;
+}
+
+static void mptable_add_lintsrc(struct mp_config_table *mc, int bus_isa)
+{
+	mp_write_lintsrc(mc, MP_EXTINT,
+			 MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+			 bus_isa, 0, MP_APIC_ALL, 0);
+	mp_write_lintsrc(mc, MP_NMI,
+			 MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
+			 bus_isa, 0, MP_APIC_ALL, 1);
+}
+
+u32 write_mp_table(u32 addr)
+{
+	struct mp_config_table *mc;
+	int ioapic_id, ioapic_ver;
+	int bus_isa = 0xff;
+	int ret;
+	u32 end;
+
+	/* 16 byte align the table address */
+	addr = ALIGN(addr, 16);
+
+	/* Write floating table */
+	mc = mp_write_floating_table((struct mp_floating_table *)addr);
+
+	/* Write configuration table header */
+	mp_config_table_init(mc);
+
+	/* Write processor entry */
+	mp_write_processor(mc);
+
+	/* Write bus entry */
+	mp_write_bus(mc, bus_isa, BUSTYPE_ISA);
+
+	/* Write I/O APIC entry */
+	ioapic_id = io_apic_read(IO_APIC_ID) >> 24;
+	ioapic_ver = io_apic_read(IO_APIC_VER) & 0xff;
+	mp_write_ioapic(mc, ioapic_id, ioapic_ver, IO_APIC_ADDR);
+
+	/* Write I/O interrupt assignment entry */
+	ret = mptable_add_intsrc(mc, bus_isa, ioapic_id);
+	if (ret)
+		debug("Failed to write I/O interrupt assignment table\n");
+
+	/* Write local interrupt assignment entry */
+	mptable_add_lintsrc(mc, bus_isa);
+
+	/* Finalize the MP table */
+	end = mptable_finalize(mc);
+
+	return end;
+}
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c
index 8031201..75ffbc1 100644
--- a/arch/x86/lib/tables.c
+++ b/arch/x86/lib/tables.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <asm/sfi.h>
+#include <asm/mpspec.h>
 #include <asm/tables.h>
 
 u8 table_compute_checksum(void *v, int len)
@@ -20,6 +21,20 @@
 	return checksum;
 }
 
+void table_fill_string(char *dest, const char *src, size_t n, char pad)
+{
+	int start, len;
+	int i;
+
+	strncpy(dest, src, n);
+
+	/* Fill the remaining bytes with pad */
+	len = strlen(src);
+	start = len < n ? len : n;
+	for (i = start; i < n; i++)
+		dest[i] = pad;
+}
+
 void write_tables(void)
 {
 	u32 __maybe_unused rom_table_end = ROM_TABLE_ADDR;
@@ -32,4 +47,8 @@
 	rom_table_end = write_sfi_table(rom_table_end);
 	rom_table_end = ALIGN(rom_table_end, 1024);
 #endif
+#ifdef CONFIG_GENERATE_MP_TABLE
+	rom_table_end = write_mp_table(rom_table_end);
+	rom_table_end = ALIGN(rom_table_end, 1024);
+#endif
 }
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index c3f8a73..144471c 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -273,6 +273,8 @@
 		build_command_line(cmd_line, auto_boot);
 	}
 
+	setup_video(&setup_base->screen_info);
+
 	return 0;
 }
 
diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig
index 9c8d020..d3644a9 100644
--- a/board/google/chromebook_link/Kconfig
+++ b/board/google/chromebook_link/Kconfig
@@ -22,7 +22,6 @@
 	select NORTHBRIDGE_INTEL_IVYBRIDGE
 	select SOUTHBRIDGE_INTEL_C216
 	select HAVE_ACPI_RESUME
-	select MARK_GRAPHICS_MEM_WRCOMB
 	select BOARD_ROMSIZE_KB_8192
 
 config PCIE_ECAM_BASE
diff --git a/board/google/chromebox_panther/Kconfig b/board/google/chromebox_panther/Kconfig
index e3604eb..d56d903 100644
--- a/board/google/chromebox_panther/Kconfig
+++ b/board/google/chromebox_panther/Kconfig
@@ -23,7 +23,6 @@
 	select NORTHBRIDGE_INTEL_IVYBRIDGE
 	select SOUTHBRIDGE_INTEL_C216
 	select HAVE_ACPI_RESUME
-	select MARK_GRAPHICS_MEM_WRCOMB
 	select BOARD_ROMSIZE_KB_8192
 
 config SYS_CAR_ADDR
diff --git a/common/board_f.c b/common/board_f.c
index fbbad1b..21be26f 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -753,6 +753,9 @@
 #ifdef CONFIG_OF_CONTROL
 	fdtdec_setup,
 #endif
+#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
+	x86_fsp_init,
+#endif
 #ifdef CONFIG_TRACE
 	trace_early_init,
 #endif
diff --git a/common/cmd_cpu.c b/common/cmd_cpu.c
index c3e229f..b4af64f5 100644
--- a/common/cmd_cpu.c
+++ b/common/cmd_cpu.c
@@ -9,6 +9,7 @@
 #include <command.h>
 #include <cpu.h>
 #include <dm.h>
+#include <errno.h>
 
 static const char *cpu_feature_name[CPU_FEAT_COUNT] = {
 	"L1 cache",
diff --git a/common/cmd_date.c b/common/cmd_date.c
index 61727e3..8714699 100644
--- a/common/cmd_date.c
+++ b/common/cmd_date.c
@@ -37,7 +37,7 @@
 	int old_bus __maybe_unused;
 
 	/* switch to correct I2C bus */
-#ifdef CONFIG_DM_I2C
+#ifdef CONFIG_DM_RTC
 	struct udevice *dev;
 
 	rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
@@ -57,7 +57,7 @@
 	case 2:			/* set date & time */
 		if (strcmp(argv[1],"reset") == 0) {
 			puts ("Reset RTC...\n");
-#ifdef CONFIG_DM_I2C
+#ifdef CONFIG_DM_RTC
 			rcode = dm_rtc_reset(dev);
 			if (!rcode)
 				rcode = dm_rtc_set(dev, &default_tm);
@@ -69,7 +69,7 @@
 				puts("## Failed to set date after RTC reset\n");
 		} else {
 			/* initialize tm with current time */
-#ifdef CONFIG_DM_I2C
+#ifdef CONFIG_DM_RTC
 			rcode = dm_rtc_get(dev, &tm);
 #else
 			rcode = rtc_get(&tm);
@@ -81,7 +81,7 @@
 					break;
 				}
 				/* and write to RTC */
-#ifdef CONFIG_DM_I2C
+#ifdef CONFIG_DM_RTC
 				rcode = dm_rtc_set(dev, &tm);
 #else
 				rcode = rtc_set(&tm);
@@ -96,7 +96,7 @@
 		}
 		/* FALL TROUGH */
 	case 1:			/* get date & time */
-#ifdef CONFIG_DM_I2C
+#ifdef CONFIG_DM_RTC
 		rcode = dm_rtc_get(dev, &tm);
 #else
 		rcode = rtc_get(&tm);
@@ -120,7 +120,7 @@
 	/* switch back to original I2C bus */
 #ifdef CONFIG_SYS_I2C
 	i2c_set_bus_num(old_bus);
-#elif !defined(CONFIG_DM_I2C)
+#elif !defined(CONFIG_DM_RTC)
 	I2C_SET_BUS(old_bus);
 #endif
 
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index aef8c2a..3746e0d 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -303,8 +303,12 @@
 		else
 			ret = spi_flash_write(flash, offset, len, buf);
 
-		printf("SF: %zu bytes @ %#x %s: %s\n", (size_t)len, (u32)offset,
-		       read ? "Read" : "Written", ret ? "ERROR" : "OK");
+		printf("SF: %zu bytes @ %#x %s: ", (size_t)len, (u32)offset,
+		       read ? "Read" : "Written");
+		if (ret)
+			printf("ERROR %d\n", ret);
+		else
+			printf("OK\n");
 	}
 
 	unmap_physmem(buf, len);
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig
index 018fe91..9931d65 100644
--- a/configs/chromebook_link_defconfig
+++ b/configs/chromebook_link_defconfig
@@ -3,6 +3,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
 CONFIG_TARGET_CHROMEBOOK_LINK=y
 CONFIG_HAVE_MRC=y
+CONFIG_HAVE_VGA_BIOS=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig
index 2ac23ed..b3a5f28 100644
--- a/configs/chromebox_panther_defconfig
+++ b/configs/chromebox_panther_defconfig
@@ -3,6 +3,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="chromebox_panther"
 CONFIG_TARGET_CHROMEBOX_PANTHER=y
 CONFIG_HAVE_MRC=y
+CONFIG_HAVE_VGA_BIOS=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig
index f3fb206..17e6a72 100644
--- a/configs/crownbay_defconfig
+++ b/configs/crownbay_defconfig
@@ -2,7 +2,12 @@
 CONFIG_VENDOR_INTEL=y
 CONFIG_DEFAULT_DEVICE_TREE="crownbay"
 CONFIG_TARGET_CROWNBAY=y
+CONFIG_SMP=y
+CONFIG_MAX_CPUS=2
+CONFIG_HAVE_VGA_BIOS=y
 CONFIG_GENERATE_PIRQ_TABLE=y
+CONFIG_GENERATE_MP_TABLE=y
+CONFIG_CMD_CPU=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
@@ -11,6 +16,10 @@
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_CMD_BOOTSTAGE=y
 CONFIG_OF_CONTROL=y
+CONFIG_CPU=y
 CONFIG_SPI_FLASH=y
+CONFIG_VIDEO_VESA=y
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_DM_RTC=y
 CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_SYS_VSNPRINTF=y
diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig
index e0a9216..29dd44b 100644
--- a/configs/minnowmax_defconfig
+++ b/configs/minnowmax_defconfig
@@ -4,6 +4,7 @@
 CONFIG_TARGET_MINNOWMAX=y
 CONFIG_HAVE_INTEL_ME=y
 CONFIG_SMP=y
+CONFIG_HAVE_VGA_BIOS=y
 CONFIG_GENERATE_SFI_TABLE=y
 CONFIG_CMD_CPU=y
 # CONFIG_CMD_IMLS is not set
@@ -15,6 +16,7 @@
 CONFIG_CMD_BOOTSTAGE=y
 CONFIG_OF_CONTROL=y
 CONFIG_CPU=y
+CONFIG_DM_PCI=y
 CONFIG_SPI_FLASH=y
 CONFIG_VIDEO_VESA=y
 CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
diff --git a/doc/README.x86 b/doc/README.x86
index c19f4a0..5d71244 100644
--- a/doc/README.x86
+++ b/doc/README.x86
@@ -79,7 +79,7 @@
 * ./northbridge/intel/sandybridge/systemagent-r6.bin
 
 The 3rd one should be renamed to mrc.bin.
-As for the video ROM, you can get it here [3].
+As for the video ROM, you can get it here [3] and rename it to vga.bin.
 Make sure all these binary blobs are put in the board directory.
 
 Now you can build U-Boot and obtain u-boot.rom:
@@ -113,6 +113,10 @@
 binary, change the following five bytes values from orginally E8 42 FF FF FF
 to B8 00 80 0B 00.
 
+As for the video ROM, you need manually extract it from the Intel provided
+BIOS for Crown Bay here [6], using the AMI MMTool [7]. Check PCI option ROM
+ID 8086:4108, extract and save it as vga.bin in the board directory.
+
 Now you can build U-Boot and obtain u-boot.rom
 
 $ make crownbay_defconfig
@@ -160,6 +164,31 @@
 $ make minnowmax_defconfig
 $ make all
 
+Checksums are as follows (but note that newer versions will invalidate this):
+
+$ md5sum -b board/intel/minnowmax/*.bin
+ffda9a3b94df5b74323afb328d51e6b4  board/intel/minnowmax/descriptor.bin
+69f65b9a580246291d20d08cbef9d7c5  board/intel/minnowmax/fsp.bin
+894a97d371544ec21de9c3e8e1716c4b  board/intel/minnowmax/me.bin
+a2588537da387da592a27219d56e9962  board/intel/minnowmax/vga.bin
+
+The ROM image is broken up into these parts:
+
+Offset   Description         Controlling config
+------------------------------------------------------------
+000000   descriptor.bin      Hard-coded to 0 in ifdtool
+001000   me.bin              Set by the descriptor
+500000   <spare>
+700000   u-boot-dtb.bin      CONFIG_SYS_TEXT_BASE
+790000   vga.bin             CONFIG_X86_OPTION_ROM_ADDR
+7c0000   fsp.bin             CONFIG_FSP_ADDR
+7f8000   <spare>             (depends on size of fsp.bin)
+7fe000   Environment         CONFIG_ENV_OFFSET
+7ff800   U-Boot 16-bit boot  CONFIG_SYS_X86_START16
+
+Overall ROM image size is controlled by CONFIG_ROM_SIZE.
+
+
 Intel Galileo instructions:
 
 Only one binary blob is needed for Remote Management Unit (RMU) within Intel
@@ -254,10 +283,21 @@
 
 CPU Microcode
 -------------
-Modern CPUs usually require a special bit stream called microcode [6] to be
+Modern CPUs usually require a special bit stream called microcode [8] to be
 loaded on the processor after power up in order to function properly. U-Boot
 has already integrated these as hex dumps in the source tree.
 
+SMP Support
+-----------
+On a multicore system, U-Boot is executed on the bootstrap processor (BSP).
+Additional application processors (AP) can be brought up by U-Boot. In order to
+have an SMP kernel to discover all of the available processors, U-Boot needs to
+prepare configuration tables which contain the multi-CPUs information before
+loading the OS kernel. Currently U-Boot supports generating two types of tables
+for SMP, called Simple Firmware Interface (SFI) [9] and Multi-Processor (MP)
+[10] tables. The writing of these two tables are controlled by two Kconfig
+options GENERATE_SFI_TABLE and GENERATE_MP_TABLE.
+
 Driver Model
 ------------
 x86 has been converted to use driver model for serial and GPIO.
@@ -361,4 +401,8 @@
 [3] http://www.coreboot.org/~stepan/pci8086,0166.rom
 [4] http://www.intel.com/content/www/us/en/embedded/design-tools/evaluation-platforms/atom-e660-eg20t-development-kit.html
 [5] http://www.intel.com/fsp
-[6] http://en.wikipedia.org/wiki/Microcode
+[6] http://www.intel.com/content/www/us/en/secure/intelligent-systems/privileged/e6xx-35-b1-cmc22211.html
+[7] http://www.ami.com/products/bios-uefi-tools-and-utilities/bios-uefi-utilities/
+[8] http://en.wikipedia.org/wiki/Microcode
+[9] http://simplefirmware.org
+[10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 8697da4..f161c01 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -6,7 +6,6 @@
 #
 
 obj-$(CONFIG_SCSI_AHCI) += ahci.o
-obj-$(CONFIG_ATA_PIIX) += ata_piix.o
 obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
 obj-$(CONFIG_FSL_SATA) += fsl_sata.o
 obj-$(CONFIG_IDE_FTIDE020) += ftide020.o
diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c
deleted file mode 100644
index 3042684..0000000
--- a/drivers/block/ata_piix.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) Procsys. All rights reserved.
- * Author: Mushtaq Khan <mushtaq_k@procsys.com>
- *			<mushtaqk_921@yahoo.co.in>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- *
- * with the reference to ata_piix driver in kernel 2.4.32
- */
-
-/*
- * This file contains SATA controller and SATA drive initialization functions
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <pci.h>
-#include <command.h>
-#include <config.h>
-#include <asm/byteorder.h>
-#include <part.h>
-#include <ide.h>
-#include <ata.h>
-#include <sata.h>
-
-#define DEBUG_SATA 0		/* For debug prints set DEBUG_SATA to 1 */
-
-#define SATA_DECL
-#define DRV_DECL		/* For file specific declarations */
-#include "ata_piix.h"
-
-/* Macros realted to PCI */
-#define PCI_SATA_BUS	0x00
-#define PCI_SATA_DEV	0x1f
-#define PCI_SATA_FUNC	0x02
-
-#define PCI_SATA_BASE1 0x10
-#define PCI_SATA_BASE2 0x14
-#define PCI_SATA_BASE3 0x18
-#define PCI_SATA_BASE4 0x1c
-#define PCI_SATA_BASE5 0x20
-#define PCI_PMR         0x90
-#define PCI_PI          0x09
-#define PCI_PCS         0x92
-#define PCI_DMA_CTL     0x48
-
-#define PORT_PRESENT (1<<0)
-#define PORT_ENABLED (1<<4)
-
-u32 bdf;
-u32 iobase1;		/* Primary cmd block */
-u32 iobase2;		/* Primary ctl block */
-u32 iobase3;		/* Sec cmd block */
-u32 iobase4;		/* sec ctl block */
-u32 iobase5;		/* BMDMA*/
-
-int pci_sata_init(void)
-{
-	u32 bus = PCI_SATA_BUS;
-	u32 dev = PCI_SATA_DEV;
-	u32 fun = PCI_SATA_FUNC;
-	u16 cmd = 0;
-	u8 lat = 0, pcibios_max_latency = 0xff;
-	u8 pmr; /* Port mapping reg */
-	u8 pi; /* Prgming Interface reg */
-
-	bdf = PCI_BDF(bus, dev, fun);
-	pci_read_config_dword(bdf, PCI_SATA_BASE1, &iobase1);
-	pci_read_config_dword(bdf, PCI_SATA_BASE2, &iobase2);
-	pci_read_config_dword(bdf, PCI_SATA_BASE3, &iobase3);
-	pci_read_config_dword(bdf, PCI_SATA_BASE4, &iobase4);
-	pci_read_config_dword(bdf, PCI_SATA_BASE5, &iobase5);
-
-	if ((iobase1 == 0xFFFFFFFF) || (iobase2 == 0xFFFFFFFF) ||
-	    (iobase3 == 0xFFFFFFFF) || (iobase4 == 0xFFFFFFFF) ||
-	    (iobase5 == 0xFFFFFFFF)) {
-		/* ERROR */
-		printf("error no base addr for SATA controller\n");
-		return 1;
-	}
-
-	iobase1 &= 0xFFFFFFFE;
-	iobase2 &= 0xFFFFFFFE;
-	iobase3 &= 0xFFFFFFFE;
-	iobase4 &= 0xFFFFFFFE;
-	iobase5 &= 0xFFFFFFFE;
-
-	/* check for mode */
-	pci_read_config_byte(bdf, PCI_PMR, &pmr);
-	if (pmr > 1) {
-		puts("combined mode not supported\n");
-		return 1;
-	}
-
-	pci_read_config_byte(bdf, PCI_PI, &pi);
-	if ((pi & 0x05) != 0x05) {
-		puts("Sata is in Legacy mode\n");
-		return 1;
-	} else
-		puts("sata is in Native mode\n");
-
-	/* MASTER CFG AND IO CFG */
-	pci_read_config_word(bdf, PCI_COMMAND, &cmd);
-	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
-	pci_write_config_word(bdf, PCI_COMMAND, cmd);
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-
-	if (lat < 16)
-		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
-	else if (lat > pcibios_max_latency)
-		lat = pcibios_max_latency;
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-
-	return 0;
-}
-
-int sata_bus_probe(int port_no)
-{
-	int orig_mask, mask;
-	u16 pcs;
-
-	mask = (PORT_PRESENT << port_no);
-	pci_read_config_word(bdf, PCI_PCS, &pcs);
-	orig_mask = (int) pcs & 0xff;
-	if ((orig_mask & mask) != mask)
-		return 0;
-	else
-		return 1;
-}
-
-int init_sata(int dev)
-{
-	static int done;
-	u8 i, rv = 0;
-
-	if (!done)
-		done = 1;
-	else
-		return 0;
-
-	rv = pci_sata_init();
-	if (rv == 1) {
-		puts("pci initialization failed\n");
-		return 1;
-	}
-
-	port[0].port_no = 0;
-	port[0].ioaddr.cmd_addr = iobase1;
-	port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr =
-	    iobase2 | ATA_PCI_CTL_OFS;
-	port[0].ioaddr.bmdma_addr = iobase5;
-
-	port[1].port_no = 1;
-	port[1].ioaddr.cmd_addr = iobase3;
-	port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr =
-	    iobase4 | ATA_PCI_CTL_OFS;
-	port[1].ioaddr.bmdma_addr = iobase5 + 0x8;
-
-	for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++)
-		sata_port(&port[i].ioaddr);
-
-	for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
-		if (!(sata_bus_probe(i))) {
-			port[i].port_state = 0;
-			printf("SATA#%d port is not present\n", i);
-		} else {
-			printf("SATA#%d port is present\n", i);
-			if (sata_bus_softreset(i))
-				port[i].port_state = 0;
-			else
-				port[i].port_state = 1;
-		}
-	}
-
-	for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
-		u8 j, devno;
-
-		if (port[i].port_state == 0)
-			continue;
-		for (j = 0; j < CONFIG_SYS_SATA_DEVS_PER_BUS; j++) {
-			sata_identify(i, j);
-			set_Feature_cmd(i, j);
-			devno = i * CONFIG_SYS_SATA_DEVS_PER_BUS + j;
-			if ((sata_dev_desc[devno].lba > 0) &&
-			    (sata_dev_desc[devno].blksz > 0)) {
-				dev_print(&sata_dev_desc[devno]);
-				/* initialize partition type */
-				init_part(&sata_dev_desc[devno]);
-			}
-		}
-	}
-	return 0;
-}
-
-int reset_sata(int dev)
-{
-	return 0;
-}
-
-static inline u8 sata_inb(unsigned long ioaddr)
-{
-	return inb(ioaddr);
-}
-
-static inline void sata_outb(unsigned char val, unsigned long ioaddr)
-{
-	outb(val, ioaddr);
-}
-
-static void output_data(struct sata_ioports *ioaddr, ulong * sect_buf,
-		int words)
-{
-	outsw(ioaddr->data_addr, sect_buf, words << 1);
-}
-
-static int input_data(struct sata_ioports *ioaddr, ulong * sect_buf, int words)
-{
-	insw(ioaddr->data_addr, sect_buf, words << 1);
-	return 0;
-}
-
-static void sata_cpy(unsigned char *dst, unsigned char *src, unsigned int len)
-{
-	unsigned char *end, *last;
-
-	last = dst;
-	end = src + len - 1;
-
-	/* reserve space for '\0' */
-	if (len < 2)
-		goto OUT;
-
-	/* skip leading white space */
-	while ((*src) && (src < end) && (*src == ' '))
-		++src;
-
-	/* copy string, omitting trailing white space */
-	while ((*src) && (src < end)) {
-		*dst++ = *src;
-		if (*src++ != ' ')
-			last = dst;
-	}
-OUT:
-	*last = '\0';
-}
-
-int sata_bus_softreset(int num)
-{
-	u8 dev = 0, status = 0, i;
-
-	port[num].dev_mask = 0;
-
-	for (i = 0; i < CONFIG_SYS_SATA_DEVS_PER_BUS; i++) {
-		if (!(sata_devchk(&port[num].ioaddr, i))) {
-			debug("dev_chk failed for dev#%d\n", i);
-		} else {
-			port[num].dev_mask |= (1 << i);
-			debug("dev_chk passed for dev#%d\n", i);
-		}
-	}
-
-	if (!(port[num].dev_mask)) {
-		printf("no devices on port%d\n", num);
-		return 1;
-	}
-
-	dev_select(&port[num].ioaddr, dev);
-
-	port[num].ctl_reg = 0x08;	/* Default value of control reg */
-	sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
-	udelay(10);
-	sata_outb(port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr);
-	udelay(10);
-	sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
-
-	/*
-	 * spec mandates ">= 2ms" before checking status.
-	 * We wait 150ms, because that was the magic delay used for
-	 * ATAPI devices in Hale Landis's ATADRVR, for the period of time
-	 * between when the ATA command register is written, and then
-	 * status is checked.  Because waiting for "a while" before
-	 * checking status is fine, post SRST, we perform this magic
-	 * delay here as well.
-	 */
-	mdelay(150);
-	status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 300);
-	while ((status & ATA_BUSY)) {
-		mdelay(100);
-		status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 3);
-	}
-
-	if (status & ATA_BUSY)
-		printf("ata%u is slow to respond,plz be patient\n", num);
-
-	while ((status & ATA_BUSY)) {
-		mdelay(100);
-		status = sata_chk_status(&port[num].ioaddr);
-	}
-
-	if (status & ATA_BUSY) {
-		printf("ata%u failed to respond : bus reset failed\n", num);
-		return 1;
-	}
-	return 0;
-}
-
-void sata_identify(int num, int dev)
-{
-	u8 cmd = 0, status = 0;
-	u8 devno = num * CONFIG_SYS_SATA_DEVS_PER_BUS + dev;
-	u16 iobuf[ATA_SECT_SIZE];
-	u64 n_sectors = 0;
-	u8 mask = 0;
-
-	memset(iobuf, 0, sizeof(iobuf));
-	hd_driveid_t *iop = (hd_driveid_t *) iobuf;
-
-	if (dev == 0)
-		mask = 0x01;
-	else
-		mask = 0x02;
-
-	if (!(port[num].dev_mask & mask)) {
-		printf("dev%d is not present on port#%d\n", dev, num);
-		return;
-	}
-
-	printf("port=%d dev=%d\n", num, dev);
-
-	dev_select(&port[num].ioaddr, dev);
-
-	status = 0;
-	cmd = ATA_CMD_IDENT;	/* Device Identify Command */
-	sata_outb(cmd, port[num].ioaddr.command_addr);
-	sata_inb(port[num].ioaddr.altstatus_addr);
-	udelay(10);
-
-	status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 1000);
-	if (status & ATA_ERR) {
-		puts("\ndevice not responding\n");
-		port[num].dev_mask &= ~mask;
-		return;
-	}
-
-	input_data(&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS);
-
-	debug("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x"
-		"86:%04x" "87:%04x 88:%04x\n", num, dev, iobuf[49],
-		iobuf[82], iobuf[83], iobuf[84], iobuf[85], iobuf[86],
-		iobuf[87], iobuf[88]);
-
-	/* we require LBA and DMA support (bits 8 & 9 of word 49) */
-	if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf))
-		debug("ata%u: no dma/lba\n", num);
-	ata_dump_id(iobuf);
-
-	if (ata_id_has_lba48(iobuf))
-		n_sectors = ata_id_u64(iobuf, 100);
-	else
-		n_sectors = ata_id_u32(iobuf, 60);
-	debug("no. of sectors %u\n", ata_id_u64(iobuf, 100));
-	debug("no. of sectors %u\n", ata_id_u32(iobuf, 60));
-
-	if (n_sectors == 0) {
-		port[num].dev_mask &= ~mask;
-		return;
-	}
-
-	sata_cpy((unsigned char *)sata_dev_desc[devno].revision, iop->fw_rev,
-		  sizeof(sata_dev_desc[devno].revision));
-	sata_cpy((unsigned char *)sata_dev_desc[devno].vendor, iop->model,
-		  sizeof(sata_dev_desc[devno].vendor));
-	sata_cpy((unsigned char *)sata_dev_desc[devno].product, iop->serial_no,
-		  sizeof(sata_dev_desc[devno].product));
-	strswab(sata_dev_desc[devno].revision);
-	strswab(sata_dev_desc[devno].vendor);
-
-	if ((iop->config & 0x0080) == 0x0080)
-		sata_dev_desc[devno].removable = 1;
-	else
-		sata_dev_desc[devno].removable = 0;
-
-	sata_dev_desc[devno].lba = iop->lba_capacity;
-	debug("lba=0x%x", sata_dev_desc[devno].lba);
-
-#ifdef CONFIG_LBA48
-	if (iop->command_set_2 & 0x0400) {
-		sata_dev_desc[devno].lba48 = 1;
-		lba = (unsigned long long) iop->lba48_capacity[0] |
-		    ((unsigned long long) iop->lba48_capacity[1] << 16) |
-		    ((unsigned long long) iop->lba48_capacity[2] << 32) |
-		    ((unsigned long long) iop->lba48_capacity[3] << 48);
-	} else {
-		sata_dev_desc[devno].lba48 = 0;
-	}
-#endif
-
-	/* assuming HD */
-	sata_dev_desc[devno].type = DEV_TYPE_HARDDISK;
-	sata_dev_desc[devno].blksz = ATA_BLOCKSIZE;
-	sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz);
-	sata_dev_desc[devno].lun = 0;	/* just to fill something in... */
-}
-
-void set_Feature_cmd(int num, int dev)
-{
-	u8 mask = 0x00, status = 0;
-
-	if (dev == 0)
-		mask = 0x01;
-	else
-		mask = 0x02;
-
-	if (!(port[num].dev_mask & mask)) {
-		debug("dev%d is not present on port#%d\n", dev, num);
-		return;
-	}
-
-	dev_select(&port[num].ioaddr, dev);
-
-	sata_outb(SETFEATURES_XFER, port[num].ioaddr.feature_addr);
-	sata_outb(XFER_PIO_4, port[num].ioaddr.nsect_addr);
-	sata_outb(0, port[num].ioaddr.lbal_addr);
-	sata_outb(0, port[num].ioaddr.lbam_addr);
-	sata_outb(0, port[num].ioaddr.lbah_addr);
-
-	sata_outb(ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
-	sata_outb(ATA_CMD_SETF, port[num].ioaddr.command_addr);
-
-	udelay(50);
-	mdelay(150);
-
-	status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 5000);
-	if ((status & (ATA_STAT_BUSY | ATA_STAT_ERR))) {
-		printf("Error  : status 0x%02x\n", status);
-		port[num].dev_mask &= ~mask;
-	}
-}
-
-void sata_port(struct sata_ioports *ioport)
-{
-	ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA;
-	ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR;
-	ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE;
-	ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT;
-	ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL;
-	ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM;
-	ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH;
-	ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE;
-	ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS;
-	ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD;
-}
-
-int sata_devchk(struct sata_ioports *ioaddr, int dev)
-{
-	u8 nsect, lbal;
-
-	dev_select(ioaddr, dev);
-
-	sata_outb(0x55, ioaddr->nsect_addr);
-	sata_outb(0xaa, ioaddr->lbal_addr);
-
-	sata_outb(0xaa, ioaddr->nsect_addr);
-	sata_outb(0x55, ioaddr->lbal_addr);
-
-	sata_outb(0x55, ioaddr->nsect_addr);
-	sata_outb(0xaa, ioaddr->lbal_addr);
-
-	nsect = sata_inb(ioaddr->nsect_addr);
-	lbal = sata_inb(ioaddr->lbal_addr);
-
-	if ((nsect == 0x55) && (lbal == 0xaa))
-		return 1;	/* we found a device */
-	else
-		return 0;	/* nothing found */
-}
-
-void dev_select(struct sata_ioports *ioaddr, int dev)
-{
-	u8 tmp = 0;
-
-	if (dev == 0)
-		tmp = ATA_DEVICE_OBS;
-	else
-		tmp = ATA_DEVICE_OBS | ATA_DEV1;
-
-	sata_outb(tmp, ioaddr->device_addr);
-	sata_inb(ioaddr->altstatus_addr);
-	udelay(5);
-}
-
-u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max)
-{
-	u8 status;
-
-	do {
-		udelay(1000);
-		status = sata_chk_status(ioaddr);
-		max--;
-	} while ((status & bits) && (max > 0));
-
-	return status;
-}
-
-u8 sata_chk_status(struct sata_ioports *ioaddr)
-{
-	return sata_inb(ioaddr->status_addr);
-}
-
-
-ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buff)
-{
-	ulong n = 0, *buffer = (ulong *)buff;
-	u8 dev = 0, num = 0, mask = 0, status = 0;
-
-#ifdef CONFIG_LBA48
-	unsigned char lba48 = 0;
-
-	if (blknr & 0x0000fffff0000000) {
-		if (!sata_dev_desc[devno].lba48) {
-			printf("Drive doesn't support 48-bit addressing\n");
-			return 0;
-		}
-		/* more than 28 bits used, use 48bit mode */
-		lba48 = 1;
-	}
-#endif
-	/* Port Number */
-	num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
-	/* dev on the port */
-	if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
-		dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
-	else
-		dev = device;
-
-	if (dev == 0)
-		mask = 0x01;
-	else
-		mask = 0x02;
-
-	if (!(port[num].dev_mask & mask)) {
-		printf("dev%d is not present on port#%d\n", dev, num);
-		return 0;
-	}
-
-	/* Select device */
-	dev_select(&port[num].ioaddr, dev);
-
-	status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
-	if (status & ATA_BUSY) {
-		printf("ata%u failed to respond\n", port[num].port_no);
-		return n;
-	}
-	while (blkcnt-- > 0) {
-		status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
-		if (status & ATA_BUSY) {
-			printf("ata%u failed to respond\n", 0);
-			return n;
-		}
-#ifdef CONFIG_LBA48
-		if (lba48) {
-			/* write high bits */
-			sata_outb(0, port[num].ioaddr.nsect_addr);
-			sata_outb((blknr >> 24) & 0xFF,
-				   port[num].ioaddr.lbal_addr);
-			sata_outb((blknr >> 32) & 0xFF,
-				   port[num].ioaddr.lbam_addr);
-			sata_outb((blknr >> 40) & 0xFF,
-				   port[num].ioaddr.lbah_addr);
-		}
-#endif
-		sata_outb(1, port[num].ioaddr.nsect_addr);
-		sata_outb(((blknr) >> 0) & 0xFF,
-			   port[num].ioaddr.lbal_addr);
-		sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
-		sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
-
-#ifdef CONFIG_LBA48
-		if (lba48) {
-			sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
-			sata_outb(ATA_CMD_READ_EXT,
-				   port[num].ioaddr.command_addr);
-		} else
-#endif
-		{
-			sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
-				   port[num].ioaddr.device_addr);
-			sata_outb(ATA_CMD_READ,
-				   port[num].ioaddr.command_addr);
-		}
-
-		mdelay(50);
-		/* may take up to 4 sec */
-		status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
-
-		if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
-		    != ATA_STAT_DRQ) {
-			u8 err = 0;
-
-			printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
-				device, (ulong) blknr, status);
-			err = sata_inb(port[num].ioaddr.error_addr);
-			printf("Error reg = 0x%x\n", err);
-			return n;
-		}
-		input_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
-		sata_inb(port[num].ioaddr.altstatus_addr);
-		udelay(50);
-
-		++n;
-		++blknr;
-		buffer += ATA_SECTORWORDS;
-	}
-	return n;
-}
-
-ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buff)
-{
-	ulong n = 0, *buffer = (ulong *)buff;
-	unsigned char status = 0, num = 0, dev = 0, mask = 0;
-
-#ifdef CONFIG_LBA48
-	unsigned char lba48 = 0;
-
-	if (blknr & 0x0000fffff0000000) {
-		if (!sata_dev_desc[devno].lba48) {
-			printf("Drive doesn't support 48-bit addressing\n");
-			return 0;
-		}
-		/* more than 28 bits used, use 48bit mode */
-		lba48 = 1;
-	}
-#endif
-	/* Port Number */
-	num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
-	/* dev on the Port */
-	if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
-		dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
-	else
-		dev = device;
-
-	if (dev == 0)
-		mask = 0x01;
-	else
-		mask = 0x02;
-
-	/* Select device */
-	dev_select(&port[num].ioaddr, dev);
-
-	status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
-	if (status & ATA_BUSY) {
-		printf("ata%u failed to respond\n", port[num].port_no);
-		return n;
-	}
-
-	while (blkcnt-- > 0) {
-		status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
-		if (status & ATA_BUSY) {
-			printf("ata%u failed to respond\n",
-				port[num].port_no);
-			return n;
-		}
-#ifdef CONFIG_LBA48
-		if (lba48) {
-			/* write high bits */
-			sata_outb(0, port[num].ioaddr.nsect_addr);
-			sata_outb((blknr >> 24) & 0xFF,
-				   port[num].ioaddr.lbal_addr);
-			sata_outb((blknr >> 32) & 0xFF,
-				   port[num].ioaddr.lbam_addr);
-			sata_outb((blknr >> 40) & 0xFF,
-				   port[num].ioaddr.lbah_addr);
-		}
-#endif
-		sata_outb(1, port[num].ioaddr.nsect_addr);
-		sata_outb((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr);
-		sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
-		sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
-#ifdef CONFIG_LBA48
-		if (lba48) {
-			sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
-			sata_outb(ATA_CMD_WRITE_EXT,
-				   port[num].ioaddr.command_addr);
-		} else
-#endif
-		{
-			sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
-				   port[num].ioaddr.device_addr);
-			sata_outb(ATA_CMD_WRITE,
-				   port[num].ioaddr.command_addr);
-		}
-
-		mdelay(50);
-		/* may take up to 4 sec */
-		status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
-		if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
-		    != ATA_STAT_DRQ) {
-			printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
-				device, (ulong) blknr, status);
-			return n;
-		}
-
-		output_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
-		sata_inb(port[num].ioaddr.altstatus_addr);
-		udelay(50);
-
-		++n;
-		++blknr;
-		buffer += ATA_SECTORWORDS;
-	}
-	return n;
-}
-
-int scan_sata(int dev)
-{
-	return 0;
-}
diff --git a/drivers/block/ata_piix.h b/drivers/block/ata_piix.h
deleted file mode 100644
index 6c68ea2..0000000
--- a/drivers/block/ata_piix.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef __ATA_PIIX_H__
-#define __ATA_PIIX_H__
-
-struct sata_ioports {
-	unsigned long cmd_addr;
-	unsigned long data_addr;
-	unsigned long error_addr;
-	unsigned long feature_addr;
-	unsigned long nsect_addr;
-	unsigned long lbal_addr;
-	unsigned long lbam_addr;
-	unsigned long lbah_addr;
-	unsigned long device_addr;
-	unsigned long status_addr;
-	unsigned long command_addr;
-	unsigned long altstatus_addr;
-	unsigned long ctl_addr;
-	unsigned long bmdma_addr;
-	unsigned long scr_addr;
-};
-
-struct sata_port {
-	unsigned char port_no;		/* primary=0, secondary=1	*/
-	struct sata_ioports ioaddr;	/* ATA cmd/ctl/dma reg blks	*/
-	unsigned char ctl_reg;
-	unsigned char last_ctl;
-	unsigned char port_state;	/* 1-port is available and	*/
-					/* 0-port is not available	*/
-	unsigned char dev_mask;
-};
-
-/***********SATA LIBRARY SPECIFIC DEFINITIONS AND DECLARATIONS**************/
-#ifdef SATA_DECL		/* SATA library specific declarations */
-inline void ata_dump_id(u16 *id)
-{
-	debug("49 = 0x%04x  "
-		"53 = 0x%04x  "
-		"63 = 0x%04x  "
-		"64 = 0x%04x  "
-		"75 = 0x%04x\n", id[49], id[53], id[63], id[64], id[75]);
-	debug("80 = 0x%04x  "
-		"81 = 0x%04x  "
-		"82 = 0x%04x  "
-		"83 = 0x%04x  "
-		"84 = 0x%04x\n", id[80], id[81], id[82], id[83], id[84]);
-	debug("88 = 0x%04x  " "93 = 0x%04x\n", id[88], id[93]);
-}
-#endif
-
-#ifdef SATA_DECL		/*SATA library specific declarations */
-int sata_bus_softreset(int num);
-void sata_identify(int num, int dev);
-void sata_port(struct sata_ioports *ioport);
-void set_Feature_cmd(int num, int dev);
-int sata_devchk(struct sata_ioports *ioaddr, int dev);
-void dev_select(struct sata_ioports *ioaddr, int dev);
-u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max);
-u8 sata_chk_status(struct sata_ioports *ioaddr);
-#endif
-
-/************DRIVER SPECIFIC DEFINITIONS AND DECLARATIONS**************/
-
-#ifdef DRV_DECL			/* Driver specific declaration */
-int init_sata(int dev);
-#endif
-
-#ifdef DRV_DECL			/* Defines Driver Specific variables */
-struct sata_port port[CONFIG_SYS_SATA_MAXBUS];
-#endif
-
-#endif /* __ATA_PIIX_H__ */
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index ab18ee2..7660f99 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -8,9 +8,12 @@
 #include <common.h>
 #include <cpu.h>
 #include <dm.h>
+#include <errno.h>
 #include <dm/lists.h>
 #include <dm/root.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 int cpu_get_desc(struct udevice *dev, char *buf, int size)
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
@@ -25,12 +28,22 @@
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
 
-	if (!ops->get_desc)
+	if (!ops->get_info)
 		return -ENOSYS;
 
 	return ops->get_info(dev, info);
 }
 
+int cpu_get_count(struct udevice *dev)
+{
+	struct cpu_ops *ops = cpu_get_ops(dev);
+
+	if (!ops->get_count)
+		return -ENOSYS;
+
+	return ops->get_count(dev);
+}
+
 U_BOOT_DRIVER(cpu_bus) = {
 	.name	= "cpu_bus",
 	.id	= UCLASS_SIMPLE_BUS,
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index de87505..5b91fe3 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -296,6 +296,7 @@
 	     !ret && dev;
 	     ret = device_find_next_child(&dev)) {
 		struct pci_child_platdata *pplat;
+		struct pci_controller *ctlr_hose;
 
 		pplat = dev_get_parent_platdata(dev);
 		unsigned int max_bus;
@@ -303,7 +304,10 @@
 
 		bdf = PCI_ADD_BUS(bus->seq, pplat->devfn);
 		debug("%s: device %s\n", __func__, dev->name);
-		max_bus = pciauto_config_device(hose, bdf);
+
+		/* The root controller has the region information */
+		ctlr_hose = hose->ctlr->uclass_priv;
+		max_bus = pciauto_config_device(ctlr_hose, bdf);
 		sub_bus = max(sub_bus, max_bus);
 	}
 	debug("%s: done\n", __func__);
@@ -330,7 +334,7 @@
 
 	sub_bus = pci_get_bus_max() + 1;
 	debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
-	pciauto_prescan_setup_bridge(hose, bdf, bus->seq);
+	pciauto_prescan_setup_bridge(hose, bdf, sub_bus);
 
 	ret = device_probe(bus);
 	if (ret) {
@@ -440,6 +444,7 @@
 {
 	int pci_addr_cells, addr_cells, size_cells;
 	int cells_per_record;
+	phys_addr_t addr;
 	const u32 *prop;
 	int len;
 	int i;
@@ -490,8 +495,11 @@
 	}
 
 	/* Add a region for our local memory */
-	pci_set_region(hose->regions + hose->region_count++, 0, 0,
-		       gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+	addr = gd->ram_size;
+	if (gd->pci_ram_top && gd->pci_ram_top < addr)
+		addr = gd->pci_ram_top;
+	pci_set_region(hose->regions + hose->region_count++, 0, 0, addr,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
 
 	return 0;
 }
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 7c10983..e034ed1 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -87,6 +87,8 @@
 	pci_size_t bar_size;
 	u16 cmdstat = 0;
 	int bar, bar_nr = 0;
+	u8 header_type;
+	int rom_addr;
 #ifndef CONFIG_PCI_ENUM_ONLY
 	pci_addr_t bar_value;
 	struct pci_region *bar_res;
@@ -182,38 +184,32 @@
 		bar_nr++;
 	}
 
+	/* Configure the expansion ROM address */
+	pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
+	if (header_type != PCI_HEADER_TYPE_CARDBUS) {
+		rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
+			   PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
+		pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe);
+		pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
+		if (bar_response) {
+			bar_size = -(bar_response & ~1);
+			DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
+			if (pciauto_region_allocate(mem, bar_size,
+						    &bar_value) == 0) {
+				pci_hose_write_config_dword(hose, dev, rom_addr,
+							    bar_value);
+			}
+			cmdstat |= PCI_COMMAND_MEMORY;
+			DEBUGF("\n");
+		}
+	}
+
 	pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
 	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
 		CONFIG_SYS_PCI_CACHE_LINE_SIZE);
 	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
 }
 
-int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev)
-{
-	pci_addr_t bar_value;
-	pci_size_t bar_size;
-	u32 bar_response;
-	u16 cmdstat = 0;
-
-	pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe);
-	pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response);
-	if (!bar_response)
-		return -ENOENT;
-
-	bar_size = -(bar_response & ~1);
-	DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
-	if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) {
-		pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS,
-					    bar_value);
-	}
-	DEBUGF("\n");
-	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
-	cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-	pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
-
-	return 0;
-}
-
 void pciauto_prescan_setup_bridge(struct pci_controller *hose,
 					 pci_dev_t dev, int sub_bus)
 {
diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c
index b9ff23f..f67c9c7 100644
--- a/drivers/pci/pci_common.c
+++ b/drivers/pci/pci_common.c
@@ -11,6 +11,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <pci.h>
 #include <asm/io.h>
@@ -221,6 +222,11 @@
 		return phys_addr;
 	}
 
+#ifdef CONFIG_DM_PCI
+	/* The root controller has the region information */
+	hose = hose->ctlr->uclass_priv;
+#endif
+
 	/*
 	 * if PCI_REGION_MEM is set we do a two pass search with preference
 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 37450c8..a33efae 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -31,6 +31,7 @@
 #include <pci_rom.h>
 #include <vbe.h>
 #include <video_fb.h>
+#include <linux/screen_info.h>
 
 #ifdef CONFIG_HAVE_ACPI_RESUME
 #include <asm/acpi.h>
@@ -79,15 +80,10 @@
 	if (vendev != mapped_vendev)
 		debug("Device ID mapped to %#08x\n", mapped_vendev);
 
-#ifdef CONFIG_X86_OPTION_ROM_ADDR
-	rom_address = CONFIG_X86_OPTION_ROM_ADDR;
+#ifdef CONFIG_VGA_BIOS_ADDR
+	rom_address = CONFIG_VGA_BIOS_ADDR;
 #else
 
-	if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) {
-		debug("Cannot find option ROM\n");
-		return -ENOENT;
-	}
-
 	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address);
 	if (rom_address == 0x00000000 || rom_address == 0xffffffff) {
 		debug("%s: rom_address=%x\n", __func__, rom_address);
@@ -108,6 +104,10 @@
 	if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
 		printf("Incorrect expansion ROM header signature %04x\n",
 		       le16_to_cpu(rom_header->signature));
+#ifndef CONFIG_VGA_BIOS_ADDR
+		/* Disable expansion ROM address decoding */
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address);
+#endif
 		return -EINVAL;
 	}
 
@@ -203,6 +203,7 @@
 	gdev->gdfBytesPP = vesa->bits_per_pixel / 8;
 
 	switch (vesa->bits_per_pixel) {
+	case 32:
 	case 24:
 		gdev->gdfIndex = GDF_32BIT_X888RGB;
 		break;
@@ -229,6 +230,33 @@
 #endif
 }
 
+void setup_video(struct screen_info *screen_info)
+{
+#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE
+	struct vesa_mode_info *vesa = &mode_info.vesa;
+
+	screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
+
+	screen_info->lfb_width = vesa->x_resolution;
+	screen_info->lfb_height = vesa->y_resolution;
+	screen_info->lfb_depth = vesa->bits_per_pixel;
+	screen_info->lfb_linelength = vesa->bytes_per_scanline;
+	screen_info->lfb_base = vesa->phys_base_ptr;
+	screen_info->lfb_size =
+		ALIGN(screen_info->lfb_linelength * screen_info->lfb_height,
+		      65536);
+	screen_info->lfb_size >>= 16;
+	screen_info->red_size = vesa->red_mask_size;
+	screen_info->red_pos = vesa->red_mask_pos;
+	screen_info->green_size = vesa->green_mask_size;
+	screen_info->green_pos = vesa->green_mask_pos;
+	screen_info->blue_size = vesa->blue_mask_size;
+	screen_info->blue_pos = vesa->blue_mask_pos;
+	screen_info->rsvd_size = vesa->reserved_mask_size;
+	screen_info->rsvd_pos = vesa->reserved_mask_pos;
+#endif
+}
+
 int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method)
 {
 	struct pci_rom_header *rom, *ram;
diff --git a/drivers/pci/pci_x86.c b/drivers/pci/pci_x86.c
index 901bdca..89e8c11 100644
--- a/drivers/pci/pci_x86.c
+++ b/drivers/pci/pci_x86.c
@@ -7,18 +7,21 @@
 #include <common.h>
 #include <dm.h>
 #include <pci.h>
+#include <asm/pci.h>
 
-static const struct dm_pci_ops x86_pci_ops = {
+static const struct dm_pci_ops pci_x86_ops = {
+	.read_config	= pci_x86_read_config,
+	.write_config	= pci_x86_write_config,
 };
 
-static const struct udevice_id x86_pci_ids[] = {
-	{ .compatible = "x86,pci" },
+static const struct udevice_id pci_x86_ids[] = {
+	{ .compatible = "pci-x86" },
 	{ }
 };
 
 U_BOOT_DRIVER(pci_x86) = {
 	.name	= "pci_x86",
 	.id	= UCLASS_PCI,
-	.of_match = x86_pci_ids,
-	.ops	= &x86_pci_ops,
+	.of_match = pci_x86_ids,
+	.ops	= &pci_x86_ops,
 };
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
index 44857a6..363ade3 100644
--- a/drivers/rtc/mc146818.c
+++ b/drivers/rtc/mc146818.c
@@ -9,10 +9,9 @@
  * Date & Time support for the MC146818 (PIXX4) RTC
  */
 
-/*#define	DEBUG*/
-
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <rtc.h>
 
 #if defined(__I386__) || defined(CONFIG_MALTA)
@@ -24,9 +23,9 @@
 #if defined(CONFIG_CMD_DATE)
 
 /* Set this to 1 to clear the CMOS RAM */
-#define CLEAR_CMOS 0
+#define CLEAR_CMOS		0
 
-#define RTC_PORT_MC146818	CONFIG_SYS_ISA_IO_BASE_ADDRESS +  0x70
+#define RTC_PORT_MC146818	CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
 #define RTC_SECONDS		0x00
 #define RTC_SECONDS_ALARM	0x01
 #define RTC_MINUTES		0x02
@@ -37,10 +36,10 @@
 #define RTC_DATE_OF_MONTH	0x07
 #define RTC_MONTH		0x08
 #define RTC_YEAR		0x09
-#define RTC_CONFIG_A		0x0A
-#define RTC_CONFIG_B		0x0B
-#define RTC_CONFIG_C		0x0C
-#define RTC_CONFIG_D		0x0D
+#define RTC_CONFIG_A		0x0a
+#define RTC_CONFIG_B		0x0b
+#define RTC_CONFIG_C		0x0c
+#define RTC_CONFIG_D		0x0d
 #define RTC_REG_SIZE		0x80
 
 #define RTC_CONFIG_A_REF_CLCK_32KHZ	(1 << 5)
@@ -50,89 +49,7 @@
 
 #define RTC_CONFIG_D_VALID_RAM_AND_TIME	0x80
 
-/* ------------------------------------------------------------------------- */
-
-int rtc_get (struct rtc_time *tmp)
-{
-	uchar sec, min, hour, mday, wday, mon, year;
-  /* here check if rtc can be accessed */
-	while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80);
-	sec	= rtc_read8(RTC_SECONDS);
-	min	= rtc_read8(RTC_MINUTES);
-	hour	= rtc_read8(RTC_HOURS);
-	mday	= rtc_read8(RTC_DATE_OF_MONTH);
-	wday	= rtc_read8(RTC_DAY_OF_WEEK);
-	mon	= rtc_read8(RTC_MONTH);
-	year	= rtc_read8(RTC_YEAR);
-#ifdef RTC_DEBUG
-	printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
-		"hr: %02x min: %02x sec: %02x\n",
-		year, mon, mday, wday,
-		hour, min, sec );
-	printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
-		rtc_read8(RTC_CONFIG_D) & 0x3F,
-		rtc_read8(RTC_HOURS_ALARM),
-		rtc_read8(RTC_MINUTES_ALARM),
-		rtc_read8(RTC_SECONDS_ALARM));
-#endif
-	tmp->tm_sec  = bcd2bin (sec  & 0x7F);
-	tmp->tm_min  = bcd2bin (min  & 0x7F);
-	tmp->tm_hour = bcd2bin (hour & 0x3F);
-	tmp->tm_mday = bcd2bin (mday & 0x3F);
-	tmp->tm_mon  = bcd2bin (mon & 0x1F);
-	tmp->tm_year = bcd2bin (year);
-	tmp->tm_wday = bcd2bin (wday & 0x07);
-	if(tmp->tm_year<70)
-		tmp->tm_year+=2000;
-	else
-		tmp->tm_year+=1900;
-	tmp->tm_yday = 0;
-	tmp->tm_isdst= 0;
-#ifdef RTC_DEBUG
-	printf ( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
-		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
-		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
-#endif
-
-	return 0;
-}
-
-int rtc_set (struct rtc_time *tmp)
-{
-#ifdef RTC_DEBUG
-	printf ( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
-		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
-		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
-#endif
-	rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
-
-	rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
-	rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
-	rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
-	rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
-	rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
-	rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
-	rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
-	rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
-
-	return 0;
-}
-
-void rtc_reset (void)
-{
-	rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
-	rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */
-	rtc_write8(RTC_CONFIG_B, 0x00);
-	rtc_write8(RTC_CONFIG_B, 0x00);
-	rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
-}
-
-/* ------------------------------------------------------------------------- */
-
-/*
- * use direct memory access
- */
-int rtc_read8(int reg)
+static int mc146818_read8(int reg)
 {
 #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
 	return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
@@ -149,7 +66,7 @@
 #endif
 }
 
-void rtc_write8(int reg, uchar val)
+static void mc146818_write8(int reg, uchar val)
 {
 #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
 	out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
@@ -165,6 +82,204 @@
 #endif
 }
 
+static int mc146818_get(struct rtc_time *tmp)
+{
+	uchar sec, min, hour, mday, wday, mon, year;
+
+	/* here check if rtc can be accessed */
+	while ((mc146818_read8(RTC_CONFIG_A) & 0x80) == 0x80)
+		;
+
+	sec	= mc146818_read8(RTC_SECONDS);
+	min	= mc146818_read8(RTC_MINUTES);
+	hour	= mc146818_read8(RTC_HOURS);
+	mday	= mc146818_read8(RTC_DATE_OF_MONTH);
+	wday	= mc146818_read8(RTC_DAY_OF_WEEK);
+	mon	= mc146818_read8(RTC_MONTH);
+	year	= mc146818_read8(RTC_YEAR);
+#ifdef RTC_DEBUG
+	printf("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x hr: %02x min: %02x sec: %02x\n",
+	       year, mon, mday, wday, hour, min, sec);
+	printf("Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
+	       mc146818_read8(RTC_CONFIG_D) & 0x3f,
+	       mc146818_read8(RTC_HOURS_ALARM),
+	       mc146818_read8(RTC_MINUTES_ALARM),
+	       mc146818_read8(RTC_SECONDS_ALARM));
+#endif
+	tmp->tm_sec  = bcd2bin(sec & 0x7f);
+	tmp->tm_min  = bcd2bin(min & 0x7f);
+	tmp->tm_hour = bcd2bin(hour & 0x3f);
+	tmp->tm_mday = bcd2bin(mday & 0x3f);
+	tmp->tm_mon  = bcd2bin(mon & 0x1f);
+	tmp->tm_year = bcd2bin(year);
+	tmp->tm_wday = bcd2bin(wday & 0x07);
+
+	if (tmp->tm_year < 70)
+		tmp->tm_year += 2000;
+	else
+		tmp->tm_year += 1900;
+
+	tmp->tm_yday = 0;
+	tmp->tm_isdst = 0;
+#ifdef RTC_DEBUG
+	printf("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+
+	return 0;
+}
+
+static int mc146818_set(struct rtc_time *tmp)
+{
+#ifdef RTC_DEBUG
+	printf("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+#endif
+	/* Disable the RTC to update the regs */
+	mc146818_write8(RTC_CONFIG_B, 0x82);
+
+	mc146818_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
+	mc146818_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
+	mc146818_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
+	mc146818_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
+	mc146818_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
+	mc146818_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
+	mc146818_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
+
+	/* Enable the RTC to update the regs */
+	mc146818_write8(RTC_CONFIG_B, 0x02);
+
+	return 0;
+}
+
+static void mc146818_reset(void)
+{
+	/* Disable the RTC to update the regs */
+	mc146818_write8(RTC_CONFIG_B, 0x82);
+
+	/* Normal OP */
+	mc146818_write8(RTC_CONFIG_A, 0x20);
+	mc146818_write8(RTC_CONFIG_B, 0x00);
+	mc146818_write8(RTC_CONFIG_B, 0x00);
+
+	/* Enable the RTC to update the regs */
+	mc146818_write8(RTC_CONFIG_B, 0x02);
+}
+
+static void mc146818_init(void)
+{
+#if CLEAR_CMOS
+	int i;
+
+	rtc_write8(RTC_SECONDS_ALARM, 0);
+	rtc_write8(RTC_MINUTES_ALARM, 0);
+	rtc_write8(RTC_HOURS_ALARM, 0);
+	for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
+		rtc_write8(i, 0);
+	printf("RTC: zeroing CMOS RAM\n");
+#endif
+
+	/* Setup the real time clock */
+	mc146818_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
+	/* Setup the frequency it operates at */
+	mc146818_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
+			RTC_CONFIG_A_RATE_1024HZ);
+	/* Ensure all reserved bits are 0 in register D */
+	mc146818_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
+
+	/* Clear any pending interrupts */
+	mc146818_read8(RTC_CONFIG_C);
+}
+#endif
+
+#ifdef CONFIG_DM_RTC
+
+static int rtc_mc146818_get(struct udevice *dev, struct rtc_time *time)
+{
+	return mc146818_get(time);
+}
+
+static int rtc_mc146818_set(struct udevice *dev, const struct rtc_time *time)
+{
+	return mc146818_set((struct rtc_time *)time);
+}
+
+static int rtc_mc146818_reset(struct udevice *dev)
+{
+	mc146818_reset();
+
+	return 0;
+}
+
+static int rtc_mc146818_read8(struct udevice *dev, unsigned int reg)
+{
+	return mc146818_read8(reg);
+}
+
+static int rtc_mc146818_write8(struct udevice *dev, unsigned int reg, int val)
+{
+	mc146818_write8(reg, val);
+
+	return 0;
+}
+
+static int rtc_mc146818_bind(struct udevice *dev)
+{
+	mc146818_init();
+
+	return 0;
+}
+
+static const struct rtc_ops rtc_mc146818_ops = {
+	.get = rtc_mc146818_get,
+	.set = rtc_mc146818_set,
+	.reset = rtc_mc146818_reset,
+	.read8 = rtc_mc146818_read8,
+	.write8 = rtc_mc146818_write8,
+};
+
+static const struct udevice_id rtc_mc146818_ids[] = {
+	{ .compatible = "motorola,mc146818" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_mc146818) = {
+	.name = "rtc_mc146818",
+	.id = UCLASS_RTC,
+	.of_match = rtc_mc146818_ids,
+	.bind = rtc_mc146818_bind,
+	.ops = &rtc_mc146818_ops,
+};
+
+#else /* !CONFIG_DM_RTC */
+
+int rtc_get(struct rtc_time *tmp)
+{
+	return mc146818_get(tmp);
+}
+
+int rtc_set(struct rtc_time *tmp)
+{
+	return mc146818_set(tmp);
+}
+
+void rtc_reset(void)
+{
+	mc146818_reset();
+}
+
+int rtc_read8(int reg)
+{
+	return mc146818_read8(reg);
+}
+
+void rtc_write8(int reg, uchar val)
+{
+	mc146818_write8(reg, val);
+}
+
 u32 rtc_read32(int reg)
 {
 	u32 value = 0;
@@ -186,26 +301,7 @@
 
 void rtc_init(void)
 {
-#if CLEAR_CMOS
-	int i;
-
-	rtc_write8(RTC_SECONDS_ALARM, 0);
-	rtc_write8(RTC_MINUTES_ALARM, 0);
-	rtc_write8(RTC_HOURS_ALARM, 0);
-	for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
-		rtc_write8(i, 0);
-	printf("RTC: zeroing CMOS RAM\n");
-#endif
-
-	/* Setup the real time clock */
-	rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
-	/* Setup the frequency it operates at */
-	rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
-		  RTC_CONFIG_A_RATE_1024HZ);
-	/* Ensure all reserved bits are 0 in register D */
-	rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
-
-	/* Clear any pending interrupts */
-	rtc_read8(RTC_CONFIG_C);
+	mc146818_init();
 }
-#endif
+
+#endif /* CONFIG_DM_RTC */
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 50354fd..2e388e7 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -40,6 +40,7 @@
 	int status;
 	int control;
 	int bbar;
+	int bcr;
 	uint32_t *pr;		/* only for ich9 */
 	int speed;		/* pointer to speed control */
 	ulong max_speed;	/* Maximum bus speed in MHz */
@@ -239,6 +240,7 @@
 		ctlr->speed = ctlr->control + 2;
 		ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
 		ctlr->preop = offsetof(struct ich9_spi_regs, preop);
+		ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
 		ctlr->pr = &ich9_spi->pr[0];
 		ctlr->base = ich9_spi;
 	} else {
@@ -411,6 +413,7 @@
 			const void *dout, void *din, unsigned long flags)
 {
 	struct udevice *bus = dev_get_parent(dev);
+	struct ich_spi_platdata *plat = dev_get_platdata(bus);
 	struct ich_spi_priv *ctlr = dev_get_priv(bus);
 	uint16_t control;
 	int16_t opcode_index;
@@ -422,7 +425,7 @@
 	int using_cmd = 0;
 	int ret;
 
-	/* Ee don't support writing partial bytes. */
+	/* We don't support writing partial bytes */
 	if (bitlen % 8) {
 		debug("ICH SPI: Accessing partial bytes not supported\n");
 		return -EPROTONOSUPPORT;
@@ -477,7 +480,10 @@
 	if (ret < 0)
 		return ret;
 
-	ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
+	if (plat->ich_version == 7)
+		ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
+	else
+		ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
 
 	spi_setup_type(trans, using_cmd ? bytes : 0);
 	opcode_index = spi_setup_opcode(ctlr, trans);
@@ -601,7 +607,7 @@
 			return status;
 
 		if (status & SPIS_FCERR) {
-			debug("ICH SPI: Data transaction error\n");
+			debug("ICH SPI: Data transaction error %x\n", status);
 			return -EIO;
 		}
 
@@ -619,7 +625,6 @@
 	return 0;
 }
 
-
 /*
  * This uses the SPI controller from the Intel Cougar Point and Panther Point
  * PCH to write-protect portions of the SPI flash until reboot. The changes
@@ -685,13 +690,10 @@
 	 * v9, deassert SMM BIOS Write Protect Disable.
 	 */
 	if (plat->use_sbase) {
-		struct ich9_spi_regs *ich9_spi;
-
-		ich9_spi = priv->base;
-		bios_cntl = ich_readb(priv, ich9_spi->bcr);
+		bios_cntl = ich_readb(priv, priv->bcr);
 		bios_cntl &= ~(1 << 5);	/* clear Enable InSMM_STS (EISS) */
 		bios_cntl |= 1;		/* Write Protect Disable (WPD) */
-		ich_writeb(priv, bios_cntl, ich9_spi->bcr);
+		ich_writeb(priv, bios_cntl, priv->bcr);
 	} else {
 		pci_read_config_byte(plat->dev, 0xdc, &bios_cntl);
 		if (plat->ich_version == 9)
diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c
index 47f824a..909f8e8 100644
--- a/drivers/video/vesa_fb.c
+++ b/drivers/video/vesa_fb.c
@@ -1,6 +1,5 @@
 /*
- *
- * Vesa frame buffer driver for x86
+ * VESA frame buffer driver
  *
  * Copyright (C) 2014 Google, Inc
  *
@@ -17,16 +16,6 @@
  */
 GraphicDevice ctfb;
 
-/* Devices to allow - only the last one works fully */
-struct pci_device_id vesa_video_ids[] = {
-	{ .vendor = 0x102b, .device = 0x0525 },
-	{ .vendor = 0x1002, .device = 0x5159 },
-	{ .vendor = 0x1002, .device = 0x4752 },
-	{ .vendor = 0x1002, .device = 0x5452 },
-	{ .vendor = 0x8086, .device = 0x0f31 },
-	{},
-};
-
 void *video_hw_init(void)
 {
 	GraphicDevice *gdev = &ctfb;
@@ -36,8 +25,7 @@
 
 	printf("Video: ");
 	if (vbe_get_video_info(gdev)) {
-		/* TODO: Should we look these up by class? */
-		dev = pci_find_devices(vesa_video_ids, 0);
+		dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
 		if (dev == -1) {
 			printf("no card detected\n");
 			return NULL;
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 6747619..db0550b 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -93,6 +93,7 @@
 #endif
 #ifdef CONFIG_PCI
 	struct pci_controller *hose;	/* PCI hose for early use */
+	phys_addr_t pci_ram_top;	/* top of region accessible to PCI */
 #endif
 #ifdef CONFIG_PCI_BOOTDELAY
 	int pcidelay_done;
diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h
index 0e1f046..6cf53a3 100644
--- a/include/configs/crownbay.h
+++ b/include/configs/crownbay.h
@@ -32,15 +32,16 @@
 #define CONFIG_PCI_IO_PHYS		CONFIG_PCI_IO_BUS
 #define CONFIG_PCI_IO_SIZE		0xe000
 
+#define CONFIG_PCI_CONFIG_HOST_BRIDGE
 #define CONFIG_SYS_EARLY_PCI_INIT
 #define CONFIG_PCI_PNP
 #define CONFIG_E1000
 
-#define CONFIG_STD_DEVICES_SETTINGS     "stdin=serial\0" \
-					"stdout=serial\0" \
-					"stderr=serial\0"
+#define CONFIG_STD_DEVICES_SETTINGS	"stdin=serial,vga,usbkbd\0" \
+					"stdout=serial,vga\0" \
+					"stderr=serial,vga\0"
 
-#define CONFIG_SCSI_DEV_LIST            \
+#define CONFIG_SCSI_DEV_LIST		\
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SATA}
 
 #define CONFIG_SPI_FLASH_SST
@@ -55,9 +56,8 @@
 #define CONFIG_PCH_GBE
 #define CONFIG_PHYLIB
 
-/* Video is not supported */
-#undef CONFIG_VIDEO
-#undef CONFIG_CFB_CONSOLE
+/* TunnelCreek IGD support */
+#define CONFIG_VGA_AS_SINGLE_DEVICE
 
 /* Environment configuration */
 #define CONFIG_ENV_SECT_SIZE		0x1000
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index 547765d..af36ac5 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -32,6 +32,7 @@
 #define CONFIG_PCI_IO_PHYS		CONFIG_PCI_IO_BUS
 #define CONFIG_PCI_IO_SIZE		0xe000
 
+#define CONFIG_PCI_CONFIG_HOST_BRIDGE
 #define CONFIG_SYS_EARLY_PCI_INIT
 #define CONFIG_PCI_PNP
 #define CONFIG_RTL8169
@@ -52,9 +53,6 @@
 #undef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT		1
 
-#define CONFIG_X86_OPTION_ROM_FILE		vga.bin
-#define CONFIG_X86_OPTION_ROM_ADDR		0xfff90000
-
 #define VIDEO_IO_OFFSET				0
 #define CONFIG_X86EMU_RAW_IO
 #define CONFIG_VGA_AS_SINGLE_DEVICE
@@ -65,8 +63,7 @@
 /* Avoid a warning in the Realtek Ethernet driver */
 #define CONFIG_SYS_CACHELINE_SIZE 16
 
-/* Environment in SPI flash is unsupported for now */
-#undef CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SECT_SIZE		0x1000
+#define CONFIG_ENV_OFFSET		0x007fe000
 
 #endif	/* __CONFIG_H */
diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h
index e0e7fca..408cbb1 100644
--- a/include/configs/x86-chromebook.h
+++ b/include/configs/x86-chromebook.h
@@ -26,9 +26,6 @@
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}, \
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_AHCI}
 
-#define CONFIG_X86_OPTION_ROM_FILE		pci8086,0166.bin
-#define CONFIG_X86_OPTION_ROM_ADDR		0xfff90000
-
 #define CONFIG_PCI_MEM_BUS	0xe0000000
 #define CONFIG_PCI_MEM_PHYS	CONFIG_PCI_MEM_BUS
 #define CONFIG_PCI_MEM_SIZE	0x10000000
diff --git a/include/cpu.h b/include/cpu.h
index 34c60bc..bfb0db2 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -58,6 +58,14 @@
 	 * @return 0 if OK, -ve on error
 	 */
 	int (*get_info)(struct udevice *dev, struct cpu_info *info);
+
+	/**
+	 * get_count() - Get number of CPUs
+	 *
+	 * @dev:	Device to check (UCLASS_CPU)
+	 * @return CPU count if OK, -ve on error
+	 */
+	int (*get_count)(struct udevice *dev);
 };
 
 #define cpu_get_ops(dev)        ((struct cpu_ops *)(dev)->driver->ops)
@@ -81,4 +89,12 @@
  */
 int cpu_get_info(struct udevice *dev, struct cpu_info *info);
 
+/**
+ * cpu_get_count() - Get number of CPUs
+ *
+ * @dev:	Device to check (UCLASS_CPU)
+ * @return CPU count if OK, -ve on error
+ */
+int cpu_get_count(struct udevice *dev);
+
 #endif
diff --git a/include/pci.h b/include/pci.h
index 07b1e9a..542e68b 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -513,6 +513,16 @@
 
 	int indirect_type;
 
+	/*
+	 * TODO(sjg@chromium.org): With driver model we use struct
+	 * pci_controller for both the controller and any bridge devices
+	 * attached to it. But there is only one region list and it is in the
+	 * top-level controller.
+	 *
+	 * This could be changed so that struct pci_controller is only used
+	 * for PCI controllers and a separate UCLASS (or perhaps
+	 * UCLASS_PCI_GENERIC) is used for bridges.
+	 */
 	struct pci_region regions[MAX_PCI_REGIONS];
 	int region_count;
 
@@ -712,15 +722,6 @@
 u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
 
 /**
- * pciauto_setup_rom() - Set up access to a device ROM
- *
- * @hose:	PCI hose to use
- * @dev:	PCI device to adjust
- * @return 0 if done, -ve on error
- */
-int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev);
-
-/**
  * pci_hose_find_devices() - Find devices by vendor/device ID
  *
  * @hose:	PCI hose to search
diff --git a/include/vbe.h b/include/vbe.h
index c5deee9..1a86db8 100644
--- a/include/vbe.h
+++ b/include/vbe.h
@@ -12,7 +12,7 @@
 #define _VBE_H
 
 /* these structs are for input from and output to OF */
-struct __packed screen_info {
+struct __packed vbe_screen_info {
 	u8 display_type;	/* 0=NONE, 1= analog, 2=digital */
 	u16 screen_width;
 	u16 screen_height;
@@ -23,7 +23,7 @@
 	u8 edid_block_zero[128];
 };
 
-struct __packed screen_info_input {
+struct __packed vbe_screen_info_input {
 	u8 signature[4];
 	u16 size_reserved;
 	u8 monitor_number;
diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py
index ce1cfdd..cf25bb8 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -356,7 +356,7 @@
         # Now write the actual build output
         if keep_outputs:
             self.CopyFiles(result.out_dir, build_dir, '', ['u-boot*', '*.bin',
-                '*.map', '*.img', 'MLO', 'include/autoconf.mk',
+                '*.map', '*.img', 'MLO', 'SPL', 'include/autoconf.mk',
                 'spl/u-boot-spl*'])
 
     def CopyFiles(self, out_dir, build_dir, dirname, patterns):
diff --git a/tools/ifdtool.c b/tools/ifdtool.c
index 1d61df1..df16616 100644
--- a/tools/ifdtool.c
+++ b/tools/ifdtool.c
@@ -987,7 +987,7 @@
 					print_usage(argv[0]);
 					exit(EXIT_FAILURE);
 				}
-				ifile->addr = strtol(optarg, NULL, 0);
+				ifile->addr = strtoll(optarg, NULL, 0);
 				ifile->type = opt == 'f' ? IF_fdt :
 					opt == 'U' ? IF_uboot : IF_normal;
 				if (ifile->type == IF_fdt)