diff options
-rw-r--r-- | sys/dev/usb2/controller/uhci2.c | 24 | ||||
-rw-r--r-- | sys/dev/usb2/controller/usb2_controller.h | 5 | ||||
-rw-r--r-- | sys/dev/usb2/core/usb2_hub.c | 8 |
3 files changed, 36 insertions, 1 deletions
diff --git a/sys/dev/usb2/controller/uhci2.c b/sys/dev/usb2/controller/uhci2.c index e393218..e967a9e 100644 --- a/sys/dev/usb2/controller/uhci2.c +++ b/sys/dev/usb2/controller/uhci2.c @@ -2396,6 +2396,24 @@ uhci_portreset(uhci_softc_t *sc, uint16_t index, uint8_t use_polling) else return (USB_ERR_IOERROR); + /* + * Before we do anything, turn on SOF messages on the USB + * BUS. Some USB devices do not cope without them! + */ + if (!(UREAD2(sc, UHCI_CMD) & UHCI_CMD_RS)) { + + DPRINTF("Activating SOFs!\n"); + + UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS)); + + /* wait a little bit */ + if (use_polling) { + DELAY(10000); + } else { + usb2_pause_mtx(&sc->sc_bus.bus_mtx, 10); + } + } + x = URWMASK(UREAD2(sc, port)); UWRITE2(sc, port, x | UHCI_PORTSC_PR); @@ -3320,7 +3338,13 @@ uhci_set_hw_power(struct usb2_bus *bus) flags = bus->hw_power_state; + /* + * WARNING: Some FULL speed USB devices require periodic SOF + * messages! If any USB devices are connected through the + * UHCI, power save will be disabled! + */ if (flags & (USB_HW_POWER_CONTROL | + USB_HW_POWER_NON_ROOT_HUB | USB_HW_POWER_BULK | USB_HW_POWER_INTERRUPT | USB_HW_POWER_ISOC)) { diff --git a/sys/dev/usb2/controller/usb2_controller.h b/sys/dev/usb2/controller/usb2_controller.h index 646b49a..80633d9 100644 --- a/sys/dev/usb2/controller/usb2_controller.h +++ b/sys/dev/usb2/controller/usb2_controller.h @@ -84,6 +84,11 @@ struct usb2_bus_methods { * are active: */ #define USB_HW_POWER_ISOC 0x08 + /* + * The following flag is set if one or more non-root-HUB devices + * are present on the given USB bus: + */ +#define USB_HW_POWER_NON_ROOT_HUB 0x10 /* USB Device mode only - Mandatory */ diff --git a/sys/dev/usb2/core/usb2_hub.c b/sys/dev/usb2/core/usb2_hub.c index 2c528d4..709fdeb 100644 --- a/sys/dev/usb2/core/usb2_hub.c +++ b/sys/dev/usb2/core/usb2_hub.c @@ -1503,7 +1503,7 @@ usb2_bus_powerd(struct usb2_bus *bus) unsigned int temp; unsigned int limit; unsigned int mintime; - uint32_t type_refs[4]; + uint32_t type_refs[5]; uint8_t x; uint8_t rem_wakeup; @@ -1564,6 +1564,7 @@ usb2_bus_powerd(struct usb2_bus *bus) type_refs[1] = 0; type_refs[2] = 0; type_refs[3] = 0; + type_refs[4] = 0; /* Re-loop all the devices to get the actual state */ @@ -1574,6 +1575,9 @@ usb2_bus_powerd(struct usb2_bus *bus) if (udev == NULL) continue; + /* we found a non-Root-Hub USB device */ + type_refs[4] += 1; + /* "last_xfer_time" can be updated by a resume */ temp = ticks - udev->pwr_save.last_xfer_time; @@ -1604,6 +1608,8 @@ usb2_bus_powerd(struct usb2_bus *bus) bus->hw_power_state |= USB_HW_POWER_INTERRUPT; if (type_refs[UE_ISOCHRONOUS] != 0) bus->hw_power_state |= USB_HW_POWER_ISOC; + if (type_refs[4] != 0) + bus->hw_power_state |= USB_HW_POWER_NON_ROOT_HUB; } USB_BUS_UNLOCK(bus); |