@@ -29,6 +29,7 @@
#include "qapi/qmp/qerror.h"
#include "qemu/main-loop.h"
+#include "sysemu/dma.h"
#include "hw/stream.h"
#define D(x)
@@ -110,6 +111,10 @@ struct Stream {
unsigned int complete_cnt;
uint32_t regs[R_MAX];
uint8_t app[20];
+
+ MemoryRegion *data_mr;
+ AddressSpace *data_as;
+ AddressSpace *sg_as;
};
struct XilinxAXIDMAStreamSlave {
@@ -129,6 +134,8 @@ struct XilinxAXIDMA {
struct Stream streams[2];
+ MemoryRegion *sg_mr;
+
StreamCanPushNotifyFn notify;
void *notify_opaque;
};
@@ -197,7 +204,7 @@ static void stream_desc_load(struct Stream *s, hwaddr addr)
{
struct SDesc *d = &s->desc;
- cpu_physical_memory_read(addr, d, sizeof *d);
+ dma_memory_read(s->sg_as, addr, d, sizeof *d);
/* Convert from LE into host endianness. */
d->buffer_address = le64_to_cpu(d->buffer_address);
@@ -215,7 +222,7 @@ static void stream_desc_store(struct Stream *s, hwaddr addr)
d->nxtdesc = cpu_to_le64(d->nxtdesc);
d->control = cpu_to_le32(d->control);
d->status = cpu_to_le32(d->status);
- cpu_physical_memory_write(addr, d, sizeof *d);
+ dma_memory_write(s->sg_as, addr, d, sizeof *d);
}
static void stream_update_irq(struct Stream *s)
@@ -296,8 +303,8 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
txlen + s->pos);
}
- cpu_physical_memory_read(s->desc.buffer_address,
- txbuf + s->pos, txlen);
+ dma_memory_read(s->data_as, s->desc.buffer_address,
+ txbuf + s->pos, txlen);
s->pos += txlen;
if (stream_desc_eof(&s->desc)) {
@@ -346,7 +353,7 @@ static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
rxlen = len;
}
- cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
+ dma_memory_write(s->data_as, s->desc.buffer_address, buf + pos, rxlen);
len -= rxlen;
pos += rxlen;
@@ -535,6 +542,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
&s->rx_control_dev);
Error *local_err = NULL;
+ AddressSpace *sg_as;
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&ds->dma,
@@ -557,12 +565,16 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
int i;
+ sg_as = address_space_init_shareable(s->sg_mr, NULL);
+
for (i = 0; i < 2; i++) {
struct Stream *st = &s->streams[i];
st->nr = i;
st->bh = qemu_bh_new(timer_hit, st);
st->ptimer = ptimer_init(st->bh);
ptimer_set_freq(st->ptimer, s->freqhz);
+ st->data_as = address_space_init_shareable(st->data_mr, NULL);
+ st->sg_as = sg_as;
}
return;
@@ -604,6 +616,22 @@ static void xilinx_axidma_init(Object *obj)
memory_region_init_io(&s->iomem, obj, &axidma_ops, s,
"xlnx.axi-dma", R_MAX * 4 * 2);
sysbus_init_mmio(sbd, &s->iomem);
+
+ object_property_add_link(obj, "mm2s", TYPE_MEMORY_REGION,
+ (Object **)&s->streams[0].data_mr,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &error_abort);
+ object_property_add_link(obj, "s2mm", TYPE_MEMORY_REGION,
+ (Object **)&s->streams[1].data_mr,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &error_abort);
+ object_property_add_link(obj, "sg", TYPE_MEMORY_REGION,
+ (Object **)&s->sg_mr,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
+ &error_abort);
}
static Property axidma_properties[] = {
@@ -157,6 +157,10 @@ petalogix_ml605_init(MachineState *machine)
eth0 = qdev_create(NULL, "xlnx.axi-ethernet");
dma = qdev_create(NULL, "xlnx.axi-dma");
+ object_property_set_link(OBJECT(dma), OBJECT(ddr_mr), "sg", &error_abort);
+ object_property_set_link(OBJECT(dma), OBJECT(ddr_mr), "s2mm", &error_abort);
+ object_property_set_link(OBJECT(dma), OBJECT(ddr_mr), "mm2s", &error_abort);
+
/* FIXME: attach to the sysbus instead */
object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0),
NULL);
Add MemoryRegion and AddressSpace's for the master attachments of the DMA engine. The MemoryRegions are exposed as links to be set by the machine model (or whatever). At realize time, the memory regions are used to construct the masterable AddressSpace's. Could have been done simpler as just one AS, but we make an attempt here to be true to real hardware. The core does physically have three AXI bus master attachments that could in theory be attached to different buses. We facilitate that, even though the only user as of now, connects them all to the one place (the DDR controller in petalogix_ml605). Update petalogix_ml605 to make it's connection properly. The changes to axidma do not support a fallback, so we must make both the device and machine changes concurrently. Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> --- hw/dma/xilinx_axidma.c | 38 ++++++++++++++++++++++++++++++++----- hw/microblaze/petalogix_ml605_mmu.c | 4 ++++ 2 files changed, 37 insertions(+), 5 deletions(-)