Commit 1df9d9ec authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Greg Kroah-Hartman

usb: musb: tusb6010_omap: Create new struct for DMA data/parameters

For the DMA we have ch (channel), dmareq and sync_dev parameters both
within the tusb_omap_dma_ch and tusb_omap_dma struct.
By creating a common struct the code can be simplified when selecting
between the shared or multichannel DMA parameters.
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
Tested-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarBin Liu <b-liu@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3565b787
...@@ -31,6 +31,12 @@ ...@@ -31,6 +31,12 @@
#define OMAP242X_DMA_EXT_DMAREQ4 16 #define OMAP242X_DMA_EXT_DMAREQ4 16
#define OMAP242X_DMA_EXT_DMAREQ5 64 #define OMAP242X_DMA_EXT_DMAREQ5 64
struct tusb_dma_data {
int ch;
s8 dmareq;
s8 sync_dev;
};
struct tusb_omap_dma_ch { struct tusb_omap_dma_ch {
struct musb *musb; struct musb *musb;
void __iomem *tbase; void __iomem *tbase;
...@@ -39,9 +45,7 @@ struct tusb_omap_dma_ch { ...@@ -39,9 +45,7 @@ struct tusb_omap_dma_ch {
u8 tx; u8 tx;
struct musb_hw_ep *hw_ep; struct musb_hw_ep *hw_ep;
int ch; struct tusb_dma_data dma_data;
s8 dmareq;
s8 sync_dev;
struct tusb_omap_dma *tusb_dma; struct tusb_omap_dma *tusb_dma;
...@@ -58,9 +62,7 @@ struct tusb_omap_dma { ...@@ -58,9 +62,7 @@ struct tusb_omap_dma {
struct dma_controller controller; struct dma_controller controller;
void __iomem *tbase; void __iomem *tbase;
int ch; struct tusb_dma_data dma_data;
s8 dmareq;
s8 sync_dev;
unsigned multichannel:1; unsigned multichannel:1;
}; };
...@@ -119,9 +121,9 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) ...@@ -119,9 +121,9 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
if (tusb_dma->multichannel) if (tusb_dma->multichannel)
ch = chdat->ch; ch = chdat->dma_data.ch;
else else
ch = tusb_dma->ch; ch = tusb_dma->dma_data.ch;
if (ch_status != OMAP_DMA_BLOCK_IRQ) if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status); printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
...@@ -140,8 +142,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) ...@@ -140,8 +142,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */ /* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) { if (unlikely(remaining > chdat->transfer_len)) {
dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n", dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n",
chdat->tx ? "tx" : "rx", chdat->ch, chdat->tx ? "tx" : "rx", ch, remaining);
remaining);
remaining = 0; remaining = 0;
} }
...@@ -220,9 +221,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -220,9 +221,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
int src_burst, dst_burst; int src_burst, dst_burst;
u16 csr; u16 csr;
u32 psize; u32 psize;
int ch; struct tusb_dma_data *dma_data;
s8 dmareq;
s8 sync_dev;
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz)) if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false; return false;
...@@ -249,7 +248,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -249,7 +248,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining); dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) { if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n", dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
chdat->tx ? "tx" : "rx", chdat->ch, chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
dma_remaining); dma_remaining);
return false; return false;
} }
...@@ -262,15 +261,15 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -262,15 +261,15 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
chdat->transfer_packet_sz = packet_sz; chdat->transfer_packet_sz = packet_sz;
if (tusb_dma->multichannel) { if (tusb_dma->multichannel) {
ch = chdat->ch; dma_data = &chdat->dma_data;
dmareq = chdat->dmareq;
sync_dev = chdat->sync_dev;
} else { } else {
dma_data = &tusb_dma->dma_data;
if (tusb_omap_use_shared_dmareq(chdat) != 0) { if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum); dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum);
return false; return false;
} }
if (tusb_dma->ch < 0) { if (dma_data->ch < 0) {
/* REVISIT: This should get blocked earlier, happens /* REVISIT: This should get blocked earlier, happens
* with MSC ErrorRecoveryTest * with MSC ErrorRecoveryTest
*/ */
...@@ -278,10 +277,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -278,10 +277,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
return false; return false;
} }
ch = tusb_dma->ch; omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
dmareq = tusb_dma->dmareq;
sync_dev = tusb_dma->sync_dev;
omap_set_dma_callback(ch, tusb_omap_dma_cb, channel);
} }
chdat->packet_sz = packet_sz; chdat->packet_sz = packet_sz;
...@@ -312,7 +308,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -312,7 +308,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dev_dbg(musb->controller, "ep%i %s dma ch%i dma: %pad len: %u(%u) packet_sz: %i(%i)\n", dev_dbg(musb->controller, "ep%i %s dma ch%i dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
chdat->epnum, chdat->tx ? "tx" : "rx", chdat->epnum, chdat->tx ? "tx" : "rx",
ch, &dma_addr, chdat->transfer_len, len, dma_data->ch, &dma_addr, chdat->transfer_len, len,
chdat->transfer_packet_sz, packet_sz); chdat->transfer_packet_sz, packet_sz);
/* /*
...@@ -329,7 +325,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -329,7 +325,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dma_params.dst_ei = 1; dma_params.dst_ei = 1;
dma_params.dst_fi = -31; /* Loop 32 byte window */ dma_params.dst_fi = -31; /* Loop 32 byte window */
dma_params.trigger = sync_dev; dma_params.trigger = dma_data->sync_dev;
dma_params.sync_mode = OMAP_DMA_SYNC_FRAME; dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
dma_params.src_or_dst_synch = 0; /* Dest sync */ dma_params.src_or_dst_synch = 0; /* Dest sync */
...@@ -346,7 +342,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -346,7 +342,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
dma_params.dst_ei = 0; dma_params.dst_ei = 0;
dma_params.dst_fi = 0; dma_params.dst_fi = 0;
dma_params.trigger = sync_dev; dma_params.trigger = dma_data->sync_dev;
dma_params.sync_mode = OMAP_DMA_SYNC_FRAME; dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
dma_params.src_or_dst_synch = 1; /* Source sync */ dma_params.src_or_dst_synch = 1; /* Source sync */
...@@ -360,10 +356,10 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -360,10 +356,10 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
((dma_addr & 0x3) == 0) ? "sync" : "async", ((dma_addr & 0x3) == 0) ? "sync" : "async",
dma_params.src_start, dma_params.dst_start); dma_params.src_start, dma_params.dst_start);
omap_set_dma_params(ch, &dma_params); omap_set_dma_params(dma_data->ch, &dma_params);
omap_set_dma_src_burst_mode(ch, src_burst); omap_set_dma_src_burst_mode(dma_data->ch, src_burst);
omap_set_dma_dest_burst_mode(ch, dst_burst); omap_set_dma_dest_burst_mode(dma_data->ch, dst_burst);
omap_set_dma_write_mode(ch, OMAP_DMA_WRITE_LAST_NON_POSTED); omap_set_dma_write_mode(dma_data->ch, OMAP_DMA_WRITE_LAST_NON_POSTED);
/* /*
* Prepare MUSB for DMA transfer * Prepare MUSB for DMA transfer
...@@ -386,7 +382,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -386,7 +382,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
/* /*
* Start DMA transfer * Start DMA transfer
*/ */
omap_start_dma(ch); omap_start_dma(dma_data->ch);
if (chdat->tx) { if (chdat->tx) {
/* Send transfer_packet_sz packets at a time */ /* Send transfer_packet_sz packets at a time */
...@@ -415,16 +411,17 @@ static int tusb_omap_dma_abort(struct dma_channel *channel) ...@@ -415,16 +411,17 @@ static int tusb_omap_dma_abort(struct dma_channel *channel)
{ {
struct tusb_omap_dma_ch *chdat = to_chdat(channel); struct tusb_omap_dma_ch *chdat = to_chdat(channel);
struct tusb_omap_dma *tusb_dma = chdat->tusb_dma; struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
struct tusb_dma_data *dma_data = &tusb_dma->dma_data;
if (!tusb_dma->multichannel) { if (!tusb_dma->multichannel) {
if (tusb_dma->ch >= 0) { if (dma_data->ch >= 0) {
omap_stop_dma(tusb_dma->ch); omap_stop_dma(dma_data->ch);
omap_free_dma(tusb_dma->ch); omap_free_dma(dma_data->ch);
tusb_dma->ch = -1; dma_data->ch = -1;
} }
tusb_dma->dmareq = -1; dma_data->dmareq = -1;
tusb_dma->sync_dev = -1; dma_data->sync_dev = -1;
} }
channel->status = MUSB_DMA_STATUS_FREE; channel->status = MUSB_DMA_STATUS_FREE;
...@@ -462,8 +459,8 @@ static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat) ...@@ -462,8 +459,8 @@ static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
reg |= ((1 << 4) << (dmareq_nr * 5)); reg |= ((1 << 4) << (dmareq_nr * 5));
musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg); musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
chdat->dmareq = dmareq_nr; chdat->dma_data.dmareq = dmareq_nr;
chdat->sync_dev = sync_dev[chdat->dmareq]; chdat->dma_data.sync_dev = sync_dev[chdat->dma_data.dmareq];
return 0; return 0;
} }
...@@ -472,15 +469,15 @@ static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat) ...@@ -472,15 +469,15 @@ static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
{ {
u32 reg; u32 reg;
if (!chdat || chdat->dmareq < 0) if (!chdat || chdat->dma_data.dmareq < 0)
return; return;
reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP); reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
reg &= ~(0x1f << (chdat->dmareq * 5)); reg &= ~(0x1f << (chdat->dma_data.dmareq * 5));
musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg); musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
chdat->dmareq = -1; chdat->dma_data.dmareq = -1;
chdat->sync_dev = -1; chdat->dma_data.sync_dev = -1;
} }
static struct dma_channel *dma_channel_pool[MAX_DMAREQ]; static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
...@@ -492,11 +489,13 @@ tusb_omap_dma_allocate(struct dma_controller *c, ...@@ -492,11 +489,13 @@ tusb_omap_dma_allocate(struct dma_controller *c,
{ {
int ret, i; int ret, i;
const char *dev_name; const char *dev_name;
void *cb_data;
struct tusb_omap_dma *tusb_dma; struct tusb_omap_dma *tusb_dma;
struct musb *musb; struct musb *musb;
void __iomem *tbase; void __iomem *tbase;
struct dma_channel *channel = NULL; struct dma_channel *channel = NULL;
struct tusb_omap_dma_ch *chdat = NULL; struct tusb_omap_dma_ch *chdat = NULL;
struct tusb_dma_data *dma_data = NULL;
u32 reg; u32 reg;
tusb_dma = container_of(c, struct tusb_omap_dma, controller); tusb_dma = container_of(c, struct tusb_omap_dma, controller);
...@@ -529,56 +528,62 @@ tusb_omap_dma_allocate(struct dma_controller *c, ...@@ -529,56 +528,62 @@ tusb_omap_dma_allocate(struct dma_controller *c,
if (!channel) if (!channel)
return NULL; return NULL;
if (tx) {
chdat->tx = 1;
dev_name = "TUSB transmit";
} else {
chdat->tx = 0;
dev_name = "TUSB receive";
}
chdat->musb = tusb_dma->controller.musb; chdat->musb = tusb_dma->controller.musb;
chdat->tbase = tusb_dma->tbase; chdat->tbase = tusb_dma->tbase;
chdat->hw_ep = hw_ep; chdat->hw_ep = hw_ep;
chdat->epnum = hw_ep->epnum; chdat->epnum = hw_ep->epnum;
chdat->dmareq = -1;
chdat->completed_len = 0; chdat->completed_len = 0;
chdat->tusb_dma = tusb_dma; chdat->tusb_dma = tusb_dma;
if (tx)
chdat->tx = 1;
else
chdat->tx = 0;
channel->max_len = 0x7fffffff; channel->max_len = 0x7fffffff;
channel->desired_mode = 0; channel->desired_mode = 0;
channel->actual_len = 0; channel->actual_len = 0;
if (tusb_dma->multichannel) { if (tusb_dma->multichannel) {
dma_data = &chdat->dma_data;
ret = tusb_omap_dma_allocate_dmareq(chdat); ret = tusb_omap_dma_allocate_dmareq(chdat);
if (ret != 0) if (ret != 0)
goto free_dmareq; goto free_dmareq;
ret = omap_request_dma(chdat->sync_dev, dev_name, if (chdat->tx)
tusb_omap_dma_cb, channel, &chdat->ch); dev_name = "TUSB transmit";
if (ret != 0) else
goto free_dmareq; dev_name = "TUSB receive";
} else if (tusb_dma->ch == -1) { cb_data = channel;
tusb_dma->dmareq = 0; } else if (tusb_dma->dma_data.ch == -1) {
tusb_dma->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0; dma_data = &tusb_dma->dma_data;
dma_data->dmareq = 0;
dma_data->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0;
dev_name = "TUSB shared";
/* Callback data gets set later in the shared dmareq case */ /* Callback data gets set later in the shared dmareq case */
ret = omap_request_dma(tusb_dma->sync_dev, "TUSB shared", cb_data = NULL;
tusb_omap_dma_cb, NULL, &tusb_dma->ch);
chdat->dma_data.dmareq = -1;
chdat->dma_data.ch = -1;
chdat->dma_data.sync_dev = -1;
}
if (dma_data) {
ret = omap_request_dma(dma_data->sync_dev, dev_name,
tusb_omap_dma_cb, cb_data,
&dma_data->ch);
if (ret != 0) if (ret != 0)
goto free_dmareq; goto free_dmareq;
} else {
chdat->dmareq = -1; /* Already allocated shared, single DMA channel. */
chdat->ch = -1; dma_data = &tusb_dma->dma_data;
} }
dev_dbg(musb->controller, "ep%i %s dma: %s dma%i dmareq%i sync%i\n", dev_dbg(musb->controller, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
chdat->epnum, chdat->epnum,
chdat->tx ? "tx" : "rx", chdat->tx ? "tx" : "rx",
chdat->ch >= 0 ? "dedicated" : "shared", chdat->dma_data.ch >= 0 ? "dedicated" : "shared",
chdat->ch >= 0 ? chdat->ch : tusb_dma->ch, dma_data->ch, dma_data->dmareq, dma_data->sync_dev);
chdat->dmareq >= 0 ? chdat->dmareq : tusb_dma->dmareq,
chdat->sync_dev >= 0 ? chdat->sync_dev : tusb_dma->sync_dev);
return channel; return channel;
...@@ -598,7 +603,8 @@ static void tusb_omap_dma_release(struct dma_channel *channel) ...@@ -598,7 +603,8 @@ static void tusb_omap_dma_release(struct dma_channel *channel)
void __iomem *tbase = musb->ctrl_base; void __iomem *tbase = musb->ctrl_base;
u32 reg; u32 reg;
dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum, chdat->ch); dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
chdat->dma_data.ch);
reg = musb_readl(tbase, TUSB_DMA_INT_MASK); reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
if (chdat->tx) if (chdat->tx)
...@@ -616,13 +622,13 @@ static void tusb_omap_dma_release(struct dma_channel *channel) ...@@ -616,13 +622,13 @@ static void tusb_omap_dma_release(struct dma_channel *channel)
channel->status = MUSB_DMA_STATUS_UNKNOWN; channel->status = MUSB_DMA_STATUS_UNKNOWN;
if (chdat->ch >= 0) { if (chdat->dma_data.ch >= 0) {
omap_stop_dma(chdat->ch); omap_stop_dma(chdat->dma_data.ch);
omap_free_dma(chdat->ch); omap_free_dma(chdat->dma_data.ch);
chdat->ch = -1; chdat->dma_data.ch = -1;
} }
if (chdat->dmareq >= 0) if (chdat->dma_data.dmareq >= 0)
tusb_omap_dma_free_dmareq(chdat); tusb_omap_dma_free_dmareq(chdat);
channel = NULL; channel = NULL;
...@@ -642,8 +648,8 @@ void tusb_dma_controller_destroy(struct dma_controller *c) ...@@ -642,8 +648,8 @@ void tusb_dma_controller_destroy(struct dma_controller *c)
} }
} }
if (tusb_dma && !tusb_dma->multichannel && tusb_dma->ch >= 0) if (tusb_dma && !tusb_dma->multichannel && tusb_dma->dma_data.ch >= 0)
omap_free_dma(tusb_dma->ch); omap_free_dma(tusb_dma->dma_data.ch);
kfree(tusb_dma); kfree(tusb_dma);
} }
...@@ -673,9 +679,9 @@ tusb_dma_controller_create(struct musb *musb, void __iomem *base) ...@@ -673,9 +679,9 @@ tusb_dma_controller_create(struct musb *musb, void __iomem *base)
tusb_dma->controller.musb = musb; tusb_dma->controller.musb = musb;
tusb_dma->tbase = musb->ctrl_base; tusb_dma->tbase = musb->ctrl_base;
tusb_dma->ch = -1; tusb_dma->dma_data.ch = -1;
tusb_dma->dmareq = -1; tusb_dma->dma_data.dmareq = -1;
tusb_dma->sync_dev = -1; tusb_dma->dma_data.sync_dev = -1;
tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate; tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
tusb_dma->controller.channel_release = tusb_omap_dma_release; tusb_dma->controller.channel_release = tusb_omap_dma_release;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment