blob: a2de2d4711892f9d8940148b30edea30599e8505 [file] [log] [blame]
Marc Jones1f500842020-10-15 14:32:51 -06001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
Patrick Rudolphe357ac32024-02-23 09:47:24 +01003#include <acpi/acpigen_pci.h>
Marc Jones1f500842020-10-15 14:32:51 -06004#include <assert.h>
5#include <console/console.h>
Marc Jones1f500842020-10-15 14:32:51 -06006#include <device/pci.h>
Patrick Rudolph40e07482024-02-23 09:23:41 +01007#include <intelblocks/acpi.h>
Patrick Rudolph40e07482024-02-23 09:23:41 +01008#include <soc/acpi.h>
Marc Jones1f500842020-10-15 14:32:51 -06009#include <soc/chip_common.h>
10#include <soc/soc_util.h>
11#include <soc/util.h>
Marc Jones1f500842020-10-15 14:32:51 -060012
Patrick Rudolph9fa40482024-01-18 08:55:08 +010013/**
Shuo Liu7f922102024-03-04 23:59:48 +080014 * Find all device of a given vendor and type for the specified socket.
Patrick Rudolph9fa40482024-01-18 08:55:08 +010015 * The function iterates over all PCI domains of the specified socket
16 * and matches the PCI vendor and device ID.
17 *
18 * @param socket The socket where to search for the device.
19 * @param vendor A PCI vendor ID (e.g. 0x8086 for Intel).
20 * @param device A PCI device ID.
Shuo Liu7f922102024-03-04 23:59:48 +080021 * @param from The device pointer to start search from.
22 *
23 * @return Pointer to the device struct. When there are multiple device
24 * instances, the caller should continue search upon a non-NULL match.
25 */
26struct device *dev_find_all_devices_on_socket(uint8_t socket, u16 vendor, u16 device,
27 struct device *from)
28{
29 return dev_find_all_devices_on_stack(socket, XEONSP_STACK_MAX, vendor, device, from);
30}
31
32/*
33 * Find device of a given vendor and type for the specified socket.
34 * The function will return at the 1st match.
Patrick Rudolph9fa40482024-01-18 08:55:08 +010035 */
36struct device *dev_find_device_on_socket(uint8_t socket, u16 vendor, u16 device)
37{
Shuo Liu7f922102024-03-04 23:59:48 +080038 return dev_find_all_devices_on_socket(socket, vendor, device, NULL);
39}
Patrick Rudolph9fa40482024-01-18 08:55:08 +010040
Shuo Liu7f922102024-03-04 23:59:48 +080041static int filter_device_on_stack(struct device *dev, uint8_t socket, uint8_t stack,
42 u16 vendor, u16 device)
43{
44 struct device *domain = dev_get_pci_domain(dev);
45 if (!domain)
46 return 0;
47 if (dev->path.type != DEVICE_PATH_PCI)
48 return 0;
49
50 union xeon_domain_path dn;
51 dn.domain_path = domain->path.domain.domain;
52
53 if (socket != XEONSP_SOCKET_MAX && dn.socket != socket)
54 return 0;
55 if (stack != XEONSP_STACK_MAX && dn.stack != stack)
56 return 0;
57 if (vendor != XEONSP_VENDOR_MAX && dev->vendor != vendor)
58 return 0;
59 if (device != XEONSP_DEVICE_MAX && dev->device != device)
60 return 0;
61
62 return 1;
63};
64
65/**
66 * Find all device of a given vendor and type for the specified socket and stack.
67 *
68 * @param socket The socket where to search for the device.
69 * XEONSP_SOCKET_MAX indicates any socket.
70 * @param stack The stack where to search for the device.
71 * XEONSP_STACK_MAX indicates any stack.
72 * @param vendor A PCI vendor ID (e.g. 0x8086 for Intel).
73 * XEONSP_VENDOR_MAX indicates any vendor.
74 * @param device A PCI device ID.
75 * XEONSP_DEVICE_MAX indicates any device.
76 * @param from The device pointer to start search from.
77 *
78 * @return Pointer to the device struct. When there are multiple device
79 * instances, the caller should continue search upon a non-NULL match.
80 */
81struct device *dev_find_all_devices_on_stack(uint8_t socket, uint8_t stack,
82 u16 vendor, u16 device, struct device *from)
83{
84 if (!from)
85 from = all_devices;
86 else
87 from = from->next;
88
89 while (from && (!filter_device_on_stack(from, socket, stack,
90 vendor, device)))
91 from = from->next;
92
93 return from;
94}
95
96/**
97 * Find all device of a given vendor and type for the specific domain
98 * Only the direct child of the input domain is iterated
99 *
100 * @param domain Pointer to the input domain
101 * @param vendor A PCI vendor ID
102 * XEONSP_VENDOR_MAX indicates any vendor
103 * @param vendor A PCI device ID
104 * XEONSP_DEVICE_MAX indicates any vendor
105 * @param from The device pointer to start search from.
106 *
107 * @return Pointer to the device struct. When there are multiple device
108 * instances, the caller should continue search upon a non-NULL match.
109 */
110struct device *dev_find_all_devices_on_domain(struct device *domain, u16 vendor,
111 u16 device, struct device *from)
112{
113 struct device *dev = from;
114 while ((dev = dev_bus_each_child(domain->downstream, dev))) {
115 if (vendor != XEONSP_VENDOR_MAX && dev->vendor != vendor)
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100116 continue;
Shuo Liu7f922102024-03-04 23:59:48 +0800117 if (device != XEONSP_DEVICE_MAX && dev->device != device)
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100118 continue;
Shuo Liu7f922102024-03-04 23:59:48 +0800119 break;
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100120 }
121
Shuo Liu7f922102024-03-04 23:59:48 +0800122 return dev;
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100123}
124
125/**
126 * Returns the socket ID where the specified device is connected to.
127 * This is an integer in the range [0, CONFIG_MAX_SOCKET).
128 *
129 * @param dev The device to look up
130 *
131 * @return Socket ID the device is attached to, negative number on error.
132 */
133int iio_pci_domain_socket_from_dev(struct device *dev)
134{
135 struct device *domain;
136 union xeon_domain_path dn;
137
138 if (dev->path.type == DEVICE_PATH_DOMAIN)
139 domain = dev;
140 else
141 domain = dev_get_pci_domain(dev);
142
143 if (!domain)
144 return -1;
145
146 dn.domain_path = domain->path.domain.domain;
147
148 return dn.socket;
149}
150
151/**
152 * Returns the stack ID where the specified device is connected to.
153 * This is an integer in the range [0, MAX_IIO_STACK).
154 *
155 * @param dev The device to look up
156 *
157 * @return Stack ID the device is attached to, negative number on error.
158 */
159int iio_pci_domain_stack_from_dev(struct device *dev)
160{
161 struct device *domain;
162 union xeon_domain_path dn;
163
164 if (dev->path.type == DEVICE_PATH_DOMAIN)
165 domain = dev;
166 else
167 domain = dev_get_pci_domain(dev);
168
169 if (!domain)
170 return -1;
171
172 dn.domain_path = domain->path.domain.domain;
173
174 return dn.stack;
175}
176
Shuo Liuec58beb2024-03-11 07:14:07 +0800177void create_domain(const union xeon_domain_path dp, struct bus *upstream,
Patrick Rudolph80619572024-03-12 18:32:35 +0100178 int bus_base, int bus_limit, const char *type,
179 struct device_operations *ops,
180 const size_t pci_segment_group)
Shuo Liu255f9272023-03-29 20:14:11 +0800181{
Shuo Liua454b622024-03-07 07:38:36 +0800182 struct device_path path;
183 init_xeon_domain_path(&path, dp.socket, dp.stack, bus_base);
Shuo Liu255f9272023-03-29 20:14:11 +0800184
185 struct device *const domain = alloc_find_dev(upstream, &path);
186 if (!domain)
187 die("%s: out of memory.\n", __func__);
188
Shuo Liua454b622024-03-07 07:38:36 +0800189 domain->ops = ops;
190 iio_domain_set_acpi_name(domain, type);
Shuo Liu255f9272023-03-29 20:14:11 +0800191
192 struct bus *const bus = alloc_bus(domain);
Shuo Liua454b622024-03-07 07:38:36 +0800193 bus->secondary = bus_base;
194 bus->subordinate = bus_base;
195 bus->max_subordinate = bus_limit;
Patrick Rudolph80619572024-03-12 18:32:35 +0100196 bus->segment_group = pci_segment_group;
Shuo Liua454b622024-03-07 07:38:36 +0800197}
198
Patrick Rudolph15672592024-01-18 07:57:07 +0100199/* Attach stack as domains */
Shuo Liu255f9272023-03-29 20:14:11 +0800200void attach_iio_stacks(void)
Marc Jones1f500842020-10-15 14:32:51 -0600201{
Arthur Heymans550f55e2022-08-24 14:44:26 +0200202 const IIO_UDS *hob = get_iio_uds();
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100203 union xeon_domain_path dn = { .domain_path = 0 };
Arthur Heymans550f55e2022-08-24 14:44:26 +0200204 if (!hob)
205 return;
Marc Jones1f500842020-10-15 14:32:51 -0600206
Shuo Liu255f9272023-03-29 20:14:11 +0800207 struct bus *root_bus = dev_root.downstream;
Patrick Rudolphabc27442024-03-12 14:48:16 +0100208 for (int s = 0; s < CONFIG_MAX_SOCKET; ++s) {
209 if (!soc_cpu_is_enabled(s))
210 continue;
Arthur Heymans550f55e2022-08-24 14:44:26 +0200211 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
Shuo Liuf2daf242024-03-20 19:03:31 +0800212 const xSTACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
Patrick Rudolph80619572024-03-12 18:32:35 +0100213 const size_t seg = hob->PlatformData.CpuQpiInfo[s].PcieSegment;
214
Arthur Heymans470f1d32023-08-31 18:19:09 +0200215 if (ri->BusBase > ri->BusLimit)
Arthur Heymans550f55e2022-08-24 14:44:26 +0200216 continue;
Jonathan Zhang532e8c02023-01-25 11:28:49 -0800217
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100218 /* Prepare domain path */
219 dn.socket = s;
220 dn.stack = x;
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100221
Shuo Liuec58beb2024-03-11 07:14:07 +0800222 create_xeonsp_domains(dn, root_bus, ri, seg);
Marc Jones1f500842020-10-15 14:32:51 -0600223 }
224 }
Marc Jones1f500842020-10-15 14:32:51 -0600225}
Shuo Liue0c935b2024-03-08 02:11:36 +0800226
227bool is_pcie_domain(struct device *dev)
228{
229 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
230 return false;
231
232 return strstr(dev->name, DOMAIN_TYPE_PCIE);
233}
234
235bool is_ioat_domain(struct device *dev)
236{
237 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
238 return false;
239
240 return (strstr(dev->name, DOMAIN_TYPE_CPM0) ||
241 strstr(dev->name, DOMAIN_TYPE_CPM1) ||
242 strstr(dev->name, DOMAIN_TYPE_DINO) ||
243 strstr(dev->name, DOMAIN_TYPE_HQM0) ||
244 strstr(dev->name, DOMAIN_TYPE_HQM1));
245}
246
247bool is_ubox_domain(struct device *dev)
248{
249 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
250 return false;
251
252 return (strstr(dev->name, DOMAIN_TYPE_UBX0) ||
253 strstr(dev->name, DOMAIN_TYPE_UBX1));
Shuo Liue0c935b2024-03-08 02:11:36 +0800254}
255
256bool is_cxl_domain(struct device *dev)
257{
258 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
259 return false;
260
261 return strstr(dev->name, DOMAIN_TYPE_CXL);
262}