diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-12-08 12:35:48 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-12-11 09:35:57 -0500 |
commit | ad9dd94c384f7ee37b798a9349b8c42da8fa99ab (patch) | |
tree | 940d4905c17c52ca7c19bee34a79a60d0d02e72c /arch/arm | |
parent | 2f757f2ab7411cf0e2779012d8cda0cbf2f80d26 (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.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-rpc/dma.c | 146 |
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 | ||
46 | struct floppy_dma { | ||
47 | struct dma_struct dma; | ||
48 | unsigned int fiq; | ||
49 | }; | ||
50 | |||
51 | struct 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 | ||
47 | static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) | 47 | static 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 | ||
86 | static irqreturn_t iomd_dma_handle(int irq, void *dev_id) | 86 | static 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 | ||
128 | static int iomd_request_dma(unsigned int chan, dma_t *dma) | 128 | static 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 | ||
134 | static void iomd_free_dma(unsigned int chan, dma_t *dma) | 136 | static 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 | ||
139 | static void iomd_enable_dma(unsigned int chan, dma_t *dma) | 143 | static 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 | ||
172 | static void iomd_disable_dma(unsigned int chan, dma_t *dma) | 177 | static 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 | ||
239 | static void floppy_enable_dma(unsigned int chan, dma_t *dma) | 245 | static 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(®s); | 275 | set_fiq_regs(®s); |
269 | enable_fiq(dma->dma_irq); | 276 | enable_fiq(fdma->fiq); |
270 | } | 277 | } |
271 | 278 | ||
272 | static void floppy_disable_dma(unsigned int chan, dma_t *dma) | 279 | static 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 | ||
305 | static dma_t iomd_dma[6]; | 313 | static struct iomd_dma iomd_dma[6]; |
306 | 314 | ||
307 | static dma_t floppy_dma = { | 315 | static 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 | ||
312 | static dma_t sound_dma = { | 322 | static 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); |