diff options
author | Raul E Rangel <rrangel@chromium.org> | 2021-05-07 10:47:34 -0600 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2021-05-09 18:08:20 +0000 |
commit | 6ddace437cba9a7e697437d7c7ccc4a779efd08f (patch) | |
tree | f0c7635a35355110a1d37a370c840b2b2cc491a0 /src | |
parent | 9b330fafebacee293a732e3c23dae6d6b04f57c5 (diff) |
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 <rrangel@chromium.org>
Change-Id: I1a8d988d125f407f0aa7bc1722d432446aa9aff8
Reviewed-on: https://review.coreboot.org/c/coreboot/+/53922
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/amd_pci_util.h | 27 | ||||
-rw-r--r-- | src/soc/amd/common/block/pci/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/amd/common/block/pci/pci_routing_info.c | 57 |
3 files changed, 85 insertions, 0 deletions
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 <amdblocks/amd_pci_util.h> +#include <console/console.h> +#include <device/pci_def.h> +#include <types.h> + +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; +} |