Hi Sergei, on DaVinci is extremely necessary to program EP CSR before channel_program() ? I believe it's not a problem for the OMAP-based board and I doubt it's a problem for Blackfin too. I think it would be easy to drop all the DMA magic if we figure out a way to program DMA that works for all engines. Possibly following what MUSB docs say would be enough: . Program EP CSR . Program DMA ADDR and COUNT . Program DMA Control So it would be something like: >From 586d9ea1b0417640877c201fdb88d2d555b8c174 Mon Sep 17 00:00:00 2001 From: Felipe Balbi <balbi@xxxxxx> Date: Wed, 12 Jan 2011 12:50:24 +0200 Subject: [PATCH] usb: musb: gadget: drop DMA ifdeffery Organization: Texas Instruments\n MUSB DMA programming can be done in a simpler way if we drop all the DMA magic. NYET-Signed-off-by: Felipe Balbi <balbi@xxxxxx> --- Completely untested, just looking at the code. Didn't even compile this one. drivers/usb/musb/musb_gadget.c | 149 +++++++++------------------------------ 1 files changed, 35 insertions(+), 114 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 9b162df..d6aca24 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -347,87 +347,53 @@ static void txstate(struct musb *musb, struct musb_request *req) /* MUSB_TXCSR_P_ISO is still set correctly */ -#ifdef CONFIG_USB_INVENTRA_DMA - { - if (request_size < musb_ep->packet_sz) - musb_ep->dma->desired_mode = 0; - else - musb_ep->dma->desired_mode = 1; - - use_dma = use_dma && c->channel_program( - musb_ep->dma, musb_ep->packet_sz, - musb_ep->dma->desired_mode, - request->dma + request->actual, request_size); - if (use_dma) { - if (musb_ep->dma->desired_mode == 0) { - /* - * We must not clear the DMAMODE bit - * before the DMAENAB bit -- and the - * latter doesn't always get cleared - * before we get here... - */ - csr &= ~(MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB); - musb_writew(epio, MUSB_TXCSR, csr - | MUSB_TXCSR_P_WZC_BITS); - csr &= ~MUSB_TXCSR_DMAMODE; - csr |= (MUSB_TXCSR_DMAENAB | - MUSB_TXCSR_MODE); - /* against programming guide */ - } else { - csr |= (MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_DMAMODE - | MUSB_TXCSR_MODE); - if (!musb_ep->hb_mult) - csr |= MUSB_TXCSR_AUTOSET; - } - csr &= ~MUSB_TXCSR_P_UNDERRUN; + if (request_size < musb_ep->packet_sz) + musb_ep->dma->desired_mode = 0; + else + musb_ep->dma->desired_mode = 1; - musb_writew(epio, MUSB_TXCSR, csr); - } + if (musb_ep->dma->desired_mode == 0) { + /* + * We must not clear the DMAMODE bit + * before the DMAENAB bit -- and the + * latter doesn't always get cleared + * before we get here... + */ + csr &= ~(MUSB_TXCSR_AUTOSET + | MUSB_TXCSR_DMAENAB); + musb_writew(epio, MUSB_TXCSR, csr + | MUSB_TXCSR_P_WZC_BITS); + csr &= ~MUSB_TXCSR_DMAMODE; + csr |= (MUSB_TXCSR_DMAENAB | + MUSB_TXCSR_MODE); + /* against programming guide */ + } else { + csr |= (MUSB_TXCSR_DMAENAB + | MUSB_TXCSR_DMAMODE + | MUSB_TXCSR_MODE); + if (!musb_ep->hb_mult) + csr |= MUSB_TXCSR_AUTOSET; } + csr &= ~MUSB_TXCSR_P_UNDERRUN; -#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; - musb_writew(epio, MUSB_TXCSR, - (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) - | csr); - - /* ensure writebuffer is empty */ - csr = musb_readw(epio, MUSB_TXCSR); - - /* 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 - * to the USB TX fifo when both fifos are ready. - */ + musb_writew(epio, MUSB_TXCSR, csr); - /* "mode" is irrelevant here; handle terminating ZLPs like - * PIO does, since the hardware RNDIS mode seems unreliable - * except for the last-packet-is-already-short case. - */ use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, - 0, - request->dma + request->actual, - request_size); + musb_ep->dma->desired_mode, + request->dma + request->actual, request_size); if (!use_dma) { c->channel_release(musb_ep->dma); musb_ep->dma = NULL; csr &= ~MUSB_TXCSR_DMAENAB; musb_writew(epio, MUSB_TXCSR, csr); - /* invariant: prequest->buf is non-null */ + + /* Case we enabled mode1 DMA, disable it */ + if (musb_ep->dma->desired_mode) { + csr &= ~MUSB_TXCSR_DMAMODE; + musb_writew(epio, MUSB_TXCSR, csr); + } } -#elif defined(CONFIG_USB_TUSB_OMAP_DMA) - use_dma = use_dma && c->channel_program( - musb_ep->dma, musb_ep->packet_sz, - request->zero, - request->dma + request->actual, - request_size); -#endif } #endif @@ -627,37 +593,9 @@ static void rxstate(struct musb *musb, struct musb_request *req) return; } - if (is_cppi_enabled() && musb_ep->dma) { - struct dma_controller *c = musb->dma_controller; - struct dma_channel *channel = musb_ep->dma; - - /* 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 - * faults will be handled correctly. - */ - if (c->channel_program(channel, - musb_ep->packet_sz, - !request->short_not_ok, - request->dma + request->actual, - request->length - request->actual)) { - - /* make sure that if an rxpkt arrived after the irq, - * the cppi engine will be ready to take it as soon - * as DMA is enabled - */ - csr &= ~(MUSB_RXCSR_AUTOCLEAR - | MUSB_RXCSR_DMAMODE); - csr |= MUSB_RXCSR_DMAENAB | MUSB_RXCSR_P_WZC_BITS; - musb_writew(epio, MUSB_RXCSR, csr); - return; - } - } - if (csr & MUSB_RXCSR_RXPKTRDY) { len = musb_readw(epio, MUSB_RXCOUNT); if (request->actual < request->length) { -#ifdef CONFIG_USB_INVENTRA_DMA if (is_dma_capable() && musb_ep->dma) { struct dma_controller *c; struct dma_channel *channel; @@ -731,7 +669,6 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (use_dma) return; } -#endif /* Mentor's DMA */ fifo_count = request->length - request->actual; DBG(3, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n", @@ -741,22 +678,6 @@ static void rxstate(struct musb *musb, struct musb_request *req) fifo_count = min_t(unsigned, len, fifo_count); -#ifdef CONFIG_USB_TUSB_OMAP_DMA - if (tusb_dma_omap() && musb_ep->dma) { - struct dma_controller *c = musb->dma_controller; - struct dma_channel *channel = musb_ep->dma; - u32 dma_addr = request->dma + request->actual; - int ret; - - ret = c->channel_program(channel, - musb_ep->packet_sz, - channel->desired_mode, - dma_addr, - fifo_count); - if (ret) - return; - } -#endif /* * Unmap the dma buffer back to cpu if dma channel * programming fails. This buffer is mapped if the -- 1.7.3.4.598.g85356 if something like this works for DaVinci, then we can easily drop all ifdeffery and we drop quite some patches from Ming's series. -- balbi -- 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