aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/amd/stoneyridge/gpio.c27
-rw-r--r--src/soc/amd/stoneyridge/include/soc/gpio.h4
2 files changed, 30 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);
diff --git a/src/soc/amd/stoneyridge/include/soc/gpio.h b/src/soc/amd/stoneyridge/include/soc/gpio.h
index 47eae84c86..fe8240fb11 100644
--- a/src/soc/amd/stoneyridge/include/soc/gpio.h
+++ b/src/soc/amd/stoneyridge/include/soc/gpio.h
@@ -41,6 +41,10 @@ struct soc_amd_i2c_save {
uint8_t mux_value;
};
+#define GPIO_MASTER_SWITCH 0xFC
+#define GPIO_MASK_STS_EN BIT(28)
+#define GPIO_INTERRUPT_EN BIT(30)
+
#define GPIO_I2C0_SCL BIT(0)
#define GPIO_I2C1_SCL BIT(1)
#define GPIO_I2C2_SCL BIT(2)