diff options
Diffstat (limited to 'drivers/usb/chipidea/udc.c')
| -rw-r--r-- | drivers/usb/chipidea/udc.c | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index c7a032a4f0c5..d214448b677e 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
| @@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) | |||
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | /** | 80 | /** |
| 81 | * hw_device_state: enables/disables interrupts & starts/stops device (execute | 81 | * hw_device_state: enables/disables interrupts (execute without interruption) |
| 82 | * without interruption) | ||
| 83 | * @dma: 0 => disable, !0 => enable and set dma engine | 82 | * @dma: 0 => disable, !0 => enable and set dma engine |
| 84 | * | 83 | * |
| 85 | * This function returns an error code | 84 | * This function returns an error code |
| @@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) | |||
| 91 | /* interrupt, error, port change, reset, sleep/suspend */ | 90 | /* interrupt, error, port change, reset, sleep/suspend */ |
| 92 | hw_write(ci, OP_USBINTR, ~0, | 91 | hw_write(ci, OP_USBINTR, ~0, |
| 93 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); | 92 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); |
| 94 | hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); | ||
| 95 | } else { | 93 | } else { |
| 96 | hw_write(ci, OP_USBCMD, USBCMD_RS, 0); | ||
| 97 | hw_write(ci, OP_USBINTR, ~0, 0); | 94 | hw_write(ci, OP_USBINTR, ~0, 0); |
| 98 | } | 95 | } |
| 99 | return 0; | 96 | return 0; |
| @@ -774,10 +771,7 @@ __acquires(mEp->lock) | |||
| 774 | { | 771 | { |
| 775 | struct ci13xxx_req *mReq, *mReqTemp; | 772 | struct ci13xxx_req *mReq, *mReqTemp; |
| 776 | struct ci13xxx_ep *mEpTemp = mEp; | 773 | struct ci13xxx_ep *mEpTemp = mEp; |
| 777 | int uninitialized_var(retval); | 774 | int retval = 0; |
| 778 | |||
| 779 | if (list_empty(&mEp->qh.queue)) | ||
| 780 | return -EINVAL; | ||
| 781 | 775 | ||
| 782 | list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, | 776 | list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, |
| 783 | queue) { | 777 | queue) { |
| @@ -1420,6 +1414,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) | |||
| 1420 | return -ENOTSUPP; | 1414 | return -ENOTSUPP; |
| 1421 | } | 1415 | } |
| 1422 | 1416 | ||
| 1417 | /* Change Data+ pullup status | ||
| 1418 | * this func is used by usb_gadget_connect/disconnet | ||
| 1419 | */ | ||
| 1420 | static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) | ||
| 1421 | { | ||
| 1422 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | ||
| 1423 | |||
| 1424 | if (is_on) | ||
| 1425 | hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); | ||
| 1426 | else | ||
| 1427 | hw_write(ci, OP_USBCMD, USBCMD_RS, 0); | ||
| 1428 | |||
| 1429 | return 0; | ||
| 1430 | } | ||
| 1431 | |||
| 1423 | static int ci13xxx_start(struct usb_gadget *gadget, | 1432 | static int ci13xxx_start(struct usb_gadget *gadget, |
| 1424 | struct usb_gadget_driver *driver); | 1433 | struct usb_gadget_driver *driver); |
| 1425 | static int ci13xxx_stop(struct usb_gadget *gadget, | 1434 | static int ci13xxx_stop(struct usb_gadget *gadget, |
| @@ -1432,6 +1441,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, | |||
| 1432 | static const struct usb_gadget_ops usb_gadget_ops = { | 1441 | static const struct usb_gadget_ops usb_gadget_ops = { |
| 1433 | .vbus_session = ci13xxx_vbus_session, | 1442 | .vbus_session = ci13xxx_vbus_session, |
| 1434 | .wakeup = ci13xxx_wakeup, | 1443 | .wakeup = ci13xxx_wakeup, |
| 1444 | .pullup = ci13xxx_pullup, | ||
| 1435 | .vbus_draw = ci13xxx_vbus_draw, | 1445 | .vbus_draw = ci13xxx_vbus_draw, |
| 1436 | .udc_start = ci13xxx_start, | 1446 | .udc_start = ci13xxx_start, |
| 1437 | .udc_stop = ci13xxx_stop, | 1447 | .udc_stop = ci13xxx_stop, |
| @@ -1455,7 +1465,12 @@ static int init_eps(struct ci13xxx *ci) | |||
| 1455 | 1465 | ||
| 1456 | mEp->ep.name = mEp->name; | 1466 | mEp->ep.name = mEp->name; |
| 1457 | mEp->ep.ops = &usb_ep_ops; | 1467 | mEp->ep.ops = &usb_ep_ops; |
| 1458 | mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; | 1468 | /* |
| 1469 | * for ep0: maxP defined in desc, for other | ||
| 1470 | * eps, maxP is set by epautoconfig() called | ||
| 1471 | * by gadget layer | ||
| 1472 | */ | ||
| 1473 | mEp->ep.maxpacket = (unsigned short)~0; | ||
| 1459 | 1474 | ||
| 1460 | INIT_LIST_HEAD(&mEp->qh.queue); | 1475 | INIT_LIST_HEAD(&mEp->qh.queue); |
| 1461 | mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, | 1476 | mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, |
| @@ -1475,6 +1490,7 @@ static int init_eps(struct ci13xxx *ci) | |||
| 1475 | else | 1490 | else |
| 1476 | ci->ep0in = mEp; | 1491 | ci->ep0in = mEp; |
| 1477 | 1492 | ||
| 1493 | mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; | ||
| 1478 | continue; | 1494 | continue; |
| 1479 | } | 1495 | } |
| 1480 | 1496 | ||
| @@ -1484,6 +1500,17 @@ static int init_eps(struct ci13xxx *ci) | |||
| 1484 | return retval; | 1500 | return retval; |
| 1485 | } | 1501 | } |
| 1486 | 1502 | ||
| 1503 | static void destroy_eps(struct ci13xxx *ci) | ||
| 1504 | { | ||
| 1505 | int i; | ||
| 1506 | |||
| 1507 | for (i = 0; i < ci->hw_ep_max; i++) { | ||
| 1508 | struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; | ||
| 1509 | |||
| 1510 | dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); | ||
| 1511 | } | ||
| 1512 | } | ||
| 1513 | |||
| 1487 | /** | 1514 | /** |
| 1488 | * ci13xxx_start: register a gadget driver | 1515 | * ci13xxx_start: register a gadget driver |
| 1489 | * @gadget: our gadget | 1516 | * @gadget: our gadget |
| @@ -1691,7 +1718,7 @@ static int udc_start(struct ci13xxx *ci) | |||
| 1691 | if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | 1718 | if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { |
| 1692 | if (ci->transceiver == NULL) { | 1719 | if (ci->transceiver == NULL) { |
| 1693 | retval = -ENODEV; | 1720 | retval = -ENODEV; |
| 1694 | goto free_pools; | 1721 | goto destroy_eps; |
| 1695 | } | 1722 | } |
| 1696 | } | 1723 | } |
| 1697 | 1724 | ||
| @@ -1729,7 +1756,7 @@ static int udc_start(struct ci13xxx *ci) | |||
| 1729 | 1756 | ||
| 1730 | remove_trans: | 1757 | remove_trans: |
| 1731 | if (!IS_ERR_OR_NULL(ci->transceiver)) { | 1758 | if (!IS_ERR_OR_NULL(ci->transceiver)) { |
| 1732 | otg_set_peripheral(ci->transceiver->otg, &ci->gadget); | 1759 | otg_set_peripheral(ci->transceiver->otg, NULL); |
| 1733 | if (ci->global_phy) | 1760 | if (ci->global_phy) |
| 1734 | usb_put_phy(ci->transceiver); | 1761 | usb_put_phy(ci->transceiver); |
| 1735 | } | 1762 | } |
| @@ -1742,6 +1769,8 @@ unreg_device: | |||
| 1742 | put_transceiver: | 1769 | put_transceiver: |
| 1743 | if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) | 1770 | if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) |
| 1744 | usb_put_phy(ci->transceiver); | 1771 | usb_put_phy(ci->transceiver); |
| 1772 | destroy_eps: | ||
| 1773 | destroy_eps(ci); | ||
| 1745 | free_pools: | 1774 | free_pools: |
| 1746 | dma_pool_destroy(ci->td_pool); | 1775 | dma_pool_destroy(ci->td_pool); |
| 1747 | free_qh_pool: | 1776 | free_qh_pool: |
| @@ -1756,18 +1785,12 @@ free_qh_pool: | |||
| 1756 | */ | 1785 | */ |
| 1757 | static void udc_stop(struct ci13xxx *ci) | 1786 | static void udc_stop(struct ci13xxx *ci) |
| 1758 | { | 1787 | { |
| 1759 | int i; | ||
| 1760 | |||
| 1761 | if (ci == NULL) | 1788 | if (ci == NULL) |
| 1762 | return; | 1789 | return; |
| 1763 | 1790 | ||
| 1764 | usb_del_gadget_udc(&ci->gadget); | 1791 | usb_del_gadget_udc(&ci->gadget); |
| 1765 | 1792 | ||
| 1766 | for (i = 0; i < ci->hw_ep_max; i++) { | 1793 | destroy_eps(ci); |
| 1767 | struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; | ||
| 1768 | |||
| 1769 | dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); | ||
| 1770 | } | ||
| 1771 | 1794 | ||
| 1772 | dma_pool_destroy(ci->td_pool); | 1795 | dma_pool_destroy(ci->td_pool); |
| 1773 | dma_pool_destroy(ci->qh_pool); | 1796 | dma_pool_destroy(ci->qh_pool); |
