summaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
authorWeijie Gao <weijie.gao@mediatek.com>2019-09-25 17:45:18 +0800
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>2019-10-25 17:20:43 +0200
commit44fa676e58e90ad9283995b544f8e1013524161f (patch)
treee1a2550e4b878f85f29a98154dbd0784f82d8eef /drivers/serial
parent99ced5331baf1254232e3f73e113fb7ecedebad2 (diff)
serial: serial_mtk: add non-DM version for SPL
This patch adds non-DM version for mtk hsuart driver and makes it compatible with ns16550a driver in configuration. This is needed in SPL with CONFIG_SPL_DM disabled for reducing size. Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/serial.c2
-rw-r--r--drivers/serial/serial_mtk.c202
2 files changed, 187 insertions, 17 deletions
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index b907508dbe..bf5f39215d 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -124,6 +124,7 @@ serial_initfunc(ns16550_serial_initialize);
serial_initfunc(pl01x_serial_initialize);
serial_initfunc(pxa_serial_initialize);
serial_initfunc(sh_serial_initialize);
+serial_initfunc(mtk_serial_initialize);
/**
* serial_register() - Register serial driver with serial driver core
@@ -177,6 +178,7 @@ void serial_initialize(void)
pl01x_serial_initialize();
pxa_serial_initialize();
sh_serial_initialize();
+ mtk_serial_initialize();
serial_assign(default_serial_console()->name);
}
diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c
index 11892a8740..18530a4fd1 100644
--- a/drivers/serial/serial_mtk.c
+++ b/drivers/serial/serial_mtk.c
@@ -140,6 +140,37 @@ static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
}
}
+static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
+{
+ if (!(readl(&priv->regs->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
+
+ writel(ch, &priv->regs->thr);
+
+ if (ch == '\n')
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int _mtk_serial_getc(struct mtk_serial_priv *priv)
+{
+ if (!(readl(&priv->regs->lsr) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return readl(&priv->regs->rbr);
+}
+
+static int _mtk_serial_pending(struct mtk_serial_priv *priv, bool input)
+{
+ if (input)
+ return (readl(&priv->regs->lsr) & UART_LSR_DR) ? 1 : 0;
+ else
+ return (readl(&priv->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
+}
+
+#if defined(CONFIG_DM_SERIAL) && \
+ (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_DM))
static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
{
struct mtk_serial_priv *priv = dev_get_priv(dev);
@@ -153,35 +184,21 @@ static int mtk_serial_putc(struct udevice *dev, const char ch)
{
struct mtk_serial_priv *priv = dev_get_priv(dev);
- if (!(readl(&priv->regs->lsr) & UART_LSR_THRE))
- return -EAGAIN;
-
- writel(ch, &priv->regs->thr);
-
- if (ch == '\n')
- WATCHDOG_RESET();
-
- return 0;
+ return _mtk_serial_putc(priv, ch);
}
static int mtk_serial_getc(struct udevice *dev)
{
struct mtk_serial_priv *priv = dev_get_priv(dev);
- if (!(readl(&priv->regs->lsr) & UART_LSR_DR))
- return -EAGAIN;
-
- return readl(&priv->regs->rbr);
+ return _mtk_serial_getc(priv);
}
static int mtk_serial_pending(struct udevice *dev, bool input)
{
struct mtk_serial_priv *priv = dev_get_priv(dev);
- if (input)
- return (readl(&priv->regs->lsr) & UART_LSR_DR) ? 1 : 0;
- else
- return (readl(&priv->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
+ return _mtk_serial_pending(priv, input);
}
static int mtk_serial_probe(struct udevice *dev)
@@ -254,6 +271,157 @@ U_BOOT_DRIVER(serial_mtk) = {
.ops = &mtk_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};
+#else
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DECLARE_HSUART_PRIV(port) \
+ static struct mtk_serial_priv mtk_hsuart##port = { \
+ .regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \
+ .clock = CONFIG_SYS_NS16550_CLK \
+};
+
+#define DECLARE_HSUART_FUNCTIONS(port) \
+ static int mtk_serial##port##_init(void) \
+ { \
+ writel(0, &mtk_hsuart##port.regs->ier); \
+ writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
+ writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
+ _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
+ return 0 ; \
+ } \
+ static void mtk_serial##port##_setbrg(void) \
+ { \
+ _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
+ } \
+ static int mtk_serial##port##_getc(void) \
+ { \
+ int err; \
+ do { \
+ err = _mtk_serial_getc(&mtk_hsuart##port); \
+ if (err == -EAGAIN) \
+ WATCHDOG_RESET(); \
+ } while (err == -EAGAIN); \
+ return err >= 0 ? err : 0; \
+ } \
+ static int mtk_serial##port##_tstc(void) \
+ { \
+ return _mtk_serial_pending(&mtk_hsuart##port, true); \
+ } \
+ static void mtk_serial##port##_putc(const char c) \
+ { \
+ int err; \
+ if (c == '\n') \
+ mtk_serial##port##_putc('\r'); \
+ do { \
+ err = _mtk_serial_putc(&mtk_hsuart##port, c); \
+ } while (err == -EAGAIN); \
+ } \
+ static void mtk_serial##port##_puts(const char *s) \
+ { \
+ while (*s) { \
+ mtk_serial##port##_putc(*s++); \
+ } \
+ }
+
+/* Serial device descriptor */
+#define INIT_HSUART_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = mtk_serial##port##_init, \
+ .stop = NULL, \
+ .setbrg = mtk_serial##port##_setbrg, \
+ .getc = mtk_serial##port##_getc, \
+ .tstc = mtk_serial##port##_tstc, \
+ .putc = mtk_serial##port##_putc, \
+ .puts = mtk_serial##port##_puts, \
+}
+
+#define DECLARE_HSUART(port, __name) \
+ DECLARE_HSUART_PRIV(port); \
+ DECLARE_HSUART_FUNCTIONS(port); \
+ struct serial_device mtk_hsuart##port##_device = \
+ INIT_HSUART_STRUCTURE(port, __name);
+
+#if !defined(CONFIG_CONS_INDEX)
+#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6)
+#error "Invalid console index value."
+#endif
+
+#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
+#error "Console port 1 defined but not configured."
+#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
+#error "Console port 2 defined but not configured."
+#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
+#error "Console port 3 defined but not configured."
+#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
+#error "Console port 4 defined but not configured."
+#elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5)
+#error "Console port 5 defined but not configured."
+#elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6)
+#error "Console port 6 defined but not configured."
+#endif
+
+#if defined(CONFIG_SYS_NS16550_COM1)
+DECLARE_HSUART(1, "mtk-hsuart0");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+DECLARE_HSUART(2, "mtk-hsuart1");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+DECLARE_HSUART(3, "mtk-hsuart2");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+DECLARE_HSUART(4, "mtk-hsuart3");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM5)
+DECLARE_HSUART(5, "mtk-hsuart4");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM6)
+DECLARE_HSUART(6, "mtk-hsuart5");
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_CONS_INDEX == 1
+ return &mtk_hsuart1_device;
+#elif CONFIG_CONS_INDEX == 2
+ return &mtk_hsuart2_device;
+#elif CONFIG_CONS_INDEX == 3
+ return &mtk_hsuart3_device;
+#elif CONFIG_CONS_INDEX == 4
+ return &mtk_hsuart4_device;
+#elif CONFIG_CONS_INDEX == 5
+ return &mtk_hsuart5_device;
+#elif CONFIG_CONS_INDEX == 6
+ return &mtk_hsuart6_device;
+#else
+#error "Bad CONFIG_CONS_INDEX."
+#endif
+}
+
+void mtk_serial_initialize(void)
+{
+#if defined(CONFIG_SYS_NS16550_COM1)
+ serial_register(&mtk_hsuart1_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+ serial_register(&mtk_hsuart2_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+ serial_register(&mtk_hsuart3_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+ serial_register(&mtk_hsuart4_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM5)
+ serial_register(&mtk_hsuart5_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM6)
+ serial_register(&mtk_hsuart6_device);
+#endif
+}
+
+#endif
#ifdef CONFIG_DEBUG_UART_MTK