]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/musb/musbhsdma.c
usb: musb: fix bug in musbhsdma programming
[linux-2.6-omap-h63xx.git] / drivers / usb / musb / musbhsdma.c
index 8c734ef2c1ed52a8f39dceca5b7bff647b6d8dd4..4394bd3682ce514d7caaf82147c4252a15db5a00 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include "musb_core.h"
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
-#include "omap2430.h"
-#endif
-
-#define MUSB_HSDMA_BASE                0x200
-#define MUSB_HSDMA_INTR                (MUSB_HSDMA_BASE + 0)
-#define MUSB_HSDMA_CONTROL             0x4
-#define MUSB_HSDMA_ADDRESS             0x8
-#define MUSB_HSDMA_COUNT               0xc
-
-#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)          \
-               (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset)
-
-/* control register (16-bit): */
-#define MUSB_HSDMA_ENABLE_SHIFT                0
-#define MUSB_HSDMA_TRANSMIT_SHIFT              1
-#define MUSB_HSDMA_MODE1_SHIFT         2
-#define MUSB_HSDMA_IRQENABLE_SHIFT             3
-#define MUSB_HSDMA_ENDPOINT_SHIFT              4
-#define MUSB_HSDMA_BUSERROR_SHIFT              8
-#define MUSB_HSDMA_BURSTMODE_SHIFT             9
-#define MUSB_HSDMA_BURSTMODE           (3 << MUSB_HSDMA_BURSTMODE_SHIFT)
-#define MUSB_HSDMA_BURSTMODE_UNSPEC    0
-#define MUSB_HSDMA_BURSTMODE_INCR4     1
-#define MUSB_HSDMA_BURSTMODE_INCR8     2
-#define MUSB_HSDMA_BURSTMODE_INCR16    3
-
-#define MUSB_HSDMA_CHANNELS            8
-
-struct musb_dma_controller;
-
-struct musb_dma_channel {
-       struct dma_channel              channel;
-       struct musb_dma_controller      *controller;
-       u32                             start_addr;
-       u32                             len;
-       u16                             max_packet_sz;
-       u8                              idx;
-       u8                              epnum;
-       u8                              transmit;
-};
-
-struct musb_dma_controller {
-       struct dma_controller           controller;
-       struct musb_dma_channel         channel[MUSB_HSDMA_CHANNELS];
-       void                            *private_data;
-       void __iomem                    *base;
-       u8                              channel_count;
-       u8                              used_channels;
-       u8                              irq;
-};
+#include "musbhsdma.h"
 
 static int dma_controller_start(struct dma_controller *c)
 {
@@ -179,36 +128,24 @@ static void configure_channel(struct dma_channel *channel,
        DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n",
                        channel, packet_sz, dma_addr, len, mode);
 
-       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
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               } else if (packet_sz >= 16) {
-                       csr |= MUSB_HSDMA_BURSTMODE_INCR4
-                                       << MUSB_HSDMA_BURSTMODE_SHIFT;
-               }
-       }
+       if (packet_sz >= 64)
+               csr |= MUSB_HSDMA_BURSTMODE_INCR16;
+       else if (packet_sz >= 32)
+               csr |= MUSB_HSDMA_BURSTMODE_INCR8;
+       else if (packet_sz >= 16)
+               csr |= MUSB_HSDMA_BURSTMODE_INCR4;
 
        csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
-               | (1 << MUSB_HSDMA_ENABLE_SHIFT)
-               | (1 << MUSB_HSDMA_IRQENABLE_SHIFT)
+               | (mode ? MUSB_HSDMA_MODE1 : 0)
+               | MUSB_HSDMA_ENABLE
+               | MUSB_HSDMA_IRQENABLE
                | (musb_channel->transmit
-                               ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT)
+                               ? MUSB_HSDMA_TRANSMIT
                                : 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);
+       musb_write_hsdma_addr(mbase, bchannel, dma_addr);
+       musb_write_hsdma_count(mbase, bchannel, len);
 
        /* control (this should start things) */
        musb_writew(mbase,
@@ -236,10 +173,7 @@ static int dma_channel_program(struct dma_channel *channel,
        musb_channel->max_packet_sz = packet_sz;
        channel->status = MUSB_DMA_STATUS_BUSY;
 
-       if ((mode == 1) && (len >= packet_sz))
-               configure_channel(channel, packet_sz, 1, dma_addr, len);
-       else
-               configure_channel(channel, packet_sz, 0, dma_addr, len);
+       configure_channel(channel, packet_sz, mode, dma_addr, len);
 
        return true;
 }
@@ -279,13 +213,8 @@ static int dma_channel_abort(struct dma_channel *channel)
                musb_writew(mbase,
                        MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL),
                        0);
-               musb_writel(mbase,
-                       MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS),
-                       0);
-               musb_writel(mbase,
-                       MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT),
-                       0);
-
+               musb_write_hsdma_addr(mbase, bchannel, 0);
+               musb_write_hsdma_count(mbase, bchannel, 0);
                channel->status = MUSB_DMA_STATUS_FREE;
        }
 
@@ -327,16 +256,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                        MUSB_HSDMA_CHANNEL_OFFSET(bchannel,
                                                        MUSB_HSDMA_CONTROL));
 
-                       if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) {
+                       if (csr & MUSB_HSDMA_BUSERROR) {
                                musb_channel->channel.status =
                                        MUSB_DMA_STATUS_BUS_ABORT;
                        } else {
                                u8 devctl;
 
-                               addr = musb_readl(mbase,
-                                               MUSB_HSDMA_CHANNEL_OFFSET(
-                                                       bchannel,
-                                                       MUSB_HSDMA_ADDRESS));
+                               addr = musb_read_hsdma_addr(mbase,
+                                               bchannel);
                                channel->actual_len = addr
                                        - musb_channel->start_addr;
 
@@ -375,6 +302,12 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                        }
                }
        }
+
+#ifdef CONFIG_BLACKFIN
+       /* Clear DMA interrup flags */
+       musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma);
+#endif
+
        retval = IRQ_HANDLED;
 done:
        spin_unlock_irqrestore(&musb->lock, flags);