Microchip: XEC GPIO driver interrupt enable fix part 2

Fixes issue 34879
This PR updates previous PR's 37138 and 37139.
Refer to issue 34879 for information from MCHP HW
designers. A delay after enabling interrupts is a
more appropriate work-around than depending upon
behavior of ARM DMB instruction.

Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
Scott Worley 2021-08-05 14:32:48 -04:00 committed by Christopher Friedt
commit 114b84a58b
2 changed files with 13 additions and 9 deletions

View file

@ -9,13 +9,12 @@
#include <errno.h> #include <errno.h>
#include <device.h> #include <device.h>
#include <drivers/gpio.h> #include <drivers/gpio.h>
#include <sys/sys_io.h>
#include <soc.h> #include <soc.h>
#include "gpio_utils.h" #include "gpio_utils.h"
#define XEC_GPIO_EDGE_DLY_COUNT 8 #define XEC_GPIO_EDGE_DLY_COUNT 4
/* read only register in same AHB segmment for dummy writes */
#define XEC_GPIO_DLY_ADDR 0x40080150u
#define GPIO_IN_BASE(config) \ #define GPIO_IN_BASE(config) \
((__IO uint32_t *)(GPIO_PARIN_BASE + (config->port_num << 2))) ((__IO uint32_t *)(GPIO_PARIN_BASE + (config->port_num << 2)))
@ -215,7 +214,10 @@ static int gpio_xec_pin_interrupt_configure(const struct device *dev,
*/ */
current_pcr1 = config->pcr1_base + pin; current_pcr1 = config->pcr1_base + pin;
*current_pcr1 = (*current_pcr1 & ~mask) | pcr1; *current_pcr1 = (*current_pcr1 & ~mask) | pcr1;
__DMB(); /* insure write completes */ /* delay for HW to synchronize after it ungates its clock */
for (int i = 0; i < XEC_GPIO_EDGE_DLY_COUNT; i++) {
(void)*current_pcr1;
}
if (mode != GPIO_INT_MODE_DISABLED) { if (mode != GPIO_INT_MODE_DISABLED) {
/* We enable the interrupts in the EC aggregator so that the /* We enable the interrupts in the EC aggregator so that the

View file

@ -14,7 +14,7 @@
#include "gpio_utils.h" #include "gpio_utils.h"
#define XEC_ECIA_REGS ((struct ecia_regs *)(DT_REG_ADDR(DT_NODELABEL(ecia)))) #define XEC_GPIO_EDGE_DLY_COUNT 4
static const uint32_t valid_ctrl_masks[NUM_MCHP_GPIO_PORTS] = { static const uint32_t valid_ctrl_masks[NUM_MCHP_GPIO_PORTS] = {
(MCHP_GPIO_PORT_A_BITMAP), (MCHP_GPIO_PORT_A_BITMAP),
@ -268,7 +268,6 @@ static int gpio_xec_pin_interrupt_configure(const struct device *dev,
} else { } else {
pcr1 |= MCHP_GPIO_CTRL_IDET_LVL_LO; pcr1 |= MCHP_GPIO_CTRL_IDET_LVL_LO;
} }
sys_write32(pcr1, pcr1_addr);
} else if (mode == GPIO_INT_MODE_EDGE) { } else if (mode == GPIO_INT_MODE_EDGE) {
if (trig == GPIO_INT_TRIG_LOW) { if (trig == GPIO_INT_TRIG_LOW) {
pcr1 |= MCHP_GPIO_CTRL_IDET_FEDGE; pcr1 |= MCHP_GPIO_CTRL_IDET_FEDGE;
@ -277,11 +276,14 @@ static int gpio_xec_pin_interrupt_configure(const struct device *dev,
} else if (trig == GPIO_INT_TRIG_BOTH) { } else if (trig == GPIO_INT_TRIG_BOTH) {
pcr1 |= MCHP_GPIO_CTRL_IDET_BEDGE; pcr1 |= MCHP_GPIO_CTRL_IDET_BEDGE;
} }
sys_write32(pcr1, pcr1_addr);
__DMB(); /* insure write completes */
} else { } else {
pcr1 |= MCHP_GPIO_CTRL_IDET_DISABLE; pcr1 |= MCHP_GPIO_CTRL_IDET_DISABLE;
}
sys_write32(pcr1, pcr1_addr); sys_write32(pcr1, pcr1_addr);
/* delay for HW to synchronize after it ungates its clock */
for (int i = 0; i < XEC_GPIO_EDGE_DLY_COUNT; i++) {
sys_read32(pcr1_addr);
} }
mchp_soc_ecia_girq_src_clr(config->girq_id, pin); mchp_soc_ecia_girq_src_clr(config->girq_id, pin);