]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
musb_hdrc: Allow tusb3.0 and greater to use multichannel DMA
authorTony Lindgren <tony@atomide.com>
Fri, 14 Sep 2007 22:32:58 +0000 (15:32 -0700)
committerTony Lindgren <tony@atomide.com>
Thu, 11 Oct 2007 21:31:33 +0000 (14:31 -0700)
Allow tusb3.0 and greater to use multichannel DMA

Signed-off-by: Tony Lindgren <tony@atomide.com>
drivers/usb/musb/tusb6010.c
drivers/usb/musb/tusb6010.h
drivers/usb/musb/tusb6010_omap.c

index fbb402c11647c10da7bada1b828eba5d59e24c91..5026f2b598174b76dfc2ce946e74d13db06a102f 100644 (file)
@@ -34,7 +34,7 @@ static void tusb_source_power(struct musb *musb, int is_on);
  * Checks the revision. We need to use the DMA register as 3.0 does not
  * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV.
  */
-static u8 tusb_get_revision(struct musb *musb)
+u8 tusb_get_revision(struct musb *musb)
 {
        void __iomem    *tbase = musb->ctrl_base;
        u32             die_id;
index 16a311a1f03a86b929a921d6c95126a924d44e08..7ef6abf143edcc4fec7f10033c6c18892817afb0 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __TUSB6010_H__
 #define __TUSB6010_H__
 
+extern u8 tusb_get_revision(struct musb *musb);
+
 #ifdef CONFIG_USB_TUSB6010
 #define musb_in_tusb()                 1
 #else
index 42c6a6b2b40885249245a01cc60416f120d4b3da..09a6a3cc8e1511149ab5f01dc6b8c99a607623fd 100644 (file)
 
 #include "musb_core.h"
 
-/*
- * REVISIT: With TUSB2.0 only one dmareq line can be used at a time.
- * This should get fixed in hardware at some point.
- */
-#define BROKEN_DMAREQ
-
-#ifdef BROKEN_DMAREQ
-#define dmareq_works()         0
-#else
-#define dmareq_works()         1
-#endif
-
 #define to_chdat(c)            (struct tusb_omap_dma_ch *)(c)->private_data
 
 #define MAX_DMAREQ             5       /* REVISIT: Really 6, but req5 not OK */
@@ -67,6 +55,7 @@ struct tusb_omap_dma {
        int                             ch;
        s8                              dmareq;
        s8                              sync_dev;
+       unsigned                        multichannel:1;
 };
 
 static int tusb_omap_dma_start(struct dma_controller *c)
@@ -91,8 +80,6 @@ static int tusb_omap_dma_stop(struct dma_controller *c)
        return 0;
 }
 
-#ifdef BROKEN_DMAREQ
-
 /*
  * Allocate dmareq0 to the current channel unless it's already taken
  */
@@ -128,11 +115,6 @@ static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
        musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, 0);
 }
 
-#else
-#define tusb_omap_use_shared_dmareq(x, y)      do {} while (0)
-#define tusb_omap_free_shared_dmareq(x, y)     do {} while (0)
-#endif
-
 /*
  * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
  * musb_gadget.c.
@@ -151,7 +133,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
 
        spin_lock_irqsave(&musb->lock, flags);
 
-       if (dmareq_works())
+       if (tusb_dma->multichannel)
                ch = chdat->ch;
        else
                ch = tusb_dma->ch;
@@ -201,7 +183,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
                channel->actual_len += pio;
        }
 
-       if (!dmareq_works())
+       if (!tusb_dma->multichannel)
                tusb_omap_free_shared_dmareq(chdat);
 
        channel->status = MUSB_DMA_STATUS_FREE;
@@ -283,7 +265,6 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
                return false;
        }
 
-
        chdat->transfer_len = len & ~0x1f;
 
        if (len < packet_sz)
@@ -291,7 +272,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
        else
                chdat->transfer_packet_sz = packet_sz;
 
-       if (dmareq_works()) {
+       if (tusb_dma->multichannel) {
                ch = chdat->ch;
                dmareq = chdat->dmareq;
                sync_dev = chdat->sync_dev;
@@ -441,7 +422,7 @@ static int tusb_omap_dma_abort(struct dma_channel *channel)
        struct tusb_omap_dma_ch *chdat = to_chdat(channel);
        struct tusb_omap_dma    *tusb_dma = chdat->tusb_dma;
 
-       if (!dmareq_works()) {
+       if (!tusb_dma->multichannel) {
                if (tusb_dma->ch >= 0) {
                        omap_stop_dma(tusb_dma->ch);
                        omap_free_dma(tusb_dma->ch);
@@ -574,7 +555,7 @@ tusb_omap_dma_allocate(struct dma_controller *c,
        channel->desired_mode = 0;
        channel->actual_len = 0;
 
-       if (dmareq_works()) {
+       if (tusb_dma->multichannel) {
                ret = tusb_omap_dma_allocate_dmareq(chdat);
                if (ret != 0)
                        goto free_dmareq;
@@ -668,7 +649,7 @@ void dma_controller_destroy(struct dma_controller *c)
                }
        }
 
-       if (!dmareq_works() && tusb_dma && tusb_dma->ch >= 0)
+       if (!tusb_dma->multichannel && tusb_dma && tusb_dma->ch >= 0)
                omap_free_dma(tusb_dma->ch);
 
        kfree(tusb_dma);
@@ -710,6 +691,9 @@ dma_controller_create(struct musb *musb, void __iomem *base)
        tusb_dma->controller.channel_abort = tusb_omap_dma_abort;
        tusb_dma->controller.private_data = tusb_dma;
 
+       if (tusb_get_revision(musb) >= TUSB_REV_30)
+               tusb_dma->multichannel = 1;
+
        for (i = 0; i < MAX_DMAREQ; i++) {
                struct dma_channel      *ch;
                struct tusb_omap_dma_ch *chdat;