diff mbox

[RFC,v1,11/11] dma: axidma: Convert to PMA

Message ID d85393e3c6039b59fc2a86b266b80679c71c3603.1401760826.git.peter.crosthwaite@xilinx.com
State New
Headers show

Commit Message

Peter Crosthwaite June 3, 2014, 2:12 a.m. UTC
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(-)
diff mbox

Patch

diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index fb741b8..ab5e1f2 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -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[] = {
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index baf330f..aa755f7 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -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);