Patrick Rudolph has uploaded this change for review.

View Change

soc/intel/cannonlake: Add support for UART2 on PCH-H

On PCH-H the UART2 can't be used as PCI device as the parent
multi function device isn't available.

As workaround add an ACPI driver for PCH-H UART2 that generates
ACPI code for the Intel LPSS ACPI driver.

Tested on Linux with Sunrise Point ACPI ID for UART2.

Change-Id: I838d16322be38f5421c1f63b457a0af552e0ed96
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
M src/soc/intel/cannonlake/Makefile.inc
M src/soc/intel/cannonlake/acpi/serialio.asl
A src/soc/intel/cannonlake/pch_h.c
M src/soc/intel/common/block/include/intelblocks/uart.h
M src/soc/intel/common/block/uart/uart.c
5 files changed, 98 insertions(+), 4 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/05/40405/1
diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc
index c744e99..e263264 100644
--- a/src/soc/intel/cannonlake/Makefile.inc
+++ b/src/soc/intel/cannonlake/Makefile.inc
@@ -54,6 +54,11 @@
ramstage-y += vr_config.c
ramstage-y += sd.c
ramstage-y += xhci.c
+ifeq ($(CONFIG_HAVE_ACPI_TABLES),y)
+ifeq ($(CONFIG_SOC_INTEL_COMMON_BLOCK_LPSS),y)
+ramstage-$(CONFIG_SOC_INTEL_CANNONLAKE_PCH_H) += pch_h.c
+endif
+endif

smm-y += elog.c
smm-y += p2sb.c
diff --git a/src/soc/intel/cannonlake/acpi/serialio.asl b/src/soc/intel/cannonlake/acpi/serialio.asl
index 2785e3d..5e28b98 100644
--- a/src/soc/intel/cannonlake/acpi/serialio.asl
+++ b/src/soc/intel/cannonlake/acpi/serialio.asl
@@ -69,8 +69,11 @@
Name (_DDN, "Serial IO UART Controller 1")
}

+
+#if !CONFIG(SOC_INTEL_CANNONLAKE_PCH_H)
Device (UAR2)
{
Name (_ADR, 0x00190002)
Name (_DDN, "Serial IO UART Controller 2")
}
+#endif
diff --git a/src/soc/intel/cannonlake/pch_h.c b/src/soc/intel/cannonlake/pch_h.c
new file mode 100644
index 0000000..84a75e8
--- /dev/null
+++ b/src/soc/intel/cannonlake/pch_h.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <soc/irq.h>
+#include <intelblocks/uart.h>
+#include <console/console.h>
+
+/*
+ * On PCH-H the I2C4 0:19.0 device isn't usable and thus 0:19.2 isn't detected
+ * using standard PCI probing.
+ * Generate an ACPI entry if the device is enabled in devicetree for the ACPI
+ * LPSS driver.
+ */
+static void pch_h_uart2_fill_ssdt(struct device *dev)
+{
+ struct acpi_irq irq = ACPI_IRQ_LEVEL_LOW(LPSS_UART2_IRQ);
+ const char *scope = acpi_device_scope(dev);
+ printk(BIOS_ERR, "ACPIGEN: %s\n", acpi_device_name(dev));
+ struct resource *res;
+ if (!scope)
+ return;
+
+ res = find_resource(dev, PCI_BASE_ADDRESS_0);
+ if (!res)
+ return;
+
+ /* Device */
+ acpigen_write_scope(scope);
+ acpigen_write_device(acpi_device_name(dev));
+ acpigen_write_name_string("_HID", acpi_device_hid(dev));
+ /*
+ * INT344A is the Sunrise Point HID, as the Linux kernel doesn't support
+ * CannonPoint yet...
+ */
+ acpigen_write_name_string("_CID", "INT344A");
+ acpi_device_write_uid(dev);
+ acpigen_write_name_string("_DDN", "LPSS ACPI UART");
+ acpigen_write_STA(acpi_device_status(dev));
+
+ /* Resources */
+ acpigen_write_name("_CRS");
+ acpigen_write_resourcetemplate_header();
+
+ acpi_device_write_interrupt(&irq);
+ acpigen_write_mem32fixed(1, res->base, res->size);
+
+ acpigen_write_resourcetemplate_footer();
+
+ acpigen_pop_len(); /* Device */
+ acpigen_pop_len(); /* Scope */
+}
+
+static const char *pch_h_uart2_acpi_hid(const struct device *dev)
+{
+ return "INT34BA";
+}
+
+static struct device_operations device_ops_cnp_h = {
+ .read_resources = uart_common_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = uart_common_enable_resources,
+ .ops_pci = &pci_dev_ops_pci,
+ .acpi_hid = pch_h_uart2_acpi_hid,
+ .acpi_fill_ssdt_generator = pch_h_uart2_fill_ssdt,
+};
+
+static const struct pci_driver pch_h_uart __pci_driver = {
+ .ops = &device_ops_cnp_h,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_CNP_H_UART2,
+};
diff --git a/src/soc/intel/common/block/include/intelblocks/uart.h b/src/soc/intel/common/block/include/intelblocks/uart.h
index cc27f0e..a51a739 100644
--- a/src/soc/intel/common/block/include/intelblocks/uart.h
+++ b/src/soc/intel/common/block/include/intelblocks/uart.h
@@ -31,6 +31,16 @@
void uart_common_init(const struct device *dev, uintptr_t baseaddr);

/*
+ * Common routine to enable UART resources in PCI config space.
+ */
+void uart_common_enable_resources(struct device *dev);
+
+/*
+ * Common routine to read UART resources in PCI config space.
+ */
+void uart_common_read_resources(struct device *dev);
+
+/*
* Check if UART debug controller is initialized
* Returns:
* true = If debug controller PCI config space is initialized and device is
diff --git a/src/soc/intel/common/block/uart/uart.c b/src/soc/intel/common/block/uart/uart.c
index 7d75bdd..3464571 100644
--- a/src/soc/intel/common/block/uart/uart.c
+++ b/src/soc/intel/common/block/uart/uart.c
@@ -143,7 +143,7 @@

#if ENV_RAMSTAGE

-static void uart_read_resources(struct device *dev)
+void uart_common_read_resources(struct device *dev)
{
pci_dev_read_resources(dev);

@@ -213,7 +213,7 @@
return pch_uart_init_debug_controller_on_resume();
}

-static void uart_common_enable_resources(struct device *dev)
+void uart_common_enable_resources(struct device *dev)
{
pci_dev_enable_resources(dev);

@@ -227,7 +227,7 @@
}

static struct device_operations device_ops = {
- .read_resources = uart_read_resources,
+ .read_resources = uart_common_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = uart_common_enable_resources,
.ops_pci = &pci_dev_ops_pci,
@@ -256,7 +256,6 @@
PCI_DEVICE_ID_INTEL_GLK_UART3,
PCI_DEVICE_ID_INTEL_CNP_H_UART0,
PCI_DEVICE_ID_INTEL_CNP_H_UART1,
- PCI_DEVICE_ID_INTEL_CNP_H_UART2,
PCI_DEVICE_ID_INTEL_ICP_UART0,
PCI_DEVICE_ID_INTEL_ICP_UART1,
PCI_DEVICE_ID_INTEL_ICP_UART2,

To view, visit change 40405. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I838d16322be38f5421c1f63b457a0af552e0ed96
Gerrit-Change-Number: 40405
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-MessageType: newchange