[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 8/8] hw/arm/exynos4210: Connect serial port DMA busy signals w
From: |
Guenter Roeck |
Subject: |
[PATCH v3 8/8] hw/arm/exynos4210: Connect serial port DMA busy signals with pl330 |
Date: |
Wed, 22 Jan 2020 21:25:40 -0800 |
The Exynos4210 serial driver uses an interrupt line to signal if receive
data is available. Connect that interrupt with the DMA controller's
'peripheral busy' gpio pin to stop the DMA if there is no more receive
data available. Without this patch, receive DMA runs wild and fills the
entire receive DMA buffer with invalid data.
Reviewed-by: Peter Maydell <address@hidden>
Signed-off-by: Guenter Roeck <address@hidden>
---
v3: Added Reviewed-by: tag
Context changes due to increase in number of interrupt lines
v2: Context changes; improved description
This patch has an outstanding review comment, suggesting that
uart and pl330 device states should be kept in Exynos4210State.
I did not address this comment for a number of reasons.
It looks like the problem is hypothetical, the problem may
apply to all devices created in exynos4210_realize(), and I am
not sure I understand what would need to be done to fix
the problem for good (ie for all devices created in the same
function which have the same problem). Overall, I think that
handling this situation would be better left for a separate patch.
hw/arm/exynos4210.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 7701a3fa8b..59a27bdd68 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -166,8 +166,8 @@ static uint64_t exynos4210_calc_affinity(int cpu)
return (0x9 << ARM_AFF1_SHIFT) | cpu;
}
-static void pl330_create(uint32_t base, qemu_or_irq *orgate, qemu_irq irq,
- int nreq, int nevents, int width)
+static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate,
+ qemu_irq irq, int nreq, int nevents, int
width)
{
SysBusDevice *busdev;
DeviceState *dev;
@@ -196,6 +196,7 @@ static void pl330_create(uint32_t base, qemu_or_irq
*orgate, qemu_irq irq,
sysbus_connect_irq(busdev, i, qdev_get_gpio_in(DEVICE(orgate), i));
}
qdev_connect_gpio_out(DEVICE(orgate), 0, irq);
+ return dev;
}
static void exynos4210_realize(DeviceState *socdev, Error **errp)
@@ -204,7 +205,7 @@ static void exynos4210_realize(DeviceState *socdev, Error
**errp)
MemoryRegion *system_mem = get_system_memory();
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
SysBusDevice *busdev;
- DeviceState *dev;
+ DeviceState *dev, *uart[4], *pl330[3];
int i, n;
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
@@ -390,19 +391,19 @@ static void exynos4210_realize(DeviceState *socdev, Error
**errp)
/*** UARTs ***/
- exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
+ uart[0] = exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
EXYNOS4210_UART0_FIFO_SIZE, 0, serial_hd(0),
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP,
0)]);
- exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
+ uart[1] = exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
EXYNOS4210_UART1_FIFO_SIZE, 1, serial_hd(1),
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP,
1)]);
- exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
+ uart[2] = exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
EXYNOS4210_UART2_FIFO_SIZE, 2, serial_hd(2),
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP,
2)]);
- exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
+ uart[3] = exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
EXYNOS4210_UART3_FIFO_SIZE, 3, serial_hd(3),
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP,
3)]);
@@ -450,12 +451,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, &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);
+ pl330[0] = pl330_create(EXYNOS4210_PL330_BASE0_ADDR,
+ &s->pl330_irq_orgate[0],
+ s->irq_table[exynos4210_get_irq(21, 0)],
+ 32, 32, 32);
+ pl330[1] = pl330_create(EXYNOS4210_PL330_BASE1_ADDR,
+ &s->pl330_irq_orgate[1],
+ s->irq_table[exynos4210_get_irq(21, 1)],
+ 32, 32, 32);
+ pl330[2] = pl330_create(EXYNOS4210_PL330_BASE2_ADDR,
+ &s->pl330_irq_orgate[2],
+ s->irq_table[exynos4210_get_irq(20, 1)],
+ 1, 31, 64);
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(uart[0]), 1,
+ qdev_get_gpio_in(pl330[0], 15));
+ sysbus_connect_irq(SYS_BUS_DEVICE(uart[1]), 1,
+ qdev_get_gpio_in(pl330[1], 15));
+ sysbus_connect_irq(SYS_BUS_DEVICE(uart[2]), 1,
+ qdev_get_gpio_in(pl330[0], 17));
+ sysbus_connect_irq(SYS_BUS_DEVICE(uart[3]), 1,
+ qdev_get_gpio_in(pl330[1], 17));
}
static void exynos4210_init(Object *obj)
--
2.17.1
- [PATCH v3 1/8] dma/pl330: Convert to support tracing, (continued)
- [PATCH v3 3/8] hw/arm/exynos4210: Fix DMA initialization, Guenter Roeck, 2020/01/23
- [PATCH v3 2/8] hw/core/or-irq: Increase limit of or-lines to 48, Guenter Roeck, 2020/01/23
- [PATCH v3 4/8] hw/char/exynos4210_uart: Convert to support tracing, Guenter Roeck, 2020/01/23
- [PATCH v3 5/8] hw/char/exynos4210_uart: Implement post_load function, Guenter Roeck, 2020/01/23
- [PATCH v3 6/8] hw/char/exynos4210_uart: Implement Rx FIFO level triggers and timeouts, Guenter Roeck, 2020/01/23
- [PATCH v3 7/8] hw/char/exynos4210_uart: Add receive DMA support, Guenter Roeck, 2020/01/23
- [PATCH v3 8/8] hw/arm/exynos4210: Connect serial port DMA busy signals with pl330,
Guenter Roeck <=
- Re: [PATCH v3 0/8] Fix Exynos4210 DMA support, Peter Maydell, 2020/01/23