Add the hooks to disable and enable GPIO interrupts. Should fix potential
authorkettenis <kettenis@openbsd.org>
Thu, 20 Oct 2022 20:40:57 +0000 (20:40 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 20 Oct 2022 20:40:57 +0000 (20:40 +0000)
interrupt storms related to level-triggered interrupts.

ok mglocker@

sys/dev/acpi/amdgpio.c
sys/dev/acpi/aplgpio.c
sys/dev/acpi/bytgpio.c
sys/dev/acpi/chvgpio.c
sys/dev/acpi/glkgpio.c
sys/dev/acpi/pchgpio.c

index 89161bf..d9e1b77 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: amdgpio.c,v 1.9 2022/06/27 08:00:31 mlarkin Exp $     */
+/*     $OpenBSD: amdgpio.c,v 1.10 2022/10/20 20:40:57 kettenis Exp $   */
 /*
  * Copyright (c) 2016 Mark Kettenis
  * Copyright (c) 2019 James Hastings
@@ -92,6 +92,8 @@ const char *amdgpio_hids[] = {
 int    amdgpio_read_pin(void *, int);
 void   amdgpio_write_pin(void *, int, int);
 void   amdgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   amdgpio_intr_enable(void *, int);
+void   amdgpio_intr_disable(void *, int);
 int    amdgpio_pin_intr(struct amdgpio_softc *, int);
 int    amdgpio_intr(void *);
 void   amdgpio_save_pin(struct amdgpio_softc *, int pin);
@@ -163,6 +165,8 @@ amdgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = amdgpio_read_pin;
        sc->sc_gpio.write_pin = amdgpio_write_pin;
        sc->sc_gpio.intr_establish = amdgpio_intr_establish;
+       sc->sc_gpio.intr_enable = amdgpio_intr_enable;
+       sc->sc_gpio.intr_disable = amdgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        printf(", %d pins\n", sc->sc_npins);
@@ -278,6 +282,32 @@ amdgpio_intr_establish(void *cookie, int pin, int flags,
        bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg);
 }
 
+void
+amdgpio_intr_enable(void *cookie, int pin)
+{
+       struct amdgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin != 63 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4);
+       reg |= (AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN);
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg);
+}
+
+void
+amdgpio_intr_disable(void *cookie, int pin)
+{
+       struct amdgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin != 63 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, pin * 4);
+       reg &= ~(AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN);
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg);
+}
+
 int
 amdgpio_pin_intr(struct amdgpio_softc *sc, int pin)
 {
index 29106b5..0242542 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aplgpio.c,v 1.5 2022/04/06 18:59:27 naddy Exp $       */
+/*     $OpenBSD: aplgpio.c,v 1.6 2022/10/20 20:40:57 kettenis Exp $    */
 /*
  * Copyright (c) 2016 Mark Kettenis
  * Copyright (c) 2019 James Hastings
@@ -76,6 +76,8 @@ const char *aplgpio_hids[] = {
 int    aplgpio_read_pin(void *, int);
 void   aplgpio_write_pin(void *, int, int);
 void   aplgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   aplgpio_intr_enable(void *, int);
+void   aplgpio_intr_disable(void *, int);
 int    aplgpio_intr(void *);
 
 int
@@ -150,6 +152,8 @@ aplgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = aplgpio_read_pin;
        sc->sc_gpio.write_pin = aplgpio_write_pin;
        sc->sc_gpio.intr_establish = aplgpio_intr_establish;
+       sc->sc_gpio.intr_enable = aplgpio_intr_enable;
+       sc->sc_gpio.intr_disable = aplgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        /* Mask and clear all interrupts. */
@@ -231,6 +235,36 @@ aplgpio_intr_establish(void *cookie, int pin, int flags,
            APLGPIO_IRQ_EN + (pin / 32) * 4, reg);
 }
 
