2 * This file is part of the coreboot project.
4 * Copyright (C) 2003-2004 Linux Networx
5 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
6 * Copyright (C) 2003 Greg Watson <jarrah@users.sourceforge.net>
7 * Copyright (C) 2004 Li-Ta Lo <ollie@lanl.gov>
8 * Copyright (C) 2005-2006 Tyan
9 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include <console/console.h>
22 #include <device/device.h>
23 #include <device/path.h>
24 #include <device/pci.h>
25 #include <device/pci_def.h>
26 #include <device/resource.h>
28 /** Linked list of ALL devices */
29 DEVTREE_CONST
struct device
* DEVTREE_CONST all_devices
= &dev_root
;
32 * Given a PCI bus and a devfn number, find the device structure.
34 * @param bus The bus number.
35 * @param devfn A device/function number.
36 * @return Pointer to the device structure (if found), 0 otherwise.
38 DEVTREE_CONST
struct device
*dev_find_slot(unsigned int bus
,
41 DEVTREE_CONST
struct device
*dev
, *result
;
44 for (dev
= all_devices
; dev
; dev
= dev
->next
) {
45 if ((dev
->path
.type
== DEVICE_PATH_PCI
) &&
46 (dev
->bus
->secondary
== bus
) &&
47 (dev
->path
.pci
.devfn
== devfn
)) {
56 * Given a Device Path Type, find the device structure.
58 * @param prev_match The previously matched device instance.
59 * @param path_type The Device Path Type.
60 * @return Pointer to the device structure (if found), 0 otherwise.
62 DEVTREE_CONST
struct device
*dev_find_path(
63 DEVTREE_CONST
struct device
*prev_match
,
64 enum device_path_type path_type
)
66 DEVTREE_CONST
struct device
*dev
, *result
= NULL
;
68 if (prev_match
== NULL
)
69 prev_match
= all_devices
;
71 prev_match
= prev_match
->next
;
73 for (dev
= prev_match
; dev
; dev
= dev
->next
) {
74 if (dev
->path
.type
== path_type
) {
83 * Given a device pointer, find the next PCI device.
85 * @param previous_dev A pointer to a PCI device structure.
86 * @return Pointer to the next device structure (if found), 0 otherwise.
88 DEVTREE_CONST
struct device
*dev_find_next_pci_device(
89 DEVTREE_CONST
struct device
*previous_dev
)
91 return dev_find_path(previous_dev
, DEVICE_PATH_PCI
);
94 static int path_eq(const struct device_path
*path1
,
95 const struct device_path
*path2
)
99 if (path1
->type
!= path2
->type
)
102 switch (path1
->type
) {
103 case DEVICE_PATH_NONE
:
105 case DEVICE_PATH_ROOT
:
108 case DEVICE_PATH_PCI
:
109 equal
= (path1
->pci
.devfn
== path2
->pci
.devfn
);
111 case DEVICE_PATH_PNP
:
112 equal
= (path1
->pnp
.port
== path2
->pnp
.port
) &&
113 (path1
->pnp
.device
== path2
->pnp
.device
);
115 case DEVICE_PATH_I2C
:
116 equal
= (path1
->i2c
.device
== path2
->i2c
.device
) &&
117 (path1
->i2c
.mode_10bit
== path2
->i2c
.mode_10bit
);
119 case DEVICE_PATH_APIC
:
120 equal
= (path1
->apic
.apic_id
== path2
->apic
.apic_id
);
122 case DEVICE_PATH_DOMAIN
:
123 equal
= (path1
->domain
.domain
== path2
->domain
.domain
);
125 case DEVICE_PATH_CPU_CLUSTER
:
126 equal
= (path1
->cpu_cluster
.cluster
127 == path2
->cpu_cluster
.cluster
);
129 case DEVICE_PATH_CPU
:
130 equal
= (path1
->cpu
.id
== path2
->cpu
.id
);
132 case DEVICE_PATH_CPU_BUS
:
133 equal
= (path1
->cpu_bus
.id
== path2
->cpu_bus
.id
);
135 case DEVICE_PATH_GENERIC
:
136 equal
= (path1
->generic
.id
== path2
->generic
.id
) &&
137 (path1
->generic
.subid
== path2
->generic
.subid
);
139 case DEVICE_PATH_SPI
:
140 equal
= (path1
->spi
.cs
== path2
->spi
.cs
);
142 case DEVICE_PATH_USB
:
143 equal
= (path1
->usb
.port_type
== path2
->usb
.port_type
) &&
144 (path1
->usb
.port_id
== path2
->usb
.port_id
);
146 case DEVICE_PATH_MMIO
:
147 equal
= (path1
->mmio
.addr
== path2
->mmio
.addr
);
150 printk(BIOS_ERR
, "Unknown device type: %d\n", path1
->type
);
158 * See if a device structure exists for path.
160 * @param parent The bus to find the device on.
161 * @param path The relative path from the bus to the appropriate device.
162 * @return Pointer to a device structure for the device on bus at path
163 * or 0/NULL if no device is found.
165 DEVTREE_CONST
struct device
*find_dev_path(
166 const struct bus
*parent
, const struct device_path
*path
)
168 DEVTREE_CONST
struct device
*child
;
169 for (child
= parent
->children
; child
; child
= child
->sibling
) {
170 if (path_eq(path
, &child
->path
))
176 DEVTREE_CONST
struct device
*pcidev_path_behind(
177 const struct bus
*parent
, pci_devfn_t devfn
)
179 const struct device_path path
= {
180 .type
= DEVICE_PATH_PCI
,
183 return find_dev_path(parent
, &path
);
186 DEVTREE_CONST
struct device
*pcidev_path_on_root(pci_devfn_t devfn
)
188 DEVTREE_CONST
struct device
*pci_domain
;
190 /* Work around pcidev_path_behind() below failing
191 * due tue complicated devicetree with topology
192 * being manipulated on-the-fly.
194 if (IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDFAM10
))
195 return dev_find_slot(0, devfn
);
197 pci_domain
= dev_find_path(NULL
, DEVICE_PATH_DOMAIN
);
201 return pcidev_path_behind(pci_domain
->link_list
, devfn
);
204 DEVTREE_CONST
struct device
*pcidev_on_root(uint8_t dev
, uint8_t fn
)
206 return pcidev_path_on_root(PCI_DEVFN(dev
, fn
));
210 * Given an SMBus bus and a device number, find the device structure.
212 * @param bus The bus number.
213 * @param addr A device number.
214 * @return Pointer to the device structure (if found), 0 otherwise.
216 DEVTREE_CONST
struct device
*dev_find_slot_on_smbus(unsigned int bus
,
219 DEVTREE_CONST
struct device
*dev
, *result
;
222 for (dev
= all_devices
; dev
; dev
= dev
->next
) {
223 if ((dev
->path
.type
== DEVICE_PATH_I2C
) &&
224 (dev
->bus
->secondary
== bus
) &&
225 (dev
->path
.i2c
.device
== addr
)) {
234 * Given a PnP port and a device number, find the device structure.
236 * @param port The I/O port.
237 * @param device Logical device number.
238 * @return Pointer to the device structure (if found), 0 otherwise.
240 DEVTREE_CONST
struct device
*dev_find_slot_pnp(u16 port
, u16 device
)
242 DEVTREE_CONST
struct device
*dev
;
244 for (dev
= all_devices
; dev
; dev
= dev
->next
) {
245 if ((dev
->path
.type
== DEVICE_PATH_PNP
) &&
246 (dev
->path
.pnp
.port
== port
) &&
247 (dev
->path
.pnp
.device
== device
)) {
255 * Given a device and previous match iterate through all the children.
257 * @param bus parent device's bus holding all the children
258 * @param prev_child previous child already traversed, if NULL start at
259 * children of parent bus.
260 * @return pointer to child or NULL when no more children
262 DEVTREE_CONST
struct device
*dev_bus_each_child(const struct bus
*parent
,
263 DEVTREE_CONST
struct device
*prev_child
)
265 DEVTREE_CONST
struct device
*dev
;
270 if (prev_child
== NULL
)
271 dev
= parent
->children
;
273 dev
= prev_child
->sibling
;