USB: musb: enable low level DMA operation for Blackfin
authorBryan Wu <cooloney@kernel.org>
Tue, 2 Dec 2008 19:33:47 +0000 (21:33 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 7 Jan 2009 18:00:07 +0000 (10:00 -0800)
- DMA registers in Blackfin have different layout
- DMA interrupt flags need to be cleared by software

Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/musb/musbhsdma.c
drivers/usb/musb/musbhsdma.h [new file with mode: 0644]

index d193b78..8662e9e 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)
 {
@@ -203,12 +152,8 @@ static void configure_channel(struct dma_channel *channel,
                                : 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,
@@ -279,13 +224,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;
        }
 
@@ -333,10 +273,8 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                        } 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 +313,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);
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
new file mode 100644 (file)
index 0000000..1299d92
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * MUSB OTG driver - support for Mentor's DMA controller
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2007 by Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#include "omap2430.h"
+#endif
+
+#ifndef CONFIG_BLACKFIN
+
+#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)
+
+#define musb_read_hsdma_addr(mbase, bchannel)  \
+       musb_readl(mbase,       \
+                  MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS))
+
+#define musb_write_hsdma_addr(mbase, bchannel, addr) \
+       musb_writel(mbase, \
+                   MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \
+                   addr)
+
+#define musb_write_hsdma_count(mbase, bchannel, len) \
+       musb_writel(mbase, \
+                   MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \
+                   len)
+#else
+
+#define MUSB_HSDMA_BASE                0x400
+#define MUSB_HSDMA_INTR                (MUSB_HSDMA_BASE + 0)
+#define MUSB_HSDMA_CONTROL             0x04
+#define MUSB_HSDMA_ADDR_LOW            0x08
+#define MUSB_HSDMA_ADDR_HIGH           0x0C
+#define MUSB_HSDMA_COUNT_LOW           0x10
+#define MUSB_HSDMA_COUNT_HIGH          0x14
+
+#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)          \
+               (MUSB_HSDMA_BASE + (_bchannel * 0x20) + _offset)
+
+static inline u32 musb_read_hsdma_addr(void __iomem *mbase, u8 bchannel)
+{
+       u32 addr = musb_readw(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH));
+
+       addr = addr << 16;
+
+       addr |= musb_readw(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW));
+
+       return addr;
+}
+
+static inline void musb_write_hsdma_addr(void __iomem *mbase,
+                               u8 bchannel, dma_addr_t dma_addr)
+{
+       musb_writew(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW),
+               ((u16)((u32) dma_addr & 0xFFFF)));
+       musb_writew(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH),
+               ((u16)(((u32) dma_addr >> 16) & 0xFFFF)));
+}
+
+static inline void musb_write_hsdma_count(void __iomem *mbase,
+                               u8 bchannel, u32 len)
+{
+       musb_writew(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW),
+               ((u16)((u32) len & 0xFFFF)));
+       musb_writew(mbase,
+               MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH),
+               ((u16)(((u32) len >> 16) & 0xFFFF)));
+}
+
+#endif /* CONFIG_BLACKFIN */
+
+/* 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;
+};