Shaunak Saha (shaunak.saha@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@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@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 = {