summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/fsp_broadwell_de/Kconfig85
-rw-r--r--src/soc/intel/fsp_broadwell_de/Makefile.inc35
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi.c454
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi/irq_helper.h45
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi/irqlinks.asl464
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi/irqroute.asl39
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi/lpc.asl92
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi/pcie1.asl465
-rw-r--r--src/soc/intel/fsp_broadwell_de/acpi/southcluster.asl350
-rw-r--r--src/soc/intel/fsp_broadwell_de/bootblock/bootblock.c23
-rw-r--r--src/soc/intel/fsp_broadwell_de/chip.c106
-rw-r--r--src/soc/intel/fsp_broadwell_de/chip.h29
-rw-r--r--src/soc/intel/fsp_broadwell_de/cpu.c110
-rw-r--r--src/soc/intel/fsp_broadwell_de/fsp/Kconfig93
-rw-r--r--src/soc/intel/fsp_broadwell_de/fsp/Makefile.inc17
-rw-r--r--src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c126
-rw-r--r--src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.h35
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/acpi.h27
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h20
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/iomap.h66
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/irq.h88
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/lpc.h86
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/msr.h28
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/pattrs.h52
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h110
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/ramstage.h30
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/reset.h24
-rw-r--r--src/soc/intel/fsp_broadwell_de/include/soc/romstage.h35
-rw-r--r--src/soc/intel/fsp_broadwell_de/memmap.c23
-rw-r--r--src/soc/intel/fsp_broadwell_de/northcluster.c156
-rw-r--r--src/soc/intel/fsp_broadwell_de/ramstage.c86
-rw-r--r--src/soc/intel/fsp_broadwell_de/reset.c29
-rw-r--r--src/soc/intel/fsp_broadwell_de/romstage/Makefile.inc3
-rw-r--r--src/soc/intel/fsp_broadwell_de/romstage/romstage.c120
-rw-r--r--src/soc/intel/fsp_broadwell_de/southcluster.c267
-rw-r--r--src/soc/intel/fsp_broadwell_de/spi.c633
-rw-r--r--src/soc/intel/fsp_broadwell_de/uart.c112
37 files changed, 4563 insertions, 0 deletions
diff --git a/src/soc/intel/fsp_broadwell_de/Kconfig b/src/soc/intel/fsp_broadwell_de/Kconfig
new file mode 100644
index 0000000000..14db2e3bda
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/Kconfig
@@ -0,0 +1,85 @@
+config SOC_INTEL_FSP_BROADWELL_DE
+ bool
+ help
+ Broadwell-DE support using the Intel FSP.
+
+if SOC_INTEL_FSP_BROADWELL_DE
+
+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 HAVE_HARD_RESET
+ select MMCONF_SUPPORT
+ select MMCONF_SUPPORT_DEFAULT
+ select RELOCATABLE_MODULES
+ select PARALLEL_MP
+ select SMP
+ select IOAPIC
+ select SPI_FLASH
+ select UDELAY_TSC
+ select SUPPORT_CPU_UCODE_IN_CBFS
+ # Microcode header files are delivered in FSP package
+ select USES_MICROCODE_HEADER_FILES if HAVE_FSP_BIN
+
+config CBFS_SIZE
+ hex
+ default 0x200000
+
+config RAMTOP
+ hex
+ default 0x400000
+
+config HEAP_SIZE
+ hex
+ default 0x100000
+
+config BOOTBLOCK_CPU_INIT
+ string
+ default "soc/intel/fsp_broadwell_de/bootblock/bootblock.c"
+
+config MMCONF_BASE_ADDRESS
+ hex
+ default 0x80000000
+
+config MAX_CPUS
+ int
+ default 16
+
+config CPU_ADDR_BITS
+ int
+ default 36
+
+config VGA_BIOS
+ bool
+ default n
+
+config INTEGRATED_UART
+ bool "Integrated UART ports"
+ default y
+ select HAVE_UART_SPECIAL
+ select CONSOLE_SERIAL
+ help
+ Use Broadwell-DE Integrated UART ports @3F8h and 2F8h.
+
+config DRIVERS_UART_8250IO
+ bool "Serial port on SuperIO (Broadwell-DE's UART ports unselected)"
+ depends on !INTEGRATED_UART
+ help
+ Select to choose SuperIO's serial port for console output.
+ CANNOT select if intend to use SoC integrated serial ports.
+
+config CONSOLE_CBMEM
+ bool "Send console output to a CBMEM buffer"
+ default n
+
+config CPU_MICROCODE_HEADER_FILES
+ string
+ default "../intel/cpu/broadwell_de/microcode/M1050663_07000001.h ../intel/cpu/broadwell_de/microcode/M1050662_0000000A.h ../intel/cpu/broadwell_de/microcode/MFF50661_F1000008.h"
+
+## Broadwell-DE Specific FSP Kconfig
+source src/soc/intel/fsp_broadwell_de/fsp/Kconfig
+
+endif # SOC_INTEL_FSP_BROADWELL_DE
diff --git a/src/soc/intel/fsp_broadwell_de/Makefile.inc b/src/soc/intel/fsp_broadwell_de/Makefile.inc
new file mode 100644
index 0000000000..a0d5203fc4
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/Makefile.inc
@@ -0,0 +1,35 @@
+ifeq ($(CONFIG_SOC_INTEL_FSP_BROADWELL_DE),y)
+
+subdirs-y += romstage
+subdirs-y += ../../../cpu/intel/microcode
+subdirs-y += ../../../cpu/intel/turbo
+subdirs-y += ../../../cpu/x86/lapic
+subdirs-y += ../../../cpu/x86/mtrr
+subdirs-y += ../../../cpu/x86/tsc
+subdirs-y += ../../../cpu/x86/cache
+subdirs-y += ../../../lib/fsp
+subdirs-y += fsp
+
+ramstage-y += spi.c
+ramstage-y += cpu.c
+ramstage-y += chip.c
+ramstage-y += northcluster.c
+ramstage-y += ramstage.c
+romstage-y += memmap.c
+ramstage-y += memmap.c
+ramstage-y += southcluster.c
+romstage-y += reset.c
+ramstage-y += reset.c
+ramstage-y += acpi.c
+
+ifeq ($(CONFIG_INTEGRATED_UART),y)
+romstage-y += uart.c
+ramstage-y += uart.c
+smm-$(CONFIG_DEBUG_SMI) += uart.c
+endif
+
+CPPFLAGS_common += -I$(src)/soc/intel/fsp_broadwell_de/include
+CPPFLAGS_common += -I$(src)/soc/intel/fsp_broadwell_de/fsp
+CPPFLAGS_common += -I$(src)/soc/intel/fsp_broadwell_de/
+
+endif # ifeq ($(CONFIG_SOC_INTEL_FSP_BROADWELL_DE),y)
diff --git a/src/soc/intel/fsp_broadwell_de/acpi.c b/src/soc/intel/fsp_broadwell_de/acpi.c
new file mode 100644
index 0000000000..afa4048f09
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi.c
@@ -0,0 +1,454 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <string.h>
+#include <types.h>
+#include <arch/acpigen.h>
+#include <arch/cpu.h>
+#include <arch/io.h>
+#include <arch/smp/mpspec.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/intel/speedstep.h>
+#include <cpu/intel/turbo.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/acpi.h>
+#include <soc/iomap.h>
+#include <soc/irq.h>
+#include <soc/lpc.h>
+#include <soc/msr.h>
+#include <soc/pattrs.h>
+#include <soc/pci_devs.h>
+#include <chip.h>
+
+uint16_t get_pmbase(void)
+{
+ return ACPI_BASE_ADDRESS;
+}
+
+#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 */
+static acpi_cstate_t cstate_map[] = {
+ {
+ /* C1 */
+ .ctype = 1, /* ACPI C1 */
+ .latency = 1,
+ .power = 1000,
+ .resource = MWAIT_RES(0, 0),
+ },
+ {
+ /* C3 */
+ .ctype = 2, /* ACPI C2 */
+ .latency = 15,
+ .power = 500,
+ .resource = MWAIT_RES(1, 0),
+ },
+ {
+ /* C6 */
+ .ctype = 3, /* ACPI C3 */
+ .latency = 41,
+ .power = 350,
+ .resource = MWAIT_RES(2, 0),
+ }
+};
+
+static int acpi_sci_irq(void)
+{
+ return 9;
+}
+
+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;
+}
+
+/**
+ * Fill in the fadt with generic values that can be overridden later.
+ */
+
+void acpi_fill_in_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
+{
+ acpi_header_t *header = &(fadt->header);
+ u16 pmbase = get_pmbase();
+
+ memset((void *) fadt, 0, sizeof(acpi_fadt_t));
+
+ /*
+ * Reference section 5.2.9 Fixed ACPI Description Table (FADT)
+ * in the ACPI 3.0b specification.
+ */
+
+ /* FADT Header Structure */
+ memcpy(header->signature, "FACP", 4);
+ header->length = sizeof(acpi_fadt_t);
+ header->revision = ACPI_FADT_REV_ACPI_3_0;
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+ header->asl_compiler_revision = 1;
+
+ /* ACPI Pointers */
+ fadt->firmware_ctrl = (unsigned long) facs;
+ fadt->dsdt = (unsigned long) dsdt;
+
+ fadt->model = 0; /* reserved, should be 0 ACPI 3.0 */
+ fadt->preferred_pm_profile = 0;
+ fadt->sci_int = acpi_sci_irq();
+
+ /* System Management */
+ fadt->smi_cmd = 0x00; /* disable SMM */
+ fadt->acpi_enable = 0x00; /* unused if SMI_CMD = 0 */
+ fadt->acpi_disable = 0x00; /* unused if SMI_CMD = 0 */
+
+ /* Enable ACPI */
+ outl(inl(pmbase + 4) | 0x01, pmbase + 4);
+
+ /* Power Control */
+ fadt->s4bios_req = 0x00;
+ fadt->pstate_cnt = 0x00;
+
+ /* Control Registers - Base Address */
+ fadt->pm1a_evt_blk = pmbase + PM1_STS;
+ fadt->pm1b_evt_blk = 0x00; /* Not Used */
+ fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
+ fadt->pm1b_cnt_blk = 0x00; /* Not Used */
+ fadt->pm2_cnt_blk = pmbase + PM2A_CNT_BLK;
+ fadt->pm_tmr_blk = pmbase + PM1_TMR;
+ fadt->gpe0_blk = pmbase + GPE0_STS;
+ fadt->gpe1_blk = 0x00; /* Not Used */
+
+ /* Control Registers - Length */
+ fadt->pm1_evt_len = 4; /* 32 bits */
+ fadt->pm1_cnt_len = 2; /* 32 bit register, 16 bits used */
+ fadt->pm2_cnt_len = 1; /* 8 bits */
+ fadt->pm_tmr_len = 4; /* 32 bits */
+ fadt->gpe0_blk_len = 8; /* 64 bits */
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 0;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+ fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+ fadt->flush_size = 0; /* set to 0 if WBINVD is 1 in flags */
+ fadt->flush_stride = 0; /* set to 0 if WBINVD is 1 in flags */
+ fadt->duty_offset = 1;
+ fadt->duty_width = 0;
+
+ /* RTC Registers */
+ fadt->day_alrm = 0x0D;
+ fadt->mon_alrm = 0x00;
+ fadt->century = 0x00;
+ fadt->iapc_boot_arch = 0;
+
+ fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_RESET_REGISTER | ACPI_FADT_SLEEP_TYPE |
+ ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+ /* Reset Register */
+ fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->reset_reg.addrl = 0xCF9;
+ fadt->reset_reg.addrh = 0x00;
+ fadt->reset_value = 6;
+
+ /* Reserved Bits */
+ fadt->res3 = 0x00; /* reserved, MUST be 0 ACPI 3.0 */
+ fadt->res4 = 0x00; /* reserved, MUST be 0 ACPI 3.0 */
+ fadt->res5 = 0x00; /* reserved, MUST be 0 ACPI 3.0 */
+
+ /* Extended ACPI Pointers */
+ fadt->x_firmware_ctl_l = (unsigned long)facs;
+ fadt->x_firmware_ctl_h = 0x00;
+ fadt->x_dsdt_l = (unsigned long)dsdt;
+ fadt->x_dsdt_h = 0x00;
+
+ /* PM1 Status & PM1 Enable */
+ fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ 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.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
+ fadt->x_pm1a_evt_blk.addrh = 0x00;
+
+ fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_evt_blk.bit_width = 0;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.access_size = 0;
+ fadt->x_pm1b_evt_blk.addrl = fadt->pm1b_evt_blk;
+ fadt->x_pm1b_evt_blk.addrh = 0x00;
+
+ /* PM1 Control Registers */
+ fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_cnt_blk.bit_width = 16;
+ fadt->x_pm1a_cnt_blk.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+ fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
+ fadt->x_pm1a_cnt_blk.addrh = 0x00;
+
+ fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_cnt_blk.bit_width = 0;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.access_size = 0;
+ fadt->x_pm1b_cnt_blk.addrl = fadt->pm1b_cnt_blk;
+ fadt->x_pm1b_cnt_blk.addrh = 0x00;
+
+ /* PM2 Control Registers */
+ fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm2_cnt_blk.bit_width = 8;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
+ fadt->x_pm2_cnt_blk.addrh = 0x00;
+
+ /* PM1 Timer Register */
+ fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm_tmr_blk.bit_width = 32;
+ fadt->x_pm_tmr_blk.bit_offset = 0;
+ fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
+ fadt->x_pm_tmr_blk.addrh = 0x00;
+
+ /* General-Purpose Event Registers */
+ fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + EventEnable */
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
+ fadt->x_gpe0_blk.addrh = 0x00;
+
+ fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.access_size = 0;
+ fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
+ fadt->x_gpe1_blk.addrh = 0x00;
+
+ header->checksum = acpi_checksum((void *) fadt, sizeof(acpi_fadt_t));
+}
+
+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 void generate_P_state_entries(int core, int cores_per_package)
+{
+ int ratio_min, ratio_max, ratio_step;
+ int coord_type, power_max, power_unit, num_entries;
+ int ratio, power, clock, clock_max;
+ int turbo;
+ u32 control_status;
+ msr_t msr;
+
+ /* Hardware coordination of P-states */
+ coord_type = HW_ALL;
+
+ /* Check for Turbo Mode */
+ turbo = get_turbo_state() == TURBO_ENABLED;
+
+ /* CPU attributes */
+ msr = rdmsr(MSR_PLATFORM_INFO);
+ ratio_min = (msr.hi >> 8) & 0xff; // LFM
+ ratio_max = (msr.lo >> 8) & 0xff; // HFM
+ clock_max = (ratio_max * 100);
+
+ /* 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 */
+ acpigen_write_empty_PCT();
+
+ /* Write _PPC starting from first supported P-state */
+ acpigen_write_PPC(0);
+
+ /* Write PSD indicating configured coordination type */
+ acpigen_write_PSD_package(core, 1, coord_type);
+
+ /* Add P-state entries in _PSS table */
+ acpigen_write_name("_PSS");
+
+ /* Determine ratio points */
+ /* Note: There should be at most 16 performance states. If Turbo Mode
+ is enabled, the Max Turbo Ratio will occupy one of these states. */
+ ratio_step = 1;
+ num_entries = (ratio_max - ratio_min) / ratio_step;
+ while (num_entries > (15-turbo)) {
+ ratio_step <<= 1;
+ num_entries >>= 1;
+ }
+
+ if (turbo) {
+ /* _PSS package count (with turbo) */
+ acpigen_write_package(num_entries + 2);
+
+ /* Get Max Turbo Ratio */
+ msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
+ ratio = msr.lo & 0xff;
+
+ acpigen_write_PSS_package(
+ ratio * 100, /* MHz */
+ power_max, /* mW */
+ 10, /* lat1 */
+ 10, /* lat2 */
+ ratio << 8, /* control */
+ ratio << 8); /* status */
+ } else {
+ /* _PSS package count (without turbo) */
+ acpigen_write_package(num_entries + 1);
+ }
+
+ /* Generate the _PSS entries */
+ for (ratio = ratio_min + (num_entries * ratio_step);
+ ratio >= ratio_min; ratio -= ratio_step) {
+
+ /* Calculate power at this ratio */
+ power = calculate_power(power_max, ratio_max, ratio);
+ clock = ratio * 100;
+ control_status = ratio << 8;
+
+ acpigen_write_PSS_package(
+ clock, /* MHz */
+ power, /* mW */
+ 10, /* lat1 */
+ 10, /* lat2 */
+ control_status, /* control */
+ control_status); /* status */
+ }
+
+ /* Fix package length */
+ acpigen_pop_len();
+}
+
+void generate_cpu_entries(device_t device)
+{
+ int 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.CP0x */
+ acpigen_write_processor(core, pcontrol_blk, plen);
+
+ /* Generate P-state tables */
+ generate_P_state_entries(core, pattrs->num_cpus);
+
+ /* Generate C-state tables */
+ acpigen_write_CST_package(cstate_map, ARRAY_SIZE(cstate_map));
+
+ acpigen_pop_len();
+ }
+}
+
+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);
+
+ irqovr = (void *)current;
+ current += acpi_create_madt_irqoverride(irqovr, 0, 3, 3,
+ (MP_IRQ_TRIGGER_LEVEL
+ |MP_IRQ_POLARITY_LOW));
+
+ irqovr = (void *)current;
+ current += acpi_create_madt_irqoverride(irqovr, 0, 4, 4,
+ (MP_IRQ_TRIGGER_LEVEL
+ |MP_IRQ_POLARITY_LOW));
+
+ return current;
+}
diff --git a/src/soc/intel/fsp_broadwell_de/acpi/irq_helper.h b/src/soc/intel/fsp_broadwell_de/acpi/irq_helper.h
new file mode 100644
index 0000000000..8799a9b7cc
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi/irq_helper.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#undef PCI_DEV_PIRQ_ROUTES
+#undef ACPI_DEV_IRQ
+#undef PCI_DEV_PIRQ_ROUTE
+#undef PIRQ_PIC_ROUTES
+#undef PIRQ_PIC
+#undef IRQROUTE_H
+
+#if defined(PIC_MODE)
+
+#define ACPI_DEV_IRQ(dev_, pin_, pin_name_) \
+ { Package() { ## dev_ ## ffff, pin_, \_SB.PCI0.LPCB.LNK ## pin_name_, 0 } }
+
+#else /* defined(PIC_MODE) */
+
+#define ACPI_DEV_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_IRQ(dev_, 0, a_), \
+ ACPI_DEV_IRQ(dev_, 1, b_), \
+ ACPI_DEV_IRQ(dev_, 2, c_), \
+ ACPI_DEV_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/fsp_broadwell_de/acpi/irqlinks.asl b/src/soc/intel/fsp_broadwell_de/acpi/irqlinks.asl
new file mode 100644
index 0000000000..7d02eb0437
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi/irqlinks.asl
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ */
+
+OperationRegion (PRR0, PCI_Config, 0x00, 0x100)
+Field (PRR0, AnyAcc, NoLock, Preserve) {
+ Offset(0x60),
+ PIRA, 8,
+ PIRB, 8,
+ PIRC, 8,
+ PIRD, 8,
+ Offset(0x68),
+ PIRE, 8,
+ PIRF, 8,
+ PIRG, 8,
+ PIRH, 8
+}
+
+Device (LNKA) { // PCI IRQ link A
+ Name (_HID,EISAID("PNP0C0F"))
+ //Name(_UID, 1)
+ Method (_STA,0,NotSerialized) {
+ If(And(PIRA, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ } // Don't display
+ }
+
+ Method (_DIS,0,NotSerialized) {
+ Or (PIRA, 0x80, PIRA)
+ }
+
+ Method (_CRS,0,Serialized) {
+ Name (BUF0, ResourceTemplate() {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And(PIRA, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One,Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0,And (PIRA,0x0F),IRQW) // Save in buffer
+ Return (BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name (_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual (IRQW,Zero)){
+ And (Local0, 0x7F,Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80,Local0)
+ }
+ Store (Local0, PIRA)
+ } // End of _SRS Method
+}
+
+Device(LNKB) { // PCI IRQ link B
+ Name (_HID,EISAID("PNP0C0F"))
+ //Name(_UID, 2)
+ Method (_STA,0,NotSerialized) {
+ If (And (PIRB, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ } // Don't display
+ }
+
+ Method (_DIS,0,NotSerialized) {
+ Or (PIRB, 0x80,PIRB)
+ }
+
+ Method (_CRS,0,Serialized) {
+ Name(BUF0, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (PIRB, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One,Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0,And (PIRB,0x0F),IRQW) // Save in buffer
+ Return (BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name (_PRS,
+ ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual(IRQW,Zero)) {
+ And (Local0, 0x7F, Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80, Local0)
+ }
+ Store (Local0, PIRB)
+ } // End of _SRS Method
+}
+
+Device(LNKC) { // PCI IRQ link C
+ Name(_HID, EISAID("PNP0C0F"))
+ //Name(_UID, 3)
+
+ Method (_STA,0,NotSerialized) {
+ If (And (PIRC, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ } // Don't display
+ }
+
+ Method (_DIS, 0, NotSerialized) {
+ Or (PIRC, 0x80, PIRC)
+ }
+
+ Method (_CRS, 0, Serialized) {
+ Name (BUF0, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (PIRC, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One,Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0,And (PIRC,0x0F),IRQW)
+ Return (BUF0)
+ } // End of _CRS method
+
+ Name (_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual (IRQW,Zero)) {
+ And (Local0, 0x7F, Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80,Local0)
+ }
+ Store (Local0, PIRC)
+ } // End of _SRS Method
+}
+
+Device (LNKD) { // PCI IRQ link D
+ Name (_HID,EISAID ("PNP0C0F"))
+
+ //Name(_UID, 4)
+
+ Method (_STA, 0, NotSerialized) {
+ If (And (PIRD, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ } // Don't display
+ }
+
+ Method (_DIS, 0, NotSerialized) {
+ Or(PIRD, 0x80,PIRD)
+ }
+
+ Method (_CRS,0,Serialized) {
+ Name (BUF0, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (PIRD, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One,Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0, And (PIRD,0x0F), IRQW)
+ Return (BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name (_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+ FindSetRightBit (IRQW, Local0)// Set IRQ
+ If (LNotEqual (IRQW, Zero)) {
+ And (Local0, 0x7F, Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80, Local0)
+ }
+ Store(Local0, PIRD)
+ } // End of _SRS Method
+}
+
+Device(LNKE) { // PCI IRQ link E
+ Name(_HID,EISAID("PNP0C0F"))
+
+ //Name(_UID, 5)
+
+ Method (_STA,0,NotSerialized) {
+ If (And (PIRE, 0x80)) {
+ Return(0x9)
+ } Else {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method (_DIS,0,NotSerialized) {
+ Or (PIRE, 0x80, PIRE)
+ }
+
+ Method (_CRS, 0, Serialized) {
+ Name (BUF0, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (PIRE, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One, Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0, And (PIRE,0x0F), IRQW)
+ Return (BUF0) // Return Buf0
+ } // End of _CRS method
+
+ Name(_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+ FindSetRightBit (IRQW, Local0) // Set IRQ
+ If (LNotEqual (IRQW, Zero)) {
+ And (Local0, 0x7F, Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80, Local0)
+ }
+ Store (Local0, PIRE)
+ } // End of _SRS Method
+}
+
+Device(LNKF) { // PCI IRQ link F
+ Name (_HID,EISAID("PNP0C0F"))
+
+ //Name(_UID, 6)
+
+ Method (_STA,0,NotSerialized) {
+ If (And (PIRF, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ } // Don't display
+ }
+
+ Method (_DIS,0,NotSerialized) {
+ Or (PIRB, 0x80, PIRF)
+ }
+
+ Method (_CRS,0,Serialized) {
+ Name(BUF0, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (PIRF, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One, Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0, And (PIRF, 0x0F),IRQW)
+ Return (BUF0)
+ } // End of _CRS method
+
+ Name(_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+ FindSetRightBit (IRQW,Local0) // Set IRQ
+ If (LNotEqual (IRQW,Zero)) {
+ And (Local0, 0x7F,Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80, Local0)
+ }
+ Store (Local0, PIRF)
+ } // End of _SRS Method
+}
+
+Device(LNKG) { // PCI IRQ link G
+ Name(_HID,EISAID("PNP0C0F"))
+ //Name(_UID, 7)
+ Method(_STA,0,NotSerialized) {
+ If (And (PIRG, 0x80)) {
+ Return (0x9)
+ } Else {
+ Return (0xB)
+ } // Don't display
+ }
+
+ Method (_DIS, 0, NotSerialized) {
+ Or(PIRG, 0x80,PIRG)
+ }
+
+ Method (_CRS,0,Serialized){
+ Name(BUF0,ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And(PIRG, 0x80)) {
+ Store(Zero, Local0)
+ } Else {
+ Store(One,Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0,And(PIRG,0x0F),IRQW)
+ Return (BUF0)
+ } // End of _CRS method
+
+ Name (_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+ FindSetRightBit(IRQW,Local0) // Set IRQ
+ If (LNotEqual (IRQW,Zero)) {
+ And (Local0, 0x7F,Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80,Local0)
+ }
+ Store (Local0, PIRG)
+ } // End of _SRS Method
+}
+
+Device(LNKH) { // PCI IRQ link H
+ Name (_HID,EISAID("PNP0C0F"))
+
+ //Name(_UID, 8)
+
+ Method (_STA,0,NotSerialized) {
+ If (And(PIRH, 0x80)) {
+ Return(0x9)
+ } Else {
+ Return(0xB)
+ } // Don't display
+ }
+
+ Method (_DIS,0,NotSerialized) {
+ Or(PIRH, 0x80,PIRH)
+ }
+
+ Method (_CRS,0,Serialized) {
+ Name(BUF0, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){0}})
+ //
+ // Define references to buffer elements
+ //
+ CreateWordField (BUF0, 0x01, IRQW) // IRQ low
+ //
+ // Write current settings into IRQ descriptor
+ //
+ If (And (PIRH, 0x80)) {
+ Store (Zero, Local0)
+ } Else {
+ Store (One,Local0)
+ }
+ //
+ // Shift 1 by value in register 70, Save in buffer
+ //
+ ShiftLeft (Local0,And(PIRH,0x0F),IRQW)
+ Return (BUF0)
+ } // End of _CRS method
+
+ Name(_PRS, ResourceTemplate()
+ {IRQ(Level,ActiveLow,Shared){3,4,5,6,7,9,10,11,12,14,15}})
+
+ Method (_SRS,1,NotSerialized) {
+ CreateWordField (ARG0, 0x01, IRQW) // IRQ low
+ FindSetRightBit (IRQW,Local0)// Set IRQ
+ If (LNotEqual (IRQW,Zero)) {
+ And (Local0, 0x7F,Local0)
+ Decrement (Local0)
+ } Else {
+ Or (Local0, 0x80,Local0)
+ }
+ Store (Local0, PIRH)
+ }
+}
diff --git a/src/soc/intel/fsp_broadwell_de/acpi/irqroute.asl b/src/soc/intel/fsp_broadwell_de/acpi/irqroute.asl
new file mode 100644
index 0000000000..a4ce5eaddf
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi/irqroute.asl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/* PCI Interrupt Routing */
+Method(_PRT)
+{
+ /*
+ * PICM comes from _PIC, which returns the following:
+ * 0 – PIC mode
+ * 1 – APIC mode
+ * 2 – SAPIC mode
+ */
+ If (PICM) {
+ Return (Package() {
+ #undef PIC_MODE
+ #include "irq_helper.h"
+ PCI_DEV_PIRQ_ROUTES
+ })
+ } Else {
+ Return (Package() {
+ #define PIC_MODE
+ #include "irq_helper.h"
+ PCI_DEV_PIRQ_ROUTES
+ })
+ }
+}
diff --git a/src/soc/intel/fsp_broadwell_de/acpi/lpc.asl b/src/soc/intel/fsp_broadwell_de/acpi/lpc.asl
new file mode 100644
index 0000000000..6a7a2f132f
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi/lpc.asl
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2013 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/* Intel LPC Bus Device - 0:1f.0 */
+
+Device (LPC0)
+{
+ Name(_ADR, 0x001f0000)
+
+ #include "irqlinks.asl"
+
+ 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(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)
+ })
+ }
+
+ 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}
+ })
+ }
+}
diff --git a/src/soc/intel/fsp_broadwell_de/acpi/pcie1.asl b/src/soc/intel/fsp_broadwell_de/acpi/pcie1.asl
new file mode 100644
index 0000000000..950a3622db
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi/pcie1.asl
@@ -0,0 +1,465 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+Name (PR01, Package() {
+ // [SL01]: PCI Express Slot 1 on 1A on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR01, Package() {
+ // [SL01]: PCI Express Slot 1 on 1A on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH01, Package() {
+ // [SL01]: PCI Express Slot 1 on 1A on PCI0
+ Package() { 0x0000FFFF, 0, 0, 26 },
+ Package() { 0x0000FFFF, 1, 0, 28 },
+ Package() { 0x0000FFFF, 2, 0, 29 },
+ Package() { 0x0000FFFF, 3, 0, 30 },
+})
+
+Name (PR02, Package() {
+ // [SL02]: PCI Express Slot 2 on 1B on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR02, Package() {
+ // [SL02]: PCI Express Slot 2 on 1B on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH02, Package() {
+ // [SL02]: PCI Express Slot 2 on 1B on PCI0
+ Package() { 0x0000FFFF, 0, 0, 27 },
+ Package() { 0x0000FFFF, 1, 0, 30 },
+ Package() { 0x0000FFFF, 2, 0, 28 },
+ Package() { 0x0000FFFF, 3, 0, 29 },
+})
+
+Name (PR03, Package() {
+ // [CB0I]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [CB0J]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ // [CB0K]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ // [CB0L]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR03, Package() {
+ // [CB0I]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ // [CB0J]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ // [CB0K]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ // [CB0L]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH03, Package() {
+ // [CB0I]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 0, 0, 32 },
+ // [CB0J]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 1, 0, 36 },
+ // [CB0K]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 2, 0, 37 },
+ // [CB0L]: CB3DMA on IOSF
+ Package() { 0x0000FFFF, 3, 0, 38 },
+})
+
+Name (PR04, Package() {
+ // [SL04]: PCI Express Slot 4 on 2B on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR04, Package() {
+ // [SL04]: PCI Express Slot 4 on 2B on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH04, Package() {
+ // [SL04]: PCI Express Slot 4 on 2B on PCI0
+ Package() { 0x0000FFFF, 0, 0, 33 },
+ Package() { 0x0000FFFF, 1, 0, 37 },
+ Package() { 0x0000FFFF, 2, 0, 38 },
+ Package() { 0x0000FFFF, 3, 0, 36 },
+})
+
+Name (PR05, Package() {
+ // [SL05]: PCI Express Slot 5 on 2C on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR05, Package() {
+ // [SL05]: PCI Express Slot 5 on 2C on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH05, Package() {
+ // [SL05]: PCI Express Slot 5 on 2C on PCI0
+ Package() { 0x0000FFFF, 0, 0, 34 },
+ Package() { 0x0000FFFF, 1, 0, 37 },
+ Package() { 0x0000FFFF, 2, 0, 36 },
+ Package() { 0x0000FFFF, 3, 0, 38 },
+})
+
+Name (PR06, Package() {
+ // [SL06]: PCI Express Slot 6 on 2D on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR06, Package() {
+ // [SL06]: PCI Express Slot 6 on 2D on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH06, Package() {
+ // [SL06]: PCI Express Slot 6 on 2D on PCI0
+ Package() { 0x0000FFFF, 0, 0, 35 },
+ Package() { 0x0000FFFF, 1, 0, 36 },
+ Package() { 0x0000FFFF, 2, 0, 38 },
+ Package() { 0x0000FFFF, 3, 0, 37 },
+})
+
+Name (PR07, Package() {
+ // [SL07]: PCI Express Slot 7 on 3A on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR07, Package() {
+ // [SL07]: PCI Express Slot 7 on 3A on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH07, Package() {
+ // [SL07]: PCI Express Slot 7 on 3A on PCI0
+ Package() { 0x0000FFFF, 0, 0, 40 },
+ Package() { 0x0000FFFF, 1, 0, 44 },
+ Package() { 0x0000FFFF, 2, 0, 45 },
+ Package() { 0x0000FFFF, 3, 0, 46 },
+})
+
+Name (PR08, Package() {
+ // [SL08]: PCI Express Slot 8 on 3B on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR08, Package() {
+ // [SL08]: PCI Express Slot 8 on 3B on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH08, Package() {
+ // [SL08]: PCI Express Slot 8 on 3B on PCI0
+ Package() { 0x0000FFFF, 0, 0, 41 },
+ Package() { 0x0000FFFF, 1, 0, 45 },
+ Package() { 0x0000FFFF, 2, 0, 46 },
+ Package() { 0x0000FFFF, 3, 0, 44 },
+})
+
+Name (PR09, Package() {
+ // [SL09]: PCI Express Slot 9 on 3C on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR09, Package() {
+ // [SL09]: PCI Express Slot 9 on 3C on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH09, Package() {
+ // [SL09]: PCI Express Slot 9 on 3C on PCI0
+ Package() { 0x0000FFFF, 0, 0, 42 },
+ Package() { 0x0000FFFF, 1, 0, 45 },
+ Package() { 0x0000FFFF, 2, 0, 44 },
+ Package() { 0x0000FFFF, 3, 0, 46 },
+})
+
+Name (PR0A, Package() {
+ // [SL0A]: PCI Express Slot 10 on 3D on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0000FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0000FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0000FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+})
+
+Name (AR0A, Package() {
+ // [SL0A]: PCI Express Slot 10 on 3D on PCI0
+ Package() { 0x0000FFFF, 0, 0, 16 },
+ Package() { 0x0000FFFF, 1, 0, 17 },
+ Package() { 0x0000FFFF, 2, 0, 18 },
+ Package() { 0x0000FFFF, 3, 0, 19 },
+})
+
+Name (AH0A, Package() {
+ // [SL0A]: PCI Express Slot 10 on 3D on PCI0
+ Package() { 0x0000FFFF, 0, 0, 43 },
+ Package() { 0x0000FFFF, 1, 0, 44 },
+ Package() { 0x0000FFFF, 2, 0, 46 },
+ Package() { 0x0000FFFF, 3, 0, 45 },
+})
+
+
+ // PCI Express Port 1A on PCI0
+Device (BR1A) {
+ Name (_ADR, 0x00010000)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR01)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH01)
+ }
+ Return (AR01)
+ }
+
+}
+
+// PCI Express Port 1B on PCI0
+Device (BR1B) {
+ Name (_ADR, 0x00010001)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR02)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH02)
+ }
+ Return (AR02)
+ }
+
+}
+
+// PCI Express Port 2A on PCI0
+Device (BR2A) {
+ Name (_ADR, 0x00020000)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR03)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH03)
+ }
+ Return (AR03)
+ }
+
+
+ // CB3DMA on IOSF
+ Device (CB0I) {
+ Name (_ADR, 0x00000000)
+ }
+
+ // CB3DMA on IOSF
+ Device (CB0J) {
+ Name (_ADR, 0x00000001)
+ }
+
+ // CB3DMA on IOSF
+ Device (CB0K) {
+ Name (_ADR, 0x00000002)
+ }
+
+ // CB3DMA on IOSF
+ Device (CB0L) {
+ Name (_ADR, 0x00000003)
+ }
+}
+
+// PCI Express Port 2B on PCI0
+Device (BR2B) {
+ Name (_ADR, 0x00020001)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR04)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH04)
+ }
+ Return (AR04)
+ }
+
+}
+
+// PCI Express Port 2C on PCI0
+Device (BR2C) {
+ Name (_ADR, 0x00020002)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR05)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH05)
+ }
+ Return (AR05)
+ }
+
+}
+
+// PCI Express Port 2D on PCI0
+Device (BR2D) {
+ Name (_ADR, 0x00020003)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR06)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH06)
+ }
+ Return (AR06)
+ }
+
+}
+
+// PCI Express Port 3A on PCI0
+Device (BR3A) {
+ Name (_ADR, 0x00030000)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR07)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH07)
+ }
+ Return (AR07)
+ }
+
+}
+
+// PCI Express Port 3B on PCI0
+Device (BR3B) {
+ Name (_ADR, 0x00030001)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR08)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH08)
+ }
+ Return (AR08)
+ }
+
+}
+
+// PCI Express Port 3C on PCI0
+Device (BR3C) {
+ Name (_ADR, 0x00030002)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR09)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH09)
+ }
+ Return (AR09)
+ }
+
+}
+
+// PCI Express Port 3D on PCI0
+Device (BR3D) {
+ Name (_ADR, 0x00030003)
+ Method (_PRW, 0) {
+ Return (Package (0x02) {0x09, 0x04})
+ }
+ Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR0A)
+ }
+ If (LEqual(APC1, One)) {
+ Return (AH0A)
+ }
+ Return (AR0A)
+ }
+
+}
diff --git a/src/soc/intel/fsp_broadwell_de/acpi/southcluster.asl b/src/soc/intel/fsp_broadwell_de/acpi/southcluster.asl
new file mode 100644
index 0000000000..fa83f59e03
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/acpi/southcluster.asl
@@ -0,0 +1,350 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <soc/iomap.h>
+#include <soc/irq.h>
+
+Name(_HID,EISAID("PNP0A08")) // PCIe
+Name(_CID,EISAID("PNP0A03")) // PCI
+
+Name(_ADR, 0)
+Name(_BBN, 0)
+
+Name (MCRS, ResourceTemplate() {
+ // Bus Numbers
+ WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, 0x0000, 0x00fe, 0x0000, 0xff,,, 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, 0xefff, 0x0000, 0xE300,,, 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-0xfeafffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x90000000, 0xFEAFFFFF, 0x00000000,
+ 0x6EB00000,,, PMEM)
+
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0xfec00000, 0xfecfffff, 0x00000000,
+ 0x00100000,,, APIC)
+
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0xfed00000, 0xfedfffff, 0x00000000,
+ 0x00100000,,, PCHR)
+
+ QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x0000000000000000, // Granularity
+ 0x0000380000000000, // Range Minimum
+ 0x0000383FFFFFFFFF, // Range Maximum
+ 0x0000000000000000, // Translation Offset
+ 0x0000004000000000, // Length
+ ,,, AddressRangeMemory, TypeStatic)
+})
+
+Method (_CRS, 0, Serialized) {
+ 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, PSEG_BASE_ADDRESS, PSEG_BASE_SIZE)
+ Memory32Fixed(ReadWrite, IOXAPIC1_BASE_ADDRESS, IOXAPIC1_BASE_SIZE)
+ Memory32Fixed(ReadWrite, IOXAPIC2_BASE_ADDRESS, IOXAPIC2_BASE_SIZE)
+ Memory32Fixed(ReadWrite, PCH_BASE_ADDRESS, PCH_BASE_SIZE)
+ Memory32Fixed(ReadWrite, LXAPIC_BASE_ADDRESS, LXAPIC_BASE_SIZE)
+ Memory32Fixed(ReadWrite, FIRMWARE_BASE_ADDRESS, FIRMWARE_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)
+ }
+}
+
+Name (PR00, Package() {
+ // [DMI0]: Legacy PCI Express Port 0 on PCI0
+ Package() { 0x0000FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [BR1A]: PCI Express Port 1A on PCI0
+ // [BR1B]: PCI Express Port 1B on PCI0
+ Package() { 0x0001FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [BR2A]: PCI Express Port 2A on PCI0
+ // [BR2B]: PCI Express Port 2B on PCI0
+ // [BR2C]: PCI Express Port 2C on PCI0
+ // [BR2D]: PCI Express Port 2D on PCI0
+ Package() { 0x0002FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [BR3A]: PCI Express Port 3A on PCI0
+ // [BR3B]: PCI Express Port 3B on PCI0
+ // [BR3C]: PCI Express Port 3C on PCI0
+ // [BR3D]: PCI Express Port 3D on PCI0
+ Package() { 0x0003FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [CB0A]: CB3DMA on PCI0
+ // [CB0E]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [CB0B]: CB3DMA on PCI0
+ // [CB0F]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ // [CB0C]: CB3DMA on PCI0
+ // [CB0G]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ // [CB0D]: CB3DMA on PCI0
+ // [CB0H]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+ // [IIM0]: IIOMISC on PCI0
+ Package() { 0x0005FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0005FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0005FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0005FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+ // [IID0]: IIODFX0 on PCI0
+ Package() { 0x0006FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ Package() { 0x0006FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ Package() { 0x0006FFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ Package() { 0x0006FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+ // [XHCI]: xHCI controller 1 on PCH
+ Package() { 0x0014FFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+ // [HECI]: ME HECI on PCH
+ // [IDER]: ME IDE redirect on PCH
+ Package() { 0x0016FFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [HEC2]: ME HECI2 on PCH
+ // [MEKT]: MEKT on PCH
+ Package() { 0x0016FFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ // [GBEM]: GbE Controller VPRO
+ Package() { 0x0019FFFF, 0, \_SB.PCI0.LPC0.LNKE, 0 },
+ // [EHC2]: EHCI controller #2 on PCH
+ Package() { 0x001AFFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ // [ALZA]: High definition Audio Controller
+ Package() { 0x001BFFFF, 0, \_SB.PCI0.LPC0.LNKG, 0 },
+ // [RP01]: Pci Express Port 1 on PCH
+ // [RP05]: Pci Express Port 5 on PCH
+ Package() { 0x001CFFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [RP02]: Pci Express Port 2 on PCH
+ // [RP06]: Pci Express Port 6 on PCH
+ Package() { 0x001CFFFF, 1, \_SB.PCI0.LPC0.LNKB, 0 },
+ // [RP03]: Pci Express Port 3 on PCH
+ // [RP07]: Pci Express Port 7 on PCH
+ Package() { 0x001CFFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ // [RP04]: Pci Express Port 4 on PCH
+ // [RP08]: Pci Express Port 8 on ICH
+ Package() { 0x001CFFFF, 3, \_SB.PCI0.LPC0.LNKD, 0 },
+ // [EHC1]: EHCI controller #1 on PCH
+ Package() { 0x001DFFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+ // [SAT1]: SATA controller 1 on PCH
+ // [SAT2]: SATA Host controller 2 on PCH
+ Package() { 0x001FFFFF, 0, \_SB.PCI0.LPC0.LNKA, 0 },
+ // [SMBS]: SMBus controller on PCH
+ // [TERM]: Thermal Subsystem on ICH
+ Package() { 0x001FFFFF, 2, \_SB.PCI0.LPC0.LNKC, 0 },
+})
+
+Name (AR00, Package() {
+ // [DMI0]: Legacy PCI Express Port 0 on PCI0
+ Package() { 0x0000FFFF, 0, 0, 47 },
+ // [BR1A]: PCI Express Port 1A on PCI0
+ // [BR1B]: PCI Express Port 1B on PCI0
+ Package() { 0x0001FFFF, 0, 0, 47 },
+ // [BR2A]: PCI Express Port 2A on PCI0
+ // [BR2B]: PCI Express Port 2B on PCI0
+ // [BR2C]: PCI Express Port 2C on PCI0
+ // [BR2D]: PCI Express Port 2D on PCI0
+ Package() { 0x0002FFFF, 0, 0, 47 },
+ // [BR3A]: PCI Express Port 3A on PCI0
+ // [BR3B]: PCI Express Port 3B on PCI0
+ // [BR3C]: PCI Express Port 3C on PCI0
+ // [BR3D]: PCI Express Port 3D on PCI0
+ Package() { 0x0003FFFF, 0, 0, 47 },
+ // [CB0A]: CB3DMA on PCI0
+ // [CB0E]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 0, 0, 31 },
+ // [CB0B]: CB3DMA on PCI0
+ // [CB0F]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 1, 0, 39 },
+ // [CB0C]: CB3DMA on PCI0
+ // [CB0G]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 2, 0, 31 },
+ // [CB0D]: CB3DMA on PCI0
+ // [CB0H]: CB3DMA on PCI0
+ Package() { 0x0004FFFF, 3, 0, 39 },
+ // [IIM0]: IIOMISC on PCI0
+ Package() { 0x0005FFFF, 0, 0, 16 },
+ Package() { 0x0005FFFF, 1, 0, 17 },
+ Package() { 0x0005FFFF, 2, 0, 18 },
+ Package() { 0x0005FFFF, 3, 0, 19 },
+ // [IID0]: IIODFX0 on PCI0
+ Package() { 0x0006FFFF, 0, 0, 16 },
+ Package() { 0x0006FFFF, 1, 0, 17 },
+ Package() { 0x0006FFFF, 2, 0, 18 },
+ Package() { 0x0006FFFF, 3, 0, 19 },
+ // [XHCI]: xHCI controller 1 on PCH
+ Package() { 0x0014FFFF, 3, 0, 19 },
+ // [HECI]: ME HECI on PCH
+ // [IDER]: ME IDE redirect on PCH
+ Package() { 0x0016FFFF, 0, 0, 16 },
+ // [HEC2]: ME HECI2 on PCH
+ // [MEKT]: MEKT on PCH
+ Package() { 0x0016FFFF, 1, 0, 17 },
+ // [GBEM]: GbE Controller VPRO
+ Package() { 0x0019FFFF, 0, 0, 20 },
+ // [EHC2]: EHCI controller #2 on PCH
+ Package() { 0x001AFFFF, 2, 0, 18 },
+ // [ALZA]: High definition Audio Controller
+ Package() { 0x001BFFFF, 0, 0, 22 },
+ // [RP01]: Pci Express Port 1 on PCH
+ // [RP05]: Pci Express Port 5 on PCH
+ Package() { 0x001CFFFF, 0, 0, 16 },
+ // [RP02]: Pci Express Port 2 on PCH
+ // [RP06]: Pci Express Port 6 on PCH
+ Package() { 0x001CFFFF, 1, 0, 17 },
+ // [RP03]: Pci Express Port 3 on PCH
+ // [RP07]: Pci Express Port 7 on PCH
+ Package() { 0x001CFFFF, 2, 0, 18 },
+ // [RP04]: Pci Express Port 4 on PCH
+ // [RP08]: Pci Express Port 8 on ICH
+ Package() { 0x001CFFFF, 3, 0, 19 },
+ // [EHC1]: EHCI controller #1 on PCH
+ Package() { 0x001DFFFF, 2, 0, 18 },
+ // [SAT1]: SATA controller 1 on PCH
+ // [SAT2]: SATA Host controller 2 on PCH
+ Package() { 0x001FFFFF, 0, 0, 16 },
+ // [SMBS]: SMBus controller on PCH
+ // [TERM]: Thermal Subsystem on ICH
+ Package() { 0x001FFFFF, 2, 0, 18 },
+})
+
+// Socket 0 Root bridge
+Method (_PRT, 0) {
+ If (LEqual(PICM, Zero)) {
+ Return (PR00)
+ }
+ Return (AR00) // If you disable the IOxAPIC in IIO, you should return AR00
+}
+
+#include "lpc.asl"
diff --git a/src/soc/intel/fsp_broadwell_de/bootblock/bootblock.c b/src/soc/intel/fsp_broadwell_de/bootblock/bootblock.c
new file mode 100644
index 0000000000..c026c8391e
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/bootblock/bootblock.c
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cpu/intel/microcode/microcode.c>
+
+static void bootblock_cpu_init(void)
+{
+ /* Load microcode before any caching. */
+ intel_update_microcode_from_cbfs();
+}
diff --git a/src/soc/intel/fsp_broadwell_de/chip.c b/src/soc/intel/fsp_broadwell_de/chip.c
new file mode 100644
index 0000000000..78649fc796
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/chip.c
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <lib.h>
+#include <string.h>
+#include <bootstate.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <drivers/intel/fsp1_0/fsp_util.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 = broadwell_de_init_cpus,
+ .scan_bus = NULL,
+};
+
+static void enable_dev(device_t dev)
+{
+ printk(BIOS_DEBUG, "enable_dev(%s, %d)\n",
+ dev_name(dev), dev->path.type);
+
+ /* 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) > 0 &&
+ (dev->ops == NULL || dev->ops->enable == NULL)) {
+ southcluster_enable_dev(dev);
+ }
+ }
+}
+
+static void fsp_notify(void *arg)
+{
+ FspNotify (*(uint32_t *)arg);
+}
+
+static uint32_t gFspNotifyAfterPciEnumeration = EnumInitPhaseAfterPciEnumeration;
+static uint32_t gFspNotifyReadtToBoot = EnumInitPhaseReadyToBoot;
+static BOOT_STATE_CALLBACK(bscb_fspnotify1, fsp_notify, &gFspNotifyAfterPciEnumeration);
+static BOOT_STATE_CALLBACK(bscb_fspnotify2, fsp_notify, &gFspNotifyReadtToBoot);
+
+/* Called at BS_DEV_INIT_CHIPS time -- very early. Just after BS_PRE_DEVICE. */
+static void soc_init(void *chip_info)
+{
+ boot_state_sched_on_exit(&bscb_fspnotify1, BS_DEV_RESOURCES);
+ boot_state_sched_on_exit(&bscb_fspnotify2, BS_PAYLOAD_LOAD);
+ broadwell_de_init_pre_device();
+}
+
+struct chip_operations soc_intel_fsp_broadwell_de_ops = {
+ CHIP_NAME("Intel(R) Xeon(R) Processor D-1500 Product Family")
+ .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/fsp_broadwell_de/chip.h b/src/soc/intel/fsp_broadwell_de/chip.h
new file mode 100644
index 0000000000..ed01c89de1
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/chip.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_CHIP_H_
+#define _SOC_CHIP_H_
+
+#include <arch/acpi.h>
+
+/* The devicetree parser expects chip.h to reside directly in the path
+ * specified by the devicetree. */
+
+struct soc_intel_fsp_broadwell_de_config {
+};
+
+extern struct chip_operations soc_intel_fsp_broadwell_de_ops;
+#endif /* _SOC_CHIP_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/cpu.c b/src/soc/intel/fsp_broadwell_de/cpu.c
new file mode 100644
index 0000000000..173e978492
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/cpu.c
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdlib.h>
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/intel/microcode.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 <soc/msr.h>
+#include <soc/pattrs.h>
+#include <soc/ramstage.h>
+
+static void configure_mca(void);
+
+static struct mp_flight_record mp_steps[] = {
+ MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL),
+};
+
+static int adjust_apic_id(int index, int apic_id)
+{
+ return index;
+}
+
+static void configure_mca(void)
+{
+ msr_t msr;
+ const unsigned int mcg_cap_msr = 0x179;
+ int i;
+ int num_banks;
+
+ msr = rdmsr(mcg_cap_msr);
+ num_banks = msr.lo & 0xff;
+
+ /* TODO(adurbin): This should only be done on a cold boot. Also, some
+ * of these banks are core vs package scope. For now every CPU clears
+ * every bank. */
+ msr.lo = msr.hi = 0;
+ for (i = 0; i < num_banks; i++) {
+ wrmsr(MSR_IA32_MC0_STATUS + (i * 4) + 1, msr);
+ wrmsr(MSR_IA32_MC0_STATUS + (i * 4) + 2, msr);
+ wrmsr(MSR_IA32_MC0_STATUS + (i * 4) + 3, msr);
+ }
+
+ msr.lo = msr.hi = 0xffffffff;
+ for (i = 0; i < num_banks; i++)
+ wrmsr(MSR_IA32_MC0_STATUS + (i * 4), msr);
+}
+
+void broadwell_de_init_cpus(device_t dev)
+{
+ struct bus *cpu_bus = dev->link_list;
+ const struct pattrs *pattrs = pattrs_get();
+ struct mp_params mp_params;
+
+ x86_mtrr_check();
+
+ /* Enable the local cpu apics */
+ setup_lapic();
+
+ 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;
+
+ if (mp_init(cpu_bus, &mp_params)) {
+ printk(BIOS_ERR, "MP initialization failure.\n");
+ }
+}
+
+static void broadwell_de_core_init(device_t cpu)
+{
+ printk(BIOS_DEBUG, "Init Broadwell-DE core.\n");
+ configure_mca();
+}
+
+static struct device_operations cpu_dev_ops = {
+ .init = broadwell_de_core_init,
+};
+
+static struct cpu_device_id cpu_table[] = {
+ { X86_VENDOR_INTEL, 0x50661 },
+ { X86_VENDOR_INTEL, 0x50662 },
+ { X86_VENDOR_INTEL, 0x50663 },
+ { X86_VENDOR_INTEL, 0x50664 },
+ { 0, 0 },
+};
+
+static const struct cpu_driver driver __cpu_driver = {
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
+};
diff --git a/src/soc/intel/fsp_broadwell_de/fsp/Kconfig b/src/soc/intel/fsp_broadwell_de/fsp/Kconfig
new file mode 100644
index 0000000000..2e1ebebd44
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/fsp/Kconfig
@@ -0,0 +1,93 @@
+config BROADWELL_DE_FSP_SPECIFIC_OPTIONS
+ def_bool y
+ select PLATFORM_USES_FSP1_0
+ select USE_GENERIC_FSP_CAR_INC
+ select FSP_USES_UPD
+
+config FSP_FILE
+ string
+ default "../intel/fsp/broadwell_de/BROADWELLDE_FSP.bin"
+ help
+ The path and filename of the Intel FSP binary for this platform.
+
+config FSP_LOC
+ hex
+ default 0xffeb0000
+ help
+ The location in CBFS that the FSP is located. This must match the
+ value that is set in the FSP binary. If the FSP needs to be moved,
+ rebase the FSP with Intel's BCT (tool).
+
+ The Broadwell-DE FSP is built with a preferred base address of
+ 0xffeb0000.
+
+config FSP_MEMORY_DOWN
+ bool "Enable Memory Down"
+ default n
+ help
+ Load SPD data from ROM instead of trying to read from SMBus.
+
+ If the platform has DIMM sockets, say N. If memory is down, say Y and
+ supply the appropriate SPD data for each Channel/DIMM.
+
+config FSP_MEMORY_DOWN_CH0DIMM0_SPD_PRESENT
+ bool "Channel 0, DIMM 0 Present"
+ default n
+ depends on FSP_MEMORY_DOWN
+ help
+ Select Y if Channel 0, DIMM 0 is present.
+
+config FSP_MEMORY_DOWN_CH0DIMM0_SPD_FILE
+ string "Channel 0, DIMM 0 SPD File"
+ default "spd_ch0_dimm0.bin"
+ depends on FSP_MEMORY_DOWN_CH0DIMM0_SPD_PRESENT
+ help
+ Path to the file which contains the SPD data for Channel 0, DIMM 0.
+
+config FSP_MEMORY_DOWN_CH0DIMM1_SPD_PRESENT
+ bool "Channel 0, DIMM 1 Present"
+ default n
+ depends on FSP_MEMORY_DOWN
+ help
+ Select Y if Channel 0, DIMM 1 is present.
+
+config FSP_MEMORY_DOWN_CH0DIMM1_SPD_FILE
+ string "Channel 0, DIMM 1 SPD File"
+ default "spd_ch0_dimm1.bin"
+ depends on FSP_MEMORY_DOWN_CH0DIMM1_SPD_PRESENT
+ help
+ Path to the file which contains the SPD data for Channel 0, DIMM 1.
+
+config FSP_MEMORY_DOWN_CH1DIMM0_SPD_PRESENT
+ bool "Channel 1, DIMM 0 Present"
+ default n
+ depends on FSP_MEMORY_DOWN
+ help
+ Select Y if Channel 1, DIMM 0 is present.
+
+config FSP_MEMORY_DOWN_CH1DIMM0_SPD_FILE
+ string "Channel 1, DIMM 0 SPD File"
+ default "spd_ch1_dimm0.bin"
+ depends on FSP_MEMORY_DOWN_CH1DIMM0_SPD_PRESENT
+ help
+ Path to the file which contains the SPD data for Channel 1, DIMM 0.
+
+config FSP_MEMORY_DOWN_CH1DIMM1_SPD_PRESENT
+ bool "Channel 1, DIMM 1 Present"
+ default n
+ depends on FSP_MEMORY_DOWN
+ help
+ Select Y if Channel 1, DIMM 1 is present.
+
+config FSP_MEMORY_DOWN_CH1DIMM1_SPD_FILE
+ string "Channel 1, DIMM 1 SPD File"
+ default "spd_ch1_dimm1.bin"
+ depends on FSP_MEMORY_DOWN_CH1DIMM1_SPD_PRESENT
+ help
+ Path to the file which contains the SPD data for Channel 1, DIMM 1.
+
+config FSP_HYPERTHREADING
+ bool "Enable Hyper-Threading"
+ default y
+ help
+ Enable Intel(r) Hyper-Threading Technology for the Broadwell-DE SoC.
diff --git a/src/soc/intel/fsp_broadwell_de/fsp/Makefile.inc b/src/soc/intel/fsp_broadwell_de/fsp/Makefile.inc
new file mode 100644
index 0000000000..651976483e
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/fsp/Makefile.inc
@@ -0,0 +1,17 @@
+romstage-y += chipset_fsp_util.c
+
+cbfs-files-$(CONFIG_FSP_MEMORY_DOWN_CH0DIMM0_SPD_PRESENT) += spd_ch0_dimm0.bin
+spd_ch0_dimm0.bin-file := $(call strip_quotes,$(CONFIG_FSP_MEMORY_DOWN_CH0DIMM0_SPD_FILE))
+spd_ch0_dimm0.bin-type := spd
+
+cbfs-files-$(CONFIG_FSP_MEMORY_DOWN_CH0DIMM1_SPD_PRESENT) += spd_ch0_dimm1.bin
+spd_ch0_dimm1.bin-file := $(call strip_quotes,$(CONFIG_FSP_MEMORY_DOWN_CH0DIMM1_SPD_FILE))
+spd_ch0_dimm1.bin-type := spd
+
+cbfs-files-$(CONFIG_FSP_MEMORY_DOWN_CH1DIMM0_SPD_PRESENT) += spd_ch1_dimm0.bin
+spd_ch1_dimm0.bin-file := $(call strip_quotes,$(CONFIG_FSP_MEMORY_DOWN_CH1DIMM0_SPD_FILE))
+spd_ch1_dimm0.bin-type := spd
+
+cbfs-files-$(CONFIG_FSP_MEMORY_DOWN_CH1DIMM1_SPD_PRESENT) += spd_ch1_dimm1.bin
+spd_ch1_dimm1.bin-file := $(call strip_quotes,$(CONFIG_FSP_MEMORY_DOWN_CH1DIMM1_SPD_FILE))
+spd_ch1_dimm1.bin-type := spd
diff --git a/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c b/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c
new file mode 100644
index 0000000000..cab4b5919c
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015-2016 Intel Corporation. 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.
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <bootstate.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <device/device.h>
+#include <device/pci_def.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+#include <soc/pci_devs.h>
+#include <soc/reset.h>
+#include <soc/romstage.h>
+#include <chip.h>
+#include <fsp.h>
+
+/* Copy the default UPD region and settings to a buffer for modification */
+static void GetUpdDefaultFromFsp (FSP_INFO_HEADER *FspInfo, UPD_DATA_REGION *UpdData)
+{
+ VPD_DATA_REGION *VpdDataRgnPtr;
+ UPD_DATA_REGION *UpdDataRgnPtr;
+ VpdDataRgnPtr = (VPD_DATA_REGION *)(UINT32)(FspInfo->CfgRegionOffset + FspInfo->ImageBase);
+ UpdDataRgnPtr = (UPD_DATA_REGION *)(UINT32)(VpdDataRgnPtr->PcdUpdRegionOffset + FspInfo->ImageBase);
+ memcpy((void *)UpdData, (void *)UpdDataRgnPtr, sizeof(UPD_DATA_REGION));
+}
+
+typedef struct soc_intel_fsp_broadwell_de_config config_t;
+
+/**
+ * Update the UPD data based on values from devicetree.cb
+ *
+ * @param UpdData Pointer to the UPD Data structure
+ */
+static void ConfigureDefaultUpdData(UPD_DATA_REGION *UpdData)
+{
+ /*
+ * Serial Port
+ */
+ if (IS_ENABLED(CONFIG_INTEGRATED_UART))
+ UpdData->SerialPortConfigure = 1;
+
+ /*
+ * Memory Down
+ */
+ if (IS_ENABLED(CONFIG_FSP_MEMORY_DOWN)) {
+ UpdData->MemDownEnable = 1;
+
+ if (IS_ENABLED(CONFIG_FSP_MEMORY_DOWN_CH0DIMM0_SPD_PRESENT))
+ UpdData->MemDownCh0Dimm0SpdPtr
+ = (UINT32)cbfs_boot_map_with_leak("spd_ch0_dimm0.bin", CBFS_TYPE_RAW, NULL);
+ if (IS_ENABLED(CONFIG_FSP_MEMORY_DOWN_CH0DIMM1_SPD_PRESENT))
+ UpdData->MemDownCh0Dimm1SpdPtr
+ = (UINT32)cbfs_boot_map_with_leak("spd_ch0_dimm1.bin", CBFS_TYPE_RAW, NULL);
+ if (IS_ENABLED(CONFIG_FSP_MEMORY_DOWN_CH1DIMM0_SPD_PRESENT))
+ UpdData->MemDownCh1Dimm0SpdPtr
+ = (UINT32)cbfs_boot_map_with_leak("spd_ch1_dimm0.bin", CBFS_TYPE_RAW, NULL);
+ if (IS_ENABLED(CONFIG_FSP_MEMORY_DOWN_CH1DIMM1_SPD_PRESENT))
+ UpdData->MemDownCh1Dimm1SpdPtr
+ = (UINT32)cbfs_boot_map_with_leak("spd_ch1_dimm1.bin", CBFS_TYPE_RAW, NULL);
+ } else {
+ UpdData->MemDownEnable = 0;
+ }
+ printk(FSP_INFO_LEVEL, "Memory Down Support: %s\n",
+ UpdData->MemDownEnable ? "Enabled" : "Disabled");
+
+ /*
+ * Fast Boot
+ */
+ if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE))
+ UpdData->MemFastBoot = 1;
+ else
+ UpdData->MemFastBoot = 0;
+
+ /*
+ * Hyper-Threading
+ */
+ if (IS_ENABLED(CONFIG_FSP_HYPERTHREADING))
+ UpdData->HyperThreading = 1;
+ else
+ UpdData->HyperThreading = 0;
+}
+
+/* Set up the Broadwell-DE specific structures for the call into the FSP */
+void chipset_fsp_early_init(FSP_INIT_PARAMS *pFspInitParams, FSP_INFO_HEADER *fsp_ptr)
+{
+ FSP_INIT_RT_BUFFER *pFspRtBuffer = pFspInitParams->RtBufferPtr;
+
+ /* Initialize the UPD Data */
+ GetUpdDefaultFromFsp (fsp_ptr, pFspRtBuffer->Common.UpdDataRgnPtr);
+ ConfigureDefaultUpdData(pFspRtBuffer->Common.UpdDataRgnPtr);
+ pFspInitParams->NvsBufferPtr = NULL;
+
+#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+ /* Find the fastboot cache that was saved in the ROM */
+ pFspInitParams->NvsBufferPtr = find_and_set_fastboot_cache();
+#endif
+
+ return;
+}
+
+/* The FSP returns here after the fsp_early_init call */
+void ChipsetFspReturnPoint(EFI_STATUS Status, VOID *HobListPtr)
+{
+ *(void **)CBMEM_FSP_HOB_PTR = HobListPtr;
+
+ if (Status == 0xFFFFFFFF) {
+ warm_reset();
+ }
+
+ romstage_main_continue(Status, HobListPtr);
+}
diff --git a/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.h b/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.h
new file mode 100644
index 0000000000..057d7fda0d
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015-2016 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef CHIPSET_FSP_UTIL_H
+#define CHIPSET_FSP_UTIL_H
+
+#include <fsp.h>
+
+#define FSP_INFO_HEADER_GUID \
+ { \
+ 0x912740BE, 0x2284, 0x4734, {0xB9, 0x71, 0x84, 0xB0, 0x27, 0x35, 0x3F, 0x0C} \
+ }
+
+/*
+ * The FSP Image ID is different for each platform's FSP and
+ * can be used to verify that the right FSP binary is loaded.
+ * For the Broadwell-DE FSP, the Image Id is "BDX-DE".
+ */
+#define FSP_IMAGE_ID_DWORD0 ((unsigned int)(FSP_IMAGE_ID))
+#define FSP_IMAGE_ID_DWORD1 ((unsigned int)(FSP_IMAGE_ID >> 32))
+
+#endif /* CHIPSET_FSP_UTIL_H */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h b/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h
new file mode 100644
index 0000000000..f717d15a3b
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_ACPI_H_
+#define _SOC_ACPI_H_
+
+#include <arch/acpi.h>
+
+void acpi_create_intel_hpet(acpi_hpet_t *hpet);
+void acpi_fill_in_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt);
+unsigned long acpi_madt_irq_overrides(unsigned long current);
+uint16_t get_pmbase(void);
+
+#endif /* _SOC_ACPI_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h b/src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h
new file mode 100644
index 0000000000..6828d03dc9
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h
@@ -0,0 +1,20 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_BROADWELL_DE_H_
+#define _SOC_BROADWELL_DE_H_
+
+#endif /* _SOC_BROADWELL_DE_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/iomap.h b/src/soc/intel/fsp_broadwell_de/include/soc/iomap.h
new file mode 100644
index 0000000000..ca842997a9
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/iomap.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_IOMAP_H_
+#define _SOC_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 0x00010000
+
+/* PSEG */
+#define PSEG_BASE_ADDRESS 0xfeb80000
+#define PSEG_BASE_SIZE 0x00080000
+
+/* IOxAPIC */
+#define IOXAPIC1_BASE_ADDRESS 0xfec00000
+#define IOXAPIC1_BASE_SIZE 0x00100000
+#define IOXAPIC2_BASE_ADDRESS 0xfec01000
+#define IOXAPIC2_BASE_SIZE 0x00100000
+
+/* PCH (HPET/LT/TPM/Others) */
+#define PCH_BASE_ADDRESS 0xfed00000
+#define PCH_BASE_SIZE 0x00100000
+
+/* Local XAPIC */
+#define LXAPIC_BASE_ADDRESS 0xfee00000
+#define LXAPIC_BASE_SIZE 0x00100000
+
+/* High Performance Event Timer */
+#define HPET_BASE_ADDRESS 0xfed00000
+#define HPET_BASE_SIZE 0x400
+
+/* Firmware */
+#define FIRMWARE_BASE_ADDRESS 0xff000000
+#define FIRMWARE_BASE_SIZE 0x01000000
+
+/*
+ * IO Port bases.
+ */
+
+/* ACPI Base Address */
+#define ACPI_BASE_ADDRESS 0x400
+#define ACPI_BASE_SIZE 0x80
+
+#endif /* _SOC_IOMAP_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/irq.h b/src/soc/intel/fsp_broadwell_de/include/soc/irq.h
new file mode 100644
index 0000000000..ea043267e3
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/irq.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_IRQ_H_
+#define _SOC_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
+
+/* PIC IRQ settings. */
+#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
+#define PIRQ_PIC_IRQDISABLE 0x80
+#define PIRQ_PIC_UNKNOWN_UNUSED 0xff
+
+/* 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
+
+/* 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_OF_PCI_DEVS 32
+#define NUM_PIRQS 8
+
+struct broadwell_de_irq_route {
+ /* Per device configuration. */
+ uint16_t pcidev[NUM_OF_PCI_DEVS];
+ /* Route path for each internal PIRQx in PIC mode. */
+ uint8_t pic[NUM_PIRQS];
+};
+
+extern const struct broadwell_de_irq_route global_broadwell_de_irq_route;
+
+#define DEFINE_IRQ_ROUTES \
+ const struct broadwell_de_irq_route global_broadwell_de_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 /* _SOC_IRQ_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h b/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h
new file mode 100644
index 0000000000..2c02ebdf47
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_LPC_H_
+#define _SOC_LPC_H_
+
+/* LPC Interface Bridge PCI Configuration Registers */
+#define REVID 0x08
+#define PIRQ_RCR1 0x60
+#define PIRQ_RCR2 0x68
+#define GEN_PMCON_1 0xA0
+#define GEN_PMCON_2 0xA2
+#define GEN_PMCON_3 0xA4
+#define RTC_PWR_STS (1 << 2)
+
+/* 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
+
+/* 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 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 PCI_EXP_STS (1 << 9)
+#define RI_STS (1 << 8)
+#define SMB_WAK_STS (1 << 7)
+#define TCOSCI_STS (1 << 6)
+#define SWGPE_STS (1 << 2)
+#define HOT_PLUG_STS (1 << 1)
+#define GPE0_EN 0x28
+#define SMI_EN 0x30
+#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
+
+#endif /* _SOC_LPC_H_ */ \ No newline at end of file
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/msr.h b/src/soc/intel/fsp_broadwell_de/include/soc/msr.h
new file mode 100644
index 0000000000..c409ec86b6
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/msr.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_MSR_H_
+#define _SOC_MSR_H_
+
+#define MSR_IA32_PLATFORM_ID 0x17
+#define MSR_CORE_THREAD_COUNT 0x35
+#define MSR_PLATFORM_INFO 0xce
+#define MSR_TURBO_RATIO_LIMIT 0x1ad
+#define MSR_IA32_MC0_STATUS 0x400
+#define MSR_PKG_POWER_SKU_UNIT 0x606
+#define MSR_PKG_POWER_LIMIT 0x610
+
+#endif /* _SOC_MSR_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/pattrs.h b/src/soc/intel/fsp_broadwell_de/include/soc/pattrs.h
new file mode 100644
index 0000000000..232a4f4a7d
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/pattrs.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_PATTRS_H_
+#define _SOC_PATTRS_H_
+
+#include <stdint.h>
+#include <cpu/x86/msr.h>
+
+/*
+ * 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;
+ uint32_t cpuid;
+ int revid;
+ int stepping;
+ const void *microcode_patch;
+ int address_bits;
+ int num_cpus;
+};
+
+/*
+ * 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 /* _SOC_PATTRS_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h b/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h
new file mode 100644
index 0000000000..646ed3fecb
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_PCI_DEVS_H_
+#define _SOC_PCI_DEVS_H_
+
+#define BUS0 0
+
+#define SOC_DEV 0
+#define SOC_FUNC 0
+#define SOC_DEVID 0x2F00
+#define SOC_DEVID_ES2 0x6F00
+#define SOC_DEV_FUNC DEV_FUNC(SOC_DEV, SOC_FUNC)
+
+#define LPC_DEV 31
+#define LPC_FUNC 0
+#define LPC_DEVID 0x8C42
+#define LPC_DEVID_ES2 0x8C54
+#define LPC_DEV_FUNC DEV_FUNC(LPC_DEV, LPC_FUNC)
+
+#define SATA_DEV 31
+#define SATA_FUNC 2
+#define AHCI_DEVID 0x8C02
+#define SATA_DEV_FUNC DEV_FUNC(SATA_DEV, SATA_FUNC)
+
+#define SATA2_DEV 31
+#define SATA2_FUNC 5
+#define SATA2_DEV_FUNC DEV_FUNC(SATA2_DEV, SATA2_FUNC)
+
+#define EHCI1_DEV 29
+#define EHCI1_FUNC 0
+#define EHCI1_DEVID 0x8C26
+#define EHCI1_DEV_FUNC DEV_FUNC(EHCI_DEV1, EHCI_FUNC1)
+
+#define EHCI2_DEV 26
+#define EHCI2_FUNC 0
+#define EHCI2_DEVID 0x8C2D
+#define EHCI2_DEV_FUNC DEV_FUNC(EHCI_DEV2, EHCI_FUNC2)
+
+#define XHCI_DEV 20
+#define XHCI_FUNC 0
+#define XHCI_DEVID 0x8C31
+#define XHCI_FUS_REG 0xE0
+#define XHCI_FUNC_DISABLE (1 << 0)
+#define XHCI_USB2PR_REG 0xD0
+#define XHCI_DEV_FUNC DEV_FUNC(XHCI_DEV, XHCI_FUNC)
+
+#define GBE_DEV 25
+#define GBE_FUNC 0
+#define GBE_DEVID 0x8C33
+#define GBE_DEV_FUNC DEV_FUNC(GBE_DEV, GBE_FUNC)
+
+#define ME_DEV 22
+#define ME_FUNC 0
+#define ME_DEVID 0x8C3A
+#define ME_DEV_FUNC DEV_FUNC(ME_DEV, ME_FUNC)
+
+#define HDA_DEV 27
+#define HDA_FUNC 0
+#define HDA_DEVID 0x8C20
+#define HDA_DEV_FUNC DEV_FUNC(HDA_DEV, HDA_FUNC)
+
+#define PCIE_DEV 28
+#define PCIE_PORT1_DEV PCIE_DEV
+#define PCIE_PORT1_FUNC 0
+#define PCIE_PORT1_DEVID 0x8C10
+#define PCIE_PORT2_DEV PCIE_DEV
+#define PCIE_PORT2_FUNC 1
+#define PCIE_PORT2_DEVID 0x8C12
+#define PCIE_PORT3_DEV PCIE_DEV
+#define PCIE_PORT3_FUNC 2
+#define PCIE_PORT3_DEVID 0x8C14
+#define PCIE_PORT4_DEV PCIE_DEV
+#define PCIE_PORT4_FUNC 3
+#define PCIE_PORT4_DEVID 0x8C16
+#define PCIE_PORT5_DEV PCIE_DEV
+#define PCIE_PORT5_FUNC 4
+#define PCIE_PORT5_DEVID 0x8C18
+#define PCIE_PORT6_DEV PCIE_DEV
+#define PCIE_PORT6_FUNC 5
+#define PCIE_PORT6_DEVID 0x8C1A
+#define PCIE_PORT7_DEV PCIE_DEV
+#define PCIE_PORT7_FUNC 6
+#define PCIE_PORT7_DEVID 0x8C1C
+#define PCIE_PORT8_DEV PCIE_DEV
+#define PCIE_PORT8_FUNC 7
+#define PCIE_PORT8_DEVID 0x8C1E
+#define PCIE_PORT1_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT1_FUNC)
+#define PCIE_PORT2_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT2_FUNC)
+#define PCIE_PORT3_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT3_FUNC)
+#define PCIE_PORT4_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT4_FUNC)
+#define PCIE_PORT5_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT5_FUNC)
+#define PCIE_PORT6_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT6_FUNC)
+#define PCIE_PORT7_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT7_FUNC)
+#define PCIE_PORT8_DEV_FUNC DEV_FUNC(PCIE_DEV, PCIE_PORT8_FUNC)
+
+#endif /* _SOC_PCI_DEVS_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/ramstage.h b/src/soc/intel/fsp_broadwell_de/include/soc/ramstage.h
new file mode 100644
index 0000000000..c01c9ac081
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/ramstage.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_RAMSTAGE_H_
+#define _SOC_RAMSTAGE_H_
+
+#include <device/device.h>
+
+/* The broadwell_de_init_pre_device() function is called prior to device
+ * initialization, but it's after console and cbmem has been reinitialized. */
+void broadwell_de_init_pre_device(void);
+void broadwell_de_init_cpus(device_t dev);
+void southcluster_enable_dev(device_t dev);
+
+extern struct pci_operations soc_pci_ops;
+
+#endif /* _SOC_RAMSTAGE_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/reset.h b/src/soc/intel/fsp_broadwell_de/include/soc/reset.h
new file mode 100644
index 0000000000..fa0ceac091
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/reset.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_RESET_H_
+#define _SOC_RESET_H_
+
+#include <reset.h>
+
+void warm_reset(void);
+
+#endif /* _SOC_RESET_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/romstage.h b/src/soc/intel/fsp_broadwell_de/include/soc/romstage.h
new file mode 100644
index 0000000000..94a5a5669c
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/romstage.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_ROMSTAGE_H_
+#define _SOC_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 <fsp.h>
+
+void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr);
+
+#define NUM_ROMSTAGE_TS 4
+
+void early_mainboard_romstage_entry(void);
+void late_mainboard_romstage_entry(void);
+
+#endif /* _SOC_ROMSTAGE_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/memmap.c b/src/soc/intel/fsp_broadwell_de/memmap.c
new file mode 100644
index 0000000000..75100948b9
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/memmap.c
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cbmem.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+
+void *cbmem_top(void)
+{
+ return find_fsp_reserved_mem(*(void **)CBMEM_FSP_HOB_PTR);
+}
diff --git a/src/soc/intel/fsp_broadwell_de/northcluster.c b/src/soc/intel/fsp_broadwell_de/northcluster.c
new file mode 100644
index 0000000000..307137bd6a
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/northcluster.c
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <console/console.h>
+#include <cpu/x86/lapic.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+
+static const int legacy_hole_base_k = 0xa0000 / 1024;
+static const int legacy_hole_size_k = 384;
+
+static int add_fixed_resources(struct device *dev, int index)
+{
+ struct resource *resource;
+ u32 pcie_config_base, pcie_config_size;
+ pcie_config_base = MCFG_BASE_ADDRESS;
+ pcie_config_size = MCFG_BASE_SIZE;
+
+ printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x "
+ "size=0x%x\n", pcie_config_base, pcie_config_size);
+ resource = new_resource(dev, index++);
+ resource->base = (resource_t) pcie_config_base;
+ resource->size = (resource_t) pcie_config_size;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+
+ resource = new_resource(dev, index++); /* Local APIC */
+ resource->base = LAPIC_DEFAULT_BASE;
+ resource->size = 0x00001000;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+
+ mmio_resource(dev, index++, legacy_hole_base_k, legacy_hole_size_k);
+
+ return index;
+}
+
+static void mc_add_dram_resources(device_t dev)
+{
+ u32 fsp_mem_base, fsp_mem_len;
+ u32 tseg_base, tseg_length;
+ u32 rsv_base, rsv_length;
+ u32 tolm;
+ int index = 0;
+ uint64_t highmem_size = 0;
+
+ fsp_mem_base = GetFspReservedMemory(FspHobListPtr, &fsp_mem_len);
+ highmem_size = GetUsableHighMemTop(FspHobListPtr) - 0x100000000L;
+ tseg_base = GetTsegReservedMemory(FspHobListPtr, &tseg_length);
+ tolm = GetPhysicalLowMemTop(FspHobListPtr);
+
+ printk(BIOS_DEBUG, "\n\n");
+ printk(BIOS_DEBUG, "fsp_mem_base: 0x%.8x\n", fsp_mem_base);
+ printk(BIOS_DEBUG, "fsp_mem_len: 0x%.8x\n", fsp_mem_len);
+ printk(BIOS_DEBUG, "tseg_base: 0x%.8x\n", tseg_base);
+ printk(BIOS_DEBUG, "tseg_len: 0x%.8x\n", tseg_length);
+ printk(BIOS_DEBUG, "highmem_size: 0x%.8x %.8x\n",
+ (u32)(highmem_size>>32),
+ (u32)(highmem_size&0xffffffff));
+ printk(BIOS_DEBUG, "tolm: 0x%.8x\n", tolm);
+ printk(BIOS_DEBUG, "Top of system low memory: 0x%08x\n", tolm);
+ printk(BIOS_DEBUG, "FSP memory location: 0x%x\n (size: %dM)\n",
+ fsp_mem_base, fsp_mem_len >> 20);
+ printk(BIOS_DEBUG, "tseg: 0x%08x (size: 0x%.8x)\n",
+ tseg_base, tseg_length);
+
+ /* Report the memory regions. */
+ ram_resource(dev, index++, 0, legacy_hole_base_k);
+ ram_resource(dev, index++, legacy_hole_base_k + legacy_hole_size_k,
+ ((fsp_mem_base >> 10) - (legacy_hole_base_k + legacy_hole_size_k)));
+
+ /* Mark SMM & FSP regions reserved */
+ mmio_resource(dev, index++, tseg_base >> 10, tseg_length >> 10);
+ mmio_resource(dev, index++, fsp_mem_base >> 10, fsp_mem_len >> 10);
+
+ /* Reserve MMIO space */
+ rsv_base = fsp_mem_base + fsp_mem_len;
+ rsv_length = tseg_base - rsv_base;
+ if (rsv_length) {
+ mmio_resource(dev, index++, rsv_base >> 10, rsv_length >> 10);
+ printk(BIOS_DEBUG, "Reserved MMIO : 0x%08x length 0x%08x\n",
+ rsv_base, rsv_length);
+ }
+
+ rsv_base = tseg_base + tseg_length;
+ rsv_length = tolm - rsv_base;
+ if (rsv_length) {
+ mmio_resource(dev, index++, rsv_base >> 10, rsv_length >> 10);
+ printk(BIOS_DEBUG, "Reserved MMIO : 0x%08x length 0x%08x\n",
+ rsv_base, rsv_length);
+ }
+
+ if (highmem_size) {
+ ram_resource(dev, index++, 0x100000000 >> 10, highmem_size >> 10);
+ }
+ printk(BIOS_INFO, "Available memory above 4GB: %lluM\n",
+ highmem_size >> 20);
+
+ index = add_fixed_resources(dev, index);
+}
+
+static void nc_read_resources(device_t dev)
+{
+ /* Call the normal read_resources */
+ pci_dev_read_resources(dev);
+
+ /* Calculate and add DRAM resources. */
+ mc_add_dram_resources(dev);
+}
+
+static void nc_enable(device_t dev)
+{
+ print_fsp_info();
+}
+
+static struct device_operations nc_ops = {
+ .read_resources = nc_read_resources,
+ .acpi_fill_ssdt_generator = generate_cpu_entries,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = NULL,
+ .enable = &nc_enable,
+ .scan_bus = 0,
+ .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,
+};
+
+static const struct pci_driver nc_driver_es2 __pci_driver = {
+ .ops = &nc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = SOC_DEVID_ES2,
+}; \ No newline at end of file
diff --git a/src/soc/intel/fsp_broadwell_de/ramstage.c b/src/soc/intel/fsp_broadwell_de/ramstage.c
new file mode 100644
index 0000000000..7b2f141bf1
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/ramstage.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdlib.h>
+#include <arch/cpu.h>
+#include <arch/acpi.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 <romstage_handoff.h>
+#include <soc/lpc.h>
+#include <soc/msr.h>
+#include <soc/pattrs.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+
+/* Global PATTRS */
+DEFINE_PATTRS;
+
+#define SHOW_PATTRS 1
+
+static void detect_num_cpus(struct pattrs *attrs)
+{
+ msr_t core_thread_count = rdmsr(MSR_CORE_THREAD_COUNT);
+ attrs->num_cpus = core_thread_count.lo & 0xffff;
+}
+
+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[] = {
+ "U0", "V1", "V2", "Y0"
+};
+
+static void fill_in_pattrs(void)
+{
+ device_t dev;
+ struct pattrs *attrs = (struct pattrs *)pattrs_get();
+
+ attrs->cpuid = cpuid_eax(1);
+ attrs->stepping = (attrs->cpuid & 0x0F) - 1;
+ dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC));
+ attrs->revid = pci_read_config8(dev, REVID);
+ attrs->microcode_patch = intel_microcode_find();
+ attrs->address_bits = cpuid_eax(0x80000008) & 0xff;
+ detect_num_cpus(attrs);
+
+ if (SHOW_PATTRS) {
+ printk(BIOS_DEBUG, "CPUID: %08x\n", attrs->cpuid);
+ printk(BIOS_DEBUG, "Cores: %d\n", attrs->num_cpus);
+ printk(BIOS_DEBUG, "Stepping: %s\n", (attrs->stepping >= ARRAY_SIZE(stepping_str))
+ ? "??" : stepping_str[attrs->stepping]);
+ printk(BIOS_DEBUG, "Revision ID: %02x\n", attrs->revid);
+ }
+
+ fill_in_msr(&attrs->platform_id, MSR_IA32_PLATFORM_ID);
+ fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO);
+}
+
+void broadwell_de_init_pre_device(void)
+{
+ fill_in_pattrs();
+}
diff --git a/src/soc/intel/fsp_broadwell_de/reset.c b/src/soc/intel/fsp_broadwell_de/reset.c
new file mode 100644
index 0000000000..7e1c582749
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/reset.c
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <soc/reset.h>
+
+void warm_reset(void)
+{
+ outb(0x00, 0xcf9);
+ outb(0x06, 0xcf9);
+}
+
+void hard_reset(void)
+{
+ warm_reset();
+}
diff --git a/src/soc/intel/fsp_broadwell_de/romstage/Makefile.inc b/src/soc/intel/fsp_broadwell_de/romstage/Makefile.inc
new file mode 100644
index 0000000000..436f038611
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/romstage/Makefile.inc
@@ -0,0 +1,3 @@
+romstage-y += romstage.c
+
+$(obj)/soc/intel/fsp_broadwell_de/romstage/romstage.romstage.o : $(obj)/build.h \ No newline at end of file
diff --git a/src/soc/intel/fsp_broadwell_de/romstage/romstage.c b/src/soc/intel/fsp_broadwell_de/romstage/romstage.c
new file mode 100644
index 0000000000..dc883a4308
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/romstage/romstage.c
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stddef.h>
+#include <arch/cpu.h>
+#include <lib.h>
+#include <arch/io.h>
+#include <arch/cbfs.h>
+#include <arch/stages.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include <romstage_handoff.h>
+#include <timestamp.h>
+#include <version.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+#include <pc80/mc146818rtc.h>
+#include <soc/iomap.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/romstage.h>
+#include <build.h>
+
+static void init_rtc(void)
+{
+ u16 gen_pmcon3 = pci_read_config16(PCI_DEV(0, LPC_DEV, LPC_FUNC), GEN_PMCON_3);
+
+ if (gen_pmcon3 & RTC_PWR_STS) {
+ printk(BIOS_DEBUG, "RTC Failure detected. Resetting Date to %s\n",
+ coreboot_dmi_date);
+ }
+ cmos_init(gen_pmcon3 & RTC_PWR_STS);
+}
+
+/* Entry from cache-as-ram.inc. */
+void *asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
+{
+ post_code(0x40);
+ console_init();
+ init_rtc();
+
+ post_code(0x41);
+ timestamp_init(get_initial_timestamp());
+ timestamp_add_now(TS_START_ROMSTAGE);
+
+ /* Call into mainboard. */
+ early_mainboard_romstage_entry();
+
+ /*
+ * Call early init to initialize memory and chipset. This function returns
+ * to the romstage_main_continue function with a pointer to the HOB
+ * structure.
+ */
+ post_code(0x48);
+ timestamp_add_now(TS_BEFORE_INITRAM);
+ printk(BIOS_DEBUG, "Starting the Intel FSP (early_init)\n");
+ fsp_early_init(fsp_info_header);
+ die("Uh Oh! fsp_early_init should not return here.\n");
+}
+
+/*******************************************************************************
+ * The FSP early_init function returns to this function.
+ * Memory is setup and the stack is set by the FSP.
+ */
+void romstage_main_continue(EFI_STATUS status, void *hob_list_ptr)
+{
+ int cbmem_was_initted;
+ void *cbmem_hob_ptr;
+
+ post_code(0x4a);
+ timestamp_add_now(TS_AFTER_INITRAM);
+ printk(BIOS_DEBUG, "%s status: %x hob_list_ptr: %x\n",
+ __func__, (u32) status, (u32) hob_list_ptr);
+
+#if IS_ENABLED(CONFIG_USBDEBUG_IN_ROMSTAGE)
+ /* FSP reconfigures USB, so reinit it to have debug */
+ usbdebug_init();
+#endif /* IS_ENABLED(CONFIG_USBDEBUG_IN_ROMSTAGE) */
+
+ printk(BIOS_DEBUG, "FSP Status: 0x%0x\n", (u32)status);
+
+ post_code(0x4b);
+ late_mainboard_romstage_entry();
+
+ post_code(0x4c);
+ quick_ram_check();
+
+ post_code(0x4d);
+ cbmem_was_initted = !cbmem_recovery(0);
+
+ /* Save the HOB pointer in CBMEM to be used in ramstage*/
+ cbmem_hob_ptr = cbmem_add (CBMEM_ID_HOB_POINTER, sizeof(*hob_list_ptr));
+ if (cbmem_hob_ptr == NULL) {
+ printk(BIOS_DEBUG, "Failed to save HOB pointer in CBMEM.\n");
+ return;
+ }
+ *(u32 *)cbmem_hob_ptr = (u32)hob_list_ptr;
+
+ /* Load the ramstage. */
+ post_code(0x4e);
+ copy_and_run();
+ while (1);
+}
+
+uint64_t get_initial_timestamp(void)
+{
+ return 0;
+}
diff --git a/src/soc/intel/fsp_broadwell_de/southcluster.c b/src/soc/intel/fsp_broadwell_de/southcluster.c
new file mode 100644
index 0000000000..7024814bb2
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/southcluster.c
@@ -0,0 +1,267 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <arch/ioapic.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_def.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/i8254.h>
+#include <pc80/i8259.h>
+#include <pc80/isa-dma.h>
+#include <romstage_handoff.h>
+#include <soc/iomap.h>
+#include <soc/irq.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include <chip.h>
+
+typedef struct soc_intel_fsp_broadwell_de_config config_t;
+
+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, 0xfeb0,
+ ABORT_BASE_ADDRESS,
+ ABORT_BASE_SIZE);
+ add_mmio_resource(dev, 0xfeb8,
+ PSEG_BASE_ADDRESS,
+ PSEG_BASE_SIZE);
+ add_mmio_resource(dev, 0xfec0,
+ IOXAPIC1_BASE_ADDRESS,
+ IOXAPIC1_BASE_SIZE);
+ add_mmio_resource(dev, 0xfec1,
+ IOXAPIC2_BASE_ADDRESS,
+ IOXAPIC2_BASE_SIZE);
+ add_mmio_resource(dev, 0xfed0,
+ PCH_BASE_ADDRESS,
+ PCH_BASE_SIZE);
+ add_mmio_resource(dev, 0xfee0,
+ LXAPIC_BASE_ADDRESS,
+ LXAPIC_BASE_SIZE);
+ add_mmio_resource(dev, 0xff00,
+ FIRMWARE_BASE_ADDRESS,
+ FIRMWARE_BASE_SIZE);
+}
+
+/*
+ * Write PCI config space IRQ assignments. PCI devices have the INT_LINE
+ * (0x3C) and INT_PIN (0x3D) registers which report interrupt routing
+ * information to operating systems and drivers. The INT_PIN register is
+ * generally read only and reports which interrupt pin A - D it uses. The
+ * INT_LINE register is configurable and reports which IRQ (generally the
+ * PIC IRQs 1 - 15) it will use. This needs to take interrupt pin swizzling
+ * on devices that are downstream on a PCI bridge into account.
+ *
+ * This function will loop through all enabled PCI devices and program the
+ * INT_LINE register with the correct PIC IRQ number for the INT_PIN that it
+ * uses. It then configures each interrupt in the pic to be level triggered.
+ */
+static void write_pci_config_irqs(void)
+{
+ device_t irq_dev;
+ device_t targ_dev;
+ uint8_t int_line = 0;
+ uint8_t original_int_pin = 0;
+ uint8_t new_int_pin = 0;
+ uint16_t current_bdf = 0;
+ uint16_t parent_bdf = 0;
+ uint8_t pirq = 0;
+ uint8_t device_num = 0;
+ const struct broadwell_de_irq_route *ir = &global_broadwell_de_irq_route;
+
+ if (ir == NULL) {
+ printk(BIOS_WARNING, "Warning: Can't write PCI IRQ assignments because"
+ " 'global_broadwell_de_irq_route' structure does not exist\n");
+ return;
+ }
+
+ /*
+ * Loop through all enabled devices and program their
+ * INT_LINE, INT_PIN registers from values taken from
+ * the Interrupt Route registers in the ILB
+ */
+ printk(BIOS_DEBUG, "PCI_CFG IRQ: Write PCI config space IRQ assignments\n");
+ for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
+
+ if ((irq_dev->path.type != DEVICE_PATH_PCI) ||
+ (!irq_dev->enabled))
+ continue;
+
+ current_bdf = irq_dev->path.pci.devfn |
+ irq_dev->bus->secondary << 8;
+
+ /*
+ * Step 1: Get the INT_PIN and device structure to look for
+ * in the pirq_data table defined in the mainboard directory.
+ */
+ targ_dev = NULL;
+ new_int_pin = get_pci_irq_pins(irq_dev, &targ_dev);
+ if (targ_dev == NULL || new_int_pin < 1)
+ continue;
+
+ /* Get the original INT_PIN for record keeping */
+ original_int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
+
+ parent_bdf = targ_dev->path.pci.devfn
+ | targ_dev->bus->secondary << 8;
+ device_num = PCI_SLOT(parent_bdf);
+
+ if (ir->pcidev[device_num] == 0) {
+ printk(BIOS_WARNING,
+ "Warning: PCI Device %d does not have an IRQ entry, skipping it\n",
+ device_num);
+ continue;
+ }
+
+ /* Find the PIRQ that is attached to the INT_PIN this device uses */
+ pirq = (ir->pcidev[device_num] >> ((new_int_pin - 1) * 4)) & 0xF;
+
+ /* Get the INT_LINE this device/function will use */
+ int_line = ir->pic[pirq];
+
+ if (int_line != PIRQ_PIC_IRQDISABLE) {
+ /* Set this IRQ to level triggered since it is used by a PCI device */
+ i8259_configure_irq_trigger(int_line, IRQ_LEVEL_TRIGGERED);
+ /* Set the Interrupt Line register in PCI config space */
+ pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
+ } else {
+ /* Set the Interrupt line register as "unknown or unused" */
+ pci_write_config8(irq_dev, PCI_INTERRUPT_LINE,
+ PIRQ_PIC_UNKNOWN_UNUSED);
+ }
+
+ printk(BIOS_SPEW, "\tINT_PIN\t\t: %d (%s)\n",
+ original_int_pin, pin_to_str(original_int_pin));
+ if (parent_bdf != current_bdf)
+ printk(BIOS_SPEW, "\tSwizzled to\t: %d (%s)\n",
+ new_int_pin, pin_to_str(new_int_pin));
+ printk(BIOS_SPEW, "\tPIRQ\t\t: %c\n"
+ "\tINT_LINE\t: 0x%X (IRQ %d)\n",
+ 'A' + pirq, int_line, int_line);
+ }
+ printk(BIOS_DEBUG, "PCI_CFG IRQ: Finished writing PCI config space IRQ assignments\n");
+}
+
+static void sc_pirq_init(device_t dev)
+{
+ int i;
+ const uint8_t *pirq = global_broadwell_de_irq_route.pic;
+ printk(BIOS_DEBUG, "Programming PIRQ[A-H] Routing Control Register\n");
+
+ for (i = 0; i < 8; i++) {
+ pci_write_config8(dev, (i < 4) ? (PIRQ_RCR1+i) : (PIRQ_RCR2+i-4), pirq[i]);
+ printk(BIOS_DEBUG, " PIRQ[%c]: %.2x\n"
+ , 'A'+i
+ , pci_read_config8(dev, (i < 4) ? (PIRQ_RCR1+i) : (PIRQ_RCR2+i-4))
+ );
+ }
+}
+
+static void sc_add_io_resources(device_t dev)
+{
+ struct resource *res;
+ u8 io_index = 0;
+
+ /*
+ * Add the default claimed IO range for the LPC device
+ * and mark it as subtractive decode.
+ */
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 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_SUBTRACTIVE |
+ IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void sc_read_resources(device_t dev)
+{
+ pci_dev_read_resources(dev);
+ sc_add_mmio_resources(dev);
+ sc_add_io_resources(dev);
+}
+
+static void sc_init(struct device *dev)
+{
+ printk(BIOS_DEBUG, "soc: southcluster_init\n");
+
+ /* Set the value for PCI command register. */
+ pci_write_config16(dev, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL);
+
+ /* Program Serial IRQ register. */
+ pci_write_config16(dev, 0x64, 0xd0);
+
+ sc_pirq_init(dev);
+ write_pci_config_irqs();
+ isa_dma_init();
+ setup_i8259();
+ setup_i8254();
+}
+
+/*
+ * Common code for the south cluster devices.
+ */
+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);
+ }
+}
+
+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_lpc_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,
+};
+
+static const struct pci_driver southcluster_es2 __pci_driver = {
+ .ops = &device_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = LPC_DEVID_ES2,
+};
diff --git a/src/soc/intel/fsp_broadwell_de/spi.c b/src/soc/intel/fsp_broadwell_de/spi.c
new file mode 100644
index 0000000000..f98ab97843
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/spi.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright (c) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; 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.
+ */
+
+/* This file is derived from the flashrom project. */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <delay.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <spi_flash.h>
+#include <spi-generic.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 IS_ENABLED(CONFIG_DEBUG_SPI_FLASH)
+
+static u8 readb_(const void *addr)
+{
+ u8 v = read8(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(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(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;
+}
+
+void spi_init(void)
+{
+ uint8_t *rcrb; /* Root Complex Register Block */
+ uint32_t rcba; /* Root Complex Base Address */
+ uint8_t bios_cntl;
+ device_t dev;
+ ich9_spi_regs *ich9_spi;
+
+#ifdef __SMM__
+ dev = PCI_DEV(0, 31, 0);
+#else
+ dev = dev_find_slot(0, PCI_DEVFN(31, 0));
+#endif
+
+ pci_read_config_dword(dev, 0xf0, &rcba);
+ /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
+ rcrb = (uint8_t *)(rcba & 0xffffc000);
+ ich9_spi = (ich9_spi_regs *)(rcrb + 0x3800);
+ 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);
+
+ /* Disable the BIOS write protect so write commands are allowed. */
+ pci_read_config_byte(dev, 0xdc, &bios_cntl);
+ bios_cntl &= ~(1 << 5);
+ pci_write_config_byte(dev, 0xdc, bios_cntl | 0x1);
+}
+
+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);
+ opcode_index = spi_setup_opcode(&trans);
+ if (opcode_index < 0)
+ return -1;
+ with_address = spi_setup_offset(&trans);
+ if (with_address < 0)
+ return -1;
+
+ if (!ichspi_lock && 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.
+ */
+ 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
+ * bitesout 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;
+ }
+
+ goto spi_xfer_exit;
+ }
+
+ /*
+ * 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;
+ }
+ }
+
+spi_xfer_exit:
+ /* Clear atomic preop now that xfer is done */
+ writew_(0, cntlr.preop);
+
+ return 0;
+}
diff --git a/src/soc/intel/fsp_broadwell_de/uart.c b/src/soc/intel/fsp_broadwell_de/uart.c
new file mode 100644
index 0000000000..d22dd0dc50
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/uart.c
@@ -0,0 +1,112 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2003 Eric Biederman
+ * Copyright (C) 2006-2010 coresystems GmbH
+ * Copyright (C) 2015-2016 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <rules.h>
+#include <stdlib.h>
+#include <arch/io.h>
+#include <console/uart.h>
+#include <trace.h>
+#include <drivers/uart/uart8250reg.h>
+
+#ifndef __ROMCC__
+#include <boot/coreboot_tables.h>
+#endif
+
+/* Expected character delay at 1200bps is 9ms for a working UART
+ * and no flow-control. Assume UART as stuck if shift register
+ * or FIFO takes more than 50ms per character to appear empty.
+ *
+ * Estimated that inb() from UART takes 1 microsecond.
+ */
+#define SINGLE_CHAR_TIMEOUT (50 * 1000)
+#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
+
+static int uart8250_can_tx_byte(unsigned base_port)
+{
+ return inb(base_port + UART8250_LSR) & UART8250_LSR_THRE;
+}
+
+static void uart8250_tx_byte(unsigned base_port, unsigned char data)
+{
+ unsigned long int i = SINGLE_CHAR_TIMEOUT;
+ while (i-- && !uart8250_can_tx_byte(base_port));
+ outb(data, base_port + UART8250_TBR);
+}
+
+static void uart8250_tx_flush(unsigned base_port)
+{
+ unsigned long int i = FIFO_TIMEOUT;
+ while (i-- && !(inb(base_port + UART8250_LSR) & UART8250_LSR_TEMT));
+}
+
+static int uart8250_can_rx_byte(unsigned base_port)
+{
+ return inb(base_port + UART8250_LSR) & UART8250_LSR_DR;
+}
+
+static unsigned char uart8250_rx_byte(unsigned base_port)
+{
+ unsigned long int i = SINGLE_CHAR_TIMEOUT;
+ while (i-- && !uart8250_can_rx_byte(base_port));
+
+ if (i)
+ return inb(base_port + UART8250_RBR);
+ else
+ return 0x0;
+}
+
+static const unsigned bases[] = { 0x3f8, 0x2f8 };
+
+uintptr_t uart_platform_base(int idx)
+{
+ if (idx < ARRAY_SIZE(bases))
+ return bases[idx];
+ return 0;
+}
+
+void uart_init(int idx)
+{
+ // No needed to configure as setting has been done in BDX-DE FSP
+}
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+ uart8250_tx_byte(uart_platform_base(idx), data);
+}
+
+unsigned char uart_rx_byte(int idx)
+{
+ return uart8250_rx_byte(uart_platform_base(idx));
+}
+
+void uart_tx_flush(int idx)
+{
+ uart8250_tx_flush(uart_platform_base(idx));
+}
+
+#if ENV_RAMSTAGE
+void uart_fill_lb(void *data)
+{
+ struct lb_serial serial;
+ serial.type = LB_SERIAL_TYPE_IO_MAPPED;
+ serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
+ serial.baud = default_baudrate();
+ lb_add_serial(&serial, data);
+
+ lb_add_console(LB_TAG_CONSOLE_SERIAL8250, data);
+}
+#endif