linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexey Pelykh <alexey.pelykh@gmail.com>
To: Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Greg KH <gregkh@linuxfoundation.org>
Cc: linux-serial@vger.kernel.org
Subject: [PATCH] OMAP/serial: Support 1Mbaud and similar baudrates that require Mode16 instead of Mode13
Date: Wed, 16 Jan 2013 05:08:06 -0500	[thread overview]
Message-ID: <20130116100806.GA57684@inertiallabs-linux64> (raw)

From: Alexey Pelykh <alexey.pelykh@gmail.com>

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 should be 16x, but according to
that table it's determined as 13x. According to current implementation
of mode divisor selection, after requesting 1000000 baudrate from
driver, later one will configure chip to use MODE13 divisor. Assuming
48Mhz as common UART clock speed, MODE13 divisor will effectively give
1230769 baudrate, what is quite far from desired 1000000 baudrate.
While with MODE16 divisor, chip will produce exact 1000000 baudrate.
In old driver that served UART devices (8250.c and serial_core.c) this
divisor could have been configured by user-space program, but in
omap_serial.c driver implementation this ability was not implemented
(afaik, by design) thus disallowing proper usage of MODE16-compatible
baudrates.

Signed-off-by: Alexey Pelykh <alexey.pelykh@gmail.com>

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6d3d26a..6d567dd 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -182,24 +182,42 @@ static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool 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;
@@ -893,7 +911,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;

             reply	other threads:[~2013-01-16 10:08 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-16 10:08 Alexey Pelykh [this message]
  -- strict thread matches above, loose matches on Subject: below --
2012-11-28 19:03 [PATCH] OMAP/serial: Support 1Mbaud and similar baudrates that require Mode16 instead of Mode13 Alexey Pelykh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130116100806.GA57684@inertiallabs-linux64 \
    --to=alexey.pelykh@gmail.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).