[coreboot-gerrit] Change in coreboot[master]: [draft] sb/intel/common: Automatically generate ACPI PIRQ

Tobias Diedrich (Code Review) gerrit at coreboot.org
Sun Dec 10 21:42:56 CET 2017


Tobias Diedrich has uploaded this change for review. ( https://review.coreboot.org/22810


Change subject: [draft] sb/intel/common: Automatically generate ACPI PIRQ
......................................................................

[draft] sb/intel/common: Automatically generate ACPI PIRQ

Based on https://review.coreboot.org/#/c/22803/

This function generates PIRQ ACPI tables automatically based on the
chipset registers.

Linux 4.13.14 /proc/interrupts:
           CPU0       CPU1
  0:         24          0   IO-APIC   2-edge      timer
  8:          1          0   IO-APIC   8-edge      rtc0
  9:          0          0   IO-APIC   9-fasteoi   acpi
 19:         86          0   IO-APIC  19-fasteoi   ehci_hcd:usb1
 23:          0          0   IO-APIC  23-fasteoi   i801_smbus
 24:          0          0   PCI-MSI 458752-edge      PCIe PME
 25:          0          0   PCI-MSI 460800-edge      PCIe PME
 26:          0          0   PCI-MSI 462848-edge      PCIe PME
 27:        166          0   PCI-MSI 32768-edge      i915
 28:       3953          0   PCI-MSI 512000-edge      ahci[0000:00:1f.2]
 29:        656          0   PCI-MSI 409600-edge      eno1
 30:         83          0   PCI-MSI 442368-edge      snd_hda_intel:card0
[...]

Bootlog:
PCI: 00:00.0: no pin
PCI: 00:01.0: no pin
slot=2 or pin1 out of bounds
PCI: 00:02.0: pin=1 pirq=0
PCI: 00:16.0: no pin
PCI: 00:16.1: no pin
PCI: 00:16.2: no pin
PCI: 00:16.3: no pin
PCI: 00:19.0: no pin
PCI: 00:1a.0: no pin
slot=27 reg=0x3148 val=0x1070
PCI: 00:1b.0: pin=1 pirq=1
slot=28 reg=0x3146 val=0x4351
PCI: 00:1c.0: pin=1 pirq=2
slot=28 reg=0x3146 val=0x4351
PCI: 00:1c.1: pin=2 pirq=6
slot=28 reg=0x3146 val=0x4351
PCI: 00:1c.2: pin=3 pirq=4
PCI: 00:1c.3: no pin
PCI: 00:1c.4: no pin
PCI: 00:1c.5: no pin
PCI: 00:1c.6: no pin
PCI: 00:1c.7: no pin
slot=29 reg=0x3144 val=0x6543
PCI: 00:1d.0: pin=1 pirq=4
PCI: 00:1e.0: no pin
PCI: 00:1f.0: no pin
slot=31 reg=0x3140 val=0x2071
PCI: 00:1f.2: pin=1 pirq=2
slot=31 reg=0x3140 val=0x2071
PCI: 00:1f.3: pin=2 pirq=8
PCI: 00:1f.5: no pin
PCI: 00:1f.6: no pin
slot=4 or pin1 out of bounds
PCI: 00:04.0: pin=1 pirq=0
num_devs=7

Generated _PRT:
    Scope (\_SB.PCI0)
    {
        Method (_PRT, 0, NotSerialized)  // _PRT: PCI Routing Table
        {
            If (PICM)
            {
                Return (Package (0x07)
                {
                    Package (0x04)
                    {
                        0x001BFFFF,
                        0x00000000,
                        0x00000000,
                        0x00000010
                    },

                    Package (0x04)
                    {
                        0x001CFFFF,
                        0x00000000,
                        0x00000000,
                        0x00000011
                    },

                    Package (0x04)
                    {
                        0x001CFFFF,
                        0x00000001,
                        0x00000000,
                        0x00000015
                    },

                    Package (0x04)
                    {
                        0x001CFFFF,
                        0x00000002,
                        0x00000000,
                        0x00000013
                    },

                    Package (0x04)
                    {
                        0x001DFFFF,
                        0x00000000,
                        0x00000000,
                        0x00000013
                    },

                    Package (0x04)
                    {
                        0x001FFFFF,
                        0x00000000,
                        0x00000000,
                        0x00000011
                    },

                    Package (0x04)
                    {
                        0x001FFFFF,
                        0x00000001,
                        0x00000000,
                        0x00000017
                    }
                })
            }
            Else
            {
                Return (Package (0x07)
                {
                    Package (0x04)
                    {
                        0x001BFFFF,
                        0x00000000,
                        \_SB.PCI0.LPCB.LNKA,
                        0x00000000
                    },

                    Package (0x04)
                    {
                        0x001CFFFF,
                        0x00000000,
                        \_SB.PCI0.LPCB.LNKB,
                        0x00000000
                    },

                    Package (0x04)
                    {
                        0x001CFFFF,
                        0x00000001,
                        \_SB.PCI0.LPCB.LNKF,
                        0x00000000
                    },

                    Package (0x04)
                    {
                        0x001CFFFF,
                        0x00000002,
                        \_SB.PCI0.LPCB.LNKD,
                        0x00000000
                    },

                    Package (0x04)
                    {
                        0x001DFFFF,
                        0x00000000,
                        \_SB.PCI0.LPCB.LNKD,
                        0x00000000
                    },

                    Package (0x04)
                    {
                        0x001FFFFF,
                        0x00000000,
                        \_SB.PCI0.LPCB.LNKB,
                        0x00000000
                    },

                    Package (0x04)
                    {
                        0x001FFFFF,
                        0x00000001,
                        \_SB.PCI0.LPCB.LNKH,
                        0x00000000
                    }
                })
            }
        }
    }
}

