Hugo Villeneuve <[email protected]> writes:

> 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]>

Thanks, pushing today.

Kevin

> ---
>  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

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to