summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/braswell/Kconfig245
-rw-r--r--src/soc/intel/braswell/Makefile.inc107
-rw-r--r--src/soc/intel/braswell/acpi.c511
-rw-r--r--src/soc/intel/braswell/acpi/cpu.asl77
-rw-r--r--src/soc/intel/braswell/acpi/device_nvs.asl87
-rw-r--r--src/soc/intel/braswell/acpi/dptf/charger.asl59
-rw-r--r--src/soc/intel/braswell/acpi/dptf/cpu.asl144
-rw-r--r--src/soc/intel/braswell/acpi/dptf/dptf.asl78
-rw-r--r--src/soc/intel/braswell/acpi/dptf/thermal.asl203
-rw-r--r--src/soc/intel/braswell/acpi/globalnvs.asl108
-rw-r--r--src/soc/intel/braswell/acpi/gpio.asl110
-rw-r--r--src/soc/intel/braswell/acpi/irq_helper.h48
-rw-r--r--src/soc/intel/braswell/acpi/irqlinks.asl492
-rw-r--r--src/soc/intel/braswell/acpi/irqroute.asl37
-rw-r--r--src/soc/intel/braswell/acpi/lpc.asl167
-rw-r--r--src/soc/intel/braswell/acpi/lpe.asl119
-rw-r--r--src/soc/intel/braswell/acpi/lpss.asl712
-rw-r--r--src/soc/intel/braswell/acpi/pcie.asl109
-rw-r--r--src/soc/intel/braswell/acpi/platform.asl78
-rw-r--r--src/soc/intel/braswell/acpi/scc.asl187
-rw-r--r--src/soc/intel/braswell/acpi/sleepstates.asl26
-rw-r--r--src/soc/intel/braswell/acpi/southcluster.asl274
-rw-r--r--src/soc/intel/braswell/acpi/xhci.asl36
-rw-r--r--src/soc/intel/braswell/bootblock/Makefile.inc1
-rw-r--r--src/soc/intel/braswell/bootblock/bootblock.c79
-rw-r--r--src/soc/intel/braswell/bootblock/timestamp.inc18
-rw-r--r--src/soc/intel/braswell/chip.c93
-rw-r--r--src/soc/intel/braswell/chip.h95
-rw-r--r--src/soc/intel/braswell/cpu.c309
-rw-r--r--src/soc/intel/braswell/dptf.c52
-rw-r--r--src/soc/intel/braswell/ehci.c181
-rw-r--r--src/soc/intel/braswell/elog.c122
-rw-r--r--src/soc/intel/braswell/emmc.c77
-rw-r--r--src/soc/intel/braswell/gfx.c398
-rw-r--r--src/soc/intel/braswell/gpio.c245
-rw-r--r--src/soc/intel/braswell/hda.c118
-rw-r--r--src/soc/intel/braswell/include/soc/acpi.h31
-rw-r--r--src/soc/intel/braswell/include/soc/device_nvs.h68
-rw-r--r--src/soc/intel/braswell/include/soc/efi_wrapper.h52
-rw-r--r--src/soc/intel/braswell/include/soc/ehci.h44
-rw-r--r--src/soc/intel/braswell/include/soc/gfx.h64
-rw-r--r--src/soc/intel/braswell/include/soc/gpio.h459
-rw-r--r--src/soc/intel/braswell/include/soc/iomap.h90
-rw-r--r--src/soc/intel/braswell/include/soc/iosf.h349
-rw-r--r--src/soc/intel/braswell/include/soc/irq.h164
-rw-r--r--src/soc/intel/braswell/include/soc/lpc.h54
-rw-r--r--src/soc/intel/braswell/include/soc/mrc_wrapper.h107
-rw-r--r--src/soc/intel/braswell/include/soc/msr.h51
-rw-r--r--src/soc/intel/braswell/include/soc/nvs.h78
-rw-r--r--src/soc/intel/braswell/include/soc/pattrs.h64
-rw-r--r--src/soc/intel/braswell/include/soc/pci_devs.h155
-rw-r--r--src/soc/intel/braswell/include/soc/pcie.h102
-rw-r--r--src/soc/intel/braswell/include/soc/pmc.h303
-rw-r--r--src/soc/intel/braswell/include/soc/ramstage.h42
-rw-r--r--src/soc/intel/braswell/include/soc/reset.h36
-rw-r--r--src/soc/intel/braswell/include/soc/romstage.h54
-rw-r--r--src/soc/intel/braswell/include/soc/sata.h26
-rw-r--r--src/soc/intel/braswell/include/soc/smm.h49
-rw-r--r--src/soc/intel/braswell/include/soc/spi.h74
-rw-r--r--src/soc/intel/braswell/include/soc/xhci.h56
-rw-r--r--src/soc/intel/braswell/iosf.c287
-rw-r--r--src/soc/intel/braswell/lpe.c189
-rw-r--r--src/soc/intel/braswell/lpss.c206
-rw-r--r--src/soc/intel/braswell/memmap.c33
-rw-r--r--src/soc/intel/braswell/microcode/Makefile.inc1
-rw-r--r--src/soc/intel/braswell/microcode/microcode_blob.c3
-rw-r--r--src/soc/intel/braswell/northcluster.c148
-rw-r--r--src/soc/intel/braswell/pcie.c278
-rw-r--r--src/soc/intel/braswell/perf_power.c292
-rw-r--r--src/soc/intel/braswell/placeholders.c11
-rw-r--r--src/soc/intel/braswell/pmutil.c364
-rw-r--r--src/soc/intel/braswell/ramstage.c206
-rw-r--r--src/soc/intel/braswell/refcode.c148
-rw-r--r--src/soc/intel/braswell/reset.c47
-rw-r--r--src/soc/intel/braswell/romstage/Makefile.inc7
-rw-r--r--src/soc/intel/braswell/romstage/cache_as_ram.inc285
-rw-r--r--src/soc/intel/braswell/romstage/early_spi.c65
-rw-r--r--src/soc/intel/braswell/romstage/gfx.c50
-rw-r--r--src/soc/intel/braswell/romstage/pmc.c81
-rw-r--r--src/soc/intel/braswell/romstage/raminit.c191
-rw-r--r--src/soc/intel/braswell/romstage/romstage.c377
-rw-r--r--src/soc/intel/braswell/romstage/uart.c38
-rw-r--r--src/soc/intel/braswell/sata.c240
-rw-r--r--src/soc/intel/braswell/scc.c125
-rw-r--r--src/soc/intel/braswell/sd.c70
-rw-r--r--src/soc/intel/braswell/smihandler.c483
-rw-r--r--src/soc/intel/braswell/smm.c133
-rw-r--r--src/soc/intel/braswell/southcluster.c572
-rw-r--r--src/soc/intel/braswell/spi.c647
-rw-r--r--src/soc/intel/braswell/stage_cache.c35
-rw-r--r--src/soc/intel/braswell/tsc_freq.c84
-rw-r--r--src/soc/intel/braswell/xhci.c259
92 files changed, 14329 insertions, 0 deletions
diff --git a/src/soc/intel/braswell/Kconfig b/src/soc/intel/braswell/Kconfig
new file mode 100644
index 0000000000..3f938c3d2a
--- /dev/null
+++ b/src/soc/intel/braswell/Kconfig
@@ -0,0 +1,245 @@
+config SOC_INTEL_BRASWELL
+ bool
+ help
+ Bay Trail M/D part support.
+
+if SOC_INTEL_BRASWELL
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select ARCH_BOOTBLOCK_X86_32
+ select ARCH_VERSTAGE_X86_32
+ select ARCH_ROMSTAGE_X86_32
+ select ARCH_RAMSTAGE_X86_32
+ select BACKUP_DEFAULT_SMM_REGION
+ select CACHE_MRC_SETTINGS
+ select CAR_MIGRATION
+ select COLLECT_TIMESTAMPS
+ select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+ select SUPPORT_CPU_UCODE_IN_CBFS
+ select HAVE_SMI_HANDLER
+ select HAVE_HARD_RESET
+ select MMCONF_SUPPORT
+ select MMCONF_SUPPORT_DEFAULT
+ select RELOCATABLE_MODULES
+ select RELOCATABLE_RAMSTAGE
+ select PARALLEL_MP
+ select PCIEXP_ASPM
+ select PCIEXP_COMMON_CLOCK
+ select REG_SCRIPT
+ select SMM_MODULES
+ select SMM_TSEG
+ select SMP
+ select SPI_FLASH
+ select SSE2
+ select SUPPORT_CPU_UCODE_IN_CBFS
+ select TSC_CONSTANT_RATE
+ select TSC_MONOTONIC_TIMER
+ select TSC_SYNC_MFENCE
+ select UDELAY_TSC
+ select SOC_INTEL_COMMON
+
+config BOOTBLOCK_CPU_INIT
+ string
+ default "soc/intel/baytrail/bootblock/bootblock.c"
+
+config MMCONF_BASE_ADDRESS
+ hex
+ default 0xe0000000
+
+config MAX_CPUS
+ int
+ default 4
+
+config CPU_ADDR_BITS
+ int
+ default 36
+
+config SMM_TSEG_SIZE
+ hex
+ default 0x800000
+
+config SMM_RESERVED_SIZE
+ hex
+ default 0x100000
+
+config HAVE_MRC
+ bool "Add a Memory Reference Code binary"
+ default y
+ help
+ Select this option to add a blob containing
+ memory reference code.
+ Note: Without this binary coreboot will not work
+
+if HAVE_MRC
+
+config MRC_FILE
+ string "Intel memory refeference code path and filename"
+ default "3rdparty/northbridge/intel/sandybridge/systemagent-r6.bin"
+ help
+ The path and filename of the file to use as System Agent
+ binary. Note that this points to the sandybridge binary file
+ which is will not work, but it serves its purpose to do builds.
+
+config MRC_BIN_ADDRESS
+ hex
+ default 0xfffa0000
+
+config MRC_RMT
+ bool "Enable MRC RMT training + debug prints"
+ default n
+
+endif # HAVE_MRC
+
+# Cache As RAM region layout:
+#
+# +-------------+ DCACHE_RAM_BASE + DCACHE_RAM_SIZE + DCACHE_RAM_MRC_VAR_SIZE
+# | MRC usage |
+# | |
+# +-------------+ DCACHE_RAM_BASE + DCACHE_RAM_SIZE
+# | Stack |\
+# | | | * DCACHE_RAM_ROMSTAGE_STACK_SIZE
+# | v |/
+# +-------------+
+# | ^ |
+# | | |
+# | CAR Globals |
+# +-------------+ DCACHE_RAM_BASE
+#
+# Note that the MRC binary is linked to assume the region marked as "MRC usage"
+# starts at DCACHE_RAM_BASE + DCACHE_RAM_SIZE. If those values change then
+# a new MRC binary needs to be produced with the updated start and size
+# information.
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xfe000000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x8000
+ help
+ The size of the cache-as-ram region required during bootblock
+ and/or romstage. Note DCACHE_RAM_SIZE and DCACHE_RAM_MRC_VAR_SIZE
+ must add up to a power of 2.
+
+config DCACHE_RAM_MRC_VAR_SIZE
+ hex
+ default 0x8000
+ help
+ The amount of cache-as-ram region required by the reference code.
+
+config DCACHE_RAM_ROMSTAGE_STACK_SIZE
+ hex
+ default 0x800
+ help
+ The amount of anticipated stack usage from the data cache
+ during pre-RAM ROM stage execution.
+
+config RESET_ON_INVALID_RAMSTAGE_CACHE
+ bool "Reset the system on S3 wake when ramstage cache invalid."
+ default n
+ depends on RELOCATABLE_RAMSTAGE
+ help
+ The baytrail romstage code caches the loaded ramstage program
+ in SMM space. On S3 wake the romstage will copy over a fresh
+ ramstage that was cached in the SMM space. This option determines
+ the action to take when the ramstage cache is invalid. If selected
+ the system will reset otherwise the ramstage will be reloaded from
+ cbfs.
+
+config CBFS_SIZE
+ hex "Size of CBFS filesystem in ROM"
+ default 0x100000
+ help
+ On Bay Trail systems the firmware image has to store a lot more
+ than just coreboot, including:
+ - a firmware descriptor
+ - Intel Management Engine firmware
+ - MRC cache information
+ This option allows to limit the size of the CBFS portion in the
+ firmware image.
+
+config ENABLE_BUILTIN_COM1
+ bool "Enable builtin COM1 Serial Port"
+ default n
+ help
+ The PMC has a legacy COM1 serial port. Choose this option to
+ configure the pads and enable it. This serial port can be used for
+ the debug console.
+
+config HAVE_ME_BIN
+ bool "Add Intel Management Engine firmware"
+ default y
+ help
+ The Intel processor in the selected system requires a special firmware
+ for an integrated controller called Management Engine (ME). The ME
+ firmware might be provided in coreboot's 3rdparty repository. If
+ not and if you don't have the firmware elsewhere, you can still
+ build coreboot without it. In this case however, you'll have to make
+ sure that you don't overwrite your ME firmware on your flash ROM.
+
+config ME_BIN_PATH
+ string "Path to management engine firmware"
+ depends on HAVE_ME_BIN
+ default "3rdparty/mainboard/$(MAINBOARDDIR)/me.bin"
+
+config HAVE_IFD_BIN
+ bool
+ default y
+
+config BUILD_WITH_FAKE_IFD
+ bool "Build with a fake IFD"
+ default y if !HAVE_IFD_BIN
+ help
+ If you don't have an Intel Firmware Descriptor (ifd.bin) for your
+ board, you can select this option and coreboot will build without it.
+ Though, the resulting coreboot.rom will not contain all parts required
+ to get coreboot running on your board. You can however write only the
+ BIOS section to your board's flash ROM and keep the other sections
+ untouched. Unfortunately the current version of flashrom doesn't
+ support this yet. But there is a patch pending [1].
+
+ WARNING: Never write a complete coreboot.rom to your flash ROM if it
+ was built with a fake IFD. It just won't work.
+
+ [1] http://www.flashrom.org/pipermail/flashrom/2013-June/011083.html
+
+config IFD_BIOS_SECTION
+ depends on BUILD_WITH_FAKE_IFD
+ string
+ default ""
+
+config IFD_ME_SECTION
+ depends on BUILD_WITH_FAKE_IFD
+ string
+ default ""
+
+config IFD_PLATFORM_SECTION
+ depends on BUILD_WITH_FAKE_IFD
+ string
+ default ""
+
+config IFD_BIN_PATH
+ string "Path to intel firmware descriptor"
+ depends on !BUILD_WITH_FAKE_IFD
+ default "3rdparty/mainboard/$(MAINBOARDDIR)/descriptor.bin"
+
+config HAVE_REFCODE_BLOB
+ depends on ARCH_X86
+ bool "An external reference code blob should be put into cbfs."
+ default n
+ help
+ The reference code blob will be placed into cbfs.
+
+if HAVE_REFCODE_BLOB
+
+config REFCODE_BLOB_FILE
+ string "Path and filename to reference code blob."
+ default "refcode.elf"
+ help
+ The path and filename to the file to be added to cbfs.
+
+endif # HAVE_REFCODE_BLOB
+
+endif
diff --git a/src/soc/intel/braswell/Makefile.inc b/src/soc/intel/braswell/Makefile.inc
new file mode 100644
index 0000000000..0806bbb532
--- /dev/null
+++ b/src/soc/intel/braswell/Makefile.inc
@@ -0,0 +1,107 @@
+ifeq ($(CONFIG_SOC_INTEL_BRASWELL),y)
+
+subdirs-y += bootblock
+subdirs-y += microcode
+subdirs-y += romstage
+subdirs-y += ../../../cpu/x86/lapic
+subdirs-y += ../../../cpu/x86/mtrr
+subdirs-y += ../../../cpu/x86/smm
+subdirs-y += ../../../cpu/x86/tsc
+subdirs-y += ../../../cpu/intel/microcode
+subdirs-y += ../../../cpu/intel/turbo
+
+ramstage-y += memmap.c
+romstage-y += memmap.c
+ramstage-y += tsc_freq.c
+romstage-y += tsc_freq.c
+smm-y += tsc_freq.c
+ramstage-y += spi.c
+smm-y += spi.c
+ramstage-y += chip.c
+ramstage-y += gfx.c
+ramstage-y += iosf.c
+romstage-y += iosf.c
+smm-y += iosf.c
+ramstage-y += northcluster.c
+ramstage-y += ramstage.c
+ramstage-y += gpio.c
+romstage-y += reset.c
+ramstage-y += reset.c
+ramstage-y += cpu.c
+ramstage-y += pmutil.c
+smm-y += pmutil.c
+smm-y += smihandler.c
+ramstage-y += smm.c
+ramstage-y += ehci.c
+ramstage-y += xhci.c
+ramstage-y += southcluster.c
+ramstage-$(CONFIG_HAVE_REFCODE_BLOB) += refcode.c
+ramstage-y += sata.c
+ramstage-y += acpi.c
+ramstage-y += lpe.c
+ramstage-y += scc.c
+ramstage-y += emmc.c
+ramstage-y += lpss.c
+ramstage-y += pcie.c
+ramstage-y += sd.c
+ramstage-y += dptf.c
+ramstage-y += perf_power.c
+ramstage-y += stage_cache.c
+romstage-y += stage_cache.c
+ramstage-$(CONFIG_ELOG) += elog.c
+ramstage-y += hda.c
+
+# Remove as ramstage gets fleshed out
+ramstage-y += placeholders.c
+
+CPPFLAGS_common += -Isrc/soc/intel/baytrail/include
+
+# Run an intermediate step when producing coreboot.rom
+# that adds additional components to the final firmware
+# image outside of CBFS
+INTERMEDIATE:=baytrail_add_me
+
+ifeq ($(CONFIG_BUILD_WITH_FAKE_IFD),y)
+IFD_BIN_PATH := $(objgenerated)/ifdfake.bin
+IFD_SECTIONS := $(addprefix -b ,$(CONFIG_IFD_BIOS_SECTION:"%"=%)) \
+ $(addprefix -m ,$(CONFIG_IFD_ME_SECTION:"%"=%)) \
+ $(addprefix -p ,$(CONFIG_IFD_PLATFORM_SECTION:"%"=%))
+else
+IFD_BIN_PATH := $(CONFIG_IFD_BIN_PATH)
+endif
+
+baytrail_add_me: $(obj)/coreboot.pre $(IFDTOOL) $(IFDFAKE)
+ifeq ($(CONFIG_BUILD_WITH_FAKE_IFD),y)
+ printf "\n** WARNING **\n"
+ printf "Coreboot will be built with a fake Intel Firmware Descriptor (IFD).\n"
+ printf "Never write a complete coreboot.rom with a fake IFD to your board's\n"
+ printf "flash ROM! Make sure that you only write valid flash regions.\n\n"
+ printf " IFDFAKE Building a fake Intel Firmware Descriptor\n"
+ $(IFDFAKE) $(IFD_SECTIONS) $(IFD_BIN_PATH)
+endif
+ printf " DD Adding Intel Firmware Descriptor\n"
+ dd if=$(IFD_BIN_PATH) \
+ of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1
+ifeq ($(CONFIG_HAVE_ME_BIN),y)
+ printf " IFDTOOL me.bin -> coreboot.pre\n"
+ $(objutil)/ifdtool/ifdtool \
+ -i ME:$(CONFIG_ME_BIN_PATH) \
+ $(obj)/coreboot.pre
+ mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre
+endif
+
+# If an MRC file is an ELF file determine the entry address and first loadable
+# section offset in the file. Subtract the offset from the entry address to
+# determine the final location.
+mrcelfoffset = $(shell $(READELF_x86_32) -S -W $(CONFIG_MRC_FILE) | sed -e 's/\[ /[0/' | awk '$$3 ~ /PROGBITS/ { print "0x"$$5; exit }' )
+mrcelfentry = $(shell $(READELF_x86_32) -h -W $(CONFIG_MRC_FILE) | grep 'Entry point address' | awk '{print $$NF }')
+
+# Add memory reference code blob.
+cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin
+mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE))
+mrc.bin-position := $(if $(findstring elf,$(CONFIG_MRC_FILE)),$(shell printf "0x%x" $$(( $(mrcelfentry) - $(mrcelfoffset) )) ),$(CONFIG_MRC_BIN_ADDRESS))
+mrc.bin-type := mrc
+
+PHONY += baytrail_add_me
+
+endif
diff --git a/src/soc/intel/braswell/acpi.c b/src/soc/intel/braswell/acpi.c
new file mode 100644
index 0000000000..74e7336cf4
--- /dev/null
+++ b/src/soc/intel/braswell/acpi.c
@@ -0,0 +1,511 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <arch/io.h>
+#include <arch/smp/mpspec.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <console/console.h>
+#include <types.h>
+#include <string.h>
+#include <arch/cpu.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/tsc.h>
+#include <cpu/intel/turbo.h>
+
+#include <soc/acpi.h>
+#include <soc/iomap.h>
+#include <soc/irq.h>
+#include <soc/msr.h>
+#include <soc/pattrs.h>
+#include <soc/pmc.h>
+
+#include <ec/google/chromeec/ec.h>
+#include <vendorcode/google/chromeos/gnvs.h>
+
+#define MWAIT_RES(state, sub_state) \
+ { \
+ .addrl = (((state) << 4) | (sub_state)), \
+ .space_id = ACPI_ADDRESS_SPACE_FIXED, \
+ .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \
+ .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \
+ .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
+ }
+
+/* C-state map without S0ix */
+static acpi_cstate_t cstate_map[] = {
+ {
+ /* C1 */
+ .ctype = 1, /* ACPI C1 */
+ .latency = 1,
+ .power = 1000,
+ .resource = MWAIT_RES(0, 0),
+ },
+ {
+ /* C6NS with no L2 shrink */
+ /* NOTE: this substate is above CPUID limit */
+ .ctype = 2, /* ACPI C2 */
+ .latency = 500,
+ .power = 10,
+ .resource = MWAIT_RES(5, 1),
+ },
+ {
+ /* C6FS with full L2 shrink */
+ .ctype = 3, /* ACPI C3 */
+ .latency = 1500, /* 1.5ms worst case */
+ .power = 1,
+ .resource = MWAIT_RES(5, 2),
+ }
+};
+
+void acpi_init_gnvs(global_nvs_t *gnvs)
+{
+ /* Set unknown wake source */
+ gnvs->pm1i = -1;
+
+ /* CPU core count */
+ gnvs->pcnt = dev_count_cpu();
+
+ /* Top of Low Memory (start of resource allocation) */
+ gnvs->tolm = nc_read_top_of_low_memory();
+
+#if CONFIG_CONSOLE_CBMEM
+ /* Update the mem console pointer. */
+ gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE);
+#endif
+
+#if CONFIG_CHROMEOS
+ /* Initialize Verified Boot data */
+ chromeos_init_vboot(&(gnvs->chromeos));
+#if CONFIG_EC_GOOGLE_CHROMEEC
+ gnvs->chromeos.vbt2 = google_ec_running_ro() ?
+ ACTIVE_ECFW_RO : ACTIVE_ECFW_RW;
+#endif
+#endif
+}
+
+static int acpi_sci_irq(void)
+{
+ u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
+ int scis;
+ static int sci_irq;
+
+ if (sci_irq)
+ return sci_irq;
+
+ /* Determine how SCI is routed. */
+ scis = read32(actl) & SCIS_MASK;
+ switch (scis) {
+ case SCIS_IRQ9:
+ case SCIS_IRQ10:
+ case SCIS_IRQ11:
+ sci_irq = scis - SCIS_IRQ9 + 9;
+ break;
+ case SCIS_IRQ20:
+ case SCIS_IRQ21:
+ case SCIS_IRQ22:
+ case SCIS_IRQ23:
+ sci_irq = scis - SCIS_IRQ20 + 20;
+ break;
+ default:
+ printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
+ sci_irq = 9;
+ break;
+ }
+
+ printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
+ return sci_irq;
+}
+
+void acpi_create_intel_hpet(acpi_hpet_t * hpet)
+{
+ acpi_header_t *header = &(hpet->header);
+ acpi_addr_t *addr = &(hpet->addr);
+
+ memset((void *) hpet, 0, sizeof(acpi_hpet_t));
+
+ /* fill out header fields */
+ memcpy(header->signature, "HPET", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_hpet_t);
+ header->revision = 1;
+
+ /* fill out HPET address */
+ addr->space_id = 0; /* Memory */
+ addr->bit_width = 64;
+ addr->bit_offset = 0;
+ addr->addrl = (unsigned long long)HPET_BASE_ADDRESS & 0xffffffff;
+ addr->addrh = (unsigned long long)HPET_BASE_ADDRESS >> 32;
+
+ hpet->id = 0x8086a201; /* Intel */
+ hpet->number = 0x00;
+ hpet->min_tick = 0x0080;
+
+ header->checksum =
+ acpi_checksum((void *) hpet, sizeof(acpi_hpet_t));
+}
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+ current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
+ MCFG_BASE_ADDRESS, 0, 0, 255);
+ return current;
+}
+
+void acpi_fill_in_fadt(acpi_fadt_t *fadt)
+{
+ const uint16_t pmbase = ACPI_BASE_ADDRESS;
+
+ 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->s4bios_req = 0x0;
+ fadt->pstate_cnt = 0;
+
+ fadt->pm1a_evt_blk = pmbase + PM1_STS;
+ fadt->pm1b_evt_blk = 0x0;
+ fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
+ fadt->pm1b_cnt_blk = 0x0;
+ fadt->pm2_cnt_blk = pmbase + PM2A_CNT_BLK;
+ fadt->pm_tmr_blk = pmbase + PM1_TMR;
+ fadt->gpe0_blk = pmbase + GPE0_STS;
+ fadt->gpe1_blk = 0;
+
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm2_cnt_len = 1;
+ fadt->pm_tmr_len = 4;
+ fadt->gpe0_blk_len = 2 * (GPE0_EN - GPE0_STS);
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 0;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = 1;
+ fadt->p_lvl3_lat = 87;
+ fadt->flush_size = 1024;
+ fadt->flush_stride = 16;
+ fadt->duty_offset = 1;
+ fadt->duty_width = 0;
+ fadt->day_alrm = 0xd;
+ fadt->mon_alrm = 0x00;
+ fadt->century = 0x00;
+ 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.bit_offset = 0;
+ fadt->reset_reg.resv = 0;
+ fadt->reset_reg.addrl = 0xcf9;
+ fadt->reset_reg.addrh = 0;
+ 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.bit_offset = 0;
+ fadt->x_pm1a_evt_blk.resv = 0;
+ fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS;
+ fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_evt_blk.space_id = 1;
+ fadt->x_pm1b_evt_blk.bit_width = 0;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.resv = 0;
+ fadt->x_pm1b_evt_blk.addrl = 0x0;
+ fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+ 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.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.resv = 0;
+ fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT;
+ fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_cnt_blk.space_id = 1;
+ fadt->x_pm1b_cnt_blk.bit_width = 0;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.resv = 0;
+ fadt->x_pm1b_cnt_blk.addrl = 0x0;
+ fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm2_cnt_blk.space_id = 1;
+ fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.resv = 0;
+ fadt->x_pm2_cnt_blk.addrl = pmbase + PM2A_CNT_BLK;
+ fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+ 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.bit_offset = 0;
+ fadt->x_pm_tmr_blk.resv = 0;
+ fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
+ fadt->x_pm_tmr_blk.addrh = 0x0;
+
+ fadt->x_gpe0_blk.space_id = 1;
+ fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.resv = 0;
+ fadt->x_gpe0_blk.addrl = pmbase + GPE0_STS;
+ fadt->x_gpe0_blk.addrh = 0x0;
+
+ fadt->x_gpe1_blk.space_id = 1;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.resv = 0;
+ fadt->x_gpe1_blk.addrl = 0x0;
+ fadt->x_gpe1_blk.addrh = 0x0;
+}
+
+static acpi_tstate_t baytrail_tss_table[] = {
+ { 100, 1000, 0, 0x00, 0 },
+ { 88, 875, 0, 0x1e, 0 },
+ { 75, 750, 0, 0x1c, 0 },
+ { 63, 625, 0, 0x1a, 0 },
+ { 50, 500, 0, 0x18, 0 },
+ { 38, 375, 0, 0x16, 0 },
+ { 25, 250, 0, 0x14, 0 },
+ { 13, 125, 0, 0x12, 0 },
+};
+
+static int generate_T_state_entries(int core, int cores_per_package)
+{
+ int len;
+
+ /* Indicate SW_ALL coordination for T-states */
+ len = acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
+
+ /* Indicate FFixedHW so OS will use MSR */
+ len += acpigen_write_empty_PTC();
+
+ /* Set NVS controlled T-state limit */
+ len += acpigen_write_TPC("\\TLVL");
+
+ /* Write TSS table for MSR access */
+ len += acpigen_write_TSS_package(
+ ARRAY_SIZE(baytrail_tss_table), baytrail_tss_table);
+
+ return len;
+}
+
+static int calculate_power(int tdp, int p1_ratio, int ratio)
+{
+ u32 m;
+ u32 power;
+
+ /*
+ * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
+ *
+ * Power = (ratio / p1_ratio) * m * tdp
+ */
+
+ m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
+ m = (m * m) / 1000;
+
+ power = ((ratio * 100000 / p1_ratio) / 100);
+ power *= (m / 100) * (tdp / 1000);
+ power /= 1000;
+
+ return (int)power;
+}
+
+static int generate_P_state_entries(int core, int cores_per_package)
+{
+ int len, len_pss;
+ int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2;
+ int coord_type, power_max, power_unit, num_entries;
+ int ratio, power, clock, clock_max;
+ int vid, vid_turbo, vid_min, vid_max, vid_range_2;
+ u32 control_status;
+ const struct pattrs *pattrs = pattrs_get();
+ msr_t msr;
+
+ /* Inputs from CPU attributes */
+ ratio_max = pattrs->iacore_ratios[IACORE_MAX];
+ ratio_min = pattrs->iacore_ratios[IACORE_LFM];
+ vid_max = pattrs->iacore_vids[IACORE_MAX];
+ vid_min = pattrs->iacore_vids[IACORE_LFM];
+
+ /* Set P-states coordination type based on MSR disable bit */
+ coord_type = (pattrs->num_cpus > 2) ? SW_ALL : HW_ALL;
+
+ /* Max Non-Turbo Frequency */
+ clock_max = (ratio_max * pattrs->bclk_khz) / 1000;
+
+ /* Calculate CPU TDP in mW */
+ msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
+ power_unit = 1 << (msr.lo & 0xf);
+ msr = rdmsr(MSR_PKG_POWER_LIMIT);
+ power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
+
+ /* Write _PCT indicating use of FFixedHW */
+ len = acpigen_write_empty_PCT();
+
+ /* Write _PPC with NVS specified limit on supported P-state */
+ len += acpigen_write_PPC_NVS();
+
+ /* Write PSD indicating configured coordination type */
+ len += acpigen_write_PSD_package(core, 1, coord_type);
+
+ /* Add P-state entries in _PSS table */
+ len += acpigen_write_name("_PSS");
+
+ /* Determine ratio points */
+ ratio_step = 1;
+ num_entries = (ratio_max - ratio_min) / ratio_step;
+ while (num_entries > 15) { /* ACPI max is 15 ratios */
+ ratio_step <<= 1;
+ num_entries >>= 1;
+ }
+
+ /* P[T] is Turbo state if enabled */
+ if (get_turbo_state() == TURBO_ENABLED) {
+ /* _PSS package count including Turbo */
+ len_pss = acpigen_write_package(num_entries + 2);
+
+ ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO];
+ vid_turbo = pattrs->iacore_vids[IACORE_TURBO];
+ control_status = (ratio_turbo << 8) | vid_turbo;
+
+ /* Add entry for Turbo ratio */
+ len_pss += acpigen_write_PSS_package(
+ clock_max + 1, /*MHz*/
+ power_max, /*mW*/
+ 10, /*lat1*/
+ 10, /*lat2*/
+ control_status, /*control*/
+ control_status); /*status*/
+ } else {
+ /* _PSS package count without Turbo */
+ len_pss = acpigen_write_package(num_entries + 1);
+ ratio_turbo = ratio_max;
+ vid_turbo = vid_max;
+ }
+
+ /* First regular entry is max non-turbo ratio */
+ control_status = (ratio_max << 8) | vid_max;
+ len_pss += acpigen_write_PSS_package(
+ clock_max, /*MHz*/
+ power_max, /*mW*/
+ 10, /*lat1*/
+ 10, /*lat2*/
+ control_status, /*control */
+ control_status); /*status*/
+
+ /* Set up ratio and vid ranges for VID calculation */
+ ratio_range_2 = (ratio_turbo - ratio_min) * 2;
+ vid_range_2 = (vid_turbo - vid_min) * 2;
+
+ /* Generate the remaining entries */
+ for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
+ ratio >= ratio_min; ratio -= ratio_step) {
+
+ /* Calculate VID for this ratio */
+ vid = ((ratio - ratio_min) * vid_range_2) /
+ ratio_range_2 + vid_min;
+ /* Round up if remainder */
+ if (((ratio - ratio_min) * vid_range_2) % ratio_range_2)
+ vid++;
+
+ /* Calculate power at this ratio */
+ power = calculate_power(power_max, ratio_max, ratio);
+ clock = (ratio * pattrs->bclk_khz) / 1000;
+ control_status = (ratio << 8) | (vid & 0xff);
+
+ len_pss += acpigen_write_PSS_package(
+ clock, /*MHz*/
+ power, /*mW*/
+ 10, /*lat1*/
+ 10, /*lat2*/
+ control_status, /*control*/
+ control_status); /*status*/
+ }
+
+ /* Fix package length */
+ len_pss--;
+ acpigen_patch_len(len_pss);
+
+ return len + len_pss;
+}
+
+void generate_cpu_entries(void)
+{
+ int len_pr, core;
+ int pcontrol_blk = get_pmbase(), plen = 6;
+ const struct pattrs *pattrs = pattrs_get();
+
+ for (core=0; core<pattrs->num_cpus; core++) {
+ if (core > 0) {
+ pcontrol_blk = 0;
+ plen = 0;
+ }
+
+ /* Generate processor \_PR.CPUx */
+ len_pr = acpigen_write_processor(
+ core, pcontrol_blk, plen);
+
+ /* Generate P-state tables */
+ len_pr += generate_P_state_entries(
+ core, pattrs->num_cpus);
+
+ /* Generate C-state tables */
+ len_pr += acpigen_write_CST_package(
+ cstate_map, ARRAY_SIZE(cstate_map));
+
+ /* Generate T-state tables */
+ len_pr += generate_T_state_entries(
+ core, pattrs->num_cpus);
+
+ len_pr--;
+ acpigen_patch_len(len_pr);
+ }
+}
+
+unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+ int sci_irq = acpi_sci_irq();
+ acpi_madt_irqoverride_t *irqovr;
+ uint16_t sci_flags = MP_IRQ_TRIGGER_LEVEL;
+
+ /* INT_SRC_OVR */
+ irqovr = (void *)current;
+ current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
+
+ if (sci_irq >= 20)
+ sci_flags |= MP_IRQ_POLARITY_LOW;
+ else
+ sci_flags |= MP_IRQ_POLARITY_HIGH;
+
+ irqovr = (void *)current;
+ current += acpi_create_madt_irqoverride(irqovr, 0, sci_irq, sci_irq,
+ sci_flags);
+
+ return current;
+}
diff --git a/src/soc/intel/braswell/acpi/cpu.asl b/src/soc/intel/braswell/acpi/cpu.asl
new file mode 100644
index 0000000000..f7e404daba
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/cpu.asl
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* These devices are created at runtime */
+External (\_PR.CP00, DeviceObj)
+External (\_PR.CP01, DeviceObj)
+External (\_PR.CP02, DeviceObj)
+External (\_PR.CP03, 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
+ }
+}
+
+/* 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
+ }
+}
+
+/* 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
+ }
+}
+
+/* Return a package containing enabled processor entries */
+Method (PPKG)
+{
+ If (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/braswell/acpi/device_nvs.asl b/src/soc/intel/braswell/acpi/device_nvs.asl
new file mode 100644
index 0000000000..fce7b53054
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/device_nvs.asl
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Device Enabled in ACPI Mode */
+
+S0EN, 8, // SDMA Enable
+S1EN, 8, // I2C1 Enable
+S2EN, 8, // I2C2 Enable
+S3EN, 8, // I2C3 Enable
+S4EN, 8, // I2C4 Enable
+S5EN, 8, // I2C5 Enable
+S6EN, 8, // I2C6 Enable
+S7EN, 8, // I2C7 Enable
+S8EN, 8, // SDMA2 Enable
+S9EN, 8, // SPI Enable
+SAEN, 8, // PWM1 Enable
+SBEN, 8, // PWM2 Enable
+SCEN, 8, // UART2 Enable
+SDEN, 8, // UART2 Enable
+C0EN, 8, // MMC Enable
+C1EN, 8, // SDIO Enable
+C2EN, 8, // SD Card Enable
+LPEN, 8, // LPE Enable
+
+/* BAR 0 */
+
+S0B0, 32, // SDMA BAR0
+S1B0, 32, // I2C1 BAR0
+S2B0, 32, // I2C2 BAR0
+S3B0, 32, // I2C3 BAR0
+S4B0, 32, // I2C4 BAR0
+S5B0, 32, // I2C5 BAR0
+S6B0, 32, // I2C6 BAR0
+S7B0, 32, // I2C7 BAR0
+S8B0, 32, // SDMA2 BAR0
+S9B0, 32, // SPI BAR0
+SAB0, 32, // PWM1 BAR0
+SBB0, 32, // PWM2 BAR0
+SCB0, 32, // UART1 BAR0
+SDB0, 32, // UART2 BAR0
+C0B0, 32, // MMC BAR0
+C1B0, 32, // SDIO BAR0
+C2B0, 32, // SD Card BAR0
+LPB0, 32, // LPE BAR0
+
+/* BAR 1 */
+
+S0B1, 32, // SDMA BAR1
+S1B1, 32, // I2C1 BAR1
+S2B1, 32, // I2C2 BAR1
+S3B1, 32, // I2C3 BAR1
+S4B1, 32, // I2C4 BAR1
+S5B1, 32, // I2C5 BAR1
+S6B1, 32, // I2C6 BAR1
+S7B1, 32, // I2C7 BAR1
+S8B1, 32, // SDMA2 BAR1
+S9B1, 32, // SPI BAR1
+SAB1, 32, // PWM1 BAR1
+SBB1, 32, // PWM2 BAR1
+SCB1, 32, // UART1 BAR1
+SDB1, 32, // UART2 BAR1
+C0B1, 32, // MMC BAR1
+C1B1, 32, // SDIO BAR1
+C2B1, 32, // SD Card BAR1
+LPB1, 32, // LPE BAR1
+
+/* Extra */
+
+LPFW, 32, // LPE BAR2 Firmware
diff --git a/src/soc/intel/braswell/acpi/dptf/charger.asl b/src/soc/intel/braswell/acpi/dptf/charger.asl
new file mode 100644
index 0000000000..7c7f62fb57
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/dptf/charger.asl
@@ -0,0 +1,59 @@
+Device (TCHG)
+{
+ Name (_HID, "INT3403")
+ Name (_UID, 0)
+ Name (PTYP, 0x0B)
+ Name (_STR, Unicode("Battery Charger"))
+
+ Method (_STA)
+ {
+ If (LEqual (\DPTE, One)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ /* Return charger performance states defined by mainboard */
+ Method (PPSS)
+ {
+ Return (\_SB.CHPS)
+ }
+
+ /* Return maximum charger current limit */
+ Method (PPPC)
+ {
+ /* Convert size of PPSS table to index */
+ Store (SizeOf (\_SB.CHPS), Local0)
+ Decrement (Local0)
+
+ /* Check if charging is disabled (AC removed) */
+ If (LEqual (\PWRS, Zero)) {
+ /* Return last power state */
+ Return (Local0)
+ } Else {
+ /* Return highest power state */
+ Return (0)
+ }
+
+ Return (0)
+ }
+
+ /* Set charger current limit */
+ Method (SPPC, 1)
+ {
+ /* Retrieve Control (index 4) for specified PPSS level */
+ Store (DeRefOf (Index (DeRefOf (Index
+ (\_SB.CHPS, ToInteger (Arg0))), 4)), Local0)
+
+ /* Pass Control value to EC to limit charging */
+ \_SB.PCI0.LPCB.EC0.CHGS (Local0)
+ }
+
+ /* Initialize charger participant */
+ Method (INIT)
+ {
+ /* Disable charge limit */
+ \_SB.PCI0.LPCB.EC0.CHGD ()
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/dptf/cpu.asl b/src/soc/intel/braswell/acpi/dptf/cpu.asl
new file mode 100644
index 0000000000..58c1c7bea7
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/dptf/cpu.asl
@@ -0,0 +1,144 @@
+External (\_PR.CP00._TSS, MethodObj)
+External (\_PR.CP00._TPC, MethodObj)
+External (\_PR.CP00._PTC, PkgObj)
+External (\_PR.CP00._TSD, PkgObj)
+External (\_PR.CP00._PSS, MethodObj)
+
+Device (TCPU)
+{
+ Name (_HID, EISAID ("INT3401"))
+ Name (_UID, 0)
+
+ Method (_STA)
+ {
+ If (LEqual (\DPTE, One)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ /*
+ * Processor Throttling Controls
+ */
+
+ Method (_TSS)
+ {
+ If (CondRefOf (\_PR.CP00._TSS)) {
+ Return (\_PR.CP00._TSS)
+ } Else {
+ Return (Package ()
+ {
+ Package () { 0, 0, 0, 0, 0 }
+ })
+ }
+ }
+
+ Method (_TPC)
+ {
+ If (CondRefOf (\_PR.CP00._TPC)) {
+ Return (\_PR.CP00._TPC)
+ } Else {
+ Return (0)
+ }
+ }
+
+ Method (_PTC)
+ {
+ If (CondRefOf (\_PR.CP00._PTC)) {
+ Return (\_PR.CP00._PTC)
+ } Else {
+ Return (Package ()
+ {
+ Buffer () { 0 },
+ Buffer () { 0 }
+ })
+ }
+ }
+
+ Method (_TSD)
+ {
+ If (CondRefOf (\_PR.CP00._TSD)) {
+ Return (\_PR.CP00._TSD)
+ } Else {
+ Return (Package ()
+ {
+ Package () { 5, 0, 0, 0, 0 }
+ })
+ }
+ }
+
+ Method (_TDL)
+ {
+ If (CondRefOf (\_PR.CP00._TSS)) {
+ Store (SizeOf (\_PR.CP00._TSS ()), Local0)
+ Decrement (Local0)
+ Return (Local0)
+ } Else {
+ Return (0)
+ }
+ }
+
+ /*
+ * Processor Performance Control
+ */
+
+ Method (_PPC)
+ {
+ Return (0)
+ }
+
+ Method (SPPC, 1)
+ {
+ Store (Arg0, \PPCM)
+
+ /* Notify OS to re-read _PPC limit on each CPU */
+ \PPCN ()
+ }
+
+ Method (_PSS)
+ {
+ If (CondRefOf (\_PR.CP00._PSS)) {
+ Return (\_PR.CP00._PSS)
+ } Else {
+ Return (Package ()
+ {
+ Package () { 0, 0, 0, 0, 0, 0 }
+ })
+ }
+ }
+
+ Method (_PDL)
+ {
+ /* Check for mainboard specific _PDL override */
+ If (CondRefOf (\_SB.MPDL)) {
+ Return (\_SB.MPDL)
+ } ElseIf (CondRefOf (\_PR.CP00._PSS)) {
+ Store (SizeOf (\_PR.CP00._PSS ()), Local0)
+ Decrement (Local0)
+ Return (Local0)
+ } Else {
+ Return (0)
+ }
+ }
+
+ /* Return PPCC table defined by mainboard */
+ Method (PPCC)
+ {
+ Return (\_SB.MPPC)
+ }
+
+#ifdef DPTF_CPU_CRITICAL
+ Method (_CRT)
+ {
+ Return (^^CTOK (DPTF_CPU_CRITICAL))
+ }
+#endif
+
+#ifdef DPTF_CPU_PASSIVE
+ Method (_PSV)
+ {
+ Return (^^CTOK (DPTF_CPU_PASSIVE))
+ }
+#endif
+}
diff --git a/src/soc/intel/braswell/acpi/dptf/dptf.asl b/src/soc/intel/braswell/acpi/dptf/dptf.asl
new file mode 100644
index 0000000000..9ebfb8c9ce
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/dptf/dptf.asl
@@ -0,0 +1,78 @@
+Device (DPTF)
+{
+ Name (_HID, EISAID ("INT3400"))
+ Name (_UID, 0)
+
+ Name (IDSP, Package()
+ {
+ /* DPPM Passive Policy 1.0 */
+ ToUUID ("42A441D6-AE6A-462B-A84B-4A8CE79027D3"),
+
+ /* DPPM Critical Policy */
+ ToUUID ("97C68AE7-15FA-499c-B8C9-5DA81D606E0A"),
+
+ /* DPPM Cooling Policy */
+ ToUUID ("16CAF1B7-DD38-40ED-B1C1-1B8A1913D531"),
+ })
+
+ Method (_STA)
+ {
+ If (LEqual (\DPTE, One)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ /* Arg0: Buffer containing UUID
+ * Arg1: Integer containing Revision ID of buffer format
+ * Arg2: Integer containing count of entries in Arg3
+ * Arg3: Buffer containing list of DWORD capabilities
+ * Return: Buffer containing list of DWORD capabilities
+ */
+ Method (_OSC, 4, Serialized)
+ {
+ /* Check for Passive Policy UUID */
+ If (LEqual (DeRefOf (Index (IDSP, 0)), Arg0)) {
+ /* Initialize Thermal Devices */
+ ^TINI ()
+
+#ifdef DPTF_ENABLE_CHARGER
+ /* Initialize Charger Device */
+ ^TCHG.INIT ()
+#endif
+ }
+
+ Return (Arg3)
+ }
+
+ /* Priority based _TRT */
+ Name (TRTR, 1)
+
+ Method (_TRT)
+ {
+ Return (\_SB.DTRT)
+ }
+
+ /* Convert from Degrees C to 1/10 Kelvin for ACPI */
+ Method (CTOK, 1) {
+ /* 10th of Degrees C */
+ Multiply (Arg0, 10, Local0)
+
+ /* Convert to Kelvin */
+ Add (Local0, 2732, Local0)
+
+ Return (Local0)
+ }
+
+ /* Include CPU Participant */
+ #include "cpu.asl"
+
+ /* Include Thermal Participants */
+ #include "thermal.asl"
+
+#ifdef DPTF_ENABLE_CHARGER
+ /* Include Charger Participant */
+ #include "charger.asl"
+#endif
+}
diff --git a/src/soc/intel/braswell/acpi/dptf/thermal.asl b/src/soc/intel/braswell/acpi/dptf/thermal.asl
new file mode 100644
index 0000000000..7113215cd3
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/dptf/thermal.asl
@@ -0,0 +1,203 @@
+/* Thermal Threshold Event Handler */
+Method (TEVT, 1, NotSerialized)
+{
+ Store (ToInteger (Arg0), Local0)
+
+#ifdef DPTF_TSR0_SENSOR_ID
+ If (LEqual (Local0, DPTF_TSR0_SENSOR_ID)) {
+ Notify (^TSR0, 0x90)
+ }
+#endif
+#ifdef DPTF_TSR1_SENSOR_ID
+ If (LEqual (Local0, DPTF_TSR1_SENSOR_ID)) {
+ Notify (^TSR1, 0x90)
+ }
+#endif
+#ifdef DPTF_TSR2_SENSOR_ID
+ If (LEqual (Local0, DPTF_TSR2_SENSOR_ID)) {
+ Notify (^TSR2, 0x90)
+ }
+#endif
+}
+
+/* Thermal device initialization - Disable Aux Trip Points */
+Method (TINI)
+{
+#ifdef DPTF_TSR0_SENSOR_ID
+ ^TSR0.PATD ()
+#endif
+#ifdef DPTF_TSR1_SENSOR_ID
+ ^TSR1.PATD ()
+#endif
+#ifdef DPTF_TSR2_SENSOR_ID
+ ^TSR2.PATD ()
+#endif
+}
+
+#ifdef DPTF_TSR0_SENSOR_ID
+Device (TSR0)
+{
+ Name (_HID, EISAID ("INT3403"))
+ Name (_UID, 1)
+ Name (PTYP, 0x03)
+ Name (TMPI, DPTF_TSR0_SENSOR_ID)
+ Name (_STR, Unicode (DPTF_TSR0_SENSOR_NAME))
+ Name (GTSH, 20) /* 2 degree hysteresis */
+
+ Method (_STA)
+ {
+ If (LEqual (\DPTE, One)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ Method (_TMP, 0, Serialized)
+ {
+ Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+ }
+
+ Method (_PSV)
+ {
+ Return (^^CTOK (DPTF_TSR0_PASSIVE))
+ }
+
+ Method (_CRT)
+ {
+ Return (^^CTOK (DPTF_TSR0_CRITICAL))
+ }
+
+ Name (PATC, 2)
+
+ /* Set Aux Trip Point */
+ Method (PAT0, 1, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+ }
+
+ /* Set Aux Trip Point */
+ Method (PAT1, 1, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+ }
+
+ /* Disable Aux Trip Point */
+ Method (PATD, 0, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PATD (TMPI)
+ }
+}
+#endif
+
+#ifdef DPTF_TSR1_SENSOR_ID
+Device (TSR1)
+{
+ Name (_HID, EISAID ("INT3403"))
+ Name (_UID, 2)
+ Name (PTYP, 0x03)
+ Name (TMPI, DPTF_TSR1_SENSOR_ID)
+ Name (_STR, Unicode (DPTF_TSR1_SENSOR_NAME))
+ Name (GTSH, 20) /* 2 degree hysteresis */
+
+ Method (_STA)
+ {
+ If (LEqual (\DPTE, One)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ Method (_TMP, 0, Serialized)
+ {
+ Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+ }
+
+ Method (_PSV)
+ {
+ Return (^^CTOK (DPTF_TSR1_PASSIVE))
+ }
+
+ Method (_CRT)
+ {
+ Return (^^CTOK (DPTF_TSR1_CRITICAL))
+ }
+
+ Name (PATC, 2)
+
+ /* Set Aux Trip Point */
+ Method (PAT0, 1, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+ }
+
+ /* Set Aux Trip Point */
+ Method (PAT1, 1, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+ }
+
+ /* Disable Aux Trip Point */
+ Method (PATD, 0, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PATD (TMPI)
+ }
+}
+#endif
+
+#ifdef DPTF_TSR2_SENSOR_ID
+Device (TSR2)
+{
+ Name (_HID, EISAID ("INT3403"))
+ Name (_UID, 3)
+ Name (PTYP, 0x03)
+ Name (TMPI, DPTF_TSR2_SENSOR_ID)
+ Name (_STR, Unicode (DPTF_TSR2_SENSOR_NAME))
+ Name (GTSH, 20) /* 2 degree hysteresis */
+
+ Method (_STA)
+ {
+ If (LEqual (\DPTE, One)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ Method (_TMP, 0, Serialized)
+ {
+ Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI))
+ }
+
+ Method (_PSV)
+ {
+ Return (^^CTOK (DPTF_TSR2_PASSIVE))
+ }
+
+ Method (_CRT)
+ {
+ Return (^^CTOK (DPTF_TSR2_CRITICAL))
+ }
+
+ Name (PATC, 2)
+
+ /* Set Aux Trip Point */
+ Method (PAT0, 1, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0)
+ }
+
+ /* Set Aux Trip Point */
+ Method (PAT1, 1, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0)
+ }
+
+ /* Disable Aux Trip Point */
+ Method (PATD, 0, Serialized)
+ {
+ \_SB.PCI0.LPCB.EC0.PATD (TMPI)
+ }
+}
+#endif
diff --git a/src/soc/intel/braswell/acpi/globalnvs.asl b/src/soc/intel/braswell/acpi/globalnvs.asl
new file mode 100644
index 0000000000..a201c03d50
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/globalnvs.asl
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Global Variables */
+
+Name(\PICM, 0) // IOAPIC/8259
+
+/* Global ACPI memory region. This region is used for passing information
+ * between coreboot (aka "the system bios"), ACPI, and the SMI handler.
+ * Since we don't know where this will end up in memory at ACPI compile time,
+ * we have to fix it up in coreboot's ACPI creation phase.
+ */
+
+
+OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 0x2000)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+ /* Miscellaneous */
+ Offset (0x00),
+ OSYS, 16, // 0x00 - Operating System
+ SMIF, 8, // 0x02 - SMI function
+ PRM0, 8, // 0x03 - SMI function parameter
+ PRM1, 8, // 0x04 - SMI function parameter
+ SCIF, 8, // 0x05 - SCI function
+ PRM2, 8, // 0x06 - SCI function parameter
+ PRM3, 8, // 0x07 - SCI function parameter
+ LCKF, 8, // 0x08 - Global Lock function for EC
+ PRM4, 8, // 0x09 - Lock function parameter
+ PRM5, 8, // 0x0a - Lock function parameter
+ P80D, 32, // 0x0b - Debug port (IO 0x80) value
+ LIDS, 8, // 0x0f - LID state (open = 1)
+ PWRS, 8, // 0x10 - Power State (AC = 1)
+ PCNT, 8, // 0x11 - Processor count
+ TPMP, 8, // 0x12 - TPM Present and Enabled
+ TLVL, 8, // 0x13 - Throttle Level
+ PPCM, 8, // 0x14 - Maximum P-state usable by OS
+ PM1I, 32, // 0x15 - System Wake Source - PM1 Index
+
+ /* Device Config */
+ Offset (0x20),
+ S5U0, 8, // 0x20 - Enable USB0 in S5
+ S5U1, 8, // 0x21 - Enable USB1 in S5
+ S3U0, 8, // 0x22 - Enable USB0 in S3
+ S3U1, 8, // 0x23 - Enable USB1 in S3
+ TACT, 8, // 0x24 - Thermal Active trip point
+ TPSV, 8, // 0x25 - Thermal Passive trip point
+ TCRT, 8, // 0x26 - Thermal Critical trip point
+ DPTE, 8, // 0x27 - Enable DPTF
+
+ /* Base addresses */
+ Offset (0x30),
+ CMEM, 32, // 0x30 - CBMEM TOC
+ TOLM, 32, // 0x34 - Top of Low Memory
+ CBMC, 32, // 0x38 - coreboot mem console pointer
+
+ /* ChromeOS specific */
+ Offset (0x100),
+ #include <vendorcode/google/chromeos/acpi/gnvs.asl>
+
+ Offset (0x1000),
+ #include <soc/intel/baytrail/acpi/device_nvs.asl>
+}
+
+/* Set flag to enable USB charging in S3 */
+Method (S3UE)
+{
+ Store (One, \S3U0)
+ Store (One, \S3U1)
+}
+
+/* Set flag to disable USB charging in S3 */
+Method (S3UD)
+{
+ Store (Zero, \S3U0)
+ Store (Zero, \S3U1)
+}
+
+/* Set flag to enable USB charging in S5 */
+Method (S5UE)
+{
+ Store (One, \S5U0)
+ Store (One, \S5U1)
+}
+
+/* Set flag to disable USB charging in S5 */
+Method (S5UD)
+{
+ Store (Zero, \S5U0)
+ Store (Zero, \S5U1)
+}
diff --git a/src/soc/intel/braswell/acpi/gpio.asl b/src/soc/intel/braswell/acpi/gpio.asl
new file mode 100644
index 0000000000..aa6af717c1
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/gpio.asl
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <soc/iomap.h>
+#include <soc/irq.h>
+
+/* SouthCluster GPIO */
+Device (GPSC)
+{
+ Name (_HID, "INT33FC")
+ Name (_CID, "INT33FC")
+ Name (_UID, 1)
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,)
+ {
+ GPIO_SC_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+ Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPSCORE, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ Return (0xF)
+ }
+}
+
+/* NorthCluster GPIO */
+Device (GPNC)
+{
+ Name (_HID, "INT33FC")
+ Name (_CID, "INT33FC")
+ Name (_UID, 2)
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,)
+ {
+ GPIO_NC_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+ Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPNCORE, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ Return (0xF)
+ }
+}
+
+/* SUS GPIO */
+Device (GPSS)
+{
+ Name (_HID, "INT33FC")
+ Name (_CID, "INT33FC")
+ Name (_UID, 3)
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, RMEM)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,)
+ {
+ GPIO_SUS_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^RMEM._BAS, RBAS)
+ Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPSSUS, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ Return (0xF)
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/irq_helper.h b/src/soc/intel/braswell/acpi/irq_helper.h
new file mode 100644
index 0000000000..b19895b583
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/irq_helper.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#undef PCI_DEV_PIRQ_ROUTES
+#undef ACPI_DEV_APIC_IRQ
+#undef PCI_DEV_PIRQ_ROUTE
+#undef PIRQ_PIC_ROUTES
+#undef PIRQ_PIC
+
+#if defined(PIC_MODE)
+
+#define ACPI_DEV_APIC_IRQ(dev_, pin_, pin_name_) \
+ Package() { ## dev_ ## ffff, pin_, \_SB.PCI0.LPCB.LNK ## pin_name_, 0 }
+
+#else /* defined(PIC_MODE) */
+
+#define ACPI_DEV_APIC_IRQ(dev_, pin_, pin_name_) \
+ Package() { ## dev_ ## ffff, pin_, 0, PIRQ ## pin_name_ ## _APIC_IRQ }
+
+#endif
+
+#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \
+ ACPI_DEV_APIC_IRQ(dev_, 0, a_), \
+ ACPI_DEV_APIC_IRQ(dev_, 1, b_), \
+ ACPI_DEV_APIC_IRQ(dev_, 2, c_), \
+ ACPI_DEV_APIC_IRQ(dev_, 3, d_)
+
+/* Empty PIRQ_PIC definition. */
+#define PIRQ_PIC(pirq_, pic_irq_)
+
+/* Include the mainboard irq route definition. */
+#include "irqroute.h"
diff --git a/src/soc/intel/braswell/acpi/irqlinks.asl b/src/soc/intel/braswell/acpi/irqlinks.asl
new file mode 100644
index 0000000000..21f1ada02e
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/irqlinks.asl
@@ -0,0 +1,492 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (LNKA)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 1)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTA)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLA, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLA, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTA
+ ShiftLeft(1, And(PRTA, 0x0f), IRQ0)
+
+ Return (RTLA)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTA)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTA, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKB)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 2)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTB)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLB, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLB, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTB
+ ShiftLeft(1, And(PRTB, 0x0f), IRQ0)
+
+ Return (RTLB)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTB)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTB, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKC)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 3)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTC)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLC, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLC, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTC
+ ShiftLeft(1, And(PRTC, 0x0f), IRQ0)
+
+ Return (RTLC)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTC)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTC, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKD)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 4)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTD)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLD, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLD, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTD
+ ShiftLeft(1, And(PRTD, 0x0f), IRQ0)
+
+ Return (RTLD)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTD)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTD, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKE)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 5)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTE)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLE, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLE, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTE
+ ShiftLeft(1, And(PRTE, 0x0f), IRQ0)
+
+ Return (RTLE)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTE)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTE, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKF)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 6)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTF)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLF, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLF, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTF
+ ShiftLeft(1, And(PRTF, 0x0f), IRQ0)
+
+ Return (RTLF)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTF)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTF, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKG)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 7)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTG)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLG, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLG, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTG
+ ShiftLeft(1, And(PRTG, 0x0f), IRQ0)
+
+ Return (RTLG)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTG)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTG, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
+
+Device (LNKH)
+{
+ Name (_HID, EISAID("PNP0C0F"))
+ Name (_UID, 8)
+
+ // Disable method
+ Method (_DIS, 0, Serialized)
+ {
+ Store (0x80, PRTH)
+ }
+
+ // Possible Resource Settings for this Link
+ Name (_PRS, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared)
+ { 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+ })
+
+ // Current Resource Settings for this link
+ Method (_CRS, 0, Serialized)
+ {
+ Name (RTLH, ResourceTemplate()
+ {
+ IRQ(Level, ActiveLow, Shared) {}
+ })
+ CreateWordField(RTLH, 1, IRQ0)
+
+ // Clear the WordField
+ Store (Zero, IRQ0)
+
+ // Set the bit from PRTH
+ ShiftLeft(1, And(PRTH, 0x0f), IRQ0)
+
+ Return (RTLH)
+ }
+
+ // Set Resource Setting for this IRQ link
+ Method (_SRS, 1, Serialized)
+ {
+ CreateWordField(Arg0, 1, IRQ0)
+
+ // Which bit is set?
+ FindSetRightBit(IRQ0, Local0)
+
+ Decrement(Local0)
+ Store(Local0, PRTH)
+ }
+
+ // Status
+ Method (_STA, 0, Serialized)
+ {
+ If(And(PRTH, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xb)
+ }
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/irqroute.asl b/src/soc/intel/braswell/acpi/irqroute.asl
new file mode 100644
index 0000000000..23987d7d2a
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/irqroute.asl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+// PCI Interrupt Routing
+Method(_PRT)
+{
+ If (PICM) {
+ Return (Package() {
+ #undef PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTES
+ })
+ } Else {
+ Return (Package() {
+ #define PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTES
+ })
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/lpc.asl b/src/soc/intel/braswell/acpi/lpc.asl
new file mode 100644
index 0000000000..408d2b420f
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/lpc.asl
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Intel LPC Bus Device - 0:1f.0
+
+Device (LPCB)
+{
+ Name(_ADR, 0x001f0000)
+
+ #include "irqlinks.asl"
+
+ #include "acpi/ec.asl"
+
+ Device (DMAC) // DMA Controller
+ {
+ Name(_HID, EISAID("PNP0200"))
+ Name(_CRS, ResourceTemplate()
+ {
+ IO (Decode16, 0x00, 0x00, 0x01, 0x20)
+ IO (Decode16, 0x81, 0x81, 0x01, 0x11)
+ IO (Decode16, 0x93, 0x93, 0x01, 0x0d)
+ IO (Decode16, 0xc0, 0xc0, 0x01, 0x20)
+ DMA (Compatibility, NotBusMaster, Transfer8_16) { 4 }
+ })
+ }
+
+ Device (FWH) // Firmware Hub
+ {
+ Name (_HID, EISAID("INT0800"))
+ Name (_CRS, ResourceTemplate()
+ {
+ Memory32Fixed(ReadOnly, 0xff000000, 0x01000000)
+ })
+ }
+
+ Device (HPET)
+ {
+ Name (_HID, EISAID("PNP0103"))
+ Name (_CID, 0x010CD041)
+
+ Method (_STA, 0) // Device Status
+ {
+ Return (0xf) // Enable and show device
+ }
+
+ Name(_CRS, ResourceTemplate()
+ {
+ Memory32Fixed(ReadOnly, 0xfed00000, 0x400)
+ })
+ }
+
+ Device(PIC) // 8259 Interrupt Controller
+ {
+ Name(_HID,EISAID("PNP0000"))
+ Name(_CRS, ResourceTemplate()
+ {
+ IO (Decode16, 0x20, 0x20, 0x01, 0x02)
+ IO (Decode16, 0x24, 0x24, 0x01, 0x02)
+ IO (Decode16, 0x28, 0x28, 0x01, 0x02)
+ IO (Decode16, 0x2c, 0x2c, 0x01, 0x02)
+ IO (Decode16, 0x30, 0x30, 0x01, 0x02)
+ IO (Decode16, 0x34, 0x34, 0x01, 0x02)
+ IO (Decode16, 0x38, 0x38, 0x01, 0x02)
+ IO (Decode16, 0x3c, 0x3c, 0x01, 0x02)
+ IO (Decode16, 0xa0, 0xa0, 0x01, 0x02)
+ IO (Decode16, 0xa4, 0xa4, 0x01, 0x02)
+ IO (Decode16, 0xa8, 0xa8, 0x01, 0x02)
+ IO (Decode16, 0xac, 0xac, 0x01, 0x02)
+ IO (Decode16, 0xb0, 0xb0, 0x01, 0x02)
+ IO (Decode16, 0xb4, 0xb4, 0x01, 0x02)
+ IO (Decode16, 0xb8, 0xb8, 0x01, 0x02)
+ IO (Decode16, 0xbc, 0xbc, 0x01, 0x02)
+ IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02)
+ IRQNoFlags () { 2 }
+ })
+ }
+
+ Device(LDRC) // LPC device: Resource consumption
+ {
+ Name (_HID, EISAID("PNP0C02"))
+ Name (_UID, 2)
+
+ Name (RBUF, ResourceTemplate()
+ {
+ IO (Decode16, 0x61, 0x61, 0x1, 0x01) // NMI Status
+ IO (Decode16, 0x63, 0x63, 0x1, 0x01) // CPU Reserved
+ IO (Decode16, 0x65, 0x65, 0x1, 0x01) // CPU Reserved
+ IO (Decode16, 0x67, 0x67, 0x1, 0x01) // CPU Reserved
+ IO (Decode16, 0x80, 0x80, 0x1, 0x01) // Port 80 Post
+ IO (Decode16, 0x92, 0x92, 0x1, 0x01) // CPU Reserved
+ IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI
+ })
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ Return (RBUF)
+ }
+ }
+
+ Device (RTC) // Real Time Clock
+ {
+ Name (_HID, EISAID("PNP0B00"))
+ Name (_CRS, ResourceTemplate()
+ {
+ IO (Decode16, 0x70, 0x70, 1, 8)
+// Disable as Windows doesn't like it, and systems don't seem to use it.
+// IRQNoFlags() { 8 }
+ })
+ }
+
+ Device (TIMR) // Intel 8254 timer
+ {
+ Name(_HID, EISAID("PNP0100"))
+ Name(_CRS, ResourceTemplate()
+ {
+ IO (Decode16, 0x40, 0x40, 0x01, 0x04)
+ IO (Decode16, 0x50, 0x50, 0x10, 0x04)
+ IRQNoFlags() {0}
+ })
+ }
+
+ // Include mainboard's superio.asl file.
+ #include "acpi/superio.asl"
+
+#ifdef ENABLE_TPM
+ Device (TPM) // Trusted Platform Module
+ {
+ Name(_HID, EISAID("IFX0102"))
+ Name(_CID, 0x310cd041)
+ Name(_UID, 1)
+
+ Method(_STA, 0)
+ {
+ If (TPMP) {
+ Return (0xf)
+ }
+ Return (0x0)
+ }
+
+ Name(_CRS, ResourceTemplate() {
+ IO (Decode16, 0x2e, 0x2e, 0x01, 0x02)
+ IO (Decode16, 0x6f0, 0x6f0, 0x01, 0x10)
+ Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)
+ IRQ (Edge, Activehigh, Exclusive) { 6 }
+ })
+ }
+#endif
+}
diff --git a/src/soc/intel/braswell/acpi/lpe.asl b/src/soc/intel/braswell/acpi/lpe.asl
new file mode 100644
index 0000000000..dfa555c834
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/lpe.asl
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (LPEA)
+{
+ Name (_HID, "80860F28")
+ Name (_CID, "80860F28")
+ Name (_UID, 1)
+ Name (_DDN, "Low Power Audio Controller")
+ Name (_PR0, Package () { PLPE })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x00200000, BAR0)
+ Memory32Fixed (ReadWrite, 0, 0x00001000, BAR1)
+ Memory32Fixed (ReadWrite, 0, 0x00100000, BAR2)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPE_DMA0_IRQ
+ }
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPE_DMA1_IRQ
+ }
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPE_SSP0_IRQ
+ }
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPE_SSP1_IRQ
+ }
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPE_SSP2_IRQ
+ }
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPE_IPC2HOST_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ /* Update BAR0 from NVS */
+ CreateDwordField (^RBUF, ^BAR0._BAS, BAS0)
+ Store (\LPB0, BAS0)
+
+ /* Update BAR1 from NVS */
+ CreateDwordField (^RBUF, ^BAR1._BAS, BAS1)
+ Store (\LPB1, BAS1)
+
+ /* Update LPE FW from NVS */
+ CreateDwordField (^RBUF, ^BAR2._BAS, BAS2)
+ Store (\LPFW, BAS2)
+
+ /* Append any Mainboard defined GPIOs */
+ If (CondRefOf (^GBUF, Local0)) {
+ ConcatenateResTemplate (^RBUF, ^GBUF, Local1)
+ Return (Local1)
+ }
+
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\LPEN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, LPB1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ PowerResource (PLPE, 0, 0)
+ {
+ Method (_STA)
+ {
+ Return (1)
+ }
+
+ Method (_OFF)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_ON)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/lpss.asl b/src/soc/intel/braswell/acpi/lpss.asl
new file mode 100644
index 0000000000..0f8f7465f9
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/lpss.asl
@@ -0,0 +1,712 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (SDM1)
+{
+ Name (_HID, "INTL9C60")
+ Name (_UID, 1)
+ Name (_DDN, "DMA Controller #1")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_DMA1_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S0B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S0EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+}
+
+Device (SDM2)
+{
+ Name (_HID, "INTL9C60")
+ Name (_UID, 2)
+ Name (_DDN, "DMA Controller #2")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_DMA2_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S8B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S8EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+}
+
+Device (I2C1)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 1)
+ Name (_DDN, "I2C Controller #1")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C1_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S1B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S1EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S1B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (I2C2)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 2)
+ Name (_DDN, "I2C Controller #2")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C2_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S2B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S2EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S2B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (I2C3)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 3)
+ Name (_DDN, "I2C Controller #3")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C3_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S3B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S3EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S3B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (I2C4)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 4)
+ Name (_DDN, "I2C Controller #4")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C4_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S4B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S4EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S4B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (I2C5)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 5)
+ Name (_DDN, "I2C Controller #5")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C5_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S5B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S5EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S5B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (I2C6)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 6)
+ Name (_DDN, "I2C Controller #6")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C6_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S6B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S6EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S6B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (I2C7)
+{
+ Name (_HID, "80860F41")
+ Name (_UID, 7)
+ Name (_DDN, "I2C Controller #7")
+
+ /* Standard Mode: HCNT, LCNT, SDA Hold Time */
+ Name (SSCN, Package () { 0x200, 0x200, 0x6 })
+
+ /* Fast Mode: HCNT, LCNT, SDA Hold Time */
+ Name (FMCN, Package () { 0x55, 0x99, 0x6 })
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_I2C7_IRQ
+ }
+ FixedDMA (0x10, 0x0, Width32Bit, )
+ FixedDMA (0x11, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S7B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S7EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S7B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (SPI1)
+{
+ Name (_HID, "80860F0E")
+ Name (_UID, 1)
+ Name (_DDN, "SPI Controller #2")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_SPI_IRQ
+ }
+ FixedDMA (0x0, 0x0, Width32Bit, )
+ FixedDMA (0x1, 0x1, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\S9B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S9EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, S9B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (PWM1)
+{
+ Name (_HID, "80860F09")
+ Name (_UID, 1)
+ Name (_DDN, "PWM Controller #1")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\SAB0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\SAEN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+}
+
+Device (PWM2)
+{
+ Name (_HID, "80860F09")
+ Name (_UID, 2)
+ Name (_DDN, "PWM Controller #2")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\SBB0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\SBEN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+}
+
+Device (UAR1)
+{
+ Name (_HID, "80860F0A")
+ Name (_UID, 1)
+ Name (_DDN, "HS-UART Controller #1")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_HSUART1_IRQ
+ }
+ FixedDMA (0x2, 0x2, Width32Bit, )
+ FixedDMA (0x3, 0x3, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\SCB0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\SCEN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, SCB1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (UAR2)
+{
+ Name (_HID, "80860F0A")
+ Name (_UID, 2)
+ Name (_DDN, "HS-UART Controller #2")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ LPSS_HSUART2_IRQ
+ }
+ FixedDMA (0x4, 0x4, Width32Bit, )
+ FixedDMA (0x5, 0x5, Width32Bit, )
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\SDB0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\SDEN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, SDB1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/pcie.asl b/src/soc/intel/braswell/acpi/pcie.asl
new file mode 100644
index 0000000000..5ad4e788fc
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/pcie.asl
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Intel SOC PCIe support */
+
+Device (RP01)
+{
+ Name (_ADR, 0x001c0000)
+
+ Method (_PRT)
+ {
+ If (PICM) {
+ Return (Package() {
+ #undef PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, A, B, C, D)
+ })
+ } Else {
+ Return (Package() {
+ #define PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, A, B, C, D)
+ })
+ }
+ }
+}
+
+Device (RP02)
+{
+ Name (_ADR, 0x001c0001)
+
+ Method (_PRT)
+ {
+ If (PICM) {
+ Return (Package() {
+ #undef PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, B, C, D, A)
+ })
+ } Else {
+ Return (Package() {
+ #define PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, B, C, D, A)
+ })
+ }
+ }
+}
+
+Device (RP03)
+{
+ Name (_ADR, 0x001c0002)
+
+ Method (_PRT)
+ {
+ If (PICM) {
+ Return (Package() {
+ #undef PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, C, D, A, B)
+ })
+ } Else {
+ Return (Package() {
+ #define PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, C, D, A, B)
+ })
+ }
+ }
+}
+
+Device (RP04)
+{
+ Name (_ADR, 0x001c0003)
+
+ Method (_PRT)
+ {
+ If (PICM) {
+ Return (Package() {
+ #undef PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, D, A, B, C)
+ })
+ } Else {
+ Return (Package() {
+ #define PIC_MODE
+ #include <soc/intel/baytrail/acpi/irq_helper.h>
+ PCI_DEV_PIRQ_ROUTE(0x0, D, A, B, C)
+ })
+ }
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/platform.asl b/src/soc/intel/braswell/acpi/platform.asl
new file mode 100644
index 0000000000..e32880ef9b
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/platform.asl
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2012 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* The APM port can be used for generating software SMIs */
+
+OperationRegion (APMP, SystemIO, 0xb2, 2)
+Field (APMP, ByteAcc, NoLock, Preserve)
+{
+ APMC, 8, // APM command
+ APMS, 8 // APM status
+}
+
+/* Port 80 POST */
+
+OperationRegion (POST, SystemIO, 0x80, 1)
+Field (POST, ByteAcc, Lock, Preserve)
+{
+ DBG0, 8
+}
+
+/* SMI I/O Trap */
+Method(TRAP, 1, Serialized)
+{
+ Store (Arg0, SMIF) // SMI Function
+ Store (0, TRP0) // Generate trap
+ Return (SMIF) // Return value of SMI handler
+}
+
+/* The _PIC method is called by the OS to choose between interrupt
+ * routing via the i8259 interrupt controller or the APIC.
+ *
+ * _PIC is called with a parameter of 0 for i8259 configuration and
+ * with a parameter of 1 for Local Apic/IOAPIC configuration.
+ */
+
+Method(_PIC, 1)
+{
+ // Remember the OS' IRQ routing choice.
+ Store(Arg0, PICM)
+}
+
+/* The _PTS method (Prepare To Sleep) is called before the OS is
+ * entering a sleep state. The sleep state number is passed in Arg0
+ */
+
+Method(_PTS,1)
+{
+}
+
+/* The _WAK method is called on system wakeup */
+
+Method(_WAK,1)
+{
+ Return(Package(){0,0})
+}
+
+Method (_SWS)
+{
+ /* Index into PM1 for device that caused wake */
+ Return (\PM1I)
+}
diff --git a/src/soc/intel/braswell/acpi/scc.asl b/src/soc/intel/braswell/acpi/scc.asl
new file mode 100644
index 0000000000..7181fb1669
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/scc.asl
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (EMMC)
+{
+ Name (_HID, "80860F14")
+ Name (_CID, "PNP0D40")
+ Name (_UID, 1)
+ Name (_DDN, "eMMC Controller 4.5")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ SCC_EMMC_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\C0B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\C0EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, C0B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Device (EM45)
+ {
+ /* Slot 0, Function 8 */
+ Name (_ADR, 0x8)
+
+ Method (_RMV, 0, NotSerialized)
+ {
+ Return (0)
+ }
+ }
+}
+
+Device (SDIO)
+{
+ Name (_HID, "INT33BB")
+ Name (_CID, "PNP0D40")
+ Name (_UID, 2)
+ Name (_DDN, "SDIO Controller")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ SCC_SDIO_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\C1B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\C1EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, C1B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
+
+Device (SDCD)
+{
+ Name (_HID, "80860F16")
+ Name (_CID, "PNP0D40")
+ Name (_UID, 3)
+ Name (_DDN, "SD Card Controller")
+
+ Name (RBUF, ResourceTemplate()
+ {
+ Memory32Fixed (ReadWrite, 0, 0x1000, BAR0)
+ Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,)
+ {
+ SCC_SD_IRQ
+ }
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^BAR0._BAS, RBAS)
+ Store (\C2B0, RBAS)
+ Return (^RBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\C2EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ OperationRegion (KEYS, SystemMemory, C2B1, 0x100)
+ Field (KEYS, DWordAcc, NoLock, WriteAsZeros)
+ {
+ Offset (0x84),
+ PSAT, 32,
+ }
+
+ Method (_PS3)
+ {
+ Or (PSAT, 0x00000003, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+
+ Method (_PS0)
+ {
+ And (PSAT, 0xfffffffc, PSAT)
+ Or (PSAT, 0x00000000, PSAT)
+ }
+}
diff --git a/src/soc/intel/braswell/acpi/sleepstates.asl b/src/soc/intel/braswell/acpi/sleepstates.asl
new file mode 100644
index 0000000000..8abeb2d91a
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/sleepstates.asl
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Name(\_S0, Package(){0x0,0x0,0x0,0x0})
+// Name(\_S1, Package(){0x1,0x1,0x0,0x0})
+Name(\_S3, Package(){0x5,0x5,0x0,0x0})
+Name(\_S4, Package(){0x6,0x6,0x0,0x0})
+Name(\_S5, Package(){0x7,0x7,0x0,0x0})
diff --git a/src/soc/intel/braswell/acpi/southcluster.asl b/src/soc/intel/braswell/acpi/southcluster.asl
new file mode 100644
index 0000000000..9092562275
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/southcluster.asl
@@ -0,0 +1,274 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <soc/iomap.h>
+#include <soc/irq.h>
+
+Scope(\)
+{
+ // IO-Trap at 0x800. This is the ACPI->SMI communication interface.
+
+ OperationRegion(IO_T, SystemIO, 0x800, 0x10)
+ Field(IO_T, ByteAcc, NoLock, Preserve)
+ {
+ Offset(0x8),
+ TRP0, 8 // IO-Trap at 0x808
+ }
+
+ // Intel Legacy Block
+ OperationRegion(ILBS, SystemMemory, ILB_BASE_ADDRESS, ILB_BASE_SIZE)
+ Field (ILBS, AnyAcc, NoLock, Preserve)
+ {
+ Offset (0x8),
+ PRTA, 8,
+ PRTB, 8,
+ PRTC, 8,
+ PRTD, 8,
+ PRTE, 8,
+ PRTF, 8,
+ PRTG, 8,
+ PRTH, 8,
+ }
+}
+
+Name(_HID,EISAID("PNP0A08")) // PCIe
+Name(_CID,EISAID("PNP0A03")) // PCI
+
+Name(_ADR, 0)
+Name(_BBN, 0)
+
+Method (_CRS, 0, Serialized)
+{
+ Name (MCRS, ResourceTemplate()
+ {
+ // Bus Numbers
+ WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00)
+
+ // IO Region 0
+ DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00)
+
+ // PCI Config Space
+ Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+ // IO Region 1
+ DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01)
+
+ // VGA memory (0xa0000-0xbffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
+ 0x00020000,,, ASEG)
+
+ // OPROM reserved (0xc0000-0xc3fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000c0000, 0x000c3fff, 0x00000000,
+ 0x00004000,,, OPR0)
+
+ // OPROM reserved (0xc4000-0xc7fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000c4000, 0x000c7fff, 0x00000000,
+ 0x00004000,,, OPR1)
+
+ // OPROM reserved (0xc8000-0xcbfff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000c8000, 0x000cbfff, 0x00000000,
+ 0x00004000,,, OPR2)
+
+ // OPROM reserved (0xcc000-0xcffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000cc000, 0x000cffff, 0x00000000,
+ 0x00004000,,, OPR3)
+
+ // OPROM reserved (0xd0000-0xd3fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000d0000, 0x000d3fff, 0x00000000,
+ 0x00004000,,, OPR4)
+
+ // OPROM reserved (0xd4000-0xd7fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000d4000, 0x000d7fff, 0x00000000,
+ 0x00004000,,, OPR5)
+
+ // OPROM reserved (0xd8000-0xdbfff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000d8000, 0x000dbfff, 0x00000000,
+ 0x00004000,,, OPR6)
+
+ // OPROM reserved (0xdc000-0xdffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000dc000, 0x000dffff, 0x00000000,
+ 0x00004000,,, OPR7)
+
+ // BIOS Extension (0xe0000-0xe3fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000e0000, 0x000e3fff, 0x00000000,
+ 0x00004000,,, ESG0)
+
+ // BIOS Extension (0xe4000-0xe7fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000e4000, 0x000e7fff, 0x00000000,
+ 0x00004000,,, ESG1)
+
+ // BIOS Extension (0xe8000-0xebfff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000e8000, 0x000ebfff, 0x00000000,
+ 0x00004000,,, ESG2)
+
+ // BIOS Extension (0xec000-0xeffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000ec000, 0x000effff, 0x00000000,
+ 0x00004000,,, ESG3)
+
+ // System BIOS (0xf0000-0xfffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000f0000, 0x000fffff, 0x00000000,
+ 0x00010000,,, FSEG)
+
+ // PCI Memory Region (Top of memory-CONFIG_MMCONF_BASE_ADDRESS)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000,,, PMEM)
+
+ // TPM Area (0xfed40000-0xfed44fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0xfed40000, 0xfed44fff, 0x00000000,
+ 0x00005000,,, TPMR)
+ })
+
+ // Update PCI resource area
+ CreateDwordField(MCRS, PMEM._MIN, PMIN)
+ CreateDwordField(MCRS, PMEM._MAX, PMAX)
+ CreateDwordField(MCRS, PMEM._LEN, PLEN)
+
+ // TOLM is BMBOUND accessible from IOSF so is saved in NVS
+ Store (\TOLM, PMIN)
+ Store (Subtract(CONFIG_MMCONF_BASE_ADDRESS, 1), PMAX)
+ Add (Subtract (PMAX, PMIN), 1, PLEN)
+
+ Return (MCRS)
+}
+
+/* Device Resource Consumption */
+Device (PDRC)
+{
+ Name (_HID, EISAID("PNP0C02"))
+ Name (_UID, 1)
+
+ Name (PDRS, ResourceTemplate() {
+ Memory32Fixed(ReadWrite, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE)
+ Memory32Fixed(ReadWrite, MCFG_BASE_ADDRESS, MCFG_BASE_SIZE)
+ Memory32Fixed(ReadWrite, PMC_BASE_ADDRESS, PMC_BASE_SIZE)
+ Memory32Fixed(ReadWrite, ILB_BASE_ADDRESS, ILB_BASE_SIZE)
+ Memory32Fixed(ReadWrite, SPI_BASE_ADDRESS, SPI_BASE_SIZE)
+ Memory32Fixed(ReadWrite, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE)
+ Memory32Fixed(ReadWrite, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE)
+ Memory32Fixed(ReadWrite, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE)
+ })
+
+ // Current Resource Settings
+ Method (_CRS, 0, Serialized)
+ {
+ Return(PDRS)
+ }
+}
+
+Method (_OSC, 4)
+{
+ /* Check for proper GUID */
+ If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")))
+ {
+ /* Let OS control everything */
+ Return (Arg3)
+ }
+ Else
+ {
+ /* Unrecognized UUID */
+ CreateDWordField (Arg3, 0, CDW1)
+ Or (CDW1, 4, CDW1)
+ Return (Arg3)
+ }
+}
+
+/* IOSF MBI Interface for kernel access */
+Device (IOSF)
+{
+ Name (_HID, "INT33BD")
+ Name (_CID, "INT33BD")
+ Name (_UID, 1)
+
+ Name (RBUF, ResourceTemplate ()
+ {
+ /* MCR / MDR / MCRX */
+ Memory32Fixed (ReadWrite, 0, 12, RBAR)
+ })
+
+ Method (_CRS)
+ {
+ CreateDwordField (^RBUF, ^RBAR._BAS, RBAS)
+ Store (Add (MCFG_BASE_ADDRESS, 0xD0), RBAS)
+ Return (^RBUF)
+ }
+}
+
+// LPC Bridge 0:1f.0
+#include "lpc.asl"
+
+// USB XHCI 0:14.0
+#include "xhci.asl"
+
+// IRQ routing for each PCI device
+#include "irqroute.asl"
+
+// PCI Express Ports 0:1c.x
+#include "pcie.asl"
+
+Scope (\_SB)
+{
+ // GPIO Devices
+ #include "gpio.asl"
+
+ // LPSS Devices
+ #include "lpss.asl"
+
+ // SCC Devices
+ #include "scc.asl"
+
+ // LPE Device
+ #include "lpe.asl"
+}
diff --git a/src/soc/intel/braswell/acpi/xhci.asl b/src/soc/intel/braswell/acpi/xhci.asl
new file mode 100644
index 0000000000..4d5367acec
--- /dev/null
+++ b/src/soc/intel/braswell/acpi/xhci.asl
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (XHCI)
+{
+ Name (_ADR, 0x00140000)
+ Name (_PRW, Package () { 0x0d, 3 })
+ Name (_S3D, 3) /* Highest D state in S3 state */
+
+ Device (RHUB)
+ {
+ Name (_ADR, 0x00000000)
+ Device (PRT1) { Name (_ADR, 1) }
+ Device (PRT2) { Name (_ADR, 2) }
+ Device (PRT3) { Name (_ADR, 3) }
+ Device (PRT4) { Name (_ADR, 4) }
+ }
+}
diff --git a/src/soc/intel/braswell/bootblock/Makefile.inc b/src/soc/intel/braswell/bootblock/Makefile.inc
new file mode 100644
index 0000000000..3a4025198c
--- /dev/null
+++ b/src/soc/intel/braswell/bootblock/Makefile.inc
@@ -0,0 +1 @@
+chipset_bootblock_inc += $(src)/soc/intel/baytrail/bootblock/timestamp.inc
diff --git a/src/soc/intel/braswell/bootblock/bootblock.c b/src/soc/intel/braswell/bootblock/bootblock.c
new file mode 100644
index 0000000000..9d7f19c4c7
--- /dev/null
+++ b/src/soc/intel/braswell/bootblock/bootblock.c
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <soc/iosf.h>
+#include <cpu/intel/microcode/microcode.c>
+
+static void set_var_mtrr(int reg, uint32_t base, uint32_t size, int type)
+{
+ msr_t basem, maskm;
+ basem.lo = base | type;
+ basem.hi = 0;
+ wrmsr(MTRRphysBase_MSR(reg), basem);
+ maskm.lo = ~(size - 1) | MTRRphysMaskValid;
+ maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
+ wrmsr(MTRRphysMask_MSR(reg), maskm);
+}
+
+static void enable_rom_caching(void)
+{
+ msr_t msr;
+
+ disable_cache();
+ /* Why only top 4MiB ? */
+ set_var_mtrr(1, 0xffc00000, 4*1024*1024, MTRR_TYPE_WRPROT);
+ enable_cache();
+
+ /* Enable Variable MTRRs */
+ msr.hi = 0x00000000;
+ msr.lo = 0x00000800;
+ wrmsr(MTRRdefType_MSR, msr);
+}
+
+static void setup_mmconfig(void)
+{
+ uint32_t reg;
+
+ /* Set up the MMCONF range. The register lives in the BUNIT. The
+ * IO variant of the config access needs to be used initially to
+ * properly configure as the IOSF access registers live in PCI
+ * config space. */
+ reg = 0;
+ /* Clear the extended register. */
+ pci_io_write_config32(IOSF_PCI_DEV, MCRX_REG, reg);
+ reg = CONFIG_MMCONF_BASE_ADDRESS | 1;
+ pci_io_write_config32(IOSF_PCI_DEV, MDR_REG, reg);
+ reg = IOSF_OPCODE(IOSF_OP_WRITE_BUNIT) | IOSF_PORT(IOSF_PORT_BUNIT) |
+ IOSF_REG(BUNIT_MMCONF_REG) | IOSF_BYTE_EN;
+ pci_io_write_config32(IOSF_PCI_DEV, MCR_REG, reg);
+}
+
+static void bootblock_cpu_init(void)
+{
+ /* Allow memory-mapped PCI config access. */
+ setup_mmconfig();
+
+ /* Load microcode before any caching. */
+ intel_update_microcode_from_cbfs();
+ enable_rom_caching();
+}
diff --git a/src/soc/intel/braswell/bootblock/timestamp.inc b/src/soc/intel/braswell/bootblock/timestamp.inc
new file mode 100644
index 0000000000..3db5c35c4d
--- /dev/null
+++ b/src/soc/intel/braswell/bootblock/timestamp.inc
@@ -0,0 +1,18 @@
+/* Store the initial timestamp for booting in mmx registers. This works
+ * because the bootblock isn't being compiled with MMX support so mm0 and
+ * mm1 will be preserved into romstage. */
+ .code32
+
+.global stash_timestamp
+stash_timestamp:
+
+ /* Save the BIST value */
+ movl %eax, %ebp
+
+ finit
+ rdtsc
+ movd %eax, %mm0
+ movd %edx, %mm1
+
+ /* Restore the BIST value to %eax */
+ movl %ebp, %eax
diff --git a/src/soc/intel/braswell/chip.c b/src/soc/intel/braswell/chip.c
new file mode 100644
index 0000000000..281019ab95
--- /dev/null
+++ b/src/soc/intel/braswell/chip.c
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <arch/pci_ops.h>
+
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include "chip.h"
+
+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,
+};
+
+static struct device_operations cpu_bus_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+ .init = baytrail_init_cpus,
+ .scan_bus = NULL,
+};
+
+
+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;
+ } else if (dev->path.type == DEVICE_PATH_PCI) {
+ /* Handle south cluster enablement. */
+ if (PCI_SLOT(dev->path.pci.devfn) > GFX_DEV &&
+ (dev->ops == NULL || dev->ops->enable == NULL)) {
+ southcluster_enable_dev(dev);
+ }
+ }
+}
+
+/* Called at BS_DEV_INIT_CHIPS time -- very early. Just after BS_PRE_DEVICE. */
+static void soc_init(void *chip_info)
+{
+ baytrail_init_pre_device(chip_info);
+}
+
+struct chip_operations soc_intel_baytrail_ops = {
+ CHIP_NAME("Intel BayTrail SoC")
+ .enable_dev = enable_dev,
+ .init = soc_init,
+};
+
+static void pci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ if (!vendor || !device) {
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ pci_read_config32(dev, PCI_VENDOR_ID));
+ } else {
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+ }
+}
+
+struct pci_operations soc_pci_ops = {
+ .set_subsystem = &pci_set_subsystem,
+};
diff --git a/src/soc/intel/braswell/chip.h b/src/soc/intel/braswell/chip.h
new file mode 100644
index 0000000000..ecf1ce3da9
--- /dev/null
+++ b/src/soc/intel/braswell/chip.h
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* The devicetree parser expects chip.h to reside directly in the path
+ * specified by the devicetree. */
+
+#ifndef _BAYTRAIL_CHIP_H_
+#define _BAYTRAIL_CHIP_H_
+
+#include <stdint.h>
+
+struct soc_intel_baytrail_config {
+ uint8_t enable_xdp_tap;
+ uint8_t sata_port_map;
+ uint8_t sata_ahci;
+ uint8_t ide_legacy_combined;
+ uint8_t clkreq_enable;
+
+ /* VR low power settings -- enable PS2 mode for gfx and core */
+ int vnn_ps2_enable;
+ int vcc_ps2_enable;
+
+ /* Disable SLP_X stretching after SUS power well loss. */
+ int disable_slp_x_stretch_sus_fail;
+
+ /* USB Port Disable mask */
+ uint16_t usb2_port_disable_mask;
+ uint16_t usb3_port_disable_mask;
+
+ /* USB routing */
+ int usb_route_to_xhci;
+
+ /* USB PHY settings specific to the board */
+ uint32_t usb2_per_port_lane0;
+ uint32_t usb2_per_port_rcomp_hs_pullup0;
+ uint32_t usb2_per_port_lane1;
+ uint32_t usb2_per_port_rcomp_hs_pullup1;
+ uint32_t usb2_per_port_lane2;
+ uint32_t usb2_per_port_rcomp_hs_pullup2;
+ uint32_t usb2_per_port_lane3;
+ uint32_t usb2_per_port_rcomp_hs_pullup3;
+ uint32_t usb2_comp_bg;
+
+ /* LPE Audio Clock configuration. */
+ int lpe_codec_clk_freq; /* 19 or 25 are valid. */
+ int lpe_codec_clk_num; /* Platform clock pins. [0:5] are valid. */
+
+ /* Native SD Card controller - override controller capabilities. */
+ uint32_t sdcard_cap_low;
+ uint32_t sdcard_cap_high;
+
+ /* Enable devices in ACPI mode */
+ int lpss_acpi_mode;
+ int scc_acpi_mode;
+ int lpe_acpi_mode;
+
+ /* Allow PCIe devices to wake system from suspend. */
+ int pcie_wake_enable;
+
+ int gpu_pipea_port_select; /* Port select: 1=DP_B 2=DP_C */
+ uint16_t gpu_pipea_power_on_delay;
+ uint16_t gpu_pipea_light_on_delay;
+ uint16_t gpu_pipea_power_off_delay;
+ uint16_t gpu_pipea_light_off_delay;
+ uint16_t gpu_pipea_power_cycle_delay;
+ int gpu_pipea_pwm_freq_hz;
+
+ int gpu_pipeb_port_select; /* Port select: 1=DP_B 2=DP_C */
+ uint16_t gpu_pipeb_power_on_delay;
+ uint16_t gpu_pipeb_light_on_delay;
+ uint16_t gpu_pipeb_power_off_delay;
+ uint16_t gpu_pipeb_light_off_delay;
+ uint16_t gpu_pipeb_power_cycle_delay;
+ int gpu_pipeb_pwm_freq_hz;
+ int disable_ddr_2x_refresh_rate;
+};
+
+extern struct chip_operations soc_intel_baytrail_ops;
+#endif /* _BAYTRAIL_CHIP_H_ */
diff --git a/src/soc/intel/braswell/cpu.c b/src/soc/intel/braswell/cpu.c
new file mode 100644
index 0000000000..f4d752eb94
--- /dev/null
+++ b/src/soc/intel/braswell/cpu.c
@@ -0,0 +1,309 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/intel/microcode.h>
+#include <cpu/intel/turbo.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/lapic.h>
+#include <cpu/x86/mp.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/smm.h>
+#include <reg_script.h>
+
+#include <soc/iosf.h>
+#include <soc/msr.h>
+#include <soc/pattrs.h>
+#include <soc/ramstage.h>
+#include <soc/smm.h>
+
+static void smm_relocate(void *unused);
+static void enable_smis(void *unused);
+
+static struct mp_flight_record mp_steps[] = {
+ MP_FR_BLOCK_APS(smm_relocate, NULL, smm_relocate, NULL),
+ MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL),
+ /* Wait for APs to finish initialization before proceeding. */
+ MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
+};
+
+/* The APIC id space on Bay Trail is sparse. Each id is separated by 2. */
+static int adjust_apic_id(int index, int apic_id)
+{
+ return 2 * index;
+}
+
+/* Package level MSRs */
+const struct reg_script package_msr_script[] = {
+ /* Set Package TDP to ~7W */
+ REG_MSR_WRITE(MSR_PKG_POWER_LIMIT, 0x3880fa),
+ REG_MSR_RMW(MSR_PP1_POWER_LIMIT, ~(0x7f << 17), 0),
+ REG_MSR_WRITE(MSR_PKG_TURBO_CFG1, 0x702),
+ REG_MSR_WRITE(MSR_CPU_TURBO_WKLD_CFG1, 0x200b),
+ REG_MSR_WRITE(MSR_CPU_TURBO_WKLD_CFG2, 0),
+ REG_MSR_WRITE(MSR_CPU_THERM_CFG1, 0x00000305),
+ REG_MSR_WRITE(MSR_CPU_THERM_CFG2, 0x0405500d),
+ REG_MSR_WRITE(MSR_CPU_THERM_SENS_CFG, 0x27),
+ REG_SCRIPT_END
+};
+
+/* Core level MSRs */
+const struct reg_script core_msr_script[] = {
+ /* Dynamic L2 shrink enable and threshold, clear SINGLE_PCTL bit 11 */
+ REG_MSR_RMW(MSR_PMG_CST_CONFIG_CONTROL, ~0x3f080f, 0xe0008),
+ REG_MSR_RMW(MSR_POWER_MISC,
+ ~(ENABLE_ULFM_AUTOCM_MASK | ENABLE_INDP_AUTOCM_MASK), 0),
+ /* Disable C1E */
+ REG_MSR_RMW(MSR_POWER_CTL, ~0x2, 0),
+ REG_MSR_OR(MSR_POWER_MISC, 0x44),
+ REG_SCRIPT_END
+};
+
+void baytrail_init_cpus(device_t dev)
+{
+ struct bus *cpu_bus = dev->link_list;
+ const struct pattrs *pattrs = pattrs_get();
+ struct mp_params mp_params;
+ uint32_t bsmrwac;
+ void *default_smm_area;
+
+ /* Set up MTRRs based on physical address size. */
+ x86_setup_fixed_mtrrs();
+ x86_setup_var_mtrrs(pattrs->address_bits, 2);
+ x86_mtrr_check();
+
+ mp_params.num_cpus = pattrs->num_cpus,
+ mp_params.parallel_microcode_load = 1,
+ mp_params.adjust_apic_id = adjust_apic_id;
+ mp_params.flight_plan = &mp_steps[0];
+ mp_params.num_records = ARRAY_SIZE(mp_steps);
+ mp_params.microcode_pointer = pattrs->microcode_patch;
+
+ default_smm_area = backup_default_smm_area();
+
+ /*
+ * Configure the BUNIT to allow dirty cache line evictions in non-SMM
+ * mode for the lines that were dirtied while in SMM mode. Otherwise
+ * the writes would be silently dropped.
+ */
+ bsmrwac = iosf_bunit_read(BUNIT_SMRWAC) | SAI_IA_UNTRUSTED;
+ iosf_bunit_write(BUNIT_SMRWAC, bsmrwac);
+
+ /* Set package MSRs */
+ reg_script_run(package_msr_script);
+
+ /* Enable Turbo Mode on BSP and siblings of the BSP's building block. */
+ enable_turbo();
+
+ if (mp_init(cpu_bus, &mp_params)) {
+ printk(BIOS_ERR, "MP initialization failure.\n");
+ }
+
+ restore_default_smm_area(default_smm_area);
+}
+
+static void baytrail_core_init(device_t cpu)
+{
+ printk(BIOS_DEBUG, "Init BayTrail core.\n");
+
+ /* On bay trail the turbo disable bit is actually scoped at building
+ * block level -- not package. For non-bsp cores that are within a
+ * building block enable turbo. The cores within the BSP's building
+ * block will just see it already enabled and move on. */
+ if (lapicid())
+ enable_turbo();
+
+ /* Set core MSRs */
+ reg_script_run(core_msr_script);
+
+ /* Set this core to max frequency ratio */
+ set_max_freq();
+}
+
+static struct device_operations cpu_dev_ops = {
+ .init = baytrail_core_init,
+};
+
+static struct cpu_device_id cpu_table[] = {
+ { X86_VENDOR_INTEL, 0x30673 },
+ { X86_VENDOR_INTEL, 0x30678 },
+ { 0, 0 },
+};
+
+static const struct cpu_driver driver __cpu_driver = {
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
+};
+
+
+/*
+ * SMM loading and 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 adjust_apic_id_map(struct smm_loader_params *smm_params)
+{
+ int i;
+ struct smm_runtime *runtime = smm_params->runtime;
+
+ for (i = 0; i < CONFIG_MAX_CPUS; i++)
+ runtime->apic_id_to_cpu[i] = mp_get_apic_id(i);
+}
+
+static void asmlinkage cpu_smm_do_relocation(void *arg)
+{
+ msr_t smrr;
+ em64t100_smm_state_save_area_t *smm_state;
+ const struct smm_module_params *p;
+ const struct smm_runtime *runtime;
+ int cpu;
+
+ p = arg;
+ runtime = p->runtime;
+ cpu = p->cpu;
+
+ if (cpu >= CONFIG_MAX_CPUS) {
+ printk(BIOS_CRIT,
+ "Invalid CPU number assigned in SMM stub: %d\n", cpu);
+ return;
+ }
+
+ /* Set up SMRR. */
+ smrr.lo = relo_attrs.smrr_base;
+ smrr.hi = 0;
+ wrmsr(SMRRphysBase_MSR, smrr);
+ smrr.lo = relo_attrs.smrr_mask;
+ smrr.hi = 0;
+ wrmsr(SMRRphysMask_MSR, smrr);
+
+ /* The relocated handler runs with all CPUs concurrently. Therefore
+ * stagger the entry points adjusting SMBASE downwards by save state
+ * size * CPU num. */
+ smm_state = (void *)(SMM_EM64T100_SAVE_STATE_OFFSET + runtime->smbase);
+ smm_state->smbase = relo_attrs.smbase - cpu * runtime->save_state_size;
+ printk(BIOS_DEBUG, "New SMBASE 0x%08x\n", smm_state->smbase);
+}
+
+static int install_relocation_handler(int num_cpus)
+{
+ const int save_state_size = sizeof(em64t100_smm_state_save_area_t);
+
+ struct smm_loader_params smm_params = {
+ .per_cpu_stack_size = save_state_size,
+ .num_concurrent_stacks = num_cpus,
+ .per_cpu_save_state_size = save_state_size,
+ .num_concurrent_save_states = 1,
+ .handler = (smm_handler_t)&cpu_smm_do_relocation,
+ };
+
+ if (smm_setup_relocation_handler(&smm_params))
+ return -1;
+
+ adjust_apic_id_map(&smm_params);
+
+ return 0;
+}
+
+static int install_permanent_handler(int num_cpus)
+{
+ /* There are num_cpus concurrent stacks and num_cpus concurrent save
+ * state areas. Lastly, set the stack size to the save state size. */
+ int save_state_size = sizeof(em64t100_smm_state_save_area_t);
+ struct smm_loader_params smm_params = {
+ .per_cpu_stack_size = save_state_size,
+ .num_concurrent_stacks = num_cpus,
+ .per_cpu_save_state_size = save_state_size,
+ .num_concurrent_save_states = num_cpus,
+ };
+ const int tseg_size = smm_region_size() - CONFIG_SMM_RESERVED_SIZE;
+
+ printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n",
+ relo_attrs.smbase);
+
+ if (smm_load_module((void *)relo_attrs.smbase, tseg_size, &smm_params))
+ return -1;
+
+ adjust_apic_id_map(&smm_params);
+
+ return 0;
+}
+
+static int smm_load_handlers(void)
+{
+ /* All range registers are aligned to 4KiB */
+ const uint32_t rmask = ~((1 << 12) - 1);
+ const struct pattrs *pattrs = pattrs_get();
+
+ /* Initialize global tracking state. */
+ relo_attrs.smbase = (uint32_t)smm_region_start();
+ relo_attrs.smrr_base = relo_attrs.smbase | MTRR_TYPE_WRBACK;
+ relo_attrs.smrr_mask = ~(smm_region_size() - 1) & rmask;
+ relo_attrs.smrr_mask |= MTRRphysMaskValid;
+
+ /* Install handlers. */
+ if (install_relocation_handler(pattrs->num_cpus) < 0) {
+ printk(BIOS_ERR, "Unable to install SMM relocation handler.\n");
+ return -1;
+ }
+
+ if (install_permanent_handler(pattrs->num_cpus) < 0) {
+ printk(BIOS_ERR, "Unable to install SMM permanent handler.\n");
+ return -1;
+ }
+
+ /* Ensure the SMM handlers hit DRAM before performing first SMI. */
+ wbinvd();
+
+ return 0;
+}
+
+static void smm_relocate(void *unused)
+{
+ const struct pattrs *pattrs = pattrs_get();
+
+ /* Load relocation and permanent handler. */
+ if (boot_cpu()) {
+ if (smm_load_handlers() < 0) {
+ printk(BIOS_ERR, "Error loading SMM handlers.\n");
+ return;
+ }
+ southcluster_smm_clear_state();
+ }
+
+ /* Relocate SMM space. */
+ smm_initiate_relocation();
+
+ /* Load microcode after SMM relocation. */
+ intel_microcode_load_unlocked(pattrs->microcode_patch);
+}
+
+static void enable_smis(void *unused)
+{
+ southcluster_smm_enable_smi();
+}
diff --git a/src/soc/intel/braswell/dptf.c b/src/soc/intel/braswell/dptf.c
new file mode 100644
index 0000000000..20d34209de
--- /dev/null
+++ b/src/soc/intel/braswell/dptf.c
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <bootstate.h>
+#include <console/console.h>
+#include <reg_script.h>
+#include <soc/iosf.h>
+
+static const struct reg_script dptf_init_settings[] = {
+ /* SocThermInit */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PTMC, 0x00030708),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_GFXT, 0x0000C000),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_VEDT, 0x00000004),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_ISPT, 0x00000004),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PTPS, 0x00000000),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TE_AUX3, 0x00061029),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_VRIccMax, 0x00061029),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_VRHot, 0x00061029),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_XXPROCHOT, 0x00061029),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_SLM0, 0x00001029),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_SLM1, 0x00001029),
+ /* ratio 11 = 1466mhz for mid and entry celeron */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_SOC_POWER_BUDGET, 0x00000B00),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_SOC_ENERGY_CREDIT, 0x00000002),
+ REG_SCRIPT_END,
+};
+
+static void dptf_init(void *unused)
+{
+ printk(BIOS_DEBUG, "Applying SOC Thermal settings for DPTF.\n");
+ reg_script_run(dptf_init_settings);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, dptf_init, NULL);
diff --git a/src/soc/intel/braswell/ehci.c b/src/soc/intel/braswell/ehci.c
new file mode 100644
index 0000000000..7cf5e2b5a9
--- /dev/null
+++ b/src/soc/intel/braswell/ehci.c
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/acpi.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdint.h>
+#include <reg_script.h>
+
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/ramstage.h>
+#include <soc/ehci.h>
+
+#include "chip.h"
+
+static const struct reg_script ehci_init_script[] = {
+ /* Enable S0 PLL shutdown
+ * D29:F0:7A[12,10,7,6,4,3,2,1]=11111111b */
+ REG_PCI_OR16(0x7a, 0x14de),
+ /* Enable SB local clock gating
+ * D29:F0:7C[14,3,2]=111b (14 set in clock gating step) */
+ REG_PCI_OR32(0x7c, 0x0000000c),
+ REG_PCI_OR32(0x8c, 0x00000001),
+ /* Enable dynamic clock gating 0x4001=0xCE */
+ REG_IOSF_RMW(IOSF_PORT_USBPHY, 0x4001, 0xFFFFFF00, 0xCE),
+ /* Magic RCBA register set sequence */
+ /* RCBA + 0x200=0x1 */
+ REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x200, 0x00000001),
+ /* RCBA + 0x204=0x2 */
+ REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x204, 0x00000002),
+ /* RCBA + 0x208=0x0 */
+ REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x208, 0x00000000),
+ /* RCBA + 0x240[4,3,2,1,0]=00000b */
+ REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x240, ~0x0000001f, 0),
+ /* RCBA + 0x318[9,8,6,5,4,3,2,1,0]=000000111b */
+ REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x318, ~0x00000378, 0x00000007),
+ /* RCBA + 0x31c[3,2,1,0]=0011b */
+ REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x31c, ~0x0000000c, 0x00000003),
+ REG_SCRIPT_END
+};
+
+static const struct reg_script ehci_clock_gating_script[] = {
+ /* Enable SB local clock gating */
+ REG_PCI_OR32(0x7c, 0x00004000),
+ /* RCBA + 0x284=0xbe (step B0+) */
+ REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x284, 0x000000be),
+ REG_SCRIPT_END
+};
+
+static const struct reg_script ehci_disable_script[] = {
+ /* Clear Run/Stop Bit */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD, ~USB2CMD_RS, 0),
+ /* Wait for HC Halted */
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, USB2STS,
+ USB2STS_HCHALT, USB2STS_HCHALT, 10000),
+ /* Disable Interrupts */
+ REG_PCI_OR32(EHCI_CMD_STS, INTRDIS),
+ /* Disable Asynchronous and Periodic Scheduler */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD,
+ ~(USB2CMD_ASE | USB2CMD_PSE), 0),
+ /* Disable port wake */
+ REG_PCI_RMW32(EHCI_SBRN_FLA_PWC, ~(PORTWKIMP | PORTWKCAPMASK), 0),
+ /* Set Function Disable bit in RCBA */
+ REG_MMIO_OR32(RCBA_BASE_ADDRESS + RCBA_FUNC_DIS, RCBA_EHCI_DIS),
+ REG_SCRIPT_END
+};
+
+static const struct reg_script ehci_hc_reset[] = {
+ REG_RES_OR16(PCI_BASE_ADDRESS_0, USB2CMD, USB2CMD_HCRESET),
+ REG_SCRIPT_END
+};
+
+static void usb2_phy_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ u32 usb2_comp_bg = (config->usb2_comp_bg == 0 ?
+ 0x4700 : config->usb2_comp_bg);
+ struct reg_script usb2_phy_script[] = {
+ /* USB3PHYInit() */
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_COMPBG,
+ usb2_comp_bg),
+ /* Per port phy settings, set in devicetree.cb */
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE0,
+ config->usb2_per_port_lane0),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY,
+ USBPHY_PER_PORT_RCOMP_HS_PULLUP0,
+ config->usb2_per_port_rcomp_hs_pullup0),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE1,
+ config->usb2_per_port_lane1),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY,
+ USBPHY_PER_PORT_RCOMP_HS_PULLUP1,
+ config->usb2_per_port_rcomp_hs_pullup1),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE2,
+ config->usb2_per_port_lane2),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY,
+ USBPHY_PER_PORT_RCOMP_HS_PULLUP2,
+ config->usb2_per_port_rcomp_hs_pullup2),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE3,
+ config->usb2_per_port_lane3),
+ REG_IOSF_WRITE(IOSF_PORT_USBPHY,
+ USBPHY_PER_PORT_RCOMP_HS_PULLUP3,
+ config->usb2_per_port_rcomp_hs_pullup3),
+ REG_SCRIPT_END
+ };
+ reg_script_run(usb2_phy_script);
+}
+
+static void ehci_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ struct reg_script ehci_hc_init[] = {
+ /* Controller init */
+ REG_SCRIPT_NEXT(ehci_init_script),
+ /* Enable clock gating */
+ REG_SCRIPT_NEXT(ehci_clock_gating_script),
+ /*
+ * Disable ports if requested
+ */
+ /* Open per-port disable control override */
+ REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
+ REG_PCI_WRITE8(EHCI_USB2PDO, config->usb2_port_disable_mask),
+ /* Close per-port disable control override */
+ REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
+ REG_SCRIPT_END
+ };
+
+ /* Don't reset controller in S3 resume path */
+ if (!acpi_is_wakeup_s3())
+ reg_script_run_on_dev(dev, ehci_hc_reset);
+
+ /* Disable controller if ports are routed to XHCI */
+ if (config->usb_route_to_xhci) {
+ /* Disable controller */
+ reg_script_run_on_dev(dev, ehci_disable_script);
+
+ /* Hide device with southcluster function */
+ dev->enabled = 0;
+ southcluster_enable_dev(dev);
+ } else {
+ /* Initialize EHCI controller */
+ reg_script_run_on_dev(dev, ehci_hc_init);
+ }
+
+ /* Setup USB2 PHY based on board config */
+ usb2_phy_init(dev);
+}
+
+static struct device_operations ehci_device_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ehci_init,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver baytrail_ehci __pci_driver = {
+ .ops = &ehci_device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = EHCI_DEVID
+};
diff --git a/src/soc/intel/braswell/elog.c b/src/soc/intel/braswell/elog.c
new file mode 100644
index 0000000000..f20dc97235
--- /dev/null
+++ b/src/soc/intel/braswell/elog.c
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <stdint.h>
+#include <console/console.h>
+#include <cbmem.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <elog.h>
+#include <soc/iomap.h>
+#include <soc/pmc.h>
+
+static void log_power_and_resets(const struct chipset_power_state *ps)
+{
+ if (ps->gen_pmcon1 & PWR_FLR) {
+ elog_add_event(ELOG_TYPE_POWER_FAIL);
+ elog_add_event(ELOG_TYPE_PWROK_FAIL);
+ }
+
+ if (ps->gen_pmcon1 & SUS_PWR_FLR) {
+ elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
+ }
+
+ if (ps->gen_pmcon1 & RPS) {
+ elog_add_event(ELOG_TYPE_RTC_RESET);
+ }
+
+ if (ps->tco_sts & SECOND_TO_STS) {
+ elog_add_event(ELOG_TYPE_TCO_RESET);
+ }
+
+ if (ps->pm1_sts & PRBTNOR_STS) {
+ elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
+ }
+
+ if (ps->gen_pmcon1 & SRS) {
+ elog_add_event(ELOG_TYPE_RESET_BUTTON);
+ }
+
+ if (ps->gen_pmcon1 & GEN_RST_STS) {
+ elog_add_event(ELOG_TYPE_SYSTEM_RESET);
+ }
+}
+
+static void log_wake_events(const struct chipset_power_state *ps)
+{
+ const uint32_t pcie_wake_mask = PCI_EXP_STS | PCIE_WAKE3_STS |
+ PCIE_WAKE2_STS | PCIE_WAKE1_STS |
+ PCIE_WAKE0_STS;
+ uint32_t gpe0_sts;
+ uint32_t gpio_mask;
+ int i;
+
+ /* Mask off disabled events. */
+ gpe0_sts = ps->gpe0_sts & ps->gpe0_en;
+
+ if (ps->pm1_sts & WAK_STS) {
+ elog_add_event_byte(ELOG_TYPE_ACPI_WAKE,
+ acpi_is_wakeup_s3() ? 3 : 5);
+ }
+
+ if (ps->pm1_sts & PWRBTN_STS) {
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
+ }
+
+ if (ps->pm1_sts & RTC_STS) {
+ elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
+ }
+
+ if (gpe0_sts & PME_B0_EN) {
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
+ }
+
+ if (gpe0_sts & pcie_wake_mask) {
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
+ }
+
+ gpio_mask = SUS_GPIO_STS0;
+ i = 0;
+ while (gpio_mask) {
+ if (gpio_mask & gpe0_sts) {
+ elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i);
+ }
+ gpio_mask <<= 1;
+ i++;
+ }
+}
+
+void southcluster_log_state(void)
+{
+ struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+
+ if (ps == NULL) {
+ printk(BIOS_DEBUG, "Not logging power state information. "
+ "Power state not found in cbmem.\n");
+ return;
+ }
+
+ log_power_and_resets(ps);
+ log_wake_events(ps);
+}
diff --git a/src/soc/intel/braswell/emmc.c b/src/soc/intel/braswell/emmc.c
new file mode 100644
index 0000000000..1708428506
--- /dev/null
+++ b/src/soc/intel/braswell/emmc.c
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/iosf.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include "chip.h"
+
+static const struct reg_script emmc_ops[] = {
+ /* Enable 2ms card stable feature. */
+ REG_PCI_OR32(0xa8, (1 << 24)),
+ /* Enable HS200 */
+ REG_PCI_WRITE32(0xa0, 0x446cc801),
+ REG_PCI_WRITE32(0xa4, 0x80000807),
+ /* cfio_regs_score_special_bits.sdio1_dummy_loopback_en=1 */
+ REG_IOSF_OR(IOSF_PORT_SCORE, 0x49c0, (1 << 3)),
+ /* CLKGATE_EN_1 . cr_scc_mipihsi_clkgate_en = 1 */
+ REG_IOSF_RMW(IOSF_PORT_CCU, 0x1c, ~(3 << 26), (1 << 26)),
+ /* Set slew for HS200 */
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c0, ~0x3c, 0x3c),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c4, ~0x3c, 0x3c),
+ /* Max timeout */
+ REG_RES_WRITE8(PCI_BASE_ADDRESS_0, 0x002e, 0x0e),
+ REG_SCRIPT_END,
+};
+
+static void emmc_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+
+ printk(BIOS_DEBUG, "eMMC init\n");
+ reg_script_run_on_dev(dev, emmc_ops);
+
+ if (config->scc_acpi_mode)
+ scc_enable_acpi_mode(dev, SCC_MMC_CTL, SCC_NVS_MMC);
+}
+
+static struct device_operations device_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = emmc_init,
+ .enable = NULL,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = MMC_DEVID,
+};
diff --git a/src/soc/intel/braswell/gfx.c b/src/soc/intel/braswell/gfx.c
new file mode 100644
index 0000000000..0601e94d05
--- /dev/null
+++ b/src/soc/intel/braswell/gfx.c
@@ -0,0 +1,398 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+#include <stdlib.h>
+
+#include <soc/gfx.h>
+#include <soc/iosf.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+
+#include "chip.h"
+
+#define GFX_TIMEOUT 100000 /* 100ms */
+
+/*
+ * Lock Power Context Base Register to point to a 24KB block
+ * of memory in GSM. Power context save data is stored here.
+ */
+static void gfx_lock_pcbase(device_t dev)
+{
+ struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
+ const u16 gms_size_map[17] = { 0,32,64,96,128,160,192,224,256,
+ 288,320,352,384,416,448,480,512 };
+ u32 pcsize = 24 << 10; /* 24KB */
+ u32 wopcmsz = 0x100000; /* PAVP offset */
+ u32 gms, gmsize, pcbase;
+
+ gms = pci_read_config32(dev, GGC) & GGC_GSM_SIZE_MASK;
+ gms >>= 3;
+ if (gms > ARRAY_SIZE(gms_size_map))
+ return;
+ gmsize = gms_size_map[gms];
+
+ /* PcBase = BDSM + GMS Size - WOPCMSZ - PowerContextSize */
+ pcbase = pci_read_config32(dev, GSM_BASE) & 0xfff00000;
+ pcbase += (gmsize-1) * wopcmsz - pcsize;
+ pcbase |= 1; /* Lock */
+
+ write32((u32 *)(uintptr_t)(res->base + 0x182120), pcbase);
+}
+
+static const struct reg_script gfx_init_script[] = {
+ /* Allow-Wake render/media wells */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x130090, ~1, 1),
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130094, 1, 1, GFX_TIMEOUT),
+ /* Render Force-Wake */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b0, 0x80008000),
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300b4, 0x8000, 0x8000,
+ GFX_TIMEOUT),
+ /* Media Force-Wake */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b8, 0x80008000),
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300bc, 0x8000, 0x8000,
+ GFX_TIMEOUT),
+ /* Workaround - X0:261954/A0:261955 */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x182060, ~0xf, 1),
+
+ /*
+ * PowerMeter Weights
+ */
+
+ /* SET1 */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA800, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA804, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA808, 0x0000ff0A),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA80C, 0x1D000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA810, 0xAC004900),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA814, 0x000F0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA818, 0x5A000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA81C, 0x2600001F),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA820, 0x00090000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA824, 0x2000ff00),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA828, 0xff090016),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA82C, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA830, 0x00000100),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA834, 0x00A00F51),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA838, 0x000B0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA83C, 0xcb7D3307),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA840, 0x003C0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA844, 0xFFFF0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA848, 0x00220000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA84c, 0x43000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA850, 0x00000800),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA854, 0x00000F00),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA858, 0x00000021),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA85c, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA860, 0x00190000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xAA80, 0x00FF00FF),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xAA84, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x1300A4, 0x00000000),
+ /* SET2 */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA900, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA904, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA908, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa90c, 0x1D000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa910, 0xAC005000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa914, 0x000F0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa918, 0x5A000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa91c, 0x2600001F),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa920, 0x00090000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa924, 0x2000ff00),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa928, 0xff090016),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa92c, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa930, 0x00000100),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa934, 0x00A00F51),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa938, 0x000B0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA93C, 0xcb7D3307),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA940, 0x003C0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA944, 0xFFFF0000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA948, 0x00220000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA94C, 0x43000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA950, 0x00000800),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA954, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA960, 0x00000000),
+ /* SET3 */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa3c, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa54, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa60, 0x00000000),
+ /* Enable PowerMeter Counters */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA248, 0x00000058),
+
+ /* Program PUNIT_GPU_EC_VIRUS based on DPTF SDP */
+ /* SDP Profile 4 == 0x11940, others 0xcf08 */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_GPU_EC_VIRUS, 0xcf08),
+
+ /* GfxPause */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa000, 0x00071388),
+
+ /* Dynamic EU Control Settings */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa080, 0x00000004),
+
+ /* Lock ECO Bit Settings */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x80000000),
+
+ /* DOP Clock Gating */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x00000001),
+
+ /* MBCunit will send the VCR (Fuse) writes as NP-W */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x907c, 0xfffeffff, 0x00010000),
+
+ /*
+ * RC6 Settings
+ */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA090, 0x00000000),
+ /* RC1e - RC6/6p - RC6pp Wake Rate Limits */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA09C, 0x00280000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0A8, 0x0001E848),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0AC, 0x00000019),
+ /* RC Sleep / RCx Thresholds */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0B0, 0x00000000),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0B8, 0x00000557),
+
+ /*
+ * Turbo Settings
+ */
+
+ /* Render/Video/Blitter Idle Max Count */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x2054, 0x0000000A),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000A),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000A),
+ /* RP Down Timeout */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA010, 0x000F4240),
+
+ /*
+ * Turbo Control Settings
+ */
+
+ /* RP Up/Down Threshold */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA02C, 0x0000E8E8),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA030, 0x0003BD08),
+ /* RP Up/Down EI */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA068, 0x000101D0),
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA06C, 0x00055730),
+
+ /* RP Idle Hysteresis */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa070, 0x0000000a),
+
+ /* HW RC6 Control Settings */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x11000000),
+
+ /* RP Control */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000592),
+
+ /* Enable PM Interrupts */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x44024, 0x03000000),
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076),
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa168, 0x0000007e),
+
+ /* Aggressive Clock Gating */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0),
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0),
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0),
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0),
+
+ /* Enable Gfx Turbo. */
+ REG_IOSF_RMW(IOSF_PORT_PMC, SB_BIOS_CONFIG,
+ ~SB_BIOS_CONFIG_GFX_TURBO_DIS, 0),
+ REG_SCRIPT_END
+};
+
+static const struct reg_script gpu_pre_vbios_script[] = {
+ /* Make sure GFX is bus master with MMIO access */
+ REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY),
+ /* Display */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xc0),
+ REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xc0, 0xc0,
+ GFX_TIMEOUT),
+ /* Tx/Rx Lanes */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xfff0c0),
+ REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfff0c0, 0xfff0c0,
+ GFX_TIMEOUT),
+ /* Common Lane */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xfffcc0),
+ REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffcc0, 0xfffcc0,
+ GFX_TIMEOUT),
+ /* Ungating Tx only */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf00cc0),
+ REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffcc0, 0xf00cc0,
+ GFX_TIMEOUT),
+ /* Ungating Common Lane only */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf000c0),
+ REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xffffc0, 0xf000c0,
+ GFX_TIMEOUT),
+ /* Ungating Display */
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf00000),
+ REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffff0, 0xf00000,
+ GFX_TIMEOUT),
+ REG_SCRIPT_END
+};
+
+static const struct reg_script gfx_post_vbios_script[] = {
+ /* Deassert Render Force-Wake */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b0, 0x80000000),
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300b4, 0x8000, 0, GFX_TIMEOUT),
+ /* Deassert Media Force-Wake */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b8, 0x80000000),
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300bc, 0x8000, 0, GFX_TIMEOUT),
+ /* Set Lock bits */
+ REG_PCI_RMW32(GGC, 0xffffffff, 1),
+ REG_PCI_RMW32(GSM_BASE, 0xffffffff, 1),
+ REG_PCI_RMW32(GTT_BASE, 0xffffffff, 1),
+ REG_SCRIPT_END
+};
+
+static inline void gfx_run_script(device_t dev, const struct reg_script *ops)
+{
+ reg_script_run_on_dev(dev, ops);
+}
+
+static void gfx_pre_vbios_init(device_t dev)
+{
+ printk(BIOS_INFO, "GFX: Pre VBIOS Init\n");
+ gfx_run_script(dev, gpu_pre_vbios_script);
+}
+
+static void gfx_pm_init(device_t dev)
+{
+ printk(BIOS_INFO, "GFX: Power Management Init\n");
+ gfx_run_script(dev, gfx_init_script);
+
+ /* Lock power context base */
+ gfx_lock_pcbase(dev);
+}
+
+static void gfx_post_vbios_init(device_t dev)
+{
+ printk(BIOS_INFO, "GFX: Post VBIOS Init\n");
+ gfx_run_script(dev, gfx_post_vbios_script);
+}
+
+static void set_backlight_pwm(device_t dev, uint32_t bklt_reg, int req_hz)
+{
+ int divider;
+ struct resource *res;
+
+ res = find_resource(dev, PCI_BASE_ADDRESS_0);
+
+ if (res == NULL)
+ return;
+
+ /* Default to 200 Hz if nothing is set. */
+ if (req_hz == 0)
+ req_hz = 200;
+
+ /* Base clock is 25MHz */
+ divider = 25 * 1000 * 1000 / (16 * req_hz);
+
+ /* Do not set duty cycle (lower 16 bits). Just set the divider. */
+ write32((u32 *)(uintptr_t)(res->base + bklt_reg), divider << 16);
+}
+
+static void gfx_panel_setup(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ struct reg_script gfx_pipea_init[] = {
+ /* CONTROL */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_CONTROL),
+ PP_CONTROL_UNLOCK | PP_CONTROL_EDP_FORCE_VDD),
+ /* POWER ON */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_ON_DELAYS),
+ (config->gpu_pipea_port_select << 30 |
+ config->gpu_pipea_power_on_delay << 16 |
+ config->gpu_pipea_light_on_delay)),
+ /* POWER OFF */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_OFF_DELAYS),
+ (config->gpu_pipea_power_off_delay << 16 |
+ config->gpu_pipea_light_off_delay)),
+ /* DIVISOR */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_DIVISOR),
+ ~0x1f, config->gpu_pipea_power_cycle_delay),
+ REG_SCRIPT_END
+ };
+ struct reg_script gfx_pipeb_init[] = {
+ /* CONTROL */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_CONTROL),
+ PP_CONTROL_UNLOCK | PP_CONTROL_EDP_FORCE_VDD),
+ /* POWER ON */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_ON_DELAYS),
+ (config->gpu_pipeb_port_select << 30 |
+ config->gpu_pipeb_power_on_delay << 16 |
+ config->gpu_pipeb_light_on_delay)),
+ /* POWER OFF */
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_OFF_DELAYS),
+ (config->gpu_pipeb_power_off_delay << 16 |
+ config->gpu_pipeb_light_off_delay)),
+ /* DIVISOR */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_DIVISOR),
+ ~0x1f, config->gpu_pipeb_power_cycle_delay),
+ REG_SCRIPT_END
+ };
+
+ if (config->gpu_pipea_port_select) {
+ printk(BIOS_INFO, "GFX: Initialize PIPEA\n");
+ reg_script_run_on_dev(dev, gfx_pipea_init);
+ set_backlight_pwm(dev, PIPEA_REG(BACKLIGHT_CTL),
+ config->gpu_pipea_pwm_freq_hz);
+ }
+
+ if (config->gpu_pipeb_port_select) {
+ printk(BIOS_INFO, "GFX: Initialize PIPEB\n");
+ reg_script_run_on_dev(dev, gfx_pipeb_init);
+ set_backlight_pwm(dev, PIPEB_REG(BACKLIGHT_CTL),
+ config->gpu_pipeb_pwm_freq_hz);
+ }
+}
+
+static void gfx_init(device_t dev)
+{
+ /* Pre VBIOS Init */
+ gfx_pre_vbios_init(dev);
+
+ /* Power Management Init */
+ gfx_pm_init(dev);
+
+ gfx_panel_setup(dev);
+
+ /* Run VBIOS */
+ pci_dev_init(dev);
+
+ /* Post VBIOS Init */
+ gfx_post_vbios_init(dev);
+}
+
+static struct device_operations gfx_device_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = gfx_init,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver gfx_driver __pci_driver = {
+ .ops = &gfx_device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = GFX_DEVID,
+};
diff --git a/src/soc/intel/braswell/gpio.c b/src/soc/intel/braswell/gpio.c
new file mode 100644
index 0000000000..e4cc59a4b8
--- /dev/null
+++ b/src/soc/intel/braswell/gpio.c
@@ -0,0 +1,245 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/pci.h>
+#include <console/console.h>
+#include <soc/gpio.h>
+#include <soc/pmc.h>
+#include <soc/smm.h>
+
+/* GPIO-to-Pad LUTs */
+static const u8 gpncore_gpio_to_pad[GPNCORE_COUNT] =
+ { 19, 18, 17, 20, 21, 22, 24, 25, /* [ 0: 7] */
+ 23, 16, 14, 15, 12, 26, 27, 1, /* [ 8:15] */
+ 4, 8, 11, 0, 3, 6, 10, 13, /* [16:23] */
+ 2, 5, 9 }; /* [24:26] */
+
+static const u8 gpscore_gpio_to_pad[GPSCORE_COUNT] =
+ { 85, 89, 93, 96, 99, 102, 98, 101, /* [ 0: 7] */
+ 34, 37, 36, 38, 39, 35, 40, 84, /* [ 8: 15] */
+ 62, 61, 64, 59, 54, 56, 60, 55, /* [16: 23] */
+ 63, 57, 51, 50, 53, 47, 52, 49, /* [24: 31] */
+ 48, 43, 46, 41, 45, 42, 58, 44, /* [32: 39] */
+ 95, 105, 70, 68, 67, 66, 69, 71, /* [40: 47] */
+ 65, 72, 86, 90, 88, 92, 103, 77, /* [48: 55] */
+ 79, 83, 78, 81, 80, 82, 13, 12, /* [56: 63] */
+ 15, 14, 17, 18, 19, 16, 2, 1, /* [64: 71] */
+ 0, 4, 6, 7, 9, 8, 33, 32, /* [72: 79] */
+ 31, 30, 29, 27, 25, 28, 26, 23, /* [80: 87] */
+ 21, 20, 24, 22, 5, 3, 10, 11, /* [88: 95] */
+ 106, 87, 91, 104, 97, 100 }; /* [96:101] */
+
+static const u8 gpssus_gpio_to_pad[GPSSUS_COUNT] =
+ { 29, 33, 30, 31, 32, 34, 36, 35, /* [ 0: 7] */
+ 38, 37, 18, 7, 11, 20, 17, 1, /* [ 8:15] */
+ 8, 10, 19, 12, 0, 2, 23, 39, /* [16:23] */
+ 28, 27, 22, 21, 24, 25, 26, 51, /* [24:31] */
+ 56, 54, 49, 55, 48, 57, 50, 58, /* [32:39] */
+ 52, 53, 59, 40 }; /* [40:43] */
+
+/* GPIO bank descriptions */
+static const struct gpio_bank gpncore_bank = {
+ .gpio_count = GPNCORE_COUNT,
+ .gpio_to_pad = gpncore_gpio_to_pad,
+ .legacy_base = GP_LEGACY_BASE_NONE,
+ .pad_base = GPNCORE_PAD_BASE,
+ .has_wake_en = 0,
+ .gpio_f1_range_start = GPNCORE_GPIO_F1_RANGE_START,
+ .gpio_f1_range_end = GPNCORE_GPIO_F1_RANGE_END,
+};
+
+static const struct gpio_bank gpscore_bank = {
+ .gpio_count = GPSCORE_COUNT,
+ .gpio_to_pad = gpscore_gpio_to_pad,
+ .legacy_base = GPSCORE_LEGACY_BASE,
+ .pad_base = GPSCORE_PAD_BASE,
+ .has_wake_en = 0,
+ .gpio_f1_range_start = GPSCORE_GPIO_F1_RANGE_START,
+ .gpio_f1_range_end = GPSCORE_GPIO_F1_RANGE_END,
+};
+
+static const struct gpio_bank gpssus_bank = {
+ .gpio_count = GPSSUS_COUNT,
+ .gpio_to_pad = gpssus_gpio_to_pad,
+ .legacy_base = GPSSUS_LEGACY_BASE,
+ .pad_base = GPSSUS_PAD_BASE,
+ .has_wake_en = 1,
+ .gpio_f1_range_start = GPSSUS_GPIO_F1_RANGE_START,
+ .gpio_f1_range_end = GPSSUS_GPIO_F1_RANGE_END,
+};
+
+static void setup_gpios(const struct soc_gpio_map *gpios,
+ const struct gpio_bank *bank)
+{
+ const struct soc_gpio_map *config;
+ int gpio = 0;
+ u32 reg, pad_conf0;
+ u8 set, bit;
+
+ u32 use_sel[4] = {0};
+ u32 io_sel[4] = {0};
+ u32 gp_lvl[4] = {0};
+ u32 tpe[4] = {0};
+ u32 tne[4] = {0};
+ u32 wake_en[4] = {0};
+
+ if (!gpios)
+ return;
+
+ for (config = gpios; config->pad_conf0 != GPIO_LIST_END;
+ config++, gpio++) {
+ if (gpio > bank->gpio_count)
+ break;
+
+ set = gpio >> 5;
+ bit = gpio % 32;
+
+ if (bank->legacy_base != GP_LEGACY_BASE_NONE) {
+ /* Legacy IO configuration */
+ use_sel[set] |= config->use_sel << bit;
+ io_sel[set] |= config->io_sel << bit;
+ gp_lvl[set] |= config->gp_lvl << bit;
+ tpe[set] |= config->tpe << bit;
+ tne[set] |= config->tne << bit;
+
+ /* Some banks do not have wake_en ability */
+ if (bank->has_wake_en)
+ wake_en[set] |= config->wake_en << bit;
+ }
+
+ /* Pad configuration registers */
+ reg = bank->pad_base + 16 * bank->gpio_to_pad[gpio];
+
+ /* Add correct func to GPIO pad config */
+ pad_conf0 = config->pad_conf0;
+ if (config->is_gpio)
+ {
+ if (gpio >= bank->gpio_f1_range_start &&
+ gpio <= bank->gpio_f1_range_end)
+ pad_conf0 |= PAD_FUNC1;
+ else
+ pad_conf0 |= PAD_FUNC0;
+ }
+
+#ifdef GPIO_DEBUG
+ printk(BIOS_DEBUG, "Write Pad: Base(%x) - %x %x %x\n",
+ reg, pad_conf0, config->pad_conf1, config->pad_val);
+#endif
+
+ write32((u32 *)(reg + PAD_CONF0_REG), pad_conf0);
+ write32((u32 *)(reg + PAD_CONF1_REG), config->pad_conf1);
+ write32((u32 *)(reg + PAD_VAL_REG), config->pad_val);
+ }
+
+ if (bank->legacy_base != GP_LEGACY_BASE_NONE)
+ for (set = 0; set <= (bank->gpio_count - 1) / 32; ++set) {
+ reg = bank->legacy_base + 0x20 * set;
+
+#ifdef GPIO_DEBUG
+ printk(BIOS_DEBUG,
+ "Write GPIO: Reg(%x) - %x %x %x %x %x\n",
+ reg, use_sel[set], io_sel[set], gp_lvl[set],
+ tpe[set], tne[set]);
+#endif
+
+ outl(use_sel[set], reg + LEGACY_USE_SEL_REG);
+ outl(io_sel[set], reg + LEGACY_IO_SEL_REG);
+ outl(gp_lvl[set], reg + LEGACY_GP_LVL_REG);
+ outl(tpe[set], reg + LEGACY_TPE_REG);
+ outl(tne[set], reg + LEGACY_TNE_REG);
+
+ /* TS registers are WOC */
+ outl(0, reg + LEGACY_TS_REG);
+
+ if (bank->has_wake_en)
+ outl(wake_en[set], reg + LEGACY_WAKE_EN_REG);
+ }
+}
+
+static void setup_gpio_route(const struct soc_gpio_map *sus,
+ const struct soc_gpio_map *core)
+{
+ uint32_t route_reg = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ /* SMI takes precedence and wake_en implies SCI. */
+ if (sus[i].smi) {
+ route_reg |= ROUTE_SMI << (2 * i);
+ } else if (sus[i].sci) {
+ route_reg |= ROUTE_SCI << (2 * i);
+ }
+
+ if (core[i].smi) {
+ route_reg |= ROUTE_SMI << (2 * (i + 8));
+ } else if (core[i].sci) {
+ route_reg |= ROUTE_SCI << (2 * (i + 8));
+ }
+ }
+ southcluster_smm_save_param(SMM_SAVE_PARAM_GPIO_ROUTE, route_reg);
+}
+
+static void setup_dirqs(const u8 dirq[GPIO_MAX_DIRQS],
+ const struct gpio_bank *bank)
+{
+ u32 *reg = (u32 *)(bank->pad_base + PAD_BASE_DIRQ_OFFSET);
+ u32 val;
+ int i;
+
+ /* Write all four DIRQ registers */
+ for (i=0; i<4; ++i) {
+ val = dirq[i * 4 + 3] << 24 | dirq[i * 4 + 2] << 16 |
+ dirq[i * 4 + 1] << 8 | dirq[i * 4];
+ write32(reg + i, val);
+#ifdef GPIO_DEBUG
+ printk(BIOS_DEBUG, "Write DIRQ reg(%x) - %x\n",
+ reg + i, val);
+#endif
+ }
+}
+
+void setup_soc_gpios(struct soc_gpio_config *config, u8 enable_xdp_tap)
+{
+ if (config) {
+ setup_gpios(config->ncore, &gpncore_bank);
+ setup_gpios(config->score, &gpscore_bank);
+ setup_gpios(config->ssus, &gpssus_bank);
+ setup_gpio_route(config->ssus, config->score);
+
+ if (config->core_dirq)
+ setup_dirqs(*config->core_dirq, &gpscore_bank);
+ if (config->sus_dirq)
+ setup_dirqs(*config->sus_dirq, &gpssus_bank);
+ }
+
+ /* Set on die termination feature with pull up value and
+ * drive the pad high for TAP_TDO and TAP_TMS
+ */
+ if (!enable_xdp_tap) {
+ printk(BIOS_DEBUG, "Tri-state TDO and TMS\n");
+ write32((u32 *)(GPSSUS_PAD_BASE + 0x2fc), 0xc);
+ write32((u32 *)(GPSSUS_PAD_BASE + 0x2cc), 0xc);
+ }
+}
+
+struct soc_gpio_config* __attribute__((weak)) mainboard_get_gpios(void)
+{
+ printk(BIOS_DEBUG, "Default/empty GPIO config\n");
+ return NULL;
+}
diff --git a/src/soc/intel/braswell/hda.c b/src/soc/intel/braswell/hda.c
new file mode 100644
index 0000000000..dd1ba1556b
--- /dev/null
+++ b/src/soc/intel/braswell/hda.c
@@ -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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/intel/common/hda_verb.h>
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+
+static const struct reg_script init_ops[] = {
+ /* Enable no snoop traffic. */
+ REG_PCI_OR16(0x78, 1 << 11),
+ /* Configure HDMI codec connection. */
+ REG_PCI_OR32(0xc4, 1 << 1),
+ REG_PCI_OR8(0x43, (1 << 3) | (1 << 6)),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xc0),
+ REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0x00),
+ /* Configure internal settings. */
+ REG_PCI_OR32(0xc0, 0x7 << 21),
+ REG_PCI_OR32(0xc4, (0x3 << 26) | (1 << 13) | (1 << 10)),
+ REG_PCI_WRITE32(0xc8, 0x82a30000),
+ REG_PCI_RMW32(0xd0, ~(1 << 31), 0x0),
+ /* Disable docking. */
+ REG_PCI_RMW8(0x4d, ~(1 << 7), 0),
+ REG_SCRIPT_END,
+};
+
+static const uint32_t hdmi_codec_verb_table[] = {
+ /* coreboot specific header */
+ 0x80862882, /* vid did for hdmi codec */
+ 0x00000000, /* subsystem id */
+ 0x00000003, /* number of jacks */
+
+ /* pin widget 5 - port B */
+ 0x20471c10,
+ 0x20471d00,
+ 0x20471e56,
+ 0x20471f18,
+
+ /* pin widget 6 - port C */
+ 0x20571c20,
+ 0x20571d00,
+ 0x20571e56,
+ 0x20571f18,
+
+ /* pin widget 7 - port D */
+ 0x20671c30,
+ 0x20671d00,
+ 0x20671e56,
+ 0x20671f58,
+};
+
+static void hda_init(device_t dev)
+{
+ struct resource *res;
+ int codec_mask;
+ int i;
+ u8 *base;
+
+ reg_script_run_on_dev(dev, init_ops);
+
+ res = find_resource(dev, PCI_BASE_ADDRESS_0);
+ if (res == NULL)
+ return;
+
+ base = res2mmio(res, 0, 0);
+ codec_mask = hda_codec_detect(base);
+
+ printk(BIOS_DEBUG, "codec mask = %x\n", codec_mask);
+ if (!codec_mask)
+ return;
+
+ for (i = 3; i >= 0; i--) {
+ if (!((1 << i) & codec_mask))
+ continue;
+ hda_codec_init(base, i, sizeof(hdmi_codec_verb_table),
+ hdmi_codec_verb_table);
+ }
+}
+
+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 = hda_init,
+ .enable = NULL,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = HDA_DEVID,
+};
diff --git a/src/soc/intel/braswell/include/soc/acpi.h b/src/soc/intel/braswell/include/soc/acpi.h
new file mode 100644
index 0000000000..bdf1cb3ec4
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/acpi.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_ACPI_H_
+#define _BAYTRAIL_ACPI_H_
+
+#include <arch/acpi.h>
+#include <soc/nvs.h>
+
+void acpi_create_intel_hpet(acpi_hpet_t * hpet);
+void acpi_fill_in_fadt(acpi_fadt_t *fadt);
+unsigned long acpi_madt_irq_overrides(unsigned long current);
+void acpi_init_gnvs(global_nvs_t *gnvs);
+
+#endif /* _BAYTRAIL_ACPI_H_ */
diff --git a/src/soc/intel/braswell/include/soc/device_nvs.h b/src/soc/intel/braswell/include/soc/device_nvs.h
new file mode 100644
index 0000000000..1ed897f8e5
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/device_nvs.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_DEVICE_NVS_H_
+#define _BAYTRAIL_DEVICE_NVS_H_
+
+#include <stdint.h>
+
+/* Offset in Global NVS where this structure lives */
+#define DEVICE_NVS_OFFSET 0x1000
+
+#define LPSS_NVS_SIO_DMA1 0
+#define LPSS_NVS_I2C1 1
+#define LPSS_NVS_I2C2 2
+#define LPSS_NVS_I2C3 3
+#define LPSS_NVS_I2C4 4
+#define LPSS_NVS_I2C5 5
+#define LPSS_NVS_I2C6 6
+#define LPSS_NVS_I2C7 7
+#define LPSS_NVS_SIO_DMA2 8
+#define LPSS_NVS_SPI 9
+#define LPSS_NVS_PWM1 10
+#define LPSS_NVS_PWM2 11
+#define LPSS_NVS_HSUART1 12
+#define LPSS_NVS_HSUART2 13
+
+#define SCC_NVS_MMC 0
+#define SCC_NVS_SDIO 1
+#define SCC_NVS_SD 2
+
+typedef struct {
+ /* Device Enabled in ACPI Mode */
+ u8 lpss_en[14];
+ u8 scc_en[3];
+ u8 lpe_en;
+
+ /* BAR 0 */
+ u32 lpss_bar0[14];
+ u32 scc_bar0[3];
+ u32 lpe_bar0;
+
+ /* BAR 0 */
+ u32 lpss_bar1[14];
+ u32 scc_bar1[3];
+ u32 lpe_bar1;
+
+ /* Extra */
+ u32 lpe_fw; /* LPE Firmware */
+ u8 rsvd1[3930]; /* Add padding so sizeof(device_nvs_t) == 0x1000 */
+} __attribute__((packed)) device_nvs_t;
+
+#endif
diff --git a/src/soc/intel/braswell/include/soc/efi_wrapper.h b/src/soc/intel/braswell/include/soc/efi_wrapper.h
new file mode 100644
index 0000000000..3304d03451
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/efi_wrapper.h
@@ -0,0 +1,52 @@
+/*
+ * PEI EFI entry point
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * 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 Google Inc. 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 GOOGLE INC 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.
+ */
+
+#ifndef __EFI_WRAPPER_H__
+#define __EFI_WRAPPER_H__
+
+#define EFI_WRAPPER_VER 2
+
+/* Provide generic x86 calling conventions. */
+#define ABI_X86 __attribute((regparm(0)))
+
+/* Errors returned by the EFI wrapper. */
+enum efi_wrapper_error {
+ INVALID_VER = -1,
+};
+
+struct efi_wrapper_params {
+ /* Mainboard Inputs */
+ int version;
+
+ void ABI_X86 (*console_out)(unsigned char byte);
+
+ unsigned int tsc_ticks_per_microsecond;
+} __attribute__((packed));
+
+typedef int ABI_X86 (*efi_wrapper_entry_t)(struct efi_wrapper_params *);
+#endif
diff --git a/src/soc/intel/braswell/include/soc/ehci.h b/src/soc/intel/braswell/include/soc/ehci.h
new file mode 100644
index 0000000000..a1edd6dffe
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/ehci.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BAYTRAIL_EHCI_H
+#define BAYTRAIL_EHCI_H
+
+/* EHCI PCI Registers */
+#define EHCI_CMD_STS 0x04
+# define INTRDIS (1 << 10)
+#define EHCI_SBRN_FLA_PWC 0x60
+# define PORTWKIMP (1 << 16)
+# define PORTWKCAPMASK (0x3ff << 17)
+#define EHCI_USB2PDO 0x64
+
+/* EHCI Memory Registers */
+#define USB2CMD 0x20
+# define USB2CMD_ASE (1 << 5)
+# define USB2CMD_PSE (1 << 4)
+# define USB2CMD_HCRESET (1 << 1)
+# define USB2CMD_RS (1 << 0)
+#define USB2STS 0x24
+# define USB2STS_HCHALT (1 << 12)
+
+/* RCBA EHCI Registers */
+#define RCBA_FUNC_DIS 0x220
+# define RCBA_EHCI_DIS (1 << 0)
+
+#endif /* BAYTRAIL_EHCI_H */
diff --git a/src/soc/intel/braswell/include/soc/gfx.h b/src/soc/intel/braswell/include/soc/gfx.h
new file mode 100644
index 0000000000..7047dd5a6a
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/gfx.h
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_GFX_H_
+#define _BAYTRAIL_GFX_H_
+
+/*
+ * PCI config registers.
+ */
+
+#define GGC 0x50
+# define GGC_VGA_DISABLE (1 << 1)
+# define GGC_GTT_SIZE_MASK (3 << 8)
+# define GGC_GTT_SIZE_0MB (0 << 8)
+# define GGC_GTT_SIZE_1MB (1 << 8)
+# define GGC_GTT_SIZE_2MB (2 << 8)
+# define GGC_GSM_SIZE_MASK (0x1f << 3)
+# define GGC_GSM_SIZE_0MB (0 << 3)
+# define GGC_GSM_SIZE_32MB (1 << 3)
+# define GGC_GSM_SIZE_64MB (2 << 3)
+# define GGC_GSM_SIZE_128MB (4 << 3)
+
+#define GSM_BASE 0x5c
+#define GTT_BASE 0x70
+
+#define MSAC 0x62
+#define APERTURE_SIZE_MASK (3 << 1)
+#define APERTURE_SIZE_128MB (0 << 1)
+#define APERTURE_SIZE_256MB (1 << 1)
+#define APERTURE_SIZE_512MB (3 << 1)
+
+#define VLV_DISPLAY_BASE 0x180000
+#define PIPEA_REG(reg) (VLV_DISPLAY_BASE + (reg))
+#define PIPEB_REG(reg) (VLV_DISPLAY_BASE + 0x100 + (reg))
+
+/* Panel control registers */
+#define HOTPLUG_CTRL 0x61110
+#define PP_CONTROL 0x61204
+#define PP_CONTROL_UNLOCK 0xabcd0000
+#define PP_CONTROL_EDP_FORCE_VDD (1 << 3)
+#define PP_ON_DELAYS 0x61208
+#define PP_OFF_DELAYS 0x6120c
+#define PP_DIVISOR 0x61210
+#define BACKLIGHT_CTL2 0x61250
+#define BACKLIGHT_ENABLE (1 << 31)
+#define BACKLIGHT_CTL 0x61254
+
+#endif /* _BAYTRAIL_GFX_H_ */
diff --git a/src/soc/intel/braswell/include/soc/gpio.h b/src/soc/intel/braswell/include/soc/gpio.h
new file mode 100644
index 0000000000..f312cdc65f
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/gpio.h
@@ -0,0 +1,459 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_GPIO_H_
+#define _BAYTRAIL_GPIO_H_
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <soc/iomap.h>
+
+/* #define GPIO_DEBUG */
+
+/* Pad base, ex. PAD_CONF0[n]= PAD_BASE+16*n */
+#define GPSCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSCORE)
+#define GPNCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPNCORE)
+#define GPSSUS_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSSUS)
+
+/* DIRQ registers start at pad base + 0x980 */
+#define PAD_BASE_DIRQ_OFFSET 0x980
+
+/* Pad register offset */
+#define PAD_CONF0_REG 0x0
+#define PAD_CONF1_REG 0x4
+#define PAD_VAL_REG 0x8
+
+/* Legacy IO register base */
+#define GPSCORE_LEGACY_BASE (GPIO_BASE_ADDRESS + 0x00)
+#define GPSSUS_LEGACY_BASE (GPIO_BASE_ADDRESS + 0x80)
+/* Some banks have no legacy GPIO interface */
+#define GP_LEGACY_BASE_NONE 0xFFFF
+
+#define LEGACY_USE_SEL_REG 0x00
+#define LEGACY_IO_SEL_REG 0x04
+#define LEGACY_GP_LVL_REG 0x08
+#define LEGACY_TPE_REG 0x0C
+#define LEGACY_TNE_REG 0x10
+#define LEGACY_TS_REG 0x14
+#define LEGACY_WAKE_EN_REG 0x18
+
+/* Number of GPIOs in each bank */
+#define GPNCORE_COUNT 27
+#define GPSCORE_COUNT 102
+#define GPSSUS_COUNT 44
+
+/* GPIO legacy IO register settings */
+#define GPIO_USE_MMIO 0
+#define GPIO_USE_LEGACY 1
+
+#define GPIO_DIR_OUTPUT 0
+#define GPIO_DIR_INPUT 1
+
+#define GPIO_LEVEL_LOW 0
+#define GPIO_LEVEL_HIGH 1
+
+#define GPIO_PEDGE_DISABLE 0
+#define GPIO_PEDGE_ENABLE 1
+
+#define GPIO_NEDGE_DISABLE 0
+#define GPIO_NEDGE_ENABLE 1
+
+/* config0[29] - Disable second mask */
+#define PAD_MASK2_DISABLE (1 << 29)
+
+/* config0[27] - Direct Irq En */
+#define PAD_IRQ_EN (1 << 27)
+
+/* config0[26] - gd_tne */
+#define PAD_TNE_IRQ (1 << 26)
+
+/* config0[25] - gd_tpe */
+#define PAD_TPE_IRQ (1 << 25)
+
+/* config0[24] - Gd Level */
+#define PAD_LEVEL_IRQ (1 << 24)
+#define PAD_EDGE_IRQ (0 << 24)
+
+/* config0[17] - Slow clkgate / glitch filter */
+#define PAD_SLOWGF_ENABLE (1 << 17)
+
+/* config0[16] - Fast clkgate / glitch filter */
+#define PAD_FASTGF_ENABLE (1 << 16)
+
+/* config0[15] - Hysteresis enable (inverted) */
+#define PAD_HYST_DISABLE (1 << 15)
+#define PAD_HYST_ENABLE (0 << 15)
+
+/* config0[14:13] - Hysteresis control */
+#define PAD_HYST_CTRL_DEFAULT (2 << 13)
+
+/* config0[11] - Bypass Flop */
+#define PAD_FLOP_BYPASS (1 << 11)
+#define PAD_FLOP_ENABLE (0 << 11)
+
+/* config0[10:9] - Pull str */
+#define PAD_PU_2K (0 << 9)
+#define PAD_PU_10K (1 << 9)
+#define PAD_PU_20K (2 << 9)
+#define PAD_PU_40K (3 << 9)
+
+/* config0[8:7] - Pull assign */
+#define PAD_PULL_DISABLE (0 << 7)
+#define PAD_PULL_UP (1 << 7)
+#define PAD_PULL_DOWN (2 << 7)
+
+/* config0[2:0] - Func. pin mux */
+#define PAD_FUNC0 0x0
+#define PAD_FUNC1 0x1
+#define PAD_FUNC2 0x2
+#define PAD_FUNC3 0x3
+#define PAD_FUNC4 0x4
+#define PAD_FUNC5 0x5
+#define PAD_FUNC6 0x6
+
+/* pad config0 power-on values - We will not often want to change these */
+#define PAD_CONFIG0_DEFAULT (PAD_MASK2_DISABLE | PAD_SLOWGF_ENABLE | \
+ PAD_FASTGF_ENABLE | PAD_HYST_DISABLE | \
+ PAD_HYST_CTRL_DEFAULT | PAD_FLOP_BYPASS)
+
+/* pad config1 reg power-on values - Shouldn't need to change this */
+#define PAD_CONFIG1_DEFAULT 0x8000
+
+/* pad_val[2] - Iinenb - active low */
+#define PAD_VAL_INPUT_DISABLE (1 << 2)
+#define PAD_VAL_INPUT_ENABLE (0 << 2)
+
+/* pad_val[1] - Ioutenb - active low */
+#define PAD_VAL_OUTPUT_DISABLE (1 << 1)
+#define PAD_VAL_OUTPUT_ENABLE (0 << 1)
+
+/* Input / Output state should usually be mutually exclusive */
+#define PAD_VAL_INPUT (PAD_VAL_INPUT_ENABLE | PAD_VAL_OUTPUT_DISABLE)
+#define PAD_VAL_OUTPUT (PAD_VAL_OUTPUT_ENABLE | PAD_VAL_INPUT_DISABLE)
+
+/* pad_val[0] - Value */
+#define PAD_VAL_HIGH (1 << 0)
+#define PAD_VAL_LOW (0 << 0)
+
+/* pad_val reg power-on default varies by pad, and apparently can cause issues
+ * if not set correctly, even if the pin isn't configured as GPIO. */
+#define PAD_VAL_DEFAULT PAD_VAL_INPUT
+
+/* Configure GPIOs as MMIO by default */
+#define GPIO_INPUT_PU_10K \
+ { .pad_conf0 = PAD_PU_10K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_MMIO, \
+ .is_gpio = 1 }
+
+#define GPIO_INPUT_PU_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_MMIO, \
+ .is_gpio = 1 }
+
+#define GPIO_INPUT_PD_10K \
+ { .pad_conf0 = PAD_PU_10K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_MMIO, \
+ .is_gpio = 1 }
+
+#define GPIO_INPUT_PD_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_MMIO, \
+ .is_gpio = 1 }
+
+#define GPIO_INPUT_NOPU \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_MMIO, \
+ .is_gpio = 1 }
+
+#define GPIO_INPUT_LEGACY_NOPU \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_LEGACY, \
+ .io_sel = GPIO_DIR_INPUT, \
+ .is_gpio = 1 }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_LEVEL_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ_LEVELHIGH_NO_PULL \
+ { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_LEVEL_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ_LEVELLOW_PU_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_LEVEL_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ_EDGELOW_PU_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_EDGE_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ_EDGEHIGH_PD_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_EDGE_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ_EDGELOW_PD_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_EDGE_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+/* Direct / dedicated IRQ input - pass signal directly to apic */
+#define GPIO_DIRQ_EDGEBOTH_PU_20K \
+ { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \
+ | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ| PAD_TNE_IRQ | PAD_EDGE_IRQ, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, }
+
+#define GPIO_OUT_LOW \
+ { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_OUTPUT | PAD_VAL_LOW, \
+ .use_sel = GPIO_USE_LEGACY, \
+ .io_sel = GPIO_DIR_OUTPUT, \
+ .gp_lvl = GPIO_LEVEL_LOW, \
+ .is_gpio = 1 }
+
+#define GPIO_OUT_HIGH \
+ { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_OUTPUT | PAD_VAL_HIGH, \
+ .use_sel = GPIO_USE_LEGACY, \
+ .io_sel = GPIO_DIR_OUTPUT, \
+ .gp_lvl = GPIO_LEVEL_HIGH, \
+ .is_gpio = 1 }
+
+/* Define no-pull / PU / PD configs for each functional config option */
+#define GPIO_FUNC(_func, _pudir, _str) \
+ { .use_sel = GPIO_USE_MMIO, \
+ .pad_conf0 = PAD_FUNC##_func | PAD_##_pudir | PAD_PU_##_str | \
+ PAD_CONFIG0_DEFAULT, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_DEFAULT }
+
+/* Default functional configs -- no PU */
+#define GPIO_FUNC0 GPIO_FUNC(0, PULL_DISABLE, 20K)
+#define GPIO_FUNC1 GPIO_FUNC(1, PULL_DISABLE, 20K)
+#define GPIO_FUNC2 GPIO_FUNC(2, PULL_DISABLE, 20K)
+#define GPIO_FUNC3 GPIO_FUNC(3, PULL_DISABLE, 20K)
+#define GPIO_FUNC4 GPIO_FUNC(4, PULL_DISABLE, 20K)
+#define GPIO_FUNC5 GPIO_FUNC(5, PULL_DISABLE, 20K)
+#define GPIO_FUNC6 GPIO_FUNC(6, PULL_DISABLE, 20K)
+
+/* ACPI GPIO routing. Assume everything is externally pulled and negative edge
+ * triggered. SCI implies WAKE, but WAKE doesn't imply SCI. */
+#define GPIO_ACPI_SCI \
+ { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_LEGACY, \
+ .io_sel = GPIO_DIR_INPUT, \
+ .tne = 1, \
+ .sci = 1, \
+ .wake_en = 1, }
+#define GPIO_ACPI_WAKE \
+ { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_LEGACY, \
+ .io_sel = GPIO_DIR_INPUT, \
+ .tne = 1, \
+ .wake_en = 1, }
+#define GPIO_ACPI_SMI \
+ { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \
+ .pad_conf1 = PAD_CONFIG1_DEFAULT, \
+ .pad_val = PAD_VAL_INPUT, \
+ .use_sel = GPIO_USE_LEGACY, \
+ .io_sel = GPIO_DIR_INPUT, \
+ .tne = 1, \
+ .smi = 1}
+
+/* End marker */
+#define GPIO_LIST_END 0xffffffff
+
+#define GPIO_END \
+ { .pad_conf0 = GPIO_LIST_END }
+
+/* Common default GPIO settings */
+#define GPIO_INPUT GPIO_INPUT_NOPU
+#define GPIO_INPUT_LEGACY GPIO_INPUT_LEGACY_NOPU
+#define GPIO_INPUT_PU GPIO_INPUT_PU_20K
+#define GPIO_INPUT_PD GPIO_INPUT_PD_20K
+#define GPIO_NC GPIO_OUT_HIGH
+#define GPIO_DEFAULT GPIO_FUNC0
+
+/* 16 DirectIRQs per supported bank */
+#define GPIO_MAX_DIRQS 16
+
+/* Most pins are GPIO function 0. Some banks have a range of pins with GPIO
+ * function 1. Indicate first / last GPIOs with function 1. */
+#define GPIO_NONE 255
+/* All NCORE GPIOs are function 0 */
+#define GPNCORE_GPIO_F1_RANGE_START GPIO_NONE
+#define GPNCORE_GPIO_F1_RANGE_END GPIO_NONE
+/* SCORE GPIO [92:93] are function 1 */
+#define GPSCORE_GPIO_F1_RANGE_START 92
+#define GPSCORE_GPIO_F1_RANGE_END 93
+/* SSUS GPIO [11:21] are function 1 */
+#define GPSSUS_GPIO_F1_RANGE_START 11
+#define GPSSUS_GPIO_F1_RANGE_END 21
+
+struct soc_gpio_map {
+ u32 pad_conf0;
+ u32 pad_conf1;
+ u32 pad_val;
+ u32 use_sel : 1;
+ u32 io_sel : 1;
+ u32 gp_lvl : 1;
+ u32 tpe : 1;
+ u32 tne : 1;
+ u32 wake_en : 1;
+ u32 smi : 1;
+ u32 is_gpio : 1;
+ u32 sci : 1;
+} __attribute__ ((packed));
+
+struct soc_gpio_config {
+ const struct soc_gpio_map *ncore;
+ const struct soc_gpio_map *score;
+ const struct soc_gpio_map *ssus;
+ const u8 (*core_dirq)[GPIO_MAX_DIRQS];
+ const u8 (*sus_dirq)[GPIO_MAX_DIRQS];
+};
+
+/* Description of GPIO 'bank' ex. {ncore, score. ssus} */
+struct gpio_bank {
+ const int gpio_count;
+ const u8* gpio_to_pad;
+ const int legacy_base;
+ const unsigned long pad_base;
+ const u8 has_wake_en :1;
+ const u8 gpio_f1_range_start;
+ const u8 gpio_f1_range_end;
+};
+
+void setup_soc_gpios(struct soc_gpio_config *config, u8 enable_xdp_tap);
+/* This function is weak and can be overridden by a mainboard function. */
+struct soc_gpio_config* mainboard_get_gpios(void);
+
+/* Functions / defines for changing GPIOs in romstage */
+/* SCORE Pad definitions. */
+#define UART_RXD_PAD 82
+#define UART_TXD_PAD 83
+#define PCU_SMB_CLK_PAD 88
+#define PCU_SMB_DATA_PAD 90
+#define SOC_DDI1_VDDEN_PAD 16
+
+static inline u32 *ncore_pconf0(int pad_num)
+{
+ return (u32 *)(GPNCORE_PAD_BASE + pad_num * 16);
+}
+
+static inline void ncore_select_func(int pad, int func)
+{
+ uint32_t reg;
+ u32 *pconf0_addr = ncore_pconf0(pad);
+
+ reg = read32(pconf0_addr);
+ reg &= ~0x7;
+ reg |= func & 0x7;
+ write32(pconf0_addr, reg);
+}
+
+static inline u32 *score_pconf0(int pad_num)
+{
+ return (u32 *)(GPSCORE_PAD_BASE + pad_num * 16);
+}
+
+static inline u32 *ssus_pconf0(int pad_num)
+{
+ return (u32 *)(GPSSUS_PAD_BASE + pad_num * 16);
+}
+
+static inline void score_select_func(int pad, int func)
+{
+ uint32_t reg;
+ uint32_t *pconf0_addr = score_pconf0(pad);
+
+ reg = read32(pconf0_addr);
+ reg &= ~0x7;
+ reg |= func & 0x7;
+ write32(pconf0_addr, reg);
+}
+
+static inline void ssus_select_func(int pad, int func)
+{
+ uint32_t reg;
+ uint32_t *pconf0_addr = ssus_pconf0(pad);
+
+ reg = read32(pconf0_addr);
+ reg &= ~0x7;
+ reg |= func & 0x7;
+ write32(pconf0_addr, reg);
+}
+
+/* These functions require that the input pad be configured as an input GPIO */
+static inline int score_get_gpio(int pad)
+{
+ uint32_t *val_addr = score_pconf0(pad) + (PAD_VAL_REG/sizeof(uint32_t));
+
+ return read32(val_addr) & PAD_VAL_HIGH;
+}
+
+static inline int ssus_get_gpio(int pad)
+{
+ uint32_t *val_addr = ssus_pconf0(pad) + (PAD_VAL_REG/sizeof(uint32_t));
+
+ return read32(val_addr) & PAD_VAL_HIGH;
+}
+
+static inline void ssus_disable_internal_pull(int pad)
+{
+ const uint32_t pull_mask = ~(0xf << 7);
+ write32(ssus_pconf0(pad), read32(ssus_pconf0(pad)) & pull_mask);
+}
+
+#endif /* _BAYTRAIL_GPIO_H_ */
diff --git a/src/soc/intel/braswell/include/soc/iomap.h b/src/soc/intel/braswell/include/soc/iomap.h
new file mode 100644
index 0000000000..867484b178
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/iomap.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_IOMAP_H_
+#define _BAYTRAIL_IOMAP_H_
+
+
+/*
+ * Memory Mapped IO bases.
+ */
+
+/* PCI Configuration Space */
+#define MCFG_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS
+#define MCFG_BASE_SIZE 0x10000000
+
+/* Transactions in this range will abort */
+#define ABORT_BASE_ADDRESS 0xfeb00000
+#define ABORT_BASE_SIZE 0x00100000
+
+/* Power Management Controller */
+#define PMC_BASE_ADDRESS 0xfed03000
+#define PMC_BASE_SIZE 0x400
+
+/* IO Memory */
+#define IO_BASE_ADDRESS 0xfed0c000
+#define IO_BASE_OFFSET_GPSCORE 0x0000
+#define IO_BASE_OFFSET_GPNCORE 0x1000
+#define IO_BASE_OFFSET_GPSSUS 0x2000
+#define IO_BASE_SIZE 0x4000
+
+/* Intel Legacy Block */
+#define ILB_BASE_ADDRESS 0xfed08000
+#define ILB_BASE_SIZE 0x400
+
+/* SPI Bus */
+#define SPI_BASE_ADDRESS 0xfed01000
+#define SPI_BASE_SIZE 0x400
+
+/* MODPHY */
+#define MPHY_BASE_ADDRESS 0xfef00000
+#define MPHY_BASE_SIZE 0x100000
+
+/* Power Management Unit */
+#define PUNIT_BASE_ADDRESS 0xfed05000
+#define PUNIT_BASE_SIZE 0x800
+
+/* Root Complex Base Address */
+#define RCBA_BASE_ADDRESS 0xfed1c000
+#define RCBA_BASE_SIZE 0x400
+
+/* High Performance Event Timer */
+#define HPET_BASE_ADDRESS 0xfed00000
+#define HPET_BASE_SIZE 0x400
+
+/* Temporary Base Address */
+#define TEMP_BASE_ADDRESS 0xfd000000
+
+/*
+ * IO Port bases.
+ */
+#define ACPI_BASE_ADDRESS 0x0400
+#define ACPI_BASE_SIZE 0x80
+
+#define GPIO_BASE_ADDRESS 0x0500
+#define GPIO_BASE_SIZE 0x100
+
+#define SMBUS_BASE_ADDRESS 0xefa0
+
+#ifndef __ACPI__
+/* Read Top of Low Memory (BMBOUND) */
+uint32_t nc_read_top_of_low_memory(void);
+#endif
+
+#endif /* _BAYTRAIL_IOMAP_H_ */
diff --git a/src/soc/intel/braswell/include/soc/iosf.h b/src/soc/intel/braswell/include/soc/iosf.h
new file mode 100644
index 0000000000..6705a7320e
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/iosf.h
@@ -0,0 +1,349 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_IOSF_H_
+#define _BAYTRAIL_IOSF_H_
+
+#include <stdint.h>
+#include <soc/pci_devs.h>
+
+/*
+ * The Bay Trail SoC has a message network called IOSF Sideband. The access
+ * routines are through 3 registers in PCI config space of 00:00.0:
+ * MCR - control register
+ * MDR - data register
+ * MCRX - control register extension
+ * The extension regist is only used for addresses that don't fit into the
+ * 8 bit register address.
+ */
+
+#ifndef PCI_DEV
+#define PCI_DEV(SEGBUS, DEV, FN) ( \
+ (((SEGBUS) & 0xFFF) << 20) | \
+ (((DEV) & 0x1F) << 15) | \
+ (((FN) & 0x07) << 12))
+#endif
+#define IOSF_PCI_DEV PCI_DEV(0,SOC_DEV,SOC_FUNC)
+
+#define MCR_REG 0xd0
+#define IOSF_OPCODE(x) ((x) << 24)
+#define IOSF_PORT(x) ((0xff & (x)) << 16)
+#define IOSF_REG(x) ((0xff & (x)) << 8)
+#define IOSF_REG_UPPER(x) (((~0xff) & (x)))
+#define IOSF_BYTE_EN_0 0x10
+#define IOSF_BYTE_EN_1 0x20
+#define IOSF_BYTE_EN_2 0x40
+#define IOSF_BYTE_EN_3 0x80
+#define IOSF_BYTE_EN \
+ (IOSF_BYTE_EN_0 | IOSF_BYTE_EN_1 | IOSF_BYTE_EN_2 | IOSF_BYTE_EN_3)
+#define MDR_REG 0xd4
+#define MCRX_REG 0xd8
+
+uint32_t iosf_aunit_read(int reg);
+void iosf_aunit_write(int reg, uint32_t val);
+uint32_t iosf_cpu_bus_read(int reg);
+void iosf_cpu_bus_write(int reg, uint32_t val);
+uint32_t iosf_bunit_read(int reg);
+void iosf_bunit_write(int reg, uint32_t val);
+uint32_t iosf_dunit_read(int reg);
+void iosf_dunit_write(int reg, uint32_t val);
+/* Some registers are per channel while the globals live in dunit 0 */
+uint32_t iosf_dunit_ch0_read(int reg);
+uint32_t iosf_dunit_ch1_read(int reg);
+uint32_t iosf_punit_read(int reg);
+void iosf_punit_write(int reg, uint32_t val);
+uint32_t iosf_usbphy_read(int reg);
+void iosf_usbphy_write(int reg, uint32_t val);
+uint32_t iosf_ushphy_read(int reg);
+void iosf_ushphy_write(int reg, uint32_t val);
+uint32_t iosf_sec_read(int reg);
+void iosf_sec_write(int reg, uint32_t val);
+uint32_t iosf_port45_read(int reg);
+void iosf_port45_write(int reg, uint32_t val);
+uint32_t iosf_port46_read(int reg);
+void iosf_port46_write(int reg, uint32_t val);
+uint32_t iosf_port47_read(int reg);
+void iosf_port47_write(int reg, uint32_t val);
+uint32_t iosf_port55_read(int reg);
+void iosf_port55_write(int reg, uint32_t val);
+uint32_t iosf_port58_read(int reg);
+void iosf_port58_write(int reg, uint32_t val);
+uint32_t iosf_port59_read(int reg);
+void iosf_port59_write(int reg, uint32_t val);
+uint32_t iosf_port5a_read(int reg);
+void iosf_port5a_write(int reg, uint32_t val);
+uint32_t iosf_lpss_read(int reg);
+void iosf_lpss_write(int reg, uint32_t val);
+uint32_t iosf_ccu_read(int reg);
+void iosf_ccu_write(int reg, uint32_t val);
+uint32_t iosf_score_read(int reg);
+void iosf_score_write(int reg, uint32_t val);
+uint32_t iosf_scc_read(int reg);
+void iosf_scc_write(int reg, uint32_t val);
+uint32_t iosf_porta2_read(int reg);
+void iosf_porta2_write(int reg, uint32_t val);
+uint32_t iosf_ssus_read(int reg);
+void iosf_ssus_write(int reg, uint32_t val);
+
+/* IOSF ports. */
+#define IOSF_PORT_AUNIT 0x00 /* IO Arbiter unit */
+#define IOSF_PORT_SYSMEMC 0x01 /* System Memory Controller */
+#define IOSF_PORT_DUNIT_CH0 0x07 /* DUNIT Channel 0 */
+#define IOSF_PORT_CPU_BUS 0x02 /* CPU Bus Interface Controller */
+#define IOSF_PORT_BUNIT 0x03 /* System Memory Arbiter/Bunit */
+#define IOSF_PORT_PMC 0x04 /* Power Management Controller */
+#define IOSF_PORT_GFX 0x06 /* Graphics Adapter */
+#define IOSF_PORT_DUNIT_CH1 0x07 /* DUNIT Channel 1 */
+#define IOSF_PORT_SYSMEMIO 0x0c /* System Memory IO */
+#define IOSF_PORT_USBPHY 0x43 /* USB PHY */
+#define IOSF_PORT_SEC 0x44 /* SEC */
+#define IOSF_PORT_0x45 0x45
+#define IOSF_PORT_0x46 0x46
+#define IOSF_PORT_0x47 0x47
+#define IOSF_PORT_SCORE 0x48 /* SCORE */
+#define IOSF_PORT_0x55 0x55
+#define IOSF_PORT_0x58 0x58
+#define IOSF_PORT_0x59 0x59
+#define IOSF_PORT_0x5a 0x5a
+#define IOSF_PORT_USHPHY 0x61 /* USB XHCI PHY */
+#define IOSF_PORT_SCC 0x63 /* Storage Control Cluster */
+#define IOSF_PORT_LPSS 0xa0 /* LPSS - Low Power Subsystem */
+#define IOSF_PORT_0xa2 0xa2
+#define IOSF_PORT_SATAPHY 0xa3 /* SATA PHY */
+#define IOSF_PORT_PCIEPHY 0xa3 /* PCIE PHY */
+#define IOSF_PORT_SSUS 0xa8 /* SUS */
+#define IOSF_PORT_CCU 0xa9 /* Clock control unit. */
+
+/* Read and write opcodes differ per port. */
+#define IOSF_OP_READ_AUNIT 0x10
+#define IOSF_OP_WRITE_AUNIT (IOSF_OP_READ_AUNIT | 1)
+#define IOSF_OP_READ_SYSMEMC 0x10
+#define IOSF_OP_WRITE_SYSMEMC (IOSF_OP_READ_SYSMEMC | 1)
+#define IOSF_OP_READ_CPU_BUS 0x10
+#define IOSF_OP_WRITE_CPU_BUS (IOSF_OP_READ_CPU_BUS | 1)
+#define IOSF_OP_READ_BUNIT 0x10
+#define IOSF_OP_WRITE_BUNIT (IOSF_OP_READ_BUNIT | 1)
+#define IOSF_OP_READ_PMC 0x06
+#define IOSF_OP_WRITE_PMC (IOSF_OP_READ_PMC | 1)
+#define IOSF_OP_READ_GFX 0x00
+#define IOSF_OP_WRITE_GFX (IOSF_OP_READ_GFX | 1)
+#define IOSF_OP_READ_SYSMEMIO 0x06
+#define IOSF_OP_WRITE_SYSMEMIO (IOSF_OP_READ_SYSMEMIO | 1)
+#define IOSF_OP_READ_USBPHY 0x06
+#define IOSF_OP_WRITE_USBPHY (IOSF_OP_READ_USBPHY | 1)
+#define IOSF_OP_READ_SEC 0x04
+#define IOSF_OP_WRITE_SEC (IOSF_OP_READ_SEC | 1)
+#define IOSF_OP_READ_0x45 0x06
+#define IOSF_OP_WRITE_0x45 (IOSF_OP_READ_0x45 | 1)
+#define IOSF_OP_READ_0x46 0x06
+#define IOSF_OP_WRITE_0x46 (IOSF_OP_READ_0x46 | 1)
+#define IOSF_OP_READ_0x47 0x06
+#define IOSF_OP_WRITE_0x47 (IOSF_OP_READ_0x47 | 1)
+#define IOSF_OP_READ_SCORE 0x06
+#define IOSF_OP_WRITE_SCORE (IOSF_OP_READ_SCORE | 1)
+#define IOSF_OP_READ_0x55 0x04
+#define IOSF_OP_WRITE_0x55 (IOSF_OP_READ_0x55 | 1)
+#define IOSF_OP_READ_0x58 0x06
+#define IOSF_OP_WRITE_0x58 (IOSF_OP_READ_0x58 | 1)
+#define IOSF_OP_READ_0x59 0x06
+#define IOSF_OP_WRITE_0x59 (IOSF_OP_READ_0x59 | 1)
+#define IOSF_OP_READ_0x5a 0x04
+#define IOSF_OP_WRITE_0x5a (IOSF_OP_READ_0x5a | 1)
+#define IOSF_OP_READ_USHPHY 0x06
+#define IOSF_OP_WRITE_USHPHY (IOSF_OP_READ_USHPHY | 1)
+#define IOSF_OP_READ_SCC 0x06
+#define IOSF_OP_WRITE_SCC (IOSF_OP_READ_SCC | 1)
+#define IOSF_OP_READ_LPSS 0x06
+#define IOSF_OP_WRITE_LPSS (IOSF_OP_READ_LPSS | 1)
+#define IOSF_OP_READ_0xa2 0x06
+#define IOSF_OP_WRITE_0xa2 (IOSF_OP_READ_0xa2 | 1)
+#define IOSF_OP_READ_SATAPHY 0x00
+#define IOSF_OP_WRITE_SATAPHY (IOSF_OP_READ_SATAPHY | 1)
+#define IOSF_OP_READ_PCIEPHY 0x00
+#define IOSF_OP_WRITE_PCIEPHY (IOSF_OP_READ_PCIEPHY | 1)
+#define IOSF_OP_READ_SSUS 0x10
+#define IOSF_OP_WRITE_SSUS (IOSF_OP_READ_SSUS | 1)
+#define IOSF_OP_READ_CCU 0x06
+#define IOSF_OP_WRITE_CCU (IOSF_OP_READ_CCU | 1)
+
+/*
+ * BUNIT Registers.
+ */
+
+#define BNOCACHE 0x23
+/* BMBOUND has a 128MiB granularity. Highest address is 0xf8000000. */
+#define BUNIT_BMBOUND 0x25
+/* BMBOUND_HI describes the available ram above 4GiB. It has a
+ * 256MiB granularity. Physical address bits 35:28 are compared with 31:24
+ * bits in the BMBOUND_HI register. Also note that since BMBOUND has 128MiB
+ * granularity care needs to be taken with the e820 map to account for a hole
+ * in the ram. */
+#define BUNIT_BMBOUND_HI 0x26
+#define BUNIT_MMCONF_REG 0x27
+/* The SMMRR registers define the SMM region in MiB granularity. */
+#define BUNIT_SMRCP 0x2b
+#define BUNIT_SMRRAC 0x2c
+#define BUNIT_SMRWAC 0x2d
+#define BUNIT_SMRRL 0x2e
+#define BUNIT_SMRRH 0x2f
+# define BUNIT_SMRR_ENABLE (1 << 31)
+
+/* SA ID bits. */
+#define SAI_IA_UNTRUSTED (1 << 0)
+#define SAI_IA_SMM (1 << 2)
+#define SAI_IA_BOOT (1 << 4)
+
+/*
+ * DUNIT Registers.
+ */
+
+#define DRP 0x00
+# define DRP_DIMM0_RANK0_EN (0x01 << 0)
+# define DRP_DIMM0_RANK1_EN (0x01 << 1)
+# define DRP_DIMM1_RANK0_EN (0x01 << 2)
+# define DRP_DIMM1_RANK1_EN (0x01 << 3)
+# define DRP_RANK_MASK (DRP_DIMM0_RANK0_EN | DRP_DIMM0_RANK1_EN | \
+ DRP_DIMM1_RANK0_EN | DRP_DIMM1_RANK1_EN)
+#define DTR0 0x01
+# define DTR0_SPEED_MASK 0x03
+# define DTR0_SPEED_800 0x00
+# define DTR0_SPEED_1066 0x01
+# define DTR0_SPEED_1333 0x02
+# define DTR0_SPEED_1600 0x03
+
+/*
+ * PUNIT Registers
+ */
+#define SB_BIOS_CONFIG 0x06
+# define SB_BIOS_CONFIG_ECC_EN (1 << 31)
+# define SB_BIOS_CONFIG_DUAL_CH_DIS (1 << 30)
+# define SB_BIOS_CONFIG_EFF_ECC (1 << 29)
+# define SB_BIOS_CONFIG_EFF_DUAL_CH_DIS (1 << 28)
+# define SB_BIOS_CONFIG_PERF_MODE (1 << 17)
+# define SB_BIOS_CONFIG_PDM_MODE (1 << 16)
+# define SB_BIOS_CONFIG_DDRIO_PWRGATE (1 << 8)
+# define SB_BIOS_CONFIG_GFX_TURBO_DIS (1 << 7)
+# define SB_BIOS_CONFIG_PS2_EN_VNN (1 << 3)
+# define SB_BIOS_CONFIG_PS2_EN_VCC (1 << 2)
+# define SB_BIOS_CONFIG_PCIE_PLLOFFOK (1 << 1)
+# define SB_BIOS_CONFIG_USB_CACHING_EN (1 << 0)
+#define BIOS_RESET_CPL 0x05
+# define BIOS_RESET_CPL_ALL_DONE (1 << 1)
+# define BIOS_RESET_CPL_RESET_DONE (1 << 0)
+#define PUNIT_PWRGT_CONTROL 0x60
+#define PUNIT_PWRGT_STATUS 0x61
+#define PUNIT_GPU_EC_VIRUS 0xd2
+
+#define PUNIT_SOC_POWER_BUDGET 0x02
+#define PUNIT_SOC_ENERGY_CREDIT 0x03
+#define PUNIT_PTMC 0x80
+#define PUNIT_GFXT 0x88
+#define PUNIT_VEDT 0x89
+#define PUNIT_ISPT 0x8c
+#define PUNIT_PTPS 0xb2
+#define PUNIT_TE_AUX0 0xb5
+#define PUNIT_TE_AUX1 0xb6
+#define PUNIT_TE_AUX2 0xb7
+#define PUNIT_TE_AUX3 0xb8
+#define PUNIT_TTE_VRIccMax 0xb9
+#define PUNIT_TTE_VRHot 0xba
+#define PUNIT_TTE_XXPROCHOT 0xbb
+#define PUNIT_TTE_SLM0 0xbc
+#define PUNIT_TTE_SLM1 0xbd
+#define PUNIT_TTE_SWT 0xbf
+
+/*
+ * LPSS Registers
+ */
+#define LPSS_SIO_DMA1_CTL 0x280
+#define LPSS_I2C1_CTL 0x288
+#define LPSS_I2C2_CTL 0x290
+#define LPSS_I2C3_CTL 0x298
+#define LPSS_I2C4_CTL 0x2a0
+#define LPSS_I2C5_CTL 0x2a8
+#define LPSS_I2C6_CTL 0x2b0
+#define LPSS_I2C7_CTL 0x2b8
+#define LPSS_SIO_DMA2_CTL 0x240
+#define LPSS_PWM1_CTL 0x248
+#define LPSS_PWM2_CTL 0x250
+#define LPSS_HSUART1_CTL 0x258
+#define LPSS_HSUART2_CTL 0x260
+#define LPSS_SPI_CTL 0x268
+# define LPSS_CTL_ACPI_INT_EN (1 << 21)
+# define LPSS_CTL_PCI_CFG_DIS (1 << 20)
+# define LPSS_CTL_SNOOP (1 << 18)
+# define LPSS_CTL_NOSNOOP (1 << 19)
+# define LPSS_CTL_PM_CAP_PRSNT (1 << 1)
+
+/*
+ * SCC Registers
+ */
+#define SCC_SD_CTL 0x504
+#define SCC_SDIO_CTL 0x508
+#define SCC_MMC_CTL 0x50c
+# define SCC_CTL_PCI_CFG_DIS (1 << 0)
+# define SCC_CTL_ACPI_INT_EN (1 << 1)
+
+/*
+ * CCU Registers
+ */
+
+#define PLT_CLK_CTRL_0 0x3c
+#define PLT_CLK_CTRL_1 0x40
+#define PLT_CLK_CTRL_2 0x44
+#define PLT_CLK_CTRL_3 0x48
+#define PLT_CLK_CTRL_4 0x4c
+#define PLT_CLK_CTRL_5 0x50
+# define PLT_CLK_CTRL_19P2MHZ_FREQ (0 << 1)
+# define PLT_CLK_CTRL_25MHZ_FREQ (1 << 1)
+# define PLT_CLK_CTRL_SELECT_FREQ (1 << 0)
+
+/*
+ * USBPHY Registers
+ */
+#define USBPHY_COMPBG 0x7f04
+#define USBPHY_PER_PORT_LANE0 0x4100
+#define USBPHY_PER_PORT_RCOMP_HS_PULLUP0 0x4122
+#define USBPHY_PER_PORT_LANE1 0x4200
+#define USBPHY_PER_PORT_RCOMP_HS_PULLUP1 0x4222
+#define USBPHY_PER_PORT_LANE2 0x4300
+#define USBPHY_PER_PORT_RCOMP_HS_PULLUP2 0x4322
+#define USBPHY_PER_PORT_LANE3 0x4400
+#define USBPHY_PER_PORT_RCOMP_HS_PULLUP3 0x4422
+
+/*
+ * USHPHY Registers
+ */
+#define USHPHY_CDN_PLL_CONTROL 0x03c0
+#define USHPHY_CDN_VCO_START_CAL_POINT 0x0054
+#define USHPHY_CCDRLF 0x8040
+#define USHPHY_PEAKING_AMP_CONFIG_DIAG 0x80a8
+#define USHPHY_OFFSET_COR_CONFIG_DIAG 0x80b0
+#define USHPHY_VGA_GAIN_CONFIG_DIAG 0x8080
+#define USHPHY_REE_DAC_CONTROL 0x80b8
+#define USHPHY_CDN_U1_POWER_STATE_DEF 0x0000
+
+/*
+ * LPE Registers
+ */
+#define LPE_PCICFGCTR1 0x0500
+# define LPE_PCICFGCTR1_PCI_CFG_DIS (1 << 0)
+# define LPE_PCICFGCTR1_ACPI_INT_EN (1 << 1)
+
+#endif /* _BAYTRAIL_IOSF_H_ */
diff --git a/src/soc/intel/braswell/include/soc/irq.h b/src/soc/intel/braswell/include/soc/irq.h
new file mode 100644
index 0000000000..34b3f7d995
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/irq.h
@@ -0,0 +1,164 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_IRQ_H_
+#define _BAYTRAIL_IRQ_H_
+
+#define PIRQA_APIC_IRQ 16
+#define PIRQB_APIC_IRQ 17
+#define PIRQC_APIC_IRQ 18
+#define PIRQD_APIC_IRQ 19
+#define PIRQE_APIC_IRQ 20
+#define PIRQF_APIC_IRQ 21
+#define PIRQG_APIC_IRQ 22
+#define PIRQH_APIC_IRQ 23
+/* The below IRQs are for when devices are in ACPI mode. Active low. */
+#define LPE_DMA0_IRQ 24
+#define LPE_DMA1_IRQ 25
+#define LPE_SSP0_IRQ 26
+#define LPE_SSP1_IRQ 27
+#define LPE_SSP2_IRQ 28
+#define LPE_IPC2HOST_IRQ 29
+#define LPSS_I2C1_IRQ 32
+#define LPSS_I2C2_IRQ 33
+#define LPSS_I2C3_IRQ 34
+#define LPSS_I2C4_IRQ 35
+#define LPSS_I2C5_IRQ 36
+#define LPSS_I2C6_IRQ 37
+#define LPSS_I2C7_IRQ 38
+#define LPSS_HSUART1_IRQ 39
+#define LPSS_HSUART2_IRQ 40
+#define LPSS_SPI_IRQ 41
+#define LPSS_DMA1_IRQ 42
+#define LPSS_DMA2_IRQ 43
+#define SCC_EMMC_IRQ 44
+#define SCC_SDIO_IRQ 46
+#define SCC_SD_IRQ 47
+#define GPIO_NC_IRQ 48
+#define GPIO_SC_IRQ 49
+#define GPIO_SUS_IRQ 50
+/* GPIO direct / dedicated IRQs. */
+#define GPIO_S0_DED_IRQ_0 51
+#define GPIO_S0_DED_IRQ_1 52
+#define GPIO_S0_DED_IRQ_2 53
+#define GPIO_S0_DED_IRQ_3 54
+#define GPIO_S0_DED_IRQ_4 55
+#define GPIO_S0_DED_IRQ_5 56
+#define GPIO_S0_DED_IRQ_6 57
+#define GPIO_S0_DED_IRQ_7 58
+#define GPIO_S0_DED_IRQ_8 59
+#define GPIO_S0_DED_IRQ_9 60
+#define GPIO_S0_DED_IRQ_10 61
+#define GPIO_S0_DED_IRQ_11 62
+#define GPIO_S0_DED_IRQ_12 63
+#define GPIO_S0_DED_IRQ_13 64
+#define GPIO_S0_DED_IRQ_14 65
+#define GPIO_S0_DED_IRQ_15 66
+#define GPIO_S5_DED_IRQ_0 67
+#define GPIO_S5_DED_IRQ_1 68
+#define GPIO_S5_DED_IRQ_2 69
+#define GPIO_S5_DED_IRQ_3 70
+#define GPIO_S5_DED_IRQ_4 71
+#define GPIO_S5_DED_IRQ_5 72
+#define GPIO_S5_DED_IRQ_6 73
+#define GPIO_S5_DED_IRQ_7 74
+#define GPIO_S5_DED_IRQ_8 75
+#define GPIO_S5_DED_IRQ_9 76
+#define GPIO_S5_DED_IRQ_10 77
+#define GPIO_S5_DED_IRQ_11 78
+#define GPIO_S5_DED_IRQ_12 79
+#define GPIO_S5_DED_IRQ_13 80
+#define GPIO_S5_DED_IRQ_14 81
+#define GPIO_S5_DED_IRQ_15 82
+/* DIRQs - Two levels of expansion to evaluate to numeric constants for ASL. */
+#define _GPIO_S0_DED_IRQ(slot) GPIO_S0_DED_IRQ_##slot
+#define _GPIO_S5_DED_IRQ(slot) GPIO_S5_DED_IRQ_##slot
+#define GPIO_S0_DED_IRQ(slot) _GPIO_S0_DED_IRQ(slot)
+#define GPIO_S5_DED_IRQ(slot) _GPIO_S5_DED_IRQ(slot)
+
+/* PIC IRQ settings. */
+#define PIRQ_PIC_IRQDISABLE 0x0
+#define PIRQ_PIC_IRQ3 0x3
+#define PIRQ_PIC_IRQ4 0x4
+#define PIRQ_PIC_IRQ5 0x5
+#define PIRQ_PIC_IRQ6 0x6
+#define PIRQ_PIC_IRQ7 0x7
+#define PIRQ_PIC_IRQ9 0x9
+#define PIRQ_PIC_IRQ10 0xa
+#define PIRQ_PIC_IRQ11 0xb
+#define PIRQ_PIC_IRQ12 0xc
+#define PIRQ_PIC_IRQ14 0xe
+#define PIRQ_PIC_IRQ15 0xf
+
+/* Overloaded term, but these values determine the per device route. */
+#define PIRQA 0
+#define PIRQB 1
+#define PIRQC 2
+#define PIRQD 3
+#define PIRQE 4
+#define PIRQF 5
+#define PIRQG 6
+#define PIRQH 7
+
+/* These registers live behind the ILB_BASE_ADDRESS */
+#define ACTL 0x00
+# define SCIS_MASK 0x07
+# define SCIS_IRQ9 0x00
+# define SCIS_IRQ10 0x01
+# define SCIS_IRQ11 0x02
+# define SCIS_IRQ20 0x04
+# define SCIS_IRQ21 0x05
+# define SCIS_IRQ22 0x06
+# define SCIS_IRQ23 0x07
+
+/* In each mainboard directory there should exist a header file irqroute.h that
+ * defines the PCI_DEV_PIRQ_ROUTES and PIRQ_PIC_ROUTES macros which
+ * consist of PCI_DEV_PIRQ_ROUTE and PIRQ_PIC entries. */
+
+#if !defined(__ASSEMBLER__) && !defined(__ACPI__)
+#include <stdint.h>
+
+#define NUM_IR_DEVS 32
+#define NUM_PIRQS 8
+
+struct baytrail_irq_route {
+ /* Per device configuration. */
+ uint16_t pcidev[NUM_IR_DEVS];
+ /* Route path for each internal PIRQx in PIC mode. */
+ uint8_t pic[NUM_PIRQS];
+};
+
+extern const struct baytrail_irq_route global_baytrail_irq_route;
+
+#define DEFINE_IRQ_ROUTES \
+ const struct baytrail_irq_route global_baytrail_irq_route = { \
+ .pcidev = { PCI_DEV_PIRQ_ROUTES, }, \
+ .pic = { PIRQ_PIC_ROUTES, }, \
+ }
+
+#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \
+ [dev_] = ((PIRQ ## d_) << 12) | ((PIRQ ## c_) << 8) | \
+ ((PIRQ ## b_) << 4) | ((PIRQ ## a_) << 0)
+
+#define PIRQ_PIC(pirq_, pic_irq_) \
+ [PIRQ ## pirq_] = PIRQ_PIC_IRQ ## pic_irq_
+
+#endif /* !defined(__ASSEMBLER__) && !defined(__ACPI__) */
+
+#endif /* _BAYTRAIL_IRQ_H_ */
diff --git a/src/soc/intel/braswell/include/soc/lpc.h b/src/soc/intel/braswell/include/soc/lpc.h
new file mode 100644
index 0000000000..2f6256cc41
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/lpc.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_LPC_H_
+#define _BAYTRAIL_LPC_H_
+
+/* PCI config registers in LPC bridge. */
+#define REVID 0x08
+#define ABASE 0x40
+#define PBASE 0x44
+#define GBASE 0x48
+#define IOBASE 0x4c
+#define IBASE 0x50
+#define SBASE 0x54
+#define MPBASE 0x58
+#define PUBASE 0x5c
+#define UART_CONT 0x80
+#define RCBA 0xf0
+
+
+#define RID_A_STEPPING_START 1
+#define RID_B_STEPPING_START 5
+#define RID_C_STEPPING_START 0xe
+enum baytrail_stepping {
+ STEP_A0,
+ STEP_A1,
+ STEP_B0,
+ STEP_B1,
+ STEP_B2,
+ STEP_B3,
+ STEP_C0,
+};
+
+/* Registers behind the RCBA_BASE_ADDRESS bar. */
+#define GCS 0x00
+# define BILD (1 << 0)
+
+#endif /* _BAYTRAIL_LPC_H_ */
diff --git a/src/soc/intel/braswell/include/soc/mrc_wrapper.h b/src/soc/intel/braswell/include/soc/mrc_wrapper.h
new file mode 100644
index 0000000000..355dce0706
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/mrc_wrapper.h
@@ -0,0 +1,107 @@
+/*
+ * MRC wrapper definitions
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * 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 Google Inc. 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 GOOGLE INC 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.
+ */
+#ifndef _MRC_WRAPPER_H_
+#define _MRC_WRAPPER_H_
+
+#define MRC_PARAMS_VER 5
+
+#define NUM_CHANNELS 2
+
+/* Provide generic x86 calling conventions. */
+#define ABI_X86 __attribute((regparm(0)))
+
+enum {
+ DRAM_INFO_SPD_SMBUS, /* Use the typical SPD smbus access. */
+ DRAM_INFO_SPD_MEM, /* SPD info in memory. */
+ DRAM_INFO_DETAILED, /* Timing info not in SPD format. */
+};
+
+enum dram_type {
+ DRAM_DDR3,
+ DRAM_DDR3L,
+ DRAM_LPDDR3,
+};
+
+/* Errors returned by the MRC wrapper. */
+enum mrc_wrapper_error {
+ INVALID_VER = -1,
+ INVALID_DRAM_TYPE = -2,
+ INVALID_SLEEP_MODE = -3,
+ PLATFORM_SETTINGS_FAIL = -4,
+ DIMM_DETECTION_FAILURE = -5,
+ MEMORY_CONFIG_FAILURE = -6,
+ INVALID_CPU_ODT_SETTING = -7,
+ INVALID_DRAM_ODT_SETTING = -8,
+};
+
+struct mrc_mainboard_params {
+ int dram_type;
+ int dram_info_location; /* DRAM_INFO_* */
+ int dram_is_slotted; /* mobo has DRAM slots. */
+ /*
+ * The below ODT settings are only honored when !dram_is_slotted.
+ * Additionally, weaker_odt_settings being non-zero causes
+ * cpu_odt_value to not be honored as weaker_odt_settings have a
+ * special training path.
+ */
+ int weaker_odt_settings;
+ /* Allowed settings: 60, 80, 100, 120, and 150. */
+ int cpu_odt_value;
+ /* Allowed settings: 60 and 120. */
+ int dram_odt_value;
+ int spd_addrs[NUM_CHANNELS];
+ void *dram_data[NUM_CHANNELS]; /* SPD or Timing specific data. */
+} __attribute__((packed));
+
+struct mrc_params {
+ /* Mainboard Inputs */
+ int version;
+
+ struct mrc_mainboard_params mainboard;
+
+ void ABI_X86 (*console_out)(unsigned char byte);
+
+ int prev_sleep_state;
+
+ int saved_data_size;
+ const void *saved_data;
+
+ int txe_size_mb; /* TXE memory size in megabytes. */
+ int rmt_enabled; /* Enable RMT training + prints. */
+ int io_hole_mb; /* Size of IO hole in MiB. */
+
+ /* Outputs */
+ void *txe_base_address;
+ int data_to_save_size;
+ void *data_to_save;
+} __attribute__((packed));
+
+/* Call into wrapper. */
+typedef int ABI_X86 (*mrc_wrapper_entry_t)(struct mrc_params *);
+
+#endif /* _MRC_WRAPPER_H_ */
diff --git a/src/soc/intel/braswell/include/soc/msr.h b/src/soc/intel/braswell/include/soc/msr.h
new file mode 100644
index 0000000000..47b95434e9
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/msr.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_MSR_H_
+#define _BAYTRAIL_MSR_H_
+
+#define MSR_IA32_PLATFORM_ID 0x17
+#define MSR_BSEL_CR_OVERCLOCK_CONTROL 0xcd
+#define MSR_PLATFORM_INFO 0xce
+#define MSR_PMG_CST_CONFIG_CONTROL 0xe2
+#define SINGLE_PCTL (1 << 11)
+#define MSR_POWER_MISC 0x120
+#define ENABLE_ULFM_AUTOCM_MASK (1 << 2)
+#define ENABLE_INDP_AUTOCM_MASK (1 << 3)
+#define MSR_IA32_PERF_CTL 0x199
+#define MSR_IA32_MISC_ENABLES 0x1a0
+#define MSR_POWER_CTL 0x1fc
+#define MSR_PKG_POWER_SKU_UNIT 0x606
+#define MSR_PKG_POWER_LIMIT 0x610
+#define MSR_PP1_POWER_LIMIT 0x638
+#define MSR_IACORE_RATIOS 0x66a
+#define MSR_IACORE_TURBO_RATIOS 0x66c
+#define MSR_IACORE_VIDS 0x66b
+#define MSR_IACORE_TURBO_VIDS 0x66d
+#define MSR_PKG_TURBO_CFG1 0x670
+#define MSR_CPU_TURBO_WKLD_CFG1 0x671
+#define MSR_CPU_TURBO_WKLD_CFG2 0x672
+#define MSR_CPU_THERM_CFG1 0x673
+#define MSR_CPU_THERM_CFG2 0x674
+#define MSR_CPU_THERM_SENS_CFG 0x675
+
+/* Read BCLK from MSR */
+unsigned bus_freq_khz(void);
+
+#endif /* _BAYTRAIL_MSR_H_ */
diff --git a/src/soc/intel/braswell/include/soc/nvs.h b/src/soc/intel/braswell/include/soc/nvs.h
new file mode 100644
index 0000000000..1ba30d57af
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/nvs.h
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2011 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_NVS_H_
+#define _BAYTRAIL_NVS_H_
+
+#include <vendorcode/google/chromeos/gnvs.h>
+#include <soc/device_nvs.h>
+
+typedef struct {
+ /* Miscellaneous */
+ u16 osys; /* 0x00 - Operating System */
+ u8 smif; /* 0x02 - SMI function call ("TRAP") */
+ u8 prm0; /* 0x03 - SMI function call parameter */
+ u8 prm1; /* 0x04 - SMI function call parameter */
+ u8 scif; /* 0x05 - SCI function call (via _L00) */
+ u8 prm2; /* 0x06 - SCI function call parameter */
+ u8 prm3; /* 0x07 - SCI function call parameter */
+ u8 lckf; /* 0x08 - Global Lock function for EC */
+ u8 prm4; /* 0x09 - Lock function parameter */
+ u8 prm5; /* 0x0a - Lock function parameter */
+ u32 p80d; /* 0x0b - Debug port (IO 0x80) value */
+ u8 lids; /* 0x0f - LID state (open = 1) */
+ u8 pwrs; /* 0x10 - Power state (AC = 1) */
+ u8 pcnt; /* 0x11 - Processor Count */
+ u8 tpmp; /* 0x12 - TPM Present and Enabled */
+ u8 tlvl; /* 0x13 - Throttle Level */
+ u8 ppcm; /* 0x14 - Maximum P-state usable by OS */
+ u32 pm1i; /* 0x15 - System Wake Source - PM1 Index */
+ u8 rsvd1[7];
+
+ /* Device Config */
+ u8 s5u0; /* 0x20 - Enable USB0 in S5 */
+ u8 s5u1; /* 0x21 - Enable USB1 in S5 */
+ u8 s3u0; /* 0x22 - Enable USB0 in S3 */
+ u8 s3u1; /* 0x23 - Enable USB1 in S3 */
+ u8 tact; /* 0x24 - Thermal Active trip point */
+ u8 tpsv; /* 0x25 - Thermal Passive trip point */
+ u8 tcrt; /* 0x26 - Thermal Critical trip point */
+ u8 dpte; /* 0x27 - Enable DPTF */
+ u8 rsvd2[8];
+
+ /* Base Addresses */
+ u32 obsolete_cmem; /* 0x30 - CBMEM TOC */
+ u32 tolm; /* 0x34 - Top of Low Memory */
+ u32 cbmc; /* 0x38 - coreboot memconsole */
+ u8 rsvd3[196];
+
+ /* ChromeOS specific (0x100-0xfff)*/
+ chromeos_acpi_t chromeos;
+
+ /* Baytrail LPSS (0x1000) */
+ device_nvs_t dev;
+} __attribute__((packed)) global_nvs_t;
+
+#ifdef __SMM__
+/* Used in SMM to find the ACPI GNVS address */
+global_nvs_t *smm_get_gnvs(void);
+#endif
+
+#endif /* _BAYTRAIL_NVS_H_ */
diff --git a/src/soc/intel/braswell/include/soc/pattrs.h b/src/soc/intel/braswell/include/soc/pattrs.h
new file mode 100644
index 0000000000..81df73e6ff
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/pattrs.h
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _PATTRS_H_
+#define _PATTRS_H_
+
+#include <stdint.h>
+#include <cpu/x86/msr.h>
+
+enum {
+ IACORE_MIN,
+ IACORE_LFM,
+ IACORE_MAX,
+ IACORE_TURBO,
+ IACORE_END
+};
+
+/* The pattrs structure is a common place to stash pertinent information
+ * about the processor or platform. Instead of going to the source (msrs, cpuid)
+ * every time an attribute is needed use the pattrs structure.
+ */
+struct pattrs {
+ msr_t platform_id;
+ msr_t platform_info;
+ int iacore_ratios[IACORE_END];
+ int iacore_vids[IACORE_END];
+ uint32_t cpuid;
+ int revid;
+ int stepping;
+ const void *microcode_patch;
+ int address_bits;
+ int num_cpus;
+ unsigned bclk_khz;
+};
+
+/* This is just to hide the abstraction w/o relying on how the underlying
+ * storage is allocated. */
+#define PATTRS_GLOB_NAME __global_pattrs
+#define DEFINE_PATTRS struct pattrs PATTRS_GLOB_NAME
+extern DEFINE_PATTRS;
+
+static inline const struct pattrs *pattrs_get(void)
+{
+ return &PATTRS_GLOB_NAME;
+}
+
+
+#endif /* _PATTRS_H_ */
diff --git a/src/soc/intel/braswell/include/soc/pci_devs.h b/src/soc/intel/braswell/include/soc/pci_devs.h
new file mode 100644
index 0000000000..b3fdce234a
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/pci_devs.h
@@ -0,0 +1,155 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_PCI_DEVS_H_
+#define _BAYTRAIL_PCI_DEVS_H_
+
+/* All these devices live on bus 0 with the associated device and function */
+
+/* SoC transaction router */
+#define SOC_DEV 0x0
+#define SOC_FUNC 0
+# define SOC_DEVID 0x0f00
+
+/* Graphics and Display */
+#define GFX_DEV 0x2
+#define GFX_FUNC 0
+# define GFX_DEVID 0x0f31
+
+/* SDIO Port */
+#define SDIO_DEV 0x11
+#define SDIO_FUNC 0
+# define SDIO_DEVID 0x0f15
+
+/* SD Port */
+#define SD_DEV 0x12
+#define SD_FUNC 0
+# define SD_DEVID 0x0f16
+
+/* SATA */
+#define SATA_DEV 0x13
+#define SATA_FUNC 0
+#define IDE1_DEVID 0x0f20
+#define IDE2_DEVID 0x0f21
+#define AHCI1_DEVID 0x0f22
+#define AHCI2_DEVID 0x0f23
+
+/* xHCI */
+#define XHCI_DEV 0x14
+#define XHCI_FUNC 0
+# define XHCI_DEVID 0x0f35
+
+/* LPE Audio */
+#define LPE_DEV 0x15
+#define LPE_FUNC 0
+# define LPE_DEVID 0x0f28
+
+/* MMC Port */
+#define MMC_DEV 0x17
+#define MMC_FUNC 0
+# define MMC_DEVID 0x0f50
+
+/* Serial IO 1 */
+#define SIO1_DEV 0x18
+# define SIO_DMA1_DEV SIO1_DEV
+# define SIO_DMA1_FUNC 0
+# define SIO_DMA1_DEVID 0x0f40
+# define I2C1_DEV SIO1_DEV
+# define I2C1_FUNC 1
+# define I2C1_DEVID 0x0f41
+# define I2C2_DEV SIO1_DEV
+# define I2C2_FUNC 2
+# define I2C2_DEVID 0x0f42
+# define I2C3_DEV SIO1_DEV
+# define I2C3_FUNC 3
+# define I2C3_DEVID 0x0f43
+# define I2C4_DEV SIO1_DEV
+# define I2C4_FUNC 4
+# define I2C4_DEVID 0x0f44
+# define I2C5_DEV SIO1_DEV
+# define I2C5_FUNC 5
+# define I2C5_DEVID 0x0f45
+# define I2C6_DEV SIO1_DEV
+# define I2C6_FUNC 6
+# define I2C6_DEVID 0x0f46
+# define I2C7_DEV SIO1_DEV
+# define I2C7_FUNC 7
+# define I2C7_DEVID 0x0f47
+
+/* Trusted Execution Engine */
+#define TXE_DEV 0x1a
+#define TXE_FUNC 0
+# define TXE_DEVID 0x0f18
+
+/* HD Audio */
+#define HDA_DEV 0x1b
+#define HDA_FUNC 0
+# define HDA_DEVID 0x0f04
+
+/* PCIe Ports */
+#define PCIE_DEV 0x1c
+# define PCIE_PORT1_DEV PCIE_DEV
+# define PCIE_PORT1_FUNC 0
+# define PCIE_PORT1_DEVID 0x0f48
+# define PCIE_PORT2_DEV PCIE_DEV
+# define PCIE_PORT2_FUNC 1
+# define PCIE_PORT2_DEVID 0x0f4a
+# define PCIE_PORT3_DEV PCIE_DEV
+# define PCIE_PORT3_FUNC 2
+# define PCIE_PORT3_DEVID 0x0f4c
+# define PCIE_PORT4_DEV PCIE_DEV
+# define PCIE_PORT4_FUNC 3
+# define PCIE_PORT4_DEVID 0x0f4e
+
+/* EHCI */
+#define EHCI_DEV 0x1d
+#define EHCI_FUNC 0
+# define EHCI_DEVID 0x0f34
+
+/* Serial IO 2 */
+#define SIO2_DEV 0x1e
+# define SIO_DMA2_DEV SIO2_DEV
+# define SIO_DMA2_FUNC 0
+# define SIO_DMA2_DEVID 0x0f06
+# define PWM1_DEV SIO2_DEV
+# define PWM1_FUNC 1
+# define PWM1_DEVID 0x0f08
+# define PWM2_DEV SIO2_DEV
+# define PWM2_FUNC 2
+# define PWM2_DEVID 0x0f09
+# define HSUART1_DEV SIO2_DEV
+# define HSUART1_FUNC 3
+# define HSUART1_DEVID 0x0f0a
+# define HSUART2_DEV SIO2_DEV
+# define HSUART2_FUNC 4
+# define HSUART2_DEVID 0x0f0c
+# define SPI_DEV SIO2_DEV
+# define SPI_FUNC 5
+# define SPI_DEVID 0xf0e
+
+/* Platform Controller Unit */
+#define PCU_DEV 0x1f
+# define LPC_DEV PCU_DEV
+# define LPC_FUNC 0
+# define LPC_DEVID 0x0f1c
+# define SMBUS_DEV PCU_DEV
+# define SMBUS_FUNC 3
+# define SMBUS_DEVID 0x0f12
+
+#endif /* _BAYTRAIL_PCI_DEVS_H_ */
diff --git a/src/soc/intel/braswell/include/soc/pcie.h b/src/soc/intel/braswell/include/soc/pcie.h
new file mode 100644
index 0000000000..92ca3c8d7f
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/pcie.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_PCIE_H_
+#define _BAYTRAIL_PCIE_H_
+
+/* PCIe root port config space registers. */
+#define XCAP 0x40
+# define SI (1 << 24)
+#define DCAP 0x44
+# define MPS_MASK 0x7
+#define DCTL_DSTS 0x48
+# define URE (1 << 3)
+# define FEE (1 << 2)
+# define NFE (1 << 1)
+# define CEE (1 << 0)
+#define LCAP 0x4c
+# define L1EXIT_SHIFT 15
+# define L1EXIT_MASK (0x7 << L1EXIT_SHIFT)
+#define LCTL 0x50
+# define CCC (1 << 6)
+# define RL (1 << 5)
+# define LD (1 << 4)
+#define LSTS 0x52
+#define SLCAP 0x54
+# define SLN_SHIFT 19
+# define SLS_SHIFT 15
+# define SLV_SHIFT 7
+# define HPC (1 << 6)
+# define HPS (1 << 5)
+#define SLCTL_SLSTS 0x58
+# define PDS (1 << 22)
+#define DCAP2 0x64
+# define OBFFS (0x3 << 18)
+# define LTRMS (1 << 11)
+#define DSTS2 0x68
+# define OBFFEN (3 << 13)
+# define LTRME (1 << 10)
+# define CTD (1 << 4)
+#define CHCFG 0xd0
+# define UPSD (1 << 24)
+# define UNRS (1 << 15)
+# define UPRS (1 << 14)
+#define MPC2 0xd4
+# define IPF (1 << 11)
+# define LSTP (1 << 6)
+# define EOIFD (1 << 1)
+#define MPC 0xd8
+# define CCEL_SHIFT 15
+# define CCEL_MASK (0x7 << CCEL_SHIFT)
+#define RPPGEN 0xe0
+# define RPSCGEN (1 << 15)
+# define LCLKREQEN (1 << 13)
+# define BBCLKREQEN (1 << 12)
+# define SRDLCGEN (1 << 11)
+# define SRDBCGEN (1 << 10)
+# define RPDLCGEN (1 << 9)
+# define RPDBCGEN (1 << 8)
+#define PWRCTL 0xe8
+# define RPL1SQPOL (1 << 1)
+# define RPDTSQPOL (1 << 0)
+#define PHYCTL2_IOSFBCTL 0xf4
+# define PLL_OFF_EN (1 << 8)
+# define TDFT (3 << 14)
+# define TXCFGCHWAIT (3 << 12)
+# define SIID (3 << 26)
+#define STRPFUSECFG 0xfc
+# define LANECFG_SHIFT 14
+# define LANECFG_MASK (0x3 << LANECFG_SHIFT)
+#define AERCH 0x100
+#define NFTS 0x314
+#define L0SC 0x318
+#define CFG2 0x320
+# define CSREN (1 << 22)
+# define LATGC_SHIFT 6
+# define LATGC_MASK (0x7 << LATGC_SHIFT)
+#define PCIEDBG 0x324
+# define SPCE (1 << 5)
+#define PCIESTS1 0x328
+#define PCIEALC 0x338
+#define RTP 0x33c
+#define PHYCTL4 0x408
+# define SQDIS (1 << 27)
+
+#define PCIE_ROOT_PORT_COUNT 4
+#endif /* _BAYTRAIL_PCIE_H_ */
diff --git a/src/soc/intel/braswell/include/soc/pmc.h b/src/soc/intel/braswell/include/soc/pmc.h
new file mode 100644
index 0000000000..1af7ab86ce
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/pmc.h
@@ -0,0 +1,303 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_PMC_H_
+#define _BAYTRAIL_PMC_H_
+
+
+#define IOCOM1 0x3f8
+
+/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
+#define PRSTS 0x00
+# define PMC_WDT_STS (1 << 15)
+# define SEC_GBLRST_STS (1 << 7)
+# define SEC_WDT_STS (1 << 6)
+# define WOL_OVR_WK_STS (1 << 5)
+# define PMC_WAKE_STS (1 << 4)
+#define PMC_CFG 0x08
+# define SPS (1 << 5)
+# define NO_REBOOT (1 << 4)
+# define SX_ENT_TO_EN (1 << 3)
+# define TIMING_T581_SHIFT (0)
+# define TIMING_T581_MASK (3 << TIMING_T581_SHIFT)
+# define TIMING_T581_10uS (0 << TIMING_T581_SHIFT)
+# define TIMING_T581_100uS (1 << TIMING_T581_SHIFT)
+# define TIMING_T581_1mS (2 << TIMING_T581_SHIFT)
+# define TIMING_T581_10mS (3 << TIMING_T581_SHIFT)
+#define VLV_PM_STS 0x0c
+# define PMC_MSG_FULL_STS (1 << 24)
+# define PMC_MSG_4_FULL_STS (1 << 23)
+# define PMC_MSG_3_FULL_STS (1 << 22)
+# define PMC_MSG_2_FULL_STS (1 << 21)
+# define PMC_MSG_1_FULL_STS (1 << 20)
+# define CODE_REQ (1 << 8)
+# define HPR_ENT_TO (1 << 2)
+# define SX_ENT_TO (1 << 1)
+#define GEN_PMCON1 0x20
+# define UART_EN (1 << 24)
+# define DISB (1 << 23)
+# define MEM_SR (1 << 21)
+# define SRS (1 << 20)
+# define CTS (1 << 19)
+# define MS4V (1 << 18)
+# define PWR_FLR (1 << 16)
+# define PME_B0_S5_DIS (1 << 15)
+# define SUS_PWR_FLR (1 << 14)
+# define WOL_EN_OVRD (1 << 13)
+# define DIS_SLP_X_STRCH_SUS_UP (1 << 12)
+# define GEN_RST_STS (1 << 9)
+# define RPS (1 << 2)
+# define AFTERG3_EN (1 << 0)
+#define GEN_PMCON2 0x24
+# define SLPSX_STR_POL_LOCK (1 << 18)
+# define BIOS_PCI_EXP_EN (1 << 10)
+# define PWRBTN_LVL (1 << 9)
+# define SMI_LOCK (1 << 4)
+#define ETR 0x48
+# define CF9LOCK (1 << 31)
+# define LTR_DEF (1 << 22)
+# define IGNORE_HPET (1 << 21)
+# define CF9GR (1 << 20)
+# define CWORWRE (1 << 18)
+#define FUNC_DIS 0x34
+# define SIO_DMA2_DIS (1 << 0)
+# define PWM1_DIS (1 << 1)
+# define PWM2_DIS (1 << 2)
+# define HSUART1_DIS (1 << 3)
+# define HSUART2_DIS (1 << 4)
+# define SPI_DIS (1 << 5)
+# define SDIO_DIS (1 << 9)
+# define SD_DIS (1 << 10)
+# define MMC_DIS (1 << 11)
+# define HDA_DIS (1 << 12)
+# define LPE_DIS (1 << 13)
+# define OTG_DIS (1 << 14)
+# define XHCI_DIS (1 << 15)
+# define SATA_DIS (1 << 17)
+# define EHCI_DIS (1 << 18)
+# define TXE_DIS (1 << 19)
+# define PCIE_PORT1_DIS (1 << 20)
+# define PCIE_PORT2_DIS (1 << 21)
+# define PCIE_PORT3_DIS (1 << 22)
+# define PCIE_PORT4_DIS (1 << 23)
+# define SIO_DMA1_DIS (1 << 24)
+# define I2C1_DIS (1 << 25)
+# define I2C2_DIS (1 << 26)
+# define I2C3_DIS (1 << 27)
+# define I2C4_DIS (1 << 28)
+# define I2C5_DIS (1 << 29)
+# define I2C6_DIS (1 << 30)
+# define I2C7_DIS (1 << 31)
+#define FUNC_DIS2 0x38
+# define USH_SS_PHY_DIS (1 << 2)
+# define OTG_SS_PHY_DIS (1 << 1)
+# define SMBUS_DIS (1 << 0)
+#define GPIO_ROUT 0x58
+# define ROUTE_MASK 3
+# define ROUTE_NONE 0
+# define ROUTE_SMI 1
+# define ROUTE_SCI 2
+#define PLT_CLK_CTL_0 0x60
+#define PLT_CLK_CTL_1 0x64
+#define PLT_CLK_CTL_2 0x68
+#define PLT_CLK_CTL_3 0x6c
+#define PLT_CLK_CTL_4 0x70
+#define PLT_CLK_CTL_5 0x74
+# define CLK_FREQ_25MHZ (0x0 << 2)
+# define CLK_FREQ_19P2MHZ (0x1 << 2)
+# define CLK_CTL_D3_LPE (0x0 << 0)
+# define CLK_CTL_ON (0x1 << 0)
+# define CLK_CTL_OFF (0x2 << 0)
+#define PME_STS 0xc0
+#define GPE_LEVEL_EDGE 0xc4
+# define GPE_EDGE 0
+# define GPE_LEVEL 1
+#define GPE_POLARITY 0xc8
+# define GPE_ACTIVE_HIGH 1
+# define GPE_ACTIVE_LOW 0
+#define LOCK 0xcc
+
+/* IO Mapped registers behind ACPI_BASE_ADDRESS */
+#define PM1_STS 0x00
+#define WAK_STS (1 << 15)
+#define PCIEXPWAK_STS (1 << 14)
+#define USB_STS (1 << 13)
+#define PRBTNOR_STS (1 << 11)
+#define RTC_STS (1 << 10)
+#define PWRBTN_STS (1 << 8)
+#define GBL_STS (1 << 5)
+#define TMROF_STS (1 << 0)
+#define PM1_EN 0x02
+#define PCIEXPWAK_DIS (1 << 14)
+#define USB_WAKE_EN (1 << 13)
+#define RTC_EN (1 << 10)
+#define PWRBTN_EN (1 << 8)
+#define GBL_EN (1 << 5)
+#define TMROF_EN (1 << 0)
+#define PM1_CNT 0x04
+#define SLP_EN (1 << 13)
+#define SLP_TYP_SHIFT 10
+#define SLP_TYP (7 << SLP_TYP_SHIFT)
+#define SLP_TYP_S0 0
+#define SLP_TYP_S1 1
+#define SLP_TYP_S3 5
+#define SLP_TYP_S4 6
+#define SLP_TYP_S5 7
+#define GBL_RLS (1 << 2)
+#define BM_RLD (1 << 1)
+#define SCI_EN (1 << 0)
+#define PM1_TMR 0x08
+#define GPE0_STS 0x20
+#define CORE_GPIO_STS7 (1 << 31)
+#define CORE_GPIO_STS6 (1 << 30)
+#define CORE_GPIO_STS5 (1 << 29)
+#define CORE_GPIO_STS4 (1 << 28)
+#define CORE_GPIO_STS3 (1 << 27)
+#define CORE_GPIO_STS2 (1 << 26)
+#define CORE_GPIO_STS1 (1 << 25)
+#define CORE_GPIO_STS0 (1 << 24)
+#define SUS_GPIO_STS7 (1 << 23)
+#define SUS_GPIO_STS6 (1 << 22)
+#define SUS_GPIO_STS5 (1 << 21)
+#define SUS_GPIO_STS4 (1 << 20)
+#define SUS_GPIO_STS3 (1 << 19)
+#define SUS_GPIO_STS2 (1 << 18)
+#define SUS_GPIO_STS1 (1 << 17)
+#define SUS_GPIO_STS0 (1 << 16)
+#define PME_B0_STS (1 << 13)
+#define BATLOW_STS (1 << 10)
+#define PCI_EXP_STS (1 << 9)
+#define PCIE_WAKE3_STS (1 << 8)
+#define PCIE_WAKE2_STS (1 << 7)
+#define PCIE_WAKE1_STS (1 << 6)
+#define GUNIT_SCI_STS (1 << 5)
+#define PUNIT_SCI_STS (1 << 4)
+#define PCIE_WAKE0_STS (1 << 3)
+#define SWGPE_STS (1 << 2)
+#define HOT_PLUG_STS (1 << 1)
+#define GPE0_EN 0x28
+#define CORE_GPIO_EN7 (1 << 31)
+#define CORE_GPIO_EN6 (1 << 30)
+#define CORE_GPIO_EN5 (1 << 29)
+#define CORE_GPIO_EN4 (1 << 28)
+#define CORE_GPIO_EN3 (1 << 27)
+#define CORE_GPIO_EN2 (1 << 26)
+#define CORE_GPIO_EN1 (1 << 25)
+#define CORE_GPIO_EN0 (1 << 24)
+#define SUS_GPIO_EN7_BIT 23
+#define SUS_GPIO_EN7 (1 << SUS_GPIO_EN7_BIT)
+#define SUS_GPIO_EN6_BIT 22
+#define SUS_GPIO_EN6 (1 << SUS_GPIO_EN6_BIT)
+#define SUS_GPIO_EN5_BIT 21
+#define SUS_GPIO_EN5 (1 << SUS_GPIO_EN5_BIT)
+#define SUS_GPIO_EN4_BIT 20
+#define SUS_GPIO_EN4 (1 << SUS_GPIO_EN4_BIT)
+#define SUS_GPIO_EN3_BIT 19
+#define SUS_GPIO_EN3 (1 << SUS_GPIO_EN3_BIT)
+#define SUS_GPIO_EN2_BIT 18
+#define SUS_GPIO_EN2 (1 << SUS_GPIO_EN2_BIT)
+#define SUS_GPIO_EN1_BIT 17
+#define SUS_GPIO_EN1 (1 << SUS_GPIO_EN1_BIT)
+#define SUS_GPIO_EN0_BIT 16
+#define SUS_GPIO_EN0 (1 << SUS_GPIO_EN0_BIT)
+#define PME_B0_EN (1 << 13)
+#define BATLOW_EN (1 << 10)
+#define PCI_EXP_EN (1 << 9)
+#define PCIE_WAKE3_EN (1 << 8)
+#define PCIE_WAKE2_EN (1 << 7)
+#define PCIE_WAKE1_EN (1 << 6)
+#define PCIE_WAKE0_EN (1 << 3)
+#define SWGPE_EN (1 << 2)
+#define HOT_PLUG_EN (1 << 1)
+#define _ACPI_ENABLE_WAKE_SUS_GPIO(x) SUS_GPIO_EN##x##_BIT
+#define ACPI_ENABLE_WAKE_SUS_GPIO(x) _ACPI_ENABLE_WAKE_SUS_GPIO(x)
+#define SMI_EN 0x30
+#define INTEL_USB2_EN (1 << 18) // Intel-Specific USB2 SMI logic
+#define USB_EN (1 << 17) // Legacy USB2 SMI logic
+#define PERIODIC_EN (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define TCO_EN (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define BIOS_RLS (1 << 7) // asserts SCI on bit set
+#define SWSMI_TMR_EN (1 << 6) // start software smi timer on bit set
+#define APMC_EN (1 << 5) // Writes to APM_CNT cause SMI#
+#define SLP_SMI_EN (1 << 4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define BIOS_EN (1 << 2) // Assert SMI# on setting GBL_RLS bit
+#define EOS (1 << 1) // End of SMI (deassert SMI#)
+#define GBL_SMI_EN (1 << 0) // SMI# generation at all?
+#define SMI_STS 0x34
+#define ALT_GPIO_SMI 0x38
+#define UPRWC 0x3c
+# define UPRWC_WR_EN (1 << 1) // USB Per-Port Registers Write Enable
+#define GPE_CTRL 0x40
+#define PM2A_CNT_BLK 0x50
+#define TCO_RLD 0x60
+#define TCO_STS 0x64
+# define SECOND_TO_STS (1 << 17)
+# define TCO_TIMEOUT (1 << 3)
+#define TCO1_CNT 0x68
+# define TCO_LOCK (1 << 12)
+# define TCO_TMR_HALT (1 << 11)
+#define TCO_TMR 0x70
+
+/* I/O ports */
+#define RST_CNT 0xcf9
+# define FULL_RST (1 << 3)
+# define RST_CPU (1 << 2)
+# define SYS_RST (1 << 1)
+
+#if !defined(__ASSEMBLER__) && !defined(__ACPI__)
+
+/* 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;
+ uint32_t gpe0_en;
+ uint32_t tco_sts;
+ uint32_t prsts;
+ uint32_t gen_pmcon1;
+ uint32_t gen_pmcon2;
+} __attribute__((packed));
+
+/* Power Management Utility Functions. */
+uint16_t get_pmbase(void);
+uint32_t clear_smi_status(void);
+uint16_t clear_pm1_status(void);
+uint32_t clear_tco_status(void);
+uint32_t clear_gpe_status(void);
+uint32_t clear_alt_status(void);
+void clear_pmc_status(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);
+
+#if CONFIG_ELOG
+void southcluster_log_state(void);
+#else
+static inline void southcluster_log_state(void) {}
+#endif
+
+#endif /* !defined(__ASSEMBLER__) && !defined(__ACPI__) */
+
+#endif /* _BAYTRAIL_PMC_H_ */
diff --git a/src/soc/intel/braswell/include/soc/ramstage.h b/src/soc/intel/braswell/include/soc/ramstage.h
new file mode 100644
index 0000000000..0ed83bd1d4
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/ramstage.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_RAMSTAGE_H_
+#define _BAYTRAIL_RAMSTAGE_H_
+
+#include <device/device.h>
+#include <soc/intel/baytrail/chip.h>
+
+/* The baytrail_init_pre_device() function is called prior to device
+ * initialization, but it's after console and cbmem has been reinitialized. */
+void baytrail_init_pre_device(struct soc_intel_baytrail_config *config);
+void baytrail_init_cpus(device_t dev);
+void set_max_freq(void);
+void southcluster_enable_dev(device_t dev);
+#if CONFIG_HAVE_REFCODE_BLOB
+void baytrail_run_reference_code(void);
+#else
+static inline void baytrail_run_reference_code(void) {}
+#endif
+void baytrail_init_scc(void);
+void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index);
+
+extern struct pci_operations soc_pci_ops;
+
+#endif /* _BAYTRAIL_RAMSTAGE_H_ */
diff --git a/src/soc/intel/braswell/include/soc/reset.h b/src/soc/intel/braswell/include/soc/reset.h
new file mode 100644
index 0000000000..dbf0fd23cf
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/reset.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_RESET_H_
+#define _BAYTRAIL_RESET_H_
+#include <reset.h>
+
+/* Bay Trail has the following types of resets:
+ * - Soft reset (INIT# to cpu) - write 0x1 to I/O 0x92
+ * - Soft reset (INIT# to cpu)- write 0x4 to I/0 0xcf9
+ * - Cold reset (S0->S5->S0) - write 0xe to I/0 0xcf9
+ * - Warm reset (PMC_PLTRST# assertion) - write 0x6 to I/O 0xcf9
+ * - Global reset (S0->S5->S0 with TXE reset) - write 0x6 or 0xe to 0xcf9 but
+ * with ETR[20] set.
+ */
+
+void cold_reset(void);
+void warm_reset(void);
+
+#endif /* _BAYTRAIL_RESET_H_ */
diff --git a/src/soc/intel/braswell/include/soc/romstage.h b/src/soc/intel/braswell/include/soc/romstage.h
new file mode 100644
index 0000000000..f99a8e28bc
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/romstage.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_ROMSTAGE_H_
+#define _BAYTRAIL_ROMSTAGE_H_
+
+#if !defined(__PRE_RAM__)
+#error "Don't include romstage.h from a ramstage compilation unit!"
+#endif
+
+#include <stdint.h>
+#include <arch/cpu.h>
+#include <soc/mrc_wrapper.h>
+
+struct romstage_params {
+ unsigned long bist;
+ struct mrc_params *mrc_params;
+};
+
+void mainboard_romstage_entry(struct romstage_params *params);
+void romstage_common(struct romstage_params *params);
+void * asmlinkage romstage_main(unsigned long bist, uint32_t tsc_lo,
+ uint32_t tsc_high);
+void asmlinkage romstage_after_car(void);
+void raminit(struct mrc_params *mp, int prev_sleep_state);
+void gfx_init(void);
+void tco_disable(void);
+void punit_init(void);
+void set_max_freq(void);
+int early_spi_read_wpsr(u8 *sr);
+
+#if CONFIG_ENABLE_BUILTIN_COM1
+void byt_config_com1_and_enable(void);
+#else
+static inline void byt_config_com1_and_enable(void) { }
+#endif
+
+#endif /* _BAYTRAIL_ROMSTAGE_H_ */
diff --git a/src/soc/intel/braswell/include/soc/sata.h b/src/soc/intel/braswell/include/soc/sata.h
new file mode 100644
index 0000000000..7704c18f34
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/sata.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BAYTRAIL_SATA_H
+#define BAYTRAIL_SATA_H
+
+#define SATA_SIRI 0xa0
+#define SATA_SIRD 0xa4
+
+#endif
diff --git a/src/soc/intel/braswell/include/soc/smm.h b/src/soc/intel/braswell/include/soc/smm.h
new file mode 100644
index 0000000000..0d920fb642
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/smm.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_SMM_H_
+#define _BAYTRAIL_SMM_H_
+
+/* There is a bug in the order of Kconfig includes in that arch/x86/Kconfig
+ * is included after chipset code. This causes the chipset's Kconfig to be
+ * clobbered by the arch/x86/Kconfig if they have the same name. */
+static inline int smm_region_size(void)
+{
+ /* Make it 8MiB by default. */
+ if (CONFIG_SMM_TSEG_SIZE == 0)
+ return (8 << 20);
+ return CONFIG_SMM_TSEG_SIZE;
+}
+
+uintptr_t smm_region_start(void);
+
+#if !defined(__PRE_RAM__) && !defined(__SMM___)
+#include <stdint.h>
+void southcluster_smm_clear_state(void);
+void southcluster_smm_enable_smi(void);
+void southcluster_smm_save_param(int param, uint32_t data);
+#endif
+
+enum {
+ SMM_SAVE_PARAM_GPIO_ROUTE = 0,
+ SMM_SAVE_PARAM_PCIE_WAKE_ENABLE,
+ SMM_SAVE_PARAM_COUNT
+};
+
+#endif /* _BAYTRAIL_SMM_H_ */
diff --git a/src/soc/intel/braswell/include/soc/spi.h b/src/soc/intel/braswell/include/soc/spi.h
new file mode 100644
index 0000000000..ef71ad5a79
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/spi.h
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _BAYTRAIL_SPI_H_
+#define _BAYTRAIL_SPI_H_
+
+#include <stdint.h>
+
+/* These registers live behind SPI_BASE_ADDRESS. */
+#define HSFSTS 0x04
+#define FDATA0 0x10
+# define FLOCKDN (0x1 << 15)
+#define SSFS 0x90
+# define CYCLE_DONE_STATUS (0x1 << 2)
+# define FLASH_CYCLE_ERROR (0x1 << 3)
+#define SSFC 0x91
+# define SPI_CYCLE_GO (0x1 << 1)
+# define DATA_CYCLE (0x1 << 14)
+#define PREOP 0x94
+#define OPTYPE 0x96
+#define OPMENU0 0x98
+#define OPMENU1 0x9c
+#define LVSCC 0xc4
+# define VCL (0x1 << 23)
+# define EO(x) (((x) & 0xff) << 8)
+# define WG_1_BYTE (0x0 << 2)
+# define WG_64_BYTE (0x1 << 2)
+# define BES_256_BYTE (0x0 << 0)
+# define BES_4_KB (0x1 << 0)
+# define BES_8_KB (0x2 << 0)
+# define BES_64_KB (0x3 << 0)
+#define UVSCC 0xc8
+#define SCS 0xf8
+# define SMIWPEN (0x1 << 7)
+#define BCR 0xfc
+# define EISS (0x1 << 5)
+# define SRC_MASK (0x3 << 2)
+# define SRC_CACHE_NO_PREFETCH (0x0 << 2)
+# define SRC_NO_CACHE_NO_PREFETCH (0x1 << 2)
+# define SRC_CACHE_PREFETCH (0x2 << 2)
+# define BCR_LE (0x1 << 1)
+# define BCR_WPD (0x1 << 0)
+
+/*
+ * SPI lockdown configuration.
+ */
+struct spi_config {
+ uint16_t preop;
+ uint16_t optype;
+ uint32_t opmenu[2];
+ uint32_t lvscc;
+ uint32_t uvscc;
+};
+
+/* Return 0 on success < 0 on failure. */
+int mainboard_get_spi_config(struct spi_config *cfg);
+
+#endif /* _BAYTRAIL_SPI_H_ */
diff --git a/src/soc/intel/braswell/include/soc/xhci.h b/src/soc/intel/braswell/include/soc/xhci.h
new file mode 100644
index 0000000000..b317361c08
--- /dev/null
+++ b/src/soc/intel/braswell/include/soc/xhci.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BAYTRAIL_XHCI_H
+#define BAYTRAIL_XHCI_H
+
+/* XHCI PCI Registers */
+#define XHCI_PWR_CTL_STS 0x74
+#define XHCI_USB2PR 0xd0
+#define XHCI_USB2PRM 0xd4
+#define XHCI_USB3PR 0xd8
+#define XHCI_USB3PRM 0xdc
+#define XHCI_USB2PDO 0xe4
+#define XHCI_USB3PDO 0xe8
+
+/* XHCI Memory Registers */
+#define XHCI_USB3_PORTSC(port) (0x4e0 + (port * 0x10))
+# define XHCI_USB3_PORTSC_CHST (0x7f << 17)
+# define XHCI_USB3_PORTSC_WCE (1 << 25) /* Wake on Connect */
+# define XHCI_USB3_PORTSC_WDE (1 << 26) /* Wake on Disconnect */
+# define XHCI_USB3_PORTSC_WOE (1 << 27) /* Wake on Overcurrent */
+# define XHCI_USB3_PORTSC_WRC (1 << 19) /* Warm Reset Complete */
+# define XHCI_USB3_PORTSC_LWS (1 << 16) /* Link Write Strobe */
+# define XHCI_USB3_PORTSC_PED (1 << 1) /* Port Enabled/Disabled */
+# define XHCI_USB3_PORTSC_WPR (1 << 31) /* Warm Port Reset */
+# define XHCI_USB3_PORTSC_PLS (0xf << 5) /* Port Link State */
+# define XHCI_PLSR_DISABLED (4 << 5) /* Port is disabled */
+# define XHCI_PLSR_RXDETECT (5 << 5) /* Port is disconnected */
+# define XHCI_PLSR_POLLING (7 << 5) /* Port is polling */
+# define XHCI_PLSW_ENABLE (5 << 5) /* Enable port */
+
+/* The Fuse register is incorrect for Baytrail-M so use hardcoded values */
+#define BYTM_USB2_PORT_COUNT 4
+#define BYTM_USB2_PORT_MAP 0xf
+#define BYTM_USB3_PORT_COUNT 1
+#define BYTM_USB3_PORT_MAP 0x1
+
+#define XHCI_RESET_TIMEOUT 100000 /* 100ms */
+
+#endif /* BAYTRAIL_XHCI_H */
diff --git a/src/soc/intel/braswell/iosf.c b/src/soc/intel/braswell/iosf.c
new file mode 100644
index 0000000000..8dba823460
--- /dev/null
+++ b/src/soc/intel/braswell/iosf.c
@@ -0,0 +1,287 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/iosf.h>
+
+#if !defined(__PRE_RAM__)
+#define IOSF_PCI_BASE (CONFIG_MMCONF_BASE_ADDRESS + (IOSF_PCI_DEV << 12))
+
+static inline void write_iosf_reg(int reg, uint32_t value)
+{
+ write32((u32 *)(IOSF_PCI_BASE + reg), value);
+}
+static inline uint32_t read_iosf_reg(int reg)
+{
+ return read32((u32 *)(IOSF_PCI_BASE + reg));
+}
+#else
+static inline void write_iosf_reg(int reg, uint32_t value)
+{
+ pci_write_config32(IOSF_PCI_DEV, reg, value);
+}
+static inline uint32_t read_iosf_reg(int reg)
+{
+ return pci_read_config32(IOSF_PCI_DEV, reg);
+}
+#endif
+
+/* Common sequences for all the port accesses. */
+static uint32_t iosf_read_port(uint32_t cr, int reg)
+{
+ cr |= IOSF_REG(reg) | IOSF_BYTE_EN;
+ write_iosf_reg(MCRX_REG, IOSF_REG_UPPER(reg));
+ write_iosf_reg(MCR_REG, cr);
+ return read_iosf_reg(MDR_REG);
+}
+
+static void iosf_write_port(uint32_t cr, int reg, uint32_t val)
+{
+ cr |= IOSF_REG(reg) | IOSF_BYTE_EN;
+ write_iosf_reg(MDR_REG, val);
+ write_iosf_reg(MCRX_REG, IOSF_REG_UPPER(reg));
+ write_iosf_reg(MCR_REG, cr);
+}
+
+#define IOSF_READ(port) \
+ IOSF_OPCODE(IOSF_OP_READ_##port) | IOSF_PORT(IOSF_PORT_##port)
+#define IOSF_WRITE(port) \
+ IOSF_OPCODE(IOSF_OP_WRITE_##port) | IOSF_PORT(IOSF_PORT_##port)
+
+uint32_t iosf_bunit_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(BUNIT), reg);
+}
+
+void iosf_bunit_write(int reg, uint32_t val)
+{
+ iosf_write_port(IOSF_WRITE(BUNIT), reg, val);
+}
+
+uint32_t iosf_dunit_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(SYSMEMC), reg);
+}
+
+uint32_t iosf_dunit_ch0_read(int reg)
+{
+ return iosf_dunit_read(reg);
+}
+
+uint32_t iosf_dunit_ch1_read(int reg)
+{
+ uint32_t cr = IOSF_OPCODE(IOSF_OP_READ_SYSMEMC) |
+ IOSF_PORT(IOSF_PORT_DUNIT_CH1);
+ return iosf_read_port(cr, reg);
+}
+
+void iosf_dunit_write(int reg, uint32_t val)
+{
+ iosf_write_port(IOSF_WRITE(SYSMEMC), reg, val);
+}
+
+uint32_t iosf_punit_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(PMC), reg);
+}
+
+void iosf_punit_write(int reg, uint32_t val)
+{
+ iosf_write_port(IOSF_WRITE(PMC), reg, val);
+}
+
+uint32_t iosf_usbphy_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(USBPHY), reg);
+}
+
+void iosf_usbphy_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(USBPHY), reg, val);
+}
+
+uint32_t iosf_ushphy_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(USHPHY), reg);
+}
+
+void iosf_ushphy_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(USHPHY), reg, val);
+}
+
+uint32_t iosf_lpss_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(LPSS), reg);
+}
+
+void iosf_lpss_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(LPSS), reg, val);
+}
+
+uint32_t iosf_ccu_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(CCU), reg);
+}
+
+void iosf_ccu_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(CCU), reg, val);
+}
+
+uint32_t iosf_score_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(SCORE), reg);
+}
+
+void iosf_score_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(SCORE), reg, val);
+}
+
+uint32_t iosf_scc_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(SCC), reg);
+}
+
+void iosf_scc_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(SCC), reg, val);
+}
+
+uint32_t iosf_aunit_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(AUNIT), reg);
+}
+
+void iosf_aunit_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(AUNIT), reg, val);
+}
+
+uint32_t iosf_cpu_bus_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(CPU_BUS), reg);
+}
+
+void iosf_cpu_bus_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(CPU_BUS), reg, val);
+}
+
+uint32_t iosf_sec_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(SEC), reg);
+}
+
+void iosf_sec_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(SEC), reg, val);
+}
+
+uint32_t iosf_port45_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x45), reg);
+}
+
+void iosf_port45_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x45), reg, val);
+}
+
+uint32_t iosf_port46_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x46), reg);
+}
+
+void iosf_port46_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x46), reg, val);
+}
+
+uint32_t iosf_port47_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x47), reg);
+}
+
+void iosf_port47_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x47), reg, val);
+}
+
+uint32_t iosf_port55_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x55), reg);
+}
+
+void iosf_port55_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x55), reg, val);
+}
+
+uint32_t iosf_port58_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x58), reg);
+}
+
+void iosf_port58_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x58), reg, val);
+}
+
+uint32_t iosf_port59_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x59), reg);
+}
+
+void iosf_port59_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x59), reg, val);
+}
+
+uint32_t iosf_port5a_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0x5a), reg);
+}
+
+void iosf_port5a_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0x5a), reg, val);
+}
+
+uint32_t iosf_porta2_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(0xa2), reg);
+}
+
+void iosf_porta2_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(0xa2), reg, val);
+}
+
+uint32_t iosf_ssus_read(int reg)
+{
+ return iosf_read_port(IOSF_READ(SSUS), reg);
+}
+
+void iosf_ssus_write(int reg, uint32_t val)
+{
+ return iosf_write_port(IOSF_WRITE(SSUS), reg, val);
+}
diff --git a/src/soc/intel/braswell/lpe.c b/src/soc/intel/braswell/lpe.c
new file mode 100644
index 0000000000..c23fdb2be6
--- /dev/null
+++ b/src/soc/intel/braswell/lpe.c
@@ -0,0 +1,189 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/lpc.h>
+#include <soc/nvs.h>
+#include <soc/pattrs.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/ramstage.h>
+#include "chip.h"
+
+
+/* The LPE audio devices needs 1MiB of memory reserved aligned to a 512MiB
+ * address. Just take 1MiB @ 512MiB. */
+#define FIRMWARE_PHYS_BASE (512 << 20)
+#define FIRMWARE_PHYS_LENGTH (1 << 20)
+#define FIRMWARE_PCI_REG_BASE 0xa8
+#define FIRMWARE_PCI_REG_LENGTH 0xac
+#define FIRMWARE_REG_BASE_C0 0x144000
+#define FIRMWARE_REG_LENGTH_C0 (FIRMWARE_REG_BASE_C0 + 4)
+
+static void assign_device_nvs(device_t dev, u32 *field, unsigned index)
+{
+ struct resource *res;
+
+ res = find_resource(dev, index);
+ if (res)
+ *field = res->base;
+}
+
+static void lpe_enable_acpi_mode(device_t dev)
+{
+ static const struct reg_script ops[] = {
+ /* Disable PCI interrupt, enable Memory and Bus Master */
+ REG_PCI_OR32(PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)),
+ /* Enable ACPI mode */
+ REG_IOSF_OR(IOSF_PORT_0x58, LPE_PCICFGCTR1,
+ LPE_PCICFGCTR1_PCI_CFG_DIS |
+ LPE_PCICFGCTR1_ACPI_INT_EN),
+ REG_SCRIPT_END
+ };
+ global_nvs_t *gnvs;
+
+ /* Find ACPI NVS to update BARs */
+ gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (!gnvs) {
+ printk(BIOS_ERR, "Unable to locate Global NVS\n");
+ return;
+ }
+
+ /* Save BAR0, BAR1, and firmware base to ACPI NVS */
+ assign_device_nvs(dev, &gnvs->dev.lpe_bar0, PCI_BASE_ADDRESS_0);
+ assign_device_nvs(dev, &gnvs->dev.lpe_bar1, PCI_BASE_ADDRESS_1);
+ assign_device_nvs(dev, &gnvs->dev.lpe_fw, FIRMWARE_PCI_REG_BASE);
+
+ /* Device is enabled in ACPI mode */
+ gnvs->dev.lpe_en = 1;
+
+ /* Put device in ACPI mode */
+ reg_script_run_on_dev(dev, ops);
+}
+
+static void setup_codec_clock(device_t dev)
+{
+ uint32_t reg;
+ u32 *clk_reg;
+ struct soc_intel_baytrail_config *config;
+ const char *freq_str;
+
+ config = dev->chip_info;
+ switch (config->lpe_codec_clk_freq) {
+ case 19:
+ freq_str = "19.2";
+ reg = CLK_FREQ_19P2MHZ;
+ break;
+ case 25:
+ freq_str = "25";
+ reg = CLK_FREQ_25MHZ;
+ break;
+ default:
+ printk(BIOS_DEBUG, "LPE codec clock not required.\n");
+ return;
+ }
+
+ /* Default to always running. */
+ reg |= CLK_CTL_ON;
+
+ if (config->lpe_codec_clk_num < 0 || config->lpe_codec_clk_num > 5) {
+ printk(BIOS_DEBUG, "Invalid LPE codec clock number.\n");
+ return;
+ }
+
+ printk(BIOS_DEBUG, "LPE Audio codec clock set to %sMHz.\n", freq_str);
+
+ clk_reg = (u32 *)(PMC_BASE_ADDRESS + PLT_CLK_CTL_0);
+ clk_reg += config->lpe_codec_clk_num;
+
+ write32(clk_reg, (read32(clk_reg) & ~0x7) | reg);
+}
+
+static void lpe_stash_firmware_info(device_t dev)
+{
+ struct resource *res;
+ struct resource *mmio;
+ const struct pattrs *pattrs = pattrs_get();
+
+ res = find_resource(dev, FIRMWARE_PCI_REG_BASE);
+ if (res == NULL) {
+ printk(BIOS_DEBUG, "LPE Firmware memory not found.\n");
+ return;
+ }
+
+ /* Continue using old way of informing firmware address / size. */
+ pci_write_config32(dev, FIRMWARE_PCI_REG_BASE, res->base);
+ pci_write_config32(dev, FIRMWARE_PCI_REG_LENGTH, res->size);
+
+ /* C0 and later steppings use an offset in the MMIO space. */
+ if (pattrs->stepping >= STEP_C0) {
+ mmio = find_resource(dev, PCI_BASE_ADDRESS_0);
+ write32((u32 *)(uintptr_t)(mmio->base + FIRMWARE_REG_BASE_C0),
+ res->base);
+ write32((u32 *)(uintptr_t)(mmio->base + FIRMWARE_REG_LENGTH_C0),
+ res->size);
+ }
+}
+
+static void lpe_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+
+ lpe_stash_firmware_info(dev);
+
+ setup_codec_clock(dev);
+
+ if (config->lpe_acpi_mode)
+ lpe_enable_acpi_mode(dev);
+}
+
+static void lpe_read_resources(device_t dev)
+{
+ pci_dev_read_resources(dev);
+
+ reserved_ram_resource(dev, FIRMWARE_PCI_REG_BASE,
+ FIRMWARE_PHYS_BASE >> 10,
+ FIRMWARE_PHYS_LENGTH >> 10);
+}
+
+static const struct device_operations device_ops = {
+ .read_resources = lpe_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = lpe_init,
+ .enable = NULL,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = LPE_DEVID,
+};
diff --git a/src/soc/intel/braswell/lpss.c b/src/soc/intel/braswell/lpss.c
new file mode 100644
index 0000000000..caa945cc31
--- /dev/null
+++ b/src/soc/intel/braswell/lpss.c
@@ -0,0 +1,206 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/iosf.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+
+#include "chip.h"
+
+static void dev_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index)
+{
+ struct reg_script ops[] = {
+ /* Disable PCI interrupt, enable Memory and Bus Master */
+ REG_PCI_OR32(PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)),
+ /* Enable ACPI mode */
+ REG_IOSF_OR(IOSF_PORT_LPSS, iosf_reg,
+ LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN),
+ REG_SCRIPT_END
+ };
+ struct resource *bar;
+ global_nvs_t *gnvs;
+
+ /* Find ACPI NVS to update BARs */
+ gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (!gnvs) {
+ printk(BIOS_ERR, "Unable to locate Global NVS\n");
+ return;
+ }
+
+ /* Save BAR0 and BAR1 to ACPI NVS */
+ bar = find_resource(dev, PCI_BASE_ADDRESS_0);
+ if (bar)
+ gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base;
+
+ bar = find_resource(dev, PCI_BASE_ADDRESS_1);
+ if (bar)
+ gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base;
+
+ /* Device is enabled in ACPI mode */
+ gnvs->dev.lpss_en[nvs_index] = 1;
+
+ /* Put device in ACPI mode */
+ reg_script_run_on_dev(dev, ops);
+}
+
+static void dev_enable_snoop_and_pm(device_t dev, int iosf_reg)
+{
+ struct reg_script ops[] = {
+ REG_IOSF_RMW(IOSF_PORT_LPSS, iosf_reg,
+ ~(LPSS_CTL_SNOOP | LPSS_CTL_NOSNOOP),
+ LPSS_CTL_SNOOP | LPSS_CTL_PM_CAP_PRSNT),
+ REG_SCRIPT_END,
+ };
+
+ reg_script_run_on_dev(dev, ops);
+}
+
+static void dev_ctl_reg(device_t dev, int *iosf_reg, int *nvs_index)
+{
+ *iosf_reg = -1;
+ *nvs_index = -1;
+#define SET_IOSF_REG(name_) \
+ case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
+ *iosf_reg = LPSS_ ## name_ ## _CTL; \
+ *nvs_index = LPSS_NVS_ ## name_
+
+ switch (dev->path.pci.devfn) {
+ SET_IOSF_REG(SIO_DMA1);
+ break;
+ SET_IOSF_REG(I2C1);
+ break;
+ SET_IOSF_REG(I2C2);
+ break;
+ SET_IOSF_REG(I2C3);
+ break;
+ SET_IOSF_REG(I2C4);
+ break;
+ SET_IOSF_REG(I2C5);
+ break;
+ SET_IOSF_REG(I2C6);
+ break;
+ SET_IOSF_REG(I2C7);
+ break;
+ SET_IOSF_REG(SIO_DMA2);
+ break;
+ SET_IOSF_REG(PWM1);
+ break;
+ SET_IOSF_REG(PWM2);
+ break;
+ SET_IOSF_REG(HSUART1);
+ break;
+ SET_IOSF_REG(HSUART2);
+ break;
+ SET_IOSF_REG(SPI);
+ break;
+ }
+}
+
+static void i2c_disable_resets(device_t dev)
+{
+ /* Release the I2C devices from reset. */
+ static const struct reg_script ops[] = {
+ REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3),
+ REG_SCRIPT_END,
+ };
+
+#define CASE_I2C(name_) \
+ case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
+
+ switch (dev->path.pci.devfn) {
+ CASE_I2C(I2C1):
+ CASE_I2C(I2C2):
+ CASE_I2C(I2C3):
+ CASE_I2C(I2C4):
+ CASE_I2C(I2C5):
+ CASE_I2C(I2C6):
+ CASE_I2C(I2C7):
+ printk(BIOS_DEBUG, "Releasing I2C device from reset.\n");
+ reg_script_run_on_dev(dev, ops);
+ break;
+ default:
+ return;
+ }
+}
+
+static void lpss_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ int iosf_reg, nvs_index;
+
+ dev_ctl_reg(dev, &iosf_reg, &nvs_index);
+
+ if (iosf_reg < 0) {
+ int slot = PCI_SLOT(dev->path.pci.devfn);
+ int func = PCI_FUNC(dev->path.pci.devfn);
+ printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n",
+ slot, func);
+ return;
+ }
+ dev_enable_snoop_and_pm(dev, iosf_reg);
+ i2c_disable_resets(dev);
+
+ if (config->lpss_acpi_mode)
+ dev_enable_acpi_mode(dev, iosf_reg, nvs_index);
+}
+
+static struct device_operations device_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = lpss_init,
+ .enable = NULL,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const unsigned short pci_device_ids[] = {
+ SIO_DMA1_DEVID,
+ I2C1_DEVID,
+ I2C2_DEVID,
+ I2C3_DEVID,
+ I2C4_DEVID,
+ I2C5_DEVID,
+ I2C6_DEVID,
+ I2C7_DEVID,
+ SIO_DMA2_DEVID,
+ PWM1_DEVID,
+ PWM2_DEVID,
+ HSUART1_DEVID,
+ HSUART2_DEVID,
+ SPI_DEVID,
+ 0,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .devices = pci_device_ids,
+};
diff --git a/src/soc/intel/braswell/memmap.c b/src/soc/intel/braswell/memmap.c
new file mode 100644
index 0000000000..9a49e3550e
--- /dev/null
+++ b/src/soc/intel/braswell/memmap.c
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <cbmem.h>
+#include <soc/iosf.h>
+#include <soc/smm.h>
+
+uintptr_t smm_region_start(void)
+{
+ return (iosf_bunit_read(BUNIT_SMRRL) << 20);
+}
+
+void *cbmem_top(void)
+{
+ return (void *) smm_region_start();
+}
diff --git a/src/soc/intel/braswell/microcode/Makefile.inc b/src/soc/intel/braswell/microcode/Makefile.inc
new file mode 100644
index 0000000000..09bd454ce0
--- /dev/null
+++ b/src/soc/intel/braswell/microcode/Makefile.inc
@@ -0,0 +1 @@
+cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c
diff --git a/src/soc/intel/braswell/microcode/microcode_blob.c b/src/soc/intel/braswell/microcode/microcode_blob.c
new file mode 100644
index 0000000000..7c7b6f10b6
--- /dev/null
+++ b/src/soc/intel/braswell/microcode/microcode_blob.c
@@ -0,0 +1,3 @@
+unsigned microcode[] = {
+#include "../../../../../3rdparty/soc/intel/baytrail/microcode_blob.h"
+};
diff --git a/src/soc/intel/braswell/northcluster.c b/src/soc/intel/braswell/northcluster.c
new file mode 100644
index 0000000000..97b3bccba0
--- /dev/null
+++ b/src/soc/intel/braswell/northcluster.c
@@ -0,0 +1,148 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+
+/* Host Memory Map:
+ *
+ * +--------------------------+ BMBOUND_HI
+ * | Usable DRAM |
+ * +--------------------------+ 4GiB
+ * | PCI Address Space |
+ * +--------------------------+ BMBOUND
+ * | TPM |
+ * +--------------------------+ IMR2
+ * | TXE |
+ * +--------------------------+ IMR1
+ * | iGD |
+ * +--------------------------+
+ * | GTT |
+ * +--------------------------+ SMMRRH, IRM0
+ * | TSEG |
+ * +--------------------------+ SMMRRL
+ * | Usable DRAM |
+ * +--------------------------+ 0
+ *
+ * Note that there are really only a few regions that need to enumerated w.r.t.
+ * coreboot's resource model:
+ *
+ * +--------------------------+ BMBOUND_HI
+ * | Cacheable/Usable |
+ * +--------------------------+ 4GiB
+ *
+ * +--------------------------+ BMBOUND
+ * | Uncacheable/Reserved |
+ * +--------------------------+ SMMRRH
+ * | Cacheable/Reserved |
+ * +--------------------------+ SMMRRL
+ * | Cacheable/Usable |
+ * +--------------------------+ 0
+ */
+#define RES_IN_KiB(r) ((r) >> 10)
+
+uint32_t nc_read_top_of_low_memory(void)
+{
+ return iosf_bunit_read(BUNIT_BMBOUND) & ~((1 << 27) - 1);
+}
+
+static void nc_read_resources(device_t dev)
+{
+ unsigned long mmconf;
+ unsigned long bmbound;
+ unsigned long bmbound_hi;
+ unsigned long smmrrh;
+ unsigned long smmrrl;
+ unsigned long base_k, size_k;
+ const unsigned long four_gig_kib = (4 << (30 - 10));
+ int index = 0;
+
+ /* Read standard PCI resources. */
+ pci_dev_read_resources(dev);
+
+ /* PCIe memory-mapped config space access - 256 MiB. */
+ mmconf = iosf_bunit_read(BUNIT_MMCONF_REG) & ~((1 << 28) - 1);
+ mmio_resource(dev, BUNIT_MMCONF_REG, RES_IN_KiB(mmconf), 256 * 1024);
+
+ /* 0 -> 0xa0000 */
+ base_k = RES_IN_KiB(0);
+ size_k = RES_IN_KiB(0xa0000) - base_k;
+ ram_resource(dev, index++, base_k, size_k);
+
+ /* The SMMRR registers are 1MiB granularity with smmrrh being
+ * inclusive of the SMM region. */
+ smmrrl = (iosf_bunit_read(BUNIT_SMRRL) & 0xffff) << 10;
+ smmrrh = ((iosf_bunit_read(BUNIT_SMRRH) & 0xffff) + 1) << 10;
+
+ /* 0xc0000 -> smrrl - cacheable and usable */
+ base_k = RES_IN_KiB(0xc0000);
+ size_k = smmrrl - base_k;
+ ram_resource(dev, index++, base_k, size_k);
+
+ if (smmrrh > smmrrl)
+ reserved_ram_resource(dev, index++, smmrrl, smmrrh - smmrrl);
+
+ /* All address space between bmbound and smmrrh is unusable. */
+ bmbound = RES_IN_KiB(nc_read_top_of_low_memory());
+ mmio_resource(dev, index++, smmrrh, bmbound - smmrrh);
+
+ /* The BMBOUND_HI register matches register bits of 31:24 with address
+ * bits of 35:28. Therefore, shift register to align properly. */
+ bmbound_hi = iosf_bunit_read(BUNIT_BMBOUND_HI) & ~((1 << 24) - 1);
+ bmbound_hi = RES_IN_KiB(bmbound_hi) << 4;
+ if (bmbound_hi > four_gig_kib)
+ ram_resource(dev, index++, four_gig_kib,
+ bmbound_hi - four_gig_kib);
+
+ /* Reserve everything between A segment and 1MB:
+ *
+ * 0xa0000 - 0xbffff: legacy VGA
+ * 0xc0000 - 0xfffff: RAM
+ */
+ mmio_resource(dev, index++, (0xa0000 >> 10), (0xc0000 - 0xa0000) >> 10);
+ reserved_ram_resource(dev, index++, (0xc0000 >> 10),
+ (0x100000 - 0xc0000) >> 10);
+
+ chromeos_reserve_ram_oops(dev, index++);
+}
+
+static struct device_operations nc_ops = {
+ .read_resources = nc_read_resources,
+ .set_resources = NULL,
+ .enable_resources = NULL,
+ .init = NULL,
+ .enable = NULL,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver nc_driver __pci_driver = {
+ .ops = &nc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = SOC_DEVID,
+};
diff --git a/src/soc/intel/braswell/pcie.c b/src/soc/intel/braswell/pcie.c
new file mode 100644
index 0000000000..e44ebc66dd
--- /dev/null
+++ b/src/soc/intel/braswell/pcie.c
@@ -0,0 +1,278 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pciexp.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/pci_devs.h>
+#include <soc/pcie.h>
+#include <soc/ramstage.h>
+#include <soc/smm.h>
+
+#include "chip.h"
+
+static int pll_en_off;
+static uint32_t strpfusecfg;
+
+static inline int root_port_offset(device_t dev)
+{
+ return PCI_FUNC(dev->path.pci.devfn);
+}
+
+static inline int is_first_port(device_t dev)
+{
+ return root_port_offset(dev) == PCIE_PORT1_FUNC;
+}
+
+static const struct reg_script init_static_before_exit_latency[] = {
+ /* Disable optimized buffer flush fill and latency tolerant reporting */
+ REG_PCI_RMW32(DCAP2, ~(OBFFS | LTRMS), 0),
+ REG_PCI_RMW32(DSTS2, ~(OBFFEN| LTRME), 0),
+ /* Set maximum payload size. */
+ REG_PCI_RMW32(DCAP, ~MPS_MASK, 0),
+ /* Disable transmit datapath flush timer, clear transmit config change
+ * wait time, clear sideband interface idle counter. */
+ REG_PCI_RMW32(PHYCTL2_IOSFBCTL, ~(TDFT | TXCFGCHWAIT | SIID), 0),
+ REG_SCRIPT_END,
+};
+
+static const struct reg_script init_static_after_exit_latency[] = {
+ /* Set common clock configuration. */
+ REG_PCI_OR16(LCTL, CCC),
+ /* Set NFTS to 0x743a361b */
+ REG_PCI_WRITE32(NFTS, 0x743a361b),
+ /* Set common clock latency to 0x3 */
+ REG_PCI_RMW32(MPC, ~CCEL_MASK, (0x3 << CCEL_SHIFT)),
+ /* Set relay timer policy. */
+ REG_PCI_RMW32(RTP, 0xff000000, 0x854c74),
+ /* Set IOSF packet fast transmit mode and link speed training policy. */
+ REG_PCI_OR16(MPC2, IPF | LSTP),
+ /* Channel configuration - enable upstream posted split, set non-posted
+ * and posted request size */
+ REG_PCI_RMW32(CHCFG, ~UPSD, UNRS | UPRS),
+ /* Completion status replay enable and set TLP grant count */
+ REG_PCI_RMW32(CFG2, ~(LATGC_MASK), CSREN | (3 << LATGC_SHIFT)),
+ /* Assume no IOAPIC behind root port -- disable EOI forwarding. */
+ REG_PCI_OR16(MPC2, EOIFD),
+ /* Expose AER */
+ REG_PCI_RMW32(AERCH, ~0, (1 << 16) | (1 << 0)),
+ /* set completion timeout to 160ms to 170ms */
+ REG_PCI_RMW16(DSTS2, ~CTD, 0x6),
+ /* Enable AER */
+ REG_PCI_OR16(DCTL_DSTS, URE | FEE | NFE | CEE),
+ /* Read and write back capability registers. */
+ REG_PCI_OR32(0x34, 0),
+ REG_PCI_OR32(0x80, 0),
+ /* Retrain the link. */
+ REG_PCI_OR16(LCTL, RL),
+ REG_SCRIPT_END,
+};
+
+static void byt_pcie_init(device_t dev)
+{
+ struct reg_script init_script[] = {
+ REG_SCRIPT_NEXT(init_static_before_exit_latency),
+ /* Exit latency configuration based on
+ * PHYCTL2_IOSFBCTL[PLL_OFF_EN] set in root port 1*/
+ REG_PCI_RMW32(LCAP, ~L1EXIT_MASK,
+ 2 << (L1EXIT_SHIFT + pll_en_off)),
+ REG_SCRIPT_NEXT(init_static_after_exit_latency),
+ /* Disable hot plug, set power to 10W, set slot number. */
+ REG_PCI_RMW32(SLCAP, ~(HPC | HPS),
+ (1 << SLS_SHIFT) | (100 << SLV_SHIFT) |
+ (root_port_offset(dev) << SLN_SHIFT)),
+ /* Dynamic clock gating. */
+ REG_PCI_OR32(RPPGEN, RPDLCGEN | RPDBCGEN | RPSCGEN),
+ REG_PCI_OR32(PWRCTL, RPL1SQPOL | RPDTSQPOL),
+ REG_PCI_OR32(PCIEDBG, SPCE),
+ REG_SCRIPT_END,
+ };
+
+ reg_script_run_on_dev(dev, init_script);
+
+ if (is_first_port(dev)) {
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ uint32_t reg = pci_read_config32(dev, RPPGEN);
+ reg |= SRDLCGEN | SRDBCGEN;
+
+ if (config && config->clkreq_enable)
+ reg |= LCLKREQEN | BBCLKREQEN;
+
+ pci_write_config32(dev, RPPGEN, reg);
+ }
+}
+
+static const struct reg_script no_dev_behind_port[] = {
+ REG_PCI_OR32(PCIEALC, (1 << 26)),
+ REG_PCI_POLL32(PCIESTS1, 0x1f000000, (1 << 24), 50000),
+ REG_PCI_OR32(PHYCTL4, SQDIS),
+ REG_SCRIPT_END,
+};
+
+static void check_port_enabled(device_t dev)
+{
+ int rp_config = (strpfusecfg & LANECFG_MASK) >> LANECFG_SHIFT;
+
+ switch (root_port_offset(dev)) {
+ case PCIE_PORT1_FUNC:
+ /* Port 1 cannot be disabled from strapping config. */
+ break;
+ case PCIE_PORT2_FUNC:
+ /* Port 2 disabled in all configs but 4x1. */
+ if (rp_config != 0x0)
+ dev->enabled = 0;
+ break;
+ case PCIE_PORT3_FUNC:
+ /* Port 3 disabled only in 1x4 config. */
+ if (rp_config == 0x3)
+ dev->enabled = 0;
+ break;
+ case PCIE_PORT4_FUNC:
+ /* Port 4 disabled in 1x4 and 2x2 config. */
+ if (rp_config >= 0x2)
+ dev->enabled = 0;
+ break;
+ }
+}
+
+static u8 all_ports_no_dev_present(device_t dev)
+{
+ u8 func;
+ u8 temp = dev->path.pci.devfn;
+ u8 device_not_present = 1;
+ u8 data;
+
+ for (func = 1; func < PCIE_ROOT_PORT_COUNT; func++) {
+ dev->path.pci.devfn &= ~0x7;
+ dev->path.pci.devfn |= func;
+
+ /* is pcie device there */
+ if (pci_read_config32(dev, 0) == 0xFFFFFFFF)
+ continue;
+
+ data = pci_read_config8(dev, XCAP + 3) | (SI >> 24);
+ pci_write_config8(dev, XCAP + 3, data);
+
+ /* is any device present */
+ if ((pci_read_config32(dev, SLCTL_SLSTS) & PDS)) {
+ device_not_present = 0;
+ break;
+ }
+ }
+
+ dev->path.pci.devfn = temp;
+ return device_not_present;
+}
+
+static void check_device_present(device_t dev)
+{
+ /* Set slot implemented. */
+ pci_write_config32(dev, XCAP, pci_read_config32(dev, XCAP) | SI);
+
+ /* No device present. */
+ if (!(pci_read_config32(dev, SLCTL_SLSTS) & PDS)) {
+ printk(BIOS_DEBUG, "No PCIe device present.\n");
+ if (is_first_port(dev)) {
+ if (all_ports_no_dev_present(dev)) {
+ reg_script_run_on_dev(dev, no_dev_behind_port);
+ dev->enabled = 0;
+ }
+ } else {
+ reg_script_run_on_dev(dev, no_dev_behind_port);
+ dev->enabled = 0;
+ }
+ } else if(!dev->enabled) {
+ /* Port is disabled, but device present. Disable link. */
+ pci_write_config32(dev, LCTL,
+ pci_read_config32(dev, LCTL) | LD);
+ }
+}
+
+static void byt_pcie_enable(device_t dev)
+{
+ if (is_first_port(dev)) {
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ uint32_t reg = pci_read_config32(dev, PHYCTL2_IOSFBCTL);
+ pll_en_off = !!(reg & PLL_OFF_EN);
+
+ strpfusecfg = pci_read_config32(dev, STRPFUSECFG);
+
+ if (config && config->pcie_wake_enable)
+ southcluster_smm_save_param(
+ SMM_SAVE_PARAM_PCIE_WAKE_ENABLE, 1);
+ }
+
+ /* Check if device is enabled in strapping. */
+ check_port_enabled(dev);
+ /* Determine if device is behind port. */
+ check_device_present(dev);
+
+ southcluster_enable_dev(dev);
+}
+
+static unsigned int byt_pciexp_scan_bridge(device_t dev, unsigned int max)
+{
+ static const struct reg_script wait_for_link_active[] = {
+ REG_PCI_POLL32(LCTL, (1 << 29) , (1 << 29), 50000),
+ REG_SCRIPT_END,
+ };
+
+ /* wait for Link Active with 50ms timeout */
+ reg_script_run_on_dev(dev, wait_for_link_active);
+
+ return do_pci_scan_bridge(dev, max, pciexp_scan_bus);
+}
+
+static void pcie_root_set_subsystem(device_t dev, unsigned vid, unsigned did)
+{
+ uint32_t didvid = ((did & 0xffff) << 16) | (vid & 0xffff);
+
+ if (!didvid)
+ didvid = pci_read_config32(dev, PCI_VENDOR_ID);
+ pci_write_config32(dev, 0x94, didvid);
+}
+
+static struct pci_operations pcie_root_ops = {
+ .set_subsystem = &pcie_root_set_subsystem,
+};
+
+static struct device_operations device_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = byt_pcie_init,
+ .scan_bus = byt_pciexp_scan_bridge,
+ .enable = byt_pcie_enable,
+ .ops_pci = &pcie_root_ops,
+};
+
+static const unsigned short pci_device_ids[] = {
+ PCIE_PORT1_DEVID, PCIE_PORT2_DEVID, PCIE_PORT3_DEVID, PCIE_PORT4_DEVID,
+ 0
+};
+
+static const struct pci_driver pcie_root_ports __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .devices = pci_device_ids,
+};
diff --git a/src/soc/intel/braswell/perf_power.c b/src/soc/intel/braswell/perf_power.c
new file mode 100644
index 0000000000..ad5ccfedb8
--- /dev/null
+++ b/src/soc/intel/braswell/perf_power.c
@@ -0,0 +1,292 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <bootstate.h>
+#include <console/console.h>
+#include <reg_script.h>
+#include <soc/iosf.h>
+
+#define MAKE_MASK_INCLUSIVE(msb) \
+ ((1ULL << (1 + (msb))) - 1)
+#define MAKE_MASK(msb) \
+ ((1ULL << (msb)) - 1)
+#define MASK_VAL(msb, lsb, val) \
+ ~(MAKE_MASK_INCLUSIVE(msb) & ~MAKE_MASK(lsb)), (val) << (lsb)
+
+#define E(arg1, arg2, args) \
+ REG_IOSF_RMW(IOSF_PORT_##arg1, arg2, args)
+
+static const struct reg_script perf_power_settings[] = {
+E(AUNIT, 0x18, MASK_VAL(22, 22, 0x1)), // ACKGATE.AMESSAGE_MSGIF
+E(AUNIT, 0x18, MASK_VAL(21, 21, 0x1)), // ACKGATE.AREQDOWN_SCL0_ARB
+E(AUNIT, 0x18, MASK_VAL(20, 20, 0x1)), // ACKGATE.AREQUP_MIRROR
+E(AUNIT, 0x18, MASK_VAL(19, 19, 0x1)), // ACKGATE.AREQTAHACK
+E(AUNIT, 0x18, MASK_VAL(18, 18, 0x1)), // ACKGATE.AREQDOWN_TAREQQ
+E(AUNIT, 0x18, MASK_VAL(17, 17, 0x1)), // ACKGATE.AREQDOWN_CREDIT
+E(AUNIT, 0x18, MASK_VAL(16, 16, 0x1)), // ACKGATE.ASCLUP_FAIR_ARBITER
+E(AUNIT, 0x18, MASK_VAL(15, 15, 0x1)), // ACKGATE.AIOSFDOWN_DATA
+E(AUNIT, 0x18, MASK_VAL(14, 14, 0x1)), // ACKGATE.ASCLUP_IOSF_ADAPTER
+E(AUNIT, 0x18, MASK_VAL(12, 12, 0x1)), // ACKGATE.ASCLUP_CMD_QUEUE
+E(AUNIT, 0x18, MASK_VAL(11, 11, 0x1)), // ACKGATE.ASCLUP_DATA_QUEUE
+E(AUNIT, 0x18, MASK_VAL(10, 10, 0x1)), // ACKGATE.AREQUP_CMD_QUEUE
+E(AUNIT, 0x18, MASK_VAL(9, 9, 0x1)), // ACKGATE.AREQUP_DATA_QUEUE
+E(AUNIT, 0x18, MASK_VAL(8, 8, 0x1)), // ACKGATE.AREQDOWN_RSP_QUEUE
+E(AUNIT, 0x18, MASK_VAL(7, 7, 0x1)), // ACKGATE.AREQDOWN_DATA_QUEUE
+E(AUNIT, 0x18, MASK_VAL(6, 6, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DRVR
+E(AUNIT, 0x18, MASK_VAL(5, 5, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DATA_BUFF
+E(AUNIT, 0x18, MASK_VAL(4, 4, 0x1)), // ACKGATE.AT_REQ_QUEUE
+E(AUNIT, 0x18, MASK_VAL(3, 3, 0x1)), // ACKGATE.AT_DATA_QUEUE
+E(AUNIT, 0x18, MASK_VAL(2, 2, 0x1)), // ACKGATE.TA_REQ_QUEUE
+E(AUNIT, 0x18, MASK_VAL(1, 1, 0x1)), // ACKGATE.TA_DATA_QUEUE
+E(AUNIT, 0x18, MASK_VAL(0, 0, 0x1)), // ACKGATE.CONFIG_REGS
+E(AUNIT, 0x20, MASK_VAL(26, 24, 0x2)), // AISOCHCTL.CHANNEL_AB_DEADLINE_EN
+E(AUNIT, 0x20, MASK_VAL(8, 0, 0x1)), // AISOCHCTL.VC1_ISOC_CH_DEFAULT_DDLINE_DLY
+E(AUNIT, 0x21, MASK_VAL(31, 31, 0x1)), // AVCCTL.EFFICIENT_PERF_UP_EN
+E(AUNIT, 0x21, MASK_VAL(8, 8, 0x0)), // AVCCTL.VC_EN_PRIORITY_DNARB
+E(AUNIT, 0x0C0, MASK_VAL(11, 8, 0x4)), // AARBCTL0.IOSF0VC2_WGT
+E(AUNIT, 0x0C0, MASK_VAL(7, 4, 0x4)), // AARBCTL0.IOSF0VC1_WGT
+E(AUNIT, 0x0C0, MASK_VAL(3, 0, 0x4)), // AARBCTL0.IOSF0VC0_WGT
+E(BUNIT, 0x3, MASK_VAL(29, 24, 0x4)), // BARBCTRL0.AGENT3_WEIGHT
+E(BUNIT, 0x3, MASK_VAL(21, 16, 0x4)), // BARBCTRL0.AGENT2_WEIGHT
+E(BUNIT, 0x3, MASK_VAL(13, 8, 0x4)), // BARBCTRL0.AGENT1_WEIGHT
+E(BUNIT, 0x3, MASK_VAL(5, 0, 0x4)), // BARBCTRL0.AGENT0_WEIGHT
+E(BUNIT, 0x4, MASK_VAL(29, 24, 0x4)), // BARBCTRL1.AGENT7_WEIGHT
+E(BUNIT, 0x4, MASK_VAL(21, 16, 0x4)), // BARBCTRL1.AGENT6_WEIGHT
+E(BUNIT, 0x4, MASK_VAL(13, 8, 0x4)), // BARBCTRL1.AGENT5_WEIGHT
+E(BUNIT, 0x4, MASK_VAL(5, 0, 0x4)), // BARBCTRL1.AGENT4_WEIGHT
+E(BUNIT, 0x5, MASK_VAL(21, 16, 0x4)), // BARBCTRL2.AGENT10_WEIGHT
+E(BUNIT, 0x5, MASK_VAL(13, 8, 0x4)), // BARBCTRL2.AGENT9_WEIGHT
+E(BUNIT, 0x5, MASK_VAL(5, 0, 0x8)), // BARBCTRL2.AGENT8_WEIGHT
+E(BUNIT, 0x7, MASK_VAL(31, 24, 0x20)), // BWFLUSH.FLUSH_THRSHOLD
+E(BUNIT, 0x7, MASK_VAL(15, 8, 0x0A)), // BWFLUSH.DIRTY_LWM
+E(BUNIT, 0x7, MASK_VAL(7, 0, 0x10)), // BWFLUSH.DIRTY_HWM
+E(BUNIT, 0x8, MASK_VAL(23, 0, 0x0)), // BBANKMASK.BANK_MASK
+E(BUNIT, 0x9, MASK_VAL(23, 0, 0x3FFFFC)), // BROWMASK.ROW_MASK
+E(BUNIT, 0x0A, MASK_VAL(9, 0, 0x080)), // BRANKMASK.RANK_MASK
+E(BUNIT, 0x0B, MASK_VAL(29, 24, 0x1F)), // BALIMIT0.AGENT3_LIMIT
+E(BUNIT, 0x0B, MASK_VAL(21, 16, 0x2F)), // BALIMIT0.AGENT2_LIMIT
+E(BUNIT, 0x0B, MASK_VAL(13, 8, 0x2F)), // BALIMIT0.AGENT1_LIMIT
+E(BUNIT, 0x0B, MASK_VAL(5, 0, 0x2F)), // BALIMIT0.AGENT0_LIMIT
+E(BUNIT, 0x0C, MASK_VAL(29, 24, 0x2F)), // BALIMIT1.AGENT7_LIMIT
+E(BUNIT, 0x0C, MASK_VAL(21, 16, 0x2F)), // BALIMIT1.AGENT6_LIMIT
+E(BUNIT, 0x0C, MASK_VAL(13, 8, 0x2F)), // BALIMIT1.AGENT5_LIMIT
+E(BUNIT, 0x0C, MASK_VAL(5, 0, 0x2B)), // BALIMIT1.AGENT4_LIMIT
+E(BUNIT, 0x0D, MASK_VAL(21, 16, 0x2F)), // BALIMIT2.AGENT10_LIMIT
+E(BUNIT, 0x0D, MASK_VAL(13, 8, 0x2F)), // BALIMIT2.AGENT9_LIMIT
+E(BUNIT, 0x0D, MASK_VAL(5, 0, 0x2F)), // BALIMIT2.AGENT8_LIMIT
+E(BUNIT, 0x0F, MASK_VAL(29, 28, 0x0)), // BARES0.AGENT7_RSVD
+E(BUNIT, 0x0F, MASK_VAL(25, 24, 0x0)), // BARES0.AGENT6_RSVD
+E(BUNIT, 0x0F, MASK_VAL(21, 20, 0x0)), // BARES0.AGENT5_RSVD
+E(BUNIT, 0x0F, MASK_VAL(17, 16, 0x0)), // BARES0.AGENT4_RSVD
+E(BUNIT, 0x0F, MASK_VAL(13, 12, 0x0)), // BARES0.AGENT3_RSVD
+E(BUNIT, 0x0F, MASK_VAL(9, 8, 0x0)), // BARES0.AGENT2_RSVD
+E(BUNIT, 0x0F, MASK_VAL(5, 4, 0x0)), // BARES0.AGENT1_RSVD
+E(BUNIT, 0x0F, MASK_VAL(1, 0, 0x0)), // BARES0.AGENT0_RSVD
+E(BUNIT, 0x10, MASK_VAL(9, 8, 0x0)), // BARES1.AGENT10_RSVD
+E(BUNIT, 0x10, MASK_VAL(5, 4, 0x0)), // BARES1.AGENT9_RSVD
+E(BUNIT, 0x10, MASK_VAL(1, 0, 0x0)), // BARES1.AGENT8_RSVD
+E(BUNIT, 0x11, MASK_VAL(31, 22, 0x20)), // BISOC.ENTER_SELF_REFRESH_THRSH
+E(BUNIT, 0x11, MASK_VAL(18, 18, 0x1)), // BISOC.SR_EXIT_SYNC_EN
+E(BUNIT, 0x11, MASK_VAL(17, 12, 0x4)), // BISOC.ENTER_SELF_REFRESH_DLY
+E(BUNIT, 0x11, MASK_VAL(11, 8, 0x8)), // BISOC.SCHEDULER_LATENCY
+E(BUNIT, 0x12, MASK_VAL(31, 30, 0x0)), // BCOSCAT.COS_CAT_AGENT15 and BCOSCAT.BUS_LOCK_THROTTLE_ENABLE
+E(BUNIT, 0x12, MASK_VAL(29, 28, 0x0)), // BCOSCAT.COS_CAT_AGENT14
+E(BUNIT, 0x12, MASK_VAL(27, 26, 0x0)), // BCOSCAT.COS_CAT_AGENT13
+E(BUNIT, 0x12, MASK_VAL(25, 24, 0x0)), // BCOSCAT.COS_CAT_AGENT12
+E(BUNIT, 0x12, MASK_VAL(23, 22, 0x0)), // BCOSCAT.COS_CAT_AGENT11
+E(BUNIT, 0x12, MASK_VAL(21, 20, 0x0)), // BCOSCAT.COS_CAT_AGENT10
+E(BUNIT, 0x12, MASK_VAL(19, 18, 0x0)), // BCOSCAT.COS_CAT_AGENT9
+E(BUNIT, 0x12, MASK_VAL(17, 16, 0x1)), // BCOSCAT.COS_CAT_AGENT8
+E(BUNIT, 0x12, MASK_VAL(15, 14, 0x0)), // BCOSCAT.COS_CAT_AGENT7
+E(BUNIT, 0x12, MASK_VAL(13, 12, 0x0)), // BCOSCAT.COS_CAT_AGENT6
+E(BUNIT, 0x12, MASK_VAL(11, 10, 0x1)), // BCOSCAT.COS_CAT_AGENT5
+E(BUNIT, 0x12, MASK_VAL(9, 8, 0x1)), // BCOSCAT.COS_CAT_AGENT4
+E(BUNIT, 0x12, MASK_VAL(7, 6, 0x0)), // BCOSCAT.COS_CAT_AGENT3
+E(BUNIT, 0x12, MASK_VAL(5, 4, 0x0)), // BCOSCAT.COS_CAT_AGENT2
+E(BUNIT, 0x12, MASK_VAL(3, 2, 0x0)), // BCOSCAT.COS_CAT_AGENT1
+E(BUNIT, 0x12, MASK_VAL(1, 0, 0x0)), // BCOSCAT.COS_CAT_AGENT0
+E(BUNIT, 0x14, MASK_VAL(31, 31, 0x0)), // BFLWT.DISABLE_FLUSH_WEIGHTS
+E(BUNIT, 0x14, MASK_VAL(30, 30, 0x0)), // BFLWT.ENABLE_READ_INVALIDATE_TIMER
+E(BUNIT, 0x14, MASK_VAL(13, 8, 0x8)), // BFLWT.WRITE_WEIGHTS
+E(BUNIT, 0x14, MASK_VAL(5, 0, 0x10)), // BFLWT.READ_WEIGHTS
+E(BUNIT, 0x16, MASK_VAL(31, 31, 0x0)), // BISOCWT.ENABLE_ISOC_WEIGHTS
+E(BUNIT, 0x16, MASK_VAL(13, 8, 0x3F)), // BISOCWT.ISOC_REQUEST_WEIGHTS
+E(BUNIT, 0x16, MASK_VAL(5, 0, 0x8)), // BISOCWT.NON_ISOC_REQUEST_WEIGHTS
+E(BUNIT, 0x18, MASK_VAL(31, 24, 0x20)), // BSCHCTRL0.BEST_EFFORT_MAX_LATENCY
+E(BUNIT, 0x18, MASK_VAL(23, 21, 0x6)), // BSCHCTRL0.PAGE_HIT_DELAY
+E(BUNIT, 0x18, MASK_VAL(13, 7, 0x0)), // BSCHCTRL0.ISOC_BANK_PREFETCH
+E(BUNIT, 0x18, MASK_VAL(6, 0, 0x20)), // BSCHCTRL0.BEST_EFFORT_BANK_PREFETCH
+E(BUNIT, 0x3B, MASK_VAL(23, 16, 0x4)), // BDEBUG0.CASUAL_TIMER
+E(BUNIT, 0x3B, MASK_VAL(9, 9, 0x0)), // BDEBUG0.DISABLE_BADMIT_URGENT_ISOC
+E(BUNIT, 0x3B, MASK_VAL(7, 0, 0x0A)), // BDEBUG0.CASUAL_WATER_MARK
+E(BUNIT, 0x3C, MASK_VAL(31, 16, 0x0FFFF)), // BDEBUG1.AGENT_WEIGHT_ENABLE
+E(BUNIT, 0x3C, MASK_VAL(2, 2, 0x0)), // BDEBUG1.EXIT_SR_FOR_CASUAL_FLUSH
+E(BUNIT, 0x3C, MASK_VAL(1, 1, 0x0)), // BDEBUG1.ENABLE_DRAM_SELF_RFRSH
+E(BUNIT, 0x3D, MASK_VAL(14, 14, 0x1)), // BCTRL.BANK_STATUS_ENABLE
+E(BUNIT, 0x3D, MASK_VAL(13, 13, 0x0)), // BCTRL.DISABLE_OWNED
+E(BUNIT, 0x3D, MASK_VAL(12, 12, 0x0)), // BCTRL.INORDER_READ_ENABLE
+E(BUNIT, 0x3D, MASK_VAL(11, 11, 0x0)), // BCTRL.INORDER_FLUSH_ENABLE
+E(BUNIT, 0x3D, MASK_VAL(8, 8, 0x0)), // BCTRL.MISS_VALID_ENTRIES
+E(BUNIT, 0x3D, MASK_VAL(7, 7, 0x0)), // BCTRL.DIRTY_STALL
+E(BUNIT, 0x3D, MASK_VAL(6, 6, 0x0)), // BCTRL.SINGLE_TAG_ACCESS
+E(BUNIT, 0x3D, MASK_VAL(5, 5, 0x0)), // BCTRL.SINGLE_CHUNK_ACCESS
+E(BUNIT, 0x3D, MASK_VAL(2, 2, 0x1)), // BCTRL.BECLK_GATE_EN
+E(BUNIT, 0x3D, MASK_VAL(1, 1, 0x1)), // BCTRL.MASTERCLK_GATE_EN
+E(BUNIT, 0x3D, MASK_VAL(0, 0, 0x1)), // BCTRL.REQUESTCLK_GATE_EN
+E(BUNIT, 0x3E, MASK_VAL(31, 16, 0x0)), // BTHCTRL.AGENT_THROTTLING_ENABLE
+E(BUNIT, 0x3E, MASK_VAL(7, 0, 0x0)), // BTHCTRL.RANK_SELECTION_MASK
+E(BUNIT, 0x3F, MASK_VAL(31, 24, 0x0FF)), // BTHMASK.ORWRITE_MASK
+E(BUNIT, 0x3F, MASK_VAL(23, 16, 0x0FF)), // BTHMASK.ORREAD_MASK
+E(BUNIT, 0x3F, MASK_VAL(15, 8, 0x0FF)), // BTHMASK.ERWRITE_MASK
+E(BUNIT, 0x3F, MASK_VAL(7, 0, 0x0FF)), // BTHMASK.ERREAD_MASK
+ //0x02, 0x0, 2, 0, 0x1, //T_INTR_REDIR_CTL.REDIR_MODE_SEL
+E(CPU_BUS, 0x3, MASK_VAL(20, 20, 0x1)), // T_CTL.SPLIT_GOIWP_MODE
+E(CPU_BUS, 0x3, MASK_VAL(19, 19, 0x0)), // T_CTL.DISABLE_TRDY_RDGO
+E(CPU_BUS, 0x3, MASK_VAL(18, 18, 0x0)), // T_CTL.DISABLE_ISOC_HIGHPRI_RDDATA_RETURN
+E(CPU_BUS, 0x3, MASK_VAL(17, 17, 0x0)), // T_CTL.ENABLE_NPC_COLLECTOR
+E(CPU_BUS, 0x3, MASK_VAL(16, 16, 0x1)), // T_CTL.ENABLE_IN_ORDER_APIC
+E(CPU_BUS, 0x3, MASK_VAL(15, 15, 0x0)), // T_CTL.TG_HIGHPRI_WRITE_PULLS
+ //0x02, 0x3, 12, 12, 0x1, // T_CTL.TG_NDRAMSNP
+E(CPU_BUS, 0x3, MASK_VAL(10, 10, 0x1)), // T_CTL.TG_DW_POST_PUSH_LOG
+E(CPU_BUS, 0x3, MASK_VAL(3, 3, 0x0)), // T_CTL.ALWAYS_SNP_IDI
+E(CPU_BUS, 0x3, MASK_VAL(2, 2, 0x0)), // T_CTL.DIS_LIVE_BRAM_BYP_IDI
+E(CPU_BUS, 0x4, MASK_VAL(18, 18, 0x1)), // T_MISC_CTL.DISABLE_IOSF_OUTBOUND_THROTTLE
+E(CPU_BUS, 0x4, MASK_VAL(4, 1, 0x8)), // T_MISC_CTL.DPTE_CNT
+E(CPU_BUS, 0x4, MASK_VAL(0, 0, 0x0)), // T_MISC_CTL.DPTE_EN
+E(CPU_BUS, 0x5, MASK_VAL(27, 27, 0x1)), // T_CLKGATE_CTL.XUNIT_4_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(26, 26, 0x1)), // T_CLKGATE_CTL.XUNIT_3_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(25, 25, 0x1)), // T_CLKGATE_CTL.XUNIT_2_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(24, 24, 0x1)), // T_CLKGATE_CTL.XUNIT_1_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(23, 23, 0x1)), // T_CLKGATE_CTL.MON_LOG_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(22, 22, 0x1)), // T_CLKGATE_CTL.A2T_Q_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(21, 21, 0x1)), // T_CLKGATE_CTL.T2A_Q_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(20, 20, 0x1)), // T_CLKGATE_CTL.A2TAPIC_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(19, 19, 0x1)), // T_CLKGATE_CTL.B2X_DATSEL_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(18, 18, 0x1)), // T_CLKGATE_CTL.X2B_DATSEL_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(17, 17, 0x1)), // T_CLKGATE_CTL.S2C_RESP_SEL_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(16, 16, 0x1)), // T_CLKGATE_CTL.T2A_REQ_SEL_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(15, 15, 0x1)), // T_CLKGATE_CTL.C2APIC_FIFO_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(14, 14, 0x1)), // T_CLKGATE_CTL.S2C_REQ_FIFO_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(13, 13, 0x1)), // T_CLKGATE_CTL.S2C_REQ_SEL_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(12, 12, 0x1)), // T_CLKGATE_CTL.TRKR_SB_LLST_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(11, 11, 0x1)), // T_CLKGATE_CTL.TRKR_SB_OLDST_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(10, 10, 0x1)), // T_CLKGATE_CTL.TRKR_SB_S2C_RESP_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(9, 9, 0x1)), // T_CLKGATE_CTL.TRKR_SB_T2A_REQSTAT_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(8, 8, 0x1)), // T_CLKGATE_CTL.TRKR_SB_B2X_DATSTAT_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(7, 7, 0x1)), // T_CLKGATE_CTL.TRKR_SB_WRSTAT_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(6, 6, 0x1)), // T_CLKGATE_CTL.TRKR_SB_SNP_STAT_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(5, 5, 0x1)), // T_CLKGATE_CTL.TRKR_SB_REQ_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(4, 4, 0x1)), // T_CLKGATE_CTL.TRKR_SB_VIOL_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(3, 3, 0x1)), // T_CLKGATE_CTL.TRKR_SB_VALID_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(2, 2, 0x1)), // T_CLKGATE_CTL.TRKR_SB_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(1, 1, 0x1)), // T_CLKGATE_CTL.IOSF_SB_CFG_REG_CLK_GATE_EN
+E(CPU_BUS, 0x5, MASK_VAL(0, 0, 0x1)), // T_CLKGATE_CTL.IOSF_SB_MSG_CLK_GATE_EN
+E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN
+E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN
+E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN
+E(0x55, 0x54, MASK_VAL(1, 0, 0x0)), // SMB_Config_PMCSR.PS
+E(0x55, 0x0FC, MASK_VAL(17, 17, 0x0)), // SMB_Config_CGC.FUNC_CLK_CGD
+E(0x55, 0x0FC, MASK_VAL(9, 9, 0x0)), // SMB_Config_CGC.SB_LOCAL_CGD
+E(0xa2, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
+E(0x47, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
+E(0x45, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
+E(0x46, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable
+E(PMC, 0x0, MASK_VAL(11, 11, 0x1)), // PUNIT_CONTROL.MODE_DEMOTE_EN
+E(PMC, 0x0, MASK_VAL(10, 10, 0x1)), // PUNIT_CONTROL.CORE_DEMOTE_EN
+
+ //
+ //s0ix_PnP_Settings
+ //
+E(0x58, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.audio.lpe.bridge.pmctl.iosfprim_trunk_gate_en
+E(0x58, 0x1e0, MASK_VAL(0, 0, 0x0)), //vlv.audio.lpe.bridge.pmctl.iosfprimclk_gate_en
+E(0x58, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.audio.lpe.bridge.pmctl.iosfsb_trunk_gate_en
+E(0x58, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.audio.lpe.bridge.pmctl.pmctl.iosfsbclk_gate_en
+E(0x58, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.audio.lpe.bridge.pmctl.ocpclk_gate_en
+E(0x58, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.audio.lpe.bridge.pmctl.ocpclk_trunk_gate_en
+E(CCU, 0x28, MASK_VAL(31, 0, 0x0)), //vlv.ccu.ccu_trunk_clkgate
+E(CCU, 0x38, MASK_VAL(31, 0, 0x0)), //vlv.ccu.ccu_trunk_clkgate_2
+E(CCU, 0x1c, MASK_VAL(29, 28, 0x0)), //vlv.ccu.clkgate_en_1.cr_lpe_pri_clkgate_en
+E(CCU, 0x1c, MASK_VAL(25, 24, 0x0)), //vlv.ccu.clkgate_en_1.cr_lpe_sb_clkgate_en
+E(CCU, 0x1c, MASK_VAL( 1, 0, 0x0)), //vlv.ccu.clkgate_en_1.lps_free_clkgate_en
+E(CCU, 0x54, MASK_VAL(17, 16, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_func_ip_clkgate_en
+E(CCU, 0x54, MASK_VAL(13, 12, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_osc_ip_clk_en
+E(CCU, 0x54, MASK_VAL(15, 14, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_xtal_ip_clkgate_en
+E(CCU, 0x54, MASK_VAL(26, 24, 0x0)), //vlv.ccu.clkgate_en_3.psf_pri_clkgate_en
+E(CCU, 0x24, MASK_VAL(24, 20, 0x0)), //vlv.ccu.iclk_clkgate_ctrl.iopcibuffen_force_on
+E(0x59, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfprim_trunk_gate_en
+E(0x59, 0x1e0, MASK_VAL(0, 0, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfprimclk_gate_en
+E(0x59, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfsb_trunk_gate_en
+E(0x59, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfsbclk_gate_en
+E(0x59, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.ocpclk_gate_en
+E(0x59, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.ocpclk_trunk_gate_en
+E(0x5a, 0xd0, MASK_VAL(8, 0, 0x3f)), //vlv.usb.xhci.controller.usb2pr.usb2hcsel
+E(0x5a, 0x40, MASK_VAL(21, 19, 0x6)), //vlv.usb.xhci.controller.xhcc1.iil1e
+E(0x5a, 0x40, MASK_VAL(10, 8, 0x1)), //vlv.usb.xhci.controller.xhcc1.l23hrawc
+E(0x5a, 0x40, MASK_VAL(18, 18, 0x1)), //vlv.usb.xhci.controller.xhcc1.xhcil1e
+E(0x5a, 0x50, MASK_VAL(3, 3, 0x1)), //vlv.usb.xhci.controller.xhclkgten.hsltcge
+E(0x5a, 0x50, MASK_VAL(0, 0, 0x1)), //vlv.usb.xhci.controller.xhclkgten.iosfblcge
+E(0x5a, 0x50, MASK_VAL(1, 1, 0x1)), //vlv.usb.xhci.controller.xhclkgten.iosfbtcge
+E(0x5a, 0x50, MASK_VAL(2, 2, 0x1)), //vlv.usb.xhci.controller.xhclkgten.ssltcge
+E(0x5a, 0x50, MASK_VAL(7, 5, 0x2)), //vlv.usb.xhci.controller.xhclkgten.sspllsue
+E(0x5a, 0x50, MASK_VAL(13, 13, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcbbtcgipiso
+E(0x5a, 0x50, MASK_VAL(4, 4, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcblcge
+E(0x5a, 0x50, MASK_VAL(14, 14, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcftclkse
+E(0x5a, 0x50, MASK_VAL(12, 12, 0x0)), //vlv.usb.xhci.controller.xhclkgten.xhchstcgu2nrwe
+E(0x5a, 0x50, MASK_VAL(11, 10, 0x3)), //vlv.usb.xhci.controller.xhclkgten.xhcusb2pllsdle
+E(SCORE, 0x4900, MASK_VAL(16, 16, 0x1)), //vlv.gpio.gpscore.cfio_regs_com_cfg_score_pb_config.sb_clkgaten
+E(SSUS, 0x4900, MASK_VAL(16, 16, 0x1)), //vlv.gpio.gpssus.cfio_regs_com_cfg_ssus_pb_config.sb_clkgaten
+E(LPSS, 0x180, MASK_VAL(1, 1, 0x1)), //vlv.lpss.iosf2ahb.pmctl.ahb_clk_gate_en
+E(LPSS, 0x180, MASK_VAL(4, 4, 0x1)), //vlv.lpss.iosf2ahb.pmctl.ahb_trunk_gate_enable
+E(LPSS, 0x180, MASK_VAL(0, 0, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosf_clk_gate_enable
+E(LPSS, 0x180, MASK_VAL(3, 3, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosfprim_trunk_gate_enable
+E(LPSS, 0x180, MASK_VAL(5, 5, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosfsb_trunk_gate_enable
+E(LPSS, 0x180, MASK_VAL(2, 2, 0x1)), //vlv.lpss.iosf2ahb.pmctl.side_clk_gate_enable
+ //0x54, 0xfc, 31, 0, 0x0, //vlv.pcu.iosfahbep.clock_gating_control
+ //0x55, 0xfc, 1, 1, 0x0, //vlv.pcu.smbus.smb_config_cgc.pri_local_cgd
+ //0x55, 0xfc, 0, 0, 0x0, //vlv.pcu.smbus.smb_config_cgc.pri_trunk_cgd
+ //0x55, 0xfc, 8, 8, 0x0, //vlv.pcu.smbus.smb_config_cgc.sb_trunk_cgd
+E(SCC, 0x600, MASK_VAL(31, 15, 0x5)), //vlv.scc.iosf2ocp.gen_regrw1.gen_reg_rw1
+E(SCC, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfprim_trunk_gate_en
+E(SCC, 0x1e0, MASK_VAL(0, 0, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfprimclk_gate_en
+E(SCC, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfsb_trunk_gate_en
+E(SCC, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfsbclk_gate_en
+E(SCC, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.scc.iosf2ocp.pmctl.ocpclk_gate_en
+E(SCC, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.scc.iosf2ocp.pmctl.ocpclk_trunk_gate_en
+E(SEC, 0x88, MASK_VAL(7, 7, 0x0)), //vlv.sec.clk_gate_dis.nfc_cg_dis
+E(SEC, 0x88, MASK_VAL(1, 1, 0x0)), //vlv.sec.clk_gate_dis.prim_cg_dis
+E(SEC, 0x88, MASK_VAL(2, 2, 0x0)), //vlv.sec.clk_gate_dis.prim_clkreq_dis
+E(SEC, 0x88, MASK_VAL(3, 3, 0x0)), //vlv.sec.clk_gate_dis.prim_xsm_clkreq_dis
+E(SEC, 0x88, MASK_VAL(4, 4, 0x0)), //vlv.sec.clk_gate_dis.sap_cg_dis
+E(SEC, 0x88, MASK_VAL(6, 6, 0x0)), //vlv.sec.clk_gate_dis.sap_clkidle_dis
+E(SEC, 0x88, MASK_VAL(5, 5, 0x0)), //vlv.sec.clk_gate_dis.sap_ip_cg_dis
+E(SEC, 0x88, MASK_VAL(0, 0, 0x0)), //vlv.sec.clk_gate_dis.sb_cg_dis
+REG_SCRIPT_END,
+};
+
+
+static void perf_power(void *unused)
+{
+ printk(BIOS_DEBUG, "Applying perf/power settings.\n");
+ reg_script_run(perf_power_settings);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, perf_power, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, perf_power, NULL);
diff --git a/src/soc/intel/braswell/placeholders.c b/src/soc/intel/braswell/placeholders.c
new file mode 100644
index 0000000000..3495c30c72
--- /dev/null
+++ b/src/soc/intel/braswell/placeholders.c
@@ -0,0 +1,11 @@
+
+#include <arch/acpi.h>
+#include <cpu/cpu.h>
+#include <device/pci_rom.h>
+#include <soc/acpi.h>
+
+
+void smm_init(void) {}
+
+/* Rmodules don't like weak symbols. */
+u32 map_oprom_vendev(u32 vendev) { return vendev; }
diff --git a/src/soc/intel/braswell/pmutil.c b/src/soc/intel/braswell/pmutil.c
new file mode 100644
index 0000000000..0678fb78db
--- /dev/null
+++ b/src/soc/intel/braswell/pmutil.c
@@ -0,0 +1,364 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <console/console.h>
+
+#include <soc/iomap.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+
+#if defined(__SMM__)
+
+static const device_t pcu_dev = PCI_DEV(0, PCU_DEV, 0);
+
+static inline device_t get_pcu_dev(void)
+{
+ return pcu_dev;
+}
+
+#else /* !__SMM__ */
+#include <device/device.h>
+#include <device/pci.h>
+
+static device_t pcu_dev;
+static device_t get_pcu_dev(void)
+{
+ if (pcu_dev == NULL)
+ pcu_dev = dev_find_slot(0, PCI_DEVFN(PCU_DEV, 0));
+ return pcu_dev;
+}
+#endif
+
+uint16_t get_pmbase(void)
+{
+ return pci_read_config16(get_pcu_dev(), ABASE) & 0xfff8;
+}
+
+static void print_num_status_bits(int num_bits, uint32_t status,
+ const char *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 void print_status_bits(uint32_t status, const char *bit_names[])
+{
+ print_num_status_bits(32, status, bit_names);
+}
+
+static uint32_t print_smi_status(uint32_t smi_sts)
+{
+ static const char *smi_sts_bits[] = {
+ [2] = "BIOS",
+ [4] = "SLP_SMI",
+ [5] = "APM",
+ [6] = "SWSMI_TMR",
+ [8] = "PM1",
+ [9] = "GPE0",
+ [12] = "DEVMON",
+ [13] = "TCO",
+ [14] = "PERIODIC",
+ [15] = "ILB",
+ [16] = "SMBUS_SMI",
+ [17] = "LEGACY_USB2",
+ [18] = "INTEL_USB2",
+ [20] = "PCI_EXP_SMI",
+ [26] = "SPI",
+ [28] = "PUNIT",
+ [29] = "GUNIT",
+ };
+
+ if (!smi_sts)
+ return 0;
+
+ printk(BIOS_DEBUG, "SMI_STS: ");
+ print_status_bits(smi_sts, smi_sts_bits);
+ printk(BIOS_DEBUG, "\n");
+
+ return smi_sts;
+}
+
+static uint32_t reset_smi_status(void)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t smi_sts = inl(pmbase + SMI_STS);
+ outl(smi_sts, pmbase + SMI_STS);
+ return smi_sts;
+}
+
+uint32_t clear_smi_status(void)
+{
+ return print_smi_status(reset_smi_status());
+}
+
+void enable_smi(uint32_t mask)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t smi_en = inl(pmbase + SMI_EN);
+ smi_en |= mask;
+ outl(smi_en, pmbase + SMI_EN);
+}
+
+void disable_smi(uint32_t mask)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t smi_en = inl(pmbase + SMI_EN);
+ smi_en &= ~mask;
+ outl(smi_en, pmbase + SMI_EN);
+}
+
+void enable_pm1_control(uint32_t mask)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
+ pm1_cnt |= mask;
+ outl(pm1_cnt, pmbase + PM1_CNT);
+}
+
+void disable_pm1_control(uint32_t mask)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t pm1_cnt = inl(pmbase + PM1_CNT);
+ pm1_cnt &= ~mask;
+ outl(pm1_cnt, pmbase + PM1_CNT);
+}
+
+static uint16_t reset_pm1_status(void)
+{
+ uint16_t pmbase = get_pmbase();
+ uint16_t pm1_sts = inw(pmbase + PM1_STS);
+ outw(pm1_sts, pmbase + PM1_STS);
+ return pm1_sts;
+}
+
+static uint16_t print_pm1_status(uint16_t pm1_sts)
+{
+ static const char *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_status_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, get_pmbase() + PM1_EN);
+}
+
+static uint32_t print_tco_status(uint32_t tco_sts)
+{
+ static const char *tco_sts_bits[] = {
+ [3] = "TIMEOUT",
+ [17] = "SECOND_TO",
+ };
+
+ if (!tco_sts)
+ return 0;
+
+ printk(BIOS_DEBUG, "TCO_STS: ");
+ print_status_bits(tco_sts, tco_sts_bits);
+ printk(BIOS_DEBUG, "\n");
+
+ return tco_sts;
+}
+
+static uint32_t reset_tco_status(void)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t tco_sts = inl(pmbase + TCO_STS);
+ uint32_t tco_en = inl(pmbase + TCO1_CNT);
+
+ outl(tco_sts, pmbase + 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)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t gpe0_en = inl(pmbase + GPE0_EN);
+ gpe0_en |= mask;
+ outl(gpe0_en, pmbase + GPE0_EN);
+}
+
+void disable_gpe(uint32_t mask)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t gpe0_en = inl(pmbase + GPE0_EN);
+ gpe0_en &= ~mask;
+ outl(gpe0_en, pmbase + GPE0_EN);
+}
+
+void disable_all_gpe(void)
+{
+ disable_gpe(~0);
+}
+
+
+static uint32_t reset_gpe_status(void)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t gpe_sts = inl(pmbase + GPE0_STS);
+ outl(gpe_sts, pmbase + GPE0_STS);
+ return gpe_sts;
+}
+
+static uint32_t print_gpe_sts(uint32_t gpe_sts)
+{
+ static const char *gpe_sts_bits[] = {
+ [1] = "HOTPLUG",
+ [2] = "SWGPE",
+ [3] = "PCIE_WAKE0",
+ [4] = "PUNIT",
+ [5] = "GUNIT",
+ [6] = "PCIE_WAKE1",
+ [7] = "PCIE_WAKE2",
+ [8] = "PCIE_WAKE3",
+ [9] = "PCI_EXP",
+ [10] = "BATLOW",
+ [13] = "PME_B0",
+ [16] = "SUS_GPIO_0",
+ [17] = "SUS_GPIO_1",
+ [18] = "SUS_GPIO_2",
+ [19] = "SUS_GPIO_3",
+ [20] = "SUS_GPIO_4",
+ [21] = "SUS_GPIO_5",
+ [22] = "SUS_GPIO_6",
+ [23] = "SUS_GPIO_7",
+ [24] = "CORE_GPIO_0",
+ [25] = "CORE_GPIO_1",
+ [26] = "CORE_GPIO_2",
+ [27] = "CORE_GPIO_3",
+ [28] = "CORE_GPIO_4",
+ [29] = "CORE_GPIO_5",
+ [30] = "CORE_GPIO_6",
+ [31] = "CORE_GPIO_7",
+ };
+
+ if (!gpe_sts)
+ return gpe_sts;
+
+ printk(BIOS_DEBUG, "GPE0a_STS: ");
+ print_status_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());
+}
+
+static uint32_t reset_alt_status(void)
+{
+ uint16_t pmbase = get_pmbase();
+ uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI);
+ outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI);
+ return alt_gpio_smi;
+}
+
+static uint32_t print_alt_sts(uint32_t alt_gpio_smi)
+{
+ uint32_t alt_gpio_sts;
+ static const char *alt_gpio_smi_sts_bits[] = {
+ [0] = "SUS_GPIO_0",
+ [1] = "SUS_GPIO_1",
+ [2] = "SUS_GPIO_2",
+ [3] = "SUS_GPIO_3",
+ [4] = "SUS_GPIO_4",
+ [5] = "SUS_GPIO_5",
+ [6] = "SUS_GPIO_6",
+ [7] = "SUS_GPIO_7",
+ [8] = "CORE_GPIO_0",
+ [9] = "CORE_GPIO_1",
+ [10] = "CORE_GPIO_2",
+ [11] = "CORE_GPIO_3",
+ [12] = "CORE_GPIO_4",
+ [13] = "CORE_GPIO_5",
+ [14] = "CORE_GPIO_6",
+ [15] = "CORE_GPIO_7",
+ };
+
+ /* Status bits are in the upper 16 bits. */
+ alt_gpio_sts = alt_gpio_smi >> 16;
+ if (!alt_gpio_sts)
+ return alt_gpio_smi;
+
+ printk(BIOS_DEBUG, "ALT_GPIO_SMI: ");
+ print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits);
+ printk(BIOS_DEBUG, "\n");
+
+ return alt_gpio_smi;
+}
+
+uint32_t clear_alt_status(void)
+{
+ return print_alt_sts(reset_alt_status());
+}
+
+void clear_pmc_status(void)
+{
+ uint32_t prsts;
+ uint32_t gen_pmcon1;
+
+ prsts = read32((u32 *)(PMC_BASE_ADDRESS + PRSTS));
+ gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
+
+ /* Clear the status bits. The RPS field is cleared on a 0 write. */
+ write32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1), gen_pmcon1 & ~RPS);
+ write32((u32 *)(PMC_BASE_ADDRESS + PRSTS), prsts);
+}
diff --git a/src/soc/intel/braswell/ramstage.c b/src/soc/intel/braswell/ramstage.c
new file mode 100644
index 0000000000..8b6d93cbe0
--- /dev/null
+++ b/src/soc/intel/braswell/ramstage.c
@@ -0,0 +1,206 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/cpu.h>
+#include <arch/acpi.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/intel/microcode.h>
+#include <cpu/x86/cr.h>
+#include <cpu/x86/msr.h>
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <device/pci_ops.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <soc/gpio.h>
+#include <soc/lpc.h>
+#include <soc/msr.h>
+#include <soc/nvs.h>
+#include <soc/pattrs.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/ramstage.h>
+#include <soc/iosf.h>
+
+/* Global PATTRS */
+DEFINE_PATTRS;
+
+#define SHOW_PATTRS 1
+
+static void detect_num_cpus(struct pattrs *attrs)
+{
+ int ecx = 0;
+
+ while (1) {
+ struct cpuid_result leaf_b;
+
+ leaf_b = cpuid_ext(0xb, ecx);
+
+ /* Bay Trail doesn't have hyperthreading so just determine the
+ * number of cores by from level type (ecx[15:8] == * 2). */
+ if ((leaf_b.ecx & 0xff00) == 0x0200) {
+ attrs->num_cpus = leaf_b.ebx & 0xffff;
+ break;
+ }
+ ecx++;
+ }
+}
+
+static inline void fill_in_msr(msr_t *msr, int idx)
+{
+ *msr = rdmsr(idx);
+ if (SHOW_PATTRS) {
+ printk(BIOS_DEBUG, "msr(%x) = %08x%08x\n",
+ idx, msr->hi, msr->lo);
+ }
+}
+
+static const char *stepping_str[] = {
+ "A0", "A1", "B0", "B1", "B2", "B3", "C0"
+};
+
+static void fill_in_pattrs(void)
+{
+ device_t dev;
+ msr_t msr;
+ struct pattrs *attrs = (struct pattrs *)pattrs_get();
+
+ attrs->cpuid = cpuid_eax(1);
+ dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
+ attrs->revid = pci_read_config8(dev, REVID);
+ /* The revision to stepping IDs have two values per metal stepping. */
+ if (attrs->revid >= RID_C_STEPPING_START) {
+ attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2;
+ attrs->stepping += STEP_C0;
+ } else if (attrs->revid >= RID_B_STEPPING_START) {
+ attrs->stepping = (attrs->revid - RID_B_STEPPING_START) / 2;
+ attrs->stepping += STEP_B0;
+ } else {
+ attrs->stepping = (attrs->revid - RID_A_STEPPING_START) / 2;
+ attrs->stepping += STEP_A0;
+ }
+
+ attrs->microcode_patch = intel_microcode_find();
+ attrs->address_bits = cpuid_eax(0x80000008) & 0xff;
+ detect_num_cpus(attrs);
+
+ if (SHOW_PATTRS) {
+ printk(BIOS_DEBUG, "BYT: cpuid %08x cpus %d rid %02x step %s\n",
+ attrs->cpuid, attrs->num_cpus, attrs->revid,
+ (attrs->stepping >= ARRAY_SIZE(stepping_str)) ? "??" :
+ stepping_str[attrs->stepping]);
+ }
+
+ fill_in_msr(&attrs->platform_id, MSR_IA32_PLATFORM_ID);
+ fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO);
+
+ /* Set IA core speed ratio and voltages */
+ msr = rdmsr(MSR_IACORE_RATIOS);
+ attrs->iacore_ratios[IACORE_MIN] = msr.lo & 0x7f;
+ attrs->iacore_ratios[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
+ attrs->iacore_ratios[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
+ msr = rdmsr(MSR_IACORE_TURBO_RATIOS);
+ attrs->iacore_ratios[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
+
+ msr = rdmsr(MSR_IACORE_VIDS);
+ attrs->iacore_vids[IACORE_MIN] = msr.lo & 0x7f;
+ attrs->iacore_vids[IACORE_LFM] = (msr.lo >> 8) & 0x7f;
+ attrs->iacore_vids[IACORE_MAX] = (msr.lo >> 16) & 0x7f;
+ msr = rdmsr(MSR_IACORE_TURBO_VIDS);
+ attrs->iacore_vids[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */
+
+ /* Set bus clock speed */
+ attrs->bclk_khz = bus_freq_khz();
+}
+
+/* Save bit index for first enabled event in PM1_STS for \_SB._SWS */
+static void s3_save_acpi_wake_source(global_nvs_t *gnvs)
+{
+ struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+ uint16_t pm1;
+
+ if (!ps)
+ return;
+
+ pm1 = ps->pm1_sts & ps->pm1_en;
+
+ /* Scan for first set bit in PM1 */
+ for (gnvs->pm1i = 0; gnvs->pm1i < 16; gnvs->pm1i++) {
+ if (pm1 & 1)
+ break;
+ pm1 >>= 1;
+ }
+
+ /* If unable to determine then return -1 */
+ if (gnvs->pm1i >= 16)
+ gnvs->pm1i = -1;
+
+ printk(BIOS_DEBUG, "ACPI System Wake Source is PM1 Index %d\n",
+ gnvs->pm1i);
+}
+
+static void s3_resume_prepare(void)
+{
+ global_nvs_t *gnvs;
+
+ gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t));
+ if (gnvs == NULL)
+ return;
+
+ if (!acpi_is_wakeup_s3())
+ memset(gnvs, 0, sizeof(global_nvs_t));
+ else
+ s3_save_acpi_wake_source(gnvs);
+}
+
+static void baytrail_enable_2x_refresh_rate(void)
+{
+ u32 reg;
+ reg = iosf_dunit_read(0x8);
+ reg = reg & ~0x7000;
+ reg = reg | 0x2000;
+ iosf_dunit_write(0x8, reg);
+}
+
+void baytrail_init_pre_device(struct soc_intel_baytrail_config *config)
+{
+ struct soc_gpio_config *gpio_config;
+
+ fill_in_pattrs();
+
+ if (!config->disable_ddr_2x_refresh_rate)
+ baytrail_enable_2x_refresh_rate();
+
+ /* Allow for SSE instructions to be executed. */
+ write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
+
+ /* Indicate S3 resume to rest of ramstage. */
+ s3_resume_prepare();
+
+ /* Run reference code. */
+ baytrail_run_reference_code();
+
+ /* Get GPIO initial states from mainboard */
+ gpio_config = mainboard_get_gpios();
+ setup_soc_gpios(gpio_config, config->enable_xdp_tap);
+
+ baytrail_init_scc();
+}
diff --git a/src/soc/intel/braswell/refcode.c b/src/soc/intel/braswell/refcode.c
new file mode 100644
index 0000000000..558db3cc8d
--- /dev/null
+++ b/src/soc/intel/braswell/refcode.c
@@ -0,0 +1,148 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <arch/acpi.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <console/streams.h>
+#include <cpu/x86/tsc.h>
+#include <program_loading.h>
+#include <rmodule.h>
+#include <stage_cache.h>
+#if IS_ENABLED(CONFIG_CHROMEOS)
+#include <vendorcode/google/chromeos/vboot_handoff.h>
+#endif
+
+#include <soc/ramstage.h>
+#include <soc/efi_wrapper.h>
+
+static void ABI_X86 send_to_console(unsigned char b)
+{
+ console_tx_byte(b);
+}
+
+static efi_wrapper_entry_t load_refcode_from_cache(void)
+{
+ struct prog refcode;
+
+ printk(BIOS_DEBUG, "refcode loading from cache.\n");
+
+ stage_cache_load_stage(STAGE_REFCODE, &refcode);
+
+ return (efi_wrapper_entry_t)prog_entry(&refcode);
+}
+
+static void cache_refcode(const struct rmod_stage_load *rsl)
+{
+ stage_cache_add(STAGE_REFCODE, rsl->prog);
+}
+
+#if IS_ENABLED(CONFIG_CHROMEOS)
+static int load_refcode_from_vboot(struct rmod_stage_load *refcode)
+{
+ struct vboot_handoff *vboot_handoff;
+ const struct firmware_component *fwc;
+ struct cbfs_stage *stage;
+
+ vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
+ fwc = &vboot_handoff->components[CONFIG_VBOOT_REFCODE_INDEX];
+
+ if (vboot_handoff == NULL ||
+ vboot_handoff->selected_firmware == VB_SELECT_FIRMWARE_READONLY ||
+ CONFIG_VBOOT_REFCODE_INDEX >= MAX_PARSED_FW_COMPONENTS ||
+ fwc->size == 0 || fwc->address == 0)
+ return -1;
+
+ printk(BIOS_DEBUG, "refcode loading from vboot rw area.\n");
+ stage = (void *)(uintptr_t)fwc->address;
+
+ if (rmodule_stage_load(refcode, stage)) {
+ printk(BIOS_DEBUG, "Error loading reference code.\n");
+ return -1;
+ }
+ return 0;
+}
+#else
+static int load_refcode_from_vboot(struct rmod_stage_load *refcode)
+{
+ return -1;
+}
+#endif
+
+static int load_refcode_from_cbfs(struct rmod_stage_load *refcode)
+{
+ printk(BIOS_DEBUG, "refcode loading from cbfs.\n");
+
+ if (rmodule_stage_load_from_cbfs(refcode)) {
+ printk(BIOS_DEBUG, "Error loading reference code.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static efi_wrapper_entry_t load_reference_code(void)
+{
+ struct prog prog = {
+ .name = CONFIG_CBFS_PREFIX "/refcode",
+ };
+ struct rmod_stage_load refcode = {
+ .cbmem_id = CBMEM_ID_REFCODE,
+ .prog = &prog,
+ };
+
+ if (acpi_is_wakeup_s3()) {
+ return load_refcode_from_cache();
+ }
+
+ if (load_refcode_from_vboot(&refcode) ||
+ load_refcode_from_cbfs(&refcode))
+ return NULL;
+
+ /* Cache loaded reference code. */
+ cache_refcode(&refcode);
+
+ return prog_entry(&prog);
+}
+
+void baytrail_run_reference_code(void)
+{
+ int ret;
+ efi_wrapper_entry_t entry;
+ struct efi_wrapper_params wrp = {
+ .version = EFI_WRAPPER_VER,
+ .console_out = send_to_console,
+ };
+
+ entry = load_reference_code();
+
+ if (entry == NULL)
+ return;
+
+ wrp.tsc_ticks_per_microsecond = tsc_freq_mhz();
+
+ /* Call into reference code. */
+ ret = entry(&wrp);
+
+ if (ret != 0) {
+ printk(BIOS_DEBUG, "Reference code returned %d\n", ret);
+ return;
+ }
+}
diff --git a/src/soc/intel/braswell/reset.c b/src/soc/intel/braswell/reset.c
new file mode 100644
index 0000000000..c4cb2abfb7
--- /dev/null
+++ b/src/soc/intel/braswell/reset.c
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/pmc.h>
+#include <soc/reset.h>
+
+void cold_reset(void)
+{
+ /* S0->S5->S0 trip. */
+ outb(RST_CPU | SYS_RST | FULL_RST, RST_CNT);
+}
+
+void warm_reset(void)
+{
+ /* PMC_PLTRST# asserted. */
+ outb(RST_CPU | SYS_RST, RST_CNT);
+}
+
+void soft_reset(void)
+{
+ /* Sends INIT# to CPU */
+ outb(RST_CPU, RST_CNT);
+}
+
+void hard_reset(void)
+{
+ /* Don't power cycle on hard_reset(). It's not really clear what the
+ * semantics should be for the meaning of hard_reset(). */
+ warm_reset();
+}
diff --git a/src/soc/intel/braswell/romstage/Makefile.inc b/src/soc/intel/braswell/romstage/Makefile.inc
new file mode 100644
index 0000000000..345037d51f
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/Makefile.inc
@@ -0,0 +1,7 @@
+cpu_incs += $(src)/soc/intel/baytrail/romstage/cache_as_ram.inc
+romstage-y += romstage.c
+romstage-y += raminit.c
+romstage-$(CONFIG_ENABLE_BUILTIN_COM1) += uart.c
+romstage-y += gfx.c
+romstage-y += pmc.c
+romstage-y += early_spi.c \ No newline at end of file
diff --git a/src/soc/intel/braswell/romstage/cache_as_ram.inc b/src/soc/intel/braswell/romstage/cache_as_ram.inc
new file mode 100644
index 0000000000..b6fcbf248f
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/cache_as_ram.inc
@@ -0,0 +1,285 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2007-2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/post_code.h>
+#include <cbmem.h>
+
+/* The full cache-as-ram size includes the cache-as-ram portion from coreboot
+ * and the space used by the reference code. These 2 values combined should
+ * be a power of 2 because the MTRR setup assumes that. */
+#define CACHE_AS_RAM_SIZE \
+ (CONFIG_DCACHE_RAM_SIZE + CONFIG_DCACHE_RAM_MRC_VAR_SIZE)
+#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
+
+/* Cache all of CBFS just below 4GiB as Write-Protect type. */
+#define CODE_CACHE_SIZE (CONFIG_CBFS_SIZE)
+#define CODE_CACHE_BASE (-CODE_CACHE_SIZE)
+#define CODE_CACHE_MASK (~(CODE_CACHE_SIZE - 1))
+#define CPU_PHYSMASK_HI ((1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1)
+
+#define NoEvictMod_MSR 0x2e0
+#define BBL_CR_CTL3_MSR 0x11e
+#define MCG_CAP_MSR 0x179
+
+ /* Save the BIST result. */
+ movl %eax, %ebp
+
+cache_as_ram:
+ post_code(0x20)
+
+ /* Send INIT IPI to all excluding ourself. */
+ movl $0x000C4500, %eax
+ movl $0xFEE00300, %esi
+ movl %eax, (%esi)
+
+ /* All CPUs need to be in Wait for SIPI state */
+wait_for_sipi:
+ movl (%esi), %eax
+ bt $12, %eax
+ jc wait_for_sipi
+
+ post_code(0x21)
+ /* Configure the default memory type to uncacheable as well as disable
+ * fixed and variable range mtrrs. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ andl $(~0x00000cff), %eax
+ wrmsr
+
+ post_code(0x22)
+ /* Zero the variable MTRRs. */
+ movl $MCG_CAP_MSR, %ecx
+ rdmsr
+ movzx %al, %ebx
+ /* First variable MTRR. */
+ movl $0x200, %ecx
+ xorl %eax, %eax
+ xorl %edx, %edx
+ 1:
+ wrmsr
+ inc %ecx
+ dec %ebx
+ jnz 1b
+
+ /* Zero out all fixed range and variable range MTRRs. */
+ movl $fixed_mtrr_table, %esi
+ movl $((fixed_mtrr_table_end - fixed_mtrr_table) / 2), %edi
+ xorl %eax, %eax
+ xorl %edx, %edx
+ 1:
+ movw (%esi), %bx
+ movzx %bx, %ecx
+ wrmsr
+ add $2, %esi
+ dec %edi
+ jnz 1b
+
+ post_code(0x23)
+ /* Set Cache-as-RAM base address. */
+ movl $(MTRRphysBase_MSR(0)), %ecx
+ movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
+ xorl %edx, %edx
+ wrmsr
+
+ post_code(0x24)
+ /* Set Cache-as-RAM mask. */
+ movl $(MTRRphysMask_MSR(0)), %ecx
+ movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
+ movl $CPU_PHYSMASK_HI, %edx
+ wrmsr
+
+ post_code(0x25)
+ /* Set code caching up for romstage. */
+ movl $(MTRRphysBase_MSR(1)), %ecx
+ movl $(CODE_CACHE_BASE | MTRR_TYPE_WRPROT), %eax
+ xorl %edx, %edx
+ wrmsr
+
+ movl $(MTRRphysMask_MSR(1)), %ecx
+ movl $(CODE_CACHE_MASK | MTRRphysMaskValid), %eax
+ movl $CPU_PHYSMASK_HI, %edx
+ wrmsr
+
+ /* Enable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ orl $MTRRdefTypeEn, %eax
+ wrmsr
+
+ post_code(0x26)
+
+ /* Enable the L2 cache. */
+ movl $BBL_CR_CTL3_MSR, %ecx
+ rdmsr
+ orl $0x100, %eax
+ wrmsr
+
+ post_code(0x27)
+
+ /* Enable cache (CR0.CD = 0, CR0.NW = 0). */
+ movl %cr0, %eax
+ andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
+ invd
+ movl %eax, %cr0
+
+ /* enable the 'no eviction' mode */
+ movl $NoEvictMod_MSR, %ecx
+ rdmsr
+ orl $1, %eax
+ wrmsr
+
+ post_code(0x28)
+
+ /* Clear the cache memory region. This will also fill up the cache */
+ movl $CACHE_AS_RAM_BASE, %esi
+ movl %esi, %edi
+ movl $(CACHE_AS_RAM_SIZE / 4), %ecx
+ xorl %eax, %eax
+ rep stosl
+
+ /* enable no evict mode */
+ movl $NoEvictMod_MSR, %ecx
+ rdmsr
+ orl $2, %eax
+ wrmsr
+
+ post_code(0x29)
+
+ /* Setup the stack. */
+ movl $(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE), %eax
+ movl %eax, %esp
+
+ /* Push the initial TSC value from boot block. The low 32 bits are
+ * in mm0, and the high 32 bits are in mm1. */
+ movd %mm1, %eax
+ pushl %eax
+ movd %mm0, %eax
+ pushl %eax
+ /* Restore the BIST result. */
+ movl %ebp, %eax
+ movl %esp, %ebp
+ pushl %eax
+
+before_romstage:
+ post_code(0x2a)
+ /* Call romstage.c main function. */
+ call romstage_main
+ /* Save return value from romstage_main. It contains the stack to use
+ * after cache-as-ram is torn down. It also contains the information
+ * for setting up MTRRs. */
+ movl %eax, %ebx
+
+ post_code(0x2b)
+
+ /* Disable cache. */
+ movl %cr0, %eax
+ orl $CR0_CacheDisable, %eax
+ movl %eax, %cr0
+
+ post_code(0x2c)
+
+ /* Disable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ andl $(~MTRRdefTypeEn), %eax
+ wrmsr
+
+ invd
+
+ post_code(0x2d)
+
+ /* Disable the no eviction run state */
+ movl $NoEvictMod_MSR, %ecx
+ rdmsr
+ andl $~2, %eax
+ wrmsr
+
+ /* Disable the no eviction mode */
+ rdmsr
+ andl $~1, %eax
+ wrmsr
+
+ post_code(0x2e)
+
+ /* Setup stack as indicated by return value from ramstage_main(). */
+ movl %ebx, %esp
+
+ /* Get number of MTRRs. */
+ popl %ebx
+ movl $MTRRphysBase_MSR(0), %ecx
+1:
+ testl %ebx, %ebx
+ jz 1f
+
+ /* Low 32 bits of MTRR base. */
+ popl %eax
+ /* Upper 32 bits of MTRR base. */
+ popl %edx
+ /* Write MTRR base. */
+ wrmsr
+ inc %ecx
+ /* Low 32 bits of MTRR mask. */
+ popl %eax
+ /* Upper 32 bits of MTRR mask. */
+ popl %edx
+ /* Write MTRR mask. */
+ wrmsr
+ inc %ecx
+
+ dec %ebx
+ jmp 1b
+1:
+ post_code(0x2f)
+
+ /* And enable cache again after setting MTRRs. */
+ movl %cr0, %eax
+ andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
+ movl %eax, %cr0
+
+ post_code(0x30)
+
+ /* Enable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ orl $MTRRdefTypeEn, %eax
+ wrmsr
+
+ post_code(0x31)
+
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+ cld /* Clear direction flag. */
+ call romstage_after_car
+
+.Lhlt:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .Lhlt
+
+/* Fixed MTRRs */
+fixed_mtrr_table:
+ .word 0x250, 0x258, 0x259
+ .word 0x268, 0x269, 0x26A
+ .word 0x26B, 0x26C, 0x26D
+ .word 0x26E, 0x26F
+fixed_mtrr_table_end:
+
diff --git a/src/soc/intel/braswell/romstage/early_spi.c b/src/soc/intel/braswell/romstage/early_spi.c
new file mode 100644
index 0000000000..2c48af1698
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/early_spi.c
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <delay.h>
+#include <console/console.h>
+
+#include <soc/iomap.h>
+#include <soc/romstage.h>
+#include <soc/spi.h>
+
+#define SPI_CYCLE_DELAY 10 /* 10us */
+#define SPI_CYCLE_TIMEOUT 400000 / SPI_CYCLE_DELAY /* 400ms */
+
+#define SPI8(x) *((volatile u8 *)(SPI_BASE_ADDRESS + x))
+#define SPI16(x) *((volatile u16 *)(SPI_BASE_ADDRESS + x))
+#define SPI32(x) *((volatile u32 *)(SPI_BASE_ADDRESS + x))
+
+/* Minimal set of commands to read wpsr from SPI. Don't use this code outside
+ * romstage -- it trashes the opmenu table.
+ * Returns 0 on success, < 0 on failure. */
+int early_spi_read_wpsr(u8 *sr)
+{
+ int timeout = SPI_CYCLE_TIMEOUT;
+
+ /* No address associated with rdsr */
+ SPI8(OPTYPE) = 0x0;
+ /* Setup opcode[0] = read wpsr */
+ SPI8(OPMENU0) = 0x5;
+
+ /* Start transaction */
+ SPI16(SSFC) = DATA_CYCLE | SPI_CYCLE_GO;
+
+ /* Wait for error / complete status */
+ while(timeout--) {
+ u16 status = SPI16(SSFS);
+ if (status & FLASH_CYCLE_ERROR) {
+ printk(BIOS_ERR, "SPI rdsr failed\n");
+ return -1;
+ } else if (status & CYCLE_DONE_STATUS)
+ break;
+
+ udelay(SPI_CYCLE_DELAY);
+ }
+
+ *sr = SPI32(FDATA0) & 0xff;
+ return 0;
+}
diff --git a/src/soc/intel/braswell/romstage/gfx.c b/src/soc/intel/braswell/romstage/gfx.c
new file mode 100644
index 0000000000..f9bb9c9e8f
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/gfx.c
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/gfx.h>
+#include <soc/pci_devs.h>
+#include <soc/romstage.h>
+
+void gfx_init(void)
+{
+ uint32_t ggc;
+ uint8_t msac;
+ const unsigned int gfx_dev = PCI_DEV(0, GFX_DEV, GFX_FUNC);
+
+ /* The GFX device needs to set the aperture, gtt stolen size, and
+ * graphics stolen memory stolen size before running MRC. For now
+ * just hard code the defaults. Options can be added to the device
+ * tree if needed. */
+
+ ggc = pci_read_config32(gfx_dev, GGC);
+ msac = pci_read_config8(gfx_dev, MSAC);
+
+ ggc &= ~(GGC_GTT_SIZE_MASK | GGC_GSM_SIZE_MASK);
+ /* 32MB GSM is not supported with <C0 stepping. */
+ ggc |= GGC_GTT_SIZE_2MB | GGC_GSM_SIZE_64MB;
+ /* Enable VGA decoding as well. */
+ ggc &= ~(GGC_VGA_DISABLE);
+
+ msac &= ~(APERTURE_SIZE_MASK);
+ msac |= APERTURE_SIZE_256MB;
+
+ pci_write_config32(gfx_dev, GGC, ggc);
+ pci_write_config8(gfx_dev, MSAC, msac);
+}
diff --git a/src/soc/intel/braswell/romstage/pmc.c b/src/soc/intel/braswell/romstage/pmc.c
new file mode 100644
index 0000000000..b41359b7ff
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/pmc.c
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/romstage.h>
+#include "../chip.h"
+
+void tco_disable(void)
+{
+ uint32_t reg;
+
+ reg = inl(ACPI_BASE_ADDRESS + TCO1_CNT);
+ reg |= TCO_TMR_HALT;
+ outl(reg, ACPI_BASE_ADDRESS + TCO1_CNT);
+}
+
+/* This sequence signals the PUNIT to start running. */
+void punit_init(void)
+{
+ uint32_t reg;
+ uint8_t rid;
+ const struct device *dev;
+ const struct soc_intel_baytrail_config *cfg = NULL;
+
+ rid = pci_read_config8(IOSF_PCI_DEV, REVID);
+ dev = dev_find_slot(0, PCI_DEVFN(SOC_DEV, SOC_FUNC));
+
+ if (dev)
+ cfg = dev->chip_info;
+
+ reg = iosf_punit_read(SB_BIOS_CONFIG);
+ /* Write bits 17:16 of SB_BIOS_CONFIG in the PUNIT. */
+ reg |= SB_BIOS_CONFIG_PERF_MODE | SB_BIOS_CONFIG_PDM_MODE;
+ /* Configure VR low power mode for C0 and above. */
+ if (rid >= RID_C_STEPPING_START && cfg != NULL &&
+ (cfg->vnn_ps2_enable || cfg->vcc_ps2_enable)) {
+ printk(BIOS_DEBUG, "Enabling VR PS2 mode: ");
+ if (cfg->vnn_ps2_enable) {
+ reg |= SB_BIOS_CONFIG_PS2_EN_VNN;
+ printk(BIOS_DEBUG, "VNN ");
+ }
+ if (cfg->vcc_ps2_enable) {
+ reg |= SB_BIOS_CONFIG_PS2_EN_VCC;
+ printk(BIOS_DEBUG, "VCC ");
+ }
+ printk(BIOS_DEBUG, "\n");
+ }
+ iosf_punit_write(SB_BIOS_CONFIG, reg);
+
+ /* Write bits 1:0 of BIOS_RESET_CPL in the PUNIT. */
+ reg = BIOS_RESET_CPL_ALL_DONE | BIOS_RESET_CPL_RESET_DONE;
+ pci_write_config32(IOSF_PCI_DEV, MDR_REG, reg);
+ reg = IOSF_OPCODE(IOSF_OP_WRITE_PMC) | IOSF_PORT(IOSF_PORT_PMC) |
+ IOSF_REG(BIOS_RESET_CPL) | IOSF_BYTE_EN_0;
+ pci_write_config32(IOSF_PCI_DEV, MCR_REG, reg);
+}
diff --git a/src/soc/intel/braswell/romstage/raminit.c b/src/soc/intel/braswell/romstage/raminit.c
new file mode 100644
index 0000000000..61c122cd1d
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/raminit.c
@@ -0,0 +1,191 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <arch/io.h>
+#include <bootmode.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/pci_def.h>
+#include <halt.h>
+#include <stage_cache.h>
+#include <soc/gpio.h>
+#include <soc/intel/common/mrc_cache.h>
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/pci_devs.h>
+#include <soc/reset.h>
+#include <soc/romstage.h>
+#include <ec/google/chromeec/ec.h>
+#include <ec/google/chromeec/ec_commands.h>
+
+static void reset_system(void)
+{
+ warm_reset();
+ halt();
+}
+
+static void enable_smbus(void)
+{
+ uint32_t reg;
+ const uint32_t smbus_dev = PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC);
+
+ /* SMBus I/O BAR */
+ reg = SMBUS_BASE_ADDRESS | 2;
+ pci_write_config32(smbus_dev, PCI_BASE_ADDRESS_4, reg);
+ /* Enable decode of I/O space. */
+ reg = pci_read_config16(smbus_dev, PCI_COMMAND);
+ reg |= 0x1;
+ pci_write_config16(smbus_dev, PCI_COMMAND, reg);
+ /* Enable Host Controller */
+ reg = pci_read_config8(smbus_dev, 0x40);
+ reg |= 1;
+ pci_write_config8(smbus_dev, 0x40, reg);
+
+ /* Configure pads to be used for SMBus */
+ score_select_func(PCU_SMB_CLK_PAD, 1);
+ score_select_func(PCU_SMB_DATA_PAD, 1);
+}
+
+static void ABI_X86 send_to_console(unsigned char b)
+{
+ do_putchar(b);
+}
+
+static void print_dram_info(void)
+{
+ const int mrc_ver_reg = 0xf0;
+ const uint32_t soc_dev = PCI_DEV(0, SOC_DEV, SOC_FUNC);
+ uint32_t reg;
+ int num_channels;
+ int speed;
+ uint32_t ch0;
+ uint32_t ch1;
+
+ reg = pci_read_config32(soc_dev, mrc_ver_reg);
+
+ printk(BIOS_INFO, "MRC v%d.%02d\n", (reg >> 8) & 0xff, reg & 0xff);
+
+ /* Number of channels enabled and DDR3 type. Determine number of
+ * channels by keying of the rank enable bits [3:0]. * */
+ ch0 = iosf_dunit_ch0_read(DRP);
+ ch1 = iosf_dunit_ch1_read(DRP);
+ num_channels = 0;
+ if (ch0 & DRP_RANK_MASK)
+ num_channels++;
+ if (ch1 & DRP_RANK_MASK)
+ num_channels++;
+
+ printk(BIOS_INFO, "%d channels of %sDDR3 @ ", num_channels,
+ (reg & (1 << 22)) ? "LP" : "");
+
+ /* DRAM frequency -- all channels run at same frequency. */
+ reg = iosf_dunit_read(DTR0);
+ switch (reg & 0x3) {
+ case 0:
+ speed = 800; break;
+ case 1:
+ speed = 1066; break;
+ case 2:
+ speed = 1333; break;
+ case 3:
+ speed = 1600; break;
+ }
+ printk(BIOS_INFO, "%dMHz\n", speed);
+}
+
+void raminit(struct mrc_params *mp, int prev_sleep_state)
+{
+ int ret;
+ mrc_wrapper_entry_t mrc_entry;
+ const struct mrc_saved_data *cache;
+
+ /* Fill in default entries. */
+ mp->version = MRC_PARAMS_VER;
+ mp->console_out = &send_to_console;
+ mp->prev_sleep_state = prev_sleep_state;
+ mp->rmt_enabled = IS_ENABLED(CONFIG_MRC_RMT);
+
+ /* Default to 2GiB IO hole. */
+ if (!mp->io_hole_mb)
+ mp->io_hole_mb = 2048;
+
+ if (recovery_mode_enabled()) {
+ printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n");
+ } else if (!mrc_cache_get_current(&cache)) {
+ mp->saved_data_size = cache->size;
+ mp->saved_data = &cache->data[0];
+ } else if (prev_sleep_state == 3) {
+ /* If waking from S3 and no cache then. */
+ printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n");
+ post_code(POST_RESUME_FAILURE);
+ reset_system();
+ } else {
+ printk(BIOS_DEBUG, "No MRC cache found.\n");
+#if CONFIG_EC_GOOGLE_CHROMEEC
+ if (prev_sleep_state == 0) {
+ /* Ensure EC is running RO firmware. */
+ google_chromeec_check_ec_image(EC_IMAGE_RO);
+ }
+#endif
+ }
+
+ /* Determine if mrc.bin is in the cbfs. */
+ if (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC,
+ NULL) == NULL) {
+ printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
+ return;
+ }
+
+ /*
+ * The entry point is currently the first instruction. Handle the
+ * case of an ELF file being put in the cbfs by setting the entry
+ * to the CONFIG_MRC_BIN_ADDRESS.
+ */
+ mrc_entry = (void *)(uintptr_t)CONFIG_MRC_BIN_ADDRESS;
+
+ if (mp->mainboard.dram_info_location == DRAM_INFO_SPD_SMBUS)
+ enable_smbus();
+
+ ret = mrc_entry(mp);
+
+ print_dram_info();
+
+ if (prev_sleep_state != 3) {
+ cbmem_initialize_empty();
+ stage_cache_create_empty();
+ } else {
+ stage_cache_recover();
+ if (cbmem_initialize()) {
+ #if CONFIG_HAVE_ACPI_RESUME
+ printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
+ /* Failed S3 resume, reset to come up cleanly */
+ reset_system();
+ #endif
+ }
+ }
+
+ printk(BIOS_DEBUG, "MRC Wrapper returned %d\n", ret);
+ printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save,
+ mp->data_to_save_size);
+
+ if (mp->data_to_save != NULL && mp->data_to_save_size > 0)
+ mrc_cache_stash_data(mp->data_to_save, mp->data_to_save_size);
+}
diff --git a/src/soc/intel/braswell/romstage/romstage.c b/src/soc/intel/braswell/romstage/romstage.c
new file mode 100644
index 0000000000..9c8bbc40ce
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/romstage.c
@@ -0,0 +1,377 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <arch/cpu.h>
+#include <arch/io.h>
+#include <arch/stages.h>
+#include <arch/early_variables.h>
+#include <console/console.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <cpu/x86/mtrr.h>
+#if CONFIG_EC_GOOGLE_CHROMEEC
+#include <ec/google/chromeec/ec.h>
+#endif
+#include <elog.h>
+#include <romstage_handoff.h>
+#include <stage_cache.h>
+#include <timestamp.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <soc/gpio.h>
+#include <soc/iomap.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/reset.h>
+#include <soc/romstage.h>
+#include <soc/smm.h>
+#include <soc/spi.h>
+
+/* The cache-as-ram assembly file calls romstage_main() after setting up
+ * cache-as-ram. romstage_main() will then call the mainboards's
+ * mainboard_romstage_entry() function. That function then calls
+ * romstage_common() below. The reason for the back and forth is to provide
+ * common entry point from cache-as-ram while still allowing for code sharing.
+ * Because we can't use global variables the stack is used for allocations --
+ * thus the need to call back and forth. */
+
+static void *setup_stack_and_mttrs(void);
+
+static void program_base_addresses(void)
+{
+ uint32_t reg;
+ const uint32_t lpc_dev = PCI_DEV(0, LPC_DEV, LPC_FUNC);
+
+ /* Memory Mapped IO registers. */
+ reg = PMC_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, PBASE, reg);
+ reg = IO_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, IOBASE, reg);
+ reg = ILB_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, IBASE, reg);
+ reg = SPI_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, SBASE, reg);
+ reg = MPHY_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, MPBASE, reg);
+ reg = PUNIT_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, PUBASE, reg);
+ reg = RCBA_BASE_ADDRESS | 1;
+ pci_write_config32(lpc_dev, RCBA, reg);
+
+ /* IO Port Registers. */
+ reg = ACPI_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, ABASE, reg);
+ reg = GPIO_BASE_ADDRESS | 2;
+ pci_write_config32(lpc_dev, GBASE, reg);
+}
+
+static void spi_init(void)
+{
+ u32 *scs = (u32 *)(SPI_BASE_ADDRESS + SCS);
+ u32 *bcr = (u32 *)(SPI_BASE_ADDRESS + BCR);
+ uint32_t reg;
+
+ /* Disable generating SMI when setting WPD bit. */
+ write32(scs, read32(scs) & ~SMIWPEN);
+ /*
+ * Enable caching and prefetching in the SPI controller. Disable
+ * the SMM-only BIOS write and set WPD bit.
+ */
+ reg = (read32(bcr) & ~SRC_MASK) | SRC_CACHE_PREFETCH | BCR_WPD;
+ reg &= ~EISS;
+ write32(bcr, reg);
+}
+
+/* Entry from cache-as-ram.inc. */
+void * asmlinkage romstage_main(unsigned long bist,
+ uint32_t tsc_low, uint32_t tsc_hi)
+{
+ struct romstage_params rp = {
+ .bist = bist,
+ .mrc_params = NULL,
+ };
+
+ /* Save initial timestamp from bootblock. */
+ timestamp_init((((uint64_t)tsc_hi) << 32) | (uint64_t)tsc_low);
+
+ /* Save romstage begin */
+ timestamp_add_now(TS_START_ROMSTAGE);
+
+ program_base_addresses();
+
+ tco_disable();
+
+ byt_config_com1_and_enable();
+
+ console_init();
+
+ spi_init();
+
+ set_max_freq();
+
+ punit_init();
+
+ gfx_init();
+
+#if CONFIG_EC_GOOGLE_CHROMEEC
+ /* Ensure the EC is in the right mode for recovery */
+ google_chromeec_early_init();
+#endif
+
+ /* Call into mainboard. */
+ mainboard_romstage_entry(&rp);
+
+ return setup_stack_and_mttrs();
+}
+
+static struct chipset_power_state power_state CAR_GLOBAL;
+
+static void migrate_power_state(void)
+{
+ 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, "Not adding power state to cbmem!\n");
+ return;
+ }
+ memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem));
+}
+CAR_MIGRATE(migrate_power_state);
+
+static struct chipset_power_state *fill_power_state(void)
+{
+ struct chipset_power_state *ps = car_get_var_ptr(&power_state);
+
+ ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
+ ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN);
+ ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
+ ps->gpe0_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS);
+ ps->gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN);
+ ps->tco_sts = inl(ACPI_BASE_ADDRESS + TCO_STS);
+ ps->prsts = read32((u32 *)(PMC_BASE_ADDRESS + PRSTS));
+ ps->gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
+ ps->gen_pmcon2 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON2));
+
+ 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, "gpe0_sts: %08x gpe0_en: %08x tco_sts: %08x\n",
+ ps->gpe0_sts, ps->gpe0_en, ps->tco_sts);
+ printk(BIOS_DEBUG, "prsts: %08x gen_pmcon1: %08x gen_pmcon2: %08x\n",
+ ps->prsts, ps->gen_pmcon1, ps->gen_pmcon2);
+
+ return ps;
+}
+
+/* Return 0, 3, or 5 to indicate the previous sleep state. */
+static int chipset_prev_sleep_state(struct chipset_power_state *ps)
+{
+ /* Default to S0. */
+ int prev_sleep_state = 0;
+
+ if (ps->pm1_sts & WAK_STS) {
+ switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) {
+ #if CONFIG_HAVE_ACPI_RESUME
+ case SLP_TYP_S3:
+ prev_sleep_state = 3;
+ break;
+ #endif
+ case SLP_TYP_S5:
+ prev_sleep_state = 5;
+ break;
+ }
+ /* Clear SLP_TYP. */
+ outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
+ }
+
+ if (ps->gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) {
+ prev_sleep_state = 5;
+ }
+
+ return prev_sleep_state;
+}
+
+static inline void chromeos_init(int prev_sleep_state)
+{
+#if CONFIG_CHROMEOS
+ /* Normalize the sleep state to what init_chromeos() wants for S3: 2. */
+ init_chromeos(prev_sleep_state == 3 ? 2 : 0);
+#endif
+}
+
+/* Entry from the mainboard. */
+void romstage_common(struct romstage_params *params)
+{
+ struct romstage_handoff *handoff;
+ struct chipset_power_state *ps;
+ int prev_sleep_state;
+
+ timestamp_add_now(TS_BEFORE_INITRAM);
+
+ ps = fill_power_state();
+ prev_sleep_state = chipset_prev_sleep_state(ps);
+
+ printk(BIOS_DEBUG, "prev_sleep_state = S%d\n", prev_sleep_state);
+
+#if CONFIG_ELOG_BOOT_COUNT
+ if (prev_sleep_state != 3)
+ boot_count_increment();
+#endif
+
+
+ /* Initialize RAM */
+ raminit(params->mrc_params, prev_sleep_state);
+
+ timestamp_add_now(TS_AFTER_INITRAM);
+
+ handoff = romstage_handoff_find_or_add();
+ if (handoff != NULL)
+ handoff->s3_resume = (prev_sleep_state == 3);
+ else
+ printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
+
+ chromeos_init(prev_sleep_state);
+}
+
+void asmlinkage romstage_after_car(void)
+{
+ timestamp_add_now(TS_END_ROMSTAGE);
+
+ /* Load the ramstage. */
+ copy_and_run();
+ while (1);
+}
+
+static inline uint32_t *stack_push(u32 *stack, u32 value)
+{
+ stack = &stack[-1];
+ *stack = value;
+ return stack;
+}
+
+/* Romstage needs quite a bit of stack for decompressing images since the lzma
+ * lib keeps its state on the stack during romstage. */
+static unsigned long choose_top_of_stack(void)
+{
+ unsigned long stack_top;
+ const unsigned long romstage_ram_stack_size = 0x5000;
+
+ /* cbmem_add() does a find() before add(). */
+ stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK,
+ romstage_ram_stack_size);
+ stack_top += romstage_ram_stack_size;
+ return stack_top;
+}
+
+/* setup_stack_and_mttrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use. */
+static void *setup_stack_and_mttrs(void)
+{
+ unsigned long top_of_stack;
+ int num_mtrrs;
+ uint32_t *slot;
+ uint32_t mtrr_mask_upper;
+ uint32_t top_of_ram;
+
+ /* Top of stack needs to be aligned to a 4-byte boundary. */
+ top_of_stack = choose_top_of_stack() & ~3;
+ slot = (void *)top_of_stack;
+ num_mtrrs = 0;
+
+ /* The upper bits of the MTRR mask need to set according to the number
+ * of physical address bits. */
+ mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
+
+ /* The order for each MTRR is value then base with upper 32-bits of
+ * each value coming before the lower 32-bits. The reasoning for
+ * this ordering is to create a stack layout like the following:
+ * +0: Number of MTRRs
+ * +4: MTRR base 0 31:0
+ * +8: MTRR base 0 63:32
+ * +12: MTRR mask 0 31:0
+ * +16: MTRR mask 0 63:32
+ * +20: MTRR base 1 31:0
+ * +24: MTRR base 1 63:32
+ * +28: MTRR mask 1 31:0
+ * +32: MTRR mask 1 63:32
+ */
+
+ /* Cache the ROM as WP just below 4GiB. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+ num_mtrrs++;
+
+ /* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ top_of_ram = (uint32_t)cbmem_top();
+ /* Cache 8MiB below the top of ram. The top of ram under 4GiB is the
+ * start of the TSEG region. It is required to be 8MiB aligned. Set
+ * this area as cacheable so it can be used later for ramstage before
+ * setting up the entire RAM as cacheable. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /* Cache 8MiB at the top of ram. Top of ram is where the TSEG
+ * region resides. However, it is not restricted to SMM mode until
+ * SMM has been relocated. By setting the region to cacheable it
+ * provides faster access when relocating the SMM handler as well
+ * as using the TSEG region for other purposes. */
+ slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
+ slot = stack_push(slot, 0); /* upper base */
+ slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /* Save the number of MTRRs to setup. Return the stack location
+ * pointing to the number of MTRRs. */
+ slot = stack_push(slot, num_mtrrs);
+
+ return slot;
+}
+
+void ramstage_cache_invalid(void)
+{
+#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE
+ /* Perform cold reset on invalid ramstage cache. */
+ cold_reset();
+#endif
+}
+
+#if CONFIG_CHROMEOS
+int vboot_get_sw_write_protect(void)
+{
+ u8 status;
+ /* Return unprotected status if status read fails. */
+ return (early_spi_read_wpsr(&status) ? 0 : !!(status & 0x80));
+}
+#endif
diff --git a/src/soc/intel/braswell/romstage/uart.c b/src/soc/intel/braswell/romstage/uart.c
new file mode 100644
index 0000000000..7705746b9e
--- /dev/null
+++ b/src/soc/intel/braswell/romstage/uart.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/gpio.h>
+#include <soc/iomap.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/romstage.h>
+
+void byt_config_com1_and_enable(void)
+{
+ uint32_t reg;
+
+ /* Enable the UART hardware for COM1. */
+ reg = 1;
+ pci_write_config32(PCI_DEV(0, LPC_DEV, 0), UART_CONT, reg);
+
+ /* Set up the pads to select the UART function */
+ score_select_func(UART_RXD_PAD, 1);
+ score_select_func(UART_TXD_PAD, 1);
+}
diff --git a/src/soc/intel/braswell/sata.c b/src/soc/intel/braswell/sata.c
new file mode 100644
index 0000000000..5294207cd4
--- /dev/null
+++ b/src/soc/intel/braswell/sata.c
@@ -0,0 +1,240 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include <soc/sata.h>
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+#include "chip.h"
+
+typedef struct soc_intel_baytrail_config config_t;
+
+static inline void sir_write(struct device *dev, int idx, u32 value)
+{
+ pci_write_config32(dev, SATA_SIRI, idx);
+ pci_write_config32(dev, SATA_SIRD, value);
+}
+
+static void sata_init(struct device *dev)
+{
+ config_t *config = dev->chip_info;
+ u32 reg32;
+ u16 reg16;
+ u8 reg8;
+
+ printk(BIOS_DEBUG, "SATA: Initializing...\n");
+
+ if (config == NULL) {
+ printk(BIOS_ERR, "SATA: ERROR: Device not in devicetree.cb!\n");
+ return;
+ }
+
+ if (!config->sata_ahci) {
+ /* Set legacy or native decoding mode */
+ if (config->ide_legacy_combined) {
+ reg8 = pci_read_config8(dev, 0x09);
+ reg8 &= ~0x5;
+ pci_write_config8(dev, 0x09, reg8);
+ } else {
+ reg8 = pci_read_config8(dev, 0x09);
+ reg8 |= 0x5;
+ pci_write_config8(dev, 0x09, reg8);
+ }
+
+ /* Set capabilities pointer */
+ pci_write_config8(dev, 0x34, 0x70);
+ reg16 = pci_read_config16(dev, 0x70);
+ reg16 &= ~0xFF00;
+ pci_write_config16(dev, 0x70, reg16);
+ }
+
+ /* Primary timing - decode enable */
+ reg16 = pci_read_config16(dev, 0x40);
+ reg16 |= 1 << 15;
+ pci_write_config16(dev, 0x40, reg16);
+
+ /* Secondary timing - decode enable */
+ reg16 = pci_read_config16(dev, 0x42);
+ reg16 |= 1 << 15;
+ pci_write_config16(dev, 0x42, reg16);
+
+ /* Port mapping enables */
+ reg16 = pci_read_config16(dev, 0x90);
+ reg16 |= (config->sata_port_map ^ 0x3) << 8;
+ pci_write_config16(dev, 0x90, reg16);
+
+ /* Port control enables */
+ reg16 = pci_read_config16(dev, 0x92);
+ reg16 &= ~0x003f;
+ reg16 |= config->sata_port_map;
+ pci_write_config16(dev, 0x92, reg16);
+
+ if (config->sata_ahci) {
+ u8 *abar = (u8 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
+
+ /* Enable CR memory space decoding */
+ reg16 = pci_read_config16(dev, 0x04);
+ reg16 |= 0x2;
+ pci_write_config16(dev, 0x04, reg16);
+
+ /* Set capability register */
+ reg32 = read32(abar + 0x00);
+ reg32 |= 0x0c046000; // set PSC+SSC+SALP+SSS+SAM
+ reg32 &= ~0x00f20060; // clear SXS+EMS+PMS+gen bits
+ reg32 |= (0x3 << 20); // Gen3 SATA
+ write32(abar + 0x00, reg32);
+
+ /* Ports enabled */
+ reg32 = read32(abar + 0x0c);
+ reg32 &= (u32)(~0x3f);
+ reg32 |= config->sata_port_map;
+ write32(abar + 0xc, reg32);
+ /* Two extra reads to latch */
+ read32(abar + 0x0c);
+ read32(abar + 0x0c);
+
+ /* Set cap2 - Support devslp */
+ reg32 = (1 << 5) | (1 << 4) | (1 << 3);
+ write32(abar + 0x24, reg32);
+
+ /* Set PxCMD registers */
+ reg32 = read32(abar + 0x118);
+ reg32 &= ~((1 << 27) | (1 << 26) | (1 << 22) | (1 << 21) |
+ (1 << 19) | (1 << 18) | (1 << 1));
+ reg32 |= 2;
+ write32(abar + 0x118, reg32);
+
+ reg32 = read32(abar + 0x198);
+ reg32 &= ~((1 << 27) | (1 << 26) | (1 << 22) | (1 << 21) |
+ (1 << 19) | (1 << 18) | (1 << 1));
+ reg32 |= 2;
+ write32(abar + 0x198, reg32);
+
+ /* Clear reset features */
+ write32(abar + 0xc8, 0);
+
+ /* Enable interrupts */
+ reg8 = read8(abar + 0x04);
+ reg8 |= 0x02;
+ write8(abar + 0x04, reg8);
+
+ } else {
+ /* TODO(shawnn): Configure IDE SATA speed regs */
+ }
+
+ /* 1.4 us delay after configuring port / enable bits */
+ udelay(2);
+
+ /* Enable clock for ports */
+ reg32 = pci_read_config32(dev, 0x94);
+ reg32 |= 0x3f << 24;
+ pci_write_config32(dev, 0x94, reg32);
+ reg32 &= (config->sata_port_map ^ 0x3) << 24;
+ pci_write_config32(dev, 0x94, reg32);
+
+ /* Lock SataGc register */
+ reg32 = (0x1 << 31) | (0x7 << 12);
+ pci_write_config32(dev, 0x98, reg32);
+}
+
+static void sata_enable(device_t dev)
+{
+ config_t *config = dev->chip_info;
+ u8 reg8;
+ u16 reg16;
+ u32 reg32;
+
+ southcluster_enable_dev(dev);
+ if (!config)
+ return;
+
+ /* Port mapping -- mask off SPD + SMS + SC bits, then re-set */
+ reg16 = pci_read_config16(dev, 0x90);
+ reg16 &= ~0x03e0;
+ reg16 |= (config->sata_port_map ^ 0x3) << 8;
+ if(config->sata_ahci)
+ reg16 |= 0x60;
+ pci_write_config16(dev, 0x90, reg16);
+
+ /* Set reg 0x94 before starting configuration */
+ reg32 = pci_read_config32(dev, 0x94);
+ reg32 &= (u32)(~0x1ff);
+ reg32 |= 0x183;
+ pci_write_config32(dev, 0x94, reg32);
+
+ /* Set ORM bit */
+ reg16 = pci_read_config16(dev, 0x92);
+ reg16 |= (1 << 15);
+ pci_write_config16(dev, 0x92, reg16);
+
+ /* R_PCH_SATA_TM2 - Undocumented in EDS, set according to ref. code */
+ reg32 = pci_read_config32(dev, 0x98);
+ reg32 &= (u32)~(0x1f80 | (1 << 6) | (1 << 5));
+ reg32 |= (1 << 29) | (1 << 25) | (1 << 23) | (1 << 22) |
+ (1 << 20) | (1 << 19) | (1 << 18) | (1 << 9) | (1 << 5);
+ pci_write_config32(dev, 0x98, reg32);
+
+ /* CMD reg - set bus master enable (BME) */
+ reg8 = pci_read_config8(dev, 0x04);
+ reg8 |= (1 << 2);
+ pci_write_config8(dev, 0x04, reg8);
+
+ /* "Test mode registers" */
+ sir_write(dev, 0x70, 0x00288301);
+ sir_write(dev, 0x54, 0x00000300);
+ sir_write(dev, 0x58, 0x50000000);
+ /* "OOB Detection Margin */
+ sir_write(dev, 0x6c, 0x130C0603);
+ /* "Gasket Control" */
+ sir_write(dev, 0xf4, 0);
+
+ /* PCS - Enable requested SATA ports */
+ reg8 = pci_read_config8(dev, 0x92);
+ reg8 &= ~0x03;
+ reg8 |= config->sata_port_map;
+ pci_write_config8(dev, 0x92, reg8);
+}
+
+static struct device_operations sata_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = sata_init,
+ .enable = sata_enable,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const unsigned short pci_device_ids[] = {
+ IDE1_DEVID, IDE2_DEVID, /* IDE */
+ AHCI1_DEVID, AHCI2_DEVID, /* AHCI */
+ 0,
+};
+
+static const struct pci_driver baytrail_sata __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .devices = pci_device_ids,
+};
diff --git a/src/soc/intel/braswell/scc.c b/src/soc/intel/braswell/scc.c
new file mode 100644
index 0000000000..6400996ace
--- /dev/null
+++ b/src/soc/intel/braswell/scc.c
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/iosf.h>
+#include <soc/nvs.h>
+#include <soc/ramstage.h>
+
+static const struct reg_script scc_start_dll[] = {
+ /* Configure master DLL. */
+ REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4964, 0x00078000),
+ /* Configure Swing,FSM for Master DLL */
+ REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4970, 0x00000133),
+ /* Run+Local Reset on Master DLL */
+ REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4970, 0x00001933),
+ REG_SCRIPT_END,
+};
+
+static const struct reg_script scc_after_dll[] = {
+ /* Configure Write Path */
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4954, ~0x7fff, 0x35ad),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4958, ~0x7fff, 0x35ad),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x495c, ~0x7fff, 0x35ad),
+ /* Configure Read Path */
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x43e4, ~0x7fff, 0x35ad),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4324, ~0x7fff, 0x35ad),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x42b4, ~0x7fff, 0x35ad),
+ /* eMMC 4.5 TX and RX DLL */
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49a4, ~0x1f001f, 0xa000d),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49a8, ~0x1f001f, 0xd000d),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49ac, ~0x1f001f, 0xd000d),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b0, ~0x1f001f, 0xd000d),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b4, ~0x1f001f, 0xd000d),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b8, ~0x1, 0x0),
+ /* cfio_regs_mmc1_ELECTRICAL.nslew/pslew */
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c0, ~0x3c, 0x0),
+ REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c4, ~0x3c, 0x0),
+ /*
+ * iosf2ocp_private.GENREGRW1.cr_clock_enable_clk_ocp = 01
+ * iosf2ocp_private.GENREGRW1.cr_clock_enable_clk_xin = 01
+ */
+ REG_IOSF_RMW(IOSF_PORT_SCC, 0x600, ~0xf, 0x5),
+ /* Enable IOSF Snoop */
+ REG_IOSF_OR(IOSF_PORT_SCC, 0x00, (1 << 7)),
+ /* SDIO 3V Support. */
+ REG_IOSF_RMW(IOSF_PORT_SCC, 0x600, ~0x30, 0x30),
+ REG_SCRIPT_END,
+};
+
+void baytrail_init_scc(void)
+{
+ uint32_t dll_values;
+
+ printk(BIOS_DEBUG, "Initializing sideband SCC registers.\n");
+
+ /* Common Sideband Initialization for SCC */
+ reg_script_run(scc_start_dll);
+
+ /* Override Slave Path - populate DLL settings. */
+ dll_values = iosf_score_read(0x496c) & 0x7ffff;
+ dll_values |= iosf_score_read(0x4950) & ~0xfffff;
+ iosf_score_write(0x4950, dll_values | (1 << 19));
+
+ reg_script_run(scc_after_dll);
+}
+
+void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index)
+{
+ struct reg_script ops[] = {
+ /* Disable PCI interrupt, enable Memory and Bus Master */
+ REG_PCI_OR32(PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)),
+ /* Enable ACPI mode */
+ REG_IOSF_OR(IOSF_PORT_SCC, iosf_reg,
+ SCC_CTL_PCI_CFG_DIS | SCC_CTL_ACPI_INT_EN),
+ REG_SCRIPT_END
+ };
+ struct resource *bar;
+ global_nvs_t *gnvs;
+
+ /* Find ACPI NVS to update BARs */
+ gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (!gnvs) {
+ printk(BIOS_ERR, "Unable to locate Global NVS\n");
+ return;
+ }
+
+ /* Save BAR0 and BAR1 to ACPI NVS */
+ bar = find_resource(dev, PCI_BASE_ADDRESS_0);
+ if (bar)
+ gnvs->dev.scc_bar0[nvs_index] = (u32)bar->base;
+
+ bar = find_resource(dev, PCI_BASE_ADDRESS_1);
+ if (bar)
+ gnvs->dev.scc_bar1[nvs_index] = (u32)bar->base;
+
+ /* Device is enabled in ACPI mode */
+ gnvs->dev.scc_en[nvs_index] = 1;
+
+ /* Put device in ACPI mode */
+ reg_script_run_on_dev(dev, ops);
+}
diff --git a/src/soc/intel/braswell/sd.c b/src/soc/intel/braswell/sd.c
new file mode 100644
index 0000000000..577469d3aa
--- /dev/null
+++ b/src/soc/intel/braswell/sd.c
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <reg_script.h>
+
+#include <soc/iosf.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include "chip.h"
+
+#define CAP_OVERRIDE_LOW 0xa0
+#define CAP_OVERRIDE_HIGH 0xa4
+# define USE_CAP_OVERRIDES (1 << 31)
+
+static void sd_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+
+ if (config == NULL)
+ return;
+
+ if (config->sdcard_cap_low != 0 || config->sdcard_cap_high != 0) {
+ printk(BIOS_DEBUG, "Overriding SD Card controller caps.\n");
+ pci_write_config32(dev, CAP_OVERRIDE_LOW,
+ config->sdcard_cap_low);
+ pci_write_config32(dev, CAP_OVERRIDE_HIGH,
+ config->sdcard_cap_high | USE_CAP_OVERRIDES);
+ }
+
+ if (config->scc_acpi_mode)
+ scc_enable_acpi_mode(dev, SCC_SD_CTL, SCC_NVS_SD);
+}
+
+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 = sd_init,
+ .enable = NULL,
+ .scan_bus = NULL,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = SD_DEVID,
+};
diff --git a/src/soc/intel/braswell/smihandler.c b/src/soc/intel/braswell/smihandler.c
new file mode 100644
index 0000000000..3fac525069
--- /dev/null
+++ b/src/soc/intel/braswell/smihandler.c
@@ -0,0 +1,483 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <stdlib.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 <halt.h>
+#include <spi-generic.h>
+
+#include <soc/iosf.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/nvs.h>
+
+/* GNVS needs to be set by coreboot initiating a software SMI. */
+static global_nvs_t *gnvs;
+static int smm_initialized;
+
+int southbridge_io_trap_handler(int smif)
+{
+ switch (smif) {
+ case 0x32:
+ printk(BIOS_DEBUG, "OS Init\n");
+ /* gnvs->smif:
+ * On success, the IO Trap Handler returns 0
+ * On failure, the IO Trap Handler returns a value != 0
+ */
+ gnvs->smif = 0;
+ return 1; /* IO trap handled */
+ }
+
+ /* Not handled */
+ return 0;
+}
+
+void southbridge_smi_set_eos(void)
+{
+ enable_smi(EOS);
+}
+
+global_nvs_t *smm_get_gnvs(void)
+{
+ return gnvs;
+}
+
+static void busmaster_disable_on_bus(int bus)
+{
+ int slot, func;
+ unsigned int val;
+ unsigned char hdr;
+
+ for (slot = 0; slot < 0x20; slot++) {
+ for (func = 0; func < 8; func++) {
+ u32 reg32;
+ device_t dev = PCI_DEV(bus, slot, func);
+
+ val = pci_read_config32(dev, PCI_VENDOR_ID);
+
+ if (val == 0xffffffff || val == 0x00000000 ||
+ val == 0x0000ffff || val == 0xffff0000)
+ continue;
+
+ /* Disable Bus Mastering for this one device */
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ reg32 &= ~PCI_COMMAND_MASTER;
+ pci_write_config32(dev, PCI_COMMAND, reg32);
+
+ /* If this is a bridge, then follow it. */
+ hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
+ hdr &= 0x7f;
+ if (hdr == PCI_HEADER_TYPE_BRIDGE ||
+ hdr == PCI_HEADER_TYPE_CARDBUS) {
+ unsigned int buses;
+ buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
+ busmaster_disable_on_bus((buses >> 8) & 0xff);
+ }
+ }
+ }
+}
+
+static void southbridge_smi_sleep(void)
+{
+ uint32_t reg32;
+ uint8_t slp_typ;
+ uint16_t pmbase = get_pmbase();
+
+ /* First, disable further SMIs */
+ disable_smi(SLP_SMI_EN);
+
+ /* Figure out SLP_TYP */
+ reg32 = inl(pmbase + PM1_CNT);
+ printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
+ slp_typ = (reg32 >> 10) & 7;
+
+ /* Do any mainboard sleep handling */
+ mainboard_smi_sleep(slp_typ-2);
+
+#if CONFIG_ELOG_GSMI
+ /* Log S3, S4, and S5 entry */
+ if (slp_typ >= 5)
+ elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2);
+#endif
+
+ /* Next, do the deed.
+ */
+
+ switch (slp_typ) {
+ case SLP_TYP_S0:
+ printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
+ break;
+ case SLP_TYP_S1:
+ printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n");
+ break;
+ case SLP_TYP_S3:
+ printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
+
+ /* Invalidate the cache before going to S3 */
+ wbinvd();
+ break;
+ case SLP_TYP_S4:
+ printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
+ break;
+ case SLP_TYP_S5:
+ printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
+
+ /* Disable all GPE */
+ disable_all_gpe();
+
+ /* also iterates over all bridges on bus 0 */
+ busmaster_disable_on_bus(0);
+ break;
+ default:
+ printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
+ break;
+ }
+
+ /* Write back to the SLP register to cause the originally intended
+ * event again. We need to set BIT13 (SLP_EN) though to make the
+ * sleep happen.
+ */
+ enable_pm1_control(SLP_EN);
+
+ /* Make sure to stop executing code here for S3/S4/S5 */
+ if (slp_typ > 1)
+ halt();
+
+ /* In most sleep states, the code flow of this function ends at
+ * the line above. However, if we entered sleep state S1 and wake
+ * up again, we will continue to execute code in this function.
+ */
+ reg32 = inl(pmbase + PM1_CNT);
+ if (reg32 & SCI_EN) {
+ /* The OS is not an ACPI OS, so we set the state to S0 */
+ disable_pm1_control(SLP_EN | SLP_TYP);
+ }
+}
+
+/*
+ * Look for Synchronous IO SMI and use save state from that
+ * core in case we are not running on the same core that
+ * initiated the IO transaction.
+ */
+static em64t100_smm_state_save_area_t *smi_apmc_find_state_save(uint8_t cmd)
+{
+ em64t100_smm_state_save_area_t *state;
+ int node;
+
+ /* Check all nodes looking for the one that issued the IO */
+ for (node = 0; node < CONFIG_MAX_CPUS; node++) {
+ state = smm_get_save_state(node);
+
+ /* Check for Synchronous IO (bit0==1) */
+ if (!(state->io_misc_info & (1 << 0)))
+ continue;
+
+ /* Make sure it was a write (bit4==0) */
+ if (state->io_misc_info & (1 << 4))
+ continue;
+
+ /* Check for APMC IO port */
+ if (((state->io_misc_info >> 16) & 0xff) != APM_CNT)
+ continue;
+
+ /* Check AX against the requested command */
+ if ((state->rax & 0xff) != cmd)
+ continue;
+
+ return state;
+ }
+
+ return NULL;
+}
+
+#if CONFIG_ELOG_GSMI
+static void southbridge_smi_gsmi(void)
+{
+ u32 *ret, *param;
+ uint8_t sub_command;
+ em64t100_smm_state_save_area_t *io_smi =
+ smi_apmc_find_state_save(ELOG_GSMI_APM_CNT);
+
+ if (!io_smi)
+ return;
+
+ /* Command and return value in EAX */
+ ret = (u32*)&io_smi->rax;
+ sub_command = (uint8_t)(*ret >> 8);
+
+ /* Parameter buffer in EBX */
+ param = (u32*)&io_smi->rbx;
+
+ /* drivers/elog/gsmi.c */
+ *ret = gsmi_exec(sub_command, param);
+}
+#endif
+
+static void finalize(void)
+{
+ static int finalize_done;
+
+ if (finalize_done) {
+ printk(BIOS_DEBUG, "SMM already finalized.\n");
+ return;
+ }
+ finalize_done = 1;
+
+#if CONFIG_SPI_FLASH_SMM
+ /* Re-init SPI driver to handle locked BAR */
+ spi_init();
+#endif
+}
+
+/*
+ * soc_legacy: A payload (Depthcharge) has indicated that the
+ * legacy payload (SeaBIOS) is being loaded. Switch devices that are
+ * in ACPI mode to PCI mode so that non-ACPI drivers may work.
+ *
+ */
+static void soc_legacy(void)
+{
+ u32 reg32;
+
+ /* LPE Device */
+ if (gnvs->dev.lpe_en) {
+ reg32 = iosf_port58_read(LPE_PCICFGCTR1);
+ reg32 &=
+ ~(LPE_PCICFGCTR1_PCI_CFG_DIS | LPE_PCICFGCTR1_ACPI_INT_EN);
+ iosf_port58_write(LPE_PCICFGCTR1, reg32);
+ }
+
+ /* SCC Devices */
+#define SCC_ACPI_MODE_DISABLE(name_) \
+ do { if (gnvs->dev.scc_en[SCC_NVS_ ## name_]) { \
+ reg32 = iosf_scc_read(SCC_ ## name_ ## _CTL); \
+ reg32 &= ~(SCC_CTL_PCI_CFG_DIS | SCC_CTL_ACPI_INT_EN); \
+ iosf_scc_write(SCC_ ## name_ ## _CTL, reg32); \
+ } } while (0)
+
+ SCC_ACPI_MODE_DISABLE(MMC);
+ SCC_ACPI_MODE_DISABLE(SD);
+ SCC_ACPI_MODE_DISABLE(SDIO);
+
+ /* LPSS Devices */
+#define LPSS_ACPI_MODE_DISABLE(name_) \
+ do { if (gnvs->dev.lpss_en[LPSS_NVS_ ## name_]) { \
+ reg32 = iosf_lpss_read(LPSS_ ## name_ ## _CTL); \
+ reg32 &= ~LPSS_CTL_PCI_CFG_DIS | ~LPSS_CTL_ACPI_INT_EN; \
+ iosf_lpss_write(LPSS_ ## name_ ## _CTL, reg32); \
+ } } while (0)
+
+ LPSS_ACPI_MODE_DISABLE(SIO_DMA1);
+ LPSS_ACPI_MODE_DISABLE(I2C1);
+ LPSS_ACPI_MODE_DISABLE(I2C2);
+ LPSS_ACPI_MODE_DISABLE(I2C3);
+ LPSS_ACPI_MODE_DISABLE(I2C4);
+ LPSS_ACPI_MODE_DISABLE(I2C5);
+ LPSS_ACPI_MODE_DISABLE(I2C6);
+ LPSS_ACPI_MODE_DISABLE(I2C7);
+ LPSS_ACPI_MODE_DISABLE(SIO_DMA2);
+ LPSS_ACPI_MODE_DISABLE(PWM1);
+ LPSS_ACPI_MODE_DISABLE(PWM2);
+ LPSS_ACPI_MODE_DISABLE(HSUART1);
+ LPSS_ACPI_MODE_DISABLE(HSUART2);
+ LPSS_ACPI_MODE_DISABLE(SPI);
+}
+
+static void southbridge_smi_apmc(void)
+{
+ uint8_t reg8;
+ em64t100_smm_state_save_area_t *state;
+
+ /* Emulate B2 register as the FADT / Linux expects it */
+
+ reg8 = inb(APM_CNT);
+ switch (reg8) {
+ case APM_CNT_CST_CONTROL:
+ /* Calling this function seems to cause
+ * some kind of race condition in Linux
+ * and causes a kernel oops
+ */
+ printk(BIOS_DEBUG, "C-state control\n");
+ break;
+ case APM_CNT_PST_CONTROL:
+ /* Calling this function seems to cause
+ * some kind of race condition in Linux
+ * and causes a kernel oops
+ */
+ printk(BIOS_DEBUG, "P-state control\n");
+ break;
+ case APM_CNT_ACPI_DISABLE:
+ disable_pm1_control(SCI_EN);
+ printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
+ break;
+ case APM_CNT_ACPI_ENABLE:
+ enable_pm1_control(SCI_EN);
+ printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
+ break;
+ case APM_CNT_GNVS_UPDATE:
+ if (smm_initialized) {
+ printk(BIOS_DEBUG,
+ "SMI#: SMM structures already initialized!\n");
+ return;
+ }
+ state = smi_apmc_find_state_save(reg8);
+ if (state) {
+ /* EBX in the state save contains the GNVS pointer */
+ gnvs = (global_nvs_t *)((uint32_t)state->rbx);
+ smm_initialized = 1;
+ printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
+ }
+ break;
+#if CONFIG_ELOG_GSMI
+ case ELOG_GSMI_APM_CNT:
+ southbridge_smi_gsmi();
+ break;
+#endif
+ case APM_CNT_FINALIZE:
+ finalize();
+ break;
+
+ case APM_CNT_LEGACY:
+ soc_legacy();
+ break;
+ }
+
+ mainboard_smi_apmc(reg8);
+}
+
+static void southbridge_smi_pm1(void)
+{
+ uint16_t pm1_sts = clear_pm1_status();
+
+ /* While OSPM is not active, poweroff immediately
+ * on a power button event.
+ */
+ if (pm1_sts & PWRBTN_STS) {
+ // power button pressed
+#if CONFIG_ELOG_GSMI
+ elog_add_event(ELOG_TYPE_POWER_BUTTON);
+#endif
+ disable_pm1_control(-1UL);
+ enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
+ }
+}
+
+static void southbridge_smi_gpe0(void)
+{
+ clear_gpe_status();
+}
+
+static void southbridge_smi_tco(void)
+{
+ uint32_t tco_sts = clear_tco_status();
+
+ /* Any TCO event? */
+ if (!tco_sts)
+ return;
+
+ if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */
+ /* Handle TCO timeout */
+ printk(BIOS_DEBUG, "TCO Timeout.\n");
+ }
+}
+
+static void southbridge_smi_periodic(void)
+{
+ uint32_t reg32;
+
+ reg32 = inl(get_pmbase() + SMI_EN);
+
+ /* Are periodic SMIs enabled? */
+ if ((reg32 & PERIODIC_EN) == 0)
+ return;
+
+ printk(BIOS_DEBUG, "Periodic SMI.\n");
+}
+
+typedef void (*smi_handler_t)(void);
+
+static const smi_handler_t southbridge_smi[32] = {
+ NULL, // [0] reserved
+ NULL, // [1] reserved
+ NULL, // [2] BIOS_STS
+ NULL, // [3] LEGACY_USB_STS
+ southbridge_smi_sleep, // [4] SLP_SMI_STS
+ southbridge_smi_apmc, // [5] APM_STS
+ NULL, // [6] SWSMI_TMR_STS
+ NULL, // [7] reserved
+ southbridge_smi_pm1, // [8] PM1_STS
+ southbridge_smi_gpe0, // [9] GPE0_STS
+ NULL, // [10] reserved
+ NULL, // [11] reserved
+ NULL, // [12] reserved
+ southbridge_smi_tco, // [13] TCO_STS
+ southbridge_smi_periodic, // [14] PERIODIC_STS
+ NULL, // [15] SERIRQ_SMI_STS
+ NULL, // [16] SMBUS_SMI_STS
+ NULL, // [17] LEGACY_USB2_STS
+ NULL, // [18] INTEL_USB2_STS
+ NULL, // [19] reserved
+ NULL, // [20] PCI_EXP_SMI_STS
+ NULL, // [21] reserved
+ NULL, // [22] reserved
+ NULL, // [23] reserved
+ NULL, // [24] reserved
+ NULL, // [25] reserved
+ NULL, // [26] SPI_STS
+ NULL, // [27] reserved
+ NULL, // [28] PUNIT
+ NULL, // [29] GUNIT
+ NULL, // [30] reserved
+ NULL // [31] reserved
+};
+
+void southbridge_smi_handler(void)
+{
+ int i;
+ uint32_t smi_sts;
+
+ /* We need to clear the SMI status registers, or we won't see what's
+ * happening in the following calls.
+ */
+ smi_sts = clear_smi_status();
+
+ /* Call SMI sub handler for each of the status bits */
+ for (i = 0; i < ARRAY_SIZE(southbridge_smi); i++) {
+ if (!(smi_sts & (1 << i)))
+ continue;
+
+ if (southbridge_smi[i] != NULL) {
+ southbridge_smi[i]();
+ } else {
+ printk(BIOS_DEBUG,
+ "SMI_STS[%d] occurred, but no "
+ "handler available.\n", i);
+ }
+ }
+
+ /* The GPIO SMI events do not have a status bit in SMI_STS. Therefore,
+ * these events need to be cleared and checked unconditionally. */
+ mainboard_smi_gpi(clear_alt_status());
+}
diff --git a/src/soc/intel/braswell/smm.c b/src/soc/intel/braswell/smm.c
new file mode 100644
index 0000000000..bfddb6859b
--- /dev/null
+++ b/src/soc/intel/braswell/smm.c
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/smm.h>
+#include <string.h>
+
+#include <soc/iomap.h>
+#include <soc/pmc.h>
+#include <soc/smm.h>
+
+/* Save settings which will be committed in SMI functions. */
+static uint32_t smm_save_params[SMM_SAVE_PARAM_COUNT];
+
+void southcluster_smm_save_param(int param, uint32_t data)
+{
+ smm_save_params[param] = data;
+}
+
+void southcluster_smm_clear_state(void)
+{
+ uint32_t smi_en;
+
+ /* Log events from chipset before clearing */
+ southcluster_log_state();
+
+ printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
+ printk(BIOS_SPEW, " pmbase = 0x%04x\n", get_pmbase());
+
+ smi_en = inl(get_pmbase() + SMI_EN);
+ if (smi_en & APMC_EN) {
+ printk(BIOS_INFO, "SMI# handler already enabled?\n");
+ return;
+ }
+
+ /* Dump and clear status registers */
+ clear_smi_status();
+ clear_pm1_status();
+ clear_tco_status();
+ clear_gpe_status();
+ clear_alt_status();
+ clear_pmc_status();
+}
+
+static void southcluster_smm_route_gpios(void)
+{
+ u32 *gpio_rout = (u32 *)(PMC_BASE_ADDRESS + GPIO_ROUT);
+ const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI;
+ uint32_t alt_gpio_reg = 0;
+ uint32_t route_reg = smm_save_params[SMM_SAVE_PARAM_GPIO_ROUTE];
+ int i;
+
+ printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg);
+
+ /* Start the routing for the specific gpios. */
+ write32(gpio_rout, route_reg);
+
+ /* Enable SMIs for the gpios that are set to trigger the SMI. */
+ for (i = 0; i < 16; i++) {
+ if ((route_reg & ROUTE_MASK) == ROUTE_SMI) {
+ alt_gpio_reg |= (1 << i);
+ }
+ route_reg >>= 2;
+ }
+ printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg);
+
+ outl(alt_gpio_reg, alt_gpio_smi);
+}
+
+void southcluster_smm_enable_smi(void)
+{
+ uint16_t pm1_events = PWRBTN_EN | GBL_EN;
+
+ printk(BIOS_DEBUG, "Enabling SMIs.\n");
+ if (!smm_save_params[SMM_SAVE_PARAM_PCIE_WAKE_ENABLE])
+ pm1_events |= PCIEXPWAK_DIS;
+ enable_pm1(pm1_events);
+ disable_gpe(PME_B0_EN);
+
+ /* Set up the GPIO route. */
+ southcluster_smm_route_gpios();
+
+ /* Enable SMI generation:
+ * - on APMC writes (io 0xb2)
+ * - on writes to SLP_EN (sleep states)
+ * - on writes to GBL_RLS (bios commands)
+ * No SMIs:
+ * - on TCO events
+ * - on microcontroller writes (io 0x62/0x66)
+ */
+ enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | 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" ((uint32_t)gnvs),
+ "d" (APM_CNT)
+ );
+}
diff --git a/src/soc/intel/braswell/southcluster.c b/src/soc/intel/braswell/southcluster.c
new file mode 100644
index 0000000000..8df1f1a9e6
--- /dev/null
+++ b/src/soc/intel/braswell/southcluster.c
@@ -0,0 +1,572 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <bootstate.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <pc80/mc146818rtc.h>
+#include <drivers/uart/uart8250reg.h>
+
+#include <soc/iomap.h>
+#include <soc/irq.h>
+#include <soc/lpc.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/ramstage.h>
+#include <soc/spi.h>
+#include "chip.h"
+
+static inline void
+add_mmio_resource(device_t dev, int i, unsigned long addr, unsigned long size)
+{
+ mmio_resource(dev, i, addr >> 10, size >> 10);
+}
+
+static void sc_add_mmio_resources(device_t dev)
+{
+ add_mmio_resource(dev, 0xfeb, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE);
+ add_mmio_resource(dev, PBASE, PMC_BASE_ADDRESS, PMC_BASE_SIZE);
+ add_mmio_resource(dev, IOBASE, IO_BASE_ADDRESS, IO_BASE_SIZE);
+ add_mmio_resource(dev, IBASE, ILB_BASE_ADDRESS, ILB_BASE_SIZE);
+ add_mmio_resource(dev, SBASE, SPI_BASE_ADDRESS, SPI_BASE_SIZE);
+ add_mmio_resource(dev, MPBASE, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE);
+ add_mmio_resource(dev, PUBASE, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE);
+ add_mmio_resource(dev, RCBA, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE);
+}
+
+/* Default IO range claimed by the LPC device. The upper bound is exclusive. */
+#define LPC_DEFAULT_IO_RANGE_LOWER 0
+#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000
+
+static inline int io_range_in_default(int base, int size)
+{
+ /* Does it start above the range? */
+ if (base >= LPC_DEFAULT_IO_RANGE_UPPER)
+ return 0;
+
+ /* Is it entirely contained? */
+ if (base >= LPC_DEFAULT_IO_RANGE_LOWER &&
+ (base + size) < LPC_DEFAULT_IO_RANGE_UPPER)
+ return 1;
+
+ /* This will return not in range for partial overlaps. */
+ return 0;
+}
+
+/*
+ * Note: this function assumes there is no overlap with the default LPC device's
+ * claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER.
+ */
+static void sc_add_io_resource(device_t dev, int base, int size, int index)
+{
+ struct resource *res;
+
+ if (io_range_in_default(base, size))
+ return;
+
+ res = new_resource(dev, index);
+ res->base = base;
+ res->size = size;
+ res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void sc_add_io_resources(device_t dev)
+{
+ struct resource *res;
+
+ /* Add the default claimed IO range for the LPC device. */
+ res = new_resource(dev, 0);
+ res->base = LPC_DEFAULT_IO_RANGE_LOWER;
+ res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER;
+ res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
+ /* GPIO */
+ sc_add_io_resource(dev, GPIO_BASE_ADDRESS, 256, GBASE);
+
+ /* ACPI */
+ sc_add_io_resource(dev, ACPI_BASE_ADDRESS, 128, ABASE);
+}
+
+static void sc_read_resources(device_t dev)
+{
+ /* Get the normal PCI resources of this device. */
+ pci_dev_read_resources(dev);
+
+ /* Add non-standard MMIO resources. */
+ sc_add_mmio_resources(dev);
+
+ /* Add IO resources. */
+ sc_add_io_resources(dev);
+}
+
+static void sc_rtc_init(void)
+{
+ uint32_t gen_pmcon1;
+ int rtc_fail;
+ struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+
+ if (ps != NULL) {
+ gen_pmcon1 = ps->gen_pmcon1;
+ } else {
+ gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
+ }
+
+ rtc_fail = !!(gen_pmcon1 & RPS);
+
+ if (rtc_fail) {
+ printk(BIOS_DEBUG, "RTC failure.\n");
+ }
+
+ cmos_init(rtc_fail);
+}
+
+/*
+ * The UART hardware loses power while in suspend. Because of this the kernel
+ * can hang because it doesn't re-initialize serial ports it is using for
+ * consoles at resume time. The following function configures the UART
+ * if the hardware is enabled though it may not be the correct baud rate
+ * or configuration. This is definitely a hack, but it helps the kernel
+ * along.
+ */
+static void com1_configure_resume(device_t dev)
+{
+ const uint16_t port = 0x3f8;
+
+ /* Is the UART I/O port enabled? */
+ if (!(pci_read_config32(dev, UART_CONT) & 1))
+ return;
+
+ /* Disable interrupts */
+ outb(0x0, port + UART8250_IER);
+
+ /* Enable FIFOs */
+ outb(UART8250_FCR_FIFO_EN, port + UART8250_FCR);
+
+ /* assert DTR and RTS so the other end is happy */
+ outb(UART8250_MCR_DTR | UART8250_MCR_RTS, port + UART8250_MCR);
+
+ /* DLAB on */
+ outb(UART8250_LCR_DLAB | 3, port + UART8250_LCR);
+
+ /* Set Baud Rate Divisor. 1 ==> 115200 Baud */
+ outb(1, port + UART8250_DLL);
+ outb(0, port + UART8250_DLM);
+
+ /* Set to 3 for 8N1 */
+ outb(3, port + UART8250_LCR);
+}
+
+static void sc_init(device_t dev)
+{
+ int i;
+ u8 *pr_base = (u8 *)(ILB_BASE_ADDRESS + 0x08);
+ u16 *ir_base = (u16 *)ILB_BASE_ADDRESS + 0x20;
+ u32 *gen_pmcon1 = (u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1);
+ u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
+ const struct baytrail_irq_route *ir = &global_baytrail_irq_route;
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+
+ /* Set up the PIRQ PIC routing based on static config. */
+ for (i = 0; i < NUM_PIRQS; i++) {
+ write8(pr_base + i, ir->pic[i]);
+ }
+ /* Set up the per device PIRQ routing base on static config. */
+ for (i = 0; i < NUM_IR_DEVS; i++) {
+ write16(ir_base + i, ir->pcidev[i]);
+ }
+
+ /* Route SCI to IRQ9 */
+ write32(actl, (read32(actl) & ~SCIS_MASK) | SCIS_IRQ9);
+
+ sc_rtc_init();
+
+ if (config->disable_slp_x_stretch_sus_fail) {
+ printk(BIOS_DEBUG, "Disabling slp_x stretching.\n");
+ write32(gen_pmcon1,
+ read32(gen_pmcon1) | DIS_SLP_X_STRCH_SUS_UP);
+ } else {
+ write32(gen_pmcon1,
+ read32(gen_pmcon1) & ~DIS_SLP_X_STRCH_SUS_UP);
+ }
+
+ if (acpi_is_wakeup_s3())
+ com1_configure_resume(dev);
+}
+
+/*
+ * Common code for the south cluster devices.
+ */
+
+/* Set bit in function disable register to hide this device. */
+static void sc_disable_devfn(device_t dev)
+{
+ u32 *func_dis = (u32 *)(PMC_BASE_ADDRESS + FUNC_DIS);
+ u32 *func_dis2 = (u32 *)(PMC_BASE_ADDRESS + FUNC_DIS2);
+ uint32_t mask = 0;
+ uint32_t mask2 = 0;
+
+ switch (dev->path.pci.devfn) {
+ case PCI_DEVFN(SDIO_DEV, SDIO_FUNC):
+ mask |= SDIO_DIS;
+ break;
+ case PCI_DEVFN(SD_DEV, SD_FUNC):
+ mask |= SD_DIS;
+ break;
+ case PCI_DEVFN(SATA_DEV, SATA_FUNC):
+ mask |= SATA_DIS;
+ break;
+ case PCI_DEVFN(XHCI_DEV, XHCI_FUNC):
+ mask |= XHCI_DIS;
+ /* Disable super speed PHY when XHCI is not available. */
+ mask2 |= USH_SS_PHY_DIS;
+ break;
+ case PCI_DEVFN(LPE_DEV, LPE_FUNC):
+ mask |= LPE_DIS;
+ break;
+ case PCI_DEVFN(MMC_DEV, MMC_FUNC):
+ mask |= MMC_DIS;
+ break;
+ case PCI_DEVFN(SIO_DMA1_DEV, SIO_DMA1_FUNC):
+ mask |= SIO_DMA1_DIS;
+ break;
+ case PCI_DEVFN(I2C1_DEV, I2C1_FUNC):
+ mask |= I2C1_DIS;
+ break;
+ case PCI_DEVFN(I2C2_DEV, I2C2_FUNC):
+ mask |= I2C1_DIS;
+ break;
+ case PCI_DEVFN(I2C3_DEV, I2C3_FUNC):
+ mask |= I2C3_DIS;
+ break;
+ case PCI_DEVFN(I2C4_DEV, I2C4_FUNC):
+ mask |= I2C4_DIS;
+ break;
+ case PCI_DEVFN(I2C5_DEV, I2C5_FUNC):
+ mask |= I2C5_DIS;
+ break;
+ case PCI_DEVFN(I2C6_DEV, I2C6_FUNC):
+ mask |= I2C6_DIS;
+ break;
+ case PCI_DEVFN(I2C7_DEV, I2C7_FUNC):
+ mask |= I2C7_DIS;
+ break;
+ case PCI_DEVFN(TXE_DEV, TXE_FUNC):
+ mask |= TXE_DIS;
+ break;
+ case PCI_DEVFN(HDA_DEV, HDA_FUNC):
+ mask |= HDA_DIS;
+ break;
+ case PCI_DEVFN(PCIE_PORT1_DEV, PCIE_PORT1_FUNC):
+ mask |= PCIE_PORT1_DIS;
+ break;
+ case PCI_DEVFN(PCIE_PORT2_DEV, PCIE_PORT2_FUNC):
+ mask |= PCIE_PORT2_DIS;
+ break;
+ case PCI_DEVFN(PCIE_PORT3_DEV, PCIE_PORT3_FUNC):
+ mask |= PCIE_PORT3_DIS;
+ break;
+ case PCI_DEVFN(PCIE_PORT4_DEV, PCIE_PORT4_FUNC):
+ mask |= PCIE_PORT4_DIS;
+ break;
+ case PCI_DEVFN(EHCI_DEV, EHCI_FUNC):
+ mask |= EHCI_DIS;
+ break;
+ case PCI_DEVFN(SIO_DMA2_DEV, SIO_DMA2_FUNC):
+ mask |= SIO_DMA2_DIS;
+ break;
+ case PCI_DEVFN(PWM1_DEV, PWM1_FUNC):
+ mask |= PWM1_DIS;
+ break;
+ case PCI_DEVFN(PWM2_DEV, PWM2_FUNC):
+ mask |= PWM2_DIS;
+ break;
+ case PCI_DEVFN(HSUART1_DEV, HSUART1_FUNC):
+ mask |= HSUART1_DIS;
+ break;
+ case PCI_DEVFN(HSUART2_DEV, HSUART2_FUNC):
+ mask |= HSUART2_DIS;
+ break;
+ case PCI_DEVFN(SPI_DEV, SPI_FUNC):
+ mask |= SPI_DIS;
+ break;
+ case PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC):
+ mask2 |= SMBUS_DIS;
+ break;
+ }
+
+ if (mask != 0) {
+ write32(func_dis, read32(func_dis) | mask);
+ /* Ensure posted write hits. */
+ read32(func_dis);
+ }
+
+ if (mask2 != 0) {
+ write32(func_dis2, read32(func_dis2) | mask2);
+ /* Ensure posted write hits. */
+ read32(func_dis2);
+ }
+}
+
+static inline void set_d3hot_bits(device_t dev, int offset)
+{
+ uint32_t reg8;
+ printk(BIOS_DEBUG, "Power management CAP offset 0x%x.\n", offset);
+ reg8 = pci_read_config8(dev, offset + 4);
+ reg8 |= 0x3;
+ pci_write_config8(dev, offset + 4, reg8);
+}
+
+/* Parts of the audio subsystem are powered by the HDA device. Therefore, one
+ * cannot put HDA into D3Hot. Instead perform this workaround to make some of
+ * the audio paths work for LPE audio. */
+static void hda_work_around(device_t dev)
+{
+ u32 *gctl = (u32 *)(TEMP_BASE_ADDRESS + 0x8);
+
+ /* Need to set magic register 0x43 to 0xd7 in config space. */
+ pci_write_config8(dev, 0x43, 0xd7);
+
+ /* Need to set bit 0 of GCTL to take the device out of reset. However,
+ * that requires setting up the 64-bit BAR. */
+ pci_write_config32(dev, PCI_BASE_ADDRESS_0, TEMP_BASE_ADDRESS);
+ pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0);
+ pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
+ write32(gctl, read32(gctl) | 0x1);
+ pci_write_config8(dev, PCI_COMMAND, 0);
+ pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0);
+}
+
+static int place_device_in_d3hot(device_t dev)
+{
+ unsigned offset;
+
+ /* Parts of the HDA block are used for LPE audio as well.
+ * Therefore assume the HDA will never be put into D3Hot. */
+ if (dev->path.pci.devfn == PCI_DEVFN(HDA_DEV, HDA_FUNC)) {
+ hda_work_around(dev);
+ return 0;
+ }
+
+ offset = pci_find_capability(dev, PCI_CAP_ID_PM);
+
+ if (offset != 0) {
+ set_d3hot_bits(dev, offset);
+ return 0;
+ }
+
+ /* For some reason some of the devices don't have the capability
+ * pointer set correctly. Work around this by hard coding the offset. */
+ switch (dev->path.pci.devfn) {
+ case PCI_DEVFN(SDIO_DEV, SDIO_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(SD_DEV, SD_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(MMC_DEV, MMC_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(LPE_DEV, LPE_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(SIO_DMA1_DEV, SIO_DMA1_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C1_DEV, I2C1_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C2_DEV, I2C2_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C3_DEV, I2C3_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C4_DEV, I2C4_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C5_DEV, I2C5_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C6_DEV, I2C6_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(I2C7_DEV, I2C7_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(SIO_DMA2_DEV, SIO_DMA2_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(PWM1_DEV, PWM1_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(PWM2_DEV, PWM2_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(HSUART1_DEV, HSUART1_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(HSUART2_DEV, HSUART2_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(SPI_DEV, SPI_FUNC):
+ offset = 0x80;
+ break;
+ case PCI_DEVFN(SATA_DEV, SATA_FUNC):
+ offset = 0x70;
+ break;
+ case PCI_DEVFN(XHCI_DEV, XHCI_FUNC):
+ offset = 0x70;
+ break;
+ case PCI_DEVFN(EHCI_DEV, EHCI_FUNC):
+ offset = 0x70;
+ break;
+ case PCI_DEVFN(HDA_DEV, HDA_FUNC):
+ offset = 0x50;
+ break;
+ case PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC):
+ offset = 0x50;
+ break;
+ case PCI_DEVFN(TXE_DEV, TXE_FUNC):
+ /* TXE cannot be placed in D3Hot. */
+ return 0;
+ case PCI_DEVFN(PCIE_PORT1_DEV, PCIE_PORT1_FUNC):
+ offset = 0xa0;
+ break;
+ case PCI_DEVFN(PCIE_PORT2_DEV, PCIE_PORT2_FUNC):
+ offset = 0xa0;
+ break;
+ case PCI_DEVFN(PCIE_PORT3_DEV, PCIE_PORT3_FUNC):
+ offset = 0xa0;
+ break;
+ case PCI_DEVFN(PCIE_PORT4_DEV, PCIE_PORT4_FUNC):
+ offset = 0xa0;
+ break;
+ }
+
+ if (offset != 0) {
+ set_d3hot_bits(dev, offset);
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Common PCI device function disable. */
+void southcluster_enable_dev(device_t dev)
+{
+ uint32_t reg32;
+
+ if (!dev->enabled) {
+ int slot = PCI_SLOT(dev->path.pci.devfn);
+ int func = PCI_FUNC(dev->path.pci.devfn);
+ printk(BIOS_DEBUG, "%s: Disabling device: %02x.%01x\n",
+ dev_path(dev), slot, func);
+
+ /* Ensure memory, io, and bus master are all disabled */
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ reg32 &= ~(PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
+ pci_write_config32(dev, PCI_COMMAND, reg32);
+
+ /* Place device in D3Hot */
+ if (place_device_in_d3hot(dev) < 0) {
+ printk(BIOS_WARNING,
+ "Could not place %02x.%01x into D3Hot. "
+ "Keeping device visible.\n", slot, func);
+ return;
+ }
+ /* Disable this device if possible */
+ sc_disable_devfn(dev);
+ } else {
+ /* Enable SERR */
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ reg32 |= PCI_COMMAND_SERR;
+ pci_write_config32(dev, PCI_COMMAND, reg32);
+ }
+}
+
+static struct device_operations device_ops = {
+ .read_resources = sc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = NULL,
+ .init = sc_init,
+ .enable = southcluster_enable_dev,
+ .scan_bus = scan_static_bus,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = LPC_DEVID,
+};
+
+int __attribute__((weak)) mainboard_get_spi_config(struct spi_config *cfg)
+{
+ return -1;
+}
+
+static void finalize_chipset(void *unused)
+{
+ u32 *bcr = (u32 *)(SPI_BASE_ADDRESS + BCR);
+ u32 *gcs = (u32 *)(RCBA_BASE_ADDRESS + GCS);
+ u32 *gen_pmcon2 = (u32 *)(PMC_BASE_ADDRESS + GEN_PMCON2);
+ u32 *etr = (u32 *)(PMC_BASE_ADDRESS + ETR);
+ u8 *spi = (u8 *)SPI_BASE_ADDRESS;
+ struct spi_config cfg;
+
+ /* Set the lock enable on the BIOS control register. */
+ write32(bcr, read32(bcr) | BCR_LE);
+
+ /* Set BIOS lock down bit controlling boot block size and swapping. */
+ write32(gcs, read32(gcs) | BILD);
+
+ /* Lock sleep stretching policy and set SMI lock. */
+ write32(gen_pmcon2, read32(gen_pmcon2) | SLPSX_STR_POL_LOCK | SMI_LOCK);
+
+ /* Set the CF9 lock. */
+ write32(etr, read32(etr) | CF9LOCK);
+
+ if (mainboard_get_spi_config(&cfg) < 0) {
+ printk(BIOS_DEBUG, "No SPI lockdown configuration.\n");
+ } else {
+ write16(spi + PREOP, cfg.preop);
+ write16(spi + OPTYPE, cfg.optype);
+ write32(spi + OPMENU0, cfg.opmenu[0]);
+ write32(spi + OPMENU1, cfg.opmenu[1]);
+ write16(spi + HSFSTS, read16(spi + HSFSTS) | FLOCKDN);
+ write32(spi + UVSCC, cfg.uvscc);
+ write32(spi + LVSCC, cfg.lvscc | VCL);
+ }
+
+ printk(BIOS_DEBUG, "Finalizing SMM.\n");
+ outb(APM_CNT_FINALIZE, APM_CNT);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, finalize_chipset, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, finalize_chipset, NULL);
diff --git a/src/soc/intel/braswell/spi.c b/src/soc/intel/braswell/spi.c
new file mode 100644
index 0000000000..2795d3712b
--- /dev/null
+++ b/src/soc/intel/braswell/spi.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2013 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* This file is derived from the flashrom project. */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bootstate.h>
+#include <delay.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <spi_flash.h>
+
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+
+#ifdef __SMM__
+#define pci_read_config_byte(dev, reg, targ)\
+ *(targ) = pci_read_config8(dev, reg)
+#define pci_read_config_word(dev, reg, targ)\
+ *(targ) = pci_read_config16(dev, reg)
+#define pci_read_config_dword(dev, reg, targ)\
+ *(targ) = pci_read_config32(dev, reg)
+#define pci_write_config_byte(dev, reg, val)\
+ pci_write_config8(dev, reg, val)
+#define pci_write_config_word(dev, reg, val)\
+ pci_write_config16(dev, reg, val)
+#define pci_write_config_dword(dev, reg, val)\
+ pci_write_config32(dev, reg, val)
+#else /* !__SMM__ */
+#include <device/device.h>
+#include <device/pci.h>
+#define pci_read_config_byte(dev, reg, targ)\
+ *(targ) = pci_read_config8(dev, reg)
+#define pci_read_config_word(dev, reg, targ)\
+ *(targ) = pci_read_config16(dev, reg)
+#define pci_read_config_dword(dev, reg, targ)\
+ *(targ) = pci_read_config32(dev, reg)
+#define pci_write_config_byte(dev, reg, val)\
+ pci_write_config8(dev, reg, val)
+#define pci_write_config_word(dev, reg, val)\
+ pci_write_config16(dev, reg, val)
+#define pci_write_config_dword(dev, reg, val)\
+ pci_write_config32(dev, reg, val)
+#endif /* !__SMM__ */
+
+typedef struct spi_slave ich_spi_slave;
+
+static int ichspi_lock = 0;
+
+typedef struct ich9_spi_regs {
+ uint32_t bfpr;
+ uint16_t hsfs;
+ uint16_t hsfc;
+ uint32_t faddr;
+ uint32_t _reserved0;
+ uint32_t fdata[16];
+ uint32_t frap;
+ uint32_t freg[5];
+ uint32_t _reserved1[3];
+ uint32_t pr[5];
+ uint32_t _reserved2[2];
+ uint8_t ssfs;
+ uint8_t ssfc[3];
+ uint16_t preop;
+ uint16_t optype;
+ uint8_t opmenu[8];
+ uint32_t bbar;
+ uint8_t _reserved3[12];
+ uint32_t fdoc;
+ uint32_t fdod;
+ uint8_t _reserved4[8];
+ uint32_t afc;
+ uint32_t lvscc;
+ uint32_t uvscc;
+ uint8_t _reserved5[4];
+ uint32_t fpb;
+ uint8_t _reserved6[28];
+ uint32_t srdl;
+ uint32_t srdc;
+ uint32_t srd;
+} __attribute__((packed)) ich9_spi_regs;
+
+typedef struct ich_spi_controller {
+ int locked;
+
+ uint8_t *opmenu;
+ int menubytes;
+ uint16_t *preop;
+ uint16_t *optype;
+ uint32_t *addr;
+ uint8_t *data;
+ unsigned databytes;
+ uint8_t *status;
+ uint16_t *control;
+ uint32_t *bbar;
+} ich_spi_controller;
+
+static ich_spi_controller cntlr;
+
+enum {
+ SPIS_SCIP = 0x0001,
+ SPIS_GRANT = 0x0002,
+ SPIS_CDS = 0x0004,
+ SPIS_FCERR = 0x0008,
+ SSFS_AEL = 0x0010,
+ SPIS_LOCK = 0x8000,
+ SPIS_RESERVED_MASK = 0x7ff0,
+ SSFS_RESERVED_MASK = 0x7fe2
+};
+
+enum {
+ SPIC_SCGO = 0x000002,
+ SPIC_ACS = 0x000004,
+ SPIC_SPOP = 0x000008,
+ SPIC_DBC = 0x003f00,
+ SPIC_DS = 0x004000,
+ SPIC_SME = 0x008000,
+ SSFC_SCF_MASK = 0x070000,
+ SSFC_RESERVED = 0xf80000
+};
+
+enum {
+ HSFS_FDONE = 0x0001,
+ HSFS_FCERR = 0x0002,
+ HSFS_AEL = 0x0004,
+ HSFS_BERASE_MASK = 0x0018,
+ HSFS_BERASE_SHIFT = 3,
+ HSFS_SCIP = 0x0020,
+ HSFS_FDOPSS = 0x2000,
+ HSFS_FDV = 0x4000,
+ HSFS_FLOCKDN = 0x8000
+};
+
+enum {
+ HSFC_FGO = 0x0001,
+ HSFC_FCYCLE_MASK = 0x0006,
+ HSFC_FCYCLE_SHIFT = 1,
+ HSFC_FDBC_MASK = 0x3f00,
+ HSFC_FDBC_SHIFT = 8,
+ HSFC_FSMIE = 0x8000
+};
+
+enum {
+ SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0,
+ SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1,
+ SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2,
+ SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3
+};
+
+#if CONFIG_DEBUG_SPI_FLASH
+
+static u8 readb_(const void *addr)
+{
+ u8 v = read8((unsigned long)addr);
+ printk(BIOS_DEBUG, "read %2.2x from %4.4x\n",
+ v, ((unsigned) addr & 0xffff) - 0xf020);
+ return v;
+}
+
+static u16 readw_(const void *addr)
+{
+ u16 v = read16((unsigned long)addr);
+ printk(BIOS_DEBUG, "read %4.4x from %4.4x\n",
+ v, ((unsigned) addr & 0xffff) - 0xf020);
+ return v;
+}
+
+static u32 readl_(const void *addr)
+{
+ u32 v = read32((unsigned long)addr);
+ printk(BIOS_DEBUG, "read %8.8x from %4.4x\n",
+ v, ((unsigned) addr & 0xffff) - 0xf020);
+ return v;
+}
+
+static void writeb_(u8 b, const void *addr)
+{
+ write8(addr, b);
+ printk(BIOS_DEBUG, "wrote %2.2x to %4.4x\n",
+ b, ((unsigned) addr & 0xffff) - 0xf020);
+}
+
+static void writew_(u16 b, const void *addr)
+{
+ write16(addr, b);
+ printk(BIOS_DEBUG, "wrote %4.4x to %4.4x\n",
+ b, ((unsigned) addr & 0xffff) - 0xf020);
+}
+
+static void writel_(u32 b, const void *addr)
+{
+ write32(addr, b);
+ printk(BIOS_DEBUG, "wrote %8.8x to %4.4x\n",
+ b, ((unsigned) addr & 0xffff) - 0xf020);
+}
+
+#else /* CONFIG_DEBUG_SPI_FLASH ^^^ enabled vvv NOT enabled */
+
+#define readb_(a) read8(a)
+#define readw_(a) read16(a)
+#define readl_(a) read32(a)
+#define writeb_(val, addr) write8(addr, val)
+#define writew_(val, addr) write16(addr, val)
+#define writel_(val, addr) write32(addr, val)
+
+#endif /* CONFIG_DEBUG_SPI_FLASH ^^^ NOT enabled */
+
+static void write_reg(const void *value, void *dest, uint32_t size)
+{
+ const uint8_t *bvalue = value;
+ uint8_t *bdest = dest;
+
+ while (size >= 4) {
+ writel_(*(const uint32_t *)bvalue, bdest);
+ bdest += 4; bvalue += 4; size -= 4;
+ }
+ while (size) {
+ writeb_(*bvalue, bdest);
+ bdest++; bvalue++; size--;
+ }
+}
+
+static void read_reg(const void *src, void *value, uint32_t size)
+{
+ const uint8_t *bsrc = src;
+ uint8_t *bvalue = value;
+
+ while (size >= 4) {
+ *(uint32_t *)bvalue = readl_(bsrc);
+ bsrc += 4; bvalue += 4; size -= 4;
+ }
+ while (size) {
+ *bvalue = readb_(bsrc);
+ bsrc++; bvalue++; size--;
+ }
+}
+
+static void ich_set_bbar(uint32_t minaddr)
+{
+ const uint32_t bbar_mask = 0x00ffff00;
+ uint32_t ichspi_bbar;
+
+ minaddr &= bbar_mask;
+ ichspi_bbar = readl_(cntlr.bbar) & ~bbar_mask;
+ ichspi_bbar |= minaddr;
+ writel_(ichspi_bbar, cntlr.bbar);
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
+{
+ ich_spi_slave *slave = malloc(sizeof(*slave));
+
+ if (!slave) {
+ printk(BIOS_DEBUG, "ICH SPI: Bad allocation\n");
+ return NULL;
+ }
+
+ memset(slave, 0, sizeof(*slave));
+
+ slave->bus = bus;
+ slave->cs = cs;
+ return slave;
+}
+
+static ich9_spi_regs *spi_regs(void)
+{
+ device_t dev;
+ uint32_t sbase;
+
+#ifdef __SMM__
+ dev = PCI_DEV(0, LPC_DEV, LPC_FUNC);
+#else
+ dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
+#endif
+ pci_read_config_dword(dev, SBASE, &sbase);
+ sbase &= ~0x1ff;
+
+ return (void *)sbase;
+}
+
+void spi_init(void)
+{
+ ich9_spi_regs *ich9_spi = spi_regs();
+
+ ichspi_lock = readw_(&ich9_spi->hsfs) & HSFS_FLOCKDN;
+ cntlr.opmenu = ich9_spi->opmenu;
+ cntlr.menubytes = sizeof(ich9_spi->opmenu);
+ cntlr.optype = &ich9_spi->optype;
+ cntlr.addr = &ich9_spi->faddr;
+ cntlr.data = (uint8_t *)ich9_spi->fdata;
+ cntlr.databytes = sizeof(ich9_spi->fdata);
+ cntlr.status = &ich9_spi->ssfs;
+ cntlr.control = (uint16_t *)ich9_spi->ssfc;
+ cntlr.bbar = &ich9_spi->bbar;
+ cntlr.preop = &ich9_spi->preop;
+ ich_set_bbar(0);
+}
+
+#ifndef __SMM__
+static void spi_init_cb(void *unused)
+{
+ spi_init();
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
+#endif
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ /* Handled by ICH automatically. */
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* Handled by ICH automatically. */
+}
+
+typedef struct spi_transaction {
+ const uint8_t *out;
+ uint32_t bytesout;
+ uint8_t *in;
+ uint32_t bytesin;
+ uint8_t type;
+ uint8_t opcode;
+ uint32_t offset;
+} spi_transaction;
+
+static inline void spi_use_out(spi_transaction *trans, unsigned bytes)
+{
+ trans->out += bytes;
+ trans->bytesout -= bytes;
+}
+
+static inline void spi_use_in(spi_transaction *trans, unsigned bytes)
+{
+ trans->in += bytes;
+ trans->bytesin -= bytes;
+}
+
+static void spi_setup_type(spi_transaction *trans)
+{
+ trans->type = 0xFF;
+
+ /* Try to guess spi type from read/write sizes. */
+ if (trans->bytesin == 0) {
+ if (trans->bytesout > 4)
+ /*
+ * If bytesin = 0 and bytesout > 4, we presume this is
+ * a write data operation, which is accompanied by an
+ * address.
+ */
+ trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
+ else
+ trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
+ return;
+ }
+
+ if (trans->bytesout == 1) { /* and bytesin is > 0 */
+ trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
+ return;
+ }
+
+ if (trans->bytesout == 4) { /* and bytesin is > 0 */
+ trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
+ }
+
+ /* Fast read command is called with 5 bytes instead of 4 */
+ if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) {
+ trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
+ --trans->bytesout;
+ }
+}
+
+static int spi_setup_opcode(spi_transaction *trans)
+{
+ uint16_t optypes;
+ uint8_t opmenu[cntlr.menubytes];
+
+ trans->opcode = trans->out[0];
+ spi_use_out(trans, 1);
+ if (!ichspi_lock) {
+ /* The lock is off, so just use index 0. */
+ writeb_(trans->opcode, cntlr.opmenu);
+ optypes = readw_(cntlr.optype);
+ optypes = (optypes & 0xfffc) | (trans->type & 0x3);
+ writew_(optypes, cntlr.optype);
+ return 0;
+ } else {
+ /* The lock is on. See if what we need is on the menu. */
+ uint8_t optype;
+ uint16_t opcode_index;
+
+ /* Write Enable is handled as atomic prefix */
+ if (trans->opcode == SPI_OPCODE_WREN)
+ return 0;
+
+ read_reg(cntlr.opmenu, opmenu, sizeof(opmenu));
+ for (opcode_index = 0; opcode_index < cntlr.menubytes;
+ opcode_index++) {
+ if (opmenu[opcode_index] == trans->opcode)
+ break;
+ }
+
+ if (opcode_index == cntlr.menubytes) {
+ printk(BIOS_DEBUG, "ICH SPI: Opcode %x not found\n",
+ trans->opcode);
+ return -1;
+ }
+
+ optypes = readw_(cntlr.optype);
+ optype = (optypes >> (opcode_index * 2)) & 0x3;
+ if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
+ optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
+ trans->bytesout >= 3) {
+ /* We guessed wrong earlier. Fix it up. */
+ trans->type = optype;
+ }
+ if (optype != trans->type) {
+ printk(BIOS_DEBUG, "ICH SPI: Transaction doesn't fit type %d\n",
+ optype);
+ return -1;
+ }
+ return opcode_index;
+ }
+}
+
+static int spi_setup_offset(spi_transaction *trans)
+{
+ /* Separate the SPI address and data. */
+ switch (trans->type) {
+ case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
+ case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
+ return 0;
+ case SPI_OPCODE_TYPE_READ_WITH_ADDRESS:
+ case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS:
+ trans->offset = ((uint32_t)trans->out[0] << 16) |
+ ((uint32_t)trans->out[1] << 8) |
+ ((uint32_t)trans->out[2] << 0);
+ spi_use_out(trans, 3);
+ return 1;
+ default:
+ printk(BIOS_DEBUG, "Unrecognized SPI transaction type %#x\n", trans->type);
+ return -1;
+ }
+}
+
+/*
+ * Wait for up to 60ms til status register bit(s) turn 1 (in case wait_til_set
+ * below is True) or 0. In case the wait was for the bit(s) to set - write
+ * those bits back, which would cause resetting them.
+ *
+ * Return the last read status value on success or -1 on failure.
+ */
+static int ich_status_poll(u16 bitmask, int wait_til_set)
+{
+ int timeout = 40000; /* This will result in 400 ms */
+ u16 status = 0;
+
+ while (timeout--) {
+ status = readw_(cntlr.status);
+ if (wait_til_set ^ ((status & bitmask) == 0)) {
+ if (wait_til_set)
+ writew_((status & bitmask), cntlr.status);
+ return status;
+ }
+ udelay(10);
+ }
+
+ printk(BIOS_DEBUG, "ICH SPI: SCIP timeout, read %x, expected %x\n",
+ status, bitmask);
+ return -1;
+}
+
+unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
+{
+ return min(cntlr.databytes, buf_len);
+}
+
+int spi_xfer(struct spi_slave *slave, const void *dout,
+ unsigned int bytesout, void *din, unsigned int bytesin)
+{
+ uint16_t control;
+ int16_t opcode_index;
+ int with_address;
+ int status;
+
+ spi_transaction trans = {
+ dout, bytesout,
+ din, bytesin,
+ 0xff, 0xff, 0
+ };
+
+ /* There has to always at least be an opcode. */
+ if (!bytesout || !dout) {
+ printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n");
+ return -1;
+ }
+ /* Make sure if we read something we have a place to put it. */
+ if (bytesin != 0 && !din) {
+ printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n");
+ return -1;
+ }
+
+ if (ich_status_poll(SPIS_SCIP, 0) == -1)
+ return -1;
+
+ writew_(SPIS_CDS | SPIS_FCERR, cntlr.status);
+
+ spi_setup_type(&trans);
+ if ((opcode_index = spi_setup_opcode(&trans)) < 0)
+ return -1;
+ if ((with_address = spi_setup_offset(&trans)) < 0)
+ return -1;
+
+ if (trans.opcode == SPI_OPCODE_WREN) {
+ /*
+ * Treat Write Enable as Atomic Pre-Op if possible
+ * in order to prevent the Management Engine from
+ * issuing a transaction between WREN and DATA.
+ */
+ if (!ichspi_lock)
+ writew_(trans.opcode, cntlr.preop);
+ return 0;
+ }
+
+ /* Preset control fields */
+ control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
+
+ /* Issue atomic preop cycle if needed */
+ if (readw_(cntlr.preop))
+ control |= SPIC_ACS;
+
+ if (!trans.bytesout && !trans.bytesin) {
+ /* SPI addresses are 24 bit only */
+ if (with_address)
+ writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
+
+ /*
+ * This is a 'no data' command (like Write Enable), its
+ * bytesout size was 1, decremented to zero while executing
+ * spi_setup_opcode() above. Tell the chip to send the
+ * command.
+ */
+ writew_(control, cntlr.control);
+
+ /* wait for the result */
+ status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
+ if (status == -1)
+ return -1;
+
+ if (status & SPIS_FCERR) {
+ printk(BIOS_DEBUG, "ICH SPI: Command transaction error\n");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /*
+ * Check if this is a write command attempting to transfer more bytes
+ * than the controller can handle. Iterations for writes are not
+ * supported here because each SPI write command needs to be preceded
+ * and followed by other SPI commands, and this sequence is controlled
+ * by the SPI chip driver.
+ */
+ if (trans.bytesout > cntlr.databytes) {
+ printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use"
+ " spi_crop_chunk()?\n");
+ return -1;
+ }
+
+ /*
+ * Read or write up to databytes bytes at a time until everything has
+ * been sent.
+ */
+ while (trans.bytesout || trans.bytesin) {
+ uint32_t data_length;
+
+ /* SPI addresses are 24 bit only */
+ writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
+
+ if (trans.bytesout)
+ data_length = min(trans.bytesout, cntlr.databytes);
+ else
+ data_length = min(trans.bytesin, cntlr.databytes);
+
+ /* Program data into FDATA0 to N */
+ if (trans.bytesout) {
+ write_reg(trans.out, cntlr.data, data_length);
+ spi_use_out(&trans, data_length);
+ if (with_address)
+ trans.offset += data_length;
+ }
+
+ /* Add proper control fields' values */
+ control &= ~((cntlr.databytes - 1) << 8);
+ control |= SPIC_DS;
+ control |= (data_length - 1) << 8;
+
+ /* write it */
+ writew_(control, cntlr.control);
+
+ /* Wait for Cycle Done Status or Flash Cycle Error. */
+ status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
+ if (status == -1)
+ return -1;
+
+ if (status & SPIS_FCERR) {
+ printk(BIOS_DEBUG, "ICH SPI: Data transaction error\n");
+ return -1;
+ }
+
+ if (trans.bytesin) {
+ read_reg(cntlr.data, trans.in, data_length);
+ spi_use_in(&trans, data_length);
+ if (with_address)
+ trans.offset += data_length;
+ }
+ }
+
+ /* Clear atomic preop now that xfer is done */
+ writew_(0, cntlr.preop);
+
+ return 0;
+}
diff --git a/src/soc/intel/braswell/stage_cache.c b/src/soc/intel/braswell/stage_cache.c
new file mode 100644
index 0000000000..a4f510d2f4
--- /dev/null
+++ b/src/soc/intel/braswell/stage_cache.c
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cbmem.h>
+#include <stage_cache.h>
+#include <soc/smm.h>
+
+void stage_cache_external_region(void **base, size_t *size)
+{
+ char *smm_base;
+ /* 1MiB cache size */
+ const long cache_size = CONFIG_SMM_RESERVED_SIZE;
+
+ /* Ramstage cache lives in TSEG region which is the definition of
+ * cbmem_top(). */
+ smm_base = cbmem_top();
+ *size = cache_size;
+ *base = &smm_base[smm_region_size() - cache_size];
+}
diff --git a/src/soc/intel/braswell/tsc_freq.c b/src/soc/intel/braswell/tsc_freq.c
new file mode 100644
index 0000000000..700b0985ca
--- /dev/null
+++ b/src/soc/intel/braswell/tsc_freq.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/tsc.h>
+#include <soc/msr.h>
+
+unsigned bus_freq_khz(void)
+{
+ msr_t clk_info = rdmsr(MSR_BSEL_CR_OVERCLOCK_CONTROL);
+ switch (clk_info.lo & 0x3) {
+ case 0:
+ return 83333;
+ case 1:
+ return 100000;
+ case 2:
+ return 133333;
+ case 3:
+ return 116666;
+ default:
+ return 0;
+ }
+}
+
+unsigned long tsc_freq_mhz(void)
+{
+ msr_t platform_info;
+ unsigned bclk_khz = bus_freq_khz();
+
+ if (!bclk_khz)
+ return 0;
+
+ platform_info = rdmsr(MSR_PLATFORM_INFO);
+ return (bclk_khz * ((platform_info.lo >> 8) & 0xff)) / 1000;
+}
+
+#if !defined(__SMM__)
+#if !defined(__PRE_RAM__)
+#include <soc/ramstage.h>
+#else
+#include <soc/romstage.h>
+#endif
+
+void set_max_freq(void)
+{
+ msr_t perf_ctl;
+ msr_t msr;
+
+ /* Enable speed step. */
+ msr = rdmsr(MSR_IA32_MISC_ENABLES);
+ msr.lo |= (1 << 16);
+ wrmsr(MSR_IA32_MISC_ENABLES, msr);
+
+ /* Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
+ * the PERF_CTL. */
+ msr = rdmsr(MSR_IACORE_RATIOS);
+ perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
+ /* Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
+ * the PERF_CTL. */
+ msr = rdmsr(MSR_IACORE_VIDS);
+ perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
+ perf_ctl.hi = 0;
+
+ wrmsr(MSR_IA32_PERF_CTL, perf_ctl);
+}
+
+#endif /* __SMM__ */
diff --git a/src/soc/intel/braswell/xhci.c b/src/soc/intel/braswell/xhci.c
new file mode 100644
index 0000000000..776e44cc9f
--- /dev/null
+++ b/src/soc/intel/braswell/xhci.c
@@ -0,0 +1,259 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/acpi.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdint.h>
+#include <reg_script.h>
+
+#include <soc/iomap.h>
+#include <soc/iosf.h>
+#include <soc/lpc.h>
+#include <soc/pattrs.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/ramstage.h>
+#include <soc/xhci.h>
+
+#include "chip.h"
+
+struct reg_script usb3_phy_script[] = {
+ /* USB3PHYInit() */
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_PLL_CONTROL,
+ ~0x00700000, 0x00500000),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_VCO_START_CAL_POINT,
+ ~0x001f0000, 0x000A0000),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CCDRLF,
+ ~0x0000000f, 0x0000000b),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_PEAKING_AMP_CONFIG_DIAG,
+ ~0x000000f0, 0x000000f0),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_OFFSET_COR_CONFIG_DIAG,
+ ~0x000001c0, 0x00000000),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_VGA_GAIN_CONFIG_DIAG,
+ ~0x00000070, 0x00000020),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_REE_DAC_CONTROL,
+ ~0x00000002, 0x00000002),
+ REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_U1_POWER_STATE_DEF,
+ ~0x00000000, 0x00040000),
+ REG_SCRIPT_END
+};
+
+const struct reg_script xhci_init_script[] = {
+ /* CommonXhciHcInit() */
+ /* BAR + 0x0c[31:16] = 0x0200 */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0x0000ffff, 0x02000000),
+ /* BAR + 0x0c[7:0] = 0x0a */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0xffffff00, 0x0000000a),
+ /* BAR + 0x8094[23,21,14]=111b */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8094, 0x00a04000),
+ /* BAR + 0x8110[20,11,8,2]=1100b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8110, ~0x00000104, 0x00100800),
+ /* BAR + 0x8144[8,7,6]=111b */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8144, 0x000001c0),
+ /* BAR + 0x8154[21,13,3]=010b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8154, ~0x00200008, 0x80002000),
+ /* BAR + 0x816c[19:0]=1110x100000000111100b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x816c, 0xfff08000, 0x000e0030),
+ /* BAR + 0x8188[26,24]=11b */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8188, 0x05000000),
+ /* BAR + 0x8174=0x1000c0a*/
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8174, 0xfe000000, 0x01000c0a),
+ /* BAR + 0x854c[29]=0b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x854c, ~0x20000000, 0),
+ /* BAR + 0x8178[12:0]=0b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8178, ~0xffffe000, 0),
+ /* BAR + 0x8164[7:0]=0xff */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8164, 0x000000ff),
+ /* BAR + 0x0010[10,9,5]=110b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0010, ~0x00000020, 0x00000600),
+ /* BAR + 0x8058[20,16,8]=110b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8058, ~0x00000100, 0x00110000),
+ /* BAR + 0x8060[25]=1b */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8060, 0x02000000),
+ /* BAR + 0x80f0[20]=0b */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80f0, ~0x00100000, 0),
+ /* BAR + 0x8008[19]=1b (to enable LPM) */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8008, 0x00080000),
+ /* BAR + 0x80fc[25]=1b */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x80fc, 0x02000000),
+ /* 0x40/0x44 are written as bytes to avoid touching bit31 */
+ /* D20:F0:40[21,20,18,10,9,8]=111001b (don't write byte3) */
+ REG_PCI_RMW8(0x41, ~0x06, 0x01),
+ /* Except [21,20,19,18]=0001b USB wake W/A is disable IIL1E */
+ REG_PCI_RMW8(0x42, 0x3c, 0x04),
+ /* D20:F0:44[19:14,10,9,7,3:0]=1 (don't write byte3) */
+ REG_PCI_RMW8(0x44, 0x00, 0x8f),
+ REG_PCI_RMW8(0x45, ~0xcf, 0xc6),
+ REG_PCI_RMW8(0x46, ~0x0f, 0x0f),
+ /* BAR + 0x8140 = 0xff00f03c */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8140, 0, 0xff00f03c),
+ REG_SCRIPT_END
+};
+
+const struct reg_script xhci_init_boot_script[] = {
+ /* Setup USB3 phy */
+ REG_SCRIPT_NEXT(usb3_phy_script),
+ /* Initialize host controller */
+ REG_SCRIPT_NEXT(xhci_init_script),
+ /* BAR + 0x80e0[16,9,6]=001b, toggle bit 24=1 */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x00010200, 0x01000040),
+ /* BAR + 0x80e0 toggle bit 24=0 */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01000000, 0),
+ REG_SCRIPT_END
+};
+
+const struct reg_script xhci_init_resume_script[] = {
+ /* Setup USB3 phy */
+ REG_SCRIPT_NEXT(usb3_phy_script),
+ /* Initialize host controller */
+ REG_SCRIPT_NEXT(xhci_init_script),
+ /* BAR + 0x80e0[16,9,6]=001b, leave bit 24=0 to prevent HC reset */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01010200, 0x00000040),
+ REG_SCRIPT_END
+};
+
+const struct reg_script xhci_clock_gating_script[] = {
+ /* ConfigureXhciClockGating() */
+ /* D20:F0:40[21:19,18,10:8]=000,1,001 (don't write byte 3) */
+ REG_PCI_RMW16(0x40, ~0x0600, 0x0100),
+ REG_PCI_RMW8(0x42, ~0x38, 0x04),
+ /* D20:F0:44[5:3]=001b */
+ REG_PCI_RMW16(0x44, ~0x0030, 0x0008),
+ /* D20:F0:A0[19:18]=01b */
+ REG_PCI_RMW32(0xa0, ~0x00080000, 0x00040000),
+ /* D20:F0:A4[15:0]=0x00 */
+ REG_PCI_WRITE16(0xa4, 0x0000),
+ /* D20:F0:B0[21:17,14:13]=0000000b */
+ REG_PCI_RMW32(0xb0, ~0x00376000, 0x00000000),
+ /* D20:F0:50[31:0]=0x0bce6e5f */
+ REG_PCI_WRITE32(0x50, 0x0bce6e5f),
+ REG_SCRIPT_END
+};
+
+/* Warm Reset a USB3 port */
+static void xhci_reset_port_usb3(device_t dev, int port)
+{
+ struct reg_script reset_port_usb3_script[] = {
+ /* Issue Warm Port Rest to the port */
+ REG_RES_OR32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
+ XHCI_USB3_PORTSC_WPR),
+ /* Wait up to 100ms for it to complete */
+ REG_RES_POLL32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
+ XHCI_USB3_PORTSC_WRC, XHCI_USB3_PORTSC_WRC,
+ XHCI_RESET_TIMEOUT),
+ /* Clear change status bits, do not set PED */
+ REG_RES_RMW32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port),
+ ~XHCI_USB3_PORTSC_PED, XHCI_USB3_PORTSC_CHST),
+ REG_SCRIPT_END
+ };
+ reg_script_run_on_dev(dev, reset_port_usb3_script);
+}
+
+/* Prepare ports to be routed to EHCI or XHCI */
+static void xhci_route_all(device_t dev)
+{
+ static const struct reg_script xhci_route_all_script[] = {
+ /* USB3 SuperSpeed Enable */
+ REG_PCI_WRITE32(XHCI_USB3PR, BYTM_USB3_PORT_MAP),
+ /* USB2 Port Route to XHCI */
+ REG_PCI_WRITE32(XHCI_USB2PR, BYTM_USB2_PORT_MAP),
+ REG_SCRIPT_END
+ };
+ u32 port_disabled;
+ int port;
+
+ printk(BIOS_INFO, "USB: Route ports to XHCI controller\n");
+
+ /* Route ports to XHCI controller */
+ reg_script_run_on_dev(dev, xhci_route_all_script);
+
+ if (acpi_is_wakeup_s3())
+ return;
+
+ /* Reset enabled USB3 ports */
+ port_disabled = pci_read_config32(dev, XHCI_USB3PDO);
+ for (port = 0; port < BYTM_USB3_PORT_COUNT; port++) {
+ if (port_disabled & (1 << port))
+ continue;
+ xhci_reset_port_usb3(dev, port);
+ }
+}
+
+static void xhci_init(device_t dev)
+{
+ struct soc_intel_baytrail_config *config = dev->chip_info;
+ struct reg_script xhci_hc_init[] = {
+ /* Initialize clock gating */
+ REG_SCRIPT_NEXT(xhci_clock_gating_script),
+ /* Finalize XHCC1 and XHCC2 */
+ REG_PCI_RMW32(0x44, ~0x00000000, 0x83c00000),
+ REG_PCI_RMW32(0x40, ~0x00800000, 0x80000000),
+ /* Set USB2 Port Routing Mask */
+ REG_PCI_WRITE32(XHCI_USB2PRM, BYTM_USB2_PORT_MAP),
+ /* Set USB3 Port Routing Mask */
+ REG_PCI_WRITE32(XHCI_USB3PRM, BYTM_USB3_PORT_MAP),
+ /*
+ * Disable ports if requested
+ */
+ /* Open per-port disable control override */
+ REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN),
+ REG_PCI_WRITE32(XHCI_USB2PDO, config->usb2_port_disable_mask),
+ REG_PCI_WRITE32(XHCI_USB3PDO, config->usb3_port_disable_mask),
+ /* Close per-port disable control override */
+ REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0),
+ REG_SCRIPT_END
+ };
+
+ /* Initialize XHCI controller for boot or resume path */
+ if (acpi_is_wakeup_s3())
+ reg_script_run_on_dev(dev, xhci_init_resume_script);
+ else
+ reg_script_run_on_dev(dev, xhci_init_boot_script);
+
+ /* C0 steppings change iCLK/USB PLL VCO settings from 5 to 7 */
+ if (pattrs_get()->stepping == STEP_C0) {
+ uint32_t reg = iosf_ushphy_read(USHPHY_CDN_PLL_CONTROL);
+ reg |= 0x00700000;
+ iosf_ushphy_write(USHPHY_CDN_PLL_CONTROL, reg);
+ }
+
+ /* Finalize Initialization */
+ reg_script_run_on_dev(dev, xhci_hc_init);
+
+ /* Route all ports to XHCI if requested */
+ if (config->usb_route_to_xhci)
+ xhci_route_all(dev);
+}
+
+static struct device_operations xhci_device_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = xhci_init,
+ .ops_pci = &soc_pci_ops,
+};
+
+static const struct pci_driver baytrail_xhci __pci_driver = {
+ .ops = &xhci_device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = XHCI_DEVID
+};