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
7a93943baf
commit
38a807f0b0
@ -250,6 +250,7 @@ Static void uhci_dump_tds(uhci_soft_td_t *);
|
|||||||
Static void uhci_dump_td(uhci_soft_td_t *);
|
Static void uhci_dump_td(uhci_soft_td_t *);
|
||||||
#endif
|
#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 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 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))
|
#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_has_timo->timo_handle);
|
||||||
sc->sc_bus.use_polling++;
|
sc->sc_bus.use_polling++;
|
||||||
uhci_run(sc, 0); /* stop the controller */
|
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 */
|
UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
|
||||||
usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
|
usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
|
||||||
sc->sc_suspend = why;
|
sc->sc_suspend = why;
|
||||||
sc->sc_bus.use_polling--;
|
sc->sc_bus.use_polling--;
|
||||||
DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
|
DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
|
||||||
} else {
|
} 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
|
#ifdef DIAGNOSTIC
|
||||||
if (sc->sc_suspend == PWR_RESUME)
|
if (sc->sc_suspend == PWR_RESUME)
|
||||||
printf("uhci_power: weird, resume without suspend.\n");
|
printf("uhci_power: weird, resume without suspend.\n");
|
||||||
@ -584,6 +585,12 @@ uhci_power(int why, void *v)
|
|||||||
sc->sc_suspend = why;
|
sc->sc_suspend = why;
|
||||||
if (cmd & UHCI_CMD_RS)
|
if (cmd & UHCI_CMD_RS)
|
||||||
uhci_run(sc, 0); /* in case BIOS has started it */
|
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 */
|
UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
|
||||||
usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
|
usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
|
||||||
UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
|
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_addr; /* device address */
|
||||||
u_int8_t sc_conf; /* device configuration */
|
u_int8_t sc_conf; /* device configuration */
|
||||||
|
|
||||||
|
u_int8_t sc_saved_sof;
|
||||||
|
u_int16_t sc_saved_frnum;
|
||||||
|
|
||||||
char sc_isreset;
|
char sc_isreset;
|
||||||
char sc_suspend;
|
char sc_suspend;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user