diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 916ab84ea0c49e177094ee239486d1dcf3eb293b..a0713dd66c0ad25d46ec8988e7b9accd28414217 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -1,5 +1,5 @@
 variables:
-  windows_vm: vs2015-win2012r2
+  windows_vm: vs2017-win2016
   ubuntu_vm: ubuntu-18.04
   ci_runner_image: trini/u-boot-gitlab-ci-runner:bionic-20200112-17Jan2020
   # Add '-u 0' options for Azure pipelines, otherwise we get "permission
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 89b93e5de25aa7228a7699ec373efa189697a089..b733d2264efa1595c839e2fd73d6f8cb919909ff 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -709,6 +709,12 @@ config ROM_TABLE_SIZE
 	hex
 	default 0x10000
 
+config HAVE_ITSS
+	bool "Enable ITSS"
+	help
+	  Select this to include the driver for the Interrupt Timer
+	  Subsystem (ITSS) which is found on several Intel devices.
+
 menu "System tables"
 	depends on !EFI && !SYS_COREBOOT
 
diff --git a/arch/x86/cpu/apollolake/Kconfig b/arch/x86/cpu/apollolake/Kconfig
index fcff176c27d11aa9d34b834893615632a408c5b8..a760e0ac68ea27aa6813a52580634095e1ceab49 100644
--- a/arch/x86/cpu/apollolake/Kconfig
+++ b/arch/x86/cpu/apollolake/Kconfig
@@ -39,6 +39,7 @@ config INTEL_APOLLOLAKE
 	imply HAVE_X86_FIT
 	imply INTEL_GPIO
 	imply SMP
+	imply HAVE_ITSS
 
 if INTEL_APOLLOLAKE
 
diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile
index 1760df54d810d069e59ca57a3723c307b927f6d4..f99f2c6473971cf474c64da4063e226c99abbefb 100644
--- a/arch/x86/cpu/apollolake/Makefile
+++ b/arch/x86/cpu/apollolake/Makefile
@@ -19,7 +19,6 @@ obj-y += fsp_s.o
 endif
 
 obj-y += hostbridge.o
-obj-y += itss.o
 obj-y += lpc.o
 obj-y += p2sb.o
 obj-y += pch.o
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 1592b2c9d3b3a503251af4317b6541db89721e29..c8da7f10e9b611739b821d5d4c004b3acfc482f0 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -136,10 +136,14 @@ void arch_setup_gd(gd_t *new_gd)
 	/* DS: data, read/write, 4 GB, base 0 */
 	gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff);
 
-	/* FS: data, read/write, 4 GB, base (Global Data Pointer) */
+	/*
+	 * FS: data, read/write, sizeof (Global Data Pointer),
+	 * base (Global Data Pointer)
+	 */
 	new_gd->arch.gd_addr = new_gd;
-	gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0xc093,
-		     (ulong)&new_gd->arch.gd_addr, 0xfffff);
+	gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0x8093,
+					(ulong)&new_gd->arch.gd_addr,
+					sizeof(new_gd->arch.gd_addr) - 1);
 
 	/* 16-bit CS: code, read/execute, 64 kB, base 0 */
 	gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff);
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile
index cc4e1c962b99542e4eab09369064e54bd948706b..e22c70781d60644ef5661c1ee29de3b1e411b08d 100644
--- a/arch/x86/cpu/intel_common/Makefile
+++ b/arch/x86/cpu/intel_common/Makefile
@@ -27,6 +27,7 @@ obj-y += microcode.o
 endif
 endif
 obj-y += pch.o
+obj-$(CONFIG_HAVE_ITSS) += itss.o
 
 ifdef CONFIG_SPL
 ifndef CONFIG_SPL_BUILD
diff --git a/arch/x86/cpu/apollolake/itss.c b/arch/x86/cpu/intel_common/itss.c
similarity index 73%
rename from arch/x86/cpu/apollolake/itss.c
rename to arch/x86/cpu/intel_common/itss.c
index 8789f8e6bb979e0df1f13a5c28e4692b9467da0b..9df51adecc10168733dbb202dec4f315c8ad2630 100644
--- a/arch/x86/cpu/apollolake/itss.c
+++ b/arch/x86/cpu/intel_common/itss.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Something to do with Interrupts, but I don't know what ITSS stands for
+ * Interrupt Timer Subsystem
  *
  * Copyright (C) 2017 Intel Corporation.
  * Copyright (C) 2017 Siemens AG
@@ -15,12 +15,12 @@
 #include <irq.h>
 #include <p2sb.h>
 #include <spl.h>
-#include <asm/arch/itss.h>
+#include <asm/itss.h>
 
