Attention is currently required from: Jason Glenesk, Marshall Dawson, Felix Held. Raul Rangel has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/52917 )
Change subject: soc/amd/common/fsp/pci: Implement acpigen_write_pci_PRT ......................................................................
soc/amd/common/fsp/pci: Implement acpigen_write_pci_PRT
This will use the FSP PCI routing HOB to generate the PCI _PRT table.
BUG=b:184766519 TEST=Dump guybrush ACPI and verify it looks correct
Signed-off-by: Raul E Rangel rrangel@chromium.org Change-Id: I926430074acb969ceb11fdb60ab56dcf91ac4c76 --- M src/soc/amd/common/block/include/amdblocks/amd_pci_util.h M src/soc/amd/common/fsp/pci/Makefile.inc A src/soc/amd/common/fsp/pci/acpi_prt.c 3 files changed, 202 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/17/52917/1
diff --git a/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h b/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h index 081741a..a947ed6 100644 --- a/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h +++ b/src/soc/amd/common/block/include/amdblocks/amd_pci_util.h @@ -5,6 +5,7 @@
#include <types.h> #include <soc/amd_pci_int_defs.h> +#include <device/device.h>
/* FCH index/data registers */ #define PCI_INTR_INDEX 0xc00 @@ -33,5 +34,6 @@
/* Implemented by the SoC */ void populate_pirq_data(void); +void acpigen_write_pci_PRT(const struct device *dev, bool use_gnb_ioapic);
#endif /* AMD_BLOCK_PCI_UTIL_H */ diff --git a/src/soc/amd/common/fsp/pci/Makefile.inc b/src/soc/amd/common/fsp/pci/Makefile.inc index 9cfc9ff..42a460d 100644 --- a/src/soc/amd/common/fsp/pci/Makefile.inc +++ b/src/soc/amd/common/fsp/pci/Makefile.inc @@ -2,5 +2,6 @@
ramstage-y += pci_routing_info.c ramstage-y += pirq.c +ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi_prt.c
endif # CONFIG_SOC_AMD_COMMON_FSP_PCI diff --git a/src/soc/amd/common/fsp/pci/acpi_prt.c b/src/soc/amd/common/fsp/pci/acpi_prt.c new file mode 100644 index 0000000..e408332 --- /dev/null +++ b/src/soc/amd/common/fsp/pci/acpi_prt.c @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "pci_routing_info.h" +#include <acpi/acpi.h> +#include <acpi/acpigen.h> +#include <acpi/acpigen_pci.h> +#include <amdblocks/amd_pci_util.h> +#include <arch/ioapic.h> +#include <console/console.h> +#include <device/device.h> + +static void acpigen_write_PRT_GSI(const struct pci_routing_info *routing_info) +{ + unsigned int irq; + + acpigen_write_package(4); /* Package - APIC Routing */ + for (unsigned int i = 0; i < 4; ++i) { + /* GNB IO-APIC is located after the FCH IO-APIC */ + irq = IO_APIC_INTERRUPTS; + irq += pci_calculate_irq(routing_info, i); + + acpigen_write_PRT_source_entry( + 0, /* There is only one device attached to the bridge */ + i, /* pin */ + 0, /* Source: GSI */ + irq); + } + acpigen_pop_len(); /* Package - APIC Routing */ +} + +static void acpigen_write_PRT_PIC(const struct pci_routing_info *routing_info) +{ + unsigned int irq; + char link_template[] = "\_SB.INTX"; + + acpigen_write_package(4); /* Package - PIC Routing */ + for (unsigned int i = 0; i < 4; ++i) { + irq = pci_calculate_irq(routing_info, i); + + link_template[8] = 'A' + (irq % 8); + + acpigen_write_PRT_source_entry( + 0, /* There is only one device attached to the bridge */ + i, /* pin */ + link_template, 0); + } + acpigen_pop_len(); /* Package - PIC Routing */ +} + +/* + * This method writes a PCI _PRT table: + * If use_gnb_ioapic is set we use the GNB IO-APIC / PIC: + * Method (_PRT, 0, NotSerialized) // _PRT: PCI Routing Table + * { + * If (PICM) + * { + * Return (Package (0x04) + * { + * Package (0x04) + * { + * 0x0000FFFF, + * 0x00, + * 0x00, + * 0x00000034 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x01, + * 0x00, + * 0x00000035 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x02, + * 0x00, + * 0x00000036 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x03, + * 0x00, + * 0x00000037 + * } + * }) + * } + * Else + * { + * Return (Package (0x04) + * { + * Package (0x04) + * { + * 0x0000FFFF, + * 0x00, + * _SB.LNKA, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x01, + * _SB.LNKB, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x02, + * _SB.LNKC, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x03, + * _SB.LNKD, + * 0x00000000 + * } + * }) + * } + * } + * Otherwise we use the PIC / FCH IO-APIC: + * Name (_PRT, Package (0x04) + * { + * Package (0x04) + * { + * 0x0000FFFF, + * 0x00, + * _SB.LNKA, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x01, + * _SB.LNKB, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x02, + * _SB.LNKC, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x03, + * _SB.LNKD, + * 0x00000000 + * } + * }) + */ +void acpigen_write_pci_PRT(const struct device *dev, bool use_gnb_ioapic) +{ + const struct pci_routing_info *routing_info = + get_pci_routing_info(dev->path.pci.devfn); + + if (!routing_info) + return; + + if (use_gnb_ioapic) { + acpigen_write_method("_PRT", 0); + + /* If (PICM) */ + acpigen_write_if(); + acpigen_emit_namestring("PICM"); + + /* Return (Package{...}) */ + acpigen_emit_byte(RETURN_OP); + acpigen_write_PRT_GSI(routing_info); + + /* Else */ + acpigen_write_else(); + + /* Return (Package{...}) */ + acpigen_emit_byte(RETURN_OP); + acpigen_write_PRT_PIC(routing_info); + + acpigen_pop_len(); /* End Else */ + + acpigen_pop_len(); /* Method */ + } else { + acpigen_write_name("_PRT"); + acpigen_write_PRT_PIC(routing_info); + } +}