diff options
Diffstat (limited to 'hw/dma/xilinx_axidma.c')
-rw-r--r-- | hw/dma/xilinx_axidma.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index 2c95765681..02700ea4bd 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -34,10 +34,15 @@ #define D(x) #define TYPE_XILINX_AXI_DMA "xlnx.axi-dma" +#define TYPE_XILINX_AXI_DMA_DATA_STREAM "xilinx-axi-dma-data-stream" #define XILINX_AXI_DMA(obj) \ OBJECT_CHECK(XilinxAXIDMA, (obj), TYPE_XILINX_AXI_DMA) +#define XILINX_AXI_DMA_DATA_STREAM(obj) \ + OBJECT_CHECK(XilinxAXIDMAStreamSlave, (obj),\ + TYPE_XILINX_AXI_DMA_DATA_STREAM) + #define R_DMACR (0x00 / 4) #define R_DMASR (0x04 / 4) #define R_CURDESC (0x08 / 4) @@ -45,6 +50,7 @@ #define R_MAX (0x30 / 4) typedef struct XilinxAXIDMA XilinxAXIDMA; +typedef struct XilinxAXIDMAStreamSlave XilinxAXIDMAStreamSlave; enum { DMACR_RUNSTOP = 1, @@ -97,11 +103,18 @@ struct Stream { uint32_t regs[R_MAX]; }; +struct XilinxAXIDMAStreamSlave { + Object parent; + + struct XilinxAXIDMA *dma; +}; + struct XilinxAXIDMA { SysBusDevice busdev; MemoryRegion iomem; uint32_t freqhz; StreamSlave *tx_dev; + XilinxAXIDMAStreamSlave rx_data_dev; struct Stream streams[2]; }; @@ -369,10 +382,11 @@ static void xilinx_axidma_reset(DeviceState *dev) } static void -axidma_push(StreamSlave *obj, unsigned char *buf, size_t len, uint32_t *app) +xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len, + uint32_t *app) { - XilinxAXIDMA *d = XILINX_AXI_DMA(obj); - struct Stream *s = &d->streams[1]; + XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); + struct Stream *s = &ds->dma->streams[1]; if (!app) { hw_error("No stream app data!\n"); @@ -478,6 +492,19 @@ static const MemoryRegionOps axidma_ops = { static void xilinx_axidma_realize(DeviceState *dev, Error **errp) { XilinxAXIDMA *s = XILINX_AXI_DMA(dev); + XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(&s->rx_data_dev); + Error *local_errp = NULL; + + object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, + (Object **)&ds->dma, &local_errp); + if (local_errp) { + goto xilinx_axidma_realize_fail; + } + object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_errp); + if (local_errp) { + goto xilinx_axidma_realize_fail; + } + int i; for (i = 0; i < 2; i++) { @@ -486,16 +513,28 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) s->streams[i].ptimer = ptimer_init(s->streams[i].bh); ptimer_set_freq(s->streams[i].ptimer, s->freqhz); } + return; + +xilinx_axidma_realize_fail: + if (!*errp) { + *errp = local_errp; + } } static void xilinx_axidma_init(Object *obj) { XilinxAXIDMA *s = XILINX_AXI_DMA(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + Error *errp = NULL; object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE, (Object **) &s->tx_dev, NULL); + object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM); + object_property_add_child(OBJECT(s), "axistream-connected-target", + (Object *)&s->rx_data_dev, &errp); + assert_no_error(errp); + sysbus_init_irq(sbd, &s->streams[0].irq); sysbus_init_irq(sbd, &s->streams[1].irq); @@ -512,12 +551,17 @@ static Property axidma_properties[] = { static void axidma_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); dc->realize = xilinx_axidma_realize, dc->reset = xilinx_axidma_reset; dc->props = axidma_properties; - ssc->push = axidma_push; +} + +static void xilinx_axidma_stream_class_init(ObjectClass *klass, void *data) +{ + StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass); + + ssc->push = data; } static const TypeInfo axidma_info = { @@ -526,6 +570,14 @@ static const TypeInfo axidma_info = { .instance_size = sizeof(XilinxAXIDMA), .class_init = axidma_class_init, .instance_init = xilinx_axidma_init, +}; + +static const TypeInfo xilinx_axidma_data_stream_info = { + .name = TYPE_XILINX_AXI_DMA_DATA_STREAM, + .parent = TYPE_OBJECT, + .instance_size = sizeof(struct XilinxAXIDMAStreamSlave), + .class_init = xilinx_axidma_stream_class_init, + .class_data = xilinx_axidma_data_stream_push, .interfaces = (InterfaceInfo[]) { { TYPE_STREAM_SLAVE }, { } @@ -535,6 +587,7 @@ static const TypeInfo axidma_info = { static void xilinx_axidma_register_types(void) { type_register_static(&axidma_info); + type_register_static(&xilinx_axidma_data_stream_info); } type_init(xilinx_axidma_register_types) |