+void
+aplgpio_intr_enable(void *cookie, int pin)
+{
+       struct aplgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+           APLGPIO_IRQ_EN + (pin / 32) * 4);
+       reg |= (1 << (pin % 32));
+       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+           APLGPIO_IRQ_EN + (pin / 32) * 4, reg);
+}
+
+void
+aplgpio_intr_disable(void *cookie, int pin)
+{
+       struct aplgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+           APLGPIO_IRQ_EN + (pin / 32) * 4);
+       reg &= ~(1 << (pin % 32));
+       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+           APLGPIO_IRQ_EN + (pin / 32) * 4, reg);
+}
+
 int
 aplgpio_intr(void *arg)
 {
index 8b7f915..9c3302b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bytgpio.c,v 1.17 2022/04/06 18:59:27 naddy Exp $      */
+/*     $OpenBSD: bytgpio.c,v 1.18 2022/10/20 20:40:57 kettenis Exp $   */
 /*
  * Copyright (c) 2016 Mark Kettenis
  *
@@ -40,6 +40,7 @@
 struct bytgpio_intrhand {
        int (*ih_func)(void *);
        void *ih_arg;
+       int ih_tflags;
 };
 
 struct bytgpio_softc {
@@ -102,6 +103,8 @@ const int byt_sus_pins[] = {
 int    bytgpio_read_pin(void *, int);
 void   bytgpio_write_pin(void *, int, int);
 void   bytgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   bytgpio_intr_enable(void *, int);
+void   bytgpio_intr_disable(void *, int);
 int    bytgpio_intr(void *);
 
 int
@@ -177,6 +180,8 @@ bytgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = bytgpio_read_pin;
        sc->sc_gpio.write_pin = bytgpio_write_pin;
        sc->sc_gpio.intr_establish = bytgpio_intr_establish;
+       sc->sc_gpio.intr_enable = bytgpio_intr_enable;
+       sc->sc_gpio.intr_disable = bytgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        /* Mask all interrupts. */
@@ -233,12 +238,26 @@ bytgpio_intr_establish(void *cookie, int pin, int flags,
     int (*func)(void *), void *arg)
 {
        struct bytgpio_softc *sc = cookie;
-       uint32_t reg;
 
        KASSERT(pin >= 0 && pin < sc->sc_npins);
 
        sc->sc_pin_ih[pin].ih_func = func;
        sc->sc_pin_ih[pin].ih_arg = arg;
+       sc->sc_pin_ih[pin].ih_tflags = flags;
+
+       bytgpio_intr_enable(cookie, pin);
+}
+
+void
+bytgpio_intr_enable(void *cookie, int pin)
+{
+       struct bytgpio_softc *sc = cookie;
+       uint32_t reg;
+       int flags;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       flags = sc->sc_pin_ih[pin].ih_tflags;
 
        reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16);
        reg &= ~BYTGPIO_CONF_GD_MASK;
@@ -253,6 +272,19 @@ bytgpio_intr_establish(void *cookie, int pin, int flags,
        bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg);
 }
 
+void
+bytgpio_intr_disable(void *cookie, int pin)
+{
+       struct bytgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16);
+       reg &= ~BYTGPIO_CONF_GD_MASK;
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg);
+}
+
 int
 bytgpio_intr(void *arg)
 {
index 80c9dff..78bfae3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: chvgpio.c,v 1.12 2022/04/06 18:59:27 naddy Exp $      */
+/*     $OpenBSD: chvgpio.c,v 1.13 2022/10/20 20:40:57 kettenis Exp $   */
 /*
  * Copyright (c) 2016 Mark Kettenis
  *
@@ -146,6 +146,8 @@ int chvgpio_check_pin(struct chvgpio_softc *, int);
 int    chvgpio_read_pin(void *, int);
 void   chvgpio_write_pin(void *, int, int);
 void   chvgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   chvgpio_intr_enable(void *, int);
+void   chvgpio_intr_disable(void *, int);
 int    chvgpio_intr(void *);
 int    chvgpio_opreg_handler(void *, int, uint64_t, int, uint64_t *);
 
@@ -224,6 +226,8 @@ chvgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = chvgpio_read_pin;
        sc->sc_gpio.write_pin = chvgpio_write_pin;
        sc->sc_gpio.intr_establish = chvgpio_intr_establish;
+       sc->sc_gpio.intr_enable = chvgpio_intr_enable;
+       sc->sc_gpio.intr_disable = chvgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        /* Mask and ack all interrupts. */
@@ -335,6 +339,44 @@ chvgpio_intr_establish(void *cookie, int pin, int flags,
            CHVGPIO_INTERRUPT_MASK, reg | (1 << line));
 }
 
+void
+chvgpio_intr_enable(void *cookie, int pin)
+{
+       struct chvgpio_softc *sc = cookie;
+       uint32_t reg;
+       int line;
+
+       KASSERT(chvgpio_check_pin(sc, pin) == 0);
+
+       reg = chvgpio_read_pad_cfg0(sc, pin);
+       reg &= CHVGPIO_PAD_CFG0_INTSEL_MASK;
+       line = reg >> CHVGPIO_PAD_CFG0_INTSEL_SHIFT;
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+           CHVGPIO_INTERRUPT_MASK);
+       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+           CHVGPIO_INTERRUPT_MASK, reg | (1 << line));
+}      
+
+void
+chvgpio_intr_disable(void *cookie, int pin)
+{
+       struct chvgpio_softc *sc = cookie;
+       uint32_t reg;
+       int line;
+
+       KASSERT(chvgpio_check_pin(sc, pin) == 0);
+
+       reg = chvgpio_read_pad_cfg0(sc, pin);
+       reg &= CHVGPIO_PAD_CFG0_INTSEL_MASK;
+       line = reg >> CHVGPIO_PAD_CFG0_INTSEL_SHIFT;
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+           CHVGPIO_INTERRUPT_MASK);
+       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+           CHVGPIO_INTERRUPT_MASK, reg & ~(1 << line));
+}      
+
 int
 chvgpio_intr(void *arg)
 {
index 0e90b49..5eccb72 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: glkgpio.c,v 1.5 2022/04/06 18:59:27 naddy Exp $       */
+/*     $OpenBSD: glkgpio.c,v 1.6 2022/10/20 20:40:57 kettenis Exp $    */
 /*
  * Copyright (c) 2016 Mark Kettenis
  * Copyright (c) 2019 James Hastings
@@ -77,6 +77,8 @@ int   glkgpio_parse_resources(int, union acpi_resource *, void *);
 int    glkgpio_read_pin(void *, int);
 void   glkgpio_write_pin(void *, int, int);
 void   glkgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   glkgpio_intr_enable(void *, int);
+void   glkgpio_intr_disable(void *, int);
 int    glkgpio_intr(void *);
 
 int
@@ -151,6 +153,8 @@ glkgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = glkgpio_read_pin;
        sc->sc_gpio.write_pin = glkgpio_write_pin;
        sc->sc_gpio.intr_establish = glkgpio_intr_establish;
+       sc->sc_gpio.intr_enable = glkgpio_intr_enable;
+       sc->sc_gpio.intr_disable = glkgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        /* Mask and clear all interrupts. */
@@ -232,6 +236,36 @@ glkgpio_intr_establish(void *cookie, int pin, int flags,
            GLKGPIO_IRQ_EN + (pin / 32) * 4, reg);
 }
 
