diff options
author | J.R. Oldroyd <jr@opal.com> | 2021-05-31 19:33:07 +0000 |
---|---|---|
committer | Vladimir Kondratyev <wulf@FreeBSD.org> | 2021-05-31 19:33:07 +0000 |
commit | 5236888db77194c194706b122675af7355fe7ceb (patch) | |
tree | 0c4094da404e2f92c90b1b1a79a65eb91b17998e | |
parent | da93a73f834612b659b37b513c8296e1178d249b (diff) | |
download | src-5236888db77194c194706b122675af7355fe7ceb.tar.gz src-5236888db77194c194706b122675af7355fe7ceb.zip |
iichid(4): disable interrupt on suspend
Commit message of the identical change in Linux driver says:
"When an I2C HID device is powered off during system sleep, as a result
of removing its power resources (by the ACPI core) the interrupt line
might go low as well. This results inadvertent interrupts."
This change fixes suspend/resume on Asus S510UQ laptops.
While here add a couple of typo fixes as well as a slight change to the
iichid_attach() code to have the power_on flag set properly.
Submitted by: J.R. Oldroyd <jr_AT_opal_DOT_com>
Reviewed by: wulf
MFC after: 1 week
-rw-r--r-- | sys/dev/iicbus/iichid.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c index 7c51a697c4c7..68d7cfd9090f 100644 --- a/sys/dev/iicbus/iichid.c +++ b/sys/dev/iicbus/iichid.c @@ -573,7 +573,7 @@ iichid_intr(void *context) * not allowed and often returns a garbage. If a HOST needs to * communicate with the DEVICE it MUST issue a SET POWER command * (to ON) before any other command. As some hardware requires reads to - * acknoledge interrupts we fetch only length header and discard it. + * acknowledge interrupts we fetch only length header and discard it. */ maxlen = sc->power_on ? sc->intr_bufsize : 0; error = iichid_cmd_read(sc, sc->intr_buf, maxlen, &actual); @@ -1069,14 +1069,16 @@ iichid_attach(device_t dev) error = iichid_reset(sc); if (error) { device_printf(dev, "failed to reset hardware: %d\n", error); - return (ENXIO); + error = ENXIO; + goto done; } - sc->power_on = false; + sc->power_on = true; + #ifdef IICHID_SAMPLING TASK_INIT(&sc->event_task, 0, iichid_event_task, sc); /* taskqueue_create can't fail with M_WAITOK mflag passed. */ - sc->taskqueue = taskqueue_create("hmt_tq", M_WAITOK | M_ZERO, + sc->taskqueue = taskqueue_create("iichid_tq", M_WAITOK | M_ZERO, taskqueue_thread_enqueue, &sc->taskqueue); TIMEOUT_TASK_INIT(sc->taskqueue, &sc->periodic_task, 0, iichid_event_task, sc); @@ -1144,8 +1146,10 @@ iichid_attach(device_t dev) device_printf(dev, "failed to attach child: error %d\n", error); iichid_detach(dev); } + done: (void)iichid_set_power(sc, I2C_HID_POWER_OFF); + sc->power_on = false; return (error); } @@ -1178,21 +1182,27 @@ iichid_suspend(device_t dev) int error; sc = device_get_softc(dev); - DPRINTF(sc, "Suspend called, setting device to power_state 1\n"); (void)bus_generic_suspend(dev); +#ifdef IICHID_SAMPLING + if (sc->sampling_rate_slow < 0) +#endif + (void)bus_generic_suspend_intr(device_get_parent(dev), dev, + sc->irq_res); + /* * 8.2 - The HOST is going into a deep power optimized state and wishes * to put all the devices into a low power state also. The HOST * is recommended to issue a HIPO command to the DEVICE to force * the DEVICE in to a lower power state. */ + DPRINTF(sc, "Suspend called, setting device to power_state 1\n"); error = iichid_set_power_state(sc, IICHID_PS_NULL, IICHID_PS_OFF); if (error != 0) DPRINTF(sc, "Could not set power_state, error: %d\n", error); else DPRINTF(sc, "Successfully set power_state\n"); - return (0); + return (0); } static int @@ -1209,6 +1219,11 @@ iichid_resume(device_t dev) else DPRINTF(sc, "Successfully set power_state\n"); (void)bus_generic_resume(dev); +#ifdef IICHID_SAMPLING + if (sc->sampling_rate_slow < 0) +#endif + (void)bus_generic_resume_intr(device_get_parent(dev), dev, + sc->irq_res); return (0); } |