Commit db9fd0a8 authored by Paul Mundt's avatar Paul Mundt Committed by Linus Torvalds

[PATCH] sh: DMA API updates

This updates some of the sh DMA drivers and core API.  Previously modules had
to register for the channels they were interested in, but now it's dealt with
transparently by the API with only the number of physical channels needing to
be specified by each module.
Signed-off-by: default avatarPaul Mundt <paul.mundt@nokia.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ef43cf88
......@@ -211,8 +211,9 @@ int __init register_dmac(struct dma_info *info)
INIT_LIST_HEAD(&info->list);
printk(KERN_INFO "DMA: Registering %s handler (%d channels).\n",
info->name, info->nr_channels);
printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n",
info->name, info->nr_channels,
info->nr_channels > 1 ? "s" : "");
BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
......@@ -282,7 +283,6 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(request_dma);
EXPORT_SYMBOL(free_dma);
EXPORT_SYMBOL(register_dmac);
EXPORT_SYMBOL(unregister_dmac);
EXPORT_SYMBOL(get_dma_residue);
EXPORT_SYMBOL(get_dma_info);
EXPORT_SYMBOL(get_dma_channel);
......
......@@ -3,7 +3,7 @@
*
* G2 bus DMA support
*
* Copyright (C) 2003 Paul Mundt
* Copyright (C) 2003, 2004 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
......@@ -59,104 +59,102 @@ static struct irqaction g2_dma_irq = {
.flags = SA_INTERRUPT,
};
static int g2_enable_dma(struct dma_info *info)
static int g2_enable_dma(struct dma_channel *chan)
{
unsigned int chan = info->chan;
unsigned int chan_nr = chan->chan;
g2_dma->channel[chan].chan_enable = 1;
g2_dma->channel[chan].xfer_enable = 1;
g2_dma->channel[chan_nr].chan_enable = 1;
g2_dma->channel[chan_nr].xfer_enable = 1;
return 0;
}
static int g2_disable_dma(struct dma_info *info)
static int g2_disable_dma(struct dma_channel *chan)
{
unsigned int chan = info->chan;
unsigned int chan_nr = chan->chan;
g2_dma->channel[chan].chan_enable = 0;
g2_dma->channel[chan].xfer_enable = 0;
g2_dma->channel[chan_nr].chan_enable = 0;
g2_dma->channel[chan_nr].xfer_enable = 0;
return 0;
}
static int g2_xfer_dma(struct dma_info *info)
static int g2_xfer_dma(struct dma_channel *chan)
{
unsigned int chan = info->chan;
unsigned int chan_nr = chan->chan;
if (info->sar & 31) {
printk("g2dma: unaligned source 0x%lx\n", info->sar);
if (chan->sar & 31) {
printk("g2dma: unaligned source 0x%lx\n", chan->sar);
return -EINVAL;
}
if (info->dar & 31) {
printk("g2dma: unaligned dest 0x%lx\n", info->dar);
if (chan->dar & 31) {
printk("g2dma: unaligned dest 0x%lx\n", chan->dar);
return -EINVAL;
}
/* Align the count */
if (info->count & 31)
info->count = (info->count + (32 - 1)) & ~(32 - 1);
if (chan->count & 31)
chan->count = (chan->count + (32 - 1)) & ~(32 - 1);
/* Fixup destination */
info->dar += 0xa0800000;
chan->dar += 0xa0800000;
/* Fixup direction */
info->mode = !info->mode;
chan->mode = !chan->mode;
flush_icache_range((unsigned long)info->sar, info->count);
flush_icache_range((unsigned long)chan->sar, chan->count);
g2_disable_dma(info);
g2_disable_dma(chan);
g2_dma->channel[chan].g2_addr = info->dar & 0x1fffffe0;
g2_dma->channel[chan].root_addr = info->sar & 0x1fffffe0;
g2_dma->channel[chan].size = (info->count & ~31) | 0x80000000;
g2_dma->channel[chan].direction = info->mode;
g2_dma->channel[chan_nr].g2_addr = chan->dar & 0x1fffffe0;
g2_dma->channel[chan_nr].root_addr = chan->sar & 0x1fffffe0;
g2_dma->channel[chan_nr].size = (chan->count & ~31) | 0x80000000;
g2_dma->channel[chan_nr].direction = chan->mode;
/*
* bit 0 - ???
* bit 1 - if set, generate a hardware event on transfer completion
* bit 2 - ??? something to do with suspend?
*/
g2_dma->channel[chan].ctrl = 5; /* ?? */
g2_dma->channel[chan_nr].ctrl = 5; /* ?? */
g2_enable_dma(info);
g2_enable_dma(chan);
/* debug cruft */
pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, "
"0x%08lx, %ld, %ld, %ld, %ld\n",
g2_dma->channel[chan].size,
g2_dma->channel[chan].root_addr,
g2_dma->channel[chan].g2_addr,
g2_dma->channel[chan].direction,
g2_dma->channel[chan].ctrl,
g2_dma->channel[chan].chan_enable,
g2_dma->channel[chan].xfer_enable);
g2_dma->channel[chan_nr].size,
g2_dma->channel[chan_nr].root_addr,
g2_dma->channel[chan_nr].g2_addr,
g2_dma->channel[chan_nr].direction,
g2_dma->channel[chan_nr].ctrl,
g2_dma->channel[chan_nr].chan_enable,
g2_dma->channel[chan_nr].xfer_enable);
return 0;
}
static struct dma_ops g2_dma_ops = {
.name = "G2 DMA",
.xfer = g2_xfer_dma,
};
static struct dma_info g2_dma_info = {
.name = "G2 DMA",
.nr_channels = 4,
.ops = &g2_dma_ops,
.flags = DMAC_CHANNELS_TEI_CAPABLE,
};
static int __init g2_dma_init(void)
{
int i, base;
setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq);
/* Magic */
g2_dma->wait_state = 27;
g2_dma->magic = 0x4659404f;
/* G2 channels come after on-chip and pvr2 */
base = ONCHIP_NR_DMA_CHANNELS + PVR2_NR_DMA_CHANNELS;
for (i = 0; i < G2_NR_DMA_CHANNELS; i++)
dma_info[base + i].ops = &g2_dma_ops;
return register_dmac(&g2_dma_ops);
return register_dmac(&g2_dma_info);
}
static void __exit g2_dma_exit(void)
......
......@@ -3,7 +3,7 @@
*
* NEC PowerVR 2 (Dreamcast) DMA support
*
* Copyright (C) 2003 Paul Mundt
* Copyright (C) 2003, 2004 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
......@@ -38,7 +38,7 @@ static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *reg
return IRQ_HANDLED;
}
static int pvr2_request_dma(struct dma_info *info)
static int pvr2_request_dma(struct dma_channel *chan)
{
if (ctrl_inl(PVR2_DMA_MODE) != 0)
return -EBUSY;
......@@ -48,21 +48,21 @@ static int pvr2_request_dma(struct dma_info *info)
return 0;
}
static int pvr2_get_dma_residue(struct dma_info *info)
static int pvr2_get_dma_residue(struct dma_channel *chan)
{
return xfer_complete == 0;
}
static int pvr2_xfer_dma(struct dma_info *info)
static int pvr2_xfer_dma(struct dma_channel *chan)
{
if (info->sar || !info->dar)
if (chan->sar || !chan->dar)
return -EINVAL;
xfer_complete = 0;
ctrl_outl(info->dar, PVR2_DMA_ADDR);
ctrl_outl(info->count, PVR2_DMA_COUNT);
ctrl_outl(info->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
ctrl_outl(chan->dar, PVR2_DMA_ADDR);
ctrl_outl(chan->count, PVR2_DMA_COUNT);
ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
return 0;
}
......@@ -74,26 +74,24 @@ static struct irqaction pvr2_dma_irq = {
};
static struct dma_ops pvr2_dma_ops = {
.name = "PowerVR 2 DMA",
.request = pvr2_request_dma,
.get_residue = pvr2_get_dma_residue,
.xfer = pvr2_xfer_dma,
};
static struct dma_info pvr2_dma_info = {
.name = "PowerVR 2 DMA",
.nr_channels = 1,
.ops = &pvr2_dma_ops,
.flags = DMAC_CHANNELS_TEI_CAPABLE,
};
static int __init pvr2_dma_init(void)
{
int i, base;
setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq);
request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade");
/* PVR2 cascade comes after on-chip DMAC */
base = ONCHIP_NR_DMA_CHANNELS;
for (i = 0; i < PVR2_NR_DMA_CHANNELS; i++)
dma_info[base + i].ops = &pvr2_dma_ops;
return register_dmac(&pvr2_dma_ops);
return register_dmac(&pvr2_dma_info);
}
static void __exit pvr2_dma_exit(void)
......
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