aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-12-08 12:35:48 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-12-11 09:35:57 -0500
commitad9dd94c384f7ee37b798a9349b8c42da8fa99ab (patch)
tree940d4905c17c52ca7c19bee34a79a60d0d02e72c /arch/arm
parent2f757f2ab7411cf0e2779012d8cda0cbf2f80d26 (diff)
[ARM] dma: move RiscPC specific DMA data out of dma_struct
Separate the RiscPC specific (IOMD and floppy FIQ) data out of the core DMA structure by making the IOMD and floppy DMA supersets. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/include/asm/mach/dma.h18
-rw-r--r--arch/arm/mach-rpc/dma.c146
2 files changed, 91 insertions, 73 deletions
diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h
index 38a3693f1258..4326738ff36f 100644
--- a/arch/arm/include/asm/mach/dma.h
+++ b/arch/arm/include/asm/mach/dma.h
@@ -40,14 +40,22 @@ struct dma_struct {
40 unsigned int lock; /* Device is allocated */ 40 unsigned int lock; /* Device is allocated */
41 const char *device_id; /* Device name */ 41 const char *device_id; /* Device name */
42 42
43 unsigned int dma_base; /* Controller base address */
44 int dma_irq; /* Controller IRQ */
45 struct scatterlist cur_sg; /* Current controller buffer */
46 unsigned int state;
47
48 struct dma_ops *d_ops; 43 struct dma_ops *d_ops;
49}; 44};
50 45
46struct floppy_dma {
47 struct dma_struct dma;
48 unsigned int fiq;
49};
50
51struct iomd_dma {
52 struct dma_struct dma;
53 unsigned int state;
54 unsigned long base; /* Controller base address */
55 int irq; /* Controller IRQ */
56 struct scatterlist cur_sg; /* Current controller buffer */
57};
58
51/* 59/*
52 * isa_dma_add - add an ISA-style DMA channel 60 * isa_dma_add - add an ISA-style DMA channel
53 */ 61 */
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index efcf6718d1d0..0163592b2af0 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -44,15 +44,15 @@ typedef enum {
44#define CR (IOMD_IO0CR - IOMD_IO0CURA) 44#define CR (IOMD_IO0CR - IOMD_IO0CURA)
45#define ST (IOMD_IO0ST - IOMD_IO0CURA) 45#define ST (IOMD_IO0ST - IOMD_IO0CURA)
46 46
47static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) 47static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
48{ 48{
49 unsigned long end, offset, flags = 0; 49 unsigned long end, offset, flags = 0;
50 50
51 if (dma->sg) { 51 if (idma->dma.sg) {
52 sg->dma_address = dma->sg->dma_address; 52 sg->dma_address = idma->dma.sg->dma_address;
53 offset = sg->dma_address & ~PAGE_MASK; 53 offset = sg->dma_address & ~PAGE_MASK;
54 54
55 end = offset + dma->sg->length; 55 end = offset + idma->dma.sg->length;
56 56
57 if (end > PAGE_SIZE) 57 if (end > PAGE_SIZE)
58 end = PAGE_SIZE; 58 end = PAGE_SIZE;
@@ -62,15 +62,15 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
62 62
63 sg->length = end - TRANSFER_SIZE; 63 sg->length = end - TRANSFER_SIZE;
64 64
65 dma->sg->length -= end - offset; 65 idma->dma.sg->length -= end - offset;
66 dma->sg->dma_address += end - offset; 66 idma->dma.sg->dma_address += end - offset;
67 67
68 if (dma->sg->length == 0) { 68 if (idma->dma.sg->length == 0) {
69 if (dma->sgcount > 1) { 69 if (idma->dma.sgcount > 1) {
70 dma->sg++; 70 idma->dma.sg++;
71 dma->sgcount--; 71 idma->dma.sgcount--;
72 } else { 72 } else {
73 dma->sg = NULL; 73 idma->dma.sg = NULL;
74 flags |= DMA_END_S; 74 flags |= DMA_END_S;
75 } 75 }
76 } 76 }
@@ -85,8 +85,8 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
85 85
86static irqreturn_t iomd_dma_handle(int irq, void *dev_id) 86static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
87{ 87{
88 dma_t *dma = (dma_t *)dev_id; 88 struct iomd_dma *idma = dev_id;
89 unsigned long base = dma->dma_base; 89 unsigned long base = idma->base;
90 90
91 do { 91 do {
92 unsigned int status; 92 unsigned int status;
@@ -95,31 +95,31 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
95 if (!(status & DMA_ST_INT)) 95 if (!(status & DMA_ST_INT))
96 return IRQ_HANDLED; 96 return IRQ_HANDLED;
97 97
98 if ((dma->state ^ status) & DMA_ST_AB) 98 if ((idma->state ^ status) & DMA_ST_AB)
99 iomd_get_next_sg(&dma->cur_sg, dma); 99 iomd_get_next_sg(&idma->cur_sg, idma);
100 100
101 switch (status & (DMA_ST_OFL | DMA_ST_AB)) { 101 switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
102 case DMA_ST_OFL: /* OIA */ 102 case DMA_ST_OFL: /* OIA */
103 case DMA_ST_AB: /* .IB */ 103 case DMA_ST_AB: /* .IB */
104 iomd_writel(dma->cur_sg.dma_address, base + CURA); 104 iomd_writel(idma->cur_sg.dma_address, base + CURA);
105 iomd_writel(dma->cur_sg.length, base + ENDA); 105 iomd_writel(idma->cur_sg.length, base + ENDA);
106 dma->state = DMA_ST_AB; 106 idma->state = DMA_ST_AB;
107 break; 107 break;
108 108
109 case DMA_ST_OFL | DMA_ST_AB: /* OIB */ 109 case DMA_ST_OFL | DMA_ST_AB: /* OIB */
110 case 0: /* .IA */ 110 case 0: /* .IA */
111 iomd_writel(dma->cur_sg.dma_address, base + CURB); 111 iomd_writel(idma->cur_sg.dma_address, base + CURB);
112 iomd_writel(dma->cur_sg.length, base + ENDB); 112 iomd_writel(idma->cur_sg.length, base + ENDB);
113 dma->state = 0; 113 idma->state = 0;
114 break; 114 break;
115 } 115 }
116 116
117 if (status & DMA_ST_OFL && 117 if (status & DMA_ST_OFL &&
118 dma->cur_sg.length == (DMA_END_S|DMA_END_L)) 118 idma->cur_sg.length == (DMA_END_S|DMA_END_L))
119 break; 119 break;
120 } while (1); 120 } while (1);
121 121
122 dma->state = ~DMA_ST_AB; 122 idma->state = ~DMA_ST_AB;
123 disable_irq(irq); 123 disable_irq(irq);
124 124
125 return IRQ_HANDLED; 125 return IRQ_HANDLED;
@@ -127,56 +127,62 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
127 127
128static int iomd_request_dma(unsigned int chan, dma_t *dma) 128static int iomd_request_dma(unsigned int chan, dma_t *dma)
129{ 129{
130 return request_irq(dma->dma_irq, iomd_dma_handle, 130 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
131 IRQF_DISABLED, dma->device_id, dma); 131
132 return request_irq(idma->irq, iomd_dma_handle,
133 IRQF_DISABLED, idma->dma.device_id, idma);
132} 134}
133 135
134static void iomd_free_dma(unsigned int chan, dma_t *dma) 136static void iomd_free_dma(unsigned int chan, dma_t *dma)
135{ 137{
136 free_irq(dma->dma_irq, dma); 138 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
139
140 free_irq(idma->irq, idma);
137} 141}
138 142
139static void iomd_enable_dma(unsigned int chan, dma_t *dma) 143static void iomd_enable_dma(unsigned int chan, dma_t *dma)
140{ 144{
141 unsigned long dma_base = dma->dma_base; 145 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
146 unsigned long dma_base = idma->base;
142 unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; 147 unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
143 148
144 if (dma->invalid) { 149 if (idma->dma.invalid) {
145 dma->invalid = 0; 150 idma->dma.invalid = 0;
146 151
147 /* 152 /*
148 * Cope with ISA-style drivers which expect cache 153 * Cope with ISA-style drivers which expect cache
149 * coherence. 154 * coherence.
150 */ 155 */
151 if (!dma->sg) { 156 if (!idma->dma.sg) {
152 dma->sg = &dma->buf; 157 idma->dma.sg = &idma->dma.buf;
153 dma->sgcount = 1; 158 idma->dma.sgcount = 1;
154 dma->buf.length = dma->count; 159 idma->dma.buf.length = idma->dma.count;
155 dma->buf.dma_address = dma_map_single(NULL, 160 idma->dma.buf.dma_address = dma_map_single(NULL,
156 dma->addr, dma->count, 161 idma->dma.addr, idma->dma.count,
157 dma->dma_mode == DMA_MODE_READ ? 162 idma->dma.dma_mode == DMA_MODE_READ ?
158 DMA_FROM_DEVICE : DMA_TO_DEVICE); 163 DMA_FROM_DEVICE : DMA_TO_DEVICE);
159 } 164 }
160 165
161 iomd_writeb(DMA_CR_C, dma_base + CR); 166 iomd_writeb(DMA_CR_C, dma_base + CR);
162 dma->state = DMA_ST_AB; 167 idma->state = DMA_ST_AB;
163 } 168 }
164 169
165 if (dma->dma_mode == DMA_MODE_READ) 170 if (idma->dma.dma_mode == DMA_MODE_READ)
166 ctrl |= DMA_CR_D; 171 ctrl |= DMA_CR_D;
167 172
168 iomd_writeb(ctrl, dma_base + CR); 173 iomd_writeb(ctrl, dma_base + CR);
169 enable_irq(dma->dma_irq); 174 enable_irq(idma->irq);
170} 175}
171 176
172static void iomd_disable_dma(unsigned int chan, dma_t *dma) 177static void iomd_disable_dma(unsigned int chan, dma_t *dma)
173{ 178{
174 unsigned long dma_base = dma->dma_base; 179 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
180 unsigned long dma_base = idma->base;
175 unsigned long flags; 181 unsigned long flags;
176 182
177 local_irq_save(flags); 183 local_irq_save(flags);
178 if (dma->state != ~DMA_ST_AB) 184 if (idma->state != ~DMA_ST_AB)
179 disable_irq(dma->dma_irq); 185 disable_irq(idma->irq);
180 iomd_writeb(0, dma_base + CR); 186 iomd_writeb(0, dma_base + CR);
181 local_irq_restore(flags); 187 local_irq_restore(flags);
182} 188}
@@ -238,14 +244,15 @@ static struct fiq_handler fh = {
238 244
239static void floppy_enable_dma(unsigned int chan, dma_t *dma) 245static void floppy_enable_dma(unsigned int chan, dma_t *dma)
240{ 246{
247 struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma);
241 void *fiqhandler_start; 248 void *fiqhandler_start;
242 unsigned int fiqhandler_length; 249 unsigned int fiqhandler_length;
243 struct pt_regs regs; 250 struct pt_regs regs;
244 251
245 if (dma->sg) 252 if (fdma->dma.sg)
246 BUG(); 253 BUG();
247 254
248 if (dma->dma_mode == DMA_MODE_READ) { 255 if (fdma->dma.dma_mode == DMA_MODE_READ) {
249 extern unsigned char floppy_fiqin_start, floppy_fiqin_end; 256 extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
250 fiqhandler_start = &floppy_fiqin_start; 257 fiqhandler_start = &floppy_fiqin_start;
251 fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; 258 fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
@@ -255,8 +262,8 @@ static void floppy_enable_dma(unsigned int chan, dma_t *dma)
255 fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; 262 fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
256 } 263 }
257 264
258 regs.ARM_r9 = dma->count; 265 regs.ARM_r9 = fdma->dma.count;
259 regs.ARM_r10 = (unsigned long)dma->addr; 266 regs.ARM_r10 = (unsigned long)fdma->dma.addr;
260 regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE; 267 regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE;
261 268
262 if (claim_fiq(&fh)) { 269 if (claim_fiq(&fh)) {
@@ -266,12 +273,13 @@ static void floppy_enable_dma(unsigned int chan, dma_t *dma)
266 273
267 set_fiq_handler(fiqhandler_start, fiqhandler_length); 274 set_fiq_handler(fiqhandler_start, fiqhandler_length);
268 set_fiq_regs(&regs); 275 set_fiq_regs(&regs);
269 enable_fiq(dma->dma_irq); 276 enable_fiq(fdma->fiq);
270} 277}
271 278
272static void floppy_disable_dma(unsigned int chan, dma_t *dma) 279static void floppy_disable_dma(unsigned int chan, dma_t *dma)
273{ 280{
274 disable_fiq(dma->dma_irq); 281 struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma);
282 disable_fiq(fdma->fiq);
275 release_fiq(&fh); 283 release_fiq(&fh);
276} 284}
277 285
@@ -302,11 +310,13 @@ static struct dma_ops sound_dma_ops = {
302 .disable = sound_enable_disable_dma, 310 .disable = sound_enable_disable_dma,
303}; 311};
304 312
305static dma_t iomd_dma[6]; 313static struct iomd_dma iomd_dma[6];
306 314
307static dma_t floppy_dma = { 315static struct floppy_dma floppy_dma = {
308 .dma_irq = FIQ_FLOPPYDATA, 316 .dma = {
309 .d_ops = &floppy_dma_ops, 317 .d_ops = &floppy_dma_ops,
318 },
319 .fiq = FIQ_FLOPPYDATA,
310}; 320};
311 321
312static dma_t sound_dma = { 322static dma_t sound_dma = {
@@ -331,28 +341,28 @@ static int __init rpc_dma_init(void)
331 */ 341 */
332 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); 342 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
333 343
334 iomd_dma[DMA_0].dma_base = IOMD_IO0CURA; 344 iomd_dma[DMA_0].base = IOMD_IO0CURA;
335 iomd_dma[DMA_0].dma_irq = IRQ_DMA0; 345 iomd_dma[DMA_0].irq = IRQ_DMA0;
336 iomd_dma[DMA_1].dma_base = IOMD_IO1CURA; 346 iomd_dma[DMA_1].base = IOMD_IO1CURA;
337 iomd_dma[DMA_1].dma_irq = IRQ_DMA1; 347 iomd_dma[DMA_1].irq = IRQ_DMA1;
338 iomd_dma[DMA_2].dma_base = IOMD_IO2CURA; 348 iomd_dma[DMA_2].base = IOMD_IO2CURA;
339 iomd_dma[DMA_2].dma_irq = IRQ_DMA2; 349 iomd_dma[DMA_2].irq = IRQ_DMA2;
340 iomd_dma[DMA_3].dma_base = IOMD_IO3CURA; 350 iomd_dma[DMA_3].base = IOMD_IO3CURA;
341 iomd_dma[DMA_3].dma_irq = IRQ_DMA3; 351 iomd_dma[DMA_3].irq = IRQ_DMA3;
342 iomd_dma[DMA_S0].dma_base = IOMD_SD0CURA; 352 iomd_dma[DMA_S0].base = IOMD_SD0CURA;
343 iomd_dma[DMA_S0].dma_irq = IRQ_DMAS0; 353 iomd_dma[DMA_S0].irq = IRQ_DMAS0;
344 iomd_dma[DMA_S1].dma_base = IOMD_SD1CURA; 354 iomd_dma[DMA_S1].base = IOMD_SD1CURA;
345 iomd_dma[DMA_S1].dma_irq = IRQ_DMAS1; 355 iomd_dma[DMA_S1].irq = IRQ_DMAS1;
346 356
347 for (i = DMA_0; i <= DMA_S1; i++) { 357 for (i = DMA_0; i <= DMA_S1; i++) {
348 iomd_dma[i].d_ops = &iomd_dma_ops; 358 iomd_dma[i].dma.d_ops = &iomd_dma_ops;
349 359
350 ret = isa_dma_add(i, &iomd_dma[i]); 360 ret = isa_dma_add(i, &iomd_dma[i].dma);
351 if (ret) 361 if (ret)
352 printk("IOMDDMA%u: unable to register: %d\n", i, ret); 362 printk("IOMDDMA%u: unable to register: %d\n", i, ret);
353 } 363 }
354 364
355 ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma); 365 ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma.dma);
356 if (ret) 366 if (ret)
357 printk("IOMDFLOPPY: unable to register: %d\n", ret); 367 printk("IOMDFLOPPY: unable to register: %d\n", ret);
358 ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma); 368 ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma);