aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-09-30 10:58:47 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-04 10:25:54 -0700
commit879631aa658be2c1307758223b6d15236f9f6335 (patch)
tree9ab6eafbe5cee1b6d57492e42ddef317a800c469 /drivers/usb/dwc3
parenta4af9008bb69f49df3abf816d48e224aca810af4 (diff)
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: Paul Zimmerman <paulz@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/core.h6
-rw-r--r--drivers/usb/dwc3/gadget.c34
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 {
* @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 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,
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;