[coreboot-gerrit] Patch set updated for coreboot: soc/intel/apollolake: Add GPE routing code

Shaunak Saha (shaunak.saha@intel.com) gerrit at coreboot.org
Thu Jun 30 10:20:12 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/15324

-gerrit

commit 8b6b39f32863ccad8e24f9fee769d28f5f495937
Author: Shaunak Saha <shaunak.saha at intel.com>
Date:   Tue Jun 7 02:06:28 2016 -0700

    soc/intel/apollolake: Add GPE routing code
    
    This patch adds the basic framework for SCI to GPE routing code.
    
    BUG = chrome-os-partner:53438
    TEST = Toogle pch_sci_l from ec console using gpioset command and
    	see that the sci counter increases in /sys/firmware/acpi/interrupt
    	and also 9 in /proc/interrupts.
    
    Change-Id: I3b3198276530bf6513d94e9bea02ab9751212adf
    Signed-off-by: Shaunak Saha <shaunak.saha at intel.com>
---
 src/soc/intel/apollolake/chip.h                  |   6 ++
 src/soc/intel/apollolake/gpio.c                  |  30 +++++++
 src/soc/intel/apollolake/include/soc/gpe.h       | 102 +++++++++++++++++++++++
 src/soc/intel/apollolake/include/soc/gpio.h      |  11 +++
 src/soc/intel/apollolake/include/soc/gpio_defs.h |  21 +++++
 src/soc/intel/apollolake/include/soc/pm.h        |   8 +-
 src/soc/intel/apollolake/pmc.c                   |  53 ++++++++++++
 7 files changed, 230 insertions(+), 1 deletion(-)

diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index ef82c53..4446ac5 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -18,6 +18,8 @@
 #ifndef _SOC_APOLLOLAKE_CHIP_H_
 #define _SOC_APOLLOLAKE_CHIP_H_
 
+#include <soc/gpio_defs.h>
+
 #define CLKREQ_DISABLED		0xf
 
 /* Serial IRQ control. SERIRQ_QUIET is the default (0). */
@@ -79,6 +81,10 @@ struct soc_intel_apollolake_config {
 
 	/* Integrated Sensor Hub */
 	uint8_t integrated_sensor_hub_enable;
+
+	uint8_t gpe0_dw1; /* GPE0_63_32 STS/EN */
+	uint8_t gpe0_dw2; /* GPE0_95_64 STS/EN */
+	uint8_t gpe0_dw3; /* GPE0_127_96 STS/EN */
 };
 
 #endif	/* _SOC_APOLLOLAKE_CHIP_H_ */
diff --git a/src/soc/intel/apollolake/gpio.c b/src/soc/intel/apollolake/gpio.c
index d0ef648..f66ecba 100644
--- a/src/soc/intel/apollolake/gpio.c
+++ b/src/soc/intel/apollolake/gpio.c
@@ -132,3 +132,33 @@ const char *gpio_acpi_path(gpio_t gpio_num)
 
 	return NULL;
 }
+
+void gpio_route_gpe(void)
+{
+	int i;
+	uint32_t misccfg_mask;
+	uint32_t misccfg_value;
+	uint32_t misccfg_gpe0_dw0; /* ACPI GPE0[31:0] */
+	uint32_t misccfg_gpe0_dw1; /* ACPI GPE0[63:32] */
+	uint32_t misccfg_gpe0_dw2; /* ACPI GPE0[95:64] */
+
+	/* Set the group here for community specific MISCCFG register */
+	misccfg_gpe0_dw0 = GPP_N_7; /* GPE0b */
+	misccfg_gpe0_dw1 = GPP_SW_0; /* GPE0c */
+	misccfg_gpe0_dw2 = GPP_SW_0; /* GPE0d */
+
+	/* Program GPIO_MISCCFG */
+	misccfg_mask = (uint32_t) ~(MISCCFG_GPE0_DW2_MASK |
+			MISCCFG_GPE0_DW1_MASK |
+			MISCCFG_GPE0_DW0_MASK);
+	misccfg_value  = (uint32_t)((misccfg_gpe0_dw2 << MISCCFG_GPE0_DW2_SHIFT)
+		| (misccfg_gpe0_dw1 << MISCCFG_GPE0_DW1_SHIFT)
+		| (misccfg_gpe0_dw0 << MISCCFG_GPE0_DW0_SHIFT));
+
+	for (i = 0; i < ARRAY_SIZE(gpio_communities); i++) {
+		const struct pad_community *comm = &gpio_communities[i];
+
+		iosf_write(comm->port, GPIO_MISCCFG, ((iosf_read(comm->port,
+				GPIO_MISCCFG) & misccfg_mask) | misccfg_value));
+	}
+}
diff --git a/src/soc/intel/apollolake/include/soc/gpe.h b/src/soc/intel/apollolake/include/soc/gpe.h
index 8abbad8..5482ed3 100644
--- a/src/soc/intel/apollolake/include/soc/gpe.h
+++ b/src/soc/intel/apollolake/include/soc/gpe.h
@@ -34,4 +34,106 @@
 #define GPE0A_SMB_WAK_STS		16
 #define GPE0A_SATA_PME_STS		17
 
