/ src / device / device_const.c
device_const.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <assert.h>
  4  #include <console/console.h>
  5  #include <device/device.h>
  6  #include <device/pci_def.h>
  7  #include <device/pci_type.h>
  8  #include <fw_config.h>
  9  #include <types.h>
 10  
 11  /** Linked list of ALL devices */
 12  DEVTREE_CONST struct device *DEVTREE_CONST all_devices = &dev_root;
 13  
 14  /**
 15   * Given a PCI bus and a devfn number, find the device structure.
 16   *
 17   * Note that this function can return the incorrect device prior
 18   * to PCI enumeration because the secondary field of the bus object
 19   * is 0. The failing scenario is determined by the order of the
 20   * devices in all_devices singly-linked list as well as the time
 21   * when this function is called (secondary reflecting topology).
 22   *
 23   * @param bus The bus number.
 24   * @param devfn A device/function number.
 25   * @return Pointer to the device structure (if found), 0 otherwise.
 26   */
 27  
 28  static DEVTREE_CONST struct device *dev_find_slot(unsigned int bus,
 29  						unsigned int devfn)
 30  {
 31  	DEVTREE_CONST struct device *dev, *result;
 32  
 33  	result = 0;
 34  	for (dev = all_devices; dev; dev = dev->next) {
 35  		if ((dev->path.type == DEVICE_PATH_PCI) &&
 36  		    (dev->upstream->secondary == bus) &&
 37  		    (dev->upstream->segment_group == 0) &&
 38  		    (dev->path.pci.devfn == devfn)) {
 39  			result = dev;
 40  			break;
 41  		}
 42  	}
 43  	return result;
 44  }
 45  
 46  /**
 47   * Given a Device Path Type, find the device structure.
 48   *
 49   * @param prev_match The previously matched device instance.
 50   * @param path_type The Device Path Type.
 51   * @return Pointer to the device structure (if found), 0 otherwise.
 52   */
 53  DEVTREE_CONST struct device *dev_find_path(
 54  		DEVTREE_CONST struct device *prev_match,
 55  		enum device_path_type path_type)
 56  {
 57  	DEVTREE_CONST struct device *dev, *result = NULL;
 58  
 59  	if (prev_match == NULL)
 60  		prev_match = all_devices;
 61  	else
 62  		prev_match = prev_match->next;
 63  
 64  	for (dev = prev_match; dev; dev = dev->next) {
 65  		if (dev->path.type == path_type) {
 66  			result = dev;
 67  			break;
 68  		}
 69  	}
 70  	return result;
 71  }
 72  
 73  /**
 74   * Given a device pointer, find the next PCI device.
 75   *
 76   * @param previous_dev A pointer to a PCI device structure.
 77   * @return Pointer to the next device structure (if found), 0 otherwise.
 78   */
 79  DEVTREE_CONST struct device *dev_find_next_pci_device(
 80  		DEVTREE_CONST struct device *previous_dev)
 81  {
 82  	return dev_find_path(previous_dev, DEVICE_PATH_PCI);
 83  }
 84  
 85  static int path_eq(const struct device_path *path1,
 86  		const struct device_path *path2)
 87  {
 88  	int equal = 0;
 89  
 90  	if (!path1 || !path2) {
 91  		assert(path1);
 92  		assert(path2);
 93  		/* Return 0 in case assert is considered non-fatal. */
 94  		return 0;
 95  	}
 96  
 97  	if (path1->type != path2->type)
 98  		return 0;
 99  
100  	switch (path1->type) {
101  	case DEVICE_PATH_NONE:
102  		break;
103  	case DEVICE_PATH_ROOT:
104  		equal = 1;
105  		break;
106  	case DEVICE_PATH_PCI:
107  		equal = (path1->pci.devfn == path2->pci.devfn);
108  		break;
109  	case DEVICE_PATH_PNP:
110  		equal = (path1->pnp.port == path2->pnp.port) &&
111  			(path1->pnp.device == path2->pnp.device);
112  		break;
113  	case DEVICE_PATH_I2C:
114  		equal = (path1->i2c.device == path2->i2c.device) &&
115  			(path1->i2c.mode_10bit == path2->i2c.mode_10bit);
116  		break;
117  	case DEVICE_PATH_APIC:
118  		equal = (path1->apic.apic_id == path2->apic.apic_id);
119  		break;
120  	case DEVICE_PATH_DOMAIN:
121  		equal = (path1->domain.domain_id == path2->domain.domain_id);
122  		break;
123  	case DEVICE_PATH_CPU_CLUSTER:
124  		equal = (path1->cpu_cluster.cluster
125  			 == path2->cpu_cluster.cluster);
126  		break;
127  	case DEVICE_PATH_CPU:
128  		equal = (path1->cpu.id == path2->cpu.id);
129  		break;
130  	case DEVICE_PATH_CPU_BUS:
131  		equal = (path1->cpu_bus.id == path2->cpu_bus.id);
132  		break;
133  	case DEVICE_PATH_IOAPIC:
134  		equal = (path1->ioapic.ioapic_id == path2->ioapic.ioapic_id);
135  		break;
136  	case DEVICE_PATH_GENERIC:
137  		equal = (path1->generic.id == path2->generic.id) &&
138  			(path1->generic.subid == path2->generic.subid);
139  		break;
140  	case DEVICE_PATH_SPI:
141  		equal = (path1->spi.cs == path2->spi.cs);
142  		break;
143  	case DEVICE_PATH_USB:
144  		equal = (path1->usb.port_type == path2->usb.port_type) &&
145  			(path1->usb.port_id == path2->usb.port_id);
146  		break;
147  	case DEVICE_PATH_MMIO:
148  		equal = (path1->mmio.addr == path2->mmio.addr);
149  		break;
150  	case DEVICE_PATH_GPIO:
151  		equal = (path1->gpio.id == path2->gpio.id);
152  		break;
153  	case DEVICE_PATH_MDIO:
154  		equal = (path1->mdio.addr == path2->mdio.addr);
155  		break;
156  
157  	default:
158  		printk(BIOS_ERR, "Unknown device type: %d\n", path1->type);
159  		break;
160  	}
161  
162  	return equal;
163  }
164  
165  /**
166   * See if a device structure exists for path.
167   *
168   * @param parent The bus to find the device on.
169   * @param path The relative path from the bus to the appropriate device.
170   * @return Pointer to a device structure for the device on bus at path
171   *         or 0/NULL if no device is found.
172   */
173  DEVTREE_CONST struct device *find_dev_path(
174  	const struct bus *parent, const struct device_path *path)
175  {
176  	DEVTREE_CONST struct device *child;
177  
178  	if (!parent) {
179  		BUG();
180  		/* Return NULL in case asserts are considered non-fatal. */
181  		return NULL;
182  	}
183  
184  	for (child = parent->children; child; child = child->sibling) {
185  		if (path_eq(path, &child->path))
186  			break;
187  	}
188  	return child;
189  }
190  
191  /**
192   * Find the device structure given an array of nested device paths,
193   *
194   * @param parent The parent bus to start the search on.
195   * @param nested_path An array of relative paths from the parent bus to the target device.
196   * @param nested_path_length Number of path elements in nested_path array.
197   * @return Pointer to a device structure for the device at nested path
198   *         or 0/NULL if no device is found.
199   */
200  DEVTREE_CONST struct device *find_dev_nested_path(
201  	const struct bus *parent, const struct device_path nested_path[],
202  	size_t nested_path_length)
203  {
204  	DEVTREE_CONST struct device *child;
205  
206  	if (!parent || !nested_path || !nested_path_length)
207  		return NULL;
208  
209  	child = find_dev_path(parent, nested_path);
210  
211  	/* Terminate recursion at end of nested path or child not found */
212  	if (nested_path_length == 1 || !child)
213  		return child;
214  
215  	return find_dev_nested_path(child->downstream, nested_path + 1, nested_path_length - 1);
216  }
217  
218  DEVTREE_CONST struct device *pcidev_path_behind(
219  	const struct bus *parent, pci_devfn_t devfn)
220  {
221  	const struct device_path path = {
222  		.type = DEVICE_PATH_PCI,
223  		.pci.devfn = devfn,
224  	};
225  	return find_dev_path(parent, &path);
226  }
227  
228  DEVTREE_CONST struct device *pcidev_path_on_bus(unsigned int bus, pci_devfn_t devfn)
229  {
230  	DEVTREE_CONST struct bus *parent = pci_root_bus();
231  	DEVTREE_CONST struct device *dev = parent->children;
232  
233  	/* FIXME: Write the loop with topology links. */
234  	while (dev) {
235  		if (dev->path.type != DEVICE_PATH_PCI) {
236  			dev = dev->next;
237  			continue;
238  		}
239  		if (dev->upstream->secondary == bus && dev->upstream->segment_group == 0)
240  			return pcidev_path_behind(dev->upstream, devfn);
241  		dev = dev->next;
242  	}
243  	return NULL;
244  }
245  
246  DEVTREE_CONST struct bus *pci_root_bus(void)
247  {
248  	DEVTREE_CONST struct device *pci_domain;
249  	static DEVTREE_CONST struct bus *pci_root;
250  
251  	if (pci_root)
252  		return pci_root;
253  
254  	pci_domain = dev_find_path(NULL, DEVICE_PATH_DOMAIN);
255  	if (!pci_domain)
256  		return NULL;
257  
258  	pci_root = pci_domain->downstream;
259  	return pci_root;
260  }
261  
262  DEVTREE_CONST struct device *pcidev_path_on_root(pci_devfn_t devfn)
263  {
264  	return pcidev_path_behind(pci_root_bus(), devfn);
265  }
266  
267  DEVTREE_CONST struct device *pcidev_on_root(uint8_t dev, uint8_t fn)
268  {
269  	return pcidev_path_on_root(PCI_DEVFN(dev, fn));
270  }
271  
272  DEVTREE_CONST struct device *pcidev_path_behind_pci2pci_bridge(
273  							const struct device *bridge,
274  							pci_devfn_t devfn)
275  {
276  	if (!bridge || (bridge->path.type != DEVICE_PATH_PCI)) {
277  		BUG();
278  		/* Return NULL in case asserts are non-fatal. */
279  		return NULL;
280  	}
281  
282  	return pcidev_path_behind(bridge->downstream, devfn);
283  }
284  
285  DEVTREE_CONST struct device *pcidev_path_on_root_debug(pci_devfn_t devfn, const char *func)
286  {
287  	DEVTREE_CONST struct device *dev = pcidev_path_on_root(devfn);
288  	if (dev)
289  		return dev;
290  
291  	devtree_bug(func, devfn);
292  
293  	/* FIXME: This can return wrong device. */
294  	return dev_find_slot(0, devfn);
295  }
296  
297  void devtree_bug(const char *func, pci_devfn_t devfn)
298  {
299  	printk(BIOS_ERR, "BUG: %s requests hidden 00:%02x.%u\n", func, devfn >> 3, devfn & 7);
300  }
301  
302  void __noreturn devtree_die(void)
303  {
304  	die("DEVTREE: dev or chip_info is NULL\n");
305  }
306  
307  /**
308   * Given an SMBus bus and a device number, find the device structure.
309   *
310   * @param bus The bus number.
311   * @param addr A device number.
312   * @return Pointer to the device structure (if found), 0 otherwise.
313   */
314  DEVTREE_CONST struct device *dev_find_slot_on_smbus(unsigned int bus,
315  							unsigned int addr)
316  {
317  	DEVTREE_CONST struct device *dev, *result;
318  
319  	result = 0;
320  	for (dev = all_devices; dev; dev = dev->next) {
321  		if ((dev->path.type == DEVICE_PATH_I2C) &&
322  		    (dev->upstream->secondary == bus) &&
323  		    (dev->path.i2c.device == addr)) {
324  			result = dev;
325  			break;
326  		}
327  	}
328  	return result;
329  }
330  
331  /**
332   * Given a PnP port and a device number, find the device structure.
333   *
334   * @param port The I/O port.
335   * @param device Logical device number.
336   * @return Pointer to the device structure (if found), 0 otherwise.
337   */
338  DEVTREE_CONST struct device *dev_find_slot_pnp(u16 port, u16 device)
339  {
340  	DEVTREE_CONST struct device *dev;
341  
342  	for (dev = all_devices; dev; dev = dev->next) {
343  		if ((dev->path.type == DEVICE_PATH_PNP) &&
344  		    (dev->path.pnp.port == port) &&
345  		    (dev->path.pnp.device == device)) {
346  			return dev;
347  		}
348  	}
349  	return 0;
350  }
351  
352  /**
353   * Given a device and previous match iterate through all the children.
354   *
355   * @param bus parent device's bus holding all the children
356   * @param prev_child previous child already traversed, if NULL start at
357   *        children of parent bus.
358   * @return pointer to child or NULL when no more children
359   */
360  DEVTREE_CONST struct device *dev_bus_each_child(const struct bus *parent,
361  					DEVTREE_CONST struct device *prev_child)
362  {
363  	DEVTREE_CONST struct device *dev;
364  
365  	if (parent == NULL)
366  		return NULL;
367  
368  	if (prev_child == NULL)
369  		dev = parent->children;
370  	else
371  		dev = prev_child->sibling;
372  
373  	return dev;
374  }
375  
376  bool is_dev_enabled(const struct device *dev)
377  {
378  	if (!dev)
379  		return false;
380  
381  	/* For stages with immutable device tree, first check if device is disabled because of
382  	   fw_config probing. In these stages, dev->enabled does not reflect the true state of a
383  	   device that uses fw_config probing. */
384  	if (DEVTREE_EARLY && !fw_config_probe_dev(dev, NULL))
385  		return false;
386  	return dev->enabled;
387  }
388  
389  bool is_devfn_enabled(unsigned int devfn)
390  {
391  	const struct device *dev = pcidev_path_on_root(devfn);
392  	return is_dev_enabled(dev);
393  }