1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #include <acpi/acpigen_pci.h>
5 #include <console/console.h>
6 #include <device/device.h>
9 #include <hob_iiouds.h>
10 #include <intelblocks/acpi.h>
11 #include <intelblocks/vtd.h>
13 #include <IioPcieConfigUpd.h>
15 #include <soc/chip_common.h>
18 * Used for IIO stacks for accelerators and other functionality (IOAT).
19 * Those have only integrated PCI endpoints (no bridges) behind the host bridge.
22 static struct device_operations ioat_domain_ops
= {
23 .read_resources
= noop_read_resources
,
24 .set_resources
= pci_domain_set_resources
,
25 .scan_bus
= pci_host_bridge_scan_bus
,
26 #if CONFIG(HAVE_ACPI_TABLES)
27 .acpi_name
= soc_acpi_name
,
28 .write_acpi_tables
= northbridge_write_acpi_tables
,
29 .acpi_fill_ssdt
= pci_domain_fill_ssdt
,
33 static struct device
*const create_ioat_domain(const union xeon_domain_path dp
, struct bus
*const upstream
,
34 const unsigned int bus_base
, const unsigned int bus_limit
,
35 const resource_t mem32_base
, const resource_t mem32_limit
,
36 const resource_t mem64_base
, const resource_t mem64_limit
,
37 const char *prefix
, const size_t pci_segment_group
, int *res_index
)
39 union xeon_domain_path new_path
= {
40 .domain_path
= dp
.domain_path
42 new_path
.bus
= bus_base
;
44 struct device_path path
= {
45 .type
= DEVICE_PATH_DOMAIN
,
47 .domain_id
= new_path
.domain_path
,
50 struct device
*const domain
= alloc_find_dev(upstream
, &path
);
52 die("%s: out of memory.\n", __func__
);
54 domain
->ops
= &ioat_domain_ops
;
55 iio_domain_set_acpi_name(domain
, prefix
);
57 struct bus
*const bus
= alloc_bus(domain
);
58 bus
->secondary
= bus_base
;
59 bus
->subordinate
= bus
->secondary
;
60 bus
->max_subordinate
= bus_limit
;
61 bus
->segment_group
= pci_segment_group
;
63 unsigned int index
= res_index
? *res_index
: 0;
65 if (mem32_base
<= mem32_limit
)
66 domain_mem_window_from_to(domain
, index
++, mem32_base
, mem32_limit
+ 1);
68 if (mem64_base
<= mem64_limit
)
69 domain_mem_window_from_to(domain
, index
++, mem64_base
, mem64_limit
+ 1);
77 void create_ioat_domains(const union xeon_domain_path path
,
78 struct bus
*const bus
,
79 const STACK_RES
*const sr
,
80 const size_t pci_segment_group
)
82 if (sr
->BusLimit
< sr
->BusBase
+ HQM_BUS_OFFSET
+ HQM_RESERVED_BUS
) {
84 "Ignoring IOAT domain with limited bus range.\n");
88 if (sr
->PciResourceMem64Limit
- sr
->PciResourceMem64Base
+ 1
89 < 2 * CPM_MMIO_SIZE
+ 2 * HQM_MMIO_SIZE
) {
91 "Ignoring IOAT domain with limited 64-bit MMIO window.\n");
95 /* The FSP HOB doesn't provide accurate information about the
96 resource allocation. Hence use pre-defined offsets. Based
97 on ACPI code in create_dsdt_ioat_resource(), soc_acpi.c: */
98 resource_t mem64_base
, mem64_limit
, bus_base
, bus_limit
;
101 mem64_base
= sr
->PciResourceMem64Base
;
102 mem64_limit
= mem64_base
+ CPM_MMIO_SIZE
- 1;
103 bus_base
= sr
->BusBase
+ CPM_BUS_OFFSET
;
104 bus_limit
= bus_base
+ CPM_RESERVED_BUS
;
105 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
106 DOMAIN_TYPE_CPM0
, pci_segment_group
, NULL
);
109 mem64_base
= mem64_limit
+ 1;
110 mem64_limit
= mem64_base
+ HQM_MMIO_SIZE
- 1;
111 bus_base
= sr
->BusBase
+ HQM_BUS_OFFSET
;
112 bus_limit
= bus_base
+ HQM_RESERVED_BUS
;
113 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
114 DOMAIN_TYPE_HQM0
, pci_segment_group
, NULL
);
116 /* CPM1 (optional) */
117 mem64_base
= mem64_limit
+ 1;
118 mem64_limit
= mem64_base
+ CPM_MMIO_SIZE
- 1;
119 bus_base
= sr
->BusBase
+ CPM1_BUS_OFFSET
;
120 bus_limit
= bus_base
+ CPM_RESERVED_BUS
;
121 if (bus_limit
<= sr
->BusLimit
)
122 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
123 DOMAIN_TYPE_CPM1
, pci_segment_group
, NULL
);
125 /* HQM1 (optional) */
126 mem64_base
= mem64_limit
+ 1;
127 mem64_limit
= mem64_base
+ HQM_MMIO_SIZE
- 1;
128 bus_base
= sr
->BusBase
+ HQM1_BUS_OFFSET
;
129 bus_limit
= bus_base
+ HQM_RESERVED_BUS
;
130 if (bus_limit
<= sr
->BusLimit
)
131 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
132 DOMAIN_TYPE_HQM1
, pci_segment_group
, NULL
);
135 mem64_base
= mem64_limit
+ 1;
136 mem64_limit
= sr
->PciResourceMem64Limit
;
137 bus_base
= sr
->BusBase
;
138 bus_limit
= bus_base
;
140 struct device
*const dev
= create_ioat_domain(path
, bus
, bus_base
, bus_limit
,
141 sr
->PciResourceMem32Base
, sr
->PciResourceMem32Limit
,
142 mem64_base
, mem64_limit
, DOMAIN_TYPE_DINO
, pci_segment_group
,
145 /* Declare domain reserved MMIO */
146 uint64_t reserved_mmio
= sr
->VtdBarAddress
+ vtd_probe_bar_size(pcidev_on_root(0, 0));
147 if ((reserved_mmio
>= sr
->PciResourceMem32Base
) &&
148 (reserved_mmio
<= sr
->PciResourceMem32Limit
))
149 mmio_range(dev
, index
, reserved_mmio
,
150 sr
->PciResourceMem32Limit
- reserved_mmio
+ 1);