aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2020-01-23 15:22:41 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-01-23 16:34:15 +0000
commitdab15fbe2abaca696dae45e6e22e093379ed9c05 (patch)
tree19aaf2b9818e37a64a59fc96ecdeca285359326d /hw/arm
parentddf59e9ccebfce0474152db34e07efaaed417eb6 (diff)
downloadqemu-dab15fbe2abaca696dae45e6e22e093379ed9c05.zip
qemu-dab15fbe2abaca696dae45e6e22e093379ed9c05.tar.gz
qemu-dab15fbe2abaca696dae45e6e22e093379ed9c05.tar.bz2
hw/arm/exynos4210: Fix DMA initialization
First parameter to exynos4210_get_irq() is not the SPI port number, but the interrupt group number. Interrupt groups are 20 for mdma and 21 for pdma. Interrupts are not inverted. Controllers support 32 events (pdma) or 31 events (mdma). Events must all be routed to a single interrupt line. Set other parameters as documented in Exynos4210 datasheet, section 8 (DMA controller). Fixes: 59520dc65e ("hw/arm/exynos4210: Add DMA support for the Exynos4210") Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Message-id: 20200123052540.6132-4-linux@roeck-us.net Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/exynos4210.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 77fbe1b..7701a3f 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -166,17 +166,36 @@ static uint64_t exynos4210_calc_affinity(int cpu)
return (0x9 << ARM_AFF1_SHIFT) | cpu;
}
-static void pl330_create(uint32_t base, qemu_irq irq, int nreq)
+static void pl330_create(uint32_t base, qemu_or_irq *orgate, qemu_irq irq,
+ int nreq, int nevents, int width)
{
SysBusDevice *busdev;
DeviceState *dev;
+ int i;
dev = qdev_create(NULL, "pl330");
+ qdev_prop_set_uint8(dev, "num_events", nevents);
+ qdev_prop_set_uint8(dev, "num_chnls", 8);
qdev_prop_set_uint8(dev, "num_periph_req", nreq);
+
+ qdev_prop_set_uint8(dev, "wr_cap", 4);
+ qdev_prop_set_uint8(dev, "wr_q_dep", 8);
+ qdev_prop_set_uint8(dev, "rd_cap", 4);
+ qdev_prop_set_uint8(dev, "rd_q_dep", 8);
+ qdev_prop_set_uint8(dev, "data_width", width);
+ qdev_prop_set_uint16(dev, "data_buffer_dep", width);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, base);
- sysbus_connect_irq(busdev, 0, irq);
+
+ object_property_set_int(OBJECT(orgate), nevents + 1, "num-lines",
+ &error_abort);
+ object_property_set_bool(OBJECT(orgate), true, "realized", &error_abort);
+
+ for (i = 0; i < nevents + 1; i++) {
+ sysbus_connect_irq(busdev, i, qdev_get_gpio_in(DEVICE(orgate), i));
+ }
+ qdev_connect_gpio_out(DEVICE(orgate), 0, irq);
}
static void exynos4210_realize(DeviceState *socdev, Error **errp)
@@ -431,12 +450,27 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
s->irq_table[exynos4210_get_irq(28, 3)]);
/*** DMA controllers ***/
- pl330_create(EXYNOS4210_PL330_BASE0_ADDR,
- qemu_irq_invert(s->irq_table[exynos4210_get_irq(35, 1)]), 32);
- pl330_create(EXYNOS4210_PL330_BASE1_ADDR,
- qemu_irq_invert(s->irq_table[exynos4210_get_irq(36, 1)]), 32);
- pl330_create(EXYNOS4210_PL330_BASE2_ADDR,
- qemu_irq_invert(s->irq_table[exynos4210_get_irq(34, 1)]), 1);
+ pl330_create(EXYNOS4210_PL330_BASE0_ADDR, &s->pl330_irq_orgate[0],
+ s->irq_table[exynos4210_get_irq(21, 0)], 32, 32, 32);
+ pl330_create(EXYNOS4210_PL330_BASE1_ADDR, &s->pl330_irq_orgate[1],
+ s->irq_table[exynos4210_get_irq(21, 1)], 32, 32, 32);
+ pl330_create(EXYNOS4210_PL330_BASE2_ADDR, &s->pl330_irq_orgate[2],
+ s->irq_table[exynos4210_get_irq(20, 1)], 1, 31, 64);
+}
+
+static void exynos4210_init(Object *obj)
+{
+ Exynos4210State *s = EXYNOS4210_SOC(obj);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->pl330_irq_orgate); i++) {
+ char *name = g_strdup_printf("pl330-irq-orgate%d", i);
+ qemu_or_irq *orgate = &s->pl330_irq_orgate[i];
+
+ object_initialize_child(obj, name, orgate, sizeof(*orgate),
+ TYPE_OR_IRQ, &error_abort, NULL);
+ g_free(name);
+ }
}
static void exynos4210_class_init(ObjectClass *klass, void *data)
@@ -450,6 +484,7 @@ static const TypeInfo exynos4210_info = {
.name = TYPE_EXYNOS4210_SOC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210State),
+ .instance_init = exynos4210_init,
.class_init = exynos4210_class_init,
};