Re: [U-Boot] [PATCH v5 14/18] serial: MediaTek: add high-speed uart driver for MediaTek SoCs

2018-11-15 Thread Simon Glass
On 14 November 2018 at 18:08, Ryder Lee  wrote:
>
> Many SoCs from MediaTek have a high-speed uart. This UART is compatible
> with the ns16550 in legacy mode. It has extra registers for high-speed
> mode which can reach a maximum baudrate at 921600.
>
> However this UART will no longer be compatible if it's in high-speed mode.
> Some BootROM of MediaTek's SoCs will change the UART into high-speed mode
> and the U-Boot must use this driver to initialize the UART.
>
> Signed-off-by: Weijie Gao 
> Tested-by: Ryder Lee 
> ---
> Changes since v5: Add a specific driver for MTK UART
> Changes since v4: None
> ---
>  drivers/serial/Kconfig  |  20 
>  drivers/serial/Makefile |   1 +
>  drivers/serial/serial_mtk.c | 268 
> 
>  3 files changed, 289 insertions(+)
>  create mode 100644 drivers/serial/serial_mtk.c

Reviewed-by: Simon Glass 
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v5 14/18] serial: MediaTek: add high-speed uart driver for MediaTek SoCs

2018-11-14 Thread Ryder Lee
Many SoCs from MediaTek have a high-speed uart. This UART is compatible
with the ns16550 in legacy mode. It has extra registers for high-speed
mode which can reach a maximum baudrate at 921600.

However this UART will no longer be compatible if it's in high-speed mode.
Some BootROM of MediaTek's SoCs will change the UART into high-speed mode
and the U-Boot must use this driver to initialize the UART.

Signed-off-by: Weijie Gao 
Tested-by: Ryder Lee 
---
Changes since v5: Add a specific driver for MTK UART
Changes since v4: None
---
 drivers/serial/Kconfig  |  20 
 drivers/serial/Makefile |   1 +
 drivers/serial/serial_mtk.c | 268 
 3 files changed, 289 insertions(+)
 create mode 100644 drivers/serial/serial_mtk.c

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 597db4b..7ab38b7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -368,6 +368,16 @@ config DEBUG_UART_OMAP
  You will need to provide parameters to make this work. The driver
  will be available until the real driver model serial is running.
 
+config DEBUG_UART_MTK
+   bool "MediaTek High-speed UART"
+   depends on MTK_SERIAL
+   help
+ Select this to enable a debug UART using the MediaTek High-speed
+ UART driver.
+ You will need to provide parameters to make this work. The
+ driver will be available until the real driver model serial is
+ running.
+
 endchoice
 
 config DEBUG_UART_BASE
@@ -692,6 +702,16 @@ config ZYNQ_SERIAL
  This driver supports the Cadence UART. It is found e.g. in Xilinx
  Zynq/ZynqMP.
 
+config MTK_SERIAL
+   bool "MediaTek High-speed UART support"
+   depends on DM_SERIAL
+   help
+ Select this to enable UART support for MediaTek High-speed UART
+ devices. This driver uses driver model and requires a device
+ tree binding to operate.
+ The High-speed UART is compatible with the ns16550a UART and have
+ its own high-speed registers.
+
 config MPC8XX_CONS
bool "Console driver for MPC8XX"
depends on MPC8xx
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 03dc29e..2f8d065 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o
 obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
 obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
 obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
+obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
new file mode 100644
index 000..bce1be8
--- /dev/null
+++ b/drivers/serial/serial_mtk.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek High-speed UART driver
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mtk_serial_regs {
+   u32 rbr;
+   u32 ier;
+   u32 fcr;
+   u32 lcr;
+   u32 mcr;
+   u32 lsr;
+   u32 msr;
+   u32 spr;
+   u32 mdr1;
+   u32 highspeed;
+   u32 sample_count;
+   u32 sample_point;
+   u32 fracdiv_l;
+   u32 fracdiv_m;
+   u32 escape_en;
+   u32 guard;
+   u32 rx_sel;
+};
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define UART_LCR_WLS_8 0x03/* 8 bit character length */
+#define UART_LCR_DLAB  0x80/* Divisor latch access bit */
+
+#define UART_LSR_DR0x01/* Data ready */
+#define UART_LSR_THRE  0x20/* Xmit holding register empty */
+
+/* the data is correct if the real baud is within 3%. */
+#define BAUD_ALLOW_MAX(baud)   ((baud) + (baud) * 3 / 100)
+#define BAUD_ALLOW_MIX(baud)   ((baud) - (baud) * 3 / 100)
+
+struct mtk_serial_priv {
+   struct mtk_serial_regs __iomem *regs;
+   u32 clock;
+};
+
+static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
+{
+   bool support_clk12m_baud115200;
+   u32 quot, samplecount, realbaud;
+
+   if ((baud <= 115200) && (priv->clock == 1200))
+   support_clk12m_baud115200 = true;
+   else
+   support_clk12m_baud115200 = false;
+
+   if (baud <= 115200) {
+   writel(0, >regs->highspeed);
+   quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
+
+   if (support_clk12m_baud115200) {
+   writel(3, >regs->highspeed);
+   quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+   if (quot == 0)
+   quot = 1;
+
+   samplecount = DIV_ROUND_CLOSEST(priv->clock,
+   quot * baud);
+   if (samplecount != 0) {
+