aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/arm/realview.c8
-rw-r--r--hw/arm/versatilepb.c9
-rw-r--r--hw/dma/pl080.c35
-rw-r--r--include/hw/dma/pl080.h5
4 files changed, 49 insertions, 8 deletions
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index cd585d9469..ab8c14fde3 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -201,7 +201,13 @@ static void realview_init(MachineState *machine,
pl011_create(0x1000c000, pic[15], serial_hd(3));
/* DMA controller is optional, apparently. */
- sysbus_create_simple("pl081", 0x10030000, pic[24]);
+ dev = qdev_create(NULL, "pl081");
+ object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
+ &error_fatal);
+ qdev_init_nofail(dev);
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, 0x10030000);
+ sysbus_connect_irq(busdev, 0, pic[24]);
sysbus_create_simple("sp804", 0x10011000, pic[4]);
sysbus_create_simple("sp804", 0x10012000, pic[5]);
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index a5a06b6d40..8b74857059 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -287,7 +287,14 @@ static void versatile_init(MachineState *machine, int board_id)
pl011_create(0x101f3000, pic[14], serial_hd(2));
pl011_create(0x10009000, sic[6], serial_hd(3));
- sysbus_create_simple("pl080", 0x10130000, pic[17]);
+ dev = qdev_create(NULL, "pl080");
+ object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream",
+ &error_fatal);
+ qdev_init_nofail(dev);
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, 0x10130000);
+ sysbus_connect_irq(busdev, 0, pic[17]);
+
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
sysbus_create_simple("sp804", 0x101e3000, pic[5]);
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
index 301030dd11..8f9f3e08d9 100644
--- a/hw/dma/pl080.c
+++ b/hw/dma/pl080.c
@@ -12,6 +12,7 @@
#include "exec/address-spaces.h"
#include "qemu/log.h"
#include "hw/dma/pl080.h"
+#include "qapi/error.h"
#define PL080_CONF_E 0x1
#define PL080_CONF_M1 0x2
@@ -161,14 +162,16 @@ again:
swidth = 1 << ((ch->ctrl >> 18) & 7);
dwidth = 1 << ((ch->ctrl >> 21) & 7);
for (n = 0; n < dwidth; n+= swidth) {
- cpu_physical_memory_read(ch->src, buff + n, swidth);
+ address_space_read(&s->downstream_as, ch->src,
+ MEMTXATTRS_UNSPECIFIED, buff + n, swidth);
if (ch->ctrl & PL080_CCTRL_SI)
ch->src += swidth;
}
xsize = (dwidth < swidth) ? swidth : dwidth;
/* ??? This may pad the value incorrectly for dwidth < 32. */
for (n = 0; n < xsize; n += dwidth) {
- cpu_physical_memory_write(ch->dest + n, buff + n, dwidth);
+ address_space_write(&s->downstream_as, ch->dest + n,
+ MEMTXATTRS_UNSPECIFIED, buff + n, dwidth);
if (ch->ctrl & PL080_CCTRL_DI)
ch->dest += swidth;
}
@@ -178,19 +181,19 @@ again:
if (size == 0) {
/* Transfer complete. */
if (ch->lli) {
- ch->src = address_space_ldl_le(&address_space_memory,
+ ch->src = address_space_ldl_le(&s->downstream_as,
ch->lli,
MEMTXATTRS_UNSPECIFIED,
NULL);
- ch->dest = address_space_ldl_le(&address_space_memory,
+ ch->dest = address_space_ldl_le(&s->downstream_as,
ch->lli + 4,
MEMTXATTRS_UNSPECIFIED,
NULL);
- ch->ctrl = address_space_ldl_le(&address_space_memory,
+ ch->ctrl = address_space_ldl_le(&s->downstream_as,
ch->lli + 12,
MEMTXATTRS_UNSPECIFIED,
NULL);
- ch->lli = address_space_ldl_le(&address_space_memory,
+ ch->lli = address_space_ldl_le(&s->downstream_as,
ch->lli + 8,
MEMTXATTRS_UNSPECIFIED,
NULL);
@@ -358,6 +361,18 @@ static void pl080_init(Object *obj)
s->nchannels = 8;
}
+static void pl080_realize(DeviceState *dev, Error **errp)
+{
+ PL080State *s = PL080(dev);
+
+ if (!s->downstream) {
+ error_setg(errp, "PL080 'downstream' link not set");
+ return;
+ }
+
+ address_space_init(&s->downstream_as, s->downstream, "pl080-downstream");
+}
+
static void pl081_init(Object *obj)
{
PL080State *s = PL080(obj);
@@ -365,11 +380,19 @@ static void pl081_init(Object *obj)
s->nchannels = 2;
}
+static Property pl080_properties[] = {
+ DEFINE_PROP_LINK("downstream", PL080State, downstream,
+ TYPE_MEMORY_REGION, MemoryRegion *),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void pl080_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->vmsd = &vmstate_pl080;
+ dc->realize = pl080_realize;
+ dc->props = pl080_properties;
}
static const TypeInfo pl080_info = {
diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h
index 7c6a418483..9d4b3df143 100644
--- a/include/hw/dma/pl080.h
+++ b/include/hw/dma/pl080.h
@@ -21,6 +21,8 @@
* + sysbus IRQ 1: DMACINTERR error interrupt request
* + sysbus IRQ 2: DMACINTTC count interrupt request
* + sysbus MMIO region 0: MemoryRegion for the device's registers
+ * + QOM property "downstream": MemoryRegion defining where DMA
+ * bus master transactions are made
*/
#ifndef HW_DMA_PL080_H
@@ -61,6 +63,9 @@ typedef struct PL080State {
qemu_irq irq;
qemu_irq interr;
qemu_irq inttc;
+
+ MemoryRegion *downstream;
+ AddressSpace downstream_as;
} PL080State;
#endif