diff options
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 |