aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/stoneyridge/gpio.c
diff options
context:
space:
mode:
authorRaul E Rangel <rrangel@chromium.org>2019-01-24 11:52:20 -0700
committerPatrick Georgi <pgeorgi@google.com>2019-01-28 13:35:44 +0000
commitdf3064227fb252ccf0ffac6419910bdd6f6ec536 (patch)
tree76eb1e574ff3174611bd338e9abaa54482f5c5be /src/soc/amd/stoneyridge/gpio.c
parent595202c304d14e17b1ea1514169346d7cc637206 (diff)
amd/stoneyridge: Disable GPIO MASK STATUS
MASK_STATUS disables interrupt status generation for the entire GPIO controller when any debounce register is configured. This causes problems when the kernel is loading drivers because we could lose interrupts for previously loaded devices. sb_program_gpios is also not setup to wait when configuring PAD_DEBOUNCE, so there is a potential that we could lose the interrupt status enable bit for other registers. By disabling MASK_STATUS we avoid that problem. BUG=b:113880780 BRANCH=none TEST=Ran a reboot stress test that concluded that we are no longer losing TPM interrupts while booting. Change-Id: Ife1db3b1449f205092509595cbc3eca511bff57a Signed-off-by: Raul E Rangel <rrangel@chromium.org> Reviewed-on: https://review.coreboot.org/c/31082 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Daniel Kurtz <djkurtz@google.com>
Diffstat (limited to 'src/soc/amd/stoneyridge/gpio.c')
-rw-r--r--src/soc/amd/stoneyridge/gpio.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/soc/amd/stoneyridge/gpio.c b/src/soc/amd/stoneyridge/gpio.c
index 955cc6a0cc..621aca3631 100644
--- a/src/soc/amd/stoneyridge/gpio.c
+++ b/src/soc/amd/stoneyridge/gpio.c
@@ -222,15 +222,30 @@ uint16_t gpio_acpi_pin(gpio_t gpio)
void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
{
uint8_t *mux_ptr;
- uint32_t *gpio_ptr;
+ uint32_t *gpio_ptr, *inter_master;
uint32_t control, control_flags, edge_level, direction;
uint32_t mask, bit_edge, bit_level;
uint8_t mux, index, gpio;
int gevent_num;
+ inter_master = (uint32_t *)(uintptr_t)(GPIO_CONTROL_MMIO_BASE
+ + GPIO_MASTER_SWITCH);
direction = 0;
edge_level = 0;
mask = 0;
+
+ /*
+ * Disable blocking wake/interrupt status generation while updating
+ * debounce registers. Otherwise when a debounce register is updated
+ * the whole GPIO controller will zero out all interrupt enable status
+ * bits while the delay happens. This could cause us to drop the bits
+ * due to the read-modify-write that happens on each register.
+ *
+ * Additionally disable interrupt generation so we don't get any
+ * spurious interrupts while updating the registers.
+ */
+ mem_read_write32(inter_master, 0, GPIO_MASK_STS_EN | GPIO_INTERRUPT_EN);
+
for (index = 0; index < size; index++) {
gpio = gpio_list_ptr[index].gpio;
mux = gpio_list_ptr[index].function;
@@ -290,6 +305,16 @@ void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
AMD_GPIO_CONTROL_MASK);
}
}
+
+ /*
+ * Re-enable interrupt status generation.
+ *
+ * We leave MASK_STATUS disabled because the kernel may reconfigure the
+ * debounce registers while the drivers load. This will cause interrupts
+ * to be missed during boot.
+ */
+ mem_read_write32(inter_master, GPIO_INTERRUPT_EN, GPIO_INTERRUPT_EN);
+
/* Set all SCI trigger direction (high/low) */
mem_read_write32((uint32_t *)(uintptr_t)(APU_SMI_BASE + SMI_SCI_TRIG),
direction, mask);