Configure Gigabeat S with EABI compiler by default. Implement the INIT section that...
[kugel-rb.git] / firmware / target / arm / imx31 / sdma-imx31.c
blob4928108f6779685e712d8a963f239a364a306e4f
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 "ccm-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] NOCACHEBSS_ATTR;
44 /* Channel 0 (command channel) data */
45 static struct buffer_descriptor_extd c0_buffer_desc NOCACHEBSS_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_patched_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;
165 break;
167 #if 0 /* Not using this */
168 case SDMA_PER_DSP:
169 switch (transfer_type)
171 case SDMA_TRAN_EMI_2_DSP:
172 res = script_info.ap_2_bp_addr;
173 break;
174 case SDMA_TRAN_DSP_2_EMI:
175 res = script_info.bp_2_ap_addr;
176 break;
177 case SDMA_TRAN_DSP_2_EMI_LOOP:
178 res = script_info.loopback_on_dsp_side_addr;
179 break;
180 case SDMA_TRAN_EMI_2_DSP_LOOP:
181 res = script_info.mcu_interrupt_only_addr;
182 break;
184 break;
185 #endif
187 #if 0 /* Not using this */
188 case SDMA_PER_FIRI:
189 switch (transfer_type)
191 case SDMA_TRAN_PER_2_INT:
192 res = script_info.firi_2_per_addr;
193 break;
194 case SDMA_TRAN_PER_2_EMI:
195 res = script_info.firi_2_mcu_addr;
196 break;
197 case SDMA_TRAN_INT_2_PER:
198 res = script_info.per_2_firi_addr;
199 break;
200 case SDMA_TRAN_EMI_2_PER:
201 res = script_info.mcu_2_firi_addr;
202 break;
204 break;
205 #endif
207 #if 0 /* Not using this */
208 case SDMA_PER_UART:
209 switch (transfer_type)
211 case SDMA_TRAN_PER_2_INT:
212 res = script_info.uart_2_per_addr;
213 break;
214 case SDMA_TRAN_PER_2_EMI:
215 res = script_info.uart_2_mcu_addr;
216 break;
217 case SDMA_TRAN_INT_2_PER:
218 res = script_info.per_2_app_addr;
219 break;
220 case SDMA_TRAN_EMI_2_PER:
221 res = script_info.mcu_2_app_addr;
222 break;
224 break;
225 #endif
227 #if 0 /* Not using this */
228 case SDMA_PER_UART_SHP:
229 switch (transfer_type)
231 case SDMA_TRAN_PER_2_INT:
232 res = script_info.uartsh_2_per_addr;
233 break;
234 case SDMA_TRAN_PER_2_EMI:
235 res = script_info.uartsh_2_mcu_addr;
236 break;
237 case SDMA_TRAN_INT_2_PER:
238 res = script_info.per_2_shp_addr;
239 break;
240 case SDMA_TRAN_EMI_2_PER:
241 res = script_info.mcu_2_shp_addr;
242 break;
244 break;
245 #endif
247 case SDMA_PER_ATA:
248 switch (transfer_type)
250 case SDMA_TRAN_PER_2_EMI:
251 res = script_info.ata_2_mcu_addr;
252 break;
253 case SDMA_TRAN_EMI_2_PER:
254 res = script_info.mcu_2_ata_addr;
255 break;
257 break;
259 case SDMA_PER_CSPI:
260 case SDMA_PER_EXT:
261 case SDMA_PER_SSI:
262 switch (transfer_type)
264 case SDMA_TRAN_PER_2_INT:
265 res = script_info.app_2_per_addr;
266 break;
267 case SDMA_TRAN_PER_2_EMI:
268 res = script_info.app_2_mcu_addr;
269 break;
270 case SDMA_TRAN_INT_2_PER:
271 res = script_info.per_2_app_addr;
272 break;
273 case SDMA_TRAN_EMI_2_PER:
274 res = script_info.mcu_2_app_addr;
275 break;
277 break;
279 #if 0 /* Not using this */
280 case SDMA_PER_MMC:
281 case SDMA_PER_SDHC:
282 #endif
283 case SDMA_PER_SSI_SHP:
284 case SDMA_PER_CSPI_SHP:
285 switch (transfer_type)
287 case SDMA_TRAN_PER_2_INT:
288 res = script_info.shp_2_per_addr;
289 break;
290 case SDMA_TRAN_PER_2_EMI:
291 res = script_info.shp_2_mcu_addr;
292 break;
293 case SDMA_TRAN_INT_2_PER:
294 res = script_info.per_2_shp_addr;
295 break;
296 case SDMA_TRAN_EMI_2_PER:
297 res = script_info.mcu_2_shp_addr;
298 break;
300 break;
302 case SDMA_PER_MSHC:
303 switch (transfer_type)
305 case SDMA_TRAN_PER_2_EMI:
306 res = script_info.mshc_2_mcu_addr;
307 break;
308 case SDMA_TRAN_EMI_2_PER:
309 res = script_info.mcu_2_mshc_addr;
310 break;
312 break;
314 case SDMA_PER_CCM:
315 switch (transfer_type)
317 case SDMA_TRAN_PER_2_EMI:
318 res = script_info.dptc_dvfs_addr;
319 break;
321 break;
324 if (res == (unsigned short)-1)
326 logf("SDMA script not found\n");
329 return res;
332 static unsigned int get_config(unsigned int transfer_type)
334 unsigned int res = -1;
336 switch (transfer_type)
338 case SDMA_TRAN_PER_2_INT:
339 case SDMA_TRAN_PER_2_EMI:
340 case SDMA_TRAN_INT_2_PER:
341 case SDMA_TRAN_EMI_2_PER:
343 * Peripheral <------> Memory
344 * evtOvr = 0 mcuOvr = 0 dspOvr = 1
346 res = CH_OWNSHP_MCU | CH_OWNSHP_EVT;
347 break;
349 #if 0 /* Not using this */
350 case SDMA_TRAN_DSP_2_PER:
351 res = 0;
352 break;
353 case SDMA_TRAN_EMI_2_DSP:
354 case SDMA_TRAN_INT_2_DSP:
355 case SDMA_TRAN_DSP_2_INT:
356 case SDMA_TRAN_DSP_2_EMI:
357 case SDMA_TRAN_DSP_2_DSP:
359 * DSP <-----------> Memory
360 * evtOvr = 1 mcuOvr = 0 dspOvr = 0
362 res = CH_OWNSHP_MCU | CH_OWNSHP_DSP;
363 break;
364 #endif
366 case SDMA_TRAN_EMI_2_INT:
367 case SDMA_TRAN_EMI_2_EMI:
368 case SDMA_TRAN_INT_2_INT:
369 case SDMA_TRAN_INT_2_EMI:
370 #if 0 /* Not using this */
371 case SDMA_TRAN_DSP_2_EMI_LOOP:
372 case SDMA_TRAN_EMI_2_DSP_LOOP:
373 #endif
374 /* evtOvr = 1 mcuOvr = 0 dspOvr = 1 */
375 res = CH_OWNSHP_MCU;
376 break;
378 #if 0 /* Not using this */
379 case SDMA_TRAN_PER_2_DSP:
380 /* evtOvr = 0 mcuOvr = 1 dspOvr = 0 */
381 res = CH_OWNSHP_DSP | CH_OWNSHP_EVT;
382 break;
383 #endif
385 default:
386 break;
389 return res;
392 /* Fill the buffer descriptor with the values given in parameter.
393 * Expects physical addresses. */
394 static inline void set_buffer_descriptor(
395 struct buffer_descriptor *bd_p,
396 unsigned int command, /* C0_* command or transfer size */
397 unsigned int status, /* BD_* flags */
398 unsigned int count, /* Size of buffer to transfer */
399 void *buf_addr, /* Buffer to transfer */
400 void *buf_addr_ext)
402 bd_p->mode.command = command;
403 bd_p->mode.status = status;
404 bd_p->mode.count = count;
405 bd_p->buf_addr = buf_addr;
406 if (status & BD_EXTD)
407 ((struct buffer_descriptor_extd *)bd_p)->buf_addr_ext = buf_addr_ext;
410 /* Configure channel ownership */
411 static void set_channel_ownership(unsigned int channel, unsigned int config)
413 unsigned long bit = 1ul << channel;
415 /* DSP side */
416 #if 0 /* Not using this */
417 imx31_regmod32(&SDMA_DSPOVR, (config & CH_OWNSHP_DSP) ? 0 : bit, bit);
418 #endif
419 /* Event */
420 imx31_regmod32(&SDMA_EVTOVR, (config & CH_OWNSHP_EVT) ? 0 : bit, bit);
421 /* MCU side */
422 imx31_regmod32(&SDMA_HOSTOVR, (config & CH_OWNSHP_MCU) ? 0 : bit, bit);
425 static bool setup_channel(struct channel_control_block *ccb_p)
427 struct context_data context_buffer;
428 struct channel_descriptor *cd_p;
429 unsigned int channel_cfg;
430 unsigned int channel;
431 unsigned long pc;
433 memset(&context_buffer, 0x00, sizeof (context_buffer));
435 channel = ccb_p - ccb_array;
436 cd_p = ccb_p->channel_desc;
438 /* Obtain script start address for perihperal and transfer type */
439 pc = get_script_pc(cd_p->per_type, cd_p->tran_type);
441 if (pc == (unsigned short)-1)
442 return false; /* Failed to find a script */
444 context_buffer.channel_state.pc = pc;
446 if (cd_p->per_type != SDMA_PER_MEMORY && cd_p->per_type != SDMA_PER_DSP)
448 /* Set peripheral DMA request mask for this channel */
449 context_buffer.event_mask1 = 1ul << cd_p->event_id1;
451 if (cd_p->per_type == SDMA_PER_ATA)
453 /* ATA has two */
454 context_buffer.event_mask2 = 1ul << cd_p->event_id2;
457 context_buffer.shp_addr = cd_p->shp_addr;
458 context_buffer.wml = cd_p->wml;
460 else
462 context_buffer.wml = SDMA_PER_ADDR_SDRAM;
465 /* Send channel context to SDMA core */
466 clean_dcache_range(&context_buffer, sizeof (context_buffer));
467 sdma_write_words((unsigned long *)&context_buffer,
468 CHANNEL_CONTEXT_ADDR(channel),
469 sizeof (context_buffer)/4);
471 ccb_p->status.error = 0; /* Clear channel-wide error flag */
473 if (cd_p->is_setup != 0)
474 return true; /* No more to do */
476 /* Obtain channel ownership configuration */
477 channel_cfg = get_config(cd_p->tran_type);
479 if (channel_cfg == (unsigned int)-1)
480 return false;
482 /* Set who owns it and thus can activate it */
483 set_channel_ownership(channel, channel_cfg);
485 if (channel_cfg & CH_OWNSHP_EVT)
487 /* Set event ID to channel activation bitmapping */
488 imx31_regset32(&SDMA_CHNENBL(cd_p->event_id1), 1ul << channel);
490 if (cd_p->per_type == SDMA_PER_ATA)
492 /* ATA has two */
493 imx31_regset32(&SDMA_CHNENBL(cd_p->event_id2), 1ul << channel);
497 cd_p->is_setup = 1;
499 return true;
502 /** Public routines **/
503 void INIT_ATTR sdma_init(void)
505 int i;
506 unsigned long acr;
508 ccm_module_clock_gating(CG_SDMA, CGM_ON_RUN_WAIT);
510 /* Reset the controller */
511 SDMA_RESET |= SDMA_RESET_RESET;
512 while (SDMA_RESET & SDMA_RESET_RESET);
514 init_script_info();
516 /* No channel enabled, all priorities 0 */
517 for (i = 0; i < CH_NUM; i++)
519 SDMA_CHNENBL(i) = 0;
520 SDMA_CHNPRI(i) = 0;
523 /* Ensure no ints pending */
524 SDMA_INTR = 0xffffffff;
526 /* Nobody owns any channel (yet) */
527 SDMA_HOSTOVR = 0xffffffff;
528 SDMA_DSPOVR = 0xffffffff;
529 SDMA_EVTOVR = 0xffffffff;
531 SDMA_MC0PTR = 0x00000000;
533 /* 32-word channel contexts, use default bootscript address */
534 SDMA_CHN0ADDR = SDMA_CHN0ADDR_SMSZ | 0x0050;
536 avic_enable_int(INT_SDMA, INT_TYPE_IRQ, INT_PRIO_SDMA, SDMA_HANDLER);
538 /* SDMA core must run at the proper frequency based upon the AHB/IPG
539 * ratio */
540 acr = (ccm_get_ahb_clk() / ccm_get_ipg_clk()) < 2 ? SDMA_CONFIG_ACR : 0;
542 /* No dsp, no debug
543 * Static context switching - TLSbo86520L SW Workaround for SDMA Chnl0
544 * access issue */
545 SDMA_CONFIG = acr;
547 /* Tell SDMA where the host channel table is */
548 SDMA_MC0PTR = (unsigned long)ccb_array;
550 ccb_array[0].status.opened_init = 1;
551 ccb_array[0].curr_bd_ptr = &c0_buffer_desc.bd;
552 ccb_array[0].base_bd_ptr = &c0_buffer_desc.bd;
553 ccb_array[0].channel_desc = NULL; /* No channel descriptor */
555 /* Command channel owned by AP */
556 set_channel_ownership(0, CH_OWNSHP_MCU);
558 sdma_channel_set_priority(0, 1);
560 /* Load SDMA script code */
561 set_buffer_descriptor(&c0_buffer_desc.bd,
562 C0_SETPM,
563 BD_DONE | BD_WRAP | BD_EXTD,
564 script_info.ram_code_size,
565 (void *)addr_virt_to_phys(script_info.mcu_start_addr),
566 (void *)(unsigned long)script_info.ram_code_start_addr);
568 SDMA_HSTART = 1ul;
569 sdma_channel_wait_nonblocking(0);
571 /* No dsp, no debug, dynamic context switching */
572 SDMA_CONFIG = acr | SDMA_CONFIG_CSM_DYNAMIC;
575 /* Busy wait for a channel to complete */
576 void sdma_channel_wait_nonblocking(unsigned int channel)
578 unsigned long mask;
580 if (channel >= CH_NUM)
581 return;
583 if (ccb_array[channel].status.opened_init == 0)
584 return;
586 mask = 1ul << channel;
587 while (SDMA_STOP_STAT & mask);
590 /* Set a new channel priority */
591 void sdma_channel_set_priority(unsigned int channel, unsigned int priority)
593 if (channel >= CH_NUM || priority > MAX_CH_PRIORITY)
594 return;
596 if (ccb_array[channel].status.opened_init == 0)
597 return;
599 SDMA_CHNPRI(channel) = priority;
602 /* Resets a channel to start of script next time it runs. */
603 bool sdma_channel_reset(unsigned int channel)
605 struct channel_control_block *ccb_p;
607 if (channel == 0 || channel >= CH_NUM)
608 return false;
610 ccb_p = &ccb_array[channel];
612 if (ccb_p->status.opened_init == 0)
613 return false;
615 if (!setup_channel(ccb_p))
616 return false;
618 return true;
621 /* Resume or start execution on a channel */
622 void sdma_channel_run(unsigned int channel)
624 if (channel == 0 || channel >= CH_NUM)
625 return;
627 if (ccb_array[channel].status.opened_init == 0)
628 return;
630 SDMA_HSTART = 1ul << channel;
633 /* Pause a running channel - can be resumed */
634 void sdma_channel_pause(unsigned int channel)
636 if (channel == 0 || channel >= CH_NUM)
637 return;
639 if (ccb_array[channel].status.opened_init == 0)
640 return;
642 SDMA_STOP_STAT = 1ul << channel;
645 /* Stop a channel from executing - cannot be resumed */
646 void sdma_channel_stop(unsigned int channel)
648 struct channel_control_block *ccb_p;
649 unsigned long chmsk;
650 unsigned long intmsk;
651 int oldstatus;
652 int i;
654 if (channel == 0 || channel >= CH_NUM)
655 return;
657 ccb_p = &ccb_array[channel];
659 if (ccb_p->status.opened_init == 0)
660 return;
662 chmsk = 1ul << channel;
664 /* Lock callback */
665 oldstatus = disable_irq_save();
666 intmsk = sdma_enabled_ints;
667 sdma_enabled_ints &= ~chmsk;
668 restore_irq(oldstatus);
670 /* Stop execution */
671 for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--)
672 ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE;
674 SDMA_STOP_STAT = chmsk;
675 while (SDMA_STOP_STAT & chmsk);
677 /* Unlock callback if it was set */
678 if (intmsk & chmsk)
679 imx31_regset32(&sdma_enabled_ints, chmsk);
681 logf("SDMA ch closed: %d", channel);
684 bool sdma_channel_init(unsigned int channel,
685 struct channel_descriptor *cd_p,
686 struct buffer_descriptor *base_bd_p)
688 struct channel_control_block *ccb_p;
690 if (channel == 0 || channel >= CH_NUM ||
691 cd_p == NULL || base_bd_p == NULL)
692 return false;
694 ccb_p = &ccb_array[channel];
696 /* If initialized already, should close first then init. */
697 if (ccb_p->status.opened_init != 0)
698 return false;
700 /* Initialize channel control block. */
701 ccb_p->curr_bd_ptr = base_bd_p;
702 ccb_p->base_bd_ptr = base_bd_p;
703 ccb_p->channel_desc = cd_p;
704 ccb_p->status.error = 0;
705 ccb_p->status.opened_init = 1;
706 ccb_p->status.state_direction = 0;
707 ccb_p->status.execute = 0;
709 /* Finish any channel descriptor inits. */
710 cd_p->ccb_ptr = ccb_p;
711 cd_p->is_setup = 0;
713 /* Do an initial setup now. */
714 if (!setup_channel(ccb_p))
716 logf("SDMA ch init failed: %d", channel);
717 cd_p->ccb_ptr = NULL;
718 memset(ccb_p, 0x00, sizeof (struct channel_control_block));
719 return false;
722 /* Enable interrupt if a callback is specified. */
723 if (cd_p->callback != NULL)
724 imx31_regset32(&sdma_enabled_ints, 1ul << channel);
726 /* Minimum schedulable = 1 */
727 sdma_channel_set_priority(channel, 1);
729 logf("SDMA ch initialized: %d", channel);
730 return true;
733 void sdma_channel_close(unsigned int channel)
735 struct channel_control_block *ccb_p;
736 int i;
738 if (channel == 0 || channel >= CH_NUM)
739 return;
741 ccb_p = &ccb_array[channel];
743 /* Block callbacks (if not initialized, it won't be set). */
744 imx31_regclr32(&sdma_enabled_ints, 1ul << channel);
746 if (ccb_p->status.opened_init == 0)
747 return;
749 /* Stop the channel if running */
750 for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--)
751 ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE;
753 sdma_channel_stop(channel);
755 /* No ownership */
756 set_channel_ownership(channel, 0);
758 /* Cannot schedule it again */
759 sdma_channel_set_priority(channel, 0);
761 /* Reset channel control block entry */
762 memset(ccb_p, 0x00, sizeof (struct channel_control_block));
765 /* Check channel-wide error flag */
766 bool sdma_channel_is_error(unsigned int channel)
768 return channel < CH_NUM && ccb_array[channel].status.error;
771 /* Write 32-bit words to SDMA core memory. Host endian->SDMA endian. */
772 void sdma_write_words(const unsigned long *buf, unsigned long start, int count)
774 /* Setup buffer descriptor with channel 0 command */
775 set_buffer_descriptor(&c0_buffer_desc.bd,
776 C0_SETDM,
777 BD_DONE | BD_WRAP | BD_EXTD,
778 count,
779 (void *)addr_virt_to_phys((unsigned long)buf),
780 (void *)start);
782 SDMA_HSTART = 1ul;
783 sdma_channel_wait_nonblocking(0);
786 /* Read 32-bit words from SDMA core memory. SDMA endian->host endian. */
787 void sdma_read_words(unsigned long *buf, unsigned long start, int count)
789 /* Setup buffer descriptor with channel 0 command */
790 set_buffer_descriptor(&c0_buffer_desc.bd,
791 C0_GETDM,
792 BD_DONE | BD_WRAP | BD_EXTD,
793 count,
794 (void *)addr_virt_to_phys((unsigned long)buf),
795 (void *)start);
797 SDMA_HSTART = 1ul;
798 sdma_channel_wait_nonblocking(0);