diff --git a/sys/dev/amdgpio/amdgpio.c b/sys/dev/amdgpio/amdgpio.c --- a/sys/dev/amdgpio/amdgpio.c +++ b/sys/dev/amdgpio/amdgpio.c @@ -537,22 +537,72 @@ return (0); } +static int +amdgpio_suspend(device_t dev) +{ + struct amdgpio_softc *sc = device_get_softc(dev); + uint32_t reg; + size_t i; + int pin, off; + uint32_t unserviced_mask = (1 << INTERRUPT_STS_OFF) | + (1 << WAKE_STS_OFF); + + AMDGPIO_LOCK(sc); + + for (i = 0; i < AMD_GPIO_PINS_EXPOSED; i++) { + pin = kernzp_pins[i].pin_num; + off = AMDGPIO_PIN_REGISTER(pin); + + reg = amdgpio_read_4(sc, off); + if ((reg & unserviced_mask) != 0) + device_printf(dev, "unserviced interrupt on pin %d!\n", + pin); + /* + * "Service" interrupt and mask. In the future we should only + * mask non-wake interrupts (see WAKE_CNTRL_OFF_S0I3 &c). + * + * (From BKDG) write 1 to interrupt & wake status registers to + * clear them. We can do this by just writing back to them. + */ + reg &= ~(1 << INTERRUPT_MASK_OFF); + reg &= ~(1 << INTERRUPT_ENABLE_OFF); + amdgpio_write_4(sc, off, reg); + } + + amdgpio_eoi_locked(sc); + AMDGPIO_UNLOCK(sc); + + return (0); +} + +static int +amdgpio_resume(device_t dev) +{ + /* + * XXX Will have to resume properly once we're actually able to use + * amdgpio for interrupts. + */ + return (0); +} + static device_method_t amdgpio_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, amdgpio_probe), - DEVMETHOD(device_attach, amdgpio_attach), - DEVMETHOD(device_detach, amdgpio_detach), + DEVMETHOD(device_probe, amdgpio_probe), + DEVMETHOD(device_attach, amdgpio_attach), + DEVMETHOD(device_detach, amdgpio_detach), + DEVMETHOD(device_suspend, amdgpio_suspend), + DEVMETHOD(device_resume, amdgpio_resume), /* GPIO protocol */ - DEVMETHOD(gpio_get_bus, amdgpio_get_bus), - DEVMETHOD(gpio_pin_max, amdgpio_pin_max), - DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname), - DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps), - DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags), - DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags), - DEVMETHOD(gpio_pin_get, amdgpio_pin_get), - DEVMETHOD(gpio_pin_set, amdgpio_pin_set), - DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle), + DEVMETHOD(gpio_get_bus, amdgpio_get_bus), + DEVMETHOD(gpio_pin_max, amdgpio_pin_max), + DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname), + DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps), + DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags), + DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags), + DEVMETHOD(gpio_pin_get, amdgpio_pin_get), + DEVMETHOD(gpio_pin_set, amdgpio_pin_set), + DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle), DEVMETHOD_END };