1 // SPDX-License-Identifier: GPL-2.0
3 * MediaTek High-speed UART driver
5 * Copyright (C) 2018 MediaTek Inc.
6 * Author: Weijie Gao <weijie.gao@mediatek.com>
13 #include <dm/device_compat.h>
18 #include <asm/global_data.h>
20 #include <asm/types.h>
21 #include <linux/err.h>
23 struct mtk_serial_regs {
48 #define UART_LCR_WLS_8 0x03 /* 8 bit character length */
49 #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
51 #define UART_LSR_DR 0x01 /* Data ready */
52 #define UART_LSR_THRE 0x20 /* Xmit holding register empty */
53 #define UART_LSR_TEMT 0x40 /* Xmitter empty */
55 #define UART_MCR_DTR 0x01 /* DTR */
56 #define UART_MCR_RTS 0x02 /* RTS */
58 #define UART_FCR_FIFO_EN 0x01 /* Fifo enable */
59 #define UART_FCR_RXSR 0x02 /* Receiver soft reset */
60 #define UART_FCR_TXSR 0x04 /* Transmitter soft reset */
62 #define UART_MCRVAL (UART_MCR_DTR | \
65 /* Clear & enable FIFOs */
66 #define UART_FCRVAL (UART_FCR_FIFO_EN | \
70 /* the data is correct if the real baud is within 3%. */
71 #define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100)
72 #define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100)
74 /* struct mtk_serial_priv - Structure holding all information used by the
76 * @regs: Register base of the serial port
77 * @clk: The baud clock device
78 * @fixed_clk_rate: Fallback fixed baud clock rate if baud clock
79 * device is not specified
80 * @force_highspeed: Force using high-speed mode
82 struct mtk_serial_priv {
83 struct mtk_serial_regs __iomem *regs;
89 static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud,
92 u32 quot, realbaud, samplecount = 1;
94 /* Special case for low baud clock */
95 if (baud <= 115200 && clk_rate == 12000000) {
96 writel(3, &priv->regs->highspeed);
98 quot = DIV_ROUND_CLOSEST(clk_rate, 256 * baud);
102 samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
104 realbaud = clk_rate / samplecount / quot;
105 if (realbaud > BAUD_ALLOW_MAX(baud) ||
106 realbaud < BAUD_ALLOW_MIX(baud)) {
107 pr_info("baud %d can't be handled\n", baud);
113 if (priv->force_highspeed)
116 if (baud <= 115200) {
117 writel(0, &priv->regs->highspeed);
118 quot = DIV_ROUND_CLOSEST(clk_rate, 16 * baud);
119 } else if (baud <= 576000) {
120 writel(2, &priv->regs->highspeed);
122 /* Set to next lower baudrate supported */
123 if ((baud == 500000) || (baud == 576000))
126 quot = DIV_ROUND_UP(clk_rate, 4 * baud);
129 writel(3, &priv->regs->highspeed);
131 quot = DIV_ROUND_UP(clk_rate, 256 * baud);
132 samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
137 writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
138 writel(quot & 0xff, &priv->regs->dll);
139 writel((quot >> 8) & 0xff, &priv->regs->dlm);
140 writel(UART_LCR_WLS_8, &priv->regs->lcr);
142 /* set highspeed mode sample count & point */
143 writel(samplecount - 1, &priv->regs->sample_count);
144 writel((samplecount - 2) >> 1, &priv->regs->sample_point);
147 static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
149 if (!(readl(&priv->regs->lsr) & UART_LSR_THRE))
152 writel(ch, &priv->regs->thr);
160 static int _mtk_serial_getc(struct mtk_serial_priv *priv)
162 if (!(readl(&priv->regs->lsr) & UART_LSR_DR))
165 return readl(&priv->regs->rbr);
168 static int _mtk_serial_pending(struct mtk_serial_priv *priv, bool input)
171 return (readl(&priv->regs->lsr) & UART_LSR_DR) ? 1 : 0;
173 return (readl(&priv->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
176 #if defined(CONFIG_DM_SERIAL) && \
177 (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_DM))
178 static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
180 struct mtk_serial_priv *priv = dev_get_priv(dev);
183 clk_rate = clk_get_rate(&priv->clk);
184 if (IS_ERR_VALUE(clk_rate) || clk_rate == 0)
185 clk_rate = priv->fixed_clk_rate;
187 _mtk_serial_setbrg(priv, baudrate, clk_rate);
192 static int mtk_serial_putc(struct udevice *dev, const char ch)
194 struct mtk_serial_priv *priv = dev_get_priv(dev);
196 return _mtk_serial_putc(priv, ch);
199 static int mtk_serial_getc(struct udevice *dev)
201 struct mtk_serial_priv *priv = dev_get_priv(dev);
203 return _mtk_serial_getc(priv);
206 static int mtk_serial_pending(struct udevice *dev, bool input)
208 struct mtk_serial_priv *priv = dev_get_priv(dev);
210 return _mtk_serial_pending(priv, input);
213 static int mtk_serial_probe(struct udevice *dev)
215 struct mtk_serial_priv *priv = dev_get_priv(dev);
217 /* Disable interrupt */
218 writel(0, &priv->regs->ier);
220 writel(UART_MCRVAL, &priv->regs->mcr);
221 writel(UART_FCRVAL, &priv->regs->fcr);
226 static int mtk_serial_of_to_plat(struct udevice *dev)
228 struct mtk_serial_priv *priv = dev_get_priv(dev);
232 addr = dev_read_addr(dev);
233 if (addr == FDT_ADDR_T_NONE)
236 priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
238 err = clk_get_by_index(dev, 0, &priv->clk);
240 err = dev_read_u32(dev, "clock-frequency", &priv->fixed_clk_rate);
242 dev_err(dev, "baud clock not defined\n");
246 err = clk_get_rate(&priv->clk);
247 if (IS_ERR_VALUE(err)) {
248 dev_err(dev, "invalid baud clock\n");
253 priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
258 static const struct dm_serial_ops mtk_serial_ops = {
259 .putc = mtk_serial_putc,
260 .pending = mtk_serial_pending,
261 .getc = mtk_serial_getc,
262 .setbrg = mtk_serial_setbrg,
265 static const struct udevice_id mtk_serial_ids[] = {
266 { .compatible = "mediatek,hsuart" },
267 { .compatible = "mediatek,mt6577-uart" },
271 U_BOOT_DRIVER(serial_mtk) = {
272 .name = "serial_mtk",
274 .of_match = mtk_serial_ids,
275 .of_to_plat = mtk_serial_of_to_plat,
276 .priv_auto = sizeof(struct mtk_serial_priv),
277 .probe = mtk_serial_probe,
278 .ops = &mtk_serial_ops,
279 .flags = DM_FLAG_PRE_RELOC,
283 DECLARE_GLOBAL_DATA_PTR;
285 #define DECLARE_HSUART_PRIV(port) \
286 static struct mtk_serial_priv mtk_hsuart##port = { \
287 .regs = (struct mtk_serial_regs *)CFG_SYS_NS16550_COM##port, \
288 .fixed_clk_rate = CFG_SYS_NS16550_CLK \
291 #define DECLARE_HSUART_FUNCTIONS(port) \
292 static int mtk_serial##port##_init(void) \
294 writel(0, &mtk_hsuart##port.regs->ier); \
295 writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
296 writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
297 _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
298 mtk_hsuart##port.fixed_clk_rate); \
301 static void mtk_serial##port##_setbrg(void) \
303 _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
304 mtk_hsuart##port.fixed_clk_rate); \
306 static int mtk_serial##port##_getc(void) \
310 err = _mtk_serial_getc(&mtk_hsuart##port); \
311 if (err == -EAGAIN) \
313 } while (err == -EAGAIN); \
314 return err >= 0 ? err : 0; \
316 static int mtk_serial##port##_tstc(void) \
318 return _mtk_serial_pending(&mtk_hsuart##port, true); \
320 static void mtk_serial##port##_putc(const char c) \
324 mtk_serial##port##_putc('\r'); \
326 err = _mtk_serial_putc(&mtk_hsuart##port, c); \
327 } while (err == -EAGAIN); \
329 static void mtk_serial##port##_puts(const char *s) \
332 mtk_serial##port##_putc(*s++); \
336 /* Serial device descriptor */
337 #define INIT_HSUART_STRUCTURE(port, __name) { \
339 .start = mtk_serial##port##_init, \
341 .setbrg = mtk_serial##port##_setbrg, \
342 .getc = mtk_serial##port##_getc, \
343 .tstc = mtk_serial##port##_tstc, \
344 .putc = mtk_serial##port##_putc, \
345 .puts = mtk_serial##port##_puts, \
348 #define DECLARE_HSUART(port, __name) \
349 DECLARE_HSUART_PRIV(port); \
350 DECLARE_HSUART_FUNCTIONS(port); \
351 struct serial_device mtk_hsuart##port##_device = \
352 INIT_HSUART_STRUCTURE(port, __name);
354 #if !defined(CONFIG_CONS_INDEX)
355 #elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6)
356 #error "Invalid console index value."
359 #if CONFIG_CONS_INDEX == 1 && !defined(CFG_SYS_NS16550_COM1)
360 #error "Console port 1 defined but not configured."
361 #elif CONFIG_CONS_INDEX == 2 && !defined(CFG_SYS_NS16550_COM2)
362 #error "Console port 2 defined but not configured."
363 #elif CONFIG_CONS_INDEX == 3 && !defined(CFG_SYS_NS16550_COM3)
364 #error "Console port 3 defined but not configured."
365 #elif CONFIG_CONS_INDEX == 4 && !defined(CFG_SYS_NS16550_COM4)
366 #error "Console port 4 defined but not configured."
367 #elif CONFIG_CONS_INDEX == 5 && !defined(CFG_SYS_NS16550_COM5)
368 #error "Console port 5 defined but not configured."
369 #elif CONFIG_CONS_INDEX == 6 && !defined(CFG_SYS_NS16550_COM6)
370 #error "Console port 6 defined but not configured."
373 #if defined(CFG_SYS_NS16550_COM1)
374 DECLARE_HSUART(1, "mtk-hsuart0");
376 #if defined(CFG_SYS_NS16550_COM2)
377 DECLARE_HSUART(2, "mtk-hsuart1");
379 #if defined(CFG_SYS_NS16550_COM3)
380 DECLARE_HSUART(3, "mtk-hsuart2");
382 #if defined(CFG_SYS_NS16550_COM4)
383 DECLARE_HSUART(4, "mtk-hsuart3");
385 #if defined(CFG_SYS_NS16550_COM5)
386 DECLARE_HSUART(5, "mtk-hsuart4");
388 #if defined(CFG_SYS_NS16550_COM6)
389 DECLARE_HSUART(6, "mtk-hsuart5");
392 __weak struct serial_device *default_serial_console(void)
394 #if CONFIG_CONS_INDEX == 1
395 return &mtk_hsuart1_device;
396 #elif CONFIG_CONS_INDEX == 2
397 return &mtk_hsuart2_device;
398 #elif CONFIG_CONS_INDEX == 3
399 return &mtk_hsuart3_device;
400 #elif CONFIG_CONS_INDEX == 4
401 return &mtk_hsuart4_device;
402 #elif CONFIG_CONS_INDEX == 5
403 return &mtk_hsuart5_device;
404 #elif CONFIG_CONS_INDEX == 6
405 return &mtk_hsuart6_device;
407 #error "Bad CONFIG_CONS_INDEX."
411 void mtk_serial_initialize(void)
413 #if defined(CFG_SYS_NS16550_COM1)
414 serial_register(&mtk_hsuart1_device);
416 #if defined(CFG_SYS_NS16550_COM2)
417 serial_register(&mtk_hsuart2_device);
419 #if defined(CFG_SYS_NS16550_COM3)
420 serial_register(&mtk_hsuart3_device);
422 #if defined(CFG_SYS_NS16550_COM4)
423 serial_register(&mtk_hsuart4_device);
425 #if defined(CFG_SYS_NS16550_COM5)
426 serial_register(&mtk_hsuart5_device);
428 #if defined(CFG_SYS_NS16550_COM6)
429 serial_register(&mtk_hsuart6_device);
435 #ifdef CONFIG_DEBUG_UART_MTK
437 #include <debug_uart.h>
439 static inline void _debug_uart_init(void)
441 struct mtk_serial_priv priv;
443 priv.regs = (void *) CONFIG_VAL(DEBUG_UART_BASE);
444 priv.fixed_clk_rate = CONFIG_DEBUG_UART_CLOCK;
446 writel(0, &priv.regs->ier);
447 writel(UART_MCRVAL, &priv.regs->mcr);
448 writel(UART_FCRVAL, &priv.regs->fcr);
450 _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE, priv.fixed_clk_rate);
453 static inline void _debug_uart_putc(int ch)
455 struct mtk_serial_regs __iomem *regs =
456 (void *) CONFIG_VAL(DEBUG_UART_BASE);
458 while (!(readl(®s->lsr) & UART_LSR_THRE))
461 writel(ch, ®s->thr);