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