|
@@ -231,25 +231,43 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
|
|
|
pdata->enable_wakeup(up->dev, enable);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * serial_omap_baud_is_mode16 - check if baud rate is MODE16X
|
|
|
+ * @port: uart port info
|
|
|
+ * @baud: baudrate for which mode needs to be determined
|
|
|
+ *
|
|
|
+ * Returns true if baud rate is MODE16X and false if MODE13X
|
|
|
+ * Original table in OMAP TRM named "UART Mode Baud Rates, Divisor Values,
|
|
|
+ * and Error Rates" determines modes not for all common baud rates.
|
|
|
+ * E.g. for 1000000 baud rate mode must be 16x, but according to that
|
|
|
+ * table it's determined as 13x.
|
|
|
+ */
|
|
|
+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);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* serial_omap_get_divisor - calculate divisor value
|
|
|
* @port: uart port info
|
|
|
* @baud: baudrate for which divisor needs to be calculated.
|
|
|
- *
|
|
|
- * We have written our own function to get the divisor so as to support
|
|
|
- * 13x mode. 3Mbps Baudrate as an different divisor.
|
|
|
- * Reference OMAP TRM Chapter 17:
|
|
|
- * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
|
|
|
- * referring to oversampling - divisor value
|
|
|
- * baudrate 460,800 to 3,686,400 all have divisor 13
|
|
|
- * except 3,000,000 which has divisor value 16
|
|
|
*/
|
|
|
static unsigned int
|
|
|
serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
|
|
|
{
|
|
|
unsigned int divisor;
|
|
|
|
|
|
- if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
|
|
|
+ if (!serial_omap_baud_is_mode16(port, baud))
|
|
|
divisor = 13;
|
|
|
else
|
|
|
divisor = 16;
|
|
@@ -916,7 +934,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
|
|
|
serial_out(up, UART_EFR, up->efr);
|
|
|
serial_out(up, UART_LCR, cval);
|
|
|
|
|
|
- if (baud > 230400 && baud != 3000000)
|
|
|
+ if (!serial_omap_baud_is_mode16(port, baud))
|
|
|
up->mdr1 = UART_OMAP_MDR1_13X_MODE;
|
|
|
else
|
|
|
up->mdr1 = UART_OMAP_MDR1_16X_MODE;
|