blob: 743a3af6c200be299ca34ed6efe109c632c791d3 [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Uwe Hermanne4870472010-11-04 23:23:47 +00002
3/*
Martin Roth99f83bb2019-09-15 20:57:18 -07004 * Originally based on the Linux kernel (arch/i386/kernel/pci-pc.c).
Eric Biederman8ca8d762003-04-22 19:02:15 +00005 */
6
7#include <console/console.h>
Eric Biederman5899fd82003-04-24 06:25:08 +00008#include <device/device.h>
Kyösti Mälkki318066f2014-02-12 14:18:50 +02009#include <device/pci_def.h>
Li-Ta Lo54f05f62004-05-14 17:20:29 +000010#include <device/pci_ids.h>
Kyösti Mälkkice39ba92020-01-04 16:15:50 +020011#include <post.h>
Eric Biedermane9a271e32003-09-02 03:36:25 +000012#include <stdlib.h>
13#include <string.h>
Eric Biederman03acab62004-10-14 21:25:53 +000014#include <smp/spinlock.h>
Aaron Durbin05294292013-04-30 15:41:13 -050015#include <timer.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000016
Li-Ta Loe5266692004-03-23 21:28:05 +000017/** Pointer to the last device */
Myles Watson70679a02010-09-01 21:03:03 +000018extern struct device *last_dev;
Myles Watsonc25cc112010-05-21 14:33:48 +000019/** Linked list of free resources */
20struct resource *free_resources = NULL;
Subrata Baniked5c7ac2021-06-10 13:04:07 +053021/* Disable a PCI device based on bus, device and function. */
22void devfn_disable(const struct bus *bus, unsigned int devfn)
23{
24 struct device *dev = pcidev_path_behind(bus, devfn);
25 if (dev)
26 dev->enabled = 0;
27}
Eric Biederman8ca8d762003-04-22 19:02:15 +000028
Nico Huberacd7d952012-07-25 10:33:05 +020029/**
30 * Initialize all chips of statically known devices.
31 *
32 * Will be called before bus enumeration to initialize chips stated in the
33 * device tree.
34 */
35void dev_initialize_chips(void)
36{
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +020037 const struct device *dev;
Nico Huberacd7d952012-07-25 10:33:05 +020038
39 for (dev = all_devices; dev; dev = dev->next) {
40 /* Initialize chip if we haven't yet. */
41 if (dev->chip_ops && dev->chip_ops->init &&
42 !dev->chip_ops->initialized) {
Duncan Laurie8adf7a22013-06-10 10:34:20 -070043 post_log_path(dev);
Nico Huberacd7d952012-07-25 10:33:05 +020044 dev->chip_ops->init(dev->chip_info);
45 dev->chip_ops->initialized = 1;
46 }
47 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -070048 post_log_clear();
Nico Huberacd7d952012-07-25 10:33:05 +020049}
50
Marc Jones2a58ecd2013-10-29 17:32:00 -060051/**
52 * Finalize all chips of statically known devices.
53 *
54 * This is the last call before calling the payload. This is a good place
55 * to lock registers or other final cleanup.
56 */
57void dev_finalize_chips(void)
58{
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +020059 const struct device *dev;
Marc Jones2a58ecd2013-10-29 17:32:00 -060060
61 for (dev = all_devices; dev; dev = dev->next) {
62 /* Initialize chip if we haven't yet. */
63 if (dev->chip_ops && dev->chip_ops->final &&
64 !dev->chip_ops->finalized) {
65 dev->chip_ops->final(dev->chip_info);
66 dev->chip_ops->finalized = 1;
67 }
68 }
69}
70
Uwe Hermannc1ee4292010-10-17 19:01:48 +000071DECLARE_SPIN_LOCK(dev_lock)
Eric Biederman8ca8d762003-04-22 19:02:15 +000072
Li-Ta Loe5266692004-03-23 21:28:05 +000073/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +000074 * Allocate a new device structure.
Myles Watson032a9652009-05-11 22:24:53 +000075 *
Martin Roth63373ed2013-07-08 16:24:19 -060076 * Allocate a new device structure and attach it to the device tree as a
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +000077 * child of the parent bus.
Li-Ta Loe5266692004-03-23 21:28:05 +000078 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +000079 * @param parent Parent bus the newly created device should be attached to.
80 * @param path Path to the device to be created.
81 * @return Pointer to the newly created device structure.
Li-Ta Loe5266692004-03-23 21:28:05 +000082 *
83 * @see device_path
Eric Biederman8ca8d762003-04-22 19:02:15 +000084 */
Elyes HAOUASd34a7852018-09-17 10:44:14 +020085static struct device *__alloc_dev(struct bus *parent, struct device_path *path)
Eric Biederman8ca8d762003-04-22 19:02:15 +000086{
Elyes HAOUASe3480662018-05-06 20:32:23 +020087 struct device *dev, *child;
Li-Ta Loe5266692004-03-23 21:28:05 +000088
Myles Watson29cc9ed2009-07-02 18:56:24 +000089 /* Find the last child of our parent. */
Elyes HAOUASa342f392018-10-17 10:56:26 +020090 for (child = parent->children; child && child->sibling; /* */)
Eric Biedermane9a271e32003-09-02 03:36:25 +000091 child = child->sibling;
Li-Ta Lo3a812852004-12-03 22:39:34 +000092
Eric Biedermane9a271e32003-09-02 03:36:25 +000093 dev = malloc(sizeof(*dev));
Myles Watson29cc9ed2009-07-02 18:56:24 +000094 if (dev == 0)
Uwe Hermanne4870472010-11-04 23:23:47 +000095 die("alloc_dev(): out of memory.\n");
Myles Watson29cc9ed2009-07-02 18:56:24 +000096
Eric Biedermane9a271e32003-09-02 03:36:25 +000097 memset(dev, 0, sizeof(*dev));
98 memcpy(&dev->path, path, sizeof(*path));
99
Myles Watson29cc9ed2009-07-02 18:56:24 +0000100 /* By default devices are enabled. */
Eric Biederman03acab62004-10-14 21:25:53 +0000101 dev->enabled = 1;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000102
Eric Biedermanb78c1972004-10-14 20:54:17 +0000103 /* Add the new device to the list of children of the bus. */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000104 dev->bus = parent;
Uwe Hermanne4870472010-11-04 23:23:47 +0000105 if (child)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000106 child->sibling = dev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000107 else
Eric Biedermane9a271e32003-09-02 03:36:25 +0000108 parent->children = dev;
Li-Ta Loe5266692004-03-23 21:28:05 +0000109
Eric Biederman03acab62004-10-14 21:25:53 +0000110 /* Append a new device to the global device list.
111 * The list is used to find devices once everything is set up.
112 */
Myles Watson70679a02010-09-01 21:03:03 +0000113 last_dev->next = dev;
114 last_dev = dev;
Eric Biederman03acab62004-10-14 21:25:53 +0000115
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300116 return dev;
117}
118
Elyes HAOUASd34a7852018-09-17 10:44:14 +0200119struct device *alloc_dev(struct bus *parent, struct device_path *path)
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300120{
Elyes HAOUASe3480662018-05-06 20:32:23 +0200121 struct device *dev;
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300122 spin_lock(&dev_lock);
123 dev = __alloc_dev(parent, path);
Eric Biederman03acab62004-10-14 21:25:53 +0000124 spin_unlock(&dev_lock);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000125 return dev;
126}
Eric Biederman8ca8d762003-04-22 19:02:15 +0000127
Arthur Heymans3e99ba02024-01-25 22:26:07 +0100128DECLARE_SPIN_LOCK(bus_lock)
129
130/**
131 * Allocate a new bus structure
132 *
133 * Allocate a new downstream bus structure below a device and attach it
134 * to the device tree if the device doesn't already have a downstream bus.
135 *
136 * @param parent Parent device the to be created bus should be attached to.
137 * @return Pointer to the newly created bus structure or the existing bus.
138 *
139 */
140static struct bus *__alloc_bus(struct device *parent)
141{
142 if (parent->link_list)
143 return parent->link_list;
144
145 struct bus *bus = calloc(1, sizeof(struct bus));
146 if (!bus)
147 die("Couldn't allocate downstream bus!\n");
148 parent->link_list = bus;
149 bus->dev = parent;
150
151 return bus;
152}
153
154struct bus *alloc_bus(struct device *parent)
155{
156 struct bus *bus;
157 spin_lock(&bus_lock);
158 bus = __alloc_bus(parent);
159 spin_unlock(&bus_lock);
160 return bus;
161}
162
Li-Ta Loe5266692004-03-23 21:28:05 +0000163/**
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300164 * See if a device structure already exists and if not allocate it.
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 */
Elyes HAOUASd34a7852018-09-17 10:44:14 +0200170struct device *alloc_find_dev(struct bus *parent, struct device_path *path)
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300171{
Elyes HAOUASe3480662018-05-06 20:32:23 +0200172 struct device *child;
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300173 spin_lock(&dev_lock);
174 child = find_dev_path(parent, path);
175 if (!child)
176 child = __alloc_dev(parent, path);
177 spin_unlock(&dev_lock);
178 return child;
179}
180
181/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000182 * Read the resources on all devices of a given bus.
183 *
184 * @param bus Bus to read the resources on.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000185 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000186static void read_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000187{
188 struct device *curdev;
189
Arthur Heymans80c79a52023-08-24 15:12:19 +0200190 printk(BIOS_SPEW, "%s %s segment group %d bus %d\n", dev_path(bus->dev),
191 __func__, bus->segment_group, bus->secondary);
Eric Biederman448bd632004-10-14 22:52:15 +0000192
Myles Watson29cc9ed2009-07-02 18:56:24 +0000193 /* Walk through all devices and find which resources they need. */
194 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000195 if (!curdev->enabled)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000196 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000197
Eric Biedermane9a271e32003-09-02 03:36:25 +0000198 if (!curdev->ops || !curdev->ops->read_resources) {
Martin Roth7bc74ab2015-11-18 20:23:02 -0700199 if (curdev->path.type != DEVICE_PATH_APIC)
Frans Hendriksa9caa502021-02-01 11:44:37 +0100200 printk(BIOS_ERR, "%s missing %s\n",
201 dev_path(curdev), __func__);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000202 continue;
203 }
Duncan Laurie7ed39762013-07-09 10:46:52 -0700204 post_log_path(curdev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000205 curdev->ops->read_resources(curdev);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000206
207 /* Read in the resources behind the current device's links. */
Arthur Heymans80c79a52023-08-24 15:12:19 +0200208 if (curdev->link_list)
209 read_resources(curdev->link_list);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000210 }
Duncan Laurie7ed39762013-07-09 10:46:52 -0700211 post_log_clear();
Arthur Heymans80c79a52023-08-24 15:12:19 +0200212 printk(BIOS_SPEW, "%s %s segment group %d bus %d done\n",
213 dev_path(bus->dev), __func__, bus->segment_group, bus->secondary);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000214}
215
Elyes HAOUASe3480662018-05-06 20:32:23 +0200216struct device *vga_pri = NULL;
Myles Watsonc7233e02009-07-02 19:02:33 +0000217static void set_vga_bridge_bits(void)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000218{
Uwe Hermann312673c2009-10-27 21:49:33 +0000219 /*
Martin Roth63373ed2013-07-08 16:24:19 -0600220 * FIXME: Modify set_vga_bridge() so it is less PCI-centric!
Uwe Hermann312673c2009-10-27 21:49:33 +0000221 * This function knows too much about PCI stuff, it should be just
222 * an iterator/visitor.
223 */
Li-Ta Loe5266692004-03-23 21:28:05 +0000224
Myles Watson29cc9ed2009-07-02 18:56:24 +0000225 /* FIXME: Handle the VGA palette snooping. */
Patrick Georgi557ecf22012-07-20 12:16:17 +0200226 struct device *dev, *vga, *vga_onboard;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000227 struct bus *bus;
Uwe Hermanne4870472010-11-04 23:23:47 +0000228
Eric Biedermanb78c1972004-10-14 20:54:17 +0000229 bus = 0;
230 vga = 0;
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000231 vga_onboard = 0;
Uwe Hermanne4870472010-11-04 23:23:47 +0000232
Patrick Georgi557ecf22012-07-20 12:16:17 +0200233 dev = NULL;
234 while ((dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev))) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000235 if (!dev->enabled)
236 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000237
Patrick Georgi557ecf22012-07-20 12:16:17 +0200238 printk(BIOS_DEBUG, "found VGA at %s\n", dev_path(dev));
Nico Huber061b9052019-09-21 15:58:23 +0200239 if (dev->bus->no_vga16) {
240 printk(BIOS_WARNING,
241 "A bridge on the path doesn't support 16-bit VGA decoding!");
242 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000243
Frans Hendriksa9caa502021-02-01 11:44:37 +0100244 if (dev->on_mainboard)
Patrick Georgi557ecf22012-07-20 12:16:17 +0200245 vga_onboard = dev;
Frans Hendriksa9caa502021-02-01 11:44:37 +0100246 else
Patrick Georgi557ecf22012-07-20 12:16:17 +0200247 vga = dev;
Myles Watson032a9652009-05-11 22:24:53 +0000248
Patrick Georgi557ecf22012-07-20 12:16:17 +0200249 /* It isn't safe to enable all VGA cards. */
250 dev->command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Patrick Georgi594473d2012-07-25 08:55:53 +0200251 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000252
Uwe Hermanne4870472010-11-04 23:23:47 +0000253 if (!vga)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000254 vga = vga_onboard;
Patrick Georgi557ecf22012-07-20 12:16:17 +0200255
Julius Werner5d1f9a02019-03-07 17:07:26 -0800256 if (CONFIG(ONBOARD_VGA_IS_PRIMARY) && vga_onboard)
Patrick Georgi557ecf22012-07-20 12:16:17 +0200257 vga = vga_onboard;
Myles Watson032a9652009-05-11 22:24:53 +0000258
Patrick Georgi5869fa22012-07-20 12:29:33 +0200259 /* If we prefer plugin VGA over chipset VGA, the chipset might
260 want to know. */
Julius Werner5d1f9a02019-03-07 17:07:26 -0800261 if (!CONFIG(ONBOARD_VGA_IS_PRIMARY) && (vga != vga_onboard) &&
Arthur Heymansb238caa2021-02-22 18:33:08 +0100262 vga_onboard && vga_onboard->ops && vga_onboard->ops->vga_disable) {
Patrick Georgi5869fa22012-07-20 12:29:33 +0200263 printk(BIOS_DEBUG, "Use plugin graphics over integrated.\n");
Arthur Heymansb238caa2021-02-22 18:33:08 +0100264 vga_onboard->ops->vga_disable(vga_onboard);
Patrick Georgi5869fa22012-07-20 12:29:33 +0200265 }
266
arch import user (historical)dc811182005-07-06 17:16:09 +0000267 if (vga) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000268 /* VGA is first add-on card or the only onboard VGA. */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000269 printk(BIOS_DEBUG, "Setting up VGA for %s\n", dev_path(vga));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000270 /* All legacy VGA cards have MEM & I/O space registers. */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000271 vga->command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
272 vga_pri = vga;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000273 bus = vga->bus;
274 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000275
Myles Watson29cc9ed2009-07-02 18:56:24 +0000276 /* Now walk up the bridges setting the VGA enable. */
277 while (bus) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000278 printk(BIOS_DEBUG, "Setting PCI_BRIDGE_CTL_VGA for bridge %s\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000279 dev_path(bus->dev));
Nico Huber061b9052019-09-21 15:58:23 +0200280 bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA | PCI_BRIDGE_CTL_VGA16;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000281 bus = (bus == bus->dev->bus) ? 0 : bus->dev->bus;
Myles Watson032a9652009-05-11 22:24:53 +0000282 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000283}
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000284
Li-Ta Lo04930692004-11-25 17:37:19 +0000285/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000286 * Assign the computed resources to the devices on the bus.
Li-Ta Lo04930692004-11-25 17:37:19 +0000287 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000288 * Use the device specific set_resources() method to store the computed
Li-Ta Lo04930692004-11-25 17:37:19 +0000289 * resources to hardware. For bridge devices, the set_resources() method
290 * has to recurse into every down stream buses.
291 *
292 * Mutual recursion:
293 * assign_resources() -> device_operation::set_resources()
294 * device_operation::set_resources() -> assign_resources()
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000295 *
296 * @param bus Pointer to the structure for this bus.
Li-Ta Lo04930692004-11-25 17:37:19 +0000297 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000298void assign_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000299{
300 struct device *curdev;
301
Arthur Heymans80c79a52023-08-24 15:12:19 +0200302 printk(BIOS_SPEW, "%s %s, segment group %d bus %d\n",
303 dev_path(bus->dev), __func__, bus->segment_group, bus->secondary);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000304
Myles Watson29cc9ed2009-07-02 18:56:24 +0000305 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000306 if (!curdev->enabled || !curdev->resource_list)
Eric Biederman03acab62004-10-14 21:25:53 +0000307 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000308
Eric Biedermane9a271e32003-09-02 03:36:25 +0000309 if (!curdev->ops || !curdev->ops->set_resources) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000310 printk(BIOS_ERR, "%s missing set_resources\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000311 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000312 continue;
313 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700314 post_log_path(curdev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000315 curdev->ops->set_resources(curdev);
316 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700317 post_log_clear();
Arthur Heymans80c79a52023-08-24 15:12:19 +0200318 printk(BIOS_SPEW, "%s %s, segment group %d bus %d done\n",
319 dev_path(bus->dev), __func__, bus->segment_group, bus->secondary);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000320}
321
Li-Ta Lo5782d272004-04-26 17:51:20 +0000322/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000323 * Enable the resources for devices on a link.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000324 *
325 * Enable resources of the device by calling the device specific
326 * enable_resources() method.
327 *
328 * The parent's resources should be enabled first to avoid having enabling
329 * order problem. This is done by calling the parent's enable_resources()
Martin Roth63373ed2013-07-08 16:24:19 -0600330 * method before its children's enable_resources() methods.
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +0000331 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000332 * @param link The link whose devices' resources are to be enabled.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000333 */
Myles Watson7eac4452010-06-17 16:16:56 +0000334static void enable_resources(struct bus *link)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000335{
Myles Watson7eac4452010-06-17 16:16:56 +0000336 struct device *dev;
Myles Watson7eac4452010-06-17 16:16:56 +0000337
338 for (dev = link->children; dev; dev = dev->sibling) {
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700339 if (dev->enabled && dev->ops && dev->ops->enable_resources) {
340 post_log_path(dev);
Myles Watson7eac4452010-06-17 16:16:56 +0000341 dev->ops->enable_resources(dev);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700342 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000343 }
Myles Watson7eac4452010-06-17 16:16:56 +0000344
345 for (dev = link->children; dev; dev = dev->sibling) {
Arthur Heymans80c79a52023-08-24 15:12:19 +0200346 if (dev->link_list)
347 enable_resources(dev->link_list);
Eric Biederman83b991a2003-10-11 06:20:25 +0000348 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700349 post_log_clear();
Eric Biederman8ca8d762003-04-22 19:02:15 +0000350}
351
Myles Watson032a9652009-05-11 22:24:53 +0000352/**
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000353 * Reset all of the devices on a bus and clear the bus's reset_needed flag.
354 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000355 * @param bus Pointer to the bus structure.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000356 * @return 1 if the bus was successfully reset, 0 otherwise.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000357 */
358int reset_bus(struct bus *bus)
359{
Myles Watson29cc9ed2009-07-02 18:56:24 +0000360 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->reset_bus) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000361 bus->dev->ops->reset_bus(bus);
362 bus->reset_needed = 0;
363 return 1;
364 }
365 return 0;
366}
367
Myles Watson032a9652009-05-11 22:24:53 +0000368/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000369 * Scan for devices on a bus.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000370 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000371 * If there are bridges on the bus, recursively scan the buses behind the
372 * bridges. If the setting up and tuning of the bus causes a reset to be
373 * required, reset the bus and scan it again.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000374 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000375 * @param busdev Pointer to the bus device.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000376 */
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200377static void scan_bus(struct device *busdev)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000378{
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000379 int do_scan_bus;
Paul Menzel662380f2015-10-20 10:21:08 +0200380 struct stopwatch sw;
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200381 long scan_time;
Uwe Hermanne4870472010-11-04 23:23:47 +0000382
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200383 if (!busdev->enabled)
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200384 return;
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200385
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200386 printk(BIOS_DEBUG, "%s scanning...\n", dev_path(busdev));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000387
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700388 post_log_path(busdev);
389
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200390 stopwatch_init(&sw);
391
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000392 do_scan_bus = 1;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000393 while (do_scan_bus) {
Arthur Heymans80c79a52023-08-24 15:12:19 +0200394 struct bus *link = busdev->link_list;
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200395 busdev->ops->scan_bus(busdev);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000396 do_scan_bus = 0;
Arthur Heymans80c79a52023-08-24 15:12:19 +0200397 if (!link || !link->reset_needed)
398 continue;
399 if (reset_bus(link))
400 do_scan_bus = 1;
401 else
402 busdev->bus->reset_needed = 1;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000403 }
Paul Menzel662380f2015-10-20 10:21:08 +0200404
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200405 scan_time = stopwatch_duration_msecs(&sw);
406 printk(BIOS_DEBUG, "%s: bus %s finished in %ld msecs\n", __func__,
407 dev_path(busdev), scan_time);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000408}
409
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200410void scan_bridges(struct bus *bus)
411{
412 struct device *child;
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200413
414 for (child = bus->children; child; child = child->sibling) {
415 if (!child->ops || !child->ops->scan_bus)
416 continue;
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200417 scan_bus(child);
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200418 }
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200419}
420
Li-Ta Loe5266692004-03-23 21:28:05 +0000421/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000422 * Determine the existence of devices and extend the device tree.
Li-Ta Lo04930692004-11-25 17:37:19 +0000423 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000424 * Most of the devices in the system are listed in the mainboard devicetree.cb
Li-Ta Lo04930692004-11-25 17:37:19 +0000425 * file. The device structures for these devices are generated at compile
426 * time by the config tool and are organized into the device tree. This
427 * function determines if the devices created at compile time actually exist
428 * in the physical system.
429 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000430 * For devices in the physical system but not listed in devicetree.cb,
Li-Ta Lo04930692004-11-25 17:37:19 +0000431 * the device structures have to be created at run time and attached to the
Li-Ta Loe5266692004-03-23 21:28:05 +0000432 * device tree.
433 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000434 * This function starts from the root device 'dev_root', scans the buses in
435 * the system recursively, and modifies the device tree according to the
436 * result of the probe.
Li-Ta Loe5266692004-03-23 21:28:05 +0000437 *
Li-Ta Lo5782d272004-04-26 17:51:20 +0000438 * This function has no idea how to scan and probe buses and devices at all.
439 * It depends on the bus/device specific scan_bus() method to do it. The
Li-Ta Lo04930692004-11-25 17:37:19 +0000440 * scan_bus() method also has to create the device structure and attach
Myles Watson032a9652009-05-11 22:24:53 +0000441 * it to the device tree.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000442 */
443void dev_enumerate(void)
444{
445 struct device *root;
Uwe Hermanne4870472010-11-04 23:23:47 +0000446
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000447 printk(BIOS_INFO, "Enumerating buses...\n");
Uwe Hermanne4870472010-11-04 23:23:47 +0000448
Eric Biederman8ca8d762003-04-22 19:02:15 +0000449 root = &dev_root;
Myles Watsoncd5d7562009-05-12 13:43:34 +0000450
Uwe Hermanne4870472010-11-04 23:23:47 +0000451 show_all_devs(BIOS_SPEW, "Before device enumeration.");
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000452 printk(BIOS_SPEW, "Compare with tree...\n");
Kyösti Mälkki3d3c8c32016-08-15 10:04:21 +0300453 show_devs_tree(root, BIOS_SPEW, 0);
Myles Watsoncd5d7562009-05-12 13:43:34 +0000454
Stefan Reinauera675d492012-08-07 14:50:47 -0700455 if (root->chip_ops && root->chip_ops->enable_dev)
456 root->chip_ops->enable_dev(root);
Uwe Hermanne4870472010-11-04 23:23:47 +0000457
Eric Biedermanb78c1972004-10-14 20:54:17 +0000458 if (!root->ops || !root->ops->scan_bus) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000459 printk(BIOS_ERR, "dev_root missing scan_bus operation");
Eric Biedermanb78c1972004-10-14 20:54:17 +0000460 return;
461 }
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200462 scan_bus(root);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700463 post_log_clear();
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000464 printk(BIOS_INFO, "done\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000465}
466
Li-Ta Loe5266692004-03-23 21:28:05 +0000467/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000468 * Configure devices on the devices tree.
Myles Watson032a9652009-05-11 22:24:53 +0000469 *
Li-Ta Lo04930692004-11-25 17:37:19 +0000470 * Starting at the root of the device tree, travel it recursively in two
471 * passes. In the first pass, we compute and allocate resources (ranges)
Martin Roth63373ed2013-07-08 16:24:19 -0600472 * required by each device. In the second pass, the resources ranges are
Li-Ta Lo04930692004-11-25 17:37:19 +0000473 * relocated to their final position and stored to the hardware.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000474 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000475 * I/O resources grow upward. MEM resources grow downward.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000476 *
477 * Since the assignment is hierarchical we set the values into the dev_root
Myles Watson032a9652009-05-11 22:24:53 +0000478 * struct.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000479 */
480void dev_configure(void)
481{
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +0200482 const struct device *root;
Li-Ta Loe5266692004-03-23 21:28:05 +0000483
Marc Jones80bd74c2012-02-21 17:44:35 +0100484 set_vga_bridge_bits();
Marc Jones80bd74c2012-02-21 17:44:35 +0100485
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000486 printk(BIOS_INFO, "Allocating resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000487
Eric Biedermanb78c1972004-10-14 20:54:17 +0000488 root = &dev_root;
Myles Watsoncd5d7562009-05-12 13:43:34 +0000489
Uwe Hermanne4870472010-11-04 23:23:47 +0000490 /*
491 * Each domain should create resources which contain the entire address
Myles Watson29cc9ed2009-07-02 18:56:24 +0000492 * space for IO, MEM, and PREFMEM resources in the domain. The
493 * allocation of device resources will be done from this address space.
494 */
Myles Watsoncd5d7562009-05-12 13:43:34 +0000495
Myles Watson29cc9ed2009-07-02 18:56:24 +0000496 /* Read the resources for the entire tree. */
Li-Ta Lo04930692004-11-25 17:37:19 +0000497
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000498 printk(BIOS_INFO, "Reading resources...\n");
Myles Watson894a3472010-06-09 22:41:35 +0000499 read_resources(root->link_list);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000500 printk(BIOS_INFO, "Done reading resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000501
Stefan Reinauer39e72292009-10-26 16:47:05 +0000502 print_resource_tree(root, BIOS_SPEW, "After reading.");
Myles Watsoncd5d7562009-05-12 13:43:34 +0000503
Furquan Shaikh69395742020-05-15 15:43:15 -0700504 allocate_resources(root);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000505
Myles Watson894a3472010-06-09 22:41:35 +0000506 assign_resources(root->link_list);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000507 printk(BIOS_INFO, "Done setting resources.\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +0000508 print_resource_tree(root, BIOS_SPEW, "After assigning values.");
Eric Biederman03acab62004-10-14 21:25:53 +0000509
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000510 printk(BIOS_INFO, "Done allocating resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000511}
512
Li-Ta Loe5266692004-03-23 21:28:05 +0000513/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000514 * Enable devices on the device tree.
Li-Ta Loe5266692004-03-23 21:28:05 +0000515 *
516 * Starting at the root, walk the tree and enable all devices/bridges by
517 * calling the device's enable_resources() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000518 */
519void dev_enable(void)
520{
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000521 printk(BIOS_INFO, "Enabling resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000522
Uwe Hermanne4870472010-11-04 23:23:47 +0000523 /* Now enable everything. */
Arthur Heymans80c79a52023-08-24 15:12:19 +0200524 if (dev_root.link_list)
525 enable_resources(dev_root.link_list);
Li-Ta Loe5266692004-03-23 21:28:05 +0000526
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000527 printk(BIOS_INFO, "done.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000528}
529
Li-Ta Loe5266692004-03-23 21:28:05 +0000530/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000531 * Initialize a specific device.
Myles Watson7eac4452010-06-17 16:16:56 +0000532 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000533 * The parent should be initialized first to avoid having an ordering problem.
Martin Roth63373ed2013-07-08 16:24:19 -0600534 * This is done by calling the parent's init() method before its children's
Uwe Hermanne4870472010-11-04 23:23:47 +0000535 * init() methods.
Myles Watson7eac4452010-06-17 16:16:56 +0000536 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000537 * @param dev The device to be initialized.
Myles Watson7eac4452010-06-17 16:16:56 +0000538 */
539static void init_dev(struct device *dev)
540{
Uwe Hermanne4870472010-11-04 23:23:47 +0000541 if (!dev->enabled)
Myles Watson7eac4452010-06-17 16:16:56 +0000542 return;
Myles Watson7eac4452010-06-17 16:16:56 +0000543
544 if (!dev->initialized && dev->ops && dev->ops->init) {
Aaron Durbin46ba4802014-09-23 16:34:40 -0500545 struct stopwatch sw;
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200546 long init_time;
547
Myles Watson7eac4452010-06-17 16:16:56 +0000548 if (dev->path.type == DEVICE_PATH_I2C) {
Arthur Heymans80c79a52023-08-24 15:12:19 +0200549 printk(BIOS_DEBUG, "smbus: %s->", dev_path(dev->bus->dev));
Myles Watson7eac4452010-06-17 16:16:56 +0000550 }
551
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200552 printk(BIOS_DEBUG, "%s init\n", dev_path(dev));
553
554 stopwatch_init(&sw);
Myles Watson7eac4452010-06-17 16:16:56 +0000555 dev->initialized = 1;
556 dev->ops->init(dev);
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200557
558 init_time = stopwatch_duration_msecs(&sw);
559 printk(BIOS_DEBUG, "%s init finished in %ld msecs\n", dev_path(dev),
560 init_time);
Myles Watson7eac4452010-06-17 16:16:56 +0000561 }
562}
563
564static void init_link(struct bus *link)
565{
566 struct device *dev;
Myles Watson7eac4452010-06-17 16:16:56 +0000567
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700568 for (dev = link->children; dev; dev = dev->sibling) {
lilacious40cb3fe2023-06-21 23:24:14 +0200569 post_code(POSTCODE_BS_DEV_INIT);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700570 post_log_path(dev);
Myles Watson7eac4452010-06-17 16:16:56 +0000571 init_dev(dev);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700572 }
Myles Watson7eac4452010-06-17 16:16:56 +0000573
Arthur Heymans80c79a52023-08-24 15:12:19 +0200574 for (dev = link->children; dev; dev = dev->sibling)
575 if (dev->link_list)
576 init_link(dev->link_list);
Myles Watson7eac4452010-06-17 16:16:56 +0000577}
578
579/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000580 * Initialize all devices in the global device tree.
Myles Watson7eac4452010-06-17 16:16:56 +0000581 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000582 * Starting at the root device, call the device's init() method to do
583 * device-specific setup, then call each child's init() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000584 */
585void dev_initialize(void)
586{
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000587 printk(BIOS_INFO, "Initializing devices...\n");
Myles Watson7eac4452010-06-17 16:16:56 +0000588
Myles Watson1bd3fb72010-08-16 16:25:23 +0000589 /* First call the mainboard init. */
590 init_dev(&dev_root);
591
Uwe Hermanne4870472010-11-04 23:23:47 +0000592 /* Now initialize everything. */
Arthur Heymans80c79a52023-08-24 15:12:19 +0200593 if (dev_root.link_list)
594 init_link(dev_root.link_list);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700595 post_log_clear();
Myles Watson7eac4452010-06-17 16:16:56 +0000596
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000597 printk(BIOS_INFO, "Devices initialized\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +0000598 show_all_devs(BIOS_SPEW, "After init.");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000599}
Marc Jones2a58ecd2013-10-29 17:32:00 -0600600
601/**
602 * Finalize a specific device.
603 *
604 * The parent should be finalized first to avoid having an ordering problem.
Martin Roth74f18772023-09-03 21:38:29 -0600605 * This is done by calling the parent's final() method before its children's
Marc Jones2a58ecd2013-10-29 17:32:00 -0600606 * final() methods.
607 *
608 * @param dev The device to be initialized.
609 */
610static void final_dev(struct device *dev)
611{
612 if (!dev->enabled)
613 return;
614
615 if (dev->ops && dev->ops->final) {
616 printk(BIOS_DEBUG, "%s final\n", dev_path(dev));
617 dev->ops->final(dev);
618 }
619}
620
621static void final_link(struct bus *link)
622{
623 struct device *dev;
Marc Jones2a58ecd2013-10-29 17:32:00 -0600624
625 for (dev = link->children; dev; dev = dev->sibling)
626 final_dev(dev);
627
Arthur Heymans80c79a52023-08-24 15:12:19 +0200628 for (dev = link->children; dev; dev = dev->sibling)
629 if (dev->link_list)
630 final_link(dev->link_list);
Marc Jones2a58ecd2013-10-29 17:32:00 -0600631}
632/**
633 * Finalize all devices in the global device tree.
634 *
635 * Starting at the root device, call the device's final() method to do
636 * device-specific cleanup, then call each child's final() method.
637 */
638void dev_finalize(void)
639{
Marc Jones2a58ecd2013-10-29 17:32:00 -0600640 printk(BIOS_INFO, "Finalize devices...\n");
641
642 /* First call the mainboard finalize. */
643 final_dev(&dev_root);
644
645 /* Now finalize everything. */
Arthur Heymans80c79a52023-08-24 15:12:19 +0200646 final_link(dev_root.link_list);
Marc Jones2a58ecd2013-10-29 17:32:00 -0600647
648 printk(BIOS_INFO, "Devices finalized\n");
649}