[coreboot-gerrit] Patch set updated for coreboot: soc/intel/apollolake: Add PM methods to power gate SD card

Venkateswarlu V Vinjamuri (venkateswarlu.v.vinjamuri@intel.com) gerrit at coreboot.org
Wed Mar 8 02:38:13 CET 2017


Venkateswarlu V Vinjamuri (venkateswarlu.v.vinjamuri at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18496

-gerrit

commit d0d533aea139f9ec692781924ca4ed027f9cdea4
Author: Venkateswarlu Vinjamuri <venkateswarlu.v.vinjamuri at intel.com>
Date:   Fri Feb 24 15:37:30 2017 -0800

    soc/intel/apollolake: Add PM methods to power gate SD card
    
    This implements dynamic generation of sdcard GpioInt in SSDT.
    GpioInt in SSDT generation is based on the card detect GPIO if
    it is provided by the mainboard in devicetree.
    
    This implements GNVS variable to store the address of GPIO_177.
    GNVS used to store rxstate of the GPIO_177 to get card presence.
    
    Add _PS0/_PS3 methods to power gate the sd card controller in
    S0ix and runtime PM.
    
    CQ-DEPEND=448173
    BUG=chrome-os-partner:63070
    TEST=Suspend and resume using 'echo freeze > /sys/power/state'.
    System should enter S0ix and resume with no issue.
    
    Change-Id: Id2c42fc66062f0431385607cff1a83563eaeef87
    Signed-off-by: Venkateswarlu Vinjamuri <venkateswarlu.v.vinjamuri at intel.com>
---
 src/soc/intel/apollolake/Makefile.inc       |  1 +
 src/soc/intel/apollolake/acpi.c             |  4 ++
 src/soc/intel/apollolake/acpi/globalnvs.asl |  1 +
 src/soc/intel/apollolake/acpi/scs.asl       | 38 +++++++++++++
 src/soc/intel/apollolake/chip.c             | 14 +++++
 src/soc/intel/apollolake/chip.h             |  5 ++
 src/soc/intel/apollolake/include/soc/nvs.h  |  3 +-
 src/soc/intel/apollolake/sd.c               | 82 +++++++++++++++++++++++++++++
 8 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index df93f0b..bfe4273 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -84,6 +84,7 @@ ramstage-y += smi.c
 ramstage-y += sram.c
 ramstage-y += spi.c
 ramstage-y += xhci.c
+ramstage-y += sd.c
 
 postcar-y += flash_ctrlr.c
 postcar-y += memmap.c
diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c
index 3c1faa5..bcf1420 100644
--- a/src/soc/intel/apollolake/acpi.c
+++ b/src/soc/intel/apollolake/acpi.c
@@ -183,6 +183,10 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs)
 	/* Assign address of PERST_0 if GPIO is defined in devicetree */
 	if (cfg->prt0_gpio != GPIO_PRT0_UDEF)
 		gnvs->prt0 = (uintptr_t)gpio_dwx_address(cfg->prt0_gpio);
+
+	/* Assign sdcard cd address if GPIO is defined in devicetree */
+	if (cfg->sdcard_cd_gpio)
+		gnvs->scd0 = (uintptr_t)gpio_dwx_address(cfg->sdcard_cd_gpio);
 }
 
 /* Save wake source information for calculating ACPI _SWS values */
diff --git a/src/soc/intel/apollolake/acpi/globalnvs.asl b/src/soc/intel/apollolake/acpi/globalnvs.asl
index 657c834..86a1a23 100644
--- a/src/soc/intel/apollolake/acpi/globalnvs.asl
+++ b/src/soc/intel/apollolake/acpi/globalnvs.asl
@@ -39,6 +39,7 @@ Field (GNVS, ByteAcc, NoLock, Preserve)
 	NHLA,	64,     // 0x19 - 0x20 - NHLT Address
 	NHLL,	32,     // 0x21 - 0x24 - NHLT Length
 	PRT0,	32,     // 0x25 - 0x28 - PERST_0 Address
+	SCD0,	32,     // 0x29 - 0x2D - SD_CD Address
 
 	/* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */
 	Offset (0x100),
diff --git a/src/soc/intel/apollolake/acpi/scs.asl b/src/soc/intel/apollolake/acpi/scs.asl
index 4108017..17f4c10 100644
--- a/src/soc/intel/apollolake/acpi/scs.asl
+++ b/src/soc/intel/apollolake/acpi/scs.asl
@@ -22,6 +22,9 @@ Scope (\_SB.PCI0) {
 	Field (SBMM, DWordAcc, NoLock, Preserve)
 	{
 		GENR, 32,
+		Offset (0x08),
+		,  5, /* bit[5] represents Force Card Detect SD Card */
+		GRR3,  1, /* GPPRVRW3 for SD Card detect Bypass. It's active high */
 	}
 
 	/* SCC power gate control method, this method must be serialized as
@@ -64,4 +67,39 @@ Scope (\_SB.PCI0) {
 			^^SCPG(1,0x00000041)
 		}
 	} /* Device (SDHA) */
+
+	/* SD CARD */
+	Device (SDCD)
+	{
+		Name (_ADR, 0x001B0000)
+
+		Method (_PS0, 0, NotSerialized)
+		{
+			/* Check SDCard CD pin address is valid */
+			If (LNotEqual (SCD0, 0))
+			{
+				/* Store DW0 into local0 to get rxstate of GPIO */
+				Store (\_SB.GPC0 (\SCD0), Local0)
+				/* Extract rxstate [bit 1] of sdcard card detect pin */
+				And (Local0, PAD_CFG0_RX_STATE, Local0)
+				/* If the sdcard is present, rxstate is low (GPIO_177).
+				 * If sdcard is not present, rxstate is High.
+				 * Write the inverted value of rxstate to GRR3.
+				 */
+				If (LEqual (Local0, 0)) {
+					Store (1, ^^GRR3)
+				} Else {
+					Store (0, ^^GRR3)
+				}
+				Sleep (2)
+			}
+		}
+
+		Method (_PS3, 0, NotSerialized)
+		{
+			/* Clear GRR3 to Power Gate SD Controller */
+			Store (0, ^^GRR3)
+		}
+
+	} /* Device (SDCD) */
 }
diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c
index 1de41cf..975d098 100644
--- a/src/soc/intel/apollolake/chip.c
+++ b/src/soc/intel/apollolake/chip.c
@@ -113,6 +113,20 @@ static const char *soc_acpi_name(struct device *dev)
 	return NULL;
 }
 
+static void pci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+	if (!vendor || !device)
+		pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+				pci_read_config32(dev, PCI_VENDOR_ID));
+	else
+		pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+				(device << 16) | vendor);
+}
+
+struct pci_operations soc_pci_ops = {
+	.set_subsystem = &pci_set_subsystem
+};
+
 static void pci_domain_set_resources(device_t dev)
 {
        assign_resources(dev->link_list);
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index d60ffbf..1c41a6e 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -120,6 +120,11 @@ struct soc_intel_apollolake_config {
 	/* USB2 eye diagram settings per port */
 	struct usb2_eye_per_port usb2eye[APOLLOLAKE_USB2_PORT_MAX];
 
+	/* GPIO SD card detect pin */
+	unsigned sdcard_cd_gpio;
 };
 
+typedef struct soc_intel_apollolake_config config_t;
+extern struct pci_operations soc_pci_ops;
+
 #endif	/* _SOC_APOLLOLAKE_CHIP_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/nvs.h b/src/soc/intel/apollolake/include/soc/nvs.h
index 21894ca..21ac14e 100644
--- a/src/soc/intel/apollolake/include/soc/nvs.h
+++ b/src/soc/intel/apollolake/include/soc/nvs.h
@@ -39,7 +39,8 @@ typedef struct global_nvs_t {
 	uint64_t	nhla; /* 0x19 - 0x20 - NHLT Address */
 	uint32_t	nhll; /* 0x21 - 0x24 - NHLT Length */
 	uint32_t	prt0; /* 0x25 - 0x28 - PERST_0 Address */
-	uint8_t		unused[215];
+	uint32_t	scd0; /* 0x29 - 0x2D - SD_CD Address */
+	uint8_t		unused[211];
 
 	/* ChromeOS specific (0x100 - 0xfff) */
 	chromeos_acpi_t chromeos;
diff --git a/src/soc/intel/apollolake/sd.c b/src/soc/intel/apollolake/sd.c
new file mode 100644
index 0000000..2f38061
--- /dev/null
+++ b/src/soc/intel/apollolake/sd.c
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * 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/acpi_device.h>
+#include <arch/acpigen.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <gpio.h>
+#include "chip.h"
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+static void sd_fill_ssdt(struct device *dev)
+{
+	config_t *config = dev->chip_info;
+	const char *path;
+	struct acpi_gpio default_gpio = {
+		.type = ACPI_GPIO_TYPE_INTERRUPT,
+		.pull = ACPI_GPIO_PULL_NONE,
+		.irq.mode = ACPI_IRQ_EDGE_TRIGGERED,
+		.irq.polarity = ACPI_IRQ_ACTIVE_BOTH,
+		.irq.shared = ACPI_IRQ_SHARED,
+		.irq.wake = ACPI_IRQ_WAKE,
+		.interrupt_debounce_timeout = 10000, /* 100ms */
+		.pin_count = 1,
+		.pins = { config->sdcard_cd_gpio }
+	};
+	struct acpi_dp *dp;
+
+	if (!dev->enabled)
+		return;
+
+	/* Use device path as the Scope for the SSDT */
+	path = acpi_device_path(dev);
+	if (!path)
+		return;
+	if (!config->sdcard_cd_gpio)
+		return;
+	acpigen_write_scope(path);
+	acpigen_write_name("_CRS");
+
+	/* Write GpioInt() as default (if set) or custom from devicetree */
+	acpigen_write_resourcetemplate_header();
+	acpi_device_write_gpio(&default_gpio);
+	acpigen_write_resourcetemplate_footer();
+
+	/* Bind the cd-gpio name to the GpioInt() resource */
+	dp = acpi_dp_new_table("_DSD");
+	acpi_dp_add_gpio(dp, "cd-gpio", path, 0, 0, 1);
+	acpi_dp_write(dp);
+
+	acpigen_pop_len();
+}
+#endif
+
+static struct device_operations dev_ops = {
+	.read_resources		  = &pci_dev_read_resources,
+	.set_resources		  = &pci_dev_set_resources,
+	.enable_resources	  = &pci_dev_enable_resources,
+	.ops_pci		  = &soc_pci_ops,
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+	.acpi_fill_ssdt_generator = &sd_fill_ssdt,
+#endif
+};
+
+static const struct pci_driver pch_sd __pci_driver = {
+	.ops	= &dev_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= 0x5aca
+};



More information about the coreboot-gerrit mailing list