relayd: move the interface fixup to the right place
[openwrt.git] / target / linux / coldfire / files-2.6.31 / arch / m68k / coldfire / m547x / dma.c
1 /*
2  * arch/m68k/coldfire/m547x/dma.c
3  *
4  * Coldfire M547x/M548x DMA
5  *
6  * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
7  * Kurt Mahan <kmahan@freescale.com>
8  * Shrek Wu b16972@freescale.com
9  *
10  * This code is based on patches from the Freescale M547x_8x BSP
11  * release mcf547x_8x-20070107-ltib.iso
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/mm.h>
30 #include <linux/init.h>
31 #include <linux/interrupt.h>
32 #include <asm/io.h>
33 #include <asm/irq.h>
34 #include <asm/dma.h>
35 #include <asm/coldfire.h>
36 #include <asm/m5485sram.h>
37 #include <asm/mcfsim.h>
38 #include <asm/MCD_dma.h>
39
40 /*
41  * This global keeps track of which initiators have been
42  * used of the available assignments.  Initiators 0-15 are
43  * hardwired.  Initiators 16-31 are multiplexed and controlled
44  * via the Initiatior Mux Control Registe (IMCR).  The
45  * assigned requestor is stored with the associated initiator
46  * number.
47  */
48 static int used_reqs[32] = {
49         DMA_ALWAYS, DMA_DSPI_RX, DMA_DSPI_TX, DMA_DREQ0,
50         DMA_PSC0_RX, DMA_PSC0_TX, DMA_USBEP0, DMA_USBEP1,
51         DMA_USBEP2, DMA_USBEP3, DMA_PCI_TX, DMA_PCI_RX,
52         DMA_PSC1_RX, DMA_PSC1_TX, DMA_I2C_RX, DMA_I2C_TX,
53         0, 0, 0, 0,
54         0, 0, 0, 0,
55         0, 0, 0, 0,
56         0, 0, 0, 0
57 };
58
59 /*
60  * This global keeps track of which channels have been assigned
61  * to tasks.  This methology assumes that no single initiator
62  * will be tied to more than one task/channel
63  */
64 static char used_channel[16] = {
65         -1, -1, -1, -1, -1, -1, -1, -1,
66         -1, -1, -1, -1, -1, -1, -1, -1
67 };
68
69 unsigned int connected_channel[16] = {
70         0, 0, 0, 0, 0, 0, 0, 0,
71         0, 0, 0, 0, 0, 0, 0, 0
72 };
73
74 /**
75  * dma_set_initiator - enable initiator
76  * @initiator: initiator identifier
77  *
78  * Returns 0 of successful, non-zero otherwise
79  *
80  * Attempt to enable the provided Initiator in the Initiator
81  * Mux Control Register.
82  */
83 int dma_set_initiator(int initiator)
84 {
85         switch (initiator) {
86         case DMA_ALWAYS:
87         case DMA_DSPI_RX:
88         case DMA_DSPI_TX:
89         case DMA_DREQ0:
90         case DMA_PSC0_RX:
91         case DMA_PSC0_TX:
92         case DMA_USBEP0:
93         case DMA_USBEP1:
94         case DMA_USBEP2:
95         case DMA_USBEP3:
96         case DMA_PCI_TX:
97         case DMA_PCI_RX:
98         case DMA_PSC1_RX:
99         case DMA_PSC1_TX:
100         case DMA_I2C_RX:
101         case DMA_I2C_TX:
102                 /*
103                  * These initiators are always active
104                  */
105                 break;
106
107         case DMA_FEC0_RX:
108                 MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC16(3))
109                     | MCF_DMA_IMCR_SRC16_FEC0RX;
110                 used_reqs[16] = DMA_FEC0_RX;
111                 break;
112
113         case DMA_FEC0_TX:
114                 MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC17(3))
115                     | MCF_DMA_IMCR_SRC17_FEC0TX;
116                 used_reqs[17] = DMA_FEC0_TX;
117                 break;
118
119         case DMA_FEC1_RX:
120                 MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC20(3))
121                     | MCF_DMA_IMCR_SRC20_FEC1RX;
122                 used_reqs[20] = DMA_FEC1_RX;
123                 break;
124
125         case DMA_FEC1_TX:
126                 if (used_reqs[21] == 0) {
127                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC21(3))
128                             | MCF_DMA_IMCR_SRC21_FEC1TX;
129                         used_reqs[21] = DMA_FEC1_TX;
130                 } else if (used_reqs[25] == 0) {
131                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC25(3))
132                             | MCF_DMA_IMCR_SRC25_FEC1TX;
133                         used_reqs[25] = DMA_FEC1_TX;
134                 } else if (used_reqs[31] == 0) {
135                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC31(3))
136                             | MCF_DMA_IMCR_SRC31_FEC1TX;
137                         used_reqs[31] = DMA_FEC1_TX;
138                 } else          /* No empty slots */
139                         return 1;
140                 break;
141
142         case DMA_DREQ1:
143                 if (used_reqs[29] == 0) {
144                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC29(3))
145                             | MCF_DMA_IMCR_SRC29_DREQ1;
146                         used_reqs[29] = DMA_DREQ1;
147                 } else if (used_reqs[21] == 0) {
148                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC21(3))
149                             | MCF_DMA_IMCR_SRC21_DREQ1;
150                         used_reqs[21] = DMA_DREQ1;
151                 } else          /* No empty slots */
152                         return 1;
153                 break;
154
155         case DMA_CTM0:
156                 if (used_reqs[24] == 0) {
157                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC24(3))
158                             | MCF_DMA_IMCR_SRC24_CTM0;
159                         used_reqs[24] = DMA_CTM0;
160                 } else          /* No empty slots */
161                         return 1;
162                 break;
163
164         case DMA_CTM1:
165                 if (used_reqs[25] == 0) {
166                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC25(3))
167                             | MCF_DMA_IMCR_SRC25_CTM1;
168                         used_reqs[25] = DMA_CTM1;
169                 } else          /* No empty slots */
170                         return 1;
171                 break;
172
173         case DMA_CTM2:
174                 if (used_reqs[26] == 0) {
175                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC26(3))
176                             | MCF_DMA_IMCR_SRC26_CTM2;
177                         used_reqs[26] = DMA_CTM2;
178                 } else          /* No empty slots */
179                         return 1;
180                 break;
181
182         case DMA_CTM3:
183                 if (used_reqs[27] == 0) {
184                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC27(3))
185                             | MCF_DMA_IMCR_SRC27_CTM3;
186                         used_reqs[27] = DMA_CTM3;
187                 } else          /* No empty slots */
188                         return 1;
189                 break;
190
191         case DMA_CTM4:
192                 if (used_reqs[28] == 0) {
193                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC28(3))
194                             | MCF_DMA_IMCR_SRC28_CTM4;
195                         used_reqs[28] = DMA_CTM4;
196                 } else          /* No empty slots */
197                         return 1;
198                 break;
199
200         case DMA_CTM5:
201                 if (used_reqs[29] == 0) {
202                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC29(3))
203                             | MCF_DMA_IMCR_SRC29_CTM5;
204                         used_reqs[29] = DMA_CTM5;
205                 } else          /* No empty slots */
206                         return 1;
207                 break;
208
209         case DMA_CTM6:
210                 if (used_reqs[30] == 0) {
211                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC30(3))
212                             | MCF_DMA_IMCR_SRC30_CTM6;
213                         used_reqs[30] = DMA_CTM6;
214                 } else          /* No empty slots */
215                         return 1;
216                 break;
217
218         case DMA_CTM7:
219                 if (used_reqs[31] == 0) {
220                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC31(3))
221                             | MCF_DMA_IMCR_SRC31_CTM7;
222                         used_reqs[31] = DMA_CTM7;
223                 } else          /* No empty slots */
224                         return 1;
225                 break;
226
227         case DMA_USBEP4:
228                 if (used_reqs[26] == 0) {
229                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC26(3))
230                             | MCF_DMA_IMCR_SRC26_USBEP4;
231                         used_reqs[26] = DMA_USBEP4;
232                 } else          /* No empty slots */
233                         return 1;
234                 break;
235
236         case DMA_USBEP5:
237                 if (used_reqs[27] == 0) {
238                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC27(3))
239                             | MCF_DMA_IMCR_SRC27_USBEP5;
240                         used_reqs[27] = DMA_USBEP5;
241                 } else          /* No empty slots */
242                         return 1;
243                 break;
244
245         case DMA_USBEP6:
246                 if (used_reqs[28] == 0) {
247                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC28(3))
248                             | MCF_DMA_IMCR_SRC28_USBEP6;
249                         used_reqs[28] = DMA_USBEP6;
250                 } else          /* No empty slots */
251                         return 1;
252                 break;
253
254         case DMA_PSC2_RX:
255                 if (used_reqs[28] == 0) {
256                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC28(3))
257                             | MCF_DMA_IMCR_SRC28_PSC2RX;
258                         used_reqs[28] = DMA_PSC2_RX;
259                 } else          /* No empty slots */
260                         return 1;
261                 break;
262
263         case DMA_PSC2_TX:
264                 if (used_reqs[29] == 0) {
265                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC29(3))
266                             | MCF_DMA_IMCR_SRC29_PSC2TX;
267                         used_reqs[29] = DMA_PSC2_TX;
268                 } else          /* No empty slots */
269                         return 1;
270                 break;
271
272         case DMA_PSC3_RX:
273                 if (used_reqs[30] == 0) {
274                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC30(3))
275                             | MCF_DMA_IMCR_SRC30_PSC3RX;
276                         used_reqs[30] = DMA_PSC3_RX;
277                 } else          /* No empty slots */
278                         return 1;
279                 break;
280
281         case DMA_PSC3_TX:
282                 if (used_reqs[31] == 0) {
283                         MCF_DMA_IMCR = (MCF_DMA_IMCR & ~MCF_DMA_IMCR_SRC31(3))
284                             | MCF_DMA_IMCR_SRC31_PSC3TX;
285                         used_reqs[31] = DMA_PSC3_TX;
286                 } else          /* No empty slots */
287                         return 1;
288                 break;
289
290         default:
291                 return 1;
292         }
293         return 0;
294 }
295
296 /**
297  * dma_get_initiator - get the initiator for the given requestor
298  * @requestor: initiator identifier
299  *
300  * Returns initiator number (0-31) if assigned or just 0
301  */
302 unsigned int dma_get_initiator(int requestor)
303 {
304         u32 i;
305
306         for (i = 0; i < sizeof(used_reqs); ++i) {
307                 if (used_reqs[i] == requestor)
308                         return i;
309         }
310         return 0;
311 }
312
313 /**
314  * dma_remove_initiator - remove the given initiator from active list
315  * @requestor: requestor to remove
316  */
317 void dma_remove_initiator(int requestor)
318 {
319         u32 i;
320
321         for (i = 0; i < sizeof(used_reqs); ++i) {
322                 if (used_reqs[i] == requestor) {
323                         used_reqs[i] = -1;
324                         break;
325                 }
326         }
327 }
328
329 /**
330  * dma_set_channel_fec: find available channel for fec and mark
331  * @requestor: initiator/requestor identifier
332  *
333  * Returns first avaialble channel (0-5) or -1 if all occupied
334  */
335 int dma_set_channel_fec(int requestor)
336 {
337         u32 i, t;
338
339 #ifdef CONFIG_FEC_548x_ENABLE_FEC2
340         t = 4;
341 #else
342         t = 2;
343 #endif
344
345         for (i = 0; i < t ; ++i) {
346                 if (used_channel[i] == -1) {
347                         used_channel[i] = requestor;
348                         return i;
349                 }
350         }
351         /* All channels taken */
352         return -1;
353 }
354
355 /**
356  * dma_set_channel - find an available channel and mark as used
357  * @requestor: initiator/requestor identifier
358  *
359  * Returns first available channel (6-15) or -1 if all occupied
360  */
361 int dma_set_channel(int requestor)
362 {
363         u32 i;
364 #ifdef CONFIG_NET_FEC2
365         i = 4;
366 #else
367         i = 2;
368 #endif
369
370         for (; i < 16; ++i)
371                 if (used_channel[i] == -1) {
372                         used_channel[i] = requestor;
373                         return i;
374                 }
375
376         /* All channels taken */
377         return -1;
378 }
379
380 /**
381  * dma_get_channel - get the channel being initiated by the requestor
382  * @requestor: initiator/requestor identifier
383  *
384  * Returns Initiator for requestor or -1 if not found
385  */
386 int dma_get_channel(int requestor)
387 {
388         u32 i;
389
390         for (i = 0; i < sizeof(used_channel); ++i) {
391                 if (used_channel[i] == requestor)
392                         return i;
393         }
394         return -1;
395 }
396
397 /**
398  * dma_connect - connect a channel with reference on data
399  * @channel: channel number
400  * @address: reference address of data
401  *
402  * Returns 0 if success or -1 if invalid channel
403  */
404 int dma_connect(int channel, int address)
405 {
406         if ((channel < 16) && (channel >= 0)) {
407                 connected_channel[channel] = address;
408                 return 0;
409         }
410         return -1;
411 }
412
413 /**
414  * dma_disconnect - disconnect a channel
415  * @channel: channel number
416  *
417  * Returns 0 if success or -1 if invalid channel
418  */
419 int dma_disconnect(int channel)
420 {
421         if ((channel < 16) && (channel >= 0)) {
422                 connected_channel[channel] = 0;
423                 return 0;
424         }
425         return -1;
426 }
427
428 /**
429  * dma_remove_channel - remove channel from the active list
430  * @requestor: initiator/requestor identifier
431  */
432 void dma_remove_channel(int requestor)
433 {
434         u32 i;
435
436         for (i = 0; i < sizeof(used_channel); ++i) {
437                 if (used_channel[i] == requestor) {
438                         used_channel[i] = -1;
439                         break;
440                 }
441         }
442 }
443
444 /**
445  * dma_interrupt_handler - dma interrupt handler
446  * @irq: interrupt number
447  * @dev_id: data
448  *
449  * Returns IRQ_HANDLED
450  */
451 irqreturn_t dma_interrupt_handler(int irq, void *dev_id)
452 {
453         u32 i, interrupts;
454
455         /*
456          * Determine which interrupt(s) triggered by AND'ing the
457          * pending interrupts with those that aren't masked.
458          */
459         interrupts = MCF_DMA_DIPR;
460         MCF_DMA_DIPR = interrupts;
461
462         for (i = 0; i < 16; ++i, interrupts >>= 1) {
463                 if (interrupts & 0x1)
464                         if (connected_channel[i] != 0)
465                                 ((void (*)(void)) (connected_channel[i])) ();
466         }
467
468         return IRQ_HANDLED;
469 }
470
471 /**
472  * dma_remove_channel_by_number - clear dma channel
473  * @channel: channel number to clear
474  */
475 void dma_remove_channel_by_number(int channel)
476 {
477         if ((channel < sizeof(used_channel)) && (channel >= 0))
478                 used_channel[channel] = -1;
479 }
480
481 /**
482  * dma_init - initialize the dma subsystem
483  *
484  * Returns 0 if success non-zero if failure
485  *
486  * Handles the DMA initialization during device setup.
487  */
488 int __devinit dma_init()
489 {
490         int result;
491         char *dma_version_str;
492
493         MCD_getVersion(&dma_version_str);
494         printk(KERN_INFO "m547x_8x DMA: Initialize %s\n", dma_version_str);
495
496         /* attempt to setup dma interrupt handler */
497         if (request_irq(64 + ISC_DMA, dma_interrupt_handler, IRQF_DISABLED,
498                         "MCD-DMA", NULL)) {
499                 printk(KERN_ERR "MCD-DMA: Cannot allocate the DMA IRQ(48)\n");
500                 return 1;
501         }
502
503         MCF_DMA_DIMR = 0;
504         MCF_DMA_DIPR = 0xFFFFFFFF;
505
506         MCF_ICR(ISC_DMA) = ILP_DMA;
507
508         result = MCD_initDma((dmaRegs *) (MCF_MBAR + 0x8000),
509                         (void *) SYS_SRAM_DMA_START, MCD_RELOC_TASKS);
510         if (result != MCD_OK) {
511                 printk(KERN_ERR "MCD-DMA: Cannot perform DMA initialization\n");
512                 free_irq(64 + ISC_DMA, NULL);
513                 return 1;
514         }
515
516         return 0;
517 }
518 device_initcall(dma_init);