Change-Id: Ic6b8ce4a9db50211a9c26221ca10105c5a0829a0
Signed-off-by: Tobias Diedrich <ranma+coreboot at tdiedrich.de>
---
M src/southbridge/intel/bd82x6x/Kconfig
M src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl
M src/southbridge/intel/bd82x6x/lpc.c
M src/southbridge/intel/common/Kconfig
M src/southbridge/intel/common/Makefile.inc
A src/southbridge/intel/common/acpi_pirq_gen.c
A src/southbridge/intel/common/acpi_pirq_gen.h
7 files changed, 179 insertions(+), 61 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/10/22810/1

diff --git a/src/southbridge/intel/bd82x6x/Kconfig b/src/southbridge/intel/bd82x6x/Kconfig
index fe1ca34..2266a48 100644
--- a/src/southbridge/intel/bd82x6x/Kconfig
+++ b/src/southbridge/intel/bd82x6x/Kconfig
@@ -25,6 +25,7 @@
 	def_bool y
 	select ACPI_INTEL_HARDWARE_SLEEP_VALUES
 	select SOUTHBRIDGE_INTEL_COMMON
+	select SOUTHBRIDGE_INTEL_COMMON_PIRQ_ACPI_GEN
 	select SOUTHBRIDGE_INTEL_COMMON_SMBUS
 	select SOUTHBRIDGE_INTEL_COMMON_SPI
 	select IOAPIC
diff --git a/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl b/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl
index 0e6f960..c40f260 100644
--- a/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl
+++ b/src/southbridge/intel/bd82x6x/acpi/default_irq_route.asl
@@ -14,64 +14,4 @@
  * GNU General Public License for more details.
  */
 
