Statistics
| Branch: | Revision:

root / hw / dma / xilinx_axidma.c @ 6a1751b7

History | View | Annotate | Download (18.2 kB)

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 "qapi/qmp/qerror.h"
30
#include "qemu/main-loop.h"
31

    
32
#include "hw/stream.h"
33

    
34
#define D(x)
35

    
36
#define TYPE_XILINX_AXI_DMA "xlnx.axi-dma"
37
#define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream"
38
#define TYPE_XILINX_AXI_DMA_CONTROL_STREAM "xilinx-axi-dma-control-stream"
39

    
40
#define XILINX_AXI_DMA(obj) \
41
     OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA)
42

    
43
#define XILINX_AXI_DMA_DATA_STREAM(obj) \
44
     OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
45
     TYPE_XILINX_AXI_DMA_DATA_STREAM)
46

    
47
#define XILINX_AXI_DMA_CONTROL_STREAM(obj) \
48
     OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\
49
     TYPE_XILINX_AXI_DMA_CONTROL_STREAM)
50

    
51
#define R_DMACR             (0x00 / 4)
52
#define R_DMASR             (0x04 / 4)
53
#define R_CURDESC           (0x08 / 4)
54
#define R_TAILDESC          (0x10 / 4)
55
#define R_MAX               (0x30 / 4)
56

    
57
#define CONTROL_PAYLOAD_WORDS 5
58
#define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t)))
59

    
60
typedef struct XilinxAXIDMA XilinxAXIDMA;
61
typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave;
62

    
63
enum {
64
    DMACR_RUNSTOP = 1,
65
    DMACR_TAILPTR_MODE = 2,
66
    DMACR_RESET = 4
67
};
68

    
69
enum {
70
    DMASR_HALTED = 1,
71
    DMASR_IDLE  = 2,
72
    DMASR_IOC_IRQ  = 1 << 12,
73
    DMASR_DLY_IRQ  = 1 << 13,
74

    
75
    DMASR_IRQ_MASK = 7 << 12
76
};
77

    
78
struct SDesc {
79
    uint64_t nxtdesc;
80
    uint64_t buffer_address;
81
    uint64_t reserved;
82
    uint32_t control;
83
    uint32_t status;
84
    uint8_t app[CONTROL_PAYLOAD_SIZE];
85
};
86

    
87
enum {
88
    SDESC_CTRL_EOF = (1 << 26),
89
    SDESC_CTRL_SOF = (1 << 27),
90

    
91
    SDESC_CTRL_LEN_MASK = (1 << 23) - 1
92
};
93

    
94
enum {
95
    SDESC_STATUS_EOF = (1 << 26),
96
    SDESC_STATUS_SOF_BIT = 27,
97
    SDESC_STATUS_SOF = (1 << SDESC_STATUS_SOF_BIT),
98
    SDESC_STATUS_COMPLETE = (1 << 31)
99
};
100

    
101
struct Stream {
102
    QEMUBH *bh;
103
    ptimer_state *ptimer;
104
    qemu_irq irq;
105

    
106
    int nr;
107

    
108
    struct SDesc desc;
109
    int pos;
110
    unsigned int complete_cnt;
111
    uint32_t regs[R_MAX];
112
    uint8_t app[20];
113
};
114

    
115
struct XilinxAXIDMAStreamSlave {
116
    Object parent;
117

    
118
    struct XilinxAXIDMA *dma;
119
};
120

    
121
struct XilinxAXIDMA {
122
    SysBusDevice busdev;
123
    MemoryRegion iomem;
124
    uint32_t freqhz;
125
    StreamSlave *tx_data_dev;
126
    StreamSlave *tx_control_dev;
127
    XilinxAXIDMAStreamSlave rx_data_dev;
128
    XilinxAXIDMAStreamSlave rx_control_dev;
129

    
130
    struct Stream streams[2];
131

    
132
    StreamCanPushNotifyFn notify;
133
    void *notify_opaque;
134
};
135

    
136
/*
137
 * Helper calls to extract info from desriptors and other trivial
138
 * state from regs.
139
 */
