diff options
Diffstat (limited to 'src/soc/amd/common/block/pci/acpi_prt.c')
-rw-r--r-- | src/soc/amd/common/block/pci/acpi_prt.c | 206 |
1 files changed, 206 insertions, 0 deletions
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); +} |