#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 */
int ch;
s8 dmareq;
s8 sync_dev;
+ unsigned multichannel:1;
};
static int tusb_omap_dma_start(struct dma_controller *c)
return 0;
}
-#ifdef BROKEN_DMAREQ
-
/*
* Allocate dmareq0 to the current channel unless it's already taken
*/
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.
spin_lock_irqsave(&musb->lock, flags);
- if (dmareq_works())
+ if (tusb_dma->multichannel)
ch = chdat->ch;
else
ch = tusb_dma->ch;
channel->actual_len += pio;
}
- if (!dmareq_works())
+ if (!tusb_dma->multichannel)
tusb_omap_free_shared_dmareq(chdat);
channel->status = MUSB_DMA_STATUS_FREE;
return false;
}
-
chdat->transfer_len = len & ~0x1f;
if (len < 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;
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);
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;
}
}
- 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);
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;