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