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