[PATCH v4 1/2] tty: serial: 8250: Add Mediatek UART driver

2014-08-12 Thread Matthias Brugger
The device has a highspeed register which influences the calcualtion of the
divisor. The chip lacks support for some baudrates. When requested, we set the
divisor to the next smaller baudrate and adjust the c_cflag accordingly.

Signed-off-by: Matthias Brugger 
---
 drivers/tty/serial/8250/8250_mtk.c |  294 
 drivers/tty/serial/8250/Kconfig|7 +
 drivers/tty/serial/8250/Makefile   |1 +
 3 files changed, 302 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_mtk.c

diff --git a/drivers/tty/serial/8250/8250_mtk.c 
b/drivers/tty/serial/8250/8250_mtk.c
new file mode 100644
index 000..1c4b4bf
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -0,0 +1,294 @@
+/*
+ * Mediatek 8250 driver.
+ *
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "8250.h"
+
+#define UART_MTK_HIGHS 0x09/* Highspeed register */
+#define UART_MTK_SAMPLE_COUNT  0x0a/* Sample count register */
+#define UART_MTK_SAMPLE_POINT  0x0b/* Sample point register */
+#define MTK_UART_RATE_FIX  0x0d/* UART Rate Fix Register */
+
+struct mtk8250_data {
+   int line;
+   struct clk  *clk;
+};
+
+static void
+mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
+   struct ktermios *old)
+{
+   unsigned long flags;
+   unsigned int baud, quot;
+
+   struct uart_8250_port *up =
+   container_of(port, struct uart_8250_port, port);
+
+   serial8250_do_set_termios(port, termios, old);
+
+   /*
+* Mediatek UARTs use an extra highspeed register (UART_MTK_HIGHS)
+*
+* We need to recalcualte the quot register, as the claculation depends
+* on the vaule in the highspeed register.
+*
+* Some baudrates are not supported by the chip, so we use the next
+* lower rate supported and update termios c_flag.
+*
+* If highspeed register is set to 3, we need to specify sample count
+* and sample point to increase accuracy. If not, we reset the
+* registers to their default values.
+*/
+   baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0x,
+ port->uartclk / 16);
+
+   if (baud <= 115200) {
+   serial_port_out(port, UART_MTK_HIGHS, 0x0);
+   quot = uart_get_divisor(port, baud);
+   } else if (baud <= 576000) {
+   serial_port_out(port, UART_MTK_HIGHS, 0x2);
+
+   /* Set to next lower baudrate supported */
+   if ((baud == 50) || (baud == 576000))
+   baud = 460800;
+   quot = DIV_ROUND_CLOSEST(port->uartclk, 4 * baud);
+   } else {
+   serial_port_out(port, UART_MTK_HIGHS, 0x3);
+
+   /* Set to highest baudrate supported */
+   if (baud >= 1152000)
+   baud = 921600;
+   quot = DIV_ROUND_CLOSEST(port->uartclk, 256 * baud);
+   }
+
+   /*
+* Ok, we're now changing the port state.  Do it with
+* interrupts disabled.
+*/
+   spin_lock_irqsave(&port->lock, flags);
+
+   /* set DLAB we have cval saved in up->lcr from the call to the core */
+   serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
+   serial_dl_write(up, quot);
+
+   /* reset DLAB */
+   serial_port_out(port, UART_LCR, up->lcr);
+
+   if (baud > 460800) {
+   unsigned int tmp;
+
+   tmp = DIV_ROUND_CLOSEST(port->uartclk, quot * baud);
+   serial_port_out(port, UART_MTK_SAMPLE_COUNT, tmp - 1);
+   serial_port_out(port, UART_MTK_SAMPLE_POINT,
+   (tmp - 2) >> 1);
+   } else {
+   serial_port_out(port, UART_MTK_SAMPLE_COUNT, 0x00);
+   serial_port_out(port, UART_MTK_SAMPLE_POINT, 0xff);
+   }
+
+   spin_unlock_irqrestore(&port->lock, flags);
+   /* Don't rewrite B0 */
+   if (tty_termios_baud_rate(termios))
+   tty_termios_encode_baud_rate(termios, baud, baud);
+}
+
+static void
+mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
+{
+   if (!state)
+   pm_runtime_get_sync(port-

Re: [PATCH v4 1/2] tty: serial: 8250: Add Mediatek UART driver

2014-09-02 Thread Mark Rutland
[...]

> +static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port 
> *p,
> +struct mtk8250_data *data)
> +{
> + int err;
> + struct device_node *np = pdev->dev.of_node;
> +
> + data->clk = of_clk_get(np, 0);
> + if (IS_ERR(data->clk)) {
> + dev_warn(&pdev->dev, "Can't get timer clock\n");
> + return PTR_ERR(data->clk);
> + }

Elsewhere you use devm_ interfaces. Can we not use devm_clk_get?

You might need to give the clock a name, but that's generally a good
thing -- it helps if a future revision has multiple clocks.

Mark.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 1/2] tty: serial: 8250: Add Mediatek UART driver

2014-09-08 Thread Greg KH
On Tue, Aug 12, 2014 at 04:12:16PM +0200, Matthias Brugger wrote:
> The device has a highspeed register which influences the calcualtion of the
> divisor. The chip lacks support for some baudrates. When requested, we set the
> divisor to the next smaller baudrate and adjust the c_cflag accordingly.
> 
> Signed-off-by: Matthias Brugger 
> ---
>  drivers/tty/serial/8250/8250_mtk.c |  294 
> 
>  drivers/tty/serial/8250/Kconfig|7 +
>  drivers/tty/serial/8250/Makefile   |1 +
>  3 files changed, 302 insertions(+)
>  create mode 100644 drivers/tty/serial/8250/8250_mtk.c

This doesn't apply to my tree, care to refresh it against linux-next and
resend?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/