[coreboot-gerrit] New patch to review for coreboot: soc/glk: Add GLK SOC (WIP - need more patches for successful build)

Hannah Williams (hannah.williams@intel.com) gerrit at coreboot.org
Tue Dec 13 02:04:49 CET 2016


Hannah Williams (hannah.williams at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17809

-gerrit

commit 54a98b988608630632b932d9c06d6d47a4f0ea7e
Author: Hannah Williams <hannah.williams at intel.com>
Date:   Mon Oct 3 14:52:26 2016 -0700

    soc/glk: Add GLK SOC (WIP - need more patches for successful build)
    
    Derived from Apollolake
    Following IP blocks are same for Apollolake and GLK, hence starting with
    Apollolake codebase
    UART,SPI, I2C, SMBUS, SDIO, Graphics, PCIe, USB
    
    Change-Id: Ie1c8964d6bc463cd7f71ddbb8544cfbd79183bd3
    Signed-off-by: Hannah Williams <hannah.williams at intel.com>
---
 src/soc/intel/glk/Kconfig                   | 257 +++++++++++++
 src/soc/intel/glk/Makefile.inc              | 142 +++++++
 src/soc/intel/glk/acpi.c                    | 266 +++++++++++++
 src/soc/intel/glk/acpi/cpu.asl              | 118 ++++++
 src/soc/intel/glk/acpi/dptf.asl             |  44 +++
 src/soc/intel/glk/acpi/globalnvs.asl        |  46 +++
 src/soc/intel/glk/acpi/gpio.asl             | 201 ++++++++++
 src/soc/intel/glk/acpi/gpiolib.asl          |  67 ++++
 src/soc/intel/glk/acpi/lpc.asl              |  23 ++
 src/soc/intel/glk/acpi/lpss.asl             | 116 ++++++
 src/soc/intel/glk/acpi/northbridge.asl      | 132 +++++++
 src/soc/intel/glk/acpi/pch_hda.asl          |  84 +++++
 src/soc/intel/glk/acpi/pci_irqs.asl         |  63 ++++
 src/soc/intel/glk/acpi/pcie.asl             | 126 +++++++
 src/soc/intel/glk/acpi/platform.asl         |  20 +
 src/soc/intel/glk/acpi/scs.asl              |  67 ++++
 src/soc/intel/glk/acpi/sleepstates.asl      |  21 ++
 src/soc/intel/glk/acpi/soc_int.asl          |  58 +++
 src/soc/intel/glk/acpi/southbridge.asl      |  41 ++
 src/soc/intel/glk/acpi/xhci.asl             |  31 ++
 src/soc/intel/glk/bootblock/bootblock.c     | 187 ++++++++++
 src/soc/intel/glk/bootblock/cache_as_ram.S  | 251 +++++++++++++
 src/soc/intel/glk/car.c                     |  58 +++
 src/soc/intel/glk/chip.c                    | 462 +++++++++++++++++++++++
 src/soc/intel/glk/chip.h                    | 124 ++++++
 src/soc/intel/glk/cpu.c                     | 154 ++++++++
 src/soc/intel/glk/dsp.c                     |  32 ++
 src/soc/intel/glk/elog.c                    | 107 ++++++
 src/soc/intel/glk/exit_car.S                |  68 ++++
 src/soc/intel/glk/gpio.c                    | 418 +++++++++++++++++++++
 src/soc/intel/glk/graphics.c                | 103 +++++
 src/soc/intel/glk/heci.c                    |  36 ++
 src/soc/intel/glk/i2c.c                     | 126 +++++++
 src/soc/intel/glk/i2c_early.c               | 116 ++++++
 src/soc/intel/glk/include/FspUpd.h          |  48 +++
 src/soc/intel/glk/include/soc/acpi.h        |  28 ++
 src/soc/intel/glk/include/soc/cpu.h         |  63 ++++
 src/soc/intel/glk/include/soc/gpe.h         | 139 +++++++
 src/soc/intel/glk/include/soc/gpio.h        | 177 +++++++++
 src/soc/intel/glk/include/soc/gpio_defs.h   | 559 ++++++++++++++++++++++++++++
 src/soc/intel/glk/include/soc/heci.h        |  43 +++
 src/soc/intel/glk/include/soc/i2c.h         |  50 +++
 src/soc/intel/glk/include/soc/iomap.h       |  42 +++
 src/soc/intel/glk/include/soc/iosf.h        |  42 +++
 src/soc/intel/glk/include/soc/itss.h        |  29 ++
 src/soc/intel/glk/include/soc/lpc.h         |  69 ++++
 src/soc/intel/glk/include/soc/meminit.h     | 121 ++++++
 src/soc/intel/glk/include/soc/mmap_boot.h   |  22 ++
 src/soc/intel/glk/include/soc/nhlt.h        |  43 +++
 src/soc/intel/glk/include/soc/northbridge.h |  40 ++
 src/soc/intel/glk/include/soc/nvs.h         |  48 +++
 src/soc/intel/glk/include/soc/p2sb.h        |  23 ++
 src/soc/intel/glk/include/soc/pci_devs.h    | 122 ++++++
 src/soc/intel/glk/include/soc/pci_ids.h     |  47 +++
 src/soc/intel/glk/include/soc/pm.h          | 216 +++++++++++
 src/soc/intel/glk/include/soc/romstage.h    |  27 ++
 src/soc/intel/glk/include/soc/smm.h         |  41 ++
 src/soc/intel/glk/include/soc/spi.h         |  88 +++++
 src/soc/intel/glk/include/soc/uart.h        |  36 ++
 src/soc/intel/glk/itss.c                    | 129 +++++++
 src/soc/intel/glk/lpc.c                     | 176 +++++++++
 src/soc/intel/glk/lpc_lib.c                 | 180 +++++++++
 src/soc/intel/glk/meminit.c                 | 341 +++++++++++++++++
 src/soc/intel/glk/memmap.c                  |  54 +++
 src/soc/intel/glk/mmap_boot.c               | 171 +++++++++
 src/soc/intel/glk/nhlt.c                    | 142 +++++++
 src/soc/intel/glk/northbridge.c             | 169 +++++++++
 src/soc/intel/glk/p2sb.c                    |  74 ++++
 src/soc/intel/glk/pmc.c                     | 157 ++++++++
 src/soc/intel/glk/pmutil.c                  | 543 +++++++++++++++++++++++++++
 src/soc/intel/glk/reset.c                   |  73 ++++
 src/soc/intel/glk/romstage.c                | 192 ++++++++++
 src/soc/intel/glk/smi.c                     |  87 +++++
 src/soc/intel/glk/smihandler.c              |  68 ++++
 src/soc/intel/glk/spi.c                     | 395 ++++++++++++++++++++
 src/soc/intel/glk/tsc_freq.c                |  25 ++
 src/soc/intel/glk/uart.c                    |  61 +++
 src/soc/intel/glk/uart_early.c              |  86 +++++
 src/soc/intel/glk/xhci.c                    | 105 ++++++
 79 files changed, 9556 insertions(+)

diff --git a/src/soc/intel/glk/Kconfig b/src/soc/intel/glk/Kconfig
new file mode 100644
index 0000000..9d40e3b
--- /dev/null
+++ b/src/soc/intel/glk/Kconfig
@@ -0,0 +1,257 @@
+config SOC_INTEL_GLK
+	bool
+	help
+	  Intel GLK support
+
+if SOC_INTEL_GLK
+config CPU_SPECIFIC_OPTIONS
+	def_bool y
+	select ACPI_INTEL_HARDWARE_SLEEP_VALUES
+	select ARCH_BOOTBLOCK_X86_32
+	select ARCH_RAMSTAGE_X86_32
+	select ARCH_ROMSTAGE_X86_32
+	select ARCH_VERSTAGE_X86_32
+	select BOOTBLOCK_CONSOLE
+	select BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY if BOOT_DEVICE_SPI_FLASH
+	select BOOT_DEVICE_SUPPORTS_WRITES
+	# CPU specific options
+	select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
+	select IOAPIC
+	select SMP
+	select SSE2
+	select SUPPORT_CPU_UCODE_IN_CBFS
+	# Audio options
+	select ACPI_NHLT
+	select SOC_INTEL_COMMON_NHLT
+	# Misc options
+	select C_ENVIRONMENT_BOOTBLOCK
+	select COLLECT_TIMESTAMPS
+	select COMMON_FADT
+	select GENERIC_GPIO_LIB
+	select HAVE_INTEL_FIRMWARE
+	select HAVE_SMI_HANDLER
+	select MMCONF_SUPPORT
+	select MMCONF_SUPPORT_DEFAULT
+	select NO_FIXED_XIP_ROM_SIZE
+	select NO_STAGE_CACHE
+	select NO_XIP_EARLY_STAGES
+	select PARALLEL_MP
+	select PCIEXP_ASPM
+	select PCIEXP_COMMON_CLOCK
+	select PCIEXP_CLK_PM
+	select PCIEXP_L1_SUB_STATE
+	select POSTCAR_CONSOLE
+	select POSTCAR_STAGE
+	select REG_SCRIPT
+	select RELOCATABLE_RAMSTAGE	# Build fails if this is not selected
+	select RTC
+	select SMM_TSEG
+	select SOC_INTEL_COMMON
+	select SOC_INTEL_COMMON_ACPI
+	select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
+	select SOC_INTEL_COMMON_LPSS_I2C
+	select SOC_INTEL_COMMON_SMI
+	select UDELAY_TSC
+	select TSC_CONSTANT_RATE
+	select TSC_MONOTONIC_TIMER
+	select HAVE_MONOTONIC_TIMER
+	select PLATFORM_USES_FSP2_0
+	select HAVE_HARD_RESET
+	select SOC_INTEL_COMMON
+	select SOC_INTEL_COMMON_GFX_OPREGION
+	select ADD_VBT_DATA_FILE
+	select SOC_INTEL_COMMON_RESET
+
+config CHROMEOS
+	select CHROMEOS_RAMOOPS_DYNAMIC
+	select EC_SOFTWARE_SYNC if EC_GOOGLE_CHROMEEC
+	select SEPARATE_VERSTAGE
+	select VBOOT_OPROM_MATTERS
+	select VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT
+	select VBOOT_STARTS_IN_BOOTBLOCK
+	select VBOOT_VBNV_CMOS
+	select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH
+	select VIRTUAL_DEV_SWITCH
+
+config TPM_ON_FAST_SPI
+	bool
+	default n
+	select LPC_TPM
+	help
+	 TPM part is conntected on Fast SPI interface, but the LPC MMIO
+	 TPM transactions are decoded and serialized over the SPI interface.
+
+config SOC_INTEL_COMMON_RESET
+	bool
+	default y
+
+config MMCONF_BASE_ADDRESS
+	hex "PCI MMIO Base Address"
+	default 0xe0000000
+
+config IOSF_BASE_ADDRESS
+	hex "MMIO Base Address of sideband bus"
+	default 0xd0000000
+
+config DCACHE_RAM_BASE
+	hex "Base address of cache-as-RAM"
+	default 0xfef00000
+
+config DCACHE_RAM_SIZE
+	hex "Length in bytes of cache-as-RAM"
+	default 0xc0000
+	help
+	  The size of the cache-as-ram region required during bootblock
+	  and/or romstage.
+
+config DCACHE_BSP_STACK_SIZE
+	hex
+	default 0x4000
+	help
+	  The amount of anticipated stack usage in CAR by bootblock and
+	  other stages.
+
+config CPU_ADDR_BITS
+	int
+	default 36
+
+config SOC_INTEL_COMMON_LPSS_I2C_CLOCK_MHZ
+	depends on SOC_INTEL_COMMON_LPSS_I2C
+	int
+	default 133
+
+config CONSOLE_UART_BASE_ADDRESS
+	depends on CONSOLE_SERIAL
+	hex "MMIO base address for UART"
+	default 0xde000000
+
+config SOC_UART_DEBUG
+	bool "Enable SoC UART debug port selected by UART_FOR_CONSOLE."
+	default n
+	select CONSOLE_SERIAL
+	select DRIVERS_UART
+	select DRIVERS_UART_8250MEM_32
+	select NO_UART_ON_SUPERIO
+
+# 32KiB bootblock is all that is mapped in by the CSE at top of 4GiB.
+config C_ENV_BOOTBLOCK_SIZE
+	hex
+	default 0x8000
+
+# This SoC does not map SPI flash like many previous SoC. Therefore we provide
+# a custom media driver that facilitates mapping
+config X86_TOP4G_BOOTMEDIA_MAP
+	bool
+	default n
+
+config ROMSTAGE_ADDR
+	hex
+	default 0xfef20000
+	help
+	  The base address (in CAR) where romstage should be linked
+
+config VERSTAGE_ADDR
+	hex
+	default 0xfef40000
+	help
+	  The base address (in CAR) where verstage should be linked
+
+config CACHE_MRC_SETTINGS
+	bool
+	default y
+
+config FSP_M_ADDR
+	hex
+	default 0xfef40000
+	help
+	  The address FSP-M will be relocated to during build time
+
+config NEED_LBP2
+	bool "Write contents for logical boot partition 2."
+	default n
+	help
+	  Write the contents from a file into the logical boot partition 2
+	  region defined by LBP2_FMAP_NAME.
+
+config LBP2_FMAP_NAME
+	string "Name of FMAP region to put logical boot partition 2"
+	depends on NEED_LBP2
+	default "SIGN_CSE"
+	help
+	  Name of FMAP region to write logical boot partition 2 data.
+
+config LBP2_FILE_NAME
+	string "Path of file to write to logical boot partition 2 region"
+	depends on NEED_LBP2
+	default "3rdparty/blobs/mainboard/$(CONFIG_MAINBOARD_DIR)/lbp2.bin"
+	help
+	  Name of file to store in the logical boot partition 2 region.
+
+config NEED_IFWI
+	bool "Write content into IFWI region"
+	default n
+	help
+	  Write the content from a file into IFWI region defined by
+	  IFWI_FMAP_NAME.
+
+config IFWI_FMAP_NAME
+	string "Name of FMAP region to pull IFWI into"
+	depends on NEED_IFWI
+	default "IFWI"
+	help
+	  Name of FMAP region to write IFWI.
+
+config IFWI_FILE_NAME
+	string "Path of file to write to IFWI region"
+	depends on NEED_IFWI
+	default "3rdparty/blobs/mainboard/$(CONFIG_MAINBOARD_DIR)/ifwi.bin"
+	help
+	  Name of file to store in the IFWI region.
+
+config NHLT_DMIC_2CH_16B
+	bool
+	depends on ACPI_NHLT
+	default n
+	help
+	  Include DSP firmware settings for 2 channel 16B DMIC array.
+
+config NHLT_MAX98357
+	bool
+	depends on ACPI_NHLT
+	default n
+	help
+	  Include DSP firmware settings for headset codec.
+
+config NHLT_DA7219
+	bool
+	depends on ACPI_NHLT
+	default n
+	help
+	  Include DSP firmware settings for headset codec.
+choice
+	prompt "Cache-as-ram implementation"
+	default CAR_CQOS
+	help
+	  This option allows you to select how cache-as-ram (CAR) is set up.
+
+config CAR_NEM
+	bool "Non-evict mode"
+	help
+	  Traditionally, CAR is set up by using Non-Evict mode. This method
+	  does not allow CAR and cache to co-exist, because cache fills are
+	  block in NEM mode.
+
+config CAR_CQOS
+	bool "Cache Quality of Service"
+	help
+	  Cache Quality of Service allows more fine-grained control of cache
+	  usage. As result, it is possible to set up portion of L2 cache for
+	  CAR and use remainder for actual caching.
+
+endchoice
+
+config SPI_FLASH_INCLUDE_ALL_DRIVERS
+	bool
+	default n
+
+endif
diff --git a/src/soc/intel/glk/Makefile.inc b/src/soc/intel/glk/Makefile.inc
new file mode 100644
index 0000000..fb59981
--- /dev/null
+++ b/src/soc/intel/glk/Makefile.inc
@@ -0,0 +1,142 @@
+ifeq ($(CONFIG_SOC_INTEL_GLK),y)
+
+subdirs-y += ../../../cpu/intel/microcode
+subdirs-y += ../../../cpu/intel/turbo
+subdirs-y += ../../../cpu/x86/lapic
+subdirs-y += ../../../cpu/x86/mtrr
+subdirs-y += ../../../cpu/x86/smm
+subdirs-y += ../../../cpu/x86/tsc
+subdirs-y += ../../../cpu/x86/cache
+
+bootblock-y += bootblock/bootblock.c
+bootblock-y += bootblock/cache_as_ram.S
+bootblock-y += bootblock/bootblock.c
+bootblock-y += car.c
+bootblock-y += gpio.c
+bootblock-y += heci.c
+bootblock-y += itss.c
+bootblock-y += lpc_lib.c
+bootblock-y += mmap_boot.c
+bootblock-y += pmutil.c
+bootblock-y += spi.c
+bootblock-y += tsc_freq.c
+bootblock-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
+
+romstage-y += car.c
+romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += romstage.c
+romstage-y += gpio.c
+romstage-y += heci.c
+romstage-y += i2c_early.c
+romstage-y += itss.c
+romstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
+romstage-y += lpc_lib.c
+romstage-y += memmap.c
+romstage-y += meminit.c
+romstage-y += mmap_boot.c
+romstage-y += tsc_freq.c
+romstage-y += pmutil.c
+romstage-y += reset.c
+romstage-y += spi.c
+
+smm-y += mmap_boot.c
+smm-y += pmutil.c
+smm-y += gpio.c
+smm-y += smihandler.c
+smm-y += spi.c
+smm-y += tsc_freq.c
+smm-y += uart_early.c
+
+ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
+ramstage-y += cpu.c
+ramstage-y += chip.c
+ramstage-y += elog.c
+ramstage-y += dsp.c
+ramstage-y += gpio.c
+ramstage-y += graphics.c
+ramstage-y += heci.c
+ramstage-y += i2c.c
+ramstage-y += itss.c
+ramstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
+ramstage-y += lpc.c
+ramstage-y += lpc_lib.c
+ramstage-y += memmap.c
+ramstage-y += mmap_boot.c
+ramstage-y += p2sb.c
+ramstage-y += uart.c
+ramstage-y += nhlt.c
+ramstage-y += northbridge.c
+ramstage-y += spi.c
+ramstage-y += tsc_freq.c
+ramstage-y += pmutil.c
+ramstage-y += pmc.c
+ramstage-y += reset.c
+ramstage-y += smi.c
+ramstage-y += spi.c
+ramstage-y += xhci.c
+
+postcar-y += exit_car.S
+postcar-y += memmap.c
+postcar-y += mmap_boot.c
+postcar-y += spi.c
+postcar-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
+postcar-y += tsc_freq.c
+
+verstage-y += car.c
+verstage-y += i2c_early.c
+verstage-y += heci.c
+verstage-y += memmap.c
+verstage-y += mmap_boot.c
+verstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
+verstage-y += tsc_freq.c
+verstage-y += pmutil.c
+verstage-y += reset.c
+verstage-y += spi.c
+
+CPPFLAGS_common += -I$(src)/soc/intel/glk/include
+CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp2_0/apollolake
+
+# Since FSP-M runs in CAR we need to relocate it to a specific address
+$(CONFIG_FSP_M_CBFS)-options := -b $(CONFIG_FSP_M_ADDR)
+
+ifeq ($(CONFIG_NEED_LBP2),y)
+files_added::
+	$(CBFSTOOL) $(obj)/coreboot.rom write -r $(CONFIG_LBP2_FMAP_NAME) -f $(CONFIG_LBP2_FILE_NAME) --fill-upward
+endif
+
+# Bootblock on Apollolake platform lies in the IFWI region. In order to place
+# the bootblock at the right location in IFWI image -
+# a. Using ifwitool:
+#    1. Create IFWI image (ifwi.bin.tmp) from input image
+#       (CONFIG_IFWI_FILE_NAME).
+#    2. Delete OBBP sub-partition, if present.
+#    3. Replace IBBL directory entry in IBBP sub-partition with currently
+#       generated bootblock.bin.
+# b. Using cbfstool:
+#    1. Write ifwi.bin.tmp to coreboot.rom using CONFIG_IFWI_FMAP_NAME.
+ifeq ($(CONFIG_NEED_IFWI),y)
+files_added:: $(IFWITOOL)
+	$(IFWITOOL) $(CONFIG_IFWI_FILE_NAME) create -f $(objcbfs)/ifwi.bin.tmp
+	$(IFWITOOL) $(objcbfs)/ifwi.bin.tmp delete -n OBBP
+	$(IFWITOOL) $(objcbfs)/ifwi.bin.tmp replace -n IBBP -f $(objcbfs)/bootblock.bin -d -e IBBL
+	$(CBFSTOOL) $(obj)/coreboot.rom write -r $(CONFIG_IFWI_FMAP_NAME) -f $(objcbfs)/ifwi.bin.tmp --fill-upward
+endif
+
+# DSP firmware settings files.
+NHLT_BLOB_PATH = 3rdparty/blobs/soc/intel/apollolake/nhlt-blobs
+DMIC_2CH_48KHZ_16B = dmic-2ch-48khz-16b.bin
+MAX98357_RENDER = max98357-render-2ch-48khz-24b.bin
+DA7219_RENDER_CAPTURE = dialog-2ch-48khz-24b.bin
+
+cbfs-files-$(CONFIG_NHLT_DMIC_2CH_16B) += $(DMIC_2CH_48KHZ_16B)
+$(DMIC_2CH_48KHZ_16B)-file := $(NHLT_BLOB_PATH)/$(DMIC_2CH_48KHZ_16B)
+$(DMIC_2CH_48KHZ_16B)-type := raw
+
+cbfs-files-$(CONFIG_NHLT_MAX98357) += $(MAX98357_RENDER)
+$(MAX98357_RENDER)-file := $(NHLT_BLOB_PATH)/$(MAX98357_RENDER)
+$(MAX98357_RENDER)-type := raw
+
+cbfs-files-$(CONFIG_NHLT_DA7219) += $(DA7219_RENDER_CAPTURE)
+$(DA7219_RENDER_CAPTURE)-file := $(NHLT_BLOB_PATH)/$(DA7219_RENDER_CAPTURE)
+$(DA7219_RENDER_CAPTURE)-type := raw
+
+endif
diff --git a/src/soc/intel/glk/acpi.c b/src/soc/intel/glk/acpi.c
new file mode 100644
index 0000000..ca479b8
--- /dev/null
+++ b/src/soc/intel/glk/acpi.c
@@ -0,0 +1,266 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <arch/ioapic.h>
+#include <arch/smp/mpspec.h>
+#include <cbmem.h>
+#include <cpu/x86/smm.h>
+#include <cpu/cpu.h>
+#include <soc/acpi.h>
+#include <soc/intel/common/acpi.h>
+#include <soc/iomap.h>
+#include <soc/pm.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <string.h>
+#include <soc/gpio.h>
+#include "chip.h"
+
+#define CSTATE_RES(address_space, width, offset, address)		\
+	{								\
+	.space_id = address_space,					\
+	.bit_width = width,						\
+	.bit_offset = offset,						\
+	.addrl = address,						\
+	}
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+	/* PCI Segment Group 0, Start Bus Number 0, End Bus Number is 255 */
+	current += acpi_create_mcfg_mmconfig((void *) current,
+					     CONFIG_MMCONF_BASE_ADDRESS, 0, 0,
+					     255);
+	return current;
+}
+
+static int acpi_sci_irq(void)
+{
+	int sci_irq = 9;
+	return sci_irq;
+}
+
+static unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+	int sci = acpi_sci_irq();
+	uint16_t flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW;;
+
+	/* INT_SRC_OVR */
+	current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
+
+	/* SCI */
+	current += acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
+
+	return current;
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+	/* Local APICs */
+	current = acpi_create_madt_lapics(current);
+
+	/* IOAPIC */
+	current += acpi_create_madt_ioapic((void *) current,
+					     2, IO_APIC_ADDR, 0);
+
+	return acpi_madt_irq_overrides(current);
+}
+
+void acpi_fill_fadt(acpi_fadt_t * fadt)
+{
+	const uint16_t pmbase = ACPI_PMIO_BASE;
+
+	/* Use ACPI 5.0 revision. */
+	fadt->header.revision = ACPI_FADT_REV_ACPI_5_0;
+
+	fadt->sci_int = acpi_sci_irq();
+	fadt->smi_cmd = APM_CNT;
+	fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+	fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+
+	fadt->pm1a_evt_blk = pmbase + PM1_STS;
+	fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
+	fadt->pm_tmr_blk = pmbase + PM1_TMR;
+	fadt->gpe0_blk = pmbase + GPE0_STS(0);
+
+	fadt->pm1_evt_len = 4;
+	fadt->pm1_cnt_len = 2;
+	fadt->pm_tmr_len = 4;
+	/* There are 4 GPE0 STS/EN pairs each 32 bits wide. */
+	fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
+	fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+	fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+	fadt->flush_size = 0x400;	/* twice of cache size*/
+	fadt->flush_stride = 0x10;	/* Cache line width  */
+	fadt->duty_offset = 1;
+	fadt->duty_width = 3;
+	fadt->day_alrm = 0xd;
+	fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+
+	fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+	    ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+	    ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE |
+	    ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+	fadt->reset_reg.space_id = 1;
+	fadt->reset_reg.bit_width = 8;
+	fadt->reset_reg.addrl = 0xcf9;
+	fadt->reset_value = 6;
+
+	fadt->x_pm1a_evt_blk.space_id = 1;
+	fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
+	fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS;
+
+	fadt->x_pm1b_evt_blk.space_id = 1;
+
+	fadt->x_pm1a_cnt_blk.space_id = 1;
+	fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
+	fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT;
+
+	fadt->x_pm1b_cnt_blk.space_id = 1;
+
+	fadt->x_pm_tmr_blk.space_id = 1;
+	fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
+	fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
+
+	fadt->x_gpe1_blk.space_id = 1;
+}
+
+unsigned long southbridge_write_acpi_tables(device_t device,
+		unsigned long current,
+		struct acpi_rsdp *rsdp)
+{
+	return acpi_write_hpet(device, current, rsdp);
+}
+
+static void acpi_create_gnvs(struct global_nvs_t *gnvs)
+{
+	struct soc_intel_glk_config *cfg;
+	struct device *dev = NB_DEV_ROOT;
+
+	/* Clear out GNVS. */
+	memset(gnvs, 0, sizeof(*gnvs));
+
+	if (IS_ENABLED(CONFIG_CONSOLE_CBMEM))
+		gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);
+
+	if (IS_ENABLED(CONFIG_CHROMEOS)) {
+		/* Initialize Verified Boot data */
+		chromeos_init_vboot(&gnvs->chromeos);
+		gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO;
+	}
+
+	/* Set unknown wake source */
+	gnvs->pm1i = ~0ULL;
+
+	if (!dev || !dev->chip_info) {
+		printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+		return;
+	}
+	cfg = dev->chip_info;
+
+	/* Enable DPTF based on mainboard configuration */
+	gnvs->dpte = cfg->dptf_enable;
+
+	/* Assign address of PERST_0 if GPIO is defined in devicetree */
+	if (cfg->prt0_gpio != GPIO_PRT0_UDEF)
+		gnvs->prt0 = (uintptr_t)gpio_dwx_address(cfg->prt0_gpio);
+}
+
+/* Save wake source information for calculating ACPI _SWS values */
+int soc_fill_acpi_wake(uint32_t *pm1, uint32_t **gpe0)
+{
+	struct chipset_power_state *ps;
+	static uint32_t gpe0_sts[GPE0_REG_MAX];
+	uint32_t pm1_en;
+	int i;
+
+	ps = cbmem_find(CBMEM_ID_POWER_STATE);
+	if (ps == NULL)
+		return -1;
+
+	/*
+	 * PM1_EN to check the basic wake events which can happen through
+	 * powerbtn or any other wake source like lidopen, key board press etc.
+	 * WAK_STS bit is set when the system is in one of the sleep states
+	 * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting
+	 * this bit, the PMC will transition the system to the ON state and
+	 * can only be set by hardware and can only be cleared by writing a one
+	 * to this bit position.
+	 */
+	pm1_en = ps->pm1_en | WAK_STS | RTC_EN | PWRBTN_EN;
+	*pm1 = ps->pm1_sts & pm1_en;
+
+	/* Mask off GPE0 status bits that are not enabled */
+	*gpe0 = &gpe0_sts[0];
+	for (i = 0; i < GPE0_REG_MAX; i++)
+		gpe0_sts[i] = ps->gpe0_sts[i] & ps->gpe0_en[i];
+
+	return GPE0_REG_MAX;
+}
+
+void southbridge_inject_dsdt(device_t device)
+{
+	struct global_nvs_t *gnvs;
+
+	gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+
+	if (gnvs) {
+		acpi_create_gnvs(gnvs);
+		acpi_save_gnvs((uintptr_t)gnvs);
+		/* And tell SMI about it */
+		smm_setup_structures(gnvs, NULL, NULL);
+
+		/* Add it to DSDT.  */
+		acpigen_write_scope("\\");
+		acpigen_write_name_dword("NVSA", (uintptr_t)gnvs);
+		acpigen_pop_len();
+	}
+}
+static acpi_cstate_t cstate_map[] = {
+	{
+		/* C1 */
+		.ctype = 1, /* ACPI C1 */
+		.latency = 1,
+		.power = 1000,
+		.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_FIXED, 0, 0, 0),
+	},
+	{
+		.ctype = 2, /* ACPI C2 */
+		.latency = 50,
+		.power = 10,
+		.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x415),
+	},
+	{
+		.ctype = 3, /* ACPI C3 */
+		.latency = 150,
+		.power = 10,
+		.resource = CSTATE_RES(ACPI_ADDRESS_SPACE_IO, 8, 0, 0x419),
+	}
+};
+
+acpi_cstate_t *soc_get_cstate_map(int *entries)
+{
+	*entries = ARRAY_SIZE(cstate_map);
+	return cstate_map;
+}
+
+uint16_t soc_get_acpi_base_address(void)
+{
+	return ACPI_PMIO_BASE;
+}
diff --git a/src/soc/intel/glk/acpi/cpu.asl b/src/soc/intel/glk/acpi/cpu.asl
new file mode 100644
index 0000000..a202ceb
--- /dev/null
+++ b/src/soc/intel/glk/acpi/cpu.asl
@@ -0,0 +1,118 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* These devices are created at runtime */
+External (\_PR.CP00, DeviceObj)
+External (\_PR.CP01, DeviceObj)
+External (\_PR.CP02, DeviceObj)
+External (\_PR.CP03, DeviceObj)
+External (\_PR.CP04, DeviceObj)
+External (\_PR.CP05, DeviceObj)
+External (\_PR.CP06, DeviceObj)
+External (\_PR.CP07, DeviceObj)
+
+/* Notify OS to re-read CPU tables, assuming ^2 CPU count */
+Method (PNOT)
+{
+	If (LGreaterEqual (\PCNT, 2)) {
+		Notify (\_PR.CP00, 0x81)  // _CST
+		Notify (\_PR.CP01, 0x81)  // _CST
+	}
+	If (LGreaterEqual (\PCNT, 4)) {
+		Notify (\_PR.CP02, 0x81)  // _CST
+		Notify (\_PR.CP03, 0x81)  // _CST
+	}
+	If (LGreaterEqual (\PCNT, 8)) {
+		Notify (\_PR.CP04, 0x81)  // _CST
+		Notify (\_PR.CP05, 0x81)  // _CST
+		Notify (\_PR.CP06, 0x81)  // _CST
+		Notify (\_PR.CP07, 0x81)  // _CST
+	}
+}
+
+/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */
+Method (PPCN)
+{
+	If (LGreaterEqual (\PCNT, 2)) {
+		Notify (\_PR.CP00, 0x80)  // _PPC
+		Notify (\_PR.CP01, 0x80)  // _PPC
+	}
+	If (LGreaterEqual (\PCNT, 4)) {
+		Notify (\_PR.CP02, 0x80)  // _PPC
+		Notify (\_PR.CP03, 0x80)  // _PPC
+	}
+	If (LGreaterEqual (\PCNT, 8)) {
+		Notify (\_PR.CP04, 0x80)  // _PPC
+		Notify (\_PR.CP05, 0x80)  // _PPC
+		Notify (\_PR.CP06, 0x80)  // _PPC
+		Notify (\_PR.CP07, 0x80)  // _PPC
+	}
+}
+
+/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */
+Method (TNOT)
+{
+	If (LGreaterEqual (\PCNT, 2)) {
+		Notify (\_PR.CP00, 0x82)  // _TPC
+		Notify (\_PR.CP01, 0x82)  // _TPC
+	}
+	If (LGreaterEqual (\PCNT, 4)) {
+		Notify (\_PR.CP02, 0x82)  // _TPC
+		Notify (\_PR.CP03, 0x82)  // _TPC
+	}
+	If (LGreaterEqual (\PCNT, 8)) {
+		Notify (\_PR.CP04, 0x82)  // _TPC
+		Notify (\_PR.CP05, 0x82)  // _TPC
+		Notify (\_PR.CP06, 0x82)  // _TPC
+		Notify (\_PR.CP07, 0x82)  // _TPC
+	}
+}
+
+/* Return a package containing enabled processor entries */
+Method (PPKG)
+{
+	If (LGreaterEqual (\PCNT, 8)) {
+		Return (Package()
+		{
+			\_PR.CP00,
+			\_PR.CP01,
+			\_PR.CP02,
+			\_PR.CP03,
+			\_PR.CP04,
+			\_PR.CP05,
+			\_PR.CP06,
+			\_PR.CP07
+		})
+	} ElseIf (LGreaterEqual (\PCNT, 4)) {
+		Return (Package ()
+		{
+			\_PR.CP00,
+			\_PR.CP01,
+			\_PR.CP02,
+			\_PR.CP03
+		})
+	} ElseIf (LGreaterEqual (\PCNT, 2)) {
+		Return (Package ()
+		{
+			\_PR.CP00,
+			\_PR.CP01
+		})
+	} Else {
+		Return (Package ()
+		{
+			\_PR.CP00
+		})
+	}
+}
diff --git a/src/soc/intel/glk/acpi/dptf.asl b/src/soc/intel/glk/acpi/dptf.asl
new file mode 100644
index 0000000..743fa92
--- /dev/null
+++ b/src/soc/intel/glk/acpi/dptf.asl
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define DPTF_CPU_DEVICE		TCPU
+
+#ifndef DPTF_CPU_PASSIVE
+#definie DPTF_CPU_PASSIVE	80
+#endif
+
+#ifndef DPTF_CPU_CRITICAL
+#define DPTF_CPU_CRITICAL	90
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC0
+#define DPTF_CPU_ACTIVE_AC0	90
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC1
+#define DPTF_CPU_ACTIVE_AC1	80
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC2
+#define DPTF_CPU_ACTIVE_AC2	70
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC3
+#define DPTF_CPU_ACTIVE_AC3	60
+#endif
+
+#ifndef DPTF_CPU_ACTIVE_AC4
+#define DPTF_CPU_ACTIVE_AC4	50
+#endif
diff --git a/src/soc/intel/glk/acpi/globalnvs.asl b/src/soc/intel/glk/acpi/globalnvs.asl
new file mode 100644
index 0000000..5eeacfe
--- /dev/null
+++ b/src/soc/intel/glk/acpi/globalnvs.asl
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * NOTE: The layout of the GNVS structure below must match the layout in
+ * soc/intel/glk/include/soc/nvs.h !!!
+ *
+ */
+
+External (NVSA)
+
+OperationRegion (GNVS, SystemMemory, NVSA, 0x1000)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+	/* Miscellaneous */
+	Offset (0x00),
+	PCNT,	8,      // 0x00 - Processor Count
+	PPCM,	8,      // 0x01 - Max PPC State
+	LIDS,	8,      // 0x02 - LID State
+	PWRS,	8,      // 0x03 - AC Power State
+	DPTE,	8,      // 0x04 - Enable DPTF
+	CBMC,	32,     // 0x05 - 0x08 - Coreboot Memory Console
+	PM1I,	64,     // 0x09 - 0x10 - System Wake Source - PM1 Index
+	GPEI,	64,     // 0x11 - 0x18 - GPE Wake Source
+	NHLA,	64,     // 0x19 - 0x20 - NHLT Address
+	NHLL,	32,     // 0x21 - 0x24 - NHLT Length
+	PRT0,	32,     // 0x25 - 0x28 - PERST_0 Address
+
+	/* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */
+	Offset (0x100),
+	#include <vendorcode/google/chromeos/acpi/gnvs.asl>
+}
diff --git a/src/soc/intel/glk/acpi/gpio.asl b/src/soc/intel/glk/acpi/gpio.asl
new file mode 100644
index 0000000..ffc5b75
--- /dev/null
+++ b/src/soc/intel/glk/acpi/gpio.asl
@@ -0,0 +1,201 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <soc/gpio_defs.h>
+#include "gpiolib.asl"
+
+scope (\_SB) {
+
+	Device (GPO0)
+	{
+		Name (_ADR, 0)
+		Name (_HID, "INT3452")
+		Name (_CID, "INT3452")
+		Name (_DDN, "General Purpose Input/Output (GPIO) Controller - North" )
+		Name (_UID, 1)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_N, 16, Local0)
+			Or (CONFIG_IOSF_BASE_ADDRESS, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Device (GPO1)
+	{
+		Name (_ADR, 0)
+		Name (_HID, "INT3452")
+		Name (_CID, "INT3452")
+		Name (_DDN, "General Purpose Input/Output (GPIO) Controller - Northwest" )
+		Name (_UID, 2)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_NW, 16, Local0)
+			Or (CONFIG_IOSF_BASE_ADDRESS, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Device (GPO2)
+	{
+		Name (_ADR, 0)
+		Name (_HID, "INT3452")
+		Name (_CID, "INT3452")
+		Name (_DDN, "General Purpose Input/Output (GPIO) Controller - West" )
+		Name (_UID, 3)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_W, 16, Local0)
+			Or (CONFIG_IOSF_BASE_ADDRESS, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Device (GPO3)
+	{
+		Name (_ADR, 0)
+		Name (_HID, "INT3452")
+		Name (_CID, "INT3452")
+		Name (_DDN, "General Purpose Input/Output (GPIO) Controller - Southwest" )
+		Name (_UID, 4)
+
+		Name (RBUF, ResourceTemplate ()
+		{
+			Memory32Fixed (ReadWrite, 0, 0x4000, RMEM)
+			Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , )
+			{
+				GPIO_BANK_INT
+			}
+		})
+
+		Method (_CRS, 0x0, NotSerialized)
+		{
+			CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+			ShiftLeft (GPIO_SW, 16, Local0)
+			Or (CONFIG_IOSF_BASE_ADDRESS, Local0, RBAS)
+			Return (^RBUF)
+		}
+
+		Method (_STA, 0x0, NotSerialized)
+		{
+			Return(0xf)
+		}
+	}
+
+	Scope(\_SB.PCI0) {
+		/* PERST Assertion
+		 * Note: PERST is Active High
+		 */
+		Method (PRAS, 0x1, Serialized)
+		{
+			/*
+			 * Assert PERST
+			 * local1 - to toggle Tx pin of Dw0
+			 * local2 - Address of PERST
+			 */
+			Store (Arg0, Local2)
+			Store (\_SB.GPC0 (Local2), Local1)
+			Or (Local1, PAD_CFG0_TX_STATE, Local1)
+			\_SB.SPC0 (Local2, Local1)
+		}
+
+		/* PERST DE-Assertion */
+		Method (PRDA, 0x1, Serialized)
+		{
+			/*
+			 * De-assert PERST
+			 * local1 - to toggle Tx pin of Dw0
+			 * local2 - Address of PERST
+			 */
+			Store (Arg0, Local2)
+			Store (\_SB.GPC0 (Local2), Local1)
+			And (Local1, Not (PAD_CFG0_TX_STATE), Local1)
+			\_SB.SPC0 (Local2, Local1)
+		}
+	}
+
+	/*
+	 * Sleep button device ASL code. We are using this device to
+	 * add the _PRW method for a dummy wake event to kernel so that
+	 * before going to sleep kernel does not clear bit 15 in ACPI
+	 * gpe0a enable register which is actually the GPIO_TIER1_SCI_EN bit.
+	 */
+	Device (SLP)
+	{
+		Name (_HID, EisaId ("PNP0C0E"))
+
+		Name (_PRW, Package() { GPE0A_GPIO_TIER1_SCI_STS, 0x3 })
+	}
+}
+
+Scope(\_GPE)
+{
+	/*
+	 * Dummy method for the Tier 1 GPIO SCI enable bit. When kernel reads
+	 * _L0F in scope GPE it sets bit for gpio_tier1_sci_en in ACPI enable
+	 * register at 0x430. For APL ACPI enable register DW0 i.e., ACPI
+	 * GPE0a_EN at 0x430 is reserved.
+	 */
+	Method(_L0F, 0) {}
+}
diff --git a/src/soc/intel/glk/acpi/gpiolib.asl b/src/soc/intel/glk/acpi/gpiolib.asl
new file mode 100644
index 0000000..cec6d36
--- /dev/null
+++ b/src/soc/intel/glk/acpi/gpiolib.asl
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+Scope (\_SB)
+{
+	/* Get Pad Configuration DW0 register value */
+	Method (GPC0, 0x1, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		Store (Arg0, Local0)
+		OperationRegion (PDW0, SystemMemory, Local0, 4)
+		Field (PDW0, AnyAcc, NoLock, Preserve) {
+			TEMP, 32
+		}
+		Return (TEMP)
+	}
+
+	/* Set Pad Configuration DW0 register value */
+	Method (SPC0, 0x2, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		/* Arg1 - Value for DW0 register */
+		Store (Arg0, Local0)
+		OperationRegion (PDW0, SystemMemory, Local0, 4)
+		Field (PDW0, AnyAcc, NoLock, Preserve) {
+			TEMP,32
+		}
+		Store (Arg1, TEMP)
+	}
+
+	/* Get Pad Configuration DW1 register value */
+	Method (GPC1, 0x1, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		Store (Add (Arg0, 0x4), Local0)
+		OperationRegion (PDW1, SystemMemory, Local0, 4)
+		Field (PDW1, AnyAcc, NoLock, Preserve) {
+			TEMP, 32
+		}
+		Return (TEMP)
+	}
+
+	/* Set Pad Configuration DW1 register value */
+	Method (SPC1, 0x2, Serialized)
+	{
+		/* Arg0 - GPIO DW0 address */
+		/* Arg1 - Value for DW1 register */
+		Store (Add (Arg0, 0x4), Local0)
+		OperationRegion (PDW1, SystemMemory, Local0, 4)
+		Field(PDW1, AnyAcc, NoLock, Preserve) {
+			TEMP,32
+		}
+		Store (Arg1, TEMP)
+	}
+}
diff --git a/src/soc/intel/glk/acpi/lpc.asl b/src/soc/intel/glk/acpi/lpc.asl
new file mode 100644
index 0000000..749daf7
--- /dev/null
+++ b/src/soc/intel/glk/acpi/lpc.asl
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2013 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* Intel LPC Bus Device  - 0:1f.0 */
+
+Device (LPCB)
+{
+	Name (_ADR, 0x001f0000)
+}
diff --git a/src/soc/intel/glk/acpi/lpss.asl b/src/soc/intel/glk/acpi/lpss.asl
new file mode 100644
index 0000000..ab97374
--- /dev/null
+++ b/src/soc/intel/glk/acpi/lpss.asl
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+scope (\_SB.PCI0) {
+
+	/* LPIO1 PWM */
+	Device(PWM) {
+		Name (_ADR, 0x001A0000)
+		Name (_DDN, "Intel(R) PWM Controller")
+	}
+
+	/* LPIO1 HS-UART #1 */
+	Device(URT1) {
+		Name (_ADR, 0x00180000)
+		Name (_DDN, "Intel(R) HS-UART Controller #1")
+	}
+
+	/* LPIO1 HS-UART #2 */
+	Device(URT2) {
+		Name (_ADR, 0x00180001)
+		Name (_DDN, "Intel(R) HS-UART Controller #2")
+	}
+
+	/* LPIO1 HS-UART #3 */
+	Device(URT3) {
+		Name (_ADR, 0x00180002)
+		Name (_DDN, "Intel(R) HS-UART Controller #3")
+	}
+
+	/* LPIO1 HS-UART #4 */
+	Device(URT4) {
+		Name (_ADR, 0x00180003)
+		Name (_DDN, "Intel(R) HS-UART Controller #4")
+	}
+
+	/* LPIO1 SPI */
+	Device(SPI1) {
+		Name (_ADR, 0x00190000)
+		Name (_DDN, "Intel(R) SPI Controller #1")
+	}
+
+	/* LPIO1 SPI #2 */
+	Device(SPI2) {
+		Name (_ADR, 0x00190001)
+		Name (_DDN, "Intel(R) SPI Controller #2")
+	}
+
+	/* LPIO1 SPI #3 */
+	Device(SPI3) {
+		Name (_ADR, 0x00190002)
+		Name (_DDN, "Intel(R) SPI Controller #3")
+	}
+
+
+	/* LPIO2 I2C #0 */
+	Device(I2C0) {
+		Name (_ADR, 0x00160000)
+		Name (_DDN, "Intel(R) I2C Controller #0")
+	}
+
+	/* LPIO2 I2C #1 */
+	Device(I2C1) {
+		Name (_ADR, 0x00160001)
+		Name (_DDN, "Intel(R) I2C Controller #1")
+	}
+
+	/* LPIO2 I2C #2 */
+	Device(I2C2) {
+		Name (_ADR, 0x00160002)
+		Name (_DDN, "Intel(R) I2C Controller #2")
+	}
+
+	/* LPIO2 I2C #3 */
+	Device(I2C3) {
+		Name (_ADR, 0x00160003)
+		Name (_DDN, "Intel(R) I2C Controller #3")
+	}
+
+	/* LPIO2 I2C #4 */
+	Device(I2C4) {
+		Name (_ADR, 0x00170000)
+		Name (_DDN, "Intel(R) I2C Controller #4")
+	}
+
+	/* LPIO2 I2C #5 */
+	Device(I2C5) {
+		Name (_ADR, 0x00170001)
+		Name (_DDN, "Intel(R) I2C Controller #5")
+	}
+
+	/* LPIO2 I2C #6 */
+	Device(I2C6) {
+		Name (_ADR, 0x00170002)
+		Name (_DDN, "Intel(R) I2C Controller #6")
+	}
+
+	/* LPIO2 I2C #7 */
+	Device(I2C7) {
+		Name (_ADR, 0x00170003)
+		Name (_DDN, "Intel(R) I2C Controller #7")
+	}
+}
diff --git a/src/soc/intel/glk/acpi/northbridge.asl b/src/soc/intel/glk/acpi/northbridge.asl
new file mode 100644
index 0000000..919026a
--- /dev/null
+++ b/src/soc/intel/glk/acpi/northbridge.asl
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+	Name(_HID, EISAID("PNP0A08"))	/* PCIe */
+	Name(_CID, EISAID("PNP0A03"))	/* PCI */
+	Name(_ADR, 0)
+	Name(_BBN, 0)
+
+Device (MCHC)
+{
+	Name (_ADR, 0x00000000)		/*Dev0 Func0 */
+
+		OperationRegion (MCHP, PCI_Config, 0x00, 0x100)
+		Field (MCHP, DWordAcc, NoLock, Preserve)
+		{
+			Offset(0x60),
+			MCNF,	32,	/* PCI MMCONF base */
+			Offset (0xA8),
+			TUUD, 64,	/* Top of Upper Used Memory */
+			Offset(0xB4),
+			BGSM,   32,	/* Base of Graphics Stolen Memory */
+			Offset(0xBC),
+			TLUD,   32,	/* Top of Low Useable DRAM */
+		}
+}
+Name (MCRS, ResourceTemplate()
+{
+	/* Bus Numbers */
+	WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+			0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,,)
+
+	/* IO Region 0 */
+	DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+			0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,,)
+
+	/* PCI Config Space */
+	Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+	/* IO Region 1 */
+	DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+			0x0000, 0x01000, 0xffff, 0x0000, 0xf000,,,)
+
+	/* VGA memory (0xa0000-0xbffff) */
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			Cacheable, ReadWrite,
+			0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
+			0x00020000,,,)
+
+	/* Data and GFX stolen memory */
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			Cacheable, ReadWrite,
+			0x00000000, 0x3be00000, 0x3fffffff, 0x00000000,
+			0x04200000,,, STOM)
+
+	/*
+	 * PCI MMIO Region (TOLUD - PCI extended base MMCONF)
+	 * This assumes that MMCONF is placed after PCI config space,
+	 * and that no resources are allocated after the MMCONF region.
+	 * This works, sicne MMCONF is hardcoded to 0xe00000000.
+	 */
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			NonCacheable, ReadWrite,
+			0x00000000, 0x00000000, 0x00000000, 0x00000000,
+			0x00000000,,, PM01)
+
+	/* PCI Memory Region (TOUUD - (TOUUD + ABOVE_4G_MMIO_SIZE)) */
+	QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+			NonCacheable, ReadWrite,
+			0x00000000, 0x10000, 0x1ffff, 0x00000000,
+			0x10000,,, PM02)
+})
+
+/* Current Resource Settings */
+Method (_CRS, 0, Serialized)
+{
+
+	/* Find PCI resource area in MCRS */
+	CreateDwordField (MCRS, ^PM01._MIN, PMIN)
+	CreateDwordField (MCRS, ^PM01._MAX, PMAX)
+	CreateDwordField (MCRS, ^PM01._LEN, PLEN)
+
+	/* Read C-Unit PCI CFG Reg. 0xBC for TOLUD (shadow from B-Unit) */
+	And(^MCHC.TLUD, 0xFFF00000, PMIN)
+	/* Read MMCONF base */
+	And(^MCHC.MCNF, 0xF0000000, PMAX)
+
+	/* Calculate PCI MMIO Length */
+	Add(Subtract(PMAX, PMIN), 1, PLEN)
+
+	/* Find GFX resource area in GCRS */
+	CreateDwordField(MCRS, ^STOM._MIN, GMIN)
+	CreateDwordField(MCRS, ^STOM._MAX, GMAX)
+	CreateDwordField(MCRS, ^STOM._LEN, GLEN)
+
+	/* Read BGSM */
+	And(^MCHC.BGSM, 0xFFF00000, GMIN)
+
+	/* Read TOLUD */
+	And(^MCHC.TLUD, 0xFFF00000, GMAX)
+	Decrement(GMAX)
+	Add(Subtract(GMAX, GMIN), 1, GLEN)
+
+	/* Patch PM02 range based on Memory Size */
+	CreateQwordField (MCRS, ^PM02._MIN, MMIN)
+	CreateQwordField (MCRS, ^PM02._MAX, MMAX)
+	CreateQwordField (MCRS, ^PM02._LEN, MLEN)
+
+	Store (^MCHC.TUUD, Local0)
+
+	If (LLessEqual (Local0, 0x1000000000))
+	{
+		Store (0, MMIN)
+		Store (0, MLEN)
+	}
+	Subtract (Add (MMIN, MLEN), 1, MMAX)
+
+	Return (MCRS)
+}
diff --git a/src/soc/intel/glk/acpi/pch_hda.asl b/src/soc/intel/glk/acpi/pch_hda.asl
new file mode 100644
index 0000000..33cd771
--- /dev/null
+++ b/src/soc/intel/glk/acpi/pch_hda.asl
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ * Copyright (C) 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/* Audio Controller - Device 14, Function 0 */
+
+Device (HDAS)
+{
+	Name (_ADR, 0x000E0000)
+	Name (_DDN, "Audio Controller")
+	Name (UUID, ToUUID("A69F886E-6CEB-4594-A41F-7B5DCE24C553"))
+
+	/* Device is D3 wake capable */
+	Name (_S0W, 3)
+
+	/* NHLT Table Address populated from GNVS values */
+	Name (NBUF, ResourceTemplate() {
+		QWordMemory (ResourceConsumer, PosDecode, MinFixed,
+			MaxFixed, Cacheable, ReadOnly,
+			0, 0, 0, 0, 1,,, NHLT, AddressRangeACPI)
+		}
+	)
+
+	/*
+	 * Device Specific Method
+	 * Arg0 - UUID
+	 * Arg1 - Revision
+	 * Arg2 - Function Index
+	*/
+	Method (_DSM, 4) {
+		If (LEqual (Arg0, ^UUID)) {
+			/*
+			 * Function 0: Function Support Query
+			 * Returns a bitmask of functions supported.
+			 */
+			If (LEqual (Arg2, Zero)) {
+				/*
+				 * NHLT Query only supported for revision 1 and
+				 * if NHLT address and length are set in NVS.
+				 */
+				If (LAnd (LEqual (Arg1, One),
+					LAnd (LNotEqual (NHLA, Zero),
+					     LNotEqual (NHLL, Zero)))) {
+					Return (Buffer (One) { 0x03 })
+				}
+				Else {
+					Return (Buffer (One) { 0x01 })
+				}
+			}
+
+			/*
+			 * Function 1: Query NHLT memory address used by
+			 * Intel Offload Engine Driver to discover any non-HDA
+			 * devices that are supported by the DSP.
+			 *
+			 * Returns a pointer to NHLT table in memory.
+			 */
+			If (LEqual (Arg2, One)) {
+				CreateQWordField (NBUF, ^NHLT._MIN, NBAS)
+				CreateQWordField (NBUF, ^NHLT._MAX, NMAS)
+				CreateQWordField (NBUF, ^NHLT._LEN, NLEN)
+				Store (NHLA, NBAS)
+				Store (NHLA, NMAS)
+				Store (NHLL, NLEN)
+				Return (NBUF)
+			}
+		}
+
+		Return (Buffer (One) { 0x00 })
+	}
+}
diff --git a/src/soc/intel/glk/acpi/pci_irqs.asl b/src/soc/intel/glk/acpi/pci_irqs.asl
new file mode 100644
index 0000000..22878c6
--- /dev/null
+++ b/src/soc/intel/glk/acpi/pci_irqs.asl
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "soc_int.asl"
+
+Method(_PRT)
+{
+	Return(Package() {
+
+		Package(){0x0000FFFF, 0, 0, NPK_INT},
+		Package(){0x0000FFFF, 1, 0, PUNIT_INT},
+		Package(){0x0002FFFF, 0, 0, GEN_INT},
+		Package(){0x0003FFFF, 0, 0, IUNIT_INT},
+		Package(){0x000DFFFF, 1, 0, PMC_INT},
+		Package(){0x000EFFFF, 0, 0, AUDIO_INT},
+		Package(){0x000FFFFF, 0, 0, CSE_INT},
+		Package(){0x0011FFFF, 0, 0, ISH_INT},
+		Package(){0x0012FFFF, 0, 0, SATA_INT},
+		Package(){0x0013FFFF, 0, 0, PIRQA_INT},
+		Package(){0x0013FFFF, 1, 0, PIRQB_INT},
+		Package(){0x0013FFFF, 2, 0, PIRQC_INT},
+		Package(){0x0013FFFF, 3, 0, PIRQD_INT},
+		Package(){0x0014FFFF, 0, 0, PIRQB_INT},
+		Package(){0x0014FFFF, 1, 0, PIRQC_INT},
+		Package(){0x0014FFFF, 2, 0, PIRQD_INT},
+		Package(){0x0014FFFF, 3, 0, PIRQA_INT},
+		Package(){0x0015FFFF, 0, 0, XHCI_INT},
+		Package(){0x0015FFFF, 1, 0, XDCI_INT},
+		Package(){0x0016FFFF, 0, 0, I2C0_INT},
+		Package(){0x0016FFFF, 1, 0, I2C1_INT},
+		Package(){0x0016FFFF, 2, 0, I2C2_INT},
+		Package(){0x0016FFFF, 3, 0, I2C3_INT},
+		Package(){0x0017FFFF, 0, 0, I2C4_INT},
+		Package(){0x0017FFFF, 1, 0, I2C5_INT},
+		Package(){0x0017FFFF, 2, 0, I2C6_INT},
+		Package(){0x0017FFFF, 3, 0, I2C7_INT},
+		Package(){0x0018FFFF, 0, 0, UART0_INT},
+		Package(){0x0018FFFF, 1, 0, UART1_INT},
+		Package(){0x0018FFFF, 2, 0, UART2_INT},
+		Package(){0x0018FFFF, 3, 0, UART3_INT},
+		Package(){0x0019FFFF, 0, 0, SPI0_INT},
+		Package(){0x0019FFFF, 1, 0, SPI1_INT},
+		Package(){0x0019FFFF, 2, 0, SPI2_INT},
+		Package(){0x001BFFFF, 0, 0, SDCARD_INT},
+		Package(){0x001CFFFF, 0, 0, EMMC_INT},
+		Package(){0x001EFFFF, 0, 0, SDIO_INT},
+		Package(){0x001FFFFF, 1, 0, SMBUS_INT},
+	})
+}
diff --git a/src/soc/intel/glk/acpi/pcie.asl b/src/soc/intel/glk/acpi/pcie.asl
new file mode 100644
index 0000000..050f2f0
--- /dev/null
+++ b/src/soc/intel/glk/acpi/pcie.asl
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+Device (RP01)
+{
+	Name (_ADR, 0x00140000)
+	Name (_DDN, "PCIe-B 0")
+	Name (PDST, 0) /* present Detect status */
+
+	/* lowest D-state supported by
+	 * PCIe root port during S0 state
+	 */
+	Name (_S0W, 4)
+
+	/* Dynamic Opregion needed to access registers
+	 * when the controller is in D3 cold
+	 */
+	OperationRegion (PX01, PCI_Config, 0x00, 0xFF)
+	Field (PX01, AnyAcc, NoLock, Preserve)
+	{
+		Offset(0x5A),
+		, 6,
+		PDS, 1,		/* 6, Presence detect Change */
+		Offset(0xE2),	/* RPPGEN - Root Port Power Gating Enable */
+		, 2,
+		L23E, 1,	/* 2, L23_Rdy Entry Request (L23ER) */
+		L23R, 1,	/* 3, L23_Rdy to Detect Transition (L23R2DT) */
+		Offset(0xF4),	/* BLKPLLEN */
+		, 10,
+		BPLL, 1,
+	}
+
+	OperationRegion (PX02, PCI_Config, 0x338, 0x4)
+	Field (PX02, AnyAcc, NoLock, Preserve)
+	{
+		, 26,
+		BDQA, 1		/* BLKDQDA */
+	}
+
+	PowerResource (PXP, 0, 0)
+	{
+		/* Define the PowerResource for PCIe slot */
+		Method (_STA, 0, Serialized)
+		{
+			Store (PDS, PDST)
+			If (LEqual (PDS, 1)) {
+				Return (0xf)
+			} Else {
+				Return (0)
+			}
+		}
+
+		Method (_ON, 0, Serialized)
+		{
+			If (LAnd (LEqual (PDST, 1), LNotEqual (\PRT0, 0))) {
+				/* Enter this condition if device
+				 * is connected
+				 */
+
+				/* De-assert PERST */
+				\_SB.PCI0.PRDA (\PRT0)
+
+				Store (0, BDQA) /* Set BLKDQDA to 0 */
+				Store (0, BPLL) /* Set BLKPLLEN to 0 */
+
+				/* Set L23_Rdy to Detect Transition
+				 * (L23R2DT)
+				 */
+				Store (1, L23R)
+				Sleep (16)
+				Store (0, Local0)
+
+				/* Delay for transition Detect
+				 * and link to train
+				 */
+				While (L23R) {
+					If (Lgreater (Local0, 4)) {
+						Break
+					}
+					Sleep (16)
+					Increment (Local0)
+				}
+			} /* End PDS condition check */
+		}
+
+		Method (_OFF, 0, Serialized)
+		{
+			/* Set L23_Rdy Entry Request (L23ER) */
+			If (LAnd (LEqual (PDST, 1), LNotEqual (\PRT0, 0))) {
+				/* enter this condition if device
+				 * is connected
+				 */
+				Store (1, L23E)
+				Sleep (16)
+				Store (0, Local0)
+				While (L23E) {
+					If (Lgreater (Local0, 4)) {
+						Break
+					}
+					Sleep (16)
+					Increment (Local0)
+				}
+				Store (1, BDQA) /* Set BLKDQDA to 1 */
+				Store (1, BPLL) /* Set BLKPLLEN to 1 */
+
+				/* Assert PERST */
+				\_SB.PCI0.PRAS (\PRT0)
+			} /* End PDS condition check */
+		} /* End of Method_OFF */
+	} /* End PXP */
+
+	Name(_PR0, Package() { PXP })
+	Name(_PR3, Package() { PXP })
+}
diff --git a/src/soc/intel/glk/acpi/platform.asl b/src/soc/intel/glk/acpi/platform.asl
new file mode 100644
index 0000000..f3202a0
--- /dev/null
+++ b/src/soc/intel/glk/acpi/platform.asl
@@ -0,0 +1,20 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2016 Intel Corp
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* Enable ACPI _SWS methods */
+#include <soc/intel/common/acpi/acpi_wake_source.asl>
+#include <soc/intel/common/acpi/platform.asl>
diff --git a/src/soc/intel/glk/acpi/scs.asl b/src/soc/intel/glk/acpi/scs.asl
new file mode 100644
index 0000000..4108017
--- /dev/null
+++ b/src/soc/intel/glk/acpi/scs.asl
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+Scope (\_SB.PCI0) {
+	/* 0xD6- is the port address */
+	/* 0x600- is the dynamic clock gating control register offset (GENR) */
+	OperationRegion (SBMM, SystemMemory,
+				Or ( Or (CONFIG_IOSF_BASE_ADDRESS,
+					ShiftLeft(0xD6, 16)), 0x0600), 0x18)
+	Field (SBMM, DWordAcc, NoLock, Preserve)
+	{
+		GENR, 32,
+	}
+
+	/* SCC power gate control method, this method must be serialized as
+	 * multiple device will control the GENR register
+	 *
+	 * Arguments: (2)
+	 * Arg0: 0-AND  1-OR
+	 * Arg1: Value
+	 */
+	Method (SCPG, 2, Serialized)
+	{
+		if (LEqual(Arg0, 0x1)) {
+			Or (^GENR, Arg1, ^GENR)
+		} ElseIf (LEqual(Arg0, 0x0)){
+			And (^GENR, Arg1, ^GENR)
+		}
+	}
+
+	/* eMMC */
+	Device (SDHA) {
+		Name (_ADR, 0x001C0000)
+		Name (_DDN, "Intel(R) eMMC Controller - 80865ACC")
+
+		Method (_PS0, 0, NotSerialized)
+		{
+			/* Clear clock gate
+			 * Clear bit 6 and 0
+			 */
+			^^SCPG(0,0xFFFFFFBE)
+			/* Sleep 2 ms */
+			Sleep (2)
+		}
+
+		Method (_PS3, 0, NotSerialized)
+		{
+			/* Enable power gate
+			 * Restore clock gate
+			 * Restore bit 6 and 0
+			 */
+			^^SCPG(1,0x00000041)
+		}
+	} /* Device (SDHA) */
+}
diff --git a/src/soc/intel/glk/acpi/sleepstates.asl b/src/soc/intel/glk/acpi/sleepstates.asl
new file mode 100644
index 0000000..e79f2f0
--- /dev/null
+++ b/src/soc/intel/glk/acpi/sleepstates.asl
@@ -0,0 +1,21 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+Name (\_S0, Package () { 0x0, 0x0, 0x0, 0x0 })
+Name (\_S3, Package () { 0x5, 0x5, 0x0, 0x0 })
+Name (\_S5, Package () { 0x7, 0x7, 0x0, 0x0 })
diff --git a/src/soc/intel/glk/acpi/soc_int.asl b/src/soc/intel/glk/acpi/soc_int.asl
new file mode 100644
index 0000000..c643244
--- /dev/null
+++ b/src/soc/intel/glk/acpi/soc_int.asl
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_INT_DEFINE_ASL_
+#define _SOC_INT_DEFINE_ASL_
+
+#define SDCARD_INT	3	/* Need to be shared by PMC and SCC only*/
+#define UART0_INT	4	/* Need to be shared by PMC and SCC only*/
+#define UART1_INT	5	/* Need to be shared by PMC and SCC only*/
+#define UART2_INT	6	/* Need to be shared by PMC and SCC only*/
+#define UART3_INT	7	/* Need to be shared by PMC and SCC only*/
+#define XDCI_INT	13	/* Need to be shared by PMC and SCC only*/
+#define GPIO_BANK_INT	14
+#define NPK_INT		16
+#define PIRQA_INT	16
+#define PIRQB_INT	17
+#define PIRQC_INT	18
+#define SATA_INT	19
+#define GEN_INT		19
+#define PIRQD_INT	19
+#define XHCI_INT	17	/* Need to be shared by PMC and SCC only*/
+#define SMBUS_INT	20	/* PIRQE */
+#define CSE_INT		20	/* PIRQE */
+#define IUNIT_INT	21	/* PIRQF */
+#define PUNIT_INT	24
+#define AUDIO_INT	25
+#define ISH_INT		26
+#define I2C0_INT	27
+#define I2C1_INT	28
+#define I2C2_INT	29
+#define I2C3_INT	30
+#define I2C4_INT	31
+#define I2C5_INT	32
+#define I2C6_INT	33
+#define I2C7_INT	34
+#define SPI0_INT	35
+#define SPI1_INT	36
+#define SPI2_INT	37
+#define UFS_INT		38
+#define EMMC_INT	39
+#define PMC_INT		40
+#define SDIO_INT	42
+
+#endif	/* _SOC_INT_DEFINE_ASL_ */
diff --git a/src/soc/intel/glk/acpi/southbridge.asl b/src/soc/intel/glk/acpi/southbridge.asl
new file mode 100644
index 0000000..d7ced0f
--- /dev/null
+++ b/src/soc/intel/glk/acpi/southbridge.asl
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <soc/gpe.h>
+
+/* PCIE device */
+#include "pcie.asl"
+
+/* LPSS device */
+#include "lpss.asl"
+
+/* PCI IRQ assignment */
+#include "pci_irqs.asl"
+
+/* GPIO controller */
+#include "gpio.asl"
+
+#include "xhci.asl"
+
+/* LPC */
+#include "lpc.asl"
+
+/* eMMC */
+#include "scs.asl"
+
+/* PCI _OSC */
+#include <soc/intel/common/acpi/pci_osc.asl>
diff --git a/src/soc/intel/glk/acpi/xhci.asl b/src/soc/intel/glk/acpi/xhci.asl
new file mode 100644
index 0000000..c07c707
--- /dev/null
+++ b/src/soc/intel/glk/acpi/xhci.asl
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* XHCI Controller 0:15.0 */
+Device (XHC1) {
+	Name (_ADR, 0x00150000)  /* Device 21, Function 0 */
+
+	Name (_S3D, 3)  /* D3 supported in S3 */
+	Name (_S0W, 3)  /* D3 can wake device in S0 */
+	Name (_S3W, 3)  /* D3 can wake system from S3 */
+
+	/* Declare XHCI GPE status and enable bits are bit 13 */
+	Name (_PRW, Package() { GPE0A_XHCI_PME_STS, 3 })
+
+	Method (_STA, 0)
+	{
+		Return (0xF)
+	}
+}
diff --git a/src/soc/intel/glk/bootblock/bootblock.c b/src/soc/intel/glk/bootblock/bootblock.c
new file mode 100644
index 0000000..d88ba1d
--- /dev/null
+++ b/src/soc/intel/glk/bootblock/bootblock.c
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <arch/cpu.h>
+#include <bootblock_common.h>
+#include <cpu/x86/mtrr.h>
+#include <device/pci.h>
+#include <lib.h>
+#include <soc/iomap.h>
+#include <soc/cpu.h>
+#include <soc/gpio.h>
+#include <soc/iosf.h>
+#include <soc/mmap_boot.h>
+#include <soc/northbridge.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/uart.h>
+#include <spi-generic.h>
+#include <timestamp.h>
+
+static const struct pad_config tpm_spi_configs[] = {
+};
+
+static void tpm_enable(void)
+{
+	/* Configure gpios */
+	gpio_configure_pads(tpm_spi_configs, ARRAY_SIZE(tpm_spi_configs));
+}
+
+static void enable_pm_timer(void)
+{
+	/* ACPI PM timer emulation */
+	msr_t msr;
+	/*
+	 * The derived frequency is calculated as follows:
+	 *    (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
+	 * Back solve the multiplier so the 3.579545MHz ACPI timer
+	 * frequency is used.
+	 */
+	msr.hi = (3579545ULL << 32) / CTC_FREQ;
+	/* Set PM1 timer IO port and enable*/
+	msr.lo = EMULATE_PM_TMR_EN | (ACPI_PMIO_BASE + R_ACPI_PM1_TMR);
+	wrmsr(MSR_EMULATE_PM_TMR, msr);
+}
+
+static void enable_cmos_upper_bank(void)
+{
+	uint32_t reg = iosf_read(IOSF_RTC_PORT_ID, RTC_CONFIG);
+	reg |= RTC_CONFIG_UCMOS_ENABLE;
+	iosf_write(IOSF_RTC_PORT_ID, RTC_CONFIG, reg);
+}
+
+void asmlinkage bootblock_c_entry(uint64_t base_timestamp)
+{
+	device_t dev = NB_DEV_ROOT;
+
+	/* Set PCI Express BAR */
+	pci_io_write_config32(dev, PCIEXBAR, CONFIG_MMCONF_BASE_ADDRESS | 1);
+	/*
+	 * Clear TSEG register - TSEG register comes out of reset with a
+	 * non-zero default value. Clear this register to ensure that there are
+	 * no surprises in CBMEM handling.
+	 */
+	pci_write_config32(dev, TSEG, 0);
+
+	dev = P2SB_DEV;
+	/* BAR and MMIO enable for IOSF, so that GPIOs can be configured */
+	pci_write_config32(dev, PCI_BASE_ADDRESS_0, CONFIG_IOSF_BASE_ADDRESS);
+	pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0);
+	pci_write_config16(dev, PCI_COMMAND,
+				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+
+	/* Decode the ACPI I/O port range for early firmware verification.*/
+	dev = PMC_DEV;
+	pci_write_config16(dev, PCI_BASE_ADDRESS_4, ACPI_PMIO_BASE);
+	pci_write_config16(dev, PCI_COMMAND,
+				PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+
+	enable_cmos_upper_bank();
+
+	/* Call lib/bootblock.c main */
+	bootblock_main_with_timestamp(base_timestamp);
+}
+
+static void cache_bios_region(void)
+{
+	int mtrr;
+	size_t rom_size;
+	uint32_t alignment;
+
+	mtrr = get_free_var_mtrr();
+
+	if (mtrr==-1)
+		return;
+
+	/* Only the IFD BIOS region is memory mapped (at top of 4G) */
+	rom_size = get_bios_size();
+
+	if (!rom_size)
+		return;
+
+	/* Round to power of two */
+	alignment = 1 << (log2_ceil(rom_size));
+	rom_size = ALIGN_UP(rom_size, alignment);
+	set_var_mtrr(mtrr, 4ULL*GiB - rom_size, rom_size, MTRR_TYPE_WRPROT);
+}
+
+/*
+ * Program temporary BAR for SPI in case any of the stages before ramstage need
+ * to access SPI MMIO regs. Ramstage will assign a new BAR during PCI
+ * enumeration.
+ */
+static void enable_spibar(void)
+{
+	device_t dev = SPI_DEV;
+	uint8_t val;
+
+	/* Disable Bus Master and MMIO space. */
+	val = pci_read_config8(dev, PCI_COMMAND);
+	val &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+	pci_write_config8(dev, PCI_COMMAND, val);
+
+	/* Program Temporary BAR for SPI */
+	pci_write_config32(dev, PCI_BASE_ADDRESS_0,
+			   PRERAM_SPI_BASE_ADDRESS |
+			   PCI_BASE_ADDRESS_SPACE_MEMORY);
+
+	/* Enable Bus Master and MMIO Space */
+	val = pci_read_config8(dev, PCI_COMMAND);
+	val |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config8(dev, PCI_COMMAND, val);
+
+	/* Initialize SPI to allow BIOS to write/erase on flash. */
+	spi_init();
+}
+
+static void enable_pmcbar(void)
+{
+	device_t pmc = PMC_DEV;
+
+	/* Set PMC base addresses and enable decoding. */
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_0, PMC_BAR0);
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_1, 0);	/* 64-bit BAR */
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_2, PMC_BAR1);
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_3, 0);	/* 64-bit BAR */
+	pci_write_config16(pmc, PCI_BASE_ADDRESS_4, ACPI_PMIO_BASE);
+	pci_write_config16(pmc, PCI_COMMAND,
+				PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+				PCI_COMMAND_MASTER);
+}
+
+void bootblock_soc_early_init(void)
+{
+	enable_pmcbar();
+
+	/* Clear global reset promotion bit */
+	global_reset_enable(0);
+
+	/* Prepare UART for serial console. */
+	if (IS_ENABLED(CONFIG_SOC_UART_DEBUG))
+		soc_console_uart_init();
+
+	if (IS_ENABLED(CONFIG_TPM_ON_FAST_SPI))
+		tpm_enable();
+
+	enable_pm_timer();
+
+	enable_spibar();
+
+	cache_bios_region();
+
+	/* Initialize GPE for use as interrupt status */
+	pmc_gpe_init();
+}
diff --git a/src/soc/intel/glk/bootblock/cache_as_ram.S b/src/soc/intel/glk/bootblock/cache_as_ram.S
new file mode 100644
index 0000000..65dd4c8
--- /dev/null
+++ b/src/soc/intel/glk/bootblock/cache_as_ram.S
@@ -0,0 +1,251 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/pci_def.h>
+#include <commonlib/helpers.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/cr.h>
+#include <cpu/x86/post_code.h>
+#include <soc/cpu.h>
+
+.global bootblock_pre_c_entry
+bootblock_pre_c_entry:
+
+.global cache_as_ram
+cache_as_ram:
+	post_code(0x21)
+
+	/* Clear/disable fixed MTRRs */
+	mov	$fixed_mtrr_list_size, %ebx
+	xor	%eax, %eax
+	xor	%edx, %edx
+clear_fixed_mtrr:
+	add	$-2, %ebx
+	movzwl	fixed_mtrr_list(%ebx), %ecx
+	wrmsr
+	jnz	clear_fixed_mtrr
+
+	post_code(0x22)
+
+	/* Figure put how many MTRRs we have, and clear them out */
+	mov	$MTRR_CAP_MSR, %ecx
+	rdmsr
+	movzb	%al, %ebx		/* Number of variable MTRRs */
+	mov	$MTRR_PHYS_BASE(0), %ecx
+	xor	%eax, %eax
+	xor	%edx, %edx
+
+clear_var_mtrr:
+	wrmsr
+	inc	%ecx
+	wrmsr
+	inc	%ecx
+	dec	%ebx
+	jnz	clear_var_mtrr
+
+	post_code(0x23)
+
+	/* Configure default memory type to uncacheable (UC) */
+	mov	$MTRR_DEF_TYPE_MSR, %ecx
+	rdmsr
+	/* Clear enable bits and set default type to UC. */
+	and	$~(MTRR_DEF_TYPE_MASK | MTRR_DEF_TYPE_EN | \
+		   MTRR_DEF_TYPE_FIX_EN), %eax
+	wrmsr
+
+	post_code(0x24)
+
+#if ((CONFIG_DCACHE_RAM_SIZE & (CONFIG_DCACHE_RAM_SIZE - 1)) == 0)
+	/* Configure CAR region as write-back (WB) */
+	mov	$MTRR_PHYS_BASE(0), %ecx
+	mov	$CONFIG_DCACHE_RAM_BASE, %eax
+	or	$MTRR_TYPE_WRBACK, %eax
+	xor	%edx,%edx
+	wrmsr
+
+	/* Configure the MTRR mask for the size region */
+	mov	$MTRR_PHYS_MASK(0), %ecx
+	mov	$~(CONFIG_DCACHE_RAM_SIZE - 1), %eax	/* size mask */
+	or	$MTRR_PHYS_MASK_VALID, %eax
+	wrmsr
+#elif (CONFIG_DCACHE_RAM_SIZE == 768 * KiB) /* 768 KiB */
+	mov	$MTRR_PHYS_BASE(0), %ecx
+	mov	$CONFIG_DCACHE_RAM_BASE, %eax
+	or	$MTRR_TYPE_WRBACK, %eax
+	xor	%edx,%edx
+	wrmsr
+
+	mov	$MTRR_PHYS_MASK(0), %ecx
+	mov	$~(512 * KiB - 1), %eax	/* size mask */
+	or	$MTRR_PHYS_MASK_VALID, %eax
+	wrmsr
+
+	mov	$MTRR_PHYS_BASE(1), %ecx
+	mov	$(CONFIG_DCACHE_RAM_BASE + 512 * KiB), %eax
+	or	$MTRR_TYPE_WRBACK, %eax
+	xor	%edx,%edx
+	wrmsr
+
+	mov	$MTRR_PHYS_MASK(1), %ecx
+	mov	$~(256 * KiB - 1), %eax	/* size mask */
+	or	$MTRR_PHYS_MASK_VALID, %eax
+	wrmsr
+#else
+#error "DCACHE_RAM_SIZE is not a power of 2 and setup code is missing"
+#endif
+
+	post_code(0x25)
+
+	/* Enable variable MTRRs */
+	mov	$MTRR_DEF_TYPE_MSR, %ecx
+	rdmsr
+	or	$MTRR_DEF_TYPE_EN, %eax
+	wrmsr
+
+	/* Enable caching */
+	mov	%cr0, %eax
+	and	$~(CR0_CD | CR0_NW), %eax
+	invd
+	mov	%eax, %cr0
+
+#if IS_ENABLED(CONFIG_CAR_NEM)
+	/* Disable cache eviction (setup stage) */
+	mov	$MSR_EVICT_CTL, %ecx
+	rdmsr
+	or	$0x1, %eax
+	wrmsr
+#else
+	/*
+	 * Disable both L1 and L2 prefetcher. For yet-to-understood reason,
+	 * prefetchers slow down filling cache with rep stos in CQOS mode.
+	 */
+	mov	$MSR_PREFETCH_CTL, %ecx
+	rdmsr
+	or	$(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
+	wrmsr
+#endif
+
+#if IS_ENABLED(CONFIG_CAR_CQOS)
+#if (CONFIG_DCACHE_RAM_SIZE == L2_CACHE_SIZE)
+/*
+ * If CAR size is set to full L2 size, mask is calculated as all-zeros.
+ * This is not supported by the CPU/uCode.
+ */
+#error "CQOS CAR may not use whole L2 cache area"
+#endif
+	/* Calculate how many bits to be used for CAR */
+	xor	%edx, %edx
+	mov	$CONFIG_DCACHE_RAM_SIZE, %eax	/* dividend */
+	mov	$CACHE_QOS_SIZE_PER_BIT, %ecx	/* divisor */
+	div	%ecx				/* result is in eax */
+	mov	%eax, %ecx			/* save to ecx */
+	mov	$1, %ebx
+	shl	%cl, %ebx
+	sub	$1, %ebx			/* resulting mask is is in ebx */
+
+	/* Set this mask for initial cache fill */
+	mov	$MSR_L2_QOS_MASK(0), %ecx
+	rdmsr
+	mov	%bl, %al
+	wrmsr
+
+	/* Set CLOS selector to 0 */
+	mov	$MSR_IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~IA32_PQR_ASSOC_MASK, %edx	/* select mask 0 */
+	wrmsr
+
+	/* We will need to block CAR region from evicts */
+	mov	$MSR_L2_QOS_MASK(1), %ecx
+	rdmsr
+	/* Invert bits that are to be used for cache */
+	mov	%bl, %al
+	xor	$~0, %al			/* invert 8 bits */
+	wrmsr
+#endif
+	post_code(0x26)
+
+	/* Clear the cache memory region. This will also fill up the cache */
+	mov	$CONFIG_DCACHE_RAM_BASE, %edi
+	mov	$(CONFIG_DCACHE_RAM_SIZE >> 2), %ecx
+	xor	%eax, %eax
+	rep	stos %eax, %es:(%edi)
+
+	post_code(0x27)
+
+#if IS_ENABLED(CONFIG_CAR_NEM)
+	/* Disable cache eviction (run stage) */
+	mov	$MSR_EVICT_CTL, %ecx
+	rdmsr
+	or	$0x2, %eax
+	wrmsr
+#else
+	/* Cache is populated. Use mask 1 that will block evicts */
+	mov	$MSR_IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~IA32_PQR_ASSOC_MASK, %edx	/* clear index bits first */
+	or	$1, %edx			/* select mask 1 */
+	wrmsr
+
+	/* Enable prefetchers */
+	mov	$MSR_PREFETCH_CTL, %ecx
+	rdmsr
+	and	$~(PREFETCH_L1_DISABLE | PREFETCH_L2_DISABLE), %eax
+	wrmsr
+#endif
+
+	post_code(0x28)
+
+car_init_done:
+
+	/* Setup bootblock stack */
+	mov	$_car_stack_end, %esp
+
+before_carstage:
+	post_code(0x2b)
+
+	/* Restore the timestamp from bootblock_crt0.S (mm2:mm1) */
+	movd	%mm2, %eax
+	push	%eax
+	movd	%mm1, %eax
+	push	%eax
+
+	/* We can call into C functions now */
+	call bootblock_c_entry
+
+	/* Never reached */
+
+.halt_forever:
+	post_code(POST_DEAD_CODE)
+	hlt
+	jmp	.halt_forever
+
+fixed_mtrr_list:
+	.word	MTRR_FIX_64K_00000
+	.word	MTRR_FIX_16K_80000
+	.word	MTRR_FIX_16K_A0000
+	.word	MTRR_FIX_4K_C0000
+	.word	MTRR_FIX_4K_C8000
+	.word	MTRR_FIX_4K_D0000
+	.word	MTRR_FIX_4K_D8000
+	.word	MTRR_FIX_4K_E0000
+	.word	MTRR_FIX_4K_E8000
+	.word	MTRR_FIX_4K_F0000
+	.word	MTRR_FIX_4K_F8000
+fixed_mtrr_list_size = . - fixed_mtrr_list
diff --git a/src/soc/intel/glk/car.c b/src/soc/intel/glk/car.c
new file mode 100644
index 0000000..68bcb31
--- /dev/null
+++ b/src/soc/intel/glk/car.c
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/cpu.h>
+#include <assert.h>
+#include <program_loading.h>
+#include <soc/cpu.h>
+
+/*
+ * This file supports the necessary hoops one needs to jump through since
+ * early FSP component and early stages are running from cache-as-ram.
+ */
+
+static void flush_l1d_to_l2(void)
+{
+	msr_t msr = rdmsr(MSR_POWER_MISC);
+	msr.lo |= (1 << 8);
+	wrmsr(MSR_POWER_MISC, msr);
+}
+
+static inline int is_car_addr(uintptr_t addr)
+{
+	return ((addr >= CONFIG_DCACHE_RAM_BASE) &&
+		(addr < (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)));
+}
+
+void platform_segment_loaded(uintptr_t start, size_t size, int flags)
+{
+	/* Bail out if this is not the final segment. */
+	if (!(flags & SEG_FINAL))
+		return;
+
+	char start_car_check = is_car_addr(start);
+	char end_car_check = is_car_addr(start + size - 1);
+
+	/* Bail out if loaded program segment does not lie in CAR region. */
+	if (!start_car_check && !end_car_check)
+		return;
+
+	/* Loaded program segment should lie entirely within CAR region. */
+	assert (start_car_check && end_car_check);
+
+	flush_l1d_to_l2();
+}
diff --git a/src/soc/intel/glk/chip.c b/src/soc/intel/glk/chip.c
new file mode 100644
index 0000000..916096b
--- /dev/null
+++ b/src/soc/intel/glk/chip.c
@@ -0,0 +1,462 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <bootstate.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <fsp/api.h>
+#include <fsp/util.h>
+#include <soc/iomap.h>
+#include <soc/cpu.h>
+#include <soc/intel/common/vbt.h>
+#include <soc/itss.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <spi-generic.h>
+#include <soc/pm.h>
+#include <soc/p2sb.h>
+#include <soc/northbridge.h>
+
+#include "chip.h"
+
+static void *vbt;
+static struct region_device vbt_rdev;
+
+static const char *soc_acpi_name(struct device *dev)
+{
+	if (dev->path.type == DEVICE_PATH_DOMAIN)
+		return "PCI0";
+
+	if (dev->path.type != DEVICE_PATH_PCI)
+		return NULL;
+
+	switch (dev->path.pci.devfn) {
+	/* DSDT: acpi/northbridge.asl */
+	case NB_DEVFN:
+		return "MCHC";
+	/* DSDT: acpi/lpc.asl */
+	case LPC_DEVFN:
+		return "LPCB";
+	/* DSDT: acpi/xhci.asl */
+	case XHCI_DEVFN:
+		return "XHCI";
+	/* DSDT: acpi/pch_hda.asl */
+	case HDA_DEVFN:
+		return "HDAS";
+	/* DSDT: acpi/lpss.asl */
+	case LPSS_DEVFN_UART0:
+		return "URT1";
+	case LPSS_DEVFN_UART1:
+		return "URT2";
+	case LPSS_DEVFN_UART2:
+		return "URT3";
+	case LPSS_DEVFN_UART3:
+		return "URT4";
+	case LPSS_DEVFN_SPI0:
+		return "SPI1";
+	case LPSS_DEVFN_SPI1:
+		return "SPI2";
+	case LPSS_DEVFN_SPI2:
+		return "SPI3";
+	case LPSS_DEVFN_PWM:
+		return "PWM";
+	case LPSS_DEVFN_I2C0:
+		return "I2C0";
+	case LPSS_DEVFN_I2C1:
+		return "I2C1";
+	case LPSS_DEVFN_I2C2:
+		return "I2C2";
+	case LPSS_DEVFN_I2C3:
+		return "I2C3";
+	case LPSS_DEVFN_I2C4:
+		return "I2C4";
+	case LPSS_DEVFN_I2C5:
+		return "I2C5";
+	case LPSS_DEVFN_I2C6:
+		return "I2C6";
+	case LPSS_DEVFN_I2C7:
+		return "I2C7";
+	/* Storage */
+	case SDCARD_DEVFN:
+		return "SDCD";
+	case EMMC_DEVFN:
+		return "EMMC";
+	case SDIO_DEVFN:
+		return "SDIO";
+	/* PCIe */
+	case PCIEB0_DEVFN:
+		return "RP01";
+	}
+
+	return NULL;
+}
+
+static void pci_domain_set_resources(device_t dev)
+{
+       assign_resources(dev->link_list);
+}
+
+static struct device_operations pci_domain_ops = {
+	.read_resources = pci_domain_read_resources,
+	.set_resources = pci_domain_set_resources,
+	.enable_resources = NULL,
+	.init = NULL,
+	.scan_bus = pci_domain_scan_bus,
+	.ops_pci_bus = pci_bus_default_ops,
+	.acpi_name = &soc_acpi_name,
+};
+
+static struct device_operations cpu_bus_ops = {
+	.read_resources = DEVICE_NOOP,
+	.set_resources = DEVICE_NOOP,
+	.enable_resources = DEVICE_NOOP,
+	.init = glk_init_cpus,
+	.scan_bus = NULL,
+	.acpi_fill_ssdt_generator = generate_cpu_entries,
+};
+
+static void enable_dev(device_t dev)
+{
+	/* Set the operations if it is a special bus type */
+	if (dev->path.type == DEVICE_PATH_DOMAIN) {
+		dev->ops = &pci_domain_ops;
+	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+		dev->ops = &cpu_bus_ops;
+	}
+}
+
+/*
+ * If the PCIe root port at function 0 is disabled,
+ * the PCIe root ports might be coalesced after FSP silicon init.
+ * The below function will swap the devfn of the first enabled device
+ * in devicetree and function 0 resides a pci device
+ * so that it won't confuse coreboot.
+ */
+static void pcie_update_device_tree(unsigned int devfn0, int num_funcs)
+{
+	device_t func0;
+	unsigned int devfn;
+	int i;
+	unsigned int inc = PCI_DEVFN(0, 1);
+
+	func0 = dev_find_slot(0, devfn0);
+	if (func0 == NULL)
+		return;
+
+	/* No more functions if function 0 is disabled. */
+	if (pci_read_config32(func0, PCI_VENDOR_ID) == 0xffffffff)
+		return;
+
+	devfn = devfn0 + inc;
+
+	/*
+	 * Increase funtion by 1.
+	 * Then find first enabled device to replace func0
+	 * as that port was move to func0.
+	 */
+	for (i = 1; i < num_funcs; i++, devfn += inc) {
+		device_t dev = dev_find_slot(0, devfn);
+		if (dev == NULL)
+			continue;
+
+		if (!dev->enabled)
+			continue;
+		/* Found the first enabled device in given dev number */
+		func0->path.pci.devfn = dev->path.pci.devfn;
+		dev->path.pci.devfn = devfn0;
+		break;
+	}
+}
+
+static void pcie_override_devicetree_after_silicon_init(void)
+{
+	pcie_update_device_tree(PCIEA0_DEVFN, 4);
+	pcie_update_device_tree(PCIEB0_DEVFN, 2);
+}
+
+static void rapl_update(void)
+{
+	uint32_t *rapl_reg;
+	uint32_t val;
+	const uint32_t power_mw = 15000;
+
+	rapl_reg = (void*)(uintptr_t) (MCH_BASE_ADDR + MCHBAR_RAPL_PPL);
+
+	/* Due to an incorrect value set for the power limit PL1 as 6W in RAPL
+	 * MMIO register from FSP code, the system is not able to leverage full
+	 * TDP capacity. This RAPL MMIO register is a physically separate
+	 * instance from RAPL MSR register. Punit algorithm controls to the
+	 * minimum power limit PL1 mentioned in the RAPL MMIO and MSR registers.
+	 * Here, setting RAPL PL1 in Bits[14:0] to 15W in RAPL MMIO register. */
+	val = (power_mw << (rdmsr(MSR_PKG_POWER_SKU_UNIT).lo & 0xf)) / 1000;
+	write32(rapl_reg, (read32(rapl_reg) & ~0x7fff) | val);
+}
+
+static void soc_init(void *data)
+{
+	struct global_nvs_t *gnvs;
+
+	/* Save VBT info and mapping */
+	vbt = vbt_get(&vbt_rdev);
+
+	/* Snapshot the current GPIO IRQ polarities. FSP is setting a
+	 * default policy that doesn't honor boards' requirements. */
+	itss_snapshot_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
+
+	fsp_silicon_init();
+
+	/* Restore GPIO IRQ polarities back to previous settings. */
+	itss_restore_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
+
+	/* override 'enabled' setting in device tree if needed */
+	pcie_override_devicetree_after_silicon_init();
+
+	/*
+	 * Keep the P2SB device visible so it and the other devices are
+	 * visible in coreboot for driver support and PCI resource allocation.
+	 * There is a UPD setting for this, but it's more consistent to use
+	 * hide and unhide symmetrically.
+	 */
+	p2sb_unhide();
+
+	/* Allocate ACPI NVS in CBMEM */
+	gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
+
+	/* Update RAPL package power limit */
+	rapl_update();
+}
+
+static void soc_final(void *data)
+{
+	if (vbt)
+		rdev_munmap(&vbt_rdev, vbt);
+
+	/* Disable global reset, just in case */
+	global_reset_enable(0);
+	/* Make sure payload/OS can't trigger global reset */
+	global_reset_lock();
+}
+
+static void disable_dev(struct device *dev, FSP_S_CONFIG *silconfig) {
+
+	switch (dev->path.pci.devfn) {
+	case ISH_DEVFN:
+		silconfig->IshEnable = 0;
+		break;
+	case SATA_DEVFN:
+		silconfig->EnableSata = 0;
+		break;
+	case PCIEB0_DEVFN:
+		silconfig->PcieRootPortEn[0] = 0;
+		silconfig->PcieRpHotPlug[0] = 0;
+		break;
+	case PCIEB1_DEVFN:
+		silconfig->PcieRootPortEn[1] = 0;
+		silconfig->PcieRpHotPlug[1] = 0;
+		break;
+	case PCIEA0_DEVFN:
+		silconfig->PcieRootPortEn[2] = 0;
+		silconfig->PcieRpHotPlug[2] = 0;
+		break;
+	case PCIEA1_DEVFN:
+		silconfig->PcieRootPortEn[3] = 0;
+		silconfig->PcieRpHotPlug[3] = 0;
+		break;
+	case PCIEA2_DEVFN:
+		silconfig->PcieRootPortEn[4] = 0;
+		silconfig->PcieRpHotPlug[4] = 0;
+		break;
+	case PCIEA3_DEVFN:
+		silconfig->PcieRootPortEn[5] = 0;
+		silconfig->PcieRpHotPlug[5] = 0;
+		break;
+	case XHCI_DEVFN:
+		silconfig->Usb30Mode = 0;
+		break;
+	case XDCI_DEVFN:
+		silconfig->UsbOtg = 0;
+		break;
+	case LPSS_DEVFN_I2C0:
+		silconfig->I2c0Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C1:
+		silconfig->I2c1Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C2:
+		silconfig->I2c2Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C3:
+		silconfig->I2c3Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C4:
+		silconfig->I2c4Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C5:
+		silconfig->I2c5Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C6:
+		silconfig->I2c6Enable = 0;
+		break;
+	case LPSS_DEVFN_I2C7:
+		silconfig->I2c7Enable = 0;
+		break;
+	case LPSS_DEVFN_UART0:
+		silconfig->Hsuart0Enable = 0;
+		break;
+	case LPSS_DEVFN_UART1:
+		silconfig->Hsuart1Enable = 0;
+		break;
+	case LPSS_DEVFN_UART2:
+		silconfig->Hsuart2Enable = 0;
+		break;
+	case LPSS_DEVFN_UART3:
+		silconfig->Hsuart3Enable = 0;
+		break;
+	case LPSS_DEVFN_SPI0:
+		silconfig->Spi0Enable = 0;
+		break;
+	case LPSS_DEVFN_SPI1:
+		silconfig->Spi1Enable = 0;
+		break;
+	case LPSS_DEVFN_SPI2:
+		silconfig->Spi2Enable = 0;
+		break;
+	case SDCARD_DEVFN:
+		silconfig->SdcardEnabled = 0;
+		break;
+	case EMMC_DEVFN:
+		silconfig->eMMCEnabled = 0;
+		break;
+	case SDIO_DEVFN:
+		silconfig->SdioEnabled = 0;
+		break;
+	case SMBUS_DEVFN:
+		silconfig->SmbusEnable = 0;
+		break;
+	default:
+		printk(BIOS_WARNING, "PCI:%02x.%01x: Could not disable the device\n",
+			PCI_SLOT(dev->path.pci.devfn),
+			PCI_FUNC(dev->path.pci.devfn));
+		break;
+	}
+}
+
+static void parse_devicetree(FSP_S_CONFIG *silconfig)
+{
+	struct device *dev = NB_DEV_ROOT;
+
+	if (!dev) {
+		printk(BIOS_ERR, "Could not find root device\n");
+		return;
+	}
+	/* Only disable bus 0 devices. */
+	for (dev = dev->bus->children; dev; dev = dev->sibling) {
+		if (!dev->enabled)
+			disable_dev(dev, silconfig);
+	}
+}
+
+void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd)
+{
+        FSP_S_CONFIG *silconfig = &silupd->FspsConfig;
+	static struct soc_intel_glk_config *cfg;
+
+	/* Load VBT before devicetree-specific config. */
+	silconfig->GraphicsConfigPtr = (uintptr_t)vbt;
+
+	struct device *dev = NB_DEV_ROOT;
+
+	if (!dev || !dev->chip_info) {
+		printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+		return;
+	}
+
+	cfg = dev->chip_info;
+
+	/* Parse device tree and disable unused device*/
+	parse_devicetree(silconfig);
+
+	silconfig->PcieRpClkReqNumber[0] = cfg->pcie_rp0_clkreq_pin;
+	silconfig->PcieRpClkReqNumber[1] = cfg->pcie_rp1_clkreq_pin;
+	silconfig->PcieRpClkReqNumber[2] = cfg->pcie_rp2_clkreq_pin;
+	silconfig->PcieRpClkReqNumber[3] = cfg->pcie_rp3_clkreq_pin;
+	silconfig->PcieRpClkReqNumber[4] = cfg->pcie_rp4_clkreq_pin;
+	silconfig->PcieRpClkReqNumber[5] = cfg->pcie_rp5_clkreq_pin;
+
+	if (cfg->emmc_tx_cmd_cntl != 0)
+		silconfig->EmmcTxCmdCntl = cfg->emmc_tx_cmd_cntl;
+	if (cfg->emmc_tx_data_cntl1 != 0)
+		silconfig->EmmcTxDataCntl1 = cfg->emmc_tx_data_cntl1;
+	if (cfg->emmc_tx_data_cntl2 != 0)
+		silconfig->EmmcTxDataCntl2 = cfg->emmc_tx_data_cntl2;
+	if (cfg->emmc_rx_cmd_data_cntl1 != 0)
+		silconfig->EmmcRxCmdDataCntl1 = cfg->emmc_rx_cmd_data_cntl1;
+	if (cfg->emmc_rx_strobe_cntl != 0)
+		silconfig->EmmcRxStrobeCntl = cfg->emmc_rx_strobe_cntl;
+	if (cfg->emmc_rx_cmd_data_cntl2 != 0)
+		silconfig->EmmcRxCmdDataCntl2 = cfg->emmc_rx_cmd_data_cntl2;
+
+	silconfig->LPSS_S0ixEnable = cfg->lpss_s0ix_enable;
+
+	/* Disable monitor mwait since it is broken due to a hardware bug without a fix */
+	silconfig->MonitorMwaitEnable = 0;
+
+	/* Disable setting of EISS bit in FSP. */
+	silconfig->SpiEiss = 0;
+
+	/* Disable FSP from locking access to the RTC NVRAM */
+	silconfig->RtcLock = 0;
+
+	/* Enable Audio clk gate and power gate */
+	silconfig->HDAudioClkGate = cfg->hdaudio_clk_gate_enable;
+	silconfig->HDAudioPwrGate = cfg->hdaudio_pwr_gate_enable;
+	/* Bios config lockdown Audio clk and power gate */
+	silconfig->BiosCfgLockDown = cfg->hdaudio_bios_config_lockdown;
+
+}
+
+struct chip_operations soc_intel_glk_ops = {
+	CHIP_NAME("Intel GLK SOC")
+	.enable_dev = &enable_dev,
+	.init = &soc_init,
+	.final = &soc_final
+};
+
+void platform_fsp_notify_status(enum fsp_notify_phase phase)
+{
+	/* Hide the P2SB device to align with previous behavior. */
+	if (phase == END_OF_FIRMWARE)
+		p2sb_hide();
+}
+
+/*
+ * spi_init() needs to run unconditionally on every boot (including resume) to
+ * allow write protect to be disabled for eventlog and nvram updates. This needs
+ * to be done as early as possible in ramstage. Thus, add a callback for entry
+ * into BS_PRE_DEVICE.
+ */
+static void spi_init_cb(void *unused)
+{
+	spi_init();
+}
+
+BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, spi_init_cb, NULL);
diff --git a/src/soc/intel/glk/chip.h b/src/soc/intel/glk/chip.h
new file mode 100644
index 0000000..40247db
--- /dev/null
+++ b/src/soc/intel/glk/chip.h
@@ -0,0 +1,124 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_CHIP_H_
+#define _SOC_GLK_CHIP_H_
+
+#include <soc/gpe.h>
+#include <soc/gpio_defs.h>
+#include <soc/gpio.h>
+#include <soc/intel/common/lpss_i2c.h>
+#include <device/i2c.h>
+#include <soc/pm.h>
+
+#define CLKREQ_DISABLED		0xf
+#define GLK_I2C_DEV_MAX		8
+
+struct glk_i2c_config {
+	/* Bus should be enabled prior to ramstage with temporary base */
+	int early_init;
+	/* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */
+	enum i2c_speed speed;
+	/* Specific bus speed configuration */
+	struct lpss_i2c_speed_config speed_config[LPSS_I2C_SPEED_CONFIG_COUNT];
+};
+
+/* Serial IRQ control. SERIRQ_QUIET is the default (0). */
+enum serirq_mode {
+	SERIRQ_QUIET,
+	SERIRQ_CONTINUOUS,
+	SERIRQ_OFF,
+};
+
+struct soc_intel_glk_config {
+	/*
+	 * Mapping from PCIe root port to CLKREQ input on the SOC. The SOC has
+	 * four CLKREQ inputs, but six root ports. Root ports without an
+	 * associated CLKREQ signal must be marked with "CLKREQ_DISABLED"
+	 */
+	uint8_t pcie_rp0_clkreq_pin;
+	uint8_t pcie_rp1_clkreq_pin;
+	uint8_t pcie_rp2_clkreq_pin;
+	uint8_t pcie_rp3_clkreq_pin;
+	uint8_t pcie_rp4_clkreq_pin;
+	uint8_t pcie_rp5_clkreq_pin;
+
+	/* [14:8] DDR mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR mode Number of dealy elements.Each = 125pSec.
+	 */
+	uint32_t emmc_tx_cmd_cntl;
+
+	/* [14:8] HS400 mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR104/HS200 mode Number of dealy elements.Each = 125pSec.
+	 */
+	uint32_t emmc_tx_data_cntl1;
+
+	/* [30:24] SDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR12/Compatibility mode Number of dealy elements.Each = 125pSec.
+	 */
+	uint32_t emmc_tx_data_cntl2;
+
+	/* [30:24] SDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [22:16] DDR50 mode Number of dealy elements.Each = 125pSec.
+	 * [14:8] SDR25/HS50 mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR12/Compatibility mode Number of dealy elements.Each = 125pSec.
+	 */
+	uint32_t emmc_rx_cmd_data_cntl1;
+
+	/* [14:8] HS400 mode 1 Number of dealy elements.Each = 125pSec.
+	 * [6:0] HS400 mode 2 Number of dealy elements.Each = 125pSec.
+	 */
+	uint32_t emmc_rx_strobe_cntl;
+
+	/* [13:8] Auto Tuning mode Number of dealy elements.Each = 125pSec.
+	 * [6:0] SDR104/HS200 Number of dealy elements.Each = 125pSec.
+	 */
+	uint32_t emmc_rx_cmd_data_cntl2;
+
+	/* Configure serial IRQ (SERIRQ) line. */
+	enum serirq_mode serirq_mode;
+
+	/* I2C bus configuration */
+	struct glk_i2c_config i2c[GLK_I2C_DEV_MAX];
+
+	uint8_t gpe0_dw1; /* GPE0_63_32 STS/EN */
+	uint8_t gpe0_dw2; /* GPE0_95_64 STS/EN */
+	uint8_t gpe0_dw3; /* GPE0_127_96 STS/EN */
+
+	/* Configure LPSS S0ix Enable */
+	uint8_t lpss_s0ix_enable;
+
+	/* Enable DPTF support */
+	int dptf_enable;
+
+	/* Configure Audio clk gate and power gate
+	 * IOSF-SB port ID 92 offset 0x530 [5] and [3]
+	 */
+	uint8_t hdaudio_clk_gate_enable;
+	uint8_t hdaudio_pwr_gate_enable;
+	uint8_t hdaudio_bios_config_lockdown;
+
+	/* SLP S3 minimum assertion width. */
+	int slp_s3_assertion_width_usecs;
+
+	/* GPIO pin for PERST_0 */
+	uint16_t prt0_gpio;
+};
+
+#endif	/* _SOC_GLK_CHIP_H_ */
diff --git a/src/soc/intel/glk/cpu.c b/src/soc/intel/glk/cpu.c
new file mode 100644
index 0000000..7d74c2b
--- /dev/null
+++ b/src/soc/intel/glk/cpu.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/mp.h>
+#include <cpu/intel/microcode.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <soc/cpu.h>
+#include <soc/smm.h>
+
+static struct device_operations cpu_dev_ops = {
+	.init = DEVICE_NOOP,
+};
+
+static struct cpu_device_id cpu_table[] = {
+	{ X86_VENDOR_INTEL, CPUID_GLK_A0 },
+	{ 0, 0 },
+};
+
+static const struct cpu_driver driver __cpu_driver = {
+	.ops      = &cpu_dev_ops,
+	.id_table = cpu_table,
+};
+
+/*
+ * MP and SMM loading initialization.
+ */
+struct smm_relocation_attrs {
+	uint32_t smbase;
+	uint32_t smrr_base;
+	uint32_t smrr_mask;
+};
+
+static struct smm_relocation_attrs relo_attrs;
+
+static void read_cpu_topology(unsigned int *num_phys, unsigned int *num_virt)
+{
+	msr_t msr;
+	msr = rdmsr(MSR_CORE_THREAD_COUNT);
+	*num_virt = (msr.lo >> 0) & 0xffff;
+	*num_phys = (msr.lo >> 16) & 0xffff;
+}
+
+/*
+ * Do essential initialization tasks before APs can be fired up
+ *
+ * 1. Prevent race condition in MTRR solution. Enable MTRRs on the BSP. This
+ * creates the MTRR solution that the APs will use. Otherwise APs will try to
+ * apply the incomplete solution as the BSP is calculating it.
+ */
+static void pre_mp_init(void)
+{
+	x86_setup_mtrrs_with_detect();
+	x86_mtrr_check();
+}
+
+/* Find CPU topology */
+static int get_cpu_count(void)
+{
+	unsigned int num_virt_cores, num_phys_cores;
+
+	read_cpu_topology(&num_phys_cores, &num_virt_cores);
+
+	printk(BIOS_DEBUG, "Detected %u core, %u thread CPU.\n",
+	       num_phys_cores, num_virt_cores);
+
+	return num_virt_cores;
+}
+
+static void get_microcode_info(const void **microcode, int *parallel)
+{
+	*microcode = intel_microcode_find();
+	*parallel = 1;
+}
+
+static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize,
+				size_t *smm_save_state_size)
+{
+	void *smm_base;
+	size_t smm_size;
+
+	/* All range registers are aligned to 4KiB */
+	const uint32_t rmask = ~((1 << 12) - 1);
+
+	/* Initialize global tracking state. */
+	smm_region(&smm_base, &smm_size);
+	relo_attrs.smbase = (uint32_t)smm_base;
+	relo_attrs.smrr_base = relo_attrs.smbase | MTRR_TYPE_WRBACK;
+	relo_attrs.smrr_mask = ~(smm_size - 1) & rmask;
+	relo_attrs.smrr_mask |= MTRR_PHYS_MASK_VALID;
+
+	*perm_smbase = relo_attrs.smbase;
+	*perm_smsize = smm_size - CONFIG_SMM_RESERVED_SIZE;
+	*smm_save_state_size = sizeof(em64t100_smm_state_save_area_t);
+}
+
+static void relocation_handler(int cpu, uintptr_t curr_smbase,
+				uintptr_t staggered_smbase)
+{
+	msr_t smrr;
+	em64t100_smm_state_save_area_t *smm_state;
+	/* Set up SMRR. */
+	smrr.lo = relo_attrs.smrr_base;
+	smrr.hi = 0;
+	wrmsr(SMRR_PHYS_BASE, smrr);
+	smrr.lo = relo_attrs.smrr_mask;
+	smrr.hi = 0;
+	wrmsr(SMRR_PHYS_MASK, smrr);
+	smm_state = (void *)(SMM_EM64T100_SAVE_STATE_OFFSET + curr_smbase);
+	smm_state->smbase = staggered_smbase;
+}
+/*
+ * CPU initialization recipe
+ *
+ * Note that no microcode update is passed to the init function. CSE updates
+ * the microcode on all cores before releasing them from reset. That means that
+ * the BSP and all APs will come up with the same microcode revision.
+ */
+static const struct mp_ops mp_ops = {
+	.pre_mp_init = pre_mp_init,
+	.get_cpu_count = get_cpu_count,
+	.get_smm_info = get_smm_info,
+	.get_microcode_info = get_microcode_info,
+	.pre_mp_smm_init = southbridge_smm_clear_state,
+	.relocation_handler = relocation_handler,
+	.post_mp_init = southbridge_smm_enable_smi,
+};
+
+void glk_init_cpus(device_t dev)
+{
+	/* Clear for take-off */
+	if (mp_init_with_smm(dev->link_list, &mp_ops) < 0)
+		printk(BIOS_ERR, "MP initialization failure.\n");
+}
diff --git a/src/soc/intel/glk/dsp.c b/src/soc/intel/glk/dsp.c
new file mode 100644
index 0000000..a2d21aa
--- /dev/null
+++ b/src/soc/intel/glk/dsp.c
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/pci_ids.h>
+
+static struct device_operations dsp_dev_ops = {
+	.read_resources         = &pci_dev_read_resources,
+	.set_resources          = &pci_dev_set_resources,
+	.enable_resources       = &pci_dev_enable_resources,
+	.scan_bus               = &scan_static_bus,
+};
+
+static const struct pci_driver apollolake_dsp __pci_driver = {
+	.ops    = &dsp_dev_ops,
+	.vendor = PCI_VENDOR_ID_INTEL,
+	.device = PCI_DEVICE_ID_APOLLOLAKE_AUDIO
+};
diff --git a/src/soc/intel/glk/elog.c b/src/soc/intel/glk/elog.c
new file mode 100644
index 0000000..0dd44c2
--- /dev/null
+++ b/src/soc/intel/glk/elog.c
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Google Inc.
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <bootstate.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <elog.h>
+#include <soc/pm.h>
+#include <soc/pci_devs.h>
+#include <stdint.h>
+
+static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
+{
+	int i;
+
+	gpe0_sts &= gpe0_en;
+
+	for (i = 0; i <= 31; i++) {
+		if (gpe0_sts & (1 << i))
+			elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i + start);
+	}
+}
+
+static void pch_log_wake_source(struct chipset_power_state *ps)
+{
+	/* Power Button */
+	if (ps->pm1_sts & PWRBTN_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
+
+	/* RTC */
+	if (ps->pm1_sts & RTC_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
+
+	/* PCI Express (TODO: determine wake device) */
+	if (ps->pm1_sts & PCIEXPWAK_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
+
+	/* PME */
+	if(ps->gpe0_sts[GPE0_A] & CSE_PME_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
+
+	/* SMBUS Wake */
+	if (ps->gpe0_sts[GPE0_A] & SMB_WAK_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
+
+        /* ACPI Wake Event - Always Log prev_sleep_state*/
+        elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
+
+	/* Log GPIO events in set A-D */
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE0_A], ps->gpe0_en[GPE0_A], 0);
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE0_B], ps->gpe0_en[GPE0_B], 32);
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE0_C], ps->gpe0_en[GPE0_C], 64);
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE0_D], ps->gpe0_en[GPE0_D], 96);
+}
+
+static void pch_log_power_and_resets(struct chipset_power_state *ps)
+{
+	/* RTC Reset */
+	if (ps->gen_pmcon1 & RPS)
+		elog_add_event(ELOG_TYPE_RTC_RESET);
+
+	/* System Reset */
+	if (ps->gen_pmcon1 & SRS)
+		elog_add_event(ELOG_TYPE_SYSTEM_RESET);
+
+	/* TCO Timeout */
+	if (ps->prev_sleep_state != ACPI_S3 &&
+	    ps->tco_sts & TCO_TIMEOUT)
+		elog_add_event(ELOG_TYPE_TCO_RESET);
+
+	/* Power Button Override */
+	if (ps->pm1_sts & PRBTNOR_STS)
+		elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
+
+}
+
+void pch_log_state(void)
+{
+	struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+
+	if (ps == NULL) {
+		printk(BIOS_ERR,
+			"Not logging power state information. "
+			"Power state not found in cbmem.\n");
+		return;
+	}
+
+	/* Power and Reset */
+	pch_log_power_and_resets(ps);
+
+	/* Wake Sources */
+	if (ps->prev_sleep_state > ACPI_S0)
+		pch_log_wake_source(ps);
+}
diff --git a/src/soc/intel/glk/exit_car.S b/src/soc/intel/glk/exit_car.S
new file mode 100644
index 0000000..e21aa29
--- /dev/null
+++ b/src/soc/intel/glk/exit_car.S
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cr.h>
+#include <soc/cpu.h>
+
+.text
+.global chipset_teardown_car
+chipset_teardown_car:
+	/*
+	 * Retrieve return address from stack as it will get trashed below if
+	 * execution is utilizing the cache-as-ram stack.
+	 */
+	pop	%ebx
+
+	/* Disable MTRRs. */
+	mov	$(MTRR_DEF_TYPE_MSR), %ecx
+	rdmsr
+	and	$(~(MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN)), %eax
+	wrmsr
+
+#if IS_ENABLED(CONFIG_CAR_CQOS)
+	/* Go back to all-evicting mode, set both masks to all-1s */
+	mov	$MSR_L2_QOS_MASK(0), %ecx
+	rdmsr
+	mov	$~0, %al
+	wrmsr
+
+	mov	$MSR_L2_QOS_MASK(1), %ecx
+	rdmsr
+	mov	$~0, %al
+	wrmsr
+
+	/* Reset CLOS selector to 0 */
+	mov	$MSR_IA32_PQR_ASSOC, %ecx
+	rdmsr
+	and	$~IA32_PQR_ASSOC_MASK, %edx
+	wrmsr
+#endif
+	/* invalidate cache contents. */
+	invd
+
+#if IS_ENABLED(CONFIG_CAR_NEM)
+	/* Knock down bit 1 then bit 0 of NEM control not combining steps. */
+	mov	$(MSR_EVICT_CTL), %ecx
+	rdmsr
+	and	$(~(1 << 1)), %eax
+	wrmsr
+	and	$(~(1 << 0)), %eax
+	wrmsr
+#endif
+
+	/* Return to caller. */
+	jmp	*%ebx
diff --git a/src/soc/intel/glk/gpio.c b/src/soc/intel/glk/gpio.c
new file mode 100644
index 0000000..4731d56
--- /dev/null
+++ b/src/soc/intel/glk/gpio.c
@@ -0,0 +1,418 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <assert.h>
+#include <gpio.h>
+#include <soc/gpio.h>
+#include <soc/iosf.h>
+#include <soc/itss.h>
+#include <soc/pm.h>
+
+/* This list must be in order, from highest pad numbers, to lowest pad numbers*/
+static const struct pad_community {
+	uint16_t first_pad;
+	uint8_t port;
+	uint8_t num_gpi_regs;
+	uint8_t gpi_offset;
+	const char *grp_name;
+} gpio_communities[] = {
+	{
+		.port = GPIO_SW,
+		.first_pad = SW_OFFSET,
+		.num_gpi_regs = NUM_SW_GPI_REGS,
+		.gpi_offset = 0,
+		.grp_name = "GPIO_GPE_SW",
+	}, {
+		.port = GPIO_W,
+		.first_pad = W_OFFSET,
+		.num_gpi_regs = NUM_W_GPI_REGS,
+		.gpi_offset = NUM_SW_GPI_REGS,
+		.grp_name = "GPIO_GPE_W",
+	}, {
+		.port = GPIO_NW,
+		.first_pad = NW_OFFSET,
+		.num_gpi_regs = NUM_NW_GPI_REGS,
+		.gpi_offset = NUM_W_GPI_REGS + NUM_SW_GPI_REGS,
+		.grp_name = "GPIO_GPE_NW",
+	}, {
+		.port = GPIO_N,
+		.first_pad = N_OFFSET,
+		.num_gpi_regs = NUM_N_GPI_REGS,
+		.gpi_offset = NUM_NW_GPI_REGS+ NUM_W_GPI_REGS + NUM_SW_GPI_REGS,
+		.grp_name = "GPIO_GPE_N",
+	}
+};
+
+static const struct pad_community *gpio_get_community(uint16_t pad)
+{
+	const struct pad_community *map = gpio_communities;
+
+	assert(pad < TOTAL_PADS);
+
+	while (map->first_pad > pad)
+		map++;
+
+	return map;
+}
+
+static void gpio_configure_itss(const struct pad_config *cfg,
+				uint16_t port, uint16_t pad_cfg_offset)
+{
+	/* No ITSS configuration in SMM. */
+	if (ENV_SMM)
+		return;
+
+	int irq;
+
+	/* Set up ITSS polarity if pad is routed to APIC.
+	 *
+	 * The ITSS takes only active high interrupt signals. Therefore,
+	 * if the pad configuration indicates an inversion assume the
+	 * intent is for the ITSS polarity. Before forwarding on the
+	 * request to the APIC there's an inversion setting for how the
+	 * signal is forwarded to the APIC. Honor the inversion setting
+	 * in the GPIO pad configuration so that a hardware active low
+	 * signal looks that way to the APIC (double inversion).
+	 */
+	if (!(cfg->config0 & PAD_CFG0_ROUTE_IOAPIC))
+		return;
+
+	irq = iosf_read(port, pad_cfg_offset + sizeof(uint32_t));
+	irq &= PAD_CFG1_IRQ_MASK;
+	if (!irq) {
+		printk(BIOS_ERR, "GPIO %u doesn't support APIC routing,\n",
+			cfg->pad);
+		return;
+	}
+
+	itss_set_irq_polarity(irq, !!(cfg->config0 & PAD_CFG0_RX_POL_INVERT));
+}
+
+static void gpio_configure_owner(const struct pad_config *cfg,
+				 uint16_t port, int pin)
+{
+	uint32_t val;
+	uint16_t hostsw_reg;
+
+	/* The 4th bit in pad_config 1 (RO) is used to indicate if the pad
+	 * needs GPIO driver ownership.
+	 */
+	if (!(cfg->config1 & PAD_CFG1_GPIO_DRIVER))
+		return;
+
+	/* Based on the gpio pin number configure the corresponding bit in
+	 * HOSTSW_OWN register. Value of 0x1 indicates GPIO Driver onwership.
+	 */
+	hostsw_reg = HOSTSW_OWN_REG_BASE + ((pin / 32) * sizeof(uint32_t));
+	val = iosf_read(port, hostsw_reg);
+	val |= 1 << (pin % 32);
+	iosf_write(port, hostsw_reg, val);
+}
+
+static void gpi_enable_smi(const struct pad_config *cfg, uint16_t port, int pin)
+{
+	uint32_t value;
+	uint16_t sts_reg;
+	uint16_t en_reg;
+	int group;
+
+	if (((cfg->config0) & PAD_CFG0_ROUTE_SMI) != PAD_CFG0_ROUTE_SMI)
+		return;
+
+	group = pin / GPIO_MAX_NUM_PER_GROUP;
+
+	sts_reg = GPI_SMI_STS_OFFSET(group);
+	value = iosf_read(port, sts_reg);
+	/* Write back 1 to reset the sts bits */
+	iosf_write(port, sts_reg, value);
+
+	/* Set enable bits */
+	en_reg = GPI_SMI_EN_OFFSET(group);
+	value = iosf_read(port, en_reg );
+	value |= 1 << (pin % GPIO_MAX_NUM_PER_GROUP);
+	iosf_write(port, en_reg , value);
+}
+
+void gpio_configure_pad(const struct pad_config *cfg)
+{
+	uint32_t dw1;
+	const struct pad_community *comm = gpio_get_community(cfg->pad);
+	uint16_t config_offset = PAD_CFG_OFFSET(cfg->pad - comm->first_pad);
+
+	/* Iostandby bits are tentatively stored in [3:0] bits (RO) of config1.
+	 * dw1 is used to extract the bits of Iostandby.
+	 * This is done to preserve config1 size as unit16 in gpio.h.
+	 */
+	dw1 = cfg->config1 & ~PAD_CFG1_IOSSTATE_MASK;
+	dw1 |= (cfg->config1 & PAD_CFG1_IOSSTATE_MASK) << PAD_CFG1_IOSSTATE_SHIFT;
+
+	iosf_write(comm->port, config_offset, cfg->config0);
+	iosf_write(comm->port, config_offset + sizeof(uint32_t), dw1);
+
+	gpio_configure_itss(cfg, comm->port, config_offset);
+	gpio_configure_owner(cfg, comm->port, cfg->pad - comm->first_pad);
+
+	gpi_enable_smi(cfg, comm->port, cfg->pad - comm->first_pad);
+}
+
+void gpio_configure_pads(const struct pad_config *cfg, size_t num_pads)
+{
+	uint32_t i;
+
+	for (i = 0; i < num_pads; i++)
+		gpio_configure_pad(cfg + i);
+}
+
+void * gpio_dwx_address(const uint16_t pad)
+{
+	/* Calculate Address of DW0 register for given GPIO
+	 * pad - GPIO number
+	 * returns - address of GPIO
+	 */
+	const struct pad_community *comm = gpio_get_community(pad);
+	return iosf_address(comm->port, PAD_CFG_OFFSET(pad - comm->first_pad));
+}
+
+void gpio_input_pulldown(gpio_t gpio)
+{
+	struct pad_config cfg = PAD_CFG_GPI(gpio, DN_20K, DEEP);
+	gpio_configure_pad(&cfg);
+}
+
+void gpio_input_pullup(gpio_t gpio)
+{
+	struct pad_config cfg = PAD_CFG_GPI(gpio, UP_20K, DEEP);
+	gpio_configure_pad(&cfg);
+}
+
+void gpio_input(gpio_t gpio)
+{
+	struct pad_config cfg = PAD_CFG_GPI(gpio, NONE, DEEP);
+	gpio_configure_pad(&cfg);
+}
+
+void gpio_output(gpio_t gpio, int value)
+{
+	struct pad_config cfg = PAD_CFG_GPO(gpio, value, DEEP);
+	gpio_configure_pad(&cfg);
+}
+
+int gpio_get(gpio_t gpio_num)
+{
+	uint32_t reg;
+	const struct pad_community *comm = gpio_get_community(gpio_num);
+	uint16_t config_offset = PAD_CFG_OFFSET(gpio_num - comm->first_pad);
+
+	reg = iosf_read(comm->port, config_offset);
+
+	return !!(reg & PAD_CFG0_RX_STATE);
+}
+
+void gpio_set(gpio_t gpio_num, int value)
+{
+	uint32_t reg;
+	const struct pad_community *comm = gpio_get_community(gpio_num);
+	uint16_t config_offset = PAD_CFG_OFFSET(gpio_num - comm->first_pad);
+
+	reg = iosf_read(comm->port, config_offset);
+	reg &= ~PAD_CFG0_TX_STATE;
+	reg |= !!value & PAD_CFG0_TX_STATE;
+	iosf_write(comm->port, config_offset, reg);
+}
+
+const char *gpio_acpi_path(gpio_t gpio_num)
+{
+	const struct pad_community *comm = gpio_get_community(gpio_num);
+
+	switch (comm->port) {
+	case GPIO_N:
+		return "\\_SB.GPO0";
+	case GPIO_NW:
+		return "\\_SB.GPO1";
+	case GPIO_W:
+		return "\\_SB.GPO2";
+	case GPIO_SW:
+		return "\\_SB.GPO3";
+	}
+
+	return NULL;
+}
+
+uint16_t gpio_acpi_pin(gpio_t gpio_num)
+{
+	const struct pad_community *comm = gpio_get_community(gpio_num);
+
+	switch (comm->port) {
+	case GPIO_N:
+		return PAD_N(gpio_num);
+	case GPIO_NW:
+		return PAD_NW(gpio_num);
+	case GPIO_W:
+		return PAD_W(gpio_num);
+	case GPIO_SW:
+		return PAD_SW(gpio_num);
+	}
+
+	return gpio_num;
+}
+
+static void print_gpi_status(const struct gpi_status *sts)
+{
+	int i;
+	int group;
+	int index = 0;
+	int bit_set;
+	int num_groups;
+	int abs_bit;
+	const struct pad_community *comm;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_communities); i++) {
+		comm = &gpio_communities[i];
+		num_groups = comm->num_gpi_regs;
+		index = comm->gpi_offset;
+		for (group = 0; group < num_groups; group++, index++) {
+			for (bit_set = 31; bit_set >= 0; bit_set--) {
+				if (!(sts->grp[index] & (1 << bit_set)))
+					continue;
+
+				abs_bit = bit_set;
+				abs_bit += group * GPIO_MAX_NUM_PER_GROUP;
+				printk(BIOS_DEBUG, "%s %d\n",comm->grp_name,
+								abs_bit);
+			}
+		}
+	}
+}
+
+void gpi_clear_get_smi_status(struct gpi_status *sts)
+{
+	int i;
+	int group;
+	int index = 0;
+	uint32_t sts_value;
+	uint32_t en_value;
+	int num_groups;
+	const struct pad_community *comm;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_communities); i++) {
+		comm = &gpio_communities[i];
+		num_groups = comm->num_gpi_regs;
+		index = comm->gpi_offset;
+		for (group = 0; group < num_groups; group++, index++) {
+			sts_value = iosf_read(gpio_communities[i].port,
+					GPI_SMI_STS_OFFSET(group));
+			en_value = iosf_read(gpio_communities[i].port,
+					GPI_SMI_EN_OFFSET(group));
+			sts->grp[index] = sts_value & en_value;
+			/* Clear the set status bits. */
+			iosf_write(gpio_communities[i].port,
+				GPI_SMI_STS_OFFSET(group), sts->grp[index]);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_DEBUG_SMI))
+		print_gpi_status(sts);
+
+}
+
+int gpi_status_get(const struct gpi_status *sts, gpio_t gpi)
+{
+	uint8_t sts_index;
+	const struct pad_community *comm = gpio_get_community(gpi);
+
+	/* Check if valid gpi */
+	if (comm == NULL)
+		return 0;
+
+	sts_index = comm->gpi_offset + ((gpi - comm->first_pad) /
+					GPIO_MAX_NUM_PER_GROUP);
+
+	return !!(sts->grp[sts_index] & (1 << (gpi % GPIO_MAX_NUM_PER_GROUP)));
+}
+
+/* Helper function to map PMC register groups to tier1 sci groups */
+static int pmc_gpe_route_to_gpio(int route)
+{
+	switch(route) {
+	case PMC_GPE_SW_31_0:
+		return GPIO_GPE_SW_31_0;
+	case PMC_GPE_SW_63_32:
+		return GPIO_GPE_SW_63_32;
+	case PMC_GPE_NW_31_0:
+		return GPIO_GPE_NW_31_0;
+	case PMC_GPE_NW_63_32:
+		return GPIO_GPE_NW_63_32;
+	case PMC_GPE_NW_95_64:
+		return GPIO_GPE_NW_95_64;
+	case PMC_GPE_N_31_0:
+		return GPIO_GPE_N_31_0;
+	case PMC_GPE_N_63_32:
+		return GPIO_GPE_N_63_32;
+	case PMC_GPE_W_31_0:
+		return GPIO_GPE_W_31_0;
+	default:
+		return -1;
+	}
+}
+
+void gpio_route_gpe(uint8_t gpe0b, uint8_t gpe0c, uint8_t gpe0d)
+{
+	int i;
+	uint32_t misccfg_mask;
+	uint32_t misccfg_value;
+	uint32_t value;
+	int ret;
+
+	/* Get the group here for community specific MISCCFG register.
+	 * If any of these returns -1 then there is some error in devicetree
+	 * where the group is probably hardcoded and does not comply with the
+	 * PMC group defines. So we return from here and MISCFG is set to
+	 * default.
+	 */
+	ret = pmc_gpe_route_to_gpio(gpe0b);
+	if (ret == -1)
+		return;
+	gpe0b = ret;
+
+	ret = pmc_gpe_route_to_gpio(gpe0c);
+	if (ret == -1)
+		return;
+	gpe0c = ret;
+
+	ret = pmc_gpe_route_to_gpio(gpe0d);
+	if (ret == -1)
+		return;
+	gpe0d = ret;
+
+	misccfg_value = gpe0b << MISCCFG_GPE0_DW0_SHIFT;
+	misccfg_value |= gpe0c << MISCCFG_GPE0_DW1_SHIFT;
+	misccfg_value |= gpe0d << MISCCFG_GPE0_DW2_SHIFT;
+
+	/* Program GPIO_MISCCFG */
+	misccfg_mask = ~(MISCCFG_GPE0_DW2_MASK |
+			MISCCFG_GPE0_DW1_MASK |
+			MISCCFG_GPE0_DW0_MASK);
+
+	for (i = 0; i < ARRAY_SIZE(gpio_communities); i++) {
+		const struct pad_community *comm = &gpio_communities[i];
+
+		value = iosf_read(comm->port, GPIO_MISCCFG);
+		value &= misccfg_mask;
+		value |= misccfg_value;
+		iosf_write(comm->port, GPIO_MISCCFG, value);
+	}
+}
diff --git a/src/soc/intel/glk/graphics.c b/src/soc/intel/glk/graphics.c
new file mode 100644
index 0000000..9b4dbc9
--- /dev/null
+++ b/src/soc/intel/glk/graphics.c
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <console/console.h>
+#include <fsp/util.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/pci_devs.h>
+#include <soc/pci_ids.h>
+#include <soc/intel/common/opregion.h>
+
+uintptr_t fsp_soc_get_igd_bar(void)
+{
+	return find_resource(IGD_DEV, PCI_BASE_ADDRESS_2)->base;
+}
+
+static void igd_set_resources(struct device *dev)
+{
+	pci_dev_set_resources(dev);
+}
+
+static unsigned long igd_write_opregion(device_t dev, unsigned long current,
+				struct acpi_rsdp *rsdp)
+{
+	igd_opregion_t *opregion;
+	uint16_t reg16;
+
+	printk(BIOS_DEBUG, "ACPI:    * IGD OpRegion\n");
+	opregion = (igd_opregion_t *)current;
+
+	if (!init_igd_opregion(opregion))
+		return current;
+
+	current += sizeof(igd_opregion_t);
+
+	/* TODO Initialize Mailbox 3 */
+	opregion->mailbox3.bclp = IGD_BACKLIGHT_BRIGHTNESS;
+	opregion->mailbox3.pfit = IGD_FIELD_VALID | IGD_PFIT_STRETCH;
+	opregion->mailbox3.pcft = 0; /* should be (IMON << 1) & 0x3e */
+	opregion->mailbox3.cblv = IGD_FIELD_VALID | IGD_INITIAL_BRIGHTNESS;
+	opregion->mailbox3.bclm[0] = IGD_WORD_FIELD_VALID + 0x0000;
+	opregion->mailbox3.bclm[1] = IGD_WORD_FIELD_VALID + 0x0a19;
+	opregion->mailbox3.bclm[2] = IGD_WORD_FIELD_VALID + 0x1433;
+	opregion->mailbox3.bclm[3] = IGD_WORD_FIELD_VALID + 0x1e4c;
+	opregion->mailbox3.bclm[4] = IGD_WORD_FIELD_VALID + 0x2866;
+	opregion->mailbox3.bclm[5] = IGD_WORD_FIELD_VALID + 0x327f;
+	opregion->mailbox3.bclm[6] = IGD_WORD_FIELD_VALID + 0x3c99;
+	opregion->mailbox3.bclm[7] = IGD_WORD_FIELD_VALID + 0x46b2;
+	opregion->mailbox3.bclm[8] = IGD_WORD_FIELD_VALID + 0x50cc;
+	opregion->mailbox3.bclm[9] = IGD_WORD_FIELD_VALID + 0x5ae5;
+	opregion->mailbox3.bclm[10] = IGD_WORD_FIELD_VALID + 0x64ff;
+
+	/*
+	* TODO This needs to happen in S3 resume, too.
+	* Maybe it should move to the finalize handler.
+	*/
+
+	pci_write_config32(dev, ASLS, (uintptr_t)opregion);
+	reg16 = pci_read_config16(dev, SWSCI);
+	reg16 &= ~(1 << 0);
+	reg16 |= (1 << 15);
+	pci_write_config16(dev, SWSCI, reg16);
+
+	return acpi_align_current(current);
+}
+
+static const struct device_operations igd_ops = {
+	.read_resources   = pci_dev_read_resources,
+	.set_resources    = igd_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = pci_dev_init,
+	.write_acpi_tables = igd_write_opregion,
+	.enable           = DEVICE_NOOP
+};
+
+static const unsigned short pci_device_ids[] = {
+	PCI_DEVICE_ID_APOLLOLAKE_IGD_HD_505,
+	PCI_DEVICE_ID_APOLLOLAKE_IGD_HD_500,
+	0,
+};
+
+static const struct pci_driver integrated_graphics_driver __pci_driver = {
+	.ops	= &igd_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.devices= pci_device_ids,
+};
diff --git a/src/soc/intel/glk/heci.c b/src/soc/intel/glk/heci.c
new file mode 100644
index 0000000..4685895
--- /dev/null
+++ b/src/soc/intel/glk/heci.c
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <device/pci_ops.h>
+#include <soc/heci.h>
+#include <soc/pci_devs.h>
+
+uint32_t heci_fw_sts(void)
+{
+	return pci_read_config32(CSE_DEV, REG_SEC_FW_STS0);
+}
+
+bool heci_cse_normal(void)
+{
+	return ((heci_fw_sts() & MASK_SEC_STATUS) == SEC_STATE_NORMAL);
+}
+
+bool heci_cse_done(void)
+{
+	return (!!(heci_fw_sts() & MASK_SEC_FIRMWARE_COMPLETE));
+}
diff --git a/src/soc/intel/glk/i2c.c b/src/soc/intel/glk/i2c.c
new file mode 100644
index 0000000..4080987
--- /dev/null
+++ b/src/soc/intel/glk/i2c.c
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi_device.h>
+#include <arch/acpigen.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <soc/i2c.h>
+#include <soc/intel/common/lpss_i2c.h>
+#include <soc/pci_devs.h>
+#include <soc/pci_ids.h>
+#include "chip.h"
+
+uintptr_t lpss_i2c_base_address(unsigned bus)
+{
+	unsigned devfn;
+	struct device *dev;
+	struct resource *res;
+
+	/* bus -> devfn */
+	devfn = i2c_bus_to_devfn(bus);
+	if (devfn >= 0) {
+		/* devfn -> dev */
+		dev = dev_find_slot(0, devfn);
+		if (dev) {
+			/* dev -> bar0 */
+			res = find_resource(dev, PCI_BASE_ADDRESS_0);
+			if (res)
+				return res->base;
+		}
+	}
+
+	return (uintptr_t)NULL;
+}
+
+static int i2c_dev_to_bus(struct device *dev)
+{
+	return i2c_devfn_to_bus(dev->path.pci.devfn);
+}
+
+/*
+ * The device should already be enabled and out of reset,
+ * either from early init in coreboot or FSP-S.
+ */
+static void i2c_dev_init(struct device *dev)
+{
+	struct soc_intel_glk_config *config = dev->chip_info;
+	const struct lpss_i2c_speed_config *sptr;
+	enum i2c_speed speed;
+	int i, bus = i2c_dev_to_bus(dev);
+
+	if (!config || bus < 0)
+		return;
+
+	speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
+	lpss_i2c_init(bus, speed);
+
+	/* Apply custom speed config if it has been set by the board */
+	for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) {
+		sptr = &config->i2c[bus].speed_config[i];
+		if (sptr->speed == speed) {
+			lpss_i2c_set_speed_config(bus, sptr);
+			break;
+		}
+	}
+}
+
+static void i2c_fill_ssdt(struct device *dev)
+{
+	struct soc_intel_glk_config *config = dev->chip_info;
+	int bus = i2c_dev_to_bus(dev);
+
+	if (!config || bus < 0)
+		return;
+
+	acpigen_write_scope(acpi_device_path(dev));
+	lpss_i2c_acpi_fill_ssdt(config->i2c[bus].speed_config);
+	acpigen_pop_len();
+}
+
+static struct i2c_bus_operations i2c_bus_ops = {
+	.dev_to_bus			= &i2c_dev_to_bus,
+};
+
+static struct device_operations i2c_dev_ops = {
+	.read_resources			= &pci_dev_read_resources,
+	.set_resources			= &pci_dev_set_resources,
+	.enable_resources		= &pci_dev_enable_resources,
+	.scan_bus			= &scan_smbus,
+	.ops_i2c_bus			= &i2c_bus_ops,
+	.init				= &i2c_dev_init,
+	.acpi_fill_ssdt_generator	= &i2c_fill_ssdt,
+};
+
+static const unsigned short pci_device_ids[] = {
+	PCI_DEVICE_ID_APOLLOLAKE_I2C0,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C1,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C2,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C3,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C4,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C5,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C6,
+	PCI_DEVICE_ID_APOLLOLAKE_I2C7,
+	0,
+};
+
+static const struct pci_driver pch_i2c __pci_driver = {
+	.ops	 = &i2c_dev_ops,
+	.vendor	 = PCI_VENDOR_ID_INTEL,
+	.devices = pci_device_ids,
+};
diff --git a/src/soc/intel/glk/i2c_early.c b/src/soc/intel/glk/i2c_early.c
new file mode 100644
index 0000000..dbd10e5
--- /dev/null
+++ b/src/soc/intel/glk/i2c_early.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <device/pci_def.h>
+#include <soc/intel/common/lpss_i2c.h>
+#include <soc/i2c.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include "chip.h"
+
+static int i2c_early_init_bus(unsigned bus)
+{
+	ROMSTAGE_CONST struct soc_intel_glk_config *config;
+	ROMSTAGE_CONST struct device *tree_dev;
+	const struct lpss_i2c_speed_config *sptr;
+	enum i2c_speed speed;
+	pci_devfn_t dev;
+	unsigned devfn;
+	uintptr_t base;
+	uint32_t value;
+	void *reg;
+
+	/* Find the PCI device for this bus controller */
+	devfn = i2c_bus_to_devfn(bus);
+	if (devfn < 0) {
+		printk(BIOS_ERR, "I2C%u device not found\n", bus);
+		return -1;
+	}
+
+	/* Look up the controller device in the devicetree */
+	dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
+	tree_dev = dev_find_slot(0, devfn);
+	if (!tree_dev || !tree_dev->enabled) {
+		printk(BIOS_ERR, "I2C%u device not enabled\n", bus);
+		return -1;
+	}
+
+	/* Skip if not enabled for early init */
+	config = tree_dev->chip_info;
+	if (!config || !config->i2c[bus].early_init) {
+		printk(BIOS_ERR, "I2C%u not enabled for early init\n", bus);
+		return -1;
+	}
+
+	/* Prepare early base address for access before memory */
+	base = PRERAM_I2C_BASE_ADDRESS(bus);
+	pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
+	pci_write_config32(dev, PCI_COMMAND,
+			   PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+	/* Take device out of reset */
+	reg = (void *)(base + I2C_LPSS_REG_RESET);
+	value = read32(reg);
+	value |= I2C_LPSS_RESET_RELEASE_HC;
+	write32(reg, value);
+
+	/* Initialize the controller */
+	speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
+	if (lpss_i2c_init(bus, speed) < 0) {
+		printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
+		return -1;
+	}
+
+	/* Apply custom speed config if it has been set by the board */
+	for (value = 0; value < LPSS_I2C_SPEED_CONFIG_COUNT; value++) {
+		sptr = &config->i2c[bus].speed_config[value];
+		if (sptr->speed == speed) {
+			lpss_i2c_set_speed_config(bus, sptr);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+uintptr_t lpss_i2c_base_address(unsigned bus)
+{
+	unsigned devfn;
+	pci_devfn_t dev;
+	uintptr_t base;
+
+	/* Find device+function for this controller */
+	devfn = i2c_bus_to_devfn(bus);
+	if (devfn < 0)
+		return (uintptr_t)NULL;
+
+	/* Form a PCI address for this device */
+	dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+	/* Read the first base address for this device */
+	base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
+
+	/* Attempt to initialize bus if base is not set yet */
+	if (!base && !i2c_early_init_bus(bus))
+		base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
+				  16);
+
+	return base;
+}
diff --git a/src/soc/intel/glk/include/FspUpd.h b/src/soc/intel/glk/include/FspUpd.h
new file mode 100644
index 0000000..a7114ce
--- /dev/null
+++ b/src/soc/intel/glk/include/FspUpd.h
@@ -0,0 +1,48 @@
+/** @file
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+  be used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+  THE POSSIBILITY OF SUCH DAMAGE.
+
+  This file is automatically generated. Please do NOT modify !!!
+
+**/
+
+#ifndef __FSPUPD_H__
+#define __FSPUPD_H__
+
+#include <FspEas.h>
+
+#pragma pack(push, 1)
+
+#define FSPT_UPD_SIGNATURE               0x545F4450554C5041        /* 'APLUPD_T' */
+
+#define FSPM_UPD_SIGNATURE               0x4D5F4450554C5041        /* 'APLUPD_M' */
+
+#define FSPS_UPD_SIGNATURE               0x535F4450554C5041        /* 'APLUPD_S' */
+
+#pragma pack(pop)
+
+#endif
diff --git a/src/soc/intel/glk/include/soc/acpi.h b/src/soc/intel/glk/include/soc/acpi.h
new file mode 100644
index 0000000..3cbb380
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/acpi.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_ACPI_H_
+#define _SOC_GLK_ACPI_H_
+
+#include <arch/acpi.h>
+
+unsigned long southbridge_write_acpi_tables(device_t device,
+		unsigned long current, struct acpi_rsdp *rsdp);
+
+void southbridge_inject_dsdt(device_t device);
+
+#endif	/* _SOC_GLK_ACPI_H_ */
diff --git a/src/soc/intel/glk/include/soc/cpu.h b/src/soc/intel/glk/include/soc/cpu.h
new file mode 100644
index 0000000..f0a827e
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/cpu.h
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_CPU_H_
+#define _SOC_GLK_CPU_H_
+
+#ifndef __ASSEMBLER__
+#include <cpu/x86/msr.h>
+#include <device/device.h>
+
+void glk_init_cpus(struct device *dev);
+#endif
+
+#define CPUID_GLK_A0	0x706a0
+
+#define MSR_PLATFORM_INFO	0xce
+#define MSR_POWER_MISC		0x120
+#define MSR_CORE_THREAD_COUNT	0x35
+#define MSR_EVICT_CTL		0x2e0
+#define MSR_EMULATE_PM_TMR	0x121
+#define   EMULATE_PM_TMR_EN	(1 << 16)
+#define MSR_PREFETCH_CTL	0x1a4
+#define   PREFETCH_L1_DISABLE	(1 << 0)
+#define   PREFETCH_L2_DISABLE	(1 << 2)
+
+#define MSR_PKG_POWER_SKU_UNIT	0x606
+
+#define MSR_L2_QOS_MASK(reg)		(0xd10 + reg)
+#define MSR_IA32_PQR_ASSOC		0xc8f
+/* MSR bits 33:32 encode slot number 0-3 */
+#define   IA32_PQR_ASSOC_MASK		(1 << 0 | 1 << 1)
+/* 16 way cache, 8 bits per QOS, 64 byte cache line, 1024 sets */
+#define CACHE_WAYS			16
+#define CACHE_BITS_PER_MASK		8
+#define CACHE_LINE_SIZE			64
+#define CACHE_SETS			1024
+/*
+ * Each bit in QOS mask controls this many bytes. This is calculated as:
+ * (CACHE_WAYS / CACHE_BITS_PER_MASK) * CACHE_LINE_SIZE * CACHE_SETS
+ */
+#define CACHE_QOS_SIZE_PER_BIT		(128 * KiB)
+#define L2_CACHE_SIZE			0x100000
+
+#define BASE_CLOCK_MHZ		100
+
+/* Common Timer Copy (CTC) frequency - 19.2MHz. */
+#define CTC_FREQ 19200000
+
+#endif /* _SOC_GLK_CPU_H_ */
diff --git a/src/soc/intel/glk/include/soc/gpe.h b/src/soc/intel/glk/include/soc/gpe.h
new file mode 100644
index 0000000..5482ed3
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/gpe.h
@@ -0,0 +1,139 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GPE_H_
+#define _SOC_GPE_H_
+
+/* bit position in GPE0a_STS register */
+#define GPE0A_PCIE_SCI_STS		0
+#define GPE0A_SWGPE_STS			2
+#define GPE0A_PCIE_WAKE0_STS		3
+#define GPE0A_PUNIT_SCI_STS		4
+#define GPE0A_PCIE_WAKE1_STS		6
+#define GPE0A_PCIE_WAKE2_STS		7
+#define GPE0A_PCIE_WAKE3_STS		8
+#define GPE0A_PCIE_GPE_STS		9
+#define GPE0A_BATLOW_STS		10
+#define GPE0A_CSE_PME_STS		11
+#define GPE0A_XDCI_PME_STS		12
+#define GPE0A_XHCI_PME_STS		13
+#define GPE0A_AVS_PME_STS		14
+#define GPE0A_GPIO_TIER1_SCI_STS	15
+#define GPE0A_SMB_WAK_STS		16
+#define GPE0A_SATA_PME_STS		17
+
+/* Group DW0 is reserved in Apollolake */
+
+/* GPE_63_32 */
+#define GPE0_DW1_00		32
+#define GPE0_DW1_01		33
+#define GPE0_DW1_02		34
+#define GPE0_DW1_03		36
+#define GPE0_DW1_04		36
+#define GPE0_DW1_05		37
+#define GPE0_DW1_06		38
+#define GPE0_DW1_07		39
+#define GPE0_DW1_08		40
+#define GPE0_DW1_09		41
+#define GPE0_DW1_10		42
+#define GPE0_DW1_11		43
+#define GPE0_DW1_12		44
+#define GPE0_DW1_13		45
+#define GPE0_DW1_14		46
+#define GPE0_DW1_15		47
+#define GPE0_DW1_16		48
+#define GPE0_DW1_17		49
+#define GPE0_DW1_18		50
+#define GPE0_DW1_19		51
+#define GPE0_DW1_20		52
+#define GPE0_DW1_21		53
+#define GPE0_DW1_22		54
+#define GPE0_DW1_23		55
+#define GPE0_DW1_24		56
+#define GPE0_DW1_25		57
+#define GPE0_DW1_26		58
+#define GPE0_DW1_27		59
+#define GPE0_DW1_28		60
+#define GPE0_DW1_29		61
+#define GPE0_DW1_30		62
+#define GPE0_DW1_31		63
+/* GPE_95_64 */
+#define GPE0_DW2_00		64
+#define GPE0_DW2_01		65
+#define GPE0_DW2_02		66
+#define GPE0_DW2_03		67
+#define GPE0_DW2_04		68
+#define GPE0_DW2_05		69
+#define GPE0_DW2_06		70
+#define GPE0_DW2_07		71
+#define GPE0_DW2_08		72
+#define GPE0_DW2_09		73
+#define GPE0_DW2_10		74
+#define GPE0_DW2_11		75
+#define GPE0_DW2_12		76
+#define GPE0_DW2_13		77
+#define GPE0_DW2_14		78
+#define GPE0_DW2_15		79
+#define GPE0_DW2_16		80
+#define GPE0_DW2_17		81
+#define GPE0_DW2_18		82
+#define GPE0_DW2_19		83
+#define GPE0_DW2_20		84
+#define GPE0_DW2_21		85
+#define GPE0_DW2_22		86
+#define GPE0_DW2_23		87
+#define GPE0_DW2_24		88
+#define GPE0_DW2_25		89
+#define GPE0_DW2_26		90
+#define GPE0_DW2_27		91
+#define GPE0_DW2_28		92
+#define GPE0_DW2_29		93
+#define GPE0_DW2_30		94
+#define GPE0_DW2_31		95
+/* GPE_127_96 */
+#define GPE0_DW3_00		96
+#define GPE0_DW3_01		97
+#define GPE0_DW3_02		98
+#define GPE0_DW3_03		99
+#define GPE0_DW3_04		100
+#define GPE0_DW3_05		101
+#define GPE0_DW3_06		102
+#define GPE0_DW3_07		103
+#define GPE0_DW3_08		104
+#define GPE0_DW3_09		105
+#define GPE0_DW3_10		106
+#define GPE0_DW3_11		107
+#define GPE0_DW3_12		108
+#define GPE0_DW3_13		109
+#define GPE0_DW3_14		110
+#define GPE0_DW3_15		111
+#define GPE0_DW3_16		112
+#define GPE0_DW3_17		113
+#define GPE0_DW3_18		114
+#define GPE0_DW3_19		115
+#define GPE0_DW3_20		116
+#define GPE0_DW3_21		117
+#define GPE0_DW3_22		118
+#define GPE0_DW3_23		119
+#define GPE0_DW3_24		120
+#define GPE0_DW3_25		121
+#define GPE0_DW3_26		122
+#define GPE0_DW3_27		123
+#define GPE0_DW3_28		124
+#define GPE0_DW3_29		125
+#define GPE0_DW3_30		126
+#define GPE0_DW3_31		127
+
+#endif
diff --git a/src/soc/intel/glk/include/soc/gpio.h b/src/soc/intel/glk/include/soc/gpio.h
new file mode 100644
index 0000000..9495a0f
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/gpio.h
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_GPIO_H_
+#define _SOC_GLK_GPIO_H_
+
+#include <soc/gpio_defs.h>
+/* __ACPI__ guard is needed to ignore below code in ACPI/ASL compilation */
+#ifndef __ACPI__
+#include <types.h>
+
+typedef uint32_t gpio_t;
+
+/*
+ * Structure to represent GPI status for GPE and SMI. Use helper
+ * functions for interrogating particular GPIs. Here the number of
+ * array elements is total number of groups that can be present in all
+ * the communities.
+ */
+struct gpi_status {
+	uint32_t grp[NUM_GPI_STATUS_REGS];
+};
+
+/*
+ * Clear GPI SMI status and fill in the structure representing enabled
+ * and set status.
+ */
+void gpi_clear_get_smi_status(struct gpi_status *sts);
+
+/* Return 1 if gpio is set in the gpi_status struct. Otherwise 0. */
+int gpi_status_get(const struct gpi_status *sts, gpio_t gpi);
+
+#define PAD_FUNC(value)		PAD_CFG0_MODE_##value
+#define PAD_RESET(value)	PAD_CFG0_RESET_##value
+#define PAD_PULL(value)		PAD_CFG1_PULL_##value
+#define PAD_IOSSTATE(value)	PAD_CFG1_IOSSTATE_##value
+#define PAD_IRQ_CFG(route, trig, inv) \
+				(PAD_CFG0_ROUTE_##route | \
+				PAD_CFG0_TRIG_##trig | \
+				(PAD_CFG0_RX_POL_##inv))
+
+#define _PAD_CFG_STRUCT(__pad, __config0, __config1)	\
+	{					\
+		.pad = __pad,			\
+		.config0 = __config0,		\
+		.config1 = __config1,		\
+	}
+
+/* Native function configuration */
+#define PAD_CFG_NF(pad, pull, rst, func) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TxLASTRxE))
+
+/* Native function configuration for standby state */
+#define PAD_CFG_NF_IOSSTATE(pad, pull, rst, func, iosstate) \
+	_PAD_CFG_STRUCT(pad, PAD_RESET(rst) | PAD_FUNC(func), PAD_PULL(pull) | \
+		PAD_IOSSTATE(iosstate))
+
+/* General purpose output, no pullup/down. */
+#define PAD_CFG_GPO(pad, val, rst)	\
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_RX_DISABLE | !!val, \
+		PAD_PULL(NONE) | PAD_IOSSTATE(TxLASTRxE))
+
+/* General purpose input */
+#define PAD_CFG_GPI(pad, pull, rst) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE, \
+		PAD_PULL(pull) | PAD_IOSSTATE(TxLASTRxE))
+
+/* General purpose input. The following macro sets the
+ * Host Software Pad Ownership to GPIO Driver mode.
+ */
+#define PAD_CFG_GPI_GPIO_DRIVER(pad, pull, rst) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE, \
+		PAD_PULL(pull) | PAD_CFG1_GPIO_DRIVER | PAD_IOSSTATE(TxLASTRxE))
+
+/* No Connect configuration for unused pad.
+ * NC should be GPI with Term as PU20K, PD20K, NONE depending upon default Term
+ */
+#define PAD_NC(pad, pull)	PAD_CFG_GPI(pad, pull, DEEP)
+
+/* General purpose input, routed to APIC */
+#define PAD_CFG_GPI_APIC(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(IOAPIC, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TxLASTRxE))
+
+/*
+ * The following APIC macros assume the APIC will handle the filtering
+ * on its own end. One just needs to pass an active high message into the
+ * ITSS.
+ */
+#define PAD_CFG_GPI_APIC_LOW(pad, pull, rst) \
+	PAD_CFG_GPI_APIC(pad, pull, rst, LEVEL, INVERT)
+
+#define PAD_CFG_GPI_APIC_HIGH(pad, pull, rst) \
+	PAD_CFG_GPI_APIC(pad, pull, rst, LEVEL, NONE)
+
+/* General purpose input, routed to SMI */
+#define PAD_CFG_GPI_SMI(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SMI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TxLASTRxE))
+
+#define PAD_CFG_GPI_SMI_LOW(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SMI(pad, pull, rst, trig, INVERT)
+
+#define PAD_CFG_GPI_SMI_HIGH(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SMI(pad, pull, rst, trig, NONE)
+
+/* General purpose input, routed to SCI */
+#define PAD_CFG_GPI_SCI(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(SCI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TxLASTRxE))
+
+#define PAD_CFG_GPI_SCI_LOW(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SCI(pad, pull, rst, trig, INVERT)
+
+#define PAD_CFG_GPI_SCI_HIGH(pad, pull, rst, trig) \
+	PAD_CFG_GPI_SCI(pad, pull, rst, trig, NONE)
+
+/* General purpose input, routed to NMI */
+#define PAD_CFG_GPI_NMI(pad, pull, rst, trig, inv) \
+	_PAD_CFG_STRUCT(pad,		\
+		PAD_FUNC(GPIO) | PAD_RESET(rst) | PAD_CFG0_TX_DISABLE | \
+		PAD_IRQ_CFG(NMI, trig, inv), PAD_PULL(pull) | \
+		PAD_IOSSTATE(TxLASTRxE))
+
+struct pad_config {
+	uint32_t config0;
+	uint16_t config1;
+	uint16_t pad;
+};
+
+/*
+ * Configuration for raw pads. Some pads are designated as only special function
+ * pins, and don't have an associated GPIO number, so we need to expose the raw
+ * pad configuration functionality.
+ */
+void gpio_configure_pad(const struct pad_config *cfg);
+void gpio_configure_pads(const struct pad_config *cfg, size_t num_pads);
+
+/* Calculate GPIO DW0 address */
+void * gpio_dwx_address(const uint16_t pad);
+/*
+ * Set the GPIO groups for the GPE blocks. The values from PMC register GPE_CFG
+ * are passed which is then mapped to proper groups for MISCCFG. This basically
+ * sets the MISCCFG register bits:
+ *  dw0 = gpe0_route[11:8]. This is ACPI GPE0b.
+ *  dw1 = gpe0_route[15:12]. This is ACPI GPE0c.
+ *  dw2 = gpe0_route[19:16]. This is ACPI GPE0d.
+ */
+void gpio_route_gpe(uint8_t gpe0b, uint8_t gpe0c, uint8_t gpe0d);
+
+#endif /* __ACPI__ */
+
+#endif /* _SOC_GLK_GPIO_H_ */
diff --git a/src/soc/intel/glk/include/soc/gpio_defs.h b/src/soc/intel/glk/include/soc/gpio_defs.h
new file mode 100644
index 0000000..b46957c
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/gpio_defs.h
@@ -0,0 +1,559 @@
+/*
+ * Definitions for the GPIO subsystem on Apollolake
+ *
+ * Placed in a separate file since some of these definitions can be used from
+ * assembly code
+ *
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_GPIO_DEFS_H_
+#define _SOC_GLK_GPIO_DEFS_H_
+
+/*
+ * Miscellaneous Configuration register(MISCCFG).These are community specific
+ * registers and are meant to house miscellaneous configuration fields per
+ * community. There are 8 GPIO groups: GPP_0 -> GPP_8 (Group 3 is absent)
+ */
+#define GPIO_MISCCFG		0x10 /* Miscellaneous Configuration offset */
+#define  GPIO_GPE_SW_31_0	0 /* SOUTHWEST GPIO#  0 ~ 31 belong to GROUP0 */
+#define  GPIO_GPE_SW_63_32	1 /* SOUTHWEST GPIO# 32 ~ 42 belong to GROUP1 */
+#define  GPIO_GPE_W_31_0	2 /* WEST      GPIO#  0 ~ 25 belong to GROUP2 */
+#define  GPIO_GPE_NW_31_0	4 /* NORTHWEST GPIO#  0 ~ 17 belong to GROUP4 */
+#define  GPIO_GPE_NW_63_32	5 /* NORTHWEST GPIO# 32 ~ 63 belong to GROUP5 */
+#define  GPIO_GPE_NW_95_64	6 /* NORTHWEST GPIO# 64 ~ 76 belong to GROUP6 */
+#define  GPIO_GPE_N_31_0	7 /* NORTH     GPIO#  0 ~ 31 belong to GROUP7 */
+#define  GPIO_GPE_N_63_32	8 /* NORTH     GPIO# 32 ~ 61 belong to GROUP8 */
+
+#define GPIO_MAX_NUM_PER_GROUP	32
+
+#define MISCCFG_GPE0_DW0_SHIFT 8
+#define MISCCFG_GPE0_DW0_MASK (0xf << MISCCFG_GPE0_DW0_SHIFT)
+#define MISCCFG_GPE0_DW1_SHIFT 12
+#define MISCCFG_GPE0_DW1_MASK (0xf << MISCCFG_GPE0_DW1_SHIFT)
+#define MISCCFG_GPE0_DW2_SHIFT 16
+#define MISCCFG_GPE0_DW2_MASK (0xf << MISCCFG_GPE0_DW2_SHIFT)
+
+/* Host Software Pad Ownership Register.
+ * The pins in the community are divided into 3 groups :
+ * GPIO 0 ~ 31, GPIO 32 ~ 63, GPIO 64 ~ 95
+ */
+#define HOSTSW_OWN_REG_BASE		0x80
+
+#define PAD_CFG0_TX_STATE		(1 << 0)
+#define PAD_CFG0_RX_STATE		(1 << 1)
+#define PAD_CFG0_TX_DISABLE		(1 << 8)
+#define PAD_CFG0_RX_DISABLE		(1 << 9)
+#define PAD_CFG0_MODE_MASK		(7 << 10)
+#define  PAD_CFG0_MODE_GPIO		(0 << 10)
+#define  PAD_CFG0_MODE_FUNC(x)		((x) << 10)
+#define  PAD_CFG0_MODE_NF1		(1 << 10)
+#define  PAD_CFG0_MODE_NF2		(2 << 10)
+#define  PAD_CFG0_MODE_NF3		(3 << 10)
+#define  PAD_CFG0_MODE_NF4		(4 << 10)
+#define  PAD_CFG0_MODE_NF5		(5 << 10)
+#define PAD_CFG0_ROUTE_NMI		(1 << 17)
+#define PAD_CFG0_ROUTE_SMI		(1 << 18)
+#define PAD_CFG0_ROUTE_SCI		(1 << 19)
+#define PAD_CFG0_ROUTE_IOAPIC		(1 << 20)
+#define PAD_CFG0_RX_POL_INVERT		(1 << 23)
+#define PAD_CFG0_RX_POL_NONE		(0 << 23)
+
+#define PAD_CFG0_TRIG_MASK		(3 << 25)
+#define  PAD_CFG0_TRIG_LEVEL		(0 << 25)
+#define  PAD_CFG0_TRIG_EDGE_SINGLE	(1 << 25) /* controlled by RX_INVERT*/
+#define  PAD_CFG0_TRIG_OFF		(2 << 25)
+#define  PAD_CFG0_TRIG_EDGE_BOTH	(3 << 25)
+#define PAD_CFG0_RESET_MASK		(3 << 30)
+#define  PAD_CFG0_RESET_PWROK		(0 << 30)
+#define  PAD_CFG0_RESET_DEEP		(1 << 30)
+#define  PAD_CFG0_RESET_PLTRST		(2 << 30)
+#define  PAD_CFG0_RESET_RSMRST		(3 << 30)
+
+/* Use the fourth bit in IntSel field to indicate gpio
+ * ownership. This field is RO and hence not used during
+ * gpio configuration.
+ */
+#define PAD_CFG1_GPIO_DRIVER		(0x1 << 4)
+#define PAD_CFG1_IRQ_MASK		(0xff << 0)
+#define PAD_CFG1_PULL_MASK		(0xf << 10)
+#define  PAD_CFG1_PULL_NONE		(0x0 << 10)
+#define  PAD_CFG1_PULL_DN_5K		(0x2 << 10)
+#define  PAD_CFG1_PULL_DN_20K		(0x4 << 10)
+#define  PAD_CFG1_PULL_UP_1K		(0x9 << 10)
+#define  PAD_CFG1_PULL_UP_5K		(0xa << 10)
+#define  PAD_CFG1_PULL_UP_2K		(0xb << 10)
+#define  PAD_CFG1_PULL_UP_20K		(0xc << 10)
+#define  PAD_CFG1_PULL_UP_667		(0xd << 10)
+#define  PAD_CFG1_PULL_NATIVE		(0xf << 10)
+/* Tx enabled driving last value driven, Rx enabled */
+#define PAD_CFG1_IOSSTATE_TxLASTRxE	(0x0 << 0)
+/* Tx enabled driving 0, Rx disabled and Rx driving 0 back to its controller
+ * internally */
+#define PAD_CFG1_IOSSTATE_Tx0RxDCRx0	(0x1 << 0)
+/* Tx enabled driving 0, Rx disabled and Rx driving 1 back to its controller
+ * internally */
+#define PAD_CFG1_IOSSTATE_Tx0RXDCRx1	(0x2 << 0)
+/* Tx enabled driving 1, Rx disabled and Rx driving 0 back to its controller
+ * internally */
+#define PAD_CFG1_IOSSTATE_Tx1RXDCRx0	(0x3 << 0)
+/* Tx enabled driving 1, Rx disabled and Rx driving 1 back to its controller
+ * internally */
+#define PAD_CFG1_IOSSTATE_Tx1RxDCRx1	(0x4 << 0)
+/* Tx enabled driving 0, Rx enabled */
+#define PAD_CFG1_IOSSTATE_Tx0RxE	(0x5 << 0)
+/* Tx enabled driving 1, Rx enabled */
+#define PAD_CFG1_IOSSTATE_Tx1RxE	(0x6 << 0)
+/* Hi-Z, Rx driving 0 back to its controller internally */
+#define PAD_CFG1_IOSSTATE_HIZCRx0	(0x7 << 0)
+/* Hi-Z, Rx driving 1 back to its controller internally */
+#define PAD_CFG1_IOSSTATE_HIZCRx1	(0x8 << 0)
+#define PAD_CFG1_IOSSTATE_TxDRxE	(0x9 << 0) /* Tx disabled, Rx enabled */
+#define PAD_CFG1_IOSSTATE_IGNORE	(0xf << 0) /* Ignore Iostandby */
+#define PAD_CFG1_IOSSTATE_MASK		0xf /* mask to extract Iostandby bits */
+#define PAD_CFG1_IOSSTATE_SHIFT	14 /* set Iostandby bits [17:14] */
+
+#define PAD_CFG_BASE			0x500
+#define PAD_CFG_OFFSET(pad)		(PAD_CFG_BASE + ((pad) * 8))
+
+/* IOSF port numbers for GPIO comminuties*/
+#define GPIO_SW			0xc0
+#define GPIO_S			0xc2
+#define GPIO_NW			0xc4
+#define GPIO_N			0xc5
+#define GPIO_W			0xc7
+
+#define GPI_SMI_STS_0			0x140
+#define GPI_SMI_EN_0			0x150
+#define GPI_SMI_STS_OFFSET(group)	(GPI_SMI_STS_0 + ((group) * 4))
+#define GPI_SMI_EN_OFFSET(group)	(GPI_SMI_EN_0 + ((group) * 4))
+
+#define NUM_N_PADS			(PAD_N(SVID0_CLK) + 1)
+#define NUM_NW_PADS			(PAD_NW(GPIO_123) + 1)
+#define NUM_W_PADS			(PAD_W(SUSPWRDNACK) + 1)
+#define NUM_SW_PADS			(PAD_SW(LPC_FRAMEB) + 1)
+
+#define NUM_N_GPI_REGS	\
+	(ALIGN_UP(NUM_N_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_NW_GPI_REGS	\
+	(ALIGN_UP(NUM_NW_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_W_GPI_REGS	\
+	(ALIGN_UP(NUM_W_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_SW_GPI_REGS	\
+	(ALIGN_UP(NUM_SW_PADS, GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_GPI_STATUS_REGS		(NUM_N_GPI_REGS + NUM_NW_GPI_REGS \
+					+ NUM_W_GPI_REGS + NUM_SW_GPI_REGS)
+
+/* North community pads */
+#define GPIO_0				0
+#define GPIO_1				1
+#define GPIO_2				2
+#define GPIO_3				3
+#define GPIO_4				4
+#define GPIO_5				5
+#define GPIO_6				6
+#define GPIO_7				7
+#define GPIO_8				8
+#define GPIO_9				9
+#define GPIO_10				10
+#define GPIO_11				11
+#define GPIO_12				12
+#define GPIO_13				13
+#define GPIO_14				14
+#define GPIO_15				15
+#define GPIO_16				16
+#define GPIO_17				17
+#define GPIO_18				18
+#define GPIO_19				19
+#define GPIO_20				20
+#define GPIO_21				21
+#define GPIO_22				22
+#define GPIO_23				23
+#define GPIO_24				24
+#define GPIO_25				25
+#define GPIO_26				26
+#define GPIO_27				27
+#define GPIO_28				28
+#define GPIO_29				29
+#define GPIO_30				30
+#define GPIO_31				31
+#define GPIO_32				32
+#define GPIO_33				33
+#define GPIO_34				34
+#define GPIO_35				35
+#define GPIO_36				36
+#define GPIO_37				37
+#define GPIO_38				38
+#define GPIO_39				39
+#define GPIO_40				40
+#define GPIO_41				41
+#define GPIO_42				42
+#define GPIO_43				43
+#define GPIO_44				44
+#define GPIO_45				45
+#define GPIO_46				46
+#define GPIO_47				47
+#define GPIO_48				48
+#define GPIO_49				49
+#define GPIO_62				50
+#define GPIO_63				51
+#define GPIO_64				52
+#define GPIO_65				53
+#define GPIO_66				54
+#define GPIO_67				55
+#define GPIO_68				56
+#define GPIO_69				57
+#define GPIO_70				58
+#define GPIO_71				59
+#define GPIO_72				60
+#define GPIO_73				61
+#define TCK				62
+#define TRST_B				63
+#define TMS				64
+#define TDI				65
+#define CX_PMODE			66
+#define CX_PREQ_B			67
+#define JTAGX				68
+#define CX_PRDY_B			69
+#define TDO				70
+#define CNV_BRI_DT			71
+#define CNV_BRI_RSP			72
+#define CNV_RGI_DT			73
+#define CNV_RGI_RSP			74
+#define SVID0_ALERT_B			75
+#define SVID0_DATA			76
+#define SVID0_CLK			77
+
+/* Northwest community pads */
+#define GPIO_187			78
+#define GPIO_188			79
+#define GPIO_189			80
+#define GPIO_190			81
+#define GPIO_191			82
+#define GPIO_192			83
+#define GPIO_193			84
+#define GPIO_194			85
+#define GPIO_195			86
+#define GPIO_196			87
+#define GPIO_197			88
+#define GPIO_198			89
+#define GPIO_199			90
+#define GPIO_200			91
+#define GPIO_201			92
+#define GPIO_202			93
+#define GPIO_203			94
+#define GPIO_204			95
+#define PMC_SPI_FS0			96
+#define PMC_SPI_FS1			97
+#define PMC_SPI_FS2			98
+#define PMC_SPI_RXD			99
+#define PMC_SPI_TXD			100
+#define PMC_SPI_CLK			101
+#define PMIC_PWRGOOD			102
+#define PMIC_RESET_B			103
+#define GPIO_213			104
+#define GPIO_214			105
+#define GPIO_215			106
+#define PMIC_THERMTRIP_B		107
+#define PMIC_STDBY			108
+#define PROCHOT_B			109
+#define PMIC_I2C_SCL			110
+#define PMIC_I2C_SDA			111
+#define GPIO_74				112
+#define GPIO_75				113
+#define GPIO_76				114
+#define GPIO_77				115
+#define GPIO_78				116
+#define GPIO_79				117
+#define GPIO_80				118
+#define GPIO_81				119
+#define GPIO_82				120
+#define GPIO_83				121
+#define GPIO_84				122
+#define GPIO_85				123
+#define GPIO_86				124
+#define GPIO_87				125
+#define GPIO_88				126
+#define GPIO_89				127
+#define GPIO_90				128
+#define GPIO_91				129
+#define GPIO_92				130
+#define GPIO_97				131
+#define GPIO_98				132
+#define GPIO_99				133
+#define GPIO_100			134
+#define GPIO_101			135
+#define GPIO_102			136
+#define GPIO_103			137
+#define FST_SPI_CLK_FB			138
+#define GPIO_104			139
+#define GPIO_105			140
+#define GPIO_106			141
+#define GPIO_109			142
+#define GPIO_110			143
+#define GPIO_111			144
+#define GPIO_112			145
+#define GPIO_113			146
+#define GPIO_116			147
+#define GPIO_117			148
+#define GPIO_118			149
+#define GPIO_119			150
+#define GPIO_120			151
+#define GPIO_121			152
+#define GPIO_122			153
+#define GPIO_123			154
+
+/* West community pads */
+#define GPIO_124			155
+#define GPIO_125			156
+#define GPIO_126			157
+#define GPIO_127			158
+#define GPIO_128			159
+#define GPIO_129			160
+#define GPIO_130			161
+#define GPIO_131			162
+#define GPIO_132			163
+#define GPIO_133			164
+#define GPIO_134			165
+#define GPIO_135			166
+#define GPIO_136			167
+#define GPIO_137			168
+#define GPIO_138			169
+#define GPIO_139			170
+#define GPIO_146			171
+#define GPIO_147			172
+#define GPIO_148			173
+#define GPIO_149			174
+#define GPIO_150			175
+#define GPIO_151			176
+#define GPIO_152			177
+#define GPIO_153			178
+#define GPIO_154			179
+#define GPIO_155			180
+#define GPIO_209			181
+#define GPIO_210			182
+#define GPIO_211			183
+#define GPIO_212			184
+#define OSC_CLK_OUT_0			185
+#define OSC_CLK_OUT_1			186
+#define OSC_CLK_OUT_2			187
+#define OSC_CLK_OUT_3			188
+#define OSC_CLK_OUT_4			189
+#define PMU_AC_PRESENT			190
+#define PMU_BATLOW_B			191
+#define PMU_PLTRST_B			192
+#define PMU_PWRBTN_B			193
+#define PMU_RESETBUTTON_B		194
+#define PMU_SLP_S0_B			195
+#define PMU_SLP_S3_B			196
+#define PMU_SLP_S4_B			197
+#define PMU_SUSCLK			198
+#define PMU_WAKE_B			199
+#define SUS_STAT_B			200
+#define SUSPWRDNACK			201
+
+/* Southwest community pads */
+#define GPIO_205			202
+#define GPIO_206			203
+#define GPIO_207			204
+#define GPIO_208			205
+#define GPIO_156			206
+#define GPIO_157			207
+#define GPIO_158			208
+#define GPIO_159			209
+#define GPIO_160			210
+#define GPIO_161			211
+#define GPIO_162			212
+#define GPIO_163			213
+#define GPIO_164			214
+#define GPIO_165			215
+#define GPIO_166			216
+#define GPIO_167			217
+#define GPIO_168			218
+#define GPIO_169			219
+#define GPIO_170			220
+#define GPIO_171			221
+#define GPIO_172			222
+#define GPIO_179			223
+#define GPIO_173			224
+#define GPIO_174			225
+#define GPIO_175			226
+#define GPIO_176			227
+#define GPIO_177			228
+#define GPIO_178			229
+#define GPIO_186			230
+#define GPIO_182			231
+#define GPIO_183			232
+#define SMB_ALERTB			233
+#define SMB_CLK				234
+#define SMB_DATA			235
+#define LPC_ILB_SERIRQ			236
+#define LPC_CLKOUT0			237
+#define LPC_CLKOUT1			238
+#define LPC_AD0				239
+#define LPC_AD1				240
+#define LPC_AD2				241
+#define LPC_AD3				242
+#define LPC_CLKRUNB			243
+#define LPC_FRAMEB			244
+
+/* PERST_0 not defined */
+#define GPIO_PRT0_UDEF			0xFF
+
+#define TOTAL_PADS			245
+#define N_OFFSET			GPIO_0
+#define NW_OFFSET			GPIO_187
+#define W_OFFSET			GPIO_124
+#define SW_OFFSET			GPIO_205
+
+/* Macros for translating a global pad offset to a local offset */
+#define PAD_N(pad)			(pad - N_OFFSET)
+#define PAD_NW(pad)			(pad - NW_OFFSET)
+#define PAD_W(pad)			(pad - W_OFFSET)
+#define PAD_SW(pad)			(pad - SW_OFFSET)
+
+/* Linux names of the GPIO devices. */
+#define GPIO_COMM_N_NAME		"INT3452:00"
+#define GPIO_COMM_NW_NAME		"INT3452:01"
+#define GPIO_COMM_W_NAME		"INT3452:02"
+#define GPIO_COMM_SW_NAME		"INT3452:03"
+
+/* Default configurations */
+#define PAD_CFG0_DEFAULT_FUNC(x)	(PAD_CFG0_RESET_DEEP | PAD_CFG0_MODE_FUNC(x))
+#define PAD_CFG0_DEFAULT_NATIVE		PAD_CFG0_DEFAULT_FUNC(1)
+
+#define PAD_CFG1_DEFAULT_PULLUP		PAD_CFG1_PULL_UP_20K
+#define PAD_CFG1_DEFAULT_NATIVE		PAD_CFG1_PULL_NATIVE
+
+/*
+ * IOxAPIC IRQs for the GPIOs, overlap is expected as we encourage to use
+ * shared IRQ instead of direct IRQ, in case of overlapping, we can easily
+ * program one of the overlap to shared IRQ to avoid the conflict.
+ */
+
+/* NorthWest community pads */
+#define PMIC_I2C_SDA_IRQ		0x32
+#define GPIO_74_IRQ			0x33
+#define GPIO_75_IRQ			0x34
+#define GPIO_76_IRQ			0x35
+#define GPIO_77_IRQ			0x36
+#define GPIO_78_IRQ			0x37
+#define GPIO_79_IRQ			0x38
+#define GPIO_80_IRQ			0x39
+#define GPIO_81_IRQ			0x3A
+#define GPIO_82_IRQ			0x3B
+#define GPIO_83_IRQ			0x3C
+#define GPIO_84_IRQ			0x3D
+#define GPIO_85_IRQ			0x3E
+#define GPIO_86_IRQ			0x3F
+#define GPIO_87_IRQ			0x40
+#define GPIO_88_IRQ			0x41
+#define GPIO_89_IRQ			0x42
+#define GPIO_90_IRQ			0x43
+#define GPIO_91_IRQ			0x44
+#define GPIO_97_IRQ			0x49
+#define GPIO_98_IRQ			0x4A
+#define GPIO_99_IRQ			0x4B
+#define GPIO_100_IRQ			0x4C
+#define GPIO_101_IRQ			0x4D
+#define GPIO_102_IRQ			0x4E
+#define GPIO_103_IRQ			0x4F
+#define GPIO_104_IRQ			0x50
+#define GPIO_105_IRQ			0x51
+#define GPIO_106_IRQ			0x52
+#define GPIO_109_IRQ			0x54
+#define GPIO_110_IRQ			0x55
+#define GPIO_111_IRQ			0x56
+#define GPIO_112_IRQ			0x57
+#define GPIO_113_IRQ			0x58
+#define GPIO_116_IRQ			0x5B
+#define GPIO_117_IRQ			0x5C
+#define GPIO_118_IRQ			0x5D
+#define GPIO_119_IRQ			0x5E
+#define GPIO_120_IRQ			0x5F
+#define GPIO_121_IRQ			0x60
+#define GPIO_122_IRQ			0x61
+#define GPIO_123_IRQ			0x62
+
+/* North community pads */
+#define GPIO_0_IRQ			0x63
+#define GPIO_1_IRQ			0x64
+#define GPIO_2_IRQ			0x65
+#define GPIO_3_IRQ			0x66
+#define GPIO_4_IRQ			0x67
+#define GPIO_5_IRQ			0x68
+#define GPIO_6_IRQ			0x69
+#define GPIO_7_IRQ			0x6A
+#define GPIO_8_IRQ			0x6B
+#define GPIO_9_IRQ			0x6C
+#define GPIO_10_IRQ			0x6D
+#define GPIO_11_IRQ			0x6E
+#define GPIO_12_IRQ			0x6F
+#define GPIO_13_IRQ			0x6F
+#define GPIO_14_IRQ			0x71
+#define GPIO_15_IRQ			0x72
+#define GPIO_16_IRQ			0x73
+#define GPIO_17_IRQ			0x74
+#define GPIO_18_IRQ			0x75
+#define GPIO_19_IRQ			0x76
+#define GPIO_20_IRQ			0x77
+#define GPIO_21_IRQ			0x32
+#define GPIO_22_IRQ			0x33
+#define GPIO_23_IRQ			0x34
+#define GPIO_24_IRQ			0x35
+#define GPIO_25_IRQ			0x36
+#define GPIO_26_IRQ			0x37
+#define GPIO_27_IRQ			0x38
+#define GPIO_28_IRQ			0x39
+#define GPIO_29_IRQ			0x3A
+#define GPIO_30_IRQ			0x3B
+#define GPIO_31_IRQ			0x3C
+#define GPIO_32_IRQ			0x3D
+#define GPIO_33_IRQ			0x3E
+#define GPIO_34_IRQ			0x3F
+#define GPIO_35_IRQ			0x40
+#define GPIO_36_IRQ			0x41
+#define GPIO_37_IRQ			0x42
+#define GPIO_38_IRQ			0x43
+#define GPIO_39_IRQ			0x44
+#define GPIO_40_IRQ			0x45
+#define GPIO_41_IRQ			0x46
+#define GPIO_42_IRQ			0x47
+#define GPIO_43_IRQ			0x48
+#define GPIO_44_IRQ			0x49
+#define GPIO_45_IRQ			0x4A
+#define GPIO_46_IRQ			0x4B
+#define GPIO_47_IRQ			0x4C
+#define GPIO_48_IRQ			0x4D
+#define GPIO_49_IRQ			0x4E
+#define GPIO_62_IRQ			0x5B
+#define GPIO_63_IRQ			0x5C
+#define GPIO_64_IRQ			0x5D
+#define GPIO_65_IRQ			0x5E
+#define GPIO_66_IRQ			0x5F
+#define GPIO_67_IRQ			0x60
+#define GPIO_68_IRQ			0x61
+#define GPIO_69_IRQ			0x62
+#define GPIO_70_IRQ			0x63
+#define GPIO_71_IRQ			0x64
+#define GPIO_72_IRQ			0x65
+#define GPIO_73_IRQ			0x66
+
+#endif /* _SOC_GLK_GPIO_DEFS_H_ */
diff --git a/src/soc/intel/glk/include/soc/heci.h b/src/soc/intel/glk/include/soc/heci.h
new file mode 100644
index 0000000..82b89a9
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/heci.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_HECI_H_
+#define _SOC_GLK_HECI_H_
+
+enum sec_status {
+	SEC_STATE_RESET = 0,
+	SEC_STATE_INIT,
+	SEC_STATE_RECOVERY,
+	SEC_STATE_UNKNOWN0,
+	SEC_STATE_UNKNOWN1,
+	SEC_STATE_NORMAL,
+	SEC_STATE_DISABLE_WAIT,
+	SEC_STATE_TRANSITION,
+	SEC_STATE_INVALID_CPU
+};
+
+#define REG_SEC_FW_STS0					0x40
+#define MASK_SEC_FIRMWARE_COMPLETE			(1 << 9)
+#define MASK_SEC_STATUS					0xf
+
+/* Read Firmware Status register */
+uint32_t heci_fw_sts(void);
+/* Returns true if CSE is in normal status */
+bool heci_cse_normal(void);
+/* Returns true if CSE is done with whatever it was doing */
+bool heci_cse_done(void);
+
+#endif
diff --git a/src/soc/intel/glk/include/soc/i2c.h b/src/soc/intel/glk/include/soc/i2c.h
new file mode 100644
index 0000000..95ccc4a
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/i2c.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_I2C_H_
+#define _SOC_GLK_I2C_H_
+
+#include <device/pci_def.h>
+#include <soc/pci_devs.h>
+
+/* I2C Controller Reset in MMIO private region */
+#define I2C_LPSS_REG_RESET		0x204
+#define I2C_LPSS_RESET_RELEASE_HC	((1 << 1) | (1 << 0))
+#define I2C_LPSS_RESET_RELEASE_IDMA	(1 << 2)
+
+/* Convert I2C bus number to PCI device and function */
+static inline int i2c_bus_to_devfn(unsigned bus)
+{
+	if (bus >= 0 && bus <= 3)
+		return PCI_DEVFN(LPSS_DEV_SLOT_I2C_D0, bus);
+	else if (bus >= 4 && bus <= 7)
+		return PCI_DEVFN(LPSS_DEV_SLOT_I2C_D1, (bus - 4));
+	else
+		return -1;
+}
+
+/* Convert PCI device and function to I2C bus number */
+static inline int i2c_devfn_to_bus(unsigned devfn)
+{
+	if (PCI_SLOT(devfn) == LPSS_DEV_SLOT_I2C_D0)
+		return PCI_FUNC(devfn);
+	else if (PCI_SLOT(devfn) == LPSS_DEV_SLOT_I2C_D1)
+		return PCI_FUNC(devfn) + 4;
+	else
+		return -1;
+}
+
+#endif /* _SOC_GLK_I2C_H_ */
diff --git a/src/soc/intel/glk/include/soc/iomap.h b/src/soc/intel/glk/include/soc/iomap.h
new file mode 100644
index 0000000..ef1bc68
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/iomap.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_IOMAP_H_
+#define _SOC_GLK_IOMAP_H_
+
+#include <commonlib/helpers.h>
+
+#define P2SB_BAR			CONFIG_IOSF_BASE_ADDRESS
+#define P2SB_SIZE			(16 * MiB)
+#define MCH_BASE_ADDR			0xfed10000
+#define MCH_BASE_SIZE			(32 * KiB)
+
+#define ACPI_PMIO_BASE			0x400
+#define ACPI_PMIO_SIZE			0x100
+#define  R_ACPI_PM1_TMR			0x8
+
+/* Accesses to these BARs are hardcoded in FSP */
+#define PMC_BAR0			0xfe042000
+#define PMC_BAR1			0xfe044000
+
+/* Temporary BAR for SPI until PCI enumeration assigns a BAR in ramstage. */
+#define PRERAM_SPI_BASE_ADDRESS		0xfe010000
+
+/* Temporary BAR for early I2C bus access */
+#define PRERAM_I2C_BASE_ADDRESS(x)	(0xfe020000 + (0x1000 * (x)))
+
+#endif /* _SOC_GLK_IOMAP_H_ */
diff --git a/src/soc/intel/glk/include/soc/iosf.h b/src/soc/intel/glk/include/soc/iosf.h
new file mode 100644
index 0000000..77f6bf8
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/iosf.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_IOSF_H_
+#define _SOC_GLK_IOSF_H_
+
+#include <arch/io.h>
+
+#define IOSF_RTC_PORT_ID		0xD1
+#define  RTC_CONFIG			0x3400
+#define   RTC_CONFIG_UCMOS_ENABLE	(1 << 2)
+
+static inline void * iosf_address(uint16_t port, uint16_t reg)
+{
+	uintptr_t addr = (CONFIG_IOSF_BASE_ADDRESS | (port << 16) | (reg & ~3));
+	return (void *)addr;
+}
+
+inline static void iosf_write(uint16_t port, uint16_t reg, uint32_t val)
+{
+	write32(iosf_address(port, reg), val);
+}
+
+inline static uint32_t iosf_read(uint16_t port, uint16_t reg)
+{
+	return read32(iosf_address(port, reg));
+}
+#endif /* _SOC_GLK_IOSF_H_ */
diff --git a/src/soc/intel/glk/include/soc/itss.h b/src/soc/intel/glk/include/soc/itss.h
new file mode 100644
index 0000000..2669fed
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/itss.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_ITSS_H_
+#define _SOC_GLK_ITSS_H_
+
+#define GPIO_IRQ_START 50
+#define GPIO_IRQ_END 119
+
+/* Set the interrupt polarity for provided IRQ to the APIC. */
+void itss_set_irq_polarity(int irq, int active_low);
+
+/* Snapshot and restore IRQ polarity settings for the inclusive range. */
+void itss_snapshot_irq_polarities(int start, int end);
+void itss_restore_irq_polarities(int start, int end);
+
+#endif /* _SOC_GLK_ITSS_H_ */
diff --git a/src/soc/intel/glk/include/soc/lpc.h b/src/soc/intel/glk/include/soc/lpc.h
new file mode 100644
index 0000000..e104478
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/lpc.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_LPC_H_
+#define _SOC_GLK_LPC_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define REG_SERIRQ_CTL			0x64
+#define  SCNT_EN			(1 << 7)
+#define  SCNT_MODE			(1 << 6)
+
+/*
+ * IO decode enable macros are in the format IO_<peripheral>_<IO port>.
+ * For example, to open ports 0x60, 0x64 for the keyboard controller,
+ * use IOE_KBC_60_64 macro. For IOE_ macros that do not specify a port range,
+ * the port range is selectable via the IO decodes register (not referenced).
+ */
+#define REG_IO_ENABLES			0x82
+#define  IOE_EC_4E_4F			(1 << 13)
+#define  IOE_SUPERIO_2E_2F		(1 << 12)
+#define  IOE_EC_62_66			(1 << 11)
+#define  IOE_KBC_60_64			(1 << 10)
+#define  IOE_HGE_208			(1 << 9)
+#define  IOE_LGE_200			(1 << 8)
+#define  IOE_FDD_EN			(1 << 3)
+#define  IOE_LPT_EN			(1 << 2)
+#define  IOE_COMB_EN			(1 << 1)
+#define  IOE_COMA_EN			(1 << 0)
+#define REG_GENERIC_IO_RANGE(n)		((((n) & 0x3) * 4) + 0x84)
+#define  LGIR_AMASK_MASK		(0xfc << 16)
+#define  LGIR_ADDR_MASK			0xfffc
+#define  LGIR_EN			(1 << 0)
+#define LGIR_MAX_WINDOW_SIZE		256
+#define NUM_GENERIC_IO_RANGES		4
+#define REG_GENERIC_MEM_RANGE		0x98
+#define  LGMR_ADDR_MASK			0xffff0000
+#define  LGMR_EN			(1 << 0)
+#define LGMR_WINDOW_SIZE		(64 * KiB)
+
+/* Configure the SOC's LPC pads and mux them to the LPC function. */
+void lpc_configure_pads(void);
+/* Enable fixed IO ranges to LPC. IOE_* macros can be OR'ed together. */
+void lpc_enable_fixed_io_ranges(uint16_t io_enables);
+/* Open a generic IO window to the LPC bus. Four windows are available. */
+void lpc_open_pmio_window(uint16_t base, uint16_t size);
+/* Close all generic IO windows to the LPC bus. */
+void lpc_close_pmio_windows(void);
+/* Open a generic MMIO window to the LPC bus. One window is available. */
+void lpc_open_mmio_window(uintptr_t base, size_t size);
+/* Returns true if given window is decoded to LPC via a fixed range. */
+bool lpc_fits_fixed_mmio_window(uintptr_t base, size_t size);
+
+#endif /* _SOC_GLK_LPC_H_ */
diff --git a/src/soc/intel/glk/include/soc/meminit.h b/src/soc/intel/glk/include/soc/meminit.h
new file mode 100644
index 0000000..34d0a98
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/meminit.h
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_MEMINIT_H_
+#define _SOC_GLK_MEMINIT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <fsp/soc_binding.h>
+
+/*
+ * LPDDR4 helper routines for configuring the memory UPD for LPDDR4 operation.
+ * There are 4 physical LPDDR4 channels each 32-bits wide. There are 2 logical
+ * channels using 2 physical channels together to form a 64-bit interface to
+ * memory for each logical channel.
+ */
+
+enum {
+	LP4_PHYS_CH0A,
+	LP4_PHYS_CH0B,
+	LP4_PHYS_CH1A,
+	LP4_PHYS_CH1B,
+	LP4_NUM_PHYS_CHANNELS,
+};
+
+/* Logical channel identification. */
+enum {
+	LP4_LCH0,
+	LP4_LCH1,
+};
+
+/*
+ * The DQs within a physical channel can be bit-swizzled within each byte.
+ * Within a channel the bytes can be swapped, but the DQs need to be routed
+ * with the corresponding DQS (strobe).
+ */
+enum {
+	LP4_DQS0,
+	LP4_DQS1,
+	LP4_DQS2,
+	LP4_DQS3,
+	LP4_NUM_BYTE_LANES,
+	DQ_BITS_PER_DQS = 8,
+};
+
+enum {
+				/* RL-tRCD-tRP */
+	LP4_SPEED_1600 = 1600,	/* 14-15-15 */
+	LP4_SPEED_2133 = 2133,	/* 20-20-20 */
+	LP4_SPEED_2400 = 2400,	/* 24-22-22 */
+};
+
+/* LPDDR4 module density in bits. */
+enum {
+	LP4_8Gb_DENSITY = 2,
+	LP4_12Gb_DESNITY,
+	LP4_16Gb_DENSITY,
+};
+
+/* Provide bit swizzling per DQS and byte swapping within a channel. */
+struct lpddr4_chan_swizzle_cfg {
+	uint8_t dqs[LP4_NUM_BYTE_LANES][DQ_BITS_PER_DQS];
+};
+
+struct lpddr4_swizzle_cfg {
+	struct lpddr4_chan_swizzle_cfg phys[LP4_NUM_PHYS_CHANNELS];
+};
+
+/*
+ * Initialize default LPDDR4 settings with provided speed. No logical channels
+ * are enabled. Subsequent calls to logical channel enabling are required.
+ */
+void meminit_lpddr4(FSP_M_CONFIG *cfg, int speed);
+
+/*
+ * Enable logical channel providing the full lpddr4_swizzle_config to
+ * fill in per channel swizzle definitions. This assumes a 64-bit wide
+ * memory width per logical channel -- i.e. 2 physical channels are configured
+ * to the memory reference code.
+ */
+void meminit_lpddr4_enable_channel(FSP_M_CONFIG *cfg, int logical_chan,
+					int rank_density, int dual_rank,
+					const struct lpddr4_swizzle_cfg *scfg);
+
+struct lpddr4_sku {
+	int speed;
+	int ch0_rank_density;
+	int ch1_rank_density;
+	int ch0_dual_rank;
+	int ch1_dual_rank;
+	const char *part_num;
+	bool disable_periodic_retraining;
+};
+
+struct lpddr4_cfg {
+	const struct lpddr4_sku *skus;
+	size_t num_skus;
+	const struct lpddr4_swizzle_cfg *swizzle_config;
+};
+
+/*
+ * Initialize LPDDR4 settings by the provided lpddr4_cfg information and sku id.
+ * The sku id is an index into the sku array within the lpddr4_cfg struct.
+ */
+void meminit_lpddr4_by_sku(FSP_M_CONFIG *cfg,
+				const struct lpddr4_cfg *lpcfg, size_t sku_id);
+void save_lpddr4_dimm_info(const struct lpddr4_cfg *lpcfg, size_t mem_sku);
+
+#endif /* _SOC_GLK_MEMINIT_H_ */
diff --git a/src/soc/intel/glk/include/soc/mmap_boot.h b/src/soc/intel/glk/include/soc/mmap_boot.h
new file mode 100644
index 0000000..b638336
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/mmap_boot.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __SOC_GLK_MMAP_BOOT_H__
+#define __SOC_GLK_MMAP_BOOT_H__
+
+size_t get_bios_size(void);
+
+#endif /* __SOC_GLK_MMAP_BOOT_H__ */
diff --git a/src/soc/intel/glk/include/soc/nhlt.h b/src/soc/intel/glk/include/soc/nhlt.h
new file mode 100644
index 0000000..d5a462e
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/nhlt.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_NHLT_H_
+#define _SOC_GLK_NHLT_H_
+
+#include <nhlt.h>
+
+#define NHLT_VID 0x8086
+#define NHLT_DID_DMIC 0xae20
+#define NHLT_DID_BT 0xae30
+#define NHLT_DID_SSP 0xae34
+
+/* The following link values should be used for the hwlink parameters below. */
+enum {
+	AUDIO_LINK_SSP0,
+	AUDIO_LINK_SSP1,
+	AUDIO_LINK_SSP2,
+	AUDIO_LINK_SSP3,
+	AUDIO_LINK_SSP4,
+	AUDIO_LINK_SSP5,
+	AUDIO_LINK_DMIC,
+};
+
+/* Returns < 0 on error, 0 on success. */
+int nhlt_soc_add_dmic_array(struct nhlt *nhlt, int num_channels);
+int nhlt_soc_add_max98357(struct nhlt *nhlt, int hwlink);
+int nhlt_soc_add_da7219(struct nhlt *nhlt, int hwlink);
+
+#endif
diff --git a/src/soc/intel/glk/include/soc/northbridge.h b/src/soc/intel/glk/include/soc/northbridge.h
new file mode 100644
index 0000000..ba79838
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/northbridge.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_NORTHBRIDGE_H_
+#define _SOC_GLK_NORTHBRIDGE_H_
+
+#define MCHBAR		0x48
+#define PCIEXBAR	0x60
+#define PCIEX_SIZE	(256 * MiB)
+
+#define BDSM		0xb0	/* Base Data Stolen Memory */
+#define BGSM		0xb4	/* Base GTT Stolen Memory */
+#define TSEG		0xb8	/* TSEG base */
+#define TOLUD		0xbc	/* Top of Low Used Memory */
+#define TOUUD		0xa8	/* Top of Upper Usable DRAM */
+
+/* IMR registers are found under MCHBAR. */
+#define MCHBAR_IMR0BASE		0x6870
+#define MCHBAR_IMR0MASK		0x6874
+#define MCH_IMR_PITCH		0x20
+#define MCH_NUM_IMRS		20
+
+/* RAPL Package Power Limit register under MCHBAR. */
+#define MCHBAR_RAPL_PPL		0x70A8
+
+#endif /* _SOC_GLK_NORTHBRIDGE_H_ */
diff --git a/src/soc/intel/glk/include/soc/nvs.h b/src/soc/intel/glk/include/soc/nvs.h
new file mode 100644
index 0000000..f468c1a
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/nvs.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * NOTE: The layout of the global_nvs_t structure below must match the layout
+ * in soc/intel/glk/acpi/globalnvs.asl !!!
+ *
+ */
+
+#ifndef _SOC_GLK_NVS_H_
+#define _SOC_GLK_NVS_H_
+
+#include <vendorcode/google/chromeos/gnvs.h>
+
+typedef struct global_nvs_t {
+	/* Miscellaneous */
+	uint8_t		pcnt; /* 0x00 - Processor Count */
+	uint8_t		ppcm; /* 0x01 - Max PPC State */
+	uint8_t		lids; /* 0x02 - LID State */
+	uint8_t		pwrs; /* 0x03 - AC Power State */
+	uint8_t		dpte; /* 0x04 - Enable DPTF */
+	uint32_t	cbmc; /* 0x05 - 0x08 - Coreboot Memory Console */
+	uint64_t	pm1i; /* 0x09 - 0x10 - System Wake Source - PM1 Index */
+	uint64_t	gpei; /* 0x11 - 0x18 - GPE Wake Source */
+	uint64_t	nhla; /* 0x19 - 0x20 - NHLT Address */
+	uint32_t	nhll; /* 0x21 - 0x24 - NHLT Length */
+	uint32_t	prt0; /* 0x25 - 0x28 - PERST_0 Address */
+	uint8_t		unused[215];
+
+	/* ChromeOS specific (0x100 - 0xfff) */
+	chromeos_acpi_t chromeos;
+} __attribute__((packed)) global_nvs_t;
+
+#endif	/* _SOC_GLK_NVS_H_ */
diff --git a/src/soc/intel/glk/include/soc/p2sb.h b/src/soc/intel/glk/include/soc/p2sb.h
new file mode 100644
index 0000000..6cc3b8c
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/p2sb.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_P2SB_H_
+#define _SOC_GLK_P2SB_H_
+
+void p2sb_unhide(void);
+void p2sb_hide(void);
+
+#endif /* _SOC_GLK_P2SB_H_ */
diff --git a/src/soc/intel/glk/include/soc/pci_devs.h b/src/soc/intel/glk/include/soc/pci_devs.h
new file mode 100644
index 0000000..1ecfdaf
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/pci_devs.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_PCI_DEVS_H_
+#define _SOC_GLK_PCI_DEVS_H_
+
+#include <rules.h>
+
+#define _LPSS_PCI_DEVFN(slot, func)	PCI_DEVFN(LPSS_DEV_SLOT_##slot, func)
+#define _PCI_DEVFN(slot, func)		PCI_DEVFN(slot, func)
+
+#if !defined(__SIMPLE_DEVICE__)
+#include <device/device.h>
+#include <device/pci_def.h>
+#define _LPSS_PCI_DEV(slot, func)	dev_find_slot(0, _LPSS_PCI_DEVFN(slot, func))
+#define _PCI_DEV(slot, func)		dev_find_slot(0, PCI_DEVFN(slot, func))
+#else
+#include <arch/io.h>
+#define _LPSS_PCI_DEV(slot, func)	PCI_DEV(0, LPSS_DEV_SLOT_##slot, func)
+#define _PCI_DEV(slot, func)		PCI_DEV(0, slot, func)
+#endif
+
+#define NB_DEVFN			_PCI_DEVFN(0, 0)
+#define NB_DEV_ROOT			_PCI_DEV(0x0, 0)
+
+#define IGD_DEV				_PCI_DEV(0x2, 0)
+#define IGD_DEVFN			_PCI_DEVFN(0x2, 0)
+
+#define P2SB_DEV			_PCI_DEV(0xd, 0)
+#define P2SB_DEVFN			_PCI_DEVFN(0xd, 0)
+
+#define PMC_DEV				_PCI_DEV(0xd, 1)
+#define PMC_DEVFN			_PCI_DEVFN(0xd, 1)
+
+#define SPI_DEV				_PCI_DEV(0xd, 2)
+#define SPI_DEVFN			_PCI_DEVFN(0xd, 2)
+
+#define HDA_DEV				_PCI_DEV(0xe, 0)
+#define HDA_DEVFN			_PCI_DEVFN(0xe, 0)
+
+#define CSE_DEV				_PCI_DEV(0xf, 0)
+#define CSE_DEVFN			_PCI_DEVFN(0xf, 0)
+
+#define ISH_DEV				_PCI_DEV(0x11, 0)
+#define ISH_DEVFN			_PCI_DEVFN(0x11, 0)
+
+#define SATA_DEV			_PCI_DEV(0x12, 0)
+#define SATA_DEVFN			_PCI_DEVFN(0x12, 0)
+
+#define PCIEA0_DEVFN			_PCI_DEVFN(0x13, 0)
+#define PCIEA1_DEVFN			_PCI_DEVFN(0x13, 1)
+#define PCIEA2_DEVFN			_PCI_DEVFN(0x13, 2)
+#define PCIEA3_DEVFN			_PCI_DEVFN(0x13, 3)
+#define PCIEB0_DEVFN			_PCI_DEVFN(0x14, 0)
+#define PCIEB1_DEVFN			_PCI_DEVFN(0x14, 1)
+
+#define XHCI_DEV			_PCI_DEV(0x15, 0)
+#define XHCI_DEVFN			_PCI_DEVFN(0x15, 0)
+
+#define XDCI_DEV			_PCI_DEV(0x15, 1)
+#define XDCI_DEVFN			_PCI_DEVFN(0x15, 1)
+
+/* LPSS I2C, 2 devices cover 8 controllers */
+#define LPSS_DEV_SLOT_I2C_D0		0x16
+#define  LPSS_DEVFN_I2C0		_LPSS_PCI_DEVFN(I2C_D0, 0)
+#define  LPSS_DEVFN_I2C1		_LPSS_PCI_DEVFN(I2C_D0, 1)
+#define  LPSS_DEVFN_I2C2		_LPSS_PCI_DEVFN(I2C_D0, 2)
+#define  LPSS_DEVFN_I2C3		_LPSS_PCI_DEVFN(I2C_D0, 3)
+#define LPSS_DEV_SLOT_I2C_D1		0x17
+#define  LPSS_DEVFN_I2C4		_LPSS_PCI_DEVFN(I2C_D1, 0)
+#define  LPSS_DEVFN_I2C5		_LPSS_PCI_DEVFN(I2C_D1, 1)
+#define  LPSS_DEVFN_I2C6		_LPSS_PCI_DEVFN(I2C_D1, 2)
+#define  LPSS_DEVFN_I2C7		_LPSS_PCI_DEVFN(I2C_D1, 3)
+
+/* LPSS UART */
+#define LPSS_DEV_SLOT_UART		0x18
+#define  LPSS_DEVFN_UART0		_LPSS_PCI_DEVFN(UART, 0)
+#define  LPSS_DEVFN_UART1		_LPSS_PCI_DEVFN(UART, 1)
+#define  LPSS_DEVFN_UART2		_LPSS_PCI_DEVFN(UART, 2)
+#define  LPSS_DEVFN_UART3		_LPSS_PCI_DEVFN(UART, 3)
+#define  LPSS_DEV_UART0			_LPSS_PCI_DEV(UART, 0)
+#define  LPSS_DEV_UART1			_LPSS_PCI_DEV(UART, 1)
+#define  LPSS_DEV_UART2			_LPSS_PCI_DEV(UART, 2)
+#define  LPSS_DEV_UART3			_LPSS_PCI_DEV(UART, 3)
+
+/* LPSS SPI */
+#define LPSS_DEV_SLOT_SPI		0x19
+#define  LPSS_DEVFN_SPI0		_LPSS_PCI_DEVFN(SPI, 0)
+#define  LPSS_DEVFN_SPI1		_LPSS_PCI_DEVFN(SPI, 1)
+#define  LPSS_DEVFN_SPI2		_LPSS_PCI_DEVFN(SPI, 2)
+
+/* LPSS PWM */
+#define LPSS_DEV_SLOT_PWM		0x1a
+#define  LPSS_DEVFN_PWM			_LPSS_PCI_DEVFN(PWM, 0)
+
+#define SDCARD_DEV			_PCI_DEV(0x1b, 0)
+#define SDCARD_DEVFN			_PCI_DEVFN(0x1b, 0)
+
+#define EMMC_DEV			_PCI_DEV(0x1c, 0)
+#define EMMC_DEVFN			_PCI_DEVFN(0x1c, 0)
+
+#define SDIO_DEV			_PCI_DEV(0x1e, 0)
+#define SDIO_DEVFN			_PCI_DEVFN(0x1e, 0)
+
+#define LPC_DEV				_PCI_DEV(0x1f, 0)
+#define LPC_DEVFN			_PCI_DEVFN(0x1f, 0)
+
+#define SMBUS_DEV			_PCI_DEV(0x1f, 1)
+#define SMBUS_DEVFN			_PCI_DEVFN(0x1f, 1)
+
+#endif
diff --git a/src/soc/intel/glk/include/soc/pci_ids.h b/src/soc/intel/glk/include/soc/pci_ids.h
new file mode 100644
index 0000000..e1adc21
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/pci_ids.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_PCI_IDS_H_
+#define _SOC_GLK_PCI_IDS_H_
+
+#define PCI_DEVICE_ID_APOLLOLAKE_NB		0x5af0		/* 00:00.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_IGD_HD_505	0x5a84		/* 00:02.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_IGD_HD_500	0x5a85		/* 00:02.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_P2SB		0x5a92		/* 00:0d.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_PMC		0x5a94		/* 00:0d.1 */
+#define PCI_DEVICE_ID_APOLLOLAKE_HWSEQ_SPI	0x5a96		/* 00:0d.2 */
+#define PCI_DEVICE_ID_APOLLOLAKE_AUDIO		0x5a98		/* 00:0e.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_SATA		0x5ae0		/* 00:12.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_XHCI		0x5aa8		/* 00:15.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C0		0x5aac		/* 00:16.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C1		0x5aae		/* 00:16.1 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C2		0x5ab0		/* 00:16.2 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C3		0x5ab2		/* 00:16.3 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C4		0x5ab4		/* 00:17.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C5		0x5ab6		/* 00:17.1 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C6		0x5ab8		/* 00:17.2 */
+#define PCI_DEVICE_ID_APOLLOLAKE_I2C7		0x5aba		/* 00:17.3 */
+#define PCI_DEVICE_ID_APOLLOLAKE_UART0		0x5abc		/* 00:18.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_UART1		0x5abe		/* 00:18.1 */
+#define PCI_DEVICE_ID_APOLLOLAKE_UART2		0x5ac0		/* 00:18.2 */
+#define PCI_DEVICE_ID_APOLLOLAKE_UART3		0x5aee		/* 00:18.3 */
+#define PCI_DEVICE_ID_APOLLOLAKE_SPI0		0x5ac2		/* 00:19.0 */
+#define PCI_DEVICE_ID_APOLLOLAKE_SPI1		0x5ac4		/* 00:19.1 */
+#define PCI_DEVICE_ID_APOLLOLAKE_SPI2		0x5ac6		/* 00:19.2 */
+#define PCI_DEVICE_ID_APOLLOLAKE_LPC		0x5ae8		/* 00:1f.0 */
+
+#endif /* _SOC_GLK_PCI_IDS_H_ */
diff --git a/src/soc/intel/glk/include/soc/pm.h b/src/soc/intel/glk/include/soc/pm.h
new file mode 100644
index 0000000..3805649
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/pm.h
@@ -0,0 +1,216 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_PM_H_
+#define _SOC_GLK_PM_H_
+
+#include <stdint.h>
+#include <arch/acpi.h>
+
+/* ACPI_BASE_ADDRESS */
+
+#define PM1_STS			0x00
+#define   WAK_STS		(1 << 15)
+#define   PCIEXPWAK_STS		(1 << 14)
+#define   PRBTNOR_STS		(1 << 11)
+#define   RTC_STS		(1 << 10)
+#define   PWRBTN_STS		(1 << 8)
+#define   GBL_STS		(1 << 5)
+
+#define PM1_EN			0x02
+#define   PCIEXPWAK_DIS		(1 << 14)
+#define   RTC_EN		(1 << 10)
+#define   PWRBTN_EN     	(1 << 8)
+#define   GBL_EN        	(1 << 5)
+
+#define PM1_CNT			0x04
+#define   SCI_EN		(1 << 0)
+
+#define PM1_TMR			0x08
+
+#define SMI_EN			0x40
+
+#define SMI_OCP_CSE		27
+#define SMI_SPI			26
+#define SMI_SPI_SSMI		25
+#define SMI_SCC2		21
+#define SMI_PCIE		20
+#define SMI_SCS			19
+#define SMI_HOST_SMBUS		18
+#define SMI_XHCI		17
+#define SMI_SMBUS		16
+#define SMI_SERIRQ		15
+#define SMI_PERIODIC		14
+#define SMI_TCO			13
+#define SMI_MCSMI		12
+#define SMI_GPIO_UNLOCK_SSMI	11
+#define SMI_GPIO		10
+#define SMI_BIOS_RLS		7
+#define SMI_SWSMI_TMR		6
+#define SMI_APMC		5
+#define SMI_SLP			4
+#define SMI_LEGACY_USB		3
+#define SMI_BIOS		2
+#define SMI_EOS			1
+#define SMI_GBL			0
+
+#define   USB_EN		(1 << SMI_XHCI) /* Legacy USB2 SMI logic */
+#define   PERIODIC_EN		(1 << SMI_PERIODIC) /* SMI on PERIODIC_STS in SMI_STS */
+#define   TCO_EN		(1 << SMI_TCO) /* Enable TCO Logic (BIOSWE et al) */
+#define   GPIO_EN		(1 << SMI_GPIO) /* Enable GPIO SMI */
+#define   BIOS_RLS		(1 << SMI_BIOS_RLS) /* asserts SCI on bit set */
+#define   SWSMI_TMR_EN		(1 << SMI_SWSMI_TMR) /* start software smi timer on bit set */
+#define   APMC_EN		(1 << SMI_APMC) /* Writes to APM_CNT cause SMI# */
+#define   SLP_SMI_EN		(1 << SMI_SLP) /* Write to SLP_EN in PM1_CNT asserts SMI# */
+#define   BIOS_EN		(1 << SMI_BIOS) /* Assert SMI# on GBL_RLS bit */
+#define   EOS			(1 << SMI_EOS) /* End of SMI (deassert SMI#) */
+#define   GBL_SMI_EN		(1 << SMI_GBL) /* Global SMI Enable */
+
+#define SMI_STS			0x44
+/* Bits for SMI status */
+#define  PMC_OCP_SMI_STS	27
+#define  SPI_SMI_STS		26
+#define  SPI_SSMI_STS		25
+#define  SCC2_SMI_STS		21
+#define  PCIE_SMI_STS		20
+#define  SCS_SMI_STS		19
+#define  HSMBUS_SMI_STS		18
+#define  XHCI_SMI_STS		17
+#define  SMBUS_SMI_STS		16
+#define  SERIRQ_SMI_STS		15
+#define  PERIODIC_SMI_STS	14
+#define  TCO_SMI_STS		13
+#define  MC_SMI_STS		12
+#define  GPIO_UNLOCK_SMI_STS	11
+#define  GPIO_SMI_STS		10
+#define  FAKE_PM1_SMI_STS	8
+#define  SWSMI_TMR_SMI_STS	6
+#define  APM_SMI_STS		5
+#define  SLP_SMI_STS		4
+#define  LEGACY_USB_SMI_STS	3
+#define  BIOS_SMI_STS		2
+
+#define GPE_CNTL		0x50
+#define DEVACT_STS		0x4c
+#define TCO_STS			0x64
+#define   TCO_TIMEOUT		(1 << 3)
+#define TCO1_CNT		0x68
+#define   TCO_TMR_HLT		(1 << 11)
+
+#define GPE0_REG_MAX		4
+#define GPE0_REG_SIZE		32
+#define GPE0_STS(x)		(0x20 + (x * 4))
+#define  GPE0_A			0
+#define  GPE0_B			1
+#define  GPE0_C			2
+#define  GPE0_D			3
+#define   SATA_PME_STS		(1 << 17)
+#define   SMB_WAK_STS		(1 << 16)
+#define   AVS_PME_STS		(1 << 14)
+#define   XHCI_PME_STS		(1 << 13)
+#define   XDCI_PME_STS		(1 << 12)
+#define   CSE_PME_STS		(1 << 11)
+#define   BATLOW_STS		(1 << 10)
+#define   PCIE_GPE_STS		(1 << 9)
+#define   SWGPE_STS		(1 << 2)
+#define GPE0_EN(x)		(0x30 + (x * 4))
+#define   SATA_PME_EN		(1 << 17)
+#define   SMB_WAK_EN		(1 << 16)
+#define   AVS_PME_EN		(1 << 14)
+#define   PME_B0_EN		(1 << 13)
+#define   XDCI_PME_EN		(1 << 12)
+#define   CSE_PME_EN		(1 << 11)
+#define   BATLOW_EN		(1 << 10)
+#define   PCIE_GPE_EN		(1 << 9)
+#define   SWGPE_EN		(1 << 2)
+
+/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
+#define PRSTS			0x1000
+#define GEN_PMCON1		0x1020
+#define  SRS			(1 << 20)
+#define  RPS			(1 << 2)
+#define GEN_PMCON2		0x1024
+#define GEN_PMCON3		0x1028
+#       define SLP_S3_ASSERT_WIDTH_SHIFT	10
+#       define SLP_S3_ASSERT_MASK	(0x3 << SLP_S3_ASSERT_WIDTH_SHIFT)
+#       define SLP_S3_ASSERT_60_USEC	0x0
+#       define SLP_S3_ASSERT_1_MSEC	0x1
+#       define SLP_S3_ASSERT_50_MSEC	0x2
+#       define SLP_S3_ASSERT_2_SEC	0x3
+#define ETR			0x1048
+#       define CF9_LOCK         (1 << 31)
+#       define CF9_GLB_RST      (1 << 20)
+#define GPIO_GPE_CFG		0x1050
+#define  GPE0_DWX_MASK		0xf
+#define  GPE0_DW1_SHIFT		4
+#define  GPE0_DW2_SHIFT		8
+#define  GPE0_DW3_SHIFT		12
+
+#define  PMC_GPE_SW_31_0	0
+#define  PMC_GPE_SW_63_32	1
+#define  PMC_GPE_NW_31_0	3
+#define  PMC_GPE_NW_63_32	4
+#define  PMC_GPE_NW_95_64	5
+#define  PMC_GPE_N_31_0		6
+#define  PMC_GPE_N_63_32	7
+#define  PMC_GPE_W_31_0		9
+
+/* Track power state from reset to log events. */
+struct chipset_power_state {
+	uint16_t pm1_sts;
+	uint16_t pm1_en;
+	uint32_t pm1_cnt;
+	uint32_t gpe0_sts[GPE0_REG_MAX];
+	uint32_t gpe0_en[GPE0_REG_MAX];
+	uint32_t tco_sts;
+	uint32_t prsts;
+	uint32_t gen_pmcon1;
+	uint32_t gen_pmcon2;
+	uint32_t gen_pmcon3;
+	uint32_t prev_sleep_state;
+} __attribute__((packed));
+
+int fill_power_state(struct chipset_power_state *ps);
+int chipset_prev_sleep_state(struct chipset_power_state *ps);
+/* Rewrite the gpe0 registers in cbmem to proper values as per routing table */
+void fixup_power_state(void);
+
+/* Power Management Utility Functions. */
+uint32_t clear_smi_status(void);
+uint16_t clear_pm1_status(void);
+uint32_t clear_tco_status(void);
+uint32_t clear_gpe_status(void);
+void clear_pmc_status(void);
+void clear_gpi_gpe_sts(void);
+uint32_t get_smi_en(void);
+void enable_smi(uint32_t mask);
+void disable_smi(uint32_t mask);
+void enable_pm1(uint16_t events);
+void enable_pm1_control(uint32_t mask);
+void disable_pm1_control(uint32_t mask);
+void enable_gpe(uint32_t mask);
+void disable_gpe(uint32_t mask);
+void disable_all_gpe(void);
+uintptr_t get_pmc_mmio_bar(void);
+void pmc_gpe_init(void);
+
+void global_reset_enable(bool enable);
+void global_reset_lock(void);
+
+void pch_log_state(void);
+
+#endif
diff --git a/src/soc/intel/glk/include/soc/romstage.h b/src/soc/intel/glk/include/soc/romstage.h
new file mode 100644
index 0000000..fb046ef
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/romstage.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_ROMSTAGE_H_
+#define _SOC_GLK_ROMSTAGE_H_
+
+#include <arch/cpu.h>
+#include <fsp/api.h>
+
+void mainboard_memory_init_params(FSPM_UPD *mupd);
+void mainboard_save_dimm_info(void);
+
+#endif /* _SOC_GLK_ROMSTAGE_H_ */
diff --git a/src/soc/intel/glk/include/soc/smm.h b/src/soc/intel/glk/include/soc/smm.h
new file mode 100644
index 0000000..7a9846e
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/smm.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_SMM_H_
+#define _SOC_SMM_H_
+
+#include <stdint.h>
+#include <soc/gpio.h>
+
+/* These helpers are for performing SMM relocation. */
+void southbridge_clear_smi_status(void);
+
+/*
+ * The initialization of the southbridge is split into 2 compoments. One is
+ * for clearing the state in the SMM registers. The other is for enabling
+ * SMIs.
+ */
+void southbridge_smm_clear_state(void);
+void southbridge_smm_enable_smi(void);
+
+/* Mainboard handler for GPI SMIs*/
+void mainboard_smi_gpi_handler(const struct gpi_status *sts);
+
+/* Fills in the arguments for the entire SMM region covered by chipset
+ * protections. e.g. TSEG. */
+void smm_region(void **start, size_t *size);
+#endif
diff --git a/src/soc/intel/glk/include/soc/spi.h b/src/soc/intel/glk/include/soc/spi.h
new file mode 100644
index 0000000..7acdfb8
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/spi.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_SPI_H_
+#define _SOC_GLK_SPI_H_
+
+/* PCI configuration registers */
+#define SPIBAR_BIOS_CONTROL		0xdc
+/* Bit definitions for BIOS_CONTROL */
+#define  SPIBAR_BIOS_CONTROL_WPD		(1 << 0)
+#define  SPIBAR_BIOS_CONTROL_CACHE_DISABLE	(1 << 2)
+#define  SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE	(1 << 3)
+#define  SPIBAR_BIOS_CONTROL_EISS		(1 << 5)
+
+/* Maximum bytes of data that can fit in FDATAn registers */
+#define SPIBAR_FDATA_FIFO_SIZE		0x40
+
+/* Register offsets from the MMIO region base (PCI_BASE_ADDRESS_0) */
+#define SPIBAR_BIOS_BFPREG		0x00
+#define SPIBAR_HSFSTS_CTL		0x04
+#define SPIBAR_FADDR			0x08
+#define SPIBAR_FDATA(n)			(0x10 + ((n) & 0xf) * 4)
+#define SPIBAR_PTINX			0xcc
+#define SPIBAR_PTDATA			0xd0
+
+/* Bit definitions and masks for BIOS_BFPREG register. */
+#define  SPIBAR_BFPREG_PRB_MASK	(0x7fff)
+#define  SPIBAR_BFPREG_PRL_SHIFT	(16)
+#define  SPIBAR_BFPREG_PRL_MASK	(0x7fff << SPIBAR_BFPREG_PRL_SHIFT)
+#define  SPIBAR_BFPREG_SBRS		(1 << 31)
+
+/* Bit definitions for HSFSTS_CTL register */
+#define  SPIBAR_HSFSTS_FBDC_MASK	(0x3f << 24)
+#define  SPIBAR_HSFSTS_FBDC(n)		(((n) << 24) & SPIBAR_HSFSTS_FBDC_MASK)
+#define  SPIBAR_HSFSTS_WET		(1 << 21)
+#define  SPIBAR_HSFSTS_FCYCLE_MASK	(0xf << 17)
+#define  SPIBAR_HSFSTS_FCYCLE(cyc)	(((cyc) << 17) & SPIBAR_HSFSTS_FCYCLE_MASK)
+#define  SPIBAR_HSFSTS_FGO		(1 << 16)
+#define  SPIBAR_HSFSTS_FLOCKDN		(1 << 15)
+#define  SPIBAR_HSFSTS_FDV		(1 << 14)
+#define  SPIBAR_HSFSTS_FDOPSS		(1 << 13)
+#define  SPIBAR_HSFSTS_SAF_CE		(1 << 8)
+#define  SPIBAR_HSFSTS_SAF_ACTIVE	(1 << 7)
+#define  SPIBAR_HSFSTS_SAF_LE		(1 << 6)
+#define  SPIBAR_HSFSTS_SCIP		(1 << 5)
+#define  SPIBAR_HSFSTS_SAF_DLE		(1 << 4)
+#define  SPIBAR_HSFSTS_SAF_ERROR	(1 << 3)
+#define  SPIBAR_HSFSTS_AEL		(1 << 2)
+#define  SPIBAR_HSFSTS_FCERR		(1 << 1)
+#define  SPIBAR_HSFSTS_FDONE		(1 << 0)
+#define  SPIBAR_HSFSTS_W1C_BITS	(0xff)
+/* Supported flash cycle types */
+#define  SPIBAR_HSFSTS_CYCLE_READ	SPIBAR_HSFSTS_FCYCLE(0)
+#define  SPIBAR_HSFSTS_CYCLE_WRITE	SPIBAR_HSFSTS_FCYCLE(2)
+#define  SPIBAR_HSFSTS_CYCLE_4K_ERASE	SPIBAR_HSFSTS_FCYCLE(3)
+#define  SPIBAR_HSFSTS_CYCLE_64K_ERASE	SPIBAR_HSFSTS_FCYCLE(4)
+#define  SPIBAR_HSFSTS_CYCLE_RD_STATUS	SPIBAR_HSFSTS_FCYCLE(8)
+
+/* Bit definitions for PTINX register */
+#define  SPIBAR_PTINX_COMP_0		(0 << 14)
+#define  SPIBAR_PTINX_COMP_1		(1 << 14)
+#define  SPIBAR_PTINX_HORD_SFDP		(0 << 12)
+#define  SPIBAR_PTINX_HORD_PARAM	(1 << 12)
+#define  SPIBAR_PTINX_HORD_JEDEC	(2 << 12)
+#define  SPIBAR_PTINX_IDX_MASK		0xffc
+
+/*
+ * Reads status register. On success returns 0 and status contains the value
+ * read from the status register. On error returns -1.
+ */
+int spi_read_status(uint8_t *status);
+
+/* Read SPI controller register. */
+uint32_t spi_ctrlr_reg_read(uint16_t reg);
+#endif
diff --git a/src/soc/intel/glk/include/soc/uart.h b/src/soc/intel/glk/include/soc/uart.h
new file mode 100644
index 0000000..4a71c0a
--- /dev/null
+++ b/src/soc/intel/glk/include/soc/uart.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_GLK_UART_H_
+#define _SOC_GLK_UART_H_
+
+/* Clock is 100MHz * (M / N).*/
+#define UART_CLK		0x200
+# define UART_CLK_UPDATE	(1 << 31)
+# define UART_CLK_DIV_N(n)	(((n) & 0x7fff) << 16)
+# define UART_CLK_DIV_M(m)	(((m) & 0x7fff) << 1)
+# define UART_CLK_EN		(1 << 0)
+#define UART_RESET		0x204
+# define UART_RESET_DMA_EN	(1 << 2)
+# define UART_RESET_UART_EN	(3 << 0)
+
+void lpss_console_uart_init(void);
+
+/* Initialize the console UART including the pads for the configured UART. */
+void soc_console_uart_init(void);
+
+#endif /* _SOC_GLK_UART_H_ */
diff --git a/src/soc/intel/glk/itss.c b/src/soc/intel/glk/itss.c
new file mode 100644
index 0000000..9c49d6c
--- /dev/null
+++ b/src/soc/intel/glk/itss.c
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ */
+
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <stdint.h>
+#include <soc/iosf.h>
+#include <soc/itss.h>
+
+#define IOSF_ITSS_PORT_ID	0xd0
+#define ITSS_MAX_IRQ		119
+#define IPC0			0x3200
+#define IRQS_PER_IPC		32
+#define NUM_IPC_REGS		((ITSS_MAX_IRQ + IRQS_PER_IPC - 1)/IRQS_PER_IPC)
+
+void itss_set_irq_polarity(int irq, int active_low)
+{
+	uint32_t mask;
+	uint32_t val;
+	uint16_t reg;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	if (irq < 0 || irq > ITSS_MAX_IRQ)
+		return;
+
+	reg = IPC0 + sizeof(uint32_t) * (irq / IRQS_PER_IPC);
+	mask = 1 << (irq % IRQS_PER_IPC);
+
+	val = iosf_read(port, reg);
+	val &= ~mask;
+	/* Setting the bit makes the IRQ active low. */
+	val |= active_low ? mask : 0;
+	iosf_write(port, reg, val);
+}
+
+static uint32_t irq_snapshot[NUM_IPC_REGS];
+
+void itss_snapshot_irq_polarities(int start, int end)
+{
+	int i;
+	int reg_start;
+	int reg_end;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	if (start < 0 || start > ITSS_MAX_IRQ ||
+	    end < 0 || end > ITSS_MAX_IRQ || end < start)
+		return;
+
+	reg_start = start / IRQS_PER_IPC;
+	reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+
+	for (i = reg_start; i < reg_end; i++) {
+		uint16_t reg = IPC0 + sizeof(uint32_t) * i;
+		irq_snapshot[i] = iosf_read(port, reg);
+	}
+}
+
+static void show_irq_polarities(const char *msg)
+{
+	int i;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	printk(BIOS_INFO, "ITSS IRQ Polarities %s:\n", msg);
+	for (i = 0; i < NUM_IPC_REGS; i++) {
+		uint16_t reg = IPC0 + sizeof(uint32_t) * i;
+		printk(BIOS_INFO, "IPC%d: 0x%08x\n", i, iosf_read(port, reg));
+	}
+}
+
+void itss_restore_irq_polarities(int start, int end)
+{
+	int i;
+	int reg_start;
+	int reg_end;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	if (start < 0 || start > ITSS_MAX_IRQ ||
+	    end < 0 || end > ITSS_MAX_IRQ || end < start)
+		return;
+
+	show_irq_polarities("Before");
+
+	reg_start = start / IRQS_PER_IPC;
+	reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+
+	for (i = reg_start; i < reg_end; i++) {
+		uint32_t mask;
+		uint32_t val;
+		uint16_t reg;
+		int irq_start;
+		int irq_end;
+
+		irq_start = i * IRQS_PER_IPC;
+		irq_end = MIN(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ);
+
+		if (start > irq_end)
+			continue;
+		if (end < irq_start)
+			break;
+
+		/* Track bits within the bounds of of the register. */
+		irq_start = MAX(start, irq_start) % IRQS_PER_IPC;
+		irq_end = MIN(end, irq_end) % IRQS_PER_IPC;
+
+		/* Create bitmask of the inclusive range of start and end. */
+		mask = (((1U << irq_end) - 1) | (1U << irq_end));
+		mask &= ~((1U << irq_start) - 1);
+
+		reg = IPC0 + sizeof(uint32_t) * i;
+		val = iosf_read(port, reg);
+		val &= ~mask;
+		val |= mask & irq_snapshot[i];
+		iosf_write(port, reg, val);
+	}
+
+	show_irq_polarities("After");
+}
diff --git a/src/soc/intel/glk/lpc.c b/src/soc/intel/glk/lpc.c
new file mode 100644
index 0000000..aec8a9f
--- /dev/null
+++ b/src/soc/intel/glk/lpc.c
@@ -0,0 +1,176 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <pc80/mc146818rtc.h>
+#include <soc/acpi.h>
+#include <soc/lpc.h>
+#include <soc/pci_ids.h>
+#include <soc/pm.h>
+#include <vboot/vbnv.h>
+
+#include "chip.h"
+
+/*
+ * SCOPE:
+ * The purpose of this driver is to eliminate manual resource allocation for
+ * devices under the LPC bridge.
+ *
+ * BACKGROUND:
+ * The resource allocator reserves IO and memory resources to devices on the
+ * LPC bus, but it is up to the hardware driver to make sure that those
+ * resources are decoded to the LPC bus. This is what this driver does.
+ *
+ * THEORY OF OPERATION:
+ * The .scan_bus member of the driver's ops will scan the static device tree
+ * (devicetree.cb) and invoke drivers of devices on the LPC bus. This creates
+ * a list of child devices, along with their resources. set_child_resources()
+ * parses that list and looks for resources needed by the child devices. It
+ * opens up IO and memory windows as needed.
+ */
+
+static void rtc_init(void)
+{
+	int rtc_fail;
+	const struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+
+	if (!ps) {
+		printk(BIOS_ERR, "Could not find power state in cbmem, RTC init aborted\n");
+		return;
+	}
+
+	rtc_fail = !!(ps->gen_pmcon1 & RPS);
+	/* Ensure the date is set including century byte. */
+	cmos_check_update_date();
+	if (IS_ENABLED(CONFIG_VBOOT_VBNV_CMOS))
+		init_vbnv_cmos(rtc_fail);
+	else
+		cmos_init(rtc_fail);
+}
+
+static void lpc_init(struct device *dev)
+{
+	uint8_t scnt;
+	struct soc_intel_glk_config *cfg;
+
+	cfg = dev->chip_info;
+	if (!cfg) {
+		printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+		return;
+	}
+
+	scnt = pci_read_config8(dev, REG_SERIRQ_CTL);
+	scnt &= ~(SCNT_EN | SCNT_MODE);
+	if (cfg->serirq_mode == SERIRQ_QUIET)
+		scnt |= SCNT_EN;
+	else if (cfg->serirq_mode == SERIRQ_CONTINUOUS)
+		scnt |= SCNT_EN | SCNT_MODE;
+	pci_write_config8(dev, REG_SERIRQ_CTL, scnt);
+
+	/* Initialize RTC */
+	rtc_init();
+}
+
+static void soc_lpc_add_io_resources(device_t dev)
+{
+	struct resource *res;
+
+	/* Add the default claimed legacy IO range for the LPC device. */
+	res = new_resource(dev, 0);
+	res->base = 0;
+	res->size = 0x1000;
+	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void soc_lpc_read_resources(device_t dev)
+{
+	/* Get the PCI resources of this device. */
+	pci_dev_read_resources(dev);
+
+	/* Add IO resources to LPC. */
+	soc_lpc_add_io_resources(dev);
+}
+
+static void set_child_resources(struct device *dev);
+
+static void loop_resources(struct device *dev)
+{
+	struct resource *res;
+
+	for (res = dev->resource_list; res; res = res->next) {
+
+		if (res->flags & IORESOURCE_IO) {
+			lpc_open_pmio_window(res->base, res->size);
+		}
+
+		if (res->flags & IORESOURCE_MEM) {
+			/* Check if this is already decoded. */
+			if (lpc_fits_fixed_mmio_window(res->base, res->size))
+				continue;
+
+			lpc_open_mmio_window(res->base, res->size);
+		}
+
+	}
+	set_child_resources(dev);
+}
+
+/*
+ * Loop through all the child devices' resources, and open up windows to the
+ * LPC bus, as appropriate.
+ */
+static void set_child_resources(struct device *dev)
+{
+	struct bus *link;
+	struct device *child;
+
+	for (link = dev->link_list; link; link = link->next) {
+		for (child = link->children; child; child = child->sibling) {
+			loop_resources(child);
+		}
+	}
+}
+
+static void set_resources(device_t dev)
+{
+	pci_dev_set_resources(dev);
+
+	/* Close all previously opened windows and allocate from scratch. */
+	lpc_close_pmio_windows();
+	/* Now open up windows to devices which have declared resources. */
+	set_child_resources(dev);
+}
+
+static struct device_operations device_ops = {
+	.read_resources = &soc_lpc_read_resources,
+	.set_resources = set_resources,
+	.enable_resources = &pci_dev_enable_resources,
+	.write_acpi_tables = southbridge_write_acpi_tables,
+	.acpi_inject_dsdt_generator = southbridge_inject_dsdt,
+	.init = lpc_init,
+	.scan_bus = scan_lpc_bus,
+};
+
+static const struct pci_driver soc_lpc __pci_driver = {
+	.ops = &device_ops,
+	.vendor = PCI_VENDOR_ID_INTEL,
+	.device = PCI_DEVICE_ID_APOLLOLAKE_LPC,
+};
diff --git a/src/soc/intel/glk/lpc_lib.c b/src/soc/intel/glk/lpc_lib.c
new file mode 100644
index 0000000..5bda51d
--- /dev/null
+++ b/src/soc/intel/glk/lpc_lib.c
@@ -0,0 +1,180 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define __SIMPLE_DEVICE__
+
+#include <console/console.h>
+#include <device/pci.h>
+#include <lib.h>
+#include <soc/gpio.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+
+/*
+ * These are MMIO ranges that the silicon designers decided are always going to
+ * be decoded to LPC.
+ */
+static const struct lpc_mmio_range {
+	uintptr_t base;
+	size_t size;
+} lpc_fixed_mmio_ranges[] = {
+	{ 0xfed40000, 0x8000 },
+	{ 0xfedc0000, 0x4000 },
+	{ 0xfed20800, 16 },
+	{ 0xfed20880, 8 },
+	{ 0xfed208e0, 16 },
+	{ 0xfed208f0, 8 },
+	{ 0xfed30800, 16 },
+	{ 0xfed30880, 8 },
+	{ 0xfed308e0, 16 },
+	{ 0xfed308f0, 8 },
+	{ 0, 0 }
+};
+
+static const struct pad_config lpc_gpios[] = {
+};
+
+void lpc_configure_pads(void)
+{
+	gpio_configure_pads(lpc_gpios, ARRAY_SIZE(lpc_gpios));
+}
+
+void lpc_enable_fixed_io_ranges(uint16_t io_enables)
+{
+	uint16_t reg_io_enables;
+
+	reg_io_enables = pci_read_config16(LPC_DEV, REG_IO_ENABLES);
+	io_enables |= reg_io_enables;
+	pci_write_config16(LPC_DEV, REG_IO_ENABLES, io_enables);
+}
+
+/*
+ * Find the first unused IO window.
+ * Returns -1 if not found, 0 for reg 0x84, 1 for reg 0x88 ...
+ */
+static int find_unused_pmio_window(void)
+{
+	int i;
+	uint32_t lgir;
+
+	for (i = 0; i < NUM_GENERIC_IO_RANGES; i++) {
+		lgir = pci_read_config32(LPC_DEV, REG_GENERIC_IO_RANGE(i));
+
+		if (!(lgir & LGIR_EN))
+			return i;
+	}
+
+	return -1;
+}
+
+void lpc_close_pmio_windows(void)
+{
+	size_t i;
+
+	for (i = 0; i < NUM_GENERIC_IO_RANGES; i++)
+		pci_write_config32(LPC_DEV, REG_GENERIC_IO_RANGE(i), 0);
+}
+
+void lpc_open_pmio_window(uint16_t base, uint16_t size)
+{
+	int lgir_reg_num;
+	uint32_t lgir_reg_offset, lgir, window_size, alignment;
+	resource_t bridged_size, bridge_base;
+
+	printk(BIOS_SPEW, "LPC: Trying to open IO window from %x size %x\n",
+				base, size);
+
+	bridged_size = 0;
+	bridge_base = base;
+
+	while (bridged_size < size) {
+		lgir_reg_num = find_unused_pmio_window();
+		if (lgir_reg_num < 0) {
+			printk(BIOS_ERR,
+				"LPC: Cannot open IO window: %llx size %llx\n",
+				bridge_base, size - bridged_size);
+			printk(BIOS_ERR, "No more IO windows\n");
+			return;
+		}
+		lgir_reg_offset = REG_GENERIC_IO_RANGE(lgir_reg_num);
+
+		/* Each IO range register can only open a 256-byte window. */
+		window_size = MIN(size, LGIR_MAX_WINDOW_SIZE);
+
+		/* Window size must be a power of two for the AMASK to work. */
+		alignment = 1 << (log2_ceil(window_size));
+		window_size = ALIGN_UP(window_size, alignment);
+
+		/* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18]. */
+		lgir = (bridge_base & LGIR_ADDR_MASK) | LGIR_EN;
+		lgir |= ((window_size - 1) << 16) & LGIR_AMASK_MASK;
+
+		pci_write_config32(LPC_DEV, lgir_reg_offset, lgir);
+
+		printk(BIOS_DEBUG,
+		       "LPC: Opened IO window LGIR%d: base %llx size %x\n",
+		       lgir_reg_num, bridge_base, window_size);
+
+		bridged_size += window_size;
+		bridge_base += window_size;
+	}
+}
+
+void lpc_open_mmio_window(uintptr_t base, size_t size)
+{
+	uint32_t lgmr;
+
+	lgmr = pci_read_config32(LPC_DEV, REG_GENERIC_MEM_RANGE);
+
+	if (lgmr & LGMR_EN) {
+		printk(BIOS_ERR,
+		       "LPC: Cannot open window to resource %lx size %zx\n",
+		       base, size);
+		printk(BIOS_ERR, "LPC: MMIO window already in use\n");
+		return;
+	}
+
+	if (size > LGMR_WINDOW_SIZE) {
+		printk(BIOS_WARNING,
+		       "LPC:  Resource %lx size %zx larger than window(%x)\n",
+		       base, size, LGMR_WINDOW_SIZE);
+	}
+
+	lgmr = (base & LGMR_ADDR_MASK) | LGMR_EN;
+
+	pci_write_config32(LPC_DEV, REG_GENERIC_MEM_RANGE, lgmr);
+}
+
+bool lpc_fits_fixed_mmio_window(uintptr_t base, size_t size)
+{
+	resource_t res_end, range_end;
+	const struct lpc_mmio_range *range;
+
+	for (range = lpc_fixed_mmio_ranges; range->size; range++) {
+		range_end = range->base + range->size;
+		res_end = base + size;
+
+		if ((base >= range->base) && (res_end <= range_end)) {
+			printk(BIOS_DEBUG,
+			       "Resource %lx size %zx fits in fixed window"
+			       " %lx size %zx\n",
+			       base, size, range->base, range->size);
+			return true;
+		}
+	}
+	return false;
+}
diff --git a/src/soc/intel/glk/meminit.c b/src/soc/intel/glk/meminit.c
new file mode 100644
index 0000000..0f553ee
--- /dev/null
+++ b/src/soc/intel/glk/meminit.c
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <cbmem.h>
+#include <console/console.h>
+#include <fsp/util.h>
+#include <memory_info.h>
+#include <smbios.h>
+#include <soc/meminit.h>
+#include <stddef.h> /* required for FspmUpd.h */
+#include <fsp/soc_binding.h>
+#include <string.h>
+
+static void set_lpddr4_defaults(FSP_M_CONFIG *cfg)
+{
+	/* Enable memory down BGA since it's the only LPDDR4 packaging. */
+	cfg->Package = 1;
+	cfg->MemoryDown = 1;
+
+	cfg->ScramblerSupport = 1;
+	cfg->ChannelHashMask = 0x36;
+	cfg->SliceHashMask = 0x9;
+	cfg->InterleavedMode = 2;
+	cfg->ChannelsSlicesEnable = 0;
+	cfg->MinRefRate2xEnable = 0;
+	cfg->DualRankSupportEnable = 1;
+	/* Don't enforce a memory size limit. */
+	cfg->MemorySizeLimit = 0;
+	/* Use a 2GiB I/O hole -- field is in MiB units. */
+	cfg->LowMemoryMaxValue = 2 * (GiB/MiB);
+	/* No restrictions on memory above 4GiB */
+	cfg->HighMemoryMaxValue = 0;
+
+	/* Always default to attempt to use saved training data. */
+	cfg->DisableFastBoot = 0;
+
+	/* LPDDR4 is memory down so no SPD addresses. */
+	cfg->DIMM0SPDAddress = 0;
+	cfg->DIMM1SPDAddress = 0;
+
+	/* Clear all the rank enables. */
+	cfg->Ch0_RankEnable = 0x0;
+	cfg->Ch1_RankEnable = 0x0;
+	cfg->Ch2_RankEnable = 0x0;
+	cfg->Ch3_RankEnable = 0x0;
+
+	/*
+	 * Set the device width to x16 which is half a LPDDR4 module as that's
+	 * what the reference code expects.
+	 */
+	cfg->Ch0_DeviceWidth = 0x1;
+	cfg->Ch1_DeviceWidth = 0x1;
+	cfg->Ch2_DeviceWidth = 0x1;
+	cfg->Ch3_DeviceWidth = 0x1;
+
+	/*
+	 * Enable bank hashing (bit 1) and rank interleaving (bit 0) with
+	 * a 1KiB address mapping (bits 5:4).
+	 */
+	cfg->Ch0_Option = 0x3;
+	cfg->Ch1_Option = 0x3;
+	cfg->Ch2_Option = 0x3;
+	cfg->Ch3_Option = 0x3;
+
+	/* Weak on-die termination. */
+	cfg->Ch0_OdtConfig = 0;
+	cfg->Ch1_OdtConfig = 0;
+	cfg->Ch2_OdtConfig = 0;
+	cfg->Ch3_OdtConfig = 0;
+}
+
+void meminit_lpddr4(FSP_M_CONFIG *cfg, int speed)
+{
+	uint8_t profile;
+
+	switch (speed) {
+	case LP4_SPEED_1600:
+		profile = 0x9;
+		break;
+	case LP4_SPEED_2133:
+		profile = 0xa;
+		break;
+	case LP4_SPEED_2400:
+		profile = 0xb;
+		break;
+	default:
+		printk(BIOS_WARNING, "Invalid LPDDR4 speed: %d\n", speed);
+		/* Set defaults. */
+		speed = LP4_SPEED_1600;
+		profile = 0x9;
+	}
+
+	printk(BIOS_INFO, "LP4DDR speed is %dMHz\n", speed);
+	cfg->Profile = profile;
+
+	set_lpddr4_defaults(cfg);
+}
+
+static void enable_logical_chan0(FSP_M_CONFIG *cfg,
+					int rank_density, int dual_rank,
+					const struct lpddr4_swizzle_cfg *scfg)
+{
+	const struct lpddr4_chan_swizzle_cfg *chan;
+	/* Number of bytes to copy per DQS. */
+	const size_t sz = DQ_BITS_PER_DQS;
+	int rank_mask;
+
+	/*
+	 * Logical channel 0 is comprised of physical channel 0 and 1.
+	 * Physical channel 0 is comprised of the CH0_DQB signals.
+	 * Physical channel 1 is comprised of the CH0_DQA signals.
+	 */
+	cfg->Ch0_DramDensity = rank_density;
+	cfg->Ch1_DramDensity = rank_density;
+	/* Enable ranks on both channels depending on dual rank option. */
+	rank_mask = dual_rank ? 0x3 : 0x1;
+	cfg->Ch0_RankEnable = rank_mask;
+	cfg->Ch1_RankEnable = rank_mask;
+
+	/*
+	 * CH0_DQB byte lanes in the bit swizzle configuration field are
+	 * not 1:1. The mapping within the swizzling field is:
+	 *   indicies [0:7]   - byte lane 1 (DQS1) DQ[8:15]
+	 *   indicies [8:15]  - byte lane 0 (DQS0) DQ[0:7]
+	 *   indicies [16:23] - byte lane 3 (DQS3) DQ[24:31]
+	 *   indicies [24:31] - byte lane 2 (DQS2) DQ[16:23]
+	 */
+	chan = &scfg->phys[LP4_PHYS_CH0B];
+	memcpy(&cfg->Ch0_Bit_swizzling[0], &chan->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->Ch0_Bit_swizzling[8], &chan->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->Ch0_Bit_swizzling[16], &chan->dqs[LP4_DQS3], sz);
+	memcpy(&cfg->Ch0_Bit_swizzling[24], &chan->dqs[LP4_DQS2], sz);
+
+	/*
+	 * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
+	 */
+	chan = &scfg->phys[LP4_PHYS_CH0A];
+	memcpy(&cfg->Ch1_Bit_swizzling[0], &chan->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->Ch1_Bit_swizzling[8], &chan->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->Ch1_Bit_swizzling[16], &chan->dqs[LP4_DQS2], sz);
+	memcpy(&cfg->Ch1_Bit_swizzling[24], &chan->dqs[LP4_DQS3], sz);
+}
+
+static void enable_logical_chan1(FSP_M_CONFIG *cfg,
+					int rank_density, int dual_rank,
+					const struct lpddr4_swizzle_cfg *scfg)
+{
+	const struct lpddr4_chan_swizzle_cfg *chan;
+	/* Number of bytes to copy per DQS. */
+	const size_t sz = DQ_BITS_PER_DQS;
+	int rank_mask;
+
+	/*
+	 * Logical channel 1 is comprised of physical channel 2 and 3.
+	 * Physical channel 2 is comprised of the CH1_DQB signals.
+	 * Physical channel 3 is comprised of the CH1_DQA signals.
+	 */
+	cfg->Ch2_DramDensity = rank_density;
+	cfg->Ch3_DramDensity = rank_density;
+	/* Enable ranks on both channels depending on dual rank option. */
+	rank_mask = dual_rank ? 0x3 : 0x1;
+	cfg->Ch2_RankEnable = rank_mask;
+	cfg->Ch3_RankEnable = rank_mask;
+
+	/*
+	 * CH1_DQB byte lanes in the bit swizzle configuration field are
+	 * not 1:1. The mapping within the swizzling field is:
+	 *   indicies [0:7]   - byte lane 1 (DQS1) DQ[8:15]
+	 *   indicies [8:15]  - byte lane 0 (DQS0) DQ[0:7]
+	 *   indicies [16:23] - byte lane 3 (DQS3) DQ[24:31]
+	 *   indicies [24:31] - byte lane 2 (DQS2) DQ[16:23]
+	 */
+	chan = &scfg->phys[LP4_PHYS_CH1B];
+	memcpy(&cfg->Ch2_Bit_swizzling[0], &chan->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->Ch2_Bit_swizzling[8], &chan->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->Ch2_Bit_swizzling[16], &chan->dqs[LP4_DQS3], sz);
+	memcpy(&cfg->Ch2_Bit_swizzling[24], &chan->dqs[LP4_DQS2], sz);
+
+	/*
+	 * CH1_DQA byte lanes in the bit swizzle configuration field are 1:1.
+	 */
+	chan = &scfg->phys[LP4_PHYS_CH1A];
+	memcpy(&cfg->Ch3_Bit_swizzling[0], &chan->dqs[LP4_DQS0], sz);
+	memcpy(&cfg->Ch3_Bit_swizzling[8], &chan->dqs[LP4_DQS1], sz);
+	memcpy(&cfg->Ch3_Bit_swizzling[16], &chan->dqs[LP4_DQS2], sz);
+	memcpy(&cfg->Ch3_Bit_swizzling[24], &chan->dqs[LP4_DQS3], sz);
+}
+
+void meminit_lpddr4_enable_channel(FSP_M_CONFIG *cfg, int logical_chan,
+					int rank_density, int dual_rank,
+					const struct lpddr4_swizzle_cfg *scfg)
+{
+	if (rank_density < LP4_8Gb_DENSITY ||
+		rank_density > LP4_16Gb_DENSITY) {
+		printk(BIOS_ERR, "Invalid LPDDR4 density: %d\n", rank_density);
+		return;
+	}
+
+	switch (logical_chan) {
+	case LP4_LCH0:
+		enable_logical_chan0(cfg, rank_density, dual_rank, scfg);
+		break;
+	case LP4_LCH1:
+		enable_logical_chan1(cfg, rank_density, dual_rank, scfg);
+		break;
+	default:
+		printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan);
+		break;
+	}
+}
+
+void meminit_lpddr4_by_sku(FSP_M_CONFIG *cfg,
+				const struct lpddr4_cfg *lpcfg, size_t sku_id)
+{
+	const struct lpddr4_sku *sku;
+
+	if (sku_id >= lpcfg->num_skus) {
+		printk(BIOS_ERR, "Too few LPDDR4 SKUs: 0x%zx/0x%zx\n",
+			sku_id, lpcfg->num_skus);
+		return;
+	}
+
+	printk(BIOS_INFO, "LPDDR4 SKU id = 0x%zx\n", sku_id);
+
+	sku = &lpcfg->skus[sku_id];
+
+	meminit_lpddr4(cfg, sku->speed);
+
+	if (sku->ch0_rank_density) {
+		printk(BIOS_INFO, "LPDDR4 Ch0 density = %d\n",
+			sku->ch0_rank_density);
+		meminit_lpddr4_enable_channel(cfg, LP4_LCH0,
+						sku->ch0_rank_density,
+						sku->ch0_dual_rank,
+						lpcfg->swizzle_config);
+	}
+
+	if (sku->ch1_rank_density) {
+		printk(BIOS_INFO, "LPDDR4 Ch1 density = %d\n",
+			sku->ch1_rank_density);
+		meminit_lpddr4_enable_channel(cfg, LP4_LCH1,
+						sku->ch1_rank_density,
+						sku->ch1_dual_rank,
+						lpcfg->swizzle_config);
+	}
+
+	cfg->PeriodicRetrainingDisable = sku->disable_periodic_retraining;
+}
+
+void save_lpddr4_dimm_info(const struct lpddr4_cfg *lp4cfg, size_t mem_sku)
+{
+	int channel, dimm, dimm_max, index;
+	size_t hob_size;
+	const DIMM_INFO *src_dimm;
+	struct dimm_info *dest_dimm;
+	struct memory_info *mem_info;
+	const CHANNEL_INFO *channel_info;
+	const FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
+
+	if (mem_sku >= lp4cfg->num_skus) {
+		printk(BIOS_ERR, "Too few LPDDR4 SKUs: 0x%zx/0x%zx\n",
+				mem_sku, lp4cfg->num_skus);
+		return;
+	}
+
+	memory_info_hob = fsp_find_smbios_memory_info(&hob_size);
+
+	/*
+	 * Allocate CBMEM area for DIMM information used to populate SMBIOS
+	 * table 17
+	 */
+	mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
+	if (mem_info == NULL) {
+		printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
+		return;
+	}
+	memset(mem_info, 0, sizeof(*mem_info));
+
+	/* Describe the first N DIMMs in the system */
+	index = 0;
+	dimm_max = ARRAY_SIZE(mem_info->dimm);
+	for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) {
+		if (index >= dimm_max)
+			break;
+		channel_info = &memory_info_hob->ChannelInfo[channel];
+		for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
+			if (index >= dimm_max)
+				break;
+			src_dimm = &channel_info->DimmInfo[dimm];
+			dest_dimm = &mem_info->dimm[index];
+
+			if (!src_dimm->SizeInMb)
+				continue;
+
+			/* Populate the DIMM information */
+			dest_dimm->dimm_size = src_dimm->SizeInMb;
+			dest_dimm->ddr_type = memory_info_hob->MemoryType;
+			dest_dimm->ddr_frequency =
+					memory_info_hob->MemoryFrequencyInMHz;
+			dest_dimm->channel_num = channel_info->ChannelId;
+			dest_dimm->dimm_num = src_dimm->DimmId;
+			strncpy((char *)dest_dimm->module_part_number,
+					lp4cfg->skus[mem_sku].part_num,
+					sizeof(dest_dimm->module_part_number));
+
+			switch (memory_info_hob->DataWidth) {
+			case 8:
+				dest_dimm->bus_width = MEMORY_BUS_WIDTH_8;
+				break;
+			case 16:
+				dest_dimm->bus_width = MEMORY_BUS_WIDTH_16;
+				break;
+			case 32:
+				dest_dimm->bus_width = MEMORY_BUS_WIDTH_32;
+				break;
+			case 64:
+				dest_dimm->bus_width = MEMORY_BUS_WIDTH_64;
+				break;
+			case 128:
+				dest_dimm->bus_width = MEMORY_BUS_WIDTH_128;
+				break;
+			default:
+				printk(BIOS_ERR, "Incorrect DIMM Data Width");
+			}
+			index++;
+		}
+	}
+	mem_info->dimm_cnt = index;
+	printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
+}
diff --git a/src/soc/intel/glk/memmap.c b/src/soc/intel/glk/memmap.c
new file mode 100644
index 0000000..ea6f447
--- /dev/null
+++ b/src/soc/intel/glk/memmap.c
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * The device_t returned by dev_find_slot() is different than the device_t
+ * passed to pci_write_config32(). If one needs to get access to the config.h
+ * of a device and perform i/o things are incorrect. One is a pointer while
+ * the other is a 32-bit integer.
+ */
+#define __SIMPLE_DEVICE__
+
+#include <arch/io.h>
+#include <cbmem.h>
+#include <device/pci.h>
+#include <soc/northbridge.h>
+#include <soc/pci_devs.h>
+#include <soc/smm.h>
+
+static uintptr_t smm_region_start(void)
+{
+	return ALIGN_DOWN(pci_read_config32(NB_DEV_ROOT, TSEG), 1*MiB);
+}
+
+static size_t smm_region_size(void)
+{
+	uintptr_t smm_end =
+		ALIGN_DOWN(pci_read_config32(NB_DEV_ROOT, BGSM), 1*MiB);
+	return smm_end - smm_region_start();
+}
+
+void *cbmem_top(void)
+{
+	return (void *)smm_region_start();
+}
+
+void smm_region(void **start, size_t *size)
+{
+	*start = (void *)smm_region_start();
+	*size = smm_region_size();
+}
diff --git a/src/soc/intel/glk/mmap_boot.c b/src/soc/intel/glk/mmap_boot.c
new file mode 100644
index 0000000..bf2e5b9
--- /dev/null
+++ b/src/soc/intel/glk/mmap_boot.c
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/early_variables.h>
+#include <boot_device.h>
+#include <cbfs.h>
+#include <commonlib/region.h>
+#include <console/console.h>
+#include <fmap.h>
+#include <soc/intel/common/nvm.h>
+#include <soc/mmap_boot.h>
+#include <soc/spi.h>
+
+/*
+ * BIOS region on the flash is mapped right below 4GiB in the address
+ * space. However, 256KiB right below 4GiB is decoded by read-only SRAM and not
+ * boot media.
+ *
+ *                                                            +----------------+ 0
+ *                                                            |                |
+ *                                                            |                |
+ *                                                            |                |
+ *                                                            |                |
+ *                                                            |                |
+ *                                                            |                |
+ *                                                            |                |
+ *                                                            |                |
+ *                  +------------+                            |                |
+ *                  |    IFD     |                            |                |
+ * bios_start +---> +------------+--------------------------> +----------------+ 4GiB - bios_size
+ *     ^            |            |              ^             |                |
+ *     |            |            |              |             |                |
+ *     |            |            |       bios_mapped_size     |      BIOS      |
+ *     |            |    BIOS    |              |             |                |
+ * bios_size        |            |              |             |                |
+ *     |            |            |              v             |                |
+ *     |            |            +--------------------------> +----------------+ 4GiB - 256KiB
+ *     v            |            |                            | Read only SRAM |
+ * bios_end   +---> +------------+                            +----------------+ 4GiB
+ *                  | Device ext |
+ *                  +------------+
+ *
+ */
+
+static size_t bios_start CAR_GLOBAL;
+static size_t bios_size CAR_GLOBAL;
+
+static struct mem_region_device shadow_dev CAR_GLOBAL;
+static struct xlate_region_device real_dev CAR_GLOBAL;
+
+static void bios_mmap_init(void)
+{
+	size_t size;
+
+	size = car_get_var(bios_size);
+
+	/* If bios_size is initialized, then bail out. */
+	if (size != 0)
+		return;
+
+	size_t start, bios_end, bios_mapped_size;
+	uintptr_t base;
+
+	/*
+	 * BIOS_BFPREG provides info about BIOS Flash Primary Region
+	 * Base and Limit.
+	 * Base and Limit fields are in units of 4KiB.
+	 */
+	uint32_t val = spi_ctrlr_reg_read(SPIBAR_BIOS_BFPREG);
+
+	start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB;
+	bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
+		     SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB;
+	size = bios_end - start;
+
+	/* BIOS region is mapped right below 4G. */
+	base = 4ULL * GiB - size;
+
+	/*
+	 * The 256 KiB right below 4G are decoded by readonly SRAM,
+	 * not boot media.
+	 */
+	bios_mapped_size = size - 256 * KiB;
+
+	struct mem_region_device *shadow_dev_ptr;
+	struct xlate_region_device *real_dev_ptr;
+	shadow_dev_ptr = car_get_var_ptr(&shadow_dev);
+	real_dev_ptr = car_get_var_ptr(&real_dev);
+
+	mem_region_device_ro_init(shadow_dev_ptr, (void *)base,
+			       bios_mapped_size);
+
+	xlate_region_device_ro_init(real_dev_ptr, &shadow_dev_ptr->rdev,
+				 start, bios_mapped_size,
+				 CONFIG_ROM_SIZE);
+
+	car_set_var(bios_start, start);
+	car_set_var(bios_size, size);
+}
+
+const struct region_device *boot_device_ro(void)
+{
+	bios_mmap_init();
+
+	struct xlate_region_device *real_dev_ptr;
+	real_dev_ptr = car_get_var_ptr(&real_dev);
+
+	return &real_dev_ptr->rdev;
+}
+
+static int iafw_boot_region_properties(struct cbfs_props *props)
+{
+	struct region regn;
+
+	/* use fmap to locate CBFS area */
+	if (fmap_locate_area("COREBOOT", &regn))
+		return -1;
+
+	props->offset = region_offset(&regn);
+	props->size = region_sz(&regn);
+
+	printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size);
+
+	return 0;
+}
+
+/*
+ * Named cbfs_master_header_locator so that it overrides the default, but
+ * incompatible locator in cbfs.c
+ */
+const struct cbfs_locator cbfs_master_header_locator = {
+	.name = "IAFW Locator",
+	.locate = iafw_boot_region_properties,
+};
+
+uint32_t nvm_mmio_to_flash_offset(void *p)
+{
+	bios_mmap_init();
+
+	size_t start, size;
+	start = car_get_var(bios_start);
+	size = car_get_var(bios_size);
+
+	/*
+	 * Returns :
+	 * addr - base of mmaped region in addr space + offset of mmaped region
+	 * start on flash
+	 */
+	return (uintptr_t)p - (4ULL * GiB - size) + start;
+}
+
+size_t get_bios_size(void)
+{
+	bios_mmap_init();
+	return car_get_var(bios_size);
+}
diff --git a/src/soc/intel/glk/nhlt.c b/src/soc/intel/glk/nhlt.c
new file mode 100644
index 0000000..3670a13
--- /dev/null
+++ b/src/soc/intel/glk/nhlt.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <nhlt.h>
+#include <soc/nhlt.h>
+
+static const struct nhlt_format_config dmic_2ch_formats[] = {
+	/* 48 KHz 16-bits per sample. */
+	{
+		.num_channels = 2,
+		.sample_freq_khz = 48,
+		.container_bits_per_sample = 16,
+		.valid_bits_per_sample = 16,
+		.settings_file = "dmic-2ch-48khz-16b.bin",
+	},
+};
+
+static const struct nhlt_dmic_array_config dmic_2ch_mic_config = {
+	.tdm_config = {
+		.config_type = NHLT_TDM_MIC_ARRAY,
+	},
+	.array_type = NHLT_MIC_ARRAY_2CH_SMALL,
+};
+
+static const struct nhlt_endp_descriptor dmic_2ch_descriptors[] = {
+	{
+		.link = NHLT_LINK_PDM,
+		.device = NHLT_PDM_DEV,
+		.direction = NHLT_DIR_CAPTURE,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_DMIC,
+		.cfg = &dmic_2ch_mic_config,
+		.cfg_size = sizeof(dmic_2ch_mic_config),
+		.formats = dmic_2ch_formats,
+		.num_formats = ARRAY_SIZE(dmic_2ch_formats),
+	},
+};
+
+static const struct nhlt_format_config da7219_formats[] = {
+	/* 48 KHz 24-bits per sample. */
+	{
+		.num_channels = 2,
+		.sample_freq_khz = 48,
+		.container_bits_per_sample = 32,
+		.valid_bits_per_sample = 24,
+		.settings_file = "dialog-2ch-48khz-24b.bin",
+	},
+};
+
+static const struct nhlt_tdm_config tdm_config = {
+	.virtual_slot = 0,
+	.config_type = NHLT_TDM_BASIC,
+};
+
+static const struct nhlt_endp_descriptor da7219_descriptors[] = {
+	/* Render Endpoint */
+	{
+		.link = NHLT_LINK_SSP,
+		.device = NHLT_SSP_DEV_I2S,
+		.direction = NHLT_DIR_RENDER,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_SSP,
+		.cfg = &tdm_config,
+		.cfg_size = sizeof(tdm_config),
+		.formats = da7219_formats,
+		.num_formats = ARRAY_SIZE(da7219_formats),
+	},
+	/* Capture Endpoint */
+	{
+		.link = NHLT_LINK_SSP,
+		.device = NHLT_SSP_DEV_I2S,
+		.direction = NHLT_DIR_CAPTURE,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_SSP,
+		.cfg = &tdm_config,
+		.cfg_size = sizeof(tdm_config),
+		.formats = da7219_formats,
+		.num_formats = ARRAY_SIZE(da7219_formats),
+	},
+};
+
+static const struct nhlt_format_config max98357_formats[] = {
+	/* 48 KHz 24-bits per sample. */
+	{
+		.num_channels = 2,
+		.sample_freq_khz = 48,
+		.container_bits_per_sample = 32,
+		.valid_bits_per_sample = 24,
+		.settings_file = "max98357-render-2ch-48khz-24b.bin",
+	},
+};
+
+static const struct nhlt_endp_descriptor max98357_descriptors[] = {
+	{
+		.link = NHLT_LINK_SSP,
+		.device = NHLT_SSP_DEV_I2S,
+		.direction = NHLT_DIR_RENDER,
+		.vid = NHLT_VID,
+		.did = NHLT_DID_SSP,
+		.formats = max98357_formats,
+		.num_formats = ARRAY_SIZE(max98357_formats),
+	},
+};
+
+int nhlt_soc_add_dmic_array(struct nhlt *nhlt, int num_channels)
+{
+	if (num_channels != 2) {
+		printk(BIOS_ERR, "APL only supports 2CH DMIC array.\n");
+		return -1;
+	}
+
+	return nhlt_add_endpoints(nhlt, dmic_2ch_descriptors,
+				ARRAY_SIZE(dmic_2ch_descriptors));
+}
+
+int nhlt_soc_add_da7219(struct nhlt *nhlt, int hwlink)
+{
+	/* Virtual bus id of SSP links are the hardware port ids proper. */
+	return nhlt_add_ssp_endpoints(nhlt, hwlink, da7219_descriptors,
+					ARRAY_SIZE(da7219_descriptors));
+}
+
+int nhlt_soc_add_max98357(struct nhlt *nhlt, int hwlink)
+{
+	/* Virtual bus id of SSP links are the hardware port ids proper. */
+	return nhlt_add_ssp_endpoints(nhlt, hwlink, max98357_descriptors,
+					ARRAY_SIZE(max98357_descriptors));
+}
diff --git a/src/soc/intel/glk/northbridge.c b/src/soc/intel/glk/northbridge.c
new file mode 100644
index 0000000..cc097ba
--- /dev/null
+++ b/src/soc/intel/glk/northbridge.c
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <soc/iomap.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/northbridge.h>
+#include <soc/pci_ids.h>
+
+static uint32_t get_bar(device_t dev, unsigned int index)
+{
+	uint32_t bar;
+
+	bar = pci_read_config32(dev, index);
+
+	/* If not enabled return 0 else strip enabled bit */
+	return (bar & 1) ? (bar & ~1) : 0;
+}
+
+static int mc_add_fixed_mmio_resources(device_t dev, int index)
+{
+	unsigned long addr;
+
+	/* PCI extended config region */
+	addr = ALIGN_DOWN(get_bar(dev, PCIEXBAR), 256*MiB) / KiB;
+	mmio_resource(dev, index++, addr, PCIEX_SIZE / KiB);
+
+	/* Memory Controller Hub */
+	addr = ALIGN_DOWN(get_bar(dev, MCHBAR), 32*KiB) / KiB;
+	mmio_resource(dev, index++, addr, MCH_BASE_SIZE / KiB);
+
+	return index;
+}
+
+static bool is_imr_enabled(uint32_t imr_base_reg)
+{
+	return !!(imr_base_reg & (1 << 31));
+}
+
+static void imr_resource(device_t dev, int idx, uint32_t base, uint32_t mask)
+{
+	uint32_t base_k, size_k;
+	/* Bits 28:0 encode the base address bits 38:10, hence the KiB unit. */
+	base_k = (base & 0x0fffffff);
+	/* Bits 28:0 encode the AND mask used for comparison, in KiB. */
+	size_k = ((~mask & 0x0fffffff) + 1);
+	/*
+	 * IMRs sit in lower DRAM. Mark them cacheable, otherwise we run
+	 * out of MTRRs. Memory reserved by IMRs is not usable for host
+	 * so mark it reserved.
+	 */
+	reserved_ram_resource(dev, idx, base_k, size_k);
+}
+
+static int mc_add_imr_resources(device_t dev, int index)
+{
+	uint8_t *mchbar;
+	size_t i, imr_offset;
+	uint32_t base, mask;
+
+	mchbar = (void *)(ALIGN_DOWN(get_bar(dev, MCHBAR), 32*KiB));
+
+	for (i = 0; i < MCH_NUM_IMRS; i ++) {
+		imr_offset = i * MCH_IMR_PITCH;
+		base = read32(mchbar + imr_offset + MCHBAR_IMR0BASE);
+		mask = read32(mchbar + imr_offset + MCHBAR_IMR0MASK);
+
+		if (is_imr_enabled(base)) {
+			imr_resource(dev, index++, base, mask);
+		}
+	}
+
+	return index;
+}
+
+
+static int mc_add_dram_resources(device_t dev, int index)
+{
+	unsigned long base_k, size_k;
+	uint32_t bgsm, bdsm, tolud, tseg;
+	uint64_t touud;
+
+	bgsm  = ALIGN_DOWN(pci_read_config32(dev, BGSM), MiB);
+	bdsm  = ALIGN_DOWN(pci_read_config32(dev, BDSM), MiB);
+	tolud = ALIGN_DOWN(pci_read_config32(dev, TOLUD), MiB);
+	tseg  = ALIGN_DOWN(pci_read_config32(dev, TSEG), MiB);
+
+	/* TOUUD is naturally a 64 bit integer */
+	touud = pci_read_config32(dev, TOUUD + sizeof(uint32_t));
+	touud <<= 32;
+	touud |= ALIGN_DOWN(pci_read_config32(dev, TOUUD), MiB);
+
+	/* 0 - > 0xa0000: 640kb of DOS memory. Not enough for anybody nowadays */
+	ram_resource(dev, index++, 0, 640);
+
+	/* 0xa0000 - 0xbffff: legacy VGA */
+	mmio_resource(dev, index++, 640, 128);
+
+	/* 0xc0000 -> 0xfffff: leave without e820 entry, as it has special uses */
+	/* 0x100000 -> top_of_ram  */
+	base_k = 1024;
+	size_k = (tseg / KiB) - base_k;
+	ram_resource(dev, index++, base_k, size_k);
+
+	/* TSEG -> BGSM */
+	reserved_ram_resource(dev, index++, tseg / KiB, (bgsm - tseg) / KiB);
+
+	/* BGSM -> BDSM */
+	mmio_resource(dev, index++, bgsm / KiB, (bdsm - bgsm) / KiB);
+
+	/* BDSM -> TOLUD */
+	mmio_resource(dev, index++, bdsm / KiB, (tolud - bdsm) / KiB);
+
+	/* 4G -> TOUUD */
+	base_k = 4ULL*GiB / KiB;
+	size_k = (touud / KiB) - base_k;
+	ram_resource(dev, index++, base_k, size_k);
+
+
+	return index;
+}
+
+static void northbridge_read_resources(device_t dev)
+{
+
+	int index = 0;
+	/* Read standard PCI resources. */
+	pci_dev_read_resources(dev);
+
+	/* Add all fixed MMIO resources. */
+	index = mc_add_fixed_mmio_resources(dev, index);
+
+	/* Calculate and add DRAM resources. */
+	index = mc_add_dram_resources(dev, index);
+
+	/* Add the isolated memory ranges (IMRs). */
+	mc_add_imr_resources(dev, index);
+
+}
+
+static struct device_operations northbridge_ops = {
+	.read_resources   = northbridge_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = DEVICE_NOOP,
+	.enable           = DEVICE_NOOP
+};
+
+static const struct pci_driver northbridge_driver __pci_driver = {
+	.ops     = &northbridge_ops,
+	.vendor  = PCI_VENDOR_ID_INTEL,
+	.device  = PCI_DEVICE_ID_APOLLOLAKE_NB
+};
diff --git a/src/soc/intel/glk/p2sb.c b/src/soc/intel/glk/p2sb.c
new file mode 100644
index 0000000..7834e38
--- /dev/null
+++ b/src/soc/intel/glk/p2sb.c
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <rules.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/pci_ids.h>
+#include <soc/p2sb.h>
+
+#define P2SB_E0 0xe0
+#define HIDE_BIT (1 << 0)
+
+static void p2sb_set_hide_bit(int hide)
+{
+	struct device *dev;
+	const uint16_t reg = P2SB_E0 + 1;
+	const uint8_t mask = HIDE_BIT;
+	uint8_t val;
+
+	dev = P2SB_DEV;
+
+	val = pci_read_config8(dev, reg);
+	val &= ~mask;
+	if (hide)
+		val |= mask;
+	pci_write_config8(dev, reg, val);
+}
+
+void p2sb_unhide(void)
+{
+	p2sb_set_hide_bit(0);
+}
+
+void p2sb_hide(void)
+{
+	p2sb_set_hide_bit(HIDE_BIT);
+}
+
+static void read_resources(struct device *dev)
+{
+	/*
+	 * There's only one resource on the P2SB device. It's also already
+	 * manually set to a fixed address in earlier boot stages.
+	 */
+	mmio_resource(dev, PCI_BASE_ADDRESS_0, P2SB_BAR / KiB, P2SB_SIZE / KiB);
+}
+
+static const struct device_operations device_ops = {
+	.read_resources		= read_resources,
+	.set_resources		= DEVICE_NOOP,
+};
+
+static const struct pci_driver pmc __pci_driver = {
+	.ops	= &device_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= PCI_DEVICE_ID_APOLLOLAKE_P2SB,
+};
diff --git a/src/soc/intel/glk/pmc.c b/src/soc/intel/glk/pmc.c
new file mode 100644
index 0000000..7e5cf35
--- /dev/null
+++ b/src/soc/intel/glk/pmc.c
@@ -0,0 +1,157 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <soc/iomap.h>
+#include <soc/pci_ids.h>
+#include <soc/gpio.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <timer.h>
+#include "chip.h"
+
+/*
+ * The ACPI IO BAR (offset 0x20) is not PCI compliant. We've observed cases
+ * where the BAR reads back as 0, but the IO window is open. This also means
+ * that it will not respond to PCI probing. In the event that probing the BAR
+ * fails, we still need to create a resource for it.
+ */
+static void read_resources(device_t dev)
+{
+	struct resource *res;
+	pci_dev_read_resources(dev);
+
+	res = new_resource(dev, PCI_BASE_ADDRESS_4);
+	res->base = ACPI_PMIO_BASE;
+	res->size = ACPI_PMIO_SIZE;
+	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+/*
+ * Part 2:
+ * Resources are assigned, and no other device was given an IO resource to
+ * overlap with our ACPI BAR. But because the resource is FIXED,
+ * pci_dev_set_resources() will not store it for us. We need to do that
+ * explicitly.
+ */
+static void set_resources(device_t dev)
+{
+	struct resource *res;
+
+	pci_dev_set_resources(dev);
+
+	res = find_resource(dev, PCI_BASE_ADDRESS_4);
+	pci_write_config32(dev, res->index, res->base);
+	dev->command |= PCI_COMMAND_IO;
+	res->flags |= IORESOURCE_STORED;
+	report_resource_stored(dev, res, " ACPI BAR");
+}
+
+static void pch_set_acpi_mode(void)
+{
+	if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER) && !acpi_is_wakeup_s3()) {
+		printk(BIOS_DEBUG, "Disabling ACPI via APMC:");
+		outb(APM_CNT_ACPI_DISABLE, APM_CNT);
+		printk(BIOS_DEBUG, "Done.\n");
+	}
+}
+
+static int choose_slp_s3_assertion_width(int width_usecs)
+{
+	int i;
+	static const struct {
+		int max_width;
+		int value;
+	} slp_s3_settings[] = {
+		{
+			.max_width = 60,
+			.value = SLP_S3_ASSERT_60_USEC,
+		},
+		{
+			.max_width = 1 * USECS_PER_MSEC,
+			.value = SLP_S3_ASSERT_1_MSEC,
+		},
+		{
+			.max_width = 50 * USECS_PER_MSEC,
+			.value = SLP_S3_ASSERT_50_MSEC,
+		},
+		{
+			.max_width =  2 * USECS_PER_SEC,
+			.value = SLP_S3_ASSERT_2_SEC,
+		},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(slp_s3_settings); i++) {
+		if (width_usecs <= slp_s3_settings[i].max_width)
+			break;
+	}
+
+	/* Provide conservative default if nothing set in devicetree
+	 * or requested assertion width too large. */
+	if (width_usecs <= 0 || i == ARRAY_SIZE(slp_s3_settings))
+		i = ARRAY_SIZE(slp_s3_settings) - 1;
+
+	printk(BIOS_DEBUG, "SLP S3 assertion width: %d usecs\n",
+		slp_s3_settings[i].max_width);
+
+	return slp_s3_settings[i].value;
+}
+
+static void set_slp_s3_assertion_width(int width_usecs)
+{
+	uint32_t reg;
+	uintptr_t gen_pmcon3 = get_pmc_mmio_bar() + GEN_PMCON3;
+	int setting = choose_slp_s3_assertion_width(width_usecs);
+
+	reg = read32((void *)gen_pmcon3);
+	reg &= ~SLP_S3_ASSERT_MASK;
+	reg |= setting << SLP_S3_ASSERT_WIDTH_SHIFT;
+	write32((void *)gen_pmcon3, reg);
+}
+
+static void pmc_init(struct device *dev)
+{
+	const struct soc_intel_glk_config *cfg = dev->chip_info;
+
+	/* Set up GPE configuration */
+	pmc_gpe_init();
+	fixup_power_state();
+	pch_set_acpi_mode();
+
+	if (cfg != NULL)
+		set_slp_s3_assertion_width(cfg->slp_s3_assertion_width_usecs);
+
+	/* Log power state */
+	pch_log_state();
+}
+
+static const struct device_operations device_ops = {
+	.read_resources		= read_resources,
+	.set_resources		= set_resources,
+	.enable_resources	= pci_dev_enable_resources,
+	.init                   = &pmc_init,
+};
+
+static const struct pci_driver pmc __pci_driver = {
+	.ops	= &device_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= PCI_DEVICE_ID_APOLLOLAKE_PMC,
+};
diff --git a/src/soc/intel/glk/pmutil.c b/src/soc/intel/glk/pmutil.c
new file mode 100644
index 0000000..2f2e24f
--- /dev/null
+++ b/src/soc/intel/glk/pmutil.c
@@ -0,0 +1,543 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define __SIMPLE_DEVICE__
+
+#include <arch/acpi.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <cbmem.h>
+#include <rules.h>
+#include <device/pci_def.h>
+#include <halt.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <vboot/vboot_common.h>
+#include "chip.h"
+
+static uintptr_t read_pmc_mmio_bar(void)
+{
+	uint32_t bar = pci_read_config32(PMC_DEV, PCI_BASE_ADDRESS_0);
+	return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+}
+
+uintptr_t get_pmc_mmio_bar(void)
+{
+	return read_pmc_mmio_bar();
+}
+
+static void print_num_status_bits(int num_bits, uint32_t status,
+				  const char * const bit_names[])
+{
+	int i;
+
+	if (!status)
+		return;
+
+	for (i = num_bits - 1; i >= 0; i--) {
+		if (status & (1 << i)) {
+			if (bit_names[i])
+				printk(BIOS_DEBUG, "%s ", bit_names[i]);
+			else
+				printk(BIOS_DEBUG, "BIT%d ", i);
+		}
+	}
+}
+
+static uint32_t print_smi_status(uint32_t smi_sts)
+{
+	static const char * const smi_sts_bits[] = {
+		[BIOS_SMI_STS] = "BIOS",
+		[LEGACY_USB_SMI_STS] = "LEGACY USB",
+		[SLP_SMI_STS] = "SLP_SMI",
+		[APM_SMI_STS] = "APM",
+		[SWSMI_TMR_SMI_STS] = "SWSMI_TMR",
+		[FAKE_PM1_SMI_STS] = "PM1",
+		[GPIO_SMI_STS]= "GPIO_SMI",
+		[GPIO_UNLOCK_SMI_STS]= "GPIO_UNLOCK_SSMI",
+		[MC_SMI_STS] = "MCSMI",
+		[TCO_SMI_STS] = "TCO",
+		[PERIODIC_SMI_STS] = "PERIODIC",
+		[SERIRQ_SMI_STS] = "SERIRQ",
+		[SMBUS_SMI_STS] = "SMBUS_SMI",
+		[XHCI_SMI_STS] = "XHCI",
+		[HSMBUS_SMI_STS] = "HOST_SMBUS",
+		[SCS_SMI_STS] = "SCS",
+		[PCIE_SMI_STS] = "PCI_EXP_SMI",
+		[SCC2_SMI_STS] = "SCC2",
+		[SPI_SSMI_STS] = "SPI_SSMI",
+		[SPI_SMI_STS] = "SPI",
+		[PMC_OCP_SMI_STS] = "OCP_CSE",
+	};
+
+	if (!smi_sts)
+		return 0;
+
+	printk(BIOS_DEBUG, "SMI_STS: ");
+	print_num_status_bits(ARRAY_SIZE(smi_sts_bits), smi_sts, smi_sts_bits);
+	printk(BIOS_DEBUG, "\n");
+
+	return smi_sts;
+}
+
+static uint32_t reset_smi_status(void)
+{
+	uint32_t smi_sts = inl(ACPI_PMIO_BASE + SMI_STS);
+	outl(smi_sts, ACPI_PMIO_BASE + SMI_STS);
+	return smi_sts;
+}
+
+uint32_t clear_smi_status(void)
+{
+	uint32_t sts = reset_smi_status();
+
+	/*
+	 * Check for power button status if nothing else is indicating an SMI
+	 * and SMIs aren't turned into SCIs. Apparently, there is no PM1 status
+	 * bit in the SMI status register.  That makes things difficult for
+	 * determining if the power button caused an SMI.
+	 */
+	if (sts == 0 && !(inl(ACPI_PMIO_BASE + PM1_CNT) & SCI_EN)) {
+		uint16_t pm1_sts = inw(ACPI_PMIO_BASE + PM1_STS);
+
+		/* Fake PM1 status bit if power button pressed. */
+		if (pm1_sts & PWRBTN_STS)
+			sts |= (1 << FAKE_PM1_SMI_STS);
+	}
+
+	return print_smi_status(sts);
+}
+
+uint32_t get_smi_en(void)
+{
+	return inl(ACPI_PMIO_BASE + SMI_EN);
+}
+
+void enable_smi(uint32_t mask)
+{
+	uint32_t smi_en = inl(ACPI_PMIO_BASE + SMI_EN);
+	smi_en |= mask;
+	outl(smi_en, ACPI_PMIO_BASE + SMI_EN);
+}
+
+void disable_smi(uint32_t mask)
+{
+	uint32_t smi_en = inl(ACPI_PMIO_BASE + SMI_EN);
+	smi_en &= ~mask;
+	outl(smi_en, ACPI_PMIO_BASE + SMI_EN);
+}
+
+void enable_pm1_control(uint32_t mask)
+{
+	uint32_t pm1_cnt = inl(ACPI_PMIO_BASE + PM1_CNT);
+	pm1_cnt |= mask;
+	outl(pm1_cnt, ACPI_PMIO_BASE + PM1_CNT);
+}
+
+void disable_pm1_control(uint32_t mask)
+{
+	uint32_t pm1_cnt = inl(ACPI_PMIO_BASE + PM1_CNT);
+	pm1_cnt &= ~mask;
+	outl(pm1_cnt, ACPI_PMIO_BASE + PM1_CNT);
+}
+
+static uint16_t reset_pm1_status(void)
+{
+	uint16_t pm1_sts = inw(ACPI_PMIO_BASE + PM1_STS);
+	outw(pm1_sts, ACPI_PMIO_BASE + PM1_STS);
+	return pm1_sts;
+}
+
+static uint16_t print_pm1_status(uint16_t pm1_sts)
+{
+	static const char * const pm1_sts_bits[] = {
+		[0] = "TMROF",
+		[5] = "GBL",
+		[8] = "PWRBTN",
+		[10] = "RTC",
+		[11] = "PRBTNOR",
+		[13] = "USB",
+		[14] = "PCIEXPWAK",
+		[15] = "WAK",
+	};
+
+	if (!pm1_sts)
+		return 0;
+
+	printk(BIOS_SPEW, "PM1_STS: ");
+	print_num_status_bits(ARRAY_SIZE(pm1_sts_bits), pm1_sts, pm1_sts_bits);
+	printk(BIOS_SPEW, "\n");
+
+	return pm1_sts;
+}
+
+uint16_t clear_pm1_status(void)
+{
+	return print_pm1_status(reset_pm1_status());
+}
+
+void enable_pm1(uint16_t events)
+{
+	outw(events, ACPI_PMIO_BASE + PM1_EN);
+}
+
+static uint32_t print_tco_status(uint32_t tco_sts)
+{
+	static const char * const tco_sts_bits[] = {
+		[3] = "TIMEOUT",
+		[17] = "SECOND_TO",
+	};
+
+	if (!tco_sts)
+		return 0;
+
+	printk(BIOS_DEBUG, "TCO_STS: ");
+	print_num_status_bits(ARRAY_SIZE(tco_sts_bits), tco_sts, tco_sts_bits);
+	printk(BIOS_DEBUG, "\n");
+
+	return tco_sts;
+}
+
+static uint32_t reset_tco_status(void)
+{
+	uint32_t tco_sts = inl(ACPI_PMIO_BASE + TCO_STS);
+	uint32_t tco_en = inl(ACPI_PMIO_BASE + TCO1_CNT);
+
+	outl(tco_sts, ACPI_PMIO_BASE + TCO_STS);
+	return tco_sts & tco_en;
+}
+
+uint32_t clear_tco_status(void)
+{
+	return print_tco_status(reset_tco_status());
+}
+
+void enable_gpe(uint32_t mask)
+{
+	uint32_t gpe0a_en = inl(ACPI_PMIO_BASE + GPE0_EN(0));
+	gpe0a_en |= mask;
+	outl(gpe0a_en, ACPI_PMIO_BASE + GPE0_EN(0));
+}
+
+void disable_gpe(uint32_t mask)
+{
+	uint32_t gpe0a_en = inl(ACPI_PMIO_BASE + GPE0_EN(0));
+	gpe0a_en &= ~mask;
+	outl(gpe0a_en, ACPI_PMIO_BASE + GPE0_EN(0));
+}
+
+void disable_all_gpe(void)
+{
+	disable_gpe(~0);
+}
+
+/* Clear the gpio gpe0 status bits in ACPI registers */
+void clear_gpi_gpe_sts(void)
+{
+	int i;
+
+	for (i = 1; i < GPE0_REG_MAX; i++) {
+		uint32_t gpe_sts = inl(ACPI_PMIO_BASE + GPE0_STS(i));
+		outl(gpe_sts, ACPI_PMIO_BASE + GPE0_STS(i));
+	}
+}
+
+static uint32_t reset_gpe_status(void)
+{
+	uint32_t gpe_sts = inl(ACPI_PMIO_BASE + GPE0_STS(0));
+	outl(gpe_sts, ACPI_PMIO_BASE + GPE0_STS(0));
+	return gpe_sts;
+}
+
+static uint32_t print_gpe_sts(uint32_t gpe_sts)
+{
+	static const char * const gpe_sts_bits[] = {
+		[0] = "PCIE_SCI",
+		[2] = "SWGPE",
+		[3] = "PCIE_WAKE0",
+		[4] = "PUNIT",
+		[6] = "PCIE_WAKE1",
+		[7] = "PCIE_WAKE2",
+		[8] = "PCIE_WAKE3",
+		[9] = "PCI_EXP",
+		[10] = "BATLOW",
+		[11] = "CSE_PME",
+		[12] = "XDCI_PME",
+		[13] = "XHCI_PME",
+		[14] = "AVS_PME",
+		[15] = "GPIO_TIER1_SCI",
+		[16] = "SMB_WAK",
+		[17] = "SATA_PME",
+	};
+
+	if (!gpe_sts)
+		return gpe_sts;
+
+	printk(BIOS_DEBUG, "GPE0a_STS: ");
+	print_num_status_bits(ARRAY_SIZE(gpe_sts_bits), gpe_sts, gpe_sts_bits);
+	printk(BIOS_DEBUG, "\n");
+
+	return gpe_sts;
+}
+
+uint32_t clear_gpe_status(void)
+{
+	return print_gpe_sts(reset_gpe_status());
+}
+
+/* Read and clear GPE status (defined in arch/acpi.h) */
+int acpi_get_gpe(int gpe)
+{
+	int bank;
+	uint32_t mask, sts;
+
+	if (gpe < 0 || gpe > GPE0_DW3_31)
+		return -1;
+
+	bank = gpe / 32;
+	mask = 1 << (gpe % 32);
+
+	sts = inl(ACPI_PMIO_BASE + GPE0_STS(bank));
+	if (sts & mask) {
+		outl(mask, ACPI_PMIO_BASE + GPE0_STS(bank));
+		return 1;
+	}
+	return 0;
+}
+
+void clear_pmc_status(void)
+{
+	uint32_t prsts;
+	uint32_t gen_pmcon1;
+	uintptr_t pmc_bar0 = read_pmc_mmio_bar();
+
+	prsts = read32((void *)(pmc_bar0 + PRSTS));
+	gen_pmcon1 = read32((void *)(pmc_bar0 + GEN_PMCON1));
+
+	/* Clear the status bits. The RPS field is cleared on a 0 write. */
+	write32((void *)(pmc_bar0 + GEN_PMCON1), gen_pmcon1 & ~RPS);
+	write32((void *)(pmc_bar0 + PRSTS), prsts);
+}
+
+
+/* Return 0, 3, or 5 to indicate the previous sleep state. */
+int chipset_prev_sleep_state(struct chipset_power_state *ps)
+{
+	/* Default to S0. */
+	int prev_sleep_state = ACPI_S0;
+
+	if (ps->pm1_sts & WAK_STS) {
+		switch (acpi_sleep_from_pm1(ps->pm1_cnt)) {
+		case ACPI_S3:
+			if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME))
+				prev_sleep_state = ACPI_S3;
+			break;
+		case ACPI_S5:
+			prev_sleep_state = ACPI_S5;
+			break;
+		}
+
+		/* Clear SLP_TYP. */
+		outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_PMIO_BASE + PM1_CNT);
+	}
+	return prev_sleep_state;
+}
+
+/*
+ * This function re-writes the gpe0 register values in power state
+ * cbmem variable. After system wakes from sleep state internal PMC logic
+ * writes default values in GPE_CFG register which gives a wrong offset to
+ * calculate the wake reason. So we need to set it again to the routing
+ * table as per the devicetree.
+ */
+void fixup_power_state(void)
+{
+	int i;
+	struct chipset_power_state *ps;
+
+	ps = cbmem_find(CBMEM_ID_POWER_STATE);
+	if (ps == NULL)
+		return;
+
+	for (i = 0; i < GPE0_REG_MAX; i++) {
+		ps->gpe0_sts[i] = inl(ACPI_PMIO_BASE + GPE0_STS(i));
+		ps->gpe0_en[i] = inl(ACPI_PMIO_BASE + GPE0_EN(i));
+		printk(BIOS_DEBUG, "gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n",
+					i, ps->gpe0_sts[i], i, ps->gpe0_en[i]);
+	}
+}
+
+/* returns prev_sleep_state */
+int fill_power_state(struct chipset_power_state *ps)
+{
+	int i;
+	uintptr_t pmc_bar0 = read_pmc_mmio_bar();
+
+	ps->pm1_sts = inw(ACPI_PMIO_BASE + PM1_STS);
+	ps->pm1_en = inw(ACPI_PMIO_BASE + PM1_EN);
+	ps->pm1_cnt = inl(ACPI_PMIO_BASE + PM1_CNT);
+	ps->tco_sts = inl(ACPI_PMIO_BASE + TCO_STS);
+	ps->prsts = read32((void *)(pmc_bar0 + PRSTS));
+	ps->gen_pmcon1 =read32((void *)(pmc_bar0 + GEN_PMCON1));
+	ps->gen_pmcon2 = read32((void *)(pmc_bar0 + GEN_PMCON2));
+	ps->gen_pmcon3 = read32((void *)(pmc_bar0 + GEN_PMCON3));
+
+	ps->prev_sleep_state = chipset_prev_sleep_state(ps);
+
+	printk(BIOS_DEBUG, "pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
+		ps->pm1_sts, ps->pm1_en, ps->pm1_cnt);
+	printk(BIOS_DEBUG, "prsts: %08x tco_sts: %08x\n",
+		ps->prsts, ps->tco_sts);
+	printk(BIOS_DEBUG,
+		 "gen_pmcon1: %08x gen_pmcon2: %08x gen_pmcon3: %08x\n",
+		ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3);
+	printk(BIOS_DEBUG, "smi_en: %08x smi_sts: %08x\n",
+		inl(ACPI_PMIO_BASE + SMI_EN), inl(ACPI_PMIO_BASE + SMI_STS));
+	for (i=0; i < GPE0_REG_MAX; i++) {
+		ps->gpe0_sts[i] = inl(ACPI_PMIO_BASE + GPE0_STS(i));
+		ps->gpe0_en[i] = inl(ACPI_PMIO_BASE + GPE0_EN(i));
+		printk(BIOS_DEBUG, "gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n",
+			i, ps->gpe0_sts[i], i, ps->gpe0_en[i]);
+	}
+	printk(BIOS_DEBUG, "prev_sleep_state %d\n", ps->prev_sleep_state);
+	return ps->prev_sleep_state;
+}
+
+int vboot_platform_is_resuming(void)
+{
+	if (!(inw(ACPI_PMIO_BASE + PM1_STS) & WAK_STS))
+		return 0;
+
+	return acpi_sleep_from_pm1(inl(ACPI_PMIO_BASE + PM1_CNT)) == ACPI_S3;
+}
+
+/*
+ * If possible, lock 0xcf9. Once the register is locked, it can't be changed.
+ * This lock is reset on cold boot, hard reset, soft reset and Sx.
+ */
+void global_reset_lock(void)
+{
+	uintptr_t etr = read_pmc_mmio_bar() + ETR;
+	uint32_t reg;
+
+	reg = read32((void *)etr);
+	if (reg & CF9_LOCK)
+		return;
+	reg |= CF9_LOCK;
+	write32((void *)etr, reg);
+}
+
+/*
+ * Enable or disable global reset. If global reset is enabled, hard reset and
+ * soft reset will trigger global reset, where both host and TXE are reset.
+ * This is cleared on cold boot, hard reset, soft reset and Sx.
+ */
+void global_reset_enable(bool enable)
+{
+	uintptr_t etr = read_pmc_mmio_bar() + ETR;
+	uint32_t reg;
+
+	reg = read32((void *)etr);
+	reg = enable ? reg | CF9_GLB_RST : reg & ~CF9_GLB_RST;
+	write32((void *)etr, reg);
+}
+
+/*
+ * The PM1 control is set to S5 when vboot requests a reboot because the power
+ * state code above may not have collected its data yet. Therefore, set it to
+ * S5 when vboot requests a reboot. That's necessary if vboot fails in the
+ * resume path and requests a reboot. This prevents a reboot loop where the
+ * error is continually hit on the failing vboot resume path.
+ */
+void vboot_platform_prepare_reboot(void)
+{
+	const uint16_t port = ACPI_PMIO_BASE + PM1_CNT;
+	outl((inl(port) & ~(SLP_TYP)) | (SLP_TYP_S5 << SLP_TYP_SHIFT), port);
+}
+
+void poweroff(void)
+{
+	enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
+
+	/*
+	 * Setting SLP_TYP_S5 in PM1 triggers SLP_SMI, which is handled by SMM
+	 * to transition to S5 state. If halt is called in SMM, then it prevents
+	 * the SMI handler from being triggered and system never enters S5.
+	 */
+	if (!ENV_SMM)
+		halt();
+}
+
+void pmc_gpe_init(void)
+{
+	uint32_t gpio_cfg = 0;
+	uint32_t gpio_cfg_reg;
+	uint8_t dw1, dw2, dw3;
+	ROMSTAGE_CONST struct soc_intel_glk_config *config;
+
+	/* Look up the device in devicetree */
+	ROMSTAGE_CONST struct device *dev = dev_find_slot(0, NB_DEVFN);
+	if (!dev || !dev->chip_info) {
+		printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+		return;
+	}
+	config = dev->chip_info;
+
+	uintptr_t pmc_bar = get_pmc_mmio_bar();
+
+	const uint32_t gpio_cfg_mask =
+		(GPE0_DWX_MASK << GPE0_DW1_SHIFT) |
+		(GPE0_DWX_MASK << GPE0_DW2_SHIFT) |
+		(GPE0_DWX_MASK << GPE0_DW3_SHIFT);
+
+	/* Assign to local variable */
+	dw1 = config->gpe0_dw1;
+	dw2 = config->gpe0_dw2;
+	dw3 = config->gpe0_dw3;
+
+	/* Making sure that bad values don't bleed into the other fields */
+	dw1 &= GPE0_DWX_MASK;
+	dw2 &= GPE0_DWX_MASK;
+	dw3 &= GPE0_DWX_MASK;
+
+	/* Route the GPIOs to the GPE0 block. Determine that all values
+	 * are different, and if they aren't use the reset values.
+	 * DW0 is reserved/unused */
+	if (dw1 == dw2 || dw2 == dw3) {
+		printk(BIOS_INFO, "PMC: Using default GPE route.\n");
+		gpio_cfg = read32((void *)pmc_bar + GPIO_GPE_CFG);
+
+		dw1 = (gpio_cfg >> GPE0_DW1_SHIFT) & GPE0_DWX_MASK;
+		dw2 = (gpio_cfg >> GPE0_DW2_SHIFT) & GPE0_DWX_MASK;
+		dw3 = (gpio_cfg >> GPE0_DW3_SHIFT) & GPE0_DWX_MASK;
+	} else {
+		gpio_cfg |= (uint32_t)dw1 << GPE0_DW1_SHIFT;
+		gpio_cfg |= (uint32_t)dw2 << GPE0_DW2_SHIFT;
+		gpio_cfg |= (uint32_t)dw3 << GPE0_DW3_SHIFT;
+	}
+
+	gpio_cfg_reg = read32((void *)pmc_bar + GPIO_GPE_CFG) & ~gpio_cfg_mask;
+	gpio_cfg_reg |= gpio_cfg & gpio_cfg_mask;
+
+	write32((void *)pmc_bar + GPIO_GPE_CFG, gpio_cfg_reg);
+
+	/* Set the routes in the GPIO communities as well. */
+	gpio_route_gpe(dw1, dw2, dw3);
+}
diff --git a/src/soc/intel/glk/reset.c b/src/soc/intel/glk/reset.c
new file mode 100644
index 0000000..3e62d81
--- /dev/null
+++ b/src/soc/intel/glk/reset.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <delay.h>
+#include <fsp/util.h>
+#include <reset.h>
+#include <soc/heci.h>
+#include <soc/pm.h>
+#include <timer.h>
+
+#define CSE_WAIT_MAX_MS							1000
+
+void global_reset(void)
+{
+	global_reset_enable(1);
+	hard_reset();
+}
+
+void reset_prepare(void)
+{
+	struct stopwatch sw;
+
+	/*
+	 * If CSE state is something else than 'normal', it is probably in some
+	 * recovery state. In this case there is no point in  waiting for it to
+	 * get ready so we cross fingers and reset.
+	 */
+	if (!heci_cse_normal()) {
+		printk(BIOS_DEBUG, "CSE is not in normal state, resetting\n");
+		return;
+	}
+
+	/* Reset if CSE is ready */
+	if (heci_cse_done())
+		return;
+
+	printk(BIOS_SPEW, "CSE is not yet ready, waiting\n");
+	stopwatch_init_msecs_expire(&sw, CSE_WAIT_MAX_MS);
+	while (!heci_cse_done()) {
+		if (stopwatch_expired(&sw)) {
+			printk(BIOS_SPEW, "CSE timed out. Resetting\n");
+			return;
+		}
+		mdelay(1);
+	}
+	printk(BIOS_SPEW, "CSE took %lu ms\n", stopwatch_duration_msecs(&sw));
+}
+
+void chipset_handle_reset(uint32_t status)
+{
+	switch(status) {
+	case FSP_STATUS_RESET_REQUIRED_5: /* Global Reset */
+		global_reset();
+		break;
+	default:
+		printk(BIOS_ERR, "unhandled reset type %x\n", status);
+		die("unknown reset type");
+		break;
+	}
+}
diff --git a/src/soc/intel/glk/romstage.c b/src/soc/intel/glk/romstage.c
new file mode 100644
index 0000000..b9733de
--- /dev/null
+++ b/src/soc/intel/glk/romstage.c
@@ -0,0 +1,192 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/cpu.h>
+#include <arch/early_variables.h>
+#include <arch/io.h>
+#include <arch/symbols.h>
+#include <assert.h>
+#include <bootmode.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include <device/pci_def.h>
+#include <device/resource.h>
+#include <fsp/api.h>
+#include <fsp/util.h>
+#include <soc/iomap.h>
+#include <soc/northbridge.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/romstage.h>
+#include <soc/spi.h>
+#include <soc/uart.h>
+#include <string.h>
+#include <timestamp.h>
+
+static struct chipset_power_state power_state CAR_GLOBAL;
+
+/* High Performance Event Timer Configuration */
+#define P2SB_HPTC				0x60
+#define P2SB_HPTC_ADDRESS_ENABLE		(1 << 7)
+/*
+ * ADDRESS_SELECT            ENCODING_RANGE
+ *      0                 0xFED0 0000 - 0xFED0 03FF
+ *      1                 0xFED0 1000 - 0xFED0 13FF
+ *      2                 0xFED0 2000 - 0xFED0 23FF
+ *      3                 0xFED0 3000 - 0xFED0 33FF
+ */
+#define P2SB_HPTC_ADDRESS_SELECT_0		(0 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_1		(1 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_2		(2 << 0)
+#define P2SB_HPTC_ADDRESS_SELECT_3		(3 << 0)
+
+/*
+ * Enables several BARs and devices which are needed for memory init
+ * - MCH_BASE_ADDR is needed in order to talk to the memory controller
+ * - HPET is enabled because FSP wants to store a pointer to global data in the
+ *   HPET comparator register
+ */
+static void soc_early_romstage_init(void)
+{
+	/* Set MCH base address and enable bit */
+	pci_write_config32(NB_DEV_ROOT, MCHBAR, MCH_BASE_ADDR | 1);
+
+	/* Enable decoding for HPET. Needed for FSP global pointer storage */
+	pci_write_config8(P2SB_DEV, P2SB_HPTC, P2SB_HPTC_ADDRESS_SELECT_0 |
+						P2SB_HPTC_ADDRESS_ENABLE);
+}
+
+static void disable_watchdog(void)
+{
+	uint32_t reg;
+
+	/* Stop TCO timer */
+	reg = inl(ACPI_PMIO_BASE + TCO1_CNT);
+	reg |= TCO_TMR_HLT;
+	outl(reg, ACPI_PMIO_BASE + TCO1_CNT);
+}
+
+static void migrate_power_state(int is_recovery)
+{
+	struct chipset_power_state *ps_cbmem;
+	struct chipset_power_state *ps_car;
+
+	ps_car = car_get_var_ptr(&power_state);
+	ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem));
+
+	if (ps_cbmem == NULL) {
+		printk(BIOS_DEBUG, "Unable to add power state to cbmem!\n");
+		return;
+	}
+	memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem));
+}
+ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state);
+
+asmlinkage void car_stage_entry(void)
+{
+	struct postcar_frame pcf;
+	uintptr_t top_of_ram;
+	bool s3wake;
+	struct chipset_power_state *ps = car_get_var_ptr(&power_state);
+
+	timestamp_add_now(TS_START_ROMSTAGE);
+
+	soc_early_romstage_init();
+	disable_watchdog();
+
+	console_init();
+
+	s3wake = fill_power_state(ps) == ACPI_S3;
+	fsp_memory_init(s3wake);
+	if (postcar_frame_init(&pcf, 1*KiB))
+		die("Unable to initialize postcar frame.\n");
+
+	mainboard_save_dimm_info();
+
+	/*
+	 * We need to make sure ramstage will be run cached. At this point exact
+	 * location of ramstage in cbmem is not known. Instruct postcar to cache
+	 * 16 megs under cbmem top which is a safe bet to cover ramstage.
+	 */
+	top_of_ram = (uintptr_t) cbmem_top();
+	/* cbmem_top() needs to be at least 16 MiB aligned */
+	assert(ALIGN_DOWN(top_of_ram, 16*MiB) == top_of_ram);
+	postcar_frame_add_mtrr(&pcf, top_of_ram - 16*MiB, 16*MiB, MTRR_TYPE_WRBACK);
+
+	/* Cache the memory-mapped boot media. */
+	if (IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED))
+		postcar_frame_add_mtrr(&pcf, -CONFIG_ROM_SIZE, CONFIG_ROM_SIZE,
+					MTRR_TYPE_WRPROT);
+
+	run_postcar_phase(&pcf);
+}
+
+static void fill_console_params(FSPM_UPD *mupd)
+{
+	if (IS_ENABLED(CONFIG_CONSOLE_SERIAL)) {
+		mupd->FspmConfig.SerialDebugPortDevice = CONFIG_UART_FOR_CONSOLE;
+		/* use MMIO port type */
+		mupd->FspmConfig.SerialDebugPortType = 2;
+		/* use 4 byte register stride */
+		mupd->FspmConfig.SerialDebugPortStrideSize = 2;
+		/* used only for port type set to external */
+		mupd->FspmConfig.SerialDebugPortAddress = 0;
+	} else {
+		mupd->FspmConfig.SerialDebugPortType = 0;
+	}
+}
+
+void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd)
+{
+	fill_console_params(mupd);
+	mainboard_memory_init_params(mupd);
+
+	/* Do NOT let FSP do any GPIO pad configuration */
+	mupd->FspmConfig.PreMemGpioTablePtr = (uintptr_t) NULL;
+
+	/*
+	 * Tell CSE we do not need to use Ring Buffer Protocol (RBP) to fetch
+	 * firmware for us if we are using memory-mapped SPI. This lets CSE
+	 * state machine transition to next boot state, so that it can function
+	 * as designed.
+	 */
+	mupd->FspmConfig.SkipCseRbp =
+		IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED);
+}
+
+__attribute__ ((weak))
+void mainboard_memory_init_params(FSPM_UPD *mupd)
+{
+	printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+__attribute__ ((weak))
+void mainboard_save_dimm_info(void)
+{
+	printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+int get_sw_write_protect_state(void)
+{
+	uint8_t status;
+
+	/* Return unprotected status if status read fails. */
+	return spi_read_status(&status) ? 0 : !!(status & 0x80);
+}
diff --git a/src/soc/intel/glk/smi.c b/src/soc/intel/glk/smi.c
new file mode 100644
index 0000000..3ad33fd
--- /dev/null
+++ b/src/soc/intel/glk/smi.c
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Lance Zhao <lijian.zhao at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <string.h>
+#include <soc/pm.h>
+#include <soc/smm.h>
+
+void southbridge_smm_clear_state(void)
+{
+	printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
+
+	if (get_smi_en() & APMC_EN) {
+		printk(BIOS_INFO, "SMI# handler already enabled?\n");
+		return;
+	}
+
+	printk(BIOS_DEBUG, "Done\n");
+
+	/* Dump and clear status registers */
+	clear_smi_status();
+	clear_pm1_status();
+	clear_tco_status();
+	clear_gpe_status();
+}
+
+void southbridge_smm_enable_smi(void)
+{
+	printk(BIOS_DEBUG, "Enabling SMIs.\n");
+	/* Configure events */
+	enable_pm1(PWRBTN_EN | GBL_EN);
+	disable_gpe(PME_B0_EN);
+
+	/* Enable SMI generation */
+	enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS | GPIO_EN);
+}
+
+void southbridge_clear_smi_status(void)
+{
+	/* Clear SMI status */
+	clear_smi_status();
+
+	/* Clear PM1 status */
+	clear_pm1_status();
+
+	/* Set EOS bit so other SMIs can occur. */
+	enable_smi(EOS);
+}
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
+{
+	/*
+	 * Issue SMI to set the gnvs pointer in SMM.
+	 * tcg and smi1 are unused.
+	 *
+	 * EAX = APM_CNT_GNVS_UPDATE
+	 * EBX = gnvs pointer
+	 * EDX = APM_CNT
+	 */
+	asm volatile (
+		"outb %%al, %%dx\n\t"
+		: /* ignore result */
+		: "a" (APM_CNT_GNVS_UPDATE),
+		  "b" ((u32)gnvs),
+		  "d" (APM_CNT)
+	);
+}
diff --git a/src/soc/intel/glk/smihandler.c b/src/soc/intel/glk/smihandler.c
new file mode 100644
index 0000000..b84e5cb
--- /dev/null
+++ b/src/soc/intel/glk/smihandler.c
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/hlt.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <device/pci_def.h>
+#include <elog.h>
+#include <soc/nvs.h>
+#include <soc/pm.h>
+#include <soc/gpio.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/intel/common/smi.h>
+#include <spi-generic.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <soc/smm.h>
+
+int smm_disable_busmaster(device_t dev)
+{
+	if (dev == PMC_DEV)
+		return 0;
+	return 1;
+}
+
+const struct smm_save_state_ops *get_smm_save_state_ops(void)
+{
+	return &em64t100_smm_ops;
+}
+
+void __attribute__((weak))
+mainboard_smi_gpi_handler(const struct gpi_status *sts) { }
+
+static void southbridge_smi_gpi(const struct smm_save_state_ops *save_state_ops)
+{
+	struct gpi_status smi_sts;
+
+	gpi_clear_get_smi_status(&smi_sts);
+	mainboard_smi_gpi_handler(&smi_sts);
+
+	/* Clear again after mainboard handler */
+	gpi_clear_get_smi_status(&smi_sts);
+}
+
+const smi_handler_t southbridge_smi[32] = {
+	[SLP_SMI_STS] = southbridge_smi_sleep,
+	[APM_SMI_STS] = southbridge_smi_apmc,
+	[FAKE_PM1_SMI_STS] = southbridge_smi_pm1,
+	[GPIO_SMI_STS] = southbridge_smi_gpi,
+	[TCO_SMI_STS] = southbridge_smi_tco,
+	[PERIODIC_SMI_STS] = southbridge_smi_periodic,
+};
diff --git a/src/soc/intel/glk/spi.c b/src/soc/intel/glk/spi.c
new file mode 100644
index 0000000..139d36c
--- /dev/null
+++ b/src/soc/intel/glk/spi.c
@@ -0,0 +1,395 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define __SIMPLE_DEVICE__
+
+#include <arch/early_variables.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <soc/pci_devs.h>
+#include <soc/spi.h>
+#include <spi_flash.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Helper to create a SPI context on API entry. */
+#define BOILERPLATE_CREATE_CTX(ctx)		\
+	struct spi_ctx	real_ctx;		\
+	struct spi_ctx *ctx = &real_ctx;	\
+	_spi_get_ctx(ctx)
+
+/*
+ * Anything that's not success is <0. Provided solely for readability, as these
+ * constants are not used outside this file.
+ */
+enum errors {
+	SUCCESS			= 0,
+	E_NOT_IMPLEMENTED	= -1,
+	E_TIMEOUT		= -2,
+	E_HW_ERROR		= -3,
+	E_ARGUMENT		= -4,
+};
+
+/* Reduce data-passing burden by grouping transaction data in a context. */
+struct spi_ctx {
+	uintptr_t mmio_base;
+	device_t pci_dev;
+	uint32_t hsfsts_on_last_error;
+};
+
+static void _spi_get_ctx(struct spi_ctx *ctx)
+{
+	uint32_t bar;
+
+	/* FIXME: use device definition */
+	ctx->pci_dev = SPI_DEV;
+
+	bar = pci_read_config32(ctx->pci_dev, PCI_BASE_ADDRESS_0);
+	ctx->mmio_base = bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+	ctx->hsfsts_on_last_error = 0;
+}
+
+/* Read register from the SPI controller. 'reg' is the register offset. */
+static uint32_t _spi_ctrlr_reg_read(struct spi_ctx *ctx, uint16_t reg)
+{
+	uintptr_t addr =  ALIGN_DOWN(ctx->mmio_base + reg, 4);
+	return read32((void *)addr);
+}
+
+uint32_t spi_ctrlr_reg_read(uint16_t reg)
+{
+	BOILERPLATE_CREATE_CTX(ctx);
+	return _spi_ctrlr_reg_read(ctx, reg);
+}
+
+/* Write to register in the SPI controller. 'reg' is the register offset. */
+static void _spi_ctrlr_reg_write(struct spi_ctx *ctx, uint16_t reg,
+				 uint32_t val)
+{
+	uintptr_t addr =  ALIGN_DOWN(ctx->mmio_base + reg, 4);
+	write32((void *)addr, val);
+
+}
+
+/*
+ * The hardware datasheet is not clear on what HORD values actually do. It
+ * seems that HORD_SFDP provides access to the first 8 bytes of the SFDP, which
+ * is the signature and revision fields. HORD_JEDEC provides access to the
+ * actual flash parameters, and is most likely what you want to use when
+ * probing the flash from software.
+ * It's okay to rely on SFPD, since the SPI controller requires an SFDP 1.5 or
+ * newer compliant SPI chip.
+ * NOTE: Due to the register layout of the hardware, all accesses will be
+ * aligned to a 4 byte boundary.
+ */
+static uint32_t read_spi_sfdp_param(struct spi_ctx *ctx, uint16_t sfdp_reg)
+{
+	uint32_t ptinx_index = sfdp_reg & SPIBAR_PTINX_IDX_MASK;
+	_spi_ctrlr_reg_write(ctx, SPIBAR_PTINX,
+			     ptinx_index | SPIBAR_PTINX_HORD_JEDEC);
+	return _spi_ctrlr_reg_read(ctx, SPIBAR_PTDATA);
+}
+
+/* Fill FDATAn FIFO in preparation for a write transaction. */
+static void fill_xfer_fifo(struct spi_ctx *ctx, const void *data, size_t len)
+{
+	len = min(len, SPIBAR_FDATA_FIFO_SIZE);
+
+	/* YES! memcpy() works. FDATAn does not require 32-bit accesses. */
+	memcpy((void*)(ctx->mmio_base + SPIBAR_FDATA(0)), data, len);
+}
+
+/* Drain FDATAn FIFO after a read transaction populates data. */
+static void drain_xfer_fifo(struct spi_ctx *ctx, void *dest, size_t len)
+{
+	len = min(len, SPIBAR_FDATA_FIFO_SIZE);
+
+	/* YES! memcpy() works. FDATAn does not require 32-bit accesses. */
+	memcpy(dest, (void*)(ctx->mmio_base + SPIBAR_FDATA(0)), len);
+}
+
+/* Fire up a transfer using the hardware sequencer. */
+static void start_hwseq_xfer(struct spi_ctx *ctx, uint32_t hsfsts_cycle,
+				 uint32_t flash_addr, size_t len)
+{
+	/* Make sure all W1C status bits get cleared. */
+	uint32_t hsfsts = SPIBAR_HSFSTS_W1C_BITS;
+	/* Set up transaction parameters. */
+	hsfsts |= hsfsts_cycle & SPIBAR_HSFSTS_FCYCLE_MASK;
+	hsfsts |= SPIBAR_HSFSTS_FBDC(len - 1);
+
+	_spi_ctrlr_reg_write(ctx, SPIBAR_FADDR, flash_addr);
+	_spi_ctrlr_reg_write(ctx, SPIBAR_HSFSTS_CTL,
+			     hsfsts | SPIBAR_HSFSTS_FGO);
+}
+
+static void print_xfer_error(struct spi_ctx *ctx, const char *failure_reason,
+			     uint32_t flash_addr)
+{
+	printk(BIOS_ERR, "SPI Transaction %s at flash offset %x.\n"
+			 "\tHSFSTS = 0x%08x\n",
+	       failure_reason, flash_addr, ctx->hsfsts_on_last_error);
+}
+
+static int wait_for_hwseq_xfer(struct spi_ctx *ctx)
+{
+	uint32_t hsfsts;
+	do {
+		hsfsts = _spi_ctrlr_reg_read(ctx, SPIBAR_HSFSTS_CTL);
+
+		if (hsfsts & SPIBAR_HSFSTS_FCERR) {
+			ctx->hsfsts_on_last_error = hsfsts;
+			return E_HW_ERROR;
+		}
+	/* TODO: set up timer and abort on timeout */
+	} while (!(hsfsts & SPIBAR_HSFSTS_FDONE));
+
+	return SUCCESS;
+}
+
+/* Execute SPI transfer. This is a blocking call. */
+static int exec_sync_hwseq_xfer(struct spi_ctx *ctx, uint32_t hsfsts_cycle,
+				 uint32_t flash_addr, size_t len)
+{
+	int ret;
+	start_hwseq_xfer(ctx, hsfsts_cycle, flash_addr, len);
+	ret = wait_for_hwseq_xfer(ctx);
+	if (ret != SUCCESS) {
+		const char *reason = (ret == E_TIMEOUT) ? "timeout" : "error";
+		print_xfer_error(ctx, reason, flash_addr);
+	}
+	return ret;
+}
+
+unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
+{
+	return MIN(buf_len, SPIBAR_FDATA_FIFO_SIZE);
+}
+
+int spi_xfer(struct spi_slave *slave, const void *dout,
+		unsigned int bytesout, void *din, unsigned int bytesin)
+{
+	printk(BIOS_DEBUG, "NOT IMPLEMENTED: %s() !!!\n", __func__);
+	return E_NOT_IMPLEMENTED;
+}
+
+/*
+ * Write-protection status for BIOS region (BIOS_CONTROL register):
+ * EISS/WPD bits	00	01	10	11
+ * 			--	--	--	--
+ * normal mode		RO	RW	RO	RO
+ * SMM mode		RO	RW	RO	RW
+ */
+void spi_init(void)
+{
+	uint32_t bios_ctl;
+
+	BOILERPLATE_CREATE_CTX(ctx);
+
+	bios_ctl = pci_read_config32(ctx->pci_dev, SPIBAR_BIOS_CONTROL);
+	bios_ctl |= SPIBAR_BIOS_CONTROL_WPD;
+	bios_ctl &= ~SPIBAR_BIOS_CONTROL_EISS;
+
+	/* Enable Prefetching and caching. */
+	bios_ctl |= SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE;
+	bios_ctl &= ~SPIBAR_BIOS_CONTROL_CACHE_DISABLE;
+
+	pci_write_config32(ctx->pci_dev, SPIBAR_BIOS_CONTROL, bios_ctl);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	/* There's nothing we need to to here. */
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	/* No magic needed here. */
+}
+
+static int nuclear_spi_erase(struct spi_flash *flash, uint32_t offset, size_t len)
+{
+	int ret;
+	size_t erase_size;
+	uint32_t erase_cycle;
+
+	BOILERPLATE_CREATE_CTX(ctx);
+
+	if (!IS_ALIGNED(offset, 4 * KiB) || !IS_ALIGNED(len, 4 * KiB)) {
+		printk(BIOS_ERR, "BUG! SPI erase region not sector aligned.\n");
+		return E_ARGUMENT;
+	}
+
+	while (len) {
+		if (IS_ALIGNED(offset, 64 * KiB) && (len >= 64 * KiB)) {
+			erase_size = 64 * KiB;
+			erase_cycle = SPIBAR_HSFSTS_CYCLE_64K_ERASE;
+		} else {
+			erase_size = 4 * KiB;
+			erase_cycle = SPIBAR_HSFSTS_CYCLE_4K_ERASE;
+		}
+		printk(BIOS_SPEW, "Erasing flash addr %x + %zu KiB\n",
+		       offset, erase_size / KiB);
+
+		ret = exec_sync_hwseq_xfer(ctx, erase_cycle, offset, 0);
+		if (ret != SUCCESS)
+			return ret;
+
+		offset += erase_size;
+		len -= erase_size;
+	}
+
+	return SUCCESS;
+}
+
+static int nuclear_spi_read(struct spi_flash *flash, uint32_t addr, size_t len, void *buf)
+{
+	int ret;
+	size_t xfer_len;
+	uint8_t *data = buf;
+
+	BOILERPLATE_CREATE_CTX(ctx);
+
+	while (len) {
+		xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE);
+
+		ret = exec_sync_hwseq_xfer(ctx, SPIBAR_HSFSTS_CYCLE_READ,
+						addr, xfer_len);
+		if (ret != SUCCESS)
+			return ret;
+
+		drain_xfer_fifo(ctx, data, xfer_len);
+
+		addr += xfer_len;
+		data += xfer_len;
+		len -= xfer_len;
+	}
+
+	return SUCCESS;
+}
+
+static int nuclear_spi_write(struct spi_flash *flash,
+			   uint32_t addr, size_t len, const void *buf)
+{
+	int ret;
+	size_t xfer_len;
+	const uint8_t *data = buf;
+
+	BOILERPLATE_CREATE_CTX(ctx);
+
+	while (len) {
+		xfer_len = min(len, SPIBAR_FDATA_FIFO_SIZE);
+		fill_xfer_fifo(ctx, data, xfer_len);
+
+		ret = exec_sync_hwseq_xfer(ctx, SPIBAR_HSFSTS_CYCLE_WRITE,
+						addr, xfer_len);
+		if (ret != SUCCESS)
+			return ret;
+
+		addr += xfer_len;
+		data += xfer_len;
+		len -= xfer_len;
+	}
+
+	return SUCCESS;
+}
+
+static int nuclear_spi_status(struct spi_flash *flash, uint8_t *reg)
+{
+	printk(BIOS_DEBUG, "NOT IMPLEMENTED: %s() !!!\n", __func__);
+	return E_NOT_IMPLEMENTED;
+}
+
+static struct spi_slave boot_spi CAR_GLOBAL;
+static struct spi_flash boot_flash CAR_GLOBAL;
+
+/*
+ * We can't use FDOC and FDOD to read FLCOMP, as previous platforms did.
+ * For details see:
+ * Ch 31, SPI: p. 194
+ * The size of the flash component is always taken from density field in the
+ * SFDP table. FLCOMP.C0DEN is no longer used by the Flash Controller.
+ */
+static struct spi_flash *nuclear_flash_probe(struct spi_slave *spi)
+{
+	BOILERPLATE_CREATE_CTX(ctx);
+	struct spi_flash *flash;
+	uint32_t flash_bits;
+
+	flash = car_get_var_ptr(&boot_flash);
+
+	/*
+	 * bytes = (bits + 1) / 8;
+	 * But we need to do the addition in a way which doesn't overflow for
+	 * 4 Gbit devices (flash_bits == 0xffffffff).
+	 */
+	/* FIXME: Don't hardcode 0x04 ? */
+	flash_bits = read_spi_sfdp_param(ctx, 0x04);
+	flash->size = (flash_bits >> 3) + 1;
+
+	flash->spi = spi;
+	flash->name = "Apollolake hardware sequencer";
+
+	/* Can erase both 4 KiB and 64 KiB chunks. Declare the smaller size. */
+	flash->sector_size = 4 * KiB;
+	/*
+	 * FIXME: Get erase+cmd, and status_cmd from SFDP.
+	 *
+	 * flash->erase_cmd = ???
+	 * flash->status_cmd = ???
+	 */
+
+	flash->write = nuclear_spi_write;
+	flash->erase = nuclear_spi_erase;
+	flash->read = nuclear_spi_read;
+	flash->status = nuclear_spi_status;
+
+	return flash;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
+{
+	BOILERPLATE_CREATE_CTX(ctx);
+
+	/* This is special hardware. We expect bus 0 and CS line 0 here. */
+	if ((bus != 0) || (cs != 0))
+		return NULL;
+
+	struct spi_slave *slave = car_get_var_ptr(&boot_spi);
+
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->programmer_specific_probe = nuclear_flash_probe;
+	slave->force_programmer_specific = 1;
+
+	return slave;
+}
+
+int spi_read_status(uint8_t *status)
+{
+	BOILERPLATE_CREATE_CTX(ctx);
+
+	if (exec_sync_hwseq_xfer(ctx, SPIBAR_HSFSTS_CYCLE_RD_STATUS, 0,
+				 sizeof(*status)) != SUCCESS)
+		return -1;
+
+	drain_xfer_fifo(ctx, status, sizeof(*status));
+
+	return 0;
+}
diff --git a/src/soc/intel/glk/tsc_freq.c b/src/soc/intel/glk/tsc_freq.c
new file mode 100644
index 0000000..9dd1dea
--- /dev/null
+++ b/src/soc/intel/glk/tsc_freq.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <cpu/x86/msr.h>
+#include <cpu/x86/tsc.h>
+#include <soc/cpu.h>
+
+unsigned long tsc_freq_mhz(void)
+{
+    msr_t msr = rdmsr(MSR_PLATFORM_INFO);
+    return (BASE_CLOCK_MHZ * ((msr.lo >> 8) & 0xff));
+}
diff --git a/src/soc/intel/glk/uart.c b/src/soc/intel/glk/uart.c
new file mode 100644
index 0000000..7b50a21
--- /dev/null
+++ b/src/soc/intel/glk/uart.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * The sole purpose of this driver is to avoid BAR to be changed during
+ * resource allocation. Since configuration space is just 32 bytes it
+ * shouldn't cause any fragmentation.
+ */
+
+#include <console/uart.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/pci_ids.h>
+#include <soc/pci_devs.h>
+
+static void aplk_uart_read_resources(struct device *dev)
+{
+	pci_dev_read_resources(dev);
+
+	if ((IS_ENABLED(CONFIG_SOC_UART_DEBUG) &&
+	    dev->path.pci.devfn == _LPSS_PCI_DEVFN(UART,
+						CONFIG_UART_FOR_CONSOLE))) {
+		/* will override existing resource. */
+		fixed_mem_resource(dev, PCI_BASE_ADDRESS_0,
+				CONFIG_CONSOLE_UART_BASE_ADDRESS >> 10, 4, 0);
+	}
+}
+
+static struct device_operations uart_ops = {
+	.read_resources   = aplk_uart_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = pci_dev_init,
+	.enable           = DEVICE_NOOP
+};
+
+static const unsigned short uart_ids[] = {
+	PCI_DEVICE_ID_APOLLOLAKE_UART0, PCI_DEVICE_ID_APOLLOLAKE_UART1,
+	PCI_DEVICE_ID_APOLLOLAKE_UART2, PCI_DEVICE_ID_APOLLOLAKE_UART3,
+	0
+};
+
+static const struct pci_driver uart_driver __pci_driver = {
+	.ops     = &uart_ops,
+	.vendor  = PCI_VENDOR_ID_INTEL,
+	.devices = uart_ids
+};
diff --git a/src/soc/intel/glk/uart_early.c b/src/soc/intel/glk/uart_early.c
new file mode 100644
index 0000000..ea7d902
--- /dev/null
+++ b/src/soc/intel/glk/uart_early.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/uart.h>
+#include <device/pci.h>
+#include <soc/gpio.h>
+#include <soc/uart.h>
+#include <soc/pci_devs.h>
+
+static void lpss_uart_write(uint16_t reg, uint32_t val)
+{
+	uintptr_t base = CONFIG_CONSOLE_UART_BASE_ADDRESS | reg;
+	write32((void *)base, val);
+}
+
+static inline int invalid_uart_for_console(void)
+{
+	/* There are actually only 2 UARTS, and they are named UART1 and
+	 * UART2. They live at pci functions 1 and 2 respectively. */
+	if (CONFIG_UART_FOR_CONSOLE > 2 || CONFIG_UART_FOR_CONSOLE < 1)
+		return 1;
+	return 0;
+}
+
+void lpss_console_uart_init(void)
+{
+	uint32_t clk_sel;
+	device_t uart = _LPSS_PCI_DEV(UART, CONFIG_UART_FOR_CONSOLE & 3);
+
+	if (invalid_uart_for_console())
+		return;
+
+	/* Enable BAR0 for the UART -- this is where the 8250 registers hide */
+	pci_write_config32(uart, PCI_BASE_ADDRESS_0,
+			   CONFIG_CONSOLE_UART_BASE_ADDRESS);
+
+	/* Enable memory access and bus master */
+	pci_write_config32(uart, PCI_COMMAND,
+			   PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+	/* Take UART out of reset */
+	lpss_uart_write(UART_RESET, UART_RESET_UART_EN);
+
+	/* These values get us a 1.836 MHz clock (ideally we want 1.843 MHz) */
+	clk_sel = UART_CLK_DIV_N(0x7fff) | UART_CLK_DIV_M(0x025a);
+	/* Set M and N divisor inputs and enable clock */
+	lpss_uart_write(UART_CLK, clk_sel | UART_CLK_UPDATE);
+	lpss_uart_write(UART_CLK, clk_sel | UART_CLK_EN);
+
+}
+
+uintptr_t uart_platform_base(int idx)
+{
+	return (CONFIG_CONSOLE_UART_BASE_ADDRESS);
+}
+
+static const struct pad_config uart_gpios[] = {
+};
+
+void soc_console_uart_init(void)
+{
+	/* Get a 0-based pad index. See invalid_uart_for_console() above. */
+	//const int pad_index = CONFIG_UART_FOR_CONSOLE - 1;
+
+	if (invalid_uart_for_console())
+		return;
+
+	/* Configure the 2 pads per UART. */
+	//gpio_configure_pads(&uart_gpios[pad_index * 2], 2);
+
+	lpss_console_uart_init();
+}
diff --git a/src/soc/intel/glk/xhci.c b/src/soc/intel/glk/xhci.c
new file mode 100644
index 0000000..7b3cb46
--- /dev/null
+++ b/src/soc/intel/glk/xhci.c
@@ -0,0 +1,105 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/pci_devs.h>
+#include <soc/pci_ids.h>
+#include <timer.h>
+
+#define DUAL_ROLE_CFG0		0x80d8
+# define DRD_CONFIG_MASK	(0x3 << 0)
+# define DRD_CONFIG_DYNAMIC	(0x0 << 0)
+# define DRD_CONFIG_HOST	(0x1 << 0)
+# define DRD_CONFIG_DEVICE	(0x2 << 0)
+# define SW_VBUS_VALID_MASK	(1 << 24)
+# define SW_VBUS_DEASSERT_VALID	(0 << 24)
+# define SW_VBUS_ASSERT_VALID	(1 << 24)
+# define SW_IDPIN_EN_MASK	(1 << 21)
+# define SW_IDPIN_DIS		(0 << 21)
+# define SW_IDPIN_EN		(1 << 21)
+# define SW_IDPIN_MASK		(1 << 20)
+# define SW_IDPIN_HOST		(0 << 20)
+# define SW_IDPIN_DEVICE	(1 << 20)
+#define DUAL_ROLE_CFG1		0x80dc
+# define DRD_MODE_MASK		(1 << 29)
+# define DRD_MODE_DEVICE	(0 << 29)
+# define DRD_MODE_HOST		(1 << 29)
+
+static void configure_host_mode_port0(struct device *dev)
+{
+	uint32_t *cfg0;
+	uint32_t *cfg1;
+	const struct resource *res;
+	uint32_t reg;
+	struct device *xdci_dev = XDCI_DEV;
+	struct stopwatch sw;
+
+	/*
+	 * Only default to host mode if the xdci device is present and
+	 * enabled. If it's disabled assume the switch was already done
+	 * in FSP.
+	 */
+	if (xdci_dev == NULL || !xdci_dev->enabled)
+		return;
+
+	printk(BIOS_INFO, "Putting port 0 into host mode.\n");
+
+	res = find_resource(dev, PCI_BASE_ADDRESS_0);
+
+	cfg0 = (void *)(uintptr_t)(res->base + DUAL_ROLE_CFG0);
+	cfg1 = (void *)(uintptr_t)(res->base + DUAL_ROLE_CFG1);
+
+	reg = read32(cfg0);
+	reg &= ~(DRD_CONFIG_MASK | SW_IDPIN_EN_MASK | SW_IDPIN_MASK);
+	reg &= ~(SW_VBUS_VALID_MASK);
+	reg |= DRD_CONFIG_DYNAMIC | SW_IDPIN_EN | SW_IDPIN_HOST;
+	reg |= SW_VBUS_DEASSERT_VALID;
+	write32(cfg0, reg);
+
+	stopwatch_init_msecs_expire(&sw, 10);
+
+	/* Wait for the host mode status bit. */
+	while ((read32(cfg1) & DRD_MODE_MASK) != DRD_MODE_HOST) {
+		if (stopwatch_expired(&sw)) {
+			printk(BIOS_INFO, "Timed out waiting for host mode.\n");
+			break;
+		}
+	}
+
+	printk(BIOS_INFO, "XHCI port 0 host switch over took %lu ms\n",
+		stopwatch_duration_msecs(&sw));
+}
+
+static void xhci_init(struct device *dev)
+{
+	configure_host_mode_port0(dev);
+}
+
+static const struct device_operations device_ops = {
+	.read_resources		= pci_dev_read_resources,
+	.set_resources		= pci_dev_set_resources,
+	.enable_resources	= pci_dev_enable_resources,
+	.init			= xhci_init,
+};
+
+static const struct pci_driver pmc __pci_driver = {
+	.ops	= &device_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= PCI_DEVICE_ID_APOLLOLAKE_XHCI,
+};



More information about the coreboot-gerrit mailing list