diff options
author | Felipe Balbi <balbi@ti.com> | 2013-02-08 08:24:04 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-03-18 05:17:00 -0400 |
commit | 8698e2acf3a5e8d6f260ca7675f94e5087df5ae8 (patch) | |
tree | 7e18c79a0f72c410d9af65841aed9af42d9fe81f /drivers/usb/dwc3/gadget.c | |
parent | f122d33e4b0045a42238b9a4c3943adf7e8313c1 (diff) |
usb: dwc3: gadget: introduce and use enable/disable irq methods
we don't need to enable IRQs until we have
a gadget driver loaded and ready to work,
so let's delay IRQ enable to ->udc_start()
and IRQ disable to ->udc_stop().
While at that, also move the related use of
request_irq() and free_irq().
Tested-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 80 |
1 files changed, 45 insertions, 35 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 65493b6cd5a6..db2031725abc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -1469,6 +1469,32 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) | |||
1469 | return ret; | 1469 | return ret; |
1470 | } | 1470 | } |
1471 | 1471 | ||
1472 | static void dwc3_gadget_enable_irq(struct dwc3 *dwc) | ||
1473 | { | ||
1474 | u32 reg; | ||
1475 | |||
1476 | /* Enable all but Start and End of Frame IRQs */ | ||
1477 | reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | | ||
1478 | DWC3_DEVTEN_EVNTOVERFLOWEN | | ||
1479 | DWC3_DEVTEN_CMDCMPLTEN | | ||
1480 | DWC3_DEVTEN_ERRTICERREN | | ||
1481 | DWC3_DEVTEN_WKUPEVTEN | | ||
1482 | DWC3_DEVTEN_ULSTCNGEN | | ||
1483 | DWC3_DEVTEN_CONNECTDONEEN | | ||
1484 | DWC3_DEVTEN_USBRSTEN | | ||
1485 | DWC3_DEVTEN_DISCONNEVTEN); | ||
1486 | |||
1487 | dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); | ||
1488 | } | ||
1489 | |||
1490 | static void dwc3_gadget_disable_irq(struct dwc3 *dwc) | ||
1491 | { | ||
1492 | /* mask all interrupts */ | ||
1493 | dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); | ||
1494 | } | ||
1495 | |||
1496 | static irqreturn_t dwc3_interrupt(int irq, void *_dwc); | ||
1497 | |||
1472 | static int dwc3_gadget_start(struct usb_gadget *g, | 1498 | static int dwc3_gadget_start(struct usb_gadget *g, |
1473 | struct usb_gadget_driver *driver) | 1499 | struct usb_gadget_driver *driver) |
1474 | { | 1500 | { |
@@ -1476,6 +1502,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, | |||
1476 | struct dwc3_ep *dep; | 1502 | struct dwc3_ep *dep; |
1477 | unsigned long flags; | 1503 | unsigned long flags; |
1478 | int ret = 0; | 1504 | int ret = 0; |
1505 | int irq; | ||
1479 | u32 reg; | 1506 | u32 reg; |
1480 | 1507 | ||
1481 | spin_lock_irqsave(&dwc->lock, flags); | 1508 | spin_lock_irqsave(&dwc->lock, flags); |
@@ -1536,6 +1563,17 @@ static int dwc3_gadget_start(struct usb_gadget *g, | |||
1536 | dwc->ep0state = EP0_SETUP_PHASE; | 1563 | dwc->ep0state = EP0_SETUP_PHASE; |
1537 | dwc3_ep0_out_start(dwc); | 1564 | dwc3_ep0_out_start(dwc); |
1538 | 1565 | ||
1566 | irq = platform_get_irq(to_platform_device(dwc->dev), 0); | ||
1567 | ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, | ||
1568 | "dwc3", dwc); | ||
1569 | if (ret) { | ||
1570 | dev_err(dwc->dev, "failed to request irq #%d --> %d\n", | ||
1571 | irq, ret); | ||
1572 | goto err1; | ||
1573 | } | ||
1574 | |||
1575 | dwc3_gadget_enable_irq(dwc); | ||
1576 | |||
1539 | spin_unlock_irqrestore(&dwc->lock, flags); | 1577 | spin_unlock_irqrestore(&dwc->lock, flags); |
1540 | 1578 | ||
1541 | return 0; | 1579 | return 0; |
@@ -1554,9 +1592,14 @@ static int dwc3_gadget_stop(struct usb_gadget *g, | |||
1554 | { | 1592 | { |
1555 | struct dwc3 *dwc = gadget_to_dwc(g); | 1593 | struct dwc3 *dwc = gadget_to_dwc(g); |
1556 | unsigned long flags; | 1594 | unsigned long flags; |
1595 | int irq; | ||
1557 | 1596 | ||
1558 | spin_lock_irqsave(&dwc->lock, flags); | 1597 | spin_lock_irqsave(&dwc->lock, flags); |
1559 | 1598 | ||
1599 | dwc3_gadget_disable_irq(dwc); | ||
1600 | irq = platform_get_irq(to_platform_device(dwc->dev), 0); | ||
1601 | free_irq(irq, dwc); | ||
1602 | |||
1560 | __dwc3_gadget_ep_disable(dwc->eps[0]); | 1603 | __dwc3_gadget_ep_disable(dwc->eps[0]); |
1561 | __dwc3_gadget_ep_disable(dwc->eps[1]); | 1604 | __dwc3_gadget_ep_disable(dwc->eps[1]); |
1562 | 1605 | ||
@@ -2454,7 +2497,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) | |||
2454 | { | 2497 | { |
2455 | u32 reg; | 2498 | u32 reg; |
2456 | int ret; | 2499 | int ret; |
2457 | int irq; | ||
2458 | 2500 | ||
2459 | dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | 2501 | dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), |
2460 | &dwc->ctrl_req_addr, GFP_KERNEL); | 2502 | &dwc->ctrl_req_addr, GFP_KERNEL); |
@@ -2510,33 +2552,11 @@ int dwc3_gadget_init(struct dwc3 *dwc) | |||
2510 | if (ret) | 2552 | if (ret) |
2511 | goto err4; | 2553 | goto err4; |
2512 | 2554 | ||
2513 | irq = platform_get_irq(to_platform_device(dwc->dev), 0); | ||
2514 | |||
2515 | ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, | ||
2516 | "dwc3", dwc); | ||
2517 | if (ret) { | ||
2518 | dev_err(dwc->dev, "failed to request irq #%d --> %d\n", | ||
2519 | irq, ret); | ||
2520 | goto err5; | ||
2521 | } | ||
2522 | |||
2523 | reg = dwc3_readl(dwc->regs, DWC3_DCFG); | 2555 | reg = dwc3_readl(dwc->regs, DWC3_DCFG); |
2524 | reg |= DWC3_DCFG_LPM_CAP; | 2556 | reg |= DWC3_DCFG_LPM_CAP; |
2525 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); | 2557 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); |
2526 | 2558 | ||
2527 | /* Enable all but Start and End of Frame IRQs */ | 2559 | /* Enable USB2 LPM and automatic phy suspend only on recent versions */ |
2528 | reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | | ||
2529 | DWC3_DEVTEN_EVNTOVERFLOWEN | | ||
2530 | DWC3_DEVTEN_CMDCMPLTEN | | ||
2531 | DWC3_DEVTEN_ERRTICERREN | | ||
2532 | DWC3_DEVTEN_WKUPEVTEN | | ||
2533 | DWC3_DEVTEN_ULSTCNGEN | | ||
2534 | DWC3_DEVTEN_CONNECTDONEEN | | ||
2535 | DWC3_DEVTEN_USBRSTEN | | ||
2536 | DWC3_DEVTEN_DISCONNEVTEN); | ||
2537 | dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); | ||
2538 | |||
2539 | /* automatic phy suspend only on recent versions */ | ||
2540 | if (dwc->revision >= DWC3_REVISION_194A) { | 2560 | if (dwc->revision >= DWC3_REVISION_194A) { |
2541 | dwc3_gadget_usb2_phy_suspend(dwc, false); | 2561 | dwc3_gadget_usb2_phy_suspend(dwc, false); |
2542 | dwc3_gadget_usb3_phy_suspend(dwc, false); | 2562 | dwc3_gadget_usb3_phy_suspend(dwc, false); |
@@ -2545,15 +2565,11 @@ int dwc3_gadget_init(struct dwc3 *dwc) | |||
2545 | ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); | 2565 | ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); |
2546 | if (ret) { | 2566 | if (ret) { |
2547 | dev_err(dwc->dev, "failed to register udc\n"); | 2567 | dev_err(dwc->dev, "failed to register udc\n"); |
2548 | goto err6; | 2568 | goto err5; |
2549 | } | 2569 | } |
2550 | 2570 | ||
2551 | return 0; | 2571 | return 0; |
2552 | 2572 | ||
2553 | err6: | ||
2554 | dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); | ||
2555 | free_irq(irq, dwc); | ||
2556 | |||
2557 | err5: | 2573 | err5: |
2558 | dwc3_gadget_free_endpoints(dwc); | 2574 | dwc3_gadget_free_endpoints(dwc); |
2559 | 2575 | ||
@@ -2578,13 +2594,7 @@ err0: | |||
2578 | 2594 | ||
2579 | void dwc3_gadget_exit(struct dwc3 *dwc) | 2595 | void dwc3_gadget_exit(struct dwc3 *dwc) |
2580 | { | 2596 | { |
2581 | int irq; | ||
2582 | |||
2583 | usb_del_gadget_udc(&dwc->gadget); | 2597 | usb_del_gadget_udc(&dwc->gadget); |
2584 | irq = platform_get_irq(to_platform_device(dwc->dev), 0); | ||
2585 | |||
2586 | dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); | ||
2587 | free_irq(irq, dwc); | ||
2588 | 2598 | ||
2589 | dwc3_gadget_free_endpoints(dwc); | 2599 | dwc3_gadget_free_endpoints(dwc); |
2590 | 2600 | ||