blob: c142f575677a9156952d979b508cce78d87de459 [file] [log] [blame]
/* 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 <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);
}