-struct apl_itss_platdata {
+struct itss_platdata {
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
 	/* Put this first since driver model will copy the data here */
-	struct dtd_intel_apl_itss dtplat;
+	struct dtd_intel_itss dtplat;
 #endif
 };
 
@@ -30,13 +30,13 @@ struct pmc_route {
 	u32 gpio;
 };
 
-struct apl_itss_priv {
+struct itss_priv {
 	struct pmc_route *route;
 	uint route_count;
 	u32 irq_snapshot[NUM_IPC_REGS];
 };
 
-static int apl_set_polarity(struct udevice *dev, uint irq, bool active_low)
+static int set_polarity(struct udevice *dev, uint irq, bool active_low)
 {
 	u32 mask;
 	uint reg;
@@ -53,9 +53,9 @@ static int apl_set_polarity(struct udevice *dev, uint irq, bool active_low)
 }
 
 #ifndef CONFIG_TPL_BUILD
-static int apl_snapshot_polarities(struct udevice *dev)
+static int snapshot_polarities(struct udevice *dev)
 {
-	struct apl_itss_priv *priv = dev_get_priv(dev);
+	struct itss_priv *priv = dev_get_priv(dev);
 	const int start = GPIO_IRQ_START;
 	const int end = GPIO_IRQ_END;
 	int reg_start;
@@ -86,9 +86,9 @@ static void show_polarities(struct udevice *dev, const char *msg)
 	}
 }
 
-static int apl_restore_polarities(struct udevice *dev)
+static int restore_polarities(struct udevice *dev)
 {
-	struct apl_itss_priv *priv = dev_get_priv(dev);
+	struct itss_priv *priv = dev_get_priv(dev);
 	const int start = GPIO_IRQ_START;
 	const int end = GPIO_IRQ_END;
 	int reg_start;
@@ -132,9 +132,9 @@ static int apl_restore_polarities(struct udevice *dev)
 }
 #endif
 
-static int apl_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
+static int route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
 {
-	struct apl_itss_priv *priv = dev_get_priv(dev);
+	struct itss_priv *priv = dev_get_priv(dev);
 	struct pmc_route *route;
 	int i;
 
@@ -146,14 +146,14 @@ static int apl_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
 	return -ENOENT;
 }
 
-static int apl_itss_ofdata_to_platdata(struct udevice *dev)
+static int itss_ofdata_to_platdata(struct udevice *dev)
 {
-	struct apl_itss_priv *priv = dev_get_priv(dev);
+	struct itss_priv *priv = dev_get_priv(dev);
 	int ret;
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
-	struct apl_itss_platdata *plat = dev_get_platdata(dev);
-	struct dtd_intel_apl_itss *dtplat = &plat->dtplat;
+	struct itss_platdata *plat = dev_get_platdata(dev);
+	struct dtd_intel_itss *dtplat = &plat->dtplat;
 
 	/*
 	 * It would be nice to do this in the bind() method, but with
@@ -189,26 +189,26 @@ static int apl_itss_ofdata_to_platdata(struct udevice *dev)
 	return 0;
 }
 
-static const struct irq_ops apl_itss_ops = {
-	.route_pmc_gpio_gpe	= apl_route_pmc_gpio_gpe,
-	.set_polarity	= apl_set_polarity,
+static const struct irq_ops itss_ops = {
+	.route_pmc_gpio_gpe	= route_pmc_gpio_gpe,
+	.set_polarity	= set_polarity,
 #ifndef CONFIG_TPL_BUILD
-	.snapshot_polarities = apl_snapshot_polarities,
-	.restore_polarities = apl_restore_polarities,
+	.snapshot_polarities = snapshot_polarities,
+	.restore_polarities = restore_polarities,
 #endif
 };
 
-static const struct udevice_id apl_itss_ids[] = {
-	{ .compatible = "intel,apl-itss"},
+static const struct udevice_id itss_ids[] = {
+	{ .compatible = "intel,itss"},
 	{ }
 };
 
-U_BOOT_DRIVER(apl_itss_drv) = {
-	.name		= "intel_apl_itss",
+U_BOOT_DRIVER(itss_drv) = {
+	.name		= "intel_itss",
 	.id		= UCLASS_IRQ,
-	.of_match	= apl_itss_ids,
-	.ops		= &apl_itss_ops,
-	.ofdata_to_platdata = apl_itss_ofdata_to_platdata,
-	.platdata_auto_alloc_size = sizeof(struct apl_itss_platdata),
-	.priv_auto_alloc_size = sizeof(struct apl_itss_priv),
+	.of_match	= itss_ids,
+	.ops		= &itss_ops,
+	.ofdata_to_platdata = itss_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct itss_platdata),
+	.priv_auto_alloc_size = sizeof(struct itss_priv),
 };
diff --git a/arch/x86/cpu/slimbootloader/serial.c b/arch/x86/cpu/slimbootloader/serial.c
index 7b44a59bffec462b4cbbc4273e3fe2bba9635bb4..bab54b18df67d3c62a5ee900b4857dc021c3f07b 100644
--- a/arch/x86/cpu/slimbootloader/serial.c
+++ b/arch/x86/cpu/slimbootloader/serial.c
@@ -34,18 +34,15 @@ static int slimbootloader_serial_ofdata_to_platdata(struct udevice *dev)
 	      data->stride,
 	      data->clk);
 
-	/*
-	 * The data->type provides port io or mmio access type info,
-	 * but the access type will be controlled by
-	 * CONFIG_SYS_NS16550_PORT_MAPPED or CONFIG_SYS_NS16550_MEM32.
-	 *
-	 * TBD: ns16550 access type configuration in runtime.
-	 *      ex) plat->access_type = data->type
-	 */
 	plat->base = data->base;
 	/* ns16550 uses reg_shift, then covert stride to shift */
 	plat->reg_shift = data->stride >> 1;
+	plat->reg_width = data->stride;
 	plat->clock = data->clk;
+	plat->fcr = UART_FCR_DEFVAL;
+	plat->flags = 0;
+	if (data->type == 1)
+		plat->flags |= NS16550_FLAG_IO;
 
 	return 0;
 }
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 01524635e9c82d9a498653605dc36d2107ea8d90..26cf995db2d01c8eb5475ee47070ad1aab2c13ae 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -50,7 +50,7 @@ _x86boot_start:
 	movl	%cr0, %eax
 	orl	$(X86_CR0_NW | X86_CR0_CD), %eax
 	movl	%eax, %cr0
-	wbinvd
+	invd
 
 	/*
 	 * Zero the BIST (Built-In Self Test) value since we don't have it.
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
index 54f4ff6662a8d8999311be3e7553882b1b245c2a..292e750508149aae68770160f1a39090a12a9912 100644
--- a/arch/x86/cpu/start16.S
+++ b/arch/x86/cpu/start16.S
@@ -28,7 +28,7 @@ start16:
 	movl	%cr0, %eax
 	orl	$(X86_CR0_NW | X86_CR0_CD), %eax
 	movl	%eax, %cr0
-	wbinvd
+	invd
 
 	/* load the temporary Global Descriptor Table */
 data32 cs	lidt	idt_ptr
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts
index 24fcbb5063128600586253d88038a95dc0bab8a8..a1820fa1870e1c04b66cefeabf3155e428e25b3b 100644
--- a/arch/x86/dts/chromebook_coral.dts
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -171,7 +171,7 @@
 
 			itss {
 				u-boot,dm-pre-reloc;
-				compatible = "intel,apl-itss";
+				compatible = "intel,itss";
 				intel,p2sb-port-id = <PID_ITSS>;
 				intel,pmc-routes = <
 					PMC_GPE_SW_31_0 GPIO_GPE_SW_31_0
diff --git a/arch/x86/dts/coreboot.dts b/arch/x86/dts/coreboot.dts
index a88da6eafd68f472008046a5cd0015fae9fbcd47..38ddaafa1981a12de5aabb0deb840a9c972e1897 100644
--- a/arch/x86/dts/coreboot.dts
+++ b/arch/x86/dts/coreboot.dts
@@ -8,7 +8,6 @@
 /dts-v1/;
 
 /include/ "skeleton.dtsi"
-/include/ "serial.dtsi"
 /include/ "keyboard.dtsi"
 /include/ "pcspkr.dtsi"
 /include/ "reset.dtsi"
@@ -40,6 +39,11 @@
 		u-boot,dm-pre-reloc;
 	};
 
+	serial: serial {
+		u-boot,dm-pre-reloc;
+		compatible = "coreboot-serial";
+	};
+
 	coreboot-fb {
 		compatible = "coreboot-fb";
 	};
diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h
index 2c54e24e02fb2614c75ece13926ad5be5cbf4276..61de0077d72cfcd99b92ea3a131b8afa81a7c132 100644
--- a/arch/x86/include/asm/coreboot_tables.h
+++ b/arch/x86/include/asm/coreboot_tables.h
@@ -97,6 +97,25 @@ struct cb_serial {
 	u32 type;
 	u32 baseaddr;
 	u32 baud;
+	u32 regwidth;
+
+	/*
+	 * Crystal or input frequency to the chip containing the UART.
+	 * Provide the board specific details to allow the payload to
+	 * initialize the chip containing the UART and make independent
+	 * decisions as to which dividers to select and their values
+	 * to eventually arrive at the desired console baud-rate.
+	 */
+	u32 input_hertz;
+
+	/*
+	 * UART PCI address: bus, device, function
+	 * 1 << 31 - Valid bit, PCI UART in use
+	 * Bus << 20
+	 * Device << 15
+	 * Function << 12
+	 */
+	u32 uart_pci_addr;
 };
 
 #define CB_TAG_CONSOLE			0x0010
diff --git a/arch/x86/include/asm/arch-apollolake/itss.h b/arch/x86/include/asm/itss.h
similarity index 97%
rename from arch/x86/include/asm/arch-apollolake/itss.h
rename to arch/x86/include/asm/itss.h
index 1e2950397454297c6c655fcf02b700338c80dfaa..c75d8fe8c2613f25793dbbd4413523ca6516f5ab 100644
--- a/arch/x86/include/asm/arch-apollolake/itss.h
+++ b/arch/x86/include/asm/itss.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
+ * Interrupt Timer Subsystem
+ *
  * Copyright (C) 2017 Intel Corporation.
  * Copyright 2019 Google LLC
  *
diff --git a/configs/edison_defconfig b/configs/edison_defconfig
index 14b2eec3ba99e8987945072e90f27c8019295e04..58707d619a23efd41a14075e408b670fb86d9ef8 100644
--- a/configs/edison_defconfig
+++ b/configs/edison_defconfig
@@ -6,10 +6,10 @@ CONFIG_NR_DRAM_BANKS=3
 CONFIG_VENDOR_INTEL=y
 CONFIG_TARGET_EDISON=y
 CONFIG_SMP=y
+CONFIG_GENERATE_ACPI_TABLE=y
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_HUSH_PARSER=y
-# CONFIG_CMDLINE_EDITING is not set
 CONFIG_CMD_CPU=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst
index 515fd06d769fd5000dd5b6d0b834ab0504ab01e6..5dc3c97c3d1a1ffbb6e1c14ffdfa2dd15b745943 100644
--- a/doc/board/google/chromebook_coral.rst
+++ b/doc/board/google/chromebook_coral.rst
@@ -112,7 +112,7 @@ U-Boot then shuts down CAR and jumps to its relocated version.
 
 
 Boot flow - U-Boot post-relocation
----------------------------------
+----------------------------------
 
 U-Boot starts up normally, running near the top of RAM. After driver model is
 running, arch_fsp_init_r() is called which loads and runs the FSP-S binary.
@@ -142,54 +142,56 @@ Performance
 -----------
 
 Bootstage is used through all phases of U-Boot to keep accurate timimgs for
-boot. Use 'bootstage report' in U-Boot to see the report, e.g.:
-
-Timer summary in microseconds (16 records):
-       Mark    Elapsed  Stage
-          0          0  reset
-    155,325    155,325  TPL
-    204,014     48,689  end TPL
-    204,385        371  SPL
-    738,633    534,248  end SPL
-    739,161        528  board_init_f
-    842,764    103,603  board_init_r
-  1,166,233    323,469  main_loop
-  1,166,283         50  id=175
-
-Accumulated time:
-                    62  fast_spi
-                   202  dm_r
-                 7,779  dm_spl
-                15,555  dm_f
-               208,357  fsp-m
-               239,847  fsp-s
-               292,143  mmap_spi
-
-CPU performance is about 3500 DMIPS:
-
-=> dhry
-1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS
+boot. Use 'bootstage report' in U-Boot to see the report, e.g.::
+
+    Timer summary in microseconds (16 records):
+           Mark    Elapsed  Stage
+              0          0  reset
+        155,325    155,325  TPL
+        204,014     48,689  end TPL
+        204,385        371  SPL
+        738,633    534,248  end SPL
+        739,161        528  board_init_f
+        842,764    103,603  board_init_r
+      1,166,233    323,469  main_loop
+      1,166,283         50  id=175
+
+    Accumulated time:
+                        62  fast_spi
+                       202  dm_r
+                     7,779  dm_spl
+                    15,555  dm_f
+                   208,357  fsp-m
+                   239,847  fsp-s
+                   292,143  mmap_spi
+
+CPU performance is about 3500 DMIPS::
+
+    => dhry
+    1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS
 
 
 Partial memory map
 ------------------
 
-ffffffff	Top of ROM (and last byte of 32-bit address space)
-ffff8000	TPL loaded here (from IFWI)
-ff000000	Bottom of ROM
-fefc000		 Top of CAR region
-fef96000	Stack for FSP-M
-fef40000 59000	FSP-M
-fef11000	SPL loaded here
-fef10000	CONFIG_BLOBLIST_ADDR
-fef10000	Stack top in TPL, SPL and U-Boot before relocation
-fef00000  1000	CONFIG_BOOTSTAGE_STASH_ADDR
-fef00000	Base of CAR region
-
-   f0000	CONFIG_ROM_TABLE_ADDR
-  120000	BSS (defined in u-boot-spl.lds)
-  200000	FSP-S (which is run after U-Boot is relocated)
- 1110000	CONFIG_SYS_TEXT_BASE
+::
+
+    ffffffff       Top of ROM (and last byte of 32-bit address space)
+    ffff8000       TPL loaded here (from IFWI)
+    ff000000       Bottom of ROM
+     fefc000       Top of CAR region
+    fef96000       Stack for FSP-M
+    fef40000 59000 FSP-M
+    fef11000       SPL loaded here
+    fef10000       CONFIG_BLOBLIST_ADDR
+    fef10000       Stack top in TPL, SPL and U-Boot before relocation
+    fef00000  1000 CONFIG_BOOTSTAGE_STASH_ADDR
+    fef00000       Base of CAR region
+
+       f0000       CONFIG_ROM_TABLE_ADDR
+      120000       BSS (defined in u-boot-spl.lds)
+      200000       FSP-S (which is run after U-Boot is relocated)
+     1110000       CONFIG_SYS_TEXT_BASE
 
 
 Supported peripherals
diff --git a/doc/board/intel/slimbootloader.rst b/doc/board/intel/slimbootloader.rst
index 375e6768045824fb448a761851f50750e3c84e25..a8c41b1aa70fcf14e085d2b3dabf65f67f125392 100644
--- a/doc/board/intel/slimbootloader.rst
+++ b/doc/board/intel/slimbootloader.rst
@@ -111,35 +111,16 @@ Download it from http://downloads.yoctoproject.org/releases/yocto/yocto-2.0/mach
 Build Instruction for Slim Bootloader for LeafHill (APL) target
 ---------------------------------------------------------------
 
-LeafHill is using PCI UART2 device as a serial port.
-For MEM32 serial port, CONFIG_SYS_NS16550_MEM32 needs to be enabled in U-Boot.
+Prepare U-Boot and Slim Bootloader as described at the beginning of this page.
+Also, the PayloadId needs to be set for APL board.
 
-1. Enable CONFIG_SYS_NS16550_MEM32 in U-Boot::
-
-    $ vi include/configs/slimbootloader.h
-    +#define CONFIG_SYS_NS16550_MEM32
-     #ifdef CONFIG_SYS_NS16550_MEM3
-
-2. Build U-Boot::
-
-   $ make disclean
-   $ make slimbootloader_defconfig
-   $ make all
-
-3. Copy u-boot-dtb.bin to Slim Bootloader.
-   Slim Bootloader looks for a payload from the specific location.
-   Copy the build u-boot-dtb.bin to the expected location::
-
-   $ mkdir -p <Slim Bootloader Dir>/PayloadPkg/PayloadBins/
-   $ cp <U-Boot Dir>/u-boot-dtb.bin <Slim Bootloader Dir>/PayloadPkg/PayloadBins/u-boot-dtb.bin
-
-4. Update PayloadId. Let's use 'U-BT' as an example::
+1. Update PayloadId. Let's use 'U-BT' as an example::
 
     $ vi Platform/ApollolakeBoardPkg/CfgData/CfgData_Int_LeafHill.dlt
     -GEN_CFG_DATA.PayloadId                     | 'AUTO
     +GEN_CFG_DATA.PayloadId                     | 'U-BT'
 
-5. Update payload text base.
+2. Update payload text base.
 
 * PAYLOAD_EXE_BASE must be the same as U-Boot CONFIG_SYS_TEXT_BASE
   in board/intel/slimbootloader/Kconfig.
@@ -149,18 +130,18 @@ For MEM32 serial port, CONFIG_SYS_NS16550_MEM32 needs to be enabled in U-Boot.
     +               self.PAYLOAD_LOAD_HIGH    = 0
     +               self.PAYLOAD_EXE_BASE     = 0x00100000
 
-6. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId
+3. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId
    in build command. The output is Outputs/apl/Stitch_Components.zip::
 
    $ python BuildLoader.py build apl -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma"
 
-7. Stitch IFWI.
+4. Stitch IFWI.
 
    Refer to Apollolake_ page in Slim Bootloader document site::
 
    $ python Platform/ApollolakeBoardPkg/Script/StitchLoader.py -i <Existing IFWI> -s Outputs/apl/Stitch_Components.zip -o <Output IFWI>
 
-8. Flash IFWI.
+5. Flash IFWI.
 
    Use DediProg to flash IFWI. You should reach at U-Boot serial console.
 
@@ -175,7 +156,7 @@ Build Instruction to use ELF U-Boot
 
 2. Build U-Boot::
 
-   $ make disclean
+   $ make distclean
    $ make slimbootloader_defconfig
    $ make all
    $ strip u-boot (removing symbol for reduced size)
diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c
index 4bf1c9ddc4e7057544d287b9aa08f41612955814..67b8b80b9d68c07cc021540bdb213ceab8f8975a 100644
--- a/drivers/gpio/intel_gpio.c
+++ b/drivers/gpio/intel_gpio.c
@@ -39,9 +39,9 @@ static int intel_gpio_direction_output(struct udevice *dev, uint offset,
 	struct udevice *pinctrl = dev_get_parent(dev);
 	uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset);
 
-	pcr_clrsetbits32(dev, config_offset,
+	pcr_clrsetbits32(pinctrl, config_offset,
 			 PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE |
-				  PAD_CFG0_TX_DISABLE,
+				  PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE,
 			 PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE |
 				  (value ? PAD_CFG0_TX_STATE : 0));
 
@@ -59,9 +59,9 @@ static int intel_gpio_get_value(struct udevice *dev, uint offset)
 	if (!mode) {
 		rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE);
 		if (rx_tx == PAD_CFG0_TX_DISABLE)
-			return mode & PAD_CFG0_RX_STATE_BIT ? 1 : 0;
+			return reg & PAD_CFG0_RX_STATE ? 1 : 0;
 		else if (rx_tx == PAD_CFG0_RX_DISABLE)
-			return mode & PAD_CFG0_TX_STATE_BIT ? 1 : 0;
+			return reg & PAD_CFG0_TX_STATE ? 1 : 0;
 	}
 
 	return 0;
@@ -72,7 +72,7 @@ static int intel_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 	struct udevice *pinctrl = dev_get_parent(dev);
 	uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset);
 