-/* PCI Interrupt Routing */
-Method(_PRT)
-{
-	If (PICM) {
-		Return (Package() {
-			/* Onboard graphics (IGD)	0:2.0 */
-			Package() { 0x0002ffff, 0, 0, 16 },/*  GFX                INTA -> PIRQA (MSI) */
-			/* PCI Express Graphics (PEG)	0:1.0 */
-			Package() { 0x0001ffff, 0, 0, 16 },/*  GFX         PCIe   INTA -> PIRQA (MSI) */
-			Package() { 0x0001ffff, 0, 0, 17 },/*  GFX         PCIe   INTB -> PIRQB (MSI) */
-			Package() { 0x0001ffff, 0, 0, 18 },/*  GFX         PCIe   INTC -> PIRQC (MSI) */
-			Package() { 0x0001ffff, 0, 0, 19 },/*  GFX         PCIe   INTD -> PIRQD (MSI) */
-			/* XHCI	0:14.0 (ivy only) */
-			Package() { 0x0014ffff, 0, 0, 19 },
-			/* High Definition Audio	0:1b.0 */
-			Package() { 0x001bffff, 0, 0, 16 },/*  D27IP_ZIP   HDA    INTA -> PIRQA (MSI) */
-			/* PCIe Root Ports		0:1c.x */
-			Package() { 0x001cffff, 0, 0, 17 },/*  D28IP_P1IP  PCIe   INTA -> PIRQB */
-			Package() { 0x001cffff, 1, 0, 21 },/*  D28IP_P2IP  PCIe   INTB -> PIRQF */
-			Package() { 0x001cffff, 2, 0, 19 },/*  D28IP_P3IP  PCIe   INTC -> PIRQD */
-			Package() { 0x001cffff, 3, 0, 20 },/*  D28IP_P3IP  PCIe   INTD -> PIRQE */
-			/* EHCI	#1			0:1d.0 */
-			Package() { 0x001dffff, 0, 0, 19 },/*  D29IP_E1P   EHCI1  INTA -> PIRQD */
-			/* EHCI	#2			0:1a.0 */
-			Package() { 0x001affff, 0, 0, 21 },/*  D26IP_E2P   EHCI2  INTA -> PIRQF */
-			/* LPC devices			0:1f.0 */
-			Package() { 0x001fffff, 0, 0, 17 }, /* D31IP_SIP   SATA   INTA -> PIRQB (MSI) */
-			Package() { 0x001fffff, 1, 0, 23 }, /* D31IP_SMIP  SMBUS  INTB -> PIRQH */
-			Package() { 0x001fffff, 2, 0, 16 }, /* D31IP_TTIP  THRT   INTC -> PIRQA */
-			Package() { 0x001fffff, 3, 0, 18 },
-		})
-	} Else {
-		Return (Package() {
-			/* Onboard graphics (IGD)	0:2.0 */
-			Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
-			/* PCI Express Graphics (PEG)	0:1.0 */
-			Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
-			Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
-			Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 },
-			Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },
-			/* XHCI   0:14.0 (ivy only) */
-			Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },
-			/* High Definition Audio	0:1b.0 */
-			Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
-			/* PCIe Root Ports		0:1c.x */
-			Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
-			Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKF, 0 },
-			Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKD, 0 },
-			Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKE, 0 },
-			/* EHCI	#1			0:1d.0 */
-			Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },
-			/* EHCI	#2			0:1a.0 */
-			Package() { 0x001affff, 0, \_SB.PCI0.LPCB.LNKF, 0 },
-			/* LPC device			0:1f.0 */
-			Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
-			Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKH, 0 },
-			Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKA, 0 },
-			Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKC, 0 },
-		})
-	}
-}
+/* PCI Interrupt Routing is generated */
diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c
index 2bfc1e3..5224469 100644
--- a/src/southbridge/intel/bd82x6x/lpc.c
+++ b/src/southbridge/intel/bd82x6x/lpc.c
@@ -35,6 +35,7 @@
 #include "pch.h"
 #include "nvs.h"
 #include <southbridge/intel/common/pciehp.h>
+#include <southbridge/intel/common/acpi_pirq_gen.h>
 
 #define NMI_OFF	0
 
@@ -815,12 +816,42 @@
 	return "LPCB";
 }
 
