blob: 9ed9576ef3694813026ebf27aac3c6de286f3eb5 [file] [log] [blame]
Arthur Heymans550f55e2022-08-24 14:44:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Patrick Rudolphe357ac32024-02-23 09:47:24 +01002#include <acpi/acpigen_pci.h>
Arthur Heymans550f55e2022-08-24 14:44:26 +02003#include <stdbool.h>
4
5#include <console/console.h>
6#include <device/device.h>
Arthur Heymans550f55e2022-08-24 14:44:26 +02007
8#include <defs_iio.h>
9#include <hob_iiouds.h>
Patrick Rudolph40e07482024-02-23 09:23:41 +010010#include <intelblocks/acpi.h>
11#include <soc/acpi.h>
Arthur Heymans550f55e2022-08-24 14:44:26 +020012#include <IioPcieConfigUpd.h>
13
14#include <soc/chip_common.h>
15
16/*
17 * Used for IIO stacks for accelerators and other functionality (IOAT).
18 * Those have only integrated PCI endpoints (no bridges) behind the host bridge.
19 */
20
21static struct device_operations ioat_domain_ops = {
22 .read_resources = noop_read_resources,
23 .set_resources = pci_domain_set_resources,
24 .scan_bus = pci_host_bridge_scan_bus,
Patrick Rudolph40e07482024-02-23 09:23:41 +010025#if CONFIG(HAVE_ACPI_TABLES)
26 .acpi_name = soc_acpi_name,
Shuo Liu255f9272023-03-29 20:14:11 +080027 .write_acpi_tables = northbridge_write_acpi_tables,
Patrick Rudolphe357ac32024-02-23 09:47:24 +010028 .acpi_fill_ssdt = pci_domain_fill_ssdt,
Patrick Rudolph40e07482024-02-23 09:23:41 +010029#endif
Arthur Heymans550f55e2022-08-24 14:44:26 +020030};
31
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +010032static void create_ioat_domain(const union xeon_domain_path dp, struct bus *const upstream,
Arthur Heymans550f55e2022-08-24 14:44:26 +020033 const unsigned int bus_base, const unsigned int bus_limit,
34 const resource_t mem32_base, const resource_t mem32_limit,
Patrick Rudolph40e07482024-02-23 09:23:41 +010035 const resource_t mem64_base, const resource_t mem64_limit,
Patrick Rudolph80619572024-03-12 18:32:35 +010036 const char *prefix, const size_t pci_segment_group)
Arthur Heymans550f55e2022-08-24 14:44:26 +020037{
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +010038 union xeon_domain_path new_path = {
39 .domain_path = dp.domain_path
40 };
41 new_path.bus = bus_base;
42
Arthur Heymans550f55e2022-08-24 14:44:26 +020043 struct device_path path = {
44 .type = DEVICE_PATH_DOMAIN,
45 .domain = {
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +010046 .domain = new_path.domain_path,
Arthur Heymans550f55e2022-08-24 14:44:26 +020047 },
48 };
Shuo Liu255f9272023-03-29 20:14:11 +080049 struct device *const domain = alloc_find_dev(upstream, &path);
Arthur Heymans550f55e2022-08-24 14:44:26 +020050 if (!domain)
51 die("%s: out of memory.\n", __func__);
52
53 domain->ops = &ioat_domain_ops;
Patrick Rudolph40e07482024-02-23 09:23:41 +010054 iio_domain_set_acpi_name(domain, prefix);
Arthur Heymans550f55e2022-08-24 14:44:26 +020055
Arthur Heymans3e99ba02024-01-25 22:26:07 +010056 struct bus *const bus = alloc_bus(domain);
Arthur Heymans550f55e2022-08-24 14:44:26 +020057 bus->secondary = bus_base;
58 bus->subordinate = bus->secondary;
59 bus->max_subordinate = bus_limit;
Patrick Rudolph80619572024-03-12 18:32:35 +010060 bus->segment_group = pci_segment_group;
Arthur Heymans550f55e2022-08-24 14:44:26 +020061
62 unsigned int index = 0;
63
64 if (mem32_base <= mem32_limit) {
65 struct resource *const res = new_resource(domain, index++);
66 res->base = mem32_base;
67 res->limit = mem32_limit;
68 res->size = res->limit - res->base + 1;
69 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
70 }
71
72 if (mem64_base <= mem64_limit) {
73 struct resource *const res = new_resource(domain, index++);
74 res->base = mem64_base;
75 res->limit = mem64_limit;
76 res->size = res->limit - res->base + 1;
77 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
78 }
79}
80
Shuo Liuec58beb2024-03-11 07:14:07 +080081void create_ioat_domains(const union xeon_domain_path path,
82 struct bus *const bus,
83 const STACK_RES *const sr,
84 const size_t pci_segment_group)
Arthur Heymans550f55e2022-08-24 14:44:26 +020085{
Arthur Heymans550f55e2022-08-24 14:44:26 +020086 if (sr->BusLimit < sr->BusBase + HQM_BUS_OFFSET + HQM_RESERVED_BUS) {
87 printk(BIOS_WARNING,
88 "Ignoring IOAT domain with limited bus range.\n");
89 return;
90 }
91
92 if (sr->PciResourceMem64Limit - sr->PciResourceMem64Base + 1
93 < 2 * CPM_MMIO_SIZE + 2 * HQM_MMIO_SIZE) {
94 printk(BIOS_WARNING,
95 "Ignoring IOAT domain with limited 64-bit MMIO window.\n");
96 return;
97 }
98
99 /* The FSP HOB doesn't provide accurate information about the
100 resource allocation. Hence use pre-defined offsets. Based
Shuo Liu08f1f052024-01-20 02:52:17 +0800101 on ACPI code in create_dsdt_ioat_resource(), soc_acpi.c: */
Arthur Heymans550f55e2022-08-24 14:44:26 +0200102 resource_t mem64_base, mem64_limit, bus_base, bus_limit;
103
104 /* CPM0 */
105 mem64_base = sr->PciResourceMem64Base;
106 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
107 bus_base = sr->BusBase + CPM_BUS_OFFSET;
108 bus_limit = bus_base + CPM_RESERVED_BUS;
Patrick Rudolph7d834412024-02-29 18:08:09 +0100109 create_ioat_domain(path, bus, bus_base, bus_limit, -1, 0, mem64_base, mem64_limit,
Patrick Rudolph80619572024-03-12 18:32:35 +0100110 DOMAIN_TYPE_CPM0, pci_segment_group);
Arthur Heymans550f55e2022-08-24 14:44:26 +0200111
112 /* HQM0 */
113 mem64_base = mem64_limit + 1;
114 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
115 bus_base = sr->BusBase + HQM_BUS_OFFSET;
116 bus_limit = bus_base + HQM_RESERVED_BUS;
Patrick Rudolph7d834412024-02-29 18:08:09 +0100117 create_ioat_domain(path, bus, bus_base, bus_limit, -1, 0, mem64_base, mem64_limit,
Patrick Rudolph80619572024-03-12 18:32:35 +0100118 DOMAIN_TYPE_HQM0, pci_segment_group);
Arthur Heymans550f55e2022-08-24 14:44:26 +0200119
120 /* CPM1 (optional) */
121 mem64_base = mem64_limit + 1;
122 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
123 bus_base = sr->BusBase + CPM1_BUS_OFFSET;
124 bus_limit = bus_base + CPM_RESERVED_BUS;
125 if (bus_limit <= sr->BusLimit)
Patrick Rudolph7d834412024-02-29 18:08:09 +0100126 create_ioat_domain(path, bus, bus_base, bus_limit, -1, 0, mem64_base, mem64_limit,
Patrick Rudolph80619572024-03-12 18:32:35 +0100127 DOMAIN_TYPE_CPM1, pci_segment_group);
Arthur Heymans550f55e2022-08-24 14:44:26 +0200128
129 /* HQM1 (optional) */
130 mem64_base = mem64_limit + 1;
131 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
132 bus_base = sr->BusBase + HQM1_BUS_OFFSET;
133 bus_limit = bus_base + HQM_RESERVED_BUS;
134 if (bus_limit <= sr->BusLimit)
Patrick Rudolph7d834412024-02-29 18:08:09 +0100135 create_ioat_domain(path, bus, bus_base, bus_limit, -1, 0, mem64_base, mem64_limit,
Patrick Rudolph80619572024-03-12 18:32:35 +0100136 DOMAIN_TYPE_HQM1, pci_segment_group);
Arthur Heymans550f55e2022-08-24 14:44:26 +0200137
138 /* DINO */
139 mem64_base = mem64_limit + 1;
140 mem64_limit = sr->PciResourceMem64Limit;
141 bus_base = sr->BusBase;
142 bus_limit = bus_base;
Patrick Rudolph8c99ebc2024-01-19 17:28:47 +0100143 create_ioat_domain(path, bus, bus_base, bus_limit, sr->PciResourceMem32Base, sr->PciResourceMem32Limit,
Patrick Rudolph80619572024-03-12 18:32:35 +0100144 mem64_base, mem64_limit, DOMAIN_TYPE_DINO, pci_segment_group);
Arthur Heymans550f55e2022-08-24 14:44:26 +0200145}