xref: /linux/drivers/tty/serial/imx_earlycon.c (revision 3f8bab17)
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)193f8bab17SJiri 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