-	pcr_clrsetbits32(dev, config_offset, PAD_CFG0_TX_STATE,
+	pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_TX_STATE,
 			 value ? PAD_CFG0_TX_STATE : 0);
 
 	return 0;
diff --git a/drivers/pinctrl/intel/pinctrl.c b/drivers/pinctrl/intel/pinctrl.c
index 4875a3b0b52eb22b7426adb09eabb82f21de19ed..5bf5d8b0e24abb4c4094828155f8b5543f8c1bc5 100644
--- a/drivers/pinctrl/intel/pinctrl.c
+++ b/drivers/pinctrl/intel/pinctrl.c
@@ -25,7 +25,7 @@
 #include <asm/intel_pinctrl.h>
 #include <asm/intel_pinctrl_defs.h>
 #include <asm/arch/gpio.h>
-#include <asm/arch/itss.h>
+#include <asm/itss.h>
 #include <dm/device-internal.h>
 #include <dt-bindings/gpio/gpio.h>
 
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index bd95f70b61c7768d2f9e086342a811d027a38d87..cd2e098883f7acc2bf67c4f4088f8a72e7807f12 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -542,6 +542,17 @@ config BCM6345_SERIAL
 	help
 	  Select this to enable UART on BCM6345 SoCs.
 
+config COREBOOT_SERIAL
+	bool "Coreboot UART support"
+	depends on DM_SERIAL
+	default y if SYS_COREBOOT
+	select SYS_NS16550
+	help
+	  Select this to enable a ns16550-style UART where the platform data
+	  comes from the coreboot 'sysinfo' tables. This allows U-Boot to have
+	  a serial console on any platform without needing to change the
+	  device tree, etc.
+
 config FSL_LINFLEXUART
 	bool "Freescale Linflex UART support"
 	depends on DM_SERIAL
