Attention is currently required from: Arthur Heymans, Christian Walter, Johnny Lin, Tim Chu.

Patrick Rudolph has uploaded this change for review.

View Change

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,

To view, visit change 79878. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: main
Gerrit-Change-Id: I0ba5e426123234979d746d3bdfc1ddfbd71c3447
Gerrit-Change-Number: 79878
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-Reviewer: Arthur Heymans <arthur@aheymans.xyz>
Gerrit-Reviewer: Christian Walter <christian.walter@9elements.com>
Gerrit-Reviewer: Johnny Lin <Johnny_Lin@wiwynn.com>
Gerrit-Reviewer: Tim Chu <Tim.Chu@quantatw.com>
Gerrit-Attention: Johnny Lin <Johnny_Lin@wiwynn.com>
Gerrit-Attention: Christian Walter <christian.walter@9elements.com>
Gerrit-Attention: Arthur Heymans <arthur@aheymans.xyz>
Gerrit-Attention: Tim Chu <Tim.Chu@quantatw.com>
Gerrit-MessageType: newchange