diff options
-rw-r--r-- | hw/arm/realview.c | 8 | ||||
-rw-r--r-- | hw/arm/versatilepb.c | 9 | ||||
-rw-r--r-- | hw/dma/pl080.c | 35 | ||||
-rw-r--r-- | include/hw/dma/pl080.h | 5 |
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 |