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