Lean Sheng Tan has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85153?usp=email )
Change subject: soc/intel/xeon_sp: Improve PCI INTx IRQ routing for Gen6 ......................................................................
soc/intel/xeon_sp: Improve PCI INTx IRQ routing for Gen6
1. Route IRQ for on-chip end-points only (e.g. 00:1f.4 i801_smbus)
IRQ routing for devices under root ports needs additional swizzle per decided by root port configurations, which will postponed to later till there is actual usage.
2. Route IRQ based on FSP programmed end-point device ID <-> PIRQ mapping.
TESTED=Build and boot on intel/avenuecity CRB
Change-Id: Ibeb7c8fb3432e5cb240ac3b09c19d2c361e4b45a Signed-off-by: Shuo Liu shuo.liu@intel.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85153 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Angel Pons th3fanbus@gmail.com --- M src/soc/intel/xeon_sp/include/soc/irq.h M src/soc/intel/xeon_sp/lpc_gen6.c 2 files changed, 52 insertions(+), 7 deletions(-)
Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved
diff --git a/src/soc/intel/xeon_sp/include/soc/irq.h b/src/soc/intel/xeon_sp/include/soc/irq.h index 4d3ad7a..209f699 100644 --- a/src/soc/intel/xeon_sp/include/soc/irq.h +++ b/src/soc/intel/xeon_sp/include/soc/irq.h @@ -6,5 +6,6 @@ #define PCH_IRQ10 10 #define PCH_IRQ11 11 #define PCH_IRQ14 14 +#define PCH_IRQ16 16
#endif /* _SOC_IRQ_H_ */ diff --git a/src/soc/intel/xeon_sp/lpc_gen6.c b/src/soc/intel/xeon_sp/lpc_gen6.c index d4045a8..9455510 100644 --- a/src/soc/intel/xeon_sp/lpc_gen6.c +++ b/src/soc/intel/xeon_sp/lpc_gen6.c @@ -1,9 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h> +#include <device/pci.h> +#include <device/pci_ops.h> #include <intelblocks/itss.h> #include <intelblocks/lpc_lib.h> #include <intelblocks/pcr.h> +#include <soc/irq.h> #include <soc/pcr_ids.h>
#include <acpi/acpigen.h> @@ -30,15 +33,56 @@ acpigen_write_scope_end(); /* Scope */ }
+uint32_t itss_soc_get_on_chip_dev_pir(const struct device *dev) +{ + assert(is_pci(dev)); + return PCI_ITSS_PIR(PCI_SLOT(dev->path.pci.devfn)); +} + +static void soc_itss_route_irq(const struct device *irq_dev, uint8_t int_pin) +{ + uint8_t pirq = itss_get_on_chip_dev_pirq(irq_dev, int_pin); + if (pirq == PIRQ_INVALID) + return; + + uint8_t pirq_rout = pcr_read8(PID_ITSS, + PCR_ITSS_PIRQA_ROUT + pirq_idx(pirq)); + uint8_t int_line = (pirq_rout & 0x80) ? pirq_idx(pirq) + PCH_IRQ16 : pirq_rout & 0xf; + + printk(BIOS_SPEW, "routing irq: dev %s, pin %d, pirq %d, intline %d\n", + dev_path(irq_dev), int_pin, pirq, int_line); + pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line); +} + +static void soc_pch_pirq_init(void) +{ + /* Program irq pin/line for PCI devices using 8259 compatible mode */ + size_t pirq_routes; + const uint8_t *pirq_routing_legacy = lpc_get_pic_pirq_routing(&pirq_routes); + + itss_irq_init(pirq_routing_legacy); + for (int i = 0; i < PIRQ_COUNT; i++) + itss_set_irq_polarity(pirq_routing_legacy[i], 1); + + /* Route irq for end-points */ + struct device *domain = NULL; + while ((domain = dev_find_path(domain, DEVICE_PATH_DOMAIN))) { + struct device *irq_dev = NULL; + while ((irq_dev = dev_bus_each_child(domain->downstream, irq_dev))) { + if (!is_enabled_pci(irq_dev)) + continue; + uint8_t int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + if (int_pin < PCI_INT_A || int_pin > PCI_INT_D) + continue; + + soc_itss_route_irq(irq_dev, int_pin); + } + } +} + void lpc_soc_init(struct device *dev) { printk(BIOS_SPEW, "pch: lpc_init\n");
- /* Program irq pin/line for PCI devices by PCH convention */ - pch_pirq_init(); - - /* Explicitly set polarity low for PIRQA to PIRQH */ - for (int i = 0; i < PIRQ_COUNT; i++) { - itss_set_irq_polarity(pcr_read8(PID_ITSS, PCR_ITSS_PIRQA_ROUT + i), 1); - } + soc_pch_pirq_init(); }