xref: /openbmc/qemu/hw/dma/xilinx_axidma.c (revision fb37726d)
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 #ifdef DEBUG_ENET
181 static void stream_desc_show(struct SDesc *d)
182 {
183     qemu_log("buffer_addr  = " PRIx64 "\n", d->buffer_address);
184     qemu_log("nxtdesc      = " PRIx64 "\n", d->nxtdesc);
185     qemu_log("control      = %x\n", d->control);
186     qemu_log("status       = %x\n", d->status);
187 }
188 #endif
189 
190 static void stream_desc_load(struct Stream *s, hwaddr addr)
191 {
192     struct SDesc *d = &s->desc;
193 
194     cpu_physical_memory_read(addr, d, sizeof *d);
195 
196     /* Convert from LE into host endianness.  */
197     d->buffer_address = le64_to_cpu(d->buffer_address);
198     d->nxtdesc = le64_to_cpu(d->nxtdesc);
199     d->control = le32_to_cpu(d->control);
200     d->status = le32_to_cpu(d->status);
201 }
202 
203 static void stream_desc_store(struct Stream *s, hwaddr addr)
204 {
205     struct SDesc *d = &s->desc;
206 
207     /* Convert from host endianness into LE.  */
208     d->buffer_address = cpu_to_le64(d->buffer_address);
209     d->nxtdesc = cpu_to_le64(d->nxtdesc);
210     d->control = cpu_to_le32(d->control);
211     d->status = cpu_to_le32(d->status);
212     cpu_physical_memory_write(addr, d, sizeof *d);
213 }
214 
215 static void stream_update_irq(struct Stream *s)
216 {
217     unsigned int pending, mask, irq;
218 
219     pending = s->regs[R_DMASR] & DMASR_IRQ_MASK;
220     mask = s->regs[R_DMACR] & DMASR_IRQ_MASK;
221 
222     irq = pending & mask;
223 
224     qemu_set_irq(s->irq, !!irq);
225 }
226 
227 static void stream_reload_complete_cnt(struct Stream *s)
228 {
229     unsigned int comp_th;
230     comp_th = (s->regs[R_DMACR] >> 16) & 0xff;
231     s->complete_cnt = comp_th;
232 }
233 
234 static void timer_hit(void *opaque)
235 {
236     struct Stream *s = opaque;
237 
238     stream_reload_complete_cnt(s);
239     s->regs[R_DMASR] |= DMASR_DLY_IRQ;
240     stream_update_irq(s);
241 }
242 
243 static void stream_complete(struct Stream *s)
244 {
245     unsigned int comp_delay;
246 
247     /* Start the delayed timer.  */
248     comp_delay = s->regs[R_DMACR] >> 24;
249     if (comp_delay) {
250         ptimer_stop(s->ptimer);
251         ptimer_set_count(s->ptimer, comp_delay);
252         ptimer_run(s->ptimer, 1);
253     }
254 
255     s->complete_cnt--;
256     if (s->complete_cnt == 0) {
257         /* Raise the IOC irq.  */
258         s->regs[R_DMASR] |= DMASR_IOC_IRQ;
259         stream_reload_complete_cnt(s);
260     }
261 }
262 
263 static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
264                                  StreamSlave *tx_control_dev)
265 {
266     uint32_t prev_d;
267     unsigned char txbuf[16 * 1024];
268     unsigned int txlen;
269 
270     if (!stream_running(s) || stream_idle(s)) {
271         return;
272     }
273 
274     while (1) {
275         stream_desc_load(s, s->regs[R_CURDESC]);
276 
277         if (s->desc.status & SDESC_STATUS_COMPLETE) {
278             s->regs[R_DMASR] |= DMASR_HALTED;
279             break;
280         }
281 
282         if (stream_desc_sof(&s->desc)) {
283             s->pos = 0;
284             stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app));
285         }
286 
287         txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
288         if ((txlen + s->pos) > sizeof txbuf) {
289             hw_error("%s: too small internal txbuf! %d\n", __func__,
290                      txlen + s->pos);
291         }
292 
293         cpu_physical_memory_read(s->desc.buffer_address,
294                                  txbuf + s->pos, txlen);
295         s->pos += txlen;
296 
297         if (stream_desc_eof(&s->desc)) {
298             stream_push(tx_data_dev, txbuf, s->pos);
299             s->pos = 0;
300             stream_complete(s);
301         }
302 
303         /* Update the descriptor.  */
304         s->desc.status = txlen | SDESC_STATUS_COMPLETE;
305         stream_desc_store(s, s->regs[R_CURDESC]);
306 
307         /* Advance.  */
308         prev_d = s->regs[R_CURDESC];
309         s->regs[R_CURDESC] = s->desc.nxtdesc;
310         if (prev_d == s->regs[R_TAILDESC]) {
311             s->regs[R_DMASR] |= DMASR_IDLE;
312             break;
313         }
314     }
315 }
316 
317 static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
318                                    size_t len)
319 {
320     uint32_t prev_d;
321     unsigned int rxlen;
322     size_t pos = 0;
323     int sof = 1;
324 
325     if (!stream_running(s) || stream_idle(s)) {
326         return 0;
327     }
328 
329     while (len) {
330         stream_desc_load(s, s->regs[R_CURDESC]);
331 
332         if (s->desc.status & SDESC_STATUS_COMPLETE) {
333             s->regs[R_DMASR] |= DMASR_HALTED;
334             break;
335         }
336 
337         rxlen = s->desc.control & SDESC_CTRL_LEN_MASK;
338         if (rxlen > len) {
339             /* It fits.  */
340             rxlen = len;
341         }
342 
343         cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
344         len -= rxlen;
345         pos += rxlen;
346 
347         /* Update the descriptor.  */
348         if (!len) {
349             stream_complete(s);
350             memcpy(s->desc.app, s->app, sizeof(s->desc.app));
351             s->desc.status |= SDESC_STATUS_EOF;
352         }
353 
354         s->desc.status |= sof << SDESC_STATUS_SOF_BIT;
355         s->desc.status |= SDESC_STATUS_COMPLETE;
356         stream_desc_store(s, s->regs[R_CURDESC]);
357         sof = 0;
358 
359         /* Advance.  */
360         prev_d = s->regs[R_CURDESC];
361         s->regs[R_CURDESC] = s->desc.nxtdesc;
362         if (prev_d == s->regs[R_TAILDESC]) {
363             s->regs[R_DMASR] |= DMASR_IDLE;
364             break;
365         }
366     }
367 
368     return pos;
369 }
370 
371 static void xilinx_axidma_reset(DeviceState *dev)
372 {
373     int i;
374     XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
375 
376     for (i = 0; i < 2; i++) {
377         stream_reset(&s->streams[i]);
378     }
379 }
380 
381 static size_t
382 xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
383                                   size_t len)
384 {
385     XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
386     struct Stream *s = &cs->dma->streams[1];
387 
388     if (len != CONTROL_PAYLOAD_SIZE) {
389         hw_error("AXI DMA requires %d byte control stream payload\n",
390                  (int)CONTROL_PAYLOAD_SIZE);
391     }
392 
393     memcpy(s->app, buf, len);
394     return len;
395 }
396 
397 static bool
398 xilinx_axidma_data_stream_can_push(StreamSlave *obj,
399                                    StreamCanPushNotifyFn notify,
400                                    void *notify_opaque)
401 {
402     XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
403     struct Stream *s = &ds->dma->streams[1];
404 
405     if (!stream_running(s) || stream_idle(s)) {
406         ds->dma->notify = notify;
407         ds->dma->notify_opaque = notify_opaque;
408         return false;
409     }
410 
411     return true;
412 }
413 
414 static size_t
415 xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len)
416 {
417     XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
418     struct Stream *s = &ds->dma->streams[1];
419     size_t ret;
420 
421     ret = stream_process_s2mem(s, buf, len);
422     stream_update_irq(s);
423     return ret;
424 }
425 
426 static uint64_t axidma_read(void *opaque, hwaddr addr,
427                             unsigned size)
428 {
429     XilinxAXIDMA *d = opaque;
430     struct Stream *s;
431     uint32_t r = 0;
432     int sid;
433 
434     sid = streamid_from_addr(addr);
435     s = &d->streams[sid];
436 
437     addr = addr % 0x30;
438     addr >>= 2;
439     switch (addr) {
440         case R_DMACR:
441             /* Simulate one cycles reset delay.  */
442             s->regs[addr] &= ~DMACR_RESET;
443             r = s->regs[addr];
444             break;
445         case R_DMASR:
446             s->regs[addr] &= 0xffff;
447             s->regs[addr] |= (s->complete_cnt & 0xff) << 16;
448             s->regs[addr] |= (ptimer_get_count(s->ptimer) & 0xff) << 24;
449             r = s->regs[addr];
450             break;
451         default:
452             r = s->regs[addr];
453             D(qemu_log("%s ch=%d addr=" TARGET_FMT_plx " v=%x\n",
454                            __func__, sid, addr * 4, r));
455             break;
456     }
457     return r;
458 
459 }
460 
461 static void axidma_write(void *opaque, hwaddr addr,
462                          uint64_t value, unsigned size)
463 {
464     XilinxAXIDMA *d = opaque;
465     struct Stream *s;
466     int sid;
467 
468     sid = streamid_from_addr(addr);
469     s = &d->streams[sid];
470 
471     addr = addr % 0x30;
472     addr >>= 2;
473     switch (addr) {
474         case R_DMACR:
475             /* Tailptr mode is always on.  */
476             value |= DMACR_TAILPTR_MODE;
477             /* Remember our previous reset state.  */
478             value |= (s->regs[addr] & DMACR_RESET);
479             s->regs[addr] = value;
480 
481             if (value & DMACR_RESET) {
482                 stream_reset(s);
483             }
484 
485             if ((value & 1) && !stream_resetting(s)) {
486                 /* Start processing.  */
487                 s->regs[R_DMASR] &= ~(DMASR_HALTED | DMASR_IDLE);
488             }
489             stream_reload_complete_cnt(s);
490             break;
491 
492         case R_DMASR:
493             /* Mask away write to clear irq lines.  */
494             value &= ~(value & DMASR_IRQ_MASK);
495             s->regs[addr] = value;
496             break;
497 
498         case R_TAILDESC:
499             s->regs[addr] = value;
500             s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle.  */
501             if (!sid) {
502                 stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev);
503             }
504             break;
505         default:
506             D(qemu_log("%s: ch=%d addr=" TARGET_FMT_plx " v=%x\n",
507                   __func__, sid, addr * 4, (unsigned)value));
508             s->regs[addr] = value;
509             break;
510     }
511     if (sid == 1 && d->notify) {
512         StreamCanPushNotifyFn notifytmp = d->notify;
513         d->notify = NULL;
514         notifytmp(d->notify_opaque);
515     }
516     stream_update_irq(s);
517 }
518 
519 static const MemoryRegionOps axidma_ops = {
520     .read = axidma_read,
521     .write = axidma_write,
522     .endianness = DEVICE_NATIVE_ENDIAN,
523 };
524 
525 static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
526 {
527     XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
528     XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
529     XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
530                                                             &s->rx_control_dev);
531     Error *local_err = NULL;
532 
533     object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
534                              (Object **)&ds->dma,
535                              object_property_allow_set_link,
536                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
537                              &local_err);
538     object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
539                              (Object **)&cs->dma,
540                              object_property_allow_set_link,
541                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
542                              &local_err);
543     if (local_err) {
544         goto xilinx_axidma_realize_fail;
545     }
546     object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_err);
547     object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_err);
548     if (local_err) {
549         goto xilinx_axidma_realize_fail;
550     }
551 
552     int i;
553 
554     for (i = 0; i < 2; i++) {
555         struct Stream *st = &s->streams[i];
556 
557         st->nr = i;
558         st->bh = qemu_bh_new(timer_hit, st);
559         st->ptimer = ptimer_init(st->bh);
560         ptimer_set_freq(st->ptimer, s->freqhz);
561     }
562     return;
563 
564 xilinx_axidma_realize_fail:
565     if (!*errp) {
566         *errp = local_err;
567     }
568 }
569 
570 static void xilinx_axidma_init(Object *obj)
571 {
572     XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
573     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
574 
575     object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
576                              (Object **)&s->tx_data_dev,
577                              qdev_prop_allow_set_link_before_realize,
578                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
579                              &error_abort);
580     object_property_add_link(obj, "axistream-control-connected",
581                              TYPE_STREAM_SLAVE,
582                              (Object **)&s->tx_control_dev,
583                              qdev_prop_allow_set_link_before_realize,
584                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
585                              &error_abort);
586 
587     object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
588                       TYPE_XILINX_AXI_DMA_DATA_STREAM);
589     object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev),
590                       TYPE_XILINX_AXI_DMA_CONTROL_STREAM);
591     object_property_add_child(OBJECT(s), "axistream-connected-target",
592                               (Object *)&s->rx_data_dev, &error_abort);
593     object_property_add_child(OBJECT(s), "axistream-control-connected-target",
594                               (Object *)&s->rx_control_dev, &error_abort);
595 
596     sysbus_init_irq(sbd, &s->streams[0].irq);
597     sysbus_init_irq(sbd, &s->streams[1].irq);
598 
599     memory_region_init_io(&s->iomem, obj, &axidma_ops, s,
600                           "xlnx.axi-dma", R_MAX * 4 * 2);
601     sysbus_init_mmio(sbd, &s->iomem);
602 }
603 
604 static Property axidma_properties[] = {
605     DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000),
606     DEFINE_PROP_END_OF_LIST(),
607 };
608 
609 static void axidma_class_init(ObjectClass *klass, void *data)
610 {
611     DeviceClass *dc = DEVICE_CLASS(klass);
612 
613     dc->realize = xilinx_axidma_realize,
614     dc->reset = xilinx_axidma_reset;
615     dc->props = axidma_properties;
616 }
617 
618 static StreamSlaveClass xilinx_axidma_data_stream_class = {
619     .push = xilinx_axidma_data_stream_push,
620     .can_push = xilinx_axidma_data_stream_can_push,
621 };
622 
623 static StreamSlaveClass xilinx_axidma_control_stream_class = {
624     .push = xilinx_axidma_control_stream_push,
625 };
626 
627 static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
628 {
629     StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
630 
631     ssc->push = ((StreamSlaveClass *)data)->push;
632     ssc->can_push = ((StreamSlaveClass *)data)->can_push;
633 }
634 
635 static const TypeInfo axidma_info = {
636     .name          = TYPE_XILINX_AXI_DMA,
637     .parent        = TYPE_SYS_BUS_DEVICE,
638     .instance_size = sizeof(XilinxAXIDMA),
639     .class_init    = axidma_class_init,
640     .instance_init = xilinx_axidma_init,
641 };
642 
643 static const TypeInfo xilinx_axidma_data_stream_info = {
644     .name          = TYPE_XILINX_AXI_DMA_DATA_STREAM,
645     .parent        = TYPE_OBJECT,
646     .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
647     .class_init    = xilinx_axidma_stream_class_init,
648     .class_data    = &xilinx_axidma_data_stream_class,
649     .interfaces = (InterfaceInfo[]) {
650         { TYPE_STREAM_SLAVE },
651         { }
652     }
653 };
654 
655 static const TypeInfo xilinx_axidma_control_stream_info = {
656     .name          = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
657     .parent        = TYPE_OBJECT,
658     .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
659     .class_init    = xilinx_axidma_stream_class_init,
660     .class_data    = &xilinx_axidma_control_stream_class,
661     .interfaces = (InterfaceInfo[]) {
662         { TYPE_STREAM_SLAVE },
663         { }
664     }
665 };
666 
667 static void xilinx_axidma_register_types(void)
668 {
669     type_register_static(&axidma_info);
670     type_register_static(&xilinx_axidma_data_stream_info);
671     type_register_static(&xilinx_axidma_control_stream_info);
672 }
673 
674 type_init(xilinx_axidma_register_types)
675