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 502582c..c6de53c 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -329,6 +329,7 @@ struct dwc3_event_buffer { * @interval: the intervall on which the ISOC transfer is started * @name: a human readable name e.g. ep1out-bulk * @direction: true for TX, false for RX + * @stream_capable: true when streams are enabled */ struct dwc3_ep { struct usb_ep endpoint; @@ -362,6 +363,7 @@ struct dwc3_ep { char name[20]; unsigned direction:1; + unsigned stream_capable:1; }; enum dwc3_phy { @@ -650,6 +652,10 @@ struct dwc3_event_depevt { #define DEPEVT_STATUS_IOC (1 << 2) #define DEPEVT_STATUS_LST (1 << 3) +/* Stream event only */ +#define DEPEVT_STREAMEVT_FOUND 1 +#define DEPEVT_STREAMEVT_NOTFOUND 2 + /* Control-only Status */ #define DEPEVT_STATUS_CONTROL_SETUP 0 #define DEPEVT_STATUS_CONTROL_DATA 1 diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 524ff91..8d85023 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, params.param1.depcfg.xfer_complete_enable = true; params.param1.depcfg.xfer_not_ready_enable = true; + if (usb_endpoint_xfer_bulk(desc) && dep->endpoint.max_streams) { + params.param1.depcfg.stream_capable = true; + params.param1.depcfg.stream_event_enable = true; + dep->stream_capable = true; + } + if (usb_endpoint_xfer_isoc(desc)) params.param1.depcfg.xfer_in_progress_enable = true; @@ -391,15 +397,16 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) struct dwc3 *dwc = dep->dwc; u32 reg; - dep->flags &= ~DWC3_EP_ENABLED; dwc3_remove_requests(dwc, dep); reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg &= ~DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + dep->stream_capable = false; dep->desc = NULL; dep->type = 0; + dep->flags = 0; return 0; } @@ -633,6 +640,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, trb.lst = last_one; } + if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) + trb.sid_sofn = req->request.stream_id; + switch (usb_endpoint_type(dep->desc)) { case USB_ENDPOINT_XFER_CONTROL: trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; @@ -1505,12 +1515,28 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, } break; + case DWC3_DEPEVT_STREAMEVT: + if (!usb_endpoint_xfer_bulk(dep->desc)) { + dev_err(dwc->dev, "Stream event for non-Bulk %s\n", + dep->name); + return; + } + + switch (event->status) { + case DEPEVT_STREAMEVT_FOUND: + dev_vdbg(dwc->dev, "Stream %d found and started\n", + event->parameters); + + break; + case DEPEVT_STREAMEVT_NOTFOUND: + /* FALLTHROUGH */ + default: + dev_dbg(dwc->dev, "Couldn't find suitable stream\n"); + } + break; case DWC3_DEPEVT_RXTXFIFOEVT: dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); break; - case DWC3_DEPEVT_STREAMEVT: - dev_dbg(dwc->dev, "%s Stream Event\n", dep->name); - break; case DWC3_DEPEVT_EPCMDCMPLT: dwc3_ep_cmd_compl(dep, event); break; |