+static const u32 pirq_dir_route_reg[] = {
+	D20IR, 0, D22IR, 0, 0, D25IR, D26IR, D27IR, D28IR, D29IR, 0, D31IR,
+};
+
+u8 intel_common_map_pirq(device_t dev, u8 pci_pin)
+{
+	u8 slot = PCI_SLOT(dev->path.pci.devfn);
+	u8 shift = 4 * (pci_pin - 1);
+	u8 pirq;
+	u32 reg;
+
+	if (slot < 20 || slot > 31 || pci_pin < 1 || pci_pin > 4) {
+		printk(BIOS_DEBUG, "slot=%d or pin%d out of bounds\n",
+			slot, pci_pin);
+		return 0;
+	}
+
+	reg = pirq_dir_route_reg[slot - 20];
+	printk(BIOS_DEBUG, "slot=%d reg=0x%04x val=0x%04x\n",
+		slot, reg, RCBA16(reg));
+
+	pirq = ((RCBA16(reg) >> shift) & 0xf);
+	if (pirq > 8) {
+		printk(BIOS_DEBUG, "pirq=%d out of bounds\n", pirq);
+		return 0;
+	}
+	return 1 + pirq;
+}
+
 static void southbridge_fill_ssdt(device_t device)
 {
 	device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
 	config_t *chip = dev->chip_info;
 
 	intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
+	intel_acpi_gen_def_acpi_pirq(dev);
 }
 
 static void lpc_final(struct device *dev)
diff --git a/src/southbridge/intel/common/Kconfig b/src/southbridge/intel/common/Kconfig
index 6ce6b33..f6a0180 100644
--- a/src/southbridge/intel/common/Kconfig
+++ b/src/southbridge/intel/common/Kconfig
@@ -15,6 +15,9 @@
 config HAVE_INTEL_CHIPSET_LOCKDOWN
 	def_bool n
 
+config SOUTHBRIDGE_INTEL_COMMON_PIRQ_ACPI_GEN
+	def_bool n
+
 config INTEL_CHIPSET_LOCKDOWN
 	depends on HAVE_INTEL_CHIPSET_LOCKDOWN && HAVE_SMI_HANDLER && !CHROMEOS
 	#ChromeOS's payload seems to handle finalization on its on.
diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc
index 0128505..13150d9 100644
--- a/src/southbridge/intel/common/Makefile.inc
+++ b/src/southbridge/intel/common/Makefile.inc
@@ -33,4 +33,6 @@
 smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c
 endif
 
+ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_PIRQ_ACPI_GEN) += acpi_pirq_gen.c
+
 endif
