[coreboot-gerrit] Patch set updated for coreboot: soc/apollolake: Return correct wake status in _SWS

Shaunak Saha (shaunak.saha@intel.com) gerrit at coreboot.org
Wed Aug 3 02:51:29 CEST 2016


Shaunak Saha (shaunak.saha at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16040

-gerrit

commit bbc7bb14144bd781c5018e0947c9988a1d45e1c6
Author: Shaunak Saha <shaunak.saha at intel.com>
Date:   Tue Aug 2 17:25:13 2016 -0700

    soc/apollolake: Return correct wake status in _SWS
    
    Wake status is calculated from the four pairs of gpe0 in
    cbmem CBMEM_ID_POWER_STATE which is filled very early
    in romstage and depends on the routing information in
    PMC GPE_CFG register. Coreboot sets the proper value
    of routing based on devicetree from pmc_init. But when
    system wakes up from sleep state PMC is writing default
    values again in GPE_CFG which results in returning
    wrong wake status in _SWS. This patch resolves that
    behaviour by correcting the gpe0 pairs in cbmem after
    PMC sets the routing table in resume path.
    
    BUG=chrome-os-partner:54876
    TEST=On resume through powerbtn, lidopen, keyboard press,  etc.
         we are getting proper wake status.
    
    Change-Id: I5942d5c20d8c6aef73468dc611190bb7c49c7c7a
    Signed-off-by: Shaunak Saha <shaunak.saha at intel.com>
---
 src/soc/intel/apollolake/Kconfig          |  1 +
 src/soc/intel/apollolake/acpi.c           | 27 +++++++++++++++++++++++++++
 src/soc/intel/apollolake/include/soc/pm.h |  3 +++
 src/soc/intel/apollolake/pmc.c            |  3 +++
 src/soc/intel/apollolake/pmutil.c         | 24 ++++++++++++++++++++++++
 5 files changed, 58 insertions(+)

diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 0745679..a85d94a 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -44,6 +44,7 @@ config CPU_SPECIFIC_OPTIONS
 	select SMM_TSEG
 	select SOC_INTEL_COMMON
 	select SOC_INTEL_COMMON_ACPI
+	select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
 	select SOC_INTEL_COMMON_LPSS_I2C
 	select SOC_INTEL_COMMON_SMI
 	select SPI_FLASH
diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c
index 262e140..6af6d69 100644
--- a/src/soc/intel/apollolake/acpi.c
+++ b/src/soc/intel/apollolake/acpi.c
@@ -168,6 +168,33 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs)
 
 	/* Enable DPTF based on mainboard configuration */
 	gnvs->dpte = cfg->dptf_enable;
+
+	/* Set unknown wake source */
+	gnvs->pm1i = -1;
+}
+
+/* Save wake source information for calculating ACPI _SWS values */
+int soc_fill_acpi_wake(uint32_t *pm1, uint32_t **gpe0)
+{
+	struct chipset_power_state *ps;
+	static uint32_t gpe0_sts[GPE0_REG_MAX];
+	uint32_t pm1_en;
+	int i;
+
+	ps = cbmem_find(CBMEM_ID_POWER_STATE);
+	if (ps == NULL)
+		return -1;
+
+	/* PM1_EN state is lost in Deep S3 so enable basic wake events */
+	pm1_en = ps->pm1_en | WAK_STS | RTC_STS | PWRBTN_STS ;
+	*pm1 = ps->pm1_sts & pm1_en;
+
+	/* Mask off GPE0 status bits that are not enabled */
+	*gpe0 = &gpe0_sts[0];
+	for (i = 0; i < GPE0_REG_MAX; i++)
+		gpe0_sts[i] = ps->gpe0_sts[i] & ps->gpe0_en[i];
+
+	return GPE0_REG_MAX;
 }
 
 void southbridge_inject_dsdt(device_t device)
diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h
index d8eb50b..e84ecb0 100644
--- a/src/soc/intel/apollolake/include/soc/pm.h
+++ b/src/soc/intel/apollolake/include/soc/pm.h
@@ -25,6 +25,7 @@
 
 #define PM1_STS			0x00
 #define   WAK_STS		(1 << 15)
+#define   RTC_STS		(1 << 10)
 #define   PWRBTN_STS		(1 << 8)
 
 #define PM1_EN			0x02
@@ -162,6 +163,8 @@ struct chipset_power_state {
 
 int fill_power_state(struct chipset_power_state *ps);
 int chipset_prev_sleep_state(struct chipset_power_state *ps);
+/* Rewrite the gpe0 registers in cbmem to proper values as per routing table */
+void reset_power_state(void);
 
 /* Power Management Utility Functions. */
 uint32_t clear_smi_status(void);
diff --git a/src/soc/intel/apollolake/pmc.c b/src/soc/intel/apollolake/pmc.c
index 9d1be5c..9997b3f 100644
--- a/src/soc/intel/apollolake/pmc.c
+++ b/src/soc/intel/apollolake/pmc.c
@@ -117,6 +117,9 @@ static void pmc_gpe_init(void)
 
 	/* Set the routes in the GPIO communities as well. */
 	gpio_route_gpe(dw1, dw2, dw3);
+
+	/* Reset the power state in cbmem as routing */
+	reset_power_state();
 }
 
 static void pmc_init(struct device *dev)
diff --git a/src/soc/intel/apollolake/pmutil.c b/src/soc/intel/apollolake/pmutil.c
index 61aa637..ad16bbd 100644
--- a/src/soc/intel/apollolake/pmutil.c
+++ b/src/soc/intel/apollolake/pmutil.c
@@ -19,6 +19,7 @@
 
 #include <arch/io.h>
 #include <console/console.h>
+#include <cbmem.h>
 #include <rules.h>
 #include <device/pci_def.h>
 #include <halt.h>
@@ -327,6 +328,29 @@ int chipset_prev_sleep_state(struct chipset_power_state *ps)
 	return prev_sleep_state;
 }
 
+/* This function re-writes the gpe0 register values in power state
+ * cbmem variable. After system wakes from sleep state internal PMC logic
+ * writes default values in GPE_CFG register which gives a wrong offset to
+ * calculate the wake reason. So we need to set it again to  the routing
+ * table as per the devicetree.
+ */
+void reset_power_state(void)
+{
+	int i;
+	struct chipset_power_state *ps;
+
+	ps = cbmem_find(CBMEM_ID_POWER_STATE);
+	if (ps == NULL)
+		return;
+
+	for (i=0; i < GPE0_REG_MAX; i++) {
+		ps->gpe0_sts[i] = inl(ACPI_PMIO_BASE + GPE0_STS(i));
+		ps->gpe0_en[i] = inl(ACPI_PMIO_BASE + GPE0_EN(i));
+		printk(BIOS_DEBUG, "gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n",
+					i, ps->gpe0_sts[i], i, ps->gpe0_en[i]);
+	}
+}
+
 /* returns prev_sleep_state */
 int fill_power_state(struct chipset_power_state *ps)
 {



More information about the coreboot-gerrit mailing list