140
static inline int stream_desc_sof(struct SDesc *d)
141
{
142
    return d->control & SDESC_CTRL_SOF;
143
}
144

    
145
static inline int stream_desc_eof(struct SDesc *d)
146
{
147
    return d->control & SDESC_CTRL_EOF;
148
}
149

    
150
static inline int stream_resetting(struct Stream *s)
151
{
152
    return !!(s->regs[R_DMACR] & DMACR_RESET);
153
}
154

    
155
static inline int stream_running(struct Stream *s)
156
{
157
    return s->regs[R_DMACR] & DMACR_RUNSTOP;
158
}
159

    
160
static inline int stream_halted(struct Stream *s)
161
{
162
    return s->regs[R_DMASR] & DMASR_HALTED;
163
}
164

    
165
static inline int stream_idle(struct Stream *s)
166
{
167
    return !!(s->regs[R_DMASR] & DMASR_IDLE);
168
}
169

    
170
static void stream_reset(struct Stream *s)
171
{
172
    s->regs[R_DMASR] = DMASR_HALTED;  /* starts up halted.  */
173
    s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold.  */
174
}
175

    
176
/* Map an offset addr into a channel index.  */
177
static inline int streamid_from_addr(hwaddr addr)
178
{
179
    int sid;
180

    
181
    sid = addr / (0x30);
182
    sid &= 1;
183
    return sid;
184
}
185

    
186
#ifdef DEBUG_ENET
187
static void stream_desc_show(struct SDesc *d)
188
{
189
    qemu_log("buffer_addr  = " PRIx64 "\n", d->buffer_address);
190
    qemu_log("nxtdesc      = " PRIx64 "\n", d->nxtdesc);
191
    qemu_log("control      = %x\n", d->control);
192
    qemu_log("status       = %x\n", d->status);
193
}
194
#endif
195

    
196
static void stream_desc_load(struct Stream *s, hwaddr addr)
197
{
198
    struct SDesc *d = &s->desc;
199

    
200
    cpu_physical_memory_read(addr, d, sizeof *d);
201

    
202
    /* Convert from LE into host endianness.  */
203
    d->buffer_address = le64_to_cpu(d->buffer_address);
204
    d->nxtdesc = le64_to_cpu(d->nxtdesc);
205
    d->control = le32_to_cpu(d->control);
206
    d->status = le32_to_cpu(d->status);
207
}
208

    
209
static void stream_desc_store(struct Stream *s, hwaddr addr)
210
{
211
    struct SDesc *d = &s->desc;
212

    
213
    /* Convert from host endianness into LE.  */
214
    d->buffer_address = cpu_to_le64(d->buffer_address);
215
    d->nxtdesc = cpu_to_le64(d->nxtdesc);
216
    d->control = cpu_to_le32(d->control);
217
    d->status = cpu_to_le32(d->status);
218
    cpu_physical_memory_write(addr, d, sizeof *d);
219
}
220

    
221
static void stream_update_irq(struct Stream *s)
222
{
223
    unsigned int pending, mask, irq;
224

    
225
    pending = s->regs[R_DMASR] & DMASR_IRQ_MASK;
226
    mask = s->regs[R_DMACR] & DMASR_IRQ_MASK;
227

    
228
    irq = pending & mask;
229

    
230
    qemu_set_irq(s->irq, !!irq);
231
}
232

    
233
static void stream_reload_complete_cnt(struct Stream *s)
234
{
235
    unsigned int comp_th;
236
    comp_th = (s->regs[R_DMACR] >> 16) & 0xff;
237
    s->complete_cnt = comp_th;
238
}
239

    
240
static void timer_hit(void *opaque)
241
{
242
    struct Stream *s = opaque;
243

    
244
    stream_reload_complete_cnt(s);
245
    s->regs[R_DMASR] |= DMASR_DLY_IRQ;
246
    stream_update_irq(s);
247
}
248

    
249
static void stream_complete(struct Stream *s)
250
{
251
    unsigned int comp_delay;
252

    
253
    /* Start the delayed timer.  */
254
    comp_delay = s->regs[R_DMACR] >> 24;
255
    if (comp_delay) {
256
        ptimer_stop(s->ptimer);
257
        ptimer_set_count(s->ptimer, comp_delay);
258
        ptimer_run(s->ptimer, 1);
259
    }
260

    
261
    s->complete_cnt--;
262
    if (s->complete_cnt == 0) {
263
        /* Raise the IOC irq.  */
264
        s->regs[R_DMASR] |= DMASR_IOC_IRQ;
265
        stream_reload_complete_cnt(s);
266
    }
267
}
268

    
269
static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
270
                                 StreamSlave *tx_control_dev)
271
{
272
    uint32_t prev_d;
273
    unsigned char txbuf[16 * 1024];
274
    unsigned int txlen;
275

    
276
    if (!stream_running(s) || stream_idle(s)) {
277
        return;
278
    }
279

    
280
    while (1) {
281
        stream_desc_load(s, s->regs[R_CURDESC]);
282

    
283
        if (s->desc.status & SDESC_STATUS_COMPLETE) {
284
            s->regs[R_DMASR] |= DMASR_HALTED;
285
            break;
286
        }
287

    
288
        if (stream_desc_sof(&s->desc)) {
289
            s->pos = 0;
290
            stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app));
291
        }
