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

Shaunak Saha (shaunak.saha@intel.com) gerrit at coreboot.org
Fri Jul 1 01:58:48 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 215f9b58e761085d16fb1b3497d1dde16398b0ad
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                  |  57 +++++++++++++
 src/soc/intel/apollolake/include/soc/gpe.h       | 102 +++++++++++++++++++++++
 src/soc/intel/apollolake/include/soc/gpio.h      |  12 +++
 src/soc/intel/apollolake/include/soc/gpio_defs.h |  21 +++++
 src/soc/intel/apollolake/include/soc/pm.h        |  18 +++-
 src/soc/intel/apollolake/pmc.c                   |  59 +++++++++++++
 7 files changed, 274 insertions(+), 1 deletion(-)

diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index ef82c53..5571672 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/pm.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..4f2203f 100644
--- a/src/soc/intel/apollolake/gpio.c
+++ b/src/soc/intel/apollolake/gpio.c
@@ -19,6 +19,7 @@
 #include <gpio.h>
 #include <soc/gpio.h>
 #include <soc/iosf.h>
+#include <soc/pm.h>
 
 /* This list must be in order, from highest pad numbers, to lowest pad numbers*/
 static const struct pad_community {
@@ -132,3 +133,59 @@ const char *gpio_acpi_path(gpio_t gpio_num)
 
 	return NULL;
 }
+
+/* Helper function to map PMC register groups to tier1 sci groups */
+static int pmc_gpe_route_to_gpio(int route)
+{
+	switch(route) {
+	case PMC_GPE_SW_31_0:
+		return GPIO_GPE_SW_31_0;
+	case PMC_GPE_SW_63_32:
+		return GPIO_GPE_SW_63_32;
+	case PMC_GPE_NW_31_0:
+		return GPIO_GPE_NW_31_0;
+	case PMC_GPE_NW_63_32:
+		return GPIO_GPE_NW_63_32;
+	case PMC_GPE_NW_95_64:
+		return GPIO_GPE_NW_95_64;
+	case PMC_GPE_N_31_0:
+		return GPIO_GPE_N_31_0;
+	case PMC_GPE_N_63_32:
+		return GPIO_GPE_N_63_32;
+	case PMC_GPE_W_31_0:
+		return GPIO_GPE_W_31_0;
+	default:
+		return -1;
+	}
+}
+
+void gpio_route_gpe(int gpe0b, int gpe0c, int gpe0d)
+{
+	int i;
+	uint32_t misccfg_mask;
+	uint32_t misccfg_value;
+	uint32_t value;
+
+	/* Get the group here for community specific MISCCFG register */
+	gpe0b = pmc_gpe_route_to_gpio(gpe0b);
+	gpe0c = pmc_gpe_route_to_gpio(gpe0c);
+	gpe0d = pmc_gpe_route_to_gpio(gpe0d);
+
+	misccfg_value = gpe0b << MISCCFG_GPE0_DW0_SHIFT;
+	misccfg_value |= gpe0c << MISCCFG_GPE0_DW1_SHIFT;
+	misccfg_value |= gpe0d << MISCCFG_GPE0_DW2_SHIFT;
+
+	/* Program GPIO_MISCCFG */
+	misccfg_mask = ~(MISCCFG_GPE0_DW2_MASK |
+			MISCCFG_GPE0_DW1_MASK |
+			MISCCFG_GPE0_DW0_MASK);
+
+	for (i = 0; i < ARRAY_SIZE(gpio_communities); i++) {
+		const struct pad_community *comm = &gpio_communities[i];
+
+		value = iosf_read(comm->port, GPIO_MISCCFG);
+		value &= misccfg_mask;
+		value |= misccfg_value;
+		iosf_write(comm->port, GPIO_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..a829a2a 100644
--- a/src/soc/intel/apollolake/include/soc/gpio.h
+++ b/src/soc/intel/apollolake/include/soc/gpio.h
@@ -99,5 +99,17 @@ 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. We pass the values from PMC register
+ * GPE_CFG which is then mapped to proper groups for MISCCFG. 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]. This is ACPI GPE0b.
+ *  dw1 = gpe0_route[15:12]. This is ACPI GPE0c.
+ *  dw2 = gpe0_route[19:16]. This is ACPI GPE0d.
+ */
+void gpio_route_gpe(int gpe0b, int gpe0c, int gpe0d);
+
 #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..e64783f 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 GPIO_GPE_SW_31_0	0 /* SOUTHWEST GPIO#  0 ~ 31 belong to GROUP0 */
+#define GPIO_GPE_SW_63_32	1 /* SOUTHWEST GPIO# 32 ~ 42 belong to GROUP1 */
+#define GPIO_GPE_W_31_0		2 /* WEST      GPIO#  0 ~ 25 belong to GROUP2 */
+#define GPIO_GPE_NW_31_0	4 /* NORTHWEST GPIO#  0 ~ 17 belong to GROUP4 */
+#define GPIO_GPE_NW_63_32	5 /* NORTHWEST GPIO# 32 ~ 63 belong to GROUP5 */
+#define GPIO_GPE_NW_95_64	6 /* NORTHWEST GPIO# 64 ~ 76 belong to GROUP6 */
+#define GPIO_GPE_N_31_0		7 /* NORTH     GPIO#  0 ~ 31 belong to GROUP7 */
+#define GPIO_GPE_N_63_32	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..9628323 100644
--- a/src/soc/intel/apollolake/include/soc/pm.h
+++ b/src/soc/intel/apollolake/include/soc/pm.h
@@ -19,6 +19,7 @@
 #define _SOC_APOLLOLAKE_PM_H_
 
 #include <stdint.h>
+#include <soc/gpio_defs.h>
 
 /* ACPI_BASE_ADDRESS */
 
@@ -129,10 +130,25 @@
 #       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
+
+/* GPE_CFG */
+#define PMC_GPE_SW_31_0		0
+#define PMC_GPE_SW_63_32	1
+#define PMC_GPE_NW_31_0		3
+#define PMC_GPE_NW_63_32	4
+#define PMC_GPE_NW_95_64	5
+#define PMC_GPE_N_31_0		6
+#define PMC_GPE_N_63_32		7
+#define PMC_GPE_W_31_0		9
+
 #	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..5fe3a7c 100644
--- a/src/soc/intel/apollolake/pmc.c
+++ b/src/soc/intel/apollolake/pmc.c
@@ -18,8 +18,13 @@
 #include <device/device.h>
 #include <device/pci.h>
 #include <device/pci_ids.h>
+#include <console/console.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 +63,64 @@ 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);
+
+	/* Making sure that bad values don't bleed into the other fields */
+	config->gpe0_dw1 &= GPE0_DWX_MASK;
+	config->gpe0_dw2 &= GPE0_DWX_MASK;
+	config->gpe0_dw3 &= GPE0_DWX_MASK;
+
+	/* 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(config->gpe0_dw1, config->gpe0_dw2, config->gpe0_dw3);
+}
+
+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