summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2022-06-27 07:55:29 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2022-06-27 07:55:29 +0000
commite2888cd8f88e907ee80d0edf9c53d291aeb0e4ed (patch)
tree18d34175917cf32a793ecd71bd69cfd3e6b475a8
parent73868d4f61aa672cb259aa32606518c590df661f (diff)
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
-rw-r--r--sys/dev/acpi/amdgpio.c70
1 files 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);
@@ -162,6 +176,58 @@ unmap:
}
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)
{
struct amdgpio_softc *sc = cookie;