diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 18 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 44 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 6 |
4 files changed, 62 insertions, 17 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 17cfb8a1131c..c30435499a02 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -281,14 +281,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
281 | } | 281 | } |
282 | } | 282 | } |
283 | 283 | ||
284 | /* Hold PHYs in reset while initializing EHCI controller */ | ||
284 | if (pdata->phy_reset) { | 285 | if (pdata->phy_reset) { |
285 | if (gpio_is_valid(pdata->reset_gpio_port[0])) | 286 | if (gpio_is_valid(pdata->reset_gpio_port[0])) |
286 | gpio_request_one(pdata->reset_gpio_port[0], | 287 | gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); |
287 | GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); | ||
288 | 288 | ||
289 | if (gpio_is_valid(pdata->reset_gpio_port[1])) | 289 | if (gpio_is_valid(pdata->reset_gpio_port[1])) |
290 | gpio_request_one(pdata->reset_gpio_port[1], | 290 | gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); |
291 | GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); | ||
292 | 291 | ||
293 | /* Hold the PHY in RESET for enough time till DIR is high */ | 292 | /* Hold the PHY in RESET for enough time till DIR is high */ |
294 | udelay(10); | 293 | udelay(10); |
@@ -330,6 +329,11 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
330 | omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); | 329 | omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); |
331 | 330 | ||
332 | ehci_reset(omap_ehci); | 331 | ehci_reset(omap_ehci); |
332 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
333 | if (ret) { | ||
334 | dev_err(dev, "failed to add hcd with err %d\n", ret); | ||
335 | goto err_add_hcd; | ||
336 | } | ||
333 | 337 | ||
334 | if (pdata->phy_reset) { | 338 | if (pdata->phy_reset) { |
335 | /* Hold the PHY in RESET for enough time till | 339 | /* Hold the PHY in RESET for enough time till |
@@ -344,12 +348,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
344 | gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); | 348 | gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); |
345 | } | 349 | } |
346 | 350 | ||
347 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
348 | if (ret) { | ||
349 | dev_err(dev, "failed to add hcd with err %d\n", ret); | ||
350 | goto err_add_hcd; | ||
351 | } | ||
352 | |||
353 | /* root ports should always stay powered */ | 351 | /* root ports should always stay powered */ |
354 | ehci_port_power(omap_ehci, 1); | 352 | ehci_port_power(omap_ehci, 1); |
355 | 353 | ||
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 2732ef660c5c..7b01094d7993 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -462,6 +462,42 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | |||
462 | } | 462 | } |
463 | } | 463 | } |
464 | 464 | ||
465 | /* Updates Link Status for super Speed port */ | ||
466 | static void xhci_hub_report_link_state(u32 *status, u32 status_reg) | ||
467 | { | ||
468 | u32 pls = status_reg & PORT_PLS_MASK; | ||
469 | |||
470 | /* resume state is a xHCI internal state. | ||
471 | * Do not report it to usb core. | ||
472 | */ | ||
473 | if (pls == XDEV_RESUME) | ||
474 | return; | ||
475 | |||
476 | /* When the CAS bit is set then warm reset | ||
477 | * should be performed on port | ||
478 | */ | ||
479 | if (status_reg & PORT_CAS) { | ||
480 | /* The CAS bit can be set while the port is | ||
481 | * in any link state. | ||
482 | * Only roothubs have CAS bit, so we | ||
483 | * pretend to be in compliance mode | ||
484 | * unless we're already in compliance | ||
485 | * or the inactive state. | ||
486 | */ | ||
487 | if (pls != USB_SS_PORT_LS_COMP_MOD && | ||
488 | pls != USB_SS_PORT_LS_SS_INACTIVE) { | ||
489 | pls = USB_SS_PORT_LS_COMP_MOD; | ||
490 | } | ||
491 | /* Return also connection bit - | ||
492 | * hub state machine resets port | ||
493 | * when this bit is set. | ||
494 | */ | ||
495 | pls |= USB_PORT_STAT_CONNECTION; | ||
496 | } | ||
497 | /* update status field */ | ||
498 | *status |= pls; | ||
499 | } | ||
500 | |||
465 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | 501 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
466 | u16 wIndex, char *buf, u16 wLength) | 502 | u16 wIndex, char *buf, u16 wLength) |
467 | { | 503 | { |
@@ -606,13 +642,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
606 | else | 642 | else |
607 | status |= USB_PORT_STAT_POWER; | 643 | status |= USB_PORT_STAT_POWER; |
608 | } | 644 | } |
609 | /* Port Link State */ | 645 | /* Update Port Link State for super speed ports*/ |
610 | if (hcd->speed == HCD_USB3) { | 646 | if (hcd->speed == HCD_USB3) { |
611 | /* resume state is a xHCI internal state. | 647 | xhci_hub_report_link_state(&status, temp); |
612 | * Do not report it to usb core. | ||
613 | */ | ||
614 | if ((temp & PORT_PLS_MASK) != XDEV_RESUME) | ||
615 | status |= (temp & PORT_PLS_MASK); | ||
616 | } | 648 | } |
617 | if (bus_state->port_c_suspend & (1 << wIndex)) | 649 | if (bus_state->port_c_suspend & (1 << wIndex)) |
618 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; | 650 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 23b4aefd1036..8275645889da 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -885,6 +885,17 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, | |||
885 | num_trbs_free_temp = ep_ring->num_trbs_free; | 885 | num_trbs_free_temp = ep_ring->num_trbs_free; |
886 | dequeue_temp = ep_ring->dequeue; | 886 | dequeue_temp = ep_ring->dequeue; |
887 | 887 | ||
888 | /* If we get two back-to-back stalls, and the first stalled transfer | ||
889 | * ends just before a link TRB, the dequeue pointer will be left on | ||
890 | * the link TRB by the code in the while loop. So we have to update | ||
891 | * the dequeue pointer one segment further, or we'll jump off | ||
892 | * the segment into la-la-land. | ||
893 | */ | ||
894 | if (last_trb(xhci, ep_ring, ep_ring->deq_seg, ep_ring->dequeue)) { | ||
895 | ep_ring->deq_seg = ep_ring->deq_seg->next; | ||
896 | ep_ring->dequeue = ep_ring->deq_seg->trbs; | ||
897 | } | ||
898 | |||
888 | while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) { | 899 | while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) { |
889 | /* We have more usable TRBs */ | 900 | /* We have more usable TRBs */ |
890 | ep_ring->num_trbs_free++; | 901 | ep_ring->num_trbs_free++; |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index de3d6e3e57be..55c0785810c9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -341,7 +341,11 @@ struct xhci_op_regs { | |||
341 | #define PORT_PLC (1 << 22) | 341 | #define PORT_PLC (1 << 22) |
342 | /* port configure error change - port failed to configure its link partner */ | 342 | /* port configure error change - port failed to configure its link partner */ |
343 | #define PORT_CEC (1 << 23) | 343 | #define PORT_CEC (1 << 23) |
344 | /* bit 24 reserved */ | 344 | /* Cold Attach Status - xHC can set this bit to report device attached during |
345 | * Sx state. Warm port reset should be perfomed to clear this bit and move port | ||
346 | * to connected state. | ||
347 | */ | ||
348 | #define PORT_CAS (1 << 24) | ||
345 | /* wake on connect (enable) */ | 349 | /* wake on connect (enable) */ |
346 | #define PORT_WKCONN_E (1 << 25) | 350 | #define PORT_WKCONN_E (1 << 25) |
347 | /* wake on disconnect (enable) */ | 351 | /* wake on disconnect (enable) */ |