aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/drivers/dma
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 08:49:07 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 08:49:07 -0700
commitb98adfccdf5f8dd34ae56a2d5adbe2c030bd4674 (patch)
tree1807a029520f550dd4f90c95ad0063bceb00d645 /arch/sh/drivers/dma
parentba21fe71725f94792330ebc3034ef2b35a36276f (diff)
parent33573c0e3243aaa38b6ad96942de85a1b713c2ff (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: (108 commits) sh: Fix occasional flush_cache_4096() stack corruption. sh: Calculate shm alignment at runtime. sh: dma-mapping compile fixes. sh: Initial vsyscall page support. sh: Clean up PAGE_SIZE definition for assembly use. sh: Selective flush_cache_mm() flushing. sh: More intelligent entry_mask/way_size calculation. sh: Support for L2 cache on newer SH-4A CPUs. sh: Update kexec support for API changes. sh: Optimized readsl()/writesl() support. sh: Report movli.l/movco.l capabilities. sh: CPU flags in AT_HWCAP in ELF auxvt. sh: Add support for 4K stacks. sh: Enable /proc/kcore support. sh: stack debugging support. sh: select CONFIG_EMBEDDED. sh: machvec rework. sh: Solution Engine SH7343 board support. sh: SH7710VoIPGW board support. sh: Enable verbose BUG() support. ...
Diffstat (limited to 'arch/sh/drivers/dma')
-rw-r--r--arch/sh/drivers/dma/Kconfig3
-rw-r--r--arch/sh/drivers/dma/dma-g2.c54
-rw-r--r--arch/sh/drivers/dma/dma-pvr2.c5
-rw-r--r--arch/sh/drivers/dma/dma-sh.c19
4 files changed, 55 insertions, 26 deletions
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index 0f15216cd39..defc13c37d4 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -11,6 +11,8 @@ config SH_DMA
config NR_ONCHIP_DMA_CHANNELS
depends on SH_DMA
int "Number of on-chip DMAC channels"
+ default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
+ default "12" if CPU_SUBTYPE_SH7780
default "4"
help
This allows you to specify the number of channels that the on-chip
@@ -52,4 +54,3 @@ config DMA_PAGE_OPS_CHANNEL
are dual-address capable.
endmenu
-
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
index 0f866f8789f..9cb07092418 100644
--- a/arch/sh/drivers/dma/dma-g2.c
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -3,7 +3,7 @@
*
* G2 bus DMA support
*
- * Copyright (C) 2003, 2004 Paul Mundt
+ * Copyright (C) 2003 - 2006 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
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
-
+#include <asm/cacheflush.h>
#include <asm/mach/sysasic.h>
#include <asm/mach/dma.h>
#include <asm/dma.h>
@@ -47,17 +47,31 @@ struct g2_dma_info {
static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800;
+#define g2_bytes_remaining(i) \
+ ((g2_dma->channel[i].size - \
+ g2_dma->status[i].size) & 0x0fffffff)
+
static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- /* FIXME: Do some meaningful completion work here.. */
- return IRQ_HANDLED;
-}
+ int i;
-static struct irqaction g2_dma_irq = {
- .name = "g2 DMA handler",
- .handler = g2_dma_interrupt,
- .flags = IRQF_DISABLED,
-};
+ for (i = 0; i < G2_NR_DMA_CHANNELS; i++) {
+ if (g2_dma->status[i].status & 0x20000000) {
+ unsigned int bytes = g2_bytes_remaining(i);
+
+ if (likely(bytes == 0)) {
+ struct dma_info *info = dev_id;
+ struct dma_channel *chan = info->channels + i;
+
+ wake_up(&chan->wait_queue);
+
+ return IRQ_HANDLED;
+ }
+ }
+ }
+
+ return IRQ_NONE;
+}
static int g2_enable_dma(struct dma_channel *chan)
{
@@ -135,8 +149,14 @@ static int g2_xfer_dma(struct dma_channel *chan)
return 0;
}
+static int g2_get_residue(struct dma_channel *chan)
+{
+ return g2_bytes_remaining(chan->chan);
+}
+
static struct dma_ops g2_dma_ops = {
.xfer = g2_xfer_dma,
+ .get_residue = g2_get_residue,
};
static struct dma_info g2_dma_info = {
@@ -148,13 +168,22 @@ static struct dma_info g2_dma_info = {
static int __init g2_dma_init(void)
{
- setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq);
+ int ret;
+
+ ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+ "g2 DMA handler", &g2_dma_info);
+ if (unlikely(ret))
+ return -EINVAL;
/* Magic */
g2_dma->wait_state = 27;
g2_dma->magic = 0x4659404f;
- return register_dmac(&g2_dma_info);
+ ret = register_dmac(&g2_dma_info);
+ if (unlikely(ret != 0))
+ free_irq(HW_EVENT_G2_DMA, 0);
+
+ return ret;
}
static void __exit g2_dma_exit(void)
@@ -169,4 +198,3 @@ module_exit(g2_dma_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("G2 bus DMA driver");
MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index 30a580aa7cb..3b0b0f60bb3 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -18,8 +18,8 @@
#include <asm/dma.h>
#include <asm/io.h>
-static unsigned int xfer_complete = 0;
-static int count = 0;
+static unsigned int xfer_complete;
+static int count;
static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -107,4 +107,3 @@ module_exit(pvr2_dma_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index e028a2d2a4e..cbbe8bce3d6 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -11,14 +11,10 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-
#include <linux/init.h>
-#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/dreamcast/dma.h>
-#include <asm/signal.h>
-#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/io.h>
#include "dma-sh.h"
@@ -84,18 +80,23 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
static int sh_dmac_request_dma(struct dma_channel *chan)
{
- char name[32];
+ if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
+ return 0;
- snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)",
+ chan->name = kzalloc(32, GFP_KERNEL);
+ if (unlikely(chan->name == NULL))
+ return -ENOMEM;
+ snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)",
chan->chan);
return request_irq(get_dmte_irq(chan->chan), dma_tei,
- IRQF_DISABLED, name, chan);
+ IRQF_DISABLED, chan->name, chan);
}
static void sh_dmac_free_dma(struct dma_channel *chan)
{
free_irq(get_dmte_irq(chan->chan), chan);
+ kfree(chan->name);
}
static void
@@ -259,7 +260,7 @@ static int __init sh_dmac_init(void)
#ifdef CONFIG_CPU_SH4
make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
- if (i < 0)
+ if (unlikely(i < 0))
return i;
#endif
@@ -274,7 +275,7 @@ static int __init sh_dmac_init(void)
* been set.
*/
i = dmaor_reset();
- if (i < 0)
+ if (unlikely(i != 0))
return i;
return register_dmac(info);