@@ -601,6 +612,27 @@ config SYS_NS16550
 	  be used. It can be a constant or a function to get clock, eg,
 	  get_serial_clock().
 
+config NS16550_DYNAMIC
+	bool "Allow NS16550 to be configured at runtime"
+	default y if SYS_COREBOOT || SYS_SLIMBOOTLOADER
+	help
+	  Enable this option to allow device-tree control of the driver.
+
+	  Normally this driver is controlled by the following options:
+
+	  CONFIG_SYS_NS16550_PORT_MAPPED - indicates that port I/O is used for
+	     access. If not enabled, then the UART is memory-mapped.
+	  CONFIG_SYS_NS16550_MEM32 - if memory-mapped, indicates that 32-bit
+	     access should be used (instead of 8-bit)
+	  CONFIG_SYS_NS16550_REG_SIZE - indicates register width and also
+	     endianness. If positive, big-endian access is used. If negative,
+	     little-endian is used.
+
+	  It is not a good practice for a driver to be statically configured,
+	  since it prevents the same driver being used for different types of
+	  UARTs in a system. This option avoids this problem at the cost of a
+	  slightly increased code size.
+
 config INTEL_MID_SERIAL
 	bool "Intel MID platform UART support"
 	depends on DM_SERIAL && OF_CONTROL
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 06ee30697deb0d5e486ba0f155a99327b7623ac5..76b1811510d138b075b722125cc2f11e86b7bcad 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_AR933X_UART) += serial_ar933x.o
 obj-$(CONFIG_ARM_DCC) += arm_dcc.o
 obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
 obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o
+obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
 obj-$(CONFIG_EFI_APP) += serial_efi.o
 obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
 obj-$(CONFIG_MCFUART) += mcfuart.o
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 9851663dc54f8a301fb8bb075898473621cc8538..31f6cfe421c26e6e59b7301096a3525779b422dc 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -93,19 +93,79 @@ static inline int serial_in_shift(void *addr, int shift)
 #define CONFIG_SYS_NS16550_CLK  0
 #endif
 
+/*
+ * Use this #ifdef for now since many platforms don't define in(), out(),
+ * out_le32(), etc. but we don't have #defines to indicate this.
+ *
+ * TODO(sjg@chromium.org): Add CONFIG options to indicate what I/O is available
+ * on a platform
+ */
+#ifdef CONFIG_NS16550_DYNAMIC
+static void serial_out_dynamic(struct ns16550_platdata *plat, u8 *addr,
+			       int value)
+{
+	if (plat->flags & NS16550_FLAG_IO) {
+		outb(value, addr);
+	} else if (plat->reg_width == 4) {
+		if (plat->flags & NS16550_FLAG_ENDIAN) {
+			if (plat->flags & NS16550_FLAG_BE)
+				out_be32(addr, value);
+			else
+				out_le32(addr, value);
+		} else {
+			writel(value, addr);
+		}
+	} else if (plat->flags & NS16550_FLAG_BE) {
+		writeb(value, addr + (1 << plat->reg_shift) - 1);
+	} else {
+		writeb(value, addr);
+	}
+}
+
+static int serial_in_dynamic(struct ns16550_platdata *plat, u8 *addr)
+{
+	if (plat->flags & NS16550_FLAG_IO) {
+		return inb(addr);
+	} else if (plat->reg_width == 4) {
+		if (plat->flags & NS16550_FLAG_ENDIAN) {
+			if (plat->flags & NS16550_FLAG_BE)
+				return in_be32(addr);
+			else
+				return in_le32(addr);
+		} else {
+			return readl(addr);
+		}
+	} else if (plat->flags & NS16550_FLAG_BE) {
+		return readb(addr + (1 << plat->reg_shift) - 1);
+	} else {
+		return readb(addr);
+	}
+}
+#else
+static inline void serial_out_dynamic(struct ns16550_platdata *plat, u8 *addr,
+				      int value)
+{
+}
+
+static inline int serial_in_dynamic(struct ns16550_platdata *plat, u8 *addr)
+{
+	return 0;
+}
+
+#endif /* CONFIG_NS16550_DYNAMIC */
+
 static void ns16550_writeb(NS16550_t port, int offset, int value)
 {
 	struct ns16550_platdata *plat = port->plat;
 	unsigned char *addr;
 
 	offset *= 1 << plat->reg_shift;
-	addr = (unsigned char *)plat->base + offset;
+	addr = (unsigned char *)plat->base + offset + plat->reg_offset;
 
-	/*
-	 * As far as we know it doesn't make sense to support selection of
-	 * these options at run-time, so use the existing CONFIG options.
-	 */
-	serial_out_shift(addr + plat->reg_offset, plat->reg_shift, value);
+	if (IS_ENABLED(CONFIG_NS16550_DYNAMIC))
+		serial_out_dynamic(plat, addr, value);
+	else
+		serial_out_shift(addr, plat->reg_shift, value);
 }
 
 static int ns16550_readb(NS16550_t port, int offset)
