From 9f83e873f4f0a06a68f68414720e837a69f54184 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Mon, 11 Nov 2013 14:45:27 -0600 Subject: [PATCH] baytrail: add GPIO SMI support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPIOs which trigger SMIs only set the status bits in the ALT_GPIO_SMI regier. No bits in the SMI_STS register are set. Therefore, the ALT_GPIO_SMI register needs to be read and cleared on every SMI. Additionally, the mainboard_gpi_smi() handler needs to be called as well on every SMI because of this property. BUG=chrome-os-partner:23505 BRANCH=None TEST=Built and booted to recovery screen. Typed 'lidclose' on EC console. SMI occurred which caused the board to be shutdown. Change-Id: Ic204d8b928a0cb4f51f108a649f374d9f94e4f47 Signed-off-by: Aaron Durbin Reviewed-on: https://chromium-review.googlesource.com/176391 Reviewed-by: Duncan Laurie Reviewed-on: http://review.coreboot.org/4958 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/soc/intel/baytrail/baytrail/pmc.h | 1 + src/soc/intel/baytrail/pmutil.c | 57 ++++++++++++++++++++++++++- src/soc/intel/baytrail/smihandler.c | 6 ++- src/soc/intel/baytrail/smm.c | 1 + 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/soc/intel/baytrail/baytrail/pmc.h b/src/soc/intel/baytrail/baytrail/pmc.h index f314d1dd76..088083fcdc 100644 --- a/src/soc/intel/baytrail/baytrail/pmc.h +++ b/src/soc/intel/baytrail/baytrail/pmc.h @@ -198,6 +198,7 @@ uint32_t clear_smi_status(void); uint16_t clear_pm1_status(void); uint32_t clear_tco_status(void); uint32_t clear_gpe_status(void); +uint32_t clear_alt_status(void); void enable_smi(uint32_t mask); void disable_smi(uint32_t mask); void enable_pm1(uint16_t events); diff --git a/src/soc/intel/baytrail/pmutil.c b/src/soc/intel/baytrail/pmutil.c index 738f880b75..ad37511534 100644 --- a/src/soc/intel/baytrail/pmutil.c +++ b/src/soc/intel/baytrail/pmutil.c @@ -52,14 +52,15 @@ uint16_t get_pmbase(void) return pci_read_config16(get_pcu_dev(), ABASE) & 0xfff8; } -static void print_status_bits(uint32_t status, const char *bit_names[]) +static void print_num_status_bits(int num_bits, uint32_t status, + const char *bit_names[]) { int i; if (!status) return; - for (i = 31; i >= 0; i--) { + for (i = num_bits - 1; i >= 0; i--) { if (status & (1 << i)) { if (bit_names[i]) printk(BIOS_DEBUG, "%s ", bit_names[i]); @@ -69,6 +70,11 @@ static void print_status_bits(uint32_t status, const char *bit_names[]) } } +static void print_status_bits(uint32_t status, const char *bit_names[]) +{ + print_num_status_bits(32, status, bit_names); +} + static uint32_t print_smi_status(uint32_t smi_sts) { static const char *smi_sts_bits[] = { @@ -295,3 +301,50 @@ uint32_t clear_gpe_status(void) { return print_gpe_sts(reset_gpe_status()); } + +static uint32_t reset_alt_status(void) +{ + uint16_t pmbase = get_pmbase(); + uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI); + outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI); + return alt_gpio_smi; +} + +static uint32_t print_alt_sts(uint32_t alt_gpio_smi) +{ + uint32_t alt_gpio_sts; + static const char *alt_gpio_smi_sts_bits[] = { + [0] = "SUS_GPIO_0", + [1] = "SUS_GPIO_1", + [2] = "SUS_GPIO_2", + [3] = "SUS_GPIO_3", + [4] = "SUS_GPIO_4", + [5] = "SUS_GPIO_5", + [6] = "SUS_GPIO_6", + [7] = "SUS_GPIO_7", + [8] = "CORE_GPIO_0", + [9] = "CORE_GPIO_1", + [10] = "CORE_GPIO_2", + [11] = "CORE_GPIO_3", + [12] = "CORE_GPIO_4", + [13] = "CORE_GPIO_5", + [14] = "CORE_GPIO_6", + [15] = "CORE_GPIO_7", + }; + + /* Status bits are in the upper 16 bits. */ + alt_gpio_sts = alt_gpio_smi >> 16; + if (!alt_gpio_sts) + return alt_gpio_smi; + + printk(BIOS_DEBUG, "ALT_GPIO_SMI: "); + print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return alt_gpio_smi; +} + +uint32_t clear_alt_status(void) +{ + return print_alt_sts(reset_alt_status()); +} diff --git a/src/soc/intel/baytrail/smihandler.c b/src/soc/intel/baytrail/smihandler.c index d5f6aa65d3..22b60c42d3 100644 --- a/src/soc/intel/baytrail/smihandler.c +++ b/src/soc/intel/baytrail/smihandler.c @@ -300,7 +300,7 @@ static void southbridge_smi_pm1(void) elog_add_event(ELOG_TYPE_POWER_BUTTON); #endif disable_pm1_control(-1UL); - enable_pm1_control(SLP_EN | (SLP_TYP_S5 << 10)); + enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT)); } } @@ -396,4 +396,8 @@ void southbridge_smi_handler(void) "handler available.\n", i); } } + + /* The GPIO SMI events do not have a status bit in SMI_STS. Therefore, + * these events need to be cleared and checked unconditionally. */ + mainboard_smi_gpi(clear_alt_status()); } diff --git a/src/soc/intel/baytrail/smm.c b/src/soc/intel/baytrail/smm.c index 1ba6246596..c654c8597e 100644 --- a/src/soc/intel/baytrail/smm.c +++ b/src/soc/intel/baytrail/smm.c @@ -61,6 +61,7 @@ void southcluster_smm_clear_state(void) clear_pm1_status(); clear_tco_status(); clear_gpe_status(); + clear_alt_status(); } static void southcluster_smm_route_gpios(void)