soc/intel/xeon_sp/chip_common: Improve the domain ID
[coreboot2.git] / src / soc / intel / xeon_sp / chip_common.c
blobbf2a015ed999436869d0f1d74e2d1a491700bc5a
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <assert.h>
4 #include <console/console.h>
5 #include <post.h>
6 #include <device/pci.h>
7 #include <soc/chip_common.h>
8 #include <soc/soc_util.h>
9 #include <soc/util.h>
10 #include <stdlib.h>
12 static const STACK_RES *domain_to_stack_res(const struct device *dev)
14 assert(dev->path.type == DEVICE_PATH_DOMAIN);
15 const union xeon_domain_path dn = {
16 .domain_path = dev->path.domain.domain
19 const IIO_UDS *hob = get_iio_uds();
20 assert(hob != NULL);
22 return &hob->PlatformData.IIO_resource[dn.socket].StackRes[dn.stack];
25 void iio_pci_domain_read_resources(struct device *dev)
27 struct resource *res;
28 const STACK_RES *sr = domain_to_stack_res(dev);
30 if (!sr)
31 return;
33 int index = 0;
35 if (dev->path.domain.domain == 0) {
36 /* The 0 - 0xfff IO range is not reported by the HOB but still gets decoded */
37 res = new_resource(dev, index++);
38 res->base = 0;
39 res->size = 0x1000;
40 res->limit = 0xfff;
41 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
44 if (sr->PciResourceIoBase < sr->PciResourceIoLimit) {
45 res = new_resource(dev, index++);
46 res->base = sr->PciResourceIoBase;
47 res->limit = sr->PciResourceIoLimit;
48 res->size = res->limit - res->base + 1;
49 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED;
52 if (sr->PciResourceMem32Base < sr->PciResourceMem32Limit) {
53 res = new_resource(dev, index++);
54 res->base = sr->PciResourceMem32Base;
55 res->limit = sr->PciResourceMem32Limit;
56 res->size = res->limit - res->base + 1;
57 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
60 if (sr->PciResourceMem64Base < sr->PciResourceMem64Limit) {
61 res = new_resource(dev, index++);
62 res->base = sr->PciResourceMem64Base;
63 res->limit = sr->PciResourceMem64Limit;
64 res->size = res->limit - res->base + 1;
65 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
69 void iio_pci_domain_scan_bus(struct device *dev)
71 const STACK_RES *sr = domain_to_stack_res(dev);
72 if (!sr)
73 return;
75 if (!dev->link_list) {
76 dev->link_list = calloc(1, sizeof(struct bus));
77 if (!dev->link_list)
78 die("%s: out of memory.\n", __func__);
81 struct bus *bus = dev->link_list;
82 bus->dev = dev;
83 bus->secondary = sr->BusBase;
84 bus->subordinate = sr->BusBase;
85 bus->max_subordinate = sr->BusLimit;
87 printk(BIOS_SPEW, "Scanning IIO stack %d: busses %x-%x\n", dev->path.domain.domain,
88 dev->link_list->secondary, dev->link_list->max_subordinate);
89 pci_host_bridge_scan_bus(dev);
93 * Used by IIO stacks for PCIe bridges. Those contain 1 PCI host bridges,
94 * all the bus numbers on the IIO stack can be used for this bridge
96 static struct device_operations iio_pcie_domain_ops = {
97 .read_resources = iio_pci_domain_read_resources,
98 .set_resources = pci_domain_set_resources,
99 .scan_bus = iio_pci_domain_scan_bus,
102 /* Attach IIO stack as domains */
103 void attach_iio_stacks(struct device *dev)
105 const IIO_UDS *hob = get_iio_uds();
106 union xeon_domain_path dn = { .domain_path = 0 };
107 if (!hob)
108 return;
110 for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
111 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
112 if (s == 0 && x == 0)
113 continue;
115 const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
116 if (ri->BusBase > ri->BusLimit)
117 continue;
119 /* Prepare domain path */
120 dn.socket = s;
121 dn.stack = x;
122 dn.bus = ri->BusBase;
124 if (!is_pcie_iio_stack_res(ri)) {
125 if (CONFIG(HAVE_IOAT_DOMAINS))
126 soc_create_ioat_domains(dn, dev->bus, ri);
127 continue;
130 struct device_path path;
131 path.type = DEVICE_PATH_DOMAIN;
132 path.domain.domain = dn.domain_path;
133 struct device *iio_domain = alloc_dev(dev->bus, &path);
134 if (iio_domain == NULL)
135 die("%s: out of memory.\n", __func__);
136 iio_domain->ops = &iio_pcie_domain_ops;