Commit SDMA driver changes.
[barrelfish] / usr / drivers / omap44xx / sdma / omap_sdma.c
1 /*
2  * Copyright (c) 2014, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, CAB F.78, Universitaetstr 6, CH-8092 Zurich.
8  */
9
10 #include <barrelfish/barrelfish.h>
11
12 #ifdef OMAP_SDMA_KERNELBENCH
13     #include <arch/armv7/gic.h>
14     #include <arm_hal.h>
15     #include <exceptions.h>
16     #include <kernel.h>
17 #else
18     #include <barrelfish/waitset.h>
19     #include <barrelfish/inthandler.h>
20     #include <driverkit/driverkit.h>
21 #endif
22
23 #include <string.h>
24
25 #include "omap_sdma.h"
26 #include <maps/omap44xx_map.h>
27
28 static inline errval_t omap_sdma_read_csr(omap44xx_sdma_dma4_csr_t csr)
29 {
30     if (omap44xx_sdma_dma4_csr_misaligned_adrs_err_extract(csr)) {
31         return OMAP_SDMA_ERR_MISALIGNED_ADDRESS;
32     } else if (omap44xx_sdma_dma4_csr_supervisor_err_extract(csr)) {
33         return OMAP_SDMA_ERR_SUPERVISOR;
34     } else if (omap44xx_sdma_dma4_csr_trans_err_extract(csr)) {
35         return OMAP_SDMA_ERR_TRANSACTION;
36     }
37
38     return SYS_ERR_OK;
39 }
40
41 static void omap_sdma_irq_handler(void *arg)
42 {
43     struct sdma_driver_state* st = (struct sdma_driver_state*) arg;
44     uint32_t irqstatus = omap44xx_sdma_dma4_irqstatus_line_rd(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE);
45
46     for (omap_sdma_channel_t channel=0; channel<OMAP44XX_SDMA_NUM_CHANNEL; channel++) {
47         bool active = (irqstatus >> channel) & 0x1;
48         if(!active) continue;
49
50         SDMA_PRINT("interrupt on channel %u\n", channel);
51
52         // read out status flags
53         omap44xx_sdma_dma4_csr_t csr = omap44xx_sdma_dma4_csr_rd(&st->devsdma, channel);
54
55         // check for errors
56         errval_t err = omap_sdma_read_csr(csr);
57
58         if (err_is_ok(err)) {
59             // no error found, check for "End of Block" event
60             if(omap44xx_sdma_dma4_csr_block_extract(csr)) {
61                 st->irq_callback(st, channel, err);
62             }
63         } else {
64             // OMAP4460 Multimedia Device Silicon Errata, Revision A:
65             // 1.7 sDMA Channel Is Not Disabled After A Transaction Error
66             if (err_no(err) == OMAP_SDMA_ERR_TRANSACTION) {
67                 // Workaround: disable channel by software
68                 omap44xx_sdma_dma4_ccr_enable_wrf(&st->devsdma, channel, 0);
69             }
70
71             st->irq_callback(st, channel, err);
72         }
73
74         // clear all read status flags
75         omap44xx_sdma_dma4_csr_wr(&st->devsdma, channel, csr);
76     }
77
78     SDMA_PRINT("interrupt finished\n");
79
80     // clear all set status bits
81     omap44xx_sdma_dma4_irqstatus_line_wr(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE, irqstatus);
82 }
83
84
85 #ifdef OMAP_SDMA_KERNELBENCH
86 // This interrupt handler is for use in the SDMA kernel benchmark only!
87 // It depends on GCC's code generation to create the prologue and epilogue
88 // for it to be a valid interrupt handler.
89 //
90 // Vanilla Barrelfish is not designed handle interrupts in the kernel.
91 __attribute__((interrupt("IRQ")))
92 static void omap_sdma_kernel_irq_handler(void)
93 {
94     int irq = gic_get_active_irq();
95     if(irq == OMAP44XX_SDMA_IRQ) {
96         omap_sdma_irq_handler(NULL);
97     }
98     gic_ack_irq(irq);
99 }
100 #endif
101
102 static void omap_sdma_irq_config(struct sdma_driver_state* st, omap_sdma_channel_t channel)
103 {
104     omap44xx_sdma_dma4_cicr_t dma4_cicr = omap44xx_sdma_dma4_cicr_rd(&st->devsdma, channel);
105
106     dma4_cicr = omap44xx_sdma_dma4_cicr_super_block_ie_insert(dma4_cicr, 0x0);
107     dma4_cicr = omap44xx_sdma_dma4_cicr_drain_ie_insert(dma4_cicr, 0x0);
108     dma4_cicr = omap44xx_sdma_dma4_cicr_misaligned_err_ie_insert(dma4_cicr, 0x1);
109     dma4_cicr = omap44xx_sdma_dma4_cicr_supervisor_err_ie_insert(dma4_cicr, 0x1);
110     dma4_cicr = omap44xx_sdma_dma4_cicr_trans_err_ie_insert(dma4_cicr, 0x1);
111     dma4_cicr = omap44xx_sdma_dma4_cicr_pkt_ie_insert(dma4_cicr, 0x0);
112     dma4_cicr = omap44xx_sdma_dma4_cicr_block_ie_insert(dma4_cicr, 0x1);
113     dma4_cicr = omap44xx_sdma_dma4_cicr_last_ie_insert(dma4_cicr, 0x0);
114     dma4_cicr = omap44xx_sdma_dma4_cicr_frame_ie_insert(dma4_cicr, 0x0);
115     dma4_cicr = omap44xx_sdma_dma4_cicr_half_ie_insert(dma4_cicr, 0x0);
116     dma4_cicr = omap44xx_sdma_dma4_cicr_drop_ie_insert(dma4_cicr, 0x0);
117
118     omap44xx_sdma_dma4_cicr_wr(&st->devsdma, channel, dma4_cicr);
119 }
120
121 /**
122  * \brief Initialzes a channel configuraton struct with its reset values.
123  */
124 void omap_sdma_init_channel_conf(struct omap_sdma_channel_conf *conf) {
125     // this function initializes the config struct with default values
126
127     // TRM reset values
128     conf->read_priority  = omap44xx_sdma_PORT_PRIORITY_LOW;
129     conf->write_priority = omap44xx_sdma_PORT_PRIORITY_LOW;
130
131     conf->color_mode = omap44xx_sdma_DISABLE_COLOR_MODE;
132     conf->color = 0x000000;
133
134     // no reset value here, use sane default
135     conf->write_mode = omap44xx_sdma_WRITE_MODE_LAST_NON_POSTED;
136
137     struct omap_sdma_transfer_size *transfer_size = &conf->transfer_size;
138     transfer_size->element_number = 0;
139     transfer_size->frame_number = 0;
140     transfer_size->data_type = omap44xx_sdma_DATA_TYPE_32BIT;
141
142     // default transfer config
143     struct omap_sdma_transfer_conf *src_conf = &conf->src_conf;
144     struct omap_sdma_transfer_conf *dst_conf = &conf->dst_conf;
145     src_conf->start_address = 0;
146     src_conf->addr_mode = omap44xx_sdma_ADDR_MODE_POST_INCR;
147     src_conf->element_index = 0;
148     src_conf->frame_index = 0;
149     src_conf->packed_transfer = omap44xx_sdma_SRC_PACKED_DISABLE;
150     src_conf->burst_mode = omap44xx_sdma_BURST_EN_SINGLE;
151
152     // use the same default values for the destination port
153     memcpy(dst_conf, src_conf, sizeof(struct omap_sdma_transfer_conf));
154
155     conf->enable_link = false;
156     conf->next_channel = 0;
157 }
158
159 static omap44xx_sdma_dma4_ccr_t omap_sdma_channel_conf_ccr(
160                                 omap44xx_sdma_dma4_ccr_t dma4_ccr,
161                                 struct omap_sdma_channel_conf *conf)
162 {
163     dma4_ccr = omap44xx_sdma_dma4_ccr_src_amode_insert(dma4_ccr, conf->src_conf.addr_mode);
164     dma4_ccr = omap44xx_sdma_dma4_ccr_dst_amode_insert(dma4_ccr, conf->dst_conf.addr_mode);
165
166     assert(
167         (conf->read_priority == omap44xx_sdma_PORT_PRIORITY_LOW) ||
168         (conf->read_priority == omap44xx_sdma_PORT_PRIORITY_HIGH)
169     );
170     dma4_ccr = omap44xx_sdma_dma4_ccr_read_priority_insert(dma4_ccr, conf->read_priority);
171
172     assert(
173         (conf->write_priority == omap44xx_sdma_PORT_PRIORITY_LOW) ||
174         (conf->write_priority == omap44xx_sdma_PORT_PRIORITY_HIGH)
175     );
176     dma4_ccr = omap44xx_sdma_dma4_ccr_write_priority_insert(dma4_ccr, conf->write_priority);
177
178     omap44xx_sdma_transparent_copy_t
179         transparent_copy = (conf->color_mode == omap44xx_sdma_TRANSPARENT_COPY);
180     omap44xx_sdma_const_fill_t
181         const_fill = (conf->color_mode == omap44xx_sdma_CONSTANT_FILL);
182
183     dma4_ccr = omap44xx_sdma_dma4_ccr_transparent_copy_enable_insert(dma4_ccr, transparent_copy);
184     dma4_ccr = omap44xx_sdma_dma4_ccr_const_fill_enable_insert(dma4_ccr, const_fill);
185
186     return dma4_ccr;
187 }
188
189
190 static omap44xx_sdma_dma4_color_t omap_sdma_channel_conf_color(
191                                 omap44xx_sdma_dma4_color_t dma4_color,
192                                 struct omap_sdma_channel_conf *conf)
193 {
194     // DMA4_COLORi can only be a 24 bit value
195     assert((conf->color & 0xFF000000) == 0);
196
197     return omap44xx_sdma_dma4_color_color_key_pattern_insert(dma4_color, conf->color);
198 }
199
200 static omap44xx_sdma_dma4_clnk_ctrl_t omap_sdma_channel_conf_clnk_ctrl(
201                                 omap44xx_sdma_dma4_clnk_ctrl_t dma4_clnk_ctrl,
202                                 struct omap_sdma_channel_conf *conf)
203 {
204     // if we enable channel linking, the next channel has to be valid
205     assert(!conf->enable_link || conf->next_channel < OMAP44XX_SDMA_NUM_CHANNEL);
206
207     dma4_clnk_ctrl = omap44xx_sdma_dma4_clnk_ctrl_nextlch_id_insert(
208         dma4_clnk_ctrl, conf->next_channel);
209     dma4_clnk_ctrl = omap44xx_sdma_dma4_clnk_ctrl_enable_lnk_insert(
210         dma4_clnk_ctrl, conf->enable_link ? 1 : 0);
211
212     return dma4_clnk_ctrl;
213 }
214
215 static omap44xx_sdma_dma4_csdp_t omap_sdma_channel_conf_csdp(
216                                 omap44xx_sdma_dma4_csdp_t dma4_csdp,
217                                 struct omap_sdma_channel_conf *conf)
218 {
219     assert(
220         (conf->write_mode == omap44xx_sdma_WRITE_MODE_NONE_POSTED) ||
221         (conf->write_mode == omap44xx_sdma_WRITE_MODE_ALL_POSTED) ||
222         (conf->write_mode == omap44xx_sdma_WRITE_MODE_LAST_NON_POSTED)
223     );
224
225     dma4_csdp = omap44xx_sdma_dma4_csdp_write_mode_insert(dma4_csdp, conf->write_mode);
226
227     // In memory to memory transfers, the endianness is always little endian
228     dma4_csdp = omap44xx_sdma_dma4_csdp_src_endian_insert(dma4_csdp, omap44xx_sdma_ENDIAN_LITTLE);
229     dma4_csdp = omap44xx_sdma_dma4_csdp_src_endian_lock_insert(dma4_csdp, omap44xx_sdma_ENDIAN_LOCK_ADAPT);
230
231     dma4_csdp = omap44xx_sdma_dma4_csdp_dst_endian_insert(dma4_csdp, omap44xx_sdma_ENDIAN_LITTLE);
232     dma4_csdp = omap44xx_sdma_dma4_csdp_dst_endian_lock_insert(dma4_csdp, omap44xx_sdma_ENDIAN_LOCK_ADAPT);
233
234     struct omap_sdma_transfer_conf *src_conf = &conf->src_conf;
235     dma4_csdp = omap44xx_sdma_dma4_csdp_src_burst_en_insert(dma4_csdp, src_conf->burst_mode);
236     dma4_csdp = omap44xx_sdma_dma4_csdp_src_packed_insert(dma4_csdp,
237         src_conf->packed_transfer
238             ? omap44xx_sdma_SRC_PACKED_ENABLE
239             : omap44xx_sdma_SRC_PACKED_DISABLE);
240
241     struct omap_sdma_transfer_conf *dst_conf = &conf->dst_conf;
242     dma4_csdp = omap44xx_sdma_dma4_csdp_dst_burst_en_insert(dma4_csdp, dst_conf->burst_mode);
243     dma4_csdp = omap44xx_sdma_dma4_csdp_dst_packed_insert(dma4_csdp,
244         dst_conf->packed_transfer
245             ? omap44xx_sdma_DST_PACKED_ENABLE
246             : omap44xx_sdma_DST_PACKED_DISABLE);
247
248     struct omap_sdma_transfer_size *transfer_size = &conf->transfer_size;
249
250     dma4_csdp = omap44xx_sdma_dma4_csdp_data_type_insert(dma4_csdp, transfer_size->data_type);
251
252     return dma4_csdp;
253 }
254
255 static void inline omap_sdma_channel_conf_assert_transfer_size(
256                                 struct omap_sdma_transfer_size *transfer_size)
257 {
258     assert(
259         (transfer_size->data_type == omap44xx_sdma_DATA_TYPE_8BIT) ||
260         (transfer_size->data_type == omap44xx_sdma_DATA_TYPE_16BIT) ||
261         (transfer_size->data_type == omap44xx_sdma_DATA_TYPE_32BIT)
262     );
263
264     // element number is 24 bit
265     assert((transfer_size->element_number & 0xFF000000) == 0);
266 }
267
268 static void inline omap_sdma_channel_conf_assert_transfer_conf(
269                                 struct omap_sdma_transfer_conf *transfer_conf)
270 {
271
272     // constant addressing mode is not allowed for memory to memory transfers
273     assert(
274         (transfer_conf->addr_mode == omap44xx_sdma_ADDR_MODE_POST_INCR) ||
275         (transfer_conf->addr_mode == omap44xx_sdma_ADDR_MODE_SINGLE_IDX) ||
276         (transfer_conf->addr_mode == omap44xx_sdma_ADDR_MODE_DOUBLE_IDX)
277     );
278
279     assert(
280         (transfer_conf->burst_mode == omap44xx_sdma_BURST_EN_SINGLE) ||
281         (transfer_conf->burst_mode == omap44xx_sdma_BURST_EN_16BYTE) ||
282         (transfer_conf->burst_mode == omap44xx_sdma_BURST_EN_32BYTE) ||
283         (transfer_conf->burst_mode == omap44xx_sdma_BURST_EN_64BYTE)
284     );
285
286     // if post-incrementing with burst transfers is used,
287     // data must be packed to DMA data-port width (TRM Section 16.4.7)
288     assert(
289         (transfer_conf->burst_mode == omap44xx_sdma_BURST_EN_SINGLE)    ||
290         (transfer_conf->addr_mode != omap44xx_sdma_ADDR_MODE_POST_INCR) ||
291         (transfer_conf->packed_transfer == omap44xx_sdma_SRC_PACKED_ENABLE)
292     );
293 }
294
295 /**
296  * \brief Configure an allocated channel with the given struct.
297  *
298  * \param channel   Channel to configure
299  * \param conf      Complete channel configuration
300  *
301  * This function will write all values of the struct to the SDMA device
302  * registers. Some basic santiy checks (using assert statements) are performed,
303  * but is it the callers responsibility to ensure that the configuration is
304  * sane and valid.
305  */
306 void omap_sdma_set_channel_conf(struct sdma_driver_state* st, omap_sdma_channel_t channel,
307                                 struct omap_sdma_channel_conf *conf)
308 {
309     // check transfer config and size parameters
310     assert(channel < OMAP44XX_SDMA_NUM_CHANNEL);
311
312     omap_sdma_channel_conf_assert_transfer_size(&conf->transfer_size);
313
314     omap_sdma_channel_conf_assert_transfer_conf(&conf->src_conf);
315     omap_sdma_channel_conf_assert_transfer_conf(&conf->dst_conf);
316
317
318     // Channel Control Register
319     omap44xx_sdma_dma4_ccr_t dma4_ccr;
320     dma4_ccr = omap44xx_sdma_dma4_ccr_rd(&st->devsdma, channel);
321     dma4_ccr = omap_sdma_channel_conf_ccr(dma4_ccr, conf);
322     omap44xx_sdma_dma4_ccr_wr(&st->devsdma, channel, dma4_ccr);
323
324     // Channel Color Register
325     omap44xx_sdma_dma4_color_t dma4_color;
326     dma4_color = omap44xx_sdma_dma4_color_rd(&st->devsdma, channel);
327     dma4_color = omap_sdma_channel_conf_color(channel, conf);
328     omap44xx_sdma_dma4_color_wr(&st->devsdma, channel, dma4_color);
329
330     // Channel Link Control Register
331     omap44xx_sdma_dma4_clnk_ctrl_t dma4_clnk_ctrl;
332     dma4_clnk_ctrl = omap44xx_sdma_dma4_clnk_ctrl_rd(&st->devsdma, channel);
333     dma4_clnk_ctrl = omap_sdma_channel_conf_clnk_ctrl(channel, conf);
334     omap44xx_sdma_dma4_clnk_ctrl_wr(&st->devsdma, channel, dma4_clnk_ctrl);
335
336     // Channel Source Destination Parameters
337     omap44xx_sdma_dma4_csdp_t dma4_csdp;
338     dma4_csdp = omap44xx_sdma_dma4_csdp_rd(&st->devsdma, channel);
339     dma4_csdp = omap_sdma_channel_conf_csdp(channel, conf);
340     omap44xx_sdma_dma4_csdp_wr(&st->devsdma, channel, dma4_csdp);
341
342     // Channel Element Number
343     omap44xx_sdma_dma4_cen_wr(&st->devsdma, channel, conf->transfer_size.element_number);
344
345     // Channel Frame Number
346     omap44xx_sdma_dma4_cfn_wr(&st->devsdma, channel, conf->transfer_size.frame_number);
347
348     // Channel Source Element Index
349     omap44xx_sdma_dma4_csei_wr(&st->devsdma, channel, conf->src_conf.element_index);
350     // Channel Source Frame Index
351     omap44xx_sdma_dma4_csfi_wr(&st->devsdma, channel, conf->src_conf.frame_index);
352     // Channel Destination Element Index
353     omap44xx_sdma_dma4_cdei_wr(&st->devsdma, channel, conf->dst_conf.element_index);
354     // Channel Destination Frame Index
355     omap44xx_sdma_dma4_cdfi_wr(&st->devsdma, channel, conf->dst_conf.frame_index);
356
357     // Channel Source Start Address
358     omap44xx_sdma_dma4_cssa_wr(&st->devsdma, channel, conf->src_conf.start_address);
359
360     // Channel Source Destination Address
361     omap44xx_sdma_dma4_cdsa_wr(&st->devsdma, channel, conf->dst_conf.start_address);
362 }
363
364 /**
365  * \brief Start a SDMA transfer on a pre-configured channel
366  *
367  * \param channel   Pre-configured channel to enable
368  * \param interrupt Indicate an interrupt should be sent on completion or error
369  *
370  * It is the callers responsibility to ensure that the channel was configured
371  * properly before this function is called.
372  */
373 void omap_sdma_enable_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel, bool interrupt)
374 {
375     assert(channel < OMAP44XX_SDMA_NUM_CHANNEL);
376
377     // clear all channel status flags
378     omap44xx_sdma_dma4_csr_wr(&st->devsdma, channel, 0xFFFFFFFF);
379
380     uint32_t irqenable = omap44xx_sdma_dma4_irqenable_rd(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE);
381     if (interrupt) {
382         // set channel
383         irqenable |= 1 << channel;
384         // reset irq status for this channel
385         omap44xx_sdma_dma4_irqstatus_line_wr(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE, 1 << channel);
386     } else {
387         // clear channel
388         irqenable &= ~(1 << channel);
389     }
390     omap44xx_sdma_dma4_irqenable_wr(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE, irqenable);
391
392     omap44xx_sdma_dma4_ccr_enable_wrf(&st->devsdma, channel, 1);
393 }
394
395 /**
396  * \brief Poll a enabled channel for completion of the transfer.
397  */
398 errval_t omap_sdma_poll_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel)
399 {
400     assert(channel < OMAP44XX_SDMA_NUM_CHANNEL);
401
402     // interrupts should be disabled in polling mode
403     assert((omap44xx_sdma_dma4_irqenable_rd(
404                 &st->devsdma, OMAP44XX_SDMA_IRQ_LINE) & 1 << channel) == 0x0
405     );
406
407     for (;;) {
408         omap44xx_sdma_dma4_csr_t csr = omap44xx_sdma_dma4_csr_rd(&st->devsdma, channel);
409
410         errval_t err = omap_sdma_read_csr(csr);
411
412         if (err_is_fail(err)) return err;
413
414         if(omap44xx_sdma_dma4_csr_block_extract(csr)) {
415             return err;
416         }
417     }
418 }
419
420 /**
421  * \brief Allocate a SDMA channel. Will return an error if there are no channels
422  * available.
423  */
424 errval_t omap_sdma_allocate_channel(struct sdma_driver_state* st, omap_sdma_channel_t *channel)
425 {
426     assert(channel != NULL);
427
428     for (omap_sdma_channel_t c = 0; c<OMAP44XX_SDMA_NUM_CHANNEL; c++) {
429         if (!st->allocated_channel[c]) {
430             st->allocated_channel[c] = true;
431             *channel = c;
432             return SYS_ERR_OK;
433         }
434     }
435     return OMAP_SDMA_ERR_NO_AVAIL_CHANNEL;
436 }
437
438 /**
439  * \brief Frees a previously allocated SDMA channel.
440  */
441 void omap_sdma_free_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel)
442 {
443     assert(st->allocated_channel[channel]);
444     st->allocated_channel[channel] = false;
445 }
446
447 /**
448  * \brief Initializes this Mackerel wrapper.
449  *
450  * \param dev_base  Virtual address where the SDMA module is mapped to
451  * \param irq_cb    Mandatory interrupt callback
452  *
453  * The caller has map the SDMA hardware registers before calling this function.
454  * The interrupt callback is executed for every time an SDMA channel triggered
455  * an interrupt. The source channel and the the reason of the interrupt are
456  * passed to the callback as an the argument.
457  */
458 errval_t omap_sdma_init(struct sdma_driver_state* st, mackerel_addr_t dev_base, omap_sdma_irq_handler_t irq_cb)
459 {
460     // init global variables
461     STATIC_ASSERT_SIZEOF(bool, 1);
462     memset(st->allocated_channel, false, OMAP44XX_SDMA_NUM_CHANNEL);
463
464     omap44xx_sdma_initialize(&st->devsdma, dev_base);
465
466     // check if we can read the revision
467     assert(omap44xx_sdma_dma4_revision_rd(&st->devsdma) == 0x10900);
468
469     assert(irq_cb != NULL);
470     st->irq_callback = irq_cb;
471
472     errval_t err = SYS_ERR_OK;
473 #ifdef OMAP_SDMA_KERNELBENCH
474     // in kernelspace, we hijack the normal interrupt handler by overwriting
475     // the global interrupt handler table entry.
476
477     // this is obvioulsy a hack (!) and ONLY for use in the sdma kernel
478     // benchmark which will not allow the kernel to continue after this
479     uintptr_t *irq_handler_entry = (uintptr_t*)
480                         (ETABLE_ADDR + JUMP_TABLE_OFFSET + ARM_EVECTOR_IRQ);
481     *irq_handler_entry = (uintptr_t) omap_sdma_kernel_irq_handler;
482
483     // enable the SDMA interrupt in the global interrupt controller
484     gic_enable_interrupt(OMAP44XX_SDMA_IRQ, GIC_IRQ_CPU_TRG_ALL, 0,
485                             GIC_IRQ_EDGE_TRIGGERED, GIC_IRQ_N_TO_N);
486 #else
487     // in userspace, register normal interrupt handler
488     err = inthandler_setup_arm(omap_sdma_irq_handler, st, OMAP44XX_SDMA_IRQ);
489 #endif
490
491     // set fifo depth to maximum burst size
492     omap44xx_sdma_dma4_gcr_max_channel_fifo_depth_wrf(&st->devsdma, 64);
493
494     // configure error and interrupt handling of the device
495     for(omap_sdma_channel_t channel = 0;
496         channel < OMAP44XX_SDMA_NUM_CHANNEL;
497         channel++)
498     {
499         omap_sdma_irq_config(st, channel);
500     }
501
502     return err;
503 }