From 244d7b1765700fd7cbc9c1a45e8ef15f2ae492a6 Mon Sep 17 00:00:00 2001 From: kettenis Date: Thu, 20 Oct 2022 20:40:57 +0000 Subject: [PATCH] Add the hooks to disable and enable GPIO interrupts. Should fix potential interrupt storms related to level-triggered interrupts. ok mglocker@ --- sys/dev/acpi/amdgpio.c | 32 ++++++++++++++++++++++- sys/dev/acpi/aplgpio.c | 36 +++++++++++++++++++++++++- sys/dev/acpi/bytgpio.c | 36 ++++++++++++++++++++++++-- sys/dev/acpi/chvgpio.c | 44 +++++++++++++++++++++++++++++++- sys/dev/acpi/glkgpio.c | 36 +++++++++++++++++++++++++- sys/dev/acpi/pchgpio.c | 58 +++++++++++++++++++++++++++++++++++++++++- 6 files changed, 235 insertions(+), 7 deletions(-) diff --git a/sys/dev/acpi/amdgpio.c b/sys/dev/acpi/amdgpio.c index 89161bf8012..d9e1b776d9e 100644 --- a/sys/dev/acpi/amdgpio.c +++ b/sys/dev/acpi/amdgpio.c @@ -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) { diff --git a/sys/dev/acpi/aplgpio.c b/sys/dev/acpi/aplgpio.c index 29106b5c3aa..0242542b089 100644 --- a/sys/dev/acpi/aplgpio.c +++ b/sys/dev/acpi/aplgpio.c @@ -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) { diff --git a/sys/dev/acpi/bytgpio.c b/sys/dev/acpi/bytgpio.c index 8b7f91516a7..9c3302b58cb 100644 --- a/sys/dev/acpi/bytgpio.c +++ b/sys/dev/acpi/bytgpio.c @@ -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) { diff --git a/sys/dev/acpi/chvgpio.c b/sys/dev/acpi/chvgpio.c index 80c9dff285c..78bfae352b5 100644 --- a/sys/dev/acpi/chvgpio.c +++ b/sys/dev/acpi/chvgpio.c @@ -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) { diff --git a/sys/dev/acpi/glkgpio.c b/sys/dev/acpi/glkgpio.c index 0e90b4967a0..5eccb72e4af 100644 --- a/sys/dev/acpi/glkgpio.c +++ b/sys/dev/acpi/glkgpio.c @@ -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) { diff --git a/sys/dev/acpi/pchgpio.c b/sys/dev/acpi/pchgpio.c index 7c49bc4c160..0e689768ae7 100644 --- a/sys/dev/acpi/pchgpio.c +++ b/sys/dev/acpi/pchgpio.c @@ -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) { -- 2.20.1