1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #include <acpi/acpigen_pci.h>
5 #include <console/console.h>
6 #include <device/device.h>
7 #include <device/resource.h>
10 #include <hob_iiouds.h>
11 #include <intelblocks/acpi.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 void 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
)
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
= 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
= 0;
65 if (mem32_base
<= mem32_limit
) {
66 struct resource
*const res
= new_resource(domain
, index
++);
67 res
->base
= mem32_base
;
68 res
->limit
= mem32_limit
;
69 res
->size
= res
->limit
- res
->base
+ 1;
70 res
->flags
= IORESOURCE_MEM
| IORESOURCE_ASSIGNED
;
73 if (mem64_base
<= mem64_limit
) {
74 struct resource
*const res
= new_resource(domain
, index
++);
75 res
->base
= mem64_base
;
76 res
->limit
= mem64_limit
;
77 res
->size
= res
->limit
- res
->base
+ 1;
78 res
->flags
= IORESOURCE_MEM
| IORESOURCE_ASSIGNED
;
82 void soc_create_ioat_domains(const union xeon_domain_path path
,
83 struct bus
*const bus
,
84 const STACK_RES
*const sr
,
85 const size_t pci_segment_group
)
87 if (sr
->BusLimit
< sr
->BusBase
+ HQM_BUS_OFFSET
+ HQM_RESERVED_BUS
) {
89 "Ignoring IOAT domain with limited bus range.\n");
93 if (sr
->PciResourceMem64Limit
- sr
->PciResourceMem64Base
+ 1
94 < 2 * CPM_MMIO_SIZE
+ 2 * HQM_MMIO_SIZE
) {
96 "Ignoring IOAT domain with limited 64-bit MMIO window.\n");
100 /* The FSP HOB doesn't provide accurate information about the
101 resource allocation. Hence use pre-defined offsets. Based
102 on ACPI code in create_dsdt_ioat_resource(), soc_acpi.c: */
103 resource_t mem64_base
, mem64_limit
, bus_base
, bus_limit
;
106 mem64_base
= sr
->PciResourceMem64Base
;
107 mem64_limit
= mem64_base
+ CPM_MMIO_SIZE
- 1;
108 bus_base
= sr
->BusBase
+ CPM_BUS_OFFSET
;
109 bus_limit
= bus_base
+ CPM_RESERVED_BUS
;
110 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
111 DOMAIN_TYPE_CPM0
, pci_segment_group
);
114 mem64_base
= mem64_limit
+ 1;
115 mem64_limit
= mem64_base
+ HQM_MMIO_SIZE
- 1;
116 bus_base
= sr
->BusBase
+ HQM_BUS_OFFSET
;
117 bus_limit
= bus_base
+ HQM_RESERVED_BUS
;
118 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
119 DOMAIN_TYPE_HQM0
, pci_segment_group
);
121 /* CPM1 (optional) */
122 mem64_base
= mem64_limit
+ 1;
123 mem64_limit
= mem64_base
+ CPM_MMIO_SIZE
- 1;
124 bus_base
= sr
->BusBase
+ CPM1_BUS_OFFSET
;
125 bus_limit
= bus_base
+ CPM_RESERVED_BUS
;
126 if (bus_limit
<= sr
->BusLimit
)
127 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
128 DOMAIN_TYPE_CPM1
, pci_segment_group
);
130 /* HQM1 (optional) */
131 mem64_base
= mem64_limit
+ 1;
132 mem64_limit
= mem64_base
+ HQM_MMIO_SIZE
- 1;
133 bus_base
= sr
->BusBase
+ HQM1_BUS_OFFSET
;
134 bus_limit
= bus_base
+ HQM_RESERVED_BUS
;
135 if (bus_limit
<= sr
->BusLimit
)
136 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, -1, 0, mem64_base
, mem64_limit
,
137 DOMAIN_TYPE_HQM1
, pci_segment_group
);
140 mem64_base
= mem64_limit
+ 1;
141 mem64_limit
= sr
->PciResourceMem64Limit
;
142 bus_base
= sr
->BusBase
;
143 bus_limit
= bus_base
;
144 create_ioat_domain(path
, bus
, bus_base
, bus_limit
, sr
->PciResourceMem32Base
, sr
->PciResourceMem32Limit
,
145 mem64_base
, mem64_limit
, DOMAIN_TYPE_DINO
, pci_segment_group
);