Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/22803
Change subject: sb/intel/common: Add function to automatically generate ACPI PIRQ ......................................................................
sb/intel/common: Add function to automatically generate ACPI PIRQ
With the RCBA DxxIR registers on reset default the pins are mapped quite straightforwardly namely pinA -> linkA, pinB -> linkB, pinC -> linkC, pinD -> linkD. Although this might not be optimal for performance, it does provide a good working default.
This function generates PIRQ ACPI tables automatically based on the previous assumption.
Change-Id: I2b5d68adabf0840162c6f295af8d10d8d3007a34 Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- 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 4 files changed, 145 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/03/22803/1
diff --git a/src/southbridge/intel/common/Kconfig b/src/southbridge/intel/common/Kconfig index 304ecbf..8ea8c77 100644 --- a/src/southbridge/intel/common/Kconfig +++ b/src/southbridge/intel/common/Kconfig @@ -11,6 +11,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 5810394..aae5c83 100644 --- a/src/southbridge/intel/common/Makefile.inc +++ b/src/southbridge/intel/common/Makefile.inc @@ -28,4 +28,6 @@ romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
+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..d5a17d7 --- /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@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 <device/pci_def.h> + +#include "acpi_pirq_gen.h" + +static int count_different_pirq(void) +{ + device_t irq_dev; + u8 prev_int_pin = 0; + u32 prev_pci_dev = 0; + int num_devs = 0; + + for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + u8 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + u32 pci_dev = (irq_dev->path.pci.devfn >> 3) & 0x1f; + + if (irq_dev->bus->secondary != 0) + continue; + if (int_pin == 0 || int_pin > 4) + continue; + /* Avoid dublicate entries */ + if (prev_pci_dev == pci_dev && prev_int_pin == int_pin) { + continue; + } else { + prev_int_pin = int_pin; + prev_pci_dev = pci_dev; + } + num_devs++; + } + return num_devs; +} + +void gen_def_acpi_pirq(void) +{ + device_t irq_dev; + u8 prev_int_pin = 0; + u32 prev_pci_dev = 0; + int num_devs = count_different_pirq(); + const char *link_list[4] = {"\_SB.PCI0.LPCB.LNKA", + "\_SB.PCI0.LPCB.LNKB", + "\_SB.PCI0.LPCB.LNKC", + "\_SB.PCI0.LPCB.LNKD"}; + + 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); + for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + u8 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + u32 pci_dev = (irq_dev->path.pci.devfn >> 3) & 0x1f; + + if (irq_dev->bus->secondary != 0) + continue; + if (int_pin == 0 || int_pin > 4) + continue; + /* Avoid dublicate entries */ + if (prev_pci_dev == pci_dev && prev_int_pin == int_pin) { + continue; + } else { + prev_int_pin = int_pin; + prev_pci_dev = pci_dev; + } + acpigen_write_package(4); + acpigen_write_dword((pci_dev << 16) | 0xffff); + acpigen_write_dword(int_pin - 1); + acpigen_write_dword(0); + acpigen_write_dword(16 + (int_pin - 1)); + acpigen_pop_len(); + } + acpigen_pop_len(); /* package */ + acpigen_pop_len(); /* if PICM */ + acpigen_write_else(); + acpigen_emit_byte(RETURN_OP); + acpigen_write_package(num_devs); + for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + u8 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + u32 pci_dev = (irq_dev->path.pci.devfn >> 3) & 0x1f; + + if (irq_dev->bus->secondary != 0) + continue; + if (int_pin == 0 || int_pin > 4) + continue; + /* Avoid dublicate entries */ + if (prev_pci_dev == pci_dev && prev_int_pin == int_pin) { + continue; + } else { + prev_int_pin = int_pin; + prev_pci_dev = pci_dev; + } + acpigen_write_package(4); + acpigen_write_dword((pci_dev << 16) | 0xffff); + acpigen_write_dword(int_pin - 1); + acpigen_emit_namestring(link_list[int_pin - 1]); + acpigen_write_dword(0); + acpigen_pop_len(); + } + 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..a3f0609 --- /dev/null +++ b/src/southbridge/intel/common/acpi_pirq_gen.h @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Arthur Heymans arthur@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 gen_def_acpi_pirq(void); + +#endif