summaryrefslogtreecommitdiff
path: root/drivers/usb/musb/musb_gadget.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/musb_gadget.c')
-rw-r--r--drivers/usb/musb/musb_gadget.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index ac3d2eec20f..4d15f74341a 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -401,7 +401,21 @@ static void txstate(struct musb *musb, struct musb_request *req)
csr |= (MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_DMAMODE
| MUSB_TXCSR_MODE);
- if (!musb_ep->hb_mult)
+ /*
+ * Enable Autoset according to table
+ * below
+ * ************************************
+ * bulk_split hb_mult Autoset_Enable
+ * ************************************
+ * 0 0 Yes(Normal)
+ * 0 >0 No(High BW ISO)
+ * 1 0 Yes(HS bulk)
+ * 1 >0 Yes(FS bulk)
+ */
+ if (!musb_ep->hb_mult ||
+ (musb_ep->hb_mult &&
+ can_bulk_split(musb,
+ musb_ep->type)))
csr |= MUSB_TXCSR_AUTOSET;
}
csr &= ~MUSB_TXCSR_P_UNDERRUN;
@@ -574,6 +588,15 @@ void musb_g_tx(struct musb *musb, u8 epnum)
if (request->actual == request->length) {
musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by gadget_queue function. Reselect the
+ * INDEX to be sure we are reading/modifying the
+ * right registers
+ */
+ musb_ep_select(mbase, epnum);
req = musb_ep->desc ? next_request(musb_ep) : NULL;
if (!req) {
dev_dbg(musb->controller, "%s idle now\n",
@@ -983,6 +1006,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
}
#endif
musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by gadget_queue function. Reselect the
+ * INDEX to be sure we are reading/modifying the
+ * right registers
+ */
+ musb_ep_select(mbase, epnum);
req = next_request(musb_ep);
if (!req)
@@ -1079,6 +1111,12 @@ static int musb_gadget_enable(struct usb_ep *ep,
/* REVISIT if can_bulk_split(), use by updating "tmp";
* likewise high bandwidth periodic tx
*/
+ /* Set the TXMAXP register correctly for Bulk IN
+ * endpoints in device mode
+ */
+ if (can_bulk_split(musb, musb_ep->type))
+ musb_ep->hb_mult = (hw_ep->max_packet_sz_tx /
+ musb_ep->packet_sz) - 1;
/* Set TXMAXP with the FIFO size of the endpoint
* to disable double buffering mode.
*/
@@ -1624,7 +1662,9 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
}
spin_unlock_irqrestore(&musb->lock, flags);
+#ifndef CONFIG_USB_OTG_20
otg_start_srp(musb->xceiv);
+#endif
spin_lock_irqsave(&musb->lock, flags);
/* Block idling for at least 1s */
@@ -1735,6 +1775,14 @@ static int musb_gadget_start(struct usb_gadget *g,
static int musb_gadget_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
+static struct usb_ep *musb_gadget_configure_ep(struct usb_gadget *gadget,
+ u8 type, struct usb_endpoint_descriptor *desc)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ return musb_platform_configure_ep(musb, type, desc);
+}
+
static const struct usb_gadget_ops musb_gadget_operations = {
.get_frame = musb_gadget_get_frame,
.wakeup = musb_gadget_wakeup,
@@ -1744,6 +1792,7 @@ static const struct usb_gadget_ops musb_gadget_operations = {
.pullup = musb_gadget_pullup,
.udc_start = musb_gadget_start,
.udc_stop = musb_gadget_stop,
+ .configure_ep = musb_gadget_configure_ep,
};
/* ----------------------------------------------------------------------- */