Separate running an SDMA channel from resetting it. It should make usage more flexibl...
[kugel-rb.git] / firmware / target / arm / imx31 / sdma-imx31.c
blob100bd5102820fbfcb568d7f4fc795093c41399ac
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 by Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
22 #include "system.h"
23 #include <string.h>
24 #include "logf.h"
25 #include "panic.h"
26 #include "clkctl-imx31.h"
27 #include "avic-imx31.h"
28 #include "sdma_struct.h"
29 #include "sdma-imx31.h"
30 #include "sdma_script_code.h"
31 #include "mmu-imx31.h"
33 /* Most of the code in here is based upon the Linux BSP provided by Freescale
34 * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. */
36 /* Cut down to bare bones essentials */
38 /* Script information that depends on system revision */
39 static struct sdma_script_start_addrs script_info;
40 /* Mask of channels with callback enabled */
41 static unsigned long sdma_enabled_ints = 0;
42 /* One channel control block per channel in physically mapped device RAM */
43 static struct channel_control_block ccb_array[CH_NUM] DEVBSS_ATTR;
44 /* Channel 0 (command channel) data */
45 static struct buffer_descriptor_extd c0_buffer_desc DEVBSS_ATTR;
47 /* All SDMA channel interrupts are handled here.
48 * Dispatches lower channel numbers first (prioritized by SDMA API callers
49 * who specify the desired channel number).
51 static void __attribute__((interrupt("IRQ"))) SDMA_HANDLER(void)
53 unsigned long pending = SDMA_INTR;
55 SDMA_INTR = pending; /* Ack all ints */
56 pending &= sdma_enabled_ints; /* Only dispatch ints with callback */
58 while (1)
60 unsigned int channel;
62 if (pending == 0)
63 break; /* No bits set */
65 channel = find_first_set_bit(pending);
67 pending &= ~(1ul << channel);
69 /* Call callback (required if using an interrupt) */
70 ccb_array[channel].channel_desc->callback();
74 /* Initialize script information based upon the system revision */
75 static void init_script_info(void)
77 if (iim_system_rev() == IIM_SREV_1_0)
79 /* Channel script info */
80 script_info.app_2_mcu_addr = app_2_mcu_ADDR_1;
81 script_info.ap_2_ap_addr = ap_2_ap_ADDR_1;
82 script_info.ap_2_bp_addr = -1;
83 script_info.bp_2_ap_addr = -1;
84 script_info.loopback_on_dsp_side_addr = -1;
85 script_info.mcu_2_app_addr = mcu_2_app_ADDR_1;
86 script_info.mcu_2_shp_addr = mcu_2_shp_ADDR_1;
87 script_info.mcu_interrupt_only_addr = -1;
88 script_info.shp_2_mcu_addr = shp_2_mcu_ADDR_1;
89 script_info.uartsh_2_mcu_addr = uartsh_2_mcu_ADDR_1;
90 script_info.uart_2_mcu_addr = uart_2_mcu_ADDR_1;
91 script_info.dptc_dvfs_addr = dptc_dvfs_ADDR_1;
92 script_info.firi_2_mcu_addr = firi_2_mcu_ADDR_1;
93 script_info.firi_2_per_addr = -1;
94 script_info.mshc_2_mcu_addr = mshc_2_mcu_ADDR_1;
95 script_info.per_2_app_addr = -1;
96 script_info.per_2_firi_addr = -1;
97 script_info.per_2_shp_addr = -1;
98 script_info.mcu_2_ata_addr = mcu_2_ata_ADDR_1;
99 script_info.mcu_2_firi_addr = mcu_2_firi_ADDR_1;
100 script_info.mcu_2_mshc_addr = mcu_2_mshc_ADDR_1;
101 script_info.ata_2_mcu_addr = ata_2_mcu_ADDR_1;
102 script_info.uartsh_2_per_addr = -1;
103 script_info.shp_2_per_addr = -1;
104 script_info.uart_2_per_addr = -1;
105 script_info.app_2_per_addr = -1;
106 /* Main code block info */
107 script_info.ram_code_size = RAM_CODE_SIZE_1;
108 script_info.ram_code_start_addr = RAM_CODE_START_ADDR_1;
109 script_info.mcu_start_addr = (unsigned long)sdma_code_1;
111 else
113 /* Channel script info */
114 script_info.app_2_mcu_addr = app_2_mcu_patched_ADDR_2;
115 script_info.ap_2_ap_addr = ap_2_ap_ADDR_2;
116 script_info.ap_2_bp_addr = ap_2_bp_ADDR_2;
117 script_info.bp_2_ap_addr = bp_2_ap_ADDR_2;
118 script_info.loopback_on_dsp_side_addr = -1;
119 script_info.mcu_2_app_addr = mcu_2_app_ADDR_2;
120 script_info.mcu_2_shp_addr = mcu_2_shp_patched_ADDR_2;
121 script_info.mcu_interrupt_only_addr = -1;
122 script_info.shp_2_mcu_addr = shp_2_mcu_patched_ADDR_2;
123 script_info.uartsh_2_mcu_addr = uartsh_2_mcu_patched_ADDR_2;
124 script_info.uart_2_mcu_addr = uart_2_mcu_patched_ADDR_2;
125 script_info.dptc_dvfs_addr = -1;
126 script_info.firi_2_mcu_addr = firi_2_mcu_ADDR_2;
127 script_info.firi_2_per_addr = -1;
128 script_info.mshc_2_mcu_addr = -1;
129 script_info.per_2_app_addr = -1;
130 script_info.per_2_firi_addr = -1;
131 script_info.per_2_shp_addr = per_2_shp_ADDR_2;
132 script_info.mcu_2_ata_addr = mcu_2_ata_ADDR_2;
133 script_info.mcu_2_firi_addr = mcu_2_firi_ADDR_2;
134 script_info.mcu_2_mshc_addr = -1;
135 script_info.ata_2_mcu_addr = ata_2_mcu_ADDR_2;
136 script_info.uartsh_2_per_addr = -1;
137 script_info.shp_2_per_addr = shp_2_per_ADDR_2;
138 script_info.uart_2_per_addr = -1;
139 script_info.app_2_per_addr = -1;
140 /* Main code block info */
141 script_info.ram_code_size = RAM_CODE_SIZE_2;
142 script_info.ram_code_start_addr = RAM_CODE_START_ADDR_2;
143 script_info.mcu_start_addr = (unsigned long)sdma_code_2;
147 /* Return pc of SDMA script in SDMA halfword space according to peripheral
148 * and transfer type */
149 static unsigned long get_script_pc(unsigned int peripheral_type,
150 unsigned int transfer_type)
152 unsigned long res = (unsigned short)-1;
154 switch (peripheral_type)
156 case SDMA_PER_MEMORY:
157 switch (transfer_type)
159 case SDMA_TRAN_EMI_2_INT:
160 case SDMA_TRAN_EMI_2_EMI:
161 case SDMA_TRAN_INT_2_EMI:
162 res = script_info.ap_2_ap_addr;
163 break;
164 default:
165 break;
167 break;
169 #if 0 /* Not using this */
170 case SDMA_PER_DSP:
171 switch (transfer_type)
173 case SDMA_TRAN_EMI_2_DSP:
174 res = script_info.ap_2_bp_addr;
175 break;
176 case SDMA_TRAN_DSP_2_EMI:
177 res = script_info.bp_2_ap_addr;
178 break;
179 case SDMA_TRAN_DSP_2_EMI_LOOP:
180 res = script_info.loopback_on_dsp_side_addr;
181 break;
182 case SDMA_TRAN_EMI_2_DSP_LOOP:
183 res = script_info.mcu_interrupt_only_addr;
184 break;
185 default:
186 break;
188 break;
189 #endif
191 #if 0 /* Not using this */
192 case SDMA_PER_FIRI:
193 switch (transfer_type)
195 case SDMA_TRAN_PER_2_INT:
196 res = script_info.firi_2_per_addr;
197 break;
198 case SDMA_TRAN_PER_2_EMI:
199 res = script_info.firi_2_mcu_addr;
200 break;
201 case SDMA_TRAN_INT_2_PER:
202 res = script_info.per_2_firi_addr;
203 break;
204 case SDMA_TRAN_EMI_2_PER:
205 res = script_info.mcu_2_firi_addr;
206 break;
207 default:
208 break;
210 break;
211 #endif
213 #if 0 /* Not using this */
214 case SDMA_PER_UART:
215 switch (transfer_type)
217 case SDMA_TRAN_PER_2_INT:
218 res = script_info.uart_2_per_addr;
219 break;
220 case SDMA_TRAN_PER_2_EMI:
221 res = script_info.uart_2_mcu_addr;
222 break;
223 case SDMA_TRAN_INT_2_PER:
224 res = script_info.per_2_app_addr;
225 break;
226 case SDMA_TRAN_EMI_2_PER:
227 res = script_info.mcu_2_app_addr;
228 break;
229 default:
230 break;
232 break;
233 #endif
235 #if 0 /* Not using this */
236 case SDMA_PER_UART_SP:
237 switch (transfer_type)
239 case SDMA_TRAN_PER_2_INT:
240 res = script_info.uartsh_2_per_addr;
241 break;
242 case SDMA_TRAN_PER_2_EMI:
243 res = script_info.uartsh_2_mcu_addr;
244 break;
245 case SDMA_TRAN_INT_2_PER:
246 res = script_info.per_2_shp_addr;
247 break;
248 case SDMA_TRAN_EMI_2_PER:
249 res = script_info.mcu_2_shp_addr;
250 break;
251 default:
252 break;
254 break;
255 #endif
257 case SDMA_PER_ATA:
258 switch (transfer_type)
260 case SDMA_TRAN_PER_2_EMI:
261 res = script_info.ata_2_mcu_addr;
262 break;
263 case SDMA_TRAN_EMI_2_PER:
264 res = script_info.mcu_2_ata_addr;
265 break;
266 default:
267 break;
269 break;
271 case SDMA_PER_CSPI:
272 case SDMA_PER_EXT:
273 case SDMA_PER_SSI:
274 switch (transfer_type)
276 case SDMA_TRAN_PER_2_INT:
277 res = script_info.app_2_per_addr;
278 break;
279 case SDMA_TRAN_PER_2_EMI:
280 res = script_info.app_2_mcu_addr;
281 break;
282 case SDMA_TRAN_INT_2_PER:
283 res = script_info.per_2_app_addr;
284 break;
285 case SDMA_TRAN_EMI_2_PER:
286 res = script_info.mcu_2_app_addr;
287 break;
288 default:
289 break;
291 break;
293 #if 0 /* Not using this */
294 case SDMA_PER_MMC:
295 case SDMA_PER_SDHC:
296 #endif
297 case SDMA_PER_SSI_SP:
298 case SDMA_PER_CSPI_SP:
299 switch (transfer_type)
301 case SDMA_TRAN_PER_2_INT:
302 res = script_info.shp_2_per_addr;
303 break;
304 case SDMA_TRAN_PER_2_EMI:
305 res = script_info.shp_2_mcu_addr;
306 break;
307 case SDMA_TRAN_INT_2_PER:
308 res = script_info.per_2_shp_addr;
309 break;
310 case SDMA_TRAN_EMI_2_PER:
311 res = script_info.mcu_2_shp_addr;
312 break;
313 default:
314 break;
317 case SDMA_PER_MSHC:
318 switch (transfer_type)
320 case SDMA_TRAN_PER_2_EMI:
321 res = script_info.mshc_2_mcu_addr;
322 break;
323 case SDMA_TRAN_EMI_2_PER:
324 res = script_info.mcu_2_mshc_addr;
325 break;
326 default:
327 break;
330 case SDMA_PER_CCM:
331 switch (transfer_type)
333 case SDMA_TRAN_PER_2_EMI:
334 res = script_info.dptc_dvfs_addr;
335 break;
336 default:
337 break;
341 if (res == (unsigned short)-1)
343 logf("SDMA script not found\n");
346 return res;
349 static unsigned int get_config(unsigned int transfer_type)
351 unsigned int res = -1;
353 switch (transfer_type)
355 case SDMA_TRAN_PER_2_INT:
356 case SDMA_TRAN_PER_2_EMI:
357 case SDMA_TRAN_INT_2_PER:
358 case SDMA_TRAN_EMI_2_PER:
360 * Peripheral <------> Memory
361 * evtOvr = 0 mcuOvr = 0 dspOvr = 1
363 res = CH_OWNSHP_MCU | CH_OWNSHP_EVT;
364 break;
366 #if 0 /* Not using this */
367 case SDMA_TRAN_DSP_2_PER:
368 res = 0;
369 break;
370 case SDMA_TRAN_EMI_2_DSP:
371 case SDMA_TRAN_INT_2_DSP:
372 case SDMA_TRAN_DSP_2_INT:
373 case SDMA_TRAN_DSP_2_EMI:
374 case SDMA_TRAN_DSP_2_DSP:
376 * DSP <-----------> Memory
377 * evtOvr = 1 mcuOvr = 0 dspOvr = 0
379 res = CH_OWNSHP_MCU | CH_OWNSHP_DSP;
380 break;
381 #endif
383 case SDMA_TRAN_EMI_2_INT:
384 case SDMA_TRAN_EMI_2_EMI:
385 case SDMA_TRAN_INT_2_INT:
386 case SDMA_TRAN_INT_2_EMI:
387 #if 0 /* Not using this */
388 case SDMA_TRAN_DSP_2_EMI_LOOP:
389 case SDMA_TRAN_EMI_2_DSP_LOOP:
390 #endif
391 /* evtOvr = 1 mcuOvr = 0 dspOvr = 1 */
392 res = CH_OWNSHP_MCU;
393 break;
395 #if 0 /* Not using this */
396 case SDMA_TRAN_PER_2_DSP:
397 /* evtOvr = 0 mcuOvr = 1 dspOvr = 0 */
398 res = CH_OWNSHP_DSP | CH_OWNSHP_EVT;
399 break;
400 #endif
402 default:
403 break;
406 return res;
409 /* Fill the buffer descriptor with the values given in parameter.
410 * Expects physical addresses. */
411 static inline void set_buffer_descriptor(
412 struct buffer_descriptor *bd_p,
413 unsigned int command, /* C0_* command or transfer size */
414 unsigned int status, /* BD_* flags */
415 unsigned int count, /* Size of buffer to transfer */
416 void *buf_addr, /* Buffer to transfer */
417 void *buf_addr_ext)
419 bd_p->mode.command = command;
420 bd_p->mode.status = status;
421 bd_p->mode.count = count;
422 bd_p->buf_addr = buf_addr;
423 if (status & BD_EXTD)
424 ((struct buffer_descriptor_extd *)bd_p)->buf_addr_ext = buf_addr_ext;
427 /* Configure channel ownership */
428 static void set_channel_ownership(unsigned int channel, unsigned int config)
430 unsigned long bit = 1ul << channel;
432 /* DSP side */
433 #if 0 /* Not using this */
434 imx31_regmod32(&SDMA_DSPOVR, (config & CH_OWNSHP_DSP) ? 0 : bit, bit);
435 #endif
436 /* Event */
437 imx31_regmod32(&SDMA_EVTOVR, (config & CH_OWNSHP_EVT) ? 0 : bit, bit);
438 /* MCU side */
439 imx31_regmod32(&SDMA_HOSTOVR, (config & CH_OWNSHP_MCU) ? 0 : bit, bit);
442 static bool setup_channel(struct channel_control_block *ccb_p)
444 struct context_data context_buffer;
445 struct channel_descriptor *cd_p;
446 unsigned int channel_cfg;
447 unsigned int channel;
448 unsigned long pc;
450 memset(&context_buffer, 0x00, sizeof (context_buffer));
452 channel = ccb_p - ccb_array;
453 cd_p = ccb_p->channel_desc;
455 /* Obtain script start address for perihperal and transfer type */
456 pc = get_script_pc(cd_p->per_type, cd_p->tran_type);
458 if (pc == (unsigned short)-1)
459 return false; /* Failed to find a script */
461 context_buffer.channel_state.pc = pc;
463 if (cd_p->per_type != SDMA_PER_MEMORY && cd_p->per_type != SDMA_PER_DSP)
465 /* Set peripheral DMA request mask for this channel */
466 context_buffer.event_mask1 = 1ul << cd_p->event_id1;
468 if (cd_p->per_type == SDMA_PER_ATA)
470 /* ATA has two */
471 context_buffer.event_mask2 = 1ul << cd_p->event_id2;
474 context_buffer.shp_addr = cd_p->shp_addr;
475 context_buffer.wml = cd_p->wml;
477 else
479 context_buffer.wml = SDMA_PER_ADDR_SDRAM;
482 /* Send channel context to SDMA core */
483 clean_dcache_range(&context_buffer, sizeof (context_buffer));
484 sdma_write_words((unsigned long *)&context_buffer,
485 CHANNEL_CONTEXT_ADDR(channel),
486 sizeof (context_buffer)/4);
488 if (cd_p->is_setup != 0)
489 return true; /* No more to do */
491 /* Obtain channel ownership configuration */
492 channel_cfg = get_config(cd_p->tran_type);
494 if (channel_cfg == (unsigned int)-1)
495 return false;
497 /* Set who owns it and thus can activate it */
498 set_channel_ownership(channel, channel_cfg);
500 if (channel_cfg & CH_OWNSHP_EVT)
502 /* Set event ID to channel activation bitmapping */
503 imx31_regset32(&SDMA_CHNENBL(cd_p->event_id1), 1ul << channel);
505 if (cd_p->per_type == SDMA_PER_ATA)
507 /* ATA has two */
508 imx31_regset32(&SDMA_CHNENBL(cd_p->event_id2), 1ul << channel);
512 cd_p->is_setup = 1;
514 return true;
517 /** Public routines **/
518 void sdma_init(void)
520 imx31_clkctl_module_clock_gating(CG_SDMA, CGM_ON_RUN_WAIT);
521 int i;
522 unsigned long acr;
524 /* Reset the controller */
525 SDMA_RESET |= SDMA_RESET_RESET;
526 while (SDMA_RESET & SDMA_RESET_RESET);
528 init_script_info();
530 /* No channel enabled, all priorities 0 */
531 for (i = 0; i < CH_NUM; i++)
533 SDMA_CHNENBL(i) = 0;
534 SDMA_CHNPRI(i) = 0;
537 /* Ensure no ints pending */
538 SDMA_INTR = 0xffffffff;
540 /* Nobody owns any channel (yet) */
541 SDMA_HOSTOVR = 0xffffffff;
542 SDMA_DSPOVR = 0xffffffff;
543 SDMA_EVTOVR = 0xffffffff;
545 SDMA_MC0PTR = 0x00000000;
547 /* 32-word channel contexts, use default bootscript address */
548 SDMA_CHN0ADDR = SDMA_CHN0ADDR_SMSZ | 0x0050;
550 avic_enable_int(SDMA, IRQ, 8, SDMA_HANDLER);
552 /* SDMA core must run at the proper frequency based upon the AHB/IPG ratio */
553 acr = (imx31_clkctl_get_ahb_clk() / imx31_clkctl_get_ipg_clk()) < 2 ?
554 SDMA_CONFIG_ACR : 0;
556 /* No dsp, no debug
557 * Static context switching - TLSbo86520L SW Workaround for SDMA Chnl0
558 * access issue */
559 SDMA_CONFIG = acr;
561 /* Tell SDMA where the host channel table is */
562 SDMA_MC0PTR = (unsigned long)ccb_array;
564 ccb_array[0].status.opened_init = 1;
565 ccb_array[0].curr_bd_ptr = &c0_buffer_desc.bd;
566 ccb_array[0].base_bd_ptr = &c0_buffer_desc.bd;
567 ccb_array[0].channel_desc = NULL; /* No channel descriptor */
569 /* Command channel owned by AP */
570 set_channel_ownership(0, CH_OWNSHP_MCU);
572 sdma_channel_set_priority(0, 1);
574 /* Load SDMA script code */
575 set_buffer_descriptor(&c0_buffer_desc.bd,
576 C0_SETPM,
577 BD_DONE | BD_WRAP | BD_EXTD,
578 script_info.ram_code_size,
579 (void *)addr_virt_to_phys(script_info.mcu_start_addr),
580 (void *)(unsigned long)script_info.ram_code_start_addr);
582 SDMA_HSTART = 1ul;
583 sdma_channel_wait_nonblocking(0);
585 /* No dsp, no debug, dynamic context switching */
586 SDMA_CONFIG = acr | SDMA_CONFIG_CSM_DYNAMIC;
589 /* Busy wait for a channel to complete */
590 void sdma_channel_wait_nonblocking(unsigned int channel)
592 unsigned long mask;
594 if (channel >= CH_NUM)
595 return;
597 if (ccb_array[channel].status.opened_init == 0)
598 return;
600 mask = 1ul << channel;
601 while (SDMA_STOP_STAT & mask);
604 /* Set a new channel priority */
605 void sdma_channel_set_priority(unsigned int channel, unsigned int priority)
607 if (channel >= CH_NUM || priority > MAX_CH_PRIORITY)
608 return;
610 if (ccb_array[channel].status.opened_init == 0)
611 return;
613 SDMA_CHNPRI(channel) = priority;
616 /* Resets a channel to start of script next time it runs. */
617 bool sdma_channel_reset(unsigned int channel)
619 struct channel_control_block *ccb_p;
621 if (channel == 0 || channel >= CH_NUM)
622 return false;
624 ccb_p = &ccb_array[channel];
626 if (ccb_p->status.opened_init == 0)
627 return false;
629 if (!setup_channel(ccb_p))
630 return false;
632 return true;
635 /* Resume or start execution on a channel */
636 void sdma_channel_run(unsigned int channel)
638 if (channel == 0 || channel >= CH_NUM)
639 return;
641 if (ccb_array[channel].status.opened_init == 0)
642 return;
644 SDMA_HSTART = 1ul << channel;
647 /* Pause a running channel - can be resumed */
648 void sdma_channel_pause(unsigned int channel)
650 if (channel == 0 || channel >= CH_NUM)
651 return;
653 if (ccb_array[channel].status.opened_init == 0)
654 return;
656 SDMA_STOP_STAT = 1ul << channel;
659 /* Stop a channel from executing - cannot be resumed */
660 void sdma_channel_stop(unsigned int channel)
662 struct channel_control_block *ccb_p;
663 unsigned long chmsk;
664 unsigned long intmsk;
665 int oldstatus;
666 int i;
668 if (channel == 0 || channel >= CH_NUM)
669 return;
671 ccb_p = &ccb_array[channel];
673 if (ccb_p->status.opened_init == 0)
674 return;
676 chmsk = 1ul << channel;
678 /* Lock callback */
679 oldstatus = disable_irq_save();
680 intmsk = sdma_enabled_ints;
681 sdma_enabled_ints &= ~chmsk;
682 restore_irq(oldstatus);
684 /* Stop execution */
685 for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--)
686 ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE;
688 SDMA_STOP_STAT = chmsk;
689 while (SDMA_STOP_STAT & chmsk);
691 /* Unlock callback if it was set */
692 if (intmsk & chmsk)
693 imx31_regset32(&sdma_enabled_ints, chmsk);
695 logf("SDMA ch closed: %d", channel);
698 bool sdma_channel_init(unsigned int channel,
699 struct channel_descriptor *cd_p,
700 struct buffer_descriptor *base_bd_p)
702 struct channel_control_block *ccb_p;
704 if (channel == 0 || channel >= CH_NUM ||
705 cd_p == NULL || base_bd_p == NULL)
706 return false;
708 ccb_p = &ccb_array[channel];
710 /* If initialized already, should close first then init. */
711 if (ccb_p->status.opened_init != 0)
712 return false;
714 /* Initialize channel control block. */
715 ccb_p->curr_bd_ptr = base_bd_p;
716 ccb_p->base_bd_ptr = base_bd_p;
717 ccb_p->channel_desc = cd_p;
718 ccb_p->status.error = 0;
719 ccb_p->status.opened_init = 1;
720 ccb_p->status.state_direction = 0;
721 ccb_p->status.execute = 0;
723 /* Finish any channel descriptor inits. */
724 cd_p->ccb_ptr = ccb_p;
725 cd_p->is_setup = 0;
727 /* Do an initial setup now. */
728 if (!setup_channel(ccb_p))
730 logf("SDMA ch init failed: %d", channel);
731 cd_p->ccb_ptr = NULL;
732 memset(ccb_p, 0x00, sizeof (struct channel_control_block));
733 return false;
736 /* Enable interrupt if a callback is specified. */
737 if (cd_p->callback != NULL)
738 imx31_regset32(&sdma_enabled_ints, 1ul << channel);
740 /* Minimum schedulable = 1 */
741 sdma_channel_set_priority(channel, 1);
743 logf("SDMA ch initialized: %d", channel);
744 return true;
747 void sdma_channel_close(unsigned int channel)
749 struct channel_control_block *ccb_p;
750 int i;
752 if (channel == 0 || channel >= CH_NUM)
753 return;
755 ccb_p = &ccb_array[channel];
757 /* Block callbacks (if not initialized, it won't be set). */
758 imx31_regclr32(&sdma_enabled_ints, 1ul << channel);
760 if (ccb_p->status.opened_init == 0)
761 return;
763 /* Stop the channel if running */
764 for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--)
765 ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE;
767 sdma_channel_stop(channel);
769 /* No ownership */
770 set_channel_ownership(channel, 0);
772 /* Cannot schedule it again */
773 sdma_channel_set_priority(channel, 0);
775 /* Reset channel control block entry */
776 memset(ccb_p, 0x00, sizeof (struct channel_control_block));
779 /* Write 32-bit words to SDMA core memory. Host endian->SDMA endian. */
780 void sdma_write_words(const unsigned long *buf, unsigned long start, int count)
782 /* Setup buffer descriptor with channel 0 command */
783 set_buffer_descriptor(&c0_buffer_desc.bd,
784 C0_SETDM,
785 BD_DONE | BD_WRAP | BD_EXTD,
786 count,
787 (void *)addr_virt_to_phys((unsigned long)buf),
788 (void *)start);
790 SDMA_HSTART = 1ul;
791 sdma_channel_wait_nonblocking(0);
794 /* Read 32-bit words from SDMA core memory. SDMA endian->host endian. */
795 void sdma_read_words(unsigned long *buf, unsigned long start, int count)
797 /* Setup buffer descriptor with channel 0 command */
798 set_buffer_descriptor(&c0_buffer_desc.bd,
799 C0_GETDM,
800 BD_DONE | BD_WRAP | BD_EXTD,
801 count,
802 (void *)addr_virt_to_phys((unsigned long)buf),
803 (void *)start);
805 SDMA_HSTART = 1ul;
806 sdma_channel_wait_nonblocking(0);