+/* Group DW0 is reserved in Apollolake */
+
+/* GPE_63_32 */
+#define GPE0_DW1_00		32
+#define GPE0_DW1_01		33
+#define GPE0_DW1_02		34
+#define GPE0_DW1_03		36
+#define GPE0_DW1_04		36
+#define GPE0_DW1_05		37
+#define GPE0_DW1_06		38
+#define GPE0_DW1_07		39
+#define GPE0_DW1_08		40
+#define GPE0_DW1_09		41
+#define GPE0_DW1_10		42
+#define GPE0_DW1_11		43
+#define GPE0_DW1_12		44
+#define GPE0_DW1_13		45
+#define GPE0_DW1_14		46
+#define GPE0_DW1_15		47
+#define GPE0_DW1_16		48
+#define GPE0_DW1_17		49
+#define GPE0_DW1_18		50
+#define GPE0_DW1_19		51
+#define GPE0_DW1_20		52
+#define GPE0_DW1_21		53
+#define GPE0_DW1_22		54
+#define GPE0_DW1_23		55
+#define GPE0_DW1_24		56
+#define GPE0_DW1_25		57
+#define GPE0_DW1_26		58
+#define GPE0_DW1_27		59
+#define GPE0_DW1_28		60
+#define GPE0_DW1_29		61
+#define GPE0_DW1_30		62
+#define GPE0_DW1_31		63
+/* GPE_95_64 */
+#define GPE0_DW2_00		64
+#define GPE0_DW2_01		65
+#define GPE0_DW2_02		66
+#define GPE0_DW2_03		67
+#define GPE0_DW2_04		68
+#define GPE0_DW2_05		69
+#define GPE0_DW2_06		70
+#define GPE0_DW2_07		71
+#define GPE0_DW2_08		72
+#define GPE0_DW2_09		73
+#define GPE0_DW2_10		74
+#define GPE0_DW2_11		75
+#define GPE0_DW2_12		76
+#define GPE0_DW2_13		77
+#define GPE0_DW2_14		78
+#define GPE0_DW2_15		79
+#define GPE0_DW2_16		80
+#define GPE0_DW2_17		81
+#define GPE0_DW2_18		82
+#define GPE0_DW2_19		83
+#define GPE0_DW2_20		84
+#define GPE0_DW2_21		85
+#define GPE0_DW2_22		86
+#define GPE0_DW2_23		87
+#define GPE0_DW2_24		88
+#define GPE0_DW2_25		89
+#define GPE0_DW2_26		90
+#define GPE0_DW2_27		91
+#define GPE0_DW2_28		92
+#define GPE0_DW2_29		93
+#define GPE0_DW2_30		94
+#define GPE0_DW2_31		95
+/* GPE_127_96 */
+#define GPE0_DW3_00		96
+#define GPE0_DW3_01		97
+#define GPE0_DW3_02		98
+#define GPE0_DW3_03		99
+#define GPE0_DW3_04		100
+#define GPE0_DW3_05		101
+#define GPE0_DW3_06		102
+#define GPE0_DW3_07		103
+#define GPE0_DW3_08		104
+#define GPE0_DW3_09		105
+#define GPE0_DW3_10		106
+#define GPE0_DW3_11		107
+#define GPE0_DW3_12		108
+#define GPE0_DW3_13		109
+#define GPE0_DW3_14		110
+#define GPE0_DW3_15		111
+#define GPE0_DW3_16		112
+#define GPE0_DW3_17		113
+#define GPE0_DW3_18		114
+#define GPE0_DW3_19		115
+#define GPE0_DW3_20		116
+#define GPE0_DW3_21		117
+#define GPE0_DW3_22		118
+#define GPE0_DW3_23		119
+#define GPE0_DW3_24		120
+#define GPE0_DW3_25		121
+#define GPE0_DW3_26		122
+#define GPE0_DW3_27		123
+#define GPE0_DW3_28		124
+#define GPE0_DW3_29		125
+#define GPE0_DW3_30		126
+#define GPE0_DW3_31		127
+
 #endif
