Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/38548 )
Change subject: soc/intel: Add Intel Xeon Scalable Processor support ......................................................................
soc/intel: Add Intel Xeon Scalable Processor support
This patch adds support for Intel Xeon-SP.
This patch is developed and verified with Skylake Scalable Processor, which is a processor in Xeon-SP family. The code is expected to be reusable for future geneations of Xeon-SP processors, and will be updated with smaller targeted patches accordingly, to add support for additional Xeon-SP processors, to add features, and to improve the code base.
The Skylake-SP FSP is based on FSP 2.0. The FSP is a proof-of-concept build. The binary is not shared in public, when this patch is upstreamed.
Signed-off-by: Jonathan Zhang jonzhang@fb.com Signed-off-by: Reddy Chagam anjaneya.chagam@intel.com Tested-by: johnny_lin@wiwynn.com Change-Id: Idc9c3bee17caf8b4841f0bc190cb1aa9d38fc23e Reviewed-on: https://review.coreboot.org/c/coreboot/+/38548 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: David Hendricks david.hendricks@gmail.com --- M src/drivers/intel/fsp2_0/Kconfig M src/soc/intel/Kconfig A src/soc/intel/xeon_sp/Kconfig A src/soc/intel/xeon_sp/Makefile.inc A src/soc/intel/xeon_sp/acpi.c A src/soc/intel/xeon_sp/acpi/globalnvs.asl A src/soc/intel/xeon_sp/acpi/iiostack.asl A src/soc/intel/xeon_sp/acpi/pci_irq.asl A src/soc/intel/xeon_sp/acpi/uncore.asl A src/soc/intel/xeon_sp/acpi/uncore_irq.asl A src/soc/intel/xeon_sp/bootblock/bootblock.c A src/soc/intel/xeon_sp/chip.c A src/soc/intel/xeon_sp/chip.h A src/soc/intel/xeon_sp/cpu.c A src/soc/intel/xeon_sp/hob_display.c A src/soc/intel/xeon_sp/include/soc/acpi.h A src/soc/intel/xeon_sp/include/soc/cpu.h A src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h A src/soc/intel/xeon_sp/include/soc/iomap.h A src/soc/intel/xeon_sp/include/soc/irq.h A src/soc/intel/xeon_sp/include/soc/msr.h A src/soc/intel/xeon_sp/include/soc/nvs.h A src/soc/intel/xeon_sp/include/soc/pci_devs.h A src/soc/intel/xeon_sp/include/soc/pcr_ids.h A src/soc/intel/xeon_sp/include/soc/pm.h A src/soc/intel/xeon_sp/include/soc/pmc.h A src/soc/intel/xeon_sp/include/soc/ramstage.h A src/soc/intel/xeon_sp/include/soc/romstage.h A src/soc/intel/xeon_sp/include/soc/soc_util.h A src/soc/intel/xeon_sp/lpc.c A src/soc/intel/xeon_sp/reset.c A src/soc/intel/xeon_sp/romstage.c A src/soc/intel/xeon_sp/soc_util.c A src/soc/intel/xeon_sp/spi.c A src/soc/intel/xeon_sp/uncore.c A src/soc/intel/xeon_sp/upd_display.c 36 files changed, 5,497 insertions(+), 1 deletion(-)
Approvals: build bot (Jenkins): Verified David Hendricks: Looks good to me, approved
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index 2624644..024a478 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -56,7 +56,7 @@ depends on SOC_INTEL_APOLLOLAKE || SOC_INTEL_SKYLAKE || \ SOC_INTEL_KABYLAKE || SOC_INTEL_COFFEELAKE || \ SOC_INTEL_ICELAKE || SOC_INTEL_WHISKEYLAKE || \ - SOC_INTEL_DENVERTON_NS + SOC_INTEL_DENVERTON_NS || SOC_INTEL_XEON_SP help When selecting this option, the SoC must set FSP_HEADER_PATH and FSP_FD_PATH correctly so FSP splitting works. diff --git a/src/soc/intel/Kconfig b/src/soc/intel/Kconfig index e8935b9..47efc4d 100644 --- a/src/soc/intel/Kconfig +++ b/src/soc/intel/Kconfig @@ -9,6 +9,7 @@ source "src/soc/intel/skylake/Kconfig" source "src/soc/intel/icelake/Kconfig" source "src/soc/intel/tigerlake/Kconfig" +source "src/soc/intel/xeon_sp/Kconfig"
# Load common config source "src/soc/intel/common/Kconfig" diff --git a/src/soc/intel/xeon_sp/Kconfig b/src/soc/intel/xeon_sp/Kconfig new file mode 100644 index 0000000..8c355c4 --- /dev/null +++ b/src/soc/intel/xeon_sp/Kconfig @@ -0,0 +1,134 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 - 2020 Intel Corporation +## Copyright (C) 2019 - 2020 Facebook Inc +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +config SOC_INTEL_XEON_SP + bool + help + Intel Xeon SP support + +if SOC_INTEL_XEON_SP + +config CPU_SPECIFIC_OPTIONS + def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_RAMSTAGE_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_VERSTAGE_X86_32 + select BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY if BOOT_DEVICE_SPI_FLASH + select BOOT_DEVICE_SUPPORTS_WRITES + select POSTCAR_CONSOLE + select SOC_INTEL_COMMON + select SOC_INTEL_COMMON_RESET + select PLATFORM_USES_FSP2_0 + select FSP_PLATFORM_MEMORY_SETTINGS_VERSIONS + select FSP_T_XIP + select FSP_M_XIP + select FSP_USE_REPO + select POSTCAR_STAGE + select IOAPIC + select PARALLEL_MP + select SMP + select INTEL_DESCRIPTOR_MODE_CAPABLE + select COMMON_FADT + select SOC_INTEL_COMMON_BLOCK + select SOC_INTEL_COMMON_BLOCK_CPU + select SOC_INTEL_COMMON_BLOCK_TIMER + select SOC_INTEL_COMMON_BLOCK_LPC + select SOC_INTEL_COMMON_BLOCK_RTC + select SOC_INTEL_COMMON_BLOCK_SPI + select SOC_INTEL_COMMON_BLOCK_FAST_SPI + select SOC_INTEL_COMMON_BLOCK_PCR + select TSC_MONOTONIC_TIMER + select UDELAY_TSC + select SUPPORT_CPU_UCODE_IN_CBFS + select CPU_INTEL_FIRMWARE_INTERFACE_TABLE + +config MAINBOARD_USES_FSP2_0 + bool + default y + +config USE_FSP2_0_DRIVER + def_bool y + depends on MAINBOARD_USES_FSP2_0 + select PLATFORM_USES_FSP2_0 + select UDK_2015_BINDING + select POSTCAR_CONSOLE + select POSTCAR_STAGE + +# Fake FSP binary is used, as the current FSP binary for SKX-SP +# is an engineering build. It is not available to the public +# for now. +config FSP_FD_PATH + string "Location of FSP binary" + depends on FSP_USE_REPO + default "3rdparty/fsp/KabylakeFspBinPkg/Fsp.fd" + +config FSP_HEADER_PATH + string "Location of FSP headers" + depends on MAINBOARD_USES_FSP2_0 + default "src/vendorcode/intel/fsp/fsp2_0/skylake_sp" + +config MAX_SOCKET + int + default 2 + +# For 2S config, the number of cpus could be as high as +# 2 threads * 20 cores * 2 sockets +config MAX_CPUS + int + default 80 + +config PCR_BASE_ADDRESS + hex + default 0xfd000000 + help + This option allows you to select MMIO Base Address of sideband bus. + +config DCACHE_RAM_BASE + hex + default 0xfe800000 + +config DCACHE_RAM_SIZE + hex + default 0x200000 + +config DCACHE_BSP_STACK_SIZE + hex + default 0x10000 + +config MMCONF_BASE_ADDRESS + hex + default 0x80000000 + +config CPU_MICROCODE_CBFS_LOC + hex + default 0xfff0fdc0 + +config CPU_MICROCODE_CBFS_LEN + hex + default 0x7C00 + +config C_ENV_BOOTBLOCK_SIZE + hex + default 0xC000 + +config HEAP_SIZE + hex + default 0x80000 + + +endif ## SOC_INTEL_XEON_SP diff --git a/src/soc/intel/xeon_sp/Makefile.inc b/src/soc/intel/xeon_sp/Makefile.inc new file mode 100644 index 0000000..9ad3e77 --- /dev/null +++ b/src/soc/intel/xeon_sp/Makefile.inc @@ -0,0 +1,59 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 - 2020 Intel Corporation +## Copyright (C) 2019 - 2020 Facebook Inc +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +ifeq ($(CONFIG_SOC_INTEL_XEON_SP),y) + +subdirs-y += ../../../cpu/intel/microcode +subdirs-y += ../../../cpu/intel/turbo +subdirs-y += ../../../cpu/x86/lapic +subdirs-y += ../../../cpu/x86/mtrr +subdirs-y += ../../../cpu/x86/tsc +subdirs-y += ../../../cpu/x86/cache +subdirs-$(CONFIG_HAVE_SMI_HANDLER) += ../../../cpu/x86/smm + +bootblock-y += bootblock/bootblock.c +bootblock-y += spi.c + +postcar-y += soc_util.c +postcar-y += spi.c + +romstage-y += soc_util.c +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += soc_util.c +romstage-y += spi.c +romstage-y += hob_display.c +romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c +romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c + +ramstage-y += soc_util.c +ramstage-y += uncore.c +ramstage-y += reset.c +ramstage-y += chip.c +ramstage-y += soc_util.c +ramstage-y += lpc.c +ramstage-y += cpu.c +ramstage-y += spi.c +ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c +ramstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c +ramstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c +ramstage-y += hob_display.c + +CPPFLAGS_common += -I$(src)/soc/intel/xeon_sp/include +CPPFLAGS_common += -I$(CONFIG_FSP_HEADER_PATH) + +endif ## CONFIG_SOC_INTEL_XEON_SP diff --git a/src/soc/intel/xeon_sp/acpi.c b/src/soc/intel/xeon_sp/acpi.c new file mode 100644 index 0000000..37dd420 --- /dev/null +++ b/src/soc/intel/xeon_sp/acpi.c @@ -0,0 +1,1017 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <assert.h> +#include <arch/acpigen.h> +#include <arch/smp/mpspec.h> +#include <intelblocks/acpi.h> +#include <device/pci.h> +#include <cbmem.h> +#include <soc/acpi.h> +#include <soc/cpu.h> +#include <soc/pci_devs.h> +#include <soc/soc_util.h> +#include <soc/pm.h> +#include "chip.h" + +static int acpi_sci_irq(void) +{ + int sci_irq = 9; + int32_t scis; + + scis = soc_read_sci_irq_select(); + scis &= SCI_IRQ_SEL; + scis >>= SCI_IRQ_ADJUST; + + /* Determine how SCI is routed. */ + switch (scis) { + case SCIS_IRQ9: + case SCIS_IRQ10: + case SCIS_IRQ11: + sci_irq = scis - SCIS_IRQ9 + 9; + break; + case SCIS_IRQ20: + case SCIS_IRQ21: + case SCIS_IRQ22: + case SCIS_IRQ23: + sci_irq = scis - SCIS_IRQ20 + 20; + break; + default: + printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n"); + sci_irq = 9; + break; + } + + printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq); + return sci_irq; +} + +void acpi_init_gnvs(global_nvs_t *gnvs) +{ + /* CPU core count */ + gnvs->pcnt = dev_count_cpu(); + printk(BIOS_DEBUG, "%s gnvs->pcnt: %d\n", __func__, gnvs->pcnt); + + /* Update the mem console pointer. */ + if (CONFIG(CONSOLE_CBMEM)) + gnvs->cbmc = (uint32_t)cbmem_find(CBMEM_ID_CONSOLE); +} + +uint32_t soc_read_sci_irq_select(void) +{ + struct device *dev = PCH_DEV_PMC; + + if (!dev) + return 0; + + return pci_read_config32(dev, PMC_ACPI_CNT); +} + +acpi_cstate_t *soc_get_cstate_map(size_t *entries) +{ + *entries = 0; + return NULL; +} + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, + CONFIG_MMCONF_BASE_ADDRESS, 0, 0, 255); + return current; +} + +unsigned long acpi_madt_irq_overrides(unsigned long current) +{ + int sci = acpi_sci_irq(); + uint16_t flags = MP_IRQ_TRIGGER_LEVEL; + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0); + + flags |= soc_madt_sci_irq_polarity(sci); + + /* SCI */ + current += acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags); + + current += + acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *) current, 0xff, 0x0d, 1); + + return current; +} + +static unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current) +{ + struct device *cpu; + int num_cpus = 0; + + for (cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!cpu->enabled) + continue; + current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, + num_cpus, cpu->path.apic.apic_id); + } + + return current; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + size_t hob_size = 0; + const uint8_t fsp_hob_iio_universal_data_guid[16] = + FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob; + int cur_stack; + + int gsi_bases[] = { 0, 0x18, 0x20, 0x28, 0x30, 0x48, 0x50, 0x58, 0x60 }; + int ioapic_ids[] = { 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0x10, 0x11, 0x12 }; + + /* Local APICs */ + current = xeonsp_acpi_create_madt_lapics(current); + + hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + cur_stack = 0; + for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) { + for (int stack = 0; stack < MAX_IIO_STACK; ++stack) { + const STACK_RES *ri = + &hob->PlatformData.IIO_resource[socket].StackRes[stack]; + // TODO: do we have situation with only bus 0 and one stack? + if (ri->BusBase != ri->BusLimit) { + assert(cur_stack < ARRAY_SIZE(ioapic_ids)); + assert(cur_stack < ARRAY_SIZE(gsi_bases)); + int ioapic_id = ioapic_ids[cur_stack]; + int gsi_base = gsi_bases[cur_stack]; + printk(BIOS_DEBUG, "Adding MADT IOAPIC for socket: %d, stack: %d, ioapic_id: 0x%x, " + "ioapic_base: 0x%x, gsi_base: 0x%x\n", + socket, stack, ioapic_id, ri->IoApicBase, gsi_base); + current += acpi_create_madt_ioapic( + (acpi_madt_ioapic_t *)current, + ioapic_id, ri->IoApicBase, gsi_base); + ++cur_stack; + + if (socket == 0 && stack == 0) { + assert(cur_stack < ARRAY_SIZE(ioapic_ids)); + assert(cur_stack < ARRAY_SIZE(gsi_bases)); + ioapic_id = ioapic_ids[cur_stack]; + gsi_base = gsi_bases[cur_stack]; + printk(BIOS_DEBUG, "Adding MADT IOAPIC for socket: %d, stack: %d, ioapic_id: 0x%x, " + "ioapic_base: 0x%x, gsi_base: 0x%x\n", + socket, stack, ioapic_id, + ri->IoApicBase + 0x1000, gsi_base); + current += acpi_create_madt_ioapic( + (acpi_madt_ioapic_t *)current, + ioapic_id, ri->IoApicBase + 0x1000, gsi_base); + ++cur_stack; + } + } + } + } + + return acpi_madt_irq_overrides(current); +} + +__attribute__ ((weak)) void motherboard_fill_fadt(acpi_fadt_t *fadt) +{ +} + +void generate_t_state_entries(int core, int cores_per_package) +{ +} + +void generate_p_state_entries(int core, int cores_per_package) +{ +} + +void generate_cpu_entries(struct device *device) +{ + int core_id, cpu_id, pcontrol_blk = ACPI_BASE_ADDRESS; + int plen = 6; + int total_threads = dev_count_cpu(); + int threads_per_package = get_threads_per_package(); + int numcpus = total_threads / threads_per_package; + + printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each, totalcores: %d.\n", + numcpus, threads_per_package, total_threads); + + for (cpu_id = 0; cpu_id < numcpus; cpu_id++) { + for (core_id = 0; core_id < threads_per_package; core_id++) { + if (core_id > 0) { + pcontrol_blk = 0; + plen = 0; + } + + /* Generate processor _PR.CPUx */ + acpigen_write_processor((cpu_id) * threads_per_package + + core_id, pcontrol_blk, plen); + + /* NOTE: Intel idle driver doesn't use ACPI C-state tables */ + + /* TODO: Soc specific power states generation */ + acpigen_pop_len(); + } + } + /* PPKG is usually used for thermal management + of the first and only package. */ + acpigen_write_processor_package("PPKG", 0, threads_per_package); + + /* Add a method to notify processor nodes */ + acpigen_write_processor_cnot(threads_per_package); +} + +void soc_fill_fadt(acpi_fadt_t *fadt) +{ + uint16_t pmbase = ACPI_BASE_ADDRESS; + + /* System Management */ + if (!CONFIG(HAVE_SMI_HANDLER)) { + fadt->smi_cmd = 0x00; + fadt->acpi_enable = 0x00; + fadt->acpi_disable = 0x00; + } + + /* Power Control */ + fadt->pm2_cnt_blk = pmbase + PM2_CNT; + fadt->pm_tmr_blk = pmbase + PM1_TMR; + fadt->gpe1_blk = 0; + + /* Control Registers - Length */ + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + /* There are 4 GPE0 STS/EN pairs each 32 bits wide. */ + fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t); + fadt->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 = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_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; + + /* PM1 Status & PM1 Enable */ + fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO; + fadt->x_pm1a_evt_blk.bit_width = 32; + 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; + + motherboard_fill_fadt(fadt); +} + +void acpi_fill_fadt(acpi_fadt_t *fadt) +{ + const uint16_t pmbase = ACPI_BASE_ADDRESS; + + /* Use ACPI 3.0 revision */ + fadt->header.revision = get_acpi_table_revision(FADT); + + fadt->sci_int = acpi_sci_irq(); + /* + TODO: enabled SMM mode switch when SMM handlers are set up. + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + */ + fadt->smi_cmd = 0x00; + fadt->acpi_enable = 0x00; + fadt->acpi_disable = 0x00; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase + PM1_STS; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + PM1_CNT; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + PM2_CNT; + fadt->pm_tmr_blk = pmbase + PM1_TMR; + fadt->gpe0_blk = pmbase + GPE0_STS(0); + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + /* There are 4 GPE0 STS/EN pairs each 32 bits wide. */ + fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t); + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_FREE; + if (!CONFIG(NO_FADT_8042)) + fadt->iapc_boot_arch |= ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.access_size = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + fadt->reset_value = 6; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.access_size = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.access_size = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.access_size = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.access_size = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.access_size = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + PM2_CNT; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.access_size = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.access_size = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.access_size = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + soc_fill_fadt(fadt); +} + +static acpi_tstate_t xeon_sp_tss_table[] = { + { 100, 1000, 0, 0x00, 0 }, + { 88, 875, 0, 0x1e, 0 }, + { 75, 750, 0, 0x1c, 0 }, + { 63, 625, 0, 0x1a, 0 }, + { 50, 500, 0, 0x18, 0 }, + { 38, 375, 0, 0x16, 0 }, + { 25, 250, 0, 0x14, 0 }, + { 13, 125, 0, 0x12, 0 }, +}; + +acpi_tstate_t *soc_get_tss_table(int *entries) +{ + *entries = ARRAY_SIZE(xeon_sp_tss_table); + return xeon_sp_tss_table; +} + +int soc_madt_sci_irq_polarity(int sci) +{ + if (sci >= 20) + return MP_IRQ_POLARITY_LOW; + else + return MP_IRQ_POLARITY_HIGH; +} + +unsigned long southbridge_write_acpi_tables(struct device *device, + unsigned long current, + struct acpi_rsdp *rsdp) +{ + current = acpi_write_hpet(device, current, rsdp); + current = (ALIGN(current, 16)); + printk(BIOS_DEBUG, "current = %lx\n", current); + return current; +} + +unsigned long acpi_create_srat_lapics(unsigned long current) +{ + struct device *cpu; + int cpu_index = 0; + + for (cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!cpu->enabled) + continue; + printk(BIOS_DEBUG, "SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", + cpu_index, cpu->path.apic.node_id, cpu->path.apic.apic_id); + current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, + cpu->path.apic.node_id, cpu->path.apic.apic_id); + cpu_index++; + } + return current; +} + +static unsigned long acpi_fill_srat(unsigned long current) +{ + acpi_srat_mem_t srat_mem[MAX_ACPI_MEMORY_AFFINITY_COUNT]; + unsigned int mem_count; + + /* create all subtables for processors */ + current = acpi_create_srat_lapics(current); + + mem_count = get_srat_memory_entries(srat_mem); + for (int i = 0; i < mem_count; ++i) { + printk(BIOS_DEBUG, "adding srat memory %d entry length: %d, addr: 0x%x%x, " + "length: 0x%x%x, proximity_domain: %d, flags: %x\n", + i, srat_mem[i].length, + srat_mem[i].base_address_high, srat_mem[i].base_address_low, + srat_mem[i].length_high, srat_mem[i].length_low, + srat_mem[i].proximity_domain, srat_mem[i].flags); + memcpy((acpi_srat_mem_t *)current, &srat_mem[i], sizeof(srat_mem[i])); + current += srat_mem[i].length; + } + + return current; +} + +static unsigned long acpi_fill_slit(unsigned long current) +{ + int nodes = get_cpu_count(); + + uint8_t *p = (uint8_t *)current; + memset(p, 0, 8 + nodes * nodes); + *p = (uint8_t)nodes; + p += 8; + + /* this assumes fully connected socket topology */ + for (int i = 0; i < nodes; i++) { + for (int j = 0; j < nodes; j++) { + if (i == j) + p[i*nodes+j] = 10; + else + p[i*nodes+j] = 16; + } + } + + current += 8+nodes*nodes; + return current; +} + +static int get_stack_for_port(int p) +{ + if (p == 0) + return CSTACK; + else if (p >= PORT_1A && p <= PORT_1D) + return PSTACK0; + else if (p >= PORT_2A && p <= PORT_2D) + return PSTACK1; + else if (p >= PORT_3A && p <= PORT_3D) + return PSTACK2; + else if (p >= PORT_4A && p <= PORT_4D) + return PSTACK3; // MCP0 + else + return PSTACK4; // MCP1 +} + +static unsigned long acpi_create_drhd(unsigned long current, int socket, int stack) +{ + int IoApicID[] = { + // socket 0 + PC00_IOAPIC_ID, PC01_IOAPIC_ID, PC02_IOAPIC_ID, PC03_IOAPIC_ID, + PC04_IOAPIC_ID, PC05_IOAPIC_ID, + // socket 1 + PC06_IOAPIC_ID, PC07_IOAPIC_ID, PC08_IOAPIC_ID, PC09_IOAPIC_ID, + PC10_IOAPIC_ID, PC11_IOAPIC_ID, + }; + + uint32_t enum_id; + unsigned long tmp = current; + + size_t hob_size; + const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob = fsp_find_extension_hob_by_guid( + fsp_hob_iio_universal_data_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + uint32_t bus = hob->PlatformData.CpuQpiInfo[socket].StackBus[stack]; + uint32_t pcie_seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + uint32_t reg_base = + hob->PlatformData.IIO_resource[socket].StackRes[stack].VtdBarAddress; + printk(BIOS_SPEW, "%s socket: %d, stack: %d, bus: 0x%x, pcie_seg: 0x%x, reg_base: 0x%x\n", + __func__, socket, stack, bus, pcie_seg, reg_base); + + // Add DRHD Hardware Unit + if (socket == 0 && stack == CSTACK) { + printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, " + "Register Base Address: 0x%x\n", + DRHD_INCLUDE_PCI_ALL, pcie_seg, reg_base); + current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL, + pcie_seg, reg_base); + } else { + printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, " + "Register Base Address: 0x%x\n", 0, pcie_seg, reg_base); + current += acpi_create_dmar_drhd(current, 0, pcie_seg, reg_base); + } + + // Add PCH IOAPIC + if (socket == 0 && stack == CSTACK) { + printk(BIOS_DEBUG, " [IOAPIC Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, " + "PCI Path: 0x%x, 0x%x\n", + PCH_IOAPIC_ID, PCH_IOAPIC_BUS_NUMBER, + PCH_IOAPIC_DEV_NUM, PCH_IOAPIC_FUNC_NUM); + current += acpi_create_dmar_ds_ioapic(current, PCH_IOAPIC_ID, + PCH_IOAPIC_BUS_NUMBER, PCH_IOAPIC_DEV_NUM, PCH_IOAPIC_FUNC_NUM); + } + + // Add IOAPIC entry + enum_id = IoApicID[(socket*MAX_IIO_STACK)+stack]; + printk(BIOS_DEBUG, " [IOAPIC Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, " + "PCI Path: 0x%x, 0x%x\n", enum_id, bus, APIC_DEV_NUM, APIC_FUNC_NUM); + current += acpi_create_dmar_ds_ioapic(current, enum_id, bus, + APIC_DEV_NUM, APIC_FUNC_NUM); + + // Add CBDMA devices for CSTACK + if (socket != 0 && stack == CSTACK) { + for (int cbdma_func_id = 0; cbdma_func_id < 8; ++cbdma_func_id) { + printk(BIOS_DEBUG, " [PCI Endpoint Device] Enumeration ID: 0x%x, " + "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n", + 0, bus, CBDMA_DEV_NUM, cbdma_func_id); + current += acpi_create_dmar_ds_pci(current, + bus, CBDMA_DEV_NUM, cbdma_func_id); + } + } + + // Add PCIe Ports + if (socket != 0 || stack != CSTACK) { + IIO_RESOURCE_INSTANCE iio_resource = + hob->PlatformData.IIO_resource[socket]; + for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) { + if (get_stack_for_port(p) != stack) + continue; + + uint32_t dev = iio_resource.PcieInfo.PortInfo[p].Device; + uint32_t func = iio_resource.PcieInfo.PortInfo[p].Function; + + uint32_t id = pci_mmio_read_config32(PCI_DEV(bus, dev, func), + PCI_VENDOR_ID); + if (id == 0xffffffff) + continue; + + printk(BIOS_DEBUG, " [PCI Bridge Device] Enumeration ID: 0x%x, " + "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n", + 0, bus, dev, func); + current += acpi_create_dmar_ds_pci_br(current, + bus, dev, func); + } + + // Add VMD + if (hob->PlatformData.VMDStackEnable[socket][stack] && + stack >= PSTACK0 && stack <= PSTACK2) { + printk(BIOS_DEBUG, " [PCI Endpoint Device] Enumeration ID: 0x%x, " + "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n", + 0, bus, VMD_DEV_NUM, VMD_FUNC_NUM); + current += acpi_create_dmar_ds_pci(current, + bus, VMD_DEV_NUM, VMD_FUNC_NUM); + } + } + + // Add HPET + if (socket == 0 && stack == CSTACK) { + uint16_t hpet_capid = read16((void *)HPET_BASE_ADDRESS); + uint16_t num_hpets = (hpet_capid >> 0x08) & 0x1F; // Bits [8:12] has hpet count + printk(BIOS_SPEW, "%s hpet_capid: 0x%x, num_hpets: 0x%x\n", + __func__, hpet_capid, num_hpets); + //BIT 15 + if (num_hpets && (num_hpets != 0x1f) && + (read32((void *)(HPET_BASE_ADDRESS + 0x100)) & (0x00008000))) { + printk(BIOS_DEBUG, " [Message-capable HPET Device] Enumeration ID: 0x%x, " + "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n", + 0, HPET_BUS_NUM, HPET_DEV_NUM, HPET0_FUNC_NUM); + current += acpi_create_dmar_ds_msi_hpet(current, 0, HPET_BUS_NUM, + HPET_DEV_NUM, HPET0_FUNC_NUM); + } + } + + acpi_dmar_drhd_fixup(tmp, current); + + return current; +} + +static unsigned long acpi_create_atsr(unsigned long current) +{ + size_t hob_size; + const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) { + uint32_t pcie_seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + unsigned long tmp = current; + bool first = true; + IIO_RESOURCE_INSTANCE iio_resource = + hob->PlatformData.IIO_resource[socket]; + + for (int stack = 0; stack <= PSTACK2; ++stack) { + uint32_t bus = hob->PlatformData.CpuQpiInfo[socket].StackBus[stack]; + uint32_t vtd_base = iio_resource.StackRes[stack].VtdBarAddress; + if (!vtd_base) + continue; + uint64_t vtd_mmio_cap = read64((void *)(vtd_base + VTD_EXT_CAP_LOW)); + printk(BIOS_SPEW, "%s socket: %d, stack: %d, bus: 0x%x, vtd_base: 0x%x, " + "vtd_mmio_cap: 0x%llx\n", + __func__, socket, stack, bus, vtd_base, vtd_mmio_cap); + + // ATSR is applicable only for platform supporting device IOTLBs + // through the VT-d extended capability register + assert(vtd_mmio_cap != 0xffffffffffffffff); + if ((vtd_mmio_cap & 0x4) == 0) // BIT 2 + continue; + + for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) { + if (socket == 0 && p == 0) + continue; + if (get_stack_for_port(p) != stack) + continue; + + uint32_t dev = iio_resource.PcieInfo.PortInfo[p].Device; + uint32_t func = iio_resource.PcieInfo.PortInfo[p].Function; + + u32 id = pci_mmio_read_config32(PCI_DEV(bus, dev, func), + PCI_VENDOR_ID); + if (id == 0xffffffff) + continue; + + if (first) { + printk(BIOS_DEBUG, "[Root Port ATS Capability] Flags: 0x%x, " + "PCI Segment Number: 0x%x\n", + 0, pcie_seg); + current += acpi_create_dmar_atsr(current, 0, pcie_seg); + first = 0; + } + + printk(BIOS_DEBUG, " [PCI Bridge Device] Enumeration ID: 0x%x, " + "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n", + 0, bus, dev, func); + current += acpi_create_dmar_ds_pci_br(current, bus, dev, func); + } + } + if (tmp != current) + acpi_dmar_atsr_fixup(tmp, current); + } + + return current; +} + +static unsigned long acpi_create_rmrr(unsigned long current) +{ + uint32_t size = ALIGN_UP(MEM_BLK_COUNT * sizeof(MEM_BLK), 0x1000); + + uint32_t *ptr; + + // reserve memory + ptr = cbmem_find(CBMEM_ID_STORAGE_DATA); + if (!ptr) { + ptr = cbmem_add(CBMEM_ID_STORAGE_DATA, size); + assert(ptr != NULL); + memset(ptr, 0, size); + } + + unsigned long tmp = current; + printk(BIOS_DEBUG, "[Reserved Memory Region] PCI Segment Number: 0x%x, Base Address: 0x%x, " + "End Address (limit): 0x%x\n", + 0, (uint32_t) ptr, (uint32_t) ((uint32_t) ptr + size - 1)); + current += acpi_create_dmar_rmrr(current, 0, (uint32_t) ptr, + (uint32_t) ((uint32_t) ptr + size - 1)); + + printk(BIOS_DEBUG, " [PCI Endpoint Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, " + "PCI Path: 0x%x, 0x%x\n", + 0, XHCI_BUS_NUMBER, PCH_DEV_SLOT_XHCI, XHCI_FUNC_NUM); + current += acpi_create_dmar_ds_pci(current, XHCI_BUS_NUMBER, + PCH_DEV_SLOT_XHCI, XHCI_FUNC_NUM); + + acpi_dmar_rmrr_fixup(tmp, current); + + return current; +} + +static unsigned long acpi_create_rhsa(unsigned long current) +{ + size_t hob_size; + const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) { + IIO_RESOURCE_INSTANCE iio_resource = + hob->PlatformData.IIO_resource[socket]; + for (int stack = 0; stack <= PSTACK2; ++stack) { + uint32_t vtd_base = iio_resource.StackRes[stack].VtdBarAddress; + if (!vtd_base) + continue; + + printk(BIOS_DEBUG, "[Remapping Hardware Static Affinity] Base Address: 0x%x, " + "Proximity Domain: 0x%x\n", vtd_base, socket); + current += acpi_create_dmar_rhsa(current, vtd_base, socket); + } + } + + return current; +} + +static unsigned long acpi_fill_dmar(unsigned long current) +{ + size_t hob_size; + const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + // DRHD + for (int iio = 1; iio <= hob->PlatformData.numofIIO; ++iio) { + int socket = iio; + if (socket == hob->PlatformData.numofIIO) // socket 0 should be last DRHD entry + socket = 0; + + if (socket == 0) { + for (int stack = 1; stack <= PSTACK2; ++stack) + current = acpi_create_drhd(current, socket, stack); + current = acpi_create_drhd(current, socket, CSTACK); + } else { + for (int stack = 0; stack <= PSTACK2; ++stack) + current = acpi_create_drhd(current, socket, stack); + } + } + + // RMRR + current = acpi_create_rmrr(current); + + // ATSR - causes hang + current = acpi_create_atsr(current); + + // RHSA + current = acpi_create_rhsa(current); + + return current; +} + +unsigned long northbridge_write_acpi_tables(struct device *device, + unsigned long current, + struct acpi_rsdp *rsdp) +{ + acpi_srat_t *srat; + acpi_slit_t *slit; + acpi_dmar_t *dmar; + + const struct soc_intel_xeon_sp_config *const config = config_of(device); + + /* SRAT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current); + srat = (acpi_srat_t *) current; + acpi_create_srat(srat, acpi_fill_srat); + current += srat->header.length; + acpi_add_table(rsdp, srat); + + /* SLIT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current); + slit = (acpi_slit_t *) current; + acpi_create_slit(slit, acpi_fill_slit); + current += slit->header.length; + acpi_add_table(rsdp, slit); + + /* DMAR */ + if (config->vtd_support) { + current = ALIGN(current, 8); + dmar = (acpi_dmar_t *)current; + printk(BIOS_DEBUG, "ACPI: * DMAR\n"); + printk(BIOS_DEBUG, "[DMA Remapping table] Flags: 0x%x\n", + (DMAR_INTR_REMAP | DMAR_X2APIC_OPT_OUT)); + acpi_create_dmar(dmar, (DMAR_INTR_REMAP | DMAR_X2APIC_OPT_OUT), acpi_fill_dmar); + current += dmar->header.length; + current = acpi_align_current(current); + acpi_add_table(rsdp, dmar); + } + + return current; +} + +void uncore_inject_dsdt(void) +{ + size_t hob_size; + const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + acpigen_write_scope("\_SB"); + for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) { + IIO_RESOURCE_INSTANCE iio_resource = + hob->PlatformData.IIO_resource[socket]; + for (int stack = 0; stack <= PSTACK2; ++stack) { + const STACK_RES *ri = &iio_resource.StackRes[stack]; + char rtname[16]; + snprintf(rtname, sizeof(rtname), "RT%02x", + (socket*MAX_IIO_STACK)+stack); + + acpigen_write_name(rtname); + printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", + rtname, socket, stack); + + acpigen_write_resourcetemplate_header(); + + /* bus resource */ + acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusLimit, + 0x0, (ri->BusLimit - ri->BusBase + 1)); + + // additional io resources on socket 0 bus 0 + if (socket == 0 && stack == 0) { + /* ACPI 6.4.2.5 I/O Port Descriptor */ + acpigen_write_io16(0xCF8, 0xCFF, 0x1, 0x8, 1); + + /* IO decode CF8-CFF */ + acpigen_resource_word(1, 0xc, 0x3, 0, 0x0000, 0x03AF, + 0, 0x03B0); + acpigen_resource_word(1, 0xc, 0x3, 0, 0x03E0, 0x0CF7, + 0, 0x0918); + acpigen_resource_word(1, 0xc, 0x3, 0, 0x03B0, 0x03BB, + 0, 0x000C); + acpigen_resource_word(1, 0xc, 0x3, 0, 0x03C0, 0x03DF, + 0, 0x0020); + } + + /* IO resource */ + acpigen_resource_word(1, 0xc, 0x3, 0, ri->PciResourceIoBase, + ri->PciResourceIoLimit, 0x0, + (ri->PciResourceIoLimit - ri->PciResourceIoBase + 1)); + + // additional mem32 resources on socket 0 bus 0 + if (socket == 0 && stack == 0) { + acpigen_resource_dword(0, 0xc, 3, 0, VGA_BASE_ADDRESS, + (VGA_BASE_ADDRESS + VGA_BASE_SIZE - 1), 0x0, + VGA_BASE_SIZE); + acpigen_resource_dword(0, 0xc, 1, 0, SPI_BASE_ADDRESS, + (SPI_BASE_ADDRESS + SPI_BASE_SIZE - 1), 0x0, + SPI_BASE_SIZE); + } + + /* Mem32 resource */ + acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base, + ri->PciResourceMem32Limit, 0x0, + (ri->PciResourceMem32Limit - ri->PciResourceMem32Base + 1)); + + /* Mem64 resource */ + acpigen_resource_qword(0, 0xc, 1, 0, ri->PciResourceMem64Base, + ri->PciResourceMem64Limit, 0x0, + (ri->PciResourceMem64Limit - ri->PciResourceMem64Base + 1)); + + acpigen_write_resourcetemplate_footer(); + } + } + acpigen_pop_len(); +} + +void southbridge_inject_dsdt(struct device *device) +{ + global_nvs_t *gnvs; + + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs)); + if (gnvs) + memset(gnvs, 0, sizeof(*gnvs)); + } + + if (gnvs) { + acpi_create_gnvs(gnvs); + /* TODO: tell SMI about it, if HAVE_SMI_HANDLER */ + // smm_setup_structures(gnvs, NULL, NULL); + + /* Add it to DSDT. */ + printk(BIOS_SPEW, "%s injecting NVSA with 0x%x\n", __FILE__, (uint32_t)gnvs); + acpigen_write_scope("\"); + acpigen_write_name_dword("NVSA", (uint32_t)gnvs); + acpigen_pop_len(); + } + + // Add IIOStack ACPI Resource Templates + uncore_inject_dsdt(); +} diff --git a/src/soc/intel/xeon_sp/acpi/globalnvs.asl b/src/soc/intel/xeon_sp/acpi/globalnvs.asl new file mode 100644 index 0000000..c2d5853 --- /dev/null +++ b/src/soc/intel/xeon_sp/acpi/globalnvs.asl @@ -0,0 +1,82 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2014 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/* Global Variables */ + +Name(\PICM, 0) // IOAPIC/8259 + +/* + * Global ACPI memory region. This region is used for passing information + * between coreboot (aka "the system bios"), ACPI, and the SMI handler. + * Since we don't know where this will end up in memory at ACPI compile time, + * we have to fix it up in coreboot's ACPI creation phase. + */ + + +External(NVSA) +OperationRegion (GNVS, SystemMemory, NVSA, 0x2000) +Field (GNVS, ByteAcc, NoLock, Preserve) +{ + /* Miscellaneous */ + OSYS, 16, // 0x00 - Operating System + SMIF, 8, // 0x02 - SMI function + PRM0, 8, // 0x03 - SMI function parameter + PRM1, 8, // 0x04 - SMI function parameter + SCIF, 8, // 0x05 - SCI function + PRM2, 8, // 0x06 - SCI function parameter + PRM3, 8, // 0x07 - SCI function parameter + LCKF, 8, // 0x08 - Global Lock function for EC + PRM4, 8, // 0x09 - Lock function parameter + PRM5, 8, // 0x0a - Lock function parameter + P80D, 32, // 0x0b - Debug port (IO 0x80) value + LIDS, 8, // 0x0f - LID state (open = 1) + PWRS, 8, // 0x10 - Power State (AC = 1) + PCNT, 8, // 0x11 - Processor count + TPMP, 8, // 0x12 - TPM Present and Enabled + TLVL, 8, // 0x13 - Throttle Level + PPCM, 8, // 0x14 - Maximum P-state usable by OS + PM1I, 64, // 0x15 - PM1 wake status bit + GPEI, 64, // 0x1D - GPE wake status bit + U2WE, 16, // 0x25 - USB2 Wake Enable Bitmap + U3WE, 8, // 0x27 - USB3 Wake Enable Bitmap + + + /* Device Config */ + Offset (0x30), + S5U0, 8, // 0x30 - Enable USB0 in S5 + S5U1, 8, // 0x31 - Enable USB1 in S5 + S3U0, 8, // 0x32 - Enable USB0 in S3 + S3U1, 8, // 0x33 - Enable USB1 in S3 + TACT, 8, // 0x34 - Thermal Active trip point + TPSV, 8, // 0x35 - Thermal Passive trip point + TCRT, 8, // 0x36 - Thermal Critical trip point + DPTE, 8, // 0x37 - Enable DPTF + + /* Base addresses */ + Offset (0x50), + CMEM, 32, // 0x50 - CBMEM TOC + TOLM, 32, // 0x54 - Top of Low Memory + CBMC, 32, // 0x58 - coreboot mem console pointer + MMOB, 32, // 0x5C - MMIO Base Low Base + MMOL, 32, // 0x60 - MMIO Base Low Limit + MMHB, 64, // 0x64 - MMIO Base High Base + MMHL, 64, // 0x6C - MMIO Base High Limit + TSGB, 32, // 0x74 - TSEG Base + TSSZ, 32, // 0x78 - TSEG Size +} diff --git a/src/soc/intel/xeon_sp/acpi/iiostack.asl b/src/soc/intel/xeon_sp/acpi/iiostack.asl new file mode 100644 index 0000000..2d1187f --- /dev/null +++ b/src/soc/intel/xeon_sp/acpi/iiostack.asl @@ -0,0 +1,92 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define MAKE_IIO_DEV(id,rt) \ + Device (PC##id) \ + { \ + Name (_HID, EisaId ("PNP0A08") /* PCI Express Bus */) \ + Name (_CID, EisaId ("PNP0A03") /* PCI Bus */) \ + Name (_UID, 0x##id) \ + Method (_PRT, 0, NotSerialized) \ + { \ + If (PICM) \ + { \ + Return (_SB_.AR##rt) \ + } \ + Return (_SB_.PR##rt) \ + } \ + External(_SB.RT##id) \ + Method (_CRS, 0, NotSerialized) \ + { \ + Return (_SB.RT##id) \ + } \ + Name (SUPP, 0x00) \ + Name (CTRL, 0x00) \ + Name (_PXM, 0x00) /* _PXM: Device Proximity */ \ + Method (_OSC, 4, NotSerialized) \ + { \ + CreateDWordField (Arg3, 0x00, CDW1) \ + If ((Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */)) \ + { \ + CreateDWordField (Arg3, 0x04, CDW2) \ + If ((Arg2 > 0x02)) \ + { \ + CreateDWordField (Arg3, 0x08, CDW3) \ + } \ + SUPP = CDW2 \ + CTRL = CDW3 \ + If ((AHPE || ((SUPP & 0x16) != 0x16))) \ + { \ + CTRL &= 0x1E \ + Sleep (0x03E8) \ + } \ + /* Never allow SHPC (no SHPC controller in system) */ \ + CTRL &= 0x1D \ + /* Disable Native PCIe AER handling from OS */ \ + CTRL &= 0x17 \ + If ((Arg1 != One)) /* unknown revision */ \ + { \ + CDW1 |= 0x08 \ + } \ + If ((CDW3 != CTRL)) /* capabilities bits were masked */ \ + { \ + CDW1 |= 0x10 \ + } \ + CDW3 = CTRL \ + Return (Arg3) \ + } \ + Else \ + { \ + /* indicate unrecognized UUID */ \ + CDW1 |= 0x04 \ + IO80 = 0xEE \ + Return (Arg3) \ + } \ + } \ + } + +MAKE_IIO_DEV(00, 00) +MAKE_IIO_DEV(01, 10) +MAKE_IIO_DEV(02, 20) +MAKE_IIO_DEV(03, 28) + +#if MAX_SOCKET > 1 +MAKE_IIO_DEV(06, 40) +MAKE_IIO_DEV(07, 50) +MAKE_IIO_DEV(08, 60) +MAKE_IIO_DEV(09, 68) +#endif diff --git a/src/soc/intel/xeon_sp/acpi/pci_irq.asl b/src/soc/intel/xeon_sp/acpi/pci_irq.asl new file mode 100644 index 0000000..cfa4ad5 --- /dev/null +++ b/src/soc/intel/xeon_sp/acpi/pci_irq.asl @@ -0,0 +1,113 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook 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. + */ + +/* + * Refer to Intel® C620 Series Chipset Platform Controller Hub EDS section 20.11 + * CONFIG_PCR_BASE_ADDRESS 0xfd000000 0x3100 + * (0xfd000000 | ((uint8_t)(0xC4) << 16) | (uint16_t)(0x3100) = 0xFDC43100 + * + * PIRQ routing control is in PCR ITSS region. + */ + +OperationRegion (ITSS, SystemMemory, + Add (PCR_ITSS_PIRQA_ROUT, + Add (CONFIG_PCR_BASE_ADDRESS, + ShiftLeft (PID_ITSS, PCR_PORTID_SHIFT))), 8) +Field (ITSS, ByteAcc, NoLock, Preserve) +{ + PIRA, 8, /* PIRQA Routing Control */ + PIRB, 8, /* PIRQB Routing Control */ + PIRC, 8, /* PIRQC Routing Control */ + PIRD, 8, /* PIRQD Routing Control */ + PIRE, 8, /* PIRQE Routing Control */ + PIRF, 8, /* PIRQF Routing Control */ + PIRG, 8, /* PIRQG Routing Control */ + PIRH, 8, /* PIRQH Routing Control */ +} + +Name (IREN, 0x80) /* Interrupt Routing Enable */ +Name (IREM, 0x0f) /* Interrupt Routing Mask */ + +Name (PRSA, ResourceTemplate () +{ + IRQ (Level, ActiveLow, Shared, ) + {3,4,5,6,7,10,11,12,14,15} +}) +Alias (PRSA, PRSB) +Name (PRSC, ResourceTemplate () +{ + IRQ (Level, ActiveLow, Shared, ) + {3,4,5,6,10,11,12,14,15} +}) +Alias (PRSC, PRSD) +Alias (PRSA, PRSE) +Alias (PRSA, PRSF) +Alias (PRSA, PRSG) +Alias (PRSA, PRSH) + +#define MAKE_LINK_DEV(id,uid) \ + Device (LNK##id) \ + { \ + Name (_HID, EISAID ("PNP0C0F")) \ + Name (_UID, ##uid) \ + Method (_PRS, 0, NotSerialized) \ + { \ + Return (PRS##id) \ + } \ + Method (_CRS, 0, Serialized) \ + { \ + Name (RTLA, ResourceTemplate () \ + { \ + IRQ (Level, ActiveLow, Shared) {} \ + }) \ + CreateWordField (RTLA, 1, IRQ0) \ + Store (Zero, IRQ0) \ + \ + /* Set the bit from PIRQ Routing Register */ \ + ShiftLeft (1, And (^^PIR##id, ^^IREM), IRQ0) \ + Return (RTLA) \ + } \ + Method (_SRS, 1, Serialized) \ + { \ + CreateWordField (Arg0, 1, IRQ0) \ + FindSetRightBit (IRQ0, Local0) \ + Decrement (Local0) \ + Store (Local0, ^^PIR##id) \ + } \ + Method (_STA, 0, Serialized) \ + { \ + If (And (^^PIR##id, ^^IREN)) { \ + Return (0x9) \ + } Else { \ + Return (0xb) \ + } \ + } \ + Method (_DIS, 0, Serialized) \ + { \ + Or (^^PIR##id, ^^IREN, ^^PIR##id) \ + } \ + } + +MAKE_LINK_DEV(A,1) +MAKE_LINK_DEV(B,2) +MAKE_LINK_DEV(C,3) +MAKE_LINK_DEV(D,4) +MAKE_LINK_DEV(E,5) +MAKE_LINK_DEV(F,6) +MAKE_LINK_DEV(G,7) +MAKE_LINK_DEV(H,8) diff --git a/src/soc/intel/xeon_sp/acpi/uncore.asl b/src/soc/intel/xeon_sp/acpi/uncore.asl new file mode 100644 index 0000000..35fbf98 --- /dev/null +++ b/src/soc/intel/xeon_sp/acpi/uncore.asl @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include <intelblocks/itss.h> +#include <intelblocks/pcr.h> +#include <soc/iomap.h> +#include <soc/irq.h> +#include <soc/pcr_ids.h> + +Scope() +{ + // Private Chipset Register(PCR). Memory Mapped through ILB + OperationRegion(PCRR, SystemMemory, P2SB_BAR, 0x01000000) + Field(PCRR, DWordAcc, Lock, Preserve) + { + Offset (0xD03100), // Interrupt Routing Registers + PRTA, 8, + PRTB, 8, + PRTC, 8, + PRTD, 8, + PRTE, 8, + PRTF, 8, + PRTG, 8, + PRTH, 8, + } +} + +Scope (_SB) +{ + #include "pci_irq.asl" + #include "uncore_irq.asl" + #include "iiostack.asl" +} diff --git a/src/soc/intel/xeon_sp/acpi/uncore_irq.asl b/src/soc/intel/xeon_sp/acpi/uncore_irq.asl new file mode 100644 index 0000000..8492725 --- /dev/null +++ b/src/soc/intel/xeon_sp/acpi/uncore_irq.asl @@ -0,0 +1,566 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Uncore devices PCI interrupt routing packages. + * See ACPI spec 6.2.13 _PRT (PCI routing table) for details. + * The mapping fields ae Address, Pin, Source, Source Index. + */ + +#define GEN_PCIE_LEGACY_IRQ() \ + Package (0x04) { 0x0000FFFF, 0x00, LNKA, 0x00 }, \ + Package (0x04) { 0x0001FFFF, 0x00, LNKA, 0x00 }, \ + Package (0x04) { 0x0002FFFF, 0x00, LNKA, 0x00 }, \ + Package (0x04) { 0x0003FFFF, 0x00, LNKA, 0x00 } + +#define GEN_UNCORE_LEGACY_IRQ(dev) \ + Package (0x04) { ##dev, 0x00, LNKA, 0x00 }, \ + Package (0x04) { ##dev, 0x01, LNKB, 0x00 }, \ + Package (0x04) { ##dev, 0x02, LNKC, 0x00 }, \ + Package (0x04) { ##dev, 0x03, LNKD, 0x00 } + +#define GEN_PCIE_IOAPIC_IRQ(irq) \ + Package (0x04) { 0x0000FFFF, 0x00, 0x00, ##irq }, \ + Package (0x04) { 0x0001FFFF, 0x00, 0x00, ##irq }, \ + Package (0x04) { 0x0002FFFF, 0x00, 0x00, ##irq }, \ + Package (0x04) { 0x0003FFFF, 0x00, 0x00, ##irq } + +#define GEN_UNCORE_IOAPIC_IRQ(dev,irq1,irq2,irq3,irq4) \ + Package (0x04) { ##dev, 0x00, 0x00, ##irq1 }, \ + Package (0x04) { ##dev, 0x01, 0x00, ##irq2 }, \ + Package (0x04) { ##dev, 0x02, 0x00, ##irq3 }, \ + Package (0x04) { ##dev, 0x03, 0x00, ##irq4 } + +// Socket 0, IIOStack 0 device legacy interrupt routing +Name (PR00, Package (0x28) +{ + // [DMI0]: Legacy PCI Express Port 0 + Package (0x04) { 0x0000FFFF, 0x00, LNKA, 0x00 }, + // [CB0A]: CBDMA + // [CB0E]: CBDMA + Package (0x04) { 0x0004FFFF, 0x00, LNKA, 0x00 }, + // [CB0B]: CBDMA + // [CB0F]: CBDMA + Package (0x04) { 0x0004FFFF, 0x01, LNKB, 0x00 }, + // [CB0C]: CBDMA + // [CB0G]: CBDMA + Package (0x04) { 0x0004FFFF, 0x02, LNKC, 0x00 }, + // [CB0D]: CBDMA + // [CB0H]: CBDMA + Package (0x04) { 0x0004FFFF, 0x03, LNKD, 0x00 }, + // Uncore 0 UBOX Device + Package (0x04) { 0x0008FFFF, 0x00, LNKA, 0x00 }, + Package (0x04) { 0x0008FFFF, 0x01, LNKB, 0x00 }, + Package (0x04) { 0x0008FFFF, 0x02, LNKC, 0x00 }, + Package (0x04) { 0x0008FFFF, 0x03, LNKD, 0x00 }, + // [DISP]: Display Controller + Package (0x04) { 0x000FFFFF, 0x00, LNKA, 0x00 }, + // [IHC1]: HECI #1 + // [IHC3]: HECI #3 + Package (0x04) { 0x0010FFFF, 0x00, LNKA, 0x00 }, + // [IHC2]: HECI #2 + Package (0x04) { 0x0010FFFF, 0x01, LNKB, 0x00 }, + // [IIDR]: IDE-Redirection (IDE-R) + Package (0x04) { 0x0010FFFF, 0x02, LNKC, 0x00 }, + // [IMKT]: Keyboard and Text (KT) Redirection + Package (0x04) { 0x0010FFFF, 0x03, LNKD, 0x00 }, + // [SAT2]: sSATA Host controller 2 on PCH + Package (0x04) { 0x0011FFFF, 0x00, LNKA, 0x00 }, + // // [XHCI]: xHCI controller 1 on PCH + Package (0x04) { 0x0014FFFF, 0x00, LNKA, 0x00 }, + // [OTG0]: USB Device Controller (OTG) on PCH + Package (0x04) { 0x0014FFFF, 0x01, LNKB, 0x00 }, + // [TERM]: Thermal Subsystem on PCH + Package (0x04) { 0x0014FFFF, 0x02, LNKC, 0x00 }, + // [CAMR]: Camera IO Host Controller on PCH + Package (0x04) { 0x0014FFFF, 0x03, LNKD, 0x00 }, + // [HEC1]: HECI #1 on PCH + // [HEC3]: HECI #3 on PCH + Package (0x04) { 0x0016FFFF, 0x00, LNKA, 0x00 }, + // [HEC2]: HECI #2 on PCH + Package (0x04) { 0x0016FFFF, 0x01, LNKB, 0x00 }, + // [IDER]: ME IDE redirect on PCH + Package (0x04) { 0x0016FFFF, 0x02, LNKC, 0x00 }, + // [MEKT]: MEKT on PCH + Package (0x04) { 0x0016FFFF, 0x03, LNKD, 0x00 }, + // [SAT1]: SATA controller 1 on PCH + Package (0x04) { 0x0017FFFF, 0x00, LNKA, 0x00 }, + // [NAN1]: NAND Cycle Router on PCH + Package (0x04) { 0x0018FFFF, 0x00, LNKA, 0x00 }, + // [RP17]: PCIE PCH Root Port #17 + Package (0x04) { 0x001BFFFF, 0x00, LNKA, 0x00 }, + // [RP18]: PCIE PCH Root Port #18 + Package (0x04) { 0x001BFFFF, 0x01, LNKB, 0x00 }, + // [RP19]: PCIE PCH Root Port #19 + Package (0x04) { 0x001BFFFF, 0x02, LNKC, 0x00 }, + // [RP20]: PCIE PCH Root Port #20 + Package (0x04) { 0x001BFFFF, 0x03, LNKD, 0x00 }, + // [RP01]: PCIE PCH Root Port #1 + // [RP05]: PCIE PCH Root Port #5 + Package (0x04) { 0x001CFFFF, 0x00, LNKA, 0x00 }, + // [RP02]: PCIE PCH Root Port #2 + // [RP06]: PCIE PCH Root Port #6 + Package (0x04) { 0x001CFFFF, 0x01, LNKB, 0x00 }, + // [RP03]: PCIE PCH Root Port #3 + // [RP07]: PCIE PCH Root Port #7 + Package (0x04) { 0x001CFFFF, 0x02, LNKC, 0x00 }, + // [RP04]: PCIE PCH Root Port #4 + // [RP08]: PCIE PCH Root Port #8 + Package (0x04) { 0x001CFFFF, 0x03, LNKD, 0x00 }, + // [RP09]: PCIE PCH Root Port #9 + // [RP13]: PCIE PCH Root Port #13 + Package (0x04) { 0x001DFFFF, 0x00, LNKA, 0x00 }, + // [RP10]: PCIE PCH Root Port #10 + // [RP14]: PCIE PCH Root Port #14 + Package (0x04) { 0x001DFFFF, 0x01, LNKB, 0x00 }, + // [RP11]: PCIE PCH Root Port #11 + // [RP15]: PCIE PCH Root Port #15 + Package (0x04) { 0x001DFFFF, 0x02, LNKC, 0x00 }, + // [RP12]: PCIE PCH Root Port #12 + // [RP16]: PCIE PCH Root Port #16 + Package (0x04) { 0x001DFFFF, 0x03, LNKD, 0x00 }, + // [UAR0]: UART #0 on PCH + Package (0x04) { 0x001EFFFF, 0x02, LNKC, 0x00 }, + // [UAR1]: UART #1 on PCH + Package (0x04) { 0x001EFFFF, 0x03, LNKD, 0x00 }, + // [CAVS]: HD Audio Subsystem Controller on PCH + // [SMBS]: SMBus controller on PCH + // [GBE1]: GbE Controller on PCH + // [NTPK]: Northpeak Controller on PCH + Package (0x04) { 0x001FFFFF, 0x00, LNKA, 0x00 }, +}) + +// Socket 0, IIOStack 0 device IOAPIC interrupt routing +Name (AR00, Package (0x28) +{ + // [DMI0]: Legacy PCI Express Port 0 + Package (0x04) { 0x0000FFFF, 0x00, 0x00, 0x1F }, + // [CB0A]: CB3DMA + // [CB0E]: CB3DMA + Package (0x04) { 0x0004FFFF, 0x00, 0x00, 0x1A }, + // [CB0B]: CB3DMA + // [CB0F]: CB3DMA + Package (0x04) { 0x0004FFFF, 0x01, 0x00, 0x1B }, + // [CB0C]: CB3DMA + // [CB0G]: CB3DMA + Package (0x04) { 0x0004FFFF, 0x02, 0x00, 0x1A }, + // [CB0D]: CB3DMA + // [CB0H]: CB3DMA + Package (0x04) { 0x0004FFFF, 0x03, 0x00, 0x1B }, + // [UBX0]: Uncore 0 UBOX Device + Package (0x04) { 0x0008FFFF, 0x00, 0x00, 0x18 }, + Package (0x04) { 0x0008FFFF, 0x01, 0x00, 0x1C }, + Package (0x04) { 0x0008FFFF, 0x02, 0x00, 0x1D }, + Package (0x04) { 0x0008FFFF, 0x03, 0x00, 0x1E }, + // [DISP]: Display Controller + Package (0x04) { 0x000FFFFF, 0x00, 0x00, 0x10 }, + // [IHC1]: HECI #1 + // [IHC3]: HECI #3 + Package (0x04) { 0x0010FFFF, 0x00, 0x00, 0x10 }, + // [IHC2]: HECI #2 + Package (0x04) { 0x0010FFFF, 0x01, 0x00, 0x11 }, + // [IIDR]: IDE-Redirection (IDE-R) + Package (0x04) { 0x0010FFFF, 0x02, 0x00, 0x12 }, + // [IMKT]: Keyboard and Text (KT) Redirection + Package (0x04) { 0x0010FFFF, 0x03, 0x00, 0x13 }, + // [SAT2]: sSATA Host controller 2 on PCH + Package (0x04) { 0x0011FFFF, 0x00, 0x00, 0x10 }, + // [XHCI]: xHCI controller 1 on PCH + Package (0x04) { 0x0014FFFF, 0x00, 0x00, 0x10 }, + // [OTG0]: USB Device Controller (OTG) on PCH + Package (0x04) { 0x0014FFFF, 0x01, 0x00, 0x11 }, + // [TERM]: Thermal Subsystem on PCH + Package (0x04) { 0x0014FFFF, 0x02, 0x00, 0x12 }, + // [CAMR]: Camera IO Host Controller on PCH + Package (0x04) { 0x0014FFFF, 0x03, 0x00, 0x13 }, + // [HEC1]: HECI #1 on PCH + // [HEC3]: HECI #3 on PCH + Package (0x04) { 0x0016FFFF, 0x00, 0x00, 0x10 }, + // [HEC2]: HECI #2 on PCH + Package (0x04) { 0x0016FFFF, 0x01, 0x00, 0x11 }, + // [IDER]: ME IDE redirect on PCH + Package (0x04) { 0x0016FFFF, 0x02, 0x00, 0x12 }, + // [MEKT]: MEKT on PCH + Package (0x04) { 0x0016FFFF, 0x03, 0x00, 0x13 }, + // [SAT1]: SATA controller 1 on PCH + Package (0x04) { 0x0017FFFF, 0x00, 0x00, 0x10 }, + // [NAN1]: NAND Cycle Router on PCH + Package (0x04) { 0x0018FFFF, 0x00, 0x00, 0x10 }, + // [RP17]: PCIE PCH Root Port #17 + Package (0x04) { 0x001BFFFF, 0x00, 0x00, 0x10 }, + // [RP18]: PCIE PCH Root Port #18 + Package (0x04) { 0x001BFFFF, 0x01, 0x00, 0x11 }, + // [RP19]: PCIE PCH Root Port #19 + Package (0x04) { 0x001BFFFF, 0x02, 0x00, 0x12 }, + // [RP20]: PCIE PCH Root Port #20 + Package (0x04) { 0x001BFFFF, 0x03, 0x00, 0x13 }, + // [RP01]: PCIE PCH Root Port #1 + // [RP05]: PCIE PCH Root Port #5 + Package (0x04) { 0x001CFFFF, 0x00, 0x00, 0x10 }, + // [RP02]: PCIE PCH Root Port #2 + // [RP06]: PCIE PCH Root Port #6 + Package (0x04) { 0x001CFFFF, 0x01, 0x00, 0x11 }, + // [RP03]: PCIE PCH Root Port #3 + // [RP07]: PCIE PCH Root Port #7 + Package (0x04) { 0x001CFFFF, 0x02, 0x00, 0x12 }, + // [RP04]: PCIE PCH Root Port #4 + // [RP08]: PCIE PCH Root Port #8 + Package (0x04) { 0x001CFFFF, 0x03, 0x00, 0x13 }, + // [RP09]: PCIE PCH Root Port #9 + // [RP13]: PCIE PCH Root Port #13 + Package (0x04) { 0x001DFFFF, 0x00, 0x00, 0x10 }, + // [RP10]: PCIE PCH Root Port #10 + // [RP14]: PCIE PCH Root Port #14 + Package (0x04) { 0x001DFFFF, 0x01, 0x00, 0x11 }, + // [RP11]: PCIE PCH Root Port #11 + // [RP15]: PCIE PCH Root Port #15 + Package (0x04) { 0x001DFFFF, 0x02, 0x00, 0x12 }, + // [RP12]: PCIE PCH Root Port #12 + // [RP16]: PCIE PCH Root Port #16 + Package (0x04) { 0x001DFFFF, 0x03, 0x00, 0x13 }, + // [UAR0]: UART #0 on PCH + Package (0x04) { 0x001EFFFF, 0x02, 0x00, 0x16 }, + // [UAR1]: UART #1 on PCH + Package (0x04) { 0x001EFFFF, 0x03, 0x00, 0x17 }, + // [CAVS]: HD Audio Subsystem Controller on PCH + // [SMBS]: SMBus controller on PCH + // [GBE1]: GbE Controller on PCH + // [NTPK]: Northpeak Controller on PCH + Package (0x04) { 0x001FFFFF, 0x00, 0x00, 0x10 }, +}) + +// Socket 0, IIOStack 1 device legacy interrupt routing +Name (PR10, Package (0x40) +{ + // PCI Express Port 1A-1D + GEN_PCIE_LEGACY_IRQ(), + + // Uncore CHAUTIL Devices + GEN_UNCORE_LEGACY_IRQ(0x0008FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0009FFFF), + GEN_UNCORE_LEGACY_IRQ(0x000AFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000BFFFF), + + // Uncore CHASAD Devices + GEN_UNCORE_LEGACY_IRQ(0x000EFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000FFFFF), + GEN_UNCORE_LEGACY_IRQ(0x0010FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0011FFFF), + + // Uncore CMSCHA Devices + GEN_UNCORE_LEGACY_IRQ(0x0014FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0015FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0016FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0017FFFF), + + // Uncore CHASADALL Device + GEN_UNCORE_LEGACY_IRQ(0x001DFFFF), + + // Uncore PCUCR Device + GEN_UNCORE_LEGACY_IRQ(0x001EFFFF), + + // Uncore VCUCR Device + GEN_UNCORE_LEGACY_IRQ(0x001FFFFF) +}) + +// Socket 0, IIOStack 1 device IOAPIC interrupt routing +Name (AR10, Package (0x40) +{ + // PCI Express Port 1A-1D + GEN_PCIE_IOAPIC_IRQ(0x27), + + // Uncore CHAUTIL Devices + GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x20, 0x24, 0x25, 0x26), + + // Uncore CHASAD Devices + GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x0011FFFF, 0x20, 0x24, 0x25, 0x26), + + // Uncore CMSCHA Devices + GEN_UNCORE_IOAPIC_IRQ(0x0014FFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x20, 0x24, 0x25, 0x26), + GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x20, 0x24, 0x25, 0x26), + + // Uncore CHASADALL Device + GEN_UNCORE_IOAPIC_IRQ(0x001DFFFF, 0x20, 0x24, 0x25, 0x26), + + // Uncore PCUCR Device + GEN_UNCORE_IOAPIC_IRQ(0x001EFFFF, 0x20, 0x24, 0x25, 0x26), + + // Uncore VCUCR Device + GEN_UNCORE_IOAPIC_IRQ(0x001FFFFF, 0x20, 0x24, 0x25, 0x26) +}) + +// Socket 0, IIOStack 2 device legacy interrupt routing +Name (PR20, Package (0x24) +{ + // PCI Express Port 2 on PC02 + GEN_PCIE_LEGACY_IRQ(), + + // Uncore M2MEM Devices + GEN_UNCORE_LEGACY_IRQ(0x0008FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0009FFFF), + + // Uncore MCMAIN Device + GEN_UNCORE_LEGACY_IRQ(0x000AFFFF), + + // Uncore MCDECS2 Device + GEN_UNCORE_LEGACY_IRQ(0x000BFFFF), + + // Uncore MCMAIN Device + GEN_UNCORE_LEGACY_IRQ(0x000CFFFF), + + // Uncore MCDECS Device + GEN_UNCORE_LEGACY_IRQ(0x000DFFFF), + + // Uncore Unicast MC0 DDRIO0 Device + GEN_UNCORE_LEGACY_IRQ(0x0016FFFF), + + // Uncore Unicast MC1 DDRIO0 Device + GEN_UNCORE_LEGACY_IRQ(0x0017FFFF) +}) + +// Socket 0, IIOStack 2 device IOAPIC interrupt routing +Name (AR20, Package (0x24) +{ + // PCI Express Port 2 on PC02 + GEN_PCIE_IOAPIC_IRQ(0x2F), + + // Uncore M2MEM Devices + GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x28, 0x2C, 0x2D, 0x2E), + GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x28, 0x2C, 0x2D, 0x2E), + + // Uncore MCMAIN Device + GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x28, 0x2C, 0x2D, 0x2E), + + // Uncore MCDECS2 Device + GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x28, 0x2C, 0x2D, 0x2E), + + // Uncore MCMAIN Device + GEN_UNCORE_IOAPIC_IRQ(0x000CFFFF, 0x28, 0x2C, 0x2D, 0x2E), + + // Uncore MCDECS Device + GEN_UNCORE_IOAPIC_IRQ(0x000DFFFF, 0x28, 0x2C, 0x2D, 0x2E), + + // Uncore Unicast MC0 DDRIO0 Device + GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x28, 0x2C, 0x2D, 0x2E), + + // Uncore Unicast MC1 DDRIO0 Device + GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x28, 0x2C, 0x2D, 0x2E) +}) + +// Socket 0, IIOStack 3 device legacy interrupt routing +Name (PR28, Package (0x20) +{ + // PCI Express Port 3 on PC03 + GEN_PCIE_LEGACY_IRQ(), + + // KTI Devices + GEN_UNCORE_LEGACY_IRQ(0x000EFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000FFFFF), + GEN_UNCORE_LEGACY_IRQ(0x0010FFFF), + + // M3K Device + GEN_UNCORE_LEGACY_IRQ(0x0012FFFF), + + // M2U Device + GEN_UNCORE_LEGACY_IRQ(0x0015FFFF), + + // M2D Device + GEN_UNCORE_LEGACY_IRQ(0x0016FFFF), + + // M20 Device + GEN_UNCORE_LEGACY_IRQ(0x0017FFFF) +}) + +// Socket 0, IIOStack 3 device IOAPIC interrupt routing +Name (AR28, Package (0x20) +{ + // PCI Express Port 3 on PC03 + GEN_PCIE_IOAPIC_IRQ(0x37), + + // KTI Devices + GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x30, 0x34, 0x35, 0x36), + GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x30, 0x34, 0x35, 0x36), + GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x30, 0x34, 0x35, 0x36), + + // M3K Device + GEN_UNCORE_IOAPIC_IRQ(0x0012FFFF, 0x30, 0x34, 0x35, 0x36), + + // M2U Device + GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x30, 0x34, 0x35, 0x36), + + // M2D Device + GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x30, 0x34, 0x35, 0x36), + + // M20 Device + GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x30, 0x34, 0x35, 0x36) +}) + +// Socket 1, IIOStack 0 device legacy interrupt routing +Name (PR40, Package (0x09) +{ + // DMI + Package (0x04) { 0x0000FFFF, 0x00, LNKA, 0x00 }, + + // CBDMA + GEN_UNCORE_LEGACY_IRQ(0x0004FFFF), + + // Ubox + GEN_UNCORE_LEGACY_IRQ(0x0008FFFF) +}) + +// Socket 1, IIOStack 0 device IOAPIC interrupt routing +Name (AR40, Package (0x09) +{ + // DMI + Package (0x04) { 0x0000FFFF, 0x00, 0x00, 0x4F }, + + // CBDMA + GEN_UNCORE_IOAPIC_IRQ(0x0004FFFF, 0x4A, 0x4B, 0x4A, 0x4B), + + // Ubox + GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x48, 0x4C, 0x4D, 0x4E), +}) + +// Socket 1, IIOStack 1 device legacy interrupt routing +Name (PR50, Package (0x40) +{ + // PCI Express Port + GEN_PCIE_LEGACY_IRQ(), + + // CHA Devices + GEN_UNCORE_LEGACY_IRQ(0x0008FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0009FFFF), + GEN_UNCORE_LEGACY_IRQ(0x000AFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000BFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000EFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000FFFFF), + GEN_UNCORE_LEGACY_IRQ(0x0010FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0011FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0014FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0015FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0016FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0017FFFF), + GEN_UNCORE_LEGACY_IRQ(0x001DFFFF), + + // PCU Devices + GEN_UNCORE_LEGACY_IRQ(0x001EFFFF), + GEN_UNCORE_LEGACY_IRQ(0x001FFFFF) +}) + +// Socket 1, IIOStack 1 device IOAPIC interrupt routing +Name (AR50, Package (0x40) +{ + // PCI Express Port + GEN_PCIE_IOAPIC_IRQ(0x57), + + // CHA Devices + GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0011FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0014FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x001DFFFF, 0x50, 0x54, 0x55, 0x56), + + // PCU Devices + GEN_UNCORE_IOAPIC_IRQ(0x001EFFFF, 0x50, 0x54, 0x55, 0x56), + GEN_UNCORE_IOAPIC_IRQ(0x001FFFFF, 0x50, 0x54, 0x55, 0x56) +}) + +// Socket 1, IIOStack 2 device legacy interrupt routing +Name (PR60, Package (0x24) +{ + // PCI Express Port + GEN_PCIE_LEGACY_IRQ(), + + // Integrated Memory Controller + GEN_UNCORE_LEGACY_IRQ(0x0008FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0009FFFF), + + // Uncore Devices + GEN_UNCORE_LEGACY_IRQ(0x000AFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000BFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000CFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000DFFFF), + GEN_UNCORE_LEGACY_IRQ(0x0016FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0017FFFF) +}) + +// Socket 1, IIOStack 2 device IOAPIC interrupt routing +Name (AR60, Package (0x24) +{ + // PCI Express Port + GEN_PCIE_IOAPIC_IRQ(0x5F), + + // Integrated Memory Controller + GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x58, 0x5C, 0x5D, 0x5E), + GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x58, 0x5C, 0x5D, 0x5E), + + // Uncore Devices + GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x58, 0x5C, 0x5D, 0x5E), + GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x58, 0x5C, 0x5D, 0x5E), + GEN_UNCORE_IOAPIC_IRQ(0x000CFFFF, 0x58, 0x5C, 0x5D, 0x5E), + GEN_UNCORE_IOAPIC_IRQ(0x000DFFFF, 0x58, 0x5C, 0x5D, 0x5E), + GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x58, 0x5C, 0x5D, 0x5E), + GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x58, 0x5C, 0x5D, 0x5E) +}) + +// Socket 1, IIOStack 3 device legacy interrupt routing +Name (PR68, Package (0x20) +{ + // PCI Express Port + GEN_PCIE_LEGACY_IRQ(), + + // Uncore Devices + GEN_UNCORE_LEGACY_IRQ(0x000EFFFF), + GEN_UNCORE_LEGACY_IRQ(0x000FFFFF), + GEN_UNCORE_LEGACY_IRQ(0x0010FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0012FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0015FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0016FFFF), + GEN_UNCORE_LEGACY_IRQ(0x0017FFFF) +}) + +// Socket 1, IIOStack 3 device legacy interrupt routing +Name (AR68, Package (0x20) +{ + // PCI Express Port + GEN_PCIE_IOAPIC_IRQ(0x67), + + // Uncore Devices + GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x60, 0x64, 0x65, 0x66), + GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x60, 0x64, 0x65, 0x66), + GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x60, 0x64, 0x65, 0x66), + GEN_UNCORE_IOAPIC_IRQ(0x0012FFFF, 0x60, 0x64, 0x65, 0x66), + GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x60, 0x64, 0x65, 0x66), + GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x60, 0x64, 0x65, 0x66), + GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x60, 0x64, 0x65, 0x66) +}) diff --git a/src/soc/intel/xeon_sp/bootblock/bootblock.c b/src/soc/intel/xeon_sp/bootblock/bootblock.c new file mode 100644 index 0000000..482f5b5 --- /dev/null +++ b/src/soc/intel/xeon_sp/bootblock/bootblock.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <bootblock_common.h> +#include <device/pci.h> +#include <FsptUpd.h> +#include <intelblocks/fast_spi.h> +#include <soc/iomap.h> +#include <console/console.h> + +const FSPT_UPD temp_ram_init_params = { + .FspUpdHeader = { + .Signature = FSPT_UPD_SIGNATURE, + .Revision = 1, + .Reserved = {0}, + }, + .FsptCoreUpd = { + .MicrocodeRegionBase = (UINT32)CONFIG_CPU_MICROCODE_CBFS_LOC, + .MicrocodeRegionLength = (UINT32)CONFIG_CPU_MICROCODE_CBFS_LEN, + .CodeRegionBase = (uint32_t)(0x100000000ULL - CONFIG_ROM_SIZE), + .CodeRegionLength = (UINT32)CONFIG_ROM_SIZE, + .Reserved1 = {0}, + }, + .FsptConfig = { + .PcdFsptPort80RouteDisable = 0, + .ReservedTempRamInitUpd = {0}, + }, + .UnusedUpdSpace0 = {0}, + .UpdTerminator = 0x55AA, +}; + +asmlinkage void bootblock_c_entry(uint64_t base_timestamp) +{ + fast_spi_cache_bios_region(); + + bootblock_main_with_basetime(base_timestamp); +} + +void bootblock_soc_early_init(void) +{ + fast_spi_early_init(SPI_BASE_ADDRESS); +} + +void bootblock_soc_init(void) +{ + if (CONFIG(BOOTBLOCK_CONSOLE)) + printk(BIOS_DEBUG, "FSP TempRamInit successful...\n"); +} diff --git a/src/soc/intel/xeon_sp/chip.c b/src/soc/intel/xeon_sp/chip.c new file mode 100644 index 0000000..832f98e --- /dev/null +++ b/src/soc/intel/xeon_sp/chip.c @@ -0,0 +1,603 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <cbfs.h> +#include <assert.h> +#include <device/pci.h> +#include <soc/acpi.h> +#include <soc/ramstage.h> +#include <soc/soc_util.h> + +struct pci_resource { + struct device *dev; + struct resource *res; + struct pci_resource *next; +}; + +struct stack_dev_resource { + uint8_t align; + struct pci_resource *children; + struct stack_dev_resource *next; +}; + +static void assign_stack_resources(struct iiostack_resource *stack_list, + struct device *dev, struct resource *bridge); + +static void xeonsp_pci_domain_scan_bus(struct device *dev) +{ + DEV_FUNC_ENTER(dev); + struct bus *link = dev->link_list; + + printk(BIOS_SPEW, "%s:%s scanning buses under device %s\n", + __FILE__, __func__, dev_path(dev)); + while (link != NULL) { + if (link->secondary == 0) { // scan only PSTACK buses + struct device *d; + for (d = link->children; d; d = d->sibling) + pci_probe_dev(d, link, d->path.pci.devfn); + scan_bridges(link); + } else { + pci_scan_bus(link, PCI_DEVFN(0, 0), 0xff); + } + link = link->next; + } + DEV_FUNC_EXIT(dev); +} + +static void xeonsp_pci_dev_iterator(struct bus *bus, + void (*dev_iterator)(struct device *, void *), + void (*res_iterator)(struct device *, struct resource *, void *), + void *data) +{ + struct device *curdev; + struct resource *res; + + /* Walk through all devices and find which resources they need. */ + for (curdev = bus->children; curdev; curdev = curdev->sibling) { + struct bus *link; + + if (!curdev->enabled) + continue; + + if (!curdev->ops || !curdev->ops->read_resources) { + if (curdev->path.type != DEVICE_PATH_APIC) + printk(BIOS_ERR, "%s missing read_resources\n", + dev_path(curdev)); + continue; + } + + if (dev_iterator) + dev_iterator(curdev, data); + + if (res_iterator) { + for (res = curdev->resource_list; res; res = res->next) + res_iterator(curdev, res, data); + } + + /* Read in the resources behind the current device's links. */ + for (link = curdev->link_list; link; link = link->next) + xeonsp_pci_dev_iterator(link, dev_iterator, res_iterator, data); + } +} + +static void xeonsp_pci_dev_read_resources(struct device *dev, void *data) +{ + post_log_path(dev); + dev->ops->read_resources(dev); +} + +static void xeonsp_pci_dev_dummy_func(struct device *dev) +{ +} + +static void xeonsp_reset_pci_op(struct device *dev, void *data) +{ + if (dev->ops) + dev->ops->read_resources = xeonsp_pci_dev_dummy_func; +} + +static STACK_RES *find_stack_for_bus(struct iiostack_resource *info, uint8_t bus) +{ + for (int i = 0; i < info->no_of_stacks; ++i) { + if (bus >= info->res[i].BusBase && bus <= info->res[i].BusLimit) + return &info->res[i]; + } + return NULL; +} + +static void add_res_to_stack(struct stack_dev_resource **root, + struct device *dev, struct resource *res) +{ + struct stack_dev_resource *cur = *root; + while (cur) { + if (cur->align == res->align || cur->next == NULL) /* equal or last record */ + break; + else if (cur->align > res->align) { + if (cur->next->align < res->align) /* need to insert new record here */ + break; + cur = cur->next; + } else { + break; + } + } + + struct stack_dev_resource *nr; + if (!cur || cur->align != res->align) { /* need to add new record */ + nr = malloc(sizeof(struct stack_dev_resource)); + if (nr == 0) + die("assign_resource_to_stack(): out of memory.\n"); + memset(nr, 0, sizeof(struct stack_dev_resource)); + nr->align = res->align; + if (!cur) { + *root = nr; /* head node */ + } else if (cur->align > nr->align) { + if (cur->next == NULL) { + cur->next = nr; + } else { + nr->next = cur->next; + cur->next = nr; + } + } else { /* insert in the beginning */ + nr->next = cur; + *root = nr; + } + } else { + nr = cur; + } + + assert(nr != NULL && nr->align == res->align); + + struct pci_resource *npr = malloc(sizeof(struct pci_resource)); + if (npr == NULL) + die("%s: out of memory.\n", __func__); + npr->res = res; + npr->dev = dev; + npr->next = NULL; + + if (nr->children == NULL) { + nr->children = npr; + } else { + struct pci_resource *pr = nr->children; + while (pr->next != NULL) + pr = pr->next; + pr->next = npr; + } +} + +static void reserve_dev_resources(STACK_RES *stack, unsigned long res_type, + struct stack_dev_resource *res_root, struct resource *bridge) +{ + uint8_t align; + uint64_t orig_base, base; + + if (res_type & IORESOURCE_IO) + orig_base = stack->PciResourceIoBase; + else if ((res_type & IORESOURCE_MEM) && ((res_type & IORESOURCE_PCI64) || + (!res_root && bridge && (bridge->flags & IORESOURCE_PREFETCH)))) + orig_base = stack->PciResourceMem64Base; + else + orig_base = stack->PciResourceMem32Base; + + align = 0; + base = orig_base; + int first = 1; + while (res_root) { /* loop through all devices grouped by alignment requirements */ + struct pci_resource *pr = res_root->children; + while (pr) { + if (first) { + if (bridge) { /* takes highest alignment */ + if (bridge->align < pr->res->align) + bridge->align = pr->res->align; + orig_base = ALIGN_UP(orig_base, 1 << bridge->align); + } else { + orig_base = ALIGN_UP(orig_base, 1 << pr->res->align); + } + base = orig_base; + + if (bridge) + bridge->base = base; + pr->res->base = base; + first = 0; + } else { + pr->res->base = ALIGN_UP(base, 1 << pr->res->align); + } + pr->res->limit = pr->res->base + pr->res->size - 1; + base = pr->res->limit + 1; + pr->res->flags |= (IORESOURCE_ASSIGNED); + pr = pr->next; + } + res_root = res_root->next; + } + + if (bridge) { + /* this bridge doesn't have any resources, will set it to default window */ + if (first) { + orig_base = ALIGN_UP(orig_base, 1 << bridge->align); + bridge->base = orig_base; + base = orig_base + (1ULL << bridge->gran); + } + + bridge->size = ALIGN_UP(base, 1 << bridge->align) - bridge->base; + + bridge->limit = bridge->base + bridge->size - 1; + bridge->flags |= (IORESOURCE_ASSIGNED); + base = bridge->limit + 1; + } + + /* update new limits */ + if (res_type & IORESOURCE_IO) + stack->PciResourceIoBase = base; + else if ((res_type & IORESOURCE_MEM) && ((res_type & IORESOURCE_PCI64) || + (!res_root && bridge && (bridge->flags & IORESOURCE_PREFETCH)))) + stack->PciResourceMem64Base = base; + else + stack->PciResourceMem32Base = base; +} + +static void reclaim_resource_mem(struct stack_dev_resource *res_root) +{ + while (res_root) { /* loop through all devices grouped by alignment requirements */ + /* free pci_resource */ + struct pci_resource *pr = res_root->children; + while (pr) { + struct pci_resource *dpr = pr; + pr = pr->next; + free(dpr); + } + + /* free stack_dev_resource */ + struct stack_dev_resource *ddr = res_root; + res_root = res_root->next; + free(ddr); + } +} + +static void assign_bridge_resources(struct iiostack_resource *stack_list, + struct device *dev, struct resource *bridge) +{ + struct resource *res; + if (!dev->enabled) + return; + + for (res = dev->resource_list; res; res = res->next) { + if (!(res->flags & IORESOURCE_BRIDGE) || + (bridge && ((bridge->flags & (IORESOURCE_IO | IORESOURCE_MEM | + IORESOURCE_PREFETCH | IORESOURCE_PCI64)) != + (res->flags & (IORESOURCE_IO | IORESOURCE_MEM | + IORESOURCE_PREFETCH | IORESOURCE_PCI64))))) + continue; + + assign_stack_resources(stack_list, dev, res); + if (!bridge) + continue; + /* for 1st time update, overlading IORESOURCE_ASSIGNED */ + if (!(bridge->flags & IORESOURCE_ASSIGNED)) { + bridge->base = res->base; + bridge->limit = res->limit; + bridge->flags |= (IORESOURCE_ASSIGNED); + } else { + /* update bridge range from child bridge range */ + if (res->base < bridge->base) + bridge->base = res->base; + if (res->limit > bridge->limit) + bridge->limit = res->limit; + } + bridge->size = (bridge->limit - bridge->base + 1); + } +} + +static void assign_stack_resources(struct iiostack_resource *stack_list, + struct device *dev, struct resource *bridge) +{ + struct bus *bus; + + /* Read in the resources behind the current device's links. */ + for (bus = dev->link_list; bus; bus = bus->next) { + struct device *curdev; + STACK_RES *stack; + + /* get IIO stack for this bus */ + stack = find_stack_for_bus(stack_list, bus->secondary); + assert(stack != NULL); + + /* Assign resources to bridge */ + for (curdev = bus->children; curdev; curdev = curdev->sibling) + assign_bridge_resources(stack_list, curdev, bridge); + + /* Pick non-bridged resources for resource allocation for each resource type */ + unsigned long flags[5] = {IORESOURCE_IO, IORESOURCE_MEM, + (IORESOURCE_PCI64|IORESOURCE_MEM), (IORESOURCE_MEM|IORESOURCE_PREFETCH), + (IORESOURCE_PCI64|IORESOURCE_MEM|IORESOURCE_PREFETCH)}; + uint8_t no_res_types = 5; + if (bridge) { + flags[0] = bridge->flags & + (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH); + if ((bridge->flags & IORESOURCE_MEM) && + (bridge->flags & IORESOURCE_PREFETCH)) + flags[0] |= IORESOURCE_PCI64; + no_res_types = 1; + } + + /* Process each resource type */ + for (int rt = 0; rt < no_res_types; ++rt) { + struct stack_dev_resource *res_root = NULL; + + for (curdev = bus->children; curdev; curdev = curdev->sibling) { + struct resource *res; + if (!curdev->enabled) + continue; + + for (res = curdev->resource_list; res; res = res->next) { + if ((res->flags & IORESOURCE_BRIDGE) || (res->flags & + (IORESOURCE_STORED | IORESOURCE_RESERVE | + IORESOURCE_FIXED | IORESOURCE_ASSIGNED) + ) || ((res->flags & (IORESOURCE_IO | + IORESOURCE_MEM | IORESOURCE_PCI64 + | IORESOURCE_PREFETCH)) + != flags[rt]) || res->size == 0) + continue; + else + add_res_to_stack(&res_root, curdev, res); + } + } + + /* Allocate resources and update bridge range */ + if (res_root || (bridge && !(bridge->flags & IORESOURCE_ASSIGNED))) { + reserve_dev_resources(stack, flags[rt], res_root, bridge); + reclaim_resource_mem(res_root); + } + } + } +} + +static void xeonsp_constrain_pci_resources(struct device *dev, struct resource *res, void *data) +{ + STACK_RES *stack = (STACK_RES *) data; + if (!(res->flags & IORESOURCE_FIXED)) + return; + + uint64_t base, limit; + if (res->flags & IORESOURCE_IO) { + base = stack->PciResourceIoBase; + limit = stack->PciResourceIoLimit; + } else if ((res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PCI64)) { + base = stack->PciResourceMem64Base; + limit = stack->PciResourceMem64Limit; + } else { + base = stack->PciResourceMem32Base; + limit = stack->PciResourceMem32Limit; + } + + if (((res->base + res->size - 1) < base) || (res->base > limit)) /* outside window */ + return; + + if (res->limit > limit) /* resource end is out of limit */ + limit = res->base - 1; + else + base = res->base + res->size; + + if (res->flags & IORESOURCE_IO) { + stack->PciResourceIoBase = base; + stack->PciResourceIoLimit = limit; + } else if ((res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PCI64)) { + stack->PciResourceMem64Base = base; + stack->PciResourceMem64Limit = limit; + } else { + stack->PciResourceMem32Base = base; + stack->PciResourceMem32Limit = limit; + } +} + +static void xeonsp_pci_domain_read_resources(struct device *dev) +{ + struct bus *link; + + DEV_FUNC_ENTER(dev); + + pci_domain_read_resources(dev); + + /* + * Walk through all devices in this domain and read resources. + * Since there is no callback when read resource operation is + * complete for all devices, domain read resource function initiates + * read resources for all devices and swaps read resource operation + * with dummy function to avoid warning. + */ + for (link = dev->link_list; link; link = link->next) + xeonsp_pci_dev_iterator(link, xeonsp_pci_dev_read_resources, NULL, NULL); + + for (link = dev->link_list; link; link = link->next) + xeonsp_pci_dev_iterator(link, xeonsp_reset_pci_op, NULL, NULL); + + /* + * 1. group devices, resources for each stack + * 2. order resources in descending order of requested resource allocation sizes + */ + struct iiostack_resource stack_info = {0}; + get_iiostack_info(&stack_info); + + /* constrain stack window */ + for (link = dev->link_list; link; link = link->next) { + STACK_RES *stack = find_stack_for_bus(&stack_info, link->secondary); + assert(stack != 0); + xeonsp_pci_dev_iterator(link, NULL, xeonsp_constrain_pci_resources, stack); + } + + /* assign resources */ + assign_stack_resources(&stack_info, dev, NULL); + + DEV_FUNC_EXIT(dev); +} + +static void reset_resource_to_unassigned(struct device *dev, struct resource *res, void *data) +{ + if ((res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) && + !(res->flags & (IORESOURCE_FIXED | IORESOURCE_RESERVE))) { + res->flags &= ~IORESOURCE_ASSIGNED; + } +} + +static void xeonsp_pci_domain_set_resources(struct device *dev) +{ + DEV_FUNC_ENTER(dev); + + print_resource_tree(dev, BIOS_SPEW, "Before xeonsp pci domain set resource"); + + /* reset bus 0 dev resource assignment - need to change them to FSP IIOStack window */ + xeonsp_pci_dev_iterator(dev->link_list, NULL, reset_resource_to_unassigned, NULL); + + /* update dev resources based on IIOStack IO/Mem32/Mem64 windows */ + xeonsp_pci_domain_read_resources(dev); + + struct bus *link = dev->link_list; + while (link != NULL) { + assign_resources(link); + link = link->next; + } + + print_resource_tree(dev, BIOS_SPEW, "After xeonsp pci domain set resource"); + + DEV_FUNC_EXIT(dev); +} + +static struct device_operations pci_domain_ops = { + .read_resources = &pci_domain_read_resources, + .set_resources = &xeonsp_pci_domain_set_resources, + .scan_bus = &xeonsp_pci_domain_scan_bus, +#if CONFIG(HAVE_ACPI_TABLES) + .write_acpi_tables = &northbridge_write_acpi_tables, +#endif +}; + +static struct device_operations cpu_bus_ops = { + .read_resources = DEVICE_NOOP, + .set_resources = DEVICE_NOOP, + .enable_resources = DEVICE_NOOP, + .init = xeon_sp_init_cpus, + .scan_bus = NULL, +#if CONFIG(HAVE_ACPI_TABLES) + /* defined in src/soc/intel/common/block/acpi/acpi.c */ + .acpi_fill_ssdt_generator = generate_cpu_entries, +#endif +}; + +/* Attach IIO stack bus numbers with dummy device to PCI DOMAIN 0000 device */ +static void attach_iio_stacks(struct device *dev) +{ + struct bus *iiostack_bus; + struct device dummy; + struct iiostack_resource stack_info = {0}; + + DEV_FUNC_ENTER(dev); + + get_iiostack_info(&stack_info); + for (int s = 0; s < stack_info.no_of_stacks; ++s) { + /* only non zero bus no. needs to be enumerated */ + if (stack_info.res[s].BusBase == 0) + continue; + + iiostack_bus = malloc(sizeof(struct bus)); + if (iiostack_bus == NULL) + die("%s: out of memory.\n", __func__); + memset(iiostack_bus, 0, sizeof(*iiostack_bus)); + memcpy(iiostack_bus, dev->bus, sizeof(*iiostack_bus)); + iiostack_bus->secondary = stack_info.res[s].BusBase; + iiostack_bus->subordinate = stack_info.res[s].BusBase; + iiostack_bus->dev = NULL; + iiostack_bus->children = NULL; + iiostack_bus->next = NULL; + iiostack_bus->link_num = 1; + + dummy.bus = iiostack_bus; + dummy.path.type = DEVICE_PATH_PCI; + dummy.path.pci.devfn = 0; + uint32_t id = pci_read_config32(&dummy, PCI_VENDOR_ID); + if (id == 0xffffffff) + printk(BIOS_WARNING, "IIO Stack device %s not visible\n", + dev_path(&dummy)); + + if (dev->link_list == NULL) { + dev->link_list = iiostack_bus; + } else { + struct bus *nlink = dev->link_list; + while (nlink->next != NULL) + nlink = nlink->next; + nlink->next = iiostack_bus; + } + } + + DEV_FUNC_EXIT(dev); +} + +static void soc_enable_dev(struct device *dev) +{ + /* Set the operations if it is a special bus type */ + if (dev->path.type == DEVICE_PATH_DOMAIN) { + dev->ops = &pci_domain_ops; + attach_iio_stacks(dev); + } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { + dev->ops = &cpu_bus_ops; + } +} + +static void soc_init(void *data) +{ + printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n"); + fsp_silicon_init(false); +} + +static void soc_final(void *data) +{ + // Temp Fix - should be done by FSP, in 2S bios completion + // is not carried out on socket 2 + set_bios_init_completion(); +} + +static void soc_silicon_init_params(FSPS_UPD *silupd) +{ +} + +void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd) +{ + const struct microcode *microcode_file; + size_t microcode_len; + + microcode_file = cbfs_boot_map_with_leak("cpu_microcode_blob.bin", + CBFS_TYPE_MICROCODE, µcode_len); + + if ((microcode_file != NULL) && (microcode_len != 0)) { + /* Update CPU Microcode patch base address/size */ + silupd->FspsConfig.PcdCpuMicrocodePatchBase = + (uint32_t)microcode_file; + silupd->FspsConfig.PcdCpuMicrocodePatchSize = + (uint32_t)microcode_len; + } + + soc_silicon_init_params(silupd); + mainboard_silicon_init_params(silupd); +} + +struct chip_operations soc_intel_xeon_sp_ops = { + CHIP_NAME("Intel Xeon-SP SOC") + .enable_dev = soc_enable_dev, + .init = soc_init, + .final = soc_final +}; + +struct pci_operations soc_pci_ops = { + .set_subsystem = pci_dev_set_subsystem, +}; diff --git a/src/soc/intel/xeon_sp/chip.h b/src/soc/intel/xeon_sp/chip.h new file mode 100644 index 0000000..72f2445 --- /dev/null +++ b/src/soc/intel/xeon_sp/chip.h @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef _SOC_CHIP_H_ +#define _SOC_CHIP_H_ + +#include <stdint.h> +#include <intelblocks/cfg.h> +#include <soc/irq.h> + +struct soc_intel_xeon_sp_config { + /* Common struct containing soc config data required by common code */ + struct soc_intel_common_config common_soc_config; + + /** + * Interrupt Routing configuration + * If bit7 is 1, the interrupt is disabled. + */ + uint8_t pirqa_routing; + uint8_t pirqb_routing; + uint8_t pirqc_routing; + uint8_t pirqd_routing; + uint8_t pirqe_routing; + uint8_t pirqf_routing; + uint8_t pirqg_routing; + uint8_t pirqh_routing; + + /** + * Device Interrupt Routing configuration + * Interrupt Pin x Route. + * 0h = PIRQA# + * 1h = PIRQB# + * 2h = PIRQC# + * 3h = PIRQD# + * 4h = PIRQE# + * 5h = PIRQF# + * 6h = PIRQG# + * 7h = PIRQH# + */ + uint16_t ir00_routing; + uint16_t ir01_routing; + uint16_t ir02_routing; + uint16_t ir03_routing; + uint16_t ir04_routing; + + /** + * Device Interrupt Polarity Control + * ipc0 - IRQ-00-31 - 1: Active low to IOAPIC, 0: Active high to IOAPIC + * ipc1 - IRQ-32-63 - 1: Active low to IOAPIC, 0: Active high to IOAPIC + * ipc2 - IRQ-64-95 - 1: Active low to IOAPIC, 0: Active high to IOAPIC + * ipc3 - IRQ-96-119 - 1: Active low to IOAPIC, 0: Active high to IOAPIC + */ + uint32_t ipc0; + uint32_t ipc1; + uint32_t ipc2; + uint32_t ipc3; + + uint64_t turbo_ratio_limit; + uint64_t turbo_ratio_limit_cores; + + uint32_t pstate_req_ratio; + + uint32_t vtd_support; + uint32_t coherency_support; + uint32_t ats_support; +}; + +extern struct chip_operations soc_intel_xeon_sp_ops; + +typedef struct soc_intel_xeon_sp_config config_t; + +#endif diff --git a/src/soc/intel/xeon_sp/cpu.c b/src/soc/intel/xeon_sp/cpu.c new file mode 100644 index 0000000..1d5c578 --- /dev/null +++ b/src/soc/intel/xeon_sp/cpu.c @@ -0,0 +1,260 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <console/console.h> +#include <intelblocks/cpulib.h> +#include <cpu/cpu.h> +#include <cpu/x86/mtrr.h> +#include <cpu/x86/mp.h> +#include <cpu/intel/turbo.h> +#include <soc/msr.h> +#include <soc/cpu.h> +#include <soc/soc_util.h> +#include <assert.h> +#include "chip.h" + +static const config_t *chip_config = NULL; + +static void xeon_configure_mca(void) +{ + msr_t msr; + struct cpuid_result cpuid_regs; + + /* Check feature flag in CPUID.(EAX=1):EDX[7]==1 MCE + * and CPUID.(EAX=1):EDX[14]==1 MCA*/ + cpuid_regs = cpuid(1); + if ((cpuid_regs.edx & (1<<7 | 1<<14)) != (1<<7 | 1<<14)) + return; + + msr = rdmsr(IA32_MCG_CAP); + if (msr.lo & IA32_MCG_CAP_CTL_P_MASK) { + /* Enable all error logging */ + msr.lo = msr.hi = 0xffffffff; + wrmsr(IA32_MCG_CTL, msr); + } + + /* 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. */ + mca_configure(); +} + +static void xeon_sp_core_init(struct device *cpu) +{ + msr_t msr; + + printk(BIOS_INFO, "%s dev: %s, cpu: %d, apic_id: 0x%x\n", + __func__, dev_path(cpu), cpu_index(), cpu->path.apic.apic_id); + assert(chip_config != NULL); + + /* set MSR_PKG_CST_CONFIG_CONTROL - scope per core*/ + msr.hi = 0; + msr.lo = (PKG_CSTATE_NO_LIMIT | IO_MWAIT_REDIRECTION_ENABLE | CFG_LOCK_ENABLE); + wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr); + + /* set MSR_PMG_IO_CAPTURE_BASE - scope per core */ + msr.hi = 0; + msr.lo = (LVL_2_BASE_ADDRESS | CST_RANGE_MAX_C6); + wrmsr(MSR_PMG_IO_CAPTURE_BASE, msr); + + /* Enable Energy Perf Bias Access, Dynamic switching and lock MSR */ + msr = rdmsr(MSR_POWER_CTL); + msr.lo |= (ENERGY_PERF_BIAS_ACCESS_ENABLE | PWR_PERF_TUNING_DYN_SWITCHING_ENABLE + | PROCHOT_LOCK_ENABLE); + wrmsr(MSR_POWER_CTL, msr); + + /* Set P-State ratio */ + msr = rdmsr(MSR_IA32_PERF_CTRL); + msr.lo &= ~PSTATE_REQ_MASK; + msr.lo |= (chip_config->pstate_req_ratio << PSTATE_REQ_SHIFT); + wrmsr(MSR_IA32_PERF_CTRL, msr); + + /* + * Set HWP base feature, EPP reg enumeration, lock thermal and msr + * TODO: Set LOCK_MISC_PWR_MGMT_MSR, Unexpected Exception if you + * lock & issue wrmsr on every thread + * This is package level MSR. Need to check if it updates correctly on + * multi-socket platform. + */ + msr = rdmsr(MSR_MISC_PWR_MGMT); + if (!(msr.lo & LOCK_MISC_PWR_MGMT_MSR)) { /* if already locked skip update */ + msr.lo = (HWP_ENUM_ENABLE | HWP_EPP_ENUM_ENABLE | LOCK_MISC_PWR_MGMT_MSR | + LOCK_THERM_INT); + wrmsr(MSR_MISC_PWR_MGMT, msr); + } + + /* TODO MSR_VR_MISC_CONFIG */ + + /* Set current limit lock */ + msr = rdmsr(MSR_VR_CURRENT_CONFIG); + msr.lo |= CURRENT_LIMIT_LOCK; + wrmsr(MSR_VR_CURRENT_CONFIG, msr); + + /* Set Turbo Ratio Limits */ + msr.lo = chip_config->turbo_ratio_limit & 0xffffffff; + msr.hi = (chip_config->turbo_ratio_limit >> 32) & 0xffffffff; + wrmsr(MSR_TURBO_RATIO_LIMIT, msr); + + /* Set Turbo Ratio Limit Cores */ + msr.lo = chip_config->turbo_ratio_limit_cores & 0xffffffff; + msr.hi = (chip_config->turbo_ratio_limit_cores >> 32) & 0xffffffff; + wrmsr(MSR_TURBO_RATIO_LIMIT_CORES, msr); + + /* set Turbo Activation ratio */ + msr.hi = 0; + msr = rdmsr(MSR_TURBO_ACTIVATION_RATIO); + msr.lo |= MAX_NON_TURBO_RATIO; + wrmsr(MSR_TURBO_ACTIVATION_RATIO, msr); + + /* Enable Fast Strings */ + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= FAST_STRINGS_ENABLE_BIT; + wrmsr(IA32_MISC_ENABLE, msr); + + /* Set energy policy */ + msr_t msr1 = rdmsr(MSR_ENERGY_PERF_BIAS_CONFIG); + msr.lo = (msr1.lo & EPB_ENERGY_POLICY_MASK) >> EPB_ENERGY_POLICY_SHIFT; + msr.hi = 0; + wrmsr(MSR_IA32_ENERGY_PERF_BIAS, msr); + + /* Enable Turbo */ + enable_turbo(); + + /* Enable speed step. */ + if (get_turbo_state() == TURBO_ENABLED) { + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= SPEED_STEP_ENABLE_BIT; + wrmsr(IA32_MISC_ENABLE, msr); + } + + /* Clear out pending MCEs */ + xeon_configure_mca(); +} + +static struct device_operations cpu_dev_ops = { + .init = xeon_sp_core_init, +}; + +static const struct cpu_device_id cpu_table[] = { + /* Skylake-SP A0/A1 CPUID 0x506f0*/ + {X86_VENDOR_INTEL, CPUID_SKYLAKE_SP_A0_A1}, + /* Skylake-SP B0 CPUID 0x506f1*/ + {X86_VENDOR_INTEL, CPUID_SKYLAKE_SP_B0}, + /* Skylake-SP 4 CPUID 0x50654*/ + {X86_VENDOR_INTEL, CPUID_SKYLAKE_SP_4}, + {0, 0}, +}; + +static const struct cpu_driver driver __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; + +static void set_max_turbo_freq(void) +{ + msr_t msr, perf_ctl; + + FUNC_ENTER(); + perf_ctl.hi = 0; + + /* Check for configurable TDP option */ + if (get_turbo_state() == TURBO_ENABLED) { + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else if (cpu_config_tdp_levels()) { + /* Set to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else { + /* Platform Info bits 15:8 give max ratio */ + msr = rdmsr(MSR_PLATFORM_INFO); + perf_ctl.lo = msr.lo & 0xff00; + } + wrmsr(IA32_PERF_CTL, perf_ctl); + + printk(BIOS_DEBUG, "cpu: frequency set to %d\n", + ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); + FUNC_EXIT(); +} + +/* + * Do essential initialization tasks before APs can be fired up + * + * Prevent race condition in MTRR solution. Enable MTRRs on the BSP. This + * creates the MTRR solution that the APs will use. Otherwise APs will try to + * apply the incomplete solution as the BSP is calculating it. + */ +static void pre_mp_init(void) +{ + printk(BIOS_DEBUG, "%s: entry\n", __func__); + + x86_setup_fixed_mtrrs(); +} + +static void post_mp_init(void) +{ + /* Set Max Ratio */ + set_max_turbo_freq(); + + /* + * TODO: Now that all APs have been relocated as well as the BSP let SMIs + * start flowing. + */ +} + +/* + * CPU initialization recipe + * + * Note that no microcode update is passed to the init function. CSE updates + * the microcode on all cores before releasing them from reset. That means that + * the BSP and all APs will come up with the same microcode revision. + */ +static const struct mp_ops mp_ops = { + .pre_mp_init = pre_mp_init, + .get_cpu_count = get_platform_thread_count, + //.get_smm_info = get_smm_info, /* TODO */ + .get_smm_info = NULL, + //.pre_mp_smm_init = southcluster_smm_clear_state, /* TODO */ + .pre_mp_smm_init = NULL, + //.relocation_handler = relocation_handler, /* TODO */ + .relocation_handler = NULL, + .post_mp_init = post_mp_init, +}; + + +void xeon_sp_init_cpus(struct device *dev) +{ + FUNC_ENTER(); + + /* + * This gets used in cpu device callback. Other than cpu 0, + * rest of the CPU devices do not have + * chip_info updated. Global chip_config is used as workaround + */ + chip_config = dev->chip_info; + + config_reset_cpl3_csrs(); + + /* calls src/cpu/x86/mp_init.c */ + if (mp_init_with_smm(dev->link_list, &mp_ops) < 0) + printk(BIOS_ERR, "MP initialization failure.\n"); + + /* update numa domain for all cpu devices */ + xeonsp_init_cpu_config(); + + FUNC_EXIT(); +} diff --git a/src/soc/intel/xeon_sp/hob_display.c b/src/soc/intel/xeon_sp/hob_display.c new file mode 100644 index 0000000..1508011 --- /dev/null +++ b/src/soc/intel/xeon_sp/hob_display.c @@ -0,0 +1,235 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <console/console.h> +#include <fsp/util.h> +#include <lib.h> +#include <assert.h> +#include <hob_iiouds.h> +#include <hob_memmap.h> + +static const uint8_t fsp_hob_iio_uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; +static const uint8_t fsp_hob_memmap_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; + +struct guid_name_map { + const void *guid; + const char *name; +}; + +static const struct guid_name_map guid_names[] = { + { fsp_hob_iio_uds_guid, "FSP_HOB_IIO_UNIVERSAL_DATA_GUID" }, + { fsp_hob_memmap_guid, "FSP_SYSTEM_MEMORYMAP_HOB_GUID" }, +}; + +const char *soc_get_guid_name(const uint8_t *guid) +{ + size_t index; + + /* Compare the GUID values in this module */ + for (index = 0; index < ARRAY_SIZE(guid_names); index++) + if (fsp_guid_compare(guid, guid_names[index].guid)) + return guid_names[index].name; + + return NULL; +} + +void soc_display_hob(const struct hob_header *hob) +{ + const struct hob_resource *res; + + res = fsp_hob_header_to_resource(hob); + assert(res != NULL); + printk(BIOS_DEBUG, "\tResource type: 0x%x, attribute: 0x%x, addr: 0x%08llx, len: 0x%08llx\n", + res->type, res->attribute_type, res->addr, res->length); + printk(BIOS_DEBUG, "\tOwner GUID: "); + fsp_print_guid(res->owner_guid); + printk(BIOS_DEBUG, " (%s)\n", fsp_get_guid_name(res->owner_guid)); + + if (fsp_guid_compare(res->owner_guid, fsp_hob_iio_uds_guid) == 0) + soc_display_iio_universal_data_hob(); + else if (fsp_guid_compare(res->owner_guid, fsp_hob_memmap_guid) == 0) + soc_display_memmap_hob(); + else + hexdump(hob, hob->length); +} + +void soc_display_memmap_hob(void) +{ + size_t hob_size = 0; + const struct SystemMemoryMapHob *hob = + fsp_find_extension_hob_by_guid(fsp_hob_memmap_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + printk(BIOS_DEBUG, "===================== MEMORY MAP HOB DATA =====================\n"); + printk(BIOS_DEBUG, "hob: %p, hob_size: 0x%lx, SystemMemoryMapHob size: 0x%lx, " + "MAX_SOCKET: %d, SAD_RULES: %d\n", + hob, hob_size, sizeof(struct SystemMemoryMapHob), MAX_SOCKET, SAD_RULES); + printk(BIOS_DEBUG, "\tlowMemBase: 0x%x, lowMemSize: 0x%x, highMemBase: 0x%x, " + "highMemSize: 0x%x\n", + hob->lowMemBase, hob->lowMemSize, hob->highMemBase, hob->highMemSize); + printk(BIOS_DEBUG, "\tasilLoMemBase: 0x%x, asilHiMemBase: 0x%x, asilLoMemSize: 0x%x, " + "asilHiMemSize: 0x%x\n", + hob->lowMemBase, hob->lowMemSize, hob->highMemBase, hob->highMemSize); + printk(BIOS_DEBUG, "\tmemSize: 0x%x, memFreq: 0x%x, memMode: 0x%x, volMemMode: 0x%x, " + "DimmType: 0x%x, DramType: 0x%x\n", + hob->memSize, hob->memFreq, hob->memMode, hob->volMemMode, + hob->DimmType, hob->DramType); + printk(BIOS_DEBUG, "\tNumChPerMC: 0x%x, numberEntries: 0x%x, maxIMC: 0x%x, maxCh: 0x%x\n", + hob->NumChPerMC, hob->numberEntries, hob->maxIMC, hob->maxCh); + + printk(BIOS_DEBUG, "\tSystemMemoryMapElement Entries: %d\n", hob->numberEntries); + for (int e = 0; e < hob->numberEntries; ++e) { + const struct SystemMemoryMapElement *mem_element = &hob->Element[e]; + printk(BIOS_DEBUG, "\t\tmemory_map %d BaseAddress: 0x%x, ElementSize: 0x%x, Type: 0x%x\n", + e, mem_element->BaseAddress, + mem_element->ElementSize, mem_element->Type); + } +} + +void soc_display_iio_universal_data_hob(void) +{ + size_t hob_size = 0; + const IIO_UDS *hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_uds_guid, &hob_size); + + assert(hob != NULL && hob_size != 0); + + printk(BIOS_DEBUG, "===================== IIO_UDS HOB DATA =====================\n"); + + printk(BIOS_DEBUG, "\t===================== SYSTEM STATUS =====================\n"); + printk(BIOS_DEBUG, "\tcpuType: 0x%x\n", hob->SystemStatus.cpuType); + printk(BIOS_DEBUG, "\tcpuSubType: 0x%x\n", hob->SystemStatus.cpuSubType); + printk(BIOS_DEBUG, "\tSystemRasType: 0x%x\n", hob->SystemStatus.SystemRasType); + printk(BIOS_DEBUG, "\tnumCpus: 0x%x\n", hob->SystemStatus.numCpus); + for (int x = 0; x < MAX_SOCKET; ++x) { + printk(BIOS_DEBUG, "\tSocket %d FusedCores: 0x%x, ActiveCores: 0x%x, " + "MaxCoreToBusRatio: 0x%x, MinCoreToBusRatio: 0x%x\n", + x, hob->SystemStatus.FusedCores[x], hob->SystemStatus.ActiveCores[x], + hob->SystemStatus.MaxCoreToBusRatio[x], + hob->SystemStatus.MinCoreToBusRatio[x]); + } + printk(BIOS_DEBUG, "\tCurrentCoreToBusRatio: 0x%x\n", + hob->SystemStatus.CurrentCoreToBusRatio); + printk(BIOS_DEBUG, "\tIntelSpeedSelectCapable: 0x%x\n", + hob->SystemStatus.IntelSpeedSelectCapable); + printk(BIOS_DEBUG, "\tIssConfigTdpLevelInfo: 0x%x\n", + hob->SystemStatus.IssConfigTdpLevelInfo); + for (int x = 0; x < TDP_MAX_LEVEL; ++x) { + printk(BIOS_DEBUG, "\t\tTDL Level %d IssConfigTdpTdpInfo: 0x%x, " + "IssConfigTdpPowerInfo: 0x%x, IssConfigTdpCoreCount: 0x%x\n", + x, hob->SystemStatus.IssConfigTdpTdpInfo[x], + hob->SystemStatus.IssConfigTdpPowerInfo[x], + hob->SystemStatus.IssConfigTdpCoreCount[x]); + } + printk(BIOS_DEBUG, "\tsocketPresentBitMap: 0x%x\n", + hob->SystemStatus.socketPresentBitMap); + printk(BIOS_DEBUG, "\ttolmLimit: 0x%x\n", hob->SystemStatus.tolmLimit); + printk(BIOS_DEBUG, "\ttohmLimit: 0x%x\n", hob->SystemStatus.tohmLimit); + printk(BIOS_DEBUG, "\tmmCfgBase: 0x%x\n", hob->SystemStatus.mmCfgBase); + printk(BIOS_DEBUG, "\tnumChPerMC: 0x%x\n", hob->SystemStatus.numChPerMC); + printk(BIOS_DEBUG, "\tmaxCh: 0x%x\n", hob->SystemStatus.maxCh); + printk(BIOS_DEBUG, "\tmaxIMC: 0x%x\n", hob->SystemStatus.maxIMC); + + printk(BIOS_DEBUG, "\t===================== PLATFORM DATA =====================\n"); + printk(BIOS_DEBUG, "\tPlatGlobalIoBase: 0x%x\n", hob->PlatformData.PlatGlobalIoBase); + printk(BIOS_DEBUG, "\tPlatGlobalIoLimit: 0x%x\n", hob->PlatformData.PlatGlobalIoLimit); + printk(BIOS_DEBUG, "\tPlatGlobalMmiolBase: 0x%x\n", + hob->PlatformData.PlatGlobalMmiolBase); + printk(BIOS_DEBUG, "\tPlatGlobalMmiolLimit: 0x%x\n", + hob->PlatformData.PlatGlobalMmiolLimit); + printk(BIOS_DEBUG, "\tPlatGlobalMmiohBase: 0x%llx\n", + hob->PlatformData.PlatGlobalMmiohBase); + printk(BIOS_DEBUG, "\tPlatGlobalMmiohLimit: 0x%llx\n", + hob->PlatformData.PlatGlobalMmiohLimit); + printk(BIOS_DEBUG, "\tMemTsegSize: 0x%x\n", hob->PlatformData.MemTsegSize); + printk(BIOS_DEBUG, "\tMemIedSize: 0x%x\n", hob->PlatformData.MemIedSize); + printk(BIOS_DEBUG, "\tPciExpressBase: 0x%llx\n", hob->PlatformData.PciExpressBase); + printk(BIOS_DEBUG, "\tPciExpressSize: 0x%x\n", hob->PlatformData.PciExpressSize); + printk(BIOS_DEBUG, "\tMemTolm: 0x%x\n", hob->PlatformData.MemTolm); + printk(BIOS_DEBUG, "\tnumofIIO: 0x%x\n", hob->PlatformData.numofIIO); + printk(BIOS_DEBUG, "\tMaxBusNumber: 0x%x\n", hob->PlatformData.MaxBusNumber); + printk(BIOS_DEBUG, "\tIoGranularity: 0x%x\n", hob->PlatformData.IoGranularity); + printk(BIOS_DEBUG, "\tMmiolGranularity: 0x%x\n", hob->PlatformData.MmiolGranularity); + printk(BIOS_DEBUG, "\tMmiohGranularity: hi: 0x%x, lo:0x%x\n", + hob->PlatformData.MmiohGranularity.hi, hob->PlatformData.MmiohGranularity.lo); + + for (int s = 0; s < hob->PlatformData.numofIIO; ++s) { + printk(BIOS_DEBUG, "\t============ Socket %d Info ================\n", s); + printk(BIOS_DEBUG, "\tSocketID: 0x%x\n", + hob->PlatformData.IIO_resource[s].SocketID); + printk(BIOS_DEBUG, "\tBusBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].BusBase); + printk(BIOS_DEBUG, "\tBusLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].BusLimit); + printk(BIOS_DEBUG, "\tPciResourceIoBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceIoBase); + printk(BIOS_DEBUG, "\tPciResourceIoLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceIoLimit); + printk(BIOS_DEBUG, "\tIoApicBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].IoApicBase); + printk(BIOS_DEBUG, "\tIoApicLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].IoApicLimit); + printk(BIOS_DEBUG, "\tPciResourceMem32Base: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceMem32Base); + printk(BIOS_DEBUG, "\tPciResourceMem32Limit: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceMem32Limit); + printk(BIOS_DEBUG, "\tPciResourceMem64Base: 0x%llx\n", + hob->PlatformData.IIO_resource[s].PciResourceMem64Base); + printk(BIOS_DEBUG, "\tPciResourceMem64Limit: 0x%llx\n", + hob->PlatformData.IIO_resource[s].PciResourceMem64Limit); + + printk(BIOS_DEBUG, "\t============ Stack Info ================\n"); + for (int x = 0; x < MAX_IIO_STACK; ++x) { + const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x]; + printk(BIOS_DEBUG, "\t\t========== Stack %d ===============\n", x); + printk(BIOS_DEBUG, "\t\tBusBase: 0x%x\n", ri->BusBase); + printk(BIOS_DEBUG, "\t\tBusLimit: 0x%x\n", ri->BusLimit); + printk(BIOS_DEBUG, "\t\tPciResourceIoBase: 0x%x\n", + ri->PciResourceIoBase); + printk(BIOS_DEBUG, "\t\tPciResourceIoLimit: 0x%x\n", + ri->PciResourceIoLimit); + printk(BIOS_DEBUG, "\t\tIoApicBase: 0x%x\n", ri->IoApicBase); + printk(BIOS_DEBUG, "\t\tIoApicLimit: 0x%x\n", ri->IoApicLimit); + printk(BIOS_DEBUG, "\t\tPciResourceMem32Base: 0x%x\n", + ri->PciResourceMem32Base); + printk(BIOS_DEBUG, "\t\tPciResourceMem32Limit: 0x%x\n", + ri->PciResourceMem32Limit); + printk(BIOS_DEBUG, "\t\tPciResourceMem64Base: 0x%llx\n", + ri->PciResourceMem64Base); + printk(BIOS_DEBUG, "\t\tPciResourceMem64Limit: 0x%llx\n", + ri->PciResourceMem64Limit); + printk(BIOS_DEBUG, "\t\tVtdBarAddress: 0x%x\n", ri->VtdBarAddress); + } + + printk(BIOS_DEBUG, "\t============ PcieInfo ================\n"); + IIO_RESOURCE_INSTANCE iio_resource = + hob->PlatformData.IIO_resource[s]; + for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) { + printk(BIOS_DEBUG, "\t\tPort: %d, Device: 0x%x, Function: 0x%x\n", + p, iio_resource.PcieInfo.PortInfo[p].Device, + iio_resource.PcieInfo.PortInfo[p].Function); + } + } + + printk(BIOS_DEBUG, "\t============ Bus Bases ===============\n"); + for (int socket = 0; socket < MAX_SOCKET; ++socket) { + for (int stack = 0; stack < MAX_IIO_STACK; ++stack) { + printk(BIOS_DEBUG, "socket: %d, stack: %d, busno: 0x%x\n", + socket, stack, + hob->PlatformData.CpuQpiInfo[socket].StackBus[stack]); + } + } +} diff --git a/src/soc/intel/xeon_sp/include/soc/acpi.h b/src/soc/intel/xeon_sp/include/soc/acpi.h new file mode 100644 index 0000000..641a3c5 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/acpi.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef _SOC_ACPI_H_ +#define _SOC_ACPI_H_ + +#include <arch/acpi.h> +#include <soc/nvs.h> + +#define MEM_BLK_COUNT 0x140 +typedef struct { + uint8_t buf[32]; +} MEM_BLK; + +void acpi_create_serialio_ssdt(acpi_header_t *ssdt); +unsigned long acpi_madt_irq_overrides(unsigned long current); +void acpi_init_gnvs(global_nvs_t *gnvs); +unsigned long northbridge_write_acpi_tables(struct device *device, + unsigned long current, struct acpi_rsdp *rsdp); +void uncore_inject_dsdt(void); +void motherboard_fill_fadt(acpi_fadt_t *fadt); + +#endif /* _SOC_ACPI_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/cpu.h b/src/soc/intel/xeon_sp/include/soc/cpu.h new file mode 100644 index 0000000..82b893c --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/cpu.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_CPU_H_ +#define _SOC_CPU_H_ + +#include <device/device.h> + +/* SKXSP CPUID */ +#define CPUID_SKYLAKE_SP_A0_A1 0x506f0 +#define CPUID_SKYLAKE_SP_B0 0x506f1 +#define CPUID_SKYLAKE_SP_4 0x50654 + +/* CPU bus clock is fixed at 100MHz */ +#define CPU_BCLK 100 + +int get_cpu_count(void); +void xeon_sp_init_cpus(struct device *dev); + +#endif diff --git a/src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h b/src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h new file mode 100644 index 0000000..8cb472d --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h @@ -0,0 +1,299 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _GPIO_SOC_DEFS_H_ +#define _GPIO_SOC_DEFS_H_ + +/// +/// Skylake-SP chipset GPIO Groups +/// +#define GPIO_SKL_H_GROUP_GPP_A 0x0100 +#define GPIO_SKL_H_GROUP_GPP_B 0x0101 +#define GPIO_SKL_H_GROUP_GPP_C 0x0102 +#define GPIO_SKL_H_GROUP_GPP_D 0x0103 +#define GPIO_SKL_H_GROUP_GPP_E 0x0104 +#define GPIO_SKL_H_GROUP_GPP_F 0x0105 +#define GPIO_SKL_H_GROUP_GPP_G 0x0106 +#define GPIO_SKL_H_GROUP_GPP_H 0x0107 +#define GPIO_SKL_H_GROUP_GPP_I 0x0108 +#define GPIO_SKL_H_GROUP_GPP_J 0x0109 +#define GPIO_SKL_H_GROUP_GPP_K 0x010A +#define GPIO_SKL_H_GROUP_GPP_L 0x010B +#define GPIO_SKL_H_GROUP_GPD 0x010C + +/// +/// SKL H GPIO pins +/// +#define GPIO_SKL_H_GPP_A0 0x01000000 +#define GPIO_SKL_H_GPP_A1 0x01000001 +#define GPIO_SKL_H_GPP_A2 0x01000002 +#define GPIO_SKL_H_GPP_A3 0x01000003 +#define GPIO_SKL_H_GPP_A4 0x01000004 +#define GPIO_SKL_H_GPP_A5 0x01000005 +#define GPIO_SKL_H_GPP_A6 0x01000006 +#define GPIO_SKL_H_GPP_A7 0x01000007 +#define GPIO_SKL_H_GPP_A8 0x01000008 +#define GPIO_SKL_H_GPP_A9 0x01000009 +#define GPIO_SKL_H_GPP_A10 0x0100000A +#define GPIO_SKL_H_GPP_A11 0x0100000B +#define GPIO_SKL_H_GPP_A12 0x0100000C +#define GPIO_SKL_H_GPP_A13 0x0100000D +#define GPIO_SKL_H_GPP_A14 0x0100000E +#define GPIO_SKL_H_GPP_A15 0x0100000F +#define GPIO_SKL_H_GPP_A16 0x01000010 +#define GPIO_SKL_H_GPP_A17 0x01000011 +#define GPIO_SKL_H_GPP_A18 0x01000012 +#define GPIO_SKL_H_GPP_A19 0x01000013 +#define GPIO_SKL_H_GPP_A20 0x01000014 +#define GPIO_SKL_H_GPP_A21 0x01000015 +#define GPIO_SKL_H_GPP_A22 0x01000016 +#define GPIO_SKL_H_GPP_A23 0x01000017 +#define GPIO_SKL_H_GPP_B0 0x01010000 +#define GPIO_SKL_H_GPP_B1 0x01010001 +#define GPIO_SKL_H_GPP_B2 0x01010002 +#define GPIO_SKL_H_GPP_B3 0x01010003 +#define GPIO_SKL_H_GPP_B4 0x01010004 +#define GPIO_SKL_H_GPP_B5 0x01010005 +#define GPIO_SKL_H_GPP_B6 0x01010006 +#define GPIO_SKL_H_GPP_B7 0x01010007 +#define GPIO_SKL_H_GPP_B8 0x01010008 +#define GPIO_SKL_H_GPP_B9 0x01010009 +#define GPIO_SKL_H_GPP_B10 0x0101000A +#define GPIO_SKL_H_GPP_B11 0x0101000B +#define GPIO_SKL_H_GPP_B12 0x0101000C +#define GPIO_SKL_H_GPP_B13 0x0101000D +#define GPIO_SKL_H_GPP_B14 0x0101000E +#define GPIO_SKL_H_GPP_B15 0x0101000F +#define GPIO_SKL_H_GPP_B16 0x01010010 +#define GPIO_SKL_H_GPP_B17 0x01010011 +#define GPIO_SKL_H_GPP_B18 0x01010012 +#define GPIO_SKL_H_GPP_B19 0x01010013 +#define GPIO_SKL_H_GPP_B20 0x01010014 +#define GPIO_SKL_H_GPP_B21 0x01010015 +#define GPIO_SKL_H_GPP_B22 0x01010016 +#define GPIO_SKL_H_GPP_B23 0x01010017 +#define GPIO_SKL_H_GPP_C0 0x01020000 +#define GPIO_SKL_H_GPP_C1 0x01020001 +#define GPIO_SKL_H_GPP_C2 0x01020002 +#define GPIO_SKL_H_GPP_C3 0x01020003 +#define GPIO_SKL_H_GPP_C4 0x01020004 +#define GPIO_SKL_H_GPP_C5 0x01020005 +#define GPIO_SKL_H_GPP_C6 0x01020006 +#define GPIO_SKL_H_GPP_C7 0x01020007 +#define GPIO_SKL_H_GPP_C8 0x01020008 +#define GPIO_SKL_H_GPP_C9 0x01020009 +#define GPIO_SKL_H_GPP_C10 0x0102000A +#define GPIO_SKL_H_GPP_C11 0x0102000B +#define GPIO_SKL_H_GPP_C12 0x0102000C +#define GPIO_SKL_H_GPP_C13 0x0102000D +#define GPIO_SKL_H_GPP_C14 0x0102000E +#define GPIO_SKL_H_GPP_C15 0x0102000F +#define GPIO_SKL_H_GPP_C16 0x01020010 +#define GPIO_SKL_H_GPP_C17 0x01020011 +#define GPIO_SKL_H_GPP_C18 0x01020012 +#define GPIO_SKL_H_GPP_C19 0x01020013 +#define GPIO_SKL_H_GPP_C20 0x01020014 +#define GPIO_SKL_H_GPP_C21 0x01020015 +#define GPIO_SKL_H_GPP_C22 0x01020016 +#define GPIO_SKL_H_GPP_C23 0x01020017 +#define GPIO_SKL_H_GPP_D0 0x01030000 +#define GPIO_SKL_H_GPP_D1 0x01030001 +#define GPIO_SKL_H_GPP_D2 0x01030002 +#define GPIO_SKL_H_GPP_D3 0x01030003 +#define GPIO_SKL_H_GPP_D4 0x01030004 +#define GPIO_SKL_H_GPP_D5 0x01030005 +#define GPIO_SKL_H_GPP_D6 0x01030006 +#define GPIO_SKL_H_GPP_D7 0x01030007 +#define GPIO_SKL_H_GPP_D8 0x01030008 +#define GPIO_SKL_H_GPP_D9 0x01030009 +#define GPIO_SKL_H_GPP_D10 0x0103000A +#define GPIO_SKL_H_GPP_D11 0x0103000B +#define GPIO_SKL_H_GPP_D12 0x0103000C +#define GPIO_SKL_H_GPP_D13 0x0103000D +#define GPIO_SKL_H_GPP_D14 0x0103000E +#define GPIO_SKL_H_GPP_D15 0x0103000F +#define GPIO_SKL_H_GPP_D16 0x01030010 +#define GPIO_SKL_H_GPP_D17 0x01030011 +#define GPIO_SKL_H_GPP_D18 0x01030012 +#define GPIO_SKL_H_GPP_D19 0x01030013 +#define GPIO_SKL_H_GPP_D20 0x01030014 +#define GPIO_SKL_H_GPP_D21 0x01030015 +#define GPIO_SKL_H_GPP_D22 0x01030016 +#define GPIO_SKL_H_GPP_D23 0x01030017 +#define GPIO_SKL_H_GPP_E0 0x01040000 +#define GPIO_SKL_H_GPP_E1 0x01040001 +#define GPIO_SKL_H_GPP_E2 0x01040002 +#define GPIO_SKL_H_GPP_E3 0x01040003 +#define GPIO_SKL_H_GPP_E4 0x01040004 +#define GPIO_SKL_H_GPP_E5 0x01040005 +#define GPIO_SKL_H_GPP_E6 0x01040006 +#define GPIO_SKL_H_GPP_E7 0x01040007 +#define GPIO_SKL_H_GPP_E8 0x01040008 +#define GPIO_SKL_H_GPP_E9 0x01040009 +#define GPIO_SKL_H_GPP_E10 0x0104000A +#define GPIO_SKL_H_GPP_E11 0x0104000B +#define GPIO_SKL_H_GPP_E12 0x0104000C +#define GPIO_SKL_H_GPP_F0 0x01050000 +#define GPIO_SKL_H_GPP_F1 0x01050001 +#define GPIO_SKL_H_GPP_F2 0x01050002 +#define GPIO_SKL_H_GPP_F3 0x01050003 +#define GPIO_SKL_H_GPP_F4 0x01050004 +#define GPIO_SKL_H_GPP_F5 0x01050005 +#define GPIO_SKL_H_GPP_F6 0x01050006 +#define GPIO_SKL_H_GPP_F7 0x01050007 +#define GPIO_SKL_H_GPP_F8 0x01050008 +#define GPIO_SKL_H_GPP_F9 0x01050009 +#define GPIO_SKL_H_GPP_F10 0x0105000A +#define GPIO_SKL_H_GPP_F11 0x0105000B +#define GPIO_SKL_H_GPP_F12 0x0105000C +#define GPIO_SKL_H_GPP_F13 0x0105000D +#define GPIO_SKL_H_GPP_F14 0x0105000E +#define GPIO_SKL_H_GPP_F15 0x0105000F +#define GPIO_SKL_H_GPP_F16 0x01050010 +#define GPIO_SKL_H_GPP_F17 0x01050011 +#define GPIO_SKL_H_GPP_F18 0x01050012 +#define GPIO_SKL_H_GPP_F19 0x01050013 +#define GPIO_SKL_H_GPP_F20 0x01050014 +#define GPIO_SKL_H_GPP_F21 0x01050015 +#define GPIO_SKL_H_GPP_F22 0x01050016 +#define GPIO_SKL_H_GPP_F23 0x01050017 +#define GPIO_SKL_H_GPP_G0 0x01060000 +#define GPIO_SKL_H_GPP_G1 0x01060001 +#define GPIO_SKL_H_GPP_G2 0x01060002 +#define GPIO_SKL_H_GPP_G3 0x01060003 +#define GPIO_SKL_H_GPP_G4 0x01060004 +#define GPIO_SKL_H_GPP_G5 0x01060005 +#define GPIO_SKL_H_GPP_G6 0x01060006 +#define GPIO_SKL_H_GPP_G7 0x01060007 +#define GPIO_SKL_H_GPP_G8 0x01060008 +#define GPIO_SKL_H_GPP_G9 0x01060009 +#define GPIO_SKL_H_GPP_G10 0x0106000A +#define GPIO_SKL_H_GPP_G11 0x0106000B +#define GPIO_SKL_H_GPP_G12 0x0106000C +#define GPIO_SKL_H_GPP_G13 0x0106000D +#define GPIO_SKL_H_GPP_G14 0x0106000E +#define GPIO_SKL_H_GPP_G15 0x0106000F +#define GPIO_SKL_H_GPP_G16 0x01060010 +#define GPIO_SKL_H_GPP_G17 0x01060011 +#define GPIO_SKL_H_GPP_G18 0x01060012 +#define GPIO_SKL_H_GPP_G19 0x01060013 +#define GPIO_SKL_H_GPP_G20 0x01060014 +#define GPIO_SKL_H_GPP_G21 0x01060015 +#define GPIO_SKL_H_GPP_G22 0x01060016 +#define GPIO_SKL_H_GPP_G23 0x01060017 +#define GPIO_SKL_H_GPP_H0 0x01070000 +#define GPIO_SKL_H_GPP_H1 0x01070001 +#define GPIO_SKL_H_GPP_H2 0x01070002 +#define GPIO_SKL_H_GPP_H3 0x01070003 +#define GPIO_SKL_H_GPP_H4 0x01070004 +#define GPIO_SKL_H_GPP_H5 0x01070005 +#define GPIO_SKL_H_GPP_H6 0x01070006 +#define GPIO_SKL_H_GPP_H7 0x01070007 +#define GPIO_SKL_H_GPP_H8 0x01070008 +#define GPIO_SKL_H_GPP_H9 0x01070009 +#define GPIO_SKL_H_GPP_H10 0x0107000A +#define GPIO_SKL_H_GPP_H11 0x0107000B +#define GPIO_SKL_H_GPP_H12 0x0107000C +#define GPIO_SKL_H_GPP_H13 0x0107000D +#define GPIO_SKL_H_GPP_H14 0x0107000E +#define GPIO_SKL_H_GPP_H15 0x0107000F +#define GPIO_SKL_H_GPP_H16 0x01070010 +#define GPIO_SKL_H_GPP_H17 0x01070011 +#define GPIO_SKL_H_GPP_H18 0x01070012 +#define GPIO_SKL_H_GPP_H19 0x01070013 +#define GPIO_SKL_H_GPP_H20 0x01070014 +#define GPIO_SKL_H_GPP_H21 0x01070015 +#define GPIO_SKL_H_GPP_H22 0x01070016 +#define GPIO_SKL_H_GPP_H23 0x01070017 +#define GPIO_SKL_H_GPP_I0 0x01080000 +#define GPIO_SKL_H_GPP_I1 0x01080001 +#define GPIO_SKL_H_GPP_I2 0x01080002 +#define GPIO_SKL_H_GPP_I3 0x01080003 +#define GPIO_SKL_H_GPP_I4 0x01080004 +#define GPIO_SKL_H_GPP_I5 0x01080005 +#define GPIO_SKL_H_GPP_I6 0x01080006 +#define GPIO_SKL_H_GPP_I7 0x01080007 +#define GPIO_SKL_H_GPP_I8 0x01080008 +#define GPIO_SKL_H_GPP_I9 0x01080009 +#define GPIO_SKL_H_GPP_I10 0x0108000A + +#define GPIO_SKL_H_GPP_J0 0x01090000 +#define GPIO_SKL_H_GPP_J1 0x01090001 +#define GPIO_SKL_H_GPP_J2 0x01090002 +#define GPIO_SKL_H_GPP_J3 0x01090003 +#define GPIO_SKL_H_GPP_J4 0x01090004 +#define GPIO_SKL_H_GPP_J5 0x01090005 +#define GPIO_SKL_H_GPP_J6 0x01090006 +#define GPIO_SKL_H_GPP_J7 0x01090007 +#define GPIO_SKL_H_GPP_J8 0x01090008 +#define GPIO_SKL_H_GPP_J9 0x01090009 +#define GPIO_SKL_H_GPP_J10 0x0109000A +#define GPIO_SKL_H_GPP_J11 0x0109000B +#define GPIO_SKL_H_GPP_J12 0x0109000C +#define GPIO_SKL_H_GPP_J13 0x0109000D +#define GPIO_SKL_H_GPP_J14 0x0109000E +#define GPIO_SKL_H_GPP_J15 0x0109000F +#define GPIO_SKL_H_GPP_J16 0x01090010 +#define GPIO_SKL_H_GPP_J17 0x01090011 +#define GPIO_SKL_H_GPP_J18 0x01090012 +#define GPIO_SKL_H_GPP_J19 0x01090013 +#define GPIO_SKL_H_GPP_J20 0x01090014 +#define GPIO_SKL_H_GPP_J21 0x01090015 +#define GPIO_SKL_H_GPP_J22 0x01090016 +#define GPIO_SKL_H_GPP_J23 0x01090017 +#define GPIO_SKL_H_GPP_K0 0x010A0000 +#define GPIO_SKL_H_GPP_K1 0x010A0001 +#define GPIO_SKL_H_GPP_K2 0x010A0002 +#define GPIO_SKL_H_GPP_K3 0x010A0003 +#define GPIO_SKL_H_GPP_K4 0x010A0004 +#define GPIO_SKL_H_GPP_K5 0x010A0005 +#define GPIO_SKL_H_GPP_K6 0x010A0006 +#define GPIO_SKL_H_GPP_K7 0x010A0007 +#define GPIO_SKL_H_GPP_K8 0x010A0008 +#define GPIO_SKL_H_GPP_K9 0x010A0009 +#define GPIO_SKL_H_GPP_K10 0x010A000A +#define GPIO_SKL_H_GPP_L2 0x010B0002 +#define GPIO_SKL_H_GPP_L3 0x010B0003 +#define GPIO_SKL_H_GPP_L4 0x010B0004 +#define GPIO_SKL_H_GPP_L5 0x010B0005 +#define GPIO_SKL_H_GPP_L6 0x010B0006 +#define GPIO_SKL_H_GPP_L7 0x010B0007 +#define GPIO_SKL_H_GPP_L8 0x010B0008 +#define GPIO_SKL_H_GPP_L9 0x010B0009 +#define GPIO_SKL_H_GPP_L10 0x010B000A +#define GPIO_SKL_H_GPP_L11 0x010B000B +#define GPIO_SKL_H_GPP_L12 0x010B000C +#define GPIO_SKL_H_GPP_L13 0x010B000D +#define GPIO_SKL_H_GPP_L14 0x010B000E +#define GPIO_SKL_H_GPP_L15 0x010B000F +#define GPIO_SKL_H_GPP_L16 0x010B0010 +#define GPIO_SKL_H_GPP_L17 0x010B0011 +#define GPIO_SKL_H_GPP_L18 0x010B0012 +#define GPIO_SKL_H_GPP_L19 0x010B0013 +#define GPIO_SKL_H_GPD0 0x010C0000 +#define GPIO_SKL_H_GPD1 0x010C0001 +#define GPIO_SKL_H_GPD2 0x010C0002 +#define GPIO_SKL_H_GPD3 0x010C0003 +#define GPIO_SKL_H_GPD4 0x010C0004 +#define GPIO_SKL_H_GPD5 0x010C0005 +#define GPIO_SKL_H_GPD6 0x010C0006 +#define GPIO_SKL_H_GPD7 0x010C0007 +#define GPIO_SKL_H_GPD8 0x010C0008 +#define GPIO_SKL_H_GPD9 0x010C0009 +#define GPIO_SKL_H_GPD10 0x010C000A +#define GPIO_SKL_H_GPD11 0x010C000B + +#endif diff --git a/src/soc/intel/xeon_sp/include/soc/iomap.h b/src/soc/intel/xeon_sp/include/soc/iomap.h new file mode 100644 index 0000000..7c825a4 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/iomap.h @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef _SOC_IOMAP_H_ +#define _SOC_IOMAP_H_ + +#define MAP_ENTRY(reg_, is_64_, is_limit_, mask_bits_, desc_) \ + { \ + .reg = reg_, .is_64_bit = is_64_, .is_limit = is_limit_, \ + .mask_bits = mask_bits_, .description = desc_, \ + } + +#define MAP_ENTRY_BASE_64(reg_, desc_) MAP_ENTRY(reg_, 1, 0, 0, desc_) +#define MAP_ENTRY_LIMIT_64(reg_, mask_bits_, desc_) MAP_ENTRY(reg_, 1, 1, mask_bits_, desc_) +#define MAP_ENTRY_BASE_32(reg_, desc_) MAP_ENTRY(reg_, 0, 0, 0, desc_) +#define MAP_ENTRY_LIMIT_32(reg_, mask_bits_, desc_) MAP_ENTRY(reg_, 0, 1, mask_bits_, desc_) + +// SPI BAR0 MMIO base address +#define SPI_BASE_ADDRESS 0xfe010000 +#define SPI_BASE_SIZE 0x1000 + +#define ACPI_BASE_ADDRESS 0x500 + +/* Video RAM */ +#define VGA_BASE_ADDRESS 0xa0000 +#define VGA_BASE_SIZE 0x20000 + +/* High Performance Event Timer */ +#define HPET_BASE_ADDRESS 0xfed00000 + +#define P2SB_BAR CONFIG_PCR_BASE_ADDRESS + +#endif /* _SOC_IOMAP_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/irq.h b/src/soc/intel/xeon_sp/include/soc/irq.h new file mode 100644 index 0000000..06942ae --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/irq.h @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_IRQ_H_ +#define _SOC_IRQ_H_ + +#define PCH_IRQ10 10 +#define PCH_IRQ11 11 + +#endif /* _SOC_IRQ_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/msr.h b/src/soc/intel/xeon_sp/include/soc/msr.h new file mode 100644 index 0000000..6004490 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/msr.h @@ -0,0 +1,113 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_MSR_H_ +#define _SOC_MSR_H_ + +#include <intelblocks/msr.h> + +#define IA32_MCG_CAP 0x179 +#define IA32_MCG_CAP_COUNT_MASK 0xff +#define IA32_MCG_CAP_CTL_P_BIT 8 +#define IA32_MCG_CAP_CTL_P_MASK (1 << IA32_MCG_CAP_CTL_P_BIT) + +#define IA32_MCG_CTL 0x17b + +/* IA32_MISC_ENABLE bits */ +#define FAST_STRINGS_ENABLE_BIT (1 << 0) +#define SPEED_STEP_ENABLE_BIT (1 << 16) +#define MONIOR_ENABLE_BIT (1 << 18) + +#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0 + +/* MSR_PKG_CST_CONFIG_CONTROL bits */ +#define MSR_PKG_CST_CONFIG_CONTROL 0xe2 +#define PKG_CSTATE_LIMIT_SHIFT 0 /* 0:3 */ +/* No package C-state limit. All C-States supported by the processor are available. */ +#define PKG_CSTATE_LIMIT_MASK (0xf << PKG_CSTATE_LIMIT_SHIFT) +#define PKG_CSTATE_NO_LIMIT (0x7 << PKG_CSTATE_LIMIT_SHIFT) +#define IO_MWAIT_REDIRECTION_SHIFT 10 +#define IO_MWAIT_REDIRECTION_ENABLE (1 << IO_MWAIT_REDIRECTION_SHIFT) +#define CFG_LOCK_SHIFT 15 +#define CFG_LOCK_ENABLE (1 << CFG_LOCK_SHIFT) + +/* MSR_PMG_IO_CAPTURE_BASE bits */ +#define MSR_PMG_IO_CAPTURE_BASE 0xe4 +#define LVL_2_BASE_ADDRESS_SHIFT 0 /* 15:0 bits */ +#define LVL_2_BASE_ADDRESS (0x0514 << LVL_2_BASE_ADDRESS_SHIFT) +#define CST_RANGE_SHIFT 16 /* 18:16 bits */ +#define CST_RANGE_MAX_C6 (0x1 << CST_RANGE_SHIFT) + +/* MSR_POWER_CTL bits */ +#define MSR_POWER_CTL 0x1fc +#define BIDIR_PROCHOT_ENABLE_SHIFT 0 +#define BIDIR_PROCHOT_ENABLE (1 << BIDIR_PROCHOT_ENABLE_SHIFT) +#define FAST_BRK_SNP_ENABLE_SHIFT 3 +#define FAST_BRK_SNP_ENABLE (1 << FAST_BRK_SNP_ENABLE_SHIFT) +#define FAST_BRK_INT_ENABLE_SHIFT 4 +#define FAST_BRK_INT_ENABLE (1 << FAST_BRK_INT_ENABLE_SHIFT) +#define PHOLD_CST_PREVENTION_INIT_SHIFT 6 +#define PHOLD_CST_PREVENTION_INIT_VALUE (1 << PHOLD_CST_PREVENTION_INIT_SHIFT) +#define ENERGY_PERF_BIAS_ACCESS_ENABLE_SHIFT 18 +#define ENERGY_PERF_BIAS_ACCESS_ENABLE (1 << ENERGY_PERF_BIAS_ACCESS_ENABLE_SHIFT) +#define PROCHOT_OUTPUT_DISABLE_SHIFT 21 +#define PROCHOT_OUTPUT_DISABLE (1 << PROCHOT_OUTPUT_DISABLE_SHIFT) +#define PWR_PERF_TUNING_DYN_SWITCHING_SHIFT 24 +#define PWR_PERF_TUNING_DYN_SWITCHING_ENABLE (1 << PWR_PERF_TUNING_DYN_SWITCHING_SHIFT) +#define PROCHOT_LOCK_SHIFT 27 +#define PROCHOT_LOCK_ENABLE (1 << PROCHOT_LOCK_SHIFT) +#define LTR_IIO_DISABLE_SHIFT 29 +#define LTR_IIO_DISABLE (1 << LTR_IIO_DISABLE_SHIFT) + +/* MSR_IA32_PERF_CTRL (0x199) bits */ +#define MSR_IA32_PERF_CTRL 0x199 +#define PSTATE_REQ_SHIFT 8 /* 8:14 bits */ +#define PSTATE_REQ_MASK (0x7f << PSTATE_REQ_SHIFT) +#define PSTATE_REQ_RATIO (0xa << PSTATE_REQ_SHIFT) + +/* MSR_MISC_PWR_MGMT bits */ +#define MSR_MISC_PWR_MGMT 0x1aa +#define HWP_ENUM_SHIFT 6 +#define HWP_ENUM_ENABLE (1 << HWP_ENUM_SHIFT) +#define HWP_EPP_SHIFT 12 +#define HWP_EPP_ENUM_ENABLE (1 << HWP_EPP_SHIFT) +#define LOCK_MISC_PWR_MGMT_MSR_SHIFT 13 +#define LOCK_MISC_PWR_MGMT_MSR (1 << LOCK_MISC_PWR_MGMT_MSR_SHIFT) +#define LOCK_THERM_INT_SHIFT 22 +#define LOCK_THERM_INT (1 << LOCK_THERM_INT_SHIFT) + +/* MSR_TURBO_RATIO_LIMIT bits */ +#define MSR_TURBO_RATIO_LIMIT 0x1ad + +/* MSR_TURBO_RATIO_LIMIT_CORES (0x1ae) */ +#define MSR_TURBO_RATIO_LIMIT_CORES 0x1ae + +/* MSR_VR_CURRENT_CONFIG bits */ +#define MSR_VR_CURRENT_CONFIG 0x601 +#define CURRENT_LIMIT_LOCK_SHIFT 31 +#define CURRENT_LIMIT_LOCK (0x1 << CURRENT_LIMIT_LOCK_SHIFT) + +/* MSR_TURBO_ACTIVATION_RATIO bits */ +#define MSR_TURBO_ACTIVATION_RATIO 0x64c +#define MAX_NON_TURBO_RATIO_SHIFT 0 +#define MAX_NON_TURBO_RATIO (0xff << MAX_NON_TURBO_RATIO_SHIFT) + +/* MSR_ENERGY_PERF_BIAS_CONFIG bits */ +#define MSR_ENERGY_PERF_BIAS_CONFIG 0xa01 +#define EPB_ENERGY_POLICY_SHIFT 3 +#define EPB_ENERGY_POLICY_MASK (0xf << EPB_ENERGY_POLICY_SHIFT) + +#endif /* _SOC_MSR_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/nvs.h b/src/soc/intel/xeon_sp/include/soc/nvs.h new file mode 100644 index 0000000..00dded3 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/nvs.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 - 2009 coresystems GmbH + * Copyright (C) 2011 Google Inc + * Copyright (C) 2014 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _SOC_NVS_H_ +#define _SOC_NVS_H_ + +#include <stdint.h> + +/* TODO - this requires xeon sp, server board support */ +/* NOTE: We do not use intelblocks/nvs.h since it includes + mostly client specific attributes */ +typedef struct global_nvs_t { + uint8_t pcnt; /* 0x00 - Processor Count */ + uint32_t cbmc; /* 0x01 - coreboot memconsole */ + uint8_t rsvd3[251]; +} __packed global_nvs_t; + +#endif /* _SOC_NVS_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/include/soc/pci_devs.h new file mode 100644 index 0000000..db78c82 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/pci_devs.h @@ -0,0 +1,186 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_PCI_DEVS_H_ +#define _SOC_PCI_DEVS_H_ + +#include <device/pci_def.h> +#include <hob_iiouds.h> + +#define dump_csr(fmt, dev, reg) \ + printk(BIOS_SPEW, "%s%x:%x:%x reg: %s (0x%x), data: 0x%x\n", \ + fmt, ((uint32_t)dev >> 20) & 0xfff, ((uint32_t)dev >> 15) & 0x1f, \ + ((uint32_t)dev >> 12) & 0x07, \ + #reg, reg, pci_mmio_read_config32(dev, reg)) + +#define dump_csr64(fmt, dev, reg) \ + printk(BIOS_SPEW, "%s%x:%x:%x reg: %s (0x%x), data: 0x%x%x\n", \ + fmt, ((uint32_t)dev >> 20) & 0xfff, ((uint32_t)dev >> 15) & 0x1f, \ + ((uint32_t)dev >> 12) & 0x07, #reg, reg, \ + pci_mmio_read_config32(dev, reg+4), pci_mmio_read_config32(dev, reg)) + +#define _SA_DEVFN(slot) PCI_DEVFN(SA_DEV_SLOT_ ## slot, 0) +#define _PCH_DEVFN(slot, func) PCI_DEVFN(PCH_DEV_SLOT_ ## slot, func) + +#if !defined(__SIMPLE_DEVICE__) +#include <device/device.h> +#define _SA_DEV(slot) pcidev_path_on_root_debug(_SA_DEVFN(slot), __func__) +#define _PCH_DEV(slot, func) pcidev_path_on_root_debug(_PCH_DEVFN(slot, func), __func__) +#else +#include <arch/io.h> +#define _SA_DEV(slot) PCI_DEV(0, SA_DEV_SLOT_ ## slot, 0) +#define _PCH_DEV(slot, func) PCI_DEV(0, PCH_DEV_SLOT_ ## slot, func) +#endif + +#define MMAP_VTD_CFG_REG_DEVID 0x2024 +#define VTD_DEV 5 +#define VTD_FUNC 0 + +#define VTD_TOLM_CSR 0xd0 +#define VTD_TSEG_BASE_CSR 0xa8 +#define VTD_TSEG_LIMIT_CSR 0xac +#define VTD_EXT_CAP_LOW 0x10 +#define VTD_MMCFG_BASE_CSR 0x90 +#define VTD_MMCFG_LIMIT_CSR 0x98 +#define VTD_TOHM_CSR 0xd4 +#define VTD_MMIOL_CSR 0xdc +#define VTD_ME_BASE_CSR 0xf0 +#define VTD_ME_LIMIT_CSR 0xf8 +#define VTD_VERSION 0x00 +#define VTD_CAP 0x08 +#define VTD_CAP_LOW 0x08 +#define VTD_CAP_HIGH 0x0C +#define VTD_EXT_CAP_HIGH 0x14 + +#define SAD_ALL_DEV 29 +#define SAD_ALL_FUNC 0 +#define SAD_ALL_PAM0123_CSR 0x40 +#define SAD_ALL_PAM456_CSR 0x44 + +#define PCU_IIO_STACK 1 +#define PCU_DEV 30 +#define PCU_CR1_FUN 1 + +#define PCU_CR0_FUN 0 +#define PCU_CR0_PLATFORM_INFO 0xa8 +#define PCU_CR0_P_STATE_LIMITS 0xd8 +#define P_STATE_LIMITS_LOCK_SHIFT 31 +#define P_STATE_LIMITS_LOCK (1 << P_STATE_LIMITS_LOCK_SHIFT) +#define PCU_CR0_TEMPERATURE_TARGET 0xe4 +#define PCU_CR0_PACKAGE_RAPL_LIMIT 0xe8 +#define PCU_CR0_CURRENT_CONFIG 0xf8 +#define MAX_NON_TURBO_LIM_RATIO_SHIFT 8 /* 8:15 */ +#define MAX_NON_TURBO_LIM_RATIO_MASK (0xff << MAX_NON_TURBO_LIM_RATIO_SHIFT) + +#define PCU_CR1_BIOS_RESET_CPL_REG 0x94 +#define RST_CPL1_MASK ((uint32_t)1 << 1) +#define RST_CPL2_MASK ((uint32_t)1 << 2) +#define RST_CPL3_MASK ((uint32_t)1 << 3) +#define RST_CPL4_MASK ((uint32_t)1 << 4) +#define PCODE_INIT_DONE1_MASK ((uint32_t)1 << 9) +#define PCODE_INIT_DONE2_MASK ((uint32_t)1 << 10) +#define PCODE_INIT_DONE3_MASK ((uint32_t)1 << 11) +#define PCODE_INIT_DONE4_MASK ((uint32_t)1 << 12) + +#define PCU_CR1_BIOS_MB_DATA_REG 0x8c + +#define PCU_CR1_BIOS_MB_INTERFACE_REG 0x90 +#define BIOS_MB_RUN_BUSY_MASK ((uint32_t)1 << 31) +#define BIOS_MB_CMD_MASK ((uint32_t)0xff) +#define BIOS_CMD_READ_PCU_MISC_CFG 0x5 +#define BIOS_CMD_WRITE_PCU_MISC_CFG 0x6 +#define BIOS_ERR_INVALID_CMD 0x01 + +#define PCU_CR1_DESIRED_CORES_CFG2_REG 0xa0 +#define PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK ((uint32_t)1 << 31) + +#define PCU_CR1_C2C3TT_REG 0xdc +#define PCU_CR1_PCIE_ILTR_OVRD 0xfc +#define PCU_CR1_SAPMCTL 0xb0 +#define SAPMCTL_LOCK_SHIFT 31 +#define SAPMCTL_LOCK_MASK (1 << SAPMCTL_LOCK_SHIFT) +#define PCU_CR1_MC_BIOS_REQ 0x98 + +#define PCU_CR2_FUN 2 +#define PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK 0x8c +#define PCIE_IN_PKGCSTATE_L1_MASK 0xFFFFFF /* 23:0 bits */ +#define PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK2 0x90 +#define KTI_IN_PKGCSTATE_L1_MASK 0x7 /* 2:0 bits */ +#define PCU_CR2_DYNAMIC_PERF_POWER_CTL 0xdc +#define UNCORE_PLIMIT_OVERRIDE_BIT 20 +#define UNOCRE_PLIMIT_OVERRIDE_SHIFT (1 << UNCORE_PLIMIT_OVERRIDE_BIT) +#define PCU_CR2_PROCHOT_RESPONSE_RATIO_REG 0xb0 +#define PROCHOT_RATIO 0xa /* bits 0:7 */ + +#define UBOX_DECS_BUS 0 +#define UBOX_DECS_DEV 8 +#define UBOX_DECS_FUNC 2 +#define UBOX_DECS_CPUBUSNO_CSR 0xcc + +#define CHA_UTIL_ALL_DEV 29 +#define CHA_UTIL_ALL_FUNC 1 +#define CHA_UTIL_ALL_MMCFG_CSR 0xc0 + +#define CBDMA_DEV_NUM 0x04 +#define IIO_CBDMA_MMIO_SIZE 0x10000 //64kB for one CBDMA function +#define IIO_CBDMA_MMIO_ALIGNMENT 14 //2^14 - 16kB + +#define VMD_DEV_NUM 5 +#define VMD_FUNC_NUM 5 + +#define APIC_DEV_NUM 5 +#define APIC_FUNC_NUM 0 + +#define PCH_IOAPIC_BUS_NUMBER 0xF0 +#define PCH_IOAPIC_DEV_NUM 0x1F +#define PCH_IOAPIC_FUNC_NUM 0x00 + +// ================================== IOAPIC Definitions for DMAR/ACPI ==================== +#define PCH_IOAPIC_ID 0x08 +#define PC00_IOAPIC_ID 0x09 +#define PC01_IOAPIC_ID 0x0A +#define PC02_IOAPIC_ID 0x0B +#define PC03_IOAPIC_ID 0x0C +#define PC04_IOAPIC_ID 0x0D +#define PC05_IOAPIC_ID 0x0E +#define PC06_IOAPIC_ID 0x0F +#define PC07_IOAPIC_ID 0x10 +#define PC08_IOAPIC_ID 0x11 +#define PC09_IOAPIC_ID 0x12 +#define PC10_IOAPIC_ID 0x13 +#define PC11_IOAPIC_ID 0x14 + +/* PCH Device info */ + +#define XHCI_BUS_NUMBER 0x0 +#define PCH_DEV_SLOT_XHCI 0x14 +#define XHCI_FUNC_NUM 0x0 + +#define HPET_BUS_NUM 0x0 +#define HPET_DEV_NUM PCH_DEV_SLOT_LPC +#define HPET0_FUNC_NUM 0x00 + +#define PCH_DEV_SLOT_LPC 0x1f +#define PCH_DEVFN_LPC _PCH_DEVFN(LPC, 0) +#define PCH_DEVFN_P2SB _PCH_DEVFN(LPC, 1) +#define PCH_DEVFN_PMC _PCH_DEVFN(LPC, 2) +#define PCH_DEVFN_SPI _PCH_DEVFN(LPC, 5) +#define PCH_DEV_LPC _PCH_DEV(LPC, 0) +#define PCH_DEV_P2SB _PCH_DEV(LPC, 1) +#define PCH_DEV_PMC _PCH_DEV(LPC, 2) +#define PCH_DEV_SPI _PCH_DEV(LPC, 5) + +#endif /* _SOC_PCI_DEVS_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/pcr_ids.h b/src/soc/intel/xeon_sp/include/soc/pcr_ids.h new file mode 100644 index 0000000..c679692 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/pcr_ids.h @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _PCR_IDS_H_ +#define _PCR_IDS_H_ + +#define PID_ITSS 0xC4 +#define PID_RTC 0xC3 + +#endif /* _PCR_IDS_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/pm.h b/src/soc/intel/xeon_sp/include/soc/pm.h new file mode 100644 index 0000000..ea111cde --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/pm.h @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_PM_H_ +#define _SOC_PM_H_ + +#include <soc/iomap.h> +#include <soc/pmc.h> + +#define PM1_CNT 0x04 +#define PM1_STS 0x00 +#define PM1_TMR 0x08 +#define PM2_CNT 0x50 + +#define GPE0_REG_MAX 4 +#define GPE0_STS(x) (0x80 + (x * 4)) + +#endif diff --git a/src/soc/intel/xeon_sp/include/soc/pmc.h b/src/soc/intel/xeon_sp/include/soc/pmc.h new file mode 100644 index 0000000..c080749 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/pmc.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_PMC_H_ +#define _SOC_PMC_H_ + +/* PCI Configuration Space (D31:F2): PMC */ +#define PMC_ACPI_CNT 0x44 + +#define SCI_IRQ_SEL (7 << 0) +#define SCIS_IRQ9 0 +#define SCIS_IRQ10 1 +#define SCIS_IRQ11 2 +#define SCIS_IRQ20 4 +#define SCIS_IRQ21 5 +#define SCIS_IRQ22 6 +#define SCIS_IRQ23 7 + +#define SCI_IRQ_ADJUST 0 + +#endif diff --git a/src/soc/intel/xeon_sp/include/soc/ramstage.h b/src/soc/intel/xeon_sp/include/soc/ramstage.h new file mode 100644 index 0000000..c012dd6 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/ramstage.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_RAMSTAGE_H_ +#define _SOC_RAMSTAGE_H_ + +#include <device/device.h> +#include <fsp/api.h> +#include <fsp/util.h> +#include <memory_info.h> + +void xeon_sp_init_cpus(struct device *dev); +void mainboard_silicon_init_params(FSPS_UPD *params); + +extern struct pci_operations soc_pci_ops; + +#endif diff --git a/src/soc/intel/xeon_sp/include/soc/romstage.h b/src/soc/intel/xeon_sp/include/soc/romstage.h new file mode 100644 index 0000000..623306f --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/romstage.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef _SOC_ROMSTAGE_H_ +#define _SOC_ROMSTAGE_H_ + +#include <fsp/api.h> + +/* These functions are weak and can be overridden by a mainboard functions. */ +void mainboard_memory_init_params(FSPM_UPD * mupd); + +#endif /* _SOC_ROMSTAGE_H_ */ diff --git a/src/soc/intel/xeon_sp/include/soc/soc_util.h b/src/soc/intel/xeon_sp/include/soc/soc_util.h new file mode 100644 index 0000000..8b5e1a2 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/soc_util.h @@ -0,0 +1,80 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef _SOC_UTIL_H_ +#define _SOC_UTIL_H_ + +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <arch/acpi.h> + +#define LOG_MEM_RESOURCE(type, dev, index, base_kb, size_kb) \ + printk(BIOS_SPEW, "%s:%d res: %s, dev: %s, index: 0x%x, base: 0x%llx, " \ + "end: 0x%llx, size_kb: 0x%llx\n", \ + __func__, __LINE__, type, dev_path(dev), index, (base_kb << 10), \ + (base_kb << 10) + (size_kb << 10) - 1, size_kb) + +#define LOG_IO_RESOURCE(type, dev, index, base, size) \ + printk(BIOS_SPEW, "%s:%d res: %s, dev: %s, index: 0x%x, base: 0x%llx, " \ + "end: 0x%llx, size: 0x%llx\n", \ + __func__, __LINE__, type, dev_path(dev), index, base, base + size - 1, size) + +#define DEV_FUNC_ENTER(dev) \ + printk(BIOS_SPEW, "%s:%s:%d: ENTER (dev: %s)\n", \ + __FILE__, __func__, __LINE__, dev_path(dev)) + +#define DEV_FUNC_EXIT(dev) \ + printk(BIOS_SPEW, "%s:%s:%d: EXIT (dev: %s)\n", __FILE__, \ + __func__, __LINE__, dev_path(dev)) + +#define FUNC_ENTER() \ + printk(BIOS_SPEW, "%s:%s:%d: ENTER\n", __FILE__, __func__, __LINE__) + +#define FUNC_EXIT() \ + printk(BIOS_SPEW, "%s:%s:%d: EXIT\n", __FILE__, __func__, __LINE__) + +struct iiostack_resource { + uint8_t no_of_stacks; + STACK_RES res[CONFIG_MAX_SOCKET * MAX_IIO_STACK]; +}; + +uintptr_t get_tolm(uint32_t bus); +void get_tseg_base_lim(uint32_t bus, uint32_t *base, uint32_t *limit); +uintptr_t get_cha_mmcfg_base(uint32_t bus); +uint32_t top_of_32bit_ram(void); // Top of 32bit usable memory + +uint32_t pci_read_mmio_reg(int bus, uint32_t dev, uint32_t func, int offset); + +void get_stack_busnos(uint32_t *bus); +void get_cpubusnos(uint32_t *bus0, uint32_t *bus1, uint32_t *bus2, uint32_t *bus3); +uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack); +void get_iiostack_info(struct iiostack_resource *info); + +int get_threads_per_package(void); +int get_platform_thread_count(void); +void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits); + +unsigned int get_srat_memory_entries(acpi_srat_mem_t *srat_mem); +void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, + uint32_t thread_bits, uint8_t *package, uint8_t *core, uint8_t *thread); + +void unlock_pam_regions(void); +void xeonsp_init_cpu_config(void); +void set_bios_init_completion(void); +void config_reset_cpl3_csrs(void); + +#endif /* _SOC_UTIL_H_ */ diff --git a/src/soc/intel/xeon_sp/lpc.c b/src/soc/intel/xeon_sp/lpc.c new file mode 100644 index 0000000..b0ba681 --- /dev/null +++ b/src/soc/intel/xeon_sp/lpc.c @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <console/console.h> +#include <arch/ioapic.h> +#include <intelblocks/lpc_lib.h> +#include <soc/soc_util.h> +#include <soc/iomap.h> + +static const struct lpc_mmio_range xeon_lpc_fixed_mmio_ranges[] = { + { 0, 0 } +}; + +const struct lpc_mmio_range *soc_get_fixed_mmio_ranges(void) +{ + return xeon_lpc_fixed_mmio_ranges; +} + +void lpc_soc_init(struct device *dev) +{ + printk(BIOS_SPEW, "pch: lpc_init\n"); + + /* FSP configures IOAPIC and PCHInterrupt Config */ + printk(BIOS_SPEW, "IOAPICID 0x%x, 0x%x\n", + io_apic_read((void *)IO_APIC_ADDR, 0x00), + ((io_apic_read((void *)IO_APIC_ADDR, 0x00) & 0x0f000000) >> 24)); +} + +void pch_lpc_soc_fill_io_resources(struct device *dev) +{ +} diff --git a/src/soc/intel/xeon_sp/reset.c b/src/soc/intel/xeon_sp/reset.c new file mode 100644 index 0000000..80a452b --- /dev/null +++ b/src/soc/intel/xeon_sp/reset.c @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <console/console.h> +#include <fsp/util.h> + +void chipset_handle_reset(uint32_t status) +{ + die("Reset not implemented!\n"); +} diff --git a/src/soc/intel/xeon_sp/romstage.c b/src/soc/intel/xeon_sp/romstage.c new file mode 100644 index 0000000..dc94dc6 --- /dev/null +++ b/src/soc/intel/xeon_sp/romstage.c @@ -0,0 +1,83 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/romstage.h> +#include <cbmem.h> +#include <intelblocks/rtc.h> +#include <console/console.h> +#include <cpu/x86/mtrr.h> +#include <soc/romstage.h> +#include <soc/soc_util.h> +#include "chip.h" + +asmlinkage void car_stage_entry(void) +{ + struct postcar_frame pcf; + uintptr_t top_of_ram; + + printk(BIOS_DEBUG, "FSP TempRamInit was successful...\n"); + + console_init(); + rtc_init(); + + fsp_memory_init(false); + printk(BIOS_DEBUG, "coreboot fsp_memory_init finished...\n"); + + unlock_pam_regions(); + + if (postcar_frame_init(&pcf, 1 * KiB)) + die("Unable to initialize postcar frame.\n"); + + /* + * We need to make sure ramstage will be run cached. At this point exact + * location of ramstage in cbmem is not known. Instruct postcar to cache + * 16 megs under cbmem top which is a safe bet to cover ramstage. + */ + top_of_ram = (uintptr_t)cbmem_top(); + printk(BIOS_DEBUG, "top_of_ram: 0x%lx\n", top_of_ram); + postcar_frame_add_mtrr(&pcf, top_of_ram - 16 * MiB, 16 * MiB, + MTRR_TYPE_WRBACK); + + /* Cache the memory-mapped boot media. */ + postcar_frame_add_romcache(&pcf, MTRR_TYPE_WRPROT); + + run_postcar_phase(&pcf); +} + +static void soc_memory_init_params(FSP_M_CONFIG *m_cfg) +{ +} + +void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) +{ + const config_t *config = config_of_soc(); + FSP_M_CONFIG *m_cfg = &mupd->FspmConfig; + + mupd->FspmUpdVersion = FSP_UPD_VERSION; + + // ErrorLevel - 0 (disable) to 8 (verbose) + m_cfg->PcdFspMrcDebugPrintErrorLevel = 0; + m_cfg->PcdFspKtiDebugPrintErrorLevel = 0; + + soc_memory_init_params(m_cfg); + + mainboard_memory_init_params(mupd); + + m_cfg->VTdConfig.VTdSupport = config->vtd_support; + m_cfg->VTdConfig.CoherencySupport = config->coherency_support; + m_cfg->VTdConfig.ATS = config->ats_support; +} diff --git a/src/soc/intel/xeon_sp/soc_util.c b/src/soc/intel/xeon_sp/soc_util.c new file mode 100644 index 0000000..6310bac --- /dev/null +++ b/src/soc/intel/xeon_sp/soc_util.c @@ -0,0 +1,577 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <assert.h> +#include <commonlib/sort.h> +#include <console/console.h> +#include <cpu/cpu.h> +#include <cpu/x86/msr.h> +#include <delay.h> +#include <device/pci.h> +#include <hob_iiouds.h> +#include <intelblocks/cpulib.h> +#include <intelblocks/pcr.h> +#include <soc/iomap.h> +#include <soc/cpu.h> +#include <soc/msr.h> +#include <soc/pci_devs.h> +#include <soc/pcr_ids.h> +#include <soc/soc_util.h> +#include <stdlib.h> +#include <timer.h> + +/* + * Get TOLM CSR B0:D5:F0:Offset_d0h + */ +uintptr_t get_tolm(uint32_t bus) +{ + uint32_t w = pci_io_read_config32(PCI_DEV(bus, VTD_DEV, VTD_FUNC), + VTD_TOLM_CSR); + uintptr_t addr = w & 0xfc000000; + printk(BIOS_DEBUG, "VTD_TOLM_CSR 0x%x, addr: 0x%lx\n", w, addr); + return addr; +} + +void get_tseg_base_lim(uint32_t bus, uint32_t *base, uint32_t *limit) +{ + uint32_t w1 = pci_io_read_config32(PCI_DEV(bus, VTD_DEV, VTD_FUNC), + VTD_TSEG_BASE_CSR); + uint32_t wh = pci_io_read_config32(PCI_DEV(bus, VTD_DEV, VTD_FUNC), + VTD_TSEG_LIMIT_CSR); + *base = w1 & 0xfff00000; + *limit = wh & 0xfff00000; +} + +/* + * Get MMCFG CSR B1:D29:F1:Offset_C0h + */ +uintptr_t get_cha_mmcfg_base(uint32_t bus) +{ + uint32_t wl = pci_io_read_config32(PCI_DEV(bus, CHA_UTIL_ALL_DEV, + CHA_UTIL_ALL_FUNC), CHA_UTIL_ALL_MMCFG_CSR); + uint32_t wh = pci_io_read_config32(PCI_DEV(bus, CHA_UTIL_ALL_DEV, + CHA_UTIL_ALL_FUNC), CHA_UTIL_ALL_MMCFG_CSR + 4); + uintptr_t addr = ((((wh & 0x3fff) << 6) | ((wl >> 26) & 0x3f)) << 26); + printk(BIOS_DEBUG, "CHA_UTIL_ALL_MMCFG_CSR wl: 0x%x, wh: 0x%x, addr: 0x%lx\n", + wl, wh, addr); + return addr; +} + +/* + * Get Socket 0 CPUBUSNO(0), CPUBUSNO(1) PCI bus numbers UBOX (B0:D8:F2:Offset_CCh) + * TODO: D0h + */ +void get_cpubusnos(uint32_t *bus0, uint32_t *bus1, uint32_t *bus2, uint32_t *bus3) +{ + uint32_t bus = pci_io_read_config32(PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV, + UBOX_DECS_FUNC), UBOX_DECS_CPUBUSNO_CSR); + if (bus0) + *bus0 = (bus & 0xff); + if (bus1) + *bus1 = (bus >> 8) & 0xff; + if (bus2) + *bus2 = (bus >> 16) & 0xff; + if (bus3) + *bus3 = (bus >> 24) & 0xff; +} + +uint32_t top_of_32bit_ram(void) +{ + uintptr_t mmcfg, tolm; + uint32_t bus0 = 0, bus1 = 0; + uint32_t base = 0, limit = 0; + + get_cpubusnos(&bus0, &bus1, NULL, NULL); + + mmcfg = get_cha_mmcfg_base(bus1); + tolm = get_tolm(bus0); + printk(BIOS_DEBUG, "bus0: 0x%x, bus1: 0x%x, mmcfg: 0x%lx, tolm: 0x%lx\n", + bus0, bus1, mmcfg, tolm); + get_tseg_base_lim(bus0, &base, &limit); + printk(BIOS_DEBUG, "tseg base: 0x%x, limit: 0x%x\n", base, limit); + + /* We will use TSEG base as the top of DRAM */ + return base; +} + +/* + * +-------------------------+ TOLM + * | System Management Mode | + * | code and data | + * | (TSEG) | + * +-------------------------+ SMM base (aligned) + * | | + * | Chipset Reserved Memory | + * | | + * +-------------------------+ top_of_ram (aligned) + * | | + * | CBMEM Root | + * | | + * +-------------------------+ + * | | + * | FSP Reserved Memory | + * | | + * +-------------------------+ + * | | + * | Various CBMEM Entries | + * | | + * +-------------------------+ top_of_stack (8 byte aligned) + * | | + * | stack (CBMEM Entry) | + * | | + * +-------------------------+ + */ + +uint32_t pci_read_mmio_reg(int bus, uint32_t dev, uint32_t func, int offset) +{ + return pci_mmio_read_config32(PCI_DEV(bus, dev, func), offset); +} + +uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack) +{ + size_t hob_size; + const IIO_UDS *hob; + const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + + assert(socket < MAX_SOCKET && stack < MAX_IIO_STACK); + + hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + return hob->PlatformData.CpuQpiInfo[socket].StackBus[stack]; +} + +/* bus needs to be of size 6 (MAX_IIO_STACK) */ +void get_stack_busnos(uint32_t *bus) +{ + uint32_t reg1, reg2; + + reg1 = pci_mmio_read_config32(PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV, UBOX_DECS_FUNC), + 0xcc); + reg2 = pci_mmio_read_config32(PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV, UBOX_DECS_FUNC), + 0xd0); + + for (int i = 0; i < 4; ++i) + bus[i] = ((reg1 >> (i * 8)) & 0xff); + for (int i = 0; i < 2; ++i) + bus[4+i] = ((reg2 >> (i * 8)) & 0xff); +} + +void unlock_pam_regions(void) +{ + uint32_t bus1 = 0; + uint32_t pam0123_unlock_dram = 0x33333330; + uint32_t pam456_unlock_dram = 0x00333333; + + get_cpubusnos(NULL, &bus1, NULL, NULL); + pci_io_write_config32(PCI_DEV(bus1, SAD_ALL_DEV, SAD_ALL_FUNC), + SAD_ALL_PAM0123_CSR, pam0123_unlock_dram); + pci_io_write_config32(PCI_DEV(bus1, SAD_ALL_DEV, SAD_ALL_FUNC), + SAD_ALL_PAM456_CSR, pam456_unlock_dram); + + uint32_t reg1 = pci_io_read_config32(PCI_DEV(bus1, SAD_ALL_DEV, + SAD_ALL_FUNC), SAD_ALL_PAM0123_CSR); + uint32_t reg2 = pci_io_read_config32(PCI_DEV(bus1, SAD_ALL_DEV, + SAD_ALL_FUNC), SAD_ALL_PAM456_CSR); + printk(BIOS_DEBUG, "%s:%s pam0123_csr: 0x%x, pam456_csr: 0x%x\n", + __FILE__, __func__, reg1, reg2); +} + +/* return 1 if command timed out else 0 */ +static uint32_t wait_for_bios_cmd_cpl(pci_devfn_t dev, uint32_t reg, uint32_t mask, + uint32_t target) +{ + uint32_t max_delay = 5000; /* 5 seconds max */ + uint32_t step_delay = 50; /* 50 us */ + struct stopwatch sw; + + stopwatch_init_msecs_expire(&sw, max_delay); + while ((pci_mmio_read_config32(dev, reg) & mask) != target) { + udelay(step_delay); + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "%s timed out for dev: 0x%x, reg: 0x%x, " + "mask: 0x%x, target: 0x%x\n", __func__, dev, reg, mask, target); + return 1; /* timedout */ + } + } + return 0; /* successful */ +} + +/* return 1 if command timed out else 0 */ +static int set_bios_reset_cpl_for_package(uint32_t socket, uint32_t rst_cpl_mask, + uint32_t pcode_init_mask, uint32_t val) +{ + uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK); + pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN); + + uint32_t reg = pci_mmio_read_config32(dev, PCU_CR1_BIOS_RESET_CPL_REG); + reg &= (uint32_t) ~rst_cpl_mask; + reg |= rst_cpl_mask; + reg |= val; + + /* update BIOS RESET completion bit */ + pci_mmio_write_config32(dev, PCU_CR1_BIOS_RESET_CPL_REG, reg); + + /* wait for PCU ack */ + return wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_RESET_CPL_REG, pcode_init_mask, + pcode_init_mask); +} + +/* return 1 if command timed out else 0 */ +static uint32_t write_bios_mailbox_cmd(pci_devfn_t dev, uint32_t command, uint32_t data) +{ + /* verify bios is not in busy state */ + if (wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_MB_INTERFACE_REG, BIOS_MB_RUN_BUSY_MASK, 0)) + return 1; /* timed out */ + + /* write data to data register */ + printk(BIOS_SPEW, "%s - pci_mmio_write_config32 reg: 0x%x, data: 0x%x\n", __func__, + PCU_CR1_BIOS_MB_DATA_REG, data); + pci_mmio_write_config32(dev, PCU_CR1_BIOS_MB_DATA_REG, data); + + /* write the command */ + printk(BIOS_SPEW, "%s - pci_mmio_write_config32 reg: 0x%x, data: 0x%x\n", __func__, + PCU_CR1_BIOS_MB_INTERFACE_REG, + (uint32_t) (command | BIOS_MB_RUN_BUSY_MASK)); + pci_mmio_write_config32(dev, PCU_CR1_BIOS_MB_INTERFACE_REG, + (uint32_t) (command | BIOS_MB_RUN_BUSY_MASK)); + + /* wait for completion or time out*/ + return wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_MB_INTERFACE_REG, + BIOS_MB_RUN_BUSY_MASK, 0); +} + +void config_reset_cpl3_csrs(void) +{ + uint32_t data, plat_info, max_min_turbo_limit_ratio; + + for (uint32_t socket = 0; socket < MAX_SOCKET; ++socket) { + uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK); + + /* configure PCU_CR0_FUN csrs */ + pci_devfn_t cr0_dev = PCI_DEV(bus, PCU_DEV, PCU_CR0_FUN); + data = pci_mmio_read_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS); + data |= P_STATE_LIMITS_LOCK; + pci_mmio_write_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS, data); + + plat_info = pci_mmio_read_config32(cr0_dev, PCU_CR0_PLATFORM_INFO); + dump_csr64("", cr0_dev, PCU_CR0_PLATFORM_INFO); + max_min_turbo_limit_ratio = + (plat_info & MAX_NON_TURBO_LIM_RATIO_MASK) >> + MAX_NON_TURBO_LIM_RATIO_SHIFT; + printk(BIOS_SPEW, "plat_info: 0x%x, max_min_turbo_limit_ratio: 0x%x\n", + plat_info, max_min_turbo_limit_ratio); + + /* configure PCU_CR1_FUN csrs */ + pci_devfn_t cr1_dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN); + + data = pci_mmio_read_config32(cr1_dev, PCU_CR1_SAPMCTL); + /* clear bits 27:31 - FSP sets this with 0x7 which needs to be cleared */ + data &= 0x0fffffff; + data |= SAPMCTL_LOCK_MASK; + pci_mmio_write_config32(cr1_dev, PCU_CR1_SAPMCTL, data); + + /* configure PCU_CR1_FUN csrs */ + pci_devfn_t cr2_dev = PCI_DEV(bus, PCU_DEV, PCU_CR2_FUN); + + data = PCIE_IN_PKGCSTATE_L1_MASK; + pci_mmio_write_config32(cr2_dev, PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK, data); + + data = KTI_IN_PKGCSTATE_L1_MASK; + pci_mmio_write_config32(cr2_dev, PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK2, data); + + data = PROCHOT_RATIO; + printk(BIOS_SPEW, "PCU_CR2_PROCHOT_RESPONSE_RATIO_REG data: 0x%x\n", data); + pci_mmio_write_config32(cr2_dev, PCU_CR2_PROCHOT_RESPONSE_RATIO_REG, data); + dump_csr("", cr2_dev, PCU_CR2_PROCHOT_RESPONSE_RATIO_REG); + + data = pci_mmio_read_config32(cr2_dev, PCU_CR2_DYNAMIC_PERF_POWER_CTL); + data |= UNOCRE_PLIMIT_OVERRIDE_SHIFT; + pci_mmio_write_config32(cr2_dev, PCU_CR2_DYNAMIC_PERF_POWER_CTL, data); + } +} + +static void set_bios_init_completion_for_package(uint32_t socket) +{ + uint32_t data; + uint32_t timedout; + uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK); + pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN); + + /* read pcu config */ + timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0); + if (timedout) { + /* 2nd try */ + timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0); + if (timedout) + die("BIOS PCU Misc Config Read timed out.\n"); + + data = pci_mmio_read_config32(dev, PCU_CR1_BIOS_MB_DATA_REG); + printk(BIOS_SPEW, "%s - pci_mmio_read_config32 reg: 0x%x, data: 0x%x\n", + __func__, PCU_CR1_BIOS_MB_DATA_REG, data); + + /* write PCU config */ + timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_WRITE_PCU_MISC_CFG, data); + if (timedout) + die("BIOS PCU Misc Config Write timed out.\n"); + } + + /* update RST_CPL3, PCODE_INIT_DONE3 */ + timedout = set_bios_reset_cpl_for_package(socket, RST_CPL3_MASK, + PCODE_INIT_DONE3_MASK, RST_CPL3_MASK); + if (timedout) + die("BIOS RESET CPL3 timed out.\n"); + + /* update RST_CPL4, PCODE_INIT_DONE4 */ + timedout = set_bios_reset_cpl_for_package(socket, RST_CPL4_MASK, + PCODE_INIT_DONE4_MASK, RST_CPL4_MASK); + if (timedout) + die("BIOS RESET CPL4 timed out.\n"); + /* set CSR_DESIRED_CORES_CFG2 lock bit */ + data = pci_mmio_read_config32(dev, PCU_CR1_DESIRED_CORES_CFG2_REG); + data |= PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK; + printk(BIOS_SPEW, "%s - pci_mmio_write_config32 PCU_CR1_DESIRED_CORES_CFG2_REG 0x%x, data: 0x%x\n", + __func__, PCU_CR1_DESIRED_CORES_CFG2_REG, data); + pci_mmio_write_config32(dev, PCU_CR1_DESIRED_CORES_CFG2_REG, data); +} + +void set_bios_init_completion(void) +{ + uint32_t sbsp_socket_id = 0; /* TODO - this needs to be configurable */ + + for (uint32_t socket = 0; socket < MAX_SOCKET; ++socket) { + if (socket == sbsp_socket_id) + continue; + set_bios_init_completion_for_package(socket); + } + set_bios_init_completion_for_package(sbsp_socket_id); +} + +void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits) +{ + register int ecx; + struct cpuid_result cpuid_regs; + + /* get max index of CPUID */ + cpuid_regs = cpuid(0); + assert(cpuid_regs.eax >= 0xb); /* cpuid_regs.eax is max input value for cpuid */ + + *thread_bits = *core_bits = 0; + ecx = 0; + while (1) { + cpuid_regs = cpuid_ext(0xb, ecx); + if (ecx == 0) { + *thread_bits = (cpuid_regs.eax & 0x1f); + } else { + *core_bits = (cpuid_regs.eax & 0x1f) - *thread_bits; + break; + } + ecx++; + } +} + +void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, uint32_t thread_bits, + uint8_t *package, uint8_t *core, uint8_t *thread) +{ + if (package != NULL) + *package = (apicid >> (thread_bits + core_bits)); + if (core != NULL) + *core = (uint32_t)((apicid >> thread_bits) & ~((~0) << core_bits)); + if (thread != NULL) + *thread = (uint32_t)(apicid & ~((~0) << thread_bits)); +} + +int get_cpu_count(void) +{ + size_t hob_size; + const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob; + + /* these fields are incorrect - need debugging */ + hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + return hob->SystemStatus.numCpus; +} + +int get_threads_per_package(void) +{ + unsigned int core_count, thread_count; + cpu_read_topology(&core_count, &thread_count); + return thread_count; +} + +int get_platform_thread_count(void) +{ + return get_cpu_count() * get_threads_per_package(); +} + +void get_iiostack_info(struct iiostack_resource *info) +{ + size_t hob_size; + const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + const IIO_UDS *hob; + + hob = fsp_find_extension_hob_by_guid( + fsp_hob_iio_universal_data_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + + // copy IIO Stack info from FSP HOB + info->no_of_stacks = 0; + for (int s = 0; s < hob->PlatformData.numofIIO; ++s) { + for (int x = 0; x < MAX_IIO_STACK; ++x) { + const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x]; + // TODO: do we have situation with only bux 0 and one stack? + if (ri->BusBase >= ri->BusLimit) + continue; + assert(info->no_of_stacks < (CONFIG_MAX_SOCKET * MAX_IIO_STACK)); + memcpy(&info->res[info->no_of_stacks++], ri, sizeof(STACK_RES)); + } + } +} + +#if ENV_RAMSTAGE + +void xeonsp_init_cpu_config(void) +{ + struct device *dev; + int apic_ids[CONFIG_MAX_CPUS] = {0}, apic_ids_by_thread[CONFIG_MAX_CPUS] = {0}; + int num_apics = 0; + uint32_t core_bits, thread_bits; + unsigned int core_count, thread_count; + unsigned int num_cpus; + + /* sort APIC ids in asending order to identify apicid ranges for + each numa domain + */ + for (dev = all_devices; dev; dev = dev->next) { + if ((dev->path.type != DEVICE_PATH_APIC) || + (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!dev->enabled) + continue; + if (num_apics >= ARRAY_SIZE(apic_ids)) + break; + apic_ids[num_apics++] = dev->path.apic.apic_id; + } + if (num_apics > 1) + bubblesort(apic_ids, num_apics, NUM_ASCENDING); + + num_cpus = get_cpu_count(); + cpu_read_topology(&core_count, &thread_count); + assert(num_apics == (num_cpus * thread_count)); + + /* sort them by thread i.e., all cores with thread 0 and then thread 1 */ + int index = 0; + for (int id = 0; id < num_apics; ++id) { + int apic_id = apic_ids[id]; + if (apic_id & 0x1) { /* 2nd thread */ + apic_ids_by_thread[index + (num_apics/2) - 1] = apic_id; + } else { /* 1st thread */ + apic_ids_by_thread[index++] = apic_id; + } + } + + + /* update apic_id, node_id in sorted order */ + num_apics = 0; + get_core_thread_bits(&core_bits, &thread_bits); + for (dev = all_devices; dev; dev = dev->next) { + uint8_t package; + + if ((dev->path.type != DEVICE_PATH_APIC) || + (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!dev->enabled) + continue; + if (num_apics >= ARRAY_SIZE(apic_ids)) + break; + dev->path.apic.apic_id = apic_ids_by_thread[num_apics]; + get_cpu_info_from_apicid(dev->path.apic.apic_id, core_bits, thread_bits, + &package, NULL, NULL); + dev->path.apic.node_id = package; + printk(BIOS_DEBUG, "CPU %d apic_id: 0x%x (%d), node_id: 0x%x\n", + num_apics, dev->path.apic.apic_id, + dev->path.apic.apic_id, dev->path.apic.node_id); + + ++num_apics; + } +} + +unsigned int get_srat_memory_entries(acpi_srat_mem_t *srat_mem) +{ + const struct SystemMemoryMapHob *memory_map; + size_t hob_size; + const uint8_t mem_hob_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; + unsigned int mmap_index; + + memory_map = fsp_find_extension_hob_by_guid(mem_hob_guid, &hob_size); + assert(memory_map != NULL && hob_size != 0); + printk(BIOS_DEBUG, "FSP_SYSTEM_MEMORYMAP_HOB_GUID hob_size: %ld\n", hob_size); + + mmap_index = 0; + for (int e = 0; e < memory_map->numberEntries; ++e) { + const struct SystemMemoryMapElement *mem_element = &memory_map->Element[e]; + uint64_t addr = + (uint64_t) ((uint64_t)mem_element->BaseAddress << + MEM_ADDR_64MB_SHIFT_BITS); + uint64_t size = + (uint64_t) ((uint64_t)mem_element->ElementSize << + MEM_ADDR_64MB_SHIFT_BITS); + + printk(BIOS_DEBUG, "memory_map %d addr: 0x%llx, BaseAddress: 0x%x, size: 0x%llx, " + "ElementSize: 0x%x, reserved: %d\n", + e, addr, mem_element->BaseAddress, size, + mem_element->ElementSize, (mem_element->Type & MEM_TYPE_RESERVED)); + + assert(mmap_index < MAX_ACPI_MEMORY_AFFINITY_COUNT); + + /* skip reserved memory region */ + if (mem_element->Type & MEM_TYPE_RESERVED) + continue; + + /* skip if this address is already added */ + bool skip = false; + for (int idx = 0; idx < mmap_index; ++idx) { + uint64_t base_addr = ((uint64_t)srat_mem[idx].base_address_high << 32) + + srat_mem[idx].base_address_low; + if (addr == base_addr) { + skip = true; + break; + } + } + if (skip) + continue; + + srat_mem[mmap_index].type = 1; /* Memory affinity structure */ + srat_mem[mmap_index].length = sizeof(acpi_srat_mem_t); + srat_mem[mmap_index].base_address_low = (uint32_t) (addr & 0xffffffff); + srat_mem[mmap_index].base_address_high = (uint32_t) (addr >> 32); + srat_mem[mmap_index].length_low = (uint32_t) (size & 0xffffffff); + srat_mem[mmap_index].length_high = (uint32_t) (size >> 32); + srat_mem[mmap_index].proximity_domain = mem_element->SocketId; + srat_mem[mmap_index].flags = SRAT_ACPI_MEMORY_ENABLED; + if ((mem_element->Type & MEMTYPE_VOLATILE_MASK) == 0) + srat_mem[mmap_index].flags |= SRAT_ACPI_MEMORY_NONVOLATILE; + ++mmap_index; + } + + return mmap_index; +} + +#endif diff --git a/src/soc/intel/xeon_sp/spi.c b/src/soc/intel/xeon_sp/spi.c new file mode 100644 index 0000000..18af5e4 --- /dev/null +++ b/src/soc/intel/xeon_sp/spi.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <intelblocks/spi.h> +#include <soc/pci_devs.h> + +int spi_soc_devfn_to_bus(unsigned int devfn) +{ + switch (devfn) { + case PCH_DEVFN_SPI: + return 0; + } + return -1; +} diff --git a/src/soc/intel/xeon_sp/uncore.c b/src/soc/intel/xeon_sp/uncore.c new file mode 100644 index 0000000..adf3e3e --- /dev/null +++ b/src/soc/intel/xeon_sp/uncore.c @@ -0,0 +1,305 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <cbmem.h> +#include <console/console.h> +#include <cpu/x86/lapic.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <soc/iomap.h> +#include <soc/pci_devs.h> +#include <soc/ramstage.h> +#include <soc/soc_util.h> + +struct map_entry { + uint32_t reg; + int is_64_bit; + int is_limit; + int mask_bits; + const char *description; +}; + +enum { + TOHM_REG, + MMIOL_REG, + MMCFG_BASE_REG, + MMCFG_LIMIT_REG, + TOLM_REG, + ME_BASE_REG, + ME_LIMIT_REG, + TSEG_BASE_REG, + TSEG_LIMIT_REG, + /* Must be last. */ + NUM_MAP_ENTRIES +}; + +static struct map_entry memory_map[NUM_MAP_ENTRIES] = { + [TOHM_REG] = MAP_ENTRY_LIMIT_64(VTD_TOHM_CSR, 26, "TOHM"), + [MMIOL_REG] = MAP_ENTRY_BASE_32(VTD_MMIOL_CSR, "MMIOL"), + [MMCFG_BASE_REG] = MAP_ENTRY_BASE_64(VTD_MMCFG_BASE_CSR, "MMCFG_BASE"), + [MMCFG_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_MMCFG_LIMIT_CSR, 26, "MMCFG_LIMIT"), + [TOLM_REG] = MAP_ENTRY_LIMIT_32(VTD_TOLM_CSR, 26, "TOLM"), + [ME_BASE_REG] = MAP_ENTRY_BASE_64(VTD_ME_BASE_CSR, "ME_BASE"), + [ME_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_ME_LIMIT_CSR, 19, "ME_LIMIT"), + [TSEG_BASE_REG] = MAP_ENTRY_BASE_32(VTD_TSEG_BASE_CSR, "TSEGMB_BASE"), + [TSEG_LIMIT_REG] = MAP_ENTRY_LIMIT_32(VTD_TSEG_LIMIT_CSR, 20, "TSEGMB_LIMIT"), +}; + +static void read_map_entry(struct device *dev, struct map_entry *entry, + uint64_t *result) +{ + uint64_t value; + uint64_t mask; + + /* All registers are on a 1MiB granularity. */ + mask = ((1ULL << entry->mask_bits) - 1); + mask = ~mask; + + value = 0; + + if (entry->is_64_bit) { + value = pci_read_config32(dev, entry->reg + sizeof(uint32_t)); + value <<= 32; + } + + value |= (uint64_t)pci_read_config32(dev, entry->reg); + value &= mask; + + if (entry->is_limit) + value |= ~mask; + + *result = value; +} + +static void mc_read_map_entries(struct device *dev, uint64_t *values) +{ + int i; + for (i = 0; i < NUM_MAP_ENTRIES; i++) + read_map_entry(dev, &memory_map[i], &values[i]); +} + +static void mc_report_map_entries(struct device *dev, uint64_t *values) +{ + int i; + for (i = 0; i < NUM_MAP_ENTRIES; i++) { + printk(BIOS_DEBUG, "MC MAP: %s: 0x%llx\n", + memory_map[i].description, values[i]); + } +} + +/* + * Host Memory Map: + * + * +--------------------------+ TOCM (2 pow 46 - 1) + * | Reserved | + * +--------------------------+ + * | MMIOH (relocatable) | + * +--------------------------+ + * | PCISeg | + * +--------------------------+ TOHM + * | High DRAM Memory | + * +--------------------------+ 4GiB (0x100000000) + * +--------------------------+ 0xFFFF_FFFF + * | Firmware | + * +--------------------------+ 0xFF00_0000 + * | Reserved | + * +--------------------------+ 0xFEF0_0000 + * | Local xAPIC | + * +--------------------------+ 0xFEE0_0000 + * | HPET/LT/TPM/Others | + * +--------------------------+ 0xFED0_0000 + * | I/O xAPIC | + * +--------------------------+ 0xFEC0_0000 + * | Reserved | + * +--------------------------+ 0xFEB8_0000 + * | Reserved | + * +--------------------------+ 0xFEB0_0000 + * | Reserved | + * +--------------------------+ 0xFE00_0000 + * | MMIOL (relocatable) | + * | P2SB PCR cfg BAR | (0xfd000000 - 0xfdffffff + * | BAR space | [mem 0x90000000-0xfcffffff] available for PCI devices + * +--------------------------+ 0x9000_0000 + * |PCIe MMCFG (relocatable) | CONFIG_MMCONF_BASE_ADDRESS 64 or 256MB + * | | (0x80000000 - 0x8fffffff, 0x40000) + * +--------------------------+ TOLM + * | MEseg (relocatable) | 32, 64, 128 or 256 MB (0x78000000 - 0x7fffffff, 0x20000) + * +--------------------------+ + * | Tseg (relocatable) | N x 8MB (0x70000000 - 0x77ffffff, 0x20000) + * +--------------------------+ cbmem_top + * | Reserved - CBMEM | (0x6fffe000 - 0x6fffffff, 0x2000) + * +--------------------------+ + * | Reserved - FSP | (0x6fbfe000 - 0x6fffdfff, 0x400000) + * +--------------------------+ top_of_ram (0x6fbfdfff) + * | Low DRAM Memory | + * +--------------------------+ FFFFF (1MB) + * | E & F segments | + * +--------------------------+ E0000 + * | C & D segments | + * +--------------------------+ C0000 + * | VGA & SMM Memory | + * +--------------------------+ A0000 + * | Conventional Memory | + * | (DOS Range) | + * +--------------------------+ 0 + */ + +static void mc_add_dram_resources(struct device *dev, int *res_count) +{ + struct range_entry fsp_mem; + uint64_t base_kb; + uint64_t size_kb; + uint64_t top_of_ram; + uint64_t mc_values[NUM_MAP_ENTRIES]; + struct resource *resource; + int index = *res_count; + + fsp_find_reserved_memory(&fsp_mem); + + /* Read in the MAP registers and report their values. */ + mc_read_map_entries(dev, &mc_values[0]); + mc_report_map_entries(dev, &mc_values[0]); + + top_of_ram = range_entry_base(&fsp_mem) - 1; + printk(BIOS_SPEW, "cbmem_top: 0x%lx, fsp range: [0x%llx - 0x%llx], top_of_ram: 0x%llx\n", + (uintptr_t) cbmem_top(), range_entry_base(&fsp_mem), + range_entry_end(&fsp_mem), top_of_ram); + + /* Conventional Memory (DOS region, 0x0 to 0x9FFFF) */ + base_kb = 0; + size_kb = (0xa0000 >> 10); + LOG_MEM_RESOURCE("legacy_ram", dev, index, base_kb, size_kb); + ram_resource(dev, index++, base_kb, size_kb); + + /* 1MB -> top_of_ram i.e., fsp_mem_base+1*/ + base_kb = (0x100000 >> 10); + size_kb = (top_of_ram - 0xfffff) >> 10; + LOG_MEM_RESOURCE("low_ram", dev, index, base_kb, size_kb); + ram_resource(dev, index++, base_kb, size_kb); + + /* + * FSP meomoy, CBMem regions are already added as reserved + * Add TSEG and MESEG Regions as reserved memory + * src/drivers/intel/fsp2_0/memory_init.c sets CBMEM reserved size + * arch_upd->BootLoaderTolumSize = cbmem_overhead_size(); == 2 * CBMEM_ROOT_MIN_SIZE + * typically 0x2000 + * Example config: + * FSP_RESERVED_MEMORY_RESOURCE_HOB + * FspReservedMemoryResource Base : 6FBFE000 + * FspReservedMemoryResource Size : 400000 + * FSP_BOOT_LOADER_TOLUM_HOB + * FspBootLoaderTolum Base : 6FFFE000 + * FspBootLoaderTolum Size : 2000 + */ + + /* Mark TSEG/SMM region as reserved */ + base_kb = (mc_values[TSEG_BASE_REG] >> 10); + size_kb = (mc_values[TSEG_LIMIT_REG] - mc_values[TSEG_BASE_REG] + 1) >> 10; + LOG_MEM_RESOURCE("mmio_tseg", dev, index, base_kb, size_kb); + reserved_ram_resource(dev, index++, base_kb, size_kb); + + /* Mark region between TSEG - TOLM (eg. MESEG) as reserved */ + if (mc_values[TSEG_LIMIT_REG] < mc_values[TOLM_REG]) { + base_kb = ((mc_values[TSEG_LIMIT_REG] + 1) >> 10); + size_kb = (mc_values[TOLM_REG] - mc_values[TSEG_LIMIT_REG]) >> 10; + LOG_MEM_RESOURCE("mmio_tolm", dev, index, base_kb, size_kb); + reserved_ram_resource(dev, index++, base_kb, size_kb); + } + + /* 4GiB -> TOHM */ + if (mc_values[TOHM_REG] > 0x100000000) { + base_kb = (0x100000000 >> 10); + size_kb = (mc_values[TOHM_REG] - 0x100000000 + 1) >> 10; + LOG_MEM_RESOURCE("high_ram", dev, index, base_kb, size_kb); + ram_resource(dev, index++, base_kb, size_kb); + } + + /* add MMIO CFG resource */ + resource = new_resource(dev, index++); + resource->base = (resource_t) mc_values[MMCFG_BASE_REG]; + resource->size = (resource_t) (mc_values[MMCFG_LIMIT_REG] - + mc_values[MMCFG_BASE_REG] + 1); + resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + LOG_MEM_RESOURCE("mmiocfg_res", dev, index-1, (resource->base >> 10), + (resource->size >> 10)); + + /* add Local APIC resource */ + resource = new_resource(dev, index++); + resource->base = LAPIC_DEFAULT_BASE; + resource->size = 0x00001000; + resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE | + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; + LOG_MEM_RESOURCE("apic_res", dev, index-1, (resource->base >> 10), + (resource->size >> 10)); + + /* + * Add legacy region as reserved - 0xa000 - 1MB + * Reserve everything between A segment and 1MB: + * + * 0xa0000 - 0xbffff: legacy VGA + * 0xc0000 - 0xfffff: RAM + */ + base_kb = VGA_BASE_ADDRESS >> 10; + size_kb = VGA_BASE_SIZE >> 10; + LOG_MEM_RESOURCE("legacy_mmio", dev, index, base_kb, size_kb); + mmio_resource(dev, index++, base_kb, size_kb); + + base_kb = (0xc0000 >> 10); + size_kb = (0x100000 - 0xc0000) >> 10; + LOG_MEM_RESOURCE("legacy_write_protect", dev, index, base_kb, size_kb); + reserved_ram_resource(dev, index++, base_kb, size_kb); + + *res_count = index; +} + +static void mmapvtd_read_resources(struct device *dev) +{ + int index = 0; + + /* Read standard PCI resources. */ + pci_dev_read_resources(dev); + + /* Calculate and add DRAM resources. */ + mc_add_dram_resources(dev, &index); +} + +static void mmapvtd_init(struct device *dev) +{ +} + +static struct device_operations mmapvtd_ops = { + .read_resources = mmapvtd_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = mmapvtd_init, + .ops_pci = &soc_pci_ops, +#if CONFIG(HAVE_ACPI_TABLES) + .acpi_inject_dsdt_generator = NULL, +#endif +}; + +static const unsigned short mmapvtd_ids[] = { + MMAP_VTD_CFG_REG_DEVID, /* Memory Map/Intel® VT-d Configuration Registers */ + 0 +}; + +static const struct pci_driver mmapvtd_driver __pci_driver = { + .ops = &mmapvtd_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = mmapvtd_ids +}; diff --git a/src/soc/intel/xeon_sp/upd_display.c b/src/soc/intel/xeon_sp/upd_display.c new file mode 100644 index 0000000..2ae34ed --- /dev/null +++ b/src/soc/intel/xeon_sp/upd_display.c @@ -0,0 +1,80 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 - 2020 Intel Corporation + * Copyright (C) 2019 - 2020 Facebook Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include <console/console.h> +#include <fsp/util.h> +#include <lib.h> + +#define DUMP_UPD(old, new, field) \ + fsp_display_upd_value(#field, sizeof(old->field), old->field, new->field) + +/* Display the UPD parameters for MemoryInit */ +void soc_display_fspm_upd_params( + const FSPM_UPD *fspm_old_upd, + const FSPM_UPD *fspm_new_upd) +{ + const FSP_M_CONFIG *new; + const FSP_M_CONFIG *old; + + old = &fspm_old_upd->FspmConfig; + new = &fspm_new_upd->FspmConfig; + + printk(BIOS_DEBUG, "UPD values for MemoryInit:\n"); + + DUMP_UPD(old, new, PcdFspMrcDebugPrintErrorLevel); + DUMP_UPD(old, new, PcdFspKtiDebugPrintErrorLevel); + DUMP_UPD(old, new, PcdHsuartDevice); + + hexdump(fspm_new_upd, sizeof(*fspm_new_upd)); +} + +/* Display the UPD parameters for SiliconInit */ +void soc_display_fsps_upd_params( + const FSPS_UPD *fsps_old_upd, + const FSPS_UPD *fsps_new_upd) +{ + const FSPS_CONFIG *new; + const FSPS_CONFIG *old; + + old = &fsps_old_upd->FspsConfig; + new = &fsps_new_upd->FspsConfig; + + printk(BIOS_DEBUG, "UPD values for SiliconInit:\n"); + + DUMP_UPD(old, new, PcdBifurcationPcie0); + DUMP_UPD(old, new, PcdBifurcationPcie1); + DUMP_UPD(old, new, PcdActiveCoreCount); + DUMP_UPD(old, new, PcdCpuMicrocodePatchBase); + DUMP_UPD(old, new, PcdCpuMicrocodePatchSize); + DUMP_UPD(old, new, PcdEnablePcie0); + DUMP_UPD(old, new, PcdEnablePcie1); + DUMP_UPD(old, new, PcdEnableEmmc); + DUMP_UPD(old, new, PcdEnableGbE); + DUMP_UPD(old, new, PcdFiaMuxConfigRequestPtr); + DUMP_UPD(old, new, PcdPcieRootPort0DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort1DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort2DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort3DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort4DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort5DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort6DeEmphasis); + DUMP_UPD(old, new, PcdPcieRootPort7DeEmphasis); + DUMP_UPD(old, new, PcdEMMCDLLConfigPtr); + + hexdump(fsps_new_upd, sizeof(*fsps_new_upd)); +}