aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers/dma/dma-api.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/drivers/dma/dma-api.c')
-rw-r--r--arch/sh/drivers/dma/dma-api.c51
1 files changed, 37 insertions, 14 deletions
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index 96e3036ec2bb..47c3e837599b 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * SuperH-specific DMA management API 4 * SuperH-specific DMA management API
5 * 5 *
6 * Copyright (C) 2003, 2004 Paul Mundt 6 * Copyright (C) 2003, 2004, 2005 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
@@ -15,6 +15,7 @@
15#include <linux/spinlock.h> 15#include <linux/spinlock.h>
16#include <linux/proc_fs.h> 16#include <linux/proc_fs.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/platform_device.h>
18#include <asm/dma.h> 19#include <asm/dma.h>
19 20
20DEFINE_SPINLOCK(dma_spin_lock); 21DEFINE_SPINLOCK(dma_spin_lock);
@@ -55,16 +56,14 @@ static LIST_HEAD(registered_dmac_list);
55 56
56struct dma_info *get_dma_info(unsigned int chan) 57struct dma_info *get_dma_info(unsigned int chan)
57{ 58{
58 struct list_head *pos, *tmp; 59 struct dma_info *info;
59 unsigned int total = 0; 60 unsigned int total = 0;
60 61
61 /* 62 /*
62 * Look for each DMAC's range to determine who the owner of 63 * Look for each DMAC's range to determine who the owner of
63 * the channel is. 64 * the channel is.
64 */ 65 */
65 list_for_each_safe(pos, tmp, &registered_dmac_list) { 66 list_for_each_entry(info, &registered_dmac_list, list) {
66 struct dma_info *info = list_entry(pos, struct dma_info, list);
67
68 total += info->nr_channels; 67 total += info->nr_channels;
69 if (chan > total) 68 if (chan > total)
70 continue; 69 continue;
@@ -75,6 +74,20 @@ struct dma_info *get_dma_info(unsigned int chan)
75 return NULL; 74 return NULL;
76} 75}
77 76
77static unsigned int get_nr_channels(void)
78{
79 struct dma_info *info;
80 unsigned int nr = 0;
81
82 if (unlikely(list_empty(&registered_dmac_list)))
83 return nr;
84
85 list_for_each_entry(info, &registered_dmac_list, list)
86 nr += info->nr_channels;
87
88 return nr;
89}
90
78struct dma_channel *get_dma_channel(unsigned int chan) 91struct dma_channel *get_dma_channel(unsigned int chan)
79{ 92{
80 struct dma_info *info = get_dma_info(chan); 93 struct dma_info *info = get_dma_info(chan);
@@ -173,7 +186,7 @@ int dma_xfer(unsigned int chan, unsigned long from,
173static int dma_read_proc(char *buf, char **start, off_t off, 186static int dma_read_proc(char *buf, char **start, off_t off,
174 int len, int *eof, void *data) 187 int len, int *eof, void *data)
175{ 188{
176 struct list_head *pos, *tmp; 189 struct dma_info *info;
177 char *p = buf; 190 char *p = buf;
178 191
179 if (list_empty(&registered_dmac_list)) 192 if (list_empty(&registered_dmac_list))
@@ -182,8 +195,7 @@ static int dma_read_proc(char *buf, char **start, off_t off,
182 /* 195 /*
183 * Iterate over each registered DMAC 196 * Iterate over each registered DMAC
184 */ 197 */
185 list_for_each_safe(pos, tmp, &registered_dmac_list) { 198 list_for_each_entry(info, &registered_dmac_list, list) {
186 struct dma_info *info = list_entry(pos, struct dma_info, list);
187 int i; 199 int i;
188 200
189 /* 201 /*
@@ -205,9 +217,9 @@ static int dma_read_proc(char *buf, char **start, off_t off,
205#endif 217#endif
206 218
207 219
208int __init register_dmac(struct dma_info *info) 220int register_dmac(struct dma_info *info)
209{ 221{
210 int i; 222 unsigned int total_channels, i;
211 223
212 INIT_LIST_HEAD(&info->list); 224 INIT_LIST_HEAD(&info->list);
213 225
@@ -217,6 +229,11 @@ int __init register_dmac(struct dma_info *info)
217 229
218 BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); 230 BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
219 231
232 info->pdev = platform_device_register_simple((char *)info->name, -1,
233 NULL, 0);
234 if (IS_ERR(info->pdev))
235 return PTR_ERR(info->pdev);
236
220 /* 237 /*
221 * Don't touch pre-configured channels 238 * Don't touch pre-configured channels
222 */ 239 */
@@ -232,10 +249,12 @@ int __init register_dmac(struct dma_info *info)
232 memset(info->channels, 0, size); 249 memset(info->channels, 0, size);
233 } 250 }
234 251
252 total_channels = get_nr_channels();
235 for (i = 0; i < info->nr_channels; i++) { 253 for (i = 0; i < info->nr_channels; i++) {
236 struct dma_channel *chan = info->channels + i; 254 struct dma_channel *chan = info->channels + i;
237 255
238 chan->chan = i; 256 chan->chan = i;
257 chan->vchan = i + total_channels;
239 258
240 memcpy(chan->dev_id, "Unused", 7); 259 memcpy(chan->dev_id, "Unused", 7);
241 260
@@ -245,9 +264,7 @@ int __init register_dmac(struct dma_info *info)
245 init_MUTEX(&chan->sem); 264 init_MUTEX(&chan->sem);
246 init_waitqueue_head(&chan->wait_queue); 265 init_waitqueue_head(&chan->wait_queue);
247 266
248#ifdef CONFIG_SYSFS 267 dma_create_sysfs_files(chan, info);
249 dma_create_sysfs_files(chan);
250#endif
251 } 268 }
252 269
253 list_add(&info->list, &registered_dmac_list); 270 list_add(&info->list, &registered_dmac_list);
@@ -255,12 +272,18 @@ int __init register_dmac(struct dma_info *info)
255 return 0; 272 return 0;
256} 273}
257 274
258void __exit unregister_dmac(struct dma_info *info) 275void unregister_dmac(struct dma_info *info)
259{ 276{
277 unsigned int i;
278
279 for (i = 0; i < info->nr_channels; i++)
280 dma_remove_sysfs_files(info->channels + i, info);
281
260 if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) 282 if (!(info->flags & DMAC_CHANNELS_CONFIGURED))
261 kfree(info->channels); 283 kfree(info->channels);
262 284
263 list_del(&info->list); 285 list_del(&info->list);
286 platform_device_unregister(info->pdev);
264} 287}
265 288
266static int __init dma_api_init(void) 289static int __init dma_api_init(void)