blob: 003a03f3168792624db7a8fd74d35109d888600f [file] [log] [blame]
Marc Jones1f500842020-10-15 14:32:51 -06001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <assert.h>
4#include <console/console.h>
5#include <post.h>
6#include <device/pci.h>
7#include <soc/chip_common.h>
8#include <soc/soc_util.h>
9#include <soc/util.h>
10#include <stdlib.h>
11
Arthur Heymans550f55e2022-08-24 14:44:26 +020012static const STACK_RES *domain_to_stack_res(const struct device *dev)
Marc Jones1f500842020-10-15 14:32:51 -060013{
Arthur Heymans550f55e2022-08-24 14:44:26 +020014 assert(dev->path.type == DEVICE_PATH_DOMAIN);
15 const unsigned int dn = dev->path.domain.domain;
16
17 const IIO_UDS *hob = get_iio_uds();
18 assert(hob != NULL);
19
20 return &hob->PlatformData.IIO_resource[dn / MAX_LOGIC_IIO_STACK].StackRes[dn % MAX_LOGIC_IIO_STACK];
Marc Jones1f500842020-10-15 14:32:51 -060021}
22
Arthur Heymans550f55e2022-08-24 14:44:26 +020023void iio_pci_domain_read_resources(struct device *dev)
Marc Jones1f500842020-10-15 14:32:51 -060024{
25 struct resource *res;
Arthur Heymans550f55e2022-08-24 14:44:26 +020026 const STACK_RES *sr = domain_to_stack_res(dev);
27
28 if (!sr)
Marc Jones1f500842020-10-15 14:32:51 -060029 return;
30
Arthur Heymans550f55e2022-08-24 14:44:26 +020031 int index = 0;
Marc Jones1f500842020-10-15 14:32:51 -060032
Arthur Heymans550f55e2022-08-24 14:44:26 +020033 if (dev->path.domain.domain == 0) {
34 /* The 0 - 0xfff IO range is not reported by the HOB but still gets decoded */
35 res = new_resource(dev, index++);
36 res->base = 0;
37 res->size = 0x1000;
38 res->limit = 0xfff;
39 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
40 }
Marc Jones1f500842020-10-15 14:32:51 -060041
Arthur Heymans550f55e2022-08-24 14:44:26 +020042 if (sr->PciResourceIoBase < sr->PciResourceIoLimit) {
43 res = new_resource(dev, index++);
44 res->base = sr->PciResourceIoBase;
45 res->limit = sr->PciResourceIoLimit;
46 res->size = res->limit - res->base + 1;
47 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED;
48 }
Marc Jones1f500842020-10-15 14:32:51 -060049
Arthur Heymans550f55e2022-08-24 14:44:26 +020050 if (sr->PciResourceMem32Base < sr->PciResourceMem32Limit) {
51 res = new_resource(dev, index++);
52 res->base = sr->PciResourceMem32Base;
53 res->limit = sr->PciResourceMem32Limit;
54 res->size = res->limit - res->base + 1;
55 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
56 }
57
58 if (sr->PciResourceMem64Base < sr->PciResourceMem64Limit) {
59 res = new_resource(dev, index++);
60 res->base = sr->PciResourceMem64Base;
61 res->limit = sr->PciResourceMem64Limit;
62 res->size = res->limit - res->base + 1;
63 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
Marc Jones1f500842020-10-15 14:32:51 -060064 }
65}
66
Arthur Heymans550f55e2022-08-24 14:44:26 +020067void iio_pci_domain_scan_bus(struct device *dev)
Marc Jones1f500842020-10-15 14:32:51 -060068{
Arthur Heymans550f55e2022-08-24 14:44:26 +020069 const STACK_RES *sr = domain_to_stack_res(dev);
70 if (!sr)
71 return;
Marc Jones1f500842020-10-15 14:32:51 -060072
Arthur Heymans550f55e2022-08-24 14:44:26 +020073 if (!dev->link_list) {
74 dev->link_list = calloc(1, sizeof(struct bus));
75 if (!dev->link_list)
76 die("%s: out of memory.\n", __func__);
Marc Jones1f500842020-10-15 14:32:51 -060077 }
Arthur Heymans550f55e2022-08-24 14:44:26 +020078
79 struct bus *bus = dev->link_list;
Patrick Rudolphee0a2f92024-01-19 08:27:13 +010080 bus->dev = dev;
Arthur Heymans550f55e2022-08-24 14:44:26 +020081 bus->secondary = sr->BusBase;
82 bus->subordinate = sr->BusBase;
83 bus->max_subordinate = sr->BusLimit;
84
85 printk(BIOS_SPEW, "Scanning IIO stack %d: busses %x-%x\n", dev->path.domain.domain,
86 dev->link_list->secondary, dev->link_list->max_subordinate);
87 pci_host_bridge_scan_bus(dev);
Marc Jones1f500842020-10-15 14:32:51 -060088}
89
Jonathan Zhanga63ea892023-01-25 11:16:58 -080090/*
Arthur Heymans550f55e2022-08-24 14:44:26 +020091 * Used by IIO stacks for PCIe bridges. Those contain 1 PCI host bridges,
92 * all the bus numbers on the IIO stack can be used for this bridge
Jonathan Zhanga63ea892023-01-25 11:16:58 -080093 */
Arthur Heymans550f55e2022-08-24 14:44:26 +020094static struct device_operations iio_pcie_domain_ops = {
95 .read_resources = iio_pci_domain_read_resources,
96 .set_resources = pci_domain_set_resources,
97 .scan_bus = iio_pci_domain_scan_bus,
98};
Arthur Heymans165893b2020-11-06 12:15:41 +010099
Arthur Heymans550f55e2022-08-24 14:44:26 +0200100/* Attach IIO stack as domains */
Marc Jones1f500842020-10-15 14:32:51 -0600101void attach_iio_stacks(struct device *dev)
102{
Arthur Heymans550f55e2022-08-24 14:44:26 +0200103 const IIO_UDS *hob = get_iio_uds();
104 if (!hob)
105 return;
Marc Jones1f500842020-10-15 14:32:51 -0600106
Arthur Heymans550f55e2022-08-24 14:44:26 +0200107 for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
108 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
109 if (s == 0 && x == 0)
110 continue;
Marc Jones1f500842020-10-15 14:32:51 -0600111
Arthur Heymans550f55e2022-08-24 14:44:26 +0200112 const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
Arthur Heymans470f1d32023-08-31 18:19:09 +0200113 if (ri->BusBase > ri->BusLimit)
Arthur Heymans550f55e2022-08-24 14:44:26 +0200114 continue;
Jonathan Zhang532e8c02023-01-25 11:28:49 -0800115
Arthur Heymans550f55e2022-08-24 14:44:26 +0200116 if (!is_pcie_iio_stack_res(ri)) {
117 if (CONFIG(HAVE_IOAT_DOMAINS))
118 soc_create_ioat_domains(dev->bus, ri);
Jonathan Zhang532e8c02023-01-25 11:28:49 -0800119 continue;
120 }
121
Arthur Heymans550f55e2022-08-24 14:44:26 +0200122 struct device_path path;
123 path.type = DEVICE_PATH_DOMAIN;
124 path.domain.domain = s * MAX_LOGIC_IIO_STACK + x;
125 struct device *iio_domain = alloc_dev(dev->bus, &path);
126 if (iio_domain == NULL)
Jonathan Zhang532e8c02023-01-25 11:28:49 -0800127 die("%s: out of memory.\n", __func__);
Arthur Heymans550f55e2022-08-24 14:44:26 +0200128 iio_domain->ops = &iio_pcie_domain_ops;
Marc Jones1f500842020-10-15 14:32:51 -0600129 }
130 }
Marc Jones1f500842020-10-15 14:32:51 -0600131}