summaryrefslogtreecommitdiff
path: root/packages/linux/linux-omap/musb-dmafix.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-omap/musb-dmafix.patch')
-rw-r--r--packages/linux/linux-omap/musb-dmafix.patch275
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 |