Blackfin arch: Fix BUG - JUMP error in kernel (relocation truncated to fit: R_pcrel12...
[deliverable/linux.git] / arch / blackfin / kernel / bfin_dma_5xx.c
CommitLineData
1394f032
BW
1/*
2 * File: arch/blackfin/kernel/bfin_dma_5xx.c
3 * Based on:
4 * Author:
5 *
6 * Created:
7 * Description: This file contains the simple DMA Implementation for Blackfin
8 *
9 * Modified:
10 * Copyright 2004-2006 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30#include <linux/errno.h>
31#include <linux/module.h>
32#include <linux/sched.h>
33#include <linux/interrupt.h>
34#include <linux/kernel.h>
35#include <linux/param.h>
36
24a07a12 37#include <asm/blackfin.h>
1394f032
BW
38#include <asm/dma.h>
39#include <asm/cacheflush.h>
40
41/* Remove unused code not exported by symbol or internally called */
42#define REMOVE_DEAD_CODE
43
44/**************************************************************************
45 * Global Variables
46***************************************************************************/
47
48static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
1394f032
BW
49
50/*------------------------------------------------------------------------------
51 * Set the Buffer Clear bit in the Configuration register of specific DMA
52 * channel. This will stop the descriptor based DMA operation.
53 *-----------------------------------------------------------------------------*/
54static void clear_dma_buffer(unsigned int channel)
55{
56 dma_ch[channel].regs->cfg |= RESTART;
57 SSYNC();
58 dma_ch[channel].regs->cfg &= ~RESTART;
59 SSYNC();
60}
61
a161bb05 62static int __init blackfin_dma_init(void)
1394f032
BW
63{
64 int i;
65
66 printk(KERN_INFO "Blackfin DMA Controller\n");
67
68 for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
69 dma_ch[i].chan_status = DMA_CHANNEL_FREE;
77955664 70 dma_ch[i].regs = dma_io_base_addr[i];
1394f032
BW
71 mutex_init(&(dma_ch[i].dmalock));
72 }
23ee968d
MH
73 /* Mark MEMDMA Channel 0 as requested since we're using it internally */
74 dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED;
75 dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED;
a924db7c
MH
76
77#if defined(CONFIG_DEB_DMA_URGENT)
78 bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE()
79 | DEB1_URGENT | DEB2_URGENT | DEB3_URGENT);
80#endif
1394f032
BW
81 return 0;
82}
83
84arch_initcall(blackfin_dma_init);
85
1394f032
BW
86/*------------------------------------------------------------------------------
87 * Request the specific DMA channel from the system.
88 *-----------------------------------------------------------------------------*/
89int request_dma(unsigned int channel, char *device_id)
90{
91
92 pr_debug("request_dma() : BEGIN \n");
5ce998cf
MH
93
94#if defined(CONFIG_BF561) && ANOMALY_05000182
95 if (channel >= CH_IMEM_STREAM0_DEST && channel <= CH_IMEM_STREAM1_DEST) {
96 if (get_cclk() > 500000000) {
97 printk(KERN_WARNING
98 "Request IMDMA failed due to ANOMALY 05000182\n");
99 return -EFAULT;
100 }
101 }
102#endif
103
1394f032
BW
104 mutex_lock(&(dma_ch[channel].dmalock));
105
106 if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
107 || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
108 mutex_unlock(&(dma_ch[channel].dmalock));
109 pr_debug("DMA CHANNEL IN USE \n");
110 return -EBUSY;
111 } else {
112 dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
113 pr_debug("DMA CHANNEL IS ALLOCATED \n");
114 }
115
116 mutex_unlock(&(dma_ch[channel].dmalock));
117
8b01eaff 118#ifdef CONFIG_BF54x
549aaa84 119 if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
565c0d3f
GY
120 if (strncmp(device_id, "BFIN_UART", 9) == 0) {
121 dma_ch[channel].regs->peripheral_map &= 0x0FFF;
549aaa84 122 dma_ch[channel].regs->peripheral_map |=
5be36d22 123 ((channel - CH_UART2_RX + 0xC)<<12);
565c0d3f
GY
124 } else {
125 dma_ch[channel].regs->peripheral_map &= 0x0FFF;
549aaa84 126 dma_ch[channel].regs->peripheral_map |=
5be36d22 127 ((channel - CH_UART2_RX + 0x6)<<12);
565c0d3f 128 }
549aaa84 129 }
8b01eaff
SZ
130#endif
131
1394f032
BW
132 dma_ch[channel].device_id = device_id;
133 dma_ch[channel].irq_callback = NULL;
134
135 /* This is to be enabled by putting a restriction -
136 * you have to request DMA, before doing any operations on
137 * descriptor/channel
138 */
139 pr_debug("request_dma() : END \n");
140 return channel;
141}
142EXPORT_SYMBOL(request_dma);
143
144int set_dma_callback(unsigned int channel, dma_interrupt_t callback, void *data)
145{
146 int ret_irq = 0;
147
148 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
149 && channel < MAX_BLACKFIN_DMA_CHANNEL));
150
151 if (callback != NULL) {
152 int ret_val;
153 ret_irq = channel2irq(channel);
154
155 dma_ch[channel].data = data;
156
157 ret_val =
158 request_irq(ret_irq, (void *)callback, IRQF_DISABLED,
159 dma_ch[channel].device_id, data);
160 if (ret_val) {
161 printk(KERN_NOTICE
162 "Request irq in DMA engine failed.\n");
163 return -EPERM;
164 }
165 dma_ch[channel].irq_callback = callback;
166 }
167 return 0;
168}
169EXPORT_SYMBOL(set_dma_callback);
170
171void free_dma(unsigned int channel)
172{
173 int ret_irq;
174
175 pr_debug("freedma() : BEGIN \n");
176 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
177 && channel < MAX_BLACKFIN_DMA_CHANNEL));
178
179 /* Halt the DMA */
180 disable_dma(channel);
181 clear_dma_buffer(channel);
182
183 if (dma_ch[channel].irq_callback != NULL) {
184 ret_irq = channel2irq(channel);
185 free_irq(ret_irq, dma_ch[channel].data);
186 }
187
188 /* Clear the DMA Variable in the Channel */
189 mutex_lock(&(dma_ch[channel].dmalock));
190 dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
191 mutex_unlock(&(dma_ch[channel].dmalock));
192
193 pr_debug("freedma() : END \n");
194}
195EXPORT_SYMBOL(free_dma);
196
197void dma_enable_irq(unsigned int channel)
198{
199 int ret_irq;
200
201 pr_debug("dma_enable_irq() : BEGIN \n");
202 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
203 && channel < MAX_BLACKFIN_DMA_CHANNEL));
204
205 ret_irq = channel2irq(channel);
206 enable_irq(ret_irq);
207}
208EXPORT_SYMBOL(dma_enable_irq);
209
210void dma_disable_irq(unsigned int channel)
211{
212 int ret_irq;
213
214 pr_debug("dma_disable_irq() : BEGIN \n");
215 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
216 && channel < MAX_BLACKFIN_DMA_CHANNEL));
217
218 ret_irq = channel2irq(channel);
219 disable_irq(ret_irq);
220}
221EXPORT_SYMBOL(dma_disable_irq);
222
223int dma_channel_active(unsigned int channel)
224{
225 if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE) {
226 return 0;
227 } else {
228 return 1;
229 }
230}
231EXPORT_SYMBOL(dma_channel_active);
232
233/*------------------------------------------------------------------------------
234* stop the specific DMA channel.
235*-----------------------------------------------------------------------------*/
236void disable_dma(unsigned int channel)
237{
238 pr_debug("stop_dma() : BEGIN \n");
239
240 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
241 && channel < MAX_BLACKFIN_DMA_CHANNEL));
242
243 dma_ch[channel].regs->cfg &= ~DMAEN; /* Clean the enable bit */
244 SSYNC();
245 dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
246 /* Needs to be enabled Later */
247 pr_debug("stop_dma() : END \n");
248 return;
249}
250EXPORT_SYMBOL(disable_dma);
251
252void enable_dma(unsigned int channel)
253{
254 pr_debug("enable_dma() : BEGIN \n");
255
256 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
257 && channel < MAX_BLACKFIN_DMA_CHANNEL));
258
259 dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
260 dma_ch[channel].regs->curr_x_count = 0;
261 dma_ch[channel].regs->curr_y_count = 0;
262
263 dma_ch[channel].regs->cfg |= DMAEN; /* Set the enable bit */
264 SSYNC();
265 pr_debug("enable_dma() : END \n");
266 return;
267}
268EXPORT_SYMBOL(enable_dma);
269
270/*------------------------------------------------------------------------------
271* Set the Start Address register for the specific DMA channel
272* This function can be used for register based DMA,
273* to setup the start address
274* addr: Starting address of the DMA Data to be transferred.
275*-----------------------------------------------------------------------------*/
276void set_dma_start_addr(unsigned int channel, unsigned long addr)
277{
278 pr_debug("set_dma_start_addr() : BEGIN \n");
279
280 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
281 && channel < MAX_BLACKFIN_DMA_CHANNEL));
282
283 dma_ch[channel].regs->start_addr = addr;
284 SSYNC();
285 pr_debug("set_dma_start_addr() : END\n");
286}
287EXPORT_SYMBOL(set_dma_start_addr);
288
289void set_dma_next_desc_addr(unsigned int channel, unsigned long addr)
290{
291 pr_debug("set_dma_next_desc_addr() : BEGIN \n");
292
293 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
294 && channel < MAX_BLACKFIN_DMA_CHANNEL));
295
296 dma_ch[channel].regs->next_desc_ptr = addr;
297 SSYNC();
8a26ac70 298 pr_debug("set_dma_next_desc_addr() : END\n");
1394f032
BW
299}
300EXPORT_SYMBOL(set_dma_next_desc_addr);
301
8a26ac70
SZ
302void set_dma_curr_desc_addr(unsigned int channel, unsigned long addr)
303{
304 pr_debug("set_dma_curr_desc_addr() : BEGIN \n");
305
306 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
307 && channel < MAX_BLACKFIN_DMA_CHANNEL));
308
309 dma_ch[channel].regs->curr_desc_ptr = addr;
310 SSYNC();
311 pr_debug("set_dma_curr_desc_addr() : END\n");
312}
313EXPORT_SYMBOL(set_dma_curr_desc_addr);
314
1394f032
BW
315void set_dma_x_count(unsigned int channel, unsigned short x_count)
316{
317 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
318 && channel < MAX_BLACKFIN_DMA_CHANNEL));
319
320 dma_ch[channel].regs->x_count = x_count;
321 SSYNC();
322}
323EXPORT_SYMBOL(set_dma_x_count);
324
325void set_dma_y_count(unsigned int channel, unsigned short y_count)
326{
327 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
328 && channel < MAX_BLACKFIN_DMA_CHANNEL));
329
330 dma_ch[channel].regs->y_count = y_count;
331 SSYNC();
332}
333EXPORT_SYMBOL(set_dma_y_count);
334
335void set_dma_x_modify(unsigned int channel, short x_modify)
336{
337 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
338 && channel < MAX_BLACKFIN_DMA_CHANNEL));
339
340 dma_ch[channel].regs->x_modify = x_modify;
341 SSYNC();
342}
343EXPORT_SYMBOL(set_dma_x_modify);
344
345void set_dma_y_modify(unsigned int channel, short y_modify)
346{
347 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
348 && channel < MAX_BLACKFIN_DMA_CHANNEL));
349
350 dma_ch[channel].regs->y_modify = y_modify;
351 SSYNC();
352}
353EXPORT_SYMBOL(set_dma_y_modify);
354
355void set_dma_config(unsigned int channel, unsigned short config)
356{
357 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
358 && channel < MAX_BLACKFIN_DMA_CHANNEL));
359
360 dma_ch[channel].regs->cfg = config;
361 SSYNC();
362}
363EXPORT_SYMBOL(set_dma_config);
364
365unsigned short
366set_bfin_dma_config(char direction, char flow_mode,
2047e40d 367 char intr_mode, char dma_mode, char width, char syncmode)
1394f032
BW
368{
369 unsigned short config;
370
371 config =
372 ((direction << 1) | (width << 2) | (dma_mode << 4) |
2047e40d 373 (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5));
1394f032
BW
374 return config;
375}
376EXPORT_SYMBOL(set_bfin_dma_config);
377
1f83b8f1 378void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg)
1394f032
BW
379{
380 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
381 && channel < MAX_BLACKFIN_DMA_CHANNEL));
382
383 dma_ch[channel].regs->cfg |= ((nr_sg & 0x0F) << 8);
384
385 dma_ch[channel].regs->next_desc_ptr = (unsigned int)sg;
386
387 SSYNC();
388}
389EXPORT_SYMBOL(set_dma_sg);
390
1d945e2b
RH
391void set_dma_curr_addr(unsigned int channel, unsigned long addr)
392{
393 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
394 && channel < MAX_BLACKFIN_DMA_CHANNEL));
395
396 dma_ch[channel].regs->curr_addr_ptr = addr;
397 SSYNC();
398}
399EXPORT_SYMBOL(set_dma_curr_addr);
400
1394f032
BW
401/*------------------------------------------------------------------------------
402 * Get the DMA status of a specific DMA channel from the system.
403 *-----------------------------------------------------------------------------*/
404unsigned short get_dma_curr_irqstat(unsigned int channel)
405{
406 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
407 && channel < MAX_BLACKFIN_DMA_CHANNEL));
408
409 return dma_ch[channel].regs->irq_status;
410}
411EXPORT_SYMBOL(get_dma_curr_irqstat);
412
413/*------------------------------------------------------------------------------
414 * Clear the DMA_DONE bit in DMA status. Stop the DMA completion interrupt.
415 *-----------------------------------------------------------------------------*/
416void clear_dma_irqstat(unsigned int channel)
417{
418 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
419 && channel < MAX_BLACKFIN_DMA_CHANNEL));
420 dma_ch[channel].regs->irq_status |= 3;
421}
422EXPORT_SYMBOL(clear_dma_irqstat);
423
424/*------------------------------------------------------------------------------
425 * Get current DMA xcount of a specific DMA channel from the system.
426 *-----------------------------------------------------------------------------*/
427unsigned short get_dma_curr_xcount(unsigned int channel)
428{
429 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
430 && channel < MAX_BLACKFIN_DMA_CHANNEL));
431
432 return dma_ch[channel].regs->curr_x_count;
433}
434EXPORT_SYMBOL(get_dma_curr_xcount);
435
436/*------------------------------------------------------------------------------
437 * Get current DMA ycount of a specific DMA channel from the system.
438 *-----------------------------------------------------------------------------*/
439unsigned short get_dma_curr_ycount(unsigned int channel)
440{
441 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
442 && channel < MAX_BLACKFIN_DMA_CHANNEL));
443
444 return dma_ch[channel].regs->curr_y_count;
445}
446EXPORT_SYMBOL(get_dma_curr_ycount);
447
452af71f
BW
448unsigned long get_dma_next_desc_ptr(unsigned int channel)
449{
450 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
451 && channel < MAX_BLACKFIN_DMA_CHANNEL));
452
453 return dma_ch[channel].regs->next_desc_ptr;
454}
455EXPORT_SYMBOL(get_dma_next_desc_ptr);
456
457unsigned long get_dma_curr_desc_ptr(unsigned int channel)
458{
459 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
460 && channel < MAX_BLACKFIN_DMA_CHANNEL));
461
462 return dma_ch[channel].regs->curr_desc_ptr;
463}
28a44d4b 464EXPORT_SYMBOL(get_dma_curr_desc_ptr);
452af71f
BW
465
466unsigned long get_dma_curr_addr(unsigned int channel)
467{
468 BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
469 && channel < MAX_BLACKFIN_DMA_CHANNEL));
470
471 return dma_ch[channel].regs->curr_addr_ptr;
472}
473EXPORT_SYMBOL(get_dma_curr_addr);
474
ac1bd53c 475static void *__dma_memcpy(void *dest, const void *src, size_t size)
1394f032
BW
476{
477 int direction; /* 1 - address decrease, 0 - address increase */
478 int flag_align; /* 1 - address aligned, 0 - address unaligned */
479 int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */
23ee968d 480 unsigned long flags;
1394f032
BW
481
482 if (size <= 0)
483 return NULL;
1f83b8f1 484
23ee968d 485 local_irq_save(flags);
1394f032
BW
486
487 if ((unsigned long)src < memory_end)
488 blackfin_dcache_flush_range((unsigned int)src,
489 (unsigned int)(src + size));
490
1a7d91d6
MH
491 if ((unsigned long)dest < memory_end)
492 blackfin_dcache_invalidate_range((unsigned int)dest,
493 (unsigned int)(dest + size));
494
1394f032
BW
495 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
496
497 if ((unsigned long)src < (unsigned long)dest)
498 direction = 1;
499 else
500 direction = 0;
501
502 if ((((unsigned long)dest % 2) == 0) && (((unsigned long)src % 2) == 0)
503 && ((size % 2) == 0))
504 flag_align = 1;
505 else
506 flag_align = 0;
507
508 if (size > 0x10000) /* size > 64K */
509 flag_2D = 1;
510 else
511 flag_2D = 0;
512
513 /* Setup destination and source start address */
514 if (direction) {
515 if (flag_align) {
516 bfin_write_MDMA_D0_START_ADDR(dest + size - 2);
517 bfin_write_MDMA_S0_START_ADDR(src + size - 2);
518 } else {
519 bfin_write_MDMA_D0_START_ADDR(dest + size - 1);
520 bfin_write_MDMA_S0_START_ADDR(src + size - 1);
521 }
522 } else {
523 bfin_write_MDMA_D0_START_ADDR(dest);
524 bfin_write_MDMA_S0_START_ADDR(src);
525 }
526
527 /* Setup destination and source xcount */
528 if (flag_2D) {
529 if (flag_align) {
530 bfin_write_MDMA_D0_X_COUNT(1024 / 2);
531 bfin_write_MDMA_S0_X_COUNT(1024 / 2);
532 } else {
533 bfin_write_MDMA_D0_X_COUNT(1024);
534 bfin_write_MDMA_S0_X_COUNT(1024);
535 }
536 bfin_write_MDMA_D0_Y_COUNT(size >> 10);
537 bfin_write_MDMA_S0_Y_COUNT(size >> 10);
538 } else {
539 if (flag_align) {
540 bfin_write_MDMA_D0_X_COUNT(size / 2);
541 bfin_write_MDMA_S0_X_COUNT(size / 2);
542 } else {
543 bfin_write_MDMA_D0_X_COUNT(size);
544 bfin_write_MDMA_S0_X_COUNT(size);
545 }
546 }
547
548 /* Setup destination and source xmodify and ymodify */
549 if (direction) {
550 if (flag_align) {
551 bfin_write_MDMA_D0_X_MODIFY(-2);
552 bfin_write_MDMA_S0_X_MODIFY(-2);
553 if (flag_2D) {
554 bfin_write_MDMA_D0_Y_MODIFY(-2);
555 bfin_write_MDMA_S0_Y_MODIFY(-2);
556 }
557 } else {
558 bfin_write_MDMA_D0_X_MODIFY(-1);
559 bfin_write_MDMA_S0_X_MODIFY(-1);
560 if (flag_2D) {
561 bfin_write_MDMA_D0_Y_MODIFY(-1);
562 bfin_write_MDMA_S0_Y_MODIFY(-1);
563 }
564 }
565 } else {
566 if (flag_align) {
567 bfin_write_MDMA_D0_X_MODIFY(2);
568 bfin_write_MDMA_S0_X_MODIFY(2);
569 if (flag_2D) {
570 bfin_write_MDMA_D0_Y_MODIFY(2);
571 bfin_write_MDMA_S0_Y_MODIFY(2);
572 }
573 } else {
574 bfin_write_MDMA_D0_X_MODIFY(1);
575 bfin_write_MDMA_S0_X_MODIFY(1);
576 if (flag_2D) {
577 bfin_write_MDMA_D0_Y_MODIFY(1);
578 bfin_write_MDMA_S0_Y_MODIFY(1);
579 }
580 }
581 }
582
583 /* Enable source DMA */
584 if (flag_2D) {
585 if (flag_align) {
586 bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D | WDSIZE_16);
587 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D | WDSIZE_16);
588 } else {
589 bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D);
590 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D);
591 }
592 } else {
593 if (flag_align) {
594 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
595 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
596 } else {
597 bfin_write_MDMA_S0_CONFIG(DMAEN);
598 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN);
599 }
600 }
601
1a7d91d6
MH
602 SSYNC();
603
1394f032
BW
604 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
605 ;
606
607 bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() |
608 (DMA_DONE | DMA_ERR));
609
610 bfin_write_MDMA_S0_CONFIG(0);
611 bfin_write_MDMA_D0_CONFIG(0);
612
23ee968d 613 local_irq_restore(flags);
1394f032
BW
614
615 return dest;
616}
5f9a3e89
AL
617
618void *dma_memcpy(void *dest, const void *src, size_t size)
619{
620 size_t bulk;
621 size_t rest;
622 void * addr;
623
624 bulk = (size >> 16) << 16;
625 rest = size - bulk;
626 if (bulk)
ac1bd53c
AL
627 __dma_memcpy(dest, src, bulk);
628 addr = __dma_memcpy(dest+bulk, src+bulk, rest);
5f9a3e89
AL
629 return addr;
630}
1394f032
BW
631EXPORT_SYMBOL(dma_memcpy);
632
633void *safe_dma_memcpy(void *dest, const void *src, size_t size)
634{
1394f032 635 void *addr;
1394f032 636 addr = dma_memcpy(dest, src, size);
1394f032
BW
637 return addr;
638}
639EXPORT_SYMBOL(safe_dma_memcpy);
23ee968d 640
b7b2d344 641void dma_outsb(unsigned long addr, const void *buf, unsigned short len)
23ee968d 642{
23ee968d 643 unsigned long flags;
1f83b8f1 644
23ee968d 645 local_irq_save(flags);
23ee968d 646
1a7d91d6
MH
647 blackfin_dcache_flush_range((unsigned int)buf,
648 (unsigned int)(buf) + len);
1f83b8f1
MF
649
650 bfin_write_MDMA_D0_START_ADDR(addr);
23ee968d
MH
651 bfin_write_MDMA_D0_X_COUNT(len);
652 bfin_write_MDMA_D0_X_MODIFY(0);
653 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
654
655 bfin_write_MDMA_S0_START_ADDR(buf);
656 bfin_write_MDMA_S0_X_COUNT(len);
657 bfin_write_MDMA_S0_X_MODIFY(1);
658 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
659
660 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
661 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
662
1a7d91d6
MH
663 SSYNC();
664
23ee968d
MH
665 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
666
667 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
668
669 bfin_write_MDMA_S0_CONFIG(0);
670 bfin_write_MDMA_D0_CONFIG(0);
671 local_irq_restore(flags);
672
673}
674EXPORT_SYMBOL(dma_outsb);
675
676
b7b2d344 677void dma_insb(unsigned long addr, void *buf, unsigned short len)
23ee968d
MH
678{
679 unsigned long flags;
1f83b8f1 680
1a7d91d6
MH
681 blackfin_dcache_invalidate_range((unsigned int)buf,
682 (unsigned int)(buf) + len);
683
23ee968d 684 local_irq_save(flags);
1f83b8f1 685 bfin_write_MDMA_D0_START_ADDR(buf);
23ee968d
MH
686 bfin_write_MDMA_D0_X_COUNT(len);
687 bfin_write_MDMA_D0_X_MODIFY(1);
688 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
689
690 bfin_write_MDMA_S0_START_ADDR(addr);
691 bfin_write_MDMA_S0_X_COUNT(len);
692 bfin_write_MDMA_S0_X_MODIFY(0);
693 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
694
695 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
696 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
697
1a7d91d6 698 SSYNC();
23ee968d
MH
699
700 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
701
702 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
703
704 bfin_write_MDMA_S0_CONFIG(0);
705 bfin_write_MDMA_D0_CONFIG(0);
706 local_irq_restore(flags);
707
708}
709EXPORT_SYMBOL(dma_insb);
710
b7b2d344 711void dma_outsw(unsigned long addr, const void *buf, unsigned short len)
23ee968d
MH
712{
713 unsigned long flags;
1f83b8f1 714
23ee968d 715 local_irq_save(flags);
23ee968d 716
1a7d91d6
MH
717 blackfin_dcache_flush_range((unsigned int)buf,
718 (unsigned int)(buf) + len * sizeof(short));
1f83b8f1
MF
719
720 bfin_write_MDMA_D0_START_ADDR(addr);
23ee968d
MH
721 bfin_write_MDMA_D0_X_COUNT(len);
722 bfin_write_MDMA_D0_X_MODIFY(0);
723 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
724
725 bfin_write_MDMA_S0_START_ADDR(buf);
726 bfin_write_MDMA_S0_X_COUNT(len);
727 bfin_write_MDMA_S0_X_MODIFY(2);
728 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
729
730 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
731 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
732
1a7d91d6
MH
733 SSYNC();
734
23ee968d
MH
735 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
736
737 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
738
739 bfin_write_MDMA_S0_CONFIG(0);
740 bfin_write_MDMA_D0_CONFIG(0);
741 local_irq_restore(flags);
742
743}
744EXPORT_SYMBOL(dma_outsw);
745
b7b2d344 746void dma_insw(unsigned long addr, void *buf, unsigned short len)
23ee968d
MH
747{
748 unsigned long flags;
1f83b8f1 749
1a7d91d6
MH
750 blackfin_dcache_invalidate_range((unsigned int)buf,
751 (unsigned int)(buf) + len * sizeof(short));
752
23ee968d 753 local_irq_save(flags);
1f83b8f1
MF
754
755 bfin_write_MDMA_D0_START_ADDR(buf);
23ee968d
MH
756 bfin_write_MDMA_D0_X_COUNT(len);
757 bfin_write_MDMA_D0_X_MODIFY(2);
758 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
759
760 bfin_write_MDMA_S0_START_ADDR(addr);
761 bfin_write_MDMA_S0_X_COUNT(len);
762 bfin_write_MDMA_S0_X_MODIFY(0);
763 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
764
765 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
766 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
767
1a7d91d6 768 SSYNC();
23ee968d
MH
769
770 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
771
772 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
773
774 bfin_write_MDMA_S0_CONFIG(0);
775 bfin_write_MDMA_D0_CONFIG(0);
776 local_irq_restore(flags);
777
778}
779EXPORT_SYMBOL(dma_insw);
780
b7b2d344 781void dma_outsl(unsigned long addr, const void *buf, unsigned short len)
23ee968d
MH
782{
783 unsigned long flags;
1f83b8f1 784
23ee968d 785 local_irq_save(flags);
23ee968d 786
1a7d91d6
MH
787 blackfin_dcache_flush_range((unsigned int)buf,
788 (unsigned int)(buf) + len * sizeof(long));
1f83b8f1
MF
789
790 bfin_write_MDMA_D0_START_ADDR(addr);
23ee968d
MH
791 bfin_write_MDMA_D0_X_COUNT(len);
792 bfin_write_MDMA_D0_X_MODIFY(0);
793 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
794
795 bfin_write_MDMA_S0_START_ADDR(buf);
796 bfin_write_MDMA_S0_X_COUNT(len);
797 bfin_write_MDMA_S0_X_MODIFY(4);
798 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
799
800 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
801 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
802
1a7d91d6
MH
803 SSYNC();
804
23ee968d
MH
805 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
806
807 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
808
809 bfin_write_MDMA_S0_CONFIG(0);
810 bfin_write_MDMA_D0_CONFIG(0);
811 local_irq_restore(flags);
812
813}
814EXPORT_SYMBOL(dma_outsl);
815
b7b2d344 816void dma_insl(unsigned long addr, void *buf, unsigned short len)
23ee968d
MH
817{
818 unsigned long flags;
1f83b8f1 819
1a7d91d6
MH
820 blackfin_dcache_invalidate_range((unsigned int)buf,
821 (unsigned int)(buf) + len * sizeof(long));
822
23ee968d 823 local_irq_save(flags);
1f83b8f1
MF
824
825 bfin_write_MDMA_D0_START_ADDR(buf);
23ee968d
MH
826 bfin_write_MDMA_D0_X_COUNT(len);
827 bfin_write_MDMA_D0_X_MODIFY(4);
828 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
829
830 bfin_write_MDMA_S0_START_ADDR(addr);
831 bfin_write_MDMA_S0_X_COUNT(len);
832 bfin_write_MDMA_S0_X_MODIFY(0);
833 bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
834
835 bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
836 bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
837
1a7d91d6 838 SSYNC();
23ee968d
MH
839
840 while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
841
842 bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
843
844 bfin_write_MDMA_S0_CONFIG(0);
845 bfin_write_MDMA_D0_CONFIG(0);
846 local_irq_restore(flags);
847
848}
849EXPORT_SYMBOL(dma_insl);
This page took 0.182026 seconds and 5 git commands to generate.