blob: 0521c7e8a4edceae26b545b90f2c0decf71bf20b [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer57879c92012-07-31 16:47:25 -07002
Furquan Shaikh86803782020-04-16 23:13:28 -07003#include <assert.h>
Kyösti Mälkki2df1c122018-05-21 01:52:10 +03004#include <console/console.h>
Stefan Reinauer57879c92012-07-31 16:47:25 -07005#include <device/device.h>
6#include <device/path.h>
Kyösti Mälkkiad7674e2018-05-20 10:31:23 +03007#include <device/pci_def.h>
Elyes Haouasecb5e2d2022-10-02 13:13:17 +02008#include <device/pci_type.h>
Furquan Shaikh7f6ae792021-05-20 22:47:02 -07009#include <fw_config.h>
Elyes Haouasecb5e2d2022-10-02 13:13:17 +020010#include <types.h>
Stefan Reinauer57879c92012-07-31 16:47:25 -070011
12/** Linked list of ALL devices */
Frans Hendriksa9caa502021-02-01 11:44:37 +010013DEVTREE_CONST struct device *DEVTREE_CONST all_devices = &dev_root;
Stefan Reinauer57879c92012-07-31 16:47:25 -070014
15/**
16 * Given a PCI bus and a devfn number, find the device structure.
17 *
Aaron Durbin55ef0d22019-09-26 12:05:27 -060018 * Note that this function can return the incorrect device prior
19 * to PCI enumeration because the secondary field of the bus object
20 * is 0. The failing scenario is determined by the order of the
21 * devices in all_devices singly-linked list as well as the time
22 * when this function is called (secondary reflecting topology).
23 *
Stefan Reinauer57879c92012-07-31 16:47:25 -070024 * @param bus The bus number.
25 * @param devfn A device/function number.
26 * @return Pointer to the device structure (if found), 0 otherwise.
27 */
Kyösti Mälkkibd585fa2019-07-03 07:51:43 +030028
29static DEVTREE_CONST struct device *dev_find_slot(unsigned int bus,
Stefan Reinauer57879c92012-07-31 16:47:25 -070030 unsigned int devfn)
31{
Aaron Durbine4d7abc2017-04-16 22:05:36 -050032 DEVTREE_CONST struct device *dev, *result;
Stefan Reinauer57879c92012-07-31 16:47:25 -070033
34 result = 0;
35 for (dev = all_devices; dev; dev = dev->next) {
36 if ((dev->path.type == DEVICE_PATH_PCI) &&
Arthur Heymans7fcd4d52023-08-24 15:12:19 +020037 (dev->upstream->secondary == bus) &&
38 (dev->upstream->segment_group == 0) &&
Stefan Reinauer57879c92012-07-31 16:47:25 -070039 (dev->path.pci.devfn == devfn)) {
40 result = dev;
41 break;
42 }
43 }
44 return result;
45}
46
47/**
Nico Huberf6a43442018-05-15 14:13:32 +020048 * Given a Device Path Type, find the device structure.
49 *
50 * @param prev_match The previously matched device instance.
51 * @param path_type The Device Path Type.
52 * @return Pointer to the device structure (if found), 0 otherwise.
53 */
54DEVTREE_CONST struct device *dev_find_path(
55 DEVTREE_CONST struct device *prev_match,
56 enum device_path_type path_type)
57{
58 DEVTREE_CONST struct device *dev, *result = NULL;
59
60 if (prev_match == NULL)
61 prev_match = all_devices;
62 else
63 prev_match = prev_match->next;
64
65 for (dev = prev_match; dev; dev = dev->next) {
66 if (dev->path.type == path_type) {
67 result = dev;
68 break;
69 }
70 }
71 return result;
72}
73
74/**
Martin Roth16d953a2014-05-12 17:38:59 -060075 * Given a device pointer, find the next PCI device.
76 *
77 * @param previous_dev A pointer to a PCI device structure.
78 * @return Pointer to the next device structure (if found), 0 otherwise.
79 */
Aaron Durbine4d7abc2017-04-16 22:05:36 -050080DEVTREE_CONST struct device *dev_find_next_pci_device(
81 DEVTREE_CONST struct device *previous_dev)
Martin Roth16d953a2014-05-12 17:38:59 -060082{
Nico Huberf6a43442018-05-15 14:13:32 +020083 return dev_find_path(previous_dev, DEVICE_PATH_PCI);
Martin Roth16d953a2014-05-12 17:38:59 -060084}
85
Kyösti Mälkki2df1c122018-05-21 01:52:10 +030086static int path_eq(const struct device_path *path1,
87 const struct device_path *path2)
88{
89 int equal = 0;
90
Furquan Shaikh86803782020-04-16 23:13:28 -070091 if (!path1 || !path2) {
92 assert(path1);
93 assert(path2);
94 /* Return 0 in case assert is considered non-fatal. */
95 return 0;
96 }
97
Kyösti Mälkki2df1c122018-05-21 01:52:10 +030098 if (path1->type != path2->type)
99 return 0;
100
101 switch (path1->type) {
102 case DEVICE_PATH_NONE:
103 break;
104 case DEVICE_PATH_ROOT:
105 equal = 1;
106 break;
107 case DEVICE_PATH_PCI:
108 equal = (path1->pci.devfn == path2->pci.devfn);
109 break;
110 case DEVICE_PATH_PNP:
111 equal = (path1->pnp.port == path2->pnp.port) &&
112 (path1->pnp.device == path2->pnp.device);
113 break;
114 case DEVICE_PATH_I2C:
115 equal = (path1->i2c.device == path2->i2c.device) &&
116 (path1->i2c.mode_10bit == path2->i2c.mode_10bit);
117 break;
118 case DEVICE_PATH_APIC:
119 equal = (path1->apic.apic_id == path2->apic.apic_id);
120 break;
121 case DEVICE_PATH_DOMAIN:
122 equal = (path1->domain.domain == path2->domain.domain);
123 break;
124 case DEVICE_PATH_CPU_CLUSTER:
125 equal = (path1->cpu_cluster.cluster
126 == path2->cpu_cluster.cluster);
127 break;
128 case DEVICE_PATH_CPU:
129 equal = (path1->cpu.id == path2->cpu.id);
130 break;
131 case DEVICE_PATH_CPU_BUS:
132 equal = (path1->cpu_bus.id == path2->cpu_bus.id);
133 break;
134 case DEVICE_PATH_GENERIC:
135 equal = (path1->generic.id == path2->generic.id) &&
136 (path1->generic.subid == path2->generic.subid);
137 break;
138 case DEVICE_PATH_SPI:
139 equal = (path1->spi.cs == path2->spi.cs);
140 break;
141 case DEVICE_PATH_USB:
142 equal = (path1->usb.port_type == path2->usb.port_type) &&
143 (path1->usb.port_id == path2->usb.port_id);
144 break;
145 case DEVICE_PATH_MMIO:
146 equal = (path1->mmio.addr == path2->mmio.addr);
147 break;
Michael Niewöhnerdbb667a2020-12-11 21:26:02 +0100148 case DEVICE_PATH_GPIO:
149 equal = (path1->gpio.id == path2->gpio.id);
150 break;
Mario Scheithauer67f63e72022-11-02 15:57:10 +0100151 case DEVICE_PATH_MDIO:
152 equal = (path1->mdio.addr == path2->mdio.addr);
153 break;
154
Kyösti Mälkki2df1c122018-05-21 01:52:10 +0300155 default:
156 printk(BIOS_ERR, "Unknown device type: %d\n", path1->type);
157 break;
158 }
159
160 return equal;
161}
162
163/**
164 * See if a device structure exists for path.
165 *
166 * @param parent The bus to find the device on.
167 * @param path The relative path from the bus to the appropriate device.
168 * @return Pointer to a device structure for the device on bus at path
169 * or 0/NULL if no device is found.
170 */
171DEVTREE_CONST struct device *find_dev_path(
172 const struct bus *parent, const struct device_path *path)
173{
174 DEVTREE_CONST struct device *child;
Furquan Shaikh86803782020-04-16 23:13:28 -0700175
176 if (!parent) {
Julius Werner3e034b62020-07-29 17:39:21 -0700177 BUG();
Furquan Shaikh86803782020-04-16 23:13:28 -0700178 /* Return NULL in case asserts are considered non-fatal. */
179 return NULL;
180 }
181
Kyösti Mälkki2df1c122018-05-21 01:52:10 +0300182 for (child = parent->children; child; child = child->sibling) {
183 if (path_eq(path, &child->path))
184 break;
185 }
186 return child;
187}
188
Rob Barnesa223e652020-07-23 08:25:42 -0600189/**
190 * Find the device structure given an array of nested device paths,
191 *
192 * @param parent The parent bus to start the search on.
193 * @param nested_path An array of relative paths from the parent bus to the target device.
194 * @param nested_path_length Number of path elements in nested_path array.
195 * @return Pointer to a device structure for the device at nested path
196 * or 0/NULL if no device is found.
197 */
198DEVTREE_CONST struct device *find_dev_nested_path(
199 const struct bus *parent, const struct device_path nested_path[],
200 size_t nested_path_length)
201{
202 DEVTREE_CONST struct device *child;
203
204 if (!parent || !nested_path || !nested_path_length)
205 return NULL;
206
207 child = find_dev_path(parent, nested_path);
208
209 /* Terminate recursion at end of nested path or child not found */
210 if (nested_path_length == 1 || !child)
211 return child;
212
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200213 return find_dev_nested_path(child->downstream, nested_path + 1, nested_path_length - 1);
Rob Barnesa223e652020-07-23 08:25:42 -0600214}
215
Kyösti Mälkkiad7674e2018-05-20 10:31:23 +0300216DEVTREE_CONST struct device *pcidev_path_behind(
217 const struct bus *parent, pci_devfn_t devfn)
218{
219 const struct device_path path = {
220 .type = DEVICE_PATH_PCI,
221 .pci.devfn = devfn,
222 };
223 return find_dev_path(parent, &path);
224}
225
Kyösti Mälkkiab275f02019-07-04 07:16:59 +0300226DEVTREE_CONST struct device *pcidev_path_on_bus(unsigned int bus, pci_devfn_t devfn)
227{
228 DEVTREE_CONST struct bus *parent = pci_root_bus();
229 DEVTREE_CONST struct device *dev = parent->children;
230
231 /* FIXME: Write the loop with topology links. */
232 while (dev) {
233 if (dev->path.type != DEVICE_PATH_PCI) {
234 dev = dev->next;
235 continue;
236 }
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200237 if (dev->upstream->secondary == bus && dev->upstream->segment_group == 0)
238 return pcidev_path_behind(dev->upstream, devfn);
Kyösti Mälkkiab275f02019-07-04 07:16:59 +0300239 dev = dev->next;
240 }
241 return NULL;
242}
243
Kyösti Mälkkifffc9f32019-07-03 09:55:01 +0300244DEVTREE_CONST struct bus *pci_root_bus(void)
Kyösti Mälkkiad7674e2018-05-20 10:31:23 +0300245{
246 DEVTREE_CONST struct device *pci_domain;
Kyösti Mälkkifcbbb912020-04-20 10:21:39 +0300247 static DEVTREE_CONST struct bus *pci_root;
Kyösti Mälkkiad7674e2018-05-20 10:31:23 +0300248
Kyösti Mälkkifffc9f32019-07-03 09:55:01 +0300249 if (pci_root)
250 return pci_root;
251
252 pci_domain = dev_find_path(NULL, DEVICE_PATH_DOMAIN);
253 if (!pci_domain)
254 return NULL;
255
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200256 pci_root = pci_domain->downstream;
Kyösti Mälkkifffc9f32019-07-03 09:55:01 +0300257 return pci_root;
258}
259
260DEVTREE_CONST struct device *pcidev_path_on_root(pci_devfn_t devfn)
261{
Kyösti Mälkkifffc9f32019-07-03 09:55:01 +0300262 return pcidev_path_behind(pci_root_bus(), devfn);
Kyösti Mälkkiad7674e2018-05-20 10:31:23 +0300263}
264
265DEVTREE_CONST struct device *pcidev_on_root(uint8_t dev, uint8_t fn)
266{
267 return pcidev_path_on_root(PCI_DEVFN(dev, fn));
268}
269
Furquan Shaikh7778e5c2020-04-16 08:25:58 -0700270DEVTREE_CONST struct device *pcidev_path_behind_pci2pci_bridge(
271 const struct device *bridge,
272 pci_devfn_t devfn)
273{
274 if (!bridge || (bridge->path.type != DEVICE_PATH_PCI)) {
Julius Werner3e034b62020-07-29 17:39:21 -0700275 BUG();
Furquan Shaikh7778e5c2020-04-16 08:25:58 -0700276 /* Return NULL in case asserts are non-fatal. */
277 return NULL;
278 }
279
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200280 return pcidev_path_behind(bridge->downstream, devfn);
Furquan Shaikh7778e5c2020-04-16 08:25:58 -0700281}
282
Kyösti Mälkkif2ac0132019-07-12 15:26:29 +0300283DEVTREE_CONST struct device *pcidev_path_on_root_debug(pci_devfn_t devfn, const char *func)
284{
285 DEVTREE_CONST struct device *dev = pcidev_path_on_root(devfn);
286 if (dev)
287 return dev;
288
Kyösti Mälkki4323d262019-07-12 16:20:14 +0300289 devtree_bug(func, devfn);
Kyösti Mälkkif2ac0132019-07-12 15:26:29 +0300290
291 /* FIXME: This can return wrong device. */
292 return dev_find_slot(0, devfn);
293}
294
Kyösti Mälkki4323d262019-07-12 16:20:14 +0300295void devtree_bug(const char *func, pci_devfn_t devfn)
296{
297 printk(BIOS_ERR, "BUG: %s requests hidden 00:%02x.%u\n", func, devfn >> 3, devfn & 7);
298}
299
300void __noreturn devtree_die(void)
301{
302 die("DEVTREE: dev or chip_info is NULL\n");
303}
304
Martin Roth16d953a2014-05-12 17:38:59 -0600305/**
Stefan Reinauer57879c92012-07-31 16:47:25 -0700306 * Given an SMBus bus and a device number, find the device structure.
307 *
308 * @param bus The bus number.
309 * @param addr A device number.
310 * @return Pointer to the device structure (if found), 0 otherwise.
311 */
Aaron Durbine4d7abc2017-04-16 22:05:36 -0500312DEVTREE_CONST struct device *dev_find_slot_on_smbus(unsigned int bus,
Stefan Reinauer57879c92012-07-31 16:47:25 -0700313 unsigned int addr)
314{
Aaron Durbine4d7abc2017-04-16 22:05:36 -0500315 DEVTREE_CONST struct device *dev, *result;
Stefan Reinauer57879c92012-07-31 16:47:25 -0700316
317 result = 0;
318 for (dev = all_devices; dev; dev = dev->next) {
319 if ((dev->path.type == DEVICE_PATH_I2C) &&
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200320 (dev->upstream->secondary == bus) &&
Stefan Reinauer57879c92012-07-31 16:47:25 -0700321 (dev->path.i2c.device == addr)) {
322 result = dev;
323 break;
324 }
325 }
326 return result;
327}
Kyösti Mälkki96643452015-01-28 22:03:46 +0200328
329/**
330 * Given a PnP port and a device number, find the device structure.
331 *
332 * @param port The I/O port.
333 * @param device Logical device number.
334 * @return Pointer to the device structure (if found), 0 otherwise.
335 */
Aaron Durbine4d7abc2017-04-16 22:05:36 -0500336DEVTREE_CONST struct device *dev_find_slot_pnp(u16 port, u16 device)
Kyösti Mälkki96643452015-01-28 22:03:46 +0200337{
Aaron Durbine4d7abc2017-04-16 22:05:36 -0500338 DEVTREE_CONST struct device *dev;
Kyösti Mälkki96643452015-01-28 22:03:46 +0200339
340 for (dev = all_devices; dev; dev = dev->next) {
341 if ((dev->path.type == DEVICE_PATH_PNP) &&
342 (dev->path.pnp.port == port) &&
343 (dev->path.pnp.device == device)) {
344 return dev;
345 }
346 }
347 return 0;
348}
Aaron Durbina0dabd12018-07-25 08:49:19 -0600349
350/**
351 * Given a device and previous match iterate through all the children.
352 *
353 * @param bus parent device's bus holding all the children
354 * @param prev_child previous child already traversed, if NULL start at
355 * children of parent bus.
356 * @return pointer to child or NULL when no more children
357 */
358DEVTREE_CONST struct device *dev_bus_each_child(const struct bus *parent,
359 DEVTREE_CONST struct device *prev_child)
360{
361 DEVTREE_CONST struct device *dev;
362
363 if (parent == NULL)
364 return NULL;
365
366 if (prev_child == NULL)
367 dev = parent->children;
368 else
369 dev = prev_child->sibling;
370
371 return dev;
372}
Furquan Shaikh7f6ae792021-05-20 22:47:02 -0700373
374bool is_dev_enabled(const struct device *dev)
375{
376 if (!dev)
377 return false;
378
379 /* For stages with immutable device tree, first check if device is disabled because of
380 fw_config probing. In these stages, dev->enabled does not reflect the true state of a
381 device that uses fw_config probing. */
382 if (DEVTREE_EARLY && !fw_config_probe_dev(dev, NULL))
383 return false;
384 return dev->enabled;
385}
Subrata Banikeca3e622021-06-08 00:55:04 +0530386
387bool is_devfn_enabled(unsigned int devfn)
388{
389 const struct device *dev = pcidev_path_on_root(devfn);
390 return is_dev_enabled(dev);
391}