v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / arch / arm / mach-sa1100 / dma-sa1111.c
1 /*
2  *  linux/arch/arm/mach-sa1100/dma-sa1111.c
3  *
4  *  Copyright (C) 2000 John Dorsey
5  *
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.
9  *
10  *  4 September 2000 - created.
11  */
12
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/sched.h>
16 #include <linux/delay.h>
17 #include <linux/spinlock.h>
18 #include <linux/errno.h>
19
20 #include <asm/system.h>
21 #include <asm/irq.h>
22 #include <asm/hardware.h>
23 #include <asm/io.h>
24 #include <asm/dma.h>
25
26
27 // #define DEBUG
28 #ifdef DEBUG
29 #define DPRINTK( s, arg... )  printk( "dma<%s>: " s, dma->device_id , ##arg )
30 #else
31 #define DPRINTK( x... )
32 #endif
33
34
35 /*
36  * Control register structure for the SA1111 SAC DMA
37  */
38
39 typedef struct {
40         volatile u_long SAD_CS;
41         volatile dma_addr_t SAD_SA;
42         volatile u_long SAD_CA;
43         volatile dma_addr_t SAD_SB;
44         volatile u_long SAD_CB;
45 } dma_regs_t;
46
47 #include "dma.h"
48
49
50 void sa1111_reset_sac_dma(dmach_t channel)
51 {
52         sa1100_dma_t *dma = &dma_chan[channel];
53         dma->regs->SAD_CS = 0;
54         mdelay(1);
55         dma->dma_a = dma->dma_b = 0;
56 }
57
58
59 int start_sa1111_sac_dma(sa1100_dma_t *dma, dma_addr_t dma_ptr, size_t size)
60 {
61         dma_regs_t *sac_regs = dma->regs;
62
63         DPRINTK(" SAC DMA %cCS %02x at %08x (%d)\n",
64                 (sac_regs==&SADTCS)?'T':'R', sac_regs->SAD_CS, dma_ptr, size);
65
66         /* The minimum transfer length requirement has not yet been
67          * verified:
68          */
69         if( size < SA1111_SAC_DMA_MIN_XFER )
70           printk(KERN_WARNING "Warning: SAC xfers below %u bytes may be buggy!"
71                  " (%u bytes)\n", SA1111_SAC_DMA_MIN_XFER, size);
72
73         if( dma->dma_a && dma->dma_b ){
74                 DPRINTK("  neither engine available! (A %d, B %d)\n",
75                         dma->dma_a, dma->dma_b);
76                 return -1;
77         }
78
79         if( sa1111_check_dma_bug(dma_ptr) )
80                 printk(KERN_WARNING "Warning: DMA address %08x is buggy!\n",
81                        dma_ptr);
82
83         if( (dma->last_dma || dma->dma_b) && dma->dma_a == 0 ){
84                 if( sac_regs->SAD_CS & SAD_CS_DBDB ){
85                         DPRINTK("  awaiting \"done B\" interrupt, not starting\n");
86                         return -1;
87                 }
88                 sac_regs->SAD_SA = SA1111_DMA_ADDR((u_int)dma_ptr);
89                 sac_regs->SAD_CA = size;
90                 sac_regs->SAD_CS = SAD_CS_DSTA | SAD_CS_DEN;
91                 ++dma->dma_a;
92                 DPRINTK("  with A [%02lx %08lx %04lx]\n", sac_regs->SAD_CS,
93                         sac_regs->SAD_SA, sac_regs->SAD_CA);
94         } else {
95                 if( sac_regs->SAD_CS & SAD_CS_DBDA ){
96                         DPRINTK("  awaiting \"done A\" interrupt, not starting\n");
97                         return -1;
98                 }
99                 sac_regs->SAD_SB = SA1111_DMA_ADDR((u_int)dma_ptr);
100                 sac_regs->SAD_CB = size;
101                 sac_regs->SAD_CS = SAD_CS_DSTB | SAD_CS_DEN;
102                 ++dma->dma_b;
103                 DPRINTK("  with B [%02lx %08lx %04lx]\n", sac_regs->SAD_CS,
104                         sac_regs->SAD_SB, sac_regs->SAD_CB);
105         }
106
107         /* Additional delay to avoid DMA engine lockup during record: */
108         if( sac_regs == (dma_regs_t*)&SADRCS )
109                 mdelay(1);      /* NP : wouuuh! ugly... */
110
111         return 0;
112 }
113
114
115 static void sa1111_sac_dma_irq(int irq, void *dev_id, struct pt_regs *regs)
116 {
117         sa1100_dma_t *dma = (sa1100_dma_t *) dev_id;
118
119         DPRINTK("irq %d, last DMA serviced was %c, CS %02x\n", irq,
120                 dma->last_dma?'B':'A', dma->regs->SAD_CS);
121
122         /* Occasionally, one of the DMA engines (A or B) will
123          * lock up. We try to deal with this by quietly kicking
124          * the control register for the afflicted transfer
125          * direction.
126          *
127          * Note for the debugging-inclined: we currently aren't
128          * properly flushing the DMA engines during channel
129          * shutdown. A slight hiccup at the beginning of playback
130          * after a channel has been stopped can be heard as
131          * evidence of this. Programmatically, this shows up
132          * as either a locked engine, or a spurious interrupt. -jd
133          */
134
135         if(irq==AUDXMTDMADONEA || irq==AUDRCVDMADONEA){
136
137                 if(dma->last_dma == 0){
138                         DPRINTK("DMA B has locked up!\n");
139                         dma->regs->SAD_CS = 0;
140                         mdelay(1);
141                         dma->dma_a = dma->dma_b = 0;
142                 } else {
143                         if(dma->dma_a == 0)
144                                 DPRINTK("spurious SAC IRQ %d\n", irq);
145                         else {
146                                 --dma->dma_a;
147
148                                 /* Servicing the SAC DMA engines too quickly
149                                  * after they issue a DONE interrupt causes
150                                  * them to lock up.
151                                  */
152                                 if(irq==AUDRCVDMADONEA || irq==AUDRCVDMADONEB)
153                                         mdelay(1);
154                         }
155                 }
156
157                 dma->regs->SAD_CS = SAD_CS_DBDA | SAD_CS_DEN; /* w1c */
158                 dma->last_dma = 0;
159
160         } else {
161
162                 if(dma->last_dma == 1){
163                         DPRINTK("DMA A has locked up!\n");
164                         dma->regs->SAD_CS = 0;
165                         mdelay(1);
166                         dma->dma_a = dma->dma_b = 0;
167                 } else {
168                         if(dma->dma_b == 0)
169                                 DPRINTK("spurious SAC IRQ %d\n", irq);
170                         else {
171                                 --dma->dma_b;
172
173                                 /* See lock-up note above. */
174                                 if(irq==AUDRCVDMADONEA || irq==AUDRCVDMADONEB)
175                                         mdelay(1);
176                         }
177                 }
178
179                 dma->regs->SAD_CS = SAD_CS_DBDB | SAD_CS_DEN; /* w1c */
180                 dma->last_dma = 1;
181
182         }
183
184         /* NP: maybe this shouldn't be called in all cases? */
185         sa1100_dma_done (dma);
186 }
187
188
189 int sa1111_sac_request_dma(dmach_t *channel, const char *device_id,
190                            unsigned int direction)
191 {
192         sa1100_dma_t *dma = NULL;
193         int ch, irq, err;
194
195         *channel = -1;          /* to be sure we catch the freeing of a misregistered channel */
196
197         ch = SA1111_SAC_DMA_BASE + direction;
198
199         if (!channel_is_sa1111_sac(ch)) {
200                 printk(KERN_ERR "%s: invalid SA-1111 SAC DMA channel (%d)\n",
201                        device_id, ch);
202                 return -1;
203         }
204
205         dma = &dma_chan[ch];
206
207         if (xchg(&dma->in_use, 1) == 1) {
208                 printk(KERN_ERR "%s: SA-1111 SAC DMA channel %d in use\n",
209                        device_id, ch);
210                 return -EBUSY;
211         }
212
213         irq = AUDXMTDMADONEA + direction;
214         err = request_irq(irq, sa1111_sac_dma_irq, SA_INTERRUPT,
215                           device_id, (void *) dma);
216         if (err) {
217                 printk(KERN_ERR
218                        "%s: unable to request IRQ %d for DMA channel %d (A)\n",
219                        device_id, irq, ch);
220                 dma->in_use = 0;
221                 return err;
222         }
223
224         irq = AUDXMTDMADONEB + direction;
225         err = request_irq(irq, sa1111_sac_dma_irq, SA_INTERRUPT,
226                           device_id, (void *) dma);
227         if (err) {
228                 printk(KERN_ERR
229                        "%s: unable to request IRQ %d for DMA channel %d (B)\n",
230                        device_id, irq, ch);
231                 dma->in_use = 0;
232                 return err;
233         }
234
235         *channel = ch;
236         dma->device_id = device_id;
237         dma->callback = NULL;
238         dma->spin_size = 0;
239         dma->ready = 1;
240
241         return 0;
242 }
243
244
245 /* FIXME:  need to complete the three following functions */
246
247 int sa1111_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
248 {
249         sa1100_dma_t *dma = &dma_chan[channel];
250         int flags, ret;
251
252         local_irq_save(flags);
253         if (dma->curr && dma->spin_ref <= 0) {
254                 dma_buf_t *buf = dma->curr;
255                 if (buf_id)
256                         *buf_id = buf->id;
257                 /* not fully accurate but still... */
258                 *addr = buf->dma_ptr;
259                 ret = 0;
260         } else {
261                 if (buf_id)
262                         *buf_id = NULL;
263                 *addr = 0;
264                 ret = -ENXIO;
265         }
266         local_irq_restore(flags);
267         return ret;
268 }
269
270 int sa1111_dma_stop(dmach_t channel)
271 {
272         return 0;
273 }
274
275 int sa1111_dma_resume(dmach_t channel)
276 {
277         return 0;
278 }
279
280
281 void sa1111_cleanup_sac_dma(dmach_t channel)
282 {
283         sa1100_dma_t *dma = &dma_chan[channel];
284         free_irq(AUDXMTDMADONEA + (channel - SA1111_SAC_DMA_BASE), (void*) dma);
285         free_irq(AUDXMTDMADONEB + (channel - SA1111_SAC_DMA_BASE), (void*) dma);
286 }
287
288
289 /* According to the "Intel StrongARM SA-1111 Microprocessor Companion
290  * Chip Specification Update" (June 2000), erratum #7, there is a
291  * significant bug in Serial Audio Controller DMA. If the SAC is
292  * accessing a region of memory above 1MB relative to the bank base,
293  * it is important that address bit 10 _NOT_ be asserted. Depending
294  * on the configuration of the RAM, bit 10 may correspond to one
295  * of several different (processor-relative) address bits.
296  *
297  * This routine only identifies whether or not a given DMA address
298  * is susceptible to the bug.
299  */
300 int sa1111_check_dma_bug(dma_addr_t addr){
301         unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr);
302
303         /* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
304          * User's Guide" mentions that jumpers R51 and R52 control the
305          * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
306          * SDRAM bank 1 on Neponset). The default configuration selects
307          * Assabet, so any address in bank 1 is necessarily invalid.
308          */
309         if((machine_is_assabet() || machine_is_pfs168()) && addr >= _DRAMBnk1)
310                 return -1;
311
312         /* The bug only applies to buffers located more than one megabyte
313          * above the start of the target bank:
314          */
315         if(physaddr<(1<<20))
316                 return 0;
317
318         switch(FExtr(SMCR, SMCR_DRAC)){
319         case 01: /* 10 row + bank address bits, A<20> must not be set */
320                 if(physaddr & (1<<20))
321                         return -1;
322                 break;
323         case 02: /* 11 row + bank address bits, A<23> must not be set */
324                 if(physaddr & (1<<23))
325                         return -1;
326                 break;
327         case 03: /* 12 row + bank address bits, A<24> must not be set */
328                 if(physaddr & (1<<24))
329                         return -1;
330                 break;
331         case 04: /* 13 row + bank address bits, A<25> must not be set */
332                 if(physaddr & (1<<25))
333                         return -1;
334                 break;
335         case 05: /* 14 row + bank address bits, A<20> must not be set */
336                 if(physaddr & (1<<20))
337                         return -1;
338                 break;
339         case 06: /* 15 row + bank address bits, A<20> must not be set */
340                 if(physaddr & (1<<20))
341                         return -1;
342                 break;
343         default:
344                 printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%o\n",
345                        __FUNCTION__, FExtr(SMCR, SMCR_DRAC));
346                 return -1;
347         }
348
349         return 0;
350 }
351
352
353 EXPORT_SYMBOL(sa1111_sac_request_dma);
354 EXPORT_SYMBOL(sa1111_check_dma_bug);
355
356
357 static int __init sa1111_init_sac_dma(void)
358 {
359         int channel = SA1111_SAC_DMA_BASE;
360         dma_chan[channel++].regs = (dma_regs_t *) &SADTCS;
361         dma_chan[channel++].regs = (dma_regs_t *) &SADRCS;
362         return 0;
363 }
364
365 __initcall(sa1111_init_sac_dma);