mb/google: Add OEM product names for various boards
[coreboot.git] / src / device / resource_allocator_v3.c
blob236e149cefc2193afdd48d5f28e87f60ccf1252e
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/device.h>
5 #include <post.h>
7 /**
8 * Round a number up to an alignment.
10 * @param val The starting value.
11 * @param pow Alignment as a power of two.
12 * @return Rounded up number.
14 static resource_t round(resource_t val, unsigned long pow)
16 resource_t mask;
17 mask = (1ULL << pow) - 1ULL;
18 val += mask;
19 val &= ~mask;
20 return val;
23 static const char *resource2str(struct resource *res)
25 if (res->flags & IORESOURCE_IO)
26 return "io";
27 if (res->flags & IORESOURCE_PREFETCH)
28 return "prefmem";
29 if (res->flags & IORESOURCE_MEM)
30 return "mem";
31 return "undefined";
34 /**
35 * This function is the guts of the resource allocator.
37 * The problem.
38 * - Allocate resource locations for every device.
39 * - Don't overlap, and follow the rules of bridges.
40 * - Don't overlap with resources in fixed locations.
41 * - Be efficient so we don't have ugly strategies.
43 * The strategy.
44 * - Devices that have fixed addresses are the minority so don't
45 * worry about them too much. Instead only use part of the address
46 * space for devices with programmable addresses. This easily handles
47 * everything except bridges.
49 * - PCI devices are required to have their sizes and their alignments
50 * equal. In this case an optimal solution to the packing problem
51 * exists. Allocate all devices from highest alignment to least
52 * alignment or vice versa. Use this.
54 * - So we can handle more than PCI run two allocation passes on bridges. The
55 * first to see how large the resources are behind the bridge, and what
56 * their alignment requirements are. The second to assign a safe address to
57 * the devices behind the bridge. This allows us to treat a bridge as just
58 * a device with a couple of resources, and not need to special case it in
59 * the allocator. Also this allows handling of other types of bridges.
61 * @param bus The bus we are traversing.
62 * @param bridge The bridge resource which must contain the bus' resources.
63 * @param type_mask This value gets ANDed with the resource type.
64 * @param type This value must match the result of the AND.
65 * @return TODO
67 static void compute_resources(struct bus *bus, struct resource *bridge,
68 unsigned long type_mask, unsigned long type)
70 const struct device *dev;
71 struct resource *resource;
72 resource_t base;
73 base = round(bridge->base, bridge->align);
75 if (!bus)
76 return;
78 printk(BIOS_SPEW, "%s %s: base: %llx size: %llx align: %d gran: %d"
79 " limit: %llx\n", dev_path(bus->dev), resource2str(bridge),
80 base, bridge->size, bridge->align,
81 bridge->gran, bridge->limit);
83 /* For each child which is a bridge, compute the resource needs. */
84 for (dev = bus->children; dev; dev = dev->sibling) {
85 struct resource *child_bridge;
87 if (!dev->link_list)
88 continue;
90 /* Find the resources with matching type flags. */
91 for (child_bridge = dev->resource_list; child_bridge;
92 child_bridge = child_bridge->next) {
93 struct bus* link;
95 if (!(child_bridge->flags & IORESOURCE_BRIDGE)
96 || (child_bridge->flags & type_mask) != type)
97 continue;
100 * Split prefetchable memory if combined. Many domains
101 * use the same address space for prefetchable memory
102 * and non-prefetchable memory. Bridges below them need
103 * it separated. Add the PREFETCH flag to the type_mask
104 * and type.
106 link = dev->link_list;
107 while (link && link->link_num !=
108 IOINDEX_LINK(child_bridge->index))
109 link = link->next;
111 if (link == NULL) {
112 printk(BIOS_ERR, "link %ld not found on %s\n",
113 IOINDEX_LINK(child_bridge->index),
114 dev_path(dev));
117 compute_resources(link, child_bridge,
118 type_mask | IORESOURCE_PREFETCH,
119 type | (child_bridge->flags &
120 IORESOURCE_PREFETCH));
124 /* Remember we haven't found anything yet. */
125 resource = NULL;
128 * Walk through all the resources on the current bus and compute the
129 * amount of address space taken by them. Take granularity and
130 * alignment into account.
132 while ((dev = largest_resource(bus, &resource, type_mask, type))) {
134 /* Size 0 resources can be skipped. */
135 if (!resource->size)
136 continue;
138 /* Propagate the resource alignment to the bridge resource. */
139 if (resource->align > bridge->align)
140 bridge->align = resource->align;
142 /* Propagate the resource limit to the bridge register. */
143 if (bridge->limit > resource->limit)
144 bridge->limit = resource->limit;
146 /* Warn if it looks like APICs aren't declared. */
147 if ((resource->limit == 0xffffffff) &&
148 (resource->flags & IORESOURCE_ASSIGNED)) {
149 printk(BIOS_ERR,
150 "Resource limit looks wrong! (no APIC?)\n");
151 printk(BIOS_ERR, "%s %02lx limit %08llx\n",
152 dev_path(dev), resource->index, resource->limit);
155 if (resource->flags & IORESOURCE_IO) {
157 * Don't allow potential aliases over the legacy PCI
158 * expansion card addresses. The legacy PCI decodes
159 * only 10 bits, uses 0x100 - 0x3ff. Therefore, only
160 * 0x00 - 0xff can be used out of each 0x400 block of
161 * I/O space.
163 if ((base & 0x300) != 0) {
164 base = (base & ~0x3ff) + 0x400;
167 * Don't allow allocations in the VGA I/O range.
168 * PCI has special cases for that.
170 else if ((base >= 0x3b0) && (base <= 0x3df)) {
171 base = 0x3e0;
174 /* Base must be aligned. */
175 base = round(base, resource->align);
176 resource->base = base;
177 base += resource->size;
179 printk(BIOS_SPEW, "%s %02lx * [0x%llx - 0x%llx] %s\n",
180 dev_path(dev), resource->index, resource->base,
181 resource->base + resource->size - 1,
182 resource2str(resource));
186 * A PCI bridge resource does not need to be a power of two size, but
187 * it does have a minimum granularity. Round the size up to that
188 * minimum granularity so we know not to place something else at an
189 * address positively decoded by the bridge.
191 bridge->size = round(base, bridge->gran) -
192 round(bridge->base, bridge->align);
194 printk(BIOS_SPEW, "%s %s: base: %llx size: %llx align: %d gran: %d"
195 " limit: %llx done\n", dev_path(bus->dev),
196 resource2str(bridge),
197 base, bridge->size, bridge->align, bridge->gran, bridge->limit);
201 * This function is the second part of the resource allocator.
203 * See the compute_resources function for a more detailed explanation.
205 * This function assigns the resources a value.
207 * @param bus The bus we are traversing.
208 * @param bridge The bridge resource which must contain the bus' resources.
209 * @param type_mask This value gets ANDed with the resource type.
210 * @param type This value must match the result of the AND.
212 * @see compute_resources
214 static void __allocate_resources(struct bus *bus, struct resource *bridge,
215 unsigned long type_mask, unsigned long type)
217 const struct device *dev;
218 struct resource *resource;
219 resource_t base;
220 base = bridge->base;
222 if (!bus)
223 return;
225 printk(BIOS_SPEW, "%s %s: base:%llx size:%llx align:%d gran:%d "
226 "limit:%llx\n", dev_path(bus->dev),
227 resource2str(bridge),
228 base, bridge->size, bridge->align, bridge->gran, bridge->limit);
230 /* Remember we haven't found anything yet. */
231 resource = NULL;
234 * Walk through all the resources on the current bus and allocate them
235 * address space.
237 while ((dev = largest_resource(bus, &resource, type_mask, type))) {
239 /* Propagate the bridge limit to the resource register. */
240 if (resource->limit > bridge->limit)
241 resource->limit = bridge->limit;
243 /* Size 0 resources can be skipped. */
244 if (!resource->size)
245 continue;
247 if (resource->flags & IORESOURCE_IO) {
249 * Don't allow potential aliases over the legacy PCI
250 * expansion card addresses. The legacy PCI decodes
251 * only 10 bits, uses 0x100 - 0x3ff. Therefore, only
252 * 0x00 - 0xff can be used out of each 0x400 block of
253 * I/O space.
255 if ((base & 0x300) != 0) {
256 base = (base & ~0x3ff) + 0x400;
259 * Don't allow allocations in the VGA I/O range.
260 * PCI has special cases for that.
262 else if ((base >= 0x3b0) && (base <= 0x3df)) {
263 base = 0x3e0;
267 if ((round(base, resource->align) + resource->size - 1) <=
268 resource->limit) {
269 /* Base must be aligned. */
270 base = round(base, resource->align);
271 resource->base = base;
272 resource->limit = resource->base + resource->size - 1;
273 resource->flags |= IORESOURCE_ASSIGNED;
274 resource->flags &= ~IORESOURCE_STORED;
275 base += resource->size;
276 } else {
277 printk(BIOS_ERR, "!! Resource didn't fit !!\n");
278 printk(BIOS_ERR, " aligned base %llx size %llx "
279 "limit %llx\n", round(base, resource->align),
280 resource->size, resource->limit);
281 printk(BIOS_ERR, " %llx needs to be <= %llx "
282 "(limit)\n", (round(base, resource->align) +
283 resource->size) - 1, resource->limit);
284 printk(BIOS_ERR, " %s%s %02lx * [0x%llx - 0x%llx]"
285 " %s\n", (resource->flags & IORESOURCE_ASSIGNED)
286 ? "Assigned: " : "", dev_path(dev),
287 resource->index, resource->base,
288 resource->base + resource->size - 1,
289 resource2str(resource));
292 printk(BIOS_SPEW, "%s %02lx * [0x%llx - 0x%llx] %s\n",
293 dev_path(dev), resource->index, resource->base,
294 resource->size ? resource->base + resource->size - 1 :
295 resource->base, resource2str(resource));
299 * A PCI bridge resource does not need to be a power of two size, but
300 * it does have a minimum granularity. Round the size up to that
301 * minimum granularity so we know not to place something else at an
302 * address positively decoded by the bridge.
305 bridge->flags |= IORESOURCE_ASSIGNED;
307 printk(BIOS_SPEW, "%s %s: next_base: %llx size: %llx align: %d "
308 "gran: %d done\n", dev_path(bus->dev),
309 resource2str(bridge), base, bridge->size, bridge->align,
310 bridge->gran);
312 /* For each child which is a bridge, __allocate_resources. */
313 for (dev = bus->children; dev; dev = dev->sibling) {
314 struct resource *child_bridge;
316 if (!dev->link_list)
317 continue;
319 /* Find the resources with matching type flags. */
320 for (child_bridge = dev->resource_list; child_bridge;
321 child_bridge = child_bridge->next) {
322 struct bus* link;
324 if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
325 (child_bridge->flags & type_mask) != type)
326 continue;
329 * Split prefetchable memory if combined. Many domains
330 * use the same address space for prefetchable memory
331 * and non-prefetchable memory. Bridges below them need
332 * it separated. Add the PREFETCH flag to the type_mask
333 * and type.
335 link = dev->link_list;
336 while (link && link->link_num !=
337 IOINDEX_LINK(child_bridge->index))
338 link = link->next;
339 if (link == NULL)
340 printk(BIOS_ERR, "link %ld not found on %s\n",
341 IOINDEX_LINK(child_bridge->index),
342 dev_path(dev));
344 __allocate_resources(link, child_bridge,
345 type_mask | IORESOURCE_PREFETCH,
346 type | (child_bridge->flags &
347 IORESOURCE_PREFETCH));
352 static int resource_is(struct resource *res, u32 type)
354 return (res->flags & IORESOURCE_TYPE_MASK) == type;
357 struct constraints {
358 struct resource io, mem;
361 static struct resource *resource_limit(struct constraints *limits,
362 struct resource *res)
364 struct resource *lim = NULL;
366 /* MEM, or I/O - skip any others. */
367 if (resource_is(res, IORESOURCE_MEM))
368 lim = &limits->mem;
369 else if (resource_is(res, IORESOURCE_IO))
370 lim = &limits->io;
372 return lim;
375 static void constrain_resources(const struct device *dev,
376 struct constraints* limits)
378 const struct device *child;
379 struct resource *res;
380 struct resource *lim;
381 struct bus *link;
383 /* Constrain limits based on the fixed resources of this device. */
384 for (res = dev->resource_list; res; res = res->next) {
385 if (!(res->flags & IORESOURCE_FIXED))
386 continue;
387 if (!res->size) {
388 /* It makes no sense to have 0-sized, fixed resources.*/
389 printk(BIOS_ERR, "skipping %s@%lx fixed resource, "
390 "size=0!\n", dev_path(dev), res->index);
391 continue;
394 lim = resource_limit(limits, res);
395 if (!lim)
396 continue;
399 * Is it a fixed resource outside the current known region?
400 * If so, we don't have to consider it - it will be handled
401 * correctly and doesn't affect current region's limits.
403 if (((res->base + res->size -1) < lim->base)
404 || (res->base > lim->limit))
405 continue;
407 printk(BIOS_SPEW, "%s: %s %02lx base %08llx limit %08llx %s (fixed)\n",
408 __func__, dev_path(dev), res->index, res->base,
409 res->base + res->size - 1, resource2str(res));
412 * Choose to be above or below fixed resources. This check is
413 * signed so that "negative" amounts of space are handled
414 * correctly.
416 if ((signed long long)(lim->limit - (res->base + res->size -1))
417 > (signed long long)(res->base - lim->base))
418 lim->base = res->base + res->size;
419 else
420 lim->limit = res->base -1;
423 /* Descend into every enabled child and look for fixed resources. */
424 for (link = dev->link_list; link; link = link->next) {
425 for (child = link->children; child; child = child->sibling) {
426 if (child->enabled)
427 constrain_resources(child, limits);
432 static void avoid_fixed_resources(const struct device *dev)
434 struct constraints limits;
435 struct resource *res;
436 struct resource *lim;
438 printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
440 /* Initialize constraints to maximum size. */
441 limits.io.base = 0;
442 limits.io.limit = 0xffffffffffffffffULL;
443 limits.mem.base = 0;
444 limits.mem.limit = 0xffffffffffffffffULL;
446 /* Constrain the limits to dev's initial resources. */
447 for (res = dev->resource_list; res; res = res->next) {
448 if ((res->flags & IORESOURCE_FIXED))
449 continue;
450 printk(BIOS_SPEW, "%s:@%s %02lx limit %08llx\n", __func__,
451 dev_path(dev), res->index, res->limit);
453 lim = resource_limit(&limits, res);
454 if (!lim)
455 continue;
457 if (res->base > lim->base)
458 lim->base = res->base;
459 if (res->limit < lim->limit)
460 lim->limit = res->limit;
463 /* Look through the tree for fixed resources and update the limits. */
464 constrain_resources(dev, &limits);
466 /* Update dev's resources with new limits. */
467 for (res = dev->resource_list; res; res = res->next) {
468 if ((res->flags & IORESOURCE_FIXED))
469 continue;
471 lim = resource_limit(&limits, res);
472 if (!lim)
473 continue;
475 /* Is the resource outside the limits? */
476 if (lim->base > res->base)
477 res->base = lim->base;
478 if (res->limit > lim->limit)
479 res->limit = lim->limit;
481 /* MEM resources need to start at the highest address manageable. */
482 if (res->flags & IORESOURCE_MEM)
483 res->base = resource_max(res);
485 printk(BIOS_SPEW, "%s:@%s %02lx base %08llx limit %08llx\n",
486 __func__, dev_path(dev), res->index, res->base, res->limit);
490 void allocate_resources(const struct device *root)
492 struct resource *res;
493 const struct device *child;
495 /* Compute resources for all domains. */
496 for (child = root->link_list->children; child; child = child->sibling) {
497 if (!(child->path.type == DEVICE_PATH_DOMAIN))
498 continue;
499 post_log_path(child);
500 for (res = child->resource_list; res; res = res->next) {
501 if (res->flags & IORESOURCE_FIXED)
502 continue;
503 if (res->flags & IORESOURCE_MEM) {
504 compute_resources(child->link_list,
505 res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
506 continue;
508 if (res->flags & IORESOURCE_IO) {
509 compute_resources(child->link_list,
510 res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
511 continue;
516 /* For all domains. */
517 for (child = root->link_list->children; child; child=child->sibling)
518 if (child->path.type == DEVICE_PATH_DOMAIN)
519 avoid_fixed_resources(child);
521 /* Store the computed resource allocations into device registers ... */
522 printk(BIOS_INFO, "Setting resources...\n");
523 for (child = root->link_list->children; child; child = child->sibling) {
524 if (!(child->path.type == DEVICE_PATH_DOMAIN))
525 continue;
526 post_log_path(child);
527 for (res = child->resource_list; res; res = res->next) {
528 if (res->flags & IORESOURCE_FIXED)
529 continue;
530 if (res->flags & IORESOURCE_MEM) {
531 __allocate_resources(child->link_list,
532 res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
533 continue;
535 if (res->flags & IORESOURCE_IO) {
536 __allocate_resources(child->link_list,
537 res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
538 continue;