1699cc4dfSFugang Duan // SPDX-License-Identifier: GPL-2.0+
2699cc4dfSFugang Duan /*
3699cc4dfSFugang Duan * Copyright 2020 NXP
4699cc4dfSFugang Duan */
5699cc4dfSFugang Duan
6699cc4dfSFugang Duan #include <linux/module.h>
7699cc4dfSFugang Duan #include <linux/ioport.h>
8699cc4dfSFugang Duan #include <linux/init.h>
9699cc4dfSFugang Duan #include <linux/serial_core.h>
10699cc4dfSFugang Duan #include <linux/serial.h>
11699cc4dfSFugang Duan #include <linux/delay.h>
12699cc4dfSFugang Duan #include <linux/of.h>
13699cc4dfSFugang Duan #include <linux/io.h>
14699cc4dfSFugang Duan
15699cc4dfSFugang Duan #define URTX0 0x40 /* Transmitter Register */
16699cc4dfSFugang Duan #define UTS_TXFULL (1<<4) /* TxFIFO full */
17699cc4dfSFugang Duan #define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
18699cc4dfSFugang Duan
imx_uart_console_early_putchar(struct uart_port * port,unsigned char ch)19*3f8bab17SJiri Slaby static void imx_uart_console_early_putchar(struct uart_port *port, unsigned char ch)
20699cc4dfSFugang Duan {
21699cc4dfSFugang Duan while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
22699cc4dfSFugang Duan cpu_relax();
23699cc4dfSFugang Duan
24699cc4dfSFugang Duan writel_relaxed(ch, port->membase + URTX0);
25699cc4dfSFugang Duan }
26699cc4dfSFugang Duan
imx_uart_console_early_write(struct console * con,const char * s,unsigned count)27699cc4dfSFugang Duan static void imx_uart_console_early_write(struct console *con, const char *s,
28699cc4dfSFugang Duan unsigned count)
29699cc4dfSFugang Duan {
30699cc4dfSFugang Duan struct earlycon_device *dev = con->data;
31699cc4dfSFugang Duan
32699cc4dfSFugang Duan uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
33699cc4dfSFugang Duan }
34699cc4dfSFugang Duan
35699cc4dfSFugang Duan static int __init
imx_console_early_setup(struct earlycon_device * dev,const char * opt)36699cc4dfSFugang Duan imx_console_early_setup(struct earlycon_device *dev, const char *opt)
37699cc4dfSFugang Duan {
38699cc4dfSFugang Duan if (!dev->port.membase)
39699cc4dfSFugang Duan return -ENODEV;
40699cc4dfSFugang Duan
41699cc4dfSFugang Duan dev->con->write = imx_uart_console_early_write;
42699cc4dfSFugang Duan
43699cc4dfSFugang Duan return 0;
44699cc4dfSFugang Duan }
45699cc4dfSFugang Duan OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
46699cc4dfSFugang Duan OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
47699cc4dfSFugang Duan
48699cc4dfSFugang Duan MODULE_AUTHOR("NXP");
49699cc4dfSFugang Duan MODULE_DESCRIPTION("IMX earlycon driver");
50699cc4dfSFugang Duan MODULE_LICENSE("GPL");
51