+void
+glkgpio_intr_enable(void *cookie, int pin)
+{
+       struct glkgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+           GLKGPIO_IRQ_EN + (pin / 32) * 4);
+       reg |= (1 << (pin % 32));
+       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+           GLKGPIO_IRQ_EN + (pin / 32) * 4, reg);
+}
+
+void
+glkgpio_intr_disable(void *cookie, int pin)
+{
+       struct glkgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+           GLKGPIO_IRQ_EN + (pin / 32) * 4);
+       reg &= ~(1 << (pin % 32));
+       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+           GLKGPIO_IRQ_EN + (pin / 32) * 4, reg);
+}
+
 int
 glkgpio_intr(void *arg)
 {
index 7c49bc4..0e68976 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pchgpio.c,v 1.13 2022/06/29 01:05:18 jsg Exp $        */
+/*     $OpenBSD: pchgpio.c,v 1.14 2022/10/20 20:40:57 kettenis Exp $   */
 /*
  * Copyright (c) 2020 Mark Kettenis
  * Copyright (c) 2020 James Hastings
@@ -325,6 +325,8 @@ struct pchgpio_match pchgpio_devices[] = {
 int    pchgpio_read_pin(void *, int);
 void   pchgpio_write_pin(void *, int, int);
 void   pchgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   pchgpio_intr_enable(void *, int);
+void   pchgpio_intr_disable(void *, int);
 int    pchgpio_intr(void *);
 void   pchgpio_save(struct pchgpio_softc *);
 void   pchgpio_restore(struct pchgpio_softc *);
@@ -406,6 +408,8 @@ pchgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = pchgpio_read_pin;
        sc->sc_gpio.write_pin = pchgpio_write_pin;
        sc->sc_gpio.intr_establish = pchgpio_intr_establish;
+       sc->sc_gpio.intr_enable = pchgpio_intr_enable;
+       sc->sc_gpio.intr_disable = pchgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        printf(", %d pins\n", sc->sc_npins);
@@ -538,6 +542,58 @@ pchgpio_intr_establish(void *cookie, int pin, int flags,
            sc->sc_device->gpi_ie + bank * 4, reg);
 }
 
+void
+pchgpio_intr_enable(void *cookie, int pin)
+{
+       struct pchgpio_softc *sc = cookie;
+       const struct pchgpio_group *group;
+       uint32_t reg;
+       uint16_t pad;
+       uint8_t bank, bar;
+
+       KASSERT(pin >= 0);
+
+       group = pchgpio_find_group(sc, pin);
+       if (group == NULL)
+               return;
+
+       bar = group->bar;
+       bank = group->bank;
+       pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
+
+       reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
+           sc->sc_device->gpi_ie + bank * 4);
+       reg |= (1 << (pin - group->gpiobase));
+       bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
+           sc->sc_device->gpi_ie + bank * 4, reg);
+}
+
+void
+pchgpio_intr_disable(void *cookie, int pin)
+{
+       struct pchgpio_softc *sc = cookie;
+       const struct pchgpio_group *group;
+       uint32_t reg;
+       uint16_t pad;
+       uint8_t bank, bar;
+
+       KASSERT(pin >= 0);
+
+       group = pchgpio_find_group(sc, pin);
+       if (group == NULL)
+               return;
+
+       bar = group->bar;
+       bank = group->bank;
+       pad = group->base + (pin - group->gpiobase) - sc->sc_padbase[bar];
+
+       reg = bus_space_read_4(sc->sc_memt[bar], sc->sc_memh[bar],
+           sc->sc_device->gpi_ie + bank * 4);
+       reg &= ~(1 << (pin - group->gpiobase));
+       bus_space_write_4(sc->sc_memt[bar], sc->sc_memh[bar],
+           sc->sc_device->gpi_ie + bank * 4, reg);
+}
+
 int
 pchgpio_intr_handle(struct pchgpio_softc *sc, int group, int bit)
 {