diff options
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/core.h | 6 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 34 |
2 files changed, 36 insertions, 4 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 502582ce1fc..c6de53c812a 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h | |||
@@ -329,6 +329,7 @@ struct dwc3_event_buffer { | |||
329 | * @interval: the intervall on which the ISOC transfer is started | 329 | * @interval: the intervall on which the ISOC transfer is started |
330 | * @name: a human readable name e.g. ep1out-bulk | 330 | * @name: a human readable name e.g. ep1out-bulk |
331 | * @direction: true for TX, false for RX | 331 | * @direction: true for TX, false for RX |
332 | * @stream_capable: true when streams are enabled | ||
332 | */ | 333 | */ |
333 | struct dwc3_ep { | 334 | struct dwc3_ep { |
334 | struct usb_ep endpoint; | 335 | struct usb_ep endpoint; |
@@ -362,6 +363,7 @@ struct dwc3_ep { | |||
362 | char name[20]; | 363 | char name[20]; |
363 | 364 | ||
364 | unsigned direction:1; | 365 | unsigned direction:1; |
366 | unsigned stream_capable:1; | ||
365 | }; | 367 | }; |
366 | 368 | ||
367 | enum dwc3_phy { | 369 | enum dwc3_phy { |
@@ -650,6 +652,10 @@ struct dwc3_event_depevt { | |||
650 | #define DEPEVT_STATUS_IOC (1 << 2) | 652 | #define DEPEVT_STATUS_IOC (1 << 2) |
651 | #define DEPEVT_STATUS_LST (1 << 3) | 653 | #define DEPEVT_STATUS_LST (1 << 3) |
652 | 654 | ||
655 | /* Stream event only */ | ||
656 | #define DEPEVT_STREAMEVT_FOUND 1 | ||
657 | #define DEPEVT_STREAMEVT_NOTFOUND 2 | ||
658 | |||
653 | /* Control-only Status */ | 659 | /* Control-only Status */ |
654 | #define DEPEVT_STATUS_CONTROL_SETUP 0 | 660 | #define DEPEVT_STATUS_CONTROL_SETUP 0 |
655 | #define DEPEVT_STATUS_CONTROL_DATA 1 | 661 | #define DEPEVT_STATUS_CONTROL_DATA 1 |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 524ff91bf39..8d8502373db 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -264,6 +264,12 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
264 | params.param1.depcfg.xfer_complete_enable = true; | 264 | params.param1.depcfg.xfer_complete_enable = true; |
265 | params.param1.depcfg.xfer_not_ready_enable = true; | 265 | params.param1.depcfg.xfer_not_ready_enable = true; |
266 | 266 | ||
267 | if (usb_endpoint_xfer_bulk(desc) && dep->endpoint.max_streams) { | ||
268 | params.param1.depcfg.stream_capable = true; | ||
269 | params.param1.depcfg.stream_event_enable = true; | ||
270 | dep->stream_capable = true; | ||
271 | } | ||
272 | |||
267 | if (usb_endpoint_xfer_isoc(desc)) | 273 | if (usb_endpoint_xfer_isoc(desc)) |
268 | params.param1.depcfg.xfer_in_progress_enable = true; | 274 | params.param1.depcfg.xfer_in_progress_enable = true; |
269 | 275 | ||
@@ -391,15 +397,16 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) | |||
391 | struct dwc3 *dwc = dep->dwc; | 397 | struct dwc3 *dwc = dep->dwc; |
392 | u32 reg; | 398 | u32 reg; |
393 | 399 | ||
394 | dep->flags &= ~DWC3_EP_ENABLED; | ||
395 | dwc3_remove_requests(dwc, dep); | 400 | dwc3_remove_requests(dwc, dep); |
396 | 401 | ||
397 | reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); | 402 | reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); |
398 | reg &= ~DWC3_DALEPENA_EP(dep->number); | 403 | reg &= ~DWC3_DALEPENA_EP(dep->number); |
399 | dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); | 404 | dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); |
400 | 405 | ||
406 | dep->stream_capable = false; | ||
401 | dep->desc = NULL; | 407 | dep->desc = NULL; |
402 | dep->type = 0; | 408 | dep->type = 0; |
409 | dep->flags = 0; | ||
403 | 410 | ||
404 | return 0; | 411 | return 0; |
405 | } | 412 | } |
@@ -633,6 +640,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
633 | trb.lst = last_one; | 640 | trb.lst = last_one; |
634 | } | 641 | } |
635 | 642 | ||
643 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||
644 | trb.sid_sofn = req->request.stream_id; | ||
645 | |||
636 | switch (usb_endpoint_type(dep->desc)) { | 646 | switch (usb_endpoint_type(dep->desc)) { |
637 | case USB_ENDPOINT_XFER_CONTROL: | 647 | case USB_ENDPOINT_XFER_CONTROL: |
638 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | 648 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; |
@@ -1505,12 +1515,28 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | |||
1505 | } | 1515 | } |
1506 | 1516 | ||
1507 | break; | 1517 | break; |
1518 | case DWC3_DEPEVT_STREAMEVT: | ||
1519 | if (!usb_endpoint_xfer_bulk(dep->desc)) { | ||
1520 | dev_err(dwc->dev, "Stream event for non-Bulk %s\n", | ||
1521 | dep->name); | ||
1522 | return; | ||
1523 | } | ||
1524 | |||
1525 | switch (event->status) { | ||
1526 | case DEPEVT_STREAMEVT_FOUND: | ||
1527 | dev_vdbg(dwc->dev, "Stream %d found and started\n", | ||
1528 | event->parameters); | ||
1529 | |||
1530 | break; | ||
1531 | case DEPEVT_STREAMEVT_NOTFOUND: | ||
1532 | /* FALLTHROUGH */ | ||
1533 | default: | ||
1534 | dev_dbg(dwc->dev, "Couldn't find suitable stream\n"); | ||
1535 | } | ||
1536 | break; | ||
1508 | case DWC3_DEPEVT_RXTXFIFOEVT: | 1537 | case DWC3_DEPEVT_RXTXFIFOEVT: |
1509 | dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); | 1538 | dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); |
1510 | break; | 1539 | break; |
1511 | case DWC3_DEPEVT_STREAMEVT: | ||
1512 | dev_dbg(dwc->dev, "%s Stream Event\n", dep->name); | ||
1513 | break; | ||
1514 | case DWC3_DEPEVT_EPCMDCMPLT: | 1540 | case DWC3_DEPEVT_EPCMDCMPLT: |
1515 | dwc3_ep_cmd_compl(dep, event); | 1541 | dwc3_ep_cmd_compl(dep, event); |
1516 | break; | 1542 | break; |