diff options
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/amd_pci_util.h | 4 | ||||
-rw-r--r-- | src/soc/amd/common/block/pci/Makefile.inc | 9 | ||||
-rw-r--r-- | src/soc/amd/common/block/pci/acpi_prt.c | 206 |
3 files changed, 217 insertions, 2 deletions
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 83922c9468..0a4061f631 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 @@ -60,4 +61,7 @@ const struct pci_routing_info *get_pci_routing_info(unsigned int devfn); unsigned int pci_calculate_irq(const struct pci_routing_info *routing_info, unsigned int pin); +void acpigen_write_pci_GNB_PRT(const struct device *dev); +void acpigen_write_pci_FCH_PRT(const struct device *dev); + #endif /* AMD_BLOCK_PCI_UTIL_H */ diff --git a/src/soc/amd/common/block/pci/Makefile.inc b/src/soc/amd/common/block/pci/Makefile.inc index 5df641b1d9..8c7a9899ae 100644 --- a/src/soc/amd/common/block/pci/Makefile.inc +++ b/src/soc/amd/common/block/pci/Makefile.inc @@ -1,5 +1,10 @@ -ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PCI) += amd_pci_util.c -ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PCI) += pci_routing_info.c +ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_PCI),y) + +ramstage-y += amd_pci_util.c +ramstage-y += pci_routing_info.c +ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi_prt.c + +endif # CONFIG_SOC_AMD_COMMON_BLOCK_PCI ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_PCI_MMCONF),y) diff --git a/src/soc/amd/common/block/pci/acpi_prt.c b/src/soc/amd/common/block/pci/acpi_prt.c new file mode 100644 index 0000000000..c4c50f5b6e --- /dev/null +++ b/src/soc/amd/common/block/pci/acpi_prt.c @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#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_GSI_entry( + 0, /* There is only one device attached to the bridge */ + i, /* pin */ + 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 /* Source */, + 0 /* Source Index */); + } + acpigen_pop_len(); /* Package - PIC Routing */ +} + +/* + * This method writes a PCI _PRT table that uses 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.INTA, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x01, + * \_SB.INTB, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x02, + * \_SB.INTC, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x03, + * \_SB.INTD, + * 0x00000000 + * } + * }) + * } + * } + */ +void acpigen_write_pci_GNB_PRT(const struct device *dev) +{ + const struct pci_routing_info *routing_info = + get_pci_routing_info(dev->path.pci.devfn); + + if (!routing_info) + return; + + 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 */ +} + + /* + * This method writes a PCI _PRT table that uses the FCH IO-APIC / PIC : + * Name (_PRT, Package (0x04) + * { + * Package (0x04) + * { + * 0x0000FFFF, + * 0x00, + * \_SB.INTA, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x01, + * \_SB.INTB, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x02, + * \_SB.INTC, + * 0x00000000 + * }, + * + * Package (0x04) + * { + * 0x0000FFFF, + * 0x03, + * \_SB.INTD, + * 0x00000000 + * } + * }) + */ +void acpigen_write_pci_FCH_PRT(const struct device *dev) +{ + const struct pci_routing_info *routing_info = + get_pci_routing_info(dev->path.pci.devfn); + + if (!routing_info) + return; + + acpigen_write_name("_PRT"); + acpigen_write_PRT_PIC(routing_info); +} |