292

    
293
        txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
294
        if ((txlen + s->pos) > sizeof txbuf) {
295
            hw_error("%s: too small internal txbuf! %d\n", __func__,
296
                     txlen + s->pos);
297
        }
298

    
299
        cpu_physical_memory_read(s->desc.buffer_address,
300
                                 txbuf + s->pos, txlen);
301
        s->pos += txlen;
302

    
303
        if (stream_desc_eof(&s->desc)) {
304
            stream_push(tx_data_dev, txbuf, s->pos);
305
            s->pos = 0;
306
            stream_complete(s);
307
        }
308

    
309
        /* Update the descriptor.  */
310
        s->desc.status = txlen | SDESC_STATUS_COMPLETE;
311
        stream_desc_store(s, s->regs[R_CURDESC]);
312

    
313
        /* Advance.  */
314
        prev_d = s->regs[R_CURDESC];
315
        s->regs[R_CURDESC] = s->desc.nxtdesc;
316
        if (prev_d == s->regs[R_TAILDESC]) {
317
            s->regs[R_DMASR] |= DMASR_IDLE;
318
            break;
319
        }
320
    }
321
}
322

    
323
static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
324
                                   size_t len)
325
{
326
    uint32_t prev_d;
327
    unsigned int rxlen;
328
    size_t pos = 0;
329
    int sof = 1;
330

    
331
    if (!stream_running(s) || stream_idle(s)) {
332
        return 0;
333
    }
334

    
335
    while (len) {
336
        stream_desc_load(s, s->regs[R_CURDESC]);
337

    
338
        if (s->desc.status & SDESC_STATUS_COMPLETE) {
339
            s->regs[R_DMASR] |= DMASR_HALTED;
340
            break;
341
        }
342

    
343
        rxlen = s->desc.control & SDESC_CTRL_LEN_MASK;
344
        if (rxlen > len) {
345
            /* It fits.  */
346
            rxlen = len;
347
        }
348

    
349
        cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
350
        len -= rxlen;
351
        pos += rxlen;
352

    
353
        /* Update the descriptor.  */
354
        if (!len) {
355
            stream_complete(s);
356
            memcpy(s->desc.app, s->app, sizeof(s->desc.app));
357
            s->desc.status |= SDESC_STATUS_EOF;
358
        }
359

    
360
        s->desc.status |= sof << SDESC_STATUS_SOF_BIT;
361
        s->desc.status |= SDESC_STATUS_COMPLETE;
362
        stream_desc_store(s, s->regs[R_CURDESC]);
363
        sof = 0;
364

    
365
        /* Advance.  */
366
        prev_d = s->regs[R_CURDESC];
367
        s->regs[R_CURDESC] = s->desc.nxtdesc;
368
        if (prev_d == s->regs[R_TAILDESC]) {
369
            s->regs[R_DMASR] |= DMASR_IDLE;
370
            break;
371
        }
372
    }
373

    
374
    return pos;
375
}
376

    
377
static void xilinx_axidma_reset(DeviceState *dev)
378
{
379
    int i;
380
    XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
381

    
382
    for (i = 0; i < 2; i++) {
383
        stream_reset(&s->streams[i]);
384
    }
385
}
386

    
387
static size_t
388
xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
389
                                  size_t len)
390
{
391
    XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
392
    struct Stream *s = &cs->dma->streams[1];
393

    
394
    if (len != CONTROL_PAYLOAD_SIZE) {
395
        hw_error("AXI DMA requires %d byte control stream payload\n",
396
                 (int)CONTROL_PAYLOAD_SIZE);
397
    }
398

    
399
    memcpy(s->app, buf, len);
400
    return len;
401
}
402

    
403
static bool
404
xilinx_axidma_data_stream_can_push(StreamSlave *obj,
405
                                   StreamCanPushNotifyFn notify,
406
                                   void *notify_opaque)
407
{
408
    XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
409
    struct Stream *s = &ds->dma->streams[1];
410

    
411
    if (!stream_running(s) || stream_idle(s)) {
412
        ds->dma->notify = notify;
413
        ds->dma->notify_opaque = notify_opaque;
414
        return false;
415
    }
416

    
417
    return true;
418
}
419

    
420
static size_t
421
xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len)
422
{
423
    XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
424
    struct Stream *s = &ds->dma->streams[1];
425
    size_t ret;
426

    
427
    ret = stream_process_s2mem(s, buf, len);
428
    stream_update_irq(s);
429
    return ret;
430
}
431

    
432
static uint64_t axidma_read(void *opaque, hwaddr addr,
433
                            unsigned size)
