diff options
Diffstat (limited to 'src/soc/intel')
-rw-r--r-- | src/soc/intel/xeon_sp/Kconfig | 3 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/acpi.c | 2 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/chip_common.c | 580 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/chip.c | 6 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/soc_util.c | 7 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/chip_common.h | 8 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/util.h | 3 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/memmap.c | 2 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/skx/chip.c | 6 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/skx/soc_util.c | 7 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/Kconfig | 1 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/Makefile.inc | 2 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/chip.c | 6 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/ioat.c | 130 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/soc_acpi.c | 41 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/soc_util.c | 7 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/util.c | 2 |
17 files changed, 269 insertions, 544 deletions
diff --git a/src/soc/intel/xeon_sp/Kconfig b/src/soc/intel/xeon_sp/Kconfig index 1eee8694a3..09310300dc 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 519d6c7c76..61d51862f5 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 a9b1260646..c1b331bc66 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 dd9c113491..39a7ebaae2 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 64efb612ca..e277752e5c 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 339da07e4a..ac8ba9e422 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 8e80c64d14..a03c8e8404 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 8562eb1918..e73143fc78 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 a113d5a186..b468842e92 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 b501a3e04f..d61d07489f 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 396072448d..5a21f47b43 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 3e4f9cd329..7a0d9586c5 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 f9c43dbe9a..3b3c65e4a0 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 0000000000..f10863a607 --- /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 193b85978a..e7ce5e3773 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 f352145121..86fe803e85 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 86dcb970c2..c9f4c5549a 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)); |