hw/arm/exynos4210: Connect serial port DMA busy signals with pl330
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 <peter.maydell@linaro.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Message-id: 20200123052540.6132-9-linux@roeck-us.net Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
3c77412b4a
commit
e9d20b55b2
|
@ -166,8 +166,8 @@ static uint64_t exynos4210_calc_affinity(int cpu)
|
||||||
return (0x9 << ARM_AFF1_SHIFT) | cpu;
|
return (0x9 << ARM_AFF1_SHIFT) | cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pl330_create(uint32_t base, qemu_or_irq *orgate, qemu_irq irq,
|
static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate,
|
||||||
int nreq, int nevents, int width)
|
qemu_irq irq, int nreq, int nevents, int width)
|
||||||
{
|
{
|
||||||
SysBusDevice *busdev;
|
SysBusDevice *busdev;
|
||||||
DeviceState *dev;
|
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));
|
sysbus_connect_irq(busdev, i, qdev_get_gpio_in(DEVICE(orgate), i));
|
||||||
}
|
}
|
||||||
qdev_connect_gpio_out(DEVICE(orgate), 0, irq);
|
qdev_connect_gpio_out(DEVICE(orgate), 0, irq);
|
||||||
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exynos4210_realize(DeviceState *socdev, Error **errp)
|
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();
|
MemoryRegion *system_mem = get_system_memory();
|
||||||
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
|
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
|
||||||
SysBusDevice *busdev;
|
SysBusDevice *busdev;
|
||||||
DeviceState *dev;
|
DeviceState *dev, *uart[4], *pl330[3];
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
|
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
|
||||||
|
@ -390,19 +391,19 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
|
||||||
|
|
||||||
|
|
||||||
/*** UARTs ***/
|
/*** 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),
|
EXYNOS4210_UART0_FIFO_SIZE, 0, serial_hd(0),
|
||||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 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),
|
EXYNOS4210_UART1_FIFO_SIZE, 1, serial_hd(1),
|
||||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 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),
|
EXYNOS4210_UART2_FIFO_SIZE, 2, serial_hd(2),
|
||||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 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),
|
EXYNOS4210_UART3_FIFO_SIZE, 3, serial_hd(3),
|
||||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 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)]);
|
s->irq_table[exynos4210_get_irq(28, 3)]);
|
||||||
|
|
||||||
/*** DMA controllers ***/
|
/*** DMA controllers ***/
|
||||||
pl330_create(EXYNOS4210_PL330_BASE0_ADDR, &s->pl330_irq_orgate[0],
|
pl330[0] = pl330_create(EXYNOS4210_PL330_BASE0_ADDR,
|
||||||
s->irq_table[exynos4210_get_irq(21, 0)], 32, 32, 32);
|
&s->pl330_irq_orgate[0],
|
||||||
pl330_create(EXYNOS4210_PL330_BASE1_ADDR, &s->pl330_irq_orgate[1],
|
s->irq_table[exynos4210_get_irq(21, 0)],
|
||||||
s->irq_table[exynos4210_get_irq(21, 1)], 32, 32, 32);
|
32, 32, 32);
|
||||||
pl330_create(EXYNOS4210_PL330_BASE2_ADDR, &s->pl330_irq_orgate[2],
|
pl330[1] = pl330_create(EXYNOS4210_PL330_BASE1_ADDR,
|
||||||
s->irq_table[exynos4210_get_irq(20, 1)], 1, 31, 64);
|
&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)
|
static void exynos4210_init(Object *obj)
|
||||||
|
|
Loading…
Reference in a new issue