qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

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>

authored by

Guenter Roeck and committed by
Peter Maydell
dab15fbe ddf59e9c

+47 -8
+43 -8
hw/arm/exynos4210.c
··· 166 166 return (0x9 << ARM_AFF1_SHIFT) | cpu; 167 167 } 168 168 169 - static void pl330_create(uint32_t base, qemu_irq irq, int nreq) 169 + static void pl330_create(uint32_t base, qemu_or_irq *orgate, qemu_irq irq, 170 + int nreq, int nevents, int width) 170 171 { 171 172 SysBusDevice *busdev; 172 173 DeviceState *dev; 174 + int i; 173 175 174 176 dev = qdev_create(NULL, "pl330"); 177 + qdev_prop_set_uint8(dev, "num_events", nevents); 178 + qdev_prop_set_uint8(dev, "num_chnls", 8); 175 179 qdev_prop_set_uint8(dev, "num_periph_req", nreq); 180 + 181 + qdev_prop_set_uint8(dev, "wr_cap", 4); 182 + qdev_prop_set_uint8(dev, "wr_q_dep", 8); 183 + qdev_prop_set_uint8(dev, "rd_cap", 4); 184 + qdev_prop_set_uint8(dev, "rd_q_dep", 8); 185 + qdev_prop_set_uint8(dev, "data_width", width); 186 + qdev_prop_set_uint16(dev, "data_buffer_dep", width); 176 187 qdev_init_nofail(dev); 177 188 busdev = SYS_BUS_DEVICE(dev); 178 189 sysbus_mmio_map(busdev, 0, base); 179 - sysbus_connect_irq(busdev, 0, irq); 190 + 191 + object_property_set_int(OBJECT(orgate), nevents + 1, "num-lines", 192 + &error_abort); 193 + object_property_set_bool(OBJECT(orgate), true, "realized", &error_abort); 194 + 195 + for (i = 0; i < nevents + 1; i++) { 196 + sysbus_connect_irq(busdev, i, qdev_get_gpio_in(DEVICE(orgate), i)); 197 + } 198 + qdev_connect_gpio_out(DEVICE(orgate), 0, irq); 180 199 } 181 200 182 201 static void exynos4210_realize(DeviceState *socdev, Error **errp) ··· 431 450 s->irq_table[exynos4210_get_irq(28, 3)]); 432 451 433 452 /*** DMA controllers ***/ 434 - pl330_create(EXYNOS4210_PL330_BASE0_ADDR, 435 - qemu_irq_invert(s->irq_table[exynos4210_get_irq(35, 1)]), 32); 436 - pl330_create(EXYNOS4210_PL330_BASE1_ADDR, 437 - qemu_irq_invert(s->irq_table[exynos4210_get_irq(36, 1)]), 32); 438 - pl330_create(EXYNOS4210_PL330_BASE2_ADDR, 439 - qemu_irq_invert(s->irq_table[exynos4210_get_irq(34, 1)]), 1); 453 + pl330_create(EXYNOS4210_PL330_BASE0_ADDR, &s->pl330_irq_orgate[0], 454 + s->irq_table[exynos4210_get_irq(21, 0)], 32, 32, 32); 455 + pl330_create(EXYNOS4210_PL330_BASE1_ADDR, &s->pl330_irq_orgate[1], 456 + s->irq_table[exynos4210_get_irq(21, 1)], 32, 32, 32); 457 + pl330_create(EXYNOS4210_PL330_BASE2_ADDR, &s->pl330_irq_orgate[2], 458 + s->irq_table[exynos4210_get_irq(20, 1)], 1, 31, 64); 459 + } 460 + 461 + static void exynos4210_init(Object *obj) 462 + { 463 + Exynos4210State *s = EXYNOS4210_SOC(obj); 464 + int i; 465 + 466 + for (i = 0; i < ARRAY_SIZE(s->pl330_irq_orgate); i++) { 467 + char *name = g_strdup_printf("pl330-irq-orgate%d", i); 468 + qemu_or_irq *orgate = &s->pl330_irq_orgate[i]; 469 + 470 + object_initialize_child(obj, name, orgate, sizeof(*orgate), 471 + TYPE_OR_IRQ, &error_abort, NULL); 472 + g_free(name); 473 + } 440 474 } 441 475 442 476 static void exynos4210_class_init(ObjectClass *klass, void *data) ··· 450 484 .name = TYPE_EXYNOS4210_SOC, 451 485 .parent = TYPE_SYS_BUS_DEVICE, 452 486 .instance_size = sizeof(Exynos4210State), 487 + .instance_init = exynos4210_init, 453 488 .class_init = exynos4210_class_init, 454 489 }; 455 490
+4
include/hw/arm/exynos4210.h
··· 24 24 #ifndef EXYNOS4210_H 25 25 #define EXYNOS4210_H 26 26 27 + #include "hw/or-irq.h" 27 28 #include "hw/sysbus.h" 28 29 #include "target/arm/cpu-qom.h" 29 30 ··· 74 75 75 76 #define EXYNOS4210_I2C_NUMBER 9 76 77 78 + #define EXYNOS4210_NUM_DMA 3 79 + 77 80 typedef struct Exynos4210Irq { 78 81 qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ]; 79 82 qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ]; ··· 97 100 MemoryRegion boot_secondary; 98 101 MemoryRegion bootreg_mem; 99 102 I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER]; 103 + qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA]; 100 104 } Exynos4210State; 101 105 102 106 #define TYPE_EXYNOS4210_SOC "exynos4210"