Tim Wawrzynczak has uploaded this change for review.

View Change

soc/intel/common: Add North XHCI block driver

Add a driver for the North XHCI block, which is part of the Type-C
Subsystem. This driver only adds support for logging wake events
from USB2 and USB3 ports associated with the North XHCI.

Change-Id: I9f28354e031e3eda587f4faf8ef7595dce8b33ea
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
---
A src/soc/intel/common/block/include/intelblocks/north_xhci.h
A src/soc/intel/common/block/north_xhci/Kconfig
A src/soc/intel/common/block/north_xhci/Makefile.inc
A src/soc/intel/common/block/north_xhci/elog.c
4 files changed, 138 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/11/47411/1
diff --git a/src/soc/intel/common/block/include/intelblocks/north_xhci.h b/src/soc/intel/common/block/include/intelblocks/north_xhci.h
new file mode 100644
index 0000000..a561847
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/north_xhci.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SOC_INTEL_COMMON_BLOCK_NORTH_XHCI_H
+#define SOC_INTEL_COMMON_BLOCK_NORTH_XHCI_H
+
+#include <stdint.h>
+#include <types.h>
+
+struct north_xhci_usb_info {
+ uint32_t usb2_port_status_reg;
+ uint32_t num_usb2_ports;
+ uint32_t usb3_port_status_reg;
+ uint32_t num_usb3_ports;
+};
+
+/*
+ * soc_get_north_xhci_usb_info() - Get the information about North USB2 & USB3 ports.
+ *
+ * This function is used to get USB ports and status register offset information within a North
+ * XHCI controller.
+ *
+ * Return: North USB ports and status register offset info for the SoC.
+ */
+const struct north_xhci_usb_info *soc_get_north_xhci_usb_info(void);
+
+/*
+ * pch_xhci_update_wake_event() - Identify and log North XHCI wake events.
+ * @info: Information about number of North USB ports and their status reg offset.
+ *
+ * This function goes through individual USB port status registers within the North XHCI block
+ * and identifies if any of those USB ports triggered a wake-up and logs information about those
+ * ports to the event log.
+ *
+ * Returns true if a North XHCI USB port was the source of a wake.
+ */
+bool north_xhci_update_wake_event(const struct north_xhci_usb_info *info);
+
+#endif /* SOC_INTEL_COMMON_BLOCK_NORTH_XHCI_H */
diff --git a/src/soc/intel/common/block/north_xhci/Kconfig b/src/soc/intel/common/block/north_xhci/Kconfig
new file mode 100644
index 0000000..0517d25
--- /dev/null
+++ b/src/soc/intel/common/block/north_xhci/Kconfig
@@ -0,0 +1,6 @@
+config SOC_INTEL_COMMON_BLOCK_NORTH_XHCI_ELOG
+ bool
+ default n
+ help
+ Set this option to identify if the North XHCI caused a wake and log
+ that information to the event log.
diff --git a/src/soc/intel/common/block/north_xhci/Makefile.inc b/src/soc/intel/common/block/north_xhci/Makefile.inc
new file mode 100644
index 0000000..9ac3048
--- /dev/null
+++ b/src/soc/intel/common/block/north_xhci/Makefile.inc
@@ -0,0 +1,2 @@
+#ramstage-$(SOC_INTEL_COMMON_BLOCK_NORTH_XHCI_ELOG) += elog.c
+ramstage-y += elog.c
diff --git a/src/soc/intel/common/block/north_xhci/elog.c b/src/soc/intel/common/block/north_xhci/elog.c
new file mode 100644
index 0000000..5006318
--- /dev/null
+++ b/src/soc/intel/common/block/north_xhci/elog.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <device/pci_ops.h>
+#include <elog.h>
+#include <intelblocks/north_xhci.h>
+#include <soc/pci_devs.h>
+#include <stdint.h>
+#include <types.h>
+
+/* Port Link State */
+#define PORTSC_PLS_MASK 0xf0
+#define PORTSC_PLS_RESUME 0xf0
+/* Connect Status Change */
+#define PORTSC_CSC BIT(17)
+/* Port Link State Change */
+#define PORTSC_PLC BIT(22)
+/* Wake On Connect Enable */
+#define PORTSC_WCE BIT(25)
+/* Wake On Disconnect Enable */
+#define PORTSC_WDE BIT(26)
+
+/* MMIO space between PORTSC registers */
+#define NEXT_PORT_OFFSET 0x10
+
+static bool is_connect_wake_capable(uint32_t portsc)
+{
+ return !!(portsc & (PORTSC_WDE | PORTSC_WCE));
+}
+
+static bool connect_status_changed(uint32_t portsc)
+{
+ return !!(portsc & PORTSC_CSC);
+}
+
+static bool is_link_state_changed(uint32_t portsc)
+{
+ return !!(portsc & PORTSC_PLC);
+}
+
+static bool link_status_is_resume(uint32_t portsc)
+{
+ return (portsc & PORTSC_PLS_MASK) == PORTSC_PLS_RESUME;
+}
+
+static bool log_port_wakes(uintptr_t base, uint8_t num, uint8_t event)
+{
+ uint32_t portsc;
+ unsigned int i;
+ bool found = false;
+
+ /* For each port, if it is:
+ * 1) Capable of wakes on connect/disconnect and connect status changed, or:
+ * 2) Link state changed and its new state is a resume (indicating USB activity),
+ * then add a wake event to the elog.
+ */
+ for (i = 0; i < num; i++, base += NEXT_PORT_OFFSET) {
+ portsc = read32((void *)base);
+ if (portsc == 0xffffffff)
+ continue;
+
+ if ((is_connect_wake_capable(portsc) && connect_status_changed(portsc)) ||
+ (is_link_state_changed(portsc) && link_status_is_resume(portsc))) {
+ elog_add_event_wake(event, i + 1);
+ found = true;
+ }
+ }
+
+ return found;
+}
+
+bool north_xhci_update_wake_event(const struct north_xhci_usb_info *info)
+{
+ const struct device *tcss_xhci = pcidev_path_on_root(SA_DEV_TCSS_XHCI);
+ bool found = false;
+
+ if (!tcss_xhci)
+ return false;
+
+ const uintptr_t mmio_base = pci_read_config32(tcss_xhci, PCI_BASE_ADDRESS_0) &
+ ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+
+ found |= log_port_wakes(mmio_base + info->usb2_port_status_reg,
+ info->num_usb2_ports,
+ ELOG_WAKE_SOURCE_PME_TCSS_XHCI_USB_2);
+
+ found |= log_port_wakes(mmio_base + info->usb3_port_status_reg,
+ info->num_usb3_ports,
+ ELOG_WAKE_SOURCE_PME_TCSS_XHCI_USB_3);
+
+ return found;
+}

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

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I9f28354e031e3eda587f4faf8ef7595dce8b33ea
Gerrit-Change-Number: 47411
Gerrit-PatchSet: 1
Gerrit-Owner: Tim Wawrzynczak <twawrzynczak@chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org>
Gerrit-MessageType: newchange