2 * linux/arch/arm/mach-rpc/dma.c
4 * Copyright (C) 1998 Russell King
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * DMA functions specific to RiscPC architecture
12 #include <linux/mman.h>
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
15 #include <linux/dma-mapping.h>
22 #include <mach/hardware.h>
23 #include <asm/uaccess.h>
25 #include <asm/mach/dma.h>
26 #include <asm/hardware/iomd.h>
29 struct dma_struct dma
;
31 unsigned long base
; /* Controller base address */
32 int irq
; /* Controller IRQ */
33 struct scatterlist cur_sg
; /* Current controller buffer */
39 #define TRANSFER_SIZE 2
42 #define ENDA (IOMD_IO0ENDA - IOMD_IO0CURA)
43 #define CURB (IOMD_IO0CURB - IOMD_IO0CURA)
44 #define ENDB (IOMD_IO0ENDB - IOMD_IO0CURA)
45 #define CR (IOMD_IO0CR - IOMD_IO0CURA)
46 #define ST (IOMD_IO0ST - IOMD_IO0CURA)
48 static void iomd_get_next_sg(struct scatterlist
*sg
, struct iomd_dma
*idma
)
50 unsigned long end
, offset
, flags
= 0;
53 sg
->dma_address
= idma
->dma_addr
;
54 offset
= sg
->dma_address
& ~PAGE_MASK
;
56 end
= offset
+ idma
->dma_len
;
61 if (offset
+ TRANSFER_SIZE
>= end
)
64 sg
->length
= end
- TRANSFER_SIZE
;
66 idma
->dma_len
-= end
- offset
;
67 idma
->dma_addr
+= end
- offset
;
69 if (idma
->dma_len
== 0) {
70 if (idma
->dma
.sgcount
> 1) {
71 idma
->dma
.sg
= sg_next(idma
->dma
.sg
);
72 idma
->dma_addr
= idma
->dma
.sg
->dma_address
;
73 idma
->dma_len
= idma
->dma
.sg
->length
;
81 flags
= DMA_END_S
| DMA_END_L
;
89 static irqreturn_t
iomd_dma_handle(int irq
, void *dev_id
)
91 struct iomd_dma
*idma
= dev_id
;
92 unsigned long base
= idma
->base
;
97 status
= iomd_readb(base
+ ST
);
98 if (!(status
& DMA_ST_INT
))
101 if ((idma
->state
^ status
) & DMA_ST_AB
)
102 iomd_get_next_sg(&idma
->cur_sg
, idma
);
104 switch (status
& (DMA_ST_OFL
| DMA_ST_AB
)) {
105 case DMA_ST_OFL
: /* OIA */
106 case DMA_ST_AB
: /* .IB */
107 iomd_writel(idma
->cur_sg
.dma_address
, base
+ CURA
);
108 iomd_writel(idma
->cur_sg
.length
, base
+ ENDA
);
109 idma
->state
= DMA_ST_AB
;
112 case DMA_ST_OFL
| DMA_ST_AB
: /* OIB */
114 iomd_writel(idma
->cur_sg
.dma_address
, base
+ CURB
);
115 iomd_writel(idma
->cur_sg
.length
, base
+ ENDB
);
120 if (status
& DMA_ST_OFL
&&
121 idma
->cur_sg
.length
== (DMA_END_S
|DMA_END_L
))
125 idma
->state
= ~DMA_ST_AB
;
131 static int iomd_request_dma(unsigned int chan
, dma_t
*dma
)
133 struct iomd_dma
*idma
= container_of(dma
, struct iomd_dma
, dma
);
135 return request_irq(idma
->irq
, iomd_dma_handle
,
136 IRQF_DISABLED
, idma
->dma
.device_id
, idma
);
139 static void iomd_free_dma(unsigned int chan
, dma_t
*dma
)
141 struct iomd_dma
*idma
= container_of(dma
, struct iomd_dma
, dma
);
143 free_irq(idma
->irq
, idma
);
146 static void iomd_enable_dma(unsigned int chan
, dma_t
*dma
)
148 struct iomd_dma
*idma
= container_of(dma
, struct iomd_dma
, dma
);
149 unsigned long dma_base
= idma
->base
;
150 unsigned int ctrl
= TRANSFER_SIZE
| DMA_CR_E
;
152 if (idma
->dma
.invalid
) {
153 idma
->dma
.invalid
= 0;
156 * Cope with ISA-style drivers which expect cache
160 idma
->dma
.sg
= &idma
->dma
.buf
;
161 idma
->dma
.sgcount
= 1;
162 idma
->dma
.buf
.length
= idma
->dma
.count
;
163 idma
->dma
.buf
.dma_address
= dma_map_single(NULL
,
164 idma
->dma
.addr
, idma
->dma
.count
,
165 idma
->dma
.dma_mode
== DMA_MODE_READ
?
166 DMA_FROM_DEVICE
: DMA_TO_DEVICE
);
169 iomd_writeb(DMA_CR_C
, dma_base
+ CR
);
170 idma
->state
= DMA_ST_AB
;
173 if (idma
->dma
.dma_mode
== DMA_MODE_READ
)
176 iomd_writeb(ctrl
, dma_base
+ CR
);
177 enable_irq(idma
->irq
);
180 static void iomd_disable_dma(unsigned int chan
, dma_t
*dma
)
182 struct iomd_dma
*idma
= container_of(dma
, struct iomd_dma
, dma
);
183 unsigned long dma_base
= idma
->base
;
186 local_irq_save(flags
);
187 if (idma
->state
!= ~DMA_ST_AB
)
188 disable_irq(idma
->irq
);
189 iomd_writeb(0, dma_base
+ CR
);
190 local_irq_restore(flags
);
193 static int iomd_set_dma_speed(unsigned int chan
, dma_t
*dma
, int cycle
)
199 else if (cycle
<= 250)
201 else if (cycle
< 438)
206 tcr
= iomd_readb(IOMD_DMATCR
);
211 tcr
= (tcr
& ~0x03) | speed
;
215 tcr
= (tcr
& ~0x0c) | (speed
<< 2);
219 tcr
= (tcr
& ~0x30) | (speed
<< 4);
223 tcr
= (tcr
& ~0xc0) | (speed
<< 6);
230 iomd_writeb(tcr
, IOMD_DMATCR
);
235 static struct dma_ops iomd_dma_ops
= {
237 .request
= iomd_request_dma
,
238 .free
= iomd_free_dma
,
239 .enable
= iomd_enable_dma
,
240 .disable
= iomd_disable_dma
,
241 .setspeed
= iomd_set_dma_speed
,
244 static struct fiq_handler fh
= {
249 struct dma_struct dma
;
253 static void floppy_enable_dma(unsigned int chan
, dma_t
*dma
)
255 struct floppy_dma
*fdma
= container_of(dma
, struct floppy_dma
, dma
);
256 void *fiqhandler_start
;
257 unsigned int fiqhandler_length
;
263 if (fdma
->dma
.dma_mode
== DMA_MODE_READ
) {
264 extern unsigned char floppy_fiqin_start
, floppy_fiqin_end
;
265 fiqhandler_start
= &floppy_fiqin_start
;
266 fiqhandler_length
= &floppy_fiqin_end
- &floppy_fiqin_start
;
268 extern unsigned char floppy_fiqout_start
, floppy_fiqout_end
;
269 fiqhandler_start
= &floppy_fiqout_start
;
270 fiqhandler_length
= &floppy_fiqout_end
- &floppy_fiqout_start
;
273 regs
.ARM_r9
= fdma
->dma
.count
;
274 regs
.ARM_r10
= (unsigned long)fdma
->dma
.addr
;
275 regs
.ARM_fp
= (unsigned long)FLOPPYDMA_BASE
;
277 if (claim_fiq(&fh
)) {
278 printk("floppydma: couldn't claim FIQ.\n");
282 set_fiq_handler(fiqhandler_start
, fiqhandler_length
);
284 enable_fiq(fdma
->fiq
);
287 static void floppy_disable_dma(unsigned int chan
, dma_t
*dma
)
289 struct floppy_dma
*fdma
= container_of(dma
, struct floppy_dma
, dma
);
290 disable_fiq(fdma
->fiq
);
294 static int floppy_get_residue(unsigned int chan
, dma_t
*dma
)
301 static struct dma_ops floppy_dma_ops
= {
303 .enable
= floppy_enable_dma
,
304 .disable
= floppy_disable_dma
,
305 .residue
= floppy_get_residue
,
309 * This is virtual DMA - we don't need anything here.
311 static void sound_enable_disable_dma(unsigned int chan
, dma_t
*dma
)
315 static struct dma_ops sound_dma_ops
= {
317 .enable
= sound_enable_disable_dma
,
318 .disable
= sound_enable_disable_dma
,
321 static struct iomd_dma iomd_dma
[6];
323 static struct floppy_dma floppy_dma
= {
325 .d_ops
= &floppy_dma_ops
,
327 .fiq
= FIQ_FLOPPYDATA
,
330 static dma_t sound_dma
= {
331 .d_ops
= &sound_dma_ops
,
334 static int __init
rpc_dma_init(void)
339 iomd_writeb(0, IOMD_IO0CR
);
340 iomd_writeb(0, IOMD_IO1CR
);
341 iomd_writeb(0, IOMD_IO2CR
);
342 iomd_writeb(0, IOMD_IO3CR
);
344 iomd_writeb(0xa0, IOMD_DMATCR
);
347 * Setup DMA channels 2,3 to be for podules
348 * and channels 0,1 for internal devices
350 iomd_writeb(DMA_EXT_IO3
|DMA_EXT_IO2
, IOMD_DMAEXT
);
352 iomd_dma
[DMA_0
].base
= IOMD_IO0CURA
;
353 iomd_dma
[DMA_0
].irq
= IRQ_DMA0
;
354 iomd_dma
[DMA_1
].base
= IOMD_IO1CURA
;
355 iomd_dma
[DMA_1
].irq
= IRQ_DMA1
;
356 iomd_dma
[DMA_2
].base
= IOMD_IO2CURA
;
357 iomd_dma
[DMA_2
].irq
= IRQ_DMA2
;
358 iomd_dma
[DMA_3
].base
= IOMD_IO3CURA
;
359 iomd_dma
[DMA_3
].irq
= IRQ_DMA3
;
360 iomd_dma
[DMA_S0
].base
= IOMD_SD0CURA
;
361 iomd_dma
[DMA_S0
].irq
= IRQ_DMAS0
;
362 iomd_dma
[DMA_S1
].base
= IOMD_SD1CURA
;
363 iomd_dma
[DMA_S1
].irq
= IRQ_DMAS1
;
365 for (i
= DMA_0
; i
<= DMA_S1
; i
++) {
366 iomd_dma
[i
].dma
.d_ops
= &iomd_dma_ops
;
368 ret
= isa_dma_add(i
, &iomd_dma
[i
].dma
);
370 printk("IOMDDMA%u: unable to register: %d\n", i
, ret
);
373 ret
= isa_dma_add(DMA_VIRTUAL_FLOPPY
, &floppy_dma
.dma
);
375 printk("IOMDFLOPPY: unable to register: %d\n", ret
);
376 ret
= isa_dma_add(DMA_VIRTUAL_SOUND
, &sound_dma
);
378 printk("IOMDSOUND: unable to register: %d\n", ret
);
381 core_initcall(rpc_dma_init
);