<p>Tobias Diedrich has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22810">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">[draft] sb/intel/common: Automatically generate ACPI PIRQ<br><br>Based on https://review.coreboot.org/#/c/22803/<br><br>This function generates PIRQ ACPI tables automatically based on the<br>chipset registers.<br><br>Linux 4.13.14 /proc/interrupts:<br> CPU0 CPU1<br> 0: 24 0 IO-APIC 2-edge timer<br> 8: 1 0 IO-APIC 8-edge rtc0<br> 9: 0 0 IO-APIC 9-fasteoi acpi<br> 19: 86 0 IO-APIC 19-fasteoi ehci_hcd:usb1<br> 23: 0 0 IO-APIC 23-fasteoi i801_smbus<br> 24: 0 0 PCI-MSI 458752-edge PCIe PME<br> 25: 0 0 PCI-MSI 460800-edge PCIe PME<br> 26: 0 0 PCI-MSI 462848-edge PCIe PME<br> 27: 166 0 PCI-MSI 32768-edge i915<br> 28: 3953 0 PCI-MSI 512000-edge ahci[0000:00:1f.2]<br> 29: 656 0 PCI-MSI 409600-edge eno1<br> 30: 83 0 PCI-MSI 442368-edge snd_hda_intel:card0<br>[...]<br><br>Bootlog:<br>PCI: 00:00.0: no pin<br>PCI: 00:01.0: no pin<br>slot=2 or pin1 out of bounds<br>PCI: 00:02.0: pin=1 pirq=0<br>PCI: 00:16.0: no pin<br>PCI: 00:16.1: no pin<br>PCI: 00:16.2: no pin<br>PCI: 00:16.3: no pin<br>PCI: 00:19.0: no pin<br>PCI: 00:1a.0: no pin<br>slot=27 reg=0x3148 val=0x1070<br>PCI: 00:1b.0: pin=1 pirq=1<br>slot=28 reg=0x3146 val=0x4351<br>PCI: 00:1c.0: pin=1 pirq=2<br>slot=28 reg=0x3146 val=0x4351<br>PCI: 00:1c.1: pin=2 pirq=6<br>slot=28 reg=0x3146 val=0x4351<br>PCI: 00:1c.2: pin=3 pirq=4<br>PCI: 00:1c.3: no pin<br>PCI: 00:1c.4: no pin<br>PCI: 00:1c.5: no pin<br>PCI: 00:1c.6: no pin<br>PCI: 00:1c.7: no pin<br>slot=29 reg=0x3144 val=0x6543<br>PCI: 00:1d.0: pin=1 pirq=4<br>PCI: 00:1e.0: no pin<br>PCI: 00:1f.0: no pin<br>slot=31 reg=0x3140 val=0x2071<br>PCI: 00:1f.2: pin=1 pirq=2<br>slot=31 reg=0x3140 val=0x2071<br>PCI: 00:1f.3: pin=2 pirq=8<br>PCI: 00:1f.5: no pin<br>PCI: 00:1f.6: no pin<br>slot=4 or pin1 out of bounds<br>PCI: 00:04.0: pin=1 pirq=0<br>num_devs=7<br><br>Generated _PRT:<br> Scope (\_SB.PCI0)<br> {<br> Method (_PRT, 0, NotSerialized) // _PRT: PCI Routing Table<br> {<br> If (PICM)<br> {<br> Return (Package (0x07)<br> {<br> Package (0x04)<br> {<br> 0x001BFFFF,<br> 0x00000000,<br> 0x00000000,<br> 0x00000010<br> },<br><br> Package (0x04)<br> {<br> 0x001CFFFF,<br> 0x00000000,<br> 0x00000000,<br> 0x00000011<br> },<br><br> Package (0x04)<br> {<br> 0x001CFFFF,<br> 0x00000001,<br> 0x00000000,<br> 0x00000015<br> },<br><br> Package (0x04)<br> {<br> 0x001CFFFF,<br> 0x00000002,<br> 0x00000000,<br> 0x00000013<br> },<br><br> Package (0x04)<br> {<br> 0x001DFFFF,<br> 0x00000000,<br> 0x00000000,<br> 0x00000013<br> },<br><br> Package (0x04)<br> {<br> 0x001FFFFF,<br> 0x00000000,<br> 0x00000000,<br> 0x00000011<br> },<br><br> Package (0x04)<br> {<br> 0x001FFFFF,<br> 0x00000001,<br> 0x00000000,<br> 0x00000017<br> }<br> })<br> }<br> Else<br> {<br> Return (Package (0x07)<br> {<br> Package (0x04)<br> {<br> 0x001BFFFF,<br> 0x00000000,<br> \_SB.PCI0.LPCB.LNKA,<br> 0x00000000<br> },<br><br> Package (0x04)<br> {<br> 0x001CFFFF,<br> 0x00000000,<br> \_SB.PCI0.LPCB.LNKB,<br> 0x00000000<br> },<br><br> Package (0x04)<br> {<br> 0x001CFFFF,<br> 0x00000001,<br> \_SB.PCI0.LPCB.LNKF,<br> 0x00000000<br> },<br><br> Package (0x04)<br> {<br> 0x001CFFFF,<br> 0x00000002,<br> \_SB.PCI0.LPCB.LNKD,<br> 0x00000000<br> },<br><br> Package (0x04)<br> {<br> 0x001DFFFF,<br> 0x00000000,<br> \_SB.PCI0.LPCB.LNKD,<br> 0x00000000<br> },<br><br> Package (0x04)<br> {<br> 0x001FFFFF,<br> 0x00000000,<br> \_SB.PCI0.LPCB.LNKB,<br> 0x00000000<br> },<br><br> Package (0x04)<br> {<br> 0x001FFFFF,<br> 0x00000001,<br> \_SB.PCI0.LPCB.LNKH,<br> 0x00000000<br> }<br> })<br> }<br> }<br> }<br>}<br><br>Change-Id: Ic6b8ce4a9db50211a9c26221ca10105c5a0829a0<br>Signed-off-by: Tobias Diedrich <ranma+coreboot@tdiedrich.de><br>---<br>M src/southbridge/intel/bd82x6x/Kconfig<br>M src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl<br>M src/southbridge/intel/bd82x6x/lpc.c<br>M src/southbridge/intel/common/Kconfig<br>M src/southbridge/intel/common/Makefile.inc<br>A src/southbridge/intel/common/acpi_pirq_gen.c<br>A src/southbridge/intel/common/acpi_pirq_gen.h<br>7 files changed, 179 insertions(+), 61 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/10/22810/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/southbridge/intel/bd82x6x/Kconfig b/src/southbridge/intel/bd82x6x/Kconfig<br>index fe1ca34..2266a48 100644<br>--- a/src/southbridge/intel/bd82x6x/Kconfig<br>+++ b/src/southbridge/intel/bd82x6x/Kconfig<br>@@ -25,6 +25,7 @@<br> def_bool y<br> select ACPI_INTEL_HARDWARE_SLEEP_VALUES<br> select SOUTHBRIDGE_INTEL_COMMON<br>+ select SOUTHBRIDGE_INTEL_COMMON_PIRQ_ACPI_GEN<br> select SOUTHBRIDGE_INTEL_COMMON_SMBUS<br> select SOUTHBRIDGE_INTEL_COMMON_SPI<br> select IOAPIC<br>diff --git a/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl b/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl<br>index 0e6f960..c40f260 100644<br>--- a/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl<br>+++ b/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl<br>@@ -14,64 +14,4 @@<br> * GNU General Public License for more details.<br> */<br> <br>-/* PCI Interrupt Routing */<br>-Method(_PRT)<br>-{<br>- If (PICM) {<br>- Return (Package() {<br>- /* Onboard graphics (IGD) 0:2.0 */<br>- Package() { 0x0002ffff, 0, 0, 16 },/* GFX INTA -> PIRQA (MSI) */<br>- /* PCI Express Graphics (PEG) 0:1.0 */<br>- Package() { 0x0001ffff, 0, 0, 16 },/* GFX PCIe INTA -> PIRQA (MSI) */<br>- Package() { 0x0001ffff, 0, 0, 17 },/* GFX PCIe INTB -> PIRQB (MSI) */<br>- Package() { 0x0001ffff, 0, 0, 18 },/* GFX PCIe INTC -> PIRQC (MSI) */<br>- Package() { 0x0001ffff, 0, 0, 19 },/* GFX PCIe INTD -> PIRQD (MSI) */<br>- /* XHCI 0:14.0 (ivy only) */<br>- Package() { 0x0014ffff, 0, 0, 19 },<br>- /* High Definition Audio 0:1b.0 */<br>- Package() { 0x001bffff, 0, 0, 16 },/* D27IP_ZIP HDA INTA -> PIRQA (MSI) */<br>- /* PCIe Root Ports 0:1c.x */<br>- Package() { 0x001cffff, 0, 0, 17 },/* D28IP_P1IP PCIe INTA -> PIRQB */<br>- Package() { 0x001cffff, 1, 0, 21 },/* D28IP_P2IP PCIe INTB -> PIRQF */<br>- Package() { 0x001cffff, 2, 0, 19 },/* D28IP_P3IP PCIe INTC -> PIRQD */<br>- Package() { 0x001cffff, 3, 0, 20 },/* D28IP_P3IP PCIe INTD -> PIRQE */<br>- /* EHCI #1 0:1d.0 */<br>- Package() { 0x001dffff, 0, 0, 19 },/* D29IP_E1P EHCI1 INTA -> PIRQD */<br>- /* EHCI #2 0:1a.0 */<br>- Package() { 0x001affff, 0, 0, 21 },/* D26IP_E2P EHCI2 INTA -> PIRQF */<br>- /* LPC devices 0:1f.0 */<br>- Package() { 0x001fffff, 0, 0, 17 }, /* D31IP_SIP SATA INTA -> PIRQB (MSI) */<br>- Package() { 0x001fffff, 1, 0, 23 }, /* D31IP_SMIP SMBUS INTB -> PIRQH */<br>- Package() { 0x001fffff, 2, 0, 16 }, /* D31IP_TTIP THRT INTC -> PIRQA */<br>- Package() { 0x001fffff, 3, 0, 18 },<br>- })<br>- } Else {<br>- Return (Package() {<br>- /* Onboard graphics (IGD) 0:2.0 */<br>- Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },<br>- /* PCI Express Graphics (PEG) 0:1.0 */<br>- Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },<br>- Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },<br>- Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 },<br>- Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },<br>- /* XHCI 0:14.0 (ivy only) */<br>- Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },<br>- /* High Definition Audio 0:1b.0 */<br>- Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },<br>- /* PCIe Root Ports 0:1c.x */<br>- Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },<br>- Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKF, 0 },<br>- Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKD, 0 },<br>- Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKE, 0 },<br>- /* EHCI #1 0:1d.0 */<br>- Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },<br>- /* EHCI #2 0:1a.0 */<br>- Package() { 0x001affff, 0, \_SB.PCI0.LPCB.LNKF, 0 },<br>- /* LPC device 0:1f.0 */<br>- Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },<br>- Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKH, 0 },<br>- Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKA, 0 },<br>- Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKC, 0 },<br>- })<br>- }<br>-}<br>+/* PCI Interrupt Routing is generated */<br>diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c<br>index 2bfc1e3..5224469 100644<br>--- a/src/southbridge/intel/bd82x6x/lpc.c<br>+++ b/src/southbridge/intel/bd82x6x/lpc.c<br>@@ -35,6 +35,7 @@<br> #include "pch.h"<br> #include "nvs.h"<br> #include <southbridge/intel/common/pciehp.h><br>+#include <southbridge/intel/common/acpi_pirq_gen.h><br> <br> #define NMI_OFF 0<br> <br>@@ -815,12 +816,42 @@<br> return "LPCB";<br> }<br> <br>+static const u32 pirq_dir_route_reg[] = {<br>+ D20IR, 0, D22IR, 0, 0, D25IR, D26IR, D27IR, D28IR, D29IR, 0, D31IR,<br>+};<br>+<br>+u8 intel_common_map_pirq(device_t dev, u8 pci_pin)<br>+{<br>+ u8 slot = PCI_SLOT(dev->path.pci.devfn);<br>+ u8 shift = 4 * (pci_pin - 1);<br>+ u8 pirq;<br>+ u32 reg;<br>+<br>+ if (slot < 20 || slot > 31 || pci_pin < 1 || pci_pin > 4) {<br>+ printk(BIOS_DEBUG, "slot=%d or pin%d out of bounds\n",<br>+ slot, pci_pin);<br>+ return 0;<br>+ }<br>+<br>+ reg = pirq_dir_route_reg[slot - 20];<br>+ printk(BIOS_DEBUG, "slot=%d reg=0x%04x val=0x%04x\n",<br>+ slot, reg, RCBA16(reg));<br>+<br>+ pirq = ((RCBA16(reg) >> shift) & 0xf);<br>+ if (pirq > 8) {<br>+ printk(BIOS_DEBUG, "pirq=%d out of bounds\n", pirq);<br>+ return 0;<br>+ }<br>+ return 1 + pirq;<br>+}<br>+<br> static void southbridge_fill_ssdt(device_t device)<br> {<br> device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));<br> config_t *chip = dev->chip_info;<br> <br> intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);<br>+ intel_acpi_gen_def_acpi_pirq(dev);<br> }<br> <br> static void lpc_final(struct device *dev)<br>diff --git a/src/southbridge/intel/common/Kconfig b/src/southbridge/intel/common/Kconfig<br>index 6ce6b33..f6a0180 100644<br>--- a/src/southbridge/intel/common/Kconfig<br>+++ b/src/southbridge/intel/common/Kconfig<br>@@ -15,6 +15,9 @@<br> config HAVE_INTEL_CHIPSET_LOCKDOWN<br> def_bool n<br> <br>+config SOUTHBRIDGE_INTEL_COMMON_PIRQ_ACPI_GEN<br>+ def_bool n<br>+<br> config INTEL_CHIPSET_LOCKDOWN<br> depends on HAVE_INTEL_CHIPSET_LOCKDOWN && HAVE_SMI_HANDLER && !CHROMEOS<br> #ChromeOS's payload seems to handle finalization on its on.<br>diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc<br>index 0128505..13150d9 100644<br>--- a/src/southbridge/intel/common/Makefile.inc<br>+++ b/src/southbridge/intel/common/Makefile.inc<br>@@ -33,4 +33,6 @@<br> smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c<br> endif<br> <br>+ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_PIRQ_ACPI_GEN) += acpi_pirq_gen.c<br>+<br> endif<br>diff --git a/src/southbridge/intel/common/acpi_pirq_gen.c b/src/southbridge/intel/common/acpi_pirq_gen.c<br>new file mode 100644<br>index 0000000..17d9d09<br>--- /dev/null<br>+++ b/src/southbridge/intel/common/acpi_pirq_gen.c<br>@@ -0,0 +1,119 @@<br>+/*<br>+ * This file is part of the coreboot project.<br>+ *<br>+ * Copyright (C) 2017 Arthur Heymans <arthur@aheymans.xyz><br>+ *<br>+ * This program is free software; you can redistribute it and/or modify<br>+ * it under the terms of the GNU General Public License as published by<br>+ * the Free Software Foundation; version 2 of the License.<br>+ *<br>+ * This program is distributed in the hope that it will be useful,<br>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>+ * GNU General Public License for more details.<br>+ */<br>+<br>+#include <arch/acpigen.h><br>+#include <arch/io.h><br>+#include <console/console.h><br>+#include <device/pci_def.h><br>+#include <string.h><br>+<br>+#include "acpi_pirq_gen.h"<br>+<br>+enum emit_type {<br>+ EMIT_NONE,<br>+ EMIT_APIC,<br>+ EMIT_PICM,<br>+};<br>+<br>+static int enumerate_root_pci_pins(enum emit_type emit, const char *lpcb_path)<br>+{<br>+ static char buffer[DEVICE_PATH_MAX];<br>+ device_t dev;<br>+ u8 prev_int_pin = 0;<br>+ u8 prev_pci_dev = 0;<br>+ int num_devs = 0;<br>+<br>+ for (dev = all_devices; dev; dev = dev->next) {<br>+ u8 pci_dev;<br>+ u8 int_pin;<br>+ u8 pirq;<br>+<br>+ if (dev->path.type != DEVICE_PATH_PCI ||<br>+ dev->bus->secondary != 0)<br>+ continue;<br>+<br>+ pci_dev = PCI_SLOT(dev->path.pci.devfn);<br>+ int_pin = pci_read_config8(dev, PCI_INTERRUPT_PIN);<br>+<br>+ if (int_pin == 0 || int_pin > 4) {<br>+ printk(BIOS_DEBUG, "%s: no pin\n", dev_path(dev));<br>+ continue;<br>+ }<br>+<br>+ pirq = intel_common_map_pirq(dev, int_pin);<br>+<br>+ printk(BIOS_DEBUG, "%s: pin=%d pirq=%d\n",<br>+ dev_path(dev), int_pin, pirq);<br>+<br>+ if (pirq == 0)<br>+ continue;<br>+<br>+ /* Avoid duplicate entries */<br>+ if (prev_pci_dev == pci_dev && prev_int_pin == int_pin) {<br>+ continue;<br>+ } else {<br>+ prev_int_pin = int_pin;<br>+ prev_pci_dev = pci_dev;<br>+ }<br>+ if (emit != EMIT_NONE) {<br>+ acpigen_write_package(4);<br>+ acpigen_write_dword((pci_dev << 16) | 0xffff);<br>+ acpigen_write_dword(int_pin - 1);<br>+ if (emit == EMIT_APIC) {<br>+ acpigen_write_dword(0);<br>+ acpigen_write_dword(16 + (pirq - 1));<br>+ } else {<br>+ snprintf(buffer, sizeof(buffer),<br>+ "%s.LNK%c", lpcb_path, 'A' + pirq - 1);<br>+ printk(BIOS_DEBUG, "path=%s\n", buffer);<br>+ acpigen_emit_namestring(buffer);<br>+ acpigen_write_dword(0);<br>+ }<br>+ acpigen_pop_len();<br>+ }<br>+ num_devs++;<br>+ }<br>+ return num_devs;<br>+}<br>+<br>+void intel_acpi_gen_def_acpi_pirq(device_t dev)<br>+{<br>+ const char *lpcb_path = acpi_device_path(dev);<br>+ int num_devs = enumerate_root_pci_pins(EMIT_NONE, lpcb_path);<br>+<br>+ if (!lpcb_path) {<br>+ printk(BIOS_ERR, "Missing LPCB ACPI path\n");<br>+ return;<br>+ }<br>+ printk(BIOS_INFO, "num_devs=%d\n", num_devs);<br>+<br>+ acpigen_write_scope("\\_SB.PCI0");<br>+ acpigen_write_method("_PRT", 0);<br>+ acpigen_write_if();<br>+ acpigen_emit_namestring("PICM");<br>+ acpigen_emit_byte(RETURN_OP);<br>+ acpigen_write_package(num_devs);<br>+ enumerate_root_pci_pins(EMIT_APIC, lpcb_path);<br>+ acpigen_pop_len(); /* package */<br>+ acpigen_pop_len(); /* if PICM */<br>+ acpigen_write_else();<br>+ acpigen_emit_byte(RETURN_OP);<br>+ acpigen_write_package(num_devs);<br>+ enumerate_root_pci_pins(EMIT_PICM, lpcb_path);<br>+ acpigen_pop_len(); /* package */<br>+ acpigen_pop_len(); /* else PICM */<br>+ acpigen_pop_len(); /* _PRT */<br>+ acpigen_pop_len(); /* \_SB */<br>+}<br>diff --git a/src/southbridge/intel/common/acpi_pirq_gen.h b/src/southbridge/intel/common/acpi_pirq_gen.h<br>new file mode 100644<br>index 0000000..d5c68f7<br>--- /dev/null<br>+++ b/src/southbridge/intel/common/acpi_pirq_gen.h<br>@@ -0,0 +1,22 @@<br>+/*<br>+ * This file is part of the coreboot project.<br>+ *<br>+ * Copyright (C) 2017 Arthur Heymans <arthur@aheymans.xyz><br>+ *<br>+ * This program is free software; you can redistribute it and/or modify<br>+ * it under the terms of the GNU General Public License as published by<br>+ * the Free Software Foundation; version 2 of the License.<br>+ *<br>+ * This program is distributed in the hope that it will be useful,<br>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>+ * GNU General Public License for more details.<br>+ */<br>+<br>+#ifndef INTEL_COMMON_ACPI_PIRQ_GEN_H<br>+#define INTEL_COMMON_ACPI_PIRQ_GEN_H<br>+<br>+void intel_acpi_gen_def_acpi_pirq(device_t dev);<br>+u8 intel_common_map_pirq(device_t dev, u8 int_pin);<br>+<br>+#endif<br></pre><p>To view, visit <a href="https://review.coreboot.org/22810">change 22810</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/22810"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ic6b8ce4a9db50211a9c26221ca10105c5a0829a0 </div>
<div style="display:none"> Gerrit-Change-Number: 22810 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Tobias Diedrich <ranma+coreboot@tdiedrich.de> </div>