diff --git a/src/soc/intel/apollolake/include/soc/gpio.h b/src/soc/intel/apollolake/include/soc/gpio.h
index c9d32cc..a5c68c7 100644
--- a/src/soc/intel/apollolake/include/soc/gpio.h
+++ b/src/soc/intel/apollolake/include/soc/gpio.h
@@ -99,5 +99,16 @@ struct pad_config {
 void gpio_configure_pad(const struct pad_config *cfg);
 void gpio_configure_pads(const struct pad_config *cfg, size_t num_pads);
 
+/*
+ * Set the GPIO groups for the GPE blocks. The gpe0_route is interpreted
+ * as the packed configuration for GPE0_DW[2:0]. This basically sets the
+ * MISCCFG register bits:
+ *  dw0 = gpe0_route[11:8]
+ *  dw1 = gpe0_route[15:12]
+ *  dw2 = gpe0_route[19:16].
+ */
+void gpio_route_gpe(void);
+
 #endif /* __ACPI__ */
+
 #endif /* _SOC_APOLLOLAKE_GPIO_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/gpio_defs.h b/src/soc/intel/apollolake/include/soc/gpio_defs.h
index 30c4bdb..b6268d2 100644
--- a/src/soc/intel/apollolake/include/soc/gpio_defs.h
+++ b/src/soc/intel/apollolake/include/soc/gpio_defs.h
@@ -23,6 +23,27 @@
 #ifndef _SOC_APOLLOLAKE_GPIO_DEFS_H_
 #define _SOC_APOLLOLAKE_GPIO_DEFS_H_
 
+/*
+ * There are 8 GPIO groups. GPP_0 -> GPP_8 (Group 3 is not present)
+ */
+#define GPP_SW_0	0 /* SOUTHWEST GPIO #  0 ~ 31 belong to GROUP0 */
+#define GPP_SW_1	1 /* SOUTHWEST GPIO # 32 ~ 42 belong to GROUP1 */
+#define GPP_W_2		2 /* WEST      GPIO #  0 ~ 25 belong to GROUP2 */
+#define GPP_NW_4	4 /* NORTHWEST GPIO #  0 ~ 17 belong to GROUP4 */
+#define GPP_NW_5	5 /* NORTHWEST GPIO # 32 ~ 63 belong to GROUP5, except # 52 and 60 */
+#define GPP_NW_6	6 /* NORTHWEST GPIO # 64 ~ 76 belong to GROUP6 */
+#define GPP_N_7		7 /* NORTH     GPIO #  0 ~ 31 belong to GROUP7 */
+#define GPP_N_8		8 /* NORTH     GPIO # 32 ~ 61 belong to GROUP8 */
+
+#define GPIO_MISCCFG	0x10         /* Miscellaneous Configuration */
+
+#define MISCCFG_GPE0_DW0_SHIFT 8
+#define MISCCFG_GPE0_DW0_MASK (0xf << MISCCFG_GPE0_DW0_SHIFT)
+#define MISCCFG_GPE0_DW1_SHIFT 12
+#define MISCCFG_GPE0_DW1_MASK (0xf << MISCCFG_GPE0_DW1_SHIFT)
+#define MISCCFG_GPE0_DW2_SHIFT 16
+#define MISCCFG_GPE0_DW2_MASK (0xf << MISCCFG_GPE0_DW2_SHIFT)
+
 #define PAD_CFG0_TX_STATE		(1 << 0)
 #define PAD_CFG0_RX_STATE		(1 << 1)
 #define PAD_CFG0_TX_DISABLE		(1 << 8)
diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h
index 72f74a6..f55de70 100644
--- a/src/soc/intel/apollolake/include/soc/pm.h
+++ b/src/soc/intel/apollolake/include/soc/pm.h
@@ -129,10 +129,16 @@
 #       define RPS		(1 <<  2)
 #define GEN_PMCON3		0x1028
 #define ETR			0x1048
+#define GPIO_GPE_CFG		0x1050
+
+#define  GPE0_DWX_MASK          0xf
+#define  GPE0_DW1_SHIFT         4
+#define  GPE0_DW2_SHIFT         8
+#define  GPE0_DW3_SHIFT         12
+
 #	define CF9_LOCK		(1 << 31)
 #	define CF9_GLB_RST	(1 << 20)
 
-
 /* Generic sleep state types */
 #define SLEEP_STATE_S0		0
 #define SLEEP_STATE_S3		3
diff --git a/src/soc/intel/apollolake/pmc.c b/src/soc/intel/apollolake/pmc.c
index c88e14c..21cb0bd 100644
--- a/src/soc/intel/apollolake/pmc.c
+++ b/src/soc/intel/apollolake/pmc.c
@@ -20,6 +20,10 @@
 #include <device/pci_ids.h>
 #include <soc/iomap.h>
 #include <soc/pci_ids.h>
+#include <soc/gpio.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include "chip.h"
 
 /*
  * The ACPI IO BAR (offset 0x20) is not PCI compliant. We've observed cases
@@ -58,10 +62,59 @@ static void set_resources(device_t dev)
 	report_resource_stored(dev, res, " ACPI BAR");
 }
 
+static void pmc_gpe_init(void)
+{
+        uint32_t gpio_cfg = 0;
+        uint32_t gpio_cfg_reg;
+        struct soc_intel_apollolake_config *config;
+
+        struct device *dev = NB_DEV_ROOT;
+        if (!dev || !dev->chip_info) {
+                printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+                return;
+        }
+        config = dev->chip_info;
+
+        uintptr_t pmc_bar = get_pmc_mmio_bar();
+
+        const uint32_t gpio_cfg_mask =
+                (GPE0_DWX_MASK << GPE0_DW1_SHIFT) |
+                (GPE0_DWX_MASK << GPE0_DW2_SHIFT) |
+                (GPE0_DWX_MASK << GPE0_DW3_SHIFT);
+
+        /* Route the GPIOs to the GPE0 block. Determine that all values
+         * are different, and if they aren't use the reset values.
+         * DW0 is reserved/unused */
+        if (config->gpe0_dw1 == config->gpe0_dw2 ||
+                config->gpe0_dw2 == config->gpe0_dw3) {
+                printk(BIOS_INFO, "PMC: Using default GPE route.\n");
+                gpio_cfg = read32((void *)pmc_bar + GPIO_GPE_CFG);
+        } else {
+                gpio_cfg |= (uint32_t)config->gpe0_dw1 << GPE0_DW1_SHIFT;
+                gpio_cfg |= (uint32_t)config->gpe0_dw2 << GPE0_DW2_SHIFT;
+                gpio_cfg |= (uint32_t)config->gpe0_dw3 << GPE0_DW3_SHIFT;
+        }
+
+        gpio_cfg_reg = read32((void *)pmc_bar + GPIO_GPE_CFG) & ~gpio_cfg_mask;
+        gpio_cfg_reg |= gpio_cfg & gpio_cfg_mask;
+
+        write32((void *)pmc_bar + GPIO_GPE_CFG, gpio_cfg_reg);
+
+        /* Set the routes in the GPIO communities as well. */
+        gpio_route_gpe();
+}
+
+static void pmc_init(struct device *dev)
+{
+	/* Set up GPE configuration */
+	pmc_gpe_init();
+}
+
 static const struct device_operations device_ops = {
 	.read_resources		= read_resources,
 	.set_resources		= set_resources,
 	.enable_resources	= pci_dev_enable_resources,
+	.init                   = &pmc_init,
 };
 
 static const struct pci_driver pmc __pci_driver = {



More information about the coreboot-gerrit mailing list