blob: 4ec52fcbd8ec27de2c59737f5579f23e9a8c1deb [file] [log] [blame]
Felix Held407bd582023-04-24 17:58:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
Felix Held7a5dd782023-04-28 22:47:33 +02003#include <acpi/acpigen.h>
Felix Held407bd582023-04-24 17:58:24 +02004#include <amdblocks/data_fabric.h>
Felix Held32169722023-07-14 19:41:06 +02005#include <amdblocks/root_complex.h>
Felix Held407bd582023-04-24 17:58:24 +02006#include <arch/ioapic.h>
Felix Held7a5dd782023-04-28 22:47:33 +02007#include <arch/vga.h>
Felix Held407bd582023-04-24 17:58:24 +02008#include <console/console.h>
9#include <cpu/amd/mtrr.h>
Felix Held89ca4782023-09-12 15:01:02 +020010#include <cpu/cpu.h>
Felix Held407bd582023-04-24 17:58:24 +020011#include <device/device.h>
12#include <device/pci_ops.h>
13#include <types.h>
14
15void amd_pci_domain_scan_bus(struct device *domain)
16{
17 uint8_t bus, limit;
18
Felix Heldea831392023-08-08 02:55:09 +020019 if (data_fabric_get_pci_bus_numbers(domain, &bus, &limit) != CB_SUCCESS) {
20 printk(BIOS_ERR, "No PCI bus numbers decoded to PCI root.\n");
21 return;
22 }
23
24 /* TODO: Check if bus >= CONFIG_ECAM_MMCONF_BUS_NUMBER and return in that case */
25
26 /* Make sure to not report more than CONFIG_ECAM_MMCONF_BUS_NUMBER PCI buses */
27 limit = MIN(limit, CONFIG_ECAM_MMCONF_BUS_NUMBER - 1);
Felix Held407bd582023-04-24 17:58:24 +020028
29 /* Set bus first number of PCI root */
30 domain->link_list->secondary = bus;
Arthur Heymans0b0113f2023-08-31 17:09:28 +020031 /* subordinate needs to be the same as secondary before pci_host_bridge_scan_bus call. */
Felix Held407bd582023-04-24 17:58:24 +020032 domain->link_list->subordinate = bus;
Felix Held9dcdec52023-08-08 21:38:43 +020033 /* Tell allocator about maximum PCI bus number in domain */
34 domain->link_list->max_subordinate = limit;
Felix Held407bd582023-04-24 17:58:24 +020035
Arthur Heymans0b0113f2023-08-31 17:09:28 +020036 pci_host_bridge_scan_bus(domain);
Felix Held407bd582023-04-24 17:58:24 +020037}
38
Felix Held407bd582023-04-24 17:58:24 +020039static void print_df_mmio_outside_of_cpu_mmio_error(unsigned int reg)
40{
41 printk(BIOS_WARNING, "DF MMIO register %u outside of CPU MMIO region.\n", reg);
42}
43
44static bool is_mmio_region_valid(unsigned int reg, resource_t mmio_base, resource_t mmio_limit)
45{
46 if (mmio_base > mmio_limit) {
47 printk(BIOS_WARNING, "DF MMIO register %u's base is above its limit.\n", reg);
48 return false;
49 }
50 if (mmio_base >= 4ULL * GiB) {
51 /* MMIO region above 4GB needs to be above TOP_MEM2 MSR value */
52 if (mmio_base < get_top_of_mem_above_4gb()) {
53 print_df_mmio_outside_of_cpu_mmio_error(reg);
54 return false;
55 }
56 } else {
57 /* MMIO region below 4GB needs to be above TOP_MEM MSR value */
58 if (mmio_base < get_top_of_mem_below_4gb()) {
59 print_df_mmio_outside_of_cpu_mmio_error(reg);
60 return false;
61 }
62 /* MMIO region below 4GB mustn't cross the 4GB boundary. */
63 if (mmio_limit >= 4ULL * GiB) {
64 printk(BIOS_WARNING, "DF MMIO register %u crosses 4GB boundary.\n",
65 reg);
66 return false;
67 }
68 }
69
70 return true;
71}
72
73static void report_data_fabric_mmio(struct device *domain, unsigned int idx,
74 resource_t mmio_base, resource_t mmio_limit)
75{
76 struct resource *res;
77 res = new_resource(domain, idx);
78 res->base = mmio_base;
79 res->limit = mmio_limit;
80 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
81}
82
83/* Tell the resource allocator about the usable MMIO ranges configured in the data fabric */
84static void add_data_fabric_mmio_regions(struct device *domain, unsigned int *idx)
85{
Felix Held9cbdc8f2023-08-11 22:30:06 +020086 const signed int iohc_dest_fabric_id = get_iohc_fabric_id(domain);
Felix Held407bd582023-04-24 17:58:24 +020087 union df_mmio_control ctrl;
88 resource_t mmio_base;
89 resource_t mmio_limit;
90
91 /* The last 12GB of the usable address space are reserved and can't be used for MMIO */
92 const resource_t reserved_upper_mmio_base =
Felix Held89ca4782023-09-12 15:01:02 +020093 (1ULL << cpu_phys_address_size()) - DF_RESERVED_TOP_12GB_MMIO_SIZE;
Felix Held407bd582023-04-24 17:58:24 +020094
95 for (unsigned int i = 0; i < DF_MMIO_REG_SET_COUNT; i++) {
Felix Held18a3c232023-08-03 00:10:03 +020096 ctrl.raw = data_fabric_broadcast_read32(DF_MMIO_CONTROL(i));
Felix Held407bd582023-04-24 17:58:24 +020097
98 /* Relevant MMIO regions need to have both reads and writes enabled */
99 if (!ctrl.we || !ctrl.re)
100 continue;
101
102 /* Non-posted region contains fixed FCH MMIO devices */
103 if (ctrl.np)
104 continue;
105
Felix Held55822d92023-08-08 21:38:07 +0200106 /* Only look at MMIO regions that are decoded to the right PCI root */
Felix Held9cbdc8f2023-08-11 22:30:06 +0200107 if (ctrl.dst_fabric_id != iohc_dest_fabric_id)
Felix Held55822d92023-08-08 21:38:07 +0200108 continue;
Felix Held407bd582023-04-24 17:58:24 +0200109
110 data_fabric_get_mmio_base_size(i, &mmio_base, &mmio_limit);
111
112 if (!is_mmio_region_valid(i, mmio_base, mmio_limit))
113 continue;
114
115 /* Make sure to not report a region overlapping with the fixed MMIO resources
116 below 4GB or the reserved MMIO range in the last 12GB of the addressable
117 address range. The code assumes that the fixed MMIO resources below 4GB
118 are between IO_APIC_ADDR and the 4GB boundary. */
119 if (mmio_base < 4ULL * GiB) {
120 if (mmio_base >= IO_APIC_ADDR)
121 continue;
122 if (mmio_limit >= IO_APIC_ADDR)
123 mmio_limit = IO_APIC_ADDR - 1;
124 } else {
125 if (mmio_base >= reserved_upper_mmio_base)
126 continue;
127 if (mmio_limit >= reserved_upper_mmio_base)
128 mmio_limit = reserved_upper_mmio_base - 1;
129 }
130
131 report_data_fabric_mmio(domain, (*idx)++, mmio_base, mmio_limit);
132 }
133}
134
Felix Held2dfd48b2023-08-04 19:22:54 +0200135static void report_data_fabric_io(struct device *domain, unsigned int idx,
136 resource_t io_base, resource_t io_limit)
137{
138 struct resource *res;
139 res = new_resource(domain, idx);
140 res->base = io_base;
141 res->limit = io_limit;
142 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED;
143}
144
Felix Held407bd582023-04-24 17:58:24 +0200145/* Tell the resource allocator about the usable I/O space */
Felix Held3f3f93b2023-08-04 22:14:40 +0200146static void add_data_fabric_io_regions(struct device *domain, unsigned int *idx)
Felix Held407bd582023-04-24 17:58:24 +0200147{
Felix Held9cbdc8f2023-08-11 22:30:06 +0200148 const signed int iohc_dest_fabric_id = get_iohc_fabric_id(domain);
Felix Held4eac0d42023-08-04 19:40:02 +0200149 union df_io_base base_reg;
150 union df_io_limit limit_reg;
151 resource_t io_base;
152 resource_t io_limit;
Felix Held407bd582023-04-24 17:58:24 +0200153
Felix Held4eac0d42023-08-04 19:40:02 +0200154 for (unsigned int i = 0; i < DF_IO_REG_COUNT; i++) {
155 base_reg.raw = data_fabric_broadcast_read32(DF_IO_BASE(i));
156
157 /* Relevant IO regions need to have both reads and writes enabled */
158 if (!base_reg.we || !base_reg.re)
159 continue;
160
161 limit_reg.raw = data_fabric_broadcast_read32(DF_IO_LIMIT(i));
162
Felix Held55822d92023-08-08 21:38:07 +0200163 /* Only look at IO regions that are decoded to the right PCI root */
Felix Held9cbdc8f2023-08-11 22:30:06 +0200164 if (limit_reg.dst_fabric_id != iohc_dest_fabric_id)
Felix Held55822d92023-08-08 21:38:07 +0200165 continue;
Felix Held4eac0d42023-08-04 19:40:02 +0200166
167 io_base = base_reg.io_base << DF_IO_ADDR_SHIFT;
168 io_limit = ((limit_reg.io_limit + 1) << DF_IO_ADDR_SHIFT) - 1;
169
170 /* Beware that the lower 25 bits of io_base and io_limit can be non-zero
171 despite there only being 16 bits worth of IO port address space. */
172 if (io_base > 0xffff) {
173 printk(BIOS_WARNING, "DF IO base register %d value outside of valid "
174 "IO port address range.\n", i);
175 continue;
176 }
177 /* If only the IO limit is outside of the valid 16 bit IO port range, report
178 the limit as 0xffff, so that the resource allcator won't put IO BARs outside
179 of the 16 bit IO port address range. */
180 io_limit = MIN(io_limit, 0xffff);
181
182 report_data_fabric_io(domain, (*idx)++, io_base, io_limit);
183 }
Felix Held407bd582023-04-24 17:58:24 +0200184}
185
186void amd_pci_domain_read_resources(struct device *domain)
187{
188 unsigned int idx = 0;
189
Felix Held3f3f93b2023-08-04 22:14:40 +0200190 add_data_fabric_io_regions(domain, &idx);
Felix Held407bd582023-04-24 17:58:24 +0200191
192 add_data_fabric_mmio_regions(domain, &idx);
Felix Held32169722023-07-14 19:41:06 +0200193
194 read_non_pci_resources(domain, &idx);
Felix Held407bd582023-04-24 17:58:24 +0200195}
Felix Held7a5dd782023-04-28 22:47:33 +0200196
197static void write_ssdt_domain_io_producer_range_helper(const char *domain_name,
198 resource_t base, resource_t limit)
199{
200 printk(BIOS_DEBUG, "%s _CRS: adding IO range [%llx-%llx]\n", domain_name, base, limit);
201 acpigen_resource_producer_io(base, limit);
202}
203
204static void write_ssdt_domain_io_producer_range(const char *domain_name,
205 resource_t base, resource_t limit)
206{
207 /*
208 * Split the IO region at the PCI config IO ports so that the IO resource producer
209 * won't cover the same IO ports that the IO resource consumer for the PCI config IO
210 * ports in the same ACPI device already covers.
211 */
212 if (base < PCI_IO_CONFIG_INDEX) {
213 write_ssdt_domain_io_producer_range_helper(domain_name,
214 base,
215 MIN(limit, PCI_IO_CONFIG_INDEX - 1));
216 }
217 if (limit > PCI_IO_CONFIG_LAST_PORT) {
218 write_ssdt_domain_io_producer_range_helper(domain_name,
219 MAX(base, PCI_IO_CONFIG_LAST_PORT + 1),
220 limit);
221 }
222}
223
224static void write_ssdt_domain_mmio_producer_range(const char *domain_name,
225 resource_t base, resource_t limit)
226{
227 printk(BIOS_DEBUG, "%s _CRS: adding MMIO range [%llx-%llx]\n",
228 domain_name, base, limit);
229 acpigen_resource_producer_mmio(base, limit,
230 MEM_RSRC_FLAG_MEM_READ_WRITE | MEM_RSRC_FLAG_MEM_ATTR_NON_CACHE);
231}
232
233void amd_pci_domain_fill_ssdt(const struct device *domain)
234{
235 const char *acpi_scope = acpi_device_path(domain);
236 printk(BIOS_DEBUG, "%s ACPI scope: '%s'\n", __func__, acpi_scope);
237 acpigen_write_scope(acpi_device_path(domain));
238
239 acpigen_write_name("_CRS");
240 acpigen_write_resourcetemplate_header();
241
242 /* PCI bus number range in domain */
243 printk(BIOS_DEBUG, "%s _CRS: adding busses [%x-%x]\n", acpi_device_name(domain),
Felix Held9dcdec52023-08-08 21:38:43 +0200244 domain->link_list->secondary, domain->link_list->max_subordinate);
Felix Held7a5dd782023-04-28 22:47:33 +0200245 acpigen_resource_producer_bus_number(domain->link_list->secondary,
Felix Held9dcdec52023-08-08 21:38:43 +0200246 domain->link_list->max_subordinate);
Felix Held7a5dd782023-04-28 22:47:33 +0200247
248 if (domain->link_list->secondary == 0) {
249 /* ACPI 6.4.2.5 I/O Port Descriptor */
250 acpigen_write_io16(PCI_IO_CONFIG_INDEX, PCI_IO_CONFIG_LAST_PORT, 1,
251 PCI_IO_CONFIG_PORT_COUNT, 1);
252 }
253
254 struct resource *res;
255 for (res = domain->resource_list; res != NULL; res = res->next) {
256 if (!(res->flags & IORESOURCE_ASSIGNED))
Felix Helda239cf42023-07-29 01:45:31 +0200257 continue;
Felix Held0df754b2023-07-29 01:49:15 +0200258 /* Don't add MMIO producer ranges for reserved MMIO regions from non-PCI
259 devices */
260 if ((res->flags & IORESOURCE_RESERVE))
261 continue;
Felix Held7a5dd782023-04-28 22:47:33 +0200262 switch (res->flags & IORESOURCE_TYPE_MASK) {
263 case IORESOURCE_IO:
264 write_ssdt_domain_io_producer_range(acpi_device_name(domain),
265 res->base, res->limit);
266 break;
267 case IORESOURCE_MEM:
268 write_ssdt_domain_mmio_producer_range(acpi_device_name(domain),
269 res->base, res->limit);
270 break;
271 default:
272 break;
273 }
274 }
275
276 if (domain->link_list->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
277 printk(BIOS_DEBUG, "%s _CRS: adding VGA resource\n", acpi_device_name(domain));
278 acpigen_resource_producer_mmio(VGA_MMIO_BASE, VGA_MMIO_LIMIT,
279 MEM_RSRC_FLAG_MEM_READ_WRITE | MEM_RSRC_FLAG_MEM_ATTR_CACHE);
280 }
281
282 acpigen_write_resourcetemplate_footer();
Felix Helde4b65cc2023-05-05 20:46:11 +0200283
284 acpigen_write_BBN(domain->link_list->secondary);
285
Felix Held7a5dd782023-04-28 22:47:33 +0200286 /* Scope */
287 acpigen_pop_len();
288}