--- a/sys/bus/gpio/gpio_intel/gpio_cherryview.c +++ b/sys/bus/gpio/gpio_intel/gpio_cherryview.c @@ -381,7 +381,8 @@ gpio_cherryview_unmap_intr(struct gpio_intel_softc *sc, struct pin_intr_map *map) { - uint32_t reg, intcfg, gpiocfg; + uint32_t reg, intcfg, gpiocfg, mask; + int intidx = map->intidx; uint16_t pin = map->pin; intcfg = map->orig_intcfg; @@ -396,6 +397,21 @@ map->orig_intcfg = 0; map->orig_gpiocfg = 0; + /* + * Make sure the interrupt line is masked and has no pending + * status, in case the caller did not tear the interrupt down + * before freeing it. Leaving the line armed with no mapping + * turns a level-asserted pad into an endless interrupt storm, + * because gpio_cherryview_intr() then takes the is_level==0 + * edge-clear path on a source that re-asserts immediately. + */ + if (intidx >= 0) { + mask = chvgpio_read(sc, CHV_GPIO_REG_MASK); + mask &= ~(1U << intidx); + chvgpio_write(sc, CHV_GPIO_REG_MASK, mask); + chvgpio_write(sc, CHV_GPIO_REG_IS, 1U << intidx); + } + /* Restore interrupt configuration if needed */ reg = chvgpio_read(sc, PIN_CTL1(pin)); if ((reg & CHV_GPIO_CTL1_INTCFG_MASK) != intcfg) {