434
{
435
    XilinxAXIDMA *d = opaque;
436
    struct Stream *s;
437
    uint32_t r = 0;
438
    int sid;
439

    
440
    sid = streamid_from_addr(addr);
441
    s = &d->streams[sid];
442

    
443
    addr = addr % 0x30;
444
    addr >>= 2;
445
    switch (addr) {
446
        case R_DMACR:
447
            /* Simulate one cycles reset delay.  */
448
            s->regs[addr] &= ~DMACR_RESET;
449
            r = s->regs[addr];
450
            break;
451
        case R_DMASR:
452
            s->regs[addr] &= 0xffff;
453
            s->regs[addr] |= (s->complete_cnt & 0xff) << 16;
454
            s->regs[addr] |= (ptimer_get_count(s->ptimer) & 0xff) << 24;
455
            r = s->regs[addr];
456
            break;
457
        default:
458
            r = s->regs[addr];
459
            D(qemu_log("%s ch=%d addr=" TARGET_FMT_plx " v=%x\n",
460
                           __func__, sid, addr * 4, r));
461
            break;
462
    }
463
    return r;
464

    
465
}
466

    
467
static void axidma_write(void *opaque, hwaddr addr,
468
                         uint64_t value, unsigned size)
469
{
470
    XilinxAXIDMA *d = opaque;
471
    struct Stream *s;
472
    int sid;
473

    
474
    sid = streamid_from_addr(addr);
475
    s = &d->streams[sid];
476

    
477
    addr = addr % 0x30;
478
    addr >>= 2;
479
    switch (addr) {
480
        case R_DMACR:
481
            /* Tailptr mode is always on.  */
482
            value |= DMACR_TAILPTR_MODE;
483
            /* Remember our previous reset state.  */
484
            value |= (s->regs[addr] & DMACR_RESET);
485
            s->regs[addr] = value;
486

    
487
            if (value & DMACR_RESET) {
488
                stream_reset(s);
489
            }
490

    
491
            if ((value & 1) && !stream_resetting(s)) {
492
                /* Start processing.  */
493
                s->regs[R_DMASR] &= ~(DMASR_HALTED | DMASR_IDLE);
494
            }
495
            stream_reload_complete_cnt(s);
496
            break;
497

    
498
        case R_DMASR:
499
            /* Mask away write to clear irq lines.  */
500
            value &= ~(value & DMASR_IRQ_MASK);
501
            s->regs[addr] = value;
502
            break;
503

    
504
        case R_TAILDESC:
505
            s->regs[addr] = value;
506
            s->regs[R_DMASR] &= ~DMASR_IDLE; /* Not idle.  */
507
            if (!sid) {
508
                stream_process_mem2s(s, d->tx_data_dev, d->tx_control_dev);
509
            }
510
            break;
511
        default:
512
            D(qemu_log("%s: ch=%d addr=" TARGET_FMT_plx " v=%x\n",
513
                  __func__, sid, addr * 4, (unsigned)value));
514
            s->regs[addr] = value;
515
            break;
516
    }
517
    if (sid == 1 && d->notify) {
518
        StreamCanPushNotifyFn notifytmp = d->notify;
519
        d->notify = NULL;
520
        notifytmp(d->notify_opaque);
521
    }
522
    stream_update_irq(s);
523
}
524

    
525
static const MemoryRegionOps axidma_ops = {
526
    .read = axidma_read,
527
    .write = axidma_write,
528
    .endianness = DEVICE_NATIVE_ENDIAN,
529
};
530

    
531
static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
532
{
533
    XilinxAXIDMA *s = XILINX_AXI_DMA(dev);
534
    XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev);
535
    XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
536
                                                            &s->rx_control_dev);
537
    Error *local_errp = NULL;
538

    
539
    object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
540
                             (Object **)&ds->dma, &local_errp);
541
    object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
542
                             (Object **)&cs->dma, &local_errp);
543
    if (local_errp) {
544
        goto xilinx_axidma_realize_fail;
545
    }
546
    object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_errp);
547
    object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_errp);
548
    if (local_errp) {
549
        goto xilinx_axidma_realize_fail;
550
    }
551

    
552
    int i;
