From 6ddace437cba9a7e697437d7c7ccc4a779efd08f Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Fri, 7 May 2021 10:47:34 -0600 Subject: [PATCH] soc/amd/common/block/pci: Introduce struct pci_routing_info This struct is similar to `struct pci_routing` defined in picasso/pcie_gpp.c. It additionally contains the irq used for the bridge and is structured in a way that the FSP can provide via HOB. The next set of CLs will migrate the pci routing functions used by picasso into common and enable pci routing table generation for cezanne. BUG=b:184766519 TEST=Build guybrush Signed-off-by: Raul E Rangel Change-Id: I1a8d988d125f407f0aa7bc1722d432446aa9aff8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/53922 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- .../block/include/amdblocks/amd_pci_util.h | 27 +++++++++ src/soc/amd/common/block/pci/Makefile.inc | 1 + .../amd/common/block/pci/pci_routing_info.c | 57 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 src/soc/amd/common/block/pci/pci_routing_info.c 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 081741ad28..b9cd1406c9 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 @@ -31,7 +31,34 @@ void write_pci_cfg_irqs(void); void write_pci_int_table(void); const struct irq_idx_name *sb_get_apic_reg_association(size_t *size); +enum pci_routing_swizzle { + PCI_SWIZZLE_ABCD = 0, + PCI_SWIZZLE_BCDA, + PCI_SWIZZLE_CDAB, + PCI_SWIZZLE_DABC, +}; + +/** + * Each PCI bridge has its INTx lines routed to one of the GNB IO-APIC PCI + * groups. Each group has 4 interrupts. The INTx lines can be swizzled before + * being routed to the IO-APIC. If the IO-APIC redirection entry is masked, the + * interrupt is reduced modulo 8 onto INT[A-H] and forwarded to the FCH IO-APIC. + **/ +struct pci_routing_info { + uint8_t devfn; + uint8_t group; + uint8_t swizzle; + uint8_t irq; +} __packed; + /* Implemented by the SoC */ void populate_pirq_data(void); +/* Implemented by the SoC */ +const struct pci_routing_info *get_pci_routing_table(size_t *entries); + +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); + #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 78453d464f..5df641b1d9 100644 --- a/src/soc/amd/common/block/pci/Makefile.inc +++ b/src/soc/amd/common/block/pci/Makefile.inc @@ -1,4 +1,5 @@ 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_MMCONF),y) diff --git a/src/soc/amd/common/block/pci/pci_routing_info.c b/src/soc/amd/common/block/pci/pci_routing_info.c new file mode 100644 index 0000000000..e0a696442e --- /dev/null +++ b/src/soc/amd/common/block/pci/pci_routing_info.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +enum pcie_swizzle_pin { + PIN_A, + PIN_B, + PIN_C, + PIN_D, +}; + +static const uint8_t pcie_swizzle_table[][4] = { + {PIN_A, PIN_B, PIN_C, PIN_D}, + {PIN_B, PIN_C, PIN_D, PIN_A}, + {PIN_C, PIN_D, PIN_A, PIN_B}, + {PIN_D, PIN_A, PIN_B, PIN_C}, +}; + +const struct pci_routing_info *get_pci_routing_info(unsigned int devfn) +{ + const struct pci_routing_info *routing_info; + size_t entries = 0; + + routing_info = get_pci_routing_table(&entries); + + if (!routing_info || !entries) + return NULL; + + for (size_t i = 0; i < entries; ++i, ++routing_info) + if (routing_info->devfn == devfn) + return routing_info; + + printk(BIOS_ERR, "Failed to find PCIe routing info for dev: %#x, fn: %#x\n", + PCI_SLOT(devfn), PCI_FUNC(devfn)); + + return NULL; +} + +unsigned int pci_calculate_irq(const struct pci_routing_info *routing_info, + unsigned int pin) +{ + unsigned int irq; + + if (routing_info->swizzle >= ARRAY_SIZE(pcie_swizzle_table)) + die("%s: swizzle %u out of bounds\n", __func__, routing_info->swizzle); + + if (pin >= ARRAY_SIZE(pcie_swizzle_table[routing_info->swizzle])) + die("%s: pin %u out of bounds\n", __func__, pin); + + irq = routing_info->group * 4; + irq += pcie_swizzle_table[routing_info->swizzle][pin]; + + return irq; +}