1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpigen.h>
4 #include <acpi/acpigen_pci.h>
5 #include <arch/pci_io_cfg.h>
7 #include <console/console.h>
8 #include <device/device.h>
11 static void write_ssdt_domain_io_producer_range_helper(const char *domain_name
,
12 resource_t base
, resource_t limit
)
14 printk(BIOS_DEBUG
, "%s _CRS: adding IO range [%04llx-%04llx]\n", domain_name
, base
, limit
);
15 acpigen_resource_producer_io(base
, limit
);
18 static void write_ssdt_domain_io_producer_range(const char *domain_name
,
19 resource_t base
, resource_t limit
)
22 * Split the IO region at the PCI config IO ports so that the IO resource producer
23 * won't cover the same IO ports that the IO resource consumer for the PCI config IO
24 * ports in the same ACPI device already covers.
26 if (base
< PCI_IO_CONFIG_INDEX
) {
27 write_ssdt_domain_io_producer_range_helper(domain_name
,
29 MIN(limit
, PCI_IO_CONFIG_INDEX
- 1));
31 if (limit
> PCI_IO_CONFIG_LAST_PORT
) {
32 write_ssdt_domain_io_producer_range_helper(domain_name
,
33 MAX(base
, PCI_IO_CONFIG_LAST_PORT
+ 1),
38 static void write_ssdt_domain_mmio_producer_range(const char *domain_name
,
39 resource_t base
, resource_t limit
)
41 printk(BIOS_DEBUG
, "%s _CRS: adding MMIO range [%016llx-%016llx]\n",
42 domain_name
, base
, limit
);
43 acpigen_resource_producer_mmio(base
, limit
,
44 MEM_RSRC_FLAG_MEM_READ_WRITE
| MEM_RSRC_FLAG_MEM_ATTR_NON_CACHE
);
47 void pci_domain_fill_ssdt(const struct device
*domain
)
49 const char *acpi_scope
= acpi_device_path(domain
);
50 printk(BIOS_DEBUG
, "%s ACPI scope: '%s'\n", __func__
, acpi_scope
);
51 acpigen_write_scope(acpi_device_path(domain
));
53 acpigen_write_name("_CRS");
54 acpigen_write_resourcetemplate_header();
56 /* PCI bus number range in domain */
57 printk(BIOS_DEBUG
, "%s _CRS: adding busses [%02x-%02x] in segment group %x\n",
58 acpi_device_name(domain
), domain
->downstream
->secondary
,
59 domain
->downstream
->max_subordinate
, domain
->downstream
->segment_group
);
60 acpigen_resource_producer_bus_number(domain
->downstream
->secondary
,
61 domain
->downstream
->max_subordinate
);
63 if (is_domain0(domain
)) {
64 /* ACPI 6.4.2.5 I/O Port Descriptor */
65 acpigen_write_io16(PCI_IO_CONFIG_INDEX
, PCI_IO_CONFIG_LAST_PORT
, 1,
66 PCI_IO_CONFIG_PORT_COUNT
, 1);
70 for (res
= domain
->resource_list
; res
!= NULL
; res
= res
->next
) {
71 if (!(res
->flags
& IORESOURCE_ASSIGNED
))
73 /* Don't add MMIO producer ranges for reserved MMIO regions from non-PCI
75 if (res
->flags
& IORESOURCE_RESERVE
)
77 /* Don't add MMIO producer ranges for DRAM regions */
78 if (res
->flags
& IORESOURCE_STORED
)
80 switch (res
->flags
& IORESOURCE_TYPE_MASK
) {
82 write_ssdt_domain_io_producer_range(acpi_device_name(domain
),
83 res
->base
, res
->limit
);
86 write_ssdt_domain_mmio_producer_range(acpi_device_name(domain
),
87 res
->base
, res
->limit
);
94 if (domain
->downstream
->bridge_ctrl
& PCI_BRIDGE_CTL_VGA
) {
95 printk(BIOS_DEBUG
, "%s _CRS: adding VGA resource\n", acpi_device_name(domain
));
96 acpigen_resource_producer_mmio(VGA_MMIO_BASE
, VGA_MMIO_LIMIT
,
97 MEM_RSRC_FLAG_MEM_READ_WRITE
| MEM_RSRC_FLAG_MEM_ATTR_CACHE
);
100 acpigen_write_resourcetemplate_footer();
102 acpigen_write_SEG(domain
->downstream
->segment_group
);
103 acpigen_write_BBN(domain
->downstream
->secondary
);