Merge branch 'sandbox' of git://git.denx.de/u-boot-x86
diff --git a/Makefile b/Makefile
index 79cb45c..b4ed775 100644
--- a/Makefile
+++ b/Makefile
@@ -980,6 +980,9 @@
 	$(objtree)/tools/ifdtool -w \
 		$(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin \
 		u-boot.tmp
+	$(objtree)/tools/ifdtool -w \
+		$(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILENAME) \
+		u-boot.tmp
 	mv u-boot.tmp $@
 
 OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b9ac59e..0982117 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -793,6 +793,7 @@
 	bool "Panasonic UniPhier platform"
 	select CPU_V7
 	select SUPPORT_SPL
+	select OF_CONTROL if !SPL_BUILD
 
 endchoice
 
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
index fba1cc7..5d682d3 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
-obj-y += platdevice.o
+obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
 obj-y += boot-mode.o
 obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
 								clkrst_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c
index 62f5b01..9d51299 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c
@@ -14,7 +14,6 @@
 SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
 SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)
 
-/* USB : TODO for Masahiro Yamada: move base address to Device Tree */
 struct uniphier_ehci_platform_data uniphier_ehci_platdata[] = {
 	{
 		.base = 0x5a800100,
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
index 74129bc..fd1c432 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
-obj-y += platdevice.o
+obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
 obj-y += boot-mode.o
 obj-$(CONFIG_SOC_INIT) += sbc_init.o sg_init.o pll_init.o clkrst_init.o
 obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c
index 1843d04..31ee2a2 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c
@@ -14,7 +14,6 @@
 SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
 SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)
 
-/* USB : TODO for Masahiro Yamada: move base address to Device Tree */
 struct uniphier_ehci_platform_data uniphier_ehci_platdata[] = {
 	{
 		.base = 0x5a800100,
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
index fba1cc7..5d682d3 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
-obj-y += platdevice.o
+obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
 obj-y += boot-mode.o
 obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
 								clkrst_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c
index 72ec599..ea0691d 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c
@@ -14,7 +14,6 @@
 SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
 SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)
 
-/* USB : TODO for Masahiro Yamada: move base address to Device Tree */
 struct uniphier_ehci_platform_data uniphier_ehci_platdata[] = {
 	{
 		.base = 0x5a800100,
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index e5846ea..01df9a9 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -32,6 +32,10 @@
 	tegra114-dalmore.dtb \
 	tegra124-jetson-tk1.dtb \
 	tegra124-venice2.dtb
+dtb-$(CONFIG_ARCH_UNIPHIER) += \
+	uniphier-ph1-pro4-ref.dtb \
+	uniphier-ph1-ld4-ref.dtb \
+	uniphier-ph1-sld8-ref.dtb
 dtb-$(CONFIG_ZYNQ) += zynq-zc702.dtb \
 	zynq-zc706.dtb \
 	zynq-zed.dtb \
diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
new file mode 100644
index 0000000..f01189c
--- /dev/null
+++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
@@ -0,0 +1,42 @@
+/*
+ * Device Tree Source for UniPhier PH1-LD4 Reference Board
+ *
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+/include/ "uniphier-ph1-ld4.dtsi"
+
+/ {
+	model = "Panasonic UniPhier PH1-LD4 Reference Board";
+	compatible = "panasonic,ph1-ld4-ref", "panasonic,ph1-ld4";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyPS0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&usb0 {
+      status = "okay";
+};
+
+&usb1 {
+      status = "okay";
+};
diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi
new file mode 100644
index 0000000..80074c5
--- /dev/null
+++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Device Tree Source for UniPhier PH1-LD4 SoC
+ *
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "panasonic,ph1-ld4";
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		uart0: serial@54006800 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x20>;
+			clock-frequency = <36864000>;
+		};
+
+		uart1: serial@54006900 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x20>;
+			clock-frequency = <36864000>;
+		};
+
+		uart2: serial@54006a00 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x20>;
+			clock-frequency = <36864000>;
+		};
+
+		uart3: serial@54006b00 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x20>;
+			clock-frequency = <36864000>;
+		};
+
+		usb0: usb@5a800100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a800100 0x100>;
+		};
+
+		usb1: usb@5a810100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a810100 0x100>;
+		};
+
+		usb2: usb@5a820100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a820100 0x100>;
+		};
+	};
+};
diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
new file mode 100644
index 0000000..52fa81f
--- /dev/null
+++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
@@ -0,0 +1,42 @@
+/*
+ * Device Tree Source for UniPhier PH1-Pro4 Reference Board
+ *
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+/include/ "uniphier-ph1-pro4.dtsi"
+
+/ {
+	model = "Panasonic UniPhier PH1-Pro4 Reference Board";
+	compatible = "panasonic,ph1-pro4-ref", "panasonic,ph1-pro4";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyPS0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&usb0 {
+      status = "okay";
+};
+
+&usb1 {
+      status = "okay";
+};
diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi
new file mode 100644
index 0000000..dd84269
--- /dev/null
+++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Device Tree Source for UniPhier PH1-Pro4 SoC
+ *
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "panasonic,ph1-pro4";
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		uart0: serial@54006800 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x20>;
+			clock-frequency = <73728000>;
+		};
+
+		uart1: serial@54006900 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x20>;
+			clock-frequency = <73728000>;
+		};
+
+		uart2: serial@54006a00 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x20>;
+			clock-frequency = <73728000>;
+		};
+
+		uart3: serial@54006b00 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x20>;
+			clock-frequency = <73728000>;
+		};
+
+		usb0: usb@5a800100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a800100 0x100>;
+		};
+
+		usb1: usb@5a810100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a810100 0x100>;
+		};
+	};
+};
diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
new file mode 100644
index 0000000..ac73aad
--- /dev/null
+++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
@@ -0,0 +1,42 @@
+/*
+ * Device Tree Source for UniPhier PH1-sLD8 Reference Board
+ *
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+/include/ "uniphier-ph1-sld8.dtsi"
+
+/ {
+	model = "Panasonic UniPhier PH1-sLD8 Reference Board";
+	compatible = "panasonic,ph1-sld8-ref", "panasonic,ph1-sld8";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyPS0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&usb0 {
+      status = "okay";
+};
+
+&usb1 {
+      status = "okay";
+};
diff --git a/arch/arm/dts/uniphier-ph1-sld8.dtsi b/arch/arm/dts/uniphier-ph1-sld8.dtsi
new file mode 100644
index 0000000..43a39f5
--- /dev/null
+++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Device Tree Source for UniPhier PH1-sLD8 SoC
+ *
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "panasonic,ph1-sld8";
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		uart0: serial@54006800 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x20>;
+			clock-frequency = <80000000>;
+		};
+
+		uart1: serial@54006900 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x20>;
+			clock-frequency = <80000000>;
+		};
+
+		uart2: serial@54006a00 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x20>;
+			clock-frequency = <80000000>;
+		};
+
+		uart3: serial@54006b00 {
+			compatible = "panasonic,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x20>;
+			clock-frequency = <80000000>;
+		};
+
+		usb0: usb@5a800100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a800100 0x100>;
+		};
+
+		usb1: usb@5a810100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a810100 0x100>;
+		};
+
+		usb2: usb@5a820100 {
+			compatible = "panasonic,uniphier-ehci", "usb-ehci";
+			status = "disabled";
+			reg = <0x5a820100 0x100>;
+		};
+	};
+};
diff --git a/arch/arm/include/asm/arch-s3c24x0/s3c2410.h b/arch/arm/include/asm/arch-s3c24x0/s3c2410.h
index ce4186f..8773ce3 100644
--- a/arch/arm/include/asm/arch-s3c24x0/s3c2410.h
+++ b/arch/arm/include/asm/arch-s3c24x0/s3c2410.h
@@ -83,9 +83,9 @@
 	return (struct s3c24x0_lcd *)S3C24X0_LCD_BASE;
 }
 
-static inline struct s3c2410_nand *s3c2410_get_base_nand(void)
+static inline struct s3c24x0_nand *s3c24x0_get_base_nand(void)
 {
-	return (struct s3c2410_nand *)S3C2410_NAND_BASE;
+	return (struct s3c24x0_nand *)S3C2410_NAND_BASE;
 }
 
 static inline struct s3c24x0_uart
diff --git a/arch/arm/include/asm/arch-s3c24x0/s3c2440.h b/arch/arm/include/asm/arch-s3c24x0/s3c2440.h
index 3f44bdc..7a525f2 100644
--- a/arch/arm/include/asm/arch-s3c24x0/s3c2440.h
+++ b/arch/arm/include/asm/arch-s3c24x0/s3c2440.h
@@ -81,9 +81,9 @@
 	return (struct s3c24x0_lcd *)S3C24X0_LCD_BASE;
 }
 
-static inline struct s3c2440_nand *s3c2440_get_base_nand(void)
+static inline struct s3c24x0_nand *s3c24x0_get_base_nand(void)
 {
-	return (struct s3c2440_nand *)S3C2440_NAND_BASE;
+	return (struct s3c24x0_nand *)S3C2440_NAND_BASE;
 }
 
 static inline struct s3c24x0_uart
diff --git a/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h b/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
index ed9df34..2dae9fc 100644
--- a/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
+++ b/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
@@ -135,34 +135,33 @@
 };
 
 
-#ifdef CONFIG_S3C2410
-/* NAND FLASH (see S3C2410 manual chapter 6) */
-struct s3c2410_nand {
+/* NAND FLASH (see manual chapter 6) */
+struct s3c24x0_nand {
 	u32	nfconf;
-	u32	nfcmd;
-	u32	nfaddr;
-	u32	nfdata;
-	u32	nfstat;
-	u32	nfecc;
-};
-#endif
-#ifdef CONFIG_S3C2440
-/* NAND FLASH (see S3C2440 manual chapter 6) */
-struct s3c2440_nand {
-	u32	nfconf;
+#ifndef CONFIG_S3C2410
 	u32	nfcont;
+#endif
 	u32	nfcmd;
 	u32	nfaddr;
 	u32	nfdata;
+#ifndef CONFIG_S3C2410
 	u32	nfeccd0;
 	u32	nfeccd1;
 	u32	nfeccd;
+#endif
 	u32	nfstat;
+#ifdef CONFIG_S3C2410
+	u32	nfecc;
+#else
 	u32	nfstat0;
 	u32	nfstat1;
-};
+	u32	nfmecc0;
+	u32	nfmecc1;
+	u32	nfsecc;
+	u32	nfsblk;
+	u32	nfeblk;
 #endif
-
+};
 
 /* UART (see manual chapter 11) */
 struct s3c24x0_uart {
diff --git a/arch/arm/include/asm/arch-uniphier/gpio.h b/arch/arm/include/asm/arch-uniphier/gpio.h
new file mode 100644
index 0000000..1fc4e19
--- /dev/null
+++ b/arch/arm/include/asm/arch-uniphier/gpio.h
@@ -0,0 +1,6 @@
+/*
+ * Dummy header file to enable CONFIG_OF_CONTROL.
+ * If CONFIG_OF_CONTROL is enabled, lib/fdtdec.c is compiled.
+ * It includes <asm/arch/gpio.h> via <asm/gpio.h>, so those SoCs that enable
+ * OF_CONTROL must have arch/gpio.h even if GPIO is not supported.
+ */
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/mips32/start.S
index 68e59b5..384ea26 100644
--- a/arch/mips/cpu/mips32/start.S
+++ b/arch/mips/cpu/mips32/start.S
@@ -136,10 +136,11 @@
 
 	/* Set up temporary stack */
 	li	sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
+	move	fp, sp
 
 	la	t9, board_init_f
 	jr	t9
-	 nop
+	 move	ra, zero
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -155,6 +156,7 @@
 	.ent	relocate_code
 relocate_code:
 	move	sp, a0			# set new stack pointer
+	move	fp, sp
 
 	move	s0, a1			# save gd in s0
 	move	s2, a2			# save destination address in s2
@@ -260,8 +262,9 @@
 	 addi	t1, 4
 
 	move	a0, s0			# a0 <-- gd
+	move	a1, s2
 	la	t9, board_init_r
 	jr	t9
-	 move	a1, s2
+	 move	ra, zero
 
 	.end	relocate_code
diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S
index 92954e1..6ff714e 100644
--- a/arch/mips/cpu/mips64/start.S
+++ b/arch/mips/cpu/mips64/start.S
@@ -130,10 +130,11 @@
 
 	/* Set up temporary stack */
 	dli	sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
+	move	fp, sp
 
 	dla	t9, board_init_f
 	jr	t9
-	 nop
+	 move	ra, zero
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -149,6 +150,7 @@
 	.ent	relocate_code
 relocate_code:
 	move	sp, a0			# set new stack pointer
+	move	fp, sp
 
 	move	s0, a1			# save gd in s0
 	move	s2, a2			# save destination address in s2
@@ -254,8 +256,9 @@
 	 daddi	t1, 8
 
 	move	a0, s0			# a0 <-- gd
+	move	a1, s2
 	dla	t9, board_init_r
 	jr	t9
-	 move	a1, s2
+	 move	ra, zero
 
 	.end	relocate_code
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index e483e86..7f9b653 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -5,9 +5,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-ifndef CONFIG_SYS_GENERIC_BOARD
-obj-y	+= board.o
-endif
 obj-y	+= io.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c
deleted file mode 100644
index 3feb020..0000000
--- a/arch/mips/lib/board.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <malloc.h>
-#include <serial.h>
-#include <stdio_dev.h>
-#include <version.h>
-#include <net.h>
-#include <environment.h>
-#include <nand.h>
-#include <onenand_uboot.h>
-#include <spi.h>
-
-#ifdef CONFIG_BITBANGMII
-#include <miiphy.h>
-#endif
-
-DECLARE_GLOBAL_DATA_PTR;
-
-ulong monitor_flash_len;
-
-static char *failed = "*** failed ***\n";
-
-int __board_early_init_f(void)
-{
-	/*
-	 * Nothing to do in this dummy implementation
-	 */
-	return 0;
-}
-int board_early_init_f(void)
-	__attribute__((weak, alias("__board_early_init_f")));
-
-static int init_func_ram(void)
-{
-#ifdef	CONFIG_BOARD_TYPES
-	int board_type = gd->board_type;
-#else
-	int board_type = 0;	/* use dummy arg */
-#endif
-	puts("DRAM:  ");
-
-	gd->ram_size = initdram(board_type);
-	if (gd->ram_size > 0) {
-		print_size(gd->ram_size, "\n");
-		return 0;
-	}
-	puts(failed);
-	return 1;
-}
-
-static int display_banner(void)
-{
-
-	printf("\n\n%s\n\n", version_string);
-	return 0;
-}
-
-#ifndef CONFIG_SYS_NO_FLASH
-static void display_flash_config(ulong size)
-{
-	puts("Flash: ");
-	print_size(size, "\n");
-}
-#endif
-
-static int init_baudrate(void)
-{
-	gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
-	return 0;
-}
-
-
-/*
- * Breath some life into the board...
- *
- * The first part of initialization is running from Flash memory;
- * its main purpose is to initialize the RAM so that we
- * can relocate the monitor code to RAM.
- */
-
-/*
- * All attempts to come up with a "common" initialization sequence
- * that works for all boards and architectures failed: some of the
- * requirements are just _too_ different. To get rid of the resulting
- * mess of board dependend #ifdef'ed code we now make the whole
- * initialization sequence configurable to the user.
- *
- * The requirements for any new initalization function is simple: it
- * receives a pointer to the "global data" structure as it's only
- * argument, and returns an integer return code, where 0 means
- * "continue" and != 0 means "fatal error, hang the system".
- */
-typedef int (init_fnc_t)(void);
-
-init_fnc_t *init_sequence[] = {
-	board_early_init_f,
-	timer_init,
-	env_init,		/* initialize environment */
-	init_baudrate,		/* initialize baudrate settings */
-	serial_init,		/* serial communications setup */
-	console_init_f,
-	display_banner,		/* say that we are here */
-	checkboard,
-	init_func_ram,
-	NULL,
-};
-
-
-void board_init_f(ulong bootflag)
-{
-	gd_t gd_data, *id;
-	bd_t *bd;
-	init_fnc_t **init_fnc_ptr;
-	ulong addr, addr_sp, len;
-	ulong *s;
-
-	/* Pointer is writable since we allocated a register for it.
-	 */
-	gd = &gd_data;
-	/* compiler optimization barrier needed for GCC >= 3.4 */
-	__asm__ __volatile__("" : : : "memory");
-
-	memset((void *)gd, 0, sizeof(gd_t));
-
-	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		if ((*init_fnc_ptr)() != 0)
-			hang();
-	}
-
-	/*
-	 * Now that we have DRAM mapped and working, we can
-	 * relocate the code and continue running from DRAM.
-	 */
-	addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
-
-	/* We can reserve some RAM "on top" here.
-	 */
-
-	/* round down to next 4 kB limit.
-	 */
-	addr &= ~(4096 - 1);
-	debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
-
-	/* Reserve memory for U-Boot code, data & bss
-	 * round down to next 16 kB limit
-	 */
-	len = bss_end() - CONFIG_SYS_MONITOR_BASE;
-	addr -= len;
-	addr &= ~(16 * 1024 - 1);
-
-	debug("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
-
-	 /* Reserve memory for malloc() arena.
-	 */
-	addr_sp = addr - TOTAL_MALLOC_LEN;
-	debug("Reserving %dk for malloc() at: %08lx\n",
-			TOTAL_MALLOC_LEN >> 10, addr_sp);
-
-	/*
-	 * (permanently) allocate a Board Info struct
-	 * and a permanent copy of the "global" data
-	 */
-	addr_sp -= sizeof(bd_t);
-	bd = (bd_t *)addr_sp;
-	gd->bd = bd;
-	debug("Reserving %zu Bytes for Board Info at: %08lx\n",
-			sizeof(bd_t), addr_sp);
-
-	addr_sp -= sizeof(gd_t);
-	id = (gd_t *)addr_sp;
-	debug("Reserving %zu Bytes for Global Data at: %08lx\n",
-			sizeof(gd_t), addr_sp);
-
-	/* Reserve memory for boot params.
-	 */
-	addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
-	bd->bi_boot_params = addr_sp;
-	debug("Reserving %dk for boot params() at: %08lx\n",
-			CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
-
-	/*
-	 * Finally, we set up a new (bigger) stack.
-	 *
-	 * Leave some safety gap for SP, force alignment on 16 byte boundary
-	 * Clear initial stack frame
-	 */
-	addr_sp -= 16;
-	addr_sp &= ~0xF;
-	s = (ulong *)addr_sp;
-	*s-- = 0;
-	*s-- = 0;
-	addr_sp = (ulong)s;
-	debug("Stack Pointer at: %08lx\n", addr_sp);
-
-	/*
-	 * Save local variables to board info struct
-	 */
-	bd->bi_memstart	= CONFIG_SYS_SDRAM_BASE;	/* start of DRAM */
-	bd->bi_memsize	= gd->ram_size;		/* size of DRAM in bytes */
-
-	memcpy(id, (void *)gd, sizeof(gd_t));
-
-	relocate_code(addr_sp, id, addr);
-
-	/* NOTREACHED - relocate_code() does not return */
-}
-
-/*
- * This is the next part if the initialization sequence: we are now
- * running from RAM and have a "normal" C environment, i. e. global
- * data can be written, BSS has been cleared, the stack size in not
- * that critical any more, etc.
- */
-
-void board_init_r(gd_t *id, ulong dest_addr)
-{
-#ifndef CONFIG_SYS_NO_FLASH
-	ulong size;
-#endif
-	bd_t *bd;
-
-	gd = id;
-	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
-
-	debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
-
-	gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
-
-	monitor_flash_len = image_copy_end() - dest_addr;
-
-	serial_initialize();
-
-	bd = gd->bd;
-
-	/* The Malloc area is immediately below the monitor copy in DRAM */
-	mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
-			TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
-
-#ifndef CONFIG_SYS_NO_FLASH
-	/* configure available FLASH banks */
-	size = flash_init();
-	display_flash_config(size);
-	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
-	bd->bi_flashsize = size;
-
-#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
-	bd->bi_flashoffset = monitor_flash_len;	/* reserved area for U-Boot */
-#else
-	bd->bi_flashoffset = 0;
-#endif
-#else
-	bd->bi_flashstart = 0;
-	bd->bi_flashsize = 0;
-	bd->bi_flashoffset = 0;
-#endif
-
-#ifdef CONFIG_CMD_NAND
-	puts("NAND:  ");
-	nand_init();		/* go init the NAND */
-#endif
-
-#if defined(CONFIG_CMD_ONENAND)
-	onenand_init();
-#endif
-
-	/* relocate environment function pointers etc. */
-	env_relocate();
-
-#if defined(CONFIG_PCI)
-	/*
-	 * Do pci configuration
-	 */
-	pci_init();
-#endif
-
-/** leave this here (after malloc(), environment and PCI are working) **/
-	/* Initialize stdio devices */
-	stdio_init();
-
-	jumptable_init();
-
-	/* Initialize the console (after the relocation and devices init) */
-	console_init_r();
-/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
-
-	/* Initialize from environment */
-	load_addr = getenv_ulong("loadaddr", 16, load_addr);
-
-#ifdef CONFIG_CMD_SPI
-	puts("SPI:   ");
-	spi_init();		/* go init the SPI */
-	puts("ready\n");
-#endif
-
-#if defined(CONFIG_MISC_INIT_R)
-	/* miscellaneous platform dependent initialisations */
-	misc_init_r();
-#endif
-
-#ifdef CONFIG_BITBANGMII
-	bb_miiphy_init();
-#endif
-#if defined(CONFIG_CMD_NET)
-	puts("Net:   ");
-	eth_initialize(gd->bd);
-#endif
-
-	/* main_loop() can return to retry autoboot, if so just run it again. */
-	for (;;)
-		main_loop();
-
-	/* NOTREACHED - no way out of command loop except booting */
-}
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 71bb0d2..e0722d2 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -6,10 +6,7 @@
  */
 
 #include <common.h>
-#include <command.h>
 #include <image.h>
-#include <u-boot/zlib.h>
-#include <asm/byteorder.h>
 #include <asm/addrspace.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -52,6 +49,20 @@
 	lmb_reserve(lmb, sp, CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp);
 }
 
+static int boot_setup_linux(bootm_headers_t *images)
+{
+	int ret;
+	ulong rd_len;
+
+	rd_len = images->rd_end - images->rd_start;
+	ret = boot_ramdisk_high(&images->lmb, images->rd_start,
+		rd_len, &images->initrd_start, &images->initrd_end);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static void linux_cmdline_init(void)
 {
 	linux_argc = 1;
@@ -224,6 +235,8 @@
 int do_bootm_linux(int flag, int argc, char * const argv[],
 			bootm_headers_t *images)
 {
+	int ret;
+
 	/* No need for those on MIPS */
 	if (flag & BOOTM_STATE_OS_BD_T)
 		return -1;
@@ -243,6 +256,10 @@
 		return 0;
 	}
 
+	ret = boot_setup_linux(images);
+	if (ret)
+		return ret;
+
 	boot_cmdline_linux(images);
 	boot_prep_linux(images);
 	boot_jump_linux(images);
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6e29868..4f5ce38 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -83,6 +83,155 @@
 	  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.
+
+menu "Display"
+
+config FRAMEBUFFER_SET_VESA_MODE
+	prompt "Set framebuffer graphics resolution"
+	bool
+	help
+	  Set VESA/native framebuffer mode (needed for bootsplash and graphical framebuffer console)
+
+choice
+	prompt "framebuffer graphics resolution"
+	default FRAMEBUFFER_VESA_MODE_117
+	depends on FRAMEBUFFER_SET_VESA_MODE
+	help
+	  This option sets the resolution used for the coreboot framebuffer (and
+	  bootsplash screen).
+
+config FRAMEBUFFER_VESA_MODE_100
+	bool "640x400 256-color"
+
+config FRAMEBUFFER_VESA_MODE_101
+	bool "640x480 256-color"
+
+config FRAMEBUFFER_VESA_MODE_102
+	bool "800x600 16-color"
+
+config FRAMEBUFFER_VESA_MODE_103
+	bool "800x600 256-color"
+
+config FRAMEBUFFER_VESA_MODE_104
+	bool "1024x768 16-color"
+
+config FRAMEBUFFER_VESA_MODE_105
+	bool "1024x7686 256-color"
+
+config FRAMEBUFFER_VESA_MODE_106
+	bool "1280x1024 16-color"
+
+config FRAMEBUFFER_VESA_MODE_107
+	bool "1280x1024 256-color"
+
+config FRAMEBUFFER_VESA_MODE_108
+	bool "80x60 text"
+
+config FRAMEBUFFER_VESA_MODE_109
+	bool "132x25 text"
+
+config FRAMEBUFFER_VESA_MODE_10A
+	bool "132x43 text"
+
+config FRAMEBUFFER_VESA_MODE_10B
+	bool "132x50 text"
+
+config FRAMEBUFFER_VESA_MODE_10C
+	bool "132x60 text"
+
+config FRAMEBUFFER_VESA_MODE_10D
+	bool "320x200 32k-color (1:5:5:5)"
+
+config FRAMEBUFFER_VESA_MODE_10E
+	bool "320x200 64k-color (5:6:5)"
+
+config FRAMEBUFFER_VESA_MODE_10F
+	bool "320x200 16.8M-color (8:8:8)"
+
+config FRAMEBUFFER_VESA_MODE_110
+	bool "640x480 32k-color (1:5:5:5)"
+
+config FRAMEBUFFER_VESA_MODE_111
+	bool "640x480 64k-color (5:6:5)"
+
+config FRAMEBUFFER_VESA_MODE_112
+	bool "640x480 16.8M-color (8:8:8)"
+
+config FRAMEBUFFER_VESA_MODE_113
+	bool "800x600 32k-color (1:5:5:5)"
+
+config FRAMEBUFFER_VESA_MODE_114
+	bool "800x600 64k-color (5:6:5)"
+
+config FRAMEBUFFER_VESA_MODE_115
+	bool "800x600 16.8M-color (8:8:8)"
+
+config FRAMEBUFFER_VESA_MODE_116
+	bool "1024x768 32k-color (1:5:5:5)"
+
+config FRAMEBUFFER_VESA_MODE_117
+	bool "1024x768 64k-color (5:6:5)"
+
+config FRAMEBUFFER_VESA_MODE_118
+	bool "1024x768 16.8M-color (8:8:8)"
+
+config FRAMEBUFFER_VESA_MODE_119
+	bool "1280x1024 32k-color (1:5:5:5)"
+
+config FRAMEBUFFER_VESA_MODE_11A
+	bool "1280x1024 64k-color (5:6:5)"
+
+config FRAMEBUFFER_VESA_MODE_11B
+	bool "1280x1024 16.8M-color (8:8:8)"
+
+config FRAMEBUFFER_VESA_MODE_USER
+	bool "Manually select VESA mode"
+
+endchoice
+
+# Map the config names to an integer (KB).
+config FRAMEBUFFER_VESA_MODE
+	prompt "VESA mode" if FRAMEBUFFER_VESA_MODE_USER
+	hex
+	default 0x100 if FRAMEBUFFER_VESA_MODE_100
+	default 0x101 if FRAMEBUFFER_VESA_MODE_101
+	default 0x102 if FRAMEBUFFER_VESA_MODE_102
+	default 0x103 if FRAMEBUFFER_VESA_MODE_103
+	default 0x104 if FRAMEBUFFER_VESA_MODE_104
+	default 0x105 if FRAMEBUFFER_VESA_MODE_105
+	default 0x106 if FRAMEBUFFER_VESA_MODE_106
+	default 0x107 if FRAMEBUFFER_VESA_MODE_107
+	default 0x108 if FRAMEBUFFER_VESA_MODE_108
+	default 0x109 if FRAMEBUFFER_VESA_MODE_109
+	default 0x10A if FRAMEBUFFER_VESA_MODE_10A
+	default 0x10B if FRAMEBUFFER_VESA_MODE_10B
+	default 0x10C if FRAMEBUFFER_VESA_MODE_10C
+	default 0x10D if FRAMEBUFFER_VESA_MODE_10D
+	default 0x10E if FRAMEBUFFER_VESA_MODE_10E
+	default 0x10F if FRAMEBUFFER_VESA_MODE_10F
+	default 0x110 if FRAMEBUFFER_VESA_MODE_110
+	default 0x111 if FRAMEBUFFER_VESA_MODE_111
+	default 0x112 if FRAMEBUFFER_VESA_MODE_112
+	default 0x113 if FRAMEBUFFER_VESA_MODE_113
+	default 0x114 if FRAMEBUFFER_VESA_MODE_114
+	default 0x115 if FRAMEBUFFER_VESA_MODE_115
+	default 0x116 if FRAMEBUFFER_VESA_MODE_116
+	default 0x117 if FRAMEBUFFER_VESA_MODE_117
+	default 0x118 if FRAMEBUFFER_VESA_MODE_118
+	default 0x119 if FRAMEBUFFER_VESA_MODE_119
+	default 0x11A if FRAMEBUFFER_VESA_MODE_11A
+	default 0x11B if FRAMEBUFFER_VESA_MODE_11B
+	default 0x117 if FRAMEBUFFER_VESA_MODE_USER
+
+endmenu
+
 source "arch/x86/cpu/ivybridge/Kconfig"
 
 source "board/coreboot/coreboot/Kconfig"
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 2b9e9b9..7f09db5 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -13,4 +13,8 @@
 obj-y	+= interrupts.o cpu.o call64.o
 
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
+obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
+obj-y += lapic.o
 obj-$(CONFIG_PCI) += pci.o
+obj-y += turbo.o
diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk
index f7b01d3..84aeaf3 100644
--- a/arch/x86/cpu/config.mk
+++ b/arch/x86/cpu/config.mk
@@ -12,5 +12,6 @@
 # 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=0xfff0
-LDPPFLAGS += -DSTART_16=0xf800
+LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0
+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/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 2df7288..cfacc05 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -39,17 +39,6 @@
 	return 0;
 }
 
-int board_early_init_r(void)
-{
-	/* CPU Speed to 100MHz */
-	gd->cpu_clk = 100000000;
-
-	/* Crystal is 33.000MHz */
-	gd->bus_clk = 33000000;
-
-	return 0;
-}
-
 int print_cpuinfo(void)
 {
 	return default_print_cpuinfo();
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index b391b7a..30e5069 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -124,7 +124,7 @@
 {
 	struct gdt_ptr gdt;
 
-	gdt.len = (num_entries * 8) - 1;
+	gdt.len = (num_entries * X86_GDT_ENTRY_SIZE) - 1;
 	gdt.ptr = (u32)boot_gdt;
 
 	asm volatile("lgdtl %0\n" : : "m" (gdt));
@@ -144,10 +144,13 @@
 		     (ulong)&id->arch.gd_addr, 0xfffff);
 
 	/* 16-bit CS: code, read/execute, 64 kB, base 0 */
-	gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff);
+	gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff);
 
 	/* 16-bit DS: data, read/write, 64 kB, base 0 */
-	gdt_addr[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff);
+	gdt_addr[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x0093, 0, 0x0ffff);
+
+	gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff);
+	gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff);
 
 	load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES);
 	load_ds(X86_GDT_ENTRY_32BIT_DS);
@@ -319,14 +322,6 @@
 
 	return 0;
 }
-
-int x86_cpu_init_r(void)
-{
-	/* Initialize core interrupt and exception functionality of CPU */
-	cpu_init_interrupts();
-	return 0;
-}
-int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r")));
 
 void x86_enable_caches(void)
 {
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index 51e2c59..a21d2a6 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -20,6 +20,7 @@
 #include <linux/compiler.h>
 #include <asm/msr.h>
 #include <asm/u-boot-x86.h>
+#include <asm/i8259.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -128,9 +129,6 @@
 	int irq_entry_size = irq_1 - irq_0;
 	void *irq_entry = (void *)irq_0;
 
-	/* Just in case... */
-	disable_interrupts();
-
 	/* Setup the IDT */
 	for (i = 0; i < 256; i++) {
 		idt[i].access = 0x8e;
@@ -146,9 +144,6 @@
 
 	load_idt(&idt_ptr);
 
-	/* It is now safe to enable interrupts */
-	enable_interrupts();
-
 	return 0;
 }
 
@@ -172,6 +167,25 @@
 	return flags & X86_EFLAGS_IF;
 }
 
+int interrupt_init(void)
+{
+	/* Just in case... */
+	disable_interrupts();
+
+#ifdef CONFIG_SYS_PCAT_INTERRUPTS
+	/* Initialize the master/slave i8259 pic */
+	i8259_init();
+#endif
+
+	/* Initialize core interrupt and exception functionality of CPU */
+	cpu_init_interrupts();
+
+	/* It is now safe to enable interrupts */
+	enable_interrupts();
+
+	return 0;
+}
+
 /* IRQ Low-Level Service Routine */
 void irq_llsr(struct irq_regs *regs)
 {
@@ -603,31 +617,3 @@
 	DECLARE_INTERRUPT(253) \
 	DECLARE_INTERRUPT(254) \
 	DECLARE_INTERRUPT(255));
-
-#if defined(CONFIG_INTEL_CORE_ARCH)
-/*
- * Get the number of CPU time counter ticks since it was read first time after
- * restart. This yields a free running counter guaranteed to take almost 6
- * years to wrap around even at 100GHz clock rate.
- */
-u64 get_ticks(void)
-{
-	u64 now_tick = rdtsc();
-
-	if (!gd->arch.tsc_base)
-		gd->arch.tsc_base = now_tick;
-
-	return now_tick - gd->arch.tsc_base;
-}
-
-#define PLATFORM_INFO_MSR 0xce
-
-unsigned long get_tbclk(void)
-{
-	u32 ratio;
-	u64 platform_info = native_read_msr(PLATFORM_INFO_MSR);
-
-	ratio = (platform_info >> 8) & 0xff;
-	return 100 * 1000 * 1000 * ratio; /* 100MHz times Max Non Turbo ratio */
-}
-#endif
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
index 721b37e..0c7efae 100644
--- a/arch/x86/cpu/ivybridge/Makefile
+++ b/arch/x86/cpu/ivybridge/Makefile
@@ -4,13 +4,21 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-y += bd82x6x.o
 obj-y += car.o
 obj-y += cpu.o
 obj-y += early_init.o
 obj-y += early_me.o
+obj-y += gma.o
 obj-y += lpc.o
 obj-y += me_status.o
+obj-y += model_206ax.o
 obj-y += microcode_intel.o
+obj-y += northbridge.o
+obj-y += pch.o
 obj-y += pci.o
 obj-y += report_platform.o
+obj-y += sata.o
 obj-y += sdram.o
+obj-y += usb_ehci.o
+obj-y += usb_xhci.o
diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c
new file mode 100644
index 0000000..65a17d3
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/bd82x6x.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/lapic.h>
+#include <asm/pci.h>
+#include <asm/arch/bd82x6x.h>
+#include <asm/arch/model_206ax.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+
+void bd82x6x_pci_init(pci_dev_t dev)
+{
+	u16 reg16;
+	u8 reg8;
+
+	debug("bd82x6x PCI init.\n");
+	/* Enable Bus Master */
+	reg16 = pci_read_config16(dev, PCI_COMMAND);
+	reg16 |= PCI_COMMAND_MASTER;
+	pci_write_config16(dev, PCI_COMMAND, reg16);
+
+	/* This device has no interrupt */
+	pci_write_config8(dev, INTR, 0xff);
+
+	/* disable parity error response and SERR */
+	reg16 = pci_read_config16(dev, BCTRL);
+	reg16 &= ~(1 << 0);
+	reg16 &= ~(1 << 1);
+	pci_write_config16(dev, BCTRL, reg16);
+
+	/* Master Latency Count must be set to 0x04! */
+	reg8 = pci_read_config8(dev, SMLT);
+	reg8 &= 0x07;
+	reg8 |= (0x04 << 3);
+	pci_write_config8(dev, SMLT, reg8);
+
+	/* Will this improve throughput of bus masters? */
+	pci_write_config8(dev, PCI_MIN_GNT, 0x06);
+
+	/* Clear errors in status registers */
+	reg16 = pci_read_config16(dev, PSTS);
+	/* reg16 |= 0xf900; */
+	pci_write_config16(dev, PSTS, reg16);
+
+	reg16 = pci_read_config16(dev, SECSTS);
+	/* reg16 |= 0xf900; */
+	pci_write_config16(dev, SECSTS, reg16);
+}
+
+#define PCI_BRIDGE_UPDATE_COMMAND
+void bd82x6x_pci_dev_enable_resources(pci_dev_t dev)
+{
+	uint16_t command;
+
+	command = pci_read_config16(dev, PCI_COMMAND);
+	command |= PCI_COMMAND_IO;
+#ifdef PCI_BRIDGE_UPDATE_COMMAND
+	/*
+	 * If we write to PCI_COMMAND, on some systems this will cause the
+	 * ROM and APICs to become invisible.
+	 */
+	debug("%x cmd <- %02x\n", dev, command);
+	pci_write_config16(dev, PCI_COMMAND, command);
+#else
+	printf("%s cmd <- %02x (NOT WRITTEN!)\n", dev_path(dev), command);
+#endif
+}
+
+void bd82x6x_pci_bus_enable_resources(pci_dev_t dev)
+{
+	uint16_t ctrl;
+
+	ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
+	ctrl |= PCI_COMMAND_IO;
+	ctrl |= PCI_BRIDGE_CTL_VGA;
+	debug("%x bridge ctrl <- %04x\n", dev, ctrl);
+	pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	bd82x6x_pci_dev_enable_resources(dev);
+}
+
+int bd82x6x_init_pci_devices(void)
+{
+	const void *blob = gd->fdt_blob;
+	struct pci_controller *hose;
+	struct x86_cpu_priv *cpu;
+	int sata_node, gma_node;
+	int ret;
+
+	hose = pci_bus_to_hose(0);
+	lpc_enable(PCH_LPC_DEV);
+	lpc_init(hose, PCH_LPC_DEV);
+	sata_node = fdtdec_next_compatible(blob, 0,
+					   COMPAT_INTEL_PANTHERPOINT_AHCI);
+	if (sata_node < 0) {
+		debug("%s: Cannot find SATA node\n", __func__);
+		return -EINVAL;
+	}
+	bd82x6x_sata_init(PCH_SATA_DEV, blob, sata_node);
+	bd82x6x_usb_ehci_init(PCH_EHCI1_DEV);
+	bd82x6x_usb_ehci_init(PCH_EHCI2_DEV);
+
+	cpu = calloc(1, sizeof(*cpu));
+	if (!cpu)
+		return -ENOMEM;
+	model_206ax_init(cpu);
+
+	gma_node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_GMA);
+	if (gma_node < 0) {
+		debug("%s: Cannot find GMA node\n", __func__);
+		return -EINVAL;
+	}
+	ret = gma_func0_init(PCH_VIDEO_DEV, pci_bus_to_hose(0), blob,
+			     gma_node);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int bd82x6x_init(void)
+{
+	const void *blob = gd->fdt_blob;
+	int sata_node;
+
+	sata_node = fdtdec_next_compatible(blob, 0,
+					   COMPAT_INTEL_PANTHERPOINT_AHCI);
+	if (sata_node < 0) {
+		debug("%s: Cannot find SATA node\n", __func__);
+		return -EINVAL;
+	}
+
+	bd82x6x_pci_init(PCH_DEV);
+	bd82x6x_sata_enable(PCH_SATA_DEV, blob, sata_node);
+	northbridge_enable(PCH_DEV);
+	northbridge_init(PCH_DEV);
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c
new file mode 100644
index 0000000..3d7f740
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/gma.c
@@ -0,0 +1,756 @@
+/*
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2011 Chromium OS Authors
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <bios_emul.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <pci_rom.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+
+struct gt_powermeter {
+	u16 reg;
+	u32 value;
+};
+
+static const struct gt_powermeter snb_pm_gt1[] = {
+	{ 0xa200, 0xcc000000 },
+	{ 0xa204, 0x07000040 },
+	{ 0xa208, 0x0000fe00 },
+	{ 0xa20c, 0x00000000 },
+	{ 0xa210, 0x17000000 },
+	{ 0xa214, 0x00000021 },
+	{ 0xa218, 0x0817fe19 },
+	{ 0xa21c, 0x00000000 },
+	{ 0xa220, 0x00000000 },
+	{ 0xa224, 0xcc000000 },
+	{ 0xa228, 0x07000040 },
+	{ 0xa22c, 0x0000fe00 },
+	{ 0xa230, 0x00000000 },
+	{ 0xa234, 0x17000000 },
+	{ 0xa238, 0x00000021 },
+	{ 0xa23c, 0x0817fe19 },
+	{ 0xa240, 0x00000000 },
+	{ 0xa244, 0x00000000 },
+	{ 0xa248, 0x8000421e },
+	{ 0 }
+};
+
+static const struct gt_powermeter snb_pm_gt2[] = {
+	{ 0xa200, 0x330000a6 },
+	{ 0xa204, 0x402d0031 },
+	{ 0xa208, 0x00165f83 },
+	{ 0xa20c, 0xf1000000 },
+	{ 0xa210, 0x00000000 },
+	{ 0xa214, 0x00160016 },
+	{ 0xa218, 0x002a002b },
+	{ 0xa21c, 0x00000000 },
+	{ 0xa220, 0x00000000 },
+	{ 0xa224, 0x330000a6 },
+	{ 0xa228, 0x402d0031 },
+	{ 0xa22c, 0x00165f83 },
+	{ 0xa230, 0xf1000000 },
+	{ 0xa234, 0x00000000 },
+	{ 0xa238, 0x00160016 },
+	{ 0xa23c, 0x002a002b },
+	{ 0xa240, 0x00000000 },
+	{ 0xa244, 0x00000000 },
+	{ 0xa248, 0x8000421e },
+	{ 0 }
+};
+
+static const struct gt_powermeter ivb_pm_gt1[] = {
+	{ 0xa800, 0x00000000 },
+	{ 0xa804, 0x00021c00 },
+	{ 0xa808, 0x00000403 },
+	{ 0xa80c, 0x02001700 },
+	{ 0xa810, 0x05000200 },
+	{ 0xa814, 0x00000000 },
+	{ 0xa818, 0x00690500 },
+	{ 0xa81c, 0x0000007f },
+	{ 0xa820, 0x01002501 },
+	{ 0xa824, 0x00000300 },
+	{ 0xa828, 0x01000331 },
+	{ 0xa82c, 0x0000000c },
+	{ 0xa830, 0x00010016 },
+	{ 0xa834, 0x01100101 },
+	{ 0xa838, 0x00010103 },
+	{ 0xa83c, 0x00041300 },
+	{ 0xa840, 0x00000b30 },
+	{ 0xa844, 0x00000000 },
+	{ 0xa848, 0x7f000000 },
+	{ 0xa84c, 0x05000008 },
+	{ 0xa850, 0x00000001 },
+	{ 0xa854, 0x00000004 },
+	{ 0xa858, 0x00000007 },
+	{ 0xa85c, 0x00000000 },
+	{ 0xa860, 0x00010000 },
+	{ 0xa248, 0x0000221e },
+	{ 0xa900, 0x00000000 },
+	{ 0xa904, 0x00001c00 },
+	{ 0xa908, 0x00000000 },
+	{ 0xa90c, 0x06000000 },
+	{ 0xa910, 0x09000200 },
+	{ 0xa914, 0x00000000 },
+	{ 0xa918, 0x00590000 },
+	{ 0xa91c, 0x00000000 },
+	{ 0xa920, 0x04002501 },
+	{ 0xa924, 0x00000100 },
+	{ 0xa928, 0x03000410 },
+	{ 0xa92c, 0x00000000 },
+	{ 0xa930, 0x00020000 },
+	{ 0xa934, 0x02070106 },
+	{ 0xa938, 0x00010100 },
+	{ 0xa93c, 0x00401c00 },
+	{ 0xa940, 0x00000000 },
+	{ 0xa944, 0x00000000 },
+	{ 0xa948, 0x10000e00 },
+	{ 0xa94c, 0x02000004 },
+	{ 0xa950, 0x00000001 },
+	{ 0xa954, 0x00000004 },
+	{ 0xa960, 0x00060000 },
+	{ 0xaa3c, 0x00001c00 },
+	{ 0xaa54, 0x00000004 },
+	{ 0xaa60, 0x00060000 },
+	{ 0 }
+};
+
+static const struct gt_powermeter ivb_pm_gt2[] = {
+	{ 0xa800, 0x10000000 },
+	{ 0xa804, 0x00033800 },
+	{ 0xa808, 0x00000902 },
+	{ 0xa80c, 0x0c002f00 },
+	{ 0xa810, 0x12000400 },
+	{ 0xa814, 0x00000000 },
+	{ 0xa818, 0x00d20800 },
+	{ 0xa81c, 0x00000002 },
+	{ 0xa820, 0x03004b02 },
+	{ 0xa824, 0x00000600 },
+	{ 0xa828, 0x07000773 },
+	{ 0xa82c, 0x00000000 },
+	{ 0xa830, 0x00010032 },
+	{ 0xa834, 0x1520040d },
+	{ 0xa838, 0x00020105 },
+	{ 0xa83c, 0x00083700 },
+	{ 0xa840, 0x0000151d },
+	{ 0xa844, 0x00000000 },
+	{ 0xa848, 0x20001b00 },
+	{ 0xa84c, 0x0a000010 },
+	{ 0xa850, 0x00000000 },
+	{ 0xa854, 0x00000008 },
+	{ 0xa858, 0x00000008 },
+	{ 0xa85c, 0x00000000 },
+	{ 0xa860, 0x00020000 },
+	{ 0xa248, 0x0000221e },
+	{ 0xa900, 0x00000000 },
+	{ 0xa904, 0x00003500 },
+	{ 0xa908, 0x00000000 },
+	{ 0xa90c, 0x0c000000 },
+	{ 0xa910, 0x12000500 },
+	{ 0xa914, 0x00000000 },
+	{ 0xa918, 0x00b20000 },
+	{ 0xa91c, 0x00000000 },
+	{ 0xa920, 0x08004b02 },
+	{ 0xa924, 0x00000200 },
+	{ 0xa928, 0x07000820 },
+	{ 0xa92c, 0x00000000 },
+	{ 0xa930, 0x00030000 },
+	{ 0xa934, 0x050f020d },
+	{ 0xa938, 0x00020300 },
+	{ 0xa93c, 0x00903900 },
+	{ 0xa940, 0x00000000 },
+	{ 0xa944, 0x00000000 },
+	{ 0xa948, 0x20001b00 },
+	{ 0xa94c, 0x0a000010 },
+	{ 0xa950, 0x00000000 },
+	{ 0xa954, 0x00000008 },
+	{ 0xa960, 0x00110000 },
+	{ 0xaa3c, 0x00003900 },
+	{ 0xaa54, 0x00000008 },
+	{ 0xaa60, 0x00110000 },
+	{ 0 }
+};
+
+static const struct gt_powermeter ivb_pm_gt2_17w[] = {
+	{ 0xa800, 0x20000000 },
+	{ 0xa804, 0x000e3800 },
+	{ 0xa808, 0x00000806 },
+	{ 0xa80c, 0x0c002f00 },
+	{ 0xa810, 0x0c000800 },
+	{ 0xa814, 0x00000000 },
+	{ 0xa818, 0x00d20d00 },
+	{ 0xa81c, 0x000000ff },
+	{ 0xa820, 0x03004b02 },
+	{ 0xa824, 0x00000600 },
+	{ 0xa828, 0x07000773 },
+	{ 0xa82c, 0x00000000 },
+	{ 0xa830, 0x00020032 },
+	{ 0xa834, 0x1520040d },
+	{ 0xa838, 0x00020105 },
+	{ 0xa83c, 0x00083700 },
+	{ 0xa840, 0x000016ff },
+	{ 0xa844, 0x00000000 },
+	{ 0xa848, 0xff000000 },
+	{ 0xa84c, 0x0a000010 },
+	{ 0xa850, 0x00000002 },
+	{ 0xa854, 0x00000008 },
+	{ 0xa858, 0x0000000f },
+	{ 0xa85c, 0x00000000 },
+	{ 0xa860, 0x00020000 },
+	{ 0xa248, 0x0000221e },
+	{ 0xa900, 0x00000000 },
+	{ 0xa904, 0x00003800 },
+	{ 0xa908, 0x00000000 },
+	{ 0xa90c, 0x0c000000 },
+	{ 0xa910, 0x12000800 },
+	{ 0xa914, 0x00000000 },
+	{ 0xa918, 0x00b20000 },
+	{ 0xa91c, 0x00000000 },
+	{ 0xa920, 0x08004b02 },
+	{ 0xa924, 0x00000300 },
+	{ 0xa928, 0x01000820 },
+	{ 0xa92c, 0x00000000 },
+	{ 0xa930, 0x00030000 },
+	{ 0xa934, 0x15150406 },
+	{ 0xa938, 0x00020300 },
+	{ 0xa93c, 0x00903900 },
+	{ 0xa940, 0x00000000 },
+	{ 0xa944, 0x00000000 },
+	{ 0xa948, 0x20001b00 },
+	{ 0xa94c, 0x0a000010 },
+	{ 0xa950, 0x00000000 },
+	{ 0xa954, 0x00000008 },
+	{ 0xa960, 0x00110000 },
+	{ 0xaa3c, 0x00003900 },
+	{ 0xaa54, 0x00000008 },
+	{ 0xaa60, 0x00110000 },
+	{ 0 }
+};
+
+static const struct gt_powermeter ivb_pm_gt2_35w[] = {
+	{ 0xa800, 0x00000000 },
+	{ 0xa804, 0x00030400 },
+	{ 0xa808, 0x00000806 },
+	{ 0xa80c, 0x0c002f00 },
+	{ 0xa810, 0x0c000300 },
+	{ 0xa814, 0x00000000 },
+	{ 0xa818, 0x00d20d00 },
+	{ 0xa81c, 0x000000ff },
+	{ 0xa820, 0x03004b02 },
+	{ 0xa824, 0x00000600 },
+	{ 0xa828, 0x07000773 },
+	{ 0xa82c, 0x00000000 },
+	{ 0xa830, 0x00020032 },
+	{ 0xa834, 0x1520040d },
+	{ 0xa838, 0x00020105 },
+	{ 0xa83c, 0x00083700 },
+	{ 0xa840, 0x000016ff },
+	{ 0xa844, 0x00000000 },
+	{ 0xa848, 0xff000000 },
+	{ 0xa84c, 0x0a000010 },
+	{ 0xa850, 0x00000001 },
+	{ 0xa854, 0x00000008 },
+	{ 0xa858, 0x00000008 },
+	{ 0xa85c, 0x00000000 },
+	{ 0xa860, 0x00020000 },
+	{ 0xa248, 0x0000221e },
+	{ 0xa900, 0x00000000 },
+	{ 0xa904, 0x00003800 },
+	{ 0xa908, 0x00000000 },
+	{ 0xa90c, 0x0c000000 },
+	{ 0xa910, 0x12000800 },
+	{ 0xa914, 0x00000000 },
+	{ 0xa918, 0x00b20000 },
+	{ 0xa91c, 0x00000000 },
+	{ 0xa920, 0x08004b02 },
+	{ 0xa924, 0x00000300 },
+	{ 0xa928, 0x01000820 },
+	{ 0xa92c, 0x00000000 },
+	{ 0xa930, 0x00030000 },
+	{ 0xa934, 0x15150406 },
+	{ 0xa938, 0x00020300 },
+	{ 0xa93c, 0x00903900 },
+	{ 0xa940, 0x00000000 },
+	{ 0xa944, 0x00000000 },
+	{ 0xa948, 0x20001b00 },
+	{ 0xa94c, 0x0a000010 },
+	{ 0xa950, 0x00000000 },
+	{ 0xa954, 0x00000008 },
+	{ 0xa960, 0x00110000 },
+	{ 0xaa3c, 0x00003900 },
+	{ 0xaa54, 0x00000008 },
+	{ 0xaa60, 0x00110000 },
+	{ 0 }
+};
+
+/*
+ * Some vga option roms are used for several chipsets but they only have one
+ * PCI ID in their header. If we encounter such an option rom, we need to do
+ * the mapping ourselves.
+ */
+
+u32 map_oprom_vendev(u32 vendev)
+{
+	u32 new_vendev = vendev;
+
+	switch (vendev) {
+	case 0x80860102:		/* GT1 Desktop */
+	case 0x8086010a:		/* GT1 Server */
+	case 0x80860112:		/* GT2 Desktop */
+	case 0x80860116:		/* GT2 Mobile */
+	case 0x80860122:		/* GT2 Desktop >=1.3GHz */
+	case 0x80860126:		/* GT2 Mobile >=1.3GHz */
+	case 0x80860156:		/* IVB */
+	case 0x80860166:		/* IVB */
+		/* Set to GT1 Mobile */
+		new_vendev = 0x80860106;
+		break;
+	}
+
+	return new_vendev;
+}
+
+static inline u32 gtt_read(void *bar, u32 reg)
+{
+	return readl(bar + reg);
+}
+
+static inline void gtt_write(void *bar, u32 reg, u32 data)
+{
+	writel(data, bar + reg);
+}
+
+static void gtt_write_powermeter(void *bar, const struct gt_powermeter *pm)
+{
+	for (; pm && pm->reg; pm++)
+		gtt_write(bar, pm->reg, pm->value);
+}
+
+#define GTT_RETRY 1000
+static int gtt_poll(void *bar, u32 reg, u32 mask, u32 value)
+{
+	unsigned try = GTT_RETRY;
+	u32 data;
+
+	while (try--) {
+		data = gtt_read(bar, reg);
+		if ((data & mask) == value)
+			return 1;
+		udelay(10);
+	}
+
+	printf("GT init timeout\n");
+	return 0;
+}
+
+static int gma_pm_init_pre_vbios(void *gtt_bar)
+{
+	u32 reg32;
+
+	debug("GT Power Management Init, silicon = %#x\n",
+	      bridge_silicon_revision());
+
+	if (bridge_silicon_revision() < IVB_STEP_C0) {
+		/* 1: Enable force wake */
+		gtt_write(gtt_bar, 0xa18c, 0x00000001);
+		gtt_poll(gtt_bar, 0x130090, (1 << 0), (1 << 0));
+	} else {
+		gtt_write(gtt_bar, 0xa180, 1 << 5);
+		gtt_write(gtt_bar, 0xa188, 0xffff0001);
+		gtt_poll(gtt_bar, 0x130040, (1 << 0), (1 << 0));
+	}
+
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
+		/* 1d: Set GTT+0x42004 [15:14]=11 (SnB C1+) */
+		reg32 = gtt_read(gtt_bar, 0x42004);
+		reg32 |= (1 << 14) | (1 << 15);
+		gtt_write(gtt_bar, 0x42004, reg32);
+	}
+
+	if (bridge_silicon_revision() >= IVB_STEP_A0) {
+		/* Display Reset Acknowledge Settings */
+		reg32 = gtt_read(gtt_bar, 0x45010);
+		reg32 |= (1 << 1) | (1 << 0);
+		gtt_write(gtt_bar, 0x45010, reg32);
+	}
+
+	/* 2: Get GT SKU from GTT+0x911c[13] */
+	reg32 = gtt_read(gtt_bar, 0x911c);
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
+		if (reg32 & (1 << 13)) {
+			debug("SNB GT1 Power Meter Weights\n");
+			gtt_write_powermeter(gtt_bar, snb_pm_gt1);
+		} else {
+			debug("SNB GT2 Power Meter Weights\n");
+			gtt_write_powermeter(gtt_bar, snb_pm_gt2);
+		}
+	} else {
+		u32 unit = readl(MCHBAR_REG(0x5938)) & 0xf;
+
+		if (reg32 & (1 << 13)) {
+			/* GT1 SKU */
+			debug("IVB GT1 Power Meter Weights\n");
+			gtt_write_powermeter(gtt_bar, ivb_pm_gt1);
+		} else {
+			/* GT2 SKU */
+			u32 tdp = readl(MCHBAR_REG(0x5930)) & 0x7fff;
+			tdp /= (1 << unit);
+
+			if (tdp <= 17) {
+				/* <=17W ULV */
+				debug("IVB GT2 17W Power Meter Weights\n");
+				gtt_write_powermeter(gtt_bar, ivb_pm_gt2_17w);
+			} else if ((tdp >= 25) && (tdp <= 35)) {
+				/* 25W-35W */
+				debug("IVB GT2 25W-35W Power Meter Weights\n");
+				gtt_write_powermeter(gtt_bar, ivb_pm_gt2_35w);
+			} else {
+				/* All others */
+				debug("IVB GT2 35W Power Meter Weights\n");
+				gtt_write_powermeter(gtt_bar, ivb_pm_gt2_35w);
+			}
+		}
+	}
+
+	/* 3: Gear ratio map */
+	gtt_write(gtt_bar, 0xa004, 0x00000010);
+
+	/* 4: GFXPAUSE */
+	gtt_write(gtt_bar, 0xa000, 0x00070020);
+
+	/* 5: Dynamic EU trip control */
+	gtt_write(gtt_bar, 0xa080, 0x00000004);
+
+	/* 6: ECO bits */
+	reg32 = gtt_read(gtt_bar, 0xa180);
+	reg32 |= (1 << 26) | (1 << 31);
+	/* (bit 20=1 for SNB step D1+ / IVB A0+) */
+	if (bridge_silicon_revision() >= SNB_STEP_D1)
+		reg32 |= (1 << 20);
+	gtt_write(gtt_bar, 0xa180, reg32);
+
+	/* 6a: for SnB step D2+ only */
+	if (((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) &&
+	    (bridge_silicon_revision() >= SNB_STEP_D2)) {
+		reg32 = gtt_read(gtt_bar, 0x9400);
+		reg32 |= (1 << 7);
+		gtt_write(gtt_bar, 0x9400, reg32);
+
+		reg32 = gtt_read(gtt_bar, 0x941c);
+		reg32 &= 0xf;
+		reg32 |= (1 << 1);
+		gtt_write(gtt_bar, 0x941c, reg32);
+		gtt_poll(gtt_bar, 0x941c, (1 << 1), (0 << 1));
+	}
+
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) {
+		reg32 = gtt_read(gtt_bar, 0x907c);
+		reg32 |= (1 << 16);
+		gtt_write(gtt_bar, 0x907c, reg32);
+
+		/* 6b: Clocking reset controls */
+		gtt_write(gtt_bar, 0x9424, 0x00000001);
+	} else {
+		/* 6b: Clocking reset controls */
+		gtt_write(gtt_bar, 0x9424, 0x00000000);
+	}
+
+	/* 7 */
+	if (gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31))) {
+		gtt_write(gtt_bar, 0x138128, 0x00000029); /* Mailbox Data */
+		/* Mailbox Cmd for RC6 VID */
+		gtt_write(gtt_bar, 0x138124, 0x80000004);
+		if (gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31)))
+			gtt_write(gtt_bar, 0x138124, 0x8000000a);
+		gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31));
+	}
+
+	/* 8 */
+	gtt_write(gtt_bar, 0xa090, 0x00000000); /* RC Control */
+	gtt_write(gtt_bar, 0xa098, 0x03e80000); /* RC1e Wake Rate Limit */
+	gtt_write(gtt_bar, 0xa09c, 0x0028001e); /* RC6/6p Wake Rate Limit */
+	gtt_write(gtt_bar, 0xa0a0, 0x0000001e); /* RC6pp Wake Rate Limit */
+	gtt_write(gtt_bar, 0xa0a8, 0x0001e848); /* RC Evaluation Interval */
+	gtt_write(gtt_bar, 0xa0ac, 0x00000019); /* RC Idle Hysteresis */
+
+	/* 9 */
+	gtt_write(gtt_bar, 0x2054, 0x0000000a); /* Render Idle Max Count */
+	gtt_write(gtt_bar, 0x12054, 0x0000000a); /* Video Idle Max Count */
+	gtt_write(gtt_bar, 0x22054, 0x0000000a); /* Blitter Idle Max Count */
+
+	/* 10 */
+	gtt_write(gtt_bar, 0xa0b0, 0x00000000); /* Unblock Ack to Busy */
+	gtt_write(gtt_bar, 0xa0b4, 0x000003e8); /* RC1e Threshold */
+	gtt_write(gtt_bar, 0xa0b8, 0x0000c350); /* RC6 Threshold */
+	gtt_write(gtt_bar, 0xa0bc, 0x000186a0); /* RC6p Threshold */
+	gtt_write(gtt_bar, 0xa0c0, 0x0000fa00); /* RC6pp Threshold */
+
+	/* 11 */
+	gtt_write(gtt_bar, 0xa010, 0x000f4240); /* RP Down Timeout */
+	gtt_write(gtt_bar, 0xa014, 0x12060000); /* RP Interrupt Limits */
+	gtt_write(gtt_bar, 0xa02c, 0x00015f90); /* RP Up Threshold */
+	gtt_write(gtt_bar, 0xa030, 0x000186a0); /* RP Down Threshold */
+	gtt_write(gtt_bar, 0xa068, 0x000186a0); /* RP Up EI */
+	gtt_write(gtt_bar, 0xa06c, 0x000493e0); /* RP Down EI */
+	gtt_write(gtt_bar, 0xa070, 0x0000000a); /* RP Idle Hysteresis */
+
+	/* 11a: Enable Render Standby (RC6) */
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) {
+		/*
+		 * IvyBridge should also support DeepRenderStandby.
+		 *
+		 * Unfortunately it does not work reliably on all SKUs so
+		 * disable it here and it can be enabled by the kernel.
+		 */
+		gtt_write(gtt_bar, 0xa090, 0x88040000); /* HW RC Control */
+	} else {
+		gtt_write(gtt_bar, 0xa090, 0x88040000); /* HW RC Control */
+	}
+
+	/* 12: Normal Frequency Request */
+	/* RPNFREQ_VAL comes from MCHBAR 0x5998 23:16 (8 bits!? use 7) */
+	reg32 = readl(MCHBAR_REG(0x5998));
+	reg32 >>= 16;
+	reg32 &= 0xef;
+	reg32 <<= 25;
+	gtt_write(gtt_bar, 0xa008, reg32);
+
+	/* 13: RP Control */
+	gtt_write(gtt_bar, 0xa024, 0x00000592);
+
+	/* 14: Enable PM Interrupts */
+	gtt_write(gtt_bar, 0x4402c, 0x03000076);
+
+	/* Clear 0x6c024 [8:6] */
+	reg32 = gtt_read(gtt_bar, 0x6c024);
+	reg32 &= ~0x000001c0;
+	gtt_write(gtt_bar, 0x6c024, reg32);
+
+	return 0;
+}
+
+int gma_pm_init_post_vbios(void *gtt_bar, const void *blob, int node)
+{
+	u32 reg32, cycle_delay;
+
+	debug("GT Power Management Init (post VBIOS)\n");
+
+	/* 15: Deassert Force Wake */
+	if (bridge_silicon_revision() < IVB_STEP_C0) {
+		gtt_write(gtt_bar, 0xa18c, gtt_read(gtt_bar, 0xa18c) & ~1);
+		gtt_poll(gtt_bar, 0x130090, (1 << 0), (0 << 0));
+	} else {
+		gtt_write(gtt_bar, 0xa188, 0x1fffe);
+		if (gtt_poll(gtt_bar, 0x130040, (1 << 0), (0 << 0))) {
+			gtt_write(gtt_bar, 0xa188,
+				  gtt_read(gtt_bar, 0xa188) | 1);
+		}
+	}
+
+	/* 16: SW RC Control */
+	gtt_write(gtt_bar, 0xa094, 0x00060000);
+
+	/* Setup Digital Port Hotplug */
+	reg32 = gtt_read(gtt_bar, 0xc4030);
+	if (!reg32) {
+		u32 dp_hotplug[3];
+
+		if (fdtdec_get_int_array(blob, node, "intel,dp_hotplug",
+					 dp_hotplug, ARRAY_SIZE(dp_hotplug)))
+			return -EINVAL;
+
+		reg32 = (dp_hotplug[0] & 0x7) << 2;
+		reg32 |= (dp_hotplug[0] & 0x7) << 10;
+		reg32 |= (dp_hotplug[0] & 0x7) << 18;
+		gtt_write(gtt_bar, 0xc4030, reg32);
+	}
+
+	/* Setup Panel Power On Delays */
+	reg32 = gtt_read(gtt_bar, 0xc7208);
+	if (!reg32) {
+		reg32 = (unsigned)fdtdec_get_int(blob, node,
+						 "panel-port-select", 0) << 30;
+		reg32 |= fdtdec_get_int(blob, node, "panel-power-up-delay", 0)
+				<< 16;
+		reg32 |= fdtdec_get_int(blob, node,
+					"panel-power-backlight-on-delay", 0);
+		gtt_write(gtt_bar, 0xc7208, reg32);
+	}
+
+	/* Setup Panel Power Off Delays */
+	reg32 = gtt_read(gtt_bar, 0xc720c);
+	if (!reg32) {
+		reg32 = fdtdec_get_int(blob, node, "panel-power-down-delay", 0)
+				<< 16;
+		reg32 |= fdtdec_get_int(blob, node,
+					"panel-power-backlight-off-delay", 0);
+		gtt_write(gtt_bar, 0xc720c, reg32);
+	}
+
+	/* Setup Panel Power Cycle Delay */
+	cycle_delay = fdtdec_get_int(blob, node,
+				     "intel,panel-power-cycle-delay", 0);
+	if (cycle_delay) {
+		reg32 = gtt_read(gtt_bar, 0xc7210);
+		reg32 &= ~0xff;
+		reg32 |= cycle_delay;
+		gtt_write(gtt_bar, 0xc7210, reg32);
+	}
+
+	/* Enable Backlight if needed */
+	reg32 = fdtdec_get_int(blob, node, "intel,cpu-backlight", 0);
+	if (reg32) {
+		gtt_write(gtt_bar, 0x48250, (1 << 31));
+		gtt_write(gtt_bar, 0x48254, reg32);
+	}
+	reg32 = fdtdec_get_int(blob, node, "intel,pch-backlight", 0);
+	if (reg32) {
+		gtt_write(gtt_bar, 0xc8250, (1 << 31));
+		gtt_write(gtt_bar, 0xc8254, reg32);
+	}
+
+	return 0;
+}
+
+/*
+ * Some vga option roms are used for several chipsets but they only have one
+ * PCI ID in their header. If we encounter such an option rom, we need to do
+ * the mapping ourselves.
+ */
+
+uint32_t board_map_oprom_vendev(uint32_t vendev)
+{
+	switch (vendev) {
+	case 0x80860102:		/* GT1 Desktop */
+	case 0x8086010a:		/* GT1 Server */
+	case 0x80860112:		/* GT2 Desktop */
+	case 0x80860116:		/* GT2 Mobile */
+	case 0x80860122:		/* GT2 Desktop >=1.3GHz */
+	case 0x80860126:		/* GT2 Mobile >=1.3GHz */
+	case 0x80860156:                /* IVB */
+	case 0x80860166:                /* IVB */
+		return 0x80860106;	/* GT1 Mobile */
+	}
+
+	return vendev;
+}
+
+static int int15_handler(void)
+{
+	int res = 0;
+
+	debug("%s: INT15 function %04x!\n", __func__, M.x86.R_AX);
+
+	switch (M.x86.R_AX) {
+	case 0x5f34:
+		/*
+		 * Set Panel Fitting Hook:
+		 *  bit 2 = Graphics Stretching
+		 *  bit 1 = Text Stretching
+		 *  bit 0 = Centering (do not set with bit1 or bit2)
+		 *  0     = video bios default
+		 */
+		M.x86.R_AX = 0x005f;
+		M.x86.R_CL = 0x00; /* Use video bios default */
+		res = 1;
+		break;
+	case 0x5f35:
+		/*
+		 * Boot Display Device Hook:
+		 *  bit 0 = CRT
+		 *  bit 1 = TV (eDP)
+		 *  bit 2 = EFP
+		 *  bit 3 = LFP
+		 *  bit 4 = CRT2
+		 *  bit 5 = TV2 (eDP)
+		 *  bit 6 = EFP2
+		 *  bit 7 = LFP2
+		 */
+		M.x86.R_AX = 0x005f;
+		M.x86.R_CX = 0x0000; /* Use video bios default */
+		res = 1;
+		break;
+	case 0x5f51:
+		/*
+		 * Hook to select active LFP configuration:
+		 *  00h = No LVDS, VBIOS does not enable LVDS
+		 *  01h = Int-LVDS, LFP driven by integrated LVDS decoder
+		 *  02h = SVDO-LVDS, LFP driven by SVDO decoder
+		 *  03h = eDP, LFP Driven by Int-DisplayPort encoder
+		 */
+		M.x86.R_AX = 0x005f;
+		M.x86.R_CX = 0x0003; /* eDP */
+		res = 1;
+		break;
+	case 0x5f70:
+		switch (M.x86.R_CH) {
+		case 0:
+			/* Get Mux */
+			M.x86.R_AX = 0x005f;
+			M.x86.R_CX = 0x0000;
+			res = 1;
+			break;
+		case 1:
+			/* Set Mux */
+			M.x86.R_AX = 0x005f;
+			M.x86.R_CX = 0x0000;
+			res = 1;
+			break;
+		case 2:
+			/* Get SG/Non-SG mode */
+			M.x86.R_AX = 0x005f;
+			M.x86.R_CX = 0x0000;
+			res = 1;
+			break;
+		default:
+			/* Interrupt was not handled */
+			debug("Unknown INT15 5f70 function: 0x%02x\n",
+			      M.x86.R_CH);
+			break;
+		}
+		break;
+	case 0x5fac:
+		res = 1;
+		break;
+	default:
+		debug("Unknown INT15 function %04x!\n", M.x86.R_AX);
+		break;
+	}
+	return res;
+}
+
+int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
+		   const void *blob, int node)
+{
+	void *gtt_bar;
+	u32 reg32;
+	int ret;
+
+	/* IGD needs to be Bus Master */
+	reg32 = pci_read_config32(dev, PCI_COMMAND);
+	reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+	pci_write_config32(dev, PCI_COMMAND, reg32);
+
+	gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0);
+	debug("GT bar %p\n", gtt_bar);
+	ret = gma_pm_init_pre_vbios(gtt_bar);
+	if (ret)
+		return ret;
+
+	ret = pci_run_vga_bios(dev, int15_handler, false);
+
+	/* Post VBIOS init */
+	ret = gma_pm_init_post_vbios(gtt_bar, blob, node);
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/gma.h b/arch/x86/cpu/ivybridge/gma.h
new file mode 100644
index 0000000..e7ec649
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/gma.h
@@ -0,0 +1,156 @@
+/*
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2012 Chromium OS Authors
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+/* mailbox 0: header */
+__packed struct opregion_header {
+	u8	signature[16];
+	u32	size;
+	u32	version;
+	u8	sbios_version[32];
+	u8	vbios_version[16];
+	u8	driver_version[16];
+	u32	mailboxes;
+	u8	reserved[164];
+};
+
+#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
+#define IGD_OPREGION_VERSION  2
+
+#define IGD_MBOX1	(1 << 0)
+#define IGD_MBOX2	(1 << 1)
+#define IGD_MBOX3	(1 << 2)
+#define IGD_MBOX4	(1 << 3)
+#define IGD_MBOX5	(1 << 4)
+
+#define MAILBOXES_MOBILE  (IGD_MBOX1 | IGD_MBOX2 | IGD_MBOX3 | \
+			   IGD_MBOX4 | IGD_MBOX5)
+#define MAILBOXES_DESKTOP (IGD_MBOX2 | IGD_MBOX4)
+
+#define SBIOS_VERSION_SIZE 32
+
+/* mailbox 1: public acpi methods */
+__packed struct opregion_mailbox1 {
+	u32	drdy;
+	u32	csts;
+	u32	cevt;
+	u8	reserved1[20];
+	u32	didl[8];
+	u32	cpdl[8];
+	u32	cadl[8];
+	u32	nadl[8];
+	u32	aslp;
+	u32	tidx;
+	u32	chpd;
+	u32	clid;
+	u32	cdck;
+	u32	sxsw;
+	u32	evts;
+	u32	cnot;
+	u32	nrdy;
+	u8	reserved2[60];
+};
+
+/* mailbox 2: software sci interface */
+__packed struct opregion_mailbox2 {
+	u32	scic;
+	u32	parm;
+	u32	dslp;
+	u8	reserved[244];
+};
+
+/* mailbox 3: power conservation */
+__packed struct opregion_mailbox3 {
+	u32	ardy;
+	u32	aslc;
+	u32	tche;
+	u32	alsi;
+	u32	bclp;
+	u32	pfit;
+	u32	cblv;
+	u16	bclm[20];
+	u32	cpfm;
+	u32	epfm;
+	u8	plut[74];
+	u32	pfmb;
+	u32	ccdv;
+	u32	pcft;
+	u8	reserved[94];
+};
+
+#define IGD_BACKLIGHT_BRIGHTNESS 0xff
+#define IGD_INITIAL_BRIGHTNESS 0x64
+
+#define IGD_FIELD_VALID	(1 << 31)
+#define IGD_WORD_FIELD_VALID (1 << 15)
+#define IGD_PFIT_STRETCH 6
+
+/* mailbox 4: vbt */
+__packed struct {
+	u8 gvd1[7168];
+} opregion_vbt_t;
+
+/* IGD OpRegion */
+__packed struct igd_opregion {
+	opregion_header_t header;
+	opregion_mailbox1_t mailbox1;
+	opregion_mailbox2_t mailbox2;
+	opregion_mailbox3_t mailbox3;
+	opregion_vbt_t vbt;
+};
+
+/* Intel Video BIOS (Option ROM) */
+__packed struct optionrom_header {
+	u16	signature;
+	u8	size;
+	u8	reserved[21];
+	u16	pcir_offset;
+	u16	vbt_offset;
+};
+
+#define OPROM_SIGNATURE 0xaa55
+
+__packed struct optionrom_pcir {
+	u32 signature;
+	u16 vendor;
+	u16 device;
+	u16 reserved1;
+	u16 length;
+	u8  revision;
+	u8  classcode[3];
+	u16 imagelength;
+	u16 coderevision;
+	u8  codetype;
+	u8  indicator;
+	u16 reserved2;
+};
+
+__packed struct optionrom_vbt {
+	u8  hdr_signature[20];
+	u16 hdr_version;
+	u16 hdr_size;
+	u16 hdr_vbt_size;
+	u8  hdr_vbt_checksum;
+	u8  hdr_reserved;
+	u32 hdr_vbt_datablock;
+	u32 hdr_aim[4];
+	u8  datahdr_signature[16];
+	u16 datahdr_version;
+	u16 datahdr_size;
+	u16 datahdr_datablocksize;
+	u8  coreblock_id;
+	u16 coreblock_size;
+	u16 coreblock_biossize;
+	u8  coreblock_biostype;
+	u8  coreblock_releasestatus;
+	u8  coreblock_hwsupported;
+	u8  coreblock_integratedhw;
+	u8  coreblock_biosbuild[4];
+	u8  coreblock_biossignon[155];
+};
+
+#define VBT_SIGNATURE 0x54425624
diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c
index 621ef2c..43fdd31 100644
--- a/arch/x86/cpu/ivybridge/lpc.c
+++ b/arch/x86/cpu/ivybridge/lpc.c
@@ -9,10 +9,460 @@
 #include <common.h>
 #include <errno.h>
 #include <fdtdec.h>
+#include <rtc.h>
 #include <pci.h>
+#include <asm/acpi.h>
+#include <asm/interrupt.h>
+#include <asm/io.h>
+#include <asm/ioapic.h>
 #include <asm/pci.h>
 #include <asm/arch/pch.h>
 
+#define NMI_OFF				0
+
+#define ENABLE_ACPI_MODE_IN_COREBOOT	0
+#define TEST_SMM_FLASH_LOCKDOWN		0
+
+static int pch_enable_apic(pci_dev_t dev)
+{
+	u32 reg32;
+	int i;
+
+	/* Enable ACPI I/O and power management. Set SCI IRQ to IRQ9 */
+	pci_write_config8(dev, ACPI_CNTL, 0x80);
+
+	writel(0, IO_APIC_INDEX);
+	writel(1 << 25, IO_APIC_DATA);
+
+	/* affirm full set of redirection table entries ("write once") */
+	writel(1, IO_APIC_INDEX);
+	reg32 = readl(IO_APIC_DATA);
+	writel(1, IO_APIC_INDEX);
+	writel(reg32, IO_APIC_DATA);
+
+	writel(0, IO_APIC_INDEX);
+	reg32 = readl(IO_APIC_DATA);
+	debug("PCH APIC ID = %x\n", (reg32 >> 24) & 0x0f);
+	if (reg32 != (1 << 25)) {
+		printf("APIC Error - cannot write to registers\n");
+		return -EPERM;
+	}
+
+	debug("Dumping IOAPIC registers\n");
+	for (i = 0;  i < 3; i++) {
+		writel(i, IO_APIC_INDEX);
+		debug("  reg 0x%04x:", i);
+		reg32 = readl(IO_APIC_DATA);
+		debug(" 0x%08x\n", reg32);
+	}
+
+	/* Select Boot Configuration register. */
+	writel(3, IO_APIC_INDEX);
+
+	/* Use Processor System Bus to deliver interrupts. */
+	writel(1, IO_APIC_DATA);
+
+	return 0;
+}
+
+static void pch_enable_serial_irqs(pci_dev_t dev)
+{
+	u32 value;
+
+	/* Set packet length and toggle silent mode bit for one frame. */
+	value = (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0);
+#ifdef CONFIG_SERIRQ_CONTINUOUS_MODE
+	pci_write_config8(dev, SERIRQ_CNTL, value);
+#else
+	pci_write_config8(dev, SERIRQ_CNTL, value | (1 << 6));
+#endif
+}
+
+static int pch_pirq_init(const void *blob, int node, pci_dev_t dev)
+{
+	uint8_t route[8], *ptr;
+
+	if (fdtdec_get_byte_array(blob, node, "intel,pirq-routing", route,
+				  sizeof(route)))
+		return -EINVAL;
+	ptr = route;
+	pci_write_config8(dev, PIRQA_ROUT, *ptr++);
+	pci_write_config8(dev, PIRQB_ROUT, *ptr++);
+	pci_write_config8(dev, PIRQC_ROUT, *ptr++);
+	pci_write_config8(dev, PIRQD_ROUT, *ptr++);
+
+	pci_write_config8(dev, PIRQE_ROUT, *ptr++);
+	pci_write_config8(dev, PIRQF_ROUT, *ptr++);
+	pci_write_config8(dev, PIRQG_ROUT, *ptr++);
+	pci_write_config8(dev, PIRQH_ROUT, *ptr++);
+
+	/*
+	 * TODO(sjg@chromium.org): U-Boot does not set up the interrupts
+	 * here. It's unclear if it is needed
+	 */
+	return 0;
+}
+
+static int pch_gpi_routing(const void *blob, int node, pci_dev_t dev)
+{
+	u8 route[16];
+	u32 reg;
+	int gpi;
+
+	if (fdtdec_get_byte_array(blob, node, "intel,gpi-routing", route,
+				  sizeof(route)))
+		return -EINVAL;
+
+	for (reg = 0, gpi = 0; gpi < ARRAY_SIZE(route); gpi++)
+		reg |= route[gpi] << (gpi * 2);
+
+	pci_write_config32(dev, 0xb8, reg);
+
+	return 0;
+}
+
+static int pch_power_options(const void *blob, int node, pci_dev_t dev)
+{
+	u8 reg8;
+	u16 reg16, pmbase;
+	u32 reg32;
+	const char *state;
+	int pwr_on;
+	int nmi_option;
+	int ret;
+
+	/*
+	 * Which state do we want to goto after g3 (power restored)?
+	 * 0 == S0 Full On
+	 * 1 == S5 Soft Off
+	 *
+	 * If the option is not existent (Laptops), use Kconfig setting.
+	 * TODO(sjg@chromium.org): Make this configurable
+	 */
+	pwr_on = MAINBOARD_POWER_ON;
+
+	reg16 = pci_read_config16(dev, GEN_PMCON_3);
+	reg16 &= 0xfffe;
+	switch (pwr_on) {
+	case MAINBOARD_POWER_OFF:
+		reg16 |= 1;
+		state = "off";
+		break;
+	case MAINBOARD_POWER_ON:
+		reg16 &= ~1;
+		state = "on";
+		break;
+	case MAINBOARD_POWER_KEEP:
+		reg16 &= ~1;
+		state = "state keep";
+		break;
+	default:
+		state = "undefined";
+	}
+
+	reg16 &= ~(3 << 4);	/* SLP_S4# Assertion Stretch 4s */
+	reg16 |= (1 << 3);	/* SLP_S4# Assertion Stretch Enable */
+
+	reg16 &= ~(1 << 10);
+	reg16 |= (1 << 11);	/* SLP_S3# Min Assertion Width 50ms */
+
+	reg16 |= (1 << 12);	/* Disable SLP stretch after SUS well */
+
+	pci_write_config16(dev, GEN_PMCON_3, reg16);
+	debug("Set power %s after power failure.\n", state);
+
+	/* Set up NMI on errors. */
+	reg8 = inb(0x61);
+	reg8 &= 0x0f;		/* Higher Nibble must be 0 */
+	reg8 &= ~(1 << 3);	/* IOCHK# NMI Enable */
+	reg8 |= (1 << 2); /* PCI SERR# Disable for now */
+	outb(reg8, 0x61);
+
+	reg8 = inb(0x70);
+	/* TODO(sjg@chromium.org): Make this configurable */
+	nmi_option = NMI_OFF;
+	if (nmi_option) {
+		debug("NMI sources enabled.\n");
+		reg8 &= ~(1 << 7);	/* Set NMI. */
+	} else {
+		debug("NMI sources disabled.\n");
+		/* Can't mask NMI from PCI-E and NMI_NOW */
+		reg8 |= (1 << 7);
+	}
+	outb(reg8, 0x70);
+
+	/* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
+	reg16 = pci_read_config16(dev, GEN_PMCON_1);
+	reg16 &= ~(3 << 0);	/* SMI# rate 1 minute */
+	reg16 &= ~(1 << 10);	/* Disable BIOS_PCI_EXP_EN for native PME */
+#if DEBUG_PERIODIC_SMIS
+	/* Set DEBUG_PERIODIC_SMIS in pch.h to debug using periodic SMIs */
+	reg16 |= (3 << 0);	/* Periodic SMI every 8s */
+#endif
+	pci_write_config16(dev, GEN_PMCON_1, reg16);
+
+	/* Set the board's GPI routing. */
+	ret = pch_gpi_routing(blob, node, dev);
+	if (ret)
+		return ret;
+
+	pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
+
+	writel(pmbase + GPE0_EN, fdtdec_get_int(blob, node,
+						"intel,gpe0-enable", 0));
+	writew(pmbase + ALT_GP_SMI_EN, fdtdec_get_int(blob, node,
+						"intel,alt-gp-smi-enable", 0));
+
+	/* Set up power management block and determine sleep mode */
+	reg32 = inl(pmbase + 0x04); /* PM1_CNT */
+	reg32 &= ~(7 << 10);	/* SLP_TYP */
+	reg32 |= (1 << 0);	/* SCI_EN */
+	outl(reg32, pmbase + 0x04);
+
+	/* Clear magic status bits to prevent unexpected wake */
+	setbits_le32(RCB_REG(0x3310), (1 << 4) | (1 << 5) | (1 << 0));
+	clrbits_le32(RCB_REG(0x3f02), 0xf);
+
+	return 0;
+}
+
+static void pch_rtc_init(pci_dev_t dev)
+{
+	int rtc_failed;
+	u8 reg8;
+
+	reg8 = pci_read_config8(dev, GEN_PMCON_3);
+	rtc_failed = reg8 & RTC_BATTERY_DEAD;
+	if (rtc_failed) {
+		reg8 &= ~RTC_BATTERY_DEAD;
+		pci_write_config8(dev, GEN_PMCON_3, reg8);
+	}
+	debug("rtc_failed = 0x%x\n", rtc_failed);
+
+#if CONFIG_HAVE_ACPI_RESUME
+	/* Avoid clearing pending interrupts and resetting the RTC control
+	 * register in the resume path because the Linux kernel relies on
+	 * this to know if it should restart the RTC timerqueue if the wake
+	 * was due to the RTC alarm.
+	 */
+	if (acpi_get_slp_type() == 3)
+		return;
+#endif
+	/* TODO: Handle power failure */
+	if (rtc_failed)
+		printf("RTC power failed\n");
+	rtc_init();
+}
+
+/* CougarPoint PCH Power Management init */
+static void cpt_pm_init(pci_dev_t dev)
+{
+	debug("CougarPoint PM init\n");
+	pci_write_config8(dev, 0xa9, 0x47);
+	setbits_le32(RCB_REG(0x2238), (1 << 6) | (1 << 0));
+
+	setbits_le32(RCB_REG(0x228c), 1 << 0);
+	setbits_le32(RCB_REG(0x1100), (1 << 13) | (1 << 14));
+	setbits_le32(RCB_REG(0x0900), 1 << 14);
+	writel(0xc0388400, RCB_REG(0x2304));
+	setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18));
+	setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1));
+	clrsetbits_le32(RCB_REG(0x3314), ~0x1f, 0xf);
+	writel(0x050f0000, RCB_REG(0x3318));
+	writel(0x04000000, RCB_REG(0x3324));
+	setbits_le32(RCB_REG(0x3340), 0xfffff);
+	setbits_le32(RCB_REG(0x3344), 1 << 1);
+
+	writel(0x0001c000, RCB_REG(0x3360));
+	writel(0x00061100, RCB_REG(0x3368));
+	writel(0x7f8fdfff, RCB_REG(0x3378));
+	writel(0x000003fc, RCB_REG(0x337c));
+	writel(0x00001000, RCB_REG(0x3388));
+	writel(0x0001c000, RCB_REG(0x3390));
+	writel(0x00000800, RCB_REG(0x33a0));
+	writel(0x00001000, RCB_REG(0x33b0));
+	writel(0x00093900, RCB_REG(0x33c0));
+	writel(0x24653002, RCB_REG(0x33cc));
+	writel(0x062108fe, RCB_REG(0x33d0));
+	clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060);
+	writel(0x01010000, RCB_REG(0x3a28));
+	writel(0x01010404, RCB_REG(0x3a2c));
+	writel(0x01041041, RCB_REG(0x3a80));
+	clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001);
+	setbits_le32(RCB_REG(0x3a84), 1 << 24); /* SATA 2/3 disabled */
+	setbits_le32(RCB_REG(0x3a88), 1 << 0);  /* SATA 4/5 disabled */
+	writel(0x00000001, RCB_REG(0x3a6c));
+	clrsetbits_le32(RCB_REG(0x2344), ~0x00ffff00, 0xff00000c);
+	clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20);
+	writel(0, RCB_REG(0x33c8));
+	setbits_le32(RCB_REG(0x21b0), 0xf);
+}
+
+/* PantherPoint PCH Power Management init */
+static void ppt_pm_init(pci_dev_t dev)
+{
+	debug("PantherPoint PM init\n");
+	pci_write_config8(dev, 0xa9, 0x47);
+	setbits_le32(RCB_REG(0x2238), 1 << 0);
+	setbits_le32(RCB_REG(0x228c), 1 << 0);
+	setbits_le16(RCB_REG(0x1100), (1 << 13) | (1 << 14));
+	setbits_le16(RCB_REG(0x0900), 1 << 14);
+	writel(0xc03b8400, RCB_REG(0x2304));
+	setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18));
+	setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1));
+	clrsetbits_le32(RCB_REG(0x3314), 0x1f, 0xf);
+	writel(0x054f0000, RCB_REG(0x3318));
+	writel(0x04000000, RCB_REG(0x3324));
+	setbits_le32(RCB_REG(0x3340), 0xfffff);
+	setbits_le32(RCB_REG(0x3344), (1 << 1) | (1 << 0));
+	writel(0x0001c000, RCB_REG(0x3360));
+	writel(0x00061100, RCB_REG(0x3368));
+	writel(0x7f8fdfff, RCB_REG(0x3378));
+	writel(0x000003fd, RCB_REG(0x337c));
+	writel(0x00001000, RCB_REG(0x3388));
+	writel(0x0001c000, RCB_REG(0x3390));
+	writel(0x00000800, RCB_REG(0x33a0));
+	writel(0x00001000, RCB_REG(0x33b0));
+	writel(0x00093900, RCB_REG(0x33c0));
+	writel(0x24653002, RCB_REG(0x33cc));
+	writel(0x067388fe, RCB_REG(0x33d0));
+	clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060);
+	writel(0x01010000, RCB_REG(0x3a28));
+	writel(0x01010404, RCB_REG(0x3a2c));
+	writel(0x01040000, RCB_REG(0x3a80));
+	clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001);
+	/* SATA 2/3 disabled */
+	setbits_le32(RCB_REG(0x3a84), 1 << 24);
+	/* SATA 4/5 disabled */
+	setbits_le32(RCB_REG(0x3a88), 1 << 0);
+	writel(0x00000001, RCB_REG(0x3a6c));
+	clrsetbits_le32(RCB_REG(0x2344), 0xff0000ff, 0xff00000c);
+	clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20);
+	setbits_le32(RCB_REG(0x33a4), (1 << 0));
+	writel(0, RCB_REG(0x33c8));
+	setbits_le32(RCB_REG(0x21b0), 0xf);
+}
+
+static void enable_hpet(void)
+{
+	/* Move HPET to default address 0xfed00000 and enable it */
+	clrsetbits_le32(RCB_REG(HPTC), 3 << 0, 1 << 7);
+}
+
+static void enable_clock_gating(pci_dev_t dev)
+{
+	u32 reg32;
+	u16 reg16;
+
+	setbits_le32(RCB_REG(0x2234), 0xf);
+
+	reg16 = pci_read_config16(dev, GEN_PMCON_1);
+	reg16 |= (1 << 2) | (1 << 11);
+	pci_write_config16(dev, GEN_PMCON_1, reg16);
+
+	pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
+	pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
+	pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
+	pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
+
+	reg32 = readl(RCB_REG(CG));
+	reg32 |= (1 << 31);
+	reg32 |= (1 << 29) | (1 << 28);
+	reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
+	reg32 |= (1 << 16);
+	reg32 |= (1 << 17);
+	reg32 |= (1 << 18);
+	reg32 |= (1 << 22);
+	reg32 |= (1 << 23);
+	reg32 &= ~(1 << 20);
+	reg32 |= (1 << 19);
+	reg32 |= (1 << 0);
+	reg32 |= (0xf << 1);
+	writel(reg32, RCB_REG(CG));
+
+	setbits_le32(RCB_REG(0x38c0), 0x7);
+	setbits_le32(RCB_REG(0x36d4), 0x6680c004);
+	setbits_le32(RCB_REG(0x3564), 0x3);
+}
+
+#if CONFIG_HAVE_SMI_HANDLER
+static void pch_lock_smm(pci_dev_t dev)
+{
+#if TEST_SMM_FLASH_LOCKDOWN
+	u8 reg8;
+#endif
+
+	if (acpi_slp_type != 3) {
+#if ENABLE_ACPI_MODE_IN_COREBOOT
+		debug("Enabling ACPI via APMC:\n");
+		outb(0xe1, 0xb2); /* Enable ACPI mode */
+		debug("done.\n");
+#else
+		debug("Disabling ACPI via APMC:\n");
+		outb(0x1e, 0xb2); /* Disable ACPI mode */
+		debug("done.\n");
+#endif
+	}
+
+	/* Don't allow evil boot loaders, kernels, or
+	 * userspace applications to deceive us:
+	 */
+	smm_lock();
+
+#if TEST_SMM_FLASH_LOCKDOWN
+	/* Now try this: */
+	debug("Locking BIOS to RO... ");
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off",
+	      (reg8 & 1) ? "rw" : "ro");
+	reg8 &= ~(1 << 0);			/* clear BIOSWE */
+	pci_write_config8(dev, 0xdc, reg8);
+	reg8 |= (1 << 1);			/* set BLE */
+	pci_write_config8(dev, 0xdc, reg8);
+	debug("ok.\n");
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off",
+	      (reg8 & 1) ? "rw" : "ro");
+
+	debug("Writing:\n");
+	writeb(0, 0xfff00000);
+	debug("Testing:\n");
+	reg8 |= (1 << 0);			/* set BIOSWE */
+	pci_write_config8(dev, 0xdc, reg8);
+
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off",
+	      (reg8 & 1) ? "rw" : "ro");
+	debug("Done.\n");
+#endif
+}
+#endif
+
+static void pch_disable_smm_only_flashing(pci_dev_t dev)
+{
+	u8 reg8;
+
+	debug("Enabling BIOS updates outside of SMM... ");
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	reg8 &= ~(1 << 5);
+	pci_write_config8(dev, 0xdc, reg8);
+}
+
+static void pch_fixups(pci_dev_t dev)
+{
+	u8 gen_pmcon_2;
+
+	/* Indicate DRAM init done for MRC S3 to know it can resume */
+	gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
+	gen_pmcon_2 |= (1 << 7);
+	pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
+
+	/* Enable DMI ASPM in the PCH */
+	clrbits_le32(RCB_REG(0x2304), 1 << 10);
+	setbits_le32(RCB_REG(0x21a4), (1 << 11) | (1 << 10));
+	setbits_le32(RCB_REG(0x21a8), 0x3);
+}
+
 int lpc_early_init(const void *blob, int node, pci_dev_t dev)
 {
 	struct reg_info {
@@ -22,7 +472,7 @@
 	int count;
 	int i;
 
-	count = fdtdec_get_int_array_count(blob, node, "gen-dec",
+	count = fdtdec_get_int_array_count(blob, node, "intel,gen-dec",
 			(u32 *)values, sizeof(values) / sizeof(u32));
 	if (count < 0)
 		return -EINVAL;
@@ -46,3 +496,74 @@
 
 	return 0;
 }
+
+int lpc_init(struct pci_controller *hose, pci_dev_t dev)
+{
+	const void *blob = gd->fdt_blob;
+	int node;
+
+	debug("pch: lpc_init\n");
+	pci_write_bar32(hose, dev, 0, 0);
+	pci_write_bar32(hose, dev, 1, 0xff800000);
+	pci_write_bar32(hose, dev, 2, 0xfec00000);
+	pci_write_bar32(hose, dev, 3, 0x800);
+	pci_write_bar32(hose, dev, 4, 0x900);
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC);
+	if (node < 0)
+		return -ENOENT;
+
+	/* Set the value for PCI command register. */
+	pci_write_config16(dev, PCI_COMMAND, 0x000f);
+
+	/* IO APIC initialization. */
+	pch_enable_apic(dev);
+
+	pch_enable_serial_irqs(dev);
+
+	/* Setup the PIRQ. */
+	pch_pirq_init(blob, node, dev);
+
+	/* Setup power options. */
+	pch_power_options(blob, node, dev);
+
+	/* Initialize power management */
+	switch (pch_silicon_type()) {
+	case PCH_TYPE_CPT: /* CougarPoint */
+		cpt_pm_init(dev);
+		break;
+	case PCH_TYPE_PPT: /* PantherPoint */
+		ppt_pm_init(dev);
+		break;
+	default:
+		printf("Unknown Chipset: %#02x.%dx\n", PCI_DEV(dev),
+		       PCI_FUNC(dev));
+		return -ENOSYS;
+	}
+
+	/* Initialize the real time clock. */
+	pch_rtc_init(dev);
+
+	/* Initialize the High Precision Event Timers, if present. */
+	enable_hpet();
+
+	/* Initialize Clock Gating */
+	enable_clock_gating(dev);
+
+	pch_disable_smm_only_flashing(dev);
+
+#if CONFIG_HAVE_SMI_HANDLER
+	pch_lock_smm(dev);
+#endif
+
+	pch_fixups(dev);
+
+	return 0;
+}
+
+void lpc_enable(pci_dev_t dev)
+{
+	/* Enable PCH Display Port */
+	writew(0x0010, RCB_REG(DISPBDF));
+	setbits_le32(RCB_REG(FD2), PCH_ENABLE_DBDF);
+}
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
new file mode 100644
index 0000000..11dc625
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -0,0 +1,514 @@
+/*
+ * From Coreboot file of same name
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The Chromium Authors
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#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/model_206ax.h>
+
+static void enable_vmx(void)
+{
+	struct cpuid_result regs;
+#ifdef CONFIG_ENABLE_VMX
+	int enable = true;
+#else
+	int enable = false;
+#endif
+	msr_t msr;
+
+	regs = cpuid(1);
+	/* Check that the VMX is supported before reading or writing the MSR. */
+	if (!((regs.ecx & CPUID_VMX) || (regs.ecx & CPUID_SMX)))
+		return;
+
+	msr = msr_read(MSR_IA32_FEATURE_CONTROL);
+
+	if (msr.lo & (1 << 0)) {
+		debug("VMX is locked, so %s will do nothing\n", __func__);
+		/* VMX locked. If we set it again we get an illegal
+		 * instruction
+		 */
+		return;
+	}
+
+	/* The IA32_FEATURE_CONTROL MSR may initialize with random values.
+	 * It must be cleared regardless of VMX config setting.
+	 */
+	msr.hi = 0;
+	msr.lo = 0;
+
+	debug("%s VMX\n", enable ? "Enabling" : "Disabling");
+
+	/*
+	 * Even though the Intel manual says you must set the lock bit in
+	 * addition to the VMX bit in order for VMX to work, it is incorrect.
+	 * Thus we leave it unlocked for the OS to manage things itself.
+	 * This is good for a few reasons:
+	 * - No need to reflash the bios just to toggle the lock bit.
+	 * - The VMX bits really really should match each other across cores,
+	 *   so hard locking it on one while another has the opposite setting
+	 *   can easily lead to crashes as code using VMX migrates between
+	 *   them.
+	 * - Vendors that want to "upsell" from a bios that disables+locks to
+	 *   one that doesn't is sleazy.
+	 * By leaving this to the OS (e.g. Linux), people can do exactly what
+	 * they want on the fly, and do it correctly (e.g. across multiple
+	 * cores).
+	 */
+	if (enable) {
+		msr.lo |= (1 << 2);
+		if (regs.ecx & CPUID_SMX)
+			msr.lo |= (1 << 1);
+	}
+
+	msr_write(MSR_IA32_FEATURE_CONTROL, msr);
+}
+
+/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
+static const u8 power_limit_time_sec_to_msr[] = {
+	[0]   = 0x00,
+	[1]   = 0x0a,
+	[2]   = 0x0b,
+	[3]   = 0x4b,
+	[4]   = 0x0c,
+	[5]   = 0x2c,
+	[6]   = 0x4c,
+	[7]   = 0x6c,
+	[8]   = 0x0d,
+	[10]  = 0x2d,
+	[12]  = 0x4d,
+	[14]  = 0x6d,
+	[16]  = 0x0e,
+	[20]  = 0x2e,
+	[24]  = 0x4e,
+	[28]  = 0x6e,
+	[32]  = 0x0f,
+	[40]  = 0x2f,
+	[48]  = 0x4f,
+	[56]  = 0x6f,
+	[64]  = 0x10,
+	[80]  = 0x30,
+	[96]  = 0x50,
+	[112] = 0x70,
+	[128] = 0x11,
+};
+
+/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
+static const u8 power_limit_time_msr_to_sec[] = {
+	[0x00] = 0,
+	[0x0a] = 1,
+	[0x0b] = 2,
+	[0x4b] = 3,
+	[0x0c] = 4,
+	[0x2c] = 5,
+	[0x4c] = 6,
+	[0x6c] = 7,
+	[0x0d] = 8,
+	[0x2d] = 10,
+	[0x4d] = 12,
+	[0x6d] = 14,
+	[0x0e] = 16,
+	[0x2e] = 20,
+	[0x4e] = 24,
+	[0x6e] = 28,
+	[0x0f] = 32,
+	[0x2f] = 40,
+	[0x4f] = 48,
+	[0x6f] = 56,
+	[0x10] = 64,
+	[0x30] = 80,
+	[0x50] = 96,
+	[0x70] = 112,
+	[0x11] = 128,
+};
+
+int cpu_config_tdp_levels(void)
+{
+	struct cpuid_result result;
+	msr_t platform_info;
+
+	/* Minimum CPU revision */
+	result = cpuid(1);
+	if (result.eax < IVB_CONFIG_TDP_MIN_CPUID)
+		return 0;
+
+	/* Bits 34:33 indicate how many levels supported */
+	platform_info = msr_read(MSR_PLATFORM_INFO);
+	return (platform_info.hi >> 1) & 3;
+}
+
+/*
+ * Configure processor power limits if possible
+ * This must be done AFTER set of BIOS_RESET_CPL
+ */
+void set_power_limits(u8 power_limit_1_time)
+{
+	msr_t msr = msr_read(MSR_PLATFORM_INFO);
+	msr_t limit;
+	unsigned power_unit;
+	unsigned tdp, min_power, max_power, max_time;
+	u8 power_limit_1_val;
+
+	if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
+		return;
+
+	if (!(msr.lo & PLATFORM_INFO_SET_TDP))
+		return;
+
+	/* Get units */
+	msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
+	power_unit = 2 << ((msr.lo & 0xf) - 1);
+
+	/* Get power defaults for this SKU */
+	msr = msr_read(MSR_PKG_POWER_SKU);
+	tdp = msr.lo & 0x7fff;
+	min_power = (msr.lo >> 16) & 0x7fff;
+	max_power = msr.hi & 0x7fff;
+	max_time = (msr.hi >> 16) & 0x7f;
+
+	debug("CPU TDP: %u Watts\n", tdp / power_unit);
+
+	if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
+		power_limit_1_time = power_limit_time_msr_to_sec[max_time];
+
+	if (min_power > 0 && tdp < min_power)
+		tdp = min_power;
+
+	if (max_power > 0 && tdp > max_power)
+		tdp = max_power;
+
+	power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
+
+	/* Set long term power limit to TDP */
+	limit.lo = 0;
+	limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
+	limit.lo |= PKG_POWER_LIMIT_EN;
+	limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
+		PKG_POWER_LIMIT_TIME_SHIFT;
+
+	/* Set short term power limit to 1.25 * TDP */
+	limit.hi = 0;
+	limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
+	limit.hi |= PKG_POWER_LIMIT_EN;
+	/* Power limit 2 time is only programmable on SNB EP/EX */
+
+	msr_write(MSR_PKG_POWER_LIMIT, limit);
+
+	/* Use nominal TDP values for CPUs with configurable TDP */
+	if (cpu_config_tdp_levels()) {
+		msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+		limit.hi = 0;
+		limit.lo = msr.lo & 0xff;
+		msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
+	}
+}
+
+static void configure_c_states(void)
+{
+	struct cpuid_result result;
+	msr_t msr;
+
+	msr = msr_read(MSR_PMG_CST_CONFIG_CTL);
+	msr.lo |= (1 << 28);	/* C1 Auto Undemotion Enable */
+	msr.lo |= (1 << 27);	/* C3 Auto Undemotion Enable */
+	msr.lo |= (1 << 26);	/* C1 Auto Demotion Enable */
+	msr.lo |= (1 << 25);	/* C3 Auto Demotion Enable */
+	msr.lo &= ~(1 << 10);	/* Disable IO MWAIT redirection */
+	msr.lo |= 7;		/* No package C-state limit */
+	msr_write(MSR_PMG_CST_CONFIG_CTL, msr);
+
+	msr = msr_read(MSR_PMG_IO_CAPTURE_ADR);
+	msr.lo &= ~0x7ffff;
+	msr.lo |= (PMB0_BASE + 4);	/* LVL_2 base address */
+	msr.lo |= (2 << 16);		/* CST Range: C7 is max C-state */
+	msr_write(MSR_PMG_IO_CAPTURE_ADR, msr);
+
+	msr = msr_read(MSR_MISC_PWR_MGMT);
+	msr.lo &= ~(1 << 0);	/* Enable P-state HW_ALL coordination */
+	msr_write(MSR_MISC_PWR_MGMT, msr);
+
+	msr = msr_read(MSR_POWER_CTL);
+	msr.lo |= (1 << 18);	/* Enable Energy Perf Bias MSR 0x1b0 */
+	msr.lo |= (1 << 1);	/* C1E Enable */
+	msr.lo |= (1 << 0);	/* Bi-directional PROCHOT# */
+	msr_write(MSR_POWER_CTL, msr);
+
+	/* C3 Interrupt Response Time Limit */
+	msr.hi = 0;
+	msr.lo = IRTL_VALID | IRTL_1024_NS | 0x50;
+	msr_write(MSR_PKGC3_IRTL, msr);
+
+	/* C6 Interrupt Response Time Limit */
+	msr.hi = 0;
+	msr.lo = IRTL_VALID | IRTL_1024_NS | 0x68;
+	msr_write(MSR_PKGC6_IRTL, msr);
+
+	/* C7 Interrupt Response Time Limit */
+	msr.hi = 0;
+	msr.lo = IRTL_VALID | IRTL_1024_NS | 0x6D;
+	msr_write(MSR_PKGC7_IRTL, msr);
+
+	/* Primary Plane Current Limit */
+	msr = msr_read(MSR_PP0_CURRENT_CONFIG);
+	msr.lo &= ~0x1fff;
+	msr.lo |= PP0_CURRENT_LIMIT;
+	msr_write(MSR_PP0_CURRENT_CONFIG, msr);
+
+	/* Secondary Plane Current Limit */
+	msr = msr_read(MSR_PP1_CURRENT_CONFIG);
+	msr.lo &= ~0x1fff;
+	result = cpuid(1);
+	if (result.eax >= 0x30600)
+		msr.lo |= PP1_CURRENT_LIMIT_IVB;
+	else
+		msr.lo |= PP1_CURRENT_LIMIT_SNB;
+	msr_write(MSR_PP1_CURRENT_CONFIG, msr);
+}
+
+static int configure_thermal_target(void)
+{
+	int tcc_offset;
+	msr_t msr;
+	int node;
+
+	/* Find pointer to CPU configuration */
+	node = fdtdec_next_compatible(gd->fdt_blob, 0,
+				      COMPAT_INTEL_MODEL_206AX);
+	if (node < 0)
+		return -ENOENT;
+	tcc_offset = fdtdec_get_int(gd->fdt_blob, node, "tcc-offset", 0);
+
+	/* Set TCC activaiton offset if supported */
+	msr = msr_read(MSR_PLATFORM_INFO);
+	if ((msr.lo & (1 << 30)) && tcc_offset) {
+		msr = msr_read(MSR_TEMPERATURE_TARGET);
+		msr.lo &= ~(0xf << 24); /* Bits 27:24 */
+		msr.lo |= (tcc_offset & 0xf) << 24;
+		msr_write(MSR_TEMPERATURE_TARGET, msr);
+	}
+
+	return 0;
+}
+
+static void configure_misc(void)
+{
+	msr_t msr;
+
+	msr = msr_read(IA32_MISC_ENABLE);
+	msr.lo |= (1 << 0);	  /* Fast String enable */
+	msr.lo |= (1 << 3);	  /* TM1/TM2/EMTTM enable */
+	msr.lo |= (1 << 16);	  /* Enhanced SpeedStep Enable */
+	msr_write(IA32_MISC_ENABLE, msr);
+
+	/* Disable Thermal interrupts */
+	msr.lo = 0;
+	msr.hi = 0;
+	msr_write(IA32_THERM_INTERRUPT, msr);
+
+	/* Enable package critical interrupt only */
+	msr.lo = 1 << 4;
+	msr.hi = 0;
+	msr_write(IA32_PACKAGE_THERM_INTERRUPT, msr);
+}
+
+static void enable_lapic_tpr(void)
+{
+	msr_t msr;
+
+	msr = msr_read(MSR_PIC_MSG_CONTROL);
+	msr.lo &= ~(1 << 10);	/* Enable APIC TPR updates */
+	msr_write(MSR_PIC_MSG_CONTROL, msr);
+}
+
+static void configure_dca_cap(void)
+{
+	struct cpuid_result cpuid_regs;
+	msr_t msr;
+
+	/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
+	cpuid_regs = cpuid(1);
+	if (cpuid_regs.ecx & (1 << 18)) {
+		msr = msr_read(IA32_PLATFORM_DCA_CAP);
+		msr.lo |= 1;
+		msr_write(IA32_PLATFORM_DCA_CAP, msr);
+	}
+}
+
+static void set_max_ratio(void)
+{
+	msr_t msr, perf_ctl;
+
+	perf_ctl.hi = 0;
+
+	/* Check for configurable TDP option */
+	if (cpu_config_tdp_levels()) {
+		/* Set to nominal TDP ratio */
+		msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+		perf_ctl.lo = (msr.lo & 0xff) << 8;
+	} else {
+		/* Platform Info bits 15:8 give max ratio */
+		msr = msr_read(MSR_PLATFORM_INFO);
+		perf_ctl.lo = msr.lo & 0xff00;
+	}
+	msr_write(IA32_PERF_CTL, perf_ctl);
+
+	debug("model_x06ax: frequency set to %d\n",
+	      ((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK);
+}
+
+static void set_energy_perf_bias(u8 policy)
+{
+	msr_t msr;
+
+	/* Energy Policy is bits 3:0 */
+	msr = msr_read(IA32_ENERGY_PERFORMANCE_BIAS);
+	msr.lo &= ~0xf;
+	msr.lo |= policy & 0xf;
+	msr_write(IA32_ENERGY_PERFORMANCE_BIAS, msr);
+
+	debug("model_x06ax: energy policy set to %u\n", policy);
+}
+
+static void configure_mca(void)
+{
+	msr_t msr;
+	int i;
+
+	msr.lo = 0;
+	msr.hi = 0;
+	/* This should only be done on a cold boot */
+	for (i = 0; i < 7; i++)
+		msr_write(IA32_MC0_STATUS + (i * 4), msr);
+}
+
+#if CONFIG_USBDEBUG
+static unsigned ehci_debug_addr;
+#endif
+
+/*
+ * Initialize any extra cores/threads in this package.
+ */
+static int intel_cores_init(struct x86_cpu_priv *cpu)
+{
+	struct cpuid_result result;
+	unsigned threads_per_package, threads_per_core, i;
+
+	/* Logical processors (threads) per core */
+	result = cpuid_ext(0xb, 0);
+	threads_per_core = result.ebx & 0xffff;
+
+	/* Logical processors (threads) per package */
+	result = cpuid_ext(0xb, 1);
+	threads_per_package = result.ebx & 0xffff;
+
+	debug("CPU: %u has %u cores, %u threads per core\n",
+	      cpu->apic_id, threads_per_package / threads_per_core,
+	      threads_per_core);
+
+	for (i = 1; i < threads_per_package; ++i) {
+		struct x86_cpu_priv *new_cpu;
+
+		new_cpu = calloc(1, sizeof(*new_cpu));
+		if (!new_cpu)
+			return -ENOMEM;
+
+		new_cpu->apic_id = cpu->apic_id + i;
+
+		/* Update APIC ID if no hyperthreading */
+		if (threads_per_core == 1)
+			new_cpu->apic_id <<= 1;
+
+		debug("CPU: %u has core %u\n", cpu->apic_id, new_cpu->apic_id);
+
+#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
+		/* Start the new cpu */
+		if (!start_cpu(new_cpu)) {
+			/* Record the error in cpu? */
+			printk(BIOS_ERR, "CPU %u would not start!\n",
+			       new_cpu->apic_id);
+			new_cpu->start_err = 1;
+		}
+#endif
+	}
+
+	return 0;
+}
+
+int model_206ax_init(struct x86_cpu_priv *cpu)
+{
+	int ret;
+
+	/* Clear out pending MCEs */
+	configure_mca();
+
+#if CONFIG_USBDEBUG
+	/* Is this caution really needed? */
+	if (!ehci_debug_addr)
+		ehci_debug_addr = get_ehci_debug();
+	set_ehci_debug(0);
+#endif
+
+	/* Setup MTRRs based on physical address size */
+#if 0 /* TODO: Implement this */
+	struct cpuid_result cpuid_regs;
+
+	cpuid_regs = cpuid(0x80000008);
+	x86_setup_fixed_mtrrs();
+	x86_setup_var_mtrrs(cpuid_regs.eax & 0xff, 2);
+	x86_mtrr_check();
+#endif
+
+#if CONFIG_USBDEBUG
+	set_ehci_debug(ehci_debug_addr);
+#endif
+
+	/* Enable the local cpu apics */
+	enable_lapic_tpr();
+	lapic_setup();
+
+	/* Enable virtualization if enabled in CMOS */
+	enable_vmx();
+
+	/* Configure C States */
+	configure_c_states();
+
+	/* Configure Enhanced SpeedStep and Thermal Sensors */
+	configure_misc();
+
+	/* Thermal throttle activation offset */
+	ret = configure_thermal_target();
+	if (ret)
+		return ret;
+
+	/* Enable Direct Cache Access */
+	configure_dca_cap();
+
+	/* Set energy policy */
+	set_energy_perf_bias(ENERGY_POLICY_NORMAL);
+
+	/* Set Max Ratio */
+	set_max_ratio();
+
+	/* Enable Turbo */
+	turbo_enable();
+
+	/* Start up extra cores */
+	intel_cores_init(cpu);
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c
new file mode 100644
index 0000000..c50b5de
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/northbridge.c
@@ -0,0 +1,188 @@
+/*
+ * From Coreboot northbridge/intel/sandybridge/northbridge.c
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The Chromium Authors
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/msr.h>
+#include <asm/acpi.h>
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/model_206ax.h>
+#include <asm/arch/sandybridge.h>
+
+static int bridge_revision_id = -1;
+
+int bridge_silicon_revision(void)
+{
+	if (bridge_revision_id < 0) {
+		struct cpuid_result result;
+		uint8_t stepping, bridge_id;
+		pci_dev_t dev;
+
+		result = cpuid(1);
+		stepping = result.eax & 0xf;
+		dev = PCI_BDF(0, 0, 0);
+		bridge_id = pci_read_config16(dev, PCI_DEVICE_ID) & 0xf0;
+		bridge_revision_id = bridge_id | stepping;
+	}
+
+	return bridge_revision_id;
+}
+
+/*
+ * Reserve everything between A segment and 1MB:
+ *
+ * 0xa0000 - 0xbffff: legacy VGA
+ * 0xc0000 - 0xcffff: VGA OPROM (needed by kernel)
+ * 0xe0000 - 0xfffff: SeaBIOS, if used, otherwise DMI
+ */
+static const int legacy_hole_base_k = 0xa0000 / 1024;
+static const int legacy_hole_size_k = 384;
+
+static int get_pcie_bar(u32 *base, u32 *len)
+{
+	pci_dev_t dev = PCI_BDF(0, 0, 0);
+	u32 pciexbar_reg;
+
+	*base = 0;
+	*len = 0;
+
+	pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
+
+	if (!(pciexbar_reg & (1 << 0)))
+		return 0;
+
+	switch ((pciexbar_reg >> 1) & 3) {
+	case 0: /* 256MB */
+		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
+				(1 << 28));
+		*len = 256 * 1024 * 1024;
+		return 1;
+	case 1: /* 128M */
+		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
+				(1 << 28) | (1 << 27));
+		*len = 128 * 1024 * 1024;
+		return 1;
+	case 2: /* 64M */
+		*base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) |
+				(1 << 28) | (1 << 27) | (1 << 26));
+		*len = 64 * 1024 * 1024;
+		return 1;
+	}
+
+	return 0;
+}
+
+static void add_fixed_resources(pci_dev_t dev, int index)
+{
+	u32 pcie_config_base, pcie_config_size;
+
+	if (get_pcie_bar(&pcie_config_base, &pcie_config_size)) {
+		debug("Adding PCIe config bar base=0x%08x size=0x%x\n",
+		      pcie_config_base, pcie_config_size);
+	}
+}
+
+static void northbridge_dmi_init(pci_dev_t dev)
+{
+	/* Clear error status bits */
+	writel(0xffffffff, DMIBAR_REG(0x1c4));
+	writel(0xffffffff, DMIBAR_REG(0x1d0));
+
+	/* Steps prior to DMI ASPM */
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
+		clrsetbits_le32(DMIBAR_REG(0x250), (1 << 22) | (1 << 20),
+				1 << 21);
+	}
+
+	setbits_le32(DMIBAR_REG(0x238), 1 << 29);
+
+	if (bridge_silicon_revision() >= SNB_STEP_D0) {
+		setbits_le32(DMIBAR_REG(0x1f8), 1 << 16);
+	} else if (bridge_silicon_revision() >= SNB_STEP_D1) {
+		clrsetbits_le32(DMIBAR_REG(0x1f8), 1 << 26, 1 << 16);
+		setbits_le32(DMIBAR_REG(0x1fc), (1 << 12) | (1 << 23));
+	}
+
+	/* Enable ASPM on SNB link, should happen before PCH link */
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB)
+		setbits_le32(DMIBAR_REG(0xd04), 1 << 4);
+
+	setbits_le32(DMIBAR_REG(0x88), (1 << 1) | (1 << 0));
+}
+
+void northbridge_init(pci_dev_t dev)
+{
+	u32 bridge_type;
+
+	add_fixed_resources(dev, 6);
+	northbridge_dmi_init(dev);
+
+	bridge_type = readl(MCHBAR_REG(0x5f10));
+	bridge_type &= ~0xff;
+
+	if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) {
+		/* Enable Power Aware Interrupt Routing - fixed priority */
+		clrsetbits_8(MCHBAR_REG(0x5418), 0xf, 0x4);
+
+		/* 30h for IvyBridge */
+		bridge_type |= 0x30;
+	} else {
+		/* 20h for Sandybridge */
+		bridge_type |= 0x20;
+	}
+	writel(bridge_type, MCHBAR_REG(0x5f10));
+
+	/*
+	 * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU
+	 * that BIOS has initialized memory and power management
+	 */
+	setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 1);
+	debug("Set BIOS_RESET_CPL\n");
+
+	/* Configure turbo power limits 1ms after reset complete bit */
+	mdelay(1);
+	set_power_limits(28);
+
+	/*
+	 * CPUs with configurable TDP also need power limits set
+	 * in MCHBAR.  Use same values from MSR_PKG_POWER_LIMIT.
+	 */
+	if (cpu_config_tdp_levels()) {
+		msr_t msr = msr_read(MSR_PKG_POWER_LIMIT);
+
+		writel(msr.lo, MCHBAR_REG(0x59A0));
+		writel(msr.hi, MCHBAR_REG(0x59A4));
+	}
+
+	/* Set here before graphics PM init */
+	writel(0x00100001, MCHBAR_REG(0x5500));
+}
+
+void northbridge_enable(pci_dev_t dev)
+{
+#if CONFIG_HAVE_ACPI_RESUME
+	switch (pci_read_config32(dev, SKPAD)) {
+	case 0xcafebabe:
+		debug("Normal boot.\n");
+		apci_set_slp_type(0);
+		break;
+	case 0xcafed00d:
+		debug("S3 Resume.\n");
+		apci_set_slp_type(3);
+		break;
+	default:
+		debug("Unknown boot method, assuming normal.\n");
+		apci_set_slp_type(0);
+		break;
+	}
+#endif
+}
diff --git a/arch/x86/cpu/ivybridge/pch.c b/arch/x86/cpu/ivybridge/pch.c
new file mode 100644
index 0000000..fa04d48
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/pch.c
@@ -0,0 +1,123 @@
+/*
+ * From Coreboot
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2012 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+static int pch_revision_id = -1;
+static int pch_type = -1;
+
+int pch_silicon_revision(void)
+{
+	pci_dev_t dev;
+
+	dev = PCH_LPC_DEV;
+
+	if (pch_revision_id < 0)
+		pch_revision_id = pci_read_config8(dev, PCI_REVISION_ID);
+	return pch_revision_id;
+}
+
+int pch_silicon_type(void)
+{
+	pci_dev_t dev;
+
+	dev = PCH_LPC_DEV;
+
+	if (pch_type < 0)
+		pch_type = pci_read_config8(dev, PCI_DEVICE_ID + 1);
+	return pch_type;
+}
+
+int pch_silicon_supported(int type, int rev)
+{
+	int cur_type = pch_silicon_type();
+	int cur_rev = pch_silicon_revision();
+
+	switch (type) {
+	case PCH_TYPE_CPT:
+		/* CougarPoint minimum revision */
+		if (cur_type == PCH_TYPE_CPT && cur_rev >= rev)
+			return 1;
+		/* PantherPoint any revision */
+		if (cur_type == PCH_TYPE_PPT)
+			return 1;
+		break;
+
+	case PCH_TYPE_PPT:
+		/* PantherPoint minimum revision */
+		if (cur_type == PCH_TYPE_PPT && cur_rev >= rev)
+			return 1;
+		break;
+	}
+
+	return 0;
+}
+
+#define IOBP_RETRY 1000
+static inline int iobp_poll(void)
+{
+	unsigned try = IOBP_RETRY;
+	u32 data;
+
+	while (try--) {
+		data = readl(RCB_REG(IOBPS));
+		if ((data & 1) == 0)
+			return 1;
+		udelay(10);
+	}
+
+	printf("IOBP timeout\n");
+	return 0;
+}
+
+void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
+{
+	u32 data;
+
+	/* Set the address */
+	writel(address, RCB_REG(IOBPIRI));
+
+	/* READ OPCODE */
+	if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
+		writel(IOBPS_RW_BX, RCB_REG(IOBPS));
+	else
+		writel(IOBPS_READ_AX, RCB_REG(IOBPS));
+	if (!iobp_poll())
+		return;
+
+	/* Read IOBP data */
+	data = readl(RCB_REG(IOBPD));
+	if (!iobp_poll())
+		return;
+
+	/* Check for successful transaction */
+	if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) {
+		printf("IOBP read 0x%08x failed\n", address);
+		return;
+	}
+
+	/* Update the data */
+	data &= andvalue;
+	data |= orvalue;
+
+	/* WRITE OPCODE */
+	if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0))
+		writel(IOBPS_RW_BX, RCB_REG(IOBPS));
+	else
+		writel(IOBPS_WRITE_AX, RCB_REG(IOBPS));
+	if (!iobp_poll())
+		return;
+
+	/* Write IOBP data */
+	writel(data, RCB_REG(IOBPD));
+	if (!iobp_poll())
+		return;
+}
diff --git a/arch/x86/cpu/ivybridge/pci.c b/arch/x86/cpu/ivybridge/pci.c
index c1ae658..452d1c3 100644
--- a/arch/x86/cpu/ivybridge/pci.c
+++ b/arch/x86/cpu/ivybridge/pci.c
@@ -12,6 +12,8 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/pci.h>
+#include <asm/arch/bd82x6x.h>
+#include <asm/arch/pch.h>
 
 static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
 			      struct pci_config_table *table)
@@ -58,3 +60,41 @@
 
 	hose->region_count = 3;
 }
+
+int board_pci_pre_scan(struct pci_controller *hose)
+{
+	pci_dev_t dev;
+	u16 reg16;
+
+	bd82x6x_init();
+
+	reg16 = 0xff;
+	dev = PCH_DEV;
+	reg16 = pci_read_config16(dev, PCI_COMMAND);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config16(dev, PCI_COMMAND, reg16);
+
+	/*
+	* Clear non-reserved bits in status register.
+	*/
+	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+	pci_write_bar32(hose, dev, 0, 0xf0000000);
+
+	return 0;
+}
+
+int board_pci_post_scan(struct pci_controller *hose)
+{
+	int ret;
+
+	ret = bd82x6x_init_pci_devices();
+	if (ret) {
+		printf("bd82x6x_init_pci_devices() failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c
new file mode 100644
index 0000000..bbcd47d
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/sata.c
@@ -0,0 +1,225 @@
+/*
+ * From Coreboot
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/bd82x6x.h>
+
+static inline u32 sir_read(pci_dev_t dev, int idx)
+{
+	pci_write_config32(dev, SATA_SIRI, idx);
+	return pci_read_config32(dev, SATA_SIRD);
+}
+
+static inline void sir_write(pci_dev_t dev, int idx, u32 value)
+{
+	pci_write_config32(dev, SATA_SIRI, idx);
+	pci_write_config32(dev, SATA_SIRD, value);
+}
+
+static void common_sata_init(pci_dev_t dev, unsigned int port_map)
+{
+	u32 reg32;
+	u16 reg16;
+
+	/* Set IDE I/O Configuration */
+	reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+	pci_write_config32(dev, IDE_CONFIG, reg32);
+
+	/* Port enable */
+	reg16 = pci_read_config16(dev, 0x92);
+	reg16 &= ~0x3f;
+	reg16 |= port_map;
+	pci_write_config16(dev, 0x92, reg16);
+
+	/* SATA Initialization register */
+	port_map &= 0xff;
+	pci_write_config32(dev, 0x94, ((port_map ^ 0x3f) << 24) | 0x183);
+}
+
+void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node)
+{
+	unsigned int port_map, speed_support, port_tx;
+	struct pci_controller *hose = pci_bus_to_hose(0);
+	const char *mode;
+	u32 reg32;
+	u16 reg16;
+
+	debug("SATA: Initializing...\n");
+
+	/* SATA configuration */
+	port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0);
+	speed_support = fdtdec_get_int(blob, node,
+				       "sata_interface_speed_support", 0);
+
+	/* Enable BARs */
+	pci_write_config16(dev, PCI_COMMAND, 0x0007);
+
+	mode = fdt_getprop(blob, node, "intel,sata-mode", NULL);
+	if (!mode || !strcmp(mode, "ahci")) {
+		u32 abar;
+
+		debug("SATA: Controller in AHCI mode\n");
+
+		/* Set Interrupt Line, Interrupt Pin is set by D31IP.PIP */
+		pci_write_config8(dev, INTR_LN, 0x0a);
+
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+				IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+				IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+		pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+				IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
+
+		/* Sync DMA */
+		pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0);
+		pci_write_config16(dev, IDE_SDMA_TIM, 0x0001);
+
+		common_sata_init(dev, 0x8000 | port_map);
+
+		/* Initialize AHCI memory-mapped space */
+		abar = pci_read_bar32(hose, dev, 5);
+		debug("ABAR: %08X\n", abar);
+		/* CAP (HBA Capabilities) : enable power management */
+		reg32 = readl(abar + 0x00);
+		reg32 |= 0x0c006000;  /* set PSC+SSC+SALP+SSS */
+		reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */
+		/* Set ISS, if available */
+		if (speed_support) {
+			reg32 &= ~0x00f00000;
+			reg32 |= (speed_support & 0x03) << 20;
+		}
+		writel(reg32, abar + 0x00);
+		/* PI (Ports implemented) */
+		writel(port_map, abar + 0x0c);
+		(void) readl(abar + 0x0c); /* Read back 1 */
+		(void) readl(abar + 0x0c); /* Read back 2 */
+		/* CAP2 (HBA Capabilities Extended)*/
+		reg32 = readl(abar + 0x24);
+		reg32 &= ~0x00000002;
+		writel(reg32, abar + 0x24);
+		/* VSP (Vendor Specific Register */
+		reg32 = readl(abar + 0xa0);
+		reg32 &= ~0x00000005;
+		writel(reg32, abar + 0xa0);
+	} else if (!strcmp(mode, "combined")) {
+		debug("SATA: Controller in combined mode\n");
+
+		/* No AHCI: clear AHCI base */
+		pci_write_bar32(hose, dev, 5, 0x00000000);
+		/* And without AHCI BAR no memory decoding */
+		reg16 = pci_read_config16(dev, PCI_COMMAND);
+		reg16 &= ~PCI_COMMAND_MEMORY;
+		pci_write_config16(dev, PCI_COMMAND, reg16);
+
+		pci_write_config8(dev, 0x09, 0x80);
+
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+				IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS);
+		pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+				IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+				IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+
+		/* Sync DMA */
+		pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0);
+		pci_write_config16(dev, IDE_SDMA_TIM, 0x0200);
+
+		common_sata_init(dev, port_map);
+	} else {
+		debug("SATA: Controller in plain-ide mode\n");
+
+		/* No AHCI: clear AHCI base */
+		pci_write_bar32(hose, dev, 5, 0x00000000);
+
+		/* And without AHCI BAR no memory decoding */
+		reg16 = pci_read_config16(dev, PCI_COMMAND);
+		reg16 &= ~PCI_COMMAND_MEMORY;
+		pci_write_config16(dev, PCI_COMMAND, reg16);
+
+		/*
+		 * Native mode capable on both primary and secondary (0xa)
+		 * OR'ed with enabled (0x50) = 0xf
+		 */
+		pci_write_config8(dev, 0x09, 0x8f);
+
+		/* Set Interrupt Line */
+		/* Interrupt Pin is set by D31IP.PIP */
+		pci_write_config8(dev, INTR_LN, 0xff);
+
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE |
+				IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS |
+				IDE_PPE0 | IDE_IE0 | IDE_TIME0);
+		pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE |
+				IDE_SITRE | IDE_ISP_3_CLOCKS |
+				IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0);
+
+		/* Sync DMA */
+		pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0);
+		pci_write_config16(dev, IDE_SDMA_TIM, 0x0201);
+
+		common_sata_init(dev, port_map);
+	}
+
+	/* Set Gen3 Transmitter settings if needed */
+	port_tx = fdtdec_get_int(blob, node, "intel,sata-port0-gen3-tx", 0);
+	if (port_tx)
+		pch_iobp_update(SATA_IOBP_SP0G3IR, 0, port_tx);
+
+	port_tx = fdtdec_get_int(blob, node, "intel,sata-port1-gen3-tx", 0);
+	if (port_tx)
+		pch_iobp_update(SATA_IOBP_SP1G3IR, 0, port_tx);
+
+	/* Additional Programming Requirements */
+	sir_write(dev, 0x04, 0x00001600);
+	sir_write(dev, 0x28, 0xa0000033);
+	reg32 = sir_read(dev, 0x54);
+	reg32 &= 0xff000000;
+	reg32 |= 0x5555aa;
+	sir_write(dev, 0x54, reg32);
+	sir_write(dev, 0x64, 0xcccc8484);
+	reg32 = sir_read(dev, 0x68);
+	reg32 &= 0xffff0000;
+	reg32 |= 0xcccc;
+	sir_write(dev, 0x68, reg32);
+	reg32 = sir_read(dev, 0x78);
+	reg32 &= 0x0000ffff;
+	reg32 |= 0x88880000;
+	sir_write(dev, 0x78, reg32);
+	sir_write(dev, 0x84, 0x001c7000);
+	sir_write(dev, 0x88, 0x88338822);
+	sir_write(dev, 0xa0, 0x001c7000);
+	sir_write(dev, 0xc4, 0x0c0c0c0c);
+	sir_write(dev, 0xc8, 0x0c0c0c0c);
+	sir_write(dev, 0xd4, 0x10000000);
+
+	pch_iobp_update(0xea004001, 0x3fffffff, 0xc0000000);
+	pch_iobp_update(0xea00408a, 0xfffffcff, 0x00000100);
+}
+
+void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node)
+{
+	unsigned port_map;
+	const char *mode;
+	u16 map = 0;
+
+	/*
+	 * Set SATA controller mode early so the resource allocator can
+	 * properly assign IO/Memory resources for the controller.
+	 */
+	mode = fdt_getprop(blob, node, "intel,sata-mode", NULL);
+	if (mode && !strcmp(mode, "ahci"))
+		map = 0x0060;
+	port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0);
+
+	map |= (port_map ^ 0x3f) << 8;
+	pci_write_config16(dev, 0x90, map);
+}
diff --git a/arch/x86/cpu/ivybridge/usb_ehci.c b/arch/x86/cpu/ivybridge/usb_ehci.c
new file mode 100644
index 0000000..291c971
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/usb_ehci.c
@@ -0,0 +1,29 @@
+/*
+ * From Coreboot
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+void bd82x6x_usb_ehci_init(pci_dev_t dev)
+{
+	u32 reg32;
+
+	/* Disable Wake on Disconnect in RMH */
+	reg32 = readl(RCB_REG(0x35b0));
+	reg32 |= 0x22;
+	writel(reg32, RCB_REG(0x35b0));
+
+	debug("EHCI: Setting up controller.. ");
+	reg32 = pci_read_config32(dev, PCI_COMMAND);
+	reg32 |= PCI_COMMAND_MASTER;
+	/* reg32 |= PCI_COMMAND_SERR; */
+	pci_write_config32(dev, PCI_COMMAND, reg32);
+
+	debug("done.\n");
+}
diff --git a/arch/x86/cpu/ivybridge/usb_xhci.c b/arch/x86/cpu/ivybridge/usb_xhci.c
new file mode 100644
index 0000000..4a32a7e
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/usb_xhci.c
@@ -0,0 +1,32 @@
+/*
+ * From Coreboot
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+void bd82x6x_usb_xhci_init(pci_dev_t dev)
+{
+	u32 reg32;
+
+	debug("XHCI: Setting up controller.. ");
+
+	/* lock overcurrent map */
+	reg32 = pci_read_config32(dev, 0x44);
+	reg32 |= 1;
+	pci_write_config32(dev, 0x44, reg32);
+
+	/* Enable clock gating */
+	reg32 = pci_read_config32(dev, 0x40);
+	reg32 &= ~((1 << 20) | (1 << 21));
+	reg32 |= (1 << 19) | (1 << 18) | (1 << 17);
+	reg32 |= (1 << 10) | (1 << 9) | (1 << 8);
+	reg32 |= (1 << 31); /* lock */
+	pci_write_config32(dev, 0x40, reg32);
+
+	debug("done.\n");
+}
diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c
new file mode 100644
index 0000000..4690603
--- /dev/null
+++ b/arch/x86/cpu/lapic.c
@@ -0,0 +1,57 @@
+/*
+ * From coreboot file of same name
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/msr.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/post.h>
+
+void lapic_setup(void)
+{
+#if NEED_LAPIC == 1
+	/* 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);
+
+	/* 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));
+
+	debug("apic_id: 0x%02lx, ", lapicid());
+#else /* !NEED_LLAPIC */
+	/* Only Pentium Pro and later have those MSR stuff */
+	debug("Disabling local apic: ");
+	disable_lapic();
+#endif /* !NEED_LAPIC */
+	debug("done.\n");
+	post_code(POST_LAPIC);
+}
diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c
index e399388..f3492c3 100644
--- a/arch/x86/cpu/pci.c
+++ b/arch/x86/cpu/pci.c
@@ -33,6 +33,16 @@
 	return 0;
 }
 
+__weak int board_pci_pre_scan(struct pci_controller *hose)
+{
+	return 0;
+}
+
+__weak int board_pci_post_scan(struct pci_controller *hose)
+{
+	return 0;
+}
+
 void pci_init_board(void)
 {
 	struct pci_controller *hose = &x86_hose;
@@ -44,7 +54,9 @@
 	pci_setup_type1(hose);
 	pci_register_hose(hose);
 
+	board_pci_pre_scan(hose);
 	hose->last_busno = pci_hose_scan(hose);
+	board_pci_post_scan(hose);
 }
 
 static struct pci_controller *get_hose(void)
diff --git a/arch/x86/cpu/turbo.c b/arch/x86/cpu/turbo.c
new file mode 100644
index 0000000..254d0de
--- /dev/null
+++ b/arch/x86/cpu/turbo.c
@@ -0,0 +1,98 @@
+/*
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2011 The Chromium Authors.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/cpu.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/turbo.h>
+
+#if CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+static inline int get_global_turbo_state(void)
+{
+	return TURBO_UNKNOWN;
+}
+
+static inline void set_global_turbo_state(int state)
+{
+}
+#else
+static int g_turbo_state = TURBO_UNKNOWN;
+
+static inline int get_global_turbo_state(void)
+{
+	return g_turbo_state;
+}
+
+static inline void set_global_turbo_state(int state)
+{
+	g_turbo_state = state;
+}
+#endif
+
+static const char *const turbo_state_desc[] = {
+	[TURBO_UNKNOWN]		= "unknown",
+	[TURBO_UNAVAILABLE]	= "unavailable",
+	[TURBO_DISABLED]	= "available but hidden",
+	[TURBO_ENABLED]		= "available and visible"
+};
+
+/*
+ * Determine the current state of Turbo and cache it for later.
+ * Turbo is a package level config so it does not need to be
+ * enabled on every core.
+ */
+int turbo_get_state(void)
+{
+	struct cpuid_result cpuid_regs;
+	int turbo_en, turbo_cap;
+	msr_t msr;
+	int turbo_state = get_global_turbo_state();
+
+	/* Return cached state if available */
+	if (turbo_state != TURBO_UNKNOWN)
+		return turbo_state;
+
+	cpuid_regs = cpuid(CPUID_LEAF_PM);
+	turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE);
+
+	msr = msr_read(MSR_IA32_MISC_ENABLES);
+	turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO);
+
+	if (!turbo_cap && turbo_en) {
+		/* Unavailable */
+		turbo_state = TURBO_UNAVAILABLE;
+	} else if (!turbo_cap && !turbo_en) {
+		/* Available but disabled */
+		turbo_state = TURBO_DISABLED;
+	} else if (turbo_cap && turbo_en) {
+		/* Available */
+		turbo_state = TURBO_ENABLED;
+	}
+
+	set_global_turbo_state(turbo_state);
+	debug("Turbo is %s\n", turbo_state_desc[turbo_state]);
+	return turbo_state;
+}
+
+void turbo_enable(void)
+{
+	msr_t msr;
+
+	/* Only possible if turbo is available but hidden */
+	if (turbo_get_state() == TURBO_DISABLED) {
+		/* Clear Turbo Disable bit in Misc Enables */
+		msr = msr_read(MSR_IA32_MISC_ENABLES);
+		msr.hi &= ~H_MISC_DISABLE_TURBO;
+		msr_write(MSR_IA32_MISC_ENABLES, msr);
+
+		/* Update cached turbo state */
+		set_global_turbo_state(TURBO_ENABLED);
+		debug("Turbo has been enabled\n");
+	}
+}
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
index f48bff5..b0d8531 100644
--- a/arch/x86/cpu/u-boot.lds
+++ b/arch/x86/cpu/u-boot.lds
@@ -44,7 +44,9 @@
 
 	. = ALIGN(4);
 	__rel_dyn_start = .;
-	.rel.dyn : { *(.rel.dyn) }
+	.rel.dyn : {
+		*(.rel*)
+	}
 	__rel_dyn_end = .;
 	. = ALIGN(4);
 	_end = .;
@@ -64,15 +66,19 @@
 	/DISCARD/ : { *(.gnu*) }
 
 #ifdef CONFIG_X86_RESET_VECTOR
-
 	/*
 	 * The following expressions place the 16-bit Real-Mode code and
 	 * Reset Vector at the end of the Flash ROM
 	 */
-	. = START_16;
-	.start16 : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + START_16)) { KEEP(*(.start16)); }
+	. = START_16 - RESET_SEG_START;
+	.start16 : AT (START_16) {
+		KEEP(*(.start16));
+	}
 
-	. = RESET_VEC_LOC;
-	.resetvec : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + RESET_VEC_LOC)) { KEEP(*(.resetvec)); }
+	. = RESET_VEC_LOC - RESET_SEG_START;
+	.resetvec : AT (RESET_VEC_LOC) {
+		KEEP(*(.resetvec));
+	}
 #endif
+
 }
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts
index 9329916..592af16 100644
--- a/arch/x86/dts/link.dts
+++ b/arch/x86/dts/link.dts
@@ -163,21 +163,51 @@
 		};
 	};
 
-	lpc {
-		compatible = "intel,lpc";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		gen-dec = <0x800 0xfc 0x900 0xfc>;
-		cros-ec@200 {
-			compatible = "google,cros-ec";
-			reg = <0x204 1 0x200 1 0x880 0x80>;
+	pci {
+		sata {
+			compatible = "intel,pantherpoint-ahci";
+			intel,sata-mode = "ahci";
+			intel,sata-port-map = <1>;
+			intel,sata-port0-gen3-tx = <0x00880a7f>;
+		};
 
-			/* This describes the flash memory within the EC */
+		gma {
+			compatible = "intel,gma";
+			intel,dp_hotplug = <0 0 0x06>;
+			intel,panel-port-select = <1>;
+			intel,panel-power-cycle-delay = <6>;
+			intel,panel-power-up-delay = <2000>;
+			intel,panel-power-down-delay = <500>;
+			intel,panel-power-backlight-on-delay = <2000>;
+			intel,panel-power-backlight-off-delay = <2000>;
+			intel,cpu-backlight = <0x00000200>;
+			intel,pch-backlight = <0x04000000>;
+		};
+
+		lpc {
+			compatible = "intel,lpc";
 			#address-cells = <1>;
 			#size-cells = <1>;
-			flash@8000000 {
-				reg = <0x08000000 0x20000>;
-				erase-value = <0xff>;
+			gen-dec = <0x800 0xfc 0x900 0xfc>;
+			intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
+			intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b
+						0x80 0x80 0x80 0x80>;
+			intel,gpi-routing = <0 0 0 0 0 0 0 2
+						1 0 0 0 0 0 0 0>;
+			/* Enable EC SMI source */
+			intel,alt-gp-smi-enable = <0x0100>;
+
+			cros-ec@200 {
+				compatible = "google,cros-ec";
+				reg = <0x204 1 0x200 1 0x880 0x80>;
+
+				/* Describes the flash memory within the EC */
+				#address-cells = <1>;
+				#size-cells = <1>;
+				flash@8000000 {
+					reg = <0x08000000 0x20000>;
+					erase-value = <0xff>;
+				};
 			};
 		};
 	};
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
new file mode 100644
index 0000000..4872b92
--- /dev/null
+++ b/arch/x86/include/asm/acpi.h
@@ -0,0 +1,24 @@
+/*
+ * From coreboot
+ *
+ * Copyright (C) 2004 SUSE LINUX AG
+ * Copyright (C) 2004 Nick Barker
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * (Written by Stefan Reinauer <stepan@coresystems.de>)
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ASM_ACPI_H
+#define __ASM_ACPI_H
+
+#define RSDP_SIG		"RSD PTR "  /* RSDT pointer signature */
+#define ACPI_TABLE_CREATOR	"U-BootAC"  /* Must be exactly 8 bytes long! */
+#define OEM_ID			"U-Boot"    /* Must be exactly 6 bytes long! */
+#define ASLC			"U-Bo"      /* Must be exactly 4 bytes long! */
+
+/* 0 = S0, 1 = S1 ...*/
+int acpi_get_slp_type(void);
+void apci_set_slp_type(int type);
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
new file mode 100644
index 0000000..e1d9a9b
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_BD82X6X_H
+#define _ASM_ARCH_BD82X6X_H
+
+void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node);
+void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node);
+void bd82x6x_pci_init(pci_dev_t dev);
+void bd82x6x_usb_ehci_init(pci_dev_t dev);
+void bd82x6x_usb_xhci_init(pci_dev_t dev);
+int bd82x6x_init_pci_devices(void);
+int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
+		   const void *blob, int node);
+int bd82x6x_init(void);
+
+struct x86_cpu_priv;
+int model_206ax_init(struct x86_cpu_priv *cpu);
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
index 8281d7a..7b4f2e7 100644
--- a/arch/x86/include/asm/arch-ivybridge/model_206ax.h
+++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
@@ -79,4 +79,8 @@
 #define PSS_LATENCY_TRANSITION		10
 #define PSS_LATENCY_BUSMASTER		10
 
+/* Configure power limits for turbo mode */
+void set_power_limits(u8 power_limit_1_time);
+int cpu_config_tdp_levels(void);
+
 #endif
diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
index c6efdb8..21df083 100644
--- a/arch/x86/include/asm/arch-ivybridge/pch.h
+++ b/arch/x86/include/asm/arch-ivybridge/pch.h
@@ -14,11 +14,41 @@
 
 #include <pci.h>
 
+/* PCH types */
+#define PCH_TYPE_CPT	0x1c /* CougarPoint */
+#define PCH_TYPE_PPT	0x1e /* IvyBridge */
+
+/* PCH stepping values for LPC device */
+#define PCH_STEP_A0	0
+#define PCH_STEP_A1	1
+#define PCH_STEP_B0	2
+#define PCH_STEP_B1	3
+#define PCH_STEP_B2	4
+#define PCH_STEP_B3	5
 #define DEFAULT_GPIOBASE	0x0480
 #define DEFAULT_PMBASE		0x0500
 
 #define SMBUS_IO_BASE		0x0400
 
+int pch_silicon_revision(void);
+int pch_silicon_type(void);
+int pch_silicon_supported(int type, int rev);
+void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
+
+#define MAINBOARD_POWER_OFF	0
+#define MAINBOARD_POWER_ON	1
+#define MAINBOARD_POWER_KEEP	2
+
+/* PCI Configuration Space (D30:F0): PCI2PCI */
+#define PSTS	0x06
+#define SMLT	0x1b
+#define SECSTS	0x1e
+#define INTR	0x3c
+#define BCTRL	0x3e
+#define   SBR	(1 << 6)
+#define   SEE	(1 << 1)
+#define   PERE	(1 << 0)
+
 #define PCH_EHCI1_DEV		PCI_BDF(0, 0x1d, 0)
 #define PCH_EHCI2_DEV		PCI_BDF(0, 0x1a, 0)
 #define PCH_XHCI_DEV		PCI_BDF(0, 0x14, 0)
@@ -30,6 +60,35 @@
 
 /* PCI Configuration Space (D31:F0): LPC */
 #define PCH_LPC_DEV		PCI_BDF(0, 0x1f, 0)
+#define SERIRQ_CNTL		0x64
+
+#define GEN_PMCON_1		0xa0
+#define GEN_PMCON_2		0xa2
+#define GEN_PMCON_3		0xa4
+#define ETR3			0xac
+#define  ETR3_CWORWRE		(1 << 18)
+#define  ETR3_CF9GR		(1 << 20)
+
+/* GEN_PMCON_3 bits */
+#define RTC_BATTERY_DEAD	(1 << 2)
+#define RTC_POWER_FAILED	(1 << 1)
+#define SLEEP_AFTER_POWER_FAIL	(1 << 0)
+
+#define PMBASE			0x40
+#define ACPI_CNTL		0x44
+#define BIOS_CNTL		0xDC
+#define GPIO_BASE		0x48 /* LPC GPIO Base Address Register */
+#define GPIO_CNTL		0x4C /* LPC GPIO Control Register */
+#define GPIO_ROUT		0xb8
+
+#define PIRQA_ROUT		0x60
+#define PIRQB_ROUT		0x61
+#define PIRQC_ROUT		0x62
+#define PIRQD_ROUT		0x63
+#define PIRQE_ROUT		0x68
+#define PIRQF_ROUT		0x69
+#define PIRQG_ROUT		0x6A
+#define PIRQH_ROUT		0x6B
 
 #define GEN_PMCON_1		0xa0
 #define GEN_PMCON_2		0xa2
@@ -63,6 +122,64 @@
 #define LPC_GEN4_DEC		0x90 /* LPC IF Generic Decode Range 4 */
 #define LPC_GENX_DEC(x)		(0x84 + 4 * (x))
 
+/* PCI Configuration Space (D31:F1): IDE */
+#define PCH_IDE_DEV		PCI_BDF(0, 0x1f, 1)
+#define PCH_SATA_DEV		PCI_BDF(0, 0x1f, 2)
+#define PCH_SATA2_DEV		PCI_BDF(0, 0x1f, 5)
+
+#define INTR_LN			0x3c
+#define IDE_TIM_PRI		0x40	/* IDE timings, primary */
+#define   IDE_DECODE_ENABLE	(1 << 15)
+#define   IDE_SITRE		(1 << 14)
+#define   IDE_ISP_5_CLOCKS	(0 << 12)
+#define   IDE_ISP_4_CLOCKS	(1 << 12)
+#define   IDE_ISP_3_CLOCKS	(2 << 12)
+#define   IDE_RCT_4_CLOCKS	(0 <<  8)
+#define   IDE_RCT_3_CLOCKS	(1 <<  8)
+#define   IDE_RCT_2_CLOCKS	(2 <<  8)
+#define   IDE_RCT_1_CLOCKS	(3 <<  8)
+#define   IDE_DTE1		(1 <<  7)
+#define   IDE_PPE1		(1 <<  6)
+#define   IDE_IE1		(1 <<  5)
+#define   IDE_TIME1		(1 <<  4)
+#define   IDE_DTE0		(1 <<  3)
+#define   IDE_PPE0		(1 <<  2)
+#define   IDE_IE0		(1 <<  1)
+#define   IDE_TIME0		(1 <<  0)
+#define IDE_TIM_SEC		0x42	/* IDE timings, secondary */
+
+#define IDE_SDMA_CNT		0x48	/* Synchronous DMA control */
+#define   IDE_SSDE1		(1 <<  3)
+#define   IDE_SSDE0		(1 <<  2)
+#define   IDE_PSDE1		(1 <<  1)
+#define   IDE_PSDE0		(1 <<  0)
+
+#define IDE_SDMA_TIM		0x4a
+
+#define IDE_CONFIG		0x54	/* IDE I/O Configuration Register */
+#define   SIG_MODE_SEC_NORMAL	(0 << 18)
+#define   SIG_MODE_SEC_TRISTATE	(1 << 18)
+#define   SIG_MODE_SEC_DRIVELOW	(2 << 18)
+#define   SIG_MODE_PRI_NORMAL	(0 << 16)
+#define   SIG_MODE_PRI_TRISTATE	(1 << 16)
+#define   SIG_MODE_PRI_DRIVELOW	(2 << 16)
+#define   FAST_SCB1		(1 << 15)
+#define   FAST_SCB0		(1 << 14)
+#define   FAST_PCB1		(1 << 13)
+#define   FAST_PCB0		(1 << 12)
+#define   SCB1			(1 <<  3)
+#define   SCB0			(1 <<  2)
+#define   PCB1			(1 <<  1)
+#define   PCB0			(1 <<  0)
+
+#define SATA_SIRI		0xa0 /* SATA Indexed Register Index */
+#define SATA_SIRD		0xa4 /* SATA Indexed Register Data */
+#define SATA_SP			0xd0 /* Scratchpad */
+
+/* SATA IOBP Registers */
+#define SATA_IOBP_SP0G3IR	0xea000151
+#define SATA_IOBP_SP1G3IR	0xea000051
+
 /* PCI Configuration Space (D31:F3): SMBus */
 #define PCH_SMBUS_DEV		PCI_BDF(0, 0x1f, 3)
 #define SMB_BASE		0x20
@@ -343,6 +460,9 @@
 #define   DMISCI_STS	(1 << 9)
 #define TCO2_STS	0x66
 
+int lpc_init(struct pci_controller *hose, pci_dev_t dev);
+void lpc_enable(pci_dev_t dev);
+
 /**
  * lpc_early_init() - set up LPC serial ports and other early things
  *
diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
index 114ee19..cf7457f 100644
--- a/arch/x86/include/asm/arch-ivybridge/sandybridge.h
+++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
@@ -97,11 +97,22 @@
 /*
  * MCHBAR
  */
-#define MCHBAR_REG(reg)		(DEFAULT_RCBA + (reg))
+#define MCHBAR_REG(reg)		(DEFAULT_MCHBAR + (reg))
 
 #define SSKPD		0x5d14	/* 16bit (scratchpad) */
 #define BIOS_RESET_CPL	0x5da8	/* 8bit */
 
+/*
+ * DMIBAR
+ */
+
+#define DMIBAR_REG(x)	(DEFAULT_DMIBAR + x)
+
+int bridge_silicon_revision(void);
+
+void northbridge_enable(pci_dev_t dev);
+void northbridge_init(pci_dev_t dev);
+
 void report_platform_info(void);
 
 void sandybridge_early_init(int chipset_type);
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 73113f9..bc4033b 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -69,4 +69,6 @@
 #define	ICW4_AEOI	0x02	/* Automatic EOI Mode */
 #define ICW4_PM		0x01	/* Microprocessor Mode */
 
+int i8259_init(void);
+
 #endif
diff --git a/arch/x86/include/asm/interrupt.h b/arch/x86/include/asm/interrupt.h
index 3f46e09..25abde7 100644
--- a/arch/x86/include/asm/interrupt.h
+++ b/arch/x86/include/asm/interrupt.h
@@ -27,4 +27,15 @@
 
 extern char exception_stack[];
 
+/**
+ * configure_irq_trigger() - Configure IRQ triggering
+ *
+ * Switch the given interrupt to be level / edge triggered
+ *
+ * @param int_num legacy interrupt number (3-7, 9-15)
+ * @param is_level_triggered true for level triggered interrupt, false for
+ *	edge triggered interrupt
+ */
+void configure_irq_trigger(int int_num, bool is_level_triggered);
+
 #endif
diff --git a/arch/x86/include/asm/ioapic.h b/arch/x86/include/asm/ioapic.h
new file mode 100644
index 0000000..699160f
--- /dev/null
+++ b/arch/x86/include/asm/ioapic.h
@@ -0,0 +1,38 @@
+/*
+ * From coreboot file of the same name
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ASM_IOAPIC_H
+#define __ASM_IOAPIC_H
+
+#define IO_APIC_ADDR		0xfec00000
+#define IO_APIC_INDEX		IO_APIC_ADDR
+#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)
+
+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);
+
+#endif
diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h
index 948e643..0a7f443 100644
--- a/arch/x86/include/asm/lapic.h
+++ b/arch/x86/include/asm/lapic.h
@@ -14,6 +14,13 @@
 #include <asm/msr.h>
 #include <asm/processor.h>
 
+/* See if I need to initialize the local apic */
+#if CONFIG_SMP || CONFIG_IOAPIC
+#  define NEED_LAPIC 1
+#else
+#  define NEED_LAPIC 0
+#endif
+
 static inline __attribute__((always_inline))
 		unsigned long lapic_read(unsigned long reg)
 {
@@ -37,8 +44,9 @@
 
 	msr = msr_read(LAPIC_BASE_MSR);
 	msr.hi &= 0xffffff00;
-	msr.lo &= 0x000007ff;
-	msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11);
+	msr.lo |= LAPIC_BASE_MSR_ENABLE;
+	msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
+	msr.lo |= LAPIC_DEFAULT_BASE;
 	msr_write(LAPIC_BASE_MSR, msr);
 }
 
@@ -56,4 +64,116 @@
 	return lapic_read(LAPIC_ID) >> 24;
 }
 
+#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
+
+#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. --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;
+}
+
+
+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/msr-index.h b/arch/x86/include/asm/msr-index.h
index 6027d59..2cbb270 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -326,6 +326,8 @@
 #define MSR_AMD_PERF_STATUS		0xc0010063
 #define MSR_AMD_PERF_CTL		0xc0010062
 
+#define MSR_PMG_CST_CONFIG_CTL		0x000000e2
+#define MSR_PMG_IO_CAPTURE_ADR		0x000000e4
 #define MSR_IA32_MPERF			0x000000e7
 #define MSR_IA32_APERF			0x000000e8
 
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index df43983..1955a75 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -229,17 +229,6 @@
 struct msr *msrs_alloc(void);
 void msrs_free(struct msr *msrs);
 
-#ifdef CONFIG_SMP
-int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
-int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
-void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
-int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
-
-#endif  /* CONFIG_SMP */
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_X86_MSR_H */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 98817aa..ac1a808 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -34,6 +34,9 @@
  */
 int pci_early_init_hose(struct pci_controller **hosep);
 
+int board_pci_pre_scan(struct pci_controller *hose);
+int board_pci_post_scan(struct pci_controller *hose);
+
 /*
  * Simple PCI access routines - these work from either the early PCI hose
  * or the 'real' one, created after U-Boot has memory available
diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h
index ce68839..6d2ae5d 100644
--- a/arch/x86/include/asm/post.h
+++ b/arch/x86/include/asm/post.h
@@ -30,6 +30,7 @@
 #define POST_PRE_MRC		0x2e
 #define POST_MRC		0x2f
 #define POST_DRAM		0x2f
+#define POST_LAPIC		0x30
 
 #define POST_RAM_FAILURE	0xea
 
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index b9317cb..3e26202 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -8,25 +8,18 @@
 #ifndef __ASM_PROCESSOR_H_
 #define __ASM_PROCESSOR_H_ 1
 
-#define X86_GDT_ENTRY_SIZE	8
-
-#ifndef __ASSEMBLY__
+#define X86_GDT_ENTRY_SIZE		8
 
-enum {
-	X86_GDT_ENTRY_NULL = 0,
-	X86_GDT_ENTRY_UNUSED,
-	X86_GDT_ENTRY_32BIT_CS,
-	X86_GDT_ENTRY_32BIT_DS,
-	X86_GDT_ENTRY_32BIT_FS,
-	X86_GDT_ENTRY_16BIT_CS,
-	X86_GDT_ENTRY_16BIT_DS,
-	X86_GDT_NUM_ENTRIES
-};
-#else
-/* NOTE: If the above enum is modified, this define must be checked */
-#define X86_GDT_ENTRY_32BIT_DS	3
-#define X86_GDT_NUM_ENTRIES	7
-#endif
+#define X86_GDT_ENTRY_NULL		0
+#define X86_GDT_ENTRY_UNUSED		1
+#define X86_GDT_ENTRY_32BIT_CS		2
+#define X86_GDT_ENTRY_32BIT_DS		3
+#define X86_GDT_ENTRY_32BIT_FS		4
+#define X86_GDT_ENTRY_16BIT_CS		5
+#define X86_GDT_ENTRY_16BIT_DS		6
+#define X86_GDT_ENTRY_16BIT_FLAT_CS	7
+#define X86_GDT_ENTRY_16BIT_FLAT_DS	8
+#define X86_GDT_NUM_ENTRIES		9
 
 #define X86_GDT_SIZE		(X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE)
 
diff --git a/arch/x86/include/asm/speedstep.h b/arch/x86/include/asm/speedstep.h
new file mode 100644
index 0000000..b938b86
--- /dev/null
+++ b/arch/x86/include/asm/speedstep.h
@@ -0,0 +1,89 @@
+/*
+ * From Coreboot file of same name
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *               2012 secunet Security Networks AG
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_SPEEDSTEP_H
+#define _ASM_SPEEDSTEP_H
+
+/* Magic value used to locate speedstep configuration in the device tree */
+#define SPEEDSTEP_APIC_MAGIC 0xACAC
+
+/* MWAIT coordination I/O base address. This must match
+ * the \_PR_.CPU0 PM base address.
+ */
+#define PMB0_BASE 0x510
+
+/* PMB1: I/O port that triggers SMI once cores are in the same state.
+ * See CSM Trigger, at PMG_CST_CONFIG_CONTROL[6:4]
+ */
+#define PMB1_BASE 0x800
+
+struct sst_state {
+	uint8_t dynfsb:1; /* whether this is SLFM */
+	uint8_t nonint:1; /* add .5 to ratio */
+	uint8_t ratio:6;
+	uint8_t vid;
+	uint8_t is_turbo;
+	uint8_t is_slfm;
+	uint32_t power;
+};
+#define SPEEDSTEP_RATIO_SHIFT		8
+#define SPEEDSTEP_RATIO_DYNFSB_SHIFT	(7 + SPEEDSTEP_RATIO_SHIFT)
+#define SPEEDSTEP_RATIO_DYNFSB		(1 << SPEEDSTEP_RATIO_DYNFSB_SHIFT)
+#define SPEEDSTEP_RATIO_NONINT_SHIFT	(6 + SPEEDSTEP_RATIO_SHIFT)
+#define SPEEDSTEP_RATIO_NONINT		(1 << SPEEDSTEP_RATIO_NONINT_SHIFT)
+#define SPEEDSTEP_RATIO_VALUE_MASK	(0x1f << SPEEDSTEP_RATIO_SHIFT)
+#define SPEEDSTEP_VID_MASK		0x3f
+#define SPEEDSTEP_STATE_FROM_MSR(val, mask) ((struct sst_state){	\
+		0, /* dynfsb won't be read. */				\
+		((val & mask) & SPEEDSTEP_RATIO_NONINT) ? 1 : 0,	\
+		(((val & mask) & SPEEDSTEP_RATIO_VALUE_MASK)		\
+					>> SPEEDSTEP_RATIO_SHIFT),	\
+		(val & mask) & SPEEDSTEP_VID_MASK,			\
+		0, /* not turbo by default */				\
+		0, /* not slfm by default */				\
+		0  /* power is hardcoded in software. */		\
+	})
+#define SPEEDSTEP_ENCODE_STATE(state)	(				\
+	((uint16_t)(state).dynfsb << SPEEDSTEP_RATIO_DYNFSB_SHIFT) |	\
+	((uint16_t)(state).nonint << SPEEDSTEP_RATIO_NONINT_SHIFT) |	\
+	((uint16_t)(state).ratio << SPEEDSTEP_RATIO_SHIFT) |		\
+	((uint16_t)(state).vid & SPEEDSTEP_VID_MASK))
+#define SPEEDSTEP_DOUBLE_RATIO(state)	(				\
+	((uint8_t)(state).ratio * 2) + (state).nonint)
+
+struct sst_params {
+	struct sst_state slfm;
+	struct sst_state min;
+	struct sst_state max;
+	struct sst_state turbo;
+};
+
+/* Looking at core2's spec, the highest normal bus ratio for an eist enabled
+   processor is 14, the lowest is always 6. This makes 5 states with the
+   minimal step width of 2. With turbo mode and super LFM we have at most 7. */
+#define SPEEDSTEP_MAX_NORMAL_STATES	5
+#define SPEEDSTEP_MAX_STATES		(SPEEDSTEP_MAX_NORMAL_STATES + 2)
+struct sst_table {
+	/* Table of p-states for EMTTM and ACPI by decreasing performance. */
+	struct sst_state states[SPEEDSTEP_MAX_STATES];
+	int num_states;
+};
+
+void speedstep_gen_pstates(struct sst_table *);
+
+#define SPEEDSTEP_MAX_POWER_YONAH	31000
+#define SPEEDSTEP_MIN_POWER_YONAH	13100
+#define SPEEDSTEP_MAX_POWER_MEROM	35000
+#define SPEEDSTEP_MIN_POWER_MEROM	25000
+#define SPEEDSTEP_SLFM_POWER_MEROM	12000
+#define SPEEDSTEP_MAX_POWER_PENRYN	35000
+#define SPEEDSTEP_MIN_POWER_PENRYN	15000
+#define SPEEDSTEP_SLFM_POWER_PENRYN	12000
+
+#endif
diff --git a/arch/x86/include/asm/turbo.h b/arch/x86/include/asm/turbo.h
new file mode 100644
index 0000000..bb0d4b4
--- /dev/null
+++ b/arch/x86/include/asm/turbo.h
@@ -0,0 +1,31 @@
+/*
+ * From coreboot file of the same name
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_TURBO_H
+#define _ASM_TURBO_H
+
+#define CPUID_LEAF_PM		6
+#define PM_CAP_TURBO_MODE	(1 << 1)
+
+#define MSR_IA32_MISC_ENABLES	0x1a0
+#define H_MISC_DISABLE_TURBO	(1 << 6)
+
+enum {
+	TURBO_UNKNOWN,
+	TURBO_UNAVAILABLE,
+	TURBO_DISABLED,
+	TURBO_ENABLED,
+};
+
+/* Return current turbo state */
+int turbo_get_state(void);
+
+/* Enable turbo */
+void turbo_enable(void);
+
+#endif
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 98217dd..36145cb 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -10,8 +10,6 @@
 
 /* cpu/.../cpu.c */
 int arch_cpu_init(void);
-int x86_cpu_init_r(void);
-int cpu_init_r(void);
 int x86_cpu_init_f(void);
 int cpu_init_f(void);
 void init_gd(gd_t *id, u64 *gdt_addr);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index e146e64..55de788 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -5,6 +5,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-y += bios.o
+obj-y += bios_asm.o
+obj-y += bios_interrupts.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-y	+= cmd_boot.o
 obj-y	+= gcc.o
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
new file mode 100644
index 0000000..298fca6
--- /dev/null
+++ b/arch/x86/lib/bios.c
@@ -0,0 +1,347 @@
+/*
+ * From Coreboot file device/oprom/realmode/x86.c
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009-2010 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+#include <common.h>
+#include <bios_emul.h>
+#include <vbe.h>
+#include <asm/cache.h>
+#include <asm/processor.h>
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/post.h>
+#include "bios.h"
+
+/* Interrupt handlers for each interrupt the ROM can call */
+static int (*int_handler[256])(void);
+
+/* to have a common register file for interrupt handlers */
+X86EMU_sysEnv _X86EMU_env;
+
+asmlinkage void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
+				 u32 esi, u32 edi);
+
+asmlinkage void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx,
+				      u32 edx, u32 esi, u32 edi);
+
+static void setup_realmode_code(void)
+{
+	memcpy((void *)REALMODE_BASE, &asm_realmode_code,
+	       asm_realmode_code_size);
+
+	/* Ensure the global pointers are relocated properly. */
+	realmode_call = PTR_TO_REAL_MODE(asm_realmode_call);
+	realmode_interrupt = PTR_TO_REAL_MODE(__realmode_interrupt);
+
+	debug("Real mode stub @%x: %d bytes\n", REALMODE_BASE,
+	      asm_realmode_code_size);
+}
+
+static void setup_rombios(void)
+{
+	const char date[] = "06/11/99";
+	memcpy((void *)0xffff5, &date, 8);
+
+	const char ident[] = "PCI_ISA";
+	memcpy((void *)0xfffd9, &ident, 7);
+
+	/* system model: IBM-AT */
+	writeb(0xfc, 0xffffe);
+}
+
+static int int_exception_handler(void)
+{
+	/* compatibility shim */
+	struct eregs reg_info = {
+		.eax = M.x86.R_EAX,
+		.ecx = M.x86.R_ECX,
+		.edx = M.x86.R_EDX,
+		.ebx = M.x86.R_EBX,
+		.esp = M.x86.R_ESP,
+		.ebp = M.x86.R_EBP,
+		.esi = M.x86.R_ESI,
+		.edi = M.x86.R_EDI,
+		.vector = M.x86.intno,
+		.error_code = 0,
+		.eip = M.x86.R_EIP,
+		.cs = M.x86.R_CS,
+		.eflags = M.x86.R_EFLG
+	};
+	struct eregs *regs = &reg_info;
+
+	debug("Oops, exception %d while executing option rom\n", regs->vector);
+	cpu_hlt();
+
+	return 0;
+}
+
+static int int_unknown_handler(void)
+{
+	debug("Unsupported software interrupt #0x%x eax 0x%x\n",
+	      M.x86.intno, M.x86.R_EAX);
+
+	return -1;
+}
+
+/* setup interrupt handlers for mainboard */
+void bios_set_interrupt_handler(int intnum, int (*int_func)(void))
+{
+	int_handler[intnum] = int_func;
+}
+
+static void setup_interrupt_handlers(void)
+{
+	int i;
+
+	/*
+	 * The first 16 int_handler functions are not BIOS services,
+	 * but the CPU-generated exceptions ("hardware interrupts")
+	 */
+	for (i = 0; i < 0x10; i++)
+		int_handler[i] = &int_exception_handler;
+
+	/* Mark all other int_handler calls as unknown first */
+	for (i = 0x10; i < 0x100; i++) {
+		/* Skip if bios_set_interrupt_handler() isn't called first */
+		if (int_handler[i])
+			continue;
+
+		 /*
+		  * Now set the default functions that are actually needed
+		  * to initialize the option roms. The board may override
+		  * these with bios_set_interrupt_handler()
+		 */
+		switch (i) {
+		case 0x10:
+			int_handler[0x10] = &int10_handler;
+			break;
+		case 0x12:
+			int_handler[0x12] = &int12_handler;
+			break;
+		case 0x16:
+			int_handler[0x16] = &int16_handler;
+			break;
+		case 0x1a:
+			int_handler[0x1a] = &int1a_handler;
+			break;
+		default:
+			int_handler[i] = &int_unknown_handler;
+			break;
+		}
+	}
+}
+
+static void write_idt_stub(void *target, u8 intnum)
+{
+	unsigned char *codeptr;
+
+	codeptr = (unsigned char *)target;
+	memcpy(codeptr, &__idt_handler, __idt_handler_size);
+	codeptr[3] = intnum; /* modify int# in the code stub. */
+}
+
+static void setup_realmode_idt(void)
+{
+	struct realmode_idt *idts = NULL;
+	int i;
+
+	/*
+	 * Copy IDT stub code for each interrupt. This might seem wasteful
+	 * but it is really simple
+	 */
+	 for (i = 0; i < 256; i++) {
+		idts[i].cs = 0;
+		idts[i].offset = 0x1000 + (i * __idt_handler_size);
+		write_idt_stub((void *)((u32)idts[i].offset), i);
+	}
+
+	/*
+	 * Many option ROMs use the hard coded interrupt entry points in the
+	 * system bios. So install them at the known locations.
+	 */
+
+	/* int42 is the relocated int10 */
+	write_idt_stub((void *)0xff065, 0x42);
+	/* BIOS Int 11 Handler F000:F84D */
+	write_idt_stub((void *)0xff84d, 0x11);
+	/* BIOS Int 12 Handler F000:F841 */
+	write_idt_stub((void *)0xff841, 0x12);
+	/* BIOS Int 13 Handler F000:EC59 */
+	write_idt_stub((void *)0xfec59, 0x13);
+	/* BIOS Int 14 Handler F000:E739 */
+	write_idt_stub((void *)0xfe739, 0x14);
+	/* BIOS Int 15 Handler F000:F859 */
+	write_idt_stub((void *)0xff859, 0x15);
+	/* BIOS Int 16 Handler F000:E82E */
+	write_idt_stub((void *)0xfe82e, 0x16);
+	/* BIOS Int 17 Handler F000:EFD2 */
+	write_idt_stub((void *)0xfefd2, 0x17);
+	/* ROM BIOS Int 1A Handler F000:FE6E */
+	write_idt_stub((void *)0xffe6e, 0x1a);
+}
+
+static u8 vbe_get_mode_info(struct vbe_mode_info *mi)
+{
+	u16 buffer_seg;
+	u16 buffer_adr;
+	char *buffer;
+
+	debug("VBE: Getting information about VESA mode %04x\n",
+	      mi->video_mode);
+	buffer = PTR_TO_REAL_MODE(asm_realmode_buffer);
+	buffer_seg = (((unsigned long)buffer) >> 4) & 0xff00;
+	buffer_adr = ((unsigned long)buffer) & 0xffff;
+
+	realmode_interrupt(0x10, VESA_GET_MODE_INFO, 0x0000, mi->video_mode,
+			   0x0000, buffer_seg, buffer_adr);
+	memcpy(mi->mode_info_block, buffer, sizeof(struct vbe_mode_info));
+	mi->valid = true;
+
+	return 0;
+}
+
+static u8 vbe_set_mode(struct vbe_mode_info *mi)
+{
+	debug("VBE: Setting VESA mode %#04x\n", mi->video_mode);
+	/* request linear framebuffer mode */
+	mi->video_mode |= (1 << 14);
+	/* request clearing of framebuffer */
+	mi->video_mode &= ~(1 << 15);
+	realmode_interrupt(0x10, VESA_SET_MODE, mi->video_mode,
+			   0x0000, 0x0000, 0x0000, 0x0000);
+
+	return 0;
+}
+
+static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info)
+{
+	unsigned char *framebuffer;
+
+	mode_info->video_mode = (1 << 14) | vesa_mode;
+	vbe_get_mode_info(mode_info);
+
+	framebuffer = (unsigned char *)mode_info->vesa.phys_base_ptr;
+	debug("VBE: resolution:  %dx%d@%d\n",
+	      le16_to_cpu(mode_info->vesa.x_resolution),
+	      le16_to_cpu(mode_info->vesa.y_resolution),
+	      mode_info->vesa.bits_per_pixel);
+	debug("VBE: framebuffer: %p\n", framebuffer);
+	if (!framebuffer) {
+		debug("VBE: Mode does not support linear framebuffer\n");
+		return;
+	}
+
+	vbe_set_mode(mode_info);
+}
+
+void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode,
+		     struct vbe_mode_info *mode_info)
+{
+	u32 num_dev;
+
+	num_dev = PCI_BUS(pcidev) << 8 | PCI_DEV(pcidev) << 3 |
+			PCI_FUNC(pcidev);
+
+	/* Needed to avoid exceptions in some ROMs */
+	interrupt_init();
+
+	/* Set up some legacy information in the F segment */
+	setup_rombios();
+
+	/* Set up C interrupt handlers */
+	setup_interrupt_handlers();
+
+	/* Set up real-mode IDT */
+	setup_realmode_idt();
+
+	/* Make sure the code is placed. */
+	setup_realmode_code();
+
+	disable_caches();
+	debug("Calling Option ROM at %lx, pci device %#x...", addr, num_dev);
+
+	/* Option ROM entry point is at OPROM start + 3 */
+	realmode_call(addr + 0x0003, num_dev, 0xffff, 0x0000, 0xffff, 0x0,
+		      0x0);
+	debug("done\n");
+
+	if (vesa_mode != -1)
+		vbe_set_graphics(vesa_mode, mode_info);
+}
+
+asmlinkage int interrupt_handler(u32 intnumber, u32 gsfs, u32 dses,
+				 u32 edi, u32 esi, u32 ebp, u32 esp,
+				 u32 ebx, u32 edx, u32 ecx, u32 eax,
+				 u32 cs_ip, u16 stackflags)
+{
+	u32 ip;
+	u32 cs;
+	u32 flags;
+	int ret = 0;
+
+	ip = cs_ip & 0xffff;
+	cs = cs_ip >> 16;
+	flags = stackflags;
+
+#ifdef CONFIG_REALMODE_DEBUG
+	debug("oprom: INT# 0x%x\n", intnumber);
+	debug("oprom: eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
+	      eax, ebx, ecx, edx);
+	debug("oprom: ebp: %08x esp: %08x edi: %08x esi: %08x\n",
+	      ebp, esp, edi, esi);
+	debug("oprom:  ip: %04x      cs: %04x   flags: %08x\n",
+	      ip, cs, flags);
+	debug("oprom: stackflags = %04x\n", stackflags);
+#endif
+
+	/*
+	 * Fetch arguments from the stack and put them to a place
+	 * suitable for the interrupt handlers
+	 */
+	M.x86.R_EAX = eax;
+	M.x86.R_ECX = ecx;
+	M.x86.R_EDX = edx;
+	M.x86.R_EBX = ebx;
+	M.x86.R_ESP = esp;
+	M.x86.R_EBP = ebp;
+	M.x86.R_ESI = esi;
+	M.x86.R_EDI = edi;
+	M.x86.intno = intnumber;
+	M.x86.R_EIP = ip;
+	M.x86.R_CS = cs;
+	M.x86.R_EFLG = flags;
+
+	/* Call the interrupt handler for this interrupt number */
+	ret = int_handler[intnumber]();
+
+	/*
+	 * This code is quite strange...
+	 *
+	 * Put registers back on the stack. The assembler code will pop them
+	 * later. We force (volatile!) changing the values of the parameters
+	 * of this function. We know that they stay alive on the stack after
+	 * we leave this function.
+	 */
+	*(volatile u32 *)&eax = M.x86.R_EAX;
+	*(volatile u32 *)&ecx = M.x86.R_ECX;
+	*(volatile u32 *)&edx = M.x86.R_EDX;
+	*(volatile u32 *)&ebx = M.x86.R_EBX;
+	*(volatile u32 *)&esi = M.x86.R_ESI;
+	*(volatile u32 *)&edi = M.x86.R_EDI;
+	flags = M.x86.R_EFLG;
+
+	/* Pass success or error back to our caller via the CARRY flag */
+	if (ret) {
+		flags &= ~1; /* no error: clear carry */
+	} else {
+		debug("int%02x call returned error\n", intnumber);
+		flags |= 1;  /* error: set carry */
+	}
+	*(volatile u16 *)&stackflags = flags;
+
+	return ret;
+}
diff --git a/arch/x86/lib/bios.h b/arch/x86/lib/bios.h
new file mode 100644
index 0000000..8491b4a
--- /dev/null
+++ b/arch/x86/lib/bios.h
@@ -0,0 +1,98 @@
+/*
+ * From Coreboot file device/oprom/realmode/x86.h
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009-2010 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _X86_LIB_BIOS_H
+#define _X86_LIB_BIOS_H
+
+#define REALMODE_BASE		0x600
+
+#ifdef __ASSEMBLY__
+
+#define PTR_TO_REAL_MODE(x)	(x - asm_realmode_code + REALMODE_BASE)
+
+#else
+
+/* Convert a symbol address to our real mode area */
+#define PTR_TO_REAL_MODE(sym)\
+	(void *)(REALMODE_BASE + ((char *)&(sym) - (char *)&asm_realmode_code))
+
+/*
+ * The following symbols cannot be used directly. They need to be fixed up
+ * to point to the correct address location after the code has been copied
+ * to REALMODE_BASE. Absolute symbols are not used because those symbols are
+ * relocated by U-Boot.
+ */
+extern unsigned char asm_realmode_call, __realmode_interrupt;
+extern unsigned char asm_realmode_buffer;
+
+#define DOWNTO8(A) \
+	union { \
+		struct { \
+			union { \
+				struct { \
+					uint8_t A##l; \
+					uint8_t A##h; \
+				} __packed; \
+				uint16_t A##x; \
+			} __packed; \
+			uint16_t h##A##x; \
+		} __packed; \
+		uint32_t e##A##x; \
+	} __packed;
+
+#define DOWNTO16(A) \
+	union { \
+		struct { \
+			uint16_t A; \
+			uint16_t h##A; \
+		} __packed; \
+		uint32_t e##A; \
+	} __packed;
+
+struct eregs {
+	DOWNTO8(a);
+	DOWNTO8(c);
+	DOWNTO8(d);
+	DOWNTO8(b);
+	DOWNTO16(sp);
+	DOWNTO16(bp);
+	DOWNTO16(si);
+	DOWNTO16(di);
+	uint32_t vector;
+	uint32_t error_code;
+	uint32_t eip;
+	uint32_t cs;
+	uint32_t eflags;
+};
+
+struct realmode_idt {
+	u16 offset, cs;
+};
+
+void x86_exception(struct eregs *info);
+
+/* From x86_asm.S */
+extern unsigned char __idt_handler;
+extern unsigned int __idt_handler_size;
+extern unsigned char asm_realmode_code;
+extern unsigned int asm_realmode_code_size;
+
+asmlinkage void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
+				 u32 esi, u32 edi);
+
+asmlinkage void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx,
+				      u32 edx, u32 esi, u32 edi);
+
+int int10_handler(void);
+int int12_handler(void);
+int int16_handler(void);
+int int1a_handler(void);
+#endif /*__ASSEMBLY__ */
+
+#endif
diff --git a/arch/x86/lib/bios_asm.S b/arch/x86/lib/bios_asm.S
new file mode 100644
index 0000000..4faa70e
--- /dev/null
+++ b/arch/x86/lib/bios_asm.S
@@ -0,0 +1,281 @@
+/*
+ * From coreboot x86_asm.S, cleaned up substantially
+ *
+ * Copyright (C) 2009-2010 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include "bios.h"
+
+#define SEG(segment)	$segment * X86_GDT_ENTRY_SIZE
+
+/*
+ * This is the interrupt handler stub code. It gets copied to the IDT and
+ * to some fixed addresses in the F segment. Before the code can used,
+ * it gets patched up by the C function copying it: byte 3 (the $0 in
+ * movb $0, %al) is overwritten with the interrupt numbers.
+ */
+
+	.code16
+	.globl __idt_handler
+__idt_handler:
+	pushal
+	movb 	$0, %al /* This instruction gets modified */
+	ljmp 	$0, $__interrupt_handler_16bit
+	.globl __idt_handler_size
+__idt_handler_size:
+	.long  . - __idt_handler
+
+.macro setup_registers
+	/* initial register values */
+	movl	44(%ebp), %eax
+	movl	%eax, __registers +  0 /* eax */
+	movl	48(%ebp), %eax
+	movl	%eax, __registers +  4 /* ebx */
+	movl	52(%ebp), %eax
+	movl	%eax, __registers +  8 /* ecx */
+	movl	56(%ebp), %eax
+	movl	%eax, __registers + 12 /* edx */
+	movl	60(%ebp), %eax
+	movl	%eax, __registers + 16 /* esi */
+	movl	64(%ebp), %eax
+	movl	%eax, __registers + 20 /* edi */
+.endm
+
+.macro	enter_real_mode
+	/* Activate the right segment descriptor real mode. */
+	ljmp	SEG(X86_GDT_ENTRY_16BIT_CS), $PTR_TO_REAL_MODE(1f)
+1:
+.code16
+	/*
+	 * Load the segment registers with properly configured segment
+	 * descriptors. They will retain these configurations (limits,
+	 * writability, etc.) once protected mode is turned off.
+	 */
+	mov	SEG(X86_GDT_ENTRY_16BIT_DS), %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	%ax, %ss
+
+	/* Turn off protection */
+	movl	%cr0, %eax
+	andl	$~X86_CR0_PE, %eax
+	movl	%eax, %cr0
+
+	/* Now really going into real mode */
+	ljmp	$0, $PTR_TO_REAL_MODE(1f)
+1:
+	/*
+	 * Set up a stack: Put the stack at the end of page zero. That way
+	 * we can easily share it between real and protected, since the
+	 * 16-bit ESP at segment 0 will work for any case.
+	 */
+	mov	$0x0, %ax
+	mov	%ax, %ss
+
+	/* Load 16 bit IDT */
+	xor	%ax, %ax
+	mov	%ax, %ds
+	lidt	__realmode_idt
+
+.endm
+
+.macro	prepare_for_irom
+	movl	$0x1000, %eax
+	movl	%eax, %esp
+
+	/* Initialise registers for option rom lcall */
+	movl	__registers +  0, %eax
+	movl	__registers +  4, %ebx
+	movl	__registers +  8, %ecx
+	movl	__registers + 12, %edx
+	movl	__registers + 16, %esi
+	movl	__registers + 20, %edi
+
+	/* Set all segments to 0x0000, ds to 0x0040 */
+	push	%ax
+	xor	%ax, %ax
+	mov	%ax, %es
+	mov	%ax, %fs
+	mov	%ax, %gs
+	mov	SEG(X86_GDT_ENTRY_16BIT_FLAT_DS), %ax
+	mov	%ax, %ds
+	pop	%ax
+
+.endm
+
+.macro	enter_protected_mode
+	/* Go back to protected mode */
+	movl	%cr0, %eax
+	orl	$X86_CR0_PE, %eax
+	movl	%eax, %cr0
+
+	/* Now that we are in protected mode jump to a 32 bit code segment */
+	data32	ljmp	SEG(X86_GDT_ENTRY_32BIT_CS), $PTR_TO_REAL_MODE(1f)
+1:
+	.code32
+	mov	SEG(X86_GDT_ENTRY_32BIT_DS), %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %gs
+	mov	%ax, %ss
+	mov	SEG(X86_GDT_ENTRY_32BIT_FS), %ax
+	mov	%ax, %fs
+
+	/* restore proper idt */
+	lidt	idt_ptr
+.endm
+
+/*
+ * In order to be independent of U-Boot's position in RAM we relocate a part
+ * of the code to the first megabyte of RAM, so the CPU can use it in
+ * real-mode. This code lives at asm_realmode_code.
+ */
+	.globl asm_realmode_code
+asm_realmode_code:
+
+/* Realmode IDT pointer structure. */
+__realmode_idt = PTR_TO_REAL_MODE(.)
+	.word 1023	/* 16 bit limit */
+	.long 0		/* 24 bit base */
+	.word 0
+
+/* Preserve old stack */
+__stack = PTR_TO_REAL_MODE(.)
+	.long 0
+
+/* Register store for realmode_call and realmode_interrupt */
+__registers = PTR_TO_REAL_MODE(.)
+	.long 0 /*  0 - EAX */
+	.long 0 /*  4 - EBX */
+	.long 0 /*  8 - ECX */
+	.long 0 /* 12 - EDX */
+	.long 0 /* 16 - ESI */
+	.long 0 /* 20 - EDI */
+
+/* 256 byte buffer, used by int10 */
+	.globl asm_realmode_buffer
+asm_realmode_buffer:
+	.skip 256
+
+	.code32
+	.globl asm_realmode_call
+asm_realmode_call:
+	/* save all registers to the stack */
+	pusha
+	pushf
+	movl	%esp, __stack
+	movl	%esp, %ebp
+
+	/*
+	 * This function is called with regparm=0 and we have to skip the
+	 * 36 bytes from pushf+pusha. Hence start at 40.
+	 * Set up our call instruction.
+	 */
+	movl	40(%ebp), %eax
+	mov	%ax, __lcall_instr + 1
+	andl	$0xffff0000, %eax
+	shrl	$4, %eax
+	mov	%ax, __lcall_instr + 3
+
+	wbinvd
+
+	setup_registers
+	enter_real_mode
+	prepare_for_irom
+
+__lcall_instr = PTR_TO_REAL_MODE(.)
+	.byte 0x9a
+	.word 0x0000, 0x0000
+
+	enter_protected_mode
+
+	/* restore stack pointer, eflags and register values and exit */
+	movl	__stack, %esp
+	popf
+	popa
+	ret
+
+	.globl __realmode_interrupt
+__realmode_interrupt:
+	/* save all registers to the stack and store the stack pointer */
+	pusha
+	pushf
+	movl	%esp, __stack
+	movl	%esp, %ebp
+
+	/*
+	 * This function is called with regparm=0 and we have to skip the
+	 * 36 bytes from pushf+pusha. Hence start at 40.
+	 * Prepare interrupt calling code.
+	 */
+	movl	40(%ebp), %eax
+	movb	%al, __intXX_instr + 1 /* intno */
+
+	setup_registers
+	enter_real_mode
+	prepare_for_irom
+
+__intXX_instr = PTR_TO_REAL_MODE(.)
+	.byte 0xcd, 0x00 /* This becomes intXX */
+
+	enter_protected_mode
+
+	/* restore stack pointer, eflags and register values and exit */
+	movl	__stack, %esp
+	popf
+	popa
+	ret
+
+/*
+ * This is the 16-bit interrupt entry point called by the IDT stub code.
+ *
+ * Before this code code is called, %eax is pushed to the stack, and the
+ * interrupt number is loaded into %al. On return this function cleans up
+ * for its caller.
+ */
+	.code16
+__interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
+	push	%ds
+	push	%es
+	push	%fs
+	push	%gs
+
+	/* Clear DF to not break ABI assumptions */
+	cld
+
+	/*
+	 * Clean up the interrupt number. We could do this in the stub, but
+	 * it would cost two more bytes per stub entry.
+	 */
+	andl	$0xff, %eax
+	pushl	%eax		/* ... and make it the first parameter */
+
+	enter_protected_mode
+
+	/* Call the C interrupt handler */
+	movl	$interrupt_handler, %eax
+	call	*%eax
+
+	enter_real_mode
+
+	/*
+	 * Restore all registers, including those manipulated by the C
+	 * handler
+	 */
+	popl	%eax
+	pop	%gs
+	pop	%fs
+	pop	%es
+	pop	%ds
+	popal
+	iret
+
+	.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
new file mode 100644
index 0000000..b0e2ecb
--- /dev/null
+++ b/arch/x86/lib/bios_interrupts.c
@@ -0,0 +1,217 @@
+/*
+ * From Coreboot
+ *
+ * Copyright (C) 2001 Ronald G. Minnich
+ * Copyright (C) 2005 Nick.Barker9@btinternet.com
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/pci.h>
+#include "bios_emul.h"
+
+/* errors go in AH. Just set these up so that word assigns will work */
+enum {
+	PCIBIOS_SUCCESSFUL = 0x0000,
+	PCIBIOS_UNSUPPORTED = 0x8100,
+	PCIBIOS_BADVENDOR = 0x8300,
+	PCIBIOS_NODEV = 0x8600,
+	PCIBIOS_BADREG = 0x8700
+};
+
+int int10_handler(void)
+{
+	static u8 cursor_row, cursor_col;
+	int res = 0;
+
+	switch ((M.x86.R_EAX & 0xff00) >> 8) {
+	case 0x01: /* Set cursor shape */
+		res = 1;
+		break;
+	case 0x02: /* Set cursor position */
+		if (cursor_row != ((M.x86.R_EDX >> 8) & 0xff) ||
+		    cursor_col >= (M.x86.R_EDX & 0xff)) {
+			debug("\n");
+		}
+		cursor_row = (M.x86.R_EDX >> 8) & 0xff;
+		cursor_col = M.x86.R_EDX & 0xff;
+		res = 1;
+		break;
+	case 0x03: /* Get cursor position */
+		M.x86.R_EAX &= 0x00ff;
+		M.x86.R_ECX = 0x0607;
+		M.x86.R_EDX = (cursor_row << 8) | cursor_col;
+		res = 1;
+		break;
+	case 0x06: /* Scroll up */
+		debug("\n");
+		res = 1;
+		break;
+	case 0x08: /* Get Character and Mode at Cursor Position */
+		M.x86.R_EAX = 0x0f00 | 'A'; /* White on black 'A' */
+		res = 1;
+		break;
+	case 0x09: /* Write Character and attribute */
+	case 0x0e: /* Write Character */
+		debug("%c", M.x86.R_EAX & 0xff);
+		res = 1;
+		break;
+	case 0x0f: /* Get video mode */
+		M.x86.R_EAX = 0x5002; /*80 x 25 */
+		M.x86.R_EBX &= 0x00ff;
+		res = 1;
+		break;
+	default:
+		printf("Unknown INT10 function %04x\n", M.x86.R_EAX & 0xffff);
+		break;
+	}
+	return res;
+}
+
+int int12_handler(void)
+{
+	M.x86.R_EAX = 64 * 1024;
+	return 1;
+}
+
+int int16_handler(void)
+{
+	int res = 0;
+
+	switch ((M.x86.R_EAX & 0xff00) >> 8) {
+	case 0x00: /* Check for Keystroke */
+		M.x86.R_EAX = 0x6120; /* Space Bar, Space */
+		res = 1;
+		break;
+	case 0x01: /* Check for Keystroke */
+		M.x86.R_EFLG |= 1 << 6; /* Zero Flag set (no key available) */
+		res = 1;
+		break;
+	default:
+		printf("Unknown INT16 function %04x\n", M.x86.R_EAX & 0xffff);
+
+break;
+	}
+	return res;
+}
+
+#define PCI_CONFIG_SPACE_TYPE1	(1 << 0)
+#define PCI_SPECIAL_CYCLE_TYPE1	(1 << 4)
+
+int int1a_handler(void)
+{
+	unsigned short func = (unsigned short)M.x86.R_EAX;
+	int retval = 1;
+	unsigned short devid, vendorid, devfn;
+	/* Use short to get rid of gabage in upper half of 32-bit register */
+	short devindex;
+	unsigned char bus;
+	pci_dev_t dev;
+	u32 dword;
+	u16 word;
+	u8 byte, reg;
+
+	switch (func) {
+	case 0xb101: /* PCIBIOS Check */
+		M.x86.R_EDX = 0x20494350;	/* ' ICP' */
+		M.x86.R_EAX &= 0xffff0000; /* Clear AH / AL */
+		M.x86.R_EAX |= PCI_CONFIG_SPACE_TYPE1 |
+				PCI_SPECIAL_CYCLE_TYPE1;
+		/*
+		 * last bus in the system. Hard code to 255 for now.
+		 * dev_enumerate() does not seem to tell us (publically)
+		 */
+		M.x86.R_ECX = 0xff;
+		M.x86.R_EDI = 0x00000000;	/* protected mode entry */
+		retval = 1;
+		break;
+	case 0xb102: /* Find Device */
+		devid = M.x86.R_ECX;
+		vendorid = M.x86.R_EDX;
+		devindex = M.x86.R_ESI;
+		dev = pci_find_device(vendorid, devid, devindex);
+		if (dev != -1) {
+			unsigned short busdevfn;
+			M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
+			M.x86.R_EAX |= PCIBIOS_SUCCESSFUL;
+			/*
+			 * busnum is an unsigned char;
+			 * devfn is an int, so we mask it off.
+			 */
+			busdevfn = (PCI_BUS(dev) << 8) | PCI_DEV(dev) << 3 |
+				PCI_FUNC(dev);
+			debug("0x%x: return 0x%x\n", func, busdevfn);
+			M.x86.R_EBX = busdevfn;
+			retval = 1;
+		} else {
+			M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
+			M.x86.R_EAX |= PCIBIOS_NODEV;
+			retval = 0;
+		}
+		break;
+	case 0xb10a: /* Read Config Dword */
+	case 0xb109: /* Read Config Word */
+	case 0xb108: /* Read Config Byte */
+	case 0xb10d: /* Write Config Dword */
+	case 0xb10c: /* Write Config Word */
+	case 0xb10b: /* Write Config Byte */
+		devfn = M.x86.R_EBX & 0xff;
+		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 = pci_read_config8(dev, reg);
+			M.x86.R_ECX = byte;
+			break;
+		case 0xb109: /* Read Config Word */
+			word = pci_read_config16(dev, reg);
+			M.x86.R_ECX = word;
+			break;
+		case 0xb10a: /* Read Config Dword */
+			dword = pci_read_config32(dev, reg);
+			M.x86.R_ECX = dword;
+			break;
+		case 0xb10b: /* Write Config Byte */
+			byte = M.x86.R_ECX;
+			pci_write_config8(dev, reg, byte);
+			break;
+		case 0xb10c: /* Write Config Word */
+			word = M.x86.R_ECX;
+			pci_write_config16(dev, reg, word);
+			break;
+		case 0xb10d: /* Write Config Dword */
+			dword = M.x86.R_ECX;
+			pci_write_config32(dev, reg, dword);
+			break;
+		}
+
+#ifdef CONFIG_REALMODE_DEBUG
+		debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n", func,
+		      bus, devfn, reg, M.x86.R_ECX);
+#endif
+		M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
+		M.x86.R_EAX |= PCIBIOS_SUCCESSFUL;
+		retval = 1;
+		break;
+	default:
+		printf("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
+		M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
+		M.x86.R_EAX |= PCIBIOS_UNSUPPORTED;
+		retval = 0;
+		break;
+	}
+
+	return retval;
+}
diff --git a/arch/x86/lib/pcat_interrupts.c b/arch/x86/lib/pcat_interrupts.c
index 4c86f7f..a9af87e 100644
--- a/arch/x86/lib/pcat_interrupts.c
+++ b/arch/x86/lib/pcat_interrupts.c
@@ -24,12 +24,10 @@
 #error "CONFIG_SYS_NUM_IRQS must equal 16 if CONFIG_SYS_NUM_IRQS is defined"
 #endif
 
-int interrupt_init(void)
+int i8259_init(void)
 {
 	u8 i;
 
-	disable_interrupts();
-
 	/* Mask all interrupts */
 	outb(0xff, MASTER_PIC + IMR);
 	outb(0xff, SLAVE_PIC + IMR);
@@ -62,7 +60,8 @@
 	 */
 	unmask_irq(2);
 
-	enable_interrupts();
+	/* Interrupt 9 should be level triggered (SCI). The OS might do this */
+	configure_irq_trigger(9, true);
 
 	return 0;
 }
@@ -114,3 +113,38 @@
 
 	outb(OCW2_SEOI | irq, MASTER_PIC + OCW2);
 }
+
+#define ELCR1			0x4d0
+#define ELCR2			0x4d1
+
+void configure_irq_trigger(int int_num, bool is_level_triggered)
+{
+	u16 int_bits = inb(ELCR1) | (((u16)inb(ELCR2)) << 8);
+
+	debug("%s: current interrupts are 0x%x\n", __func__, int_bits);
+	if (is_level_triggered)
+		int_bits |= (1 << int_num);
+	else
+		int_bits &= ~(1 << int_num);
+
+	/* Write new values */
+	debug("%s: try to set interrupts 0x%x\n", __func__, int_bits);
+	outb((u8)(int_bits & 0xff), ELCR1);
+	outb((u8)(int_bits >> 8), ELCR2);
+
+#ifdef PARANOID_IRQ_TRIGGERS
+	/*
+	 * Try reading back the new values. This seems like an error but is
+	 * not
+	 */
+	if (inb(ELCR1) != (int_bits & 0xff)) {
+		printf("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
+		       __func__, (int_bits & 0xff), inb(ELCR1));
+	}
+
+	if (inb(ELCR2) != (int_bits >> 8)) {
+		printf("%s: higher order bits are wrong: want 0x%x, got 0x%x\n",
+		       __func__, (int_bits>>8), inb(ELCR2));
+	}
+#endif
+}
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c
index faca38f..b33586b 100644
--- a/arch/x86/lib/relocate.c
+++ b/arch/x86/lib/relocate.c
@@ -76,6 +76,9 @@
 	/* The size of the region of u-boot that runs out of RAM. */
 	uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
 
+	if (re_src == re_end)
+		panic("No relocation data");
+
 	do {
 		/* Get the location from the relocation entry */
 		offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
diff --git a/board/google/chromebook_link/link.c b/board/google/chromebook_link/link.c
index 88cee05..1822237 100644
--- a/board/google/chromebook_link/link.c
+++ b/board/google/chromebook_link/link.c
@@ -5,15 +5,14 @@
  */
 
 #include <common.h>
+#include <cros_ec.h>
 #include <asm/gpio.h>
 
 int arch_early_init_r(void)
 {
-	return 0;
-}
+	if (cros_ec_board_init())
+		return -1;
 
-int board_early_init_r(void)
-{
 	return 0;
 }
 
diff --git a/common/board_r.c b/common/board_r.c
index 19c6427..1b8998d 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -775,7 +775,7 @@
 	initr_flash,
 #endif
 	INIT_FUNC_WATCHDOG_RESET
-#if defined(CONFIG_PPC) || defined(CONFIG_X86)
+#if defined(CONFIG_PPC)
 	/* initialize higher level parts of CPU like time base and timers */
 	cpu_init_r,
 #endif
@@ -838,11 +838,8 @@
 #ifdef CONFIG_CMD_KGDB
 	initr_kgdb,
 #endif
-#ifdef CONFIG_X86
-	board_early_init_r,
-#endif
 	interrupt_init,
-#if defined(CONFIG_ARM) || defined(CONFIG_x86)
+#if defined(CONFIG_ARM)
 	initr_enable_interrupts,
 #endif
 #ifdef CONFIG_X86
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 127e17c..8266bca 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -371,22 +371,22 @@
 			int n)
 {
 	int i;
-	int address_len = fdt_address_cells(fdt, 0);
-	int size_len = fdt_size_cells(fdt, 0);
+	int address_cells = fdt_address_cells(fdt, 0);
+	int size_cells = fdt_size_cells(fdt, 0);
 	char *p = buf;
 
 	for (i = 0; i < n; i++) {
-		if (address_len == 2)
+		if (address_cells == 2)
 			*(fdt64_t *)p = cpu_to_fdt64(address[i]);
 		else
 			*(fdt32_t *)p = cpu_to_fdt32(address[i]);
-		p += address_len;
+		p += 4 * address_cells;
 
-		if (size_len == 2)
+		if (size_cells == 2)
 			*(fdt64_t *)p = cpu_to_fdt64(size[i]);
 		else
 			*(fdt32_t *)p = cpu_to_fdt32(size[i]);
-		p += size_len;
+		p += 4 * size_cells;
 	}
 
 	return p - (char *)buf;
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 1d76bd6..8db3ccb 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -413,11 +413,11 @@
 			}
 		} else {
 			debug("## No Flattened Device Tree\n");
-			goto error;
+			return 0;
 		}
 	} else {
 		debug("## No Flattened Device Tree\n");
-		goto error;
+		return 0;
 	}
 
 	*of_flat_tree = fdt_blob;
diff --git a/configs/ph1_ld4_defconfig b/configs/ph1_ld4_defconfig
index f54b15f..de068e9 100644
--- a/configs/ph1_ld4_defconfig
+++ b/configs/ph1_ld4_defconfig
@@ -1,7 +1,33 @@
 CONFIG_SPL=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_UNIPHIER=y
 +S:CONFIG_MACH_PH1_LD4=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BDI=y
+CONFIG_CMD_CONSOLE=y
+CONFIG_CMD_BOOTD=y
+CONFIG_CMD_RUN=y
+CONFIG_CMD_IMI=y
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_EDITENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ITEST=y
+CONFIG_CMD_SOURCE=y
+CONFIG_CMD_NET=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_NFS=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-ld4-ref"
 CONFIG_DM=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/configs/ph1_pro4_defconfig b/configs/ph1_pro4_defconfig
index e795752..f4ddf5f 100644
--- a/configs/ph1_pro4_defconfig
+++ b/configs/ph1_pro4_defconfig
@@ -1,7 +1,33 @@
 CONFIG_SPL=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_UNIPHIER=y
 +S:CONFIG_MACH_PH1_PRO4=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BDI=y
+CONFIG_CMD_CONSOLE=y
+CONFIG_CMD_BOOTD=y
+CONFIG_CMD_RUN=y
+CONFIG_CMD_IMI=y
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_EDITENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ITEST=y
+CONFIG_CMD_SOURCE=y
+CONFIG_CMD_NET=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_NFS=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-pro4-ref"
 CONFIG_DM=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/configs/ph1_sld8_defconfig b/configs/ph1_sld8_defconfig
index 6510937..ee14382 100644
--- a/configs/ph1_sld8_defconfig
+++ b/configs/ph1_sld8_defconfig
@@ -1,7 +1,33 @@
 CONFIG_SPL=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_UNIPHIER=y
 +S:CONFIG_MACH_PH1_SLD8=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BDI=y
+CONFIG_CMD_CONSOLE=y
+CONFIG_CMD_BOOTD=y
+CONFIG_CMD_RUN=y
+CONFIG_CMD_IMI=y
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_EDITENV=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ITEST=y
+CONFIG_CMD_SOURCE=y
+CONFIG_CMD_NET=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_NFS=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-sld8-ref"
 CONFIG_DM=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
diff --git a/doc/device-tree-bindings/ata/intel-sata.txt b/doc/device-tree-bindings/ata/intel-sata.txt
new file mode 100644
index 0000000..5e4da83
--- /dev/null
+++ b/doc/device-tree-bindings/ata/intel-sata.txt
@@ -0,0 +1,26 @@
+Intel Pantherpoint SATA Device Binding
+======================================
+
+The device tree node which describes the operation of the Intel Pantherpoint
+SATA device is as follows:
+
+Required properties :
+- compatible = "intel,pantherpoint-ahci"
+- intel,sata-mode : string, one of:
+     "ahci" : Use AHCI mode (default)
+     "combined" : Use combined IDE + legacy mode
+     "plain-ide" : Use plain IDE mode
+- intel,sata-port-map : Which SATA ports are enabled, bit 0=enable first port,
+    bit 1=enable second port, etc.
+- intel,sata-port0-gen3-tx : Value for the IOBP_SP0G3IR register
+- intel,sata-port1-gen3-tx : Value for the IOBP_SP1G3IR register
+
+Example
+-------
+
+sata {
+	compatible = "intel,pantherpoint-ahci";
+	intel,sata-mode = "ahci";
+	intel,sata-port-map = <1>;
+	intel,sata-port0-gen3-tx = <0x00880a7f>;
+};
diff --git a/doc/device-tree-bindings/misc/intel-lpc.txt b/doc/device-tree-bindings/misc/intel-lpc.txt
index 7e1b389..ba6ca9d 100644
--- a/doc/device-tree-bindings/misc/intel-lpc.txt
+++ b/doc/device-tree-bindings/misc/intel-lpc.txt
@@ -6,10 +6,37 @@
 
 Required properties :
 - compatible = "intel,lpc"
-- gen-dec : Specifies the values for the gen-dec registers. Up to four cell
-   pairs can be provided - the first of each pair is the base address and
+- intel,alt-gp-smi-enable : Enable SMI sources. This cell is written to the
+    ALT_GP_SMI_EN register
+- intel,gen-dec : Specifies the values for the gen-dec registers. Up to four
+   cell pairs can be provided - the first of each pair is the base address and
    the second is the size. These are written into the GENx_DEC registers of
    the LPC device
+- intel,gpi-routing : Specifies the GPI routing. There are 16 cells, valid
+   values are:
+     0 No effect (default)
+     1 SMI# (if corresponding ALT_GPI_SMI_EN bit is also set)
+     2 SCI (if corresponding GPIO_EN bit is also set)
+- intel,pirq-routing : Speciffies the routing IRQ number for each of PIRQA-H,
+   one cell for each.
+     0x00 - 0000 = Reserved
+     0x01 - 0001 = Reserved
+     0x02 - 0010 = Reserved
+     0x03 - 0011 = IRQ3
+     0x04 - 0100 = IRQ4
+     0x05 - 0101 = IRQ5
+     0x06 - 0110 = IRQ6
+     0x07 - 0111 = IRQ7
+     0x08 - 1000 = Reserved
+     0x09 - 1001 = IRQ9
+     0x0A - 1010 = IRQ10
+     0x0B - 1011 = IRQ11
+     0x0C - 1100 = IRQ12
+     0x0D - 1101 = Reserved
+     0x0E - 1110 = IRQ14
+     0x0F - 1111 = IRQ15
+     PIRQ[n]_ROUT[7] - PIRQ Routing Control
+     0x80 - The PIRQ is not routed.
 
 
 Example
@@ -19,5 +46,19 @@
 	compatible = "intel,lpc";
 	#address-cells = <1>;
 	#size-cells = <1>;
-	gen-dec = <0x800 0xfc 0x900 0xfc>;
+	intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
+
+	intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b
+				0x80 0x80 0x80 0x80>;
+	/*
+		* GPI routing
+		* 0 No effect (default)
+		* 1 SMI# (if corresponding ALT_GPI_SMI_EN bit is
+		*	also set)
+		* 2 SCI (if corresponding GPIO_EN bit is also set)
+		*/
+	intel,gpi-routing = <0 0 0 0 0 0 0 2
+				1 0 0 0 0 0 0 0>;
+	/* Enable EC SMI source */
+	intel,alt-gp-smi-enable = <0x0100>;
 };
diff --git a/doc/device-tree-bindings/video/intel-gma.txt b/doc/device-tree-bindings/video/intel-gma.txt
new file mode 100644
index 0000000..914be4f
--- /dev/null
+++ b/doc/device-tree-bindings/video/intel-gma.txt
@@ -0,0 +1,40 @@
+Intel GMA Bindings
+==================
+
+This is the Intel Graphics Media Accelerator. This binding supports selection
+of display parameters only.
+
+
+Required properties:
+ - compatible : "intel,gma";
+
+Optional properties:
+ - intel,dp-hotplug : values for digital port hotplug, one cell per value for
+     ports B, C and D
+  - intel,panel-port-select : output port to use: 0=LVDS 1=DP_B 2=DP_C 3=DP_D
+  - intel,panel-power-cycle-delay : T4 time sequence (6 = 500ms)
+
+  The following delays are in units of 0.1ms:
+  - intel,panel-power-up-delay : T1+T2 time sequence
+  - intel,panel-power-down-delay : T3 time sequence
+  - intel,panel-power-backlight-on-delay : T5 time sequence
+  - intel,panel-power-backlight-off-delay : Tx time sequence
+
+  - intel,cpu-backlight : Value for CPU Backlight PWM
+  - intel,pch-backlight : Value for PCH Backlight PWM
+
+Example
+-------
+
+gma {
+	compatible = "intel,gma";
+	intel,dp_hotplug = <0 0 0x06>;
+	intel,panel-port-select = <1>;
+	intel,panel-power-cycle-delay = <6>;
+	intel,panel-power-up-delay = <2000>;
+	intel,panel-power-down-delay = <500>;
+	intel,panel-power-backlight-on-delay = <2000>;
+	intel,panel-power-backlight-off-delay = <2000>;
+	intel,cpu-backlight = <0x00000200>;
+	intel,pch-backlight = <0x04000000>;
+};
diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile
index e56356e..2ba43ac 100644
--- a/drivers/bios_emulator/Makefile
+++ b/drivers/bios_emulator/Makefile
@@ -9,4 +9,4 @@
 	$(X86DIR)/debug.o
 
 ccflags-y := -I$(srctree)/$(src) -I$(srctree)/$(src)/include \
-	-D__PPC__  -D__BIG_ENDIAN__
+	$(if $(CONFIG_PPC),-D__PPC__  -D__BIG_ENDIAN__)
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c
index 3b2ed6e..93b815c 100644
--- a/drivers/bios_emulator/atibios.c
+++ b/drivers/bios_emulator/atibios.c
@@ -46,8 +46,11 @@
 *		BIOS in u-boot.
 ****************************************************************************/
 #include <common.h>
-#include "biosemui.h"
+#include <bios_emul.h>
+#include <errno.h>
 #include <malloc.h>
+#include <vbe.h>
+#include "biosemui.h"
 
 /* Length of the BIOS image */
 #define MAX_BIOSLEN	    (128 * 1024L)
@@ -59,17 +62,54 @@
 static u32 saveBaseAddress18;
 static u32 saveBaseAddress20;
 
+static void atibios_set_vesa_mode(RMREGS *regs, int vesa_mode,
+				  struct vbe_mode_info *mode_info)
+{
+	debug("VBE: Setting VESA mode %#04x\n", vesa_mode);
+	/* request linear framebuffer mode */
+	vesa_mode |= (1 << 14);
+	/* request clearing of framebuffer */
+	vesa_mode &= ~(1 << 15);
+	regs->e.eax = VESA_SET_MODE;
+	regs->e.ebx = vesa_mode;
+	BE_int86(0x10, regs, regs);
+
+	int offset = 0x2000;
+	void *buffer = (void *)(M.mem_base + offset);
+
+	u16 buffer_seg = (((unsigned long)offset) >> 4) & 0xff00;
+	u16 buffer_adr = ((unsigned long)offset) & 0xffff;
+	regs->e.eax = VESA_GET_MODE_INFO;
+	regs->e.ebx = 0;
+	regs->e.ecx = vesa_mode;
+	regs->e.edx = 0;
+	regs->e.esi = buffer_seg;
+	regs->e.edi = buffer_adr;
+	BE_int86(0x10, regs, regs);
+	memcpy(mode_info->mode_info_block, buffer,
+	       sizeof(struct vbe_mode_info));
+	mode_info->valid = true;
+
+	vesa_mode |= (1 << 14);
+	/* request clearing of framebuffer */
+	vesa_mode &= ~(1 << 15);
+	regs->e.eax = VESA_SET_MODE;
+	regs->e.ebx = vesa_mode;
+	BE_int86(0x10, regs, regs);
+}
+
 /****************************************************************************
 PARAMETERS:
 pcidev	- PCI device info for the video card on the bus to boot
-VGAInfo - BIOS emulator VGA info structure
+vga_info - BIOS emulator VGA info structure
 
 REMARKS:
 This function executes the BIOS POST code on the controller. We assume that
 at this stage the controller has its I/O and memory space enabled and
 that all other controllers are in a disabled state.
 ****************************************************************************/
-static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo * VGAInfo)
+static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo *vga_info,
+			   int vesa_mode, struct vbe_mode_info *mode_info)
 {
 	RMREGS regs;
 	RMSREGS sregs;
@@ -84,13 +124,16 @@
 	    ((int)PCI_DEV(pcidev) << 3) | (int)PCI_FUNC(pcidev);
 
 	/*Setup the X86 emulator for the VGA BIOS*/
-	BE_setVGA(VGAInfo);
+	BE_setVGA(vga_info);
 
 	/*Execute the BIOS POST code*/
 	BE_callRealMode(0xC000, 0x0003, &regs, &sregs);
 
 	/*Cleanup and exit*/
-	BE_getVGA(VGAInfo);
+	BE_getVGA(vga_info);
+
+	if (vesa_mode != -1)
+		atibios_set_vesa_mode(&regs, vesa_mode, mode_info);
 }
 
 /****************************************************************************
@@ -244,60 +287,61 @@
 Loads and POST's the display controllers BIOS, directly from the BIOS
 image we can extract over the PCI bus.
 ****************************************************************************/
-static int PCI_postController(pci_dev_t pcidev, BE_VGAInfo * VGAInfo)
+static int PCI_postController(pci_dev_t pcidev, uchar *bios_rom, int bios_len,
+			      BE_VGAInfo *vga_info, int vesa_mode,
+			      struct vbe_mode_info *mode_info)
 {
-	u32 BIOSImageLen;
-	uchar *mappedBIOS;
-	uchar *copyOfBIOS;
+	u32 bios_image_len;
+	uchar *mapped_bios;
+	uchar *copy_of_bios;
 
-	/*Allocate memory to store copy of BIOS from display controller*/
-	if ((mappedBIOS = PCI_mapBIOSImage(pcidev)) == NULL) {
-		printf("videoboot: Video ROM failed to map!\n");
-		return false;
-	}
+	if (bios_rom) {
+		copy_of_bios = bios_rom;
+		bios_image_len = bios_len;
+	} else {
+		/*
+		 * Allocate memory to store copy of BIOS from display
+		 * controller
+		 */
+		mapped_bios = PCI_mapBIOSImage(pcidev);
+		if (mapped_bios == NULL) {
+			printf("videoboot: Video ROM failed to map!\n");
+			return false;
+		}
 
-	BIOSImageLen = mappedBIOS[2] * 512;
+		bios_image_len = mapped_bios[2] * 512;
 
-	if ((copyOfBIOS = malloc(BIOSImageLen)) == NULL) {
-		printf("videoboot: Out of memory!\n");
-		return false;
+		copy_of_bios = malloc(bios_image_len);
+		if (copy_of_bios == NULL) {
+			printf("videoboot: Out of memory!\n");
+			return false;
+		}
+		memcpy(copy_of_bios, mapped_bios, bios_image_len);
+		PCI_unmapBIOSImage(pcidev, mapped_bios);
 	}
-	memcpy(copyOfBIOS, mappedBIOS, BIOSImageLen);
-
-	PCI_unmapBIOSImage(pcidev, mappedBIOS);
 
-	/*Save information in VGAInfo structure*/
-	VGAInfo->function = PCI_FUNC(pcidev);
-	VGAInfo->device = PCI_DEV(pcidev);
-	VGAInfo->bus = PCI_BUS(pcidev);
-	VGAInfo->pcidev = pcidev;
-	VGAInfo->BIOSImage = copyOfBIOS;
-	VGAInfo->BIOSImageLen = BIOSImageLen;
+	/*Save information in vga_info structure*/
+	vga_info->function = PCI_FUNC(pcidev);
+	vga_info->device = PCI_DEV(pcidev);
+	vga_info->bus = PCI_BUS(pcidev);
+	vga_info->pcidev = pcidev;
+	vga_info->BIOSImage = copy_of_bios;
+	vga_info->BIOSImageLen = bios_image_len;
 
 	/*Now execute the BIOS POST for the device*/
-	if (copyOfBIOS[0] != 0x55 || copyOfBIOS[1] != 0xAA) {
+	if (copy_of_bios[0] != 0x55 || copy_of_bios[1] != 0xAA) {
 		printf("videoboot: Video ROM image is invalid!\n");
 		return false;
 	}
 
-	PCI_doBIOSPOST(pcidev, VGAInfo);
+	PCI_doBIOSPOST(pcidev, vga_info, vesa_mode, mode_info);
 
 	/*Reset the size of the BIOS image to the final size*/
-	VGAInfo->BIOSImageLen = copyOfBIOS[2] * 512;
+	vga_info->BIOSImageLen = copy_of_bios[2] * 512;
 	return true;
 }
 
-/****************************************************************************
-PARAMETERS:
-pcidev	    - PCI device info for the video card on the bus to boot
-pVGAInfo    - Place to return VGA info structure is requested
-cleanUp	    - true to clean up on exit, false to leave emulator active
-
-REMARKS:
-Boots the PCI/AGP video card on the bus using the Video ROM BIOS image
-and the X86 BIOS emulator module.
-****************************************************************************/
-int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp)
+int biosemu_setup(pci_dev_t pcidev, BE_VGAInfo **vga_infop)
 {
 	BE_VGAInfo *VGAInfo;
 
@@ -307,28 +351,70 @@
 	/*Initialise the x86 BIOS emulator*/
 	if ((VGAInfo = malloc(sizeof(*VGAInfo))) == NULL) {
 		printf("videoboot: Out of memory!\n");
-		return false;
+		return -ENOMEM;
 	}
 	memset(VGAInfo, 0, sizeof(*VGAInfo));
 	BE_init(0, 65536, VGAInfo, 0);
+	*vga_infop = VGAInfo;
 
+	return 0;
+}
+
+void biosemu_set_interrupt_handler(int intnum, int (*int_func)(void))
+{
+	X86EMU_setupIntrFunc(intnum, (X86EMU_intrFuncs)int_func);
+}
+
+int biosemu_run(pci_dev_t pcidev, uchar *bios_rom, int bios_len,
+		BE_VGAInfo *vga_info, int clean_up, int vesa_mode,
+		struct vbe_mode_info *mode_info)
+{
 	/*Post all the display controller BIOS'es*/
-	if (!PCI_postController(pcidev, VGAInfo))
-		return false;
+	if (!PCI_postController(pcidev, bios_rom, bios_len, vga_info,
+				vesa_mode, mode_info))
+		return -EINVAL;
 
-	/*Cleanup and exit the emulator if requested. If the BIOS emulator
-	is needed after booting the card, we will not call BE_exit and
-	leave it enabled for further use (ie: VESA driver etc).
+	/*
+	 * Cleanup and exit the emulator if requested. If the BIOS emulator
+	 * is needed after booting the card, we will not call BE_exit and
+	 * leave it enabled for further use (ie: VESA driver etc).
 	*/
-	if (cleanUp) {
+	if (clean_up) {
 		BE_exit();
-		if (VGAInfo->BIOSImage)
-			free(VGAInfo->BIOSImage);
-		free(VGAInfo);
-		VGAInfo = NULL;
+		if (vga_info->BIOSImage)
+			free(vga_info->BIOSImage);
+		free(vga_info);
+		vga_info = NULL;
 	}
-	/*Return VGA info pointer if the caller requested it*/
+
+	return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+pcidev	    - PCI device info for the video card on the bus to boot
+pVGAInfo    - Place to return VGA info structure is requested
+cleanUp	    - true to clean up on exit, false to leave emulator active
+
+REMARKS:
+Boots the PCI/AGP video card on the bus using the Video ROM BIOS image
+and the X86 BIOS emulator module.
+****************************************************************************/
+int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo **pVGAInfo, int clean_up)
+{
+	BE_VGAInfo *VGAInfo;
+	int ret;
+
+	ret = biosemu_setup(pcidev, &VGAInfo);
+	if (ret)
+		return false;
+	ret = biosemu_run(pcidev, NULL, 0, VGAInfo, clean_up, -1, NULL);
+	if (ret)
+		return false;
+
+	/* Return VGA info pointer if the caller requested it*/
 	if (pVGAInfo)
 		*pVGAInfo = VGAInfo;
+
 	return true;
 }
diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c
index ad88a53..752a928 100644
--- a/drivers/bios_emulator/besys.c
+++ b/drivers/bios_emulator/besys.c
@@ -54,12 +54,20 @@
 
 /*------------------------- Global Variables ------------------------------*/
 
-#ifndef __i386__
+#ifndef CONFIG_X86EMU_RAW_IO
 static char *BE_biosDate = "08/14/99";
 static u8 BE_model = 0xFC;
 static u8 BE_submodel = 0x00;
 #endif
 
+#undef DEBUG_IO_ACCESS
+
+#ifdef DEBUG_IO_ACCESS
+#define debug_io(fmt, ...)	printf(fmt, ##__VA_ARGS__)
+#else
+#define debug_io(x, b...)
+#endif
+
 /*----------------------------- Implementation ----------------------------*/
 
 /****************************************************************************
@@ -80,38 +88,40 @@
 	if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
 		return (u8*)(_BE_env.biosmem_base + addr - 0xC0000);
 	} else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) {
-		DB(printf("BE_memaddr: address %#lx may be invalid!\n", addr);)
-		return M.mem_base;
+		DB(printf("BE_memaddr: address %#lx may be invalid!\n",
+			  (ulong)addr);)
+		return (u8 *)M.mem_base;
 	} else if (addr >= 0xA0000 && addr <= 0xBFFFF) {
 		return (u8*)(_BE_env.busmem_base + addr - 0xA0000);
 	}
-#ifdef __i386__
+#ifdef CONFIG_X86EMU_RAW_IO
 	else if (addr >= 0xD0000 && addr <= 0xFFFFF) {
 		/* We map the real System BIOS directly on real PC's */
-		DB(printf("BE_memaddr: System BIOS address %#lx\n", addr);)
-		    return _BE_env.busmem_base + addr - 0xA0000;
+		DB(printf("BE_memaddr: System BIOS address %#lx\n",
+			  (ulong)addr);)
+		    return (u8 *)_BE_env.busmem_base + addr - 0xA0000;
 	}
 #else
 	else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
 		/* Return a faked BIOS date string for non-x86 machines */
-		DB(printf("BE_memaddr - Returning BIOS date\n");)
+		debug_io("BE_memaddr - Returning BIOS date\n");
 		return (u8 *)(BE_biosDate + addr - 0xFFFF5);
 	} else if (addr == 0xFFFFE) {
 		/* Return system model identifier for non-x86 machines */
-		DB(printf("BE_memaddr - Returning model\n");)
+		debug_io("BE_memaddr - Returning model\n");
 		return &BE_model;
 	} else if (addr == 0xFFFFF) {
 		/* Return system submodel identifier for non-x86 machines */
-		DB(printf("BE_memaddr - Returning submodel\n");)
+		debug_io("BE_memaddr - Returning submodel\n");
 		return &BE_submodel;
 	}
 #endif
 	else if (addr > M.mem_size - 1) {
 		HALT_SYS();
-		return M.mem_base;
+		return (u8 *)M.mem_base;
 	}
 
-	return M.mem_base + addr;
+	return (u8 *)(M.mem_base + addr);
 }
 
 /****************************************************************************
@@ -230,7 +240,7 @@
 	}
 }
 
-#if defined(DEBUG) || !defined(__i386__)
+#if !defined(CONFIG_X86EMU_RAW_IO)
 
 /* For Non-Intel machines we may need to emulate some I/O port accesses that
  * the BIOS may try to access, such as the PCI config registers.
@@ -258,6 +268,7 @@
 {
 	u8 val = 0xff;
 
+	debug_io("vga_inb.%04X -> ", (u16) port);
 	switch (port) {
 	case 0x3C0:
 		/* 3C0 has funky characteristics because it can act as either
@@ -560,7 +571,7 @@
 {
 	u8 val = 0;
 
-#if defined(DEBUG) || !defined(__i386__)
+#if !defined(CONFIG_X86EMU_RAW_IO)
 	if (IS_VGA_PORT(port)){
 		/*seems reading port 0x3c3 return the high 16 bit of io port*/
 		if(port == 0x3c3)
@@ -581,7 +592,12 @@
 		val = LOG_inpb(port);
 	} else
 #endif
+	{
+		debug_io("inb.%04X -> ", (u16) port);
 		val = LOG_inpb(port);
+		debug_io("%02X\n", val);
+	}
+
 	return val;
 }
 
@@ -601,7 +617,7 @@
 {
 	u16 val = 0;
 
-#if defined(DEBUG) || !defined(__i386__)
+#if !defined(CONFIG_X86EMU_RAW_IO)
 	if (IS_PCI_PORT(port))
 		val = PCI_inp(port, REG_READ_WORD);
 	else if (port < 0x100) {
@@ -609,7 +625,12 @@
 		val = LOG_inpw(port);
 	} else
 #endif
+	{
+		debug_io("inw.%04X -> ", (u16) port);
 		val = LOG_inpw(port);
+		debug_io("%04X\n", val);
+	}
+
 	return val;
 }
 
@@ -629,14 +650,19 @@
 {
 	u32 val = 0;
 
-#if defined(DEBUG) || !defined(__i386__)
+#if !defined(CONFIG_X86EMU_RAW_IO)
 	if (IS_PCI_PORT(port))
 		val = PCI_inp(port, REG_READ_DWORD);
 	else if (port < 0x100) {
 		val = LOG_inpd(port);
 	} else
 #endif
+	{
+		debug_io("inl.%04X -> ", (u16) port);
 		val = LOG_inpd(port);
+		debug_io("%08X\n", val);
+	}
+
 	return val;
 }
 
@@ -652,7 +678,7 @@
 ****************************************************************************/
 void X86API BE_outb(X86EMU_pioAddr port, u8 val)
 {
-#if defined(DEBUG) || !defined(__i386__)
+#if !defined(CONFIG_X86EMU_RAW_IO)
 	if (IS_VGA_PORT(port))
 		VGA_outpb(port, val);
 	else if (IS_TIMER_PORT(port))
@@ -668,7 +694,11 @@
 		LOG_outpb(port, val);
 	} else
 #endif
+	{
+		debug_io("outb.%04X <- %02X", (u16) port, val);
 		LOG_outpb(port, val);
+		debug_io("\n");
+	}
 }
 
 /****************************************************************************
@@ -683,19 +713,23 @@
 ****************************************************************************/
 void X86API BE_outw(X86EMU_pioAddr port, u16 val)
 {
-#if defined(DEBUG) || !defined(__i386__)
-		if (IS_VGA_PORT(port)) {
-			VGA_outpb(port, val);
-			VGA_outpb(port + 1, val >> 8);
-		} else if (IS_PCI_PORT(port))
-			PCI_outp(port, val, REG_WRITE_WORD);
-		else if (port < 0x100) {
-			DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port,
-			       val);)
-			LOG_outpw(port, val);
-		} else
+#if !defined(CONFIG_X86EMU_RAW_IO)
+	if (IS_VGA_PORT(port)) {
+		VGA_outpb(port, val);
+		VGA_outpb(port + 1, val >> 8);
+	} else if (IS_PCI_PORT(port)) {
+		PCI_outp(port, val, REG_WRITE_WORD);
+	} else if (port < 0x100) {
+		DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16)port,
+			  val);)
+		LOG_outpw(port, val);
+	} else
 #endif
-			LOG_outpw(port, val);
+	{
+		debug_io("outw.%04X <- %04X", (u16) port, val);
+		LOG_outpw(port, val);
+		debug_io("\n");
+	}
 }
 
 /****************************************************************************
@@ -710,13 +744,17 @@
 ****************************************************************************/
 void X86API BE_outl(X86EMU_pioAddr port, u32 val)
 {
-#if defined(DEBUG) || !defined(__i386__)
-	if (IS_PCI_PORT(port))
+#if !defined(CONFIG_X86EMU_RAW_IO)
+	if (IS_PCI_PORT(port)) {
 		PCI_outp(port, val, REG_WRITE_DWORD);
-	else if (port < 0x100) {
+	} else if (port < 0x100) {
 		DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
 		LOG_outpd(port, val);
 	} else
 #endif
+	{
+		debug_io("outl.%04X <- %08X", (u16) port, val);
 		LOG_outpd(port, val);
+		debug_io("\n");
+	}
 }
diff --git a/drivers/bios_emulator/bios.c b/drivers/bios_emulator/bios.c
index bcc192f..152d70a 100644
--- a/drivers/bios_emulator/bios.c
+++ b/drivers/bios_emulator/bios.c
@@ -84,14 +84,14 @@
 			PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8) ~ 0x02);
 			return;
 		}
-#ifdef  DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 		else {
 			printf("int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n",
 			     M.x86.R_AL);
 		}
 #endif
 	}
-#ifdef  DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 	else {
 		printf("int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n",
 		     M.x86.R_AH, M.x86.R_AL, M.x86.R_BL);
diff --git a/drivers/bios_emulator/biosemui.h b/drivers/bios_emulator/biosemui.h
index 8c1f111..7853015 100644
--- a/drivers/bios_emulator/biosemui.h
+++ b/drivers/bios_emulator/biosemui.h
@@ -48,7 +48,7 @@
 #include <asm/io.h>
 /*---------------------- Macros and type definitions ----------------------*/
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 #define DB(x)	x
 #else
 #define DB(x)	do{}while(0);
diff --git a/drivers/bios_emulator/include/biosemu.h b/drivers/bios_emulator/include/biosemu.h
index e92e96e..124d79d 100644
--- a/drivers/bios_emulator/include/biosemu.h
+++ b/drivers/bios_emulator/include/biosemu.h
@@ -43,6 +43,8 @@
 #ifndef __BIOSEMU_H
 #define __BIOSEMU_H
 
+#include <bios_emul.h>
+
 #ifdef __KERNEL__
 #include "x86emu.h"
 #else
@@ -55,57 +57,6 @@
 
 #pragma pack(1)
 
-#ifndef __KERNEL__
-/****************************************************************************
-REMARKS:
-Data structure used to describe the details specific to a particular VGA
-controller. This information is used to allow the VGA controller to be
-swapped on the fly within the BIOS emulator.
-
-HEADER:
-biosemu.h
-
-MEMBERS:
-pciInfo         - PCI device information block for the controller
-BIOSImage       - Pointer to a read/write copy of the BIOS image
-BIOSImageLen    - Length of the BIOS image
-LowMem          - Copy of key low memory areas
-****************************************************************************/
-typedef struct {
-	PCIDeviceInfo *pciInfo;
-	void *BIOSImage;
-	ulong BIOSImageLen;
-	uchar LowMem[1536];
-} BE_VGAInfo;
-#else
-/****************************************************************************
-REMARKS:
-Data structure used to describe the details for the BIOS emulator system
-environment as used by the X86 emulator library.
-
-HEADER:
-biosemu.h
-
-MEMBERS:
-vgaInfo         - VGA BIOS information structure
-biosmem_base    - Base of the BIOS image
-biosmem_limit   - Limit of the BIOS image
-busmem_base     - Base of the VGA bus memory
-****************************************************************************/
-typedef struct {
-	int function;
-	int device;
-	int bus;
-	u32 VendorID;
-	u32 DeviceID;
-	pci_dev_t pcidev;
-	void *BIOSImage;
-	u32 BIOSImageLen;
-	u8 LowMem[1536];
-} BE_VGAInfo;
-
-#endif				/* __KERNEL__ */
-
 #define CRT_C   24		/* 24  CRT Controller Registers             */
 #define ATT_C   21		/* 21  Attribute Controller Registers       */
 #define GRA_C   9		/* 9   Graphics Controller Registers        */
diff --git a/drivers/bios_emulator/include/x86emu.h b/drivers/bios_emulator/include/x86emu.h
index a70a768..b28cdc6 100644
--- a/drivers/bios_emulator/include/x86emu.h
+++ b/drivers/bios_emulator/include/x86emu.h
@@ -53,9 +53,9 @@
 
 /*---------------------- Macros and type definitions ----------------------*/
 
-#if defined (CONFIG_ARM)
+#if defined(CONFIG_ARM)
 #define GAS_LINE_COMMENT	"@"
-#elif defined(CONFIG_MIPS) || defined(CONFIG_PPC)
+#elif defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_X86)
 #define GAS_LINE_COMMENT	"#"
 #elif defined (CONFIG_SH)
 #define GAS_LINE_COMMENT	"!"
@@ -153,6 +153,7 @@
 	void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs);
 	void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs);
 	void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
+	void X86EMU_setupIntrFunc(int intnum, X86EMU_intrFuncs func);
 	void X86EMU_prepareForInt(int num);
 
 /* decode.c */
@@ -160,7 +161,7 @@
 	void X86EMU_exec(void);
 	void X86EMU_halt_sys(void);
 
-#ifdef  DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 #define HALT_SYS()  \
     printf("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \
     X86EMU_halt_sys()
diff --git a/drivers/bios_emulator/include/x86emu/debug.h b/drivers/bios_emulator/include/x86emu/debug.h
index 268c9d3..304b2bf 100644
--- a/drivers/bios_emulator/include/x86emu/debug.h
+++ b/drivers/bios_emulator/include/x86emu/debug.h
@@ -48,7 +48,7 @@
 #define CHECK_MEM_ACCESS_F		0x4	/*using regular linear pointer */
 #define CHECK_DATA_ACCESS_F		0x8	/*using segment:offset */
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 # define CHECK_IP_FETCH()		(M.x86.check & CHECK_IP_FETCH_F)
 # define CHECK_SP_ACCESS()		(M.x86.check & CHECK_SP_ACCESS_F)
 # define CHECK_MEM_ACCESS()		(M.x86.check & CHECK_MEM_ACCESS_F)
@@ -60,7 +60,7 @@
 # define CHECK_DATA_ACCESS()
 #endif
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 # define DEBUG_INSTRUMENT()	(M.x86.debug & DEBUG_INSTRUMENT_F)
 # define DEBUG_DECODE()		(M.x86.debug & DEBUG_DECODE_F)
 # define DEBUG_TRACE()		(M.x86.debug & DEBUG_TRACE_F)
@@ -99,7 +99,11 @@
 # define DEBUG_DECODE_NOPRINT() 0
 #endif
 
-#ifdef DEBUG
+# define ERR_PRINTF(x)		printf(x)
+# define ERR_PRINTF2(x, y)	printf(x, y)
+
+#ifdef CONFIG_X86EMU_DEBUG103
+
 
 # define DECODE_PRINTF(x)	if (DEBUG_DECODE()) \
 				    x86emu_decode_printf(x)
@@ -129,7 +133,7 @@
 # define SAVE_IP_CS(x,y)
 #endif
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 #define TRACE_REGS()					    \
     if (DEBUG_DISASSEMBLE()) {				    \
 	x86emu_just_disassemble();			    \
@@ -140,7 +144,7 @@
 # define TRACE_REGS()
 #endif
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 # define SINGLE_STEP()	    if (DEBUG_STEP()) x86emu_single_step()
 #else
 # define SINGLE_STEP()
@@ -150,7 +154,7 @@
     TRACE_REGS();	    \
     SINGLE_STEP()
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 # define START_OF_INSTR()
 # define END_OF_INSTR()	    EndOfTheInstructionProcedure: x86emu_end_instr();
 # define END_OF_INSTR_NO_TRACE()    x86emu_end_instr();
@@ -160,7 +164,7 @@
 # define END_OF_INSTR_NO_TRACE()
 #endif
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 # define  CALL_TRACE(u,v,w,x,s)					\
     if (DEBUG_TRACECALLREGS())					\
 	x86emu_dump_regs();					\
@@ -176,7 +180,7 @@
 # define RETURN_TRACE(n,u,v)
 #endif
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 #define DB(x)	x
 #else
 #define DB(x)
diff --git a/drivers/bios_emulator/include/x86emu/regs.h b/drivers/bios_emulator/include/x86emu/regs.h
index a7fedd2..2934129 100644
--- a/drivers/bios_emulator/include/x86emu/regs.h
+++ b/drivers/bios_emulator/include/x86emu/regs.h
@@ -282,7 +282,7 @@
 	u8 intno;
 	volatile int intr;	/* mask of pending interrupts */
 	int debug;
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 	int check;
 	u16 saved_ip;
 	u16 saved_cs;
diff --git a/drivers/bios_emulator/x86emu/debug.c b/drivers/bios_emulator/x86emu/debug.c
index 2fa8050..27e90e4 100644
--- a/drivers/bios_emulator/x86emu/debug.c
+++ b/drivers/bios_emulator/x86emu/debug.c
@@ -44,7 +44,7 @@
 
 /*----------------------------- Implementation ----------------------------*/
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 
 static void print_encoded_bytes(u16 s, u16 o);
 static void print_decoded_instruction(void);
@@ -211,9 +211,7 @@
 	u32 start = off & 0xfffffff0;
 	u32 end = (off + 16) & 0xfffffff0;
 	u32 i;
-	u32 current;
 
-	current = start;
 	while (end <= off + amt) {
 		printk("%04x:%04x ", seg, start);
 		for (i = start; i < off; i++)
@@ -229,7 +227,7 @@
 void x86emu_single_step(void)
 {
 	char s[1024];
-	int ps[10];
+	 int ps[10];
 	int ntok;
 	int cmd;
 	int done;
@@ -238,8 +236,6 @@
 	static int breakpoint;
 	static int noDecode = 1;
 
-	char *p;
-
 	if (DEBUG_BREAK()) {
 		if (M.x86.saved_ip != breakpoint) {
 			return;
@@ -255,6 +251,8 @@
 	offset = M.x86.saved_ip;
 	while (!done) {
 		printk("-");
+		ps[1] = 0; /* Avoid dodgy compiler warnings */
+		ps[2] = 0;
 		cmd = x86emu_parse_line(s, ps, &ntok);
 		switch (cmd) {
 		case 'u':
diff --git a/drivers/bios_emulator/x86emu/decode.c b/drivers/bios_emulator/x86emu/decode.c
index a782b81..da44c3d 100644
--- a/drivers/bios_emulator/x86emu/decode.c
+++ b/drivers/bios_emulator/x86emu/decode.c
@@ -303,7 +303,7 @@
 u8 fetch_data_byte(
     uint offset)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access((u16)get_data_segment(), offset);
 #endif
@@ -322,7 +322,7 @@
 u16 fetch_data_word(
     uint offset)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access((u16)get_data_segment(), offset);
 #endif
@@ -341,7 +341,7 @@
 u32 fetch_data_long(
     uint offset)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access((u16)get_data_segment(), offset);
 #endif
@@ -362,7 +362,7 @@
     uint segment,
     uint offset)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access(segment, offset);
 #endif
@@ -383,7 +383,7 @@
     uint segment,
     uint offset)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access(segment, offset);
 #endif
@@ -404,7 +404,7 @@
     uint segment,
     uint offset)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access(segment, offset);
 #endif
@@ -426,7 +426,7 @@
     uint offset,
     u8 val)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access((u16)get_data_segment(), offset);
 #endif
@@ -448,7 +448,7 @@
     uint offset,
     u16 val)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access((u16)get_data_segment(), offset);
 #endif
@@ -470,7 +470,7 @@
     uint offset,
     u32 val)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access((u16)get_data_segment(), offset);
 #endif
@@ -493,7 +493,7 @@
     uint offset,
     u8 val)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access(segment, offset);
 #endif
@@ -516,7 +516,7 @@
     uint offset,
     u16 val)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access(segment, offset);
 #endif
@@ -539,7 +539,7 @@
     uint offset,
     u32 val)
 {
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (CHECK_DATA_ACCESS())
 	x86emu_check_data_access(segment, offset);
 #endif
diff --git a/drivers/bios_emulator/x86emu/ops.c b/drivers/bios_emulator/x86emu/ops.c
index f8e093d..2bb5e2d 100644
--- a/drivers/bios_emulator/x86emu/ops.c
+++ b/drivers/bios_emulator/x86emu/ops.c
@@ -79,7 +79,7 @@
 
 /* constant arrays to do several instructions in just one function */
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 static char *x86emu_GenOpName[8] = {
     "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
 #endif
@@ -160,7 +160,7 @@
     sar_long,
 };
 
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
 
 static char *opF6_names[8] =
   { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
@@ -179,7 +179,7 @@
 {
     START_OF_INSTR();
     if (M.x86.R_SP != 0) {
-	DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
+	ERR_PRINTF("ILLEGAL X86 OPCODE\n");
 	TRACE_REGS();
 	DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
 	    M.x86.R_CS, M.x86.R_IP-1,op1));
@@ -1281,7 +1281,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -1359,7 +1359,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -1475,7 +1475,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -1551,7 +1551,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -2148,7 +2148,7 @@
     DECODE_PRINTF("POP\t");
     FETCH_DECODE_MODRM(mod, rh, rl);
     if (rh != 0) {
-	DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+	ERR_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
 	HALT_SYS();
     }
     if (mod < 3) {
@@ -3083,7 +3083,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -3158,7 +3158,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -3347,7 +3347,7 @@
     DECODE_PRINTF("MOV\t");
     FETCH_DECODE_MODRM(mod, rh, rl);
     if (rh != 0) {
-	DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
+	ERR_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
 	HALT_SYS();
     }
     if (mod < 3) {
@@ -3381,7 +3381,7 @@
     DECODE_PRINTF("MOV\t");
     FETCH_DECODE_MODRM(mod, rh, rl);
     if (rh != 0) {
-	DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+	ERR_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
 	HALT_SYS();
     }
     if (mod < 3) {
@@ -3630,7 +3630,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -3701,7 +3701,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -3803,7 +3803,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -3876,7 +3876,7 @@
      */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -3968,7 +3968,7 @@
     DECODE_PRINTF("AAM\n");
     a = fetch_byte_imm();      /* this is a stupid encoding. */
     if (a != 10) {
-	DECODE_PRINTF("ERROR DECODING AAM\n");
+	ERR_PRINTF("ERROR DECODING AAM\n");
 	TRACE_REGS();
 	HALT_SYS();
     }
@@ -4443,7 +4443,7 @@
 	    test_byte(destval, srcval);
 	    break;
 	case 1:
-	    DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+	    ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
 	    HALT_SYS();
 	    break;
 	case 2:
@@ -4490,7 +4490,7 @@
 	    test_byte(*destreg, srcval);
 	    break;
 	case 1:
-	    DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+	    ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
 	    HALT_SYS();
 	    break;
 	case 2:
@@ -4559,7 +4559,7 @@
 		test_long(destval, srcval);
 		break;
 	    case 1:
-		DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+		ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
 		HALT_SYS();
 		break;
 	    case 2:
@@ -4611,7 +4611,7 @@
 		test_word(destval, srcval);
 		break;
 	    case 1:
-		DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+		ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
 		HALT_SYS();
 		break;
 	    case 2:
@@ -4666,7 +4666,7 @@
 		test_long(*destreg, srcval);
 		break;
 	    case 1:
-		DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+		ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
 		HALT_SYS();
 		break;
 	    case 2:
@@ -4715,7 +4715,7 @@
 		test_word(*destreg, srcval);
 		break;
 	    case 1:
-		DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+		ERR_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
 		HALT_SYS();
 		break;
 	    case 2:
@@ -4859,7 +4859,7 @@
     /* Yet another special case instruction. */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -4879,7 +4879,7 @@
 	case 5:
 	case 6:
 	case 7:
-	    DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
+	    ERR_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x\n", mod);
 	    HALT_SYS();
 	    break;
 	}
@@ -4923,7 +4923,7 @@
     /* Yet another special case instruction. */
     START_OF_INSTR();
     FETCH_DECODE_MODRM(mod, rh, rl);
-#ifdef DEBUG
+#ifdef CONFIG_X86EMU_DEBUG
     if (DEBUG_DECODE()) {
 	/* XXX DECODE_PRINTF may be changed to something more
 	   general, so that it is important to leave the strings
@@ -4961,7 +4961,7 @@
 	    DECODE_PRINTF("PUSH\t");
 	    break;
 	case 7:
-	    DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
+	    ERR_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
 	    HALT_SYS();
 	    break;
 	}
@@ -5092,7 +5092,7 @@
 	    M.x86.R_IP = *destreg;
 	    break;
 	case 3:		/* jmp far ptr ... */
-	    DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+	    ERR_PRINTF("OPERATION UNDEFINED 0XFF\n");
 	    TRACE_AND_STEP();
 	    HALT_SYS();
 	    break;
@@ -5104,7 +5104,7 @@
 	    M.x86.R_IP = (u16) (*destreg);
 	    break;
 	case 5:		/* jmp far ptr ... */
-	    DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+	    ERR_PRINTF("OPERATION UNDEFINED 0XFF\n");
 	    TRACE_AND_STEP();
 	    HALT_SYS();
 	    break;
diff --git a/drivers/bios_emulator/x86emu/ops2.c b/drivers/bios_emulator/x86emu/ops2.c
index 59dbb42..be4ef36 100644
--- a/drivers/bios_emulator/x86emu/ops2.c
+++ b/drivers/bios_emulator/x86emu/ops2.c
@@ -58,7 +58,7 @@
     u8 op2)
 {
     START_OF_INSTR();
-    DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+    ERR_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
     TRACE_REGS();
     printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
 	M.x86.R_CS, M.x86.R_IP-2,op2);
@@ -1089,7 +1089,7 @@
 	DECODE_PRINTF("BTC\t");
 	break;
     default:
-	DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+	ERR_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
 	TRACE_REGS();
 	printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
 		M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c
index 21f9730..0ba9c0c 100644
--- a/drivers/bios_emulator/x86emu/sys.c
+++ b/drivers/bios_emulator/x86emu/sys.c
@@ -273,6 +273,11 @@
 	sys_outl = funcs->outl;
 }
 
+void X86EMU_setupIntrFunc(int intnum, X86EMU_intrFuncs func)
+{
+	_X86EMU_intrTab[intnum] = func;
+}
+
 /****************************************************************************
 PARAMETERS:
 funcs   - New interrupt vector table to make active
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 75c2c06..c242214 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,9 +1,16 @@
 menu "NAND Device Support"
 
+config SYS_NAND_SELF_INIT
+	bool
+	help
+	  This option, if enabled, provides more flexible and linux-like
+	  NAND initialization process.
+
 if !SPL_BUILD
 
 config NAND_DENALI
 	bool "Support Denali NAND controller"
+	select SYS_NAND_SELF_INIT
 	help
 	  Enable support for the Denali NAND controller.
 
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 308b784..9e0429a 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -44,7 +44,7 @@
  * this macro allows us to convert from an MTD structure to our own
  * device context (denali) structure.
  */
-#define mtd_to_denali(m) (((struct nand_chip *)mtd->priv)->priv)
+#define mtd_to_denali(m) container_of(m->priv, struct denali_nand_info, nand)
 
 /* These constants are defined by the driver to enable common driver
  * configuration options. */
@@ -1144,70 +1144,128 @@
 
 static struct nand_ecclayout nand_oob;
 
-static int denali_nand_init(struct nand_chip *nand)
+static int denali_init(struct denali_nand_info *denali)
 {
-	struct denali_nand_info *denali;
+	int ret;
 
-	denali = malloc(sizeof(*denali));
-	if (!denali)
-		return -ENOMEM;
+	denali_hw_init(denali);
 
-	nand->priv = denali;
+	denali->mtd->name = "denali-nand";
+	denali->mtd->owner = THIS_MODULE;
+	denali->mtd->priv = &denali->nand;
 
-	denali->flash_reg = (void  __iomem *)CONFIG_SYS_NAND_REGS_BASE;
-	denali->flash_mem = (void  __iomem *)CONFIG_SYS_NAND_DATA_BASE;
+	/* register the driver with the NAND core subsystem */
+	denali->nand.select_chip = denali_select_chip;
+	denali->nand.cmdfunc = denali_cmdfunc;
+	denali->nand.read_byte = denali_read_byte;
+	denali->nand.read_buf = denali_read_buf;
+	denali->nand.waitfunc = denali_waitfunc;
+
+	/*
+	 * scan for NAND devices attached to the controller
+	 * this is the first stage in a two step process to register
+	 * with the nand subsystem
+	 */
+	if (nand_scan_ident(denali->mtd, denali->max_banks, NULL)) {
+		ret = -ENXIO;
+		goto fail;
+	}
 
 #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
 	/* check whether flash got BBT table (located at end of flash). As we
 	 * use NAND_BBT_NO_OOB, the BBT page will start with
 	 * bbt_pattern. We will have mirror pattern too */
-	nand->bbt_options |= NAND_BBT_USE_FLASH;
+	denali->nand.bbt_options |= NAND_BBT_USE_FLASH;
 	/*
 	 * We are using main + spare with ECC support. As BBT need ECC support,
 	 * we need to ensure BBT code don't write to OOB for the BBT pattern.
 	 * All BBT info will be stored into data area with ECC support.
 	 */
-	nand->bbt_options |= NAND_BBT_NO_OOB;
+	denali->nand.bbt_options |= NAND_BBT_NO_OOB;
 #endif
 
+	denali->nand.ecc.mode = NAND_ECC_HW;
+	denali->nand.ecc.size = CONFIG_NAND_DENALI_ECC_SIZE;
+
-	nand->ecc.mode = NAND_ECC_HW;
-	nand->ecc.size = CONFIG_NAND_DENALI_ECC_SIZE;
-	nand->ecc.read_oob = denali_read_oob;
-	nand->ecc.write_oob = denali_write_oob;
-	nand->ecc.read_page = denali_read_page;
-	nand->ecc.read_page_raw = denali_read_page_raw;
-	nand->ecc.write_page = denali_write_page;
-	nand->ecc.write_page_raw = denali_write_page_raw;
 	/*
 	 * Tell driver the ecc strength. This register may be already set
 	 * correctly. So we read this value out.
 	 */
-	nand->ecc.strength = readl(denali->flash_reg + ECC_CORRECTION);
-	switch (nand->ecc.size) {
+	denali->nand.ecc.strength = readl(denali->flash_reg + ECC_CORRECTION);
+	switch (denali->nand.ecc.size) {
 	case 512:
-		nand->ecc.bytes = (nand->ecc.strength * 13 + 15) / 16 * 2;
+		denali->nand.ecc.bytes =
+			(denali->nand.ecc.strength * 13 + 15) / 16 * 2;
 		break;
 	case 1024:
-		nand->ecc.bytes = (nand->ecc.strength * 14 + 15) / 16 * 2;
+		denali->nand.ecc.bytes =
+			(denali->nand.ecc.strength * 14 + 15) / 16 * 2;
 		break;
 	default:
 		pr_err("Unsupported ECC size\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto fail;
 	}
-	nand_oob.eccbytes = nand->ecc.bytes;
-	nand->ecc.layout = &nand_oob;
+	nand_oob.eccbytes = denali->nand.ecc.bytes;
+	denali->nand.ecc.layout = &nand_oob;
 
-	/* Set address of hardware control function */
-	nand->cmdfunc = denali_cmdfunc;
-	nand->read_byte = denali_read_byte;
-	nand->read_buf = denali_read_buf;
-	nand->select_chip = denali_select_chip;
-	nand->waitfunc = denali_waitfunc;
-	denali_hw_init(denali);
-	return 0;
+	writel(denali->mtd->erasesize / denali->mtd->writesize,
+	       denali->flash_reg + PAGES_PER_BLOCK);
+	writel(denali->nand.options & NAND_BUSWIDTH_16 ? 1 : 0,
+	       denali->flash_reg + DEVICE_WIDTH);
+	writel(denali->mtd->writesize,
+	       denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
+	writel(denali->mtd->oobsize,
+	       denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
+	if (readl(denali->flash_reg + DEVICES_CONNECTED) == 0)
+		writel(1, denali->flash_reg + DEVICES_CONNECTED);
+
+	/* override the default operations */
+	denali->nand.ecc.read_page = denali_read_page;
+	denali->nand.ecc.read_page_raw = denali_read_page_raw;
+	denali->nand.ecc.write_page = denali_write_page;
+	denali->nand.ecc.write_page_raw = denali_write_page_raw;
+	denali->nand.ecc.read_oob = denali_read_oob;
+	denali->nand.ecc.write_oob = denali_write_oob;
+
+	if (nand_scan_tail(denali->mtd)) {
+		ret = -ENXIO;
+		goto fail;
+	}
+
+	ret = nand_register(0);
+
+fail:
+	return ret;
+}
+
+static int __board_nand_init(void)
+{
+	struct denali_nand_info *denali;
+
+	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
+	if (!denali)
+		return -ENOMEM;
+
+	/*
+	 * If CONFIG_SYS_NAND_SELF_INIT is defined, each driver is responsible
+	 * for instantiating struct nand_chip, while drivers/mtd/nand/nand.c
+	 * still provides a "struct mtd_info nand_info" instance.
+	 */
+	denali->mtd = &nand_info[0];
+
+	/*
+	 * In the future, these base addresses should be taken from
+	 * Device Tree or platform data.
+	 */
+	denali->flash_reg = (void  __iomem *)CONFIG_SYS_NAND_REGS_BASE;
+	denali->flash_mem = (void  __iomem *)CONFIG_SYS_NAND_DATA_BASE;
+
+	return denali_init(denali);
 }
 
-int board_nand_init(struct nand_chip *chip)
+void board_nand_init(void)
 {
-	return denali_nand_init(chip);
+	if (__board_nand_init() < 0)
+		pr_warn("Failed to initialize Denali NAND controller.\n");
 }
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 3277da7..a258df0 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -434,9 +434,8 @@
 #define DT		3
 
 struct denali_nand_info {
-	struct mtd_info mtd;
-	struct nand_chip *nand;
-
+	struct mtd_info *mtd;
+	struct nand_chip nand;
 	int flash_bank; /* currently selected chip */
 	int status;
 	int platform;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 0b6e7ee..70e780c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -634,6 +634,11 @@
 {
 	struct nand_chip *chip = mtd->priv;
 
+	if (!(chip->options & NAND_BBT_SCANNED)) {
+		chip->scan_bbt(mtd);
+		chip->options |= NAND_BBT_SCANNED;
+	}
+
 	if (!chip->bbt)
 		return chip->block_bad(mtd, ofs, getchip);
 
@@ -4322,10 +4327,9 @@
 
 	/* Check, if we should skip the bad block table scan */
 	if (chip->options & NAND_SKIP_BBTSCAN)
-		return 0;
+		chip->options |= NAND_BBT_SCANNED;
 
-	/* Build bad block table */
-	return chip->scan_bbt(mtd);
+	return 0;
 }
 EXPORT_SYMBOL(nand_scan_tail);
 
diff --git a/drivers/mtd/nand/s3c2410_nand.c b/drivers/mtd/nand/s3c2410_nand.c
index db87d07..b3a2a60 100644
--- a/drivers/mtd/nand/s3c2410_nand.c
+++ b/drivers/mtd/nand/s3c2410_nand.c
@@ -38,10 +38,10 @@
 }
 #endif
 
-static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+static void s3c24x0_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
 	struct nand_chip *chip = mtd->priv;
-	struct s3c2410_nand *nand = s3c2410_get_base_nand();
+	struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
 
 	debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
 
@@ -67,35 +67,35 @@
 		writeb(cmd, chip->IO_ADDR_W);
 }
 
-static int s3c2410_dev_ready(struct mtd_info *mtd)
+static int s3c24x0_dev_ready(struct mtd_info *mtd)
 {
-	struct s3c2410_nand *nand = s3c2410_get_base_nand();
+	struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
 	debug("dev_ready\n");
 	return readl(&nand->nfstat) & 0x01;
 }
 
 #ifdef CONFIG_S3C2410_NAND_HWECC
-void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+void s3c24x0_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	struct s3c2410_nand *nand = s3c2410_get_base_nand();
-	debug("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
+	struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
+	debug("s3c24x0_nand_enable_hwecc(%p, %d)\n", mtd, mode);
 	writel(readl(&nand->nfconf) | S3C2410_NFCONF_INITECC, &nand->nfconf);
 }
 
-static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+static int s3c24x0_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 				      u_char *ecc_code)
 {
-	struct s3c2410_nand *nand = s3c2410_get_base_nand();
+	struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
 	ecc_code[0] = readb(&nand->nfecc);
 	ecc_code[1] = readb(&nand->nfecc + 1);
 	ecc_code[2] = readb(&nand->nfecc + 2);
-	debug("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
-	       mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
+	debug("s3c24x0_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
+	      mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
 
 	return 0;
 }
 
-static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+static int s3c24x0_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				     u_char *read_ecc, u_char *calc_ecc)
 {
 	if (read_ecc[0] == calc_ecc[0] &&
@@ -103,7 +103,7 @@
 	    read_ecc[2] == calc_ecc[2])
 		return 0;
 
-	printf("s3c2410_nand_correct_data: not implemented\n");
+	printf("s3c24x0_nand_correct_data: not implemented\n");
 	return -1;
 }
 #endif
@@ -113,7 +113,7 @@
 	u_int32_t cfg;
 	u_int8_t tacls, twrph0, twrph1;
 	struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
-	struct s3c2410_nand *nand_reg = s3c2410_get_base_nand();
+	struct s3c24x0_nand *nand_reg = s3c24x0_get_base_nand();
 
 	debug("board_nand_init()\n");
 
@@ -149,14 +149,14 @@
 #endif
 
 	/* hwcontrol always must be implemented */
-	nand->cmd_ctrl = s3c2410_hwcontrol;
+	nand->cmd_ctrl = s3c24x0_hwcontrol;
 
-	nand->dev_ready = s3c2410_dev_ready;
+	nand->dev_ready = s3c24x0_dev_ready;
 
 #ifdef CONFIG_S3C2410_NAND_HWECC
-	nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
-	nand->ecc.calculate = s3c2410_nand_calculate_ecc;
-	nand->ecc.correct = s3c2410_nand_correct_data;
+	nand->ecc.hwctl = s3c24x0_nand_enable_hwecc;
+	nand->ecc.calculate = s3c24x0_nand_calculate_ecc;
+	nand->ecc.correct = s3c24x0_nand_correct_data;
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
 	nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
index 7feb3a7..928d58b 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -611,6 +611,9 @@
 		vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
 	}
 
+	/* Disable subpage writes as we do not provide ecc->hwctl */
+	chip->options |= NAND_NO_SUBPAGE_WRITE;
+
 	chip->dev_ready = vf610_nfc_dev_ready;
 	chip->cmdfunc = vf610_nfc_command;
 	chip->read_byte = vf610_nfc_read_byte;
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e73a4986..55d6a9b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -6,7 +6,7 @@
 #
 
 obj-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o
-obj-$(CONFIG_PCI) += pci.o pci_auto.o
+obj-$(CONFIG_PCI) += pci.o pci_auto.o pci_rom.o
 obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
 obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o
 obj-$(CONFIG_PCI_MSC01) += pci_msc01.o
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7ee21d1..3daf73c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -366,9 +366,27 @@
 	return phys_addr;
 }
 
-/*
- *
- */
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
+		     u32 addr_and_ctrl)
+{
+	int bar;
+
+	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
+	pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
+}
+
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
+{
+	u32 addr;
+	int bar;
+
+	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
+	pci_hose_read_config_dword(hose, dev, bar, &addr);
+	if (addr & PCI_BASE_ADDRESS_SPACE_IO)
+		return addr & PCI_BASE_ADDRESS_IO_MASK;
+	else
+		return addr & PCI_BASE_ADDRESS_MEM_MASK;
+}
 
 int pci_hose_config_device(struct pci_controller *hose,
 			   pci_dev_t dev,
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
new file mode 100644
index 0000000..af6a3ae
--- /dev/null
+++ b/drivers/pci/pci_rom.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2014 Google, Inc
+ *
+ * From coreboot, originally based on the Linux kernel (drivers/pci/pci.c).
+ *
+ * Modifications are:
+ * Copyright (C) 2003-2004 Linux Networx
+ * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
+ * Copyright (C) 2003-2006 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2004-2005 Li-Ta Lo <ollie@lanl.gov>
+ * Copyright (C) 2005-2006 Tyan
+ * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
+ * Copyright (C) 2005-2009 coresystems GmbH
+ * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
+ *
+ * PCI Bus Services, see include/linux/pci.h for further explanation.
+ *
+ * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
+ * David Mosberger-Tang
+ *
+ * Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <bios_emul.h>
+#include <errno.h>
+#include <malloc.h>
+#include <pci.h>
+#include <pci_rom.h>
+#include <vbe.h>
+#include <video_fb.h>
+
+#ifdef CONFIG_HAVE_ACPI_RESUME
+#include <asm/acpi.h>
+#endif
+
+__weak bool board_should_run_oprom(pci_dev_t dev)
+{
+	return true;
+}
+
+static bool should_load_oprom(pci_dev_t dev)
+{
+#ifdef CONFIG_HAVE_ACPI_RESUME
+	if (acpi_get_slp_type() == 3)
+		return false;
+#endif
+	if (IS_ENABLED(CONFIG_ALWAYS_LOAD_OPROM))
+		return 1;
+	if (board_should_run_oprom(dev))
+		return 1;
+
+	return 0;
+}
+
+__weak uint32_t board_map_oprom_vendev(uint32_t vendev)
+{
+	return vendev;
+}
+
+static int pci_rom_probe(pci_dev_t dev, uint class,
+			 struct pci_rom_header **hdrp)
+{
+	struct pci_rom_header *rom_header;
+	struct pci_rom_data *rom_data;
+	u16 vendor, device;
+	u32 vendev;
+	u32 mapped_vendev;
+	u32 rom_address;
+
+	pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+	pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+	vendev = vendor << 16 | device;
+	mapped_vendev = board_map_oprom_vendev(vendev);
+	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;
+#else
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
+	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);
+		return -ENOENT;
+	}
+
+	/* Enable expansion ROM address decoding. */
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS,
+			       rom_address | PCI_ROM_ADDRESS_ENABLE);
+#endif
+	debug("Option ROM address %x\n", rom_address);
+	rom_header = (struct pci_rom_header *)rom_address;
+
+	debug("PCI expansion ROM, signature %#04x, INIT size %#04x, data ptr %#04x\n",
+	      le32_to_cpu(rom_header->signature),
+	      rom_header->size * 512, le32_to_cpu(rom_header->data));
+
+	if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
+		printf("Incorrect expansion ROM header signature %04x\n",
+		       le32_to_cpu(rom_header->signature));
+		return -EINVAL;
+	}
+
+	rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
+
+	debug("PCI ROM image, vendor ID %04x, device ID %04x,\n",
+	      rom_data->vendor, rom_data->device);
+
+	/* If the device id is mapped, a mismatch is expected */
+	if ((vendor != rom_data->vendor || device != rom_data->device) &&
+	    (vendev == mapped_vendev)) {
+		printf("ID mismatch: vendor ID %04x, device ID %04x\n",
+		       rom_data->vendor, rom_data->device);
+		return -EPERM;
+	}
+
+	debug("PCI ROM image, Class Code %04x%02x, Code Type %02x\n",
+	      rom_data->class_hi, rom_data->class_lo, rom_data->type);
+
+	if (class != ((rom_data->class_hi << 8) | rom_data->class_lo)) {
+		debug("Class Code mismatch ROM %08x, dev %08x\n",
+		      (rom_data->class_hi << 8) | rom_data->class_lo,
+		      class);
+	}
+	*hdrp = rom_header;
+
+	return 0;
+}
+
+int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header,
+		 struct pci_rom_header **ram_headerp)
+{
+	struct pci_rom_data *rom_data;
+	unsigned int rom_size;
+	unsigned int image_size = 0;
+	void *target;
+
+	do {
+		/* Get next image, until we see an x86 version */
+		rom_header = (struct pci_rom_header *)((void *)rom_header +
+							    image_size);
+
+		rom_data = (struct pci_rom_data *)((void *)rom_header +
+				le32_to_cpu(rom_header->data));
+
+		image_size = le32_to_cpu(rom_data->ilen) * 512;
+	} while ((rom_data->type != 0) && (rom_data->indicator != 0));
+
+	if (rom_data->type != 0)
+		return -EACCES;
+
+	rom_size = rom_header->size * 512;
+
+	target = (void *)PCI_VGA_RAM_IMAGE_START;
+	if (target != rom_header) {
+		debug("Copying VGA ROM Image from %p to %p, 0x%x bytes\n",
+		      rom_header, target, rom_size);
+		memcpy(target, rom_header, rom_size);
+		if (memcmp(target, rom_header, rom_size)) {
+			printf("VGA ROM copy failed\n");
+			return -EFAULT;
+		}
+	}
+	*ram_headerp = target;
+
+	return 0;
+}
+
+static struct vbe_mode_info mode_info;
+
+int vbe_get_video_info(struct graphic_device *gdev)
+{
+#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE
+	struct vesa_mode_info *vesa = &mode_info.vesa;
+
+	gdev->winSizeX = vesa->x_resolution;
+	gdev->winSizeY = vesa->y_resolution;
+
+	gdev->plnSizeX = vesa->x_resolution;
+	gdev->plnSizeY = vesa->y_resolution;
+
+	gdev->gdfBytesPP = vesa->bits_per_pixel / 8;
+
+	switch (vesa->bits_per_pixel) {
+	case 24:
+		gdev->gdfIndex = GDF_32BIT_X888RGB;
+		break;
+	case 16:
+		gdev->gdfIndex = GDF_16BIT_565RGB;
+		break;
+	default:
+		gdev->gdfIndex = GDF__8BIT_INDEX;
+		break;
+	}
+
+	gdev->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS;
+	gdev->pciBase = vesa->phys_base_ptr;
+
+	gdev->frameAdrs = vesa->phys_base_ptr;
+	gdev->memSize = vesa->bytes_per_scanline * vesa->y_resolution;
+
+	gdev->vprBase = vesa->phys_base_ptr;
+	gdev->cprBase = vesa->phys_base_ptr;
+
+	return 0;
+#else
+	return -ENOSYS;
+#endif
+}
+
+int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
+{
+	struct pci_rom_header *rom, *ram;
+	int vesa_mode = -1;
+	uint16_t class;
+	int ret;
+
+	/* Only execute VGA ROMs */
+	pci_read_config_word(dev, PCI_CLASS_DEVICE, &class);
+	if ((class ^ PCI_CLASS_DISPLAY_VGA) & 0xff00) {
+		debug("%s: Class %#x, should be %#x\n", __func__, class,
+		      PCI_CLASS_DISPLAY_VGA);
+		return -ENODEV;
+	}
+
+	if (!should_load_oprom(dev))
+		return -ENXIO;
+
+	ret = pci_rom_probe(dev, class, &rom);
+	if (ret)
+		return ret;
+
+	ret = pci_rom_load(class, rom, &ram);
+	if (ret)
+		return ret;
+
+	if (!board_should_run_oprom(dev))
+		return -ENXIO;
+
+#if defined(CONFIG_FRAMEBUFFER_SET_VESA_MODE) && \
+		defined(CONFIG_FRAMEBUFFER_VESA_MODE)
+	vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
+#endif
+	debug("Selected vesa mode %d\b", vesa_mode);
+	if (emulate) {
+#ifdef CONFIG_BIOSEMU
+		BE_VGAInfo *info;
+
+		ret = biosemu_setup(dev, &info);
+		if (ret)
+			return ret;
+		biosemu_set_interrupt_handler(0x15, int15_handler);
+		ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, true,
+				  vesa_mode, &mode_info);
+		if (ret)
+			return ret;
+#else
+		printf("BIOS emulation not available - see CONFIG_BIOSEMU\n");
+		return -ENOSYS;
+#endif
+	} else {
+#ifdef CONFIG_X86
+		bios_set_interrupt_handler(0x15, int15_handler);
+
+		bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
+				&mode_info);
+#else
+		printf("BIOS native execution is only available on x86\n");
+		return -ENOSYS;
+#endif
+	}
+	debug("Final vesa mode %d\n", mode_info.video_mode);
+
+	return 0;
+}
diff --git a/drivers/rtc/bfin_rtc.c b/drivers/rtc/bfin_rtc.c
index 21a2189..4cf2d83 100644
--- a/drivers/rtc/bfin_rtc.c
+++ b/drivers/rtc/bfin_rtc.c
@@ -27,7 +27,7 @@
 #define NUM_SECS_IN_DAY   DAYS_TO_SECS(1)
 
 /* Enable the RTC prescaler enable register */
-static void rtc_init(void)
+void rtc_init(void)
 {
 	if (!(bfin_read_RTC_PREN() & 0x1))
 		bfin_write_RTC_PREN(0x1);
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
index f7cf106..39e6041 100644
--- a/drivers/rtc/mc146818.c
+++ b/drivers/rtc/mc146818.c
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <command.h>
 #include <rtc.h>
+#include <version.h>
 
 #if defined(__I386__) || defined(CONFIG_MALTA)
 #include <asm/io.h>
@@ -23,6 +24,9 @@
 
 #if defined(CONFIG_CMD_DATE)
 
+/* Set this to 1 to clear the CMOS RAM */
+#define CLEAR_CMOS 0
+
 static uchar rtc_read  (uchar reg);
 static void  rtc_write (uchar reg, uchar val);
 
@@ -41,7 +45,14 @@
 #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)
+#define RTC_CONFIG_A_RATE_1024HZ	6
 
+#define RTC_CONFIG_B_24H		(1 << 1)
+
+#define RTC_CONFIG_D_VALID_RAM_AND_TIME	0x80
 
 /* ------------------------------------------------------------------------- */
 
@@ -128,25 +139,49 @@
  */
 static uchar rtc_read (uchar reg)
 {
-	return(in8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg));
+	return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
 }
 
 static void rtc_write (uchar reg, uchar val)
 {
-	out8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg, val);
+	out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
 }
 #else
 static uchar rtc_read (uchar reg)
 {
 	out8(RTC_PORT_MC146818,reg);
-	return(in8(RTC_PORT_MC146818+1));
+	return in8(RTC_PORT_MC146818 + 1);
 }
 
 static void rtc_write (uchar reg, uchar val)
 {
 	out8(RTC_PORT_MC146818,reg);
-	out8(RTC_PORT_MC146818+1,val);
+	out8(RTC_PORT_MC146818+1, val);
 }
 #endif
 
+void rtc_init(void)
+{
+#if CLEAR_CMOS
+	int i;
+
+	rtc_write(RTC_SECONDS_ALARM, 0);
+	rtc_write(RTC_MINUTES_ALARM, 0);
+	rtc_write(RTC_HOURS_ALARM, 0);
+	for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
+		rtc_write(i, 0);
+	printf("RTC: zeroing CMOS RAM\n");
+#endif
+
+	/* Setup the real time clock */
+	rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H);
+	/* Setup the frequency it operates at */
+	rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
+		  RTC_CONFIG_A_RATE_1024HZ);
+	/* Ensure all reserved bits are 0 in register D */
+	rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
+
+	/* Clear any pending interrupts */
+	rtc_read(RTC_CONFIG_C);
+}
 #endif
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index b09053f..d1b5777 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -39,7 +39,7 @@
 	/* Check for a chosen console */
 	node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path");
 	if (node < 0)
-		node = fdtdec_get_alias_node(gd->fdt_blob, "console");
+		node = fdt_path_offset(gd->fdt_blob, "console");
 	if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) {
 		gd->cur_serial_dev = dev;
 		return;
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index 6046efb..e8a1608 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -11,6 +11,7 @@
 #include <dm/device.h>
 #include <dm/platform_data/serial-uniphier.h>
 #include <serial.h>
+#include <fdtdec.h>
 
 #define UART_REG(x)					\
 	u8 x;						\
@@ -113,19 +114,21 @@
 }
 
 #ifdef CONFIG_OF_CONTROL
-static const struct udevice_id uniphier_uart_of_match = {
-	{ .compatible = "panasonic,uniphier-uart"},
+static const struct udevice_id uniphier_uart_of_match[] = {
+	{ .compatible = "panasonic,uniphier-uart" },
 	{},
 };
 
 static int uniphier_serial_ofdata_to_platdata(struct udevice *dev)
 {
-	/*
-	 * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
-	 *
-	 * Implement conversion code from DTB to platform data
-	 * when supporting CONFIG_OF_CONTROL on UniPhir platform.
-	 */
+	struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
+	DECLARE_GLOBAL_DATA_PTR;
+
+	plat->base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+	plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+				       "clock-frequency", 0);
+
+	return 0;
 }
 #endif
 
diff --git a/drivers/usb/host/ehci-uniphier.c b/drivers/usb/host/ehci-uniphier.c
index 77f6c9d..32a4375 100644
--- a/drivers/usb/host/ehci-uniphier.c
+++ b/drivers/usb/host/ehci-uniphier.c
@@ -6,10 +6,43 @@
  */
 
 #include <common.h>
+#include <linux/err.h>
 #include <usb.h>
 #include <asm/arch/ehci-uniphier.h>
 #include "ehci.h"
 
+#ifdef CONFIG_OF_CONTROL
+#include <fdtdec.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+#define FDT		gd->fdt_blob
+#define COMPAT		"panasonic,uniphier-ehci"
+
+static int get_uniphier_ehci_base(int index, struct ehci_hccr **base)
+{
+	int offset;
+
+	for (offset = fdt_node_offset_by_compatible(FDT, 0, COMPAT);
+	     offset >= 0;
+	     offset = fdt_node_offset_by_compatible(FDT, offset, COMPAT)) {
+		if (index == 0) {
+			*base = (struct ehci_hccr *)
+					fdtdec_get_addr(FDT, offset, "reg");
+			return 0;
+		}
+		index--;
+	}
+
+	return -ENODEV; /* not found */
+}
+#else
+static int get_uniphier_ehci_base(int index, struct ehci_hccr **base)
+{
+	*base = (struct ehci_hccr *)uniphier_ehci_platdata[index].base;
+	return 0;
+}
+#endif
+
 /*
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
@@ -17,12 +50,15 @@
 int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 		  struct ehci_hcor **hcor)
 {
+	int ret;
 	struct ehci_hccr *cr;
 	struct ehci_hcor *or;
 
 	uniphier_ehci_reset(index, 0);
 
-	cr = (struct ehci_hccr *)(uniphier_ehci_platdata[index].base);
+	ret = get_uniphier_ehci_base(index, &cr);
+	if (ret < 0)
+		return ret;
 	or = (void *)cr + HC_LENGTH(ehci_readl(&cr->cr_capbase));
 
 	*hccr = cr;
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 7301be3..00b563f 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o
 obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
+obj-$(CONFIG_VIDEO_X86) += x86_fb.o
 obj-$(CONFIG_FORMIKE) += formike.o
 obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
 obj-$(CONFIG_VIDEO_PARADE) += parade.o
diff --git a/drivers/video/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c
index 618f5d9..5748951 100644
--- a/drivers/video/ati_radeon_fb.c
+++ b/drivers/video/ati_radeon_fb.c
@@ -19,6 +19,7 @@
 #include <common.h>
 
 #include <command.h>
+#include <bios_emul.h>
 #include <pci.h>
 #include <asm/processor.h>
 #include <asm/errno.h>
@@ -544,7 +545,6 @@
 }
 
 #include "../bios_emulator/include/biosemu.h"
-extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
 
 int radeon_probe(struct radeonfb_info *rinfo)
 {
diff --git a/drivers/video/x86_fb.c b/drivers/video/x86_fb.c
new file mode 100644
index 0000000..8743a8c
--- /dev/null
+++ b/drivers/video/x86_fb.c
@@ -0,0 +1,37 @@
+/*
+ *
+ * Vesa frame buffer driver for x86
+ *
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <video_fb.h>
+#include <vbe.h>
+#include "videomodes.h"
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+void *video_hw_init(void)
+{
+	GraphicDevice *gdev = &ctfb;
+	int bits_per_pixel;
+
+	printf("Video: ");
+	if (vbe_get_video_info(gdev)) {
+		printf("No video mode configured\n");
+		return NULL;
+	}
+
+	bits_per_pixel = gdev->gdfBytesPP * 8;
+	sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
+		bits_per_pixel);
+	printf("%s\n", gdev->modeIdent);
+
+	return (void *)gdev;
+}
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 943b5bc..258b937 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -25,6 +25,7 @@
 #include <ext_common.h>
 #include <ext4fs.h>
 #include "ext4_common.h"
+#include <div64.h>
 
 int ext4fs_symlinknest;
 struct ext_filesystem ext_fs;
@@ -67,11 +68,11 @@
 	if (len > filesize)
 		len = filesize;
 
-	blockcnt = ((len + pos) + blocksize - 1) / blocksize;
+	blockcnt = lldiv(((len + pos) + blocksize - 1), blocksize);
 
-	for (i = pos / blocksize; i < blockcnt; i++) {
+	for (i = lldiv(pos, blocksize); i < blockcnt; i++) {
 		lbaint_t blknr;
-		int blockoff = pos % blocksize;
+		int blockoff = pos - (blocksize * i);
 		int blockend = blocksize;
 		int skipfirst = 0;
 		blknr = read_allocated_block(&(node->inode), i);
@@ -82,7 +83,7 @@
 
 		/* Last block.  */
 		if (i == blockcnt - 1) {
-			blockend = (len + pos) % blocksize;
+			blockend = (len + pos) - (blocksize * i);
 
 			/* The last portion is exactly blocksize. */
 			if (!blockend)
@@ -90,7 +91,7 @@
 		}
 
 		/* First block. */
-		if (i == pos / blocksize) {
+		if (i == lldiv(pos, blocksize)) {
 			skipfirst = blockoff;
 			blockend -= skipfirst;
 		}
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 88dd495..98b88ad 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -13,6 +13,8 @@
 #include <asm/byteorder.h>
 #include <part.h>
 #include <linux/ctype.h>
+#include <div64.h>
+#include <linux/math64.h>
 #include "fat.c"
 
 static void uppercase(char *str, int len)
@@ -770,7 +772,7 @@
  */
 static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size)
 {
-	__u32 startsect, sect_num;
+	__u32 startsect, sect_num, offset;
 
 	if (clustnum > 0) {
 		startsect = mydata->data_begin +
@@ -779,13 +781,13 @@
 		startsect = mydata->rootdir_sect;
 	}
 
-	sect_num = size / mydata->sect_size;
-	if (size % mydata->sect_size)
+	sect_num = div_u64_rem(size, mydata->sect_size, &offset);
+
+	if (offset != 0)
 		sect_num++;
 
 	if (startsect + sect_num > cur_part_info.start + total_sector)
 		return -1;
-
 	return 0;
 }
 
diff --git a/fs/fs.c b/fs/fs.c
index 3da7860..ddd751c 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -23,6 +23,8 @@
 #include <fs.h>
 #include <sandboxfs.h>
 #include <asm/io.h>
+#include <div64.h>
+#include <linux/math64.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -399,7 +401,7 @@
 	printf("%llu bytes read in %lu ms", len_read, time);
 	if (time > 0) {
 		puts(" (");
-		print_size(len_read / time * 1000, "/s");
+		print_size(div_u64(len_read, time) * 1000, "/s");
 		puts(")");
 	}
 	puts("\n");
@@ -469,7 +471,7 @@
 	printf("%llu bytes written in %lu ms", len, time);
 	if (time > 0) {
 		puts(" (");
-		print_size(len / time * 1000, "/s");
+		print_size(div_u64(len, time) * 1000, "/s");
 		puts(")");
 	}
 	puts("\n");
diff --git a/include/bios_emul.h b/include/bios_emul.h
new file mode 100644
index 0000000..3643b82
--- /dev/null
+++ b/include/bios_emul.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 1996-1999 SciTech Software, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _BIOS_EMUL_H
+#define _BIOS_EMUL_H
+
+/* Include the register header directly here */
+#include "../drivers/bios_emulator/include/x86emu/regs.h"
+#include <pci.h>
+
+/****************************************************************************
+REMARKS:
+Data structure used to describe the details for the BIOS emulator system
+environment as used by the X86 emulator library.
+
+HEADER:
+biosemu.h
+
+MEMBERS:
+vgaInfo         - VGA BIOS information structure
+biosmem_base    - Base of the BIOS image
+biosmem_limit   - Limit of the BIOS image
+busmem_base     - Base of the VGA bus memory
+****************************************************************************/
+typedef struct {
+	int function;
+	int device;
+	int bus;
+	u32 VendorID;
+	u32 DeviceID;
+	pci_dev_t pcidev;
+	void *BIOSImage;
+	u32 BIOSImageLen;
+	u8 LowMem[1536];
+} BE_VGAInfo;
+
+struct vbe_mode_info;
+
+int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo **pVGAInfo, int cleanUp);
+
+/* Run a BIOS ROM natively (only supported on x86 machines) */
+void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode,
+		     struct vbe_mode_info *mode_info);
+
+/**
+ * bios_set_interrupt_handler() - Install an interrupt handler for the BIOS
+ *
+ * This installs an interrupt handler that the BIOS will call when needed.
+ *
+ * @intnum:		Interrupt number to install a handler for
+ * @int_handler_func:	Function to call to handle interrupt
+ */
+void bios_set_interrupt_handler(int intnum, int (*int_handler_func)(void));
+
+void biosemu_set_interrupt_handler(int intnum, int (*int_func)(void));
+
+int biosemu_setup(pci_dev_t pcidev, BE_VGAInfo **pVGAInfo);
+
+int biosemu_run(pci_dev_t pcidev, uchar *bios_rom, int bios_len,
+		BE_VGAInfo *vga_info, int clean_up, int vesa_mode,
+		struct vbe_mode_info *mode_info);
+
+#endif
diff --git a/include/common.h b/include/common.h
index f1ab2cf..94c354b 100644
--- a/include/common.h
+++ b/include/common.h
@@ -73,6 +73,9 @@
 #ifdef CONFIG_ARM
 #define asmlinkage	/* nothing */
 #endif
+#ifdef CONFIG_X86
+#define asmlinkage __attribute__((regparm(0)))
+#endif
 #ifdef CONFIG_BLACKFIN
 #include <asm/blackfin.h>
 #endif
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h
index 8caeca6..645b31c 100644
--- a/include/configs/chromebook_link.h
+++ b/include/configs/chromebook_link.h
@@ -21,7 +21,6 @@
 #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE		0x4000
 #define CONFIG_SYS_X86_START16			0xfffff800
 #define CONFIG_BOARD_EARLY_INIT_F
-#define CONFIG_BOARD_EARLY_INIT_R
 #define CONFIG_DISPLAY_CPUINFO
 
 #define CONFIG_X86_RESET_VECTOR
@@ -40,20 +39,9 @@
 	{PCI_VENDOR_ID_INTEL,		\
 			PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}
 
-/*
- * These common x86 features are not yet supported, but are added in
- * follow-on patches in this series. Add undefs here to avoid every patch
- * having to put things back into x86-common.h
- */
-#undef CONFIG_VIDEO
-#undef CONFIG_CFB_CONSOLE
-#undef CONFIG_ICH_SPI
-#undef CONFIG_SPI
-#undef CONFIG_CMD_SPI
-#undef CONFIG_CMD_SF
-#undef CONFIG_USB_EHCI
-#undef CONFIG_CMD_USB
-#undef CONFIG_CMD_SCSI
+#define CONFIG_X86_OPTION_ROM_FILENAME		pci8086,0166.bin
+#define CONFIG_X86_OPTION_ROM_ADDR		0xfff90000
+#define CONFIG_VIDEO_X86
 
 #define CONFIG_PCI_MEM_BUS	0xe0000000
 #define CONFIG_PCI_MEM_PHYS	CONFIG_PCI_MEM_BUS
@@ -67,6 +55,18 @@
 #define CONFIG_PCI_IO_PHYS	CONFIG_PCI_IO_BUS
 #define CONFIG_PCI_IO_SIZE	0xefff
 
+#define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_PCI_PNP
+
+#define CONFIG_BIOSEMU
+#define VIDEO_IO_OFFSET				0
+#define CONFIG_X86EMU_RAW_IO
+
+#define CONFIG_CROS_EC
+#define CONFIG_CROS_EC_LPC
+#define CONFIG_CMD_CROS_EC
+#define CONFIG_ARCH_EARLY_INIT_R
+
 #define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
 					"stdout=vga,serial\0" \
 					"stderr=vga,serial\0"
diff --git a/include/configs/dbau1x00.h b/include/configs/dbau1x00.h
index e0bf3dc..8a7447d 100644
--- a/include/configs/dbau1x00.h
+++ b/include/configs/dbau1x00.h
@@ -15,6 +15,9 @@
 #define CONFIG_DBAU1X00		1
 #define CONFIG_SOC_AU1X00	1  /* alchemy series cpu */
 
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO
+
 #ifdef CONFIG_DBAU1000
 /* Also known as Merlot */
 #define CONFIG_SOC_AU1000	1
diff --git a/include/configs/pb1x00.h b/include/configs/pb1x00.h
index 1c04a58..61e6af3 100644
--- a/include/configs/pb1x00.h
+++ b/include/configs/pb1x00.h
@@ -15,6 +15,9 @@
 #define CONFIG_PB1X00		1
 #define CONFIG_SOC_AU1X00	1  /* alchemy series cpu */
 
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO
+
 #ifdef CONFIG_PB1000
 #define CONFIG_SOC_AU1000	1
 #else
diff --git a/include/configs/qemu-mips.h b/include/configs/qemu-mips.h
index 98ed8bc..1548d3e 100644
--- a/include/configs/qemu-mips.h
+++ b/include/configs/qemu-mips.h
@@ -13,6 +13,9 @@
 #define __CONFIG_H
 
 #define CONFIG_QEMU_MIPS
+
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO
 #define CONFIG_MISC_INIT_R
 
 #define CONFIG_BOOTDELAY	10	/* autoboot after 10 seconds */
diff --git a/include/configs/qemu-mips64.h b/include/configs/qemu-mips64.h
index e8f5a4c..61cafad 100644
--- a/include/configs/qemu-mips64.h
+++ b/include/configs/qemu-mips64.h
@@ -13,6 +13,9 @@
 #define __CONFIG_H
 
 #define CONFIG_QEMU_MIPS
+
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO
 #define CONFIG_MISC_INIT_R
 
 #define CONFIG_BOOTDELAY	10	/* autoboot after 10 seconds */
diff --git a/include/configs/uniphier-common.h b/include/configs/uniphier-common.h
index 7c4dba0..2140fcc 100644
--- a/include/configs/uniphier-common.h
+++ b/include/configs/uniphier-common.h
@@ -112,7 +112,6 @@
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
 
 #define CONFIG_CMDLINE_EDITING		/* add command line history	*/
-#define CONFIG_SYS_HUSH_PARSER		/* use "hush" command parser */
 #define CONFIG_SYS_CBSIZE		1024	/* Console I/O Buffer Size */
 /* Print Buffer Size */
 #define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
@@ -143,15 +142,6 @@
  */
 #define CONFIG_ARP_TIMEOUT	500UL  /* 0.5 msec */
 
-/*
- * Command line configuration.
- */
-#include <config_cmd_default.h>
-
-#define CONFIG_CMD_PING
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_NAND		/* NAND flash suppport */
-
 #define CONFIG_SYS_MAX_NAND_DEVICE			1
 #define CONFIG_SYS_NAND_MAX_CHIPS			2
 #define CONFIG_SYS_NAND_ONFI_DETECTION
@@ -167,7 +157,6 @@
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS			0
 
 /* USB */
-#define CONFIG_CMD_USB
 #define CONFIG_USB_MAX_CONTROLLER_COUNT		2
 #define CONFIG_CMD_FAT
 #define CONFIG_FAT_WRITE
@@ -225,10 +214,6 @@
 	"add_default_bootargs=setenv bootargs $bootargs"		\
 		" console=ttyS0,$baudrate\0"				\
 
-/* FIT support */
-#define CONFIG_FIT
-#define CONFIG_FIT_VERBOSE	1 /* enable fit_format_{error,warning}() */
-
 /* Open Firmware flat tree */
 #define CONFIG_OF_LIBFDT
 
diff --git a/include/configs/vct.h b/include/configs/vct.h
index 217ba2f..83e4163 100644
--- a/include/configs/vct.h
+++ b/include/configs/vct.h
@@ -25,6 +25,9 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO
+
 #define CPU_CLOCK_RATE			324000000 /* Clock for the MIPS core */
 #define CONFIG_SYS_MIPS_TIMER_FREQ	(CPU_CLOCK_RATE / 2)
 
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 3da9fab..d2b665c 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -120,6 +120,9 @@
 	COMPAT_INTEL_LPC,		/* Intel Low Pin Count I/F */
 	COMPAT_INTEL_MICROCODE,		/* Intel microcode update */
 	COMPAT_MEMORY_SPD,		/* Memory SPD information */
+	COMPAT_INTEL_PANTHERPOINT_AHCI,	/* Intel Pantherpoint AHCI */
+	COMPAT_INTEL_MODEL_206AX,	/* Intel Model 206AX CPU */
+	COMPAT_INTEL_GMA,		/* Intel Graphics Media Accelerator */
 
 	COMPAT_COUNT,
 };
@@ -390,17 +393,6 @@
 			 int *seqp);
 
 /**
- * Get the offset of the given alias node
- *
- * This looks up an alias in /aliases then finds the offset of that node.
- *
- * @param blob		Device tree blob (if NULL, then error is returned)
- * @param name		Alias name, e.g. "console"
- * @return Node offset referred to by that alias, or -ve FDT_ERR_...
- */
-int fdtdec_get_alias_node(const void *blob, const char *name);
-
-/**
  * Get the offset of the given chosen node
  *
  * This looks up a property in /chosen containing the path to another node,
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 89fcae0..0b61671 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -16,7 +16,9 @@
 #define LLONG_MAX	((long long)(~0ULL>>1))
 #define LLONG_MIN	(-LLONG_MAX - 1)
 #define ULLONG_MAX	(~0ULL)
+#ifndef SIZE_MAX
 #define SIZE_MAX	(~(size_t)0)
+#endif
 
 #define U8_MAX		((u8)~0U)
 #define S8_MAX		((s8)(U8_MAX>>1))
diff --git a/include/pci.h b/include/pci.h
index d211351..216f448 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -678,5 +678,28 @@
 extern void pci_mpc85xx_init (struct pci_controller *hose);
 #endif
 
+/**
+ * pci_write_bar32() - Write the address of a BAR including control bits
+ *
+ * This writes a raw address (with control bits) to a bar
+ *
+ * @hose:	PCI hose to use
+ * @dev:	PCI device to update
+ * @barnum:	BAR number (0-5)
+ * @addr:	BAR address with control bits
+ */
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
+		     u32 addr_and_ctrl);
+
+/**
+ * pci_read_bar32() - read the address of a bar
+ *
+ * @hose:	PCI hose to use
+ * @dev:	PCI device to inspect
+ * @barnum:	BAR number (0-5)
+ * @return address of the bar, masking out any control bits
+ * */
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
+
 #endif /* __ASSEMBLY__ */
 #endif /* _PCI_H */
diff --git a/include/pci_ids.h b/include/pci_ids.h
index f84c13a..ee98bee 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -526,7 +526,19 @@
 #define PCI_DEVICE_ID_AMD_11H_NB_DRAM	0x1302
 #define PCI_DEVICE_ID_AMD_11H_NB_MISC	0x1303
 #define PCI_DEVICE_ID_AMD_11H_NB_LINK	0x1304
-#define PCI_DEVICE_ID_AMD_15H_NB_MISC	0x1603
+#define PCI_DEVICE_ID_AMD_15H_M10H_F3	0x1403
+#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d
+#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e
+#define PCI_DEVICE_ID_AMD_15H_NB_F0	0x1600
+#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
+#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
+#define PCI_DEVICE_ID_AMD_15H_NB_F3	0x1603
+#define PCI_DEVICE_ID_AMD_15H_NB_F4	0x1604
+#define PCI_DEVICE_ID_AMD_15H_NB_F5	0x1605
+#define PCI_DEVICE_ID_AMD_16H_NB_F3	0x1533
+#define PCI_DEVICE_ID_AMD_16H_NB_F4	0x1534
+#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F3 0x1583
+#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F4 0x1584
 #define PCI_DEVICE_ID_AMD_CNB17H_F3	0x1703
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
@@ -569,8 +581,9 @@
 #define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
 #define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
 #define PCI_DEVICE_ID_AMD_LX_AES    0x2082
-#define PCI_DEVICE_ID_AMD_HUDSON2_IDE		0x780c
 #define PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE	0x7800
+#define PCI_DEVICE_ID_AMD_HUDSON2_SMBUS		0x780b
+#define PCI_DEVICE_ID_AMD_HUDSON2_IDE		0x780c
 
 #define PCI_VENDOR_ID_TRIDENT		0x1023
 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX	0x2000
@@ -616,6 +629,8 @@
 #define PCI_DEVICE_ID_MATROX_G550	0x2527
 #define PCI_DEVICE_ID_MATROX_VIA	0x4536
 
+#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS	0x14f2
+
 #define PCI_VENDOR_ID_CT		0x102c
 #define PCI_DEVICE_ID_CT_69000		0x00c0
 #define PCI_DEVICE_ID_CT_65545		0x00d8
@@ -724,6 +739,7 @@
 #define PCI_DEVICE_ID_SI_7018		0x7018
 
 #define PCI_VENDOR_ID_HP		0x103c
+#define PCI_VENDOR_ID_HP_3PAR		0x1590
 #define PCI_DEVICE_ID_HP_VISUALIZE_EG	0x1005
 #define PCI_DEVICE_ID_HP_VISUALIZE_FX6	0x1006
 #define PCI_DEVICE_ID_HP_VISUALIZE_FX4	0x1008
@@ -755,6 +771,8 @@
 #define PCI_DEVICE_ID_HP_CISSD		0x3238
 #define PCI_DEVICE_ID_HP_CISSE		0x323a
 #define PCI_DEVICE_ID_HP_CISSF		0x323b
+#define PCI_DEVICE_ID_HP_CISSH		0x323c
+#define PCI_DEVICE_ID_HP_CISSI		0x3239
 #define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
@@ -779,6 +797,29 @@
 #define PCI_DEVICE_ID_ELSA_QS3000	0x3000
 
 #define PCI_VENDOR_ID_STMICRO		0x104A
+#define PCI_DEVICE_ID_STMICRO_USB_HOST	0xCC00
+#define PCI_DEVICE_ID_STMICRO_USB_OHCI	0xCC01
+#define PCI_DEVICE_ID_STMICRO_USB_OTG	0xCC02
+#define PCI_DEVICE_ID_STMICRO_UART_HWFC 0xCC03
+#define PCI_DEVICE_ID_STMICRO_UART_NO_HWFC	0xCC04
+#define PCI_DEVICE_ID_STMICRO_SOC_DMA	0xCC05
+#define PCI_DEVICE_ID_STMICRO_SATA	0xCC06
+#define PCI_DEVICE_ID_STMICRO_I2C	0xCC07
+#define PCI_DEVICE_ID_STMICRO_SPI_HS	0xCC08
+#define PCI_DEVICE_ID_STMICRO_MAC	0xCC09
+#define PCI_DEVICE_ID_STMICRO_SDIO_EMMC 0xCC0A
+#define PCI_DEVICE_ID_STMICRO_SDIO	0xCC0B
+#define PCI_DEVICE_ID_STMICRO_GPIO	0xCC0C
+#define PCI_DEVICE_ID_STMICRO_VIP	0xCC0D
+#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA	0xCC0E
+#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_SRCS 0xCC0F
+#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_MSPS 0xCC10
+#define PCI_DEVICE_ID_STMICRO_CAN	0xCC11
+#define PCI_DEVICE_ID_STMICRO_MLB	0xCC12
+#define PCI_DEVICE_ID_STMICRO_DBP	0xCC13
+#define PCI_DEVICE_ID_STMICRO_SATA_PHY	0xCC14
+#define PCI_DEVICE_ID_STMICRO_ESRAM	0xCC15
+#define PCI_DEVICE_ID_STMICRO_VIC	0xCC16
 
 #define PCI_VENDOR_ID_BUSLOGIC		      0x104B
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
@@ -1294,6 +1335,8 @@
 #define PCI_VENDOR_ID_TUNDRA		0x10e3
 #define PCI_DEVICE_ID_TUNDRA_CA91C042	0x0000
 
+#define PCI_VENDOR_ID_AMCC		0x10e8
+
 #define PCI_VENDOR_ID_INTERG		0x10ea
 #define PCI_DEVICE_ID_INTERG_1682	0x1682
 #define PCI_DEVICE_ID_INTERG_2000	0x2000
@@ -1322,6 +1365,7 @@
 #define PCI_SUBDEVICE_ID_CREATIVE_SB08801	0x0041
 #define PCI_SUBDEVICE_ID_CREATIVE_SB08802	0x0042
 #define PCI_SUBDEVICE_ID_CREATIVE_SB08803	0x0043
+#define PCI_SUBDEVICE_ID_CREATIVE_SB1270	0x0062
 #define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX	0x6000
 
 #define PCI_VENDOR_ID_ECTIVA		0x1102 /* duplicate: CREATIVE */
@@ -1411,6 +1455,7 @@
 #define PCI_DEVICE_ID_VIA_CX700_IDE	0x0581
 #define PCI_DEVICE_ID_VIA_VX800		0x8353
 #define PCI_DEVICE_ID_VIA_VX855		0x8409
+#define PCI_DEVICE_ID_VIA_VX900		0x8410
 #define PCI_DEVICE_ID_VIA_8371_1	0x8391
 #define PCI_DEVICE_ID_VIA_82C598_1	0x8598
 #define PCI_DEVICE_ID_VIA_838X_1	0xB188
@@ -1551,6 +1596,8 @@
 #define PCI_DEVICE_ID_RICOH_RL5C476	0x0476
 #define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
 #define PCI_DEVICE_ID_RICOH_R5C822	0x0822
+#define PCI_DEVICE_ID_RICOH_R5CE822	0xe822
+#define PCI_DEVICE_ID_RICOH_R5CE823	0xe823
 #define PCI_DEVICE_ID_RICOH_R5C832	0x0832
 #define PCI_DEVICE_ID_RICOH_R5C843	0x0843
 
@@ -1586,6 +1633,7 @@
 #define PCI_SUBDEVICE_ID_KEYSPAN_SX2	0x5334
 
 #define PCI_VENDOR_ID_MARVELL		0x11ab
+#define PCI_VENDOR_ID_MARVELL_EXT	0x1b4b
 #define PCI_DEVICE_ID_MARVELL_GT64111	0x4146
 #define PCI_DEVICE_ID_MARVELL_GT64260	0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360	0x6460
@@ -1798,6 +1846,8 @@
 #define PCI_VENDOR_ID_ESDGMBH		0x12fe
 #define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
 
+#define PCI_VENDOR_ID_CB		0x1307	/* Measurement Computing */
+
 #define PCI_VENDOR_ID_SIIG		0x131f
 #define PCI_SUBVENDOR_ID_SIIG		0x131f
 #define PCI_DEVICE_ID_SIIG_1S_10x_550	0x1000
@@ -1860,8 +1910,23 @@
 #define PCI_VENDOR_ID_QUATECH		0x135C
 #define PCI_DEVICE_ID_QUATECH_QSC100	0x0010
 #define PCI_DEVICE_ID_QUATECH_DSC100	0x0020
+#define PCI_DEVICE_ID_QUATECH_DSC200	0x0030
+#define PCI_DEVICE_ID_QUATECH_QSC200	0x0040
 #define PCI_DEVICE_ID_QUATECH_ESC100D	0x0050
 #define PCI_DEVICE_ID_QUATECH_ESC100M	0x0060
+#define PCI_DEVICE_ID_QUATECH_QSCP100	0x0120
+#define PCI_DEVICE_ID_QUATECH_DSCP100	0x0130
+#define PCI_DEVICE_ID_QUATECH_QSCP200	0x0140
+#define PCI_DEVICE_ID_QUATECH_DSCP200	0x0150
+#define PCI_DEVICE_ID_QUATECH_QSCLP100	0x0170
+#define PCI_DEVICE_ID_QUATECH_DSCLP100	0x0180
+#define PCI_DEVICE_ID_QUATECH_DSC100E	0x0181
+#define PCI_DEVICE_ID_QUATECH_SSCLP100	0x0190
+#define PCI_DEVICE_ID_QUATECH_QSCLP200	0x01A0
+#define PCI_DEVICE_ID_QUATECH_DSCLP200	0x01B0
+#define PCI_DEVICE_ID_QUATECH_DSC200E	0x01B1
+#define PCI_DEVICE_ID_QUATECH_SSCLP200	0x01C0
+#define PCI_DEVICE_ID_QUATECH_ESCLP100	0x01E0
 #define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
 
 #define PCI_VENDOR_ID_SEALEVEL		0x135e
@@ -1978,6 +2043,9 @@
 #define PCI_DEVICE_ID_EXAR_XR17C152	0x0152
 #define PCI_DEVICE_ID_EXAR_XR17C154	0x0154
 #define PCI_DEVICE_ID_EXAR_XR17C158	0x0158
+#define PCI_DEVICE_ID_EXAR_XR17V352	0x0352
+#define PCI_DEVICE_ID_EXAR_XR17V354	0x0354
+#define PCI_DEVICE_ID_EXAR_XR17V358	0x0358
 
 #define PCI_VENDOR_ID_MICROGATE		0x13c0
 #define PCI_DEVICE_ID_MICROGATE_USC	0x0010
@@ -2002,6 +2070,10 @@
 #define PCI_DEVICE_ID_CMEDIA_CM8738	0x0111
 #define PCI_DEVICE_ID_CMEDIA_CM8738B	0x0112
 
+#define PCI_VENDOR_ID_ADVANTECH		0x13fe
+
+#define PCI_VENDOR_ID_MEILHAUS		0x1402
+
 #define PCI_VENDOR_ID_LAVA		0x1407
 #define PCI_DEVICE_ID_LAVA_DSERIAL	0x0100 /* 2x 16550 */
 #define PCI_DEVICE_ID_LAVA_QUATRO_A	0x0101 /* 2x 16550, half of 4 port */
@@ -2047,6 +2119,8 @@
 
 #define PCI_VENDOR_ID_CHELSIO		0x1425
 
+#define PCI_VENDOR_ID_ADLINK		0x144a
+
 #define PCI_VENDOR_ID_SAMSUNG		0x144d
 
 #define PCI_VENDOR_ID_GIGABYTE		0x1458
@@ -2080,6 +2154,8 @@
 #define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
 #define PCI_SUBDEVICE_ID_AFAVLAB_P061		0x2150
 
+#define PCI_VENDOR_ID_AMPLICON		0x14dc
+
 #define PCI_VENDOR_ID_BCM_GVC          0x14a4
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
 #define PCI_DEVICE_ID_TIGON3_5752	0x1600
@@ -2100,19 +2176,25 @@
 #define PCI_DEVICE_ID_NX2_57711E	0x1650
 #define PCI_DEVICE_ID_TIGON3_5705	0x1653
 #define PCI_DEVICE_ID_TIGON3_5705_2	0x1654
+#define PCI_DEVICE_ID_TIGON3_5719	0x1657
 #define PCI_DEVICE_ID_TIGON3_5721	0x1659
 #define PCI_DEVICE_ID_TIGON3_5722	0x165a
 #define PCI_DEVICE_ID_TIGON3_5723	0x165b
 #define PCI_DEVICE_ID_TIGON3_5705M	0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2	0x165e
+#define PCI_DEVICE_ID_NX2_57712		0x1662
+#define PCI_DEVICE_ID_NX2_57712E	0x1663
+#define PCI_DEVICE_ID_NX2_57712_MF	0x1663
 #define PCI_DEVICE_ID_TIGON3_5714	0x1668
 #define PCI_DEVICE_ID_TIGON3_5714S	0x1669
 #define PCI_DEVICE_ID_TIGON3_5780	0x166a
 #define PCI_DEVICE_ID_TIGON3_5780S	0x166b
 #define PCI_DEVICE_ID_TIGON3_5705F	0x166e
+#define PCI_DEVICE_ID_NX2_57712_VF	0x166f
 #define PCI_DEVICE_ID_TIGON3_5754M	0x1672
 #define PCI_DEVICE_ID_TIGON3_5755M	0x1673
 #define PCI_DEVICE_ID_TIGON3_5756	0x1674
+#define PCI_DEVICE_ID_TIGON3_5750	0x1676
 #define PCI_DEVICE_ID_TIGON3_5751	0x1677
 #define PCI_DEVICE_ID_TIGON3_5715	0x1678
 #define PCI_DEVICE_ID_TIGON3_5715S	0x1679
@@ -2124,6 +2206,9 @@
 #define PCI_DEVICE_ID_TIGON3_5761E	0x1680
 #define PCI_DEVICE_ID_TIGON3_5761	0x1681
 #define PCI_DEVICE_ID_TIGON3_5764	0x1684
+#define PCI_DEVICE_ID_NX2_57800		0x168a
+#define PCI_DEVICE_ID_NX2_57840		0x168d
+#define PCI_DEVICE_ID_NX2_57810		0x168e
 #define PCI_DEVICE_ID_TIGON3_5787M	0x1693
 #define PCI_DEVICE_ID_TIGON3_5782	0x1696
 #define PCI_DEVICE_ID_TIGON3_5784	0x1698
@@ -2131,11 +2216,19 @@
 #define PCI_DEVICE_ID_TIGON3_5787	0x169b
 #define PCI_DEVICE_ID_TIGON3_5788	0x169c
 #define PCI_DEVICE_ID_TIGON3_5789	0x169d
+#define PCI_DEVICE_ID_NX2_57840_4_10	0x16a1
+#define PCI_DEVICE_ID_NX2_57840_2_20	0x16a2
+#define PCI_DEVICE_ID_NX2_57840_MF	0x16a4
+#define PCI_DEVICE_ID_NX2_57800_MF	0x16a5
 #define PCI_DEVICE_ID_TIGON3_5702X	0x16a6
 #define PCI_DEVICE_ID_TIGON3_5703X	0x16a7
 #define PCI_DEVICE_ID_TIGON3_5704S	0x16a8
+#define PCI_DEVICE_ID_NX2_57800_VF	0x16a9
 #define PCI_DEVICE_ID_NX2_5706S		0x16aa
 #define PCI_DEVICE_ID_NX2_5708S		0x16ac
+#define PCI_DEVICE_ID_NX2_57840_VF	0x16ad
+#define PCI_DEVICE_ID_NX2_57810_MF	0x16ae
+#define PCI_DEVICE_ID_NX2_57810_VF	0x16af
 #define PCI_DEVICE_ID_TIGON3_5702A3	0x16c6
 #define PCI_DEVICE_ID_TIGON3_5703A3	0x16c7
 #define PCI_DEVICE_ID_TIGON3_5781	0x16dd
@@ -2307,6 +2400,8 @@
 
 #define PCI_VENDOR_ID_TOPSPIN		0x1867
 
+#define PCI_VENDOR_ID_COMMTECH		0x18f7
+
 #define PCI_VENDOR_ID_SILAN		0x1904
 
 #define PCI_VENDOR_ID_RENESAS		0x1912
@@ -2316,6 +2411,11 @@
 #define PCI_DEVICE_ID_RENESAS_SH7785	0x0007
 #define PCI_DEVICE_ID_RENESAS_SH7786	0x0010
 
+#define PCI_VENDOR_ID_SOLARFLARE	0x1924
+#define PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0	0x0703
+#define PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1	0x6703
+#define PCI_DEVICE_ID_SOLARFLARE_SFC4000B	0x0710
+
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
@@ -2414,6 +2514,11 @@
 
 #define PCI_VENDOR_ID_AZWAVE		0x1a3b
 
+#define PCI_VENDOR_ID_ASMEDIA		0x1b21
+
+#define PCI_VENDOR_ID_CIRCUITCO		0x1cc8
+#define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD	0x0001
+
 #define PCI_VENDOR_ID_TEKRAM		0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
 
@@ -2463,6 +2568,9 @@
 
 #define PCI_VENDOR_ID_INTEL		0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC	0x0008
+#define PCI_DEVICE_ID_INTEL_SNB_IMC	0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC	0x0154
+#define PCI_DEVICE_ID_INTEL_HSW_IMC	0x0c00
 #define PCI_DEVICE_ID_INTEL_PXHD_0	0x0320
 #define PCI_DEVICE_ID_INTEL_PXHD_1	0x0321
 #define PCI_DEVICE_ID_INTEL_PXH_0	0x0329
@@ -2485,6 +2593,7 @@
 #define PCI_DEVICE_ID_INTEL_MRST_SD2	0x084F
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM	0x0962
+#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB	0x0c60
 #define PCI_DEVICE_ID_INTEL_82541ER	0x1078
 #define PCI_DEVICE_ID_INTEL_82541GI_LF	0x107c
 #define PCI_DEVICE_ID_INTEL_82542	0x1000
@@ -2564,13 +2673,50 @@
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_HDA	0x1c20
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS	0x1c22
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN	0x1c41
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_Z68		0x1c44
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_P67		0x1c46
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_UM67	0x1c47
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_HM65	0x1c49
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_H67		0x1c4a
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_HM67	0x1c4b
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_Q65		0x1c4c
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_QS67	0x1c4d
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_Q67		0x1c4e
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_QM67	0x1c4f
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_B65		0x1c50
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_C202	0x1c52
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_C204	0x1c54
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_C206	0x1c56
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_H61		0x1c5c
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX	0x1c5f
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE	0x1e03
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA	0x1e20
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e41
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS	0x1d22
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC	0x1d40
+#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0	0x1d40
+#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1	0x1d41
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE	0x1e03
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA	0x1e20
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI	0x1e31
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN	0x1e41
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_B75	0x1e49
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_C216	0x1e53
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_H77	0x1e4A
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM70	0x1e5e
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM75	0x1e5d
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM76	0x1e59
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM77	0x1e57
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MBL_SAMPLE 0x1e42
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_NM70	0x1e5f
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Q75	0x1e48
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Q77	0x1e47
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_QM77	0x1e55
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_QS77	0x1e56
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_SFF_SAMPLE 0x1e43
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_UM77	0x1e58
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Z75	0x1e46
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Z77	0x1e44
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX	0x1e5f
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN	0x2310
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX	0x231f
 #define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3	0x2413
@@ -2783,8 +2929,30 @@
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN	0x3b00
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX	0x3b1f
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB0	0x3c20
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB1	0x3c21
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB2	0x3c22
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB3	0x3c23
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB4	0x3c24
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB5	0x3c25
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB6	0x3c26
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB7	0x3c27
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB8	0x3c2e
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB9	0x3c2f
+#define PCI_DEVICE_ID_INTEL_UNC_HA	0x3c46
+#define PCI_DEVICE_ID_INTEL_UNC_IMC0	0x3cb0
+#define PCI_DEVICE_ID_INTEL_UNC_IMC1	0x3cb1
+#define PCI_DEVICE_ID_INTEL_UNC_IMC2	0x3cb4
+#define PCI_DEVICE_ID_INTEL_UNC_IMC3	0x3cb5
+#define PCI_DEVICE_ID_INTEL_UNC_QPI0	0x3c41
+#define PCI_DEVICE_ID_INTEL_UNC_QPI1	0x3c42
+#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE	0x3c43
+#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0	0x3c44
+#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1	0x3c45
+#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX	0x3ce0
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB	0x402f
 #define PCI_DEVICE_ID_INTEL_5100_16	0x65f0
+#define PCI_DEVICE_ID_INTEL_5100_19	0x65f3
 #define PCI_DEVICE_ID_INTEL_5100_21	0x65f5
 #define PCI_DEVICE_ID_INTEL_5100_22	0x65f6
 #define PCI_DEVICE_ID_INTEL_5400_ERR	0x4030
@@ -2823,6 +2991,7 @@
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
 #define PCI_DEVICE_ID_INTEL_SCH_LPC	0x8119
 #define PCI_DEVICE_ID_INTEL_SCH_IDE	0x811a
+#define PCI_DEVICE_ID_INTEL_ITC_LPC	0x8186
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
@@ -2905,7 +3074,11 @@
 #define PCI_DEVICE_ID_NETMOS_9845	0x9845
 #define PCI_DEVICE_ID_NETMOS_9855	0x9855
 #define PCI_DEVICE_ID_NETMOS_9865	0x9865
+#define PCI_DEVICE_ID_NETMOS_9900	0x9900
 #define PCI_DEVICE_ID_NETMOS_9901	0x9901
+#define PCI_DEVICE_ID_NETMOS_9904	0x9904
+#define PCI_DEVICE_ID_NETMOS_9912	0x9912
+#define PCI_DEVICE_ID_NETMOS_9922	0x9922
 
 #define PCI_VENDOR_ID_3COM_2		0xa727
 
@@ -2927,3 +3100,5 @@
 
 #define PCI_VENDOR_ID_XEN		0x5853
 #define PCI_DEVICE_ID_XEN_PLATFORM	0x0001
+
+#define PCI_VENDOR_ID_OCZ		0x1b85
diff --git a/include/pci_rom.h b/include/pci_rom.h
new file mode 100644
index 0000000..8b2674c
--- /dev/null
+++ b/include/pci_rom.h
@@ -0,0 +1,58 @@
+/*
+ * From coreboot file of same name
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _PCI_ROM_H
+#define _PCI_ROM_H
+
+#define PCI_ROM_HDR			0xaa55
+#define PCI_VGA_RAM_IMAGE_START		0xc0000
+
+struct pci_rom_header {
+	uint16_t signature;
+	uint8_t size;
+	uint8_t init[3];
+	uint8_t reserved[0x12];
+	uint16_t data;
+};
+
+struct pci_rom_data {
+	uint32_t signature;
+	uint16_t vendor;
+	uint16_t device;
+	uint16_t reserved_1;
+	uint16_t dlen;
+	uint8_t drevision;
+	uint8_t class_lo;
+	uint16_t class_hi;
+	uint16_t ilen;
+	uint16_t irevision;
+	uint8_t type;
+	uint8_t indicator;
+	uint16_t reserved_2;
+};
+
+ /**
+ * pci_run_vga_bios() - Run the VGA BIOS in an x86 PC
+ *
+ * @dev:	Video device containing the BIOS
+ * @int15_handler:	Function to call to handle int 0x15
+ * @emulate:	true to use the x86 emulator, false to run native
+ */
+int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate);
+
+/**
+ * board_map_oprom_vendev() - map several PCI IDs to the one the ROM expects
+ *
+ * Some VGA option roms are used for several chipsets but they only have one
+ * PCI ID in their header. If we encounter such an option rom, we need to do
+ * the mapping ourselves.
+ *
+ * @vendev:	Vendor and device for the video device
+ * @return standard vendor and device expected by the ROM
+ */
+uint32_t board_map_oprom_vendev(uint32_t vendev);
+
+#endif
diff --git a/include/rtc.h b/include/rtc.h
index c034966..d11aa8b 100644
--- a/include/rtc.h
+++ b/include/rtc.h
@@ -50,4 +50,9 @@
 unsigned long mktime (unsigned int, unsigned int, unsigned int,
 		      unsigned int, unsigned int, unsigned int);
 
+/**
+ * rtc_init() - Set up the real time clock ready for use
+ */
+void rtc_init(void);
+
 #endif	/* _RTC_H_ */
diff --git a/include/vbe.h b/include/vbe.h
new file mode 100644
index 0000000..d405691
--- /dev/null
+++ b/include/vbe.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation
+ * Copyright (c) 2009 Pattrick Hueper <phueper@hueper.net>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:	BSD-2-Clause
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+#ifndef _VBE_H
+#define _VBE_H
+
+/* these structs are for input from and output to OF */
+struct __packed screen_info {
+	u8 display_type;	/* 0=NONE, 1= analog, 2=digital */
+	u16 screen_width;
+	u16 screen_height;
+	/* bytes per line in framebuffer, may be more than screen_width */
+	u16 screen_linebytes;
+	u8 color_depth;	/* color depth in bits per pixel */
+	u32 framebuffer_address;
+	u8 edid_block_zero[128];
+};
+
+struct __packed screen_info_input {
+	u8 signature[4];
+	u16 size_reserved;
+	u8 monitor_number;
+	u16 max_screen_width;
+	u8 color_depth;
+};
+
+/* these structs only store the required a subset of the VBE-defined fields */
+struct __packed vbe_info {
+	char signature[4];
+	u16 version;
+	u8 *oem_string_ptr;
+	u32 capabilities;
+	u16 video_mode_list[256];
+	u16 total_memory;
+};
+
+struct __packed vesa_mode_info {
+	u16 mode_attributes;	/* 00 */
+	u8 win_a_attributes;	/* 02 */
+	u8 win_b_attributes;	/* 03 */
+	u16 win_granularity;	/* 04 */
+	u16 win_size;		/* 06 */
+	u16 win_a_segment;	/* 08 */
+	u16 win_b_segment;	/* 0a */
+	u32 win_func_ptr;	/* 0c */
+	u16 bytes_per_scanline;	/* 10 */
+	u16 x_resolution;	/* 12 */
+	u16 y_resolution;	/* 14 */
+	u8 x_charsize;		/* 16 */
+	u8 y_charsize;		/* 17 */
+	u8 number_of_planes;	/* 18 */
+	u8 bits_per_pixel;	/* 19 */
+	u8 number_of_banks;	/* 20 */
+	u8 memory_model;	/* 21 */
+	u8 bank_size;		/* 22 */
+	u8 number_of_image_pages; /* 23 */
+	u8 reserved_page;
+	u8 red_mask_size;
+	u8 red_mask_pos;
+	u8 green_mask_size;
+	u8 green_mask_pos;
+	u8 blue_mask_size;
+	u8 blue_mask_pos;
+	u8 reserved_mask_size;
+	u8 reserved_mask_pos;
+	u8 direct_color_mode_info;
+	u32 phys_base_ptr;
+	u32 offscreen_mem_offset;
+	u16 offscreen_mem_size;
+	u8 reserved[206];
+};
+
+struct vbe_mode_info {
+	u16 video_mode;
+	bool valid;
+	union {
+		struct vesa_mode_info vesa;
+		u8 mode_info_block[256];
+	};
+};
+
+struct vbe_ddc_info {
+	u8 port_number;	/* i.e. monitor number */
+	u8 edid_transfer_time;
+	u8 ddc_level;
+	u8 edid_block_zero[128];
+};
+
+#define VESA_GET_INFO		0x4f00
+#define VESA_GET_MODE_INFO	0x4f01
+#define VESA_SET_MODE		0x4f02
+
+struct graphic_device;
+int vbe_get_video_info(struct graphic_device *gdev);
+
+#endif
diff --git a/include/video_fb.h b/include/video_fb.h
index 6cd4e37..55ec24d 100644
--- a/include/video_fb.h
+++ b/include/video_fb.h
@@ -40,7 +40,7 @@
 /* Export Graphic Driver Control                                              */
 /******************************************************************************/
 
-typedef struct {
+typedef struct graphic_device {
     unsigned int isaBase;
     unsigned int pciBase;
     unsigned int dprBase;
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 7c7e673..9d86dba 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -75,6 +75,9 @@
 	COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
 	COMPAT(INTEL_MICROCODE, "intel,microcode"),
 	COMPAT(MEMORY_SPD, "memory-spd"),
+	COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"),
+	COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"),
+	COMPAT(INTEL_GMA, "intel,gma"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -370,21 +373,6 @@
 	return -ENOENT;
 }
 
-int fdtdec_get_alias_node(const void *blob, const char *name)
-{
-	const char *prop;
-	int alias_node;
-	int len;
-
-	if (!blob)
-		return -FDT_ERR_NOTFOUND;
-	alias_node = fdt_path_offset(blob, "/aliases");
-	prop = fdt_getprop(blob, alias_node, name, &len);
-	if (!prop)
-		return -FDT_ERR_NOTFOUND;
-	return fdt_path_offset(blob, prop);
-}
-
 int fdtdec_get_chosen_node(const void *blob, const char *name)
 {
 	const char *prop;
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 9d1383a..13af604 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -260,11 +260,13 @@
 cmd_dt_S_dtb=						\
 (							\
 	echo '.section .dtb.init.rodata,"a"';		\
+	echo '.balign 16';				\
 	echo '.global __dtb_$(*F)_begin';		\
 	echo '__dtb_$(*F)_begin:';			\
 	echo '.incbin "$<" ';				\
 	echo '__dtb_$(*F)_end:';			\
 	echo '.global __dtb_$(*F)_end';			\
+	echo '.balign 16';				\
 ) > $@
 
 $(obj)/%.dtb.S: $(obj)/%.dtb
diff --git a/tools/.gitignore b/tools/.gitignore
index e7f0f8f..9bc9fec 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -4,6 +4,7 @@
 /fit_check_sign
 /fit_info
 /gen_eth_addr
+/ifdtool
 /img2srec
 /kwboot
 /dumpimage