xilinx_axidma.c 19 KB

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