diff options
Diffstat (limited to 'packages/linux/linux-omap/musb-dmafix.patch')
-rw-r--r-- | packages/linux/linux-omap/musb-dmafix.patch | 275 |
1 files changed, 0 insertions, 275 deletions
diff --git a/packages/linux/linux-omap/musb-dmafix.patch b/packages/linux/linux-omap/musb-dmafix.patch deleted file mode 100644 index 259b79be59..0000000000 --- a/packages/linux/linux-omap/musb-dmafix.patch +++ /dev/null @@ -1,275 +0,0 @@ -From: Gadiyar, Anand <gadiyar@ti.com> -Date: Wed, 13 Aug 2008 07:05:29 +0000 (+0530) -Subject: MUSB: Workaround for simultaneous TX and RX usage -X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=2e6aa4efb0e14c51ff0427927b1b38136911fa93 - -MUSB: Workaround for simultaneous TX and RX usage - -MUSB: Workaround for simultaneous TX and RX usage - -MUSB RTL V1.4 has a hardware issue which results in a DMA controller -hang when TX and RX DMA channels are simultaneously enabled. This -affects at least OMAP2430 and OMAP34XX. - -Since RX transfers are in Mode 0 and anyway result in one DMA interrupt -per packet, we can use System DMA to unload the RX fifos. MUSB DMA can -be used for all TX channels as before. - -Tested with full-duplex TX and RX transfers using g_ether. Runs for 24 -hours without a hang. Without this patch, the hang occurs within minutes. - -This issue was first reported by Jon Hunter on [1] - -[1] http://marc.info/?l=linux-omap&m=119634480534453&w=2 - -Signed-off-by: Anand Gadiyar <gadiyar@ti.com> ---- - -diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig -index a485a86..8583e54 100644 ---- a/drivers/usb/musb/Kconfig -+++ b/drivers/usb/musb/Kconfig -@@ -150,6 +150,14 @@ config USB_INVENTRA_DMA - help - Enable DMA transfers using Mentor's engine. - -+config MUSB_USE_SYSTEM_DMA_RX -+ bool 'Use System DMA for RX endpoints' -+ depends on USB_MUSB_HDRC && USB_INVENTRA_DMA -+ help -+ MUSB RTL version 1.4 has a hardware issue when TX and RX DMA -+ channels are simultaneously enabled. To work around this issue, -+ you can choose to use System DMA for RX channels. -+ - config USB_TI_CPPI_DMA - bool - depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY -diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c -index 32bb1e2..d1c1ea0 100644 ---- a/drivers/usb/musb/musbhsdma.c -+++ b/drivers/usb/musb/musbhsdma.c -@@ -34,6 +34,7 @@ - #include <linux/interrupt.h> - #include <linux/platform_device.h> - #include "musb_core.h" -+#include <asm/dma.h> - - #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) - #include "omap2430.h" -@@ -64,6 +65,9 @@ - - #define MUSB_HSDMA_CHANNELS 8 - -+#define MUSB_FIFO_ADDRESS(epnum) \ -+ ((unsigned long) (OMAP_HSOTG_BASE + MUSB_FIFO_OFFSET(epnum))) -+ - struct musb_dma_controller; - - struct musb_dma_channel { -@@ -75,6 +79,8 @@ struct musb_dma_channel { - u8 bIndex; - u8 epnum; - u8 transmit; -+ -+ int sysdma_channel; - }; - - struct musb_dma_controller { -@@ -93,6 +99,42 @@ static int dma_controller_start(struct dma_controller *c) - return 0; - } - -+#ifdef CONFIG_MUSB_USE_SYSTEM_DMA_RX -+static void musb_sysdma_completion(int lch, u16 ch_status, void *data) -+{ -+ u32 dwAddress; -+ unsigned long flags; -+ -+ struct dma_channel *pChannel; -+ -+ struct musb_dma_channel *pImplChannel = -+ (struct musb_dma_channel *) data; -+ struct musb_dma_controller *controller = pImplChannel->controller; -+ struct musb *musb = controller->pDmaPrivate; -+ pChannel = &pImplChannel->Channel; -+ -+ DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status); -+ spin_lock_irqsave(&musb->lock, flags); -+ -+ dwAddress = (u32) omap_get_dma_dst_pos(pImplChannel->sysdma_channel); -+ pChannel->actual_len = dwAddress - pImplChannel->dwStartAddress; -+ -+ DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", -+ pChannel, pImplChannel->dwStartAddress, dwAddress, -+ pChannel->actual_len, pImplChannel->len, -+ (pChannel->actual_len < pImplChannel->len) ? -+ "=> reconfig 0": "=> complete"); -+ -+ pChannel->status = MUSB_DMA_STATUS_FREE; -+ musb_dma_completion(musb, pImplChannel->epnum, pImplChannel->transmit); -+ -+ spin_unlock_irqrestore(&musb->lock, flags); -+ return; -+} -+#else -+#define musb_sysdma_completion NULL -+#endif -+ - static void dma_channel_release(struct dma_channel *pChannel); - - static int dma_controller_stop(struct dma_controller *c) -@@ -144,6 +186,29 @@ static struct dma_channel *dma_channel_allocate(struct dma_controller *c, - /* Tx => mode 1; Rx => mode 0 */ - pChannel->desired_mode = transmit; - pChannel->actual_len = 0; -+ pImplChannel->sysdma_channel = -1; -+ -+#ifdef CONFIG_MUSB_USE_SYSTEM_DMA_RX -+ if (!transmit) { -+ int ret; -+ ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, -+ "MUSB SysDMA", musb_sysdma_completion, -+ (void *) pImplChannel, -+ &(pImplChannel->sysdma_channel)); -+ -+ if (ret) { -+ printk(KERN_ERR "request_dma failed:" -+ " %d\n", ret); -+ controller->bmUsedChannels &= -+ ~(1 << bBit); -+ pChannel->status = -+ MUSB_DMA_STATUS_UNKNOWN; -+ pImplChannel->sysdma_channel = -1; -+ pChannel = NULL; -+ } -+ } -+#endif -+ - break; - } - } -@@ -163,6 +228,12 @@ static void dma_channel_release(struct dma_channel *pChannel) - ~(1 << pImplChannel->bIndex); - - pChannel->status = MUSB_DMA_STATUS_UNKNOWN; -+ -+ if (pImplChannel->sysdma_channel != -1) { -+ omap_stop_dma(pImplChannel->sysdma_channel); -+ omap_free_dma(pImplChannel->sysdma_channel); -+ pImplChannel->sysdma_channel = -1; -+ } - } - - static void configure_channel(struct dma_channel *pChannel, -@@ -179,41 +250,69 @@ static void configure_channel(struct dma_channel *pChannel, - DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", - pChannel, packet_sz, dma_addr, len, mode); - -- if (mode) { -- csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; -- BUG_ON(len < packet_sz); -+ if (pImplChannel->sysdma_channel != -1) { -+ /* System DMA */ -+ /* RX: set src = FIFO */ -+ -+ omap_set_dma_transfer_params(pImplChannel->sysdma_channel, -+ OMAP_DMA_DATA_TYPE_S8, -+ len, 1, /* One frame */ -+ OMAP_DMA_SYNC_ELEMENT, -+ OMAP24XX_DMA_NO_DEVICE, -+ 0); /* Src Sync */ -+ -+ omap_set_dma_src_params(pImplChannel->sysdma_channel, 0, -+ OMAP_DMA_AMODE_CONSTANT, -+ MUSB_FIFO_ADDRESS(pImplChannel->epnum), -+ 0, 0); - -- if (packet_sz >= 64) { -- csr |= MUSB_HSDMA_BURSTMODE_INCR16 -+ omap_set_dma_dest_params(pImplChannel->sysdma_channel, 0, -+ OMAP_DMA_AMODE_POST_INC, dma_addr, -+ 0, 0); -+ -+ omap_set_dma_dest_data_pack(pImplChannel->sysdma_channel, 1); -+ omap_set_dma_dest_burst_mode(pImplChannel->sysdma_channel, -+ OMAP_DMA_DATA_BURST_16); -+ -+ omap_start_dma(pImplChannel->sysdma_channel); -+ -+ } else { /* Mentor DMA */ -+ if (mode) { -+ csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; -+ BUG_ON(len < packet_sz); -+ -+ if (packet_sz >= 64) { -+ csr |= MUSB_HSDMA_BURSTMODE_INCR16 - << MUSB_HSDMA_BURSTMODE_SHIFT; -- } else if (packet_sz >= 32) { -- csr |= MUSB_HSDMA_BURSTMODE_INCR8 -+ } else if (packet_sz >= 32) { -+ csr |= MUSB_HSDMA_BURSTMODE_INCR8 - << MUSB_HSDMA_BURSTMODE_SHIFT; -- } else if (packet_sz >= 16) { -- csr |= MUSB_HSDMA_BURSTMODE_INCR4 -+ } else if (packet_sz >= 16) { -+ csr |= MUSB_HSDMA_BURSTMODE_INCR4 - << MUSB_HSDMA_BURSTMODE_SHIFT; -+ } - } -- } - -- csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) -- | (1 << MUSB_HSDMA_ENABLE_SHIFT) -- | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) -- | (pImplChannel->transmit -- ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) -- : 0); -- -- /* address/count */ -- musb_writel(mbase, -- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), -- dma_addr); -- musb_writel(mbase, -- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), -- len); -- -- /* control (this should start things) */ -- musb_writew(mbase, -- MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), -- csr); -+ csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) -+ | (1 << MUSB_HSDMA_ENABLE_SHIFT) -+ | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) -+ | (pImplChannel->transmit -+ ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) -+ : 0); -+ -+ /* address/count */ -+ musb_writel(mbase, -+ MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), -+ dma_addr); -+ musb_writel(mbase, -+ MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), -+ len); -+ -+ /* control (this should start things) */ -+ musb_writew(mbase, -+ MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), -+ csr); -+ } /* Mentor DMA */ - } - - static int dma_channel_program(struct dma_channel *pChannel, -@@ -265,6 +364,12 @@ static int dma_channel_abort(struct dma_channel *pChannel) - MUSB_EP_OFFSET(pImplChannel->epnum, MUSB_TXCSR), - csr); - } else { -+ if (pImplChannel->sysdma_channel != -1) { -+ omap_stop_dma(pImplChannel->sysdma_channel); -+ omap_free_dma(pImplChannel->sysdma_channel); -+ pImplChannel->sysdma_channel = -1; -+ } -+ - csr = musb_readw(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, MUSB_RXCSR)); - csr &= ~(MUSB_RXCSR_AUTOCLEAR | |