blob: a2619bf00070db755f83b8870f5806313f6352be [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermannb80dbf02007-04-22 19:08:13 +00003 *
4 * It was originally based on the Linux kernel (arch/i386/kernel/pci-pc.c).
5 *
6 * Modifications are:
7 * Copyright (C) 2003 Eric Biederman <ebiederm@xmission.com>
8 * Copyright (C) 2003-2004 Linux Networx
9 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
10 * Copyright (C) 2003 Ronald G. Minnich <rminnich@gmail.com>
11 * Copyright (C) 2004-2005 Li-Ta Lo <ollie@lanl.gov>
12 * Copyright (C) 2005-2006 Tyan
13 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
14 * Copyright (C) 2005-2006 Stefan Reinauer <stepan@openbios.org>
Myles Watson29cc9ed2009-07-02 18:56:24 +000015 * Copyright (C) 2009 Myles Watson <mylesgw@gmail.com>
Uwe Hermannb80dbf02007-04-22 19:08:13 +000016 */
17
18/*
Eric Biederman8ca8d762003-04-22 19:02:15 +000019 * (c) 1999--2000 Martin Mares <mj@suse.cz>
Eric Biederman8ca8d762003-04-22 19:02:15 +000020 */
Uwe Hermanne4870472010-11-04 23:23:47 +000021
22/*
23 * Lots of mods by Ron Minnich <rminnich@lanl.gov>, with
24 * the final architecture guidance from Tom Merritt <tjm@codegen.com>.
25 *
Myles Watson032a9652009-05-11 22:24:53 +000026 * In particular, we changed from the one-pass original version to
27 * Tom's recommended multiple-pass version. I wasn't sure about doing
Eric Biederman8ca8d762003-04-22 19:02:15 +000028 * it with multiple passes, until I actually started doing it and saw
Uwe Hermanne4870472010-11-04 23:23:47 +000029 * the wisdom of Tom's recommendations...
Eric Biederman8ca8d762003-04-22 19:02:15 +000030 *
31 * Lots of cleanups by Eric Biederman to handle bridges, and to
Uwe Hermanne4870472010-11-04 23:23:47 +000032 * handle resource allocation for non-PCI devices.
Eric Biederman8ca8d762003-04-22 19:02:15 +000033 */
34
35#include <console/console.h>
36#include <bitops.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000037#include <arch/io.h>
Eric Biederman5899fd82003-04-24 06:25:08 +000038#include <device/device.h>
39#include <device/pci.h>
Li-Ta Lo54f05f62004-05-14 17:20:29 +000040#include <device/pci_ids.h>
Eric Biedermane9a271e32003-09-02 03:36:25 +000041#include <stdlib.h>
42#include <string.h>
Eric Biederman03acab62004-10-14 21:25:53 +000043#include <smp/spinlock.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000044
Li-Ta Loe5266692004-03-23 21:28:05 +000045/** Linked list of ALL devices */
Eric Biederman5cd81732004-03-11 15:01:31 +000046struct device *all_devices = &dev_root;
Li-Ta Loe5266692004-03-23 21:28:05 +000047/** Pointer to the last device */
Myles Watson70679a02010-09-01 21:03:03 +000048extern struct device *last_dev;
Myles Watsonc25cc112010-05-21 14:33:48 +000049/** Linked list of free resources */
50struct resource *free_resources = NULL;
Eric Biederman8ca8d762003-04-22 19:02:15 +000051
Uwe Hermannc1ee4292010-10-17 19:01:48 +000052DECLARE_SPIN_LOCK(dev_lock)
Eric Biederman8ca8d762003-04-22 19:02:15 +000053
Li-Ta Loe5266692004-03-23 21:28:05 +000054/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +000055 * Allocate a new device structure.
Myles Watson032a9652009-05-11 22:24:53 +000056 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +000057 * Allocte a new device structure and attach it to the device tree as a
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +000058 * child of the parent bus.
Li-Ta Loe5266692004-03-23 21:28:05 +000059 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +000060 * @param parent Parent bus the newly created device should be attached to.
61 * @param path Path to the device to be created.
62 * @return Pointer to the newly created device structure.
Li-Ta Loe5266692004-03-23 21:28:05 +000063 *
64 * @see device_path
Eric Biederman8ca8d762003-04-22 19:02:15 +000065 */
Eric Biedermane9a271e32003-09-02 03:36:25 +000066device_t alloc_dev(struct bus *parent, struct device_path *path)
Eric Biederman8ca8d762003-04-22 19:02:15 +000067{
Eric Biedermane9a271e32003-09-02 03:36:25 +000068 device_t dev, child;
Li-Ta Loe5266692004-03-23 21:28:05 +000069
Myles Watson032a9652009-05-11 22:24:53 +000070 spin_lock(&dev_lock);
Li-Ta Lo3a812852004-12-03 22:39:34 +000071
Myles Watson29cc9ed2009-07-02 18:56:24 +000072 /* Find the last child of our parent. */
Uwe Hermanne4870472010-11-04 23:23:47 +000073 for (child = parent->children; child && child->sibling; /* */ )
Eric Biedermane9a271e32003-09-02 03:36:25 +000074 child = child->sibling;
Li-Ta Lo3a812852004-12-03 22:39:34 +000075
Eric Biedermane9a271e32003-09-02 03:36:25 +000076 dev = malloc(sizeof(*dev));
Myles Watson29cc9ed2009-07-02 18:56:24 +000077 if (dev == 0)
Uwe Hermanne4870472010-11-04 23:23:47 +000078 die("alloc_dev(): out of memory.\n");
Myles Watson29cc9ed2009-07-02 18:56:24 +000079
Eric Biedermane9a271e32003-09-02 03:36:25 +000080 memset(dev, 0, sizeof(*dev));
81 memcpy(&dev->path, path, sizeof(*path));
82
Myles Watson29cc9ed2009-07-02 18:56:24 +000083 /* By default devices are enabled. */
Eric Biederman03acab62004-10-14 21:25:53 +000084 dev->enabled = 1;
Eric Biedermane9a271e32003-09-02 03:36:25 +000085
Eric Biedermanb78c1972004-10-14 20:54:17 +000086 /* Add the new device to the list of children of the bus. */
Eric Biedermane9a271e32003-09-02 03:36:25 +000087 dev->bus = parent;
Uwe Hermanne4870472010-11-04 23:23:47 +000088 if (child)
Eric Biedermane9a271e32003-09-02 03:36:25 +000089 child->sibling = dev;
Uwe Hermanne4870472010-11-04 23:23:47 +000090 else
Eric Biedermane9a271e32003-09-02 03:36:25 +000091 parent->children = dev;
Li-Ta Loe5266692004-03-23 21:28:05 +000092
Eric Biederman03acab62004-10-14 21:25:53 +000093 /* Append a new device to the global device list.
94 * The list is used to find devices once everything is set up.
95 */
Myles Watson70679a02010-09-01 21:03:03 +000096 last_dev->next = dev;
97 last_dev = dev;
Eric Biederman03acab62004-10-14 21:25:53 +000098
99 spin_unlock(&dev_lock);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000100 return dev;
101}
Eric Biederman8ca8d762003-04-22 19:02:15 +0000102
Li-Ta Loe5266692004-03-23 21:28:05 +0000103/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000104 * Round a number up to an alignment.
105 *
106 * @param val The starting value.
107 * @param roundup Alignment as a power of two.
108 * @return Rounded up number.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000109 */
Eric Biederman448bd632004-10-14 22:52:15 +0000110static resource_t round(resource_t val, unsigned long pow)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000111{
Eric Biederman448bd632004-10-14 22:52:15 +0000112 resource_t mask;
113 mask = (1ULL << pow) - 1ULL;
114 val += mask;
115 val &= ~mask;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000116 return val;
117}
118
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000119/**
120 * Read the resources on all devices of a given bus.
121 *
122 * @param bus Bus to read the resources on.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000123 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000124static void read_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000125{
126 struct device *curdev;
127
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000128 printk(BIOS_SPEW, "%s %s bus %x link: %d\n", dev_path(bus->dev),
129 __func__, bus->secondary, bus->link_num);
Eric Biederman448bd632004-10-14 22:52:15 +0000130
Myles Watson29cc9ed2009-07-02 18:56:24 +0000131 /* Walk through all devices and find which resources they need. */
132 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Myles Watson894a3472010-06-09 22:41:35 +0000133 struct bus *link;
Uwe Hermanne4870472010-11-04 23:23:47 +0000134
135 if (!curdev->enabled)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000136 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000137
Eric Biedermane9a271e32003-09-02 03:36:25 +0000138 if (!curdev->ops || !curdev->ops->read_resources) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000139 printk(BIOS_ERR, "%s missing read_resources\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000140 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000141 continue;
142 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000143 curdev->ops->read_resources(curdev);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000144
145 /* Read in the resources behind the current device's links. */
Myles Watson894a3472010-06-09 22:41:35 +0000146 for (link = curdev->link_list; link; link = link->next)
147 read_resources(link);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000148 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000149 printk(BIOS_SPEW, "%s read_resources bus %d link: %d done\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000150 dev_path(bus->dev), bus->secondary, bus->link_num);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000151}
152
Eric Biedermane9a271e32003-09-02 03:36:25 +0000153struct pick_largest_state {
154 struct resource *last;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000155 struct device *result_dev;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000156 struct resource *result;
157 int seen_last;
158};
159
Myles Watson29cc9ed2009-07-02 18:56:24 +0000160static void pick_largest_resource(void *gp, struct device *dev,
161 struct resource *resource)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000162{
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000163 struct pick_largest_state *state = gp;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000164 struct resource *last;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000165
Eric Biedermane9a271e32003-09-02 03:36:25 +0000166 last = state->last;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000167
168 /* Be certain to pick the successor to last. */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000169 if (resource == last) {
170 state->seen_last = 1;
171 return;
172 }
Myles Watson032a9652009-05-11 22:24:53 +0000173 if (resource->flags & IORESOURCE_FIXED)
Uwe Hermanne4870472010-11-04 23:23:47 +0000174 return; /* Skip it. */
Myles Watson032a9652009-05-11 22:24:53 +0000175 if (last && ((last->align < resource->align) ||
176 ((last->align == resource->align) &&
177 (last->size < resource->size)) ||
178 ((last->align == resource->align) &&
179 (last->size == resource->size) && (!state->seen_last)))) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000180 return;
181 }
Myles Watson032a9652009-05-11 22:24:53 +0000182 if (!state->result ||
183 (state->result->align < resource->align) ||
184 ((state->result->align == resource->align) &&
Myles Watson29cc9ed2009-07-02 18:56:24 +0000185 (state->result->size < resource->size))) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000186 state->result_dev = dev;
187 state->result = resource;
Myles Watson032a9652009-05-11 22:24:53 +0000188 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000189}
190
Myles Watson29cc9ed2009-07-02 18:56:24 +0000191static struct device *largest_resource(struct bus *bus,
192 struct resource **result_res,
193 unsigned long type_mask,
194 unsigned long type)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000195{
196 struct pick_largest_state state;
197
198 state.last = *result_res;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000199 state.result_dev = NULL;
200 state.result = NULL;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000201 state.seen_last = 0;
202
Myles Watson032a9652009-05-11 22:24:53 +0000203 search_bus_resources(bus, type_mask, type, pick_largest_resource,
204 &state);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000205
206 *result_res = state.result;
207 return state.result_dev;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000208}
209
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000210/**
Uwe Hermanne4870472010-11-04 23:23:47 +0000211 * This function is the guts of the resource allocator.
Myles Watson032a9652009-05-11 22:24:53 +0000212 *
Eric Biederman8ca8d762003-04-22 19:02:15 +0000213 * The problem.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000214 * - Allocate resource locations for every device.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000215 * - Don't overlap, and follow the rules of bridges.
216 * - Don't overlap with resources in fixed locations.
217 * - Be efficient so we don't have ugly strategies.
218 *
219 * The strategy.
220 * - Devices that have fixed addresses are the minority so don't
Myles Watson29cc9ed2009-07-02 18:56:24 +0000221 * worry about them too much. Instead only use part of the address
222 * space for devices with programmable addresses. This easily handles
Eric Biederman8ca8d762003-04-22 19:02:15 +0000223 * everything except bridges.
224 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000225 * - PCI devices are required to have their sizes and their alignments
226 * equal. In this case an optimal solution to the packing problem
227 * exists. Allocate all devices from highest alignment to least
228 * alignment or vice versa. Use this.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000229 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000230 * - So we can handle more than PCI run two allocation passes on bridges. The
231 * first to see how large the resources are behind the bridge, and what
232 * their alignment requirements are. The second to assign a safe address to
233 * the devices behind the bridge. This allows us to treat a bridge as just
234 * a device with a couple of resources, and not need to special case it in
235 * the allocator. Also this allows handling of other types of bridges.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000236 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000237 * @param bus The bus we are traversing.
238 * @param bridge The bridge resource which must contain the bus' resources.
239 * @param type_mask This value gets ANDed with the resource type.
240 * @param type This value must match the result of the AND.
241 * @return TODO
Eric Biederman8ca8d762003-04-22 19:02:15 +0000242 */
Myles Watson54913b92009-10-13 20:00:09 +0000243static void compute_resources(struct bus *bus, struct resource *bridge,
Uwe Hermanne4870472010-11-04 23:23:47 +0000244 unsigned long type_mask, unsigned long type)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000245{
246 struct device *dev;
247 struct resource *resource;
Eric Biederman03acab62004-10-14 21:25:53 +0000248 resource_t base;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000249 base = round(bridge->base, bridge->align);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000250
Uwe Hermanne4870472010-11-04 23:23:47 +0000251 printk(BIOS_SPEW, "%s %s_%s: base: %llx size: %llx align: %d gran: %d"
252 " limit: %llx\n", dev_path(bus->dev), __func__,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000253 (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
Uwe Hermanne4870472010-11-04 23:23:47 +0000254 "prefmem" : "mem", base, bridge->size, bridge->align,
255 bridge->gran, bridge->limit);
Ronald G. Minnich99dcf232003-09-30 02:16:47 +0000256
Uwe Hermanne4870472010-11-04 23:23:47 +0000257 /* For each child which is a bridge, compute the resource needs. */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000258 for (dev = bus->children; dev; dev = dev->sibling) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000259 struct resource *child_bridge;
260
Myles Watson894a3472010-06-09 22:41:35 +0000261 if (!dev->link_list)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000262 continue;
263
264 /* Find the resources with matching type flags. */
Myles Watsonc25cc112010-05-21 14:33:48 +0000265 for (child_bridge = dev->resource_list; child_bridge;
266 child_bridge = child_bridge->next) {
Myles Watson894a3472010-06-09 22:41:35 +0000267 struct bus* link;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000268
Uwe Hermanne4870472010-11-04 23:23:47 +0000269 if (!(child_bridge->flags & IORESOURCE_BRIDGE)
270 || (child_bridge->flags & type_mask) != type)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000271 continue;
272
Uwe Hermanne4870472010-11-04 23:23:47 +0000273 /*
274 * Split prefetchable memory if combined. Many domains
Myles Watson29cc9ed2009-07-02 18:56:24 +0000275 * use the same address space for prefetchable memory
Uwe Hermanne4870472010-11-04 23:23:47 +0000276 * and non-prefetchable memory. Bridges below them need
277 * it separated. Add the PREFETCH flag to the type_mask
278 * and type.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000279 */
Myles Watson894a3472010-06-09 22:41:35 +0000280 link = dev->link_list;
281 while (link && link->link_num !=
282 IOINDEX_LINK(child_bridge->index))
283 link = link->next;
Uwe Hermanne4870472010-11-04 23:23:47 +0000284
285 if (link == NULL) {
Myles Watson894a3472010-06-09 22:41:35 +0000286 printk(BIOS_ERR, "link %ld not found on %s\n",
287 IOINDEX_LINK(child_bridge->index),
288 dev_path(dev));
Uwe Hermanne4870472010-11-04 23:23:47 +0000289 }
290
Myles Watson894a3472010-06-09 22:41:35 +0000291 compute_resources(link, child_bridge,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000292 type_mask | IORESOURCE_PREFETCH,
293 type | (child_bridge->flags &
294 IORESOURCE_PREFETCH));
295 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000296 }
297
Myles Watson29cc9ed2009-07-02 18:56:24 +0000298 /* Remember we haven't found anything yet. */
299 resource = NULL;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000300
Uwe Hermanne4870472010-11-04 23:23:47 +0000301 /*
302 * Walk through all the resources on the current bus and compute the
303 * amount of address space taken by them. Take granularity and
Myles Watson29cc9ed2009-07-02 18:56:24 +0000304 * alignment into account.
Eric Biedermanb78c1972004-10-14 20:54:17 +0000305 */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000306 while ((dev = largest_resource(bus, &resource, type_mask, type))) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000307
Myles Watson29cc9ed2009-07-02 18:56:24 +0000308 /* Size 0 resources can be skipped. */
Uwe Hermanne4870472010-11-04 23:23:47 +0000309 if (!resource->size)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000310 continue;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000311
Myles Watson29cc9ed2009-07-02 18:56:24 +0000312 /* Propagate the resource alignment to the bridge resource. */
Uwe Hermanne4870472010-11-04 23:23:47 +0000313 if (resource->align > bridge->align)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000314 bridge->align = resource->align;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000315
316 /* Propagate the resource limit to the bridge register. */
Uwe Hermanne4870472010-11-04 23:23:47 +0000317 if (bridge->limit > resource->limit)
Eric Biedermandbec2d42004-10-21 10:44:08 +0000318 bridge->limit = resource->limit;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000319
320 /* Warn if it looks like APICs aren't declared. */
321 if ((resource->limit == 0xffffffff) &&
322 (resource->flags & IORESOURCE_ASSIGNED)) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000323 printk(BIOS_ERR,
324 "Resource limit looks wrong! (no APIC?)\n");
325 printk(BIOS_ERR, "%s %02lx limit %08Lx\n",
326 dev_path(dev), resource->index, resource->limit);
Eric Biedermandbec2d42004-10-21 10:44:08 +0000327 }
Stefan Reinauer51754a32008-08-01 12:28:38 +0000328
Eric Biederman8ca8d762003-04-22 19:02:15 +0000329 if (resource->flags & IORESOURCE_IO) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000330 /*
331 * Don't allow potential aliases over the legacy PCI
Myles Watson29cc9ed2009-07-02 18:56:24 +0000332 * expansion card addresses. The legacy PCI decodes
333 * only 10 bits, uses 0x100 - 0x3ff. Therefore, only
334 * 0x00 - 0xff can be used out of each 0x400 block of
335 * I/O space.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000336 */
Eric Biedermanbbb6d102003-08-04 19:54:48 +0000337 if ((base & 0x300) != 0) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000338 base = (base & ~0x3ff) + 0x400;
339 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000340 /*
341 * Don't allow allocations in the VGA I/O range.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000342 * PCI has special cases for that.
343 */
344 else if ((base >= 0x3b0) && (base <= 0x3df)) {
345 base = 0x3e0;
346 }
347 }
Myles Watson29cc9ed2009-07-02 18:56:24 +0000348 /* Base must be aligned. */
349 base = round(base, resource->align);
350 resource->base = base;
351 base += resource->size;
Myles Watson032a9652009-05-11 22:24:53 +0000352
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000353 printk(BIOS_SPEW, "%s %02lx * [0x%llx - 0x%llx] %s\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000354 dev_path(dev), resource->index, resource->base,
355 resource->base + resource->size - 1,
356 (resource->flags & IORESOURCE_IO) ? "io" :
357 (resource->flags & IORESOURCE_PREFETCH) ?
358 "prefmem" : "mem");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000359 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000360
361 /*
362 * A PCI bridge resource does not need to be a power of two size, but
363 * it does have a minimum granularity. Round the size up to that
364 * minimum granularity so we know not to place something else at an
365 * address postitively decoded by the bridge.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000366 */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000367 bridge->size = round(base, bridge->gran) -
368 round(bridge->base, bridge->align);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000369
Uwe Hermanne4870472010-11-04 23:23:47 +0000370 printk(BIOS_SPEW, "%s %s_%s: base: %llx size: %llx align: %d gran: %d"
371 " limit: %llx done\n", dev_path(bus->dev), __func__,
372 (bridge->flags & IORESOURCE_IO) ? "io" :
373 (bridge->flags & IORESOURCE_PREFETCH) ? "prefmem" : "mem",
374 base, bridge->size, bridge->align, bridge->gran, bridge->limit);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000375}
376
377/**
378 * This function is the second part of the resource allocator.
379 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000380 * See the compute_resources function for a more detailed explanation.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000381 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000382 * This function assigns the resources a value.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000383 *
384 * @param bus The bus we are traversing.
385 * @param bridge The bridge resource which must contain the bus' resources.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000386 * @param type_mask This value gets ANDed with the resource type.
387 * @param type This value must match the result of the AND.
Uwe Hermanne4870472010-11-04 23:23:47 +0000388 *
389 * @see compute_resources
Myles Watson29cc9ed2009-07-02 18:56:24 +0000390 */
Myles Watson54913b92009-10-13 20:00:09 +0000391static void allocate_resources(struct bus *bus, struct resource *bridge,
Uwe Hermanne4870472010-11-04 23:23:47 +0000392 unsigned long type_mask, unsigned long type)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000393{
394 struct device *dev;
395 struct resource *resource;
396 resource_t base;
397 base = bridge->base;
398
Uwe Hermanne4870472010-11-04 23:23:47 +0000399 printk(BIOS_SPEW, "%s %s_%s: base:%llx size:%llx align:%d gran:%d "
400 "limit:%llx\n", dev_path(bus->dev), __func__,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000401 (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
402 "prefmem" : "mem",
403 base, bridge->size, bridge->align, bridge->gran, bridge->limit);
404
405 /* Remember we haven't found anything yet. */
406 resource = NULL;
407
Uwe Hermanne4870472010-11-04 23:23:47 +0000408 /*
409 * Walk through all the resources on the current bus and allocate them
Myles Watson29cc9ed2009-07-02 18:56:24 +0000410 * address space.
411 */
412 while ((dev = largest_resource(bus, &resource, type_mask, type))) {
413
414 /* Propagate the bridge limit to the resource register. */
Uwe Hermanne4870472010-11-04 23:23:47 +0000415 if (resource->limit > bridge->limit)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000416 resource->limit = bridge->limit;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000417
418 /* Size 0 resources can be skipped. */
419 if (!resource->size) {
420 /* Set the base to limit so it doesn't confuse tolm. */
421 resource->base = resource->limit;
422 resource->flags |= IORESOURCE_ASSIGNED;
423 continue;
424 }
425
426 if (resource->flags & IORESOURCE_IO) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000427 /*
428 * Don't allow potential aliases over the legacy PCI
Myles Watson29cc9ed2009-07-02 18:56:24 +0000429 * expansion card addresses. The legacy PCI decodes
430 * only 10 bits, uses 0x100 - 0x3ff. Therefore, only
431 * 0x00 - 0xff can be used out of each 0x400 block of
432 * I/O space.
433 */
434 if ((base & 0x300) != 0) {
435 base = (base & ~0x3ff) + 0x400;
436 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000437 /*
438 * Don't allow allocations in the VGA I/O range.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000439 * PCI has special cases for that.
440 */
441 else if ((base >= 0x3b0) && (base <= 0x3df)) {
442 base = 0x3e0;
443 }
444 }
445
446 if ((round(base, resource->align) + resource->size - 1) <=
447 resource->limit) {
448 /* Base must be aligned. */
449 base = round(base, resource->align);
450 resource->base = base;
451 resource->flags |= IORESOURCE_ASSIGNED;
452 resource->flags &= ~IORESOURCE_STORED;
453 base += resource->size;
454 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000455 printk(BIOS_ERR, "!! Resource didn't fit !!\n");
Uwe Hermanne4870472010-11-04 23:23:47 +0000456 printk(BIOS_ERR, " aligned base %llx size %llx "
457 "limit %llx\n", round(base, resource->align),
458 resource->size, resource->limit);
459 printk(BIOS_ERR, " %llx needs to be <= %llx "
460 "(limit)\n", (round(base, resource->align) +
Myles Watson29cc9ed2009-07-02 18:56:24 +0000461 resource->size) - 1, resource->limit);
Uwe Hermanne4870472010-11-04 23:23:47 +0000462 printk(BIOS_ERR, " %s%s %02lx * [0x%llx - 0x%llx]"
463 " %s\n", (resource->flags & IORESOURCE_ASSIGNED)
464 ? "Assigned: " : "", dev_path(dev),
465 resource->index, resource->base,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000466 resource->base + resource->size - 1,
Uwe Hermanne4870472010-11-04 23:23:47 +0000467 (resource->flags & IORESOURCE_IO) ? "io"
468 : (resource->flags & IORESOURCE_PREFETCH)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000469 ? "prefmem" : "mem");
470 }
471
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000472 printk(BIOS_SPEW, "%s%s %02lx * [0x%llx - 0x%llx] %s\n",
Myles Watson29cc9ed2009-07-02 18:56:24 +0000473 (resource->flags & IORESOURCE_ASSIGNED) ? "Assigned: "
Uwe Hermanne4870472010-11-04 23:23:47 +0000474 : "", dev_path(dev), resource->index, resource->base,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000475 resource->size ? resource->base + resource->size - 1 :
Uwe Hermanne4870472010-11-04 23:23:47 +0000476 resource->base, (resource->flags & IORESOURCE_IO)
477 ? "io" : (resource->flags & IORESOURCE_PREFETCH)
478 ? "prefmem" : "mem");
Myles Watson29cc9ed2009-07-02 18:56:24 +0000479 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000480
481 /*
482 * A PCI bridge resource does not need to be a power of two size, but
Myles Watson29cc9ed2009-07-02 18:56:24 +0000483 * it does have a minimum granularity. Round the size up to that
484 * minimum granularity so we know not to place something else at an
485 * address positively decoded by the bridge.
486 */
487
488 bridge->flags |= IORESOURCE_ASSIGNED;
489
Uwe Hermanne4870472010-11-04 23:23:47 +0000490 printk(BIOS_SPEW, "%s %s_%s: next_base: %llx size: %llx align: %d "
491 "gran: %d done\n", dev_path(bus->dev), __func__,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000492 (type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
Uwe Hermanne4870472010-11-04 23:23:47 +0000493 "prefmem" : "mem", base, bridge->size, bridge->align,
494 bridge->gran);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000495
496 /* For each child which is a bridge, allocate_resources. */
497 for (dev = bus->children; dev; dev = dev->sibling) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000498 struct resource *child_bridge;
499
Myles Watson894a3472010-06-09 22:41:35 +0000500 if (!dev->link_list)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000501 continue;
502
503 /* Find the resources with matching type flags. */
Myles Watsonc25cc112010-05-21 14:33:48 +0000504 for (child_bridge = dev->resource_list; child_bridge;
505 child_bridge = child_bridge->next) {
Myles Watson894a3472010-06-09 22:41:35 +0000506 struct bus* link;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000507
508 if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
509 (child_bridge->flags & type_mask) != type)
510 continue;
511
Uwe Hermanne4870472010-11-04 23:23:47 +0000512 /*
513 * Split prefetchable memory if combined. Many domains
Myles Watson29cc9ed2009-07-02 18:56:24 +0000514 * use the same address space for prefetchable memory
Uwe Hermanne4870472010-11-04 23:23:47 +0000515 * and non-prefetchable memory. Bridges below them need
516 * it separated. Add the PREFETCH flag to the type_mask
517 * and type.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000518 */
Myles Watson894a3472010-06-09 22:41:35 +0000519 link = dev->link_list;
520 while (link && link->link_num !=
521 IOINDEX_LINK(child_bridge->index))
522 link = link->next;
523 if (link == NULL)
524 printk(BIOS_ERR, "link %ld not found on %s\n",
525 IOINDEX_LINK(child_bridge->index),
526 dev_path(dev));
Uwe Hermanne4870472010-11-04 23:23:47 +0000527
Myles Watson894a3472010-06-09 22:41:35 +0000528 allocate_resources(link, child_bridge,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000529 type_mask | IORESOURCE_PREFETCH,
530 type | (child_bridge->flags &
531 IORESOURCE_PREFETCH));
532 }
533 }
534}
535
536#if CONFIG_PCI_64BIT_PREF_MEM == 1
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000537#define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000538#else
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000539#define MEM_MASK (IORESOURCE_MEM)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000540#endif
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000541
Uwe Hermanne4870472010-11-04 23:23:47 +0000542#define IO_MASK (IORESOURCE_IO)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000543#define PREF_TYPE (IORESOURCE_PREFETCH | IORESOURCE_MEM)
Uwe Hermanne4870472010-11-04 23:23:47 +0000544#define MEM_TYPE (IORESOURCE_MEM)
545#define IO_TYPE (IORESOURCE_IO)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000546
547struct constraints {
548 struct resource pref, io, mem;
549};
550
551static void constrain_resources(struct device *dev, struct constraints* limits)
552{
553 struct device *child;
554 struct resource *res;
555 struct resource *lim;
Myles Watson894a3472010-06-09 22:41:35 +0000556 struct bus *link;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000557
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000558 printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000559
560 /* Constrain limits based on the fixed resources of this device. */
Myles Watsonc25cc112010-05-21 14:33:48 +0000561 for (res = dev->resource_list; res; res = res->next) {
Patrick Georgi18c585b2009-08-28 12:48:02 +0000562 if (!(res->flags & IORESOURCE_FIXED))
563 continue;
Myles Watsonce9d8642009-08-19 19:12:39 +0000564 if (!res->size) {
565 /* It makes no sense to have 0-sized, fixed resources.*/
Uwe Hermanne4870472010-11-04 23:23:47 +0000566 printk(BIOS_ERR, "skipping %s@%lx fixed resource, "
567 "size=0!\n", dev_path(dev), res->index);
Patrick Georgi6bd93f42009-08-19 17:29:41 +0000568 continue;
Myles Watsonce9d8642009-08-19 19:12:39 +0000569 }
Myles Watson29cc9ed2009-07-02 18:56:24 +0000570
571 /* PREFETCH, MEM, or I/O - skip any others. */
572 if ((res->flags & MEM_MASK) == PREF_TYPE)
573 lim = &limits->pref;
574 else if ((res->flags & MEM_MASK) == MEM_TYPE)
575 lim = &limits->mem;
576 else if ((res->flags & IO_MASK) == IO_TYPE)
577 lim = &limits->io;
578 else
579 continue;
580
Uwe Hermanne4870472010-11-04 23:23:47 +0000581 /*
582 * Is it a fixed resource outside the current known region?
583 * If so, we don't have to consider it - it will be handled
584 * correctly and doesn't affect current region's limits.
585 */
586 if (((res->base + res->size -1) < lim->base)
587 || (res->base > lim->limit))
Myles Watson29cc9ed2009-07-02 18:56:24 +0000588 continue;
589
Uwe Hermanne4870472010-11-04 23:23:47 +0000590 /*
591 * Choose to be above or below fixed resources. This check is
592 * signed so that "negative" amounts of space are handled
593 * correctly.
Myles Watson29cc9ed2009-07-02 18:56:24 +0000594 */
Uwe Hermanne4870472010-11-04 23:23:47 +0000595 if ((signed long long)(lim->limit - (res->base + res->size -1))
596 > (signed long long)(res->base - lim->base))
Myles Watson29cc9ed2009-07-02 18:56:24 +0000597 lim->base = res->base + res->size;
598 else
599 lim->limit = res->base -1;
600 }
601
602 /* Descend into every enabled child and look for fixed resources. */
Uwe Hermanne4870472010-11-04 23:23:47 +0000603 for (link = dev->link_list; link; link = link->next) {
604 for (child = link->children; child; child = child->sibling) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000605 if (child->enabled)
606 constrain_resources(child, limits);
Uwe Hermanne4870472010-11-04 23:23:47 +0000607 }
608 }
Myles Watson29cc9ed2009-07-02 18:56:24 +0000609}
610
611static void avoid_fixed_resources(struct device *dev)
612{
613 struct constraints limits;
614 struct resource *res;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000615
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000616 printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000617
Uwe Hermanne4870472010-11-04 23:23:47 +0000618 /* Initialize constraints to maximum size. */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000619 limits.pref.base = 0;
620 limits.pref.limit = 0xffffffffffffffffULL;
621 limits.io.base = 0;
622 limits.io.limit = 0xffffffffffffffffULL;
623 limits.mem.base = 0;
624 limits.mem.limit = 0xffffffffffffffffULL;
625
626 /* Constrain the limits to dev's initial resources. */
Myles Watsonc25cc112010-05-21 14:33:48 +0000627 for (res = dev->resource_list; res; res = res->next) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000628 if ((res->flags & IORESOURCE_FIXED))
629 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000630 printk(BIOS_SPEW, "%s:@%s %02lx limit %08Lx\n", __func__,
Uwe Hermanne4870472010-11-04 23:23:47 +0000631 dev_path(dev), res->index, res->limit);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000632 if ((res->flags & MEM_MASK) == PREF_TYPE &&
633 (res->limit < limits.pref.limit))
634 limits.pref.limit = res->limit;
635 if ((res->flags & MEM_MASK) == MEM_TYPE &&
636 (res->limit < limits.mem.limit))
637 limits.mem.limit = res->limit;
638 if ((res->flags & IO_MASK) == IO_TYPE &&
639 (res->limit < limits.io.limit))
640 limits.io.limit = res->limit;
641 }
642
643 /* Look through the tree for fixed resources and update the limits. */
644 constrain_resources(dev, &limits);
645
646 /* Update dev's resources with new limits. */
Myles Watsonc25cc112010-05-21 14:33:48 +0000647 for (res = dev->resource_list; res; res = res->next) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000648 struct resource *lim;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000649
650 if ((res->flags & IORESOURCE_FIXED))
651 continue;
652
653 /* PREFETCH, MEM, or I/O - skip any others. */
654 if ((res->flags & MEM_MASK) == PREF_TYPE)
655 lim = &limits.pref;
656 else if ((res->flags & MEM_MASK) == MEM_TYPE)
657 lim = &limits.mem;
658 else if ((res->flags & IO_MASK) == IO_TYPE)
659 lim = &limits.io;
660 else
661 continue;
662
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000663 printk(BIOS_SPEW, "%s2: %s@%02lx limit %08Lx\n", __func__,
Myles Watson29cc9ed2009-07-02 18:56:24 +0000664 dev_path(dev), res->index, res->limit);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000665 printk(BIOS_SPEW, "\tlim->base %08Lx lim->limit %08Lx\n",
Myles Watson29cc9ed2009-07-02 18:56:24 +0000666 lim->base, lim->limit);
667
668 /* Is the resource outside the limits? */
669 if (lim->base > res->base)
670 res->base = lim->base;
671 if (res->limit > lim->limit)
672 res->limit = lim->limit;
673 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000674}
arch import user (historical)dc811182005-07-06 17:16:09 +0000675
Myles Watson28412f52009-09-17 16:54:46 +0000676#if CONFIG_VGA_BRIDGE_SETUP == 1
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000677device_t vga_pri = 0;
Myles Watsonc7233e02009-07-02 19:02:33 +0000678static void set_vga_bridge_bits(void)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000679{
Uwe Hermann312673c2009-10-27 21:49:33 +0000680 /*
Uwe Hermanne4870472010-11-04 23:23:47 +0000681 * FIXME: Modify set_vga_bridge() so it is less PCI centric!
Uwe Hermann312673c2009-10-27 21:49:33 +0000682 * This function knows too much about PCI stuff, it should be just
683 * an iterator/visitor.
684 */
Li-Ta Loe5266692004-03-23 21:28:05 +0000685
Myles Watson29cc9ed2009-07-02 18:56:24 +0000686 /* FIXME: Handle the VGA palette snooping. */
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000687 struct device *dev, *vga, *vga_onboard, *vga_first, *vga_last;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000688 struct bus *bus;
Uwe Hermanne4870472010-11-04 23:23:47 +0000689
Eric Biedermanb78c1972004-10-14 20:54:17 +0000690 bus = 0;
691 vga = 0;
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000692 vga_onboard = 0;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000693 vga_first = 0;
694 vga_last = 0;
Uwe Hermanne4870472010-11-04 23:23:47 +0000695
Myles Watson29cc9ed2009-07-02 18:56:24 +0000696 for (dev = all_devices; dev; dev = dev->next) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000697
Myles Watson29cc9ed2009-07-02 18:56:24 +0000698 if (!dev->enabled)
699 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000700
Li-Ta Lo54f05f62004-05-14 17:20:29 +0000701 if (((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
Myles Watson29cc9ed2009-07-02 18:56:24 +0000702 ((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER)) {
703 if (!vga_first) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000704 if (dev->on_mainboard)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000705 vga_onboard = dev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000706 else
Myles Watson29cc9ed2009-07-02 18:56:24 +0000707 vga_first = dev;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000708 } else {
Uwe Hermanne4870472010-11-04 23:23:47 +0000709 if (dev->on_mainboard)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000710 vga_onboard = dev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000711 else
Myles Watson29cc9ed2009-07-02 18:56:24 +0000712 vga_last = dev;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000713 }
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000714
Myles Watson29cc9ed2009-07-02 18:56:24 +0000715 /* It isn't safe to enable other VGA cards. */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000716 dev->command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000717 }
718 }
Myles Watson032a9652009-05-11 22:24:53 +0000719
Myles Watson29cc9ed2009-07-02 18:56:24 +0000720 vga = vga_last;
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000721
Uwe Hermanne4870472010-11-04 23:23:47 +0000722 if (!vga)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000723 vga = vga_first;
Uwe Hermanne4870472010-11-04 23:23:47 +0000724
Stefan Reinauerabc0c852010-11-22 08:09:50 +0000725#if CONFIG_ONBOARD_VGA_IS_PRIMARY == 1
Uwe Hermanne4870472010-11-04 23:23:47 +0000726 if (vga_onboard) /* Will use onboard VGA as primary. */
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000727#else
Uwe Hermanne4870472010-11-04 23:23:47 +0000728 if (!vga) /* Will use last add-on adapter as primary. */
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000729#endif
Myles Watson29cc9ed2009-07-02 18:56:24 +0000730 {
731 vga = vga_onboard;
732 }
Myles Watson032a9652009-05-11 22:24:53 +0000733
arch import user (historical)dc811182005-07-06 17:16:09 +0000734 if (vga) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000735 /* VGA is first add-on card or the only onboard VGA. */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000736 printk(BIOS_DEBUG, "Setting up VGA for %s\n", dev_path(vga));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000737 /* All legacy VGA cards have MEM & I/O space registers. */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000738 vga->command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
739 vga_pri = vga;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000740 bus = vga->bus;
741 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000742
Myles Watson29cc9ed2009-07-02 18:56:24 +0000743 /* Now walk up the bridges setting the VGA enable. */
744 while (bus) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000745 printk(BIOS_DEBUG, "Setting PCI_BRIDGE_CTL_VGA for bridge %s\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000746 dev_path(bus->dev));
Li-Ta Lodb7f47c2004-01-08 21:15:49 +0000747 bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000748 bus = (bus == bus->dev->bus) ? 0 : bus->dev->bus;
Myles Watson032a9652009-05-11 22:24:53 +0000749 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000750}
Stefan Reinauer7ce8c542005-12-02 21:52:30 +0000751
Yinghai Lu9e4faef2005-01-14 22:04:49 +0000752#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000753
Li-Ta Lo04930692004-11-25 17:37:19 +0000754/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000755 * Assign the computed resources to the devices on the bus.
Li-Ta Lo04930692004-11-25 17:37:19 +0000756 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000757 * Use the device specific set_resources() method to store the computed
Li-Ta Lo04930692004-11-25 17:37:19 +0000758 * resources to hardware. For bridge devices, the set_resources() method
759 * has to recurse into every down stream buses.
760 *
761 * Mutual recursion:
762 * assign_resources() -> device_operation::set_resources()
763 * device_operation::set_resources() -> assign_resources()
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000764 *
765 * @param bus Pointer to the structure for this bus.
Li-Ta Lo04930692004-11-25 17:37:19 +0000766 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000767void assign_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000768{
769 struct device *curdev;
770
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000771 printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000772 dev_path(bus->dev), bus->secondary, bus->link_num);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000773
Myles Watson29cc9ed2009-07-02 18:56:24 +0000774 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000775 if (!curdev->enabled || !curdev->resource_list)
Eric Biederman03acab62004-10-14 21:25:53 +0000776 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000777
Eric Biedermane9a271e32003-09-02 03:36:25 +0000778 if (!curdev->ops || !curdev->ops->set_resources) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000779 printk(BIOS_ERR, "%s missing set_resources\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000780 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000781 continue;
782 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000783 curdev->ops->set_resources(curdev);
784 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000785 printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000786 dev_path(bus->dev), bus->secondary, bus->link_num);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000787}
788
Li-Ta Lo5782d272004-04-26 17:51:20 +0000789/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000790 * Enable the resources for devices on a link.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000791 *
792 * Enable resources of the device by calling the device specific
793 * enable_resources() method.
794 *
795 * The parent's resources should be enabled first to avoid having enabling
796 * order problem. This is done by calling the parent's enable_resources()
Myles Watson7eac4452010-06-17 16:16:56 +0000797 * method before its childrens' enable_resources() methods.
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +0000798 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000799 * @param link The link whose devices' resources are to be enabled.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000800 */
Myles Watson7eac4452010-06-17 16:16:56 +0000801static void enable_resources(struct bus *link)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000802{
Myles Watson7eac4452010-06-17 16:16:56 +0000803 struct device *dev;
804 struct bus *c_link;
805
806 for (dev = link->children; dev; dev = dev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000807 if (dev->enabled && dev->ops && dev->ops->enable_resources)
Myles Watson7eac4452010-06-17 16:16:56 +0000808 dev->ops->enable_resources(dev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000809 }
Myles Watson7eac4452010-06-17 16:16:56 +0000810
811 for (dev = link->children; dev; dev = dev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000812 for (c_link = dev->link_list; c_link; c_link = c_link->next)
Myles Watson7eac4452010-06-17 16:16:56 +0000813 enable_resources(c_link);
Eric Biederman83b991a2003-10-11 06:20:25 +0000814 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000815}
816
Myles Watson032a9652009-05-11 22:24:53 +0000817/**
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000818 * Reset all of the devices on a bus and clear the bus's reset_needed flag.
819 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000820 * @param bus Pointer to the bus structure.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000821 * @return 1 if the bus was successfully reset, 0 otherwise.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000822 */
823int reset_bus(struct bus *bus)
824{
Myles Watson29cc9ed2009-07-02 18:56:24 +0000825 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->reset_bus) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000826 bus->dev->ops->reset_bus(bus);
827 bus->reset_needed = 0;
828 return 1;
829 }
830 return 0;
831}
832
Myles Watson032a9652009-05-11 22:24:53 +0000833/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000834 * Scan for devices on a bus.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000835 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000836 * If there are bridges on the bus, recursively scan the buses behind the
837 * bridges. If the setting up and tuning of the bus causes a reset to be
838 * required, reset the bus and scan it again.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000839 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000840 * @param busdev Pointer to the bus device.
841 * @param max Current bus number.
842 * @return The maximum bus number found, after scanning all subordinate buses.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000843 */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000844unsigned int scan_bus(struct device *busdev, unsigned int max)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000845{
846 unsigned int new_max;
847 int do_scan_bus;
Uwe Hermanne4870472010-11-04 23:23:47 +0000848
Myles Watson29cc9ed2009-07-02 18:56:24 +0000849 if (!busdev || !busdev->enabled || !busdev->ops ||
850 !busdev->ops->scan_bus) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000851 return max;
852 }
Myles Watson29cc9ed2009-07-02 18:56:24 +0000853
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000854 do_scan_bus = 1;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000855 while (do_scan_bus) {
Myles Watson894a3472010-06-09 22:41:35 +0000856 struct bus *link;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000857 new_max = busdev->ops->scan_bus(busdev, max);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000858 do_scan_bus = 0;
Myles Watson894a3472010-06-09 22:41:35 +0000859 for (link = busdev->link_list; link; link = link->next) {
860 if (link->reset_needed) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000861 if (reset_bus(link))
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000862 do_scan_bus = 1;
Uwe Hermanne4870472010-11-04 23:23:47 +0000863 else
Myles Watson29cc9ed2009-07-02 18:56:24 +0000864 busdev->bus->reset_needed = 1;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000865 }
866 }
867 }
868 return new_max;
869}
870
Li-Ta Loe5266692004-03-23 21:28:05 +0000871/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000872 * Determine the existence of devices and extend the device tree.
Li-Ta Lo04930692004-11-25 17:37:19 +0000873 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000874 * Most of the devices in the system are listed in the mainboard devicetree.cb
Li-Ta Lo04930692004-11-25 17:37:19 +0000875 * file. The device structures for these devices are generated at compile
876 * time by the config tool and are organized into the device tree. This
877 * function determines if the devices created at compile time actually exist
878 * in the physical system.
879 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000880 * For devices in the physical system but not listed in devicetree.cb,
Li-Ta Lo04930692004-11-25 17:37:19 +0000881 * the device structures have to be created at run time and attached to the
Li-Ta Loe5266692004-03-23 21:28:05 +0000882 * device tree.
883 *
Uwe Hermanne4870472010-11-04 23:23:47 +0000884 * This function starts from the root device 'dev_root', scans the buses in
885 * the system recursively, and modifies the device tree according to the
886 * result of the probe.
Li-Ta Loe5266692004-03-23 21:28:05 +0000887 *
Li-Ta Lo5782d272004-04-26 17:51:20 +0000888 * This function has no idea how to scan and probe buses and devices at all.
889 * It depends on the bus/device specific scan_bus() method to do it. The
Li-Ta Lo04930692004-11-25 17:37:19 +0000890 * scan_bus() method also has to create the device structure and attach
Myles Watson032a9652009-05-11 22:24:53 +0000891 * it to the device tree.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000892 */
893void dev_enumerate(void)
894{
895 struct device *root;
Uwe Hermanne4870472010-11-04 23:23:47 +0000896
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000897 printk(BIOS_INFO, "Enumerating buses...\n");
Uwe Hermanne4870472010-11-04 23:23:47 +0000898
Eric Biederman8ca8d762003-04-22 19:02:15 +0000899 root = &dev_root;
Myles Watsoncd5d7562009-05-12 13:43:34 +0000900
Uwe Hermanne4870472010-11-04 23:23:47 +0000901 show_all_devs(BIOS_SPEW, "Before device enumeration.");
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000902 printk(BIOS_SPEW, "Compare with tree...\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +0000903 show_devs_tree(root, BIOS_SPEW, 0, 0);
Myles Watsoncd5d7562009-05-12 13:43:34 +0000904
Uwe Hermanne4870472010-11-04 23:23:47 +0000905 if (root->chip_ops && root->chip_ops->enable_dev)
Eric Biederman7003ba42004-10-16 06:20:29 +0000906 root->chip_ops->enable_dev(root);
Uwe Hermanne4870472010-11-04 23:23:47 +0000907
Eric Biedermanb78c1972004-10-14 20:54:17 +0000908 if (!root->ops || !root->ops->scan_bus) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000909 printk(BIOS_ERR, "dev_root missing scan_bus operation");
Eric Biedermanb78c1972004-10-14 20:54:17 +0000910 return;
911 }
Stefan Reinauer6afcea82009-07-18 17:58:44 +0000912 scan_bus(root, 0);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000913 printk(BIOS_INFO, "done\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000914}
915
Li-Ta Loe5266692004-03-23 21:28:05 +0000916/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000917 * Configure devices on the devices tree.
Myles Watson032a9652009-05-11 22:24:53 +0000918 *
Li-Ta Lo04930692004-11-25 17:37:19 +0000919 * Starting at the root of the device tree, travel it recursively in two
920 * passes. In the first pass, we compute and allocate resources (ranges)
921 * requried by each device. In the second pass, the resources ranges are
922 * relocated to their final position and stored to the hardware.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000923 *
Myles Watson29cc9ed2009-07-02 18:56:24 +0000924 * I/O resources grow upward. MEM resources grow downward.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000925 *
926 * Since the assignment is hierarchical we set the values into the dev_root
Myles Watson032a9652009-05-11 22:24:53 +0000927 * struct.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000928 */
929void dev_configure(void)
930{
Myles Watson29cc9ed2009-07-02 18:56:24 +0000931 struct resource *res;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000932 struct device *root;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000933 struct device *child;
Li-Ta Loe5266692004-03-23 21:28:05 +0000934
Myles Watson28412f52009-09-17 16:54:46 +0000935#if CONFIG_VGA_BRIDGE_SETUP == 1
Myles Watsonc7233e02009-07-02 19:02:33 +0000936 set_vga_bridge_bits();
937#endif
938
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000939 printk(BIOS_INFO, "Allocating resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000940
Eric Biedermanb78c1972004-10-14 20:54:17 +0000941 root = &dev_root;
Myles Watsoncd5d7562009-05-12 13:43:34 +0000942
Uwe Hermanne4870472010-11-04 23:23:47 +0000943 /*
944 * Each domain should create resources which contain the entire address
Myles Watson29cc9ed2009-07-02 18:56:24 +0000945 * space for IO, MEM, and PREFMEM resources in the domain. The
946 * allocation of device resources will be done from this address space.
947 */
Myles Watsoncd5d7562009-05-12 13:43:34 +0000948
Myles Watson29cc9ed2009-07-02 18:56:24 +0000949 /* Read the resources for the entire tree. */
Li-Ta Lo04930692004-11-25 17:37:19 +0000950
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000951 printk(BIOS_INFO, "Reading resources...\n");
Myles Watson894a3472010-06-09 22:41:35 +0000952 read_resources(root->link_list);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000953 printk(BIOS_INFO, "Done reading resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000954
Stefan Reinauer39e72292009-10-26 16:47:05 +0000955 print_resource_tree(root, BIOS_SPEW, "After reading.");
Myles Watsoncd5d7562009-05-12 13:43:34 +0000956
Myles Watson29cc9ed2009-07-02 18:56:24 +0000957 /* Compute resources for all domains. */
Myles Watson894a3472010-06-09 22:41:35 +0000958 for (child = root->link_list->children; child; child = child->sibling) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000959 if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
960 continue;
Myles Watsonc25cc112010-05-21 14:33:48 +0000961 for (res = child->resource_list; res; res = res->next) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000962 if (res->flags & IORESOURCE_FIXED)
963 continue;
964 if (res->flags & IORESOURCE_PREFETCH) {
Myles Watson894a3472010-06-09 22:41:35 +0000965 compute_resources(child->link_list,
Uwe Hermanne4870472010-11-04 23:23:47 +0000966 res, MEM_MASK, PREF_TYPE);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000967 continue;
968 }
969 if (res->flags & IORESOURCE_MEM) {
Myles Watson894a3472010-06-09 22:41:35 +0000970 compute_resources(child->link_list,
Uwe Hermanne4870472010-11-04 23:23:47 +0000971 res, MEM_MASK, MEM_TYPE);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000972 continue;
973 }
974 if (res->flags & IORESOURCE_IO) {
Myles Watson894a3472010-06-09 22:41:35 +0000975 compute_resources(child->link_list,
Uwe Hermanne4870472010-11-04 23:23:47 +0000976 res, IO_MASK, IO_TYPE);
Myles Watson29cc9ed2009-07-02 18:56:24 +0000977 continue;
978 }
979 }
980 }
981
982 /* For all domains. */
Myles Watson894a3472010-06-09 22:41:35 +0000983 for (child = root->link_list->children; child; child=child->sibling)
Myles Watson29cc9ed2009-07-02 18:56:24 +0000984 if (child->path.type == DEVICE_PATH_PCI_DOMAIN)
985 avoid_fixed_resources(child);
986
Uwe Hermanne4870472010-11-04 23:23:47 +0000987 /*
988 * Now we need to adjust the resources. MEM resources need to start at
Myles Watson29cc9ed2009-07-02 18:56:24 +0000989 * the highest address managable.
Eric Biedermanb78c1972004-10-14 20:54:17 +0000990 */
Myles Watson894a3472010-06-09 22:41:35 +0000991 for (child = root->link_list->children; child; child = child->sibling) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000992 if (child->path.type != DEVICE_PATH_PCI_DOMAIN)
993 continue;
Myles Watsonc25cc112010-05-21 14:33:48 +0000994 for (res = child->resource_list; res; res = res->next) {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000995 if (!(res->flags & IORESOURCE_MEM) ||
996 res->flags & IORESOURCE_FIXED)
997 continue;
998 res->base = resource_max(res);
999 }
1000 }
Eric Biederman5cd81732004-03-11 15:01:31 +00001001
Eric Biedermanb78c1972004-10-14 20:54:17 +00001002 /* Store the computed resource allocations into device registers ... */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001003 printk(BIOS_INFO, "Setting resources...\n");
Myles Watson894a3472010-06-09 22:41:35 +00001004 for (child = root->link_list->children; child; child = child->sibling) {
Myles Watson29cc9ed2009-07-02 18:56:24 +00001005 if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
1006 continue;
Myles Watsonc25cc112010-05-21 14:33:48 +00001007 for (res = child->resource_list; res; res = res->next) {
Myles Watson29cc9ed2009-07-02 18:56:24 +00001008 if (res->flags & IORESOURCE_FIXED)
1009 continue;
1010 if (res->flags & IORESOURCE_PREFETCH) {
Myles Watson894a3472010-06-09 22:41:35 +00001011 allocate_resources(child->link_list,
Uwe Hermanne4870472010-11-04 23:23:47 +00001012 res, MEM_MASK, PREF_TYPE);
Myles Watson29cc9ed2009-07-02 18:56:24 +00001013 continue;
1014 }
1015 if (res->flags & IORESOURCE_MEM) {
Myles Watson894a3472010-06-09 22:41:35 +00001016 allocate_resources(child->link_list,
Uwe Hermanne4870472010-11-04 23:23:47 +00001017 res, MEM_MASK, MEM_TYPE);
Myles Watson29cc9ed2009-07-02 18:56:24 +00001018 continue;
1019 }
1020 if (res->flags & IORESOURCE_IO) {
Myles Watson894a3472010-06-09 22:41:35 +00001021 allocate_resources(child->link_list,
Uwe Hermanne4870472010-11-04 23:23:47 +00001022 res, IO_MASK, IO_TYPE);
Myles Watson29cc9ed2009-07-02 18:56:24 +00001023 continue;
1024 }
1025 }
1026 }
Myles Watson894a3472010-06-09 22:41:35 +00001027 assign_resources(root->link_list);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001028 printk(BIOS_INFO, "Done setting resources.\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +00001029 print_resource_tree(root, BIOS_SPEW, "After assigning values.");
Eric Biederman03acab62004-10-14 21:25:53 +00001030
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001031 printk(BIOS_INFO, "Done allocating resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +00001032}
1033
Li-Ta Loe5266692004-03-23 21:28:05 +00001034/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +00001035 * Enable devices on the device tree.
Li-Ta Loe5266692004-03-23 21:28:05 +00001036 *
1037 * Starting at the root, walk the tree and enable all devices/bridges by
1038 * calling the device's enable_resources() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +00001039 */
1040void dev_enable(void)
1041{
Myles Watson7eac4452010-06-17 16:16:56 +00001042 struct bus *link;
1043
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001044 printk(BIOS_INFO, "Enabling resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +00001045
Uwe Hermanne4870472010-11-04 23:23:47 +00001046 /* Now enable everything. */
Myles Watson7eac4452010-06-17 16:16:56 +00001047 for (link = dev_root.link_list; link; link = link->next)
1048 enable_resources(link);
Li-Ta Loe5266692004-03-23 21:28:05 +00001049
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001050 printk(BIOS_INFO, "done.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +00001051}
1052
Li-Ta Loe5266692004-03-23 21:28:05 +00001053/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +00001054 * Initialize a specific device.
Myles Watson7eac4452010-06-17 16:16:56 +00001055 *
Uwe Hermanne4870472010-11-04 23:23:47 +00001056 * The parent should be initialized first to avoid having an ordering problem.
1057 * This is done by calling the parent's init() method before its childrens'
1058 * init() methods.
Myles Watson7eac4452010-06-17 16:16:56 +00001059 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +00001060 * @param dev The device to be initialized.
Myles Watson7eac4452010-06-17 16:16:56 +00001061 */
1062static void init_dev(struct device *dev)
1063{
Uwe Hermanne4870472010-11-04 23:23:47 +00001064 if (!dev->enabled)
Myles Watson7eac4452010-06-17 16:16:56 +00001065 return;
Myles Watson7eac4452010-06-17 16:16:56 +00001066
1067 if (!dev->initialized && dev->ops && dev->ops->init) {
1068 if (dev->path.type == DEVICE_PATH_I2C) {
1069 printk(BIOS_DEBUG, "smbus: %s[%d]->",
1070 dev_path(dev->bus->dev), dev->bus->link_num);
1071 }
1072
1073 printk(BIOS_DEBUG, "%s init\n", dev_path(dev));
1074 dev->initialized = 1;
1075 dev->ops->init(dev);
1076 }
1077}
1078
1079static void init_link(struct bus *link)
1080{
1081 struct device *dev;
1082 struct bus *c_link;
1083
Uwe Hermanne4870472010-11-04 23:23:47 +00001084 for (dev = link->children; dev; dev = dev->sibling)
Myles Watson7eac4452010-06-17 16:16:56 +00001085 init_dev(dev);
Myles Watson7eac4452010-06-17 16:16:56 +00001086
1087 for (dev = link->children; dev; dev = dev->sibling) {
Uwe Hermanne4870472010-11-04 23:23:47 +00001088 for (c_link = dev->link_list; c_link; c_link = c_link->next)
Myles Watson7eac4452010-06-17 16:16:56 +00001089 init_link(c_link);
Myles Watson7eac4452010-06-17 16:16:56 +00001090 }
1091}
1092
1093/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +00001094 * Initialize all devices in the global device tree.
Myles Watson7eac4452010-06-17 16:16:56 +00001095 *
Uwe Hermannc1ee4292010-10-17 19:01:48 +00001096 * Starting at the root device, call the device's init() method to do
1097 * device-specific setup, then call each child's init() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +00001098 */
1099void dev_initialize(void)
1100{
Myles Watson7eac4452010-06-17 16:16:56 +00001101 struct bus *link;
Eric Biederman8ca8d762003-04-22 19:02:15 +00001102
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001103 printk(BIOS_INFO, "Initializing devices...\n");
Myles Watson7eac4452010-06-17 16:16:56 +00001104
Myles Watson1bd3fb72010-08-16 16:25:23 +00001105 /* First call the mainboard init. */
1106 init_dev(&dev_root);
1107
Uwe Hermanne4870472010-11-04 23:23:47 +00001108 /* Now initialize everything. */
Myles Watson7eac4452010-06-17 16:16:56 +00001109 for (link = dev_root.link_list; link; link = link->next)
1110 init_link(link);
1111
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001112 printk(BIOS_INFO, "Devices initialized\n");
Stefan Reinauer39e72292009-10-26 16:47:05 +00001113 show_all_devs(BIOS_SPEW, "After init.");
Eric Biederman8ca8d762003-04-22 19:02:15 +00001114}