Attention is currently required from: Arthur Heymans, Christian Walter, Johnny Lin, Tim Chu.
Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/79878?usp=email )
Change subject: soc/intel/xeon_sp: Support multiple PCI segments ......................................................................
soc/intel/xeon_sp: Support multiple PCI segments
Untested.
Change-Id: I0ba5e426123234979d746d3bdfc1ddfbd71c3447 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/soc/intel/xeon_sp/chip_common.c M src/soc/intel/xeon_sp/cpx/chip.c M src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h M src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h M src/soc/intel/xeon_sp/cpx/soc_util.c M src/soc/intel/xeon_sp/memmap.c M src/soc/intel/xeon_sp/skx/include/soc/pci_devs.h M src/soc/intel/xeon_sp/skx/include/soc/soc_util.h M src/soc/intel/xeon_sp/skx/soc_util.c M src/soc/intel/xeon_sp/spr/acpi/cxl_resource.asl M src/soc/intel/xeon_sp/spr/acpi/pci_resource.asl M src/soc/intel/xeon_sp/spr/chip.c M src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h M src/soc/intel/xeon_sp/spr/include/soc/soc_util.h M src/soc/intel/xeon_sp/spr/ioat.c M src/soc/intel/xeon_sp/spr/soc_acpi.c M src/soc/intel/xeon_sp/spr/soc_smihandler_util.c M src/soc/intel/xeon_sp/spr/soc_util.c M src/soc/intel/xeon_sp/uncore_acpi.c M src/soc/intel/xeon_sp/util.c 20 files changed, 165 insertions(+), 70 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/78/79878/1
diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c index c1b331b..8a5e98d 100644 --- a/src/soc/intel/xeon_sp/chip_common.c +++ b/src/soc/intel/xeon_sp/chip_common.c @@ -20,6 +20,16 @@ return &hob->PlatformData.IIO_resource[dn / MAX_LOGIC_IIO_STACK].StackRes[dn % MAX_LOGIC_IIO_STACK]; }
+static int domain_to_pcie_segment(const struct device *dev) +{ + assert(dev->path.type == DEVICE_PATH_DOMAIN); + const unsigned int dn = dev->path.domain.domain; + + const IIO_UDS *hob = get_iio_uds(); + assert(hob != NULL); + return hob->PlatformData.CpuQpiInfo[dn / MAX_LOGIC_IIO_STACK].PcieSegment; +} + void iio_pci_domain_read_resources(struct device *dev) { struct resource *res; @@ -67,6 +77,7 @@ void iio_pci_domain_scan_bus(struct device *dev) { const STACK_RES *sr = domain_to_stack_res(dev); + const int seg = domain_to_pcie_segment(dev); if (!sr) return;
@@ -80,9 +91,10 @@ bus->secondary = sr->BusBase; bus->subordinate = sr->BusBase; bus->max_subordinate = sr->BusLimit; + bus->segment = seg;
- printk(BIOS_SPEW, "Scanning IIO stack %d: busses %x-%x\n", dev->path.domain.domain, - dev->link_list->secondary, dev->link_list->max_subordinate); + printk(BIOS_SPEW, "Scanning IIO stack %d: segment %x, busses %x-%x\n", dev->path.domain.domain, + dev->link_list->segment, dev->link_list->secondary, dev->link_list->max_subordinate); pci_host_bridge_scan_bus(dev); }
diff --git a/src/soc/intel/xeon_sp/cpx/chip.c b/src/soc/intel/xeon_sp/cpx/chip.c index 39a7eba..1989f3d 100644 --- a/src/soc/intel/xeon_sp/cpx/chip.c +++ b/src/soc/intel/xeon_sp/cpx/chip.c @@ -71,6 +71,7 @@
static void iio_write_mask(u16 bus, u16 dev, u8 func) { + /* FIXME: Add segment support */ pci_devfn_t device = PCI_DEV(bus, dev, func); u32 val = pci_s_read_config32(device, IIO_XPUNCCERRMSK_REG); val |= (SENT_PCIE_UNSUPP_MASK | RCVD_PCIE_CA_STS_MASK | RCVD_PCIE_UR_STS_MASK); @@ -119,25 +120,26 @@ if (!soc_cpu_is_enabled(socket)) continue; uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK); + uint8_t seg = get_socket_pci_segment(socket);
/* configure PCU_CR0_FUN csrs */ - const struct device *cr0_dev = PCU_DEV_CR0(bus); + const struct device *cr0_dev = PCU_DEV_CR0(seg, bus); pci_or_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS, P_STATE_LIMITS_LOCK); pci_or_config32(cr0_dev, PCU_CR0_PACKAGE_RAPL_LIMIT_UPR, PKG_PWR_LIM_LOCK_UPR); pci_or_config32(cr0_dev, PCU_CR0_TURBO_ACTIVATION_RATIO, TURBO_ACTIVATION_RATIO_LOCK);
/* configure PCU_CR1_FUN csrs */ - const struct device *cr1_dev = PCU_DEV_CR1(bus); + const struct device *cr1_dev = PCU_DEV_CR1(seg, bus); pci_or_config32(cr1_dev, PCU_CR1_SAPMCTL, SAPMCTL_LOCK_MASK);
/* configure PCU_CR2_FUN csrs */ - const struct device *cr2_dev = PCU_DEV_CR2(bus); + const struct device *cr2_dev = PCU_DEV_CR2(seg, bus); pci_or_config32(cr2_dev, PCU_CR2_DRAM_PLANE_POWER_LIMIT, PP_PWR_LIM_LOCK); pci_or_config32(cr2_dev, PCU_CR2_DRAM_POWER_INFO_UPR, DRAM_POWER_INFO_LOCK_UPR);
/* configure PCU_CR3_FUN csrs */ - const struct device *cr3_dev = PCU_DEV_CR3(bus); + const struct device *cr3_dev = PCU_DEV_CR3(seg, bus); pci_or_config32(cr3_dev, PCU_CR3_CONFIG_TDP_CONTROL, TDP_LOCK); pci_or_config32(cr3_dev, PCU_CR3_FLEX_RATIO, OC_LOCK); } diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h index 55268a7..46678ae 100644 --- a/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h +++ b/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h @@ -15,16 +15,16 @@ #define SAD_ALL_PAM456_CSR 0x44
#if !defined(__SIMPLE_DEVICE__) -#define _PCU_DEV(bus, func) pcidev_path_on_bus(bus, PCI_DEVFN(PCU_DEV, func)) +#define _PCU_DEV(seg, bus, func) pcidev_path_on_segbus((seg), (bus), PCI_DEVFN(PCU_DEV, func)) #else -#define _PCU_DEV(bus, func) PCI_DEV(bus, PCU_DEV, func) +#define _PCU_DEV(seg, bus, func) PCI_DEV(((seg) << 8) | (bus), PCU_DEV, func) #endif
#define PCU_IIO_STACK 1 #define PCU_DEV 30
#define PCU_CR0_FUN 0 -#define PCU_DEV_CR0(bus) _PCU_DEV(bus, PCU_CR0_FUN) +#define PCU_DEV_CR0(seg, bus) _PCU_DEV(seg, bus, PCU_CR0_FUN) #define PCU_CR0_PLATFORM_INFO 0xa8 #define PCU_CR0_TURBO_ACTIVATION_RATIO 0xb0 #define TURBO_ACTIVATION_RATIO_LOCK BIT(31) @@ -37,7 +37,7 @@ #define PMAX_LOCK BIT(31)
#define PCU_CR1_FUN 1 -#define PCU_DEV_CR1(bus) _PCU_DEV(bus, PCU_CR1_FUN) +#define PCU_DEV_CR1(seg, bus) _PCU_DEV(seg, bus, PCU_CR1_FUN) #define PCU_CR1_BIOS_MB_DATA_REG 0x8c
#define PCU_CR1_BIOS_MB_INTERFACE_REG 0x90 @@ -64,7 +64,7 @@ #define SAPMCTL_LOCK_MASK BIT(31)
#define PCU_CR2_FUN 2 -#define PCU_DEV_CR2(bus) _PCU_DEV(bus, PCU_CR2_FUN) +#define PCU_DEV_CR2(seg, bus) _PCU_DEV(seg, bus, PCU_CR2_FUN) #define PCU_CR2_DRAM_POWER_INFO_LWR 0xa8 #define PCU_CR2_DRAM_POWER_INFO_UPR (PCU_CR2_DRAM_POWER_INFO_LWR + 4) #define DRAM_POWER_INFO_LOCK_UPR BIT(31) @@ -72,7 +72,7 @@ #define PP_PWR_LIM_LOCK BIT(31)
#define PCU_CR3_FUN 3 -#define PCU_DEV_CR3(bus) _PCU_DEV(bus, PCU_CR3_FUN) +#define PCU_DEV_CR3(seg, bus) _PCU_DEV(seg, bus, PCU_CR3_FUN) #define PCU_CR3_CONFIG_TDP_CONTROL 0x60 #define TDP_LOCK BIT(31) #define PCU_CR3_FLEX_RATIO 0xa0 @@ -142,9 +142,9 @@ #define VTD_FUNC_NUM 0x0
#if !defined(__SIMPLE_DEVICE__) -#define VTD_DEV(bus) pcidev_path_on_bus((bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) +#define VTD_DEV(seg, bus) pcidev_path_on_segbus((seg), (bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) #else -#define VTD_DEV(bus) PCI_DEV((bus), VTD_DEV_NUM, VTD_FUNC_NUM) +#define VTD_DEV(seg, bus) PCI_DEV(((seg) << 8) | (bus), VTD_DEV_NUM, VTD_FUNC_NUM) #endif
#define APIC_DEV_NUM 0x05 diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h b/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h index 91919b8..ec4cf54 100644 --- a/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h +++ b/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h @@ -26,6 +26,7 @@
uint8_t get_stack_busno(const uint8_t stack); uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack); +uint8_t get_socket_pci_segment(uint32_t socket); uint32_t get_socket_ubox_busno(uint32_t socket); uint8_t get_cxl_node_count(void);
diff --git a/src/soc/intel/xeon_sp/cpx/soc_util.c b/src/soc/intel/xeon_sp/cpx/soc_util.c index e277752..30eab8b 100644 --- a/src/soc/intel/xeon_sp/cpx/soc_util.c +++ b/src/soc/intel/xeon_sp/cpx/soc_util.c @@ -41,7 +41,8 @@ printk(BIOS_ERR, "%s: Stack %u does not exist!\n", __func__, stack); return 0; } - const pci_devfn_t dev = PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV, UBOX_DECS_FUNC); + const uint8_t seg = get_socket_pci_segment(0); + const pci_devfn_t dev = PCI_DEV((seg << 8) | UBOX_DECS_BUS, UBOX_DECS_DEV, UBOX_DECS_FUNC); const uint16_t offset = stack / 4 ? UBOX_DECS_CPUBUSNO1_CSR : UBOX_DECS_CPUBUSNO_CSR; return pci_io_read_config32(dev, offset) >> (8 * (stack % 4)) & 0xff; } @@ -55,6 +56,19 @@ return hob->PlatformData.IIO_resource[socket].StackRes[stack].BusBase; }
+uint8_t get_socket_pci_segment(uint32_t socket) +{ + const IIO_UDS *hob = get_iio_uds(); + uint8_t seg; + + assert(socket < MAX_SOCKET); + + seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + assert(seg < CONFIG_ECAM_SEGMENT_COUNT); + + return seg; +} + uint32_t get_socket_ubox_busno(uint32_t socket) { if (socket == 0) diff --git a/src/soc/intel/xeon_sp/memmap.c b/src/soc/intel/xeon_sp/memmap.c index e73143f..c35b5ab 100644 --- a/src/soc/intel/xeon_sp/memmap.c +++ b/src/soc/intel/xeon_sp/memmap.c @@ -12,8 +12,8 @@
void smm_region(uintptr_t *start, size_t *size) { - uintptr_t tseg_base = pci_read_config32(VTD_DEV(0), VTD_TSEG_BASE_CSR); - uintptr_t tseg_limit = pci_read_config32(VTD_DEV(0), VTD_TSEG_LIMIT_CSR); + uintptr_t tseg_base = pci_read_config32(VTD_DEV(0, 0), VTD_TSEG_BASE_CSR); + uintptr_t tseg_limit = pci_read_config32(VTD_DEV(0, 0), VTD_TSEG_LIMIT_CSR);
tseg_base = ALIGN_DOWN(tseg_base, 1 * MiB); tseg_limit = ALIGN_DOWN(tseg_limit, 1 * MiB); @@ -55,7 +55,7 @@ { const IIO_UDS *hob = get_iio_uds(); union dpr_register dpr; - struct device *dev = VTD_DEV(0); + struct device *dev = VTD_DEV(0, 0);
dpr.raw = 0;
@@ -77,7 +77,8 @@ if (!stack_needs_resource_alloc(ri)) continue; uint8_t bus = ri->BusBase; - dev = VTD_DEV(bus); + uint8_t segment = get_socket_pci_segment(socket); + dev = VTD_DEV(segment, bus);
if (!dev) { printk(BIOS_ERR, "BUS %x: Unable to find VTD PCI dev\n", bus); diff --git a/src/soc/intel/xeon_sp/skx/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/skx/include/soc/pci_devs.h index 3d518fa..a4f65ab 100644 --- a/src/soc/intel/xeon_sp/skx/include/soc/pci_devs.h +++ b/src/soc/intel/xeon_sp/skx/include/soc/pci_devs.h @@ -28,9 +28,9 @@ #define SAD_ALL_PAM456_CSR 0x44
#if !defined(__SIMPLE_DEVICE__) -#define _PCU_DEV(bus, func) pcidev_path_on_bus(bus, PCI_DEVFN(PCU_DEV, func)) +#define _PCU_DEV(seg, bus, func) pcidev_path_on_segbus((seg), (bus), PCI_DEVFN(PCU_DEV, func)) #else -#define _PCU_DEV(bus, func) PCI_DEV(bus, PCU_DEV, func) +#define _PCU_DEV(seg, bus, func) PCI_DEV(((seg) << 8) | (bus), PCU_DEV, func) #endif
#define PCU_IIO_STACK 1 @@ -38,7 +38,7 @@ #define PCU_CR1_FUN 1
#define PCU_CR0_FUN 0 -#define PCU_DEV_CR0(bus) _PCU_DEV(bus, PCU_CR0_FUN) +#define PCU_DEV_CR0(seg, bus) _PCU_DEV(seg, bus, PCU_CR0_FUN) #define PCU_CR0_PLATFORM_INFO 0xa8 #define PCU_CR0_P_STATE_LIMITS 0xd8 #define P_STATE_LIMITS_LOCK_SHIFT 31 @@ -140,9 +140,9 @@ #define VTD_FUNC_NUM 0x0
#if !defined(__SIMPLE_DEVICE__) -#define VTD_DEV(bus) pcidev_path_on_bus((bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) +#define VTD_DEV(seg, bus) pcidev_path_on_segbus((seg), (bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) #else -#define VTD_DEV(bus) PCI_DEV((bus), VTD_DEV_NUM, VTD_FUNC_NUM) +#define VTD_DEV(seg, bus) PCI_DEV(((seg) << 8) | (bus), VTD_DEV_NUM, VTD_FUNC_NUM) #endif
#define CBDMA_DEV_NUM 0x04 diff --git a/src/soc/intel/xeon_sp/skx/include/soc/soc_util.h b/src/soc/intel/xeon_sp/skx/include/soc/soc_util.h index 379cdc8..489ad18 100644 --- a/src/soc/intel/xeon_sp/skx/include/soc/soc_util.h +++ b/src/soc/intel/xeon_sp/skx/include/soc/soc_util.h @@ -12,6 +12,7 @@
uint8_t get_stack_busno(const uint8_t stack); uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack); +uint8_t get_socket_pci_segment(uint32_t socket); uint32_t get_socket_ubox_busno(uint32_t socket);
int soc_get_stack_for_port(int port); diff --git a/src/soc/intel/xeon_sp/skx/soc_util.c b/src/soc/intel/xeon_sp/skx/soc_util.c index d61d074..74cb7f7 100644 --- a/src/soc/intel/xeon_sp/skx/soc_util.c +++ b/src/soc/intel/xeon_sp/skx/soc_util.c @@ -85,6 +85,19 @@ return hob->PlatformData.CpuQpiInfo[socket].StackBus[stack]; }
+uint8_t get_socket_pci_segment(uint32_t socket) +{ + const IIO_UDS *hob = get_iio_uds(); + uint8_t seg; + + assert(socket < MAX_SOCKET); + + seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + assert(seg < CONFIG_ECAM_SEGMENT_COUNT); + + return seg; +} + uint32_t get_socket_ubox_busno(uint32_t socket) { if (socket == 0) @@ -99,9 +112,10 @@
for (uint32_t socket = 0; socket < MAX_SOCKET; ++socket) { uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK); + uint8_t seg = get_socket_pci_segment(socket);
/* configure PCU_CR0_FUN csrs */ - pci_devfn_t cr0_dev = PCI_DEV(bus, PCU_DEV, PCU_CR0_FUN); + pci_devfn_t cr0_dev = PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR0_FUN); data = pci_s_read_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS); data |= P_STATE_LIMITS_LOCK; pci_s_write_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS, data); @@ -115,7 +129,7 @@ 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); + pci_devfn_t cr1_dev = PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR1_FUN);
data = pci_s_read_config32(cr1_dev, PCU_CR1_SAPMCTL); /* clear bits 27:31 - FSP sets this with 0x7 which needs to be cleared */ @@ -124,7 +138,7 @@ pci_s_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); + pci_devfn_t cr2_dev = PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR2_FUN);
data = PCIE_IN_PKGCSTATE_L1_MASK; pci_s_write_config32(cr2_dev, PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK, data); diff --git a/src/soc/intel/xeon_sp/spr/acpi/cxl_resource.asl b/src/soc/intel/xeon_sp/spr/acpi/cxl_resource.asl index 3644e87..4e34d8e 100644 --- a/src/soc/intel/xeon_sp/spr/acpi/cxl_resource.asl +++ b/src/soc/intel/xeon_sp/spr/acpi/cxl_resource.asl @@ -8,6 +8,9 @@ #define _IIO_DEVICE_UID(str, skt, stk) STR(str##skt##stk) #define IIO_DEVICE_UID(str, skt, stk) _IIO_DEVICE_UID(str, skt, stk)
+#define _SEG_NAME(str, skt) str##skt +#define SEG_NAME(str, skt) _SEG_NAME(str, skt) + Device (IIO_DEVICE_NAME(DEVPREFIX, SOCKET, STACK)) { Name (_HID, "ACPI0017") /* CXL */ @@ -18,6 +21,10 @@ }) Name (_UID, IIO_DEVICE_UID(DEVPREFIX, SOCKET, STACK)) External (_SB.IIO_DEVICE_NAME(STPREFIX, SOCKET, STACK)) + + External (_SB.SEG_NAME(SEG, SOCKET)) + Name (_SEG, _SB.SEG_NAME(SEG, SOCKET)) + Method (_STA, 0, NotSerialized) // _STA: Status { Return (_SB.IIO_DEVICE_NAME(STPREFIX, SOCKET, STACK)) diff --git a/src/soc/intel/xeon_sp/spr/acpi/pci_resource.asl b/src/soc/intel/xeon_sp/spr/acpi/pci_resource.asl index a369b11..945632b 100644 --- a/src/soc/intel/xeon_sp/spr/acpi/pci_resource.asl +++ b/src/soc/intel/xeon_sp/spr/acpi/pci_resource.asl @@ -8,11 +8,18 @@ #define _IIO_DEVICE_UID(str, skt, stk) STR(str##skt##stk) #define IIO_DEVICE_UID(str, skt, stk) _IIO_DEVICE_UID(str, skt, stk)
+#define _SEG_NAME(str, skt) str##skt +#define SEG_NAME(str, skt) _SEG_NAME(str, skt) + Device (IIO_DEVICE_NAME(DEVPREFIX, SOCKET, STACK)) { Name (_HID, EisaId ("PNP0A08") /* PCI Express Bus */) Name (_CID, EisaId ("PNP0A03") /* PCI Bus */) Name (_UID, IIO_DEVICE_UID(DEVPREFIX, SOCKET, STACK)) + + External (_SB.SEG_NAME(SEG, SOCKET)) + Name (_SEG, _SB.SEG_NAME(SEG, SOCKET)) + External (_SB.IIO_DEVICE_NAME(STPREFIX, SOCKET, STACK)) Method (_STA, 0, NotSerialized) { diff --git a/src/soc/intel/xeon_sp/spr/chip.c b/src/soc/intel/xeon_sp/spr/chip.c index 3b3c65e..add6cd3 100644 --- a/src/soc/intel/xeon_sp/spr/chip.c +++ b/src/soc/intel/xeon_sp/spr/chip.c @@ -80,10 +80,10 @@ } }
-static void pcu_pci_or_config32(u8 bus, u8 func, u32 reg, u32 orval) +static void pcu_pci_or_config32(u8 seg, u8 bus, u8 func, u32 reg, u32 orval) { u32 data; - const uint32_t pcie_offset = PCI_DEV(bus, PCU_DEV, func); + const uint32_t pcie_offset = PCI_DEV((seg << 8) | bus, PCU_DEV, func);
data = pci_s_read_config32(pcie_offset, reg); data |= orval; @@ -96,28 +96,29 @@ if (!soc_cpu_is_enabled(socket)) continue; const uint32_t bus = get_ubox_busno(socket, UNCORE_BUS_1); + const uint8_t seg = get_socket_pci_segment(socket);
/* configure PCU_CR0_FUN csrs */ - pcu_pci_or_config32(bus, PCU_CR0_FUN, PCU_CR0_P_STATE_LIMITS, + pcu_pci_or_config32(seg, bus, PCU_CR0_FUN, PCU_CR0_P_STATE_LIMITS, P_STATE_LIMITS_LOCK); - pcu_pci_or_config32(bus, PCU_CR0_FUN, PCU_CR0_PACKAGE_RAPL_LIMIT_UPR, + pcu_pci_or_config32(seg, bus, PCU_CR0_FUN, PCU_CR0_PACKAGE_RAPL_LIMIT_UPR, PKG_PWR_LIM_LOCK_UPR); - pcu_pci_or_config32(bus, PCU_CR0_FUN, PCU_CR0_TURBO_ACTIVATION_RATIO, + pcu_pci_or_config32(seg, bus, PCU_CR0_FUN, PCU_CR0_TURBO_ACTIVATION_RATIO, TURBO_ACTIVATION_RATIO_LOCK);
/* configure PCU_CR2_FUN csrs */ - pcu_pci_or_config32(bus, PCU_CR2_FUN, PCU_CR2_DRAM_POWER_INFO_UPR, + pcu_pci_or_config32(seg, bus, PCU_CR2_FUN, PCU_CR2_DRAM_POWER_INFO_UPR, DRAM_POWER_INFO_LOCK_UPR); - pcu_pci_or_config32(bus, PCU_CR2_FUN, PCU_CR2_DRAM_PLANE_POWER_LIMIT_UPR, + pcu_pci_or_config32(seg, bus, PCU_CR2_FUN, PCU_CR2_DRAM_PLANE_POWER_LIMIT_UPR, PP_PWR_LIM_LOCK_UPR);
/* configure PCU_CR3_FUN csrs */ - pcu_pci_or_config32(bus, PCU_CR3_FUN, PCU_CR3_CONFIG_TDP_CONTROL, TDP_LOCK); + pcu_pci_or_config32(seg, bus, PCU_CR3_FUN, PCU_CR3_CONFIG_TDP_CONTROL, TDP_LOCK);
/* configure PCU_CR6_FUN csrs */ - pcu_pci_or_config32(bus, PCU_CR6_FUN, PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_UPR, + pcu_pci_or_config32(seg, bus, PCU_CR6_FUN, PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_UPR, PLT_PWR_LIM_LOCK_UPR); - pcu_pci_or_config32(bus, PCU_CR6_FUN, PCU_CR6_PLATFORM_POWER_INFO_CFG_UPR, + pcu_pci_or_config32(seg, bus, PCU_CR6_FUN, PCU_CR6_PLATFORM_POWER_INFO_CFG_UPR, PLT_PWR_INFO_LOCK_UPR); } } diff --git a/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h index 06ec16c..5219298 100644 --- a/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h +++ b/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h @@ -38,9 +38,9 @@ #define SAD_ALL_PAM456_CSR 0x84
#if !defined(__SIMPLE_DEVICE__) -#define _PCU_DEV(bus, func) pcidev_path_on_bus(bus, PCI_DEVFN(PCU_DEV, func)) +#define _PCU_DEV(seg, bus, func) pcidev_path_on_segbus((seg), (bus), PCI_DEVFN(PCU_DEV, func)) #else -#define _PCU_DEV(bus, func) PCI_DEV(bus, PCU_DEV, func) +#define _PCU_DEV(seg, bus, func) PCI_DEV(((seg) << 8) | (bus), PCU_DEV, func) #endif
/* PCU [B:31, D:30, F:0->F:6] */ @@ -48,7 +48,7 @@ #define PCU_DEV 30
#define PCU_CR0_FUN 0 -#define PCU_DEV_CR0(bus) _PCU_DEV(bus, PCU_CR0_FUN) +#define PCU_DEV_CR0(seg, bus) _PCU_DEV(seg, bus, PCU_CR0_FUN) #define PCU_CR0_PLATFORM_INFO 0xa8 #define PCU_CR0_TURBO_ACTIVATION_RATIO 0xb0 #define TURBO_ACTIVATION_RATIO_LOCK BIT(31) @@ -63,7 +63,7 @@ #define VR_CURRENT_CONFIG_LOCK BIT(31)
#define PCU_CR1_FUN 1 -#define PCU_DEV_CR1(bus) _PCU_DEV(bus, PCU_CR1_FUN) +#define PCU_DEV_CR1(seg, bus) _PCU_DEV(seg, bus, PCU_CR1_FUN) #define PCU_CR1_BIOS_MB_DATA_REG 0x8c
#define PCU_CR1_BIOS_MB_INTERFACE_REG 0x90 @@ -87,7 +87,7 @@ #define PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK BIT(31)
#define PCU_CR2_FUN 2 -#define PCU_DEV_CR2(bus) _PCU_DEV(bus, PCU_CR2_FUN) +#define PCU_DEV_CR2(seg, bus) _PCU_DEV(seg, bus, PCU_CR2_FUN) #define PCU_CR2_DRAM_POWER_INFO_LWR 0xa8 #define PCU_CR2_DRAM_POWER_INFO_UPR (PCU_CR2_DRAM_POWER_INFO_LWR + 4) #define DRAM_POWER_INFO_LOCK_UPR BIT(31) @@ -99,7 +99,7 @@ #define PCU_CR3_FUN 3 #define PCU_CR3_CAPID4 0x94 #define ERR_SPOOFING_DIS 1 -#define PCU_DEV_CR3(bus) _PCU_DEV(bus, PCU_CR3_FUN) +#define PCU_DEV_CR3(seg, bus) _PCU_DEV(seg, bus, PCU_CR3_FUN) #define PCU_CR3_CONFIG_TDP_CONTROL 0xd8 #define TDP_LOCK BIT(31) #define PCU_CR3_FLEX_RATIO 0xa0 @@ -113,7 +113,7 @@ #define PCU_EMCA_MODE (1 << 2)
#define PCU_CR6_FUN 6 -#define PCU_DEV_CR6(bus) _PCU_DEV(bus, PCU_CR6_FUN) +#define PCU_DEV_CR6(seg, bus) _PCU_DEV(seg, bus, PCU_CR6_FUN) #define PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_LWR 0xa8 #define PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_UPR (PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_LWR + 4) #define PLT_PWR_LIM_LOCK_UPR BIT(31) @@ -148,9 +148,9 @@ #define VTD_FUNC_NUM 0x0
#if !defined(__SIMPLE_DEVICE__) -#define VTD_DEV(bus) pcidev_path_on_bus((bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) +#define VTD_DEV(seg, bus) pcidev_path_on_segbus((seg), (bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) #else -#define VTD_DEV(bus) PCI_DEV((bus), VTD_DEV_NUM, VTD_FUNC_NUM) +#define VTD_DEV(seg, bus) PCI_DEV(((seg) << 8) | (bus), VTD_DEV_NUM, VTD_FUNC_NUM) #endif
/* Root port Registers */ diff --git a/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h b/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h index 997cdb4..6f8ac18 100644 --- a/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h +++ b/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h @@ -32,6 +32,7 @@ const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num);
uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack); +uint8_t get_socket_pci_segment(uint32_t socket);
bool is_iio_cxl_stack_res(const STACK_RES *res);
diff --git a/src/soc/intel/xeon_sp/spr/ioat.c b/src/soc/intel/xeon_sp/spr/ioat.c index 8cc22c6..b4a2a7e 100644 --- a/src/soc/intel/xeon_sp/spr/ioat.c +++ b/src/soc/intel/xeon_sp/spr/ioat.c @@ -48,6 +48,7 @@ bus->secondary = bus_base; bus->subordinate = bus->secondary; bus->max_subordinate = bus_limit; + bus->segment = upstream->segment;
unsigned int index = 0;
diff --git a/src/soc/intel/xeon_sp/spr/soc_acpi.c b/src/soc/intel/xeon_sp/spr/soc_acpi.c index aab6e1f..69d370e 100644 --- a/src/soc/intel/xeon_sp/spr/soc_acpi.c +++ b/src/soc/intel/xeon_sp/spr/soc_acpi.c @@ -338,6 +338,18 @@ acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_ON); }
+/* + * Add a DSDT ACPI PCI segment. + * This is retrieved by the device _SEG defined in iiostack.asl + */ +static void create_dsdt_seg(uint8_t socket) +{ + char stack_seg[8]; + snprintf(stack_seg, sizeof(stack_seg), "SEG%d", socket); + + acpigen_write_name_integer(stack_seg, get_socket_pci_segment(socket)); +} + void uncore_inject_dsdt(const struct device *device) { bool stack_enabled; @@ -368,6 +380,7 @@ const IIO_UDS *hob = get_iio_uds(); /* Iterate over CONFIG_MAX_SOCKET to keep ASL templates and DSDT injection in sync */ for (uint8_t socket = 0; socket < CONFIG_MAX_SOCKET; ++socket) { + create_dsdt_seg(socket); for (int stack = 0; stack < MAX_LOGIC_IIO_STACK; ++stack) { const STACK_RES *ri = &hob->PlatformData.IIO_resource[socket].StackRes[stack]; diff --git a/src/soc/intel/xeon_sp/spr/soc_smihandler_util.c b/src/soc/intel/xeon_sp/spr/soc_smihandler_util.c index b2700d5..e235cb5 100644 --- a/src/soc/intel/xeon_sp/spr/soc_smihandler_util.c +++ b/src/soc/intel/xeon_sp/spr/soc_smihandler_util.c @@ -15,5 +15,6 @@ else return 0;
+ /* FIXME: Segment handling? */ return PCI_DEV(bus, UBOX_DECS_DEV, UBOX_URACU_FUNC); } diff --git a/src/soc/intel/xeon_sp/spr/soc_util.c b/src/soc/intel/xeon_sp/spr/soc_util.c index 86fe803..57bd904 100644 --- a/src/soc/intel/xeon_sp/spr/soc_util.c +++ b/src/soc/intel/xeon_sp/spr/soc_util.c @@ -139,6 +139,19 @@ return hob->PlatformData.IIO_resource[socket].StackRes[stack].BusBase; }
+uint8_t get_socket_pci_segment(uint32_t socket) +{ + const IIO_UDS *hob = get_iio_uds(); + uint8_t seg; + + assert(socket < MAX_SOCKET); + + seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + assert(seg < CONFIG_ECAM_SEGMENT_COUNT); + + return seg; +} + uint32_t get_ubox_busno(uint32_t socket, uint8_t offset) { const IIO_UDS *hob = get_iio_uds(); diff --git a/src/soc/intel/xeon_sp/uncore_acpi.c b/src/soc/intel/xeon_sp/uncore_acpi.c index e2b47329..8376d52f 100644 --- a/src/soc/intel/xeon_sp/uncore_acpi.c +++ b/src/soc/intel/xeon_sp/uncore_acpi.c @@ -222,10 +222,10 @@ */ static unsigned long acpi_create_dmar_ds_pci_br_for_port(unsigned long current, const struct device *bridge_dev, - uint32_t pcie_seg, bool is_atsr, bool *first) { - const uint32_t bus = bridge_dev->bus->secondary; + const uint8_t bus = bridge_dev->bus->secondary; + const uint8_t seg = bridge_dev->bus->segment; const uint32_t dev = PCI_SLOT(bridge_dev->path.pci.devfn); const uint32_t func = PCI_FUNC(bridge_dev->path.pci.devfn);
@@ -236,14 +236,14 @@ unsigned long pci_br_size = 0; if (is_atsr == true && first && *first == true) { printk(BIOS_DEBUG, "[Root Port ATS Capability] Flags: 0x%x, " - "PCI Segment Number: 0x%x\n", 0, pcie_seg); - atsr_size = acpi_create_dmar_atsr(current, 0, pcie_seg); + "PCI Segment Number: 0x%x\n", 0, seg); + atsr_size = acpi_create_dmar_atsr(current, 0, seg); *first = false; }
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); + 0, bus, dev, func); pci_br_size = acpi_create_dmar_ds_pci_br(current + atsr_size, bus, dev, func);
return (atsr_size + pci_br_size); @@ -255,7 +255,7 @@ unsigned long tmp = current; const STACK_RES *ri = &hob->PlatformData.IIO_resource[socket].StackRes[stack]; const uint32_t bus = ri->BusBase; - const uint32_t pcie_seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + const uint8_t pcie_seg = get_socket_pci_segment(socket); const uint32_t reg_base = ri->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); @@ -312,12 +312,12 @@
// Add PCIe Ports if (socket != 0 || stack != IioStack0) { - struct device *dev = pcidev_path_on_bus(bus, PCI_DEVFN(0, 0)); + struct device *dev = pcidev_path_on_segbus(pcie_seg, bus, PCI_DEVFN(0, 0)); while (dev) { if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) current += acpi_create_dmar_ds_pci_br_for_port( - current, dev, pcie_seg, false, NULL); + current, dev, false, NULL);
dev = dev->sibling; } @@ -339,7 +339,7 @@ // Add DINO End Points (with memory resources. We don't report every End Point device.) if (ri->Personality == TYPE_DINO) { for (int b = ri->BusBase; b <= ri->BusLimit; ++b) { - struct device *dev = pcidev_path_on_bus(b, PCI_DEVFN(0, 0)); + struct device *dev = pcidev_path_on_segbus(pcie_seg, b, PCI_DEVFN(0, 0)); while (dev) { /* This may also require a check for IORESOURCE_PREFETCH, * but that would not include the FPU (4942/0) */ @@ -389,7 +389,7 @@ continue; iio++;
- uint32_t pcie_seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment; + const uint8_t pcie_seg = get_socket_pci_segment(socket); unsigned long tmp = current; bool first = true; IIO_RESOURCE_INSTANCE iio_resource = @@ -414,12 +414,12 @@ if (bus == 0) continue;
- struct device *dev = pcidev_path_on_bus(bus, PCI_DEVFN(0, 0)); + struct device *dev = pcidev_path_on_segbus(pcie_seg, bus, PCI_DEVFN(0, 0)); while (dev) { if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) current += acpi_create_dmar_ds_pci_br_for_port( - current, dev, pcie_seg, true, &first); + current, dev, true, &first);
dev = dev->sibling; } @@ -490,10 +490,12 @@
/* Skylake-SP doesn't have DINO but not sure how to verify this on CPX */ #if CONFIG(SOC_INTEL_SAPPHIRERAPIDS_SP) || CONFIG(SOC_INTEL_COOPERLAKE_SP) -static unsigned long xeonsp_create_satc_dino(unsigned long current, const STACK_RES *ri) +static unsigned long xeonsp_create_satc_dino(int socket, unsigned long current, const STACK_RES *ri) { + const uint8_t pcie_seg = get_socket_pci_segment(socket); + for (int b = ri->BusBase; b <= ri->BusLimit; ++b) { - struct device *dev = pcidev_path_on_bus(b, PCI_DEVFN(0, 0)); + struct device *dev = pcidev_path_on_segbus(pcie_seg, b, PCI_DEVFN(0, 0)); while (dev) { if (pciexp_find_extended_cap(dev, PCIE_EXT_CAP_ID_ATS, 0)) { const uint32_t d = PCI_SLOT(dev->path.pci.devfn); @@ -525,7 +527,7 @@ const STACK_RES *ri = &hob->PlatformData.IIO_resource[socket].StackRes[stack]; // Add the DINO ATS devices to the SATC if (ri->Personality == TYPE_DINO) - current = xeonsp_create_satc_dino(current, ri); + current = xeonsp_create_satc_dino(socket, current, ri); } }
diff --git a/src/soc/intel/xeon_sp/util.c b/src/soc/intel/xeon_sp/util.c index c9f4c55..61ff409 100644 --- a/src/soc/intel/xeon_sp/util.c +++ b/src/soc/intel/xeon_sp/util.c @@ -23,8 +23,9 @@ /* section 16.3.19 of Intel doc. #612246 */ uint32_t pam0123_lock = 0x33333331; uint32_t bus1 = get_socket_ubox_busno(0); + const uint8_t seg = get_socket_pci_segment(0);
- pci_s_write_config32(PCI_DEV(bus1, SAD_ALL_DEV, SAD_ALL_FUNC), + pci_s_write_config32(PCI_DEV((seg << 8) | bus1, SAD_ALL_DEV, SAD_ALL_FUNC), SAD_ALL_PAM0123_CSR, pam0123_lock); }
@@ -33,15 +34,16 @@ uint32_t pam0123_unlock_dram = 0x33333330; uint32_t pam456_unlock_dram = 0x00333333; uint32_t bus1 = get_socket_ubox_busno(0); + const uint8_t seg = get_socket_pci_segment(0);
- pci_io_write_config32(PCI_DEV(bus1, SAD_ALL_DEV, SAD_ALL_FUNC), + pci_io_write_config32(PCI_DEV((seg << 8) | 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), + pci_io_write_config32(PCI_DEV((seg << 8) | 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, + uint32_t reg1 = pci_io_read_config32(PCI_DEV((seg << 8) | bus1, SAD_ALL_DEV, SAD_ALL_FUNC), SAD_ALL_PAM0123_CSR); - uint32_t reg2 = pci_io_read_config32(PCI_DEV(bus1, SAD_ALL_DEV, + uint32_t reg2 = pci_io_read_config32(PCI_DEV((seg << 8) | 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); @@ -188,7 +190,8 @@ uint32_t pcode_init_mask, uint32_t val) { const uint32_t bus = get_socket_ubox_busno(socket); - const pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN); + const uint8_t seg = get_socket_pci_segment(socket); + const pci_devfn_t dev = PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR1_FUN);
uint32_t reg = pci_s_read_config32(dev, PCU_CR1_BIOS_RESET_CPL_REG); reg &= (uint32_t)~rst_cpl_mask; @@ -207,7 +210,8 @@ uint32_t data; bool timedout; const uint32_t bus = get_socket_ubox_busno(socket); - const pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN); + const uint8_t seg = get_socket_pci_segment(socket); + const pci_devfn_t dev = PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR1_FUN);
/* read PCU config */ timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0); @@ -233,9 +237,9 @@ die("BIOS RESET CPL3 timed out.\n");
/* Set PMAX_LOCK - must be set before RESET CPL4 */ - data = pci_s_read_config32(PCI_DEV(bus, PCU_DEV, PCU_CR0_FUN), PCU_CR0_PMAX); + data = pci_s_read_config32(PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR0_FUN), PCU_CR0_PMAX); data |= PMAX_LOCK; - pci_s_write_config32(PCI_DEV(bus, PCU_DEV, PCU_CR0_FUN), PCU_CR0_PMAX, data); + pci_s_write_config32(PCI_DEV((seg << 8) | bus, PCU_DEV, PCU_CR0_FUN), PCU_CR0_PMAX, data);
/* update RST_CPL4, PCODE_INIT_DONE4 */ timedout = set_bios_reset_cpl_for_package(socket, RST_CPL4_MASK,