summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/xeon_sp/Kconfig3
-rw-r--r--src/soc/intel/xeon_sp/acpi.c2
-rw-r--r--src/soc/intel/xeon_sp/chip_common.c580
-rw-r--r--src/soc/intel/xeon_sp/cpx/chip.c6
-rw-r--r--src/soc/intel/xeon_sp/cpx/soc_util.c7
-rw-r--r--src/soc/intel/xeon_sp/include/soc/chip_common.h8
-rw-r--r--src/soc/intel/xeon_sp/include/soc/util.h3
-rw-r--r--src/soc/intel/xeon_sp/memmap.c2
-rw-r--r--src/soc/intel/xeon_sp/skx/chip.c6
-rw-r--r--src/soc/intel/xeon_sp/skx/soc_util.c7
-rw-r--r--src/soc/intel/xeon_sp/spr/Kconfig1
-rw-r--r--src/soc/intel/xeon_sp/spr/Makefile.inc2
-rw-r--r--src/soc/intel/xeon_sp/spr/chip.c6
-rw-r--r--src/soc/intel/xeon_sp/spr/ioat.c130
-rw-r--r--src/soc/intel/xeon_sp/spr/soc_acpi.c41
-rw-r--r--src/soc/intel/xeon_sp/spr/soc_util.c7
-rw-r--r--src/soc/intel/xeon_sp/util.c2
17 files changed, 269 insertions, 544 deletions
diff --git a/src/soc/intel/xeon_sp/Kconfig b/src/soc/intel/xeon_sp/Kconfig
index 1eee8694a3c4..09310300dceb 100644
--- a/src/soc/intel/xeon_sp/Kconfig
+++ b/src/soc/intel/xeon_sp/Kconfig
@@ -107,4 +107,7 @@ config SOC_INTEL_XEON_RAS
select SOC_ACPI_HEST
select SOC_RAS_ELOG
+config HAVE_IOAT_DOMAINS
+ bool
+
endif ## SOC_INTEL_XEON_SP
diff --git a/src/soc/intel/xeon_sp/acpi.c b/src/soc/intel/xeon_sp/acpi.c
index 519d6c7c768a..61d51862f52e 100644
--- a/src/soc/intel/xeon_sp/acpi.c
+++ b/src/soc/intel/xeon_sp/acpi.c
@@ -104,7 +104,7 @@ size_t soc_get_ioapic_info(const uintptr_t *ioapic_bases[])
for (int stack = 0; stack < MAX_IIO_STACK; ++stack) {
const STACK_RES *ri =
&hob->PlatformData.IIO_resource[socket].StackRes[stack];
- if (!is_iio_stack_res(ri))
+ if (!stack_needs_resource_alloc(ri))
continue;
uint32_t ioapic_base = ri->IoApicBase;
assert(index < ARRAY_SIZE(xeonsp_ioapic_bases));
diff --git a/src/soc/intel/xeon_sp/chip_common.c b/src/soc/intel/xeon_sp/chip_common.c
index a9b1260646aa..c1b331bc6663 100644
--- a/src/soc/intel/xeon_sp/chip_common.c
+++ b/src/soc/intel/xeon_sp/chip_common.c
@@ -9,548 +9,122 @@
#include <soc/util.h>
#include <stdlib.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;
-};
-
-typedef enum {
- RES_TYPE_IO = 0,
- RES_TYPE_NONPREF_MEM,
- RES_TYPE_PREF_MEM,
- MAX_RES_TYPES
-} RES_TYPE;
-
-static RES_TYPE get_res_type(uint64_t flags)
-{
- if (flags & IORESOURCE_IO)
- return RES_TYPE_IO;
- if (flags & IORESOURCE_MEM) {
- if (flags & IORESOURCE_PREFETCH) {
- printk(BIOS_DEBUG, "%s:%d flags: 0x%llx\n", __func__, __LINE__, flags);
- return RES_TYPE_PREF_MEM;
- }
- /* both 64-bit and 32-bit use below 4GB address space */
- return RES_TYPE_NONPREF_MEM;
- }
- die("Invalid resource type 0x%llx\n", flags);
-}
-
-static bool need_assignment(uint64_t flags)
-{
- if (flags & (IORESOURCE_STORED | IORESOURCE_RESERVE | IORESOURCE_FIXED |
- IORESOURCE_ASSIGNED))
- return false;
- else
- return true;
-}
-
-static uint64_t get_resource_base(STACK_RES *stack, RES_TYPE res_type)
-{
- if (res_type == RES_TYPE_IO) {
- assert(stack->PciResourceIoBase <= stack->PciResourceIoLimit);
- return stack->PciResourceIoBase;
- }
- if (res_type == RES_TYPE_NONPREF_MEM) {
- assert(stack->PciResourceMem32Base <= stack->PciResourceMem32Limit);
- return stack->PciResourceMem32Base;
- }
- assert(stack->PciResourceMem64Base <= stack->PciResourceMem64Limit);
- return stack->PciResourceMem64Base;
-}
-
-static void set_resource_base(STACK_RES *stack, RES_TYPE res_type, uint64_t base)
+static const STACK_RES *domain_to_stack_res(const struct device *dev)
{
- if (res_type == RES_TYPE_IO) {
- assert(base <= (stack->PciResourceIoLimit + 1));
- stack->PciResourceIoBase = base;
- } else if (res_type == RES_TYPE_NONPREF_MEM) {
- assert(base <= (stack->PciResourceMem32Limit + 1));
- stack->PciResourceMem32Base = base;
- } else {
- assert(base <= (stack->PciResourceMem64Limit + 1));
- stack->PciResourceMem64Base = base;
- }
-}
+ assert(dev->path.type == DEVICE_PATH_DOMAIN);
+ const unsigned int dn = dev->path.domain.domain;
-static void assign_stack_resources(struct iiostack_resource *stack_list,
- struct device *dev, struct resource *bridge);
-
-void xeonsp_pci_domain_scan_bus(struct device *dev)
-{
- DEV_FUNC_ENTER(dev);
- struct bus *link = dev->link_list;
+ const IIO_UDS *hob = get_iio_uds();
+ assert(hob != NULL);
- printk(BIOS_SPEW, "%s:%s scanning buses under device %s\n",
- __FILE__, __func__, dev_path(dev));
- while (link) {
- 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);
+ return &hob->PlatformData.IIO_resource[dn / MAX_LOGIC_IIO_STACK].StackRes[dn % MAX_LOGIC_IIO_STACK];
}
-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)
+void iio_pci_domain_read_resources(struct device *dev)
{
- struct device *curdev;
struct resource *res;
+ const STACK_RES *sr = domain_to_stack_res(dev);
- /* 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) /* 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) {
- 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 && nr->align == res->align);
+ if (!sr)
+ return;
- struct pci_resource *npr = malloc(sizeof(struct pci_resource));
- if (!npr)
- die("%s: out of memory.\n", __func__);
- npr->res = res;
- npr->dev = dev;
- npr->next = NULL;
+ int index = 0;
- if (!nr->children) {
- nr->children = npr;
- } else {
- struct pci_resource *pr = nr->children;
- while (pr->next)
- pr = pr->next;
- pr->next = npr;
+ if (dev->path.domain.domain == 0) {
+ /* The 0 - 0xfff IO range is not reported by the HOB but still gets decoded */
+ res = new_resource(dev, index++);
+ res->base = 0;
+ res->size = 0x1000;
+ res->limit = 0xfff;
+ res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
}
-}
-
-static void reserve_dev_resources(STACK_RES *stack, RES_TYPE res_type,
- struct stack_dev_resource *res_root, struct resource *bridge)
-{
- uint64_t orig_base, base;
-
- orig_base = get_resource_base(stack, res_type);
- 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 (sr->PciResourceIoBase < sr->PciResourceIoLimit) {
+ res = new_resource(dev, index++);
+ res->base = sr->PciResourceIoBase;
+ res->limit = sr->PciResourceIoLimit;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED;
}
- 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;
+ if (sr->PciResourceMem32Base < sr->PciResourceMem32Limit) {
+ res = new_resource(dev, index++);
+ res->base = sr->PciResourceMem32Base;
+ res->limit = sr->PciResourceMem32Limit;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
}
- set_resource_base(stack, res_type, 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);
+ if (sr->PciResourceMem64Base < sr->PciResourceMem64Limit) {
+ res = new_resource(dev, index++);
+ res->base = sr->PciResourceMem64Base;
+ res->limit = sr->PciResourceMem64Limit;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
}
}
-static void assign_bridge_resources(struct iiostack_resource *stack_list,
- struct device *dev, struct resource *bridge)
+void iio_pci_domain_scan_bus(struct device *dev)
{
- struct resource *res;
- if (!dev->enabled)
+ const STACK_RES *sr = domain_to_stack_res(dev);
+ if (!sr)
return;
- for (res = dev->resource_list; res; res = res->next) {
- if (!(res->flags & IORESOURCE_BRIDGE) ||
- (bridge && (get_res_type(bridge->flags) != get_res_type(res->flags))))
- 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);
+ if (!dev->link_list) {
+ dev->link_list = calloc(1, sizeof(struct bus));
+ if (!dev->link_list)
+ die("%s: out of memory.\n", __func__);
}
-}
-
-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);
-
- /* 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 */
- RES_TYPE res_types[MAX_RES_TYPES] = {
- RES_TYPE_IO,
- RES_TYPE_NONPREF_MEM,
- RES_TYPE_PREF_MEM
- };
- uint8_t no_res_types = MAX_RES_TYPES;
+ struct bus *bus = dev->link_list;
+ bus->secondary = sr->BusBase;
+ bus->subordinate = sr->BusBase;
+ bus->max_subordinate = sr->BusLimit;
- /* if it is a bridge, only process matching bridge resource type */
- if (bridge) {
- res_types[0] = get_res_type(bridge->flags);
- no_res_types = 1;
- }
-
- printk(BIOS_DEBUG, "%s:%d no_res_types: %d\n", __func__, __LINE__,
- no_res_types);
-
- /* Process each resource type */
- for (int rt = 0; rt < no_res_types; ++rt) {
- struct stack_dev_resource *res_root = NULL;
- printk(BIOS_DEBUG, "%s:%d rt: %d\n", __func__, __LINE__, rt);
- for (curdev = bus->children; curdev; curdev = curdev->sibling) {
- struct resource *res;
- printk(BIOS_DEBUG, "%s:%d dev: %s\n",
- __func__, __LINE__, dev_path(curdev));
- if (!curdev->enabled)
- continue;
-
- for (res = curdev->resource_list; res; res = res->next) {
- printk(BIOS_DEBUG, "%s:%d dev: %s, flags: 0x%lx\n",
- __func__, __LINE__,
- dev_path(curdev), res->flags);
- if (res->size == 0 ||
- get_res_type(res->flags) != res_types[rt] ||
- (res->flags & IORESOURCE_BRIDGE) ||
- !need_assignment(res->flags))
- 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, res_types[rt], res_root, bridge);
- reclaim_resource_mem(res_root);
- }
- }
- }
+ printk(BIOS_SPEW, "Scanning IIO stack %d: busses %x-%x\n", dev->path.domain.domain,
+ dev->link_list->secondary, dev->link_list->max_subordinate);
+ pci_host_bridge_scan_bus(dev);
}
-static uint8_t is_pci64bit_alloc(void)
-{
/*
- * For SPR-SP FSP which supports SOC_INTEL_PCIE_64BITS_ALLOC,
- * Pci64BitResourceAllocation field does not exist in IIO_UDS HOB.
+ * Used by IIO stacks for PCIe bridges. Those contain 1 PCI host bridges,
+ * all the bus numbers on the IIO stack can be used for this bridge
*/
-#if CONFIG(SOC_INTEL_PCIE_64BIT_ALLOC)
- return 1;
-#else
- const IIO_UDS *hob = get_iio_uds();
- return hob->PlatformData.Pci64BitResourceAllocation;
-#endif
-}
-
-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);
-
- struct iiostack_resource stack_info = {0};
- get_iiostack_info(&stack_info);
- if (!is_pci64bit_alloc()) {
- /*
- * Split 32 bit address space between prefetchable and
- * non-prefetchable windows
- */
- for (int s = 0; s < stack_info.no_of_stacks; ++s) {
- STACK_RES *res = &stack_info.res[s];
- uint64_t length = (res->PciResourceMem32Limit -
- res->PciResourceMem32Base + 1)/2;
- res->PciResourceMem64Limit = res->PciResourceMem32Limit;
- res->PciResourceMem32Limit = (res->PciResourceMem32Base + length - 1);
- res->PciResourceMem64Base = res->PciResourceMem32Limit + 1;
- }
- }
-
- /* 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;
- }
-}
-
-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) {
- 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 iio_pcie_domain_ops = {
+ .read_resources = iio_pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .scan_bus = iio_pci_domain_scan_bus,
+};
-/* Attach IIO stack bus numbers with dummy device to PCI DOMAIN 0000 device */
+/* Attach IIO stack as domains */
void attach_iio_stacks(struct device *dev)
{
- struct device dummy;
- struct iiostack_resource stack_info = {0};
-
- DEV_FUNC_ENTER(dev);
-
- get_iiostack_info(&stack_info);
+ const IIO_UDS *hob = get_iio_uds();
+ if (!hob)
+ return;
- for (int s = 0; s < stack_info.no_of_stacks; ++s) {
- STACK_RES *sr = &stack_info.res[s];
- /* only non zero bus no. needs to be enumerated */
- if (sr->BusBase == 0) {
- /* Update BUS 0 BusLimit */
- dev->link_list->max_subordinate = sr->BusLimit;
- continue;
- }
+ for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
+ for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
+ if (s == 0 && x == 0)
+ continue;
- for (int b = sr->BusBase; b <= sr->BusLimit; ++b) {
- struct bus tmp_bus;
- memset(&tmp_bus, 0, sizeof(tmp_bus));
- memcpy(&tmp_bus, dev->bus, sizeof(tmp_bus));
- tmp_bus.secondary = b;
- tmp_bus.subordinate = b;
- tmp_bus.max_subordinate = sr->BusLimit;
- tmp_bus.dev = NULL;
- tmp_bus.children = NULL;
- tmp_bus.next = NULL;
- tmp_bus.link_num = 1;
+ const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
+ if (!stack_needs_resource_alloc(ri))
+ continue;
- dummy.bus = &tmp_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_DEBUG, "IIO Stack device %s not visible\n",
- dev_path(&dummy));
+ if (!is_pcie_iio_stack_res(ri)) {
+ if (CONFIG(HAVE_IOAT_DOMAINS))
+ soc_create_ioat_domains(dev->bus, ri);
continue;
}
- printk(BIOS_DEBUG, "%s Attaching IIO Bus %s\n", __func__,
- dev_path(&dummy));
- printk(BIOS_DEBUG, " %s attach secondary: 0x%x, subordinate: 0x%x, dev: %s\n",
- __func__, tmp_bus.secondary,
- tmp_bus.subordinate, dev_path(&dummy));
-
- struct bus *iiostack_bus = malloc(sizeof(struct bus));
- if (iiostack_bus == NULL)
+ struct device_path path;
+ path.type = DEVICE_PATH_DOMAIN;
+ path.domain.domain = s * MAX_LOGIC_IIO_STACK + x;
+ struct device *iio_domain = alloc_dev(dev->bus, &path);
+ if (iio_domain == NULL)
die("%s: out of memory.\n", __func__);
- memcpy(iiostack_bus, &tmp_bus, sizeof(*iiostack_bus));
-
- 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;
- }
+ iio_domain->ops = &iio_pcie_domain_ops;
}
}
-
- DEV_FUNC_EXIT(dev);
}
diff --git a/src/soc/intel/xeon_sp/cpx/chip.c b/src/soc/intel/xeon_sp/cpx/chip.c
index dd9c1134918f..39a7ebaae2ae 100644
--- a/src/soc/intel/xeon_sp/cpx/chip.c
+++ b/src/soc/intel/xeon_sp/cpx/chip.c
@@ -36,9 +36,9 @@ const char *soc_acpi_name(const struct device *dev)
#endif
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,
+ .read_resources = iio_pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .scan_bus = iio_pci_domain_scan_bus,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = &northbridge_write_acpi_tables,
.acpi_name = soc_acpi_name
diff --git a/src/soc/intel/xeon_sp/cpx/soc_util.c b/src/soc/intel/xeon_sp/cpx/soc_util.c
index 64efb612ca2c..e277752e5cba 100644
--- a/src/soc/intel/xeon_sp/cpx/soc_util.c
+++ b/src/soc/intel/xeon_sp/cpx/soc_util.c
@@ -25,11 +25,16 @@ const struct SystemMemoryMapHob *get_system_memory_map(void)
return *memmap_addr;
}
-bool is_iio_stack_res(const STACK_RES *res)
+bool stack_needs_resource_alloc(const STACK_RES *res)
{
return res->Personality == TYPE_UBOX_IIO;
}
+bool is_pcie_iio_stack_res(const STACK_RES *res)
+{
+ return stack_needs_resource_alloc(res);
+}
+
uint8_t get_stack_busno(const uint8_t stack)
{
if (stack >= MAX_IIO_STACK) {
diff --git a/src/soc/intel/xeon_sp/include/soc/chip_common.h b/src/soc/intel/xeon_sp/include/soc/chip_common.h
index 339da07e4ae2..ac8ba9e422ee 100644
--- a/src/soc/intel/xeon_sp/include/soc/chip_common.h
+++ b/src/soc/intel/xeon_sp/include/soc/chip_common.h
@@ -3,8 +3,12 @@
#ifndef _CHIP_COMMON_H_
#define _CHIP_COMMON_H_
-void xeonsp_pci_domain_set_resources(struct device *dev);
-void xeonsp_pci_domain_scan_bus(struct device *dev);
+#include <hob_iiouds.h>
+
+void iio_pci_domain_read_resources(struct device *dev);
+void iio_pci_domain_scan_bus(struct device *dev);
void attach_iio_stacks(struct device *dev);
+void soc_create_ioat_domains(struct bus *bus, const STACK_RES *sr);
+
#endif /* _CHIP_COMMON_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/util.h b/src/soc/intel/xeon_sp/include/soc/util.h
index 8e80c64d1415..a03c8e84049d 100644
--- a/src/soc/intel/xeon_sp/include/soc/util.h
+++ b/src/soc/intel/xeon_sp/include/soc/util.h
@@ -23,7 +23,8 @@ struct iiostack_resource {
};
void get_iiostack_info(struct iiostack_resource *info);
-bool is_iio_stack_res(const STACK_RES *res);
+bool stack_needs_resource_alloc(const STACK_RES *res);
+bool is_pcie_iio_stack_res(const STACK_RES *res);
void bios_done_msr(void *unused);
#endif
diff --git a/src/soc/intel/xeon_sp/memmap.c b/src/soc/intel/xeon_sp/memmap.c
index 8562eb191852..e73143fc78f1 100644
--- a/src/soc/intel/xeon_sp/memmap.c
+++ b/src/soc/intel/xeon_sp/memmap.c
@@ -74,7 +74,7 @@ union dpr_register txt_get_chipset_dpr(void)
for (int stack = 0; stack < MAX_IIO_STACK; ++stack) {
const STACK_RES *ri =
&hob->PlatformData.IIO_resource[socket].StackRes[stack];
- if (!is_iio_stack_res(ri))
+ if (!stack_needs_resource_alloc(ri))
continue;
uint8_t bus = ri->BusBase;
dev = VTD_DEV(bus);
diff --git a/src/soc/intel/xeon_sp/skx/chip.c b/src/soc/intel/xeon_sp/skx/chip.c
index a113d5a18647..b468842e9202 100644
--- a/src/soc/intel/xeon_sp/skx/chip.c
+++ b/src/soc/intel/xeon_sp/skx/chip.c
@@ -23,9 +23,9 @@ const char *soc_acpi_name(const struct device *dev)
#endif
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,
+ .read_resources = iio_pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .scan_bus = iio_pci_domain_scan_bus,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = &northbridge_write_acpi_tables,
.acpi_name = soc_acpi_name
diff --git a/src/soc/intel/xeon_sp/skx/soc_util.c b/src/soc/intel/xeon_sp/skx/soc_util.c
index b501a3e04fbe..d61d07489f04 100644
--- a/src/soc/intel/xeon_sp/skx/soc_util.c
+++ b/src/soc/intel/xeon_sp/skx/soc_util.c
@@ -54,12 +54,17 @@ const struct SystemMemoryMapHob *get_system_memory_map(void)
return memmap_addr;
}
-bool is_iio_stack_res(const STACK_RES *res)
+bool stack_needs_resource_alloc(const STACK_RES *res)
{
// TODO: do we have situation with only bux 0 and one stack?
return res->BusBase < res->BusLimit;
}
+bool is_pcie_iio_stack_res(const STACK_RES *res)
+{
+ return stack_needs_resource_alloc(res);
+}
+
uint8_t get_stack_busno(const uint8_t stack)
{
if (stack >= MAX_IIO_STACK) {
diff --git a/src/soc/intel/xeon_sp/spr/Kconfig b/src/soc/intel/xeon_sp/spr/Kconfig
index 396072448dcc..5a21f47b437c 100644
--- a/src/soc/intel/xeon_sp/spr/Kconfig
+++ b/src/soc/intel/xeon_sp/spr/Kconfig
@@ -12,6 +12,7 @@ config SOC_INTEL_SAPPHIRERAPIDS_SP
select PLATFORM_USES_FSP2_3
select SOC_INTEL_CSE_SERVER_SKU
select XEON_SP_COMMON_BASE
+ select HAVE_IOAT_DOMAINS
help
Intel Sapphire Rapids-SP support
diff --git a/src/soc/intel/xeon_sp/spr/Makefile.inc b/src/soc/intel/xeon_sp/spr/Makefile.inc
index 3e4f9cd32976..7a0d9586c555 100644
--- a/src/soc/intel/xeon_sp/spr/Makefile.inc
+++ b/src/soc/intel/xeon_sp/spr/Makefile.inc
@@ -13,7 +13,7 @@ romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c
romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c
ramstage-y += chip.c cpu.c soc_util.c ramstage.c soc_acpi.c xhci.c numa.c reset.c
-ramstage-y += crashlog.c
+ramstage-y += crashlog.c ioat.c
ramstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c
ramstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += soc_smihandler_util.c
diff --git a/src/soc/intel/xeon_sp/spr/chip.c b/src/soc/intel/xeon_sp/spr/chip.c
index f9c43dbe9a66..3b3c65e4a040 100644
--- a/src/soc/intel/xeon_sp/spr/chip.c
+++ b/src/soc/intel/xeon_sp/spr/chip.c
@@ -47,9 +47,9 @@ const char *soc_acpi_name(const struct device *dev)
#endif
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,
+ .read_resources = iio_pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .scan_bus = iio_pci_domain_scan_bus,
#if CONFIG(HAVE_ACPI_TABLES)
.write_acpi_tables = &northbridge_write_acpi_tables,
.acpi_name = soc_acpi_name
diff --git a/src/soc/intel/xeon_sp/spr/ioat.c b/src/soc/intel/xeon_sp/spr/ioat.c
new file mode 100644
index 000000000000..f10863a60768
--- /dev/null
+++ b/src/soc/intel/xeon_sp/spr/ioat.c
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdbool.h>
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/resource.h>
+
+#include <defs_iio.h>
+#include <hob_iiouds.h>
+#include <IioPcieConfigUpd.h>
+
+#include <soc/chip_common.h>
+
+/*
+ * Used for IIO stacks for accelerators and other functionality (IOAT).
+ * Those have only integrated PCI endpoints (no bridges) behind the host bridge.
+ */
+
+static struct device_operations ioat_domain_ops = {
+ .read_resources = noop_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .scan_bus = pci_host_bridge_scan_bus,
+};
+
+static void create_ioat_domain(struct bus *const upstream, const unsigned int domain_base,
+ const unsigned int bus_base, const unsigned int bus_limit,
+ const resource_t mem32_base, const resource_t mem32_limit,
+ const resource_t mem64_base, const resource_t mem64_limit)
+{
+ struct device_path path = {
+ .type = DEVICE_PATH_DOMAIN,
+ .domain = {
+ .domain = domain_base + bus_base,
+ },
+ };
+ struct device *const domain = alloc_dev(upstream, &path);
+ if (!domain)
+ die("%s: out of memory.\n", __func__);
+
+ domain->ops = &ioat_domain_ops;
+
+ domain->link_list = calloc(1, sizeof(struct bus));
+ if (!domain->link_list)
+ die("%s: out of memory.\n", __func__);
+
+ struct bus *const bus = domain->link_list;
+ bus->secondary = bus_base;
+ bus->subordinate = bus->secondary;
+ bus->max_subordinate = bus_limit;
+
+ unsigned int index = 0;
+
+ if (mem32_base <= mem32_limit) {
+ struct resource *const res = new_resource(domain, index++);
+ res->base = mem32_base;
+ res->limit = mem32_limit;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
+ }
+
+ if (mem64_base <= mem64_limit) {
+ struct resource *const res = new_resource(domain, index++);
+ res->base = mem64_base;
+ res->limit = mem64_limit;
+ res->size = res->limit - res->base + 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
+ }
+}
+
+void soc_create_ioat_domains(struct bus *const bus, const STACK_RES *const sr)
+{
+ const unsigned int domain_base = MAX_SOCKET * MAX_LOGIC_IIO_STACK;
+
+ if (sr->BusLimit < sr->BusBase + HQM_BUS_OFFSET + HQM_RESERVED_BUS) {
+ printk(BIOS_WARNING,
+ "Ignoring IOAT domain with limited bus range.\n");
+ return;
+ }
+
+ if (sr->PciResourceMem64Limit - sr->PciResourceMem64Base + 1
+ < 2 * CPM_MMIO_SIZE + 2 * HQM_MMIO_SIZE) {
+ printk(BIOS_WARNING,
+ "Ignoring IOAT domain with limited 64-bit MMIO window.\n");
+ return;
+ }
+
+ /* The FSP HOB doesn't provide accurate information about the
+ resource allocation. Hence use pre-defined offsets. Based
+ on ACPI code in create_dsdt_dino_resource(), soc_acpi.c: */
+ resource_t mem64_base, mem64_limit, bus_base, bus_limit;
+
+ /* CPM0 */
+ mem64_base = sr->PciResourceMem64Base;
+ mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
+ bus_base = sr->BusBase + CPM_BUS_OFFSET;
+ bus_limit = bus_base + CPM_RESERVED_BUS;
+ create_ioat_domain(bus, domain_base, bus_base, bus_limit, 0, -1, mem64_base, mem64_limit);
+
+ /* HQM0 */
+ mem64_base = mem64_limit + 1;
+ mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
+ bus_base = sr->BusBase + HQM_BUS_OFFSET;
+ bus_limit = bus_base + HQM_RESERVED_BUS;
+ create_ioat_domain(bus, domain_base, bus_base, bus_limit, 0, -1, mem64_base, mem64_limit);
+
+ /* CPM1 (optional) */
+ mem64_base = mem64_limit + 1;
+ mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
+ bus_base = sr->BusBase + CPM1_BUS_OFFSET;
+ bus_limit = bus_base + CPM_RESERVED_BUS;
+ if (bus_limit <= sr->BusLimit)
+ create_ioat_domain(bus, domain_base, bus_base, bus_limit, 0, -1, mem64_base, mem64_limit);
+
+ /* HQM1 (optional) */
+ mem64_base = mem64_limit + 1;
+ mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
+ bus_base = sr->BusBase + HQM1_BUS_OFFSET;
+ bus_limit = bus_base + HQM_RESERVED_BUS;
+ if (bus_limit <= sr->BusLimit)
+ create_ioat_domain(bus, domain_base, bus_base, bus_limit, 0, -1, mem64_base, mem64_limit);
+
+ /* DINO */
+ mem64_base = mem64_limit + 1;
+ mem64_limit = sr->PciResourceMem64Limit;
+ bus_base = sr->BusBase;
+ bus_limit = bus_base;
+ create_ioat_domain(bus, domain_base, bus_base, bus_limit, sr->PciResourceMem32Base, sr->PciResourceMem32Limit,
+ mem64_base, mem64_limit);
+}
diff --git a/src/soc/intel/xeon_sp/spr/soc_acpi.c b/src/soc/intel/xeon_sp/spr/soc_acpi.c
index 193b85978a84..e7ce5e37739f 100644
--- a/src/soc/intel/xeon_sp/spr/soc_acpi.c
+++ b/src/soc/intel/xeon_sp/spr/soc_acpi.c
@@ -188,6 +188,9 @@ static void create_dsdt_iou_cxl_resource(uint8_t socket, uint8_t stack, const ST
static void create_dsdt_dino_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri, bool stack_enabled)
{
+ if (!stack_enabled)
+ return;
+
/*
Stacks 8 .. B (TYPE_DINO)
Scope: DI<socket><stack> for DINO, ResourceTemplate: DT
@@ -247,6 +250,11 @@ static void create_dsdt_dino_resource(uint8_t socket, uint8_t stack, const STACK
snprintf(tres, sizeof(tres), "HU%d%X", socket, stack);
}
+ /* Note, some SKU doesn't provide CPM1 and HQM1 and owns smaller bus ranges
+ accordingly*/
+ if (bus_limit > ri->BusLimit)
+ continue;
+
printk(BIOS_DEBUG,
"\tCreating Dino ResourceTemplate %s for socket: %d, "
"stack: %d\n bus_base:0x%x, bus_limit:0x%x\n",
@@ -255,30 +263,19 @@ static void create_dsdt_dino_resource(uint8_t socket, uint8_t stack, const STACK
acpigen_write_name(tres);
acpigen_write_resourcetemplate_header();
- if (stack_enabled) {
- acpigen_resource_word(2, 0xc, 0, 0, bus_base, bus_limit, 0x0,
- (bus_limit - bus_base + 1));
-
- /* Mem32 resource */
- if (rlist[i] == DSDT_DINO)
- 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, mem64_base, mem64_limit, 0,
- (mem64_limit - mem64_base + 1));
- } else {
- acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
+ acpigen_resource_word(2, 0xc, 0, 0, bus_base, bus_limit, 0x0,
+ (bus_limit - bus_base + 1));
- /* Mem32 resource */
- if (rlist[i] == DSDT_DINO)
- acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
+ /* Mem32 resource */
+ if (rlist[i] == DSDT_DINO)
+ acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base,
+ ri->PciResourceMem32Limit, 0x0,
+ (ri->PciResourceMem32Limit
+ - ri->PciResourceMem32Base + 1));
- /* Mem64 resource */
- acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
- }
+ /* Mem64 resource */
+ acpigen_resource_qword(0, 0xc, 1, 0, mem64_base, mem64_limit, 0,
+ (mem64_limit - mem64_base + 1));
acpigen_write_resourcetemplate_footer();
}
diff --git a/src/soc/intel/xeon_sp/spr/soc_util.c b/src/soc/intel/xeon_sp/spr/soc_util.c
index f35214512137..86fe803e85da 100644
--- a/src/soc/intel/xeon_sp/spr/soc_util.c
+++ b/src/soc/intel/xeon_sp/spr/soc_util.c
@@ -68,11 +68,16 @@ const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num)
return hob->Element;
}
-bool is_iio_stack_res(const STACK_RES *res)
+bool stack_needs_resource_alloc(const STACK_RES *res)
{
return res->Personality == TYPE_UBOX_IIO || res->Personality == TYPE_DINO;
}
+bool is_pcie_iio_stack_res(const STACK_RES *res)
+{
+ return res->Personality == TYPE_UBOX_IIO;
+}
+
/*
* Given a stack resource, figure out whether the corresponding stack has
* CXL device.
diff --git a/src/soc/intel/xeon_sp/util.c b/src/soc/intel/xeon_sp/util.c
index 86dcb970c256..c9f4c5549a68 100644
--- a/src/soc/intel/xeon_sp/util.c
+++ b/src/soc/intel/xeon_sp/util.c
@@ -114,7 +114,7 @@ void get_iiostack_info(struct iiostack_resource *info)
for (int x = 0; x < MAX_IIO_STACK; ++x) {
const STACK_RES *ri;
ri = &hob->PlatformData.IIO_resource[socket].StackRes[x];
- if (!is_iio_stack_res(ri))
+ if (!stack_needs_resource_alloc(ri))
continue;
assert(info->no_of_stacks < (CONFIG_MAX_SOCKET * MAX_IIO_STACK));
memcpy(&info->res[info->no_of_stacks++], ri, sizeof(STACK_RES));