blob: 303a669d9ffdd8c377172e946ce742b4929d1f94 [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001/*
2 * (c) 1999--2000 Martin Mares <mj@suse.cz>
3 * (c) 2003 Eric Biederman <ebiederm@xmission.com>
Eric Biedermane9a271e32003-09-02 03:36:25 +00004 * (c) 2003 Linux Networx
Eric Biederman8ca8d762003-04-22 19:02:15 +00005 */
6/* lots of mods by ron minnich (rminnich@lanl.gov), with
7 * the final architecture guidance from Tom Merritt (tjm@codegen.com)
8 * In particular, we changed from the one-pass original version to
9 * Tom's recommended multiple-pass version. I wasn't sure about doing
10 * it with multiple passes, until I actually started doing it and saw
11 * the wisdom of Tom's recommendations ...
12 *
13 * Lots of cleanups by Eric Biederman to handle bridges, and to
14 * handle resource allocation for non-pci devices.
15 */
16
17#include <console/console.h>
18#include <bitops.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000019#include <arch/io.h>
Eric Biederman5899fd82003-04-24 06:25:08 +000020#include <device/device.h>
21#include <device/pci.h>
Li-Ta Lo54f05f62004-05-14 17:20:29 +000022#include <device/pci_ids.h>
Eric Biedermane9a271e32003-09-02 03:36:25 +000023#include <stdlib.h>
24#include <string.h>
Eric Biederman03acab62004-10-14 21:25:53 +000025#include <smp/spinlock.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000026
Li-Ta Loe5266692004-03-23 21:28:05 +000027/** Linked list of ALL devices */
Eric Biederman5cd81732004-03-11 15:01:31 +000028struct device *all_devices = &dev_root;
Li-Ta Loe5266692004-03-23 21:28:05 +000029/** Pointer to the last device */
Eric Biederman7003ba42004-10-16 06:20:29 +000030extern struct device **last_dev_p;
Eric Biederman8ca8d762003-04-22 19:02:15 +000031
Li-Ta Loe5266692004-03-23 21:28:05 +000032/** The upper limit of MEM resource of the devices.
33 * Reserve 20M for the system */
Eric Biederman03acab62004-10-14 21:25:53 +000034#define DEVICE_MEM_HIGH 0xFEBFFFFFUL
Li-Ta Loe5266692004-03-23 21:28:05 +000035/** The lower limit of IO resource of the devices.
36 * Reserve 4k for ISA/Legacy devices */
Eric Biederman8ca8d762003-04-22 19:02:15 +000037#define DEVICE_IO_START 0x1000
38
Li-Ta Loe5266692004-03-23 21:28:05 +000039/**
40 * @brief Allocate a new device structure.
41 *
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +000042 * Allocte a new device structure and attached it to the device tree as a
43 * child of the parent bus.
Li-Ta Loe5266692004-03-23 21:28:05 +000044 *
45 * @param parent parent bus the newly created device attached to.
46 * @param path path to the device to be created.
47 *
48 * @return pointer to the newly created device structure.
49 *
50 * @see device_path
Eric Biederman8ca8d762003-04-22 19:02:15 +000051 */
Eric Biederman448bd632004-10-14 22:52:15 +000052static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
Eric Biedermane9a271e32003-09-02 03:36:25 +000053device_t alloc_dev(struct bus *parent, struct device_path *path)
Eric Biederman8ca8d762003-04-22 19:02:15 +000054{
Eric Biedermane9a271e32003-09-02 03:36:25 +000055 device_t dev, child;
56 int link;
Li-Ta Loe5266692004-03-23 21:28:05 +000057
Eric Biederman03acab62004-10-14 21:25:53 +000058 spin_lock(&dev_lock);
Li-Ta Lo3a812852004-12-03 22:39:34 +000059
Eric Biedermane9a271e32003-09-02 03:36:25 +000060 /* Find the last child of our parent */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000061 for(child = parent->children; child && child->sibling; ) {
Eric Biedermane9a271e32003-09-02 03:36:25 +000062 child = child->sibling;
63 }
Li-Ta Lo3a812852004-12-03 22:39:34 +000064
Eric Biedermane9a271e32003-09-02 03:36:25 +000065 dev = malloc(sizeof(*dev));
66 if (dev == 0) {
67 die("DEV: out of memory.\n");
68 }
69 memset(dev, 0, sizeof(*dev));
70 memcpy(&dev->path, path, sizeof(*path));
71
Eric Biedermane9a271e32003-09-02 03:36:25 +000072 /* Initialize the back pointers in the link fields */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000073 for(link = 0; link < MAX_LINKS; link++) {
Eric Biedermane9a271e32003-09-02 03:36:25 +000074 dev->link[link].dev = dev;
75 dev->link[link].link = link;
76 }
Li-Ta Lo3a812852004-12-03 22:39:34 +000077
Eric Biederman03acab62004-10-14 21:25:53 +000078 /* By default devices are enabled */
79 dev->enabled = 1;
Eric Biedermane9a271e32003-09-02 03:36:25 +000080
Eric Biedermanb78c1972004-10-14 20:54:17 +000081 /* Add the new device to the list of children of the bus. */
Eric Biedermane9a271e32003-09-02 03:36:25 +000082 dev->bus = parent;
83 if (child) {
84 child->sibling = dev;
85 } else {
86 parent->children = dev;
87 }
Li-Ta Loe5266692004-03-23 21:28:05 +000088
Eric Biederman03acab62004-10-14 21:25:53 +000089 /* Append a new device to the global device list.
90 * The list is used to find devices once everything is set up.
91 */
92 *last_dev_p = dev;
93 last_dev_p = &dev->next;
94
95 spin_unlock(&dev_lock);
Eric Biedermane9a271e32003-09-02 03:36:25 +000096 return dev;
97}
Eric Biederman8ca8d762003-04-22 19:02:15 +000098
Li-Ta Loe5266692004-03-23 21:28:05 +000099/**
100 * @brief round a number up to an alignment.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000101 * @param val the starting value
102 * @param roundup Alignment as a power of two
103 * @returns rounded up number
104 */
Eric Biederman448bd632004-10-14 22:52:15 +0000105static resource_t round(resource_t val, unsigned long pow)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000106{
Eric Biederman448bd632004-10-14 22:52:15 +0000107 resource_t mask;
108 mask = (1ULL << pow) - 1ULL;
109 val += mask;
110 val &= ~mask;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000111 return val;
112}
113
Eric Biederman8ca8d762003-04-22 19:02:15 +0000114/** Read the resources on all devices of a given bus.
115 * @param bus bus to read the resources on.
116 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000117static void read_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000118{
119 struct device *curdev;
120
Eric Biederman448bd632004-10-14 22:52:15 +0000121 printk_spew("%s read_resources bus %d link: %d\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000122 dev_path(bus->dev), bus->secondary, bus->link);
Eric Biederman448bd632004-10-14 22:52:15 +0000123
Eric Biederman8ca8d762003-04-22 19:02:15 +0000124 /* Walk through all of the devices and find which resources they need. */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000125 for(curdev = bus->children; curdev; curdev = curdev->sibling) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000126 unsigned links;
127 int i;
Eric Biederman448bd632004-10-14 22:52:15 +0000128 if (curdev->have_resources) {
129 continue;
130 }
131 if (!curdev->enabled) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000132 continue;
133 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000134 if (!curdev->ops || !curdev->ops->read_resources) {
135 printk_err("%s missing read_resources\n",
Eric Biedermanb78c1972004-10-14 20:54:17 +0000136 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000137 continue;
138 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000139 curdev->ops->read_resources(curdev);
Eric Biederman448bd632004-10-14 22:52:15 +0000140 curdev->have_resources = 1;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000141 /* Read in subtractive resources behind the current device */
142 links = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000143 for(i = 0; i < curdev->resources; i++) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000144 struct resource *resource;
Eric Biederman448bd632004-10-14 22:52:15 +0000145 unsigned link;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000146 resource = &curdev->resource[i];
Eric Biederman448bd632004-10-14 22:52:15 +0000147 if (!(resource->flags & IORESOURCE_SUBTRACTIVE))
148 continue;
149 link = IOINDEX_SUBTRACTIVE_LINK(resource->index);
150 if (link > MAX_LINKS) {
151 printk_err("%s subtractive index on link: %d\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000152 dev_path(curdev), link);
Eric Biederman448bd632004-10-14 22:52:15 +0000153 continue;
154 }
155 if (!(links & (1 << link))) {
156 links |= (1 << link);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000157 read_resources(&curdev->link[link]);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000158 }
159 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000160 }
Eric Biederman448bd632004-10-14 22:52:15 +0000161 printk_spew("%s read_resources bus %d link: %d done\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000162 dev_path(bus->dev), bus->secondary, bus->link);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000163}
164
Eric Biedermane9a271e32003-09-02 03:36:25 +0000165struct pick_largest_state {
166 struct resource *last;
167 struct device *result_dev;
168 struct resource *result;
169 int seen_last;
170};
171
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000172static void pick_largest_resource(void *gp,
Eric Biedermanb78c1972004-10-14 20:54:17 +0000173 struct device *dev, struct resource *resource)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000174{
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000175 struct pick_largest_state *state = gp;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000176 struct resource *last;
177 last = state->last;
178 /* Be certain to pick the successor to last */
179 if (resource == last) {
180 state->seen_last = 1;
181 return;
182 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000183 if (resource->flags & IORESOURCE_FIXED ) return; //skip it
Eric Biedermanb78c1972004-10-14 20:54:17 +0000184 if (last && (
185 (last->align < resource->align) ||
186 ((last->align == resource->align) &&
187 (last->size < resource->size)) ||
188 ((last->align == resource->align) &&
189 (last->size == resource->size) &&
190 (!state->seen_last)))) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000191 return;
192 }
Eric Biedermanb78c1972004-10-14 20:54:17 +0000193 if (!state->result ||
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000194 (state->result->align < resource->align) ||
195 ((state->result->align == resource->align) &&
196 (state->result->size < resource->size)))
197 {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000198 state->result_dev = dev;
199 state->result = resource;
Li-Ta Loe5266692004-03-23 21:28:05 +0000200 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000201}
202
Eric Biederman448bd632004-10-14 22:52:15 +0000203static struct device *largest_resource(struct bus *bus, struct resource **result_res,
204 unsigned long type_mask, unsigned long type)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000205{
206 struct pick_largest_state state;
207
208 state.last = *result_res;
209 state.result_dev = 0;
210 state.result = 0;
211 state.seen_last = 0;
212
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000213 search_bus_resources(bus, type_mask, type, pick_largest_resource, &state);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000214
215 *result_res = state.result;
216 return state.result_dev;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000217}
218
219/* Compute allocate resources is the guts of the resource allocator.
220 *
221 * The problem.
222 * - Allocate resources locations for every device.
223 * - Don't overlap, and follow the rules of bridges.
224 * - Don't overlap with resources in fixed locations.
225 * - Be efficient so we don't have ugly strategies.
226 *
227 * The strategy.
228 * - Devices that have fixed addresses are the minority so don't
229 * worry about them too much. Instead only use part of the address
230 * space for devices with programmable addresses. This easily handles
231 * everything except bridges.
232 *
233 * - PCI devices are required to have thier sizes and their alignments
234 * equal. In this case an optimal solution to the packing problem
235 * exists. Allocate all devices from highest alignment to least
236 * alignment or vice versa. Use this.
237 *
238 * - So we can handle more than PCI run two allocation passes on
239 * bridges. The first to see how large the resources are behind
240 * the bridge, and what their alignment requirements are. The
241 * second to assign a safe address to the devices behind the
242 * bridge. This allows me to treat a bridge as just a device with
243 * a couple of resources, and not need to special case it in the
244 * allocator. Also this allows handling of other types of bridges.
245 *
246 */
247
248void compute_allocate_resource(
Eric Biedermane9a271e32003-09-02 03:36:25 +0000249 struct bus *bus,
Eric Biederman8ca8d762003-04-22 19:02:15 +0000250 struct resource *bridge,
251 unsigned long type_mask,
252 unsigned long type)
253{
254 struct device *dev;
255 struct resource *resource;
Eric Biederman03acab62004-10-14 21:25:53 +0000256 resource_t base;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000257 unsigned long align, min_align;
258 min_align = 0;
259 base = bridge->base;
260
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000261 printk_spew("%s compute_allocate_%s: base: %08Lx size: %08Lx align: %d gran: %d\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000262 dev_path(bus->dev),
263 (bridge->flags & IORESOURCE_IO)? "io":
264 (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
265 base, bridge->size, bridge->align, bridge->gran);
Ronald G. Minnich99dcf232003-09-30 02:16:47 +0000266
Eric Biederman8ca8d762003-04-22 19:02:15 +0000267 /* We want different minimum alignments for different kinds of
268 * resources. These minimums are not device type specific
269 * but resource type specific.
270 */
271 if (bridge->flags & IORESOURCE_IO) {
272 min_align = log2(DEVICE_IO_ALIGN);
273 }
274 if (bridge->flags & IORESOURCE_MEM) {
275 min_align = log2(DEVICE_MEM_ALIGN);
276 }
277
Eric Biederman8ca8d762003-04-22 19:02:15 +0000278 /* Make certain I have read in all of the resources */
279 read_resources(bus);
280
281 /* Remember I haven't found anything yet. */
282 resource = 0;
283
Eric Biedermanb78c1972004-10-14 20:54:17 +0000284 /* Walk through all the devices on the current bus and
285 * compute the addresses.
286 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000287 while((dev = largest_resource(bus, &resource, type_mask, type))) {
Eric Biederman03acab62004-10-14 21:25:53 +0000288 resource_t size;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000289 /* Do NOT I repeat do not ignore resources which have zero size.
290 * If they need to be ignored dev->read_resources should not even
291 * return them. Some resources must be set even when they have
292 * no size. PCI bridge resources are a good example of this.
293 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000294 /* Propogate the resource alignment to the bridge register */
295 if (resource->align > bridge->align) {
296 bridge->align = resource->align;
297 }
298
299 /* Make certain we are dealing with a good minimum size */
300 size = resource->size;
301 align = resource->align;
302 if (align < min_align) {
303 align = min_align;
304 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000305
Eric Biedermane9a271e32003-09-02 03:36:25 +0000306 if (resource->flags & IORESOURCE_FIXED) {
307 continue;
308 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000309
Eric Biedermandbec2d42004-10-21 10:44:08 +0000310 /* Propogate the resource limit to the bridge register */
311 if (bridge->limit > resource->limit) {
312 bridge->limit = resource->limit;
313 }
314 /* Artificially deny limits between DEVICE_MEM_HIGH and 0xffffffff */
315 if ((bridge->limit > DEVICE_MEM_HIGH) && (bridge->limit <= 0xffffffff)) {
316 bridge->limit = DEVICE_MEM_HIGH;
317 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000318 if (resource->flags & IORESOURCE_IO) {
319 /* Don't allow potential aliases over the
320 * legacy pci expansion card addresses.
Eric Biedermanbbb6d102003-08-04 19:54:48 +0000321 * The legacy pci decodes only 10 bits,
322 * uses 100h - 3ffh. Therefor, only 0 - ff
323 * can be used out of each 400h block of io
324 * space.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000325 */
Eric Biedermanbbb6d102003-08-04 19:54:48 +0000326 if ((base & 0x300) != 0) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000327 base = (base & ~0x3ff) + 0x400;
328 }
329 /* Don't allow allocations in the VGA IO range.
330 * PCI has special cases for that.
331 */
332 else if ((base >= 0x3b0) && (base <= 0x3df)) {
333 base = 0x3e0;
334 }
335 }
Eric Biederman03acab62004-10-14 21:25:53 +0000336 if (((round(base, align) + size) -1) <= resource->limit) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000337 /* base must be aligned to size */
Eric Biederman03acab62004-10-14 21:25:53 +0000338 base = round(base, align);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000339 resource->base = base;
Eric Biederman5cd81732004-03-11 15:01:31 +0000340 resource->flags |= IORESOURCE_ASSIGNED;
341 resource->flags &= ~IORESOURCE_STORED;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000342 base += size;
343
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000344 printk_spew(
345 "%s %02x * [0x%08Lx - 0x%08Lx] %s\n",
346 dev_path(dev),
347 resource->index,
348 resource->base,
349 resource->base + resource->size - 1,
350 (resource->flags & IORESOURCE_IO)? "io":
351 (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000352 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000353 }
354 /* A pci bridge resource does not need to be a power
355 * of two size, but it does have a minimum granularity.
356 * Round the size up to that minimum granularity so we
357 * know not to place something else at an address postitively
358 * decoded by the bridge.
359 */
Eric Biederman03acab62004-10-14 21:25:53 +0000360 bridge->size = round(base, bridge->gran) - bridge->base;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000361
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000362 printk_spew("%s compute_allocate_%s: base: %08Lx size: %08Lx align: %d gran: %d done\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000363 dev_path(bus->dev),
364 (bridge->flags & IORESOURCE_IO)? "io":
365 (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
366 base, bridge->size, bridge->align, bridge->gran);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000367
368
369}
arch import user (historical)dc811182005-07-06 17:16:09 +0000370
Yinghai Lu9e4faef2005-01-14 22:04:49 +0000371#if CONFIG_CONSOLE_VGA == 1
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000372
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000373device_t vga_pri = 0;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000374static void allocate_vga_resource(void)
375{
Eric Biedermane9a271e32003-09-02 03:36:25 +0000376#warning "FIXME modify allocate_vga_resource so it is less pci centric!"
Li-Ta Loe5266692004-03-23 21:28:05 +0000377#warning "This function knows to much about PCI stuff, it should be just a ietrator/visitor."
378
Eric Biederman8ca8d762003-04-22 19:02:15 +0000379 /* FIXME handle the VGA pallette snooping */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000380 struct device *dev, *vga, *vga_onboard;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000381 struct bus *bus;
382 bus = 0;
383 vga = 0;
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000384 vga_onboard = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000385 for(dev = all_devices; dev; dev = dev->next) {
arch import user (historical)dc811182005-07-06 17:16:09 +0000386 if (!dev->enabled) continue;
Li-Ta Lo54f05f62004-05-14 17:20:29 +0000387 if (((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000388 ((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER))
389 {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000390 if (!vga) {
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000391 if (dev->on_mainboard) {
392 vga_onboard = dev;
arch import user (historical)dc811182005-07-06 17:16:09 +0000393 } else {
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000394 vga = dev;
395 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000396 }
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000397 /* It isn't safe to enable other VGA cards */
398 dev->command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000399 }
400 }
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000401
402 if (!vga) {
403 vga = vga_onboard;
404 }
405
arch import user (historical)dc811182005-07-06 17:16:09 +0000406 if (vga) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000407 /* vga is first add on card or the only onboard vga */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000408 printk_debug("Allocating VGA resource %s\n", dev_path(vga));
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000409 /* All legacy VGA cards have MEM & I/O space registers */
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000410 vga->command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
411 vga_pri = vga;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000412 bus = vga->bus;
413 }
414 /* Now walk up the bridges setting the VGA enable */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000415 while(bus) {
Li-Ta Lo515f6c72005-01-11 22:48:54 +0000416 printk_debug("Setting PCI_BRIDGE_CTL_VGA for bridge %s\n",
417 dev_path(bus->dev));
Li-Ta Lodb7f47c2004-01-08 21:15:49 +0000418 bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000419 bus = (bus == bus->dev->bus)? 0 : bus->dev->bus;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000420 }
421}
Yinghai Lu9e4faef2005-01-14 22:04:49 +0000422#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000423
Yinghai Lu1f1085b2005-01-17 21:37:12 +0000424
Li-Ta Lo04930692004-11-25 17:37:19 +0000425/**
426 * @brief Assign the computed resources to the devices on the bus.
427 *
Eric Biederman8ca8d762003-04-22 19:02:15 +0000428 * @param bus Pointer to the structure for this bus
Li-Ta Lo04930692004-11-25 17:37:19 +0000429 *
430 * Use the device specific set_resources method to store the computed
431 * resources to hardware. For bridge devices, the set_resources() method
432 * has to recurse into every down stream buses.
433 *
434 * Mutual recursion:
435 * assign_resources() -> device_operation::set_resources()
436 * device_operation::set_resources() -> assign_resources()
437 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000438void assign_resources(struct bus *bus)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000439{
440 struct device *curdev;
441
Eric Biederman03acab62004-10-14 21:25:53 +0000442 printk_spew("%s assign_resources, bus %d link: %d\n",
443 dev_path(bus->dev), bus->secondary, bus->link);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000444
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000445 for(curdev = bus->children; curdev; curdev = curdev->sibling) {
Eric Biederman03acab62004-10-14 21:25:53 +0000446 if (!curdev->enabled || !curdev->resources) {
447 continue;
448 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000449 if (!curdev->ops || !curdev->ops->set_resources) {
450 printk_err("%s missing set_resources\n",
Eric Biedermanb78c1972004-10-14 20:54:17 +0000451 dev_path(curdev));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000452 continue;
453 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000454 curdev->ops->set_resources(curdev);
455 }
Eric Biederman03acab62004-10-14 21:25:53 +0000456 printk_spew("%s assign_resources, bus %d link: %d\n",
457 dev_path(bus->dev), bus->secondary, bus->link);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000458}
459
Li-Ta Lo5782d272004-04-26 17:51:20 +0000460/**
461 * @brief Enable the resources for a specific device
462 *
463 * @param dev the device whose resources are to be enabled
464 *
465 * Enable resources of the device by calling the device specific
466 * enable_resources() method.
467 *
468 * The parent's resources should be enabled first to avoid having enabling
469 * order problem. This is done by calling the parent's enable_resources()
Li-Ta Lo04930692004-11-25 17:37:19 +0000470 * method and let that method to call it's children's enable_resoruces()
471 * method via the (global) enable_childrens_resources().
Li-Ta Lo9f0d0f92004-05-10 16:05:16 +0000472 *
473 * Indirect mutual recursion:
Li-Ta Lo04930692004-11-25 17:37:19 +0000474 * enable_resources() -> device_operations::enable_resource()
475 * device_operations::enable_resource() -> enable_children_resources()
476 * enable_children_resources() -> enable_resources()
Li-Ta Lo5782d272004-04-26 17:51:20 +0000477 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000478void enable_resources(struct device *dev)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000479{
Eric Biederman03acab62004-10-14 21:25:53 +0000480 if (!dev->enabled) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000481 return;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000482 }
Eric Biederman03acab62004-10-14 21:25:53 +0000483 if (!dev->ops || !dev->ops->enable_resources) {
484 printk_err("%s missing enable_resources\n", dev_path(dev));
Eric Biederman83b991a2003-10-11 06:20:25 +0000485 return;
486 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000487 dev->ops->enable_resources(dev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000488}
489
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000490/**
491 * @brief Reset all of the devices a bus
492 *
493 * Reset all of the devices on a bus and clear the bus's reset_needed flag.
494 *
495 * @param bus pointer to the bus structure
496 *
497 * @return 1 if the bus was successfully reset, 0 otherwise.
498 *
499 */
500int reset_bus(struct bus *bus)
501{
502 device_t dev;
503 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->reset_bus)
504 {
505 bus->dev->ops->reset_bus(bus);
506 bus->reset_needed = 0;
507 return 1;
508 }
509 return 0;
510}
511
512/**
513 * @brief Scan for devices on a bus.
514 *
515 * If there are bridges on the bus, recursively scan the buses behind the bridges.
516 * If the setting up and tuning of the bus causes a reset to be required,
517 * reset the bus and scan it again.
518 *
519 * @param bus pointer to the bus device
520 * @param max current bus number
521 *
522 * @return The maximum bus number found, after scanning all subordinate busses
523 */
524unsigned int scan_bus(device_t bus, unsigned int max)
525{
526 unsigned int new_max;
527 int do_scan_bus;
528 if ( !bus ||
529 !bus->enabled ||
530 !bus->ops ||
531 !bus->ops->scan_bus)
532 {
533 return max;
534 }
535 do_scan_bus = 1;
536 while(do_scan_bus) {
537 int link;
538 new_max = bus->ops->scan_bus(bus, max);
539 do_scan_bus = 0;
540 for(link = 0; link < bus->links; link++) {
541 if (bus->link[link].reset_needed) {
542 if (reset_bus(&bus->link[link])) {
543 do_scan_bus = 1;
544 } else {
545 bus->bus->reset_needed = 1;
546 }
547 }
548 }
549 }
550 return new_max;
551}
552
553
Li-Ta Loe5266692004-03-23 21:28:05 +0000554/**
Li-Ta Lo04930692004-11-25 17:37:19 +0000555 * @brief Determine the existence of devices and extend the device tree.
556 *
557 * Most of the devices in the system are listed in the mainboard Config.lb
558 * file. The device structures for these devices are generated at compile
559 * time by the config tool and are organized into the device tree. This
560 * function determines if the devices created at compile time actually exist
561 * in the physical system.
562 *
563 * For devices in the physical system but not listed in the Config.lb file,
564 * the device structures have to be created at run time and attached to the
Li-Ta Loe5266692004-03-23 21:28:05 +0000565 * device tree.
566 *
Li-Ta Lo04930692004-11-25 17:37:19 +0000567 * This function starts from the root device 'dev_root', scan the buses in
568 * the system recursively, modify the device tree according to the result of
569 * the probe.
Li-Ta Loe5266692004-03-23 21:28:05 +0000570 *
Li-Ta Lo5782d272004-04-26 17:51:20 +0000571 * This function has no idea how to scan and probe buses and devices at all.
572 * It depends on the bus/device specific scan_bus() method to do it. The
Li-Ta Lo04930692004-11-25 17:37:19 +0000573 * scan_bus() method also has to create the device structure and attach
Li-Ta Loe5266692004-03-23 21:28:05 +0000574 * it to the device tree.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000575 */
576void dev_enumerate(void)
577{
578 struct device *root;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000579 unsigned subordinate;
Li-Ta Loe5266692004-03-23 21:28:05 +0000580 printk_info("Enumerating buses...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000581 root = &dev_root;
Eric Biederman7003ba42004-10-16 06:20:29 +0000582 if (root->chip_ops && root->chip_ops->enable_dev) {
583 root->chip_ops->enable_dev(root);
584 }
Eric Biedermanb78c1972004-10-14 20:54:17 +0000585 if (!root->ops || !root->ops->scan_bus) {
586 printk_err("dev_root missing scan_bus operation");
587 return;
588 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000589 subordinate = scan_bus(root, 0);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000590 printk_info("done\n");
591}
592
Li-Ta Loe5266692004-03-23 21:28:05 +0000593/**
594 * @brief Configure devices on the devices tree.
595 *
Li-Ta Lo04930692004-11-25 17:37:19 +0000596 * Starting at the root of the device tree, travel it recursively in two
597 * passes. In the first pass, we compute and allocate resources (ranges)
598 * requried by each device. In the second pass, the resources ranges are
599 * relocated to their final position and stored to the hardware.
Li-Ta Lo5782d272004-04-26 17:51:20 +0000600 *
601 * I/O resources start at DEVICE_IO_START and grow upward. MEM resources start
602 * at DEVICE_MEM_START and grow downward.
603 *
604 * Since the assignment is hierarchical we set the values into the dev_root
605 * struct.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000606 */
607void dev_configure(void)
608{
Eric Biederman03acab62004-10-14 21:25:53 +0000609 struct resource *io, *mem;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000610 struct device *root;
Li-Ta Loe5266692004-03-23 21:28:05 +0000611
Li-Ta Lo54f05f62004-05-14 17:20:29 +0000612 printk_info("Allocating resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000613
Eric Biedermanb78c1972004-10-14 20:54:17 +0000614 root = &dev_root;
615 if (!root->ops || !root->ops->read_resources) {
616 printk_err("dev_root missing read_resources\n");
617 return;
618 }
619 if (!root->ops || !root->ops->set_resources) {
620 printk_err("dev_root missing set_resources\n");
621 return;
622 }
Li-Ta Lo04930692004-11-25 17:37:19 +0000623
624 printk_info("Reading resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000625 root->ops->read_resources(root);
Li-Ta Lo3a812852004-12-03 22:39:34 +0000626 printk_info("Done reading resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000627
Eric Biederman03acab62004-10-14 21:25:53 +0000628 /* Get the resources */
629 io = &root->resource[0];
630 mem = &root->resource[1];
Li-Ta Loe5266692004-03-23 21:28:05 +0000631 /* Make certain the io devices are allocated somewhere safe. */
Eric Biederman03acab62004-10-14 21:25:53 +0000632 io->base = DEVICE_IO_START;
633 io->flags |= IORESOURCE_ASSIGNED;
634 io->flags &= ~IORESOURCE_STORED;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000635 /* Now reallocate the pci resources memory with the
636 * highest addresses I can manage.
637 */
Eric Biederman03acab62004-10-14 21:25:53 +0000638 mem->base = resource_max(&root->resource[1]);
639 mem->flags |= IORESOURCE_ASSIGNED;
640 mem->flags &= ~IORESOURCE_STORED;
Eric Biederman5cd81732004-03-11 15:01:31 +0000641
Yinghai Lu9e4faef2005-01-14 22:04:49 +0000642#if CONFIG_CONSOLE_VGA == 1
Li-Ta Loe5266692004-03-23 21:28:05 +0000643 /* Allocate the VGA I/O resource.. */
Eric Biederman5cd81732004-03-11 15:01:31 +0000644 allocate_vga_resource();
Yinghai Lu9e4faef2005-01-14 22:04:49 +0000645#endif
Eric Biederman5cd81732004-03-11 15:01:31 +0000646
Eric Biedermanb78c1972004-10-14 20:54:17 +0000647 /* Store the computed resource allocations into device registers ... */
Li-Ta Lo04930692004-11-25 17:37:19 +0000648 printk_info("Setting resources...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000649 root->ops->set_resources(root);
Li-Ta Lo3a812852004-12-03 22:39:34 +0000650 printk_info("Done setting resources.\n");
Eric Biederman03acab62004-10-14 21:25:53 +0000651#if 0
652 mem->flags |= IORESOURCE_STORED;
653 report_resource_stored(root, mem, "");
654#endif
655
Li-Ta Lo3a812852004-12-03 22:39:34 +0000656 printk_info("Done allocating resources.\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000657}
658
Li-Ta Loe5266692004-03-23 21:28:05 +0000659/**
660 * @brief Enable devices on the device tree.
661 *
662 * Starting at the root, walk the tree and enable all devices/bridges by
663 * calling the device's enable_resources() method.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000664 */
665void dev_enable(void)
666{
Eric Biedermane9a271e32003-09-02 03:36:25 +0000667 printk_info("Enabling resourcess...\n");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000668
669 /* now enable everything. */
670 enable_resources(&dev_root);
Li-Ta Loe5266692004-03-23 21:28:05 +0000671
Eric Biederman8ca8d762003-04-22 19:02:15 +0000672 printk_info("done.\n");
673}
674
Li-Ta Loe5266692004-03-23 21:28:05 +0000675/**
676 * @brief Initialize all devices in the global device list.
677 *
678 * Starting at the first device on the global device link list,
Li-Ta Lo04930692004-11-25 17:37:19 +0000679 * walk the list and call the device's init() method to do deivce
680 * specific setup.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000681 */
682void dev_initialize(void)
683{
684 struct device *dev;
685
686 printk_info("Initializing devices...\n");
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000687 for(dev = all_devices; dev; dev = dev->next) {
688 if (dev->enabled && !dev->initialized &&
689 dev->ops && dev->ops->init)
690 {
691 if (dev->path.type == DEVICE_PATH_I2C) {
692 printk_debug("smbus: %s[%d]->",
693 dev_path(dev->bus->dev), dev->bus->link);
694 }
695 printk_debug("%s init\n", dev_path(dev));
696 dev->initialized = 1;
697 dev->ops->init(dev);
698 }
699 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000700 printk_info("Devices initialized\n");
701}
Eric Biederman448bd632004-10-14 22:52:15 +0000702