> Date: Tue, 19 Apr 2022 22:02:00 -0700 > From: Mike Larkin <mlar...@nested.page> > > On at least the Asus ROG Zephyrus 14 (2020), the trackpad fails to generate > any interrupts after resume. I tracked this down to amdgpio(4) not generating > interrupts after resume, and started looking at missing soft state. > > This diff preserves the interrupt pin configurations and restores them after > resume. This makes the device function properly post-zzz and post-ZZZ.
I think it might make sense to structure this a bit more like pchgpio(4). There we only restore the configuration for pins that are "in use" by OpenBSD. > Note: amdgpio_read_pin does not return the value that was previously written > during amdgpio_intr_establish (it always just returns 0x1 if the pin is > in use), so I'm just saving the actual value we write during > amdgpio_intr_establish and restoring that during resume. Well, using amdgpio_read_pin() for the purpose of saving the pin configuration doesn't make sense. That function returns the pin input state. What you need to do is to read the register using bus_space_read_4() and restore that value. Again take a look at pchgpio(4). > Note 2: In xxx_activate() functions, we usually call config_activate_children > but since amdgpio doesn't have any children, I left that out. I think that's fine. But you should do the save/restore in DVACT_SUSPEND/DVACT_RESUME. You want to restore the state as early as possible such that you don't get spurious interrupts when the BIOS leaves GPIO pins misconfigured. Again, look at pchgpio(4). > > ok? > > -ml > > > diff a82721d2c9ea32a8f6043a3e06b2a7f8280ef68b /export/bin/src/OpenBSD/g14 > blob - 1d0cd5fcede71f0495a271a9d06fc9c0ecb16412 > file + sys/dev/acpi/amdgpio.c > --- sys/dev/acpi/amdgpio.c > +++ sys/dev/acpi/amdgpio.c > @@ -62,13 +62,17 @@ struct amdgpio_softc { > struct amdgpio_intrhand *sc_pin_ih; > > struct acpi_gpio sc_gpio; > + > + uint32_t *sc_pincfg; > }; > > 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 = { > @@ -98,6 +102,24 @@ amdgpio_match(struct device *parent, void *match, void > return acpi_matchhids(aaa, amdgpio_hids, cf->cf_driver->cd_name); > } > > +int > +amdgpio_activate(struct device *self, int act) > +{ > + struct amdgpio_softc *sc = (struct amdgpio_softc *)self; > + int rv = 0, i; > + > + switch (act) { > + case DVACT_WAKEUP: > + for (i = 0; i < sc->sc_npins; i++) { > + if (sc->sc_pincfg[i]) > + bus_space_write_4(sc->sc_memt, sc->sc_memh, > + i * 4, sc->sc_pincfg[i]); > + } > + } > + > + return (rv); > +} > + > void > amdgpio_attach(struct device *parent, struct device *self, void *aux) > { > @@ -152,6 +174,8 @@ amdgpio_attach(struct device *parent, struct device *s > sc->sc_node->gpio = &sc->sc_gpio; > > printf(", %d pins\n", sc->sc_npins); > + sc->sc_pincfg = malloc(sc->sc_npins * sizeof(uint32_t), M_DEVBUF, > + M_WAITOK | M_ZERO); > > acpi_register_gpio(sc->sc_acpi, sc->sc_node); > return; > @@ -210,6 +234,8 @@ amdgpio_intr_establish(void *cookie, int pin, int flag > reg |= AMDGPIO_CONF_ACTBOTH; > reg |= (AMDGPIO_CONF_INT_MASK | AMDGPIO_CONF_INT_EN); > bus_space_write_4(sc->sc_memt, sc->sc_memh, pin * 4, reg); > + > + sc->sc_pincfg[pin] = reg; > } > > int > >