soc/amd/common/block/pci: Implement acpigen_write_pci_{GNB,FCH}_PRT

This is loosely based off of picasso/pcie_gpp.c. This version uses the
acpigen_write_PRT_X methods to write the actual records. There are also
two functions, 1 for using the GNB, and one for using the FCH. The FCH
one is useful when the GNB IO-APIC has not been initialized.

BUG=b:184766519
TEST=Dump guybrush ACPI and verify it looks correct

Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Change-Id: I926430074acb969ceb11fdb60ab56dcf91ac4c76
Reviewed-on: https://review.coreboot.org/c/coreboot/+/52917
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
Raul E Rangel 2021-05-07 14:25:09 -06:00 committed by Felix Held
parent 1d1dbc4cfa
commit 7502e10fdf
3 changed files with 217 additions and 2 deletions

View File

@ -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 */

View File

@ -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)

View File

@ -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);
}