Hi Alexey, your commit 5fe212364 causes division by zero with any baud rate larger than 3 Mbaud (IP supports up to 3686400). Maybe this patch is all we need to get it fixed ? (untested) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 816d1a2..b50327f 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -240,8 +240,14 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) { unsigned int n13 = port->uartclk / (13 * baud); unsigned int n16 = port->uartclk / (16 * baud); - int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); - int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); + int baudAbsDiff13 = 0; + int baudAbsDiff16 = 0; + + if (n13) + baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); + if (n16) + baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); + if(baudAbsDiff13 < 0) baudAbsDiff13 = -baudAbsDiff13; if(baudAbsDiff16 < 0) Another possibility would be to convert this into a lookup table (also untested): diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 816d1a2..942d68e 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -224,6 +224,48 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) pdata->enable_wakeup(up->dev, enable); } +struct uart_omap_config { + unsigned int baud; + unsigned int oversampling; + unsigned int divisor; +}; + +static struct uart_omap_config omap_port_configs[] = { + { .baud = 300, .oversampling = 16, .divisor = 10000, }, + { .baud = 300, .oversampling = 16, .divisor = 10000, }, + { .baud = 600, .oversampling = 16, .divisor = 5000, }, + { .baud = 1200, .oversampling = 16, .divisor = 2500, }, + { .baud = 2400, .oversampling = 16, .divisor = 1250, }, + { .baud = 4800, .oversampling = 16, .divisor = 625, }, + { .baud = 9600, .oversampling = 16, .divisor = 312, }, + { .baud = 14400, .oversampling = 16, .divisor = 208, }, + { .baud = 19200, .oversampling = 16, .divisor = 156, }, + { .baud = 28800, .oversampling = 16, .divisor = 704, }, + { .baud = 38400, .oversampling = 16, .divisor = 78, }, + { .baud = 57600, .oversampling = 16, .divisor = 52, }, + { .baud = 115200, .oversampling = 16, .divisor = 26, }, + { .baud = 230400, .oversampling = 16, .divisor = 13, }, + { .baud = 460800, .oversampling = 13, .divisor = 8, }, + { .baud = 921600, .oversampling = 13, .divisor = 4, }, + { .baud = 1843200, .oversampling = 13, .divisor = 2, }, + { .baud = 3000000, .oversampling = 16, .divisor = 1, }, + { .baud = 3686400, .oversampling = 13, .divisor = 1, }, + { } /* Terminating Entry */ +}; + +static struct uart_omap_config * +__serial_omap_get_config(struct uart_port *port, unsigned int baud) +{ + struct uart_omap_config *cfg = omap_port_configs; + + while (cfg++) { + if (cfg->baud == baud) + return cfg; + } + + return NULL; +} + /* * serial_omap_baud_is_mode16 - check if baud rate is MODE16X * @port: uart port info @@ -238,16 +280,12 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) static bool serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) { - unsigned int n13 = port->uartclk / (13 * baud); - unsigned int n16 = port->uartclk / (16 * baud); - int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); - int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); - if(baudAbsDiff13 < 0) - baudAbsDiff13 = -baudAbsDiff13; - if(baudAbsDiff16 < 0) - baudAbsDiff16 = -baudAbsDiff16; - - return (baudAbsDiff13 > baudAbsDiff16); + struct uart_omap_config *cfg = __serial_omap_get_config(port, baud); + + if (!cfg) + return -EINVAL; + + return (cfg->oversampling == 16); } /* @@ -258,13 +296,12 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) static unsigned int serial_omap_get_divisor(struct uart_port *port, unsigned int baud) { - unsigned int divisor; + struct uart_omap_config *cfg = __serial_omap_get_config(port, baud); - if (!serial_omap_baud_is_mode16(port, baud)) - divisor = 13; - else - divisor = 16; - return port->uartclk/(baud * divisor); + if (!cfg) + return -EINVAL; + + return cfg->divisor; } static void serial_omap_enable_ms(struct uart_port *port) -- balbi
Attachment:
signature.asc
Description: Digital signature