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