This bug occurs when the davinci serial code tries to register UART(X) when UART(X-1) or UART(X-2) is not enabled in the structure uart_config of the board setup code:
This works: .enabled_uarts = (1 << 0) This works: .enabled_uarts = (1 << 0) | (1 << 1) This works: .enabled_uarts = (1 << 0) | (1 << 1) | | (1 << 2) This fails: .enabled_uarts = (1 << 1) This fails: .enabled_uarts = (1 << 1) | (1 << 2) This fails: .enabled_uarts = (1 << 0) | (1 << 2) The bug is triggered by the fact that the 8250 serial driver stops parsing the serial_platform_data structure as soon as it sees a zero flags entry. Thus the davinci serial registration code (serial.c) must <pack> the serial_platform_data structure and only clear the flags entry when there is no more devices following. Tested on DM6446 and DM355 custom boards. Signed-off-by: Hugo Villeneuve <[email protected]> --- arch/arm/mach-davinci/serial.c | 81 +++++++++++++++++++--------------------- 1 files changed, 38 insertions(+), 43 deletions(-) diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index 95c71b9..99102ac 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c @@ -49,36 +49,24 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, __raw_writel(value, IO_ADDRESS(p->mapbase) + offset); } -static struct plat_serial8250_port serial_platform_data[] = { - { - .mapbase = DAVINCI_UART0_BASE, - .irq = IRQ_UARTINT0, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | - UPF_IOREMAP, - .iotype = UPIO_MEM, - .regshift = 2, - }, - { - .mapbase = DAVINCI_UART1_BASE, - .irq = IRQ_UARTINT1, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | - UPF_IOREMAP, - .iotype = UPIO_MEM, - .regshift = 2, - }, - { - .mapbase = DAVINCI_UART2_BASE, - .irq = IRQ_UARTINT2, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | - UPF_IOREMAP, - .iotype = UPIO_MEM, - .regshift = 2, - }, - { - .flags = 0 - }, +static const resource_size_t serial_mapbase[] = { + DAVINCI_UART0_BASE, + DAVINCI_UART1_BASE, + DAVINCI_UART2_BASE, }; +static const unsigned int serial_irq[] = { + IRQ_UARTINT0, + IRQ_UARTINT1, + IRQ_UARTINT2, +}; + +/* + * The additional entry is present because the list must be terminated with a + * zero flags entry. + */ +static struct plat_serial8250_port serial_platform_data[DAVINCI_MAX_NR_UARTS + 1]; + static struct platform_device serial_device = { .name = "serial8250", .id = PLAT8250_DEV_PLATFORM, @@ -112,29 +100,31 @@ void __init davinci_serial_init(struct davinci_uart_config *info) char name[16]; struct clk *uart_clk; struct device *dev = &serial_device.dev; + struct plat_serial8250_port *p = serial_platform_data; /* * Make sure the serial ports are muxed on at this point. - * You have to mux them off in device drivers later on - * if not needed. + * You have to mux them off in device drivers later on if not needed. */ for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) { - struct plat_serial8250_port *p = serial_platform_data + i; - - if (!(info->enabled_uarts & (1 << i))) { - p->flags = 0; + if (!(info->enabled_uarts & (1 << i))) continue; - } - if (cpu_is_davinci_dm646x()) { - p->iotype = UPIO_MEM32; - } + /* fill-in common members */ + p->flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP; + p->regshift = 2; - if (cpu_is_davinci_dm355()) { - if (i == 2) { - p->mapbase = (unsigned long)DM355_UART2_BASE; - p->irq = IRQ_DM355_UARTINT2; - } + if (cpu_is_davinci_dm646x()) + p->iotype = UPIO_MEM32; + else + p->iotype = UPIO_MEM; + + if (cpu_is_davinci_dm355() && (i == 2)) { + p->mapbase = DM355_UART2_BASE; + p->irq = IRQ_DM355_UARTINT2; + } else { + p->mapbase = serial_mapbase[i]; + p->irq = serial_irq[i]; } sprintf(name, "uart%d", i); @@ -147,7 +137,12 @@ void __init davinci_serial_init(struct davinci_uart_config *info) clk_enable(uart_clk); davinci_serial_reset(p); } + + p++; /* Point to next entry */ } + + /* Terminate the list with a zero flags entry */ + p->flags = 0; } static int __init davinci_init(void) -- 1.5.4.5 _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
