Commit 879631aa authored by Felipe Balbi's avatar Felipe Balbi Committed by Greg Kroah-Hartman

usb: dwc3: gadget: implement streams support

The following patch adds support for streams
to dwc3 driver.

While at that, also fix one small issue on
endpoint disable where we should clear all
flags not only ENABLED.
Reviewied-by: default avatarPaul Zimmerman <paulz@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a4af9008
...@@ -3,14 +3,6 @@ ...@@ -3,14 +3,6 @@
~~~~~~ ~~~~~~
Please pick something while reading :) Please pick something while reading :)
- Implement streaming support for BULK endpoints
Tatyana's patch "usb: Add streams support to the gadget framework"
introduces streaming support for the gadget driver.
Every usb_request has new field called stream_id which holds its id.
Every usb_ep has a field num_supported_strms which describes the max
number of streams supported (for this ep).
UAS is AFAIK the only gadget with streaming support.
- Convert interrupt handler to per-ep-thread-irq - Convert interrupt handler to per-ep-thread-irq
As it turns out some DWC3-commands ~1ms to complete. Currently we spin As it turns out some DWC3-commands ~1ms to complete. Currently we spin
......
...@@ -329,6 +329,7 @@ struct dwc3_event_buffer { ...@@ -329,6 +329,7 @@ struct dwc3_event_buffer {
* @interval: the intervall on which the ISOC transfer is started * @interval: the intervall on which the ISOC transfer is started
* @name: a human readable name e.g. ep1out-bulk * @name: a human readable name e.g. ep1out-bulk
* @direction: true for TX, false for RX * @direction: true for TX, false for RX
* @stream_capable: true when streams are enabled
*/ */
struct dwc3_ep { struct dwc3_ep {
struct usb_ep endpoint; struct usb_ep endpoint;
...@@ -362,6 +363,7 @@ struct dwc3_ep { ...@@ -362,6 +363,7 @@ struct dwc3_ep {
char name[20]; char name[20];
unsigned direction:1; unsigned direction:1;
unsigned stream_capable:1;
}; };
enum dwc3_phy { enum dwc3_phy {
...@@ -650,6 +652,10 @@ struct dwc3_event_depevt { ...@@ -650,6 +652,10 @@ struct dwc3_event_depevt {
#define DEPEVT_STATUS_IOC (1 << 2) #define DEPEVT_STATUS_IOC (1 << 2)
#define DEPEVT_STATUS_LST (1 << 3) #define DEPEVT_STATUS_LST (1 << 3)
/* Stream event only */
#define DEPEVT_STREAMEVT_FOUND 1
#define DEPEVT_STREAMEVT_NOTFOUND 2
/* Control-only Status */ /* Control-only Status */
#define DEPEVT_STATUS_CONTROL_SETUP 0 #define DEPEVT_STATUS_CONTROL_SETUP 0
#define DEPEVT_STATUS_CONTROL_DATA 1 #define DEPEVT_STATUS_CONTROL_DATA 1
......
...@@ -264,6 +264,12 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, ...@@ -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_complete_enable = true;
params.param1.depcfg.xfer_not_ready_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)) if (usb_endpoint_xfer_isoc(desc))
params.param1.depcfg.xfer_in_progress_enable = true; params.param1.depcfg.xfer_in_progress_enable = true;
...@@ -391,15 +397,16 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -391,15 +397,16 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
u32 reg; u32 reg;
dep->flags &= ~DWC3_EP_ENABLED;
dwc3_remove_requests(dwc, dep); dwc3_remove_requests(dwc, dep);
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number); reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
dep->stream_capable = false;
dep->desc = NULL; dep->desc = NULL;
dep->type = 0; dep->type = 0;
dep->flags = 0;
return 0; return 0;
} }
...@@ -633,6 +640,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, ...@@ -633,6 +640,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep,
trb.lst = last_one; 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)) { switch (usb_endpoint_type(dep->desc)) {
case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_CONTROL:
trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
...@@ -1504,13 +1514,29 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, ...@@ -1504,13 +1514,29 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dep->name); dep->name);
} }
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; break;
case DWC3_DEPEVT_RXTXFIFOEVT: case DWC3_DEPEVT_RXTXFIFOEVT:
dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name);
break; break;
case DWC3_DEPEVT_STREAMEVT:
dev_dbg(dwc->dev, "%s Stream Event\n", dep->name);
break;
case DWC3_DEPEVT_EPCMDCMPLT: case DWC3_DEPEVT_EPCMDCMPLT:
dwc3_ep_cmd_compl(dep, event); dwc3_ep_cmd_compl(dep, event);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment