diff options
Diffstat (limited to 'arch/sh/drivers/dma')
-rw-r--r-- | arch/sh/drivers/dma/Kconfig | 3 | ||||
-rw-r--r-- | arch/sh/drivers/dma/dma-g2.c | 54 | ||||
-rw-r--r-- | arch/sh/drivers/dma/dma-pvr2.c | 5 | ||||
-rw-r--r-- | arch/sh/drivers/dma/dma-sh.c | 19 |
4 files changed, 55 insertions, 26 deletions
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index 0f15216cd39d..defc13c37d48 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig | |||
@@ -11,6 +11,8 @@ config SH_DMA | |||
11 | config NR_ONCHIP_DMA_CHANNELS | 11 | config NR_ONCHIP_DMA_CHANNELS |
12 | depends on SH_DMA | 12 | depends on SH_DMA |
13 | int "Number of on-chip DMAC channels" | 13 | int "Number of on-chip DMAC channels" |
14 | default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R | ||
15 | default "12" if CPU_SUBTYPE_SH7780 | ||
14 | default "4" | 16 | default "4" |
15 | help | 17 | help |
16 | This allows you to specify the number of channels that the on-chip | 18 | This allows you to specify the number of channels that the on-chip |
@@ -52,4 +54,3 @@ config DMA_PAGE_OPS_CHANNEL | |||
52 | are dual-address capable. | 54 | are dual-address capable. |
53 | 55 | ||
54 | endmenu | 56 | endmenu |
55 | |||
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index 0f866f8789f0..9cb070924180 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * G2 bus DMA support | 4 | * G2 bus DMA support |
5 | * | 5 | * |
6 | * Copyright (C) 2003, 2004 Paul Mundt | 6 | * Copyright (C) 2003 - 2006 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | 16 | #include <asm/cacheflush.h> | |
17 | #include <asm/mach/sysasic.h> | 17 | #include <asm/mach/sysasic.h> |
18 | #include <asm/mach/dma.h> | 18 | #include <asm/mach/dma.h> |
19 | #include <asm/dma.h> | 19 | #include <asm/dma.h> |
@@ -47,17 +47,31 @@ struct g2_dma_info { | |||
47 | 47 | ||
48 | static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800; | 48 | static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800; |
49 | 49 | ||
50 | #define g2_bytes_remaining(i) \ | ||
51 | ((g2_dma->channel[i].size - \ | ||
52 | g2_dma->status[i].size) & 0x0fffffff) | ||
53 | |||
50 | static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 54 | static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
51 | { | 55 | { |
52 | /* FIXME: Do some meaningful completion work here.. */ | 56 | int i; |
53 | return IRQ_HANDLED; | ||
54 | } | ||
55 | 57 | ||
56 | static struct irqaction g2_dma_irq = { | 58 | for (i = 0; i < G2_NR_DMA_CHANNELS; i++) { |
57 | .name = "g2 DMA handler", | 59 | if (g2_dma->status[i].status & 0x20000000) { |
58 | .handler = g2_dma_interrupt, | 60 | unsigned int bytes = g2_bytes_remaining(i); |
59 | .flags = IRQF_DISABLED, | 61 | |
60 | }; | 62 | if (likely(bytes == 0)) { |
63 | struct dma_info *info = dev_id; | ||
64 | struct dma_channel *chan = info->channels + i; | ||
65 | |||
66 | wake_up(&chan->wait_queue); | ||
67 | |||
68 | return IRQ_HANDLED; | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | return IRQ_NONE; | ||
74 | } | ||
61 | 75 | ||
62 | static int g2_enable_dma(struct dma_channel *chan) | 76 | static int g2_enable_dma(struct dma_channel *chan) |
63 | { | 77 | { |
@@ -135,8 +149,14 @@ static int g2_xfer_dma(struct dma_channel *chan) | |||
135 | return 0; | 149 | return 0; |
136 | } | 150 | } |
137 | 151 | ||
152 | static int g2_get_residue(struct dma_channel *chan) | ||
153 | { | ||
154 | return g2_bytes_remaining(chan->chan); | ||
155 | } | ||
156 | |||
138 | static struct dma_ops g2_dma_ops = { | 157 | static struct dma_ops g2_dma_ops = { |
139 | .xfer = g2_xfer_dma, | 158 | .xfer = g2_xfer_dma, |
159 | .get_residue = g2_get_residue, | ||
140 | }; | 160 | }; |
141 | 161 | ||
142 | static struct dma_info g2_dma_info = { | 162 | static struct dma_info g2_dma_info = { |
@@ -148,13 +168,22 @@ static struct dma_info g2_dma_info = { | |||
148 | 168 | ||
149 | static int __init g2_dma_init(void) | 169 | static int __init g2_dma_init(void) |
150 | { | 170 | { |
151 | setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq); | 171 | int ret; |
172 | |||
173 | ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED, | ||
174 | "g2 DMA handler", &g2_dma_info); | ||
175 | if (unlikely(ret)) | ||
176 | return -EINVAL; | ||
152 | 177 | ||
153 | /* Magic */ | 178 | /* Magic */ |
154 | g2_dma->wait_state = 27; | 179 | g2_dma->wait_state = 27; |
155 | g2_dma->magic = 0x4659404f; | 180 | g2_dma->magic = 0x4659404f; |
156 | 181 | ||
157 | return register_dmac(&g2_dma_info); | 182 | ret = register_dmac(&g2_dma_info); |
183 | if (unlikely(ret != 0)) | ||
184 | free_irq(HW_EVENT_G2_DMA, 0); | ||
185 | |||
186 | return ret; | ||
158 | } | 187 | } |
159 | 188 | ||
160 | static void __exit g2_dma_exit(void) | 189 | static void __exit g2_dma_exit(void) |
@@ -169,4 +198,3 @@ module_exit(g2_dma_exit); | |||
169 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | 198 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); |
170 | MODULE_DESCRIPTION("G2 bus DMA driver"); | 199 | MODULE_DESCRIPTION("G2 bus DMA driver"); |
171 | MODULE_LICENSE("GPL"); | 200 | MODULE_LICENSE("GPL"); |
172 | |||
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index 30a580aa7cbd..3b0b0f60bb3c 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <asm/dma.h> | 18 | #include <asm/dma.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | 20 | ||
21 | static unsigned int xfer_complete = 0; | 21 | static unsigned int xfer_complete; |
22 | static int count = 0; | 22 | static int count; |
23 | 23 | ||
24 | static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 24 | static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
25 | { | 25 | { |
@@ -107,4 +107,3 @@ module_exit(pvr2_dma_exit); | |||
107 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | 107 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); |
108 | MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); | 108 | MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); |
109 | MODULE_LICENSE("GPL"); | 109 | MODULE_LICENSE("GPL"); |
110 | |||
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index e028a2d2a4ea..cbbe8bce3d67 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c | |||
@@ -11,14 +11,10 @@ | |||
11 | * License. See the file "COPYING" in the main directory of this archive | 11 | * License. See the file "COPYING" in the main directory of this archive |
12 | * for more details. | 12 | * for more details. |
13 | */ | 13 | */ |
14 | |||
15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
16 | #include <linux/irq.h> | ||
17 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
18 | #include <linux/module.h> | 16 | #include <linux/module.h> |
19 | #include <asm/dreamcast/dma.h> | 17 | #include <asm/dreamcast/dma.h> |
20 | #include <asm/signal.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/dma.h> | 18 | #include <asm/dma.h> |
23 | #include <asm/io.h> | 19 | #include <asm/io.h> |
24 | #include "dma-sh.h" | 20 | #include "dma-sh.h" |
@@ -84,18 +80,23 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) | |||
84 | 80 | ||
85 | static int sh_dmac_request_dma(struct dma_channel *chan) | 81 | static int sh_dmac_request_dma(struct dma_channel *chan) |
86 | { | 82 | { |
87 | char name[32]; | 83 | if (unlikely(!chan->flags & DMA_TEI_CAPABLE)) |
84 | return 0; | ||
88 | 85 | ||
89 | snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", | 86 | chan->name = kzalloc(32, GFP_KERNEL); |
87 | if (unlikely(chan->name == NULL)) | ||
88 | return -ENOMEM; | ||
89 | snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)", | ||
90 | chan->chan); | 90 | chan->chan); |
91 | 91 | ||
92 | return request_irq(get_dmte_irq(chan->chan), dma_tei, | 92 | return request_irq(get_dmte_irq(chan->chan), dma_tei, |
93 | IRQF_DISABLED, name, chan); | 93 | IRQF_DISABLED, chan->name, chan); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void sh_dmac_free_dma(struct dma_channel *chan) | 96 | static void sh_dmac_free_dma(struct dma_channel *chan) |
97 | { | 97 | { |
98 | free_irq(get_dmte_irq(chan->chan), chan); | 98 | free_irq(get_dmte_irq(chan->chan), chan); |
99 | kfree(chan->name); | ||
99 | } | 100 | } |
100 | 101 | ||
101 | static void | 102 | static void |
@@ -259,7 +260,7 @@ static int __init sh_dmac_init(void) | |||
259 | #ifdef CONFIG_CPU_SH4 | 260 | #ifdef CONFIG_CPU_SH4 |
260 | make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); | 261 | make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); |
261 | i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); | 262 | i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); |
262 | if (i < 0) | 263 | if (unlikely(i < 0)) |
263 | return i; | 264 | return i; |
264 | #endif | 265 | #endif |
265 | 266 | ||
@@ -274,7 +275,7 @@ static int __init sh_dmac_init(void) | |||
274 | * been set. | 275 | * been set. |
275 | */ | 276 | */ |
276 | i = dmaor_reset(); | 277 | i = dmaor_reset(); |
277 | if (i < 0) | 278 | if (unlikely(i != 0)) |
278 | return i; | 279 | return i; |
279 | 280 | ||
280 | return register_dmac(info); | 281 | return register_dmac(info); |