diff --git a/src/southbridge/intel/common/acpi_pirq_gen.c b/src/southbridge/intel/common/acpi_pirq_gen.c
new file mode 100644
index 0000000..17d9d09
--- /dev/null
+++ b/src/southbridge/intel/common/acpi_pirq_gen.c
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Arthur Heymans <arthur at aheymans.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpigen.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci_def.h>
+#include <string.h>
+
+#include "acpi_pirq_gen.h"
+
+enum emit_type {
+	EMIT_NONE,
+	EMIT_APIC,
+	EMIT_PICM,
+};
+
+static int enumerate_root_pci_pins(enum emit_type emit, const char *lpcb_path)
+{
+	static char buffer[DEVICE_PATH_MAX];
+	device_t dev;
+	u8 prev_int_pin = 0;
+	u8 prev_pci_dev = 0;
+	int num_devs = 0;
+
+	for (dev = all_devices; dev; dev = dev->next) {
+		u8 pci_dev;
+		u8 int_pin;
+		u8 pirq;
+
+		if (dev->path.type != DEVICE_PATH_PCI ||
+		    dev->bus->secondary != 0)
+			continue;
+
+		pci_dev = PCI_SLOT(dev->path.pci.devfn);
+		int_pin = pci_read_config8(dev, PCI_INTERRUPT_PIN);
+
+		if (int_pin == 0 || int_pin > 4) {
+			printk(BIOS_DEBUG, "%s: no pin\n", dev_path(dev));
+			continue;
+		}
+
+		pirq = intel_common_map_pirq(dev, int_pin);
+
+		printk(BIOS_DEBUG, "%s: pin=%d pirq=%d\n",
+			dev_path(dev), int_pin, pirq);
+
+		if (pirq == 0)
+			continue;
+
+		/* Avoid duplicate entries */
+		if (prev_pci_dev == pci_dev && prev_int_pin == int_pin) {
+			continue;
+		} else {
+			prev_int_pin = int_pin;
+			prev_pci_dev = pci_dev;
+		}
+		if (emit != EMIT_NONE) {
+			acpigen_write_package(4);
+			acpigen_write_dword((pci_dev << 16) | 0xffff);
+			acpigen_write_dword(int_pin - 1);
+			if (emit == EMIT_APIC) {
+				acpigen_write_dword(0);
+				acpigen_write_dword(16 + (pirq - 1));
+			} else {
+				snprintf(buffer, sizeof(buffer),
+					 "%s.LNK%c", lpcb_path, 'A' + pirq - 1);
+				printk(BIOS_DEBUG, "path=%s\n", buffer);
+				acpigen_emit_namestring(buffer);
+				acpigen_write_dword(0);
+			}
+			acpigen_pop_len();
+		}
+		num_devs++;
+	}
+	return num_devs;
+}
+
+void intel_acpi_gen_def_acpi_pirq(device_t dev)
+{
+	const char *lpcb_path = acpi_device_path(dev);
+	int num_devs = enumerate_root_pci_pins(EMIT_NONE, lpcb_path);
+
+	if (!lpcb_path) {
+		printk(BIOS_ERR, "Missing LPCB ACPI path\n");
+		return;
+	}
+	printk(BIOS_INFO, "num_devs=%d\n", num_devs);
+
+	acpigen_write_scope("\\_SB.PCI0");
+	acpigen_write_method("_PRT", 0);
+	acpigen_write_if();
+	acpigen_emit_namestring("PICM");
+	acpigen_emit_byte(RETURN_OP);
+	acpigen_write_package(num_devs);
+	enumerate_root_pci_pins(EMIT_APIC, lpcb_path);
+	acpigen_pop_len(); /* package */
+	acpigen_pop_len(); /* if PICM */
+	acpigen_write_else();
+	acpigen_emit_byte(RETURN_OP);
+	acpigen_write_package(num_devs);
+	enumerate_root_pci_pins(EMIT_PICM, lpcb_path);
+	acpigen_pop_len(); /* package */
+	acpigen_pop_len(); /* else PICM */
+	acpigen_pop_len(); /* _PRT */
+	acpigen_pop_len(); /* \_SB */
+}
diff --git a/src/southbridge/intel/common/acpi_pirq_gen.h b/src/southbridge/intel/common/acpi_pirq_gen.h
new file mode 100644
index 0000000..d5c68f7
--- /dev/null
+++ b/src/southbridge/intel/common/acpi_pirq_gen.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Arthur Heymans <arthur at aheymans.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef INTEL_COMMON_ACPI_PIRQ_GEN_H
+#define INTEL_COMMON_ACPI_PIRQ_GEN_H
+
+void intel_acpi_gen_def_acpi_pirq(device_t dev);
+u8 intel_common_map_pirq(device_t dev, u8 int_pin);
+
+#endif

-- 
To view, visit https://review.coreboot.org/22810
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic6b8ce4a9db50211a9c26221ca10105c5a0829a0
Gerrit-Change-Number: 22810
Gerrit-PatchSet: 1
Gerrit-Owner: Tobias Diedrich <ranma+coreboot at tdiedrich.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20171210/5aec5ced/attachment-0001.html>


More information about the coreboot-gerrit mailing list