[PATCH] USB: musb: support ISO high bandwidth for gadget mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ming Lei <tom.leiming@xxxxxxxxx>

This has been tested OK on beagle B5 board.

Signed-off-by: Ming Lei <tom.leiming@xxxxxxxxx>
---
 drivers/usb/musb/musb_gadget.c |   51 ++++++++++++++++++++++++++++++++++-----
 drivers/usb/musb/musb_gadget.h |    2 +
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 404b084..8f70746 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -344,6 +344,9 @@ static void txstate(struct musb *musb, struct musb_request *req)
 							| MUSB_TXCSR_MODE);
 
 				csr &= ~MUSB_TXCSR_P_UNDERRUN;
+				if (musb_ep->hb_mult)
+					csr &= ~MUSB_TXCSR_AUTOSET;
+
 				musb_writew(epio, MUSB_TXCSR, csr);
 			}
 		}
@@ -353,6 +356,9 @@ static void txstate(struct musb *musb, struct musb_request *req)
 		csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
 		csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
 		       MUSB_TXCSR_MODE;
+		if (musb_ep->hb_mult)
+			csr &= ~MUSB_TXCSR_AUTOSET;
+
 		musb_writew(epio, MUSB_TXCSR,
 			(MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
 				| csr);
@@ -446,6 +452,9 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 		/* We NAKed, no big deal... little reason to care. */
 		csr |=	 MUSB_TXCSR_P_WZC_BITS;
 		csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+		if (musb_ep->hb_mult)
+			csr &= ~MUSB_TXCSR_AUTOSET;
+
 		musb_writew(epio, MUSB_TXCSR, csr);
 		DBG(20, "underrun on ep%d, req %p\n", epnum, request);
 	}
@@ -617,6 +626,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 			csr &= ~(MUSB_RXCSR_AUTOCLEAR
 					| MUSB_RXCSR_DMAMODE);
 			csr |= MUSB_RXCSR_DMAENAB | MUSB_RXCSR_P_WZC_BITS;
+			if (musb_ep->hb_mult)
+				csr &= ~MUSB_TXCSR_AUTOSET;
 			musb_writew(epio, MUSB_RXCSR, csr);
 			return;
 		}
@@ -664,6 +675,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 				 * disabling MUSB_RXCSR_DMAMODE) is required
 				 * to get DMAReq to activate
 				 */
+				if (musb_ep->hb_mult)
+					csr &= ~MUSB_TXCSR_AUTOSET;
 				musb_writew(epio, MUSB_RXCSR,
 					csr | MUSB_RXCSR_DMAMODE);
 #endif
@@ -732,6 +745,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 			/* ack the read! */
 			csr |= MUSB_RXCSR_P_WZC_BITS;
 			csr &= ~MUSB_RXCSR_RXPKTRDY;
+			if (musb_ep->hb_mult)
+				csr &= ~MUSB_TXCSR_AUTOSET;
 			musb_writew(epio, MUSB_RXCSR, csr);
 		}
 	}
@@ -888,9 +903,25 @@ static int musb_gadget_enable(struct usb_ep *ep,
 
 	/* REVISIT this rules out high bandwidth periodic transfers */
 	tmp = le16_to_cpu(desc->wMaxPacketSize);
-	if (tmp & ~0x07ff)
-		goto fail;
-	musb_ep->packet_sz = tmp;
+	if (tmp & ~0x07ff) {
+		int ok;
+
+		if (usb_endpoint_dir_in(desc))
+			ok = musb->hb_iso_tx;
+		else
+			ok = musb->hb_iso_rx;
+
+		if (!ok) {
+			DBG(4, "%s: not support ISO high bandwidth\n", __func__);
+			goto fail;
+		}
+		musb_ep->hb_mult = (tmp >> 11) & 3;
+	} else {
+		musb_ep->hb_mult = 0;
+	}
+
+	musb_ep->packet_sz = tmp & 0x7ff;
+	tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1);
 
 	/* enable the interrupts for the endpoint, set the endpoint
 	 * packet size (or fail), set the mode, clear the fifo
@@ -903,8 +934,11 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			musb_ep->is_in = 1;
 		if (!musb_ep->is_in)
 			goto fail;
-		if (tmp > hw_ep->max_packet_sz_tx)
+
+		if (tmp > hw_ep->max_packet_sz_tx) {
+			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
 			goto fail;
+		}
 
 		int_txe |= (1 << epnum);
 		musb_writew(mbase, MUSB_INTRTXE, int_txe);
@@ -919,7 +953,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
 		if (musb->hwvers < MUSB_HWVERS_2000)
 			musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
 		else
-			musb_writew(regs, MUSB_TXMAXP, tmp);
+			musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
 
 		csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
 		if (musb_readw(regs, MUSB_TXCSR)
@@ -940,8 +974,11 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			musb_ep->is_in = 0;
 		if (musb_ep->is_in)
 			goto fail;
-		if (tmp > hw_ep->max_packet_sz_rx)
+
+		if (tmp > hw_ep->max_packet_sz_rx) {
+			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
 			goto fail;
+		}
 
 		int_rxe |= (1 << epnum);
 		musb_writew(mbase, MUSB_INTRRXE, int_rxe);
@@ -955,7 +992,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
 		if (musb->hwvers < MUSB_HWVERS_2000)
 			musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
 		else
-			musb_writew(regs, MUSB_RXMAXP, tmp);
+			musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
 
 		/* force shared fifo to OUT-only mode */
 		if (hw_ep->is_shared_fifo) {
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index c8b1403..353c619 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -79,6 +79,8 @@ struct musb_ep {
 
 	/* true if lock must be dropped but req_list may not be advanced */
 	u8				busy;
+
+	u8              hb_mult;
 };
 
 static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
-- 
1.6.2.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux