xref: /openbmc/qemu/hw/dma/xilinx_axidma.c (revision 84a3a53c)
1 /*
2  * QEMU model of Xilinx AXI-DMA block.
3  *
4  * Copyright (c) 2011 Edgar E. Iglesias.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "hw/sysbus.h"
26 #include "qemu/timer.h"
27 #include "hw/ptimer.h"
28 #include "qemu/log.h"
29 #include "qemu/main-loop.h"
30 
31 #include "hw/stream.h"
32 
33 #define D(x)
34 
35 #define TYPE_XILINX_AXI_DMA "xlnx.axi-dma"
36 #define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream"
37 #define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream"
38 
39 #define XILINX_AXI_DMA(obj) \
40      OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA)
41 
42 #define XILINX_AXI_DMA_DATA_STREAM(obj) \
43      OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
44      TYPE_XILINX_AXI_DMA_DATA_STREAM)
45 
46 #define XILINX_AXI_DMA_CONTROL_STREAM(obj) \
47      OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
48      TYPE_XILINX_AXI_DMA_CONTROL_STREAM)
49 
50 #define R_DMACR             (0x00 / 4)
51 #define R_DMASR             (0x04 / 4)
52 #define R_CURDESC           (0x08 / 4)
53 #define R_TAILDESC          (0x10 / 4)
54 #define R_MAX               (0x30 / 4)
55 
56 #define CONTROL_PAYLOAD_WORDS 5
57 #define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t)))
58 
59 typedef struct XilinxAXIDMA XilinxAXIDMA;
60 typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave;
61 
62 enum {
63     DMACR_RUNSTOP = 1,
64     DMACR_TAILPTR_MODE = 2,
65     DMACR_RESET = 4
66 };
67 
68 enum {
69     DMASR_HALTED = 1,
70     DMASR_IDLE  = 2,
71     DMASR_IOC_IRQ  = 1 << 12,
72     DMASR_DLY_IRQ  = 1 << 13,
73 
74     DMASR_IRQ_MASK = 7 << 12
75 };
76 
77 struct SDesc {
78     uint64_t nxtdesc;
79     uint64_t buffer_address;
80     uint64_t reserved;
81     uint32_t control;
82     uint32_t status;
83     uint8_t app[CONTROL_PAYLOAD_SIZE];
84 };
85 
86 enum {
87     SDESC_CTRL_EOF = (1 << 26),
88     SDESC_CTRL_SOF = (1 << 27),
89 
90     SDESC_CTRL_LEN_MASK = (1 << 23) - 1
91 };
92 
93 enum {
94     SDESC_STATUS_EOF = (1 << 26),
95     SDESC_STATUS_SOF_BIT = 27,
96     SDESC_STATUS_SOF = (1 << SDESC_STATUS_SOF_BIT),
97     SDESC_STATUS_COMPLETE = (1 << 31)
98 };
99 
100 struct Stream {
101     QEMUBH *bh;
102     ptimer_state *ptimer;
103     qemu_irq irq;
104 
105     int nr;
106 
107     struct SDesc desc;
108     int pos;
109     unsigned int complete_cnt;
110     uint32_t regs[R_MAX];
111     uint8_t app[20];
112 };
113 
114 struct XilinxAXIDMAStreamSlave {
115     Object parent;
116 
117     struct XilinxAXIDMA *dma;
118 };
119 
120 struct XilinxAXIDMA {
121     SysBusDevice busdev;
122     MemoryRegion iomem;
123     uint32_t freqhz;
124     StreamSlave *tx_data_dev;
125     StreamSlave *tx_control_dev;
126     XilinxAXIDMAStreamSlave rx_data_dev;
127     XilinxAXIDMAStreamSlave rx_control_dev;
128 
129     struct Stream streams[2];
130 
131     StreamCanPushNotifyFn notify;
132     void *notify_opaque;
133 };
134 
135 /*
136  * Helper calls to extract info from descriptors and other trivial
137  * state from regs.
138  */
139 static inline int stream_desc_sof(struct SDesc *d)
140 {
141     return d->control & SDESC_CTRL_SOF;
142 }
143 
144 static inline int stream_desc_eof(struct SDesc *d)
145 {
146     return d->control & SDESC_CTRL_EOF;
147 }
148 
149 static inline int stream_resetting(struct Stream *s)
150 {
151     return !!(s->regs[R_DMACR] & DMACR_RESET);
152 }
153 
154 static inline int stream_running(struct Stream *s)
155 {
156     return s->regs[R_DMACR] & DMACR_RUNSTOP;
157 }
158 
159 static inline int stream_idle(struct Stream *s)
160 {
161     return !!(s->regs[R_DMASR] & DMASR_IDLE);
162 }
163 
164 static void stream_reset(struct Stream *s)
165 {
166     s->regs[R_DMASR] = DMASR_HALTED;  /* starts up halted.  */
167     s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold.  */
168 }
169 
170 /* Map an offset addr into a channel index.  */
171 static inline int streamid_from_addr(hwaddr addr)
172 {
173     int sid;
174 
175     sid = addr / (0x30);
176     sid &= 1;
177     return sid;
178 }
179 
180 static void stream_desc_load(struct Stream *s, hwaddr addr)
181 {
182     struct SDesc *d = &s->desc;
183 
184     cpu_physical_memory_read(addr, d, sizeof *d);
185 
186     /* Convert from LE into host endianness.  */
187     d->buffer_address = le64_to_cpu(d->buffer_address);
188     d->nxtdesc = le64_to_cpu(d->nxtdesc);
189     d->control = le32_to_cpu(d->control);
190     d->status = le32_to_cpu(d->status);
191 }
192 
193 static void stream_desc_store(struct Stream *s, hwaddr addr)
194 {
195     struct SDesc *d = &s->desc;
196 
197     /* Convert from host endianness into LE.  */
198     d->buffer_address = cpu_to_le64(d->buffer_address);
199     d->nxtdesc = cpu_to_le64(d->nxtdesc);
200     d->control = cpu_to_le32(d->control);
201     d->status = cpu_to_le32(d->status);
202     cpu_physical_memory_write(addr, d, sizeof *d);
203 }
204 
205 static void stream_update_irq(struct Stream *s)
206 {
207     unsigned int pending, mask, irq;
208 
209     pending = s->regs[R_DMASR] & DMASR_IRQ_MASK;
210     mask = s->regs[R_DMACR] & DMASR_IRQ_MASK;
211 
212     irq = pending & mask;
213 
214     qemu_set_irq(s->irq, !!irq);
215 }
216 
217 static void stream_reload_complete_cnt(struct Stream *s)
218 {
219     unsigned int comp_th;
220     comp_th = (s->regs[R_DMACR] >> 16) & 0xff;
221     s->complete_cnt = comp_th;
222 }
223 
224 static void timer_hit(void *opaque)
225 {
226     struct Stream *s = opaque;
227 
228     stream_reload_complete_cnt(s);
229     s->regs[R_DMASR] |= DMASR_DLY_IRQ;
230     stream_update_irq(s);
231 }
232 
233 static void stream_complete(struct Stream *s)
234 {
235     unsigned int comp_delay;
236 
237     /* Start the delayed timer.  */
238     comp_delay = s->regs[R_DMACR] >> 24;
239     if (comp_delay) {
240         ptimer_stop(s->ptimer);
241         ptimer_set_count(s->ptimer, comp_delay);
242         ptimer_run(s->ptimer, 1);
243     }
244 
245     s->complete_cnt--;
246     if (s->complete_cnt == 0) {
247         /* Raise the IOC irq.  */
248         s->regs[R_DMASR] |= DMASR_IOC_IRQ;
249         stream_reload_complete_cnt(s);
250     }
251 }
252 
253 static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
254                                  StreamSlave *tx_control_dev)
255 {
256     uint32_t prev_d;
257     unsigned char txbuf[16 * 1024];
258     unsigned int txlen;
259 
260     if (!stream_running(s) || stream_idle(s)) {
261         return;
262     }
263 
264     while (1) {
265         stream_desc_load(s, s->regs[R_CURDESC]);
266 
267         if (s->desc.status & SDESC_STATUS_COMPLETE) {
268             s->regs[R_DMASR] |= DMASR_HALTED;
269             break;
270         }
271 
272         if (stream_desc_sof(&s->desc)) {
273             s->pos = 0;
274             stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app));
275         }
276 
277         txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
278         if ((txlen + s->pos) > sizeof txbuf) {
279             hw_error("%s: too small internal txbuf! %d\n", __func__,
280                      txlen + s->pos);
281         }
282 
283         cpu_physical_memory_read(s->desc.buffer_address,
284                                  txbuf + s->pos, txlen);
285         s->pos += txlen;
286 
287         if (stream_desc_eof(&s->desc)) {
288             stream_push(tx_data_dev, txbuf, s->pos);
289             s->pos = 0;
290             stream_complete(s);
291         }
292 
293         /* Update the descriptor.  */
294         s->desc.status = txlen | SDESC_STATUS_COMPLETE;
295         stream_desc_store(s, s->regs[R_CURDESC]);
296 
297         /* Advance.  */
298         prev_d = s->regs[R_CURDESC];
299         s->regs[R_CURDESC] = s->desc.nxtdesc;
300         if (prev_d == s->regs[R_TAILDESC]) {
301             s->regs[R_DMASR] |= DMASR_IDLE;
302             break;
303         }
304     }
305 }
306 
307 static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
308                                    size_t len)
309 {
310     uint32_t prev_d;
311     unsigned int rxlen;
312     size_t pos = 0;
313     int sof = 1;
314 
315     if (!stream_running(s) || stream_idle(s)) {
316         return 0;
317     }
318 
319     while (len) {
320         stream_desc_load(s, s->regs[R_CURDESC]);
321 
322         if (s->desc.status & SDESC_STATUS_COMPLETE) {
323             s->regs[R_DMASR] |= DMASR_HALTED;
324             break;
325         }
326 
327         rxlen = s->desc.control & SDESC_CTRL_LEN_MASK;
328         if (rxlen > len) {
329             /* It fits.  */
330             rxlen = len;
331         }
332 
333         cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
334         len -= rxlen;
335         pos += rxlen;
336 
337         /* Update the descriptor.  */
338         if (!len) {
339             stream_complete(s);
340             memcpy(s->desc.app, s->app, sizeof(s->desc.app));
341             s->desc.status |= SDESC_STATUS_EOF;
342         }
343 
344         s->desc.status |= sof << SDESC_STATUS_SOF_BIT;
345         s->desc.status |= SDESC_STATUS_COMPLETE;
346         stream_desc_store(s, s->regs[R_CURDESC]);
347         sof = 0;
348 
349         /* Advance.  */
350         prev_d = s->regs[R_CURDESC];
351         s->regs[R_CURDESC] = s->desc.nxtdesc;
352         if (prev_d == s->regs[R_TAILDESC]) {
353             s->regs[R_DMASR] |= DMASR_IDLE;
354             break;
355         }
356     }
357 
358     return pos;
359 }
360 
361 static void xilinx_axidma_reset(DeviceState *dev)
362 {
363     int i;
364     XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
365 
366     for (i = 0; i < 2; i++) {
367         stream_reset(&s->streams[i]);
368     }
369 }
370 
371 static size_t
372 xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
373                                   size_t len)
374 {
375     XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
376     struct Stream *s = &cs->dma->streams[1];
377 
378     if (len != CONTROL_PAYLOAD_SIZE) {
379         hw_error("AXI DMA requires %d byte control stream payload\n",
380                  (int)CONTROL_PAYLOAD_SIZE);
381     }
382 
383     memcpy(s->app, buf, len);
384     return len;
385 }
386 
387 static bool
388 xilinx_axidma_data_stream_can_push(StreamSlave *obj,
389                                    StreamCanPushNotifyFn notify,
390                                    void *notify_opaque)
391 {
392     XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
393     struct Stream *s = &ds->dma->streams[1];
394 
395     if (!stream_running(s) || stream_idle(s)) {
396         ds->dma->notify = notify;
397         ds->dma->notify_opaque = notify_opaque;
398         return false;
399     }
400 
401     return true;
402 }
403 
404 static size_t
405 xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len)
406 {
407     XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
408     struct Stream *s = &ds->dma->streams[1];
409     size_t ret;
410 
411     ret = stream_process_s2mem(s, buf, len);
412     stream_update_irq(s);
413     return ret;
414 }
415 
416 static uint64_t axidma_read(void *opaque, hwaddr addr,
417                             unsigned size)
418 {
419     XilinxAXIDMA *d = opaque;
420     struct Stream *s;
421     uint32_t r = 0;
422     int sid;
423 
424     sid = streamid_from_addr(addr);
425     s = &d->streams[sid];
426 
427     addr = addr % 0x30;
428     addr >>= 2;
429     switch (addr) {
430         case R_DMACR:
431             /* Simulate one cycles reset delay.  */
432             s->regs[addr] &= ~DMACR_RESET;
433             r = s->regs[addr];
434             break;
435         case R_DMASR:
436             s->regs[addr] &= 0xffff;
437             s->regs[addr] |= (s->complete_cnt & 0xff) << 16;
438             s->regs[addr] |= (ptimer_get_count(s->ptimer) & 0xff) << 24;
439             r = s->regs[addr];
440             break;
441         default:
442             r = s->regs[addr];
443             D(qemu_log("%s ch=%d addr=" TARGET_FMT_plx " v=%x\n",
444                            __func__, sid, addr * 4, r));
445             break;
446     }
447     return r;
448 
449 }
450 
451 static void axidma_write(void *opaque, hwaddr addr,
452                          uint64_t value, unsigned size)
453 {
454     XilinxAXIDMA *d = opaque;
455     struct Stream *s;
456     int sid;
457 
458     sid = streamid_from_addr(addr);
459     s = &d->streams[sid];
460 
461     addr = addr % 0x30;
462     addr >>= 2;
463     switch (addr) {
464         case R_DMACR:
465             /* Tailptr mode is always on.  */
466             value |= DMACR_TAILPTR_MODE;
467             /* Remember our previous reset state.  */
468             value |= (s->regs[addr] & DMACR_RESET);
469             s->regs[addr] = value;
470 
471             if (value & DMACR_RESET) {
472                 stream_reset(s);
473             }
474 
475             if ((value & 1) && !stream_resetting(s)) {
476                 /* Start processing.  */
477                 s->regs[R_DMASR] &= ~(DMASR_HALTED | DMASR_IDLE);
478             }
479             stream_reload_complete_cnt(s);
480             break;
481 
482         case R_DMASR:
483             /* Mask away write to clear irq lines.  */
484             value &= ~(value & DMASR_IRQ_MASK);
485             s->regs[addr] = value;
486             break;
487 
488         case R_TAILDESC:
489             s->regs[addr] = value;
490             s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle.  */
491             if (!sid) {
492                 stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev);
493             }
494             break;
495         default:
496             D(qemu_log("%s: ch=%d addr=" TARGET_FMT_plx " v=%x\n",
497                   __func__, sid, addr * 4, (unsigned)value));
498             s->regs[addr] = value;
499             break;
500     }
501     if (sid == 1 && d->notify) {
502         StreamCanPushNotifyFn notifytmp = d->notify;
503         d->notify = NULL;
504         notifytmp(d->notify_opaque);
505     }
506     stream_update_irq(s);
507 }
508 
509 static const MemoryRegionOps axidma_ops = {
510     .read = axidma_read,
511     .write = axidma_write,
512     .endianness = DEVICE_NATIVE_ENDIAN,
513 };
514 
515 static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
516 {
517     XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
518     XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
519     XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
520                                                             &s->rx_control_dev);
521     Error *local_err = NULL;
522 
523     object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
524                              (Object **)&ds->dma,
525                              object_property_allow_set_link,
526                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
527                              &local_err);
528     object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
529                              (Object **)&cs->dma,
530                              object_property_allow_set_link,
531                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
532                              &local_err);
533     if (local_err) {
534         goto xilinx_axidma_realize_fail;
535     }
536     object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_err);
537     object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_err);
538     if (local_err) {
539         goto xilinx_axidma_realize_fail;
540     }
541 
542     int i;
543 
544     for (i = 0; i < 2; i++) {
545         struct Stream *st = &s->streams[i];
546 
547         st->nr = i;
548         st->bh = qemu_bh_new(timer_hit, st);
549         st->ptimer = ptimer_init(st->bh);
550         ptimer_set_freq(st->ptimer, s->freqhz);
551     }
552     return;
553 
554 xilinx_axidma_realize_fail:
555     if (!*errp) {
556         *errp = local_err;
557     }
558 }
559 
560 static void xilinx_axidma_init(Object *obj)
561 {
562     XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
563     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
564 
565     object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
566                              (Object **)&s->tx_data_dev,
567                              qdev_prop_allow_set_link_before_realize,
568                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
569                              &error_abort);
570     object_property_add_link(obj, "axistream-control-connected",
571                              TYPE_STREAM_SLAVE,
572                              (Object **)&s->tx_control_dev,
573                              qdev_prop_allow_set_link_before_realize,
574                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
575                              &error_abort);
576 
577     object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
578                       TYPE_XILINX_AXI_DMA_DATA_STREAM);
579     object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev),
580                       TYPE_XILINX_AXI_DMA_CONTROL_STREAM);
581     object_property_add_child(OBJECT(s), "axistream-connected-target",
582                               (Object *)&s->rx_data_dev, &error_abort);
583     object_property_add_child(OBJECT(s), "axistream-control-connected-target",
584                               (Object *)&s->rx_control_dev, &error_abort);
585 
586     sysbus_init_irq(sbd, &s->streams[0].irq);
587     sysbus_init_irq(sbd, &s->streams[1].irq);
588 
589     memory_region_init_io(&s->iomem, obj, &axidma_ops, s,
590                           "xlnx.axi-dma", R_MAX * 4 * 2);
591     sysbus_init_mmio(sbd, &s->iomem);
592 }
593 
594 static Property axidma_properties[] = {
595     DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000),
596     DEFINE_PROP_END_OF_LIST(),
597 };
598 
599 static void axidma_class_init(ObjectClass *klass, void *data)
600 {
601     DeviceClass *dc = DEVICE_CLASS(klass);
602 
603     dc->realize = xilinx_axidma_realize,
604     dc->reset = xilinx_axidma_reset;
605     dc->props = axidma_properties;
606 }
607 
608 static StreamSlaveClass xilinx_axidma_data_stream_class = {
609     .push = xilinx_axidma_data_stream_push,
610     .can_push = xilinx_axidma_data_stream_can_push,
611 };
612 
613 static StreamSlaveClass xilinx_axidma_control_stream_class = {
614     .push = xilinx_axidma_control_stream_push,
615 };
616 
617 static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
618 {
619     StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
620 
621     ssc->push = ((StreamSlaveClass *)data)->push;
622     ssc->can_push = ((StreamSlaveClass *)data)->can_push;
623 }
624 
625 static const TypeInfo axidma_info = {
626     .name          = TYPE_XILINX_AXI_DMA,
627     .parent        = TYPE_SYS_BUS_DEVICE,
628     .instance_size = sizeof(XilinxAXIDMA),
629     .class_init    = axidma_class_init,
630     .instance_init = xilinx_axidma_init,
631 };
632 
633 static const TypeInfo xilinx_axidma_data_stream_info = {
634     .name          = TYPE_XILINX_AXI_DMA_DATA_STREAM,
635     .parent        = TYPE_OBJECT,
636     .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
637     .class_init    = xilinx_axidma_stream_class_init,
638     .class_data    = &xilinx_axidma_data_stream_class,
639     .interfaces = (InterfaceInfo[]) {
640         { TYPE_STREAM_SLAVE },
641         { }
642     }
643 };
644 
645 static const TypeInfo xilinx_axidma_control_stream_info = {
646     .name          = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
647     .parent        = TYPE_OBJECT,
648     .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
649     .class_init    = xilinx_axidma_stream_class_init,
650     .class_data    = &xilinx_axidma_control_stream_class,
651     .interfaces = (InterfaceInfo[]) {
652         { TYPE_STREAM_SLAVE },
653         { }
654     }
655 };
656 
657 static void xilinx_axidma_register_types(void)
658 {
659     type_register_static(&axidma_info);
660     type_register_static(&xilinx_axidma_data_stream_info);
661     type_register_static(&xilinx_axidma_control_stream_info);
662 }
663 
664 type_init(xilinx_axidma_register_types)
665