blob: 25e95cfa67eccba559c80a125f7f4436661781c4 [file] [log] [blame]
Angel Ponsc74dae92020-04-02 23:48:16 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Uwe Hermannb80dbf02007-04-22 19:08:13 +00003
Eric Biederman8ca8d762003-04-22 19:02:15 +00004#include <console/console.h>
Eric Biederman5899fd82003-04-24 06:25:08 +00005#include <device/device.h>
Eric Biedermane9a271e32003-09-02 03:36:25 +00006#include <device/path.h>
Kyösti Mälkki318066f2014-02-12 14:18:50 +02007#include <device/pci_def.h>
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +00008#include <device/resource.h>
Elyes HAOUASede8dd02019-06-23 06:57:53 +02009#include <stdlib.h>
Eric Biedermane9a271e32003-09-02 03:36:25 +000010#include <string.h>
11
Eric Biederman03acab62004-10-14 21:25:53 +000012/**
Duncan Laurie6f88a6e2011-07-18 10:41:36 -070013 * Given a Local APIC ID, find the device structure.
14 *
15 * @param apic_id The Local APIC ID number.
16 * @return Pointer to the device structure (if found), 0 otherwise.
17 */
Martin Roth38ddbfb2019-10-23 21:41:00 -060018struct device *dev_find_lapic(unsigned int apic_id)
Duncan Laurie6f88a6e2011-07-18 10:41:36 -070019{
Aaron Durbinf0349022017-11-10 10:47:54 -070020 struct device *dev;
21 struct device *result = NULL;
Duncan Laurie6f88a6e2011-07-18 10:41:36 -070022
23 for (dev = all_devices; dev; dev = dev->next) {
24 if (dev->path.type == DEVICE_PATH_APIC &&
25 dev->path.apic.apic_id == apic_id) {
26 result = dev;
27 break;
28 }
29 }
30 return result;
31}
32
33/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +000034 * Find a device of a given vendor and type.
35 *
36 * @param vendor A PCI vendor ID (e.g. 0x8086 for Intel).
37 * @param device A PCI device ID.
Uwe Hermanne4870472010-11-04 23:23:47 +000038 * @param from Pointer to the device structure, used as a starting point in
39 * the linked list of all_devices, which can be 0 to start at the
40 * head of the list (i.e. all_devices).
Uwe Hermannc1ee4292010-10-17 19:01:48 +000041 * @return Pointer to the device struct.
Eric Biederman8ca8d762003-04-22 19:02:15 +000042 */
Uwe Hermanne4870472010-11-04 23:23:47 +000043struct device *dev_find_device(u16 vendor, u16 device, struct device *from)
Eric Biederman8ca8d762003-04-22 19:02:15 +000044{
45 if (!from)
46 from = all_devices;
47 else
48 from = from->next;
Uwe Hermanne4870472010-11-04 23:23:47 +000049
50 while (from && (from->vendor != vendor || from->device != device))
Eric Biederman8ca8d762003-04-22 19:02:15 +000051 from = from->next;
Uwe Hermanne4870472010-11-04 23:23:47 +000052
Eric Biederman8ca8d762003-04-22 19:02:15 +000053 return from;
54}
55
Uwe Hermannc1ee4292010-10-17 19:01:48 +000056/**
57 * Find a device of a given class.
58 *
59 * @param class Class of the device.
Uwe Hermanne4870472010-11-04 23:23:47 +000060 * @param from Pointer to the device structure, used as a starting point in
61 * the linked list of all_devices, which can be 0 to start at the
62 * head of the list (i.e. all_devices).
Uwe Hermannc1ee4292010-10-17 19:01:48 +000063 * @return Pointer to the device struct.
Eric Biederman8ca8d762003-04-22 19:02:15 +000064 */
65struct device *dev_find_class(unsigned int class, struct device *from)
66{
67 if (!from)
68 from = all_devices;
69 else
70 from = from->next;
Uwe Hermanne4870472010-11-04 23:23:47 +000071
Greg Watson59651692003-12-17 17:39:53 +000072 while (from && (from->class & 0xffffff00) != class)
Eric Biederman8ca8d762003-04-22 19:02:15 +000073 from = from->next;
Uwe Hermanne4870472010-11-04 23:23:47 +000074
Eric Biederman8ca8d762003-04-22 19:02:15 +000075 return from;
76}
77
Duncan Laurie5f5d9142013-06-10 09:59:17 -070078/**
79 * Encode the device path into 3 bytes for logging to CMOS.
80 *
81 * @param dev The device path to encode.
82 * @return Device path encoded into lower 3 bytes of dword.
83 */
Subrata Banik564547f2018-05-02 10:27:36 +053084u32 dev_path_encode(const struct device *dev)
Duncan Laurie5f5d9142013-06-10 09:59:17 -070085{
86 u32 ret;
87
88 if (!dev)
89 return 0;
90
91 /* Store the device type in 3rd byte. */
92 ret = dev->path.type << 16;
93
94 /* Encode the device specific path in the low word. */
95 switch (dev->path.type) {
96 case DEVICE_PATH_ROOT:
97 break;
98 case DEVICE_PATH_PCI:
99 ret |= dev->bus->secondary << 8 | dev->path.pci.devfn;
100 break;
101 case DEVICE_PATH_PNP:
102 ret |= dev->path.pnp.port << 8 | dev->path.pnp.device;
103 break;
104 case DEVICE_PATH_I2C:
Duncan Laurieb7ce5fe2016-05-07 19:49:37 -0700105 ret |= dev->path.i2c.mode_10bit << 8 | dev->path.i2c.device;
Duncan Laurie5f5d9142013-06-10 09:59:17 -0700106 break;
107 case DEVICE_PATH_APIC:
108 ret |= dev->path.apic.apic_id;
109 break;
110 case DEVICE_PATH_DOMAIN:
111 ret |= dev->path.domain.domain;
112 break;
113 case DEVICE_PATH_CPU_CLUSTER:
114 ret |= dev->path.cpu_cluster.cluster;
115 break;
116 case DEVICE_PATH_CPU:
117 ret |= dev->path.cpu.id;
118 break;
119 case DEVICE_PATH_CPU_BUS:
120 ret |= dev->path.cpu_bus.id;
121 break;
122 case DEVICE_PATH_IOAPIC:
123 ret |= dev->path.ioapic.ioapic_id;
124 break;
Duncan Laurie4650f5b2016-05-07 20:01:34 -0700125 case DEVICE_PATH_GENERIC:
126 ret |= dev->path.generic.subid << 8 | dev->path.generic.id;
127 break;
Furquan Shaikh7606c372017-02-11 10:57:23 -0800128 case DEVICE_PATH_SPI:
129 ret |= dev->path.spi.cs;
130 break;
Duncan Lauriebae9f852018-05-07 14:18:13 -0700131 case DEVICE_PATH_USB:
Karthikeyan Ramasubramanian19398242019-07-11 12:23:35 -0600132 ret |= dev->path.usb.port_type << 8 | dev->path.usb.port_id;
Duncan Lauriebae9f852018-05-07 14:18:13 -0700133 break;
Duncan Laurie5f5d9142013-06-10 09:59:17 -0700134 case DEVICE_PATH_NONE:
Justin TerAvestca2ed9f2018-01-17 16:36:30 -0800135 case DEVICE_PATH_MMIO: /* don't care */
Duncan Laurie5f5d9142013-06-10 09:59:17 -0700136 default:
137 break;
138 }
139
140 return ret;
141}
142
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000143/*
144 * Warning: This function uses a static buffer. Don't call it more than once
145 * from the same print statement!
146 */
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +0200147const char *dev_path(const struct device *dev)
Eric Biedermane9a271e32003-09-02 03:36:25 +0000148{
149 static char buffer[DEVICE_PATH_MAX];
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000150
Eric Biedermane9a271e32003-09-02 03:36:25 +0000151 buffer[0] = '\0';
152 if (!dev) {
153 memcpy(buffer, "<null>", 7);
Uwe Hermanne4870472010-11-04 23:23:47 +0000154 } else {
Elyes HAOUAS0ce41f12018-11-13 10:03:31 +0100155 switch (dev->path.type) {
Patrick Rudolph6a811842017-11-01 11:33:00 +0100156 case DEVICE_PATH_NONE:
157 memcpy(buffer, "NONE", 5);
158 break;
Eric Biederman83b991a2003-10-11 06:20:25 +0000159 case DEVICE_PATH_ROOT:
160 memcpy(buffer, "Root Device", 12);
161 break;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000162 case DEVICE_PATH_PCI:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200163 snprintf(buffer, sizeof(buffer),
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100164 "PCI: %02x:%02x.%01x",
165 dev->bus->secondary,
166 PCI_SLOT(dev->path.pci.devfn),
167 PCI_FUNC(dev->path.pci.devfn));
Eric Biedermane9a271e32003-09-02 03:36:25 +0000168 break;
169 case DEVICE_PATH_PNP:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200170 snprintf(buffer, sizeof(buffer), "PNP: %04x.%01x",
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100171 dev->path.pnp.port, dev->path.pnp.device);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000172 break;
173 case DEVICE_PATH_I2C:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200174 snprintf(buffer, sizeof(buffer), "I2C: %02x:%02x",
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100175 dev->bus->secondary,
176 dev->path.i2c.device);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000177 break;
Eric Biederman03acab62004-10-14 21:25:53 +0000178 case DEVICE_PATH_APIC:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200179 snprintf(buffer, sizeof(buffer), "APIC: %02x",
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100180 dev->path.apic.apic_id);
Eric Biederman03acab62004-10-14 21:25:53 +0000181 break;
Sven Schnelle0fa50a12012-06-21 22:19:48 +0200182 case DEVICE_PATH_IOAPIC:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200183 snprintf(buffer, sizeof(buffer), "IOAPIC: %02x",
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100184 dev->path.ioapic.ioapic_id);
Sven Schnelle0fa50a12012-06-21 22:19:48 +0200185 break;
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800186 case DEVICE_PATH_DOMAIN:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200187 snprintf(buffer, sizeof(buffer), "DOMAIN: %04x",
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800188 dev->path.domain.domain);
Eric Biederman7003ba42004-10-16 06:20:29 +0000189 break;
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800190 case DEVICE_PATH_CPU_CLUSTER:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200191 snprintf(buffer, sizeof(buffer), "CPU_CLUSTER: %01x",
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800192 dev->path.cpu_cluster.cluster);
Eric Biederman7003ba42004-10-16 06:20:29 +0000193 break;
Eric Biedermana9e632c2004-11-18 22:38:08 +0000194 case DEVICE_PATH_CPU:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200195 snprintf(buffer, sizeof(buffer),
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100196 "CPU: %02x", dev->path.cpu.id);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000197 break;
198 case DEVICE_PATH_CPU_BUS:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200199 snprintf(buffer, sizeof(buffer),
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100200 "CPU_BUS: %02x", dev->path.cpu_bus.id);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000201 break;
Duncan Laurie4650f5b2016-05-07 20:01:34 -0700202 case DEVICE_PATH_GENERIC:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200203 snprintf(buffer, sizeof(buffer),
Duncan Laurie4650f5b2016-05-07 20:01:34 -0700204 "GENERIC: %d.%d", dev->path.generic.id,
205 dev->path.generic.subid);
206 break;
Furquan Shaikh7606c372017-02-11 10:57:23 -0800207 case DEVICE_PATH_SPI:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200208 snprintf(buffer, sizeof(buffer), "SPI: %02x",
Furquan Shaikh7606c372017-02-11 10:57:23 -0800209 dev->path.spi.cs);
210 break;
Duncan Lauriebae9f852018-05-07 14:18:13 -0700211 case DEVICE_PATH_USB:
Elyes HAOUASb7482212018-05-16 12:58:19 +0200212 snprintf(buffer, sizeof(buffer), "USB%u port %u",
Duncan Lauriebae9f852018-05-07 14:18:13 -0700213 dev->path.usb.port_type, dev->path.usb.port_id);
214 break;
Justin TerAvestca2ed9f2018-01-17 16:36:30 -0800215 case DEVICE_PATH_MMIO:
Jacob Garberd552aca2019-07-16 12:55:00 -0600216 snprintf(buffer, sizeof(buffer), "MMIO: %08lx",
Justin TerAvestca2ed9f2018-01-17 16:36:30 -0800217 dev->path.mmio.addr);
218 break;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000219 default:
Uwe Hermanne4870472010-11-04 23:23:47 +0000220 printk(BIOS_ERR, "Unknown device path type: %d\n",
221 dev->path.type);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000222 break;
223 }
224 }
225 return buffer;
226}
227
Aaron Durbinf0349022017-11-10 10:47:54 -0700228const char *dev_name(struct device *dev)
Kyösti Mälkki7baadac2012-10-07 14:57:15 +0200229{
Kyösti Mälkki7d54eb82012-10-10 23:14:28 +0300230 if (dev->name)
231 return dev->name;
232 else if (dev->chip_ops && dev->chip_ops->name)
Kyösti Mälkki7baadac2012-10-07 14:57:15 +0200233 return dev->chip_ops->name;
234 else
235 return "unknown";
236}
237
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000238const char *bus_path(struct bus *bus)
239{
240 static char buffer[BUS_PATH_MAX];
Elyes HAOUASb7482212018-05-16 12:58:19 +0200241 snprintf(buffer, sizeof(buffer),
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100242 "%s,%d", dev_path(bus->dev), bus->link_num);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000243 return buffer;
244}
245
Eric Biederman5cd81732004-03-11 15:01:31 +0000246/**
Myles Watsonc25cc112010-05-21 14:33:48 +0000247 * Allocate 64 more resources to the free list.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000248 *
249 * @return TODO.
Myles Watsonc25cc112010-05-21 14:33:48 +0000250 */
251static int allocate_more_resources(void)
252{
253 int i;
254 struct resource *new_res_list;
Uwe Hermanne4870472010-11-04 23:23:47 +0000255
Myles Watsonc25cc112010-05-21 14:33:48 +0000256 new_res_list = malloc(64 * sizeof(*new_res_list));
257
258 if (new_res_list == NULL)
259 return 0;
260
261 memset(new_res_list, 0, 64 * sizeof(*new_res_list));
262
Uwe Hermanne4870472010-11-04 23:23:47 +0000263 for (i = 0; i < 64 - 1; i++)
Myles Watsonc25cc112010-05-21 14:33:48 +0000264 new_res_list[i].next = &new_res_list[i+1];
265
266 free_resources = new_res_list;
267 return 1;
268}
269
270/**
271 * Remove resource res from the device's list and add it to the free list.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000272 *
273 * @param dev TODO
274 * @param res TODO
275 * @param prev TODO
276 * @return TODO.
Myles Watsonc25cc112010-05-21 14:33:48 +0000277 */
Aaron Durbinf0349022017-11-10 10:47:54 -0700278static void free_resource(struct device *dev, struct resource *res,
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000279 struct resource *prev)
Myles Watsonc25cc112010-05-21 14:33:48 +0000280{
281 if (prev)
282 prev->next = res->next;
283 else
284 dev->resource_list = res->next;
Uwe Hermanne4870472010-11-04 23:23:47 +0000285
Myles Watsonc25cc112010-05-21 14:33:48 +0000286 res->next = free_resources;
287 free_resources = res;
288}
289
290/**
Eric Biederman5cd81732004-03-11 15:01:31 +0000291 * See if we have unused but allocated resource structures.
Uwe Hermanne4870472010-11-04 23:23:47 +0000292 *
Eric Biederman5cd81732004-03-11 15:01:31 +0000293 * If so remove the allocation.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000294 *
295 * @param dev The device to find the resource on.
Eric Biederman5cd81732004-03-11 15:01:31 +0000296 */
Aaron Durbinf0349022017-11-10 10:47:54 -0700297void compact_resources(struct device *dev)
Eric Biederman5cd81732004-03-11 15:01:31 +0000298{
Myles Watsonc25cc112010-05-21 14:33:48 +0000299 struct resource *res, *next, *prev = NULL;
Uwe Hermanne4870472010-11-04 23:23:47 +0000300
Eric Biederman5cd81732004-03-11 15:01:31 +0000301 /* Move all of the free resources to the end */
Myles Watson894a3472010-06-09 22:41:35 +0000302 for (res = dev->resource_list; res; res = next) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000303 next = res->next;
304 if (!res->flags)
305 free_resource(dev, res, prev);
306 else
307 prev = res;
Eric Biederman5cd81732004-03-11 15:01:31 +0000308 }
309}
310
311/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000312 * See if a resource structure already exists for a given index.
313 *
314 * @param dev The device to find the resource on.
315 * @param index The index of the resource on the device.
316 * @return The resource, if it already exists.
Eric Biederman5cd81732004-03-11 15:01:31 +0000317 */
Martin Roth38ddbfb2019-10-23 21:41:00 -0600318struct resource *probe_resource(const struct device *dev, unsigned int index)
Eric Biederman5cd81732004-03-11 15:01:31 +0000319{
Myles Watsonc25cc112010-05-21 14:33:48 +0000320 struct resource *res;
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000321
Eric Biederman5cd81732004-03-11 15:01:31 +0000322 /* See if there is a resource with the appropriate index */
Myles Watson894a3472010-06-09 22:41:35 +0000323 for (res = dev->resource_list; res; res = res->next) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000324 if (res->index == index)
Eric Biederman5cd81732004-03-11 15:01:31 +0000325 break;
Eric Biederman5cd81732004-03-11 15:01:31 +0000326 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000327
Myles Watsonc25cc112010-05-21 14:33:48 +0000328 return res;
Eric Biederman03acab62004-10-14 21:25:53 +0000329}
330
331/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000332 * See if a resource structure already exists for a given index and if not
333 * allocate one.
334 *
Paul Menzel20923872014-06-07 13:31:29 +0200335 * Then initialize the resource to default values.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000336 *
337 * @param dev The device to find the resource on.
338 * @param index The index of the resource on the device.
339 * @return TODO.
Eric Biederman03acab62004-10-14 21:25:53 +0000340 */
Martin Roth38ddbfb2019-10-23 21:41:00 -0600341struct resource *new_resource(struct device *dev, unsigned int index)
Eric Biederman03acab62004-10-14 21:25:53 +0000342{
Myles Watsonc25cc112010-05-21 14:33:48 +0000343 struct resource *resource, *tail;
Eric Biederman03acab62004-10-14 21:25:53 +0000344
Uwe Hermanne4870472010-11-04 23:23:47 +0000345 /* First move all of the free resources to the end. */
Eric Biederman03acab62004-10-14 21:25:53 +0000346 compact_resources(dev);
347
Uwe Hermanne4870472010-11-04 23:23:47 +0000348 /* See if there is a resource with the appropriate index. */
Eric Biederman03acab62004-10-14 21:25:53 +0000349 resource = probe_resource(dev, index);
Eric Biederman5cd81732004-03-11 15:01:31 +0000350 if (!resource) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000351 if (free_resources == NULL && !allocate_more_resources())
352 die("Couldn't allocate more resources.");
353
354 resource = free_resources;
355 free_resources = free_resources->next;
Eric Biederman5cd81732004-03-11 15:01:31 +0000356 memset(resource, 0, sizeof(*resource));
Myles Watsonc25cc112010-05-21 14:33:48 +0000357 resource->next = NULL;
358 tail = dev->resource_list;
359 if (tail) {
360 while (tail->next) tail = tail->next;
361 tail->next = resource;
Uwe Hermanne4870472010-11-04 23:23:47 +0000362 } else {
Myles Watsonc25cc112010-05-21 14:33:48 +0000363 dev->resource_list = resource;
Uwe Hermanne4870472010-11-04 23:23:47 +0000364 }
Eric Biederman5cd81732004-03-11 15:01:31 +0000365 }
Uwe Hermanne4870472010-11-04 23:23:47 +0000366
367 /* Initialize the resource values. */
Eric Biederman5cd81732004-03-11 15:01:31 +0000368 if (!(resource->flags & IORESOURCE_FIXED)) {
369 resource->flags = 0;
370 resource->base = 0;
371 }
372 resource->size = 0;
373 resource->limit = 0;
374 resource->index = index;
375 resource->align = 0;
376 resource->gran = 0;
377
378 return resource;
379}
380
Eric Biederman03acab62004-10-14 21:25:53 +0000381/**
382 * Return an existing resource structure for a given index.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000383 *
384 * @param dev The device to find the resource on.
385 * @param index The index of the resource on the device.
386 * return TODO.
Eric Biederman03acab62004-10-14 21:25:53 +0000387 */
Martin Roth38ddbfb2019-10-23 21:41:00 -0600388struct resource *find_resource(const struct device *dev, unsigned int index)
Eric Biederman03acab62004-10-14 21:25:53 +0000389{
390 struct resource *resource;
391
Uwe Hermanne4870472010-11-04 23:23:47 +0000392 /* See if there is a resource with the appropriate index. */
Eric Biederman03acab62004-10-14 21:25:53 +0000393 resource = probe_resource(dev, index);
394 if (!resource) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000395 printk(BIOS_EMERG, "%s missing resource: %02x\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000396 dev_path(dev), index);
Eric Biederman03acab62004-10-14 21:25:53 +0000397 die("");
398 }
399 return resource;
400}
401
Eric Biederman03acab62004-10-14 21:25:53 +0000402/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000403 * Round a number up to the next multiple of gran.
404 *
405 * @param val The starting value.
406 * @param gran Granularity we are aligning the number to.
407 * @return The aligned value.
Eric Biederman03acab62004-10-14 21:25:53 +0000408 */
409static resource_t align_up(resource_t val, unsigned long gran)
410{
411 resource_t mask;
412 mask = (1ULL << gran) - 1ULL;
413 val += mask;
414 val &= ~mask;
415 return val;
416}
417
418/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000419 * Round a number up to the previous multiple of gran.
420 *
421 * @param val The starting value.
422 * @param gran Granularity we are aligning the number to.
423 * @return The aligned value.
Eric Biederman03acab62004-10-14 21:25:53 +0000424 */
425static resource_t align_down(resource_t val, unsigned long gran)
426{
427 resource_t mask;
428 mask = (1ULL << gran) - 1ULL;
429 val &= ~mask;
430 return val;
431}
432
433/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000434 * Compute the maximum address that is part of a resource.
435 *
436 * @param resource The resource whose limit is desired.
437 * @return The end.
Eric Biederman03acab62004-10-14 21:25:53 +0000438 */
439resource_t resource_end(struct resource *resource)
440{
441 resource_t base, end;
Uwe Hermanne4870472010-11-04 23:23:47 +0000442
443 /* Get the base address. */
Eric Biederman03acab62004-10-14 21:25:53 +0000444 base = resource->base;
445
Uwe Hermanne4870472010-11-04 23:23:47 +0000446 /*
447 * For a non bridge resource granularity and alignment are the same.
Eric Biederman03acab62004-10-14 21:25:53 +0000448 * For a bridge resource align is the largest needed alignment below
Uwe Hermanne4870472010-11-04 23:23:47 +0000449 * the bridge. While the granularity is simply how many low bits of
450 * the address cannot be set.
Eric Biederman03acab62004-10-14 21:25:53 +0000451 */
Stefan Reinauer14e22772010-04-27 06:56:47 +0000452
Uwe Hermanne4870472010-11-04 23:23:47 +0000453 /* Get the end (rounded up). */
Eric Biederman03acab62004-10-14 21:25:53 +0000454 end = base + align_up(resource->size, resource->gran) - 1;
455
456 return end;
457}
458
459/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000460 * Compute the maximum legal value for resource->base.
461 *
462 * @param resource The resource whose maximum is desired.
463 * @return The maximum.
Eric Biederman03acab62004-10-14 21:25:53 +0000464 */
465resource_t resource_max(struct resource *resource)
466{
467 resource_t max;
468
469 max = align_down(resource->limit - resource->size + 1, resource->align);
470
471 return max;
472}
473
474/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000475 * Return the resource type of a resource.
476 *
477 * @param resource The resource type to decode.
478 * @return TODO.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000479 */
480const char *resource_type(struct resource *resource)
481{
482 static char buffer[RESOURCE_TYPE_MAX];
Elyes HAOUASb7482212018-05-16 12:58:19 +0200483 snprintf(buffer, sizeof(buffer), "%s%s%s%s",
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100484 ((resource->flags & IORESOURCE_READONLY) ? "ro" : ""),
485 ((resource->flags & IORESOURCE_PREFETCH) ? "pref" : ""),
486 ((resource->flags == 0) ? "unused" :
487 (resource->flags & IORESOURCE_IO) ? "io" :
488 (resource->flags & IORESOURCE_DRQ) ? "drq" :
489 (resource->flags & IORESOURCE_IRQ) ? "irq" :
490 (resource->flags & IORESOURCE_MEM) ? "mem" : "??????"),
491 ((resource->flags & IORESOURCE_PCI64) ? "64" : ""));
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000492 return buffer;
493}
494
495/**
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000496 * Print the resource that was just stored.
497 *
Martin Roth63373ed2013-07-08 16:24:19 -0600498 * @param dev The device the stored resource lives on.
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000499 * @param resource The resource that was just stored.
500 * @param comment TODO
Eric Biederman03acab62004-10-14 21:25:53 +0000501 */
Aaron Durbinf0349022017-11-10 10:47:54 -0700502void report_resource_stored(struct device *dev, struct resource *resource,
Uwe Hermannc1ee4292010-10-17 19:01:48 +0000503 const char *comment)
Eric Biederman03acab62004-10-14 21:25:53 +0000504{
Uwe Hermanne4870472010-11-04 23:23:47 +0000505 char buf[10];
506 unsigned long long base, end;
507
508 if (!(resource->flags & IORESOURCE_STORED))
509 return;
510
511 base = resource->base;
512 end = resource_end(resource);
513 buf[0] = '\0';
514
515 if (resource->flags & IORESOURCE_PCI_BRIDGE) {
Elyes HAOUASb7482212018-05-16 12:58:19 +0200516 snprintf(buf, sizeof(buf),
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100517 "bus %02x ", dev->link_list->secondary);
Eric Biederman03acab62004-10-14 21:25:53 +0000518 }
Patrick Georgi51615092012-03-11 19:31:03 +0100519 printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] size 0x%08llx "
Uwe Hermanne4870472010-11-04 23:23:47 +0000520 "gran 0x%02x %s%s%s\n", dev_path(dev), resource->index,
521 base, end, resource->size, resource->gran, buf,
522 resource_type(resource), comment);
Eric Biederman03acab62004-10-14 21:25:53 +0000523}
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000524
Uwe Hermanne4870472010-11-04 23:23:47 +0000525void search_bus_resources(struct bus *bus, unsigned long type_mask,
526 unsigned long type, resource_search_t search,
527 void *gp)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000528{
529 struct device *curdev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000530
Myles Watson894a3472010-06-09 22:41:35 +0000531 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000532 struct resource *res;
Uwe Hermanne4870472010-11-04 23:23:47 +0000533
534 /* Ignore disabled devices. */
535 if (!curdev->enabled)
536 continue;
537
Myles Watson894a3472010-06-09 22:41:35 +0000538 for (res = curdev->resource_list; res; res = res->next) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000539 /* If it isn't the right kind of resource ignore it. */
540 if ((res->flags & type_mask) != type)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000541 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000542
543 /* If it is a subtractive resource recurse. */
Myles Watsonc25cc112010-05-21 14:33:48 +0000544 if (res->flags & IORESOURCE_SUBTRACTIVE) {
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000545 struct bus * subbus;
Uwe Hermanne4870472010-11-04 23:23:47 +0000546 for (subbus = curdev->link_list; subbus;
547 subbus = subbus->next)
548 if (subbus->link_num
549 == IOINDEX_SUBTRACTIVE_LINK(res->index))
Myles Watson894a3472010-06-09 22:41:35 +0000550 break;
Stefan Reinauer58075552011-05-11 15:57:07 -0700551 if (!subbus) /* Why can subbus be NULL? */
552 break;
Uwe Hermanne4870472010-11-04 23:23:47 +0000553 search_bus_resources(subbus, type_mask, type,
554 search, gp);
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000555 continue;
556 }
Myles Watsonc25cc112010-05-21 14:33:48 +0000557 search(gp, curdev, res);
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000558 }
559 }
560}
561
Uwe Hermanne4870472010-11-04 23:23:47 +0000562void search_global_resources(unsigned long type_mask, unsigned long type,
563 resource_search_t search, void *gp)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000564{
565 struct device *curdev;
Uwe Hermanne4870472010-11-04 23:23:47 +0000566
Myles Watson894a3472010-06-09 22:41:35 +0000567 for (curdev = all_devices; curdev; curdev = curdev->next) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000568 struct resource *res;
Uwe Hermanne4870472010-11-04 23:23:47 +0000569
570 /* Ignore disabled devices. */
571 if (!curdev->enabled)
572 continue;
573
Myles Watson894a3472010-06-09 22:41:35 +0000574 for (res = curdev->resource_list; res; res = res->next) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000575 /* If it isn't the right kind of resource ignore it. */
576 if ((res->flags & type_mask) != type)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000577 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000578
579 /* If it is a subtractive resource ignore it. */
580 if (res->flags & IORESOURCE_SUBTRACTIVE)
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000581 continue;
Uwe Hermanne4870472010-11-04 23:23:47 +0000582
Myles Watsonc25cc112010-05-21 14:33:48 +0000583 search(gp, curdev, res);
Eric Biedermanf8a2ddd2004-10-30 08:05:41 +0000584 }
585 }
586}
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000587
Aaron Durbinf0349022017-11-10 10:47:54 -0700588void dev_set_enabled(struct device *dev, int enable)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000589{
Uwe Hermanne4870472010-11-04 23:23:47 +0000590 if (dev->enabled == enable)
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000591 return;
Uwe Hermanne4870472010-11-04 23:23:47 +0000592
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000593 dev->enabled = enable;
594 if (dev->ops && dev->ops->enable) {
595 dev->ops->enable(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000596 } else if (dev->chip_ops && dev->chip_ops->enable_dev) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000597 dev->chip_ops->enable_dev(dev);
598 }
599}
600
601void disable_children(struct bus *bus)
602{
Aaron Durbinf0349022017-11-10 10:47:54 -0700603 struct device *child;
Uwe Hermanne4870472010-11-04 23:23:47 +0000604
Myles Watson894a3472010-06-09 22:41:35 +0000605 for (child = bus->children; child; child = child->sibling) {
606 struct bus *link;
Uwe Hermanne4870472010-11-04 23:23:47 +0000607 for (link = child->link_list; link; link = link->next)
Myles Watson894a3472010-06-09 22:41:35 +0000608 disable_children(link);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000609 dev_set_enabled(child, 0);
610 }
611}
Myles Watsonbb3d8122009-05-11 22:45:35 +0000612
Patrick Rudolpha6909f82017-05-22 18:30:27 +0200613/*
614 * Returns true if the device is an enabled bridge that has at least
Patrick Rudolphbd7739f2019-04-24 09:35:51 +0200615 * one enabled device on its secondary bus that is not of type NONE.
Patrick Rudolpha6909f82017-05-22 18:30:27 +0200616 */
Aaron Durbinf0349022017-11-10 10:47:54 -0700617bool dev_is_active_bridge(struct device *dev)
Patrick Rudolpha6909f82017-05-22 18:30:27 +0200618{
619 struct bus *link;
Aaron Durbinf0349022017-11-10 10:47:54 -0700620 struct device *child;
Patrick Rudolpha6909f82017-05-22 18:30:27 +0200621
622 if (!dev || !dev->enabled)
623 return 0;
624
625 if (!dev->link_list || !dev->link_list->children)
626 return 0;
627
628 for (link = dev->link_list; link; link = link->next) {
629 for (child = link->children; child; child = child->sibling) {
Patrick Rudolphbd7739f2019-04-24 09:35:51 +0200630 if (child->path.type == DEVICE_PATH_NONE)
631 continue;
632
Patrick Rudolpha6909f82017-05-22 18:30:27 +0200633 if (child->enabled)
634 return 1;
635 }
636 }
637
638 return 0;
639}
640
Jacob Garber464f4d62019-06-05 17:03:30 -0600641/**
642 * Ensure the device has a minimum number of bus links.
643 *
644 * @param dev The device to add links to.
645 * @param total_links The minimum number of links to have.
646 */
647void add_more_links(struct device *dev, unsigned int total_links)
Jacob Garberf77f7cd2019-06-05 16:32:28 -0600648{
649 struct bus *link, *last = NULL;
650 int link_num = -1;
651
652 for (link = dev->link_list; link; link = link->next) {
653 if (link_num < link->link_num)
654 link_num = link->link_num;
655 last = link;
656 }
657
658 if (last) {
659 int links = total_links - (link_num + 1);
660 if (links > 0) {
Jacob Garber464f4d62019-06-05 17:03:30 -0600661 link = malloc(links * sizeof(*link));
Jacob Garberf77f7cd2019-06-05 16:32:28 -0600662 if (!link)
663 die("Couldn't allocate more links!\n");
Jacob Garber464f4d62019-06-05 17:03:30 -0600664 memset(link, 0, links * sizeof(*link));
Jacob Garberf77f7cd2019-06-05 16:32:28 -0600665 last->next = link;
Jacob Garber464f4d62019-06-05 17:03:30 -0600666 } else {
667 /* No more links to add */
668 return;
Jacob Garberf77f7cd2019-06-05 16:32:28 -0600669 }
670 } else {
Jacob Garber464f4d62019-06-05 17:03:30 -0600671 link = malloc(total_links * sizeof(*link));
672 if (!link)
673 die("Couldn't allocate more links!\n");
674 memset(link, 0, total_links * sizeof(*link));
Jacob Garberf77f7cd2019-06-05 16:32:28 -0600675 dev->link_list = link;
676 }
677
678 for (link_num = link_num + 1; link_num < total_links; link_num++) {
679 link->link_num = link_num;
680 link->dev = dev;
681 link->next = link + 1;
682 last = link;
683 link = link->next;
684 }
685 last->next = NULL;
686}
687
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +0200688static void resource_tree(const struct device *root, int debug_level, int depth)
Myles Watsonbb3d8122009-05-11 22:45:35 +0000689{
Myles Watson894a3472010-06-09 22:41:35 +0000690 int i = 0;
Myles Watsonbb3d8122009-05-11 22:45:35 +0000691 struct device *child;
Myles Watson894a3472010-06-09 22:41:35 +0000692 struct bus *link;
Myles Watsonc25cc112010-05-21 14:33:48 +0000693 struct resource *res;
Myles Watsonbb3d8122009-05-11 22:45:35 +0000694 char indent[30]; /* If your tree has more levels, it's wrong. */
695
696 for (i = 0; i < depth + 1 && i < 29; i++)
697 indent[i] = ' ';
698 indent[i] = '\0';
699
Martin Roth7f35d3a2017-07-23 16:22:25 -0600700 do_printk(BIOS_DEBUG, "%s%s", indent, dev_path(root));
701 if (root->link_list && root->link_list->children)
702 do_printk(BIOS_DEBUG, " child on link 0 %s",
703 dev_path(root->link_list->children));
704 do_printk(BIOS_DEBUG, "\n");
Myles Watson894a3472010-06-09 22:41:35 +0000705
Myles Watsonc25cc112010-05-21 14:33:48 +0000706 for (res = root->resource_list; res; res = res->next) {
Uwe Hermanne4870472010-11-04 23:23:47 +0000707 do_printk(debug_level, "%s%s resource base %llx size %llx "
708 "align %d gran %d limit %llx flags %lx index %lx\n",
709 indent, dev_path(root), res->base, res->size,
710 res->align, res->gran, res->limit, res->flags,
711 res->index);
Myles Watsonbb3d8122009-05-11 22:45:35 +0000712 }
713
Myles Watson894a3472010-06-09 22:41:35 +0000714 for (link = root->link_list; link; link = link->next) {
715 for (child = link->children; child; child = child->sibling)
Myles Watsonbb3d8122009-05-11 22:45:35 +0000716 resource_tree(child, debug_level, depth + 1);
717 }
718}
719
Elyes HAOUASe3480662018-05-06 20:32:23 +0200720void print_resource_tree(const struct device *root, int debug_level,
721 const char *msg)
Myles Watsonbb3d8122009-05-11 22:45:35 +0000722{
723 /* Bail if root is null. */
724 if (!root) {
725 do_printk(debug_level, "%s passed NULL for root!\n", __func__);
726 return;
727 }
728
729 /* Bail if not printing to screen. */
730 if (!do_printk(debug_level, "Show resources in subtree (%s)...%s\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000731 dev_path(root), msg))
Myles Watsonbb3d8122009-05-11 22:45:35 +0000732 return;
Uwe Hermanne4870472010-11-04 23:23:47 +0000733
Myles Watsonbb3d8122009-05-11 22:45:35 +0000734 resource_tree(root, debug_level, 0);
735}
736
Lubomir Rintel9ba8f7c2018-04-26 00:00:22 +0200737void show_devs_tree(const struct device *dev, int debug_level, int depth)
Myles Watsonbb3d8122009-05-11 22:45:35 +0000738{
Marcelo Povoa8404dca2014-02-14 15:42:49 -0800739 char depth_str[20];
Myles Watsonbb3d8122009-05-11 22:45:35 +0000740 int i;
741 struct device *sibling;
Myles Watson894a3472010-06-09 22:41:35 +0000742 struct bus *link;
743
Myles Watsonbb3d8122009-05-11 22:45:35 +0000744 for (i = 0; i < depth; i++)
745 depth_str[i] = ' ';
746 depth_str[i] = '\0';
Uwe Hermanne4870472010-11-04 23:23:47 +0000747
Myles Watsonc25cc112010-05-21 14:33:48 +0000748 do_printk(debug_level, "%s%s: enabled %d\n",
749 depth_str, dev_path(dev), dev->enabled);
Uwe Hermanne4870472010-11-04 23:23:47 +0000750
Myles Watson894a3472010-06-09 22:41:35 +0000751 for (link = dev->link_list; link; link = link->next) {
752 for (sibling = link->children; sibling;
Myles Watsonbb3d8122009-05-11 22:45:35 +0000753 sibling = sibling->sibling)
Kyösti Mälkki3d3c8c32016-08-15 10:04:21 +0300754 show_devs_tree(sibling, debug_level, depth + 1);
Myles Watsonbb3d8122009-05-11 22:45:35 +0000755 }
756}
757
758void show_all_devs_tree(int debug_level, const char *msg)
759{
760 /* Bail if not printing to screen. */
Paul Menzeleb605d72015-02-12 00:29:32 +0100761 if (!do_printk(debug_level, "Show all devs in tree form... %s\n", msg))
Myles Watsonbb3d8122009-05-11 22:45:35 +0000762 return;
Kyösti Mälkki3d3c8c32016-08-15 10:04:21 +0300763 show_devs_tree(all_devices, debug_level, 0);
Myles Watsonbb3d8122009-05-11 22:45:35 +0000764}
765
766void show_devs_subtree(struct device *root, int debug_level, const char *msg)
767{
768 /* Bail if not printing to screen. */
Paul Menzeleb605d72015-02-12 00:29:32 +0100769 if (!do_printk(debug_level, "Show all devs in subtree %s... %s\n",
Uwe Hermanne4870472010-11-04 23:23:47 +0000770 dev_path(root), msg))
Myles Watsonbb3d8122009-05-11 22:45:35 +0000771 return;
772 do_printk(debug_level, "%s\n", msg);
Kyösti Mälkki3d3c8c32016-08-15 10:04:21 +0300773 show_devs_tree(root, debug_level, 0);
Myles Watsonbb3d8122009-05-11 22:45:35 +0000774}
775
776void show_all_devs(int debug_level, const char *msg)
777{
778 struct device *dev;
779
780 /* Bail if not printing to screen. */
Paul Menzeleb605d72015-02-12 00:29:32 +0100781 if (!do_printk(debug_level, "Show all devs... %s\n", msg))
Myles Watsonbb3d8122009-05-11 22:45:35 +0000782 return;
783 for (dev = all_devices; dev; dev = dev->next) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000784 do_printk(debug_level, "%s: enabled %d\n",
785 dev_path(dev), dev->enabled);
Myles Watsonbb3d8122009-05-11 22:45:35 +0000786 }
787}
788
789void show_one_resource(int debug_level, struct device *dev,
790 struct resource *resource, const char *comment)
791{
792 char buf[10];
793 unsigned long long base, end;
794 base = resource->base;
795 end = resource_end(resource);
796 buf[0] = '\0';
Uwe Hermanne4870472010-11-04 23:23:47 +0000797
Uwe Hermanne4870472010-11-04 23:23:47 +0000798 do_printk(debug_level, "%s %02lx <- [0x%010llx - 0x%010llx] "
Patrick Georgi51615092012-03-11 19:31:03 +0100799 "size 0x%08llx gran 0x%02x %s%s%s\n", dev_path(dev),
Uwe Hermanne4870472010-11-04 23:23:47 +0000800 resource->index, base, end, resource->size, resource->gran,
801 buf, resource_type(resource), comment);
Myles Watsonbb3d8122009-05-11 22:45:35 +0000802}
803
804void show_all_devs_resources(int debug_level, const char* msg)
805{
806 struct device *dev;
807
Paul Menzeleb605d72015-02-12 00:29:32 +0100808 if (!do_printk(debug_level, "Show all devs with resources... %s\n", msg))
Myles Watsonbb3d8122009-05-11 22:45:35 +0000809 return;
810
811 for (dev = all_devices; dev; dev = dev->next) {
Myles Watsonc25cc112010-05-21 14:33:48 +0000812 struct resource *res;
813 do_printk(debug_level, "%s: enabled %d\n",
814 dev_path(dev), dev->enabled);
815 for (res = dev->resource_list; res; res = res->next)
816 show_one_resource(debug_level, dev, res, "");
Myles Watsonbb3d8122009-05-11 22:45:35 +0000817 }
818}
Uwe Hermann4b42a622010-10-11 19:36:13 +0000819
Aaron Durbinf0349022017-11-10 10:47:54 -0700820void fixed_mem_resource(struct device *dev, unsigned long index,
Elyes HAOUASe3480662018-05-06 20:32:23 +0200821 unsigned long basek, unsigned long sizek,
822 unsigned long type)
Uwe Hermann4b42a622010-10-11 19:36:13 +0000823{
824 struct resource *resource;
825
826 if (!sizek)
827 return;
828
829 resource = new_resource(dev, index);
830 resource->base = ((resource_t)basek) << 10;
831 resource->size = ((resource_t)sizek) << 10;
Kyösti Mälkkiecf1ed42012-07-27 08:37:12 +0300832 resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
833 IORESOURCE_STORED | IORESOURCE_ASSIGNED;
Uwe Hermann4b42a622010-10-11 19:36:13 +0000834
Kyösti Mälkkiecf1ed42012-07-27 08:37:12 +0300835 resource->flags |= type;
Kyösti Mälkki63f8c082012-07-10 13:27:26 +0300836}
837
Subrata Banik217ca362019-03-15 17:18:44 +0530838void fixed_io_resource(struct device *dev, unsigned long index,
839 unsigned long base, unsigned long size)
840{
841 struct resource *resource;
842
843 resource = new_resource(dev, index);
844 resource->base = (resource_t)base;
845 resource->size = (resource_t)size;
846 resource->limit = resource->base + resource->size - 1;
847 resource->flags = IORESOURCE_IO | IORESOURCE_FIXED |
848 IORESOURCE_STORED | IORESOURCE_ASSIGNED |
849 IORESOURCE_RESERVE;
850}
851
Kyösti Mälkkie25b5ef2016-12-02 08:56:05 +0200852void mmconf_resource_init(struct resource *resource, resource_t base,
853 int buses)
854{
855 resource->base = base;
856 resource->size = buses * MiB;
857 resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
858 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
859
860 printk(BIOS_DEBUG, "Adding PCIe enhanced config space BAR "
861 "0x%08lx-0x%08lx.\n", (unsigned long)(resource->base),
862 (unsigned long)(resource->base + resource->size));
863}
864
865void mmconf_resource(struct device *dev, unsigned long index)
866{
867 struct resource *resource = new_resource(dev, index);
868 mmconf_resource_init(resource, CONFIG_MMCONF_BASE_ADDRESS,
869 CONFIG_MMCONF_BUS_NUMBER);
870}
871
Uwe Hermann4b42a622010-10-11 19:36:13 +0000872void tolm_test(void *gp, struct device *dev, struct resource *new)
873{
874 struct resource **best_p = gp;
875 struct resource *best;
876
877 best = *best_p;
878
879 if (!best || (best->base > new->base))
880 best = new;
881
882 *best_p = best;
883}
884
885u32 find_pci_tolm(struct bus *bus)
886{
887 struct resource *min = NULL;
888 u32 tolm;
889
890 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM,
891 tolm_test, &min);
892
893 tolm = 0xffffffffUL;
894
895 if (min && tolm > min->base)
896 tolm = min->base;
897
898 return tolm;
899}
Stefan Reinauerdc8448fd2012-03-30 13:52:58 -0700900
901/* Count of enabled CPUs */
902int dev_count_cpu(void)
903{
Aaron Durbinf0349022017-11-10 10:47:54 -0700904 struct device *cpu;
Stefan Reinauerdc8448fd2012-03-30 13:52:58 -0700905 int count = 0;
906
907 for (cpu = all_devices; cpu; cpu = cpu->next) {
908 if ((cpu->path.type != DEVICE_PATH_APIC) ||
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800909 (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER))
Stefan Reinauerdc8448fd2012-03-30 13:52:58 -0700910 continue;
911 if (!cpu->enabled)
912 continue;
913 count++;
914 }
915
916 return count;
917}
Lee Leahya95baf92016-02-13 06:10:04 -0800918
919/* Get device path name */
920const char *dev_path_name(enum device_path_type type)
921{
922 static const char *const type_names[] = DEVICE_PATH_NAMES;
923 const char *type_name = "Unknown";
924
925 /* Translate the type value into a string */
926 if (type < ARRAY_SIZE(type_names))
927 type_name = type_names[type];
928 return type_name;
929}