--- zzzz-none-000/linux-2.6.39.4/drivers/usb/musb/musb_gadget.c 2011-08-03 19:43:28.000000000 +0000 +++ puma6-arm-6490-729/linux-2.6.39.4/drivers/usb/musb/musb_gadget.c 2021-11-10 13:23:10.000000000 +0000 @@ -327,12 +327,13 @@ musb_ep = req->ep; +#if defined(CONFIG_USB_MUSB_HDRC_HCD) || defined(CONFIG_USB_MUSB_OTG) /* we shouldn't get here while DMA is active ... but we do ... */ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { DBG(4, "dma pending...\n"); return; } - +#endif /* read TXCSR before */ csr = musb_readw(epio, MUSB_TXCSR); @@ -340,12 +341,13 @@ fifo_count = min(max_ep_writesize(musb, musb_ep), (int)(request->length - request->actual)); +#if defined(CONFIG_USB_MUSB_HDRC_HCD) || defined(CONFIG_USB_MUSB_OTG) if (csr & MUSB_TXCSR_TXPKTRDY) { DBG(5, "%s old packet still ready , txcsr %03x\n", musb_ep->end_point.name, csr); return; } - +#endif if (csr & MUSB_TXCSR_P_SENDSTALL) { DBG(5, "%s stalling, txcsr %03x\n", musb_ep->end_point.name, csr); @@ -411,9 +413,12 @@ #elif defined(CONFIG_USB_TI_CPPI_DMA) /* program endpoint CSR first, then setup DMA */ - csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); - csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | - MUSB_TXCSR_MODE; + csr &= ~(MUSB_TXCSR_AUTOSET + | MUSB_TXCSR_DMAMODE + | MUSB_TXCSR_P_UNDERRUN + | MUSB_TXCSR_TXPKTRDY); + csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; + csr |= MUSB_TXCSR_DMAMODE; musb_writew(epio, MUSB_TXCSR, (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) | csr); @@ -421,6 +426,8 @@ /* ensure writebuffer is empty */ csr = musb_readw(epio, MUSB_TXCSR); + musb_ep->dma->actual_len = 0L; + /* NOTE host side sets DMAENAB later than this; both are * OK since the transfer dma glue (between CPPI and Mentor * fifos) just tells CPPI it could start. Data only moves @@ -434,13 +441,13 @@ use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, 0, - request->dma + request->actual, - request_size); + request->dma, + request->length); if (!use_dma) { c->channel_release(musb_ep->dma); musb_ep->dma = NULL; - csr &= ~MUSB_TXCSR_DMAENAB; - musb_writew(epio, MUSB_TXCSR, csr); + /* ASSERT: DMAENAB clear */ + csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); /* invariant: prequest->buf is non-null */ } #elif defined(CONFIG_USB_TUSB_OMAP_DMA) @@ -499,7 +506,7 @@ DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); dma = is_dma_capable() ? musb_ep->dma : NULL; - + do { /* * REVISIT: for high bandwidth, MUSB_TXCSR_P_INCOMPTX * probably rates reporting as a host error. @@ -508,7 +515,15 @@ csr |= MUSB_TXCSR_P_WZC_BITS; csr &= ~MUSB_TXCSR_P_SENTSTALL; musb_writew(epio, MUSB_TXCSR, csr); - return; + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + } + + if (request) + musb_g_giveback(musb_ep, request, -EPIPE); + + break; } if (csr & MUSB_TXCSR_P_UNDERRUN) { @@ -518,7 +533,7 @@ musb_writew(epio, MUSB_TXCSR, csr); DBG(20, "underrun on ep%d, req %p\n", epnum, request); } - +#if 0 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { /* * SHOULD NOT HAPPEN... has with CPPI though, after @@ -527,16 +542,17 @@ DBG(5, "%s dma still busy?\n", musb_ep->end_point.name); return; } - +#endif if (request) { u8 is_dma = 0; if (dma && (csr & MUSB_TXCSR_DMAENAB)) { is_dma = 1; - csr |= MUSB_TXCSR_P_WZC_BITS; - csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN | - MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET); - musb_writew(epio, MUSB_TXCSR, csr); + /* the DMA is not disable here, since the residual data + may be still available in cppi-fifo interface, since + the cppi 4.1 dma generates tx completion after the transfer + of last data bytes to cppi-fifo , it will make sure whether + all bytes are transfered to endpoint fifo */ /* Ensure writebuffer is empty. */ csr = musb_readw(epio, MUSB_TXCSR); request->actual += musb_ep->dma->actual_len; @@ -544,13 +560,14 @@ epnum, csr, musb_ep->dma->actual_len, request); } +if (is_dma || request->actual == request->length) { + /* * First, maybe a terminating short packet. Some DMA * engines might handle this by themselves. */ if ((request->zero && request->length - && (request->length % musb_ep->packet_sz == 0) - && (request->actual == request->length)) + && (request->length % musb_ep->packet_sz) == 0) #ifdef CONFIG_USB_INVENTRA_DMA || (is_dma && (!dma->desired_mode || (request->actual & @@ -561,27 +578,50 @@ * On DMA completion, FIFO may not be * available yet... */ - if (csr & MUSB_TXCSR_TXPKTRDY) - return; - - DBG(4, "sending zero pkt\n"); - musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE - | MUSB_TXCSR_TXPKTRDY); - request->zero = 0; } - - if (request->actual == request->length) { +#if defined(CONFIG_USB_MUSB_HDRC_HCD) || defined(CONFIG_USB_MUSB_OTG) + count = 0x50000; + lcount = 0; + /* Ensure that FIFO is Empty here,since the last packet + from cppi-fifo may be transfered by transfer dma is still + availabe in fifo */ + while (count--) + { + wCsrVal = musb_readw(epio,MUSB_TXCSR); + if ((wCsrVal & MUSB_TXCSR_FIFONOTEMPTY) == 0) + break; + } + if( count <= 0 ) + DBG(5,"%s Warning: USB End point DMA disable before transfer complete\n",__FUNCTION__); +#endif + /* ... or if not, then complete it */ musb_g_giveback(musb_ep, request, 0); - req = musb_ep->desc ? next_request(musb_ep) : NULL; + + /* kickstart next transfer if appropriate; + * the packet that just completed might not + * be transmitted for hours or days. + * REVISIT for double buffering... + * FIXME revisit for stalls too... + */ + + req = musb_ep->desc + ? next_request(musb_ep) + : NULL; + if (!req) { DBG(4, "%s idle now\n", musb_ep->end_point.name); - return; + break; } } + +#if defined(CONFIG_USB_MUSB_HDRC_HCD) || defined(CONFIG_USB_MUSB_OTG) txstate(musb, req); +#endif } + + } while (0); } /* ------------------------------------------------------------ */ @@ -638,22 +678,13 @@ len = musb_ep->packet_sz; - /* We shouldn't get here while DMA is active, but we do... */ - if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { - DBG(4, "DMA pending...\n"); - return; - } - - if (csr & MUSB_RXCSR_P_SENDSTALL) { - DBG(5, "%s stalling, RXCSR %04x\n", - musb_ep->end_point.name, csr); - return; - } if (is_cppi_enabled() && is_buffer_mapped(req)) { struct dma_controller *c = musb->dma_controller; struct dma_channel *channel = musb_ep->dma; + channel->actual_len = 0L; + /* NOTE: CPPI won't actually stop advancing the DMA * queue after short packet transfers, so this is almost * always going to run as IRQ-per-packet DMA so that @@ -870,18 +901,11 @@ DBG(4, "%s, incomprx\n", musb_ep->end_point.name); } - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - /* "should not happen"; likely RXPKTRDY pending for DMA */ - DBG((csr & MUSB_RXCSR_DMAENAB) ? 4 : 1, - "%s busy, csr %04x\n", - musb_ep->end_point.name, csr); - return; - } if (dma && (csr & MUSB_RXCSR_DMAENAB)) { - csr &= ~(MUSB_RXCSR_AUTOCLEAR +/* csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB - | MUSB_RXCSR_DMAMODE); + | MUSB_RXCSR_DMAMODE); */ musb_writew(epio, MUSB_RXCSR, MUSB_RXCSR_P_WZC_BITS | csr); @@ -918,15 +942,10 @@ #endif musb_g_giveback(musb_ep, request, 0); - req = next_request(musb_ep); - if (!req) - return; } #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) exit: #endif - /* Analyze request */ - rxstate(musb, req); } /* ------------------------------------------------------------ */ @@ -1261,11 +1280,13 @@ /* add request to the list */ list_add_tail(&request->list, &musb_ep->req_list); - +#if defined(CONFIG_USB_MUSB_HDRC_HCD) || defined(CONFIG_USB_MUSB_OTG) /* it this is the head of the queue, start i/o ... */ if (!musb_ep->busy && &request->list == musb_ep->req_list.next) musb_ep_restart(musb, request); - +#else + musb_ep_restart(musb, request); +#endif cleanup: spin_unlock_irqrestore(&musb->lock, lockflags); return status; @@ -1328,7 +1349,7 @@ * * exported to ep0 code */ -static int musb_gadget_set_halt(struct usb_ep *ep, int value) +int musb_gadget_set_halt(struct usb_ep *ep, int value) { struct musb_ep *musb_ep = to_musb_ep(ep); u8 epnum = musb_ep->current_epnum; @@ -1910,6 +1931,8 @@ { int i; struct musb_hw_ep *hw_ep; + struct usb_ep *ep; + /* don't disconnect if it's not connected */ if (musb->g.speed == USB_SPEED_UNKNOWN) @@ -1933,12 +1956,26 @@ i++, hw_ep++) { musb_ep_select(musb->mregs, i); if (hw_ep->is_shared_fifo /* || !epnum */) { - nuke(&hw_ep->ep_in, -ESHUTDOWN); + ep = &hw_ep->ep_in.end_point; + + spin_unlock(&musb->lock); + musb_gadget_disable(ep); + spin_lock(&musb->lock); } else { - if (hw_ep->max_packet_sz_tx) - nuke(&hw_ep->ep_in, -ESHUTDOWN); - if (hw_ep->max_packet_sz_rx) - nuke(&hw_ep->ep_out, -ESHUTDOWN); + if (hw_ep->max_packet_sz_tx) { + ep = &hw_ep->ep_in.end_point; + + spin_unlock(&musb->lock); + musb_gadget_disable(ep); + spin_lock(&musb->lock); + } + if (hw_ep->max_packet_sz_rx) { + ep = &hw_ep->ep_out.end_point; + + spin_unlock(&musb->lock); + musb_gadget_disable(ep); + spin_lock(&musb->lock); + } } }