blob: ffdfeac22caf5b274e2e083a70b3dd46ed011b6d [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>
Kyösti Mälkki7336f972020-06-08 06:05:03 +030015#if ENV_X86
Duncan Laurieb4aaaa72012-01-17 09:03:11 -080016#include <arch/ebda.h>
17#endif
Aaron Durbin05294292013-04-30 15:41:13 -050018#include <timer.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000019
Li-Ta Loe5266692004-03-23 21:28:05 +000020/** Pointer to the last device */
Myles Watson70679a02010-09-01 21:03:03 +000021extern struct device *last_dev;
Myles Watsonc25cc112010-05-21 14:33:48 +000022/** Linked list of free resources */
23struct resource *free_resources = NULL;
Eric Biederman8ca8d762003-04-22 19:02:15 +000024
Nico Huberacd7d952012-07-25 10:33:05 +020025/**
26 * Initialize all chips of statically known devices.
27 *
28 * Will be called before bus enumeration to initialize chips stated in the
29 * device tree.
30 */
31void dev_initialize_chips(void)
32{
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +020033 const struct device *dev;
Nico Huberacd7d952012-07-25 10:33:05 +020034
35 for (dev = all_devices; dev; dev = dev->next) {
36 /* Initialize chip if we haven't yet. */
37 if (dev->chip_ops && dev->chip_ops->init &&
38 !dev->chip_ops->initialized) {
Duncan Laurie8adf7a22013-06-10 10:34:20 -070039 post_log_path(dev);
Nico Huberacd7d952012-07-25 10:33:05 +020040 dev->chip_ops->init(dev->chip_info);
41 dev->chip_ops->initialized = 1;
42 }
43 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -070044 post_log_clear();
Nico Huberacd7d952012-07-25 10:33:05 +020045}
46
Marc Jones2a58ecd2013-10-29 17:32:00 -060047/**
48 * Finalize all chips of statically known devices.
49 *
50 * This is the last call before calling the payload. This is a good place
51 * to lock registers or other final cleanup.
52 */
53void dev_finalize_chips(void)
54{
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +020055 const struct device *dev;
Marc Jones2a58ecd2013-10-29 17:32:00 -060056
57 for (dev = all_devices; dev; dev = dev->next) {
58 /* Initialize chip if we haven't yet. */
59 if (dev->chip_ops && dev->chip_ops->final &&
60 !dev->chip_ops->finalized) {
61 dev->chip_ops->final(dev->chip_info);
62 dev->chip_ops->finalized = 1;
63 }
64 }
65}
66
Uwe Hermannc1ee4292010-10-17 19:01:48 +000067DECLARE_SPIN_LOCK(dev_lock)
Eric Biederman8ca8d762003-04-22 19:02:15 +000068
Julius Wernercd49cce2019-03-05 16:53:33 -080069#if CONFIG(GFXUMA)
Kyösti Mälkkicc55b9b2012-07-11 07:55:21 +030070/* IGD UMA memory */
71uint64_t uma_memory_base = 0;
72uint64_t uma_memory_size = 0;
Kyösti Mälkkib25374c2012-08-01 08:05:22 +030073#endif
Kyösti Mälkkicc55b9b2012-07-11 07:55:21 +030074
Li-Ta Loe5266692004-03-23 21:28:05 +000075/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +000076 * Allocate a new device structure.
Myles Watson032a9652009-05-11 22:24:53 +000077 *
Martin Roth63373ed2013-07-08 16:24:19 -060078 * Allocate a new device structure and attach it to the device tree as a
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +000079 * child of the parent bus.
Li-Ta Loe5266692004-03-23 21:28:05 +000080 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +000081 * @param parent Parent bus the newly created device should be attached to.
82 * @param path Path to the device to be created.
83 * @return Pointer to the newly created device structure.
Li-Ta Loe5266692004-03-23 21:28:05 +000084 *
85 * @see device_path
Eric Biederman8ca8d762003-04-22 19:02:15 +000086 */
Elyes HAOUASd34a7852018-09-17 10:44:14 +020087static struct device *__alloc_dev(struct bus *parent, struct device_path *path)
Eric Biederman8ca8d762003-04-22 19:02:15 +000088{
Elyes HAOUASe3480662018-05-06 20:32:23 +020089 struct device *dev, *child;
Li-Ta Loe5266692004-03-23 21:28:05 +000090
Myles Watson29cc9ed2009-07-02 18:56:24 +000091 /* Find the last child of our parent. */
Elyes HAOUASa342f392018-10-17 10:56:26 +020092 for (child = parent->children; child && child->sibling; /* */)
Eric Biedermane9a271e32003-09-02 03:36:25 +000093 child = child->sibling;
Li-Ta Lo3a812852004-12-03 22:39:34 +000094
Eric Biedermane9a271e32003-09-02 03:36:25 +000095 dev = malloc(sizeof(*dev));
Myles Watson29cc9ed2009-07-02 18:56:24 +000096 if (dev == 0)
Uwe Hermanne4870472010-11-04 23:23:47 +000097 die("alloc_dev(): out of memory.\n");
Myles Watson29cc9ed2009-07-02 18:56:24 +000098
Eric Biedermane9a271e32003-09-02 03:36:25 +000099 memset(dev, 0, sizeof(*dev));
100 memcpy(&dev->path, path, sizeof(*path));
101
Myles Watson29cc9ed2009-07-02 18:56:24 +0000102 /* By default devices are enabled. */
Eric Biederman03acab62004-10-14 21:25:53 +0000103 dev->enabled = 1;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000104
Eric Biedermanb78c1972004-10-14 20:54:17 +0000105 /* Add the new device to the list of children of the bus. */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000106 dev->bus = parent;
Uwe Hermanne4870472010-11-04 23:23:47 +0000107 if (child)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000108 child->sibling = dev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000109 else
Eric Biedermane9a271e32003-09-02 03:36:25 +0000110 parent->children = dev;
Li-Ta Loe5266692004-03-23 21:28:05 +0000111
Eric Biederman03acab62004-10-14 21:25:53 +0000112 /* Append a new device to the global device list.
113 * The list is used to find devices once everything is set up.
114 */
Myles Watson70679a02010-09-01 21:03:03 +0000115 last_dev->next = dev;
116 last_dev = dev;
Eric Biederman03acab62004-10-14 21:25:53 +0000117
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300118 return dev;
119}
120
Elyes HAOUASd34a7852018-09-17 10:44:14 +0200121struct device *alloc_dev(struct bus *parent, struct device_path *path)
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300122{
Elyes HAOUASe3480662018-05-06 20:32:23 +0200123 struct device *dev;
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300124 spin_lock(&dev_lock);
125 dev = __alloc_dev(parent, path);
Eric Biederman03acab62004-10-14 21:25:53 +0000126 spin_unlock(&dev_lock);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000127 return dev;
128}
Eric Biederman8ca8d762003-04-22 19:02:15 +0000129
Li-Ta Loe5266692004-03-23 21:28:05 +0000130/**
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300131 * See if a device structure already exists and if not allocate it.
132 *
133 * @param parent The bus to find the device on.
134 * @param path The relative path from the bus to the appropriate device.
135 * @return Pointer to a device structure for the device on bus at path.
136 */
Elyes HAOUASd34a7852018-09-17 10:44:14 +0200137struct device *alloc_find_dev(struct bus *parent, struct device_path *path)
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300138{
Elyes HAOUASe3480662018-05-06 20:32:23 +0200139 struct device *child;
Kyösti Mälkkia5650a42012-07-07 17:15:51 +0300140 spin_lock(&dev_lock);
141 child = find_dev_path(parent, path);
142 if (!child)
143 child = __alloc_dev(parent, path);
144 spin_unlock(&dev_lock);
145 return child;
146}
147
148/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000149 * Read the resources on all devices of a given bus.
150 *
151 * @param bus Bus to read the resources on.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000152 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000153static void read_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000154{
155 struct device *curdev;
156
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000157 printk(BIOS_SPEW, "%s %s bus %x link: %d\n", dev_path(bus->dev),
158 __func__, bus->secondary, bus->link_num);
Eric Biederman448bd632004-10-14 22:52:15 +0000159
Myles Watson29cc9ed2009-07-02 18:56:24 +0000160 /* Walk through all devices and find which resources they need. */
161 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Myles Watson894a3472010-06-09 22:41:35 +0000162 struct bus *link;
Uwe Hermanne4870472010-11-04 23:23:47 +0000163
164 if (!curdev->enabled)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000165 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000166
Eric Biedermane9a271e32003-09-02 03:36:25 +0000167 if (!curdev->ops || !curdev->ops->read_resources) {
Martin Roth7bc74ab2015-11-18 20:23:02 -0700168 if (curdev->path.type != DEVICE_PATH_APIC)
169 printk(BIOS_ERR, "%s missing read_resources\n",
170 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000171 continue;
172 }
Duncan Laurie7ed39762013-07-09 10:46:52 -0700173 post_log_path(curdev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000174 curdev->ops->read_resources(curdev);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000175
176 /* Read in the resources behind the current device's links. */
Myles Watson894a3472010-06-09 22:41:35 +0000177 for (link = curdev->link_list; link; link = link->next)
178 read_resources(link);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000179 }
Duncan Laurie7ed39762013-07-09 10:46:52 -0700180 post_log_clear();
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000181 printk(BIOS_SPEW, "%s read_resources bus %d link: %d done\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000182 dev_path(bus->dev), bus->secondary, bus->link_num);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000183}
184
Elyes HAOUASe3480662018-05-06 20:32:23 +0200185struct device *vga_pri = NULL;
Myles Watsonc7233e02009-07-02 19:02:33 +0000186static void set_vga_bridge_bits(void)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000187{
Uwe Hermann312673c2009-10-27 21:49:33 +0000188 /*
Martin Roth63373ed2013-07-08 16:24:19 -0600189 * FIXME: Modify set_vga_bridge() so it is less PCI-centric!
Uwe Hermann312673c2009-10-27 21:49:33 +0000190 * This function knows too much about PCI stuff, it should be just
191 * an iterator/visitor.
192 */
Li-Ta Loe5266692004-03-23 21:28:05 +0000193
Myles Watson29cc9ed2009-07-02 18:56:24 +0000194 /* FIXME: Handle the VGA palette snooping. */
Patrick Georgi557ecf22012-07-20 12:16:17 +0200195 struct device *dev, *vga, *vga_onboard;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000196 struct bus *bus;
Uwe Hermanne4870472010-11-04 23:23:47 +0000197
Eric Biedermanb78c1972004-10-14 20:54:17 +0000198 bus = 0;
199 vga = 0;
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000200 vga_onboard = 0;
Uwe Hermanne4870472010-11-04 23:23:47 +0000201
Patrick Georgi557ecf22012-07-20 12:16:17 +0200202 dev = NULL;
203 while ((dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev))) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000204 if (!dev->enabled)
205 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000206
Patrick Georgi557ecf22012-07-20 12:16:17 +0200207 printk(BIOS_DEBUG, "found VGA at %s\n", dev_path(dev));
Nico Huber061b9052019-09-21 15:58:23 +0200208 if (dev->bus->no_vga16) {
209 printk(BIOS_WARNING,
210 "A bridge on the path doesn't support 16-bit VGA decoding!");
211 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000212
Patrick Georgi557ecf22012-07-20 12:16:17 +0200213 if (dev->on_mainboard) {
214 vga_onboard = dev;
Kostr1f0d3792012-10-06 13:27:58 +0400215 } else {
Patrick Georgi557ecf22012-07-20 12:16:17 +0200216 vga = dev;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000217 }
Myles Watson032a9652009-05-11 22:24:53 +0000218
Patrick Georgi557ecf22012-07-20 12:16:17 +0200219 /* It isn't safe to enable all VGA cards. */
220 dev->command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Patrick Georgi594473d2012-07-25 08:55:53 +0200221 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000222
Uwe Hermanne4870472010-11-04 23:23:47 +0000223 if (!vga)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000224 vga = vga_onboard;
Patrick Georgi557ecf22012-07-20 12:16:17 +0200225
Julius Werner5d1f9a02019-03-07 17:07:26 -0800226 if (CONFIG(ONBOARD_VGA_IS_PRIMARY) && vga_onboard)
Patrick Georgi557ecf22012-07-20 12:16:17 +0200227 vga = vga_onboard;
Myles Watson032a9652009-05-11 22:24:53 +0000228
Patrick Georgi5869fa22012-07-20 12:29:33 +0200229 /* If we prefer plugin VGA over chipset VGA, the chipset might
230 want to know. */
Julius Werner5d1f9a02019-03-07 17:07:26 -0800231 if (!CONFIG(ONBOARD_VGA_IS_PRIMARY) && (vga != vga_onboard) &&
Patrick Georgi5869fa22012-07-20 12:29:33 +0200232 vga_onboard && vga_onboard->ops && vga_onboard->ops->disable) {
233 printk(BIOS_DEBUG, "Use plugin graphics over integrated.\n");
234 vga_onboard->ops->disable(vga_onboard);
235 }
236
arch import user (historical)dc811182005-07-06 17:16:09 +0000237 if (vga) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000238 /* VGA is first add-on card or the only onboard VGA. */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000239 printk(BIOS_DEBUG, "Setting up VGA for %s\n", dev_path(vga));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000240 /* All legacy VGA cards have MEM & I/O space registers. */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000241 vga->command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
242 vga_pri = vga;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000243 bus = vga->bus;
244 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000245
Myles Watson29cc9ed2009-07-02 18:56:24 +0000246 /* Now walk up the bridges setting the VGA enable. */
247 while (bus) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000248 printk(BIOS_DEBUG, "Setting PCI_BRIDGE_CTL_VGA for bridge %s\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000249 dev_path(bus->dev));
Nico Huber061b9052019-09-21 15:58:23 +0200250 bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA | PCI_BRIDGE_CTL_VGA16;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000251 bus = (bus == bus->dev->bus) ? 0 : bus->dev->bus;
Myles Watson032a9652009-05-11 22:24:53 +0000252 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000253}
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000254
Li-Ta Lo04930692004-11-25 17:37:19 +0000255/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000256 * Assign the computed resources to the devices on the bus.
Li-Ta Lo04930692004-11-25 17:37:19 +0000257 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000258 * Use the device specific set_resources() method to store the computed
Li-Ta Lo04930692004-11-25 17:37:19 +0000259 * resources to hardware. For bridge devices, the set_resources() method
260 * has to recurse into every down stream buses.
261 *
262 * Mutual recursion:
263 * assign_resources() -> device_operation::set_resources()
264 * device_operation::set_resources() -> assign_resources()
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000265 *
266 * @param bus Pointer to the structure for this bus.
Li-Ta Lo04930692004-11-25 17:37:19 +0000267 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000268void assign_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000269{
270 struct device *curdev;
271
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000272 printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000273 dev_path(bus->dev), bus->secondary, bus->link_num);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000274
Myles Watson29cc9ed2009-07-02 18:56:24 +0000275 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000276 if (!curdev->enabled || !curdev->resource_list)
Eric Biederman03acab62004-10-14 21:25:53 +0000277 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000278
Eric Biedermane9a271e32003-09-02 03:36:25 +0000279 if (!curdev->ops || !curdev->ops->set_resources) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000280 printk(BIOS_ERR, "%s missing set_resources\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000281 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000282 continue;
283 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700284 post_log_path(curdev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000285 curdev->ops->set_resources(curdev);
286 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700287 post_log_clear();
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000288 printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000289 dev_path(bus->dev), bus->secondary, bus->link_num);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000290}
291
Li-Ta Lo5782d272004-04-26 17:51:20 +0000292/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000293 * Enable the resources for devices on a link.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000294 *
295 * Enable resources of the device by calling the device specific
296 * enable_resources() method.
297 *
298 * The parent's resources should be enabled first to avoid having enabling
299 * order problem. This is done by calling the parent's enable_resources()
Martin Roth63373ed2013-07-08 16:24:19 -0600300 * method before its children's enable_resources() methods.
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +0000301 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000302 * @param link The link whose devices' resources are to be enabled.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000303 */
Myles Watson7eac4452010-06-17 16:16:56 +0000304static void enable_resources(struct bus *link)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000305{
Myles Watson7eac4452010-06-17 16:16:56 +0000306 struct device *dev;
307 struct bus *c_link;
308
309 for (dev = link->children; dev; dev = dev->sibling) {
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700310 if (dev->enabled && dev->ops && dev->ops->enable_resources) {
311 post_log_path(dev);
Myles Watson7eac4452010-06-17 16:16:56 +0000312 dev->ops->enable_resources(dev);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700313 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000314 }
Myles Watson7eac4452010-06-17 16:16:56 +0000315
316 for (dev = link->children; dev; dev = dev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000317 for (c_link = dev->link_list; c_link; c_link = c_link->next)
Myles Watson7eac4452010-06-17 16:16:56 +0000318 enable_resources(c_link);
Eric Biederman83b991a2003-10-11 06:20:25 +0000319 }
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700320 post_log_clear();
Eric Biederman8ca8d762003-04-22 19:02:15 +0000321}
322
Myles Watson032a9652009-05-11 22:24:53 +0000323/**
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000324 * Reset all of the devices on a bus and clear the bus's reset_needed flag.
325 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000326 * @param bus Pointer to the bus structure.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000327 * @return 1 if the bus was successfully reset, 0 otherwise.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000328 */
329int reset_bus(struct bus *bus)
330{
Myles Watson29cc9ed2009-07-02 18:56:24 +0000331 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->reset_bus) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000332 bus->dev->ops->reset_bus(bus);
333 bus->reset_needed = 0;
334 return 1;
335 }
336 return 0;
337}
338
Myles Watson032a9652009-05-11 22:24:53 +0000339/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000340 * Scan for devices on a bus.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000341 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000342 * If there are bridges on the bus, recursively scan the buses behind the
343 * bridges. If the setting up and tuning of the bus causes a reset to be
344 * required, reset the bus and scan it again.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000345 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000346 * @param busdev Pointer to the bus device.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000347 */
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200348static void scan_bus(struct device *busdev)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000349{
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000350 int do_scan_bus;
Paul Menzel662380f2015-10-20 10:21:08 +0200351 struct stopwatch sw;
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200352 long scan_time;
Uwe Hermanne4870472010-11-04 23:23:47 +0000353
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200354 if (!busdev->enabled)
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200355 return;
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200356
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200357 printk(BIOS_DEBUG, "%s scanning...\n", dev_path(busdev));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000358
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700359 post_log_path(busdev);
360
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200361 stopwatch_init(&sw);
362
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000363 do_scan_bus = 1;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000364 while (do_scan_bus) {
Myles Watson894a3472010-06-09 22:41:35 +0000365 struct bus *link;
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200366 busdev->ops->scan_bus(busdev);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000367 do_scan_bus = 0;
Myles Watson894a3472010-06-09 22:41:35 +0000368 for (link = busdev->link_list; link; link = link->next) {
369 if (link->reset_needed) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000370 if (reset_bus(link))
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000371 do_scan_bus = 1;
Uwe Hermanne4870472010-11-04 23:23:47 +0000372 else
Myles Watson29cc9ed2009-07-02 18:56:24 +0000373 busdev->bus->reset_needed = 1;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000374 }
375 }
376 }
Paul Menzel662380f2015-10-20 10:21:08 +0200377
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200378 scan_time = stopwatch_duration_msecs(&sw);
379 printk(BIOS_DEBUG, "%s: bus %s finished in %ld msecs\n", __func__,
380 dev_path(busdev), scan_time);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000381}
382
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200383void scan_bridges(struct bus *bus)
384{
385 struct device *child;
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200386
387 for (child = bus->children; child; child = child->sibling) {
388 if (!child->ops || !child->ops->scan_bus)
389 continue;
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200390 scan_bus(child);
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200391 }
Kyösti Mälkki2d2367c2015-02-20 21:28:31 +0200392}
393
Li-Ta Loe5266692004-03-23 21:28:05 +0000394/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000395 * Determine the existence of devices and extend the device tree.
Li-Ta Lo04930692004-11-25 17:37:19 +0000396 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000397 * Most of the devices in the system are listed in the mainboard devicetree.cb
Li-Ta Lo04930692004-11-25 17:37:19 +0000398 * file. The device structures for these devices are generated at compile
399 * time by the config tool and are organized into the device tree. This
400 * function determines if the devices created at compile time actually exist
401 * in the physical system.
402 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000403 * For devices in the physical system but not listed in devicetree.cb,
Li-Ta Lo04930692004-11-25 17:37:19 +0000404 * the device structures have to be created at run time and attached to the
Li-Ta Loe5266692004-03-23 21:28:05 +0000405 * device tree.
406 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000407 * This function starts from the root device 'dev_root', scans the buses in
408 * the system recursively, and modifies the device tree according to the
409 * result of the probe.
Li-Ta Loe5266692004-03-23 21:28:05 +0000410 *
Li-Ta Lo5782d272004-04-26 17:51:20 +0000411 * This function has no idea how to scan and probe buses and devices at all.
412 * It depends on the bus/device specific scan_bus() method to do it. The
Li-Ta Lo04930692004-11-25 17:37:19 +0000413 * scan_bus() method also has to create the device structure and attach
Myles Watson032a9652009-05-11 22:24:53 +0000414 * it to the device tree.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000415 */
416void dev_enumerate(void)
417{
418 struct device *root;
Uwe Hermanne4870472010-11-04 23:23:47 +0000419
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000420 printk(BIOS_INFO, "Enumerating buses...\n");
Uwe Hermanne4870472010-11-04 23:23:47 +0000421
Eric Biederman8ca8d762003-04-22 19:02:15 +0000422 root = &dev_root;
Myles Watsoncd5d7562009-05-12 13:43:34 +0000423
Uwe Hermanne4870472010-11-04 23:23:47 +0000424 show_all_devs(BIOS_SPEW, "Before device enumeration.");
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000425 printk(BIOS_SPEW, "Compare with tree...\n");
Kyösti Mälkki3d3c8c32016-08-15 10:04:21 +0300426 show_devs_tree(root, BIOS_SPEW, 0);
Myles Watsoncd5d7562009-05-12 13:43:34 +0000427
Stefan Reinauera675d492012-08-07 14:50:47 -0700428 if (root->chip_ops && root->chip_ops->enable_dev)
429 root->chip_ops->enable_dev(root);
Uwe Hermanne4870472010-11-04 23:23:47 +0000430
Eric Biedermanb78c1972004-10-14 20:54:17 +0000431 if (!root->ops || !root->ops->scan_bus) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000432 printk(BIOS_ERR, "dev_root missing scan_bus operation");
Eric Biedermanb78c1972004-10-14 20:54:17 +0000433 return;
434 }
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200435 scan_bus(root);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700436 post_log_clear();
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000437 printk(BIOS_INFO, "done\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000438}
439
Li-Ta Loe5266692004-03-23 21:28:05 +0000440/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000441 * Configure devices on the devices tree.
Myles Watson032a9652009-05-11 22:24:53 +0000442 *
Li-Ta Lo04930692004-11-25 17:37:19 +0000443 * Starting at the root of the device tree, travel it recursively in two
444 * passes. In the first pass, we compute and allocate resources (ranges)
Martin Roth63373ed2013-07-08 16:24:19 -0600445 * required by each device. In the second pass, the resources ranges are
Li-Ta Lo04930692004-11-25 17:37:19 +0000446 * relocated to their final position and stored to the hardware.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000447 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000448 * I/O resources grow upward. MEM resources grow downward.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000449 *
450 * Since the assignment is hierarchical we set the values into the dev_root
Myles Watson032a9652009-05-11 22:24:53 +0000451 * struct.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000452 */
453void dev_configure(void)
454{
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +0200455 const struct device *root;
Li-Ta Loe5266692004-03-23 21:28:05 +0000456
Marc Jones80bd74c2012-02-21 17:44:35 +0100457 set_vga_bridge_bits();
Marc Jones80bd74c2012-02-21 17:44:35 +0100458
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000459 printk(BIOS_INFO, "Allocating resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000460
Eric Biedermanb78c1972004-10-14 20:54:17 +0000461 root = &dev_root;
Myles Watsoncd5d7562009-05-12 13:43:34 +0000462
Uwe Hermanne4870472010-11-04 23:23:47 +0000463 /*
464 * Each domain should create resources which contain the entire address
Myles Watson29cc9ed2009-07-02 18:56:24 +0000465 * space for IO, MEM, and PREFMEM resources in the domain. The
466 * allocation of device resources will be done from this address space.
467 */
Myles Watsoncd5d7562009-05-12 13:43:34 +0000468
Myles Watson29cc9ed2009-07-02 18:56:24 +0000469 /* Read the resources for the entire tree. */
Li-Ta Lo04930692004-11-25 17:37:19 +0000470
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000471 printk(BIOS_INFO, "Reading resources...\n");
Myles Watson894a3472010-06-09 22:41:35 +0000472 read_resources(root->link_list);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000473 printk(BIOS_INFO, "Done reading resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000474
Stefan Reinauer39e72292009-10-26 16:47:05 +0000475 print_resource_tree(root, BIOS_SPEW, "After reading.");
Myles Watsoncd5d7562009-05-12 13:43:34 +0000476
Furquan Shaikh69395742020-05-15 15:43:15 -0700477 allocate_resources(root);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000478
Myles Watson894a3472010-06-09 22:41:35 +0000479 assign_resources(root->link_list);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000480 printk(BIOS_INFO, "Done setting resources.\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +0000481 print_resource_tree(root, BIOS_SPEW, "After assigning values.");
Eric Biederman03acab62004-10-14 21:25:53 +0000482
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000483 printk(BIOS_INFO, "Done allocating resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000484}
485
Li-Ta Loe5266692004-03-23 21:28:05 +0000486/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000487 * Enable devices on the device tree.
Li-Ta Loe5266692004-03-23 21:28:05 +0000488 *
489 * Starting at the root, walk the tree and enable all devices/bridges by
490 * calling the device's enable_resources() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000491 */
492void dev_enable(void)
493{
Myles Watson7eac4452010-06-17 16:16:56 +0000494 struct bus *link;
495
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000496 printk(BIOS_INFO, "Enabling resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000497
Uwe Hermanne4870472010-11-04 23:23:47 +0000498 /* Now enable everything. */
Myles Watson7eac4452010-06-17 16:16:56 +0000499 for (link = dev_root.link_list; link; link = link->next)
500 enable_resources(link);
Li-Ta Loe5266692004-03-23 21:28:05 +0000501
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000502 printk(BIOS_INFO, "done.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000503}
504
Li-Ta Loe5266692004-03-23 21:28:05 +0000505/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000506 * Initialize a specific device.
Myles Watson7eac4452010-06-17 16:16:56 +0000507 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000508 * The parent should be initialized first to avoid having an ordering problem.
Martin Roth63373ed2013-07-08 16:24:19 -0600509 * This is done by calling the parent's init() method before its children's
Uwe Hermanne4870472010-11-04 23:23:47 +0000510 * init() methods.
Myles Watson7eac4452010-06-17 16:16:56 +0000511 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000512 * @param dev The device to be initialized.
Myles Watson7eac4452010-06-17 16:16:56 +0000513 */
514static void init_dev(struct device *dev)
515{
Uwe Hermanne4870472010-11-04 23:23:47 +0000516 if (!dev->enabled)
Myles Watson7eac4452010-06-17 16:16:56 +0000517 return;
Myles Watson7eac4452010-06-17 16:16:56 +0000518
519 if (!dev->initialized && dev->ops && dev->ops->init) {
Aaron Durbin46ba4802014-09-23 16:34:40 -0500520 struct stopwatch sw;
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200521 long init_time;
522
Myles Watson7eac4452010-06-17 16:16:56 +0000523 if (dev->path.type == DEVICE_PATH_I2C) {
524 printk(BIOS_DEBUG, "smbus: %s[%d]->",
525 dev_path(dev->bus->dev), dev->bus->link_num);
526 }
527
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200528 printk(BIOS_DEBUG, "%s init\n", dev_path(dev));
529
530 stopwatch_init(&sw);
Myles Watson7eac4452010-06-17 16:16:56 +0000531 dev->initialized = 1;
532 dev->ops->init(dev);
Kyösti Mälkkie3d9d672019-12-01 12:27:44 +0200533
534 init_time = stopwatch_duration_msecs(&sw);
535 printk(BIOS_DEBUG, "%s init finished in %ld msecs\n", dev_path(dev),
536 init_time);
Myles Watson7eac4452010-06-17 16:16:56 +0000537 }
538}
539
540static void init_link(struct bus *link)
541{
542 struct device *dev;
543 struct bus *c_link;
544
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700545 for (dev = link->children; dev; dev = dev->sibling) {
Duncan Lauriecb73a842013-06-10 10:41:04 -0700546 post_code(POST_BS_DEV_INIT);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700547 post_log_path(dev);
Myles Watson7eac4452010-06-17 16:16:56 +0000548 init_dev(dev);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700549 }
Myles Watson7eac4452010-06-17 16:16:56 +0000550
551 for (dev = link->children; dev; dev = dev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000552 for (c_link = dev->link_list; c_link; c_link = c_link->next)
Myles Watson7eac4452010-06-17 16:16:56 +0000553 init_link(c_link);
Myles Watson7eac4452010-06-17 16:16:56 +0000554 }
555}
556
557/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000558 * Initialize all devices in the global device tree.
Myles Watson7eac4452010-06-17 16:16:56 +0000559 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000560 * Starting at the root device, call the device's init() method to do
561 * device-specific setup, then call each child's init() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000562 */
563void dev_initialize(void)
564{
Myles Watson7eac4452010-06-17 16:16:56 +0000565 struct bus *link;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000566
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000567 printk(BIOS_INFO, "Initializing devices...\n");
Myles Watson7eac4452010-06-17 16:16:56 +0000568
Kyösti Mälkki7336f972020-06-08 06:05:03 +0300569#if ENV_X86
Arthur Heymans8b7cd432019-10-26 20:31:41 +0200570 /* Ensure EBDA is prepared before Option ROMs. */
571 setup_default_ebda();
Duncan Laurieb4aaaa72012-01-17 09:03:11 -0800572#endif
573
Myles Watson1bd3fb72010-08-16 16:25:23 +0000574 /* First call the mainboard init. */
575 init_dev(&dev_root);
576
Uwe Hermanne4870472010-11-04 23:23:47 +0000577 /* Now initialize everything. */
Myles Watson7eac4452010-06-17 16:16:56 +0000578 for (link = dev_root.link_list; link; link = link->next)
579 init_link(link);
Duncan Laurie8adf7a22013-06-10 10:34:20 -0700580 post_log_clear();
Myles Watson7eac4452010-06-17 16:16:56 +0000581
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000582 printk(BIOS_INFO, "Devices initialized\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +0000583 show_all_devs(BIOS_SPEW, "After init.");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000584}
Marc Jones2a58ecd2013-10-29 17:32:00 -0600585
586/**
587 * Finalize a specific device.
588 *
589 * The parent should be finalized first to avoid having an ordering problem.
590 * This is done by calling the parent's final() method before its childrens'
591 * final() methods.
592 *
593 * @param dev The device to be initialized.
594 */
595static void final_dev(struct device *dev)
596{
597 if (!dev->enabled)
598 return;
599
600 if (dev->ops && dev->ops->final) {
601 printk(BIOS_DEBUG, "%s final\n", dev_path(dev));
602 dev->ops->final(dev);
603 }
604}
605
606static void final_link(struct bus *link)
607{
608 struct device *dev;
609 struct bus *c_link;
610
611 for (dev = link->children; dev; dev = dev->sibling)
612 final_dev(dev);
613
614 for (dev = link->children; dev; dev = dev->sibling) {
615 for (c_link = dev->link_list; c_link; c_link = c_link->next)
616 final_link(c_link);
617 }
618}
619/**
620 * Finalize all devices in the global device tree.
621 *
622 * Starting at the root device, call the device's final() method to do
623 * device-specific cleanup, then call each child's final() method.
624 */
625void dev_finalize(void)
626{
627 struct bus *link;
628
629 printk(BIOS_INFO, "Finalize devices...\n");
630
631 /* First call the mainboard finalize. */
632 final_dev(&dev_root);
633
634 /* Now finalize everything. */
635 for (link = dev_root.link_list; link; link = link->next)
636 final_link(link);
637
638 printk(BIOS_INFO, "Devices finalized\n");
639}