553

    
554
    for (i = 0; i < 2; i++) {
555
        s->streams[i].nr = i;
556
        s->streams[i].bh = qemu_bh_new(timer_hit, &s->streams[i]);
557
        s->streams[i].ptimer = ptimer_init(s->streams[i].bh);
558
        ptimer_set_freq(s->streams[i].ptimer, s->freqhz);
559
    }
560
    return;
561

    
562
xilinx_axidma_realize_fail:
563
    if (!*errp) {
564
        *errp = local_errp;
565
    }
566
}
567

    
568
static void xilinx_axidma_init(Object *obj)
569
{
570
    XilinxAXIDMA *s = XILINX_AXI_DMA(obj);
571
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
572
    Error *errp = NULL;
573

    
574
    object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
575
                             (Object **) &s->tx_data_dev, &errp);
576
    assert_no_error(errp);
577
    object_property_add_link(obj, "axistream-control-connected",
578
                             TYPE_STREAM_SLAVE,
579
                             (Object **) &s->tx_control_dev, &errp);
580
    assert_no_error(errp);
581

    
582
    object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM);
583
    object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_DMA_CONTROL_STREAM);
584
    object_property_add_child(OBJECT(s), "axistream-connected-target",
585
                              (Object *)&s->rx_data_dev, &errp);
586
    assert_no_error(errp);
587
    object_property_add_child(OBJECT(s), "axistream-control-connected-target",
588
                              (Object *)&s->rx_control_dev, &errp);
589
    assert_no_error(errp);
590

    
591
    sysbus_init_irq(sbd, &s->streams[0].irq);
592
    sysbus_init_irq(sbd, &s->streams[1].irq);
593

    
594
    memory_region_init_io(&s->iomem, obj, &axidma_ops, s,
595
                          "xlnx.axi-dma", R_MAX * 4 * 2);
596
    sysbus_init_mmio(sbd, &s->iomem);
597
}
598

    
599
static Property axidma_properties[] = {
600
    DEFINE_PROP_UINT32("freqhz", XilinxAXIDMA, freqhz, 50000000),
601
    DEFINE_PROP_END_OF_LIST(),
602
};
603

    
604
static void axidma_class_init(ObjectClass *klass, void *data)
605
{
606
    DeviceClass *dc = DEVICE_CLASS(klass);
607

    
608
    dc->realize = xilinx_axidma_realize,
609
    dc->reset = xilinx_axidma_reset;
610
    dc->props = axidma_properties;
611
}
612

    
613
static StreamSlaveClass xilinx_axidma_data_stream_class = {
614
    .push = xilinx_axidma_data_stream_push,
615
    .can_push = xilinx_axidma_data_stream_can_push,
616
};
617

    
618
static StreamSlaveClass xilinx_axidma_control_stream_class = {
619
    .push = xilinx_axidma_control_stream_push,
620
};
621

    
622
static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data)
623
{
624
    StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
625

    
626
    ssc->push = ((StreamSlaveClass *)data)->push;
627
    ssc->can_push = ((StreamSlaveClass *)data)->can_push;
628
}
629

    
630
static const TypeInfo axidma_info = {
631
    .name          = TYPE_XILINX_AXI_DMA,
632
    .parent        = TYPE_SYS_BUS_DEVICE,
633
    .instance_size = sizeof(XilinxAXIDMA),
634
    .class_init    = axidma_class_init,
635
    .instance_init = xilinx_axidma_init,
636
};
637

    
638
static const TypeInfo xilinx_axidma_data_stream_info = {
639
    .name          = TYPE_XILINX_AXI_DMA_DATA_STREAM,
640
    .parent        = TYPE_OBJECT,
641
    .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
642
    .class_init    = xilinx_axidma_stream_class_init,
643
    .class_data    = &xilinx_axidma_data_stream_class,
644
    .interfaces = (InterfaceInfo[]) {
645
        { TYPE_STREAM_SLAVE },
646
        { }
647
    }
648
};
649

    
650
static const TypeInfo xilinx_axidma_control_stream_info = {
651
    .name          = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
652
    .parent        = TYPE_OBJECT,
653
    .instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
654
    .class_init    = xilinx_axidma_stream_class_init,
655
    .class_data    = &xilinx_axidma_control_stream_class,
656
    .interfaces = (InterfaceInfo[]) {
657
        { TYPE_STREAM_SLAVE },
658
        { }
659
    }
660
};
661

    
662
static void xilinx_axidma_register_types(void)
663
{
664
    type_register_static(&axidma_info);
665
    type_register_static(&xilinx_axidma_data_stream_info);
666
    type_register_static(&xilinx_axidma_control_stream_info);
667
}
668

    
669
type_init(xilinx_axidma_register_types)