@@ -114,9 +174,12 @@ static int ns16550_readb(NS16550_t port, int offset)
 	unsigned char *addr;
 
 	offset *= 1 << plat->reg_shift;
-	addr = (unsigned char *)plat->base + offset;
+	addr = (unsigned char *)plat->base + offset + plat->reg_offset;
 
-	return serial_in_shift(addr + plat->reg_offset, plat->reg_shift);
+	if (IS_ENABLED(CONFIG_NS16550_DYNAMIC))
+		return serial_in_dynamic(plat, addr);
+	else
+		return serial_in_shift(addr, plat->reg_shift);
 }
 
 static u32 ns16550_getfcr(NS16550_t port)
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
new file mode 100644
index 0000000000000000000000000000000000000000..ccab347514cfb6a483431b16512dc2d6ec3d367e
--- /dev/null
+++ b/drivers/serial/serial_coreboot.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UART support for U-Boot when launched from Coreboot
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/sysinfo.h>
+
+static int coreboot_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ns16550_platdata *plat = dev_get_platdata(dev);
+	struct cb_serial *cb_info = lib_sysinfo.serial;
+
+	plat->base = cb_info->baseaddr;
+	plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0;
+	plat->reg_width = cb_info->regwidth;
+	plat->clock = cb_info->input_hertz;
+	plat->fcr = UART_FCR_DEFVAL;
+	plat->flags = 0;
+	if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED)
+		plat->flags |= NS16550_FLAG_IO;
+
+	return 0;
+}
+
+static const struct udevice_id coreboot_serial_ids[] = {
+	{ .compatible = "coreboot-serial" },
+	{ },
+};
+
+U_BOOT_DRIVER(coreboot_uart) = {
+	.name	= "coreboot_uart",
+	.id	= UCLASS_SERIAL,
+	.of_match	= coreboot_serial_ids,
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+	.ofdata_to_platdata  = coreboot_ofdata_to_platdata,
+	.probe	= ns16550_serial_probe,
+	.ops	= &ns16550_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 133b25b72e48c0960eb7393e05365ba23c74922b..a9d7715a556a5356d4526f6f33148a0ca19bd5df 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -562,16 +562,8 @@ static int ich_spi_exec_op_hwseq(struct spi_slave *slave,
 		return 0;  /* ignore */
 	case SPINOR_OP_BE_4K:
 		cycle = HSFSTS_CYCLE_4K_ERASE;
-		while (len) {
-			uint xfer_len = 0x1000;
-
-			ret = exec_sync_hwseq_xfer(regs, cycle, offset, 0);
-			if (ret)
-				return ret;
-			offset += xfer_len;
-			len -= xfer_len;
-		}
-		return 0;
+		ret = exec_sync_hwseq_xfer(regs, cycle, offset, 0);
+		return ret;
 	default:
 		debug("Unknown cycle %x\n", op->cmd.opcode);
 		return -EINVAL;
diff --git a/include/configs/slimbootloader.h b/include/configs/slimbootloader.h
index e0011ed4461bcbf12b860232d26dacbcba896797..b8169072cc86a2c10b978ab3d41a092047ef8038 100644
--- a/include/configs/slimbootloader.h
+++ b/include/configs/slimbootloader.h
@@ -8,19 +8,6 @@
 
 #include <configs/x86-common.h>
 
-/*
- * By default, CONFIG_SYS_NS16550_PORT_MAPPED is enabled for port io serial.
- * To use mmio base serial, enable CONFIG_SYS_NS16550_MEM32 and disable
- * CONFIG_SYS_NS16550_PORT_MAPPED until ns16550 driver supports serial port
- * configuration in run-time.
- *
- * #define CONFIG_SYS_NS16550_MEM32
- * #undef CONFIG_SYS_NS16550_PORT_MAPPED
- */
-#ifdef CONFIG_SYS_NS16550_MEM32
-#undef CONFIG_SYS_NS16550_PORT_MAPPED
-#endif
-
 #define CONFIG_STD_DEVICES_SETTINGS		\
 	"stdin=serial,i8042-kbd,usbkbd\0"	\
 	"stdout=serial\0"			\
diff --git a/include/ns16550.h b/include/ns16550.h
index 701efeea855f3eb5d2564d85cf796bbb1279bfc0..18c9077755bef823f388c8219d0bdc3de8fd86ee 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -31,6 +31,9 @@
 #define CONFIG_SYS_NS16550_REG_SIZE (-1)
 #endif
 
+#ifdef CONFIG_NS16550_DYNAMIC
+#define UART_REG(x)	unsigned char x
+#else
 #if !defined(CONFIG_SYS_NS16550_REG_SIZE) || (CONFIG_SYS_NS16550_REG_SIZE == 0)
 #error "Please define NS16550 registers size."
 #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_DM_SERIAL)
@@ -44,14 +47,24 @@
 	unsigned char x;						\
 	unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1];
 #endif
+#endif /* CONFIG_NS16550_DYNAMIC */
+
+enum ns16550_flags {
+	NS16550_FLAG_IO		= 1 << 0, /* Use I/O access (else mem-mapped) */
+	NS16550_FLAG_ENDIAN	= 1 << 1, /* Use out_le/be_32() */
+	NS16550_FLAG_BE		= 1 << 2, /* Big-endian access (else little) */
+};
 
 /**
  * struct ns16550_platdata - information about a NS16550 port
  *
  * @base:		Base register address
- * @reg_width:		IO accesses size of registers (in bytes)
+ * @reg_width:		IO accesses size of registers (in bytes, 1 or 4)
  * @reg_shift:		Shift size of registers (0=byte, 1=16bit, 2=32bit...)
+ * @reg_offset:		Offset to start of registers (normally 0)
  * @clock:		UART base clock speed in Hz
+ * @fcr:		Offset of FCR register (normally UART_FCR_DEFVAL)
+ * @flags:		A few flags (enum ns16550_flags)
  * @bdf:		PCI slot/function (pci_dev_t)
  */
 struct ns16550_platdata {
@@ -61,6 +74,7 @@ struct ns16550_platdata {
 	int reg_offset;
 	int clock;
 	u32 fcr;
+	int flags;
 #if defined(CONFIG_PCI) && defined(CONFIG_SPL)
 	int bdf;
 #endif