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