Karthik Ramasubramanian has uploaded this change for review.

View Change

soc/intel/tigerlake: Log PM event from an internal device

Add support to check for the Power Management (PM) Status bit for
various internal devices like USB, CNVi etc. and log them into the event
log for debugging purposes.

BUG=b:172279037
BRANCH=volteer

Change-Id: Ib3d0bf33d780444f8240f749a3319212c985950d
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
---
M src/soc/intel/tigerlake/Kconfig
M src/soc/intel/tigerlake/Makefile.inc
M src/soc/intel/tigerlake/elog.c
A src/soc/intel/tigerlake/xhci.c
4 files changed, 100 insertions(+), 2 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/27/47227/1
diff --git a/src/soc/intel/tigerlake/Kconfig b/src/soc/intel/tigerlake/Kconfig
index ed35bd6..c0fb764 100644
--- a/src/soc/intel/tigerlake/Kconfig
+++ b/src/soc/intel/tigerlake/Kconfig
@@ -55,6 +55,7 @@
select SOC_INTEL_COMMON_BLOCK_USB4
select SOC_INTEL_COMMON_BLOCK_USB4_PCIE
select SOC_INTEL_COMMON_BLOCK_USB4_XHCI
+ select SOC_INTEL_COMMON_BLOCK_XHCI_ELOG
select SOC_INTEL_COMMON_FSP_RESET
select SOC_INTEL_COMMON_PCH_BASE
select SOC_INTEL_COMMON_RESET
diff --git a/src/soc/intel/tigerlake/Makefile.inc b/src/soc/intel/tigerlake/Makefile.inc
index a25d0a4..3103d60 100644
--- a/src/soc/intel/tigerlake/Makefile.inc
+++ b/src/soc/intel/tigerlake/Makefile.inc
@@ -44,6 +44,7 @@
ramstage-y += soundwire.c
ramstage-y += systemagent.c
ramstage-y += me.c
+ramstage-y += xhci.c

smm-y += gpio.c
smm-y += p2sb.c
@@ -51,6 +52,7 @@
smm-y += smihandler.c
smm-y += uart.c
smm-y += elog.c
+smm-y += xhci.c

verstage-y += gpio.c

diff --git a/src/soc/intel/tigerlake/elog.c b/src/soc/intel/tigerlake/elog.c
index 84f0a7e..8e2db86 100644
--- a/src/soc/intel/tigerlake/elog.c
+++ b/src/soc/intel/tigerlake/elog.c
@@ -2,12 +2,26 @@

#include <bootstate.h>
#include <console/console.h>
+#include <device/pci_ops.h>
#include <stdint.h>
#include <elog.h>
#include <intelblocks/pmclib.h>
+#include <intelblocks/xhci.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>

+#define PME_STS_BIT (1 << 15)
+
+struct pme_status_info {
+#ifdef __SIMPLE_DEVICE__
+ pci_devfn_t dev;
+#else
+ struct device *dev;
+#endif
+ uint8_t reg_offset;
+ uint32_t elog_event;
+};
+
static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
{
int i;
@@ -20,6 +34,67 @@
}
}

+static void pch_log_add_elog_event(const struct pme_status_info *info)
+{
+ /*
+ * If wake source is XHCI, check for detailed wake source events on
+ * USB2/3 ports.
+ */
+ if ((info->dev == PCH_DEV_XHCI) &&
+ pch_xhci_update_wake_event(soc_get_xhci_usb_info()))
+ return;
+
+ elog_add_event_wake(info->elog_event, 0);
+}
+
+static void pch_log_pme_internal_wake_source(void)
+{
+ size_t i;
+#ifdef __SIMPLE_DEVICE__
+ pci_devfn_t dev;
+#else
+ struct device *dev;
+#endif
+ uint16_t val;
+ bool dev_found = false;
+
+ struct pme_status_info pme_status_info[] = {
+ { PCH_DEV_HDA, 0x54, ELOG_WAKE_SOURCE_PME_HDA },
+ { PCH_DEV_GBE, 0xcc, ELOG_WAKE_SOURCE_PME_GBE },
+ { PCH_DEV_SATA, 0x74, ELOG_WAKE_SOURCE_PME_SATA },
+ { PCH_DEV_CSE, 0x54, ELOG_WAKE_SOURCE_PME_CSE },
+ { PCH_DEV_XHCI, 0x74, ELOG_WAKE_SOURCE_PME_XHCI },
+ { PCH_DEV_USBOTG, 0x84, ELOG_WAKE_SOURCE_PME_XDCI },
+ { PCH_DEV_CNVI_WIFI, 0xcc, ELOG_WAKE_SOURCE_PME_WIFI },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(pme_status_info); i++) {
+ dev = pme_status_info[i].dev;
+ if (!dev)
+ continue;
+
+ val = pci_read_config16(dev, pme_status_info[i].reg_offset);
+ if ((val == 0xFFFF) || !(val & PME_STS_BIT))
+ continue;
+
+ pch_log_add_elog_event(&pme_status_info[i]);
+ dev_found = true;
+ }
+
+ /*
+ * If device is still not found, but the wake source is internal PME,
+ * try probing XHCI ports to see if any of the USB2/3 ports indicate
+ * that it was the wake source. This path would be taken in case of GSMI
+ * logging with S0ix where the pci_pm_resume_noirq runs and clears the
+ * PME_STS_BIT in controller register.
+ */
+ if (!dev_found)
+ dev_found = pch_xhci_update_wake_event(soc_get_xhci_usb_info());
+
+ if (!dev_found)
+ elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
+}
+
static void pch_log_wake_source(struct chipset_power_state *ps)
{
/* Power Button */
@@ -38,9 +113,9 @@
if (ps->gpe0_sts[GPE_STD] & PME_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);

- /* Internal PME (TODO: determine wake device) */
+ /* Internal PME */
if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
- elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
+ pch_log_pme_internal_wake_source();

/* SMBUS Wake */
if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
diff --git a/src/soc/intel/tigerlake/xhci.c b/src/soc/intel/tigerlake/xhci.c
new file mode 100644
index 0000000..18bb129
--- /dev/null
+++ b/src/soc/intel/tigerlake/xhci.c
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <intelblocks/xhci.h>
+
+#define XHCI_USB2_PORT_STATUS_REG 0x480
+#define XHCI_USB3_PORT_STATUS_REG 0x520
+#define XHCI_USB2_PORT_NUM 10
+#define XHCI_USB3_PORT_NUM 4
+
+static const struct xhci_usb_info usb_info = {
+ .usb2_port_status_reg = XHCI_USB2_PORT_STATUS_REG,
+ .num_usb2_ports = XHCI_USB2_PORT_NUM,
+ .usb3_port_status_reg = XHCI_USB3_PORT_STATUS_REG,
+ .num_usb3_ports = XHCI_USB3_PORT_NUM,
+};
+
+const struct xhci_usb_info *soc_get_xhci_usb_info(void)
+{
+ return &usb_info;
+}

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

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ib3d0bf33d780444f8240f749a3319212c985950d
Gerrit-Change-Number: 47227
Gerrit-PatchSet: 1
Gerrit-Owner: Karthik Ramasubramanian <kramasub@google.com>
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