blob: 66f71698daad9048f738d788817df134242400a2 [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>
8#include <post.h>
9#include <soc/acpi.h>
Marc Jones1f500842020-10-15 14:32:51 -060010#include <soc/chip_common.h>
11#include <soc/soc_util.h>
12#include <soc/util.h>
13#include <stdlib.h>
14
Patrick Rudolph9fa40482024-01-18 08:55:08 +010015/**
Shuo Liu7f922102024-03-04 23:59:48 +080016 * Find all device of a given vendor and type for the specified socket.
Patrick Rudolph9fa40482024-01-18 08:55:08 +010017 * The function iterates over all PCI domains of the specified socket
18 * and matches the PCI vendor and device ID.
19 *
20 * @param socket The socket where to search for the device.
21 * @param vendor A PCI vendor ID (e.g. 0x8086 for Intel).
22 * @param device A PCI device ID.
Shuo Liu7f922102024-03-04 23:59:48 +080023 * @param from The device pointer to start search from.
24 *
25 * @return Pointer to the device struct. When there are multiple device
26 * instances, the caller should continue search upon a non-NULL match.
27 */
28struct device *dev_find_all_devices_on_socket(uint8_t socket, u16 vendor, u16 device,
29 struct device *from)
30{
31 return dev_find_all_devices_on_stack(socket, XEONSP_STACK_MAX, vendor, device, from);
32}
33
34/*
35 * Find device of a given vendor and type for the specified socket.
36 * The function will return at the 1st match.
Patrick Rudolph9fa40482024-01-18 08:55:08 +010037 */
38struct device *dev_find_device_on_socket(uint8_t socket, u16 vendor, u16 device)
39{
Shuo Liu7f922102024-03-04 23:59:48 +080040 return dev_find_all_devices_on_socket(socket, vendor, device, NULL);
41}
Patrick Rudolph9fa40482024-01-18 08:55:08 +010042
Shuo Liu7f922102024-03-04 23:59:48 +080043static int filter_device_on_stack(struct device *dev, uint8_t socket, uint8_t stack,
44 u16 vendor, u16 device)
45{
46 struct device *domain = dev_get_pci_domain(dev);
47 if (!domain)
48 return 0;
49 if (dev->path.type != DEVICE_PATH_PCI)
50 return 0;
51
52 union xeon_domain_path dn;
53 dn.domain_path = domain->path.domain.domain;
54
55 if (socket != XEONSP_SOCKET_MAX && dn.socket != socket)
56 return 0;
57 if (stack != XEONSP_STACK_MAX && dn.stack != stack)
58 return 0;
59 if (vendor != XEONSP_VENDOR_MAX && dev->vendor != vendor)
60 return 0;
61 if (device != XEONSP_DEVICE_MAX && dev->device != device)
62 return 0;
63
64 return 1;
65};
66
67/**
68 * Find all device of a given vendor and type for the specified socket and stack.
69 *
70 * @param socket The socket where to search for the device.
71 * XEONSP_SOCKET_MAX indicates any socket.
72 * @param stack The stack where to search for the device.
73 * XEONSP_STACK_MAX indicates any stack.
74 * @param vendor A PCI vendor ID (e.g. 0x8086 for Intel).
75 * XEONSP_VENDOR_MAX indicates any vendor.
76 * @param device A PCI device ID.
77 * XEONSP_DEVICE_MAX indicates any device.
78 * @param from The device pointer to start search from.
79 *
80 * @return Pointer to the device struct. When there are multiple device
81 * instances, the caller should continue search upon a non-NULL match.
82 */
83struct device *dev_find_all_devices_on_stack(uint8_t socket, uint8_t stack,
84 u16 vendor, u16 device, struct device *from)
85{
86 if (!from)
87 from = all_devices;
88 else
89 from = from->next;
90
91 while (from && (!filter_device_on_stack(from, socket, stack,
92 vendor, device)))
93 from = from->next;
94
95 return from;
96}
97
98/**
99 * Find all device of a given vendor and type for the specific domain
100 * Only the direct child of the input domain is iterated
101 *
102 * @param domain Pointer to the input domain
103 * @param vendor A PCI vendor ID
104 * XEONSP_VENDOR_MAX indicates any vendor
105 * @param vendor A PCI device ID
106 * XEONSP_DEVICE_MAX indicates any vendor
107 * @param from The device pointer to start search from.
108 *
109 * @return Pointer to the device struct. When there are multiple device
110 * instances, the caller should continue search upon a non-NULL match.
111 */
112struct device *dev_find_all_devices_on_domain(struct device *domain, u16 vendor,
113 u16 device, struct device *from)
114{
115 struct device *dev = from;
116 while ((dev = dev_bus_each_child(domain->downstream, dev))) {
117 if (vendor != XEONSP_VENDOR_MAX && dev->vendor != vendor)
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100118 continue;
Shuo Liu7f922102024-03-04 23:59:48 +0800119 if (device != XEONSP_DEVICE_MAX && dev->device != device)
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100120 continue;
Shuo Liu7f922102024-03-04 23:59:48 +0800121 break;
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100122 }
123
Shuo Liu7f922102024-03-04 23:59:48 +0800124 return dev;
Patrick Rudolph9fa40482024-01-18 08:55:08 +0100125}
126
127/**
128 * Returns the socket ID where the specified device is connected to.
129 * This is an integer in the range [0, CONFIG_MAX_SOCKET).
130 *
131 * @param dev The device to look up
132 *
133 * @return Socket ID the device is attached to, negative number on error.
134 */
135int iio_pci_domain_socket_from_dev(struct device *dev)
136{
137 struct device *domain;
138 union xeon_domain_path dn;
139
140 if (dev->path.type == DEVICE_PATH_DOMAIN)
141 domain = dev;
142 else
143 domain = dev_get_pci_domain(dev);
144
145 if (!domain)
146 return -1;
147
148 dn.domain_path = domain->path.domain.domain;
149
150 return dn.socket;
151}
152
153/**
154 * Returns the stack ID where the specified device is connected to.
155 * This is an integer in the range [0, MAX_IIO_STACK).
156 *
157 * @param dev The device to look up
158 *
159 * @return Stack ID the device is attached to, negative number on error.
160 */
161int iio_pci_domain_stack_from_dev(struct device *dev)
162{
163 struct device *domain;
164 union xeon_domain_path dn;
165
166 if (dev->path.type == DEVICE_PATH_DOMAIN)
167 domain = dev;
168 else
169 domain = dev_get_pci_domain(dev);
170
171 if (!domain)
172 return -1;
173
174 dn.domain_path = domain->path.domain.domain;
175
176 return dn.stack;
177}
178
Shuo Liuec58beb2024-03-11 07:14:07 +0800179void create_domain(const union xeon_domain_path dp, struct bus *upstream,
Patrick Rudolph80619572024-03-12 18:32:35 +0100180 int bus_base, int bus_limit, const char *type,
181 struct device_operations *ops,
182 const size_t pci_segment_group)
Shuo Liu255f9272023-03-29 20:14:11 +0800183{
Shuo Liua454b622024-03-07 07:38:36 +0800184 struct device_path path;
185 init_xeon_domain_path(&path, dp.socket, dp.stack, bus_base);
Shuo Liu255f9272023-03-29 20:14:11 +0800186
187 struct device *const domain = alloc_find_dev(upstream, &path);
188 if (!domain)
189 die("%s: out of memory.\n", __func__);
190
Shuo Liua454b622024-03-07 07:38:36 +0800191 domain->ops = ops;
192 iio_domain_set_acpi_name(domain, type);
Shuo Liu255f9272023-03-29 20:14:11 +0800193
194 struct bus *const bus = alloc_bus(domain);
Shuo Liua454b622024-03-07 07:38:36 +0800195 bus->secondary = bus_base;
196 bus->subordinate = bus_base;
197 bus->max_subordinate = bus_limit;
Patrick Rudolph80619572024-03-12 18:32:35 +0100198 bus->segment_group = pci_segment_group;
Shuo Liua454b622024-03-07 07:38:36 +0800199}
200
Patrick Rudolph15672592024-01-18 07:57:07 +0100201/* Attach stack as domains */
Shuo Liu255f9272023-03-29 20:14:11 +0800202void attach_iio_stacks(void)
Marc Jones1f500842020-10-15 14:32:51 -0600203{
Arthur Heymans550f55e2022-08-24 14:44:26 +0200204 const IIO_UDS *hob = get_iio_uds();
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100205 union xeon_domain_path dn = { .domain_path = 0 };
Arthur Heymans550f55e2022-08-24 14:44:26 +0200206 if (!hob)
207 return;
Marc Jones1f500842020-10-15 14:32:51 -0600208
Shuo Liu255f9272023-03-29 20:14:11 +0800209 struct bus *root_bus = dev_root.downstream;
Patrick Rudolphabc27442024-03-12 14:48:16 +0100210 for (int s = 0; s < CONFIG_MAX_SOCKET; ++s) {
211 if (!soc_cpu_is_enabled(s))
212 continue;
Arthur Heymans550f55e2022-08-24 14:44:26 +0200213 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
Arthur Heymans550f55e2022-08-24 14:44:26 +0200214 const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
Patrick Rudolph80619572024-03-12 18:32:35 +0100215 const size_t seg = hob->PlatformData.CpuQpiInfo[s].PcieSegment;
216
Arthur Heymans470f1d32023-08-31 18:19:09 +0200217 if (ri->BusBase > ri->BusLimit)
Arthur Heymans550f55e2022-08-24 14:44:26 +0200218 continue;
Jonathan Zhang532e8c02023-01-25 11:28:49 -0800219
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100220 /* Prepare domain path */
221 dn.socket = s;
222 dn.stack = x;
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100223
Shuo Liuec58beb2024-03-11 07:14:07 +0800224 create_xeonsp_domains(dn, root_bus, ri, seg);
Marc Jones1f500842020-10-15 14:32:51 -0600225 }
226 }
Marc Jones1f500842020-10-15 14:32:51 -0600227}
Shuo Liue0c935b2024-03-08 02:11:36 +0800228
229bool is_pcie_domain(struct device *dev)
230{
231 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
232 return false;
233
234 return strstr(dev->name, DOMAIN_TYPE_PCIE);
235}
236
237bool is_ioat_domain(struct device *dev)
238{
239 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
240 return false;
241
242 return (strstr(dev->name, DOMAIN_TYPE_CPM0) ||
243 strstr(dev->name, DOMAIN_TYPE_CPM1) ||
244 strstr(dev->name, DOMAIN_TYPE_DINO) ||
245 strstr(dev->name, DOMAIN_TYPE_HQM0) ||
246 strstr(dev->name, DOMAIN_TYPE_HQM1));
247}
248
249bool is_ubox_domain(struct device *dev)
250{
251 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
252 return false;
253
254 return (strstr(dev->name, DOMAIN_TYPE_UBX0) ||
255 strstr(dev->name, DOMAIN_TYPE_UBX1));
Shuo Liue0c935b2024-03-08 02:11:36 +0800256}
257
258bool is_cxl_domain(struct device *dev)
259{
260 if ((!dev) || (dev->path.type != DEVICE_PATH_DOMAIN))
261 return false;
262
263 return strstr(dev->name, DOMAIN_TYPE_CXL);
264}