From a29e15c6de98339d7c7acea3e97c5809105a4644 Mon Sep 17 00:00:00 2001 From: mlarkin Date: Mon, 27 Jun 2022 07:55:28 +0000 Subject: [PATCH] amdgpio(4): restore pin configuration on resume Save/restore the pin configuration on suspend/resume for amdgpio(4). This fixes missing interrupts after resume for trackpads on some machines, including the ROG Zephyrus 14 and the HP DevOne (and probably others). Code based on pchgpio(4). ok deraadt, kettenis --- sys/dev/acpi/amdgpio.c | 70 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/sys/dev/acpi/amdgpio.c b/sys/dev/acpi/amdgpio.c index 1d0cd5fcede..85a5c8bae56 100644 --- a/sys/dev/acpi/amdgpio.c +++ b/sys/dev/acpi/amdgpio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: amdgpio.c,v 1.7 2022/04/06 18:59:27 naddy Exp $ */ +/* $OpenBSD: amdgpio.c,v 1.8 2022/06/27 07:55:28 mlarkin Exp $ */ /* * Copyright (c) 2016 Mark Kettenis * Copyright (c) 2019 James Hastings @@ -48,6 +48,11 @@ struct amdgpio_intrhand { void *ih_arg; }; +struct amdgpio_pincfg { + /* Modeled after pchgpio but we only have one value to save/restore */ + uint32_t pin_cfg; +}; + struct amdgpio_softc { struct device sc_dev; struct acpi_softc *sc_acpi; @@ -59,6 +64,7 @@ struct amdgpio_softc { void *sc_ih; int sc_npins; + struct amdgpio_pincfg *sc_pin_cfg; struct amdgpio_intrhand *sc_pin_ih; struct acpi_gpio sc_gpio; @@ -66,9 +72,11 @@ struct amdgpio_softc { int amdgpio_match(struct device *, void *, void *); void amdgpio_attach(struct device *, struct device *, void *); +int amdgpio_activate(struct device *, int); const struct cfattach amdgpio_ca = { - sizeof(struct amdgpio_softc), amdgpio_match, amdgpio_attach + sizeof(struct amdgpio_softc), amdgpio_match, amdgpio_attach, + NULL, amdgpio_activate }; struct cfdriver amdgpio_cd = { @@ -86,6 +94,10 @@ void amdgpio_write_pin(void *, int, int); void amdgpio_intr_establish(void *, int, int, int (*)(void *), void *); int amdgpio_pin_intr(struct amdgpio_softc *, int); int amdgpio_intr(void *); +void amdgpio_save_pin(struct amdgpio_softc *, int pin); +void amdgpio_save(struct amdgpio_softc *); +void amdgpio_restore_pin(struct amdgpio_softc *, int pin); +void amdgpio_restore(struct amdgpio_softc *); int amdgpio_match(struct device *parent, void *match, void *aux) @@ -135,6 +147,8 @@ amdgpio_attach(struct device *parent, struct device *self, void *aux) return; } + sc->sc_pin_cfg = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_cfg), + M_DEVBUF, M_WAITOK); sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih), M_DEVBUF, M_WAITOK | M_ZERO); @@ -161,6 +175,58 @@ unmap: bus_space_unmap(sc->sc_memt, sc->sc_memh, aaa->aaa_size[0]); } +int +amdgpio_activate(struct device *self, int act) +{ + struct amdgpio_softc *sc = (struct amdgpio_softc *)self; + + switch (act) { + case DVACT_SUSPEND: + amdgpio_save(sc); + break; + case DVACT_RESUME: + amdgpio_restore(sc); + break; + } + + return 0; +} + +void +amdgpio_save_pin(struct amdgpio_softc *sc, int pin) +{ + sc->sc_pin_cfg[pin].pin_cfg = bus_space_read_4(sc->sc_memt, sc->sc_memh, + pin * 4); +} + +void +amdgpio_save(struct amdgpio_softc *sc) +{ + int pin; + + for (pin = 0 ; pin < sc->sc_npins; pin++) + amdgpio_save_pin(sc, pin); +} + +void +amdgpio_restore_pin(struct amdgpio_softc *sc, int pin) +{ + if (!sc->sc_pin_ih[pin].ih_func) + return; + + bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, + sc->sc_pin_cfg[pin].pin_cfg); +} + +void +amdgpio_restore(struct amdgpio_softc *sc) +{ + int pin; + + for (pin = 0; pin < sc->sc_npins; pin++) + amdgpio_restore_pin(sc, pin); +} + int amdgpio_read_pin(void *cookie, int pin) { -- 2.20.1