Save and restore the registers SOF and FRAMENUMBER on suspend. In some
cases the registers are not correctly set on resume. This solves the problem of USB failing after resuming a machine. Submitted by: mike+fbsd@medianstrip.net PR: 18261
This commit is contained in:
parent
2a46959d8e
commit
9bd863570a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64315
@ -250,6 +250,7 @@ Static void uhci_dump_tds(uhci_soft_td_t *);
|
||||
Static void uhci_dump_td(uhci_soft_td_t *);
|
||||
#endif
|
||||
|
||||
#define UWRITE1(sc, r, x) bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x))
|
||||
#define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
|
||||
#define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
|
||||
#define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r))
|
||||
@ -565,17 +566,17 @@ uhci_power(int why, void *v)
|
||||
sc->sc_has_timo->timo_handle);
|
||||
sc->sc_bus.use_polling++;
|
||||
uhci_run(sc, 0); /* stop the controller */
|
||||
|
||||
/* save some state if BIOS doesn't */
|
||||
sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM);
|
||||
sc->sc_saved_sof = UREAD1(sc, UHCI_SOF);
|
||||
|
||||
UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
|
||||
usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
|
||||
sc->sc_suspend = why;
|
||||
sc->sc_bus.use_polling--;
|
||||
DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
|
||||
} else {
|
||||
/*
|
||||
* XXX We should really do much more here in case the
|
||||
* controller registers have been lost and BIOS has
|
||||
* not restored them.
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sc->sc_suspend == PWR_RESUME)
|
||||
printf("uhci_power: weird, resume without suspend.\n");
|
||||
@ -584,6 +585,12 @@ uhci_power(int why, void *v)
|
||||
sc->sc_suspend = why;
|
||||
if (cmd & UHCI_CMD_RS)
|
||||
uhci_run(sc, 0); /* in case BIOS has started it */
|
||||
|
||||
/* restore saved state */
|
||||
UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0));
|
||||
UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum);
|
||||
UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof);
|
||||
|
||||
UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
|
||||
usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
|
||||
UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
|
||||
|
@ -154,6 +154,9 @@ typedef struct uhci_softc {
|
||||
u_int8_t sc_addr; /* device address */
|
||||
u_int8_t sc_conf; /* device configuration */
|
||||
|
||||
u_int8_t sc_saved_sof;
|
||||
u_int16_t sc_saved_frnum;
|
||||
|
||||
char sc_isreset;
|
||||
char sc_suspend;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user