From 4e80fae2367d3a0a64ac2896dc654e0cf842fc4e Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Wed, 16 Dec 2020 10:08:41 -0700 Subject: [PATCH] soc/amd/picasso: Correctly populate the PCI interrupt line register The PCI interrupt line registers are used as a last resort if routing can't be fetched from either ACPI or the MPTable. This change correctly sets the registers. It overrides the pirq_data set by the mainboards since the routing is fixed in AGESA. BUG=b:170595019 TEST=Boot ezkinil with `pci=nomsi,noacpi amd_iommu=off noapic` Verified all PCI peripherals are still functional. Signed-off-by: Raul E Rangel Change-Id: If5d4d8f613c8d0fa9b43cefa804824681c3410d6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/48665 Tested-by: build bot (Jenkins) Reviewed-by: Nikolai Vyssotski Reviewed-by: Felix Held Reviewed-by: Angel Pons --- src/soc/amd/picasso/fch.c | 4 +++ src/soc/amd/picasso/include/soc/pci.h | 8 +++++ src/soc/amd/picasso/pcie_gpp.c | 45 +++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/soc/amd/picasso/include/soc/pci.h diff --git a/src/soc/amd/picasso/fch.c b/src/soc/amd/picasso/fch.c index d5278cbd0f..4c8c584cbf 100644 --- a/src/soc/amd/picasso/fch.c +++ b/src/soc/amd/picasso/fch.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -259,6 +260,9 @@ static void set_pci_irqs(void *unused) /* Write PCI_INTR regs 0xC00/0xC01 */ write_pci_int_table(); + /* pirq_data is consumed by `write_pci_cfg_irqs` */ + populate_pirq_data(); + /* Write IRQs for all devicetree enabled devices */ write_pci_cfg_irqs(); } diff --git a/src/soc/amd/picasso/include/soc/pci.h b/src/soc/amd/picasso/include/soc/pci.h new file mode 100644 index 0000000000..b6ff3496c5 --- /dev/null +++ b/src/soc/amd/picasso/include/soc/pci.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef AMD_PICASSO_PCI_H +#define AMD_PICASSO_PCI_H + +void populate_pirq_data(void); + +#endif /* AMD_PICASSO_PCI_H */ diff --git a/src/soc/amd/picasso/pcie_gpp.c b/src/soc/amd/picasso/pcie_gpp.c index 1b651182a4..ca368f94b1 100644 --- a/src/soc/amd/picasso/pcie_gpp.c +++ b/src/soc/amd/picasso/pcie_gpp.c @@ -2,10 +2,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -34,6 +36,26 @@ static const struct pci_routing pci_routing_table[] = { {PCIE_GPP_B_DEVFN, 7, "CDAB"}, }; +/* + * This data structure is populated from the raw data above. It is used + * by amd/common/block/pci/amd_pci_util to write the PCI_INT_LINE register + * to each PCI device. + */ +static struct pirq_struct pirq_data[] = { + { PCIE_GPP_0_DEVFN }, + { PCIE_GPP_1_DEVFN }, + { PCIE_GPP_2_DEVFN }, + { PCIE_GPP_3_DEVFN }, + { PCIE_GPP_4_DEVFN }, + { PCIE_GPP_5_DEVFN }, + { PCIE_GPP_6_DEVFN }, + { PCIE_GPP_A_DEVFN }, + { PCIE_GPP_B_DEVFN }, +}; + +_Static_assert(ARRAY_SIZE(pci_routing_table) == ARRAY_SIZE(pirq_data), + "PCI and PIRQ tables must be the same size"); + static const struct pci_routing *get_pci_routing(unsigned int devfn) { for (size_t i = 0; i < ARRAY_SIZE(pci_routing_table); ++i) { @@ -53,6 +75,29 @@ static unsigned int calculate_irq(const struct pci_routing *pci_routing, unsigne return irq_index; } +void populate_pirq_data(void) +{ + const struct pci_routing *pci_routing; + struct pirq_struct *pirq; + unsigned int irq_index; + + for (size_t i = 0; i < ARRAY_SIZE(pirq_data); ++i) { + pirq = &pirq_data[i]; + pci_routing = get_pci_routing(pirq->devfn); + if (!pci_routing) + die("%s: devfn %u not found\n", __func__, pirq->devfn); + + for (size_t j = 0; j < 4; ++j) { + irq_index = calculate_irq(pci_routing, j); + + pirq->PIN[j] = irq_index % 8; + } + } + + pirq_data_ptr = pirq_data; + pirq_data_size = ARRAY_SIZE(pirq_data); +} + static const char *pcie_gpp_acpi_name(const struct device *dev) { if (dev->path.type != DEVICE_PATH_PCI)