1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  8250/16550-type serial ports prom_putchar()
4  *
5  *  Copyright (C) 2010  Yoichi Yuasa <yuasa@linux-mips.org>
6  */
7 #include <linux/io.h>
8 #include <linux/serial_core.h>
9 #include <linux/serial_reg.h>
10 #include <asm/setup.h>
11 
12 static void __iomem *serial8250_base;
13 static unsigned int serial8250_reg_shift;
14 static unsigned int serial8250_tx_timeout;
15 
16 void setup_8250_early_printk_port(unsigned long base, unsigned int reg_shift,
17 				  unsigned int timeout)
18 {
19 	serial8250_base = (void __iomem *)base;
20 	serial8250_reg_shift = reg_shift;
21 	serial8250_tx_timeout = timeout;
22 }
23 
24 static inline u8 serial_in(int offset)
25 {
26 	return readb(serial8250_base + (offset << serial8250_reg_shift));
27 }
28 
29 static inline void serial_out(int offset, char value)
30 {
31 	writeb(value, serial8250_base + (offset << serial8250_reg_shift));
32 }
33 
34 void prom_putchar(char c)
35 {
36 	unsigned int timeout;
37 	int status, bits;
38 
39 	if (!serial8250_base)
40 		return;
41 
42 	timeout = serial8250_tx_timeout;
43 	bits = UART_LSR_TEMT | UART_LSR_THRE;
44 
45 	do {
46 		status = serial_in(UART_LSR);
47 
48 		if (--timeout == 0)
49 			break;
50 	} while ((status & bits) != bits);
51 
52 	if (timeout)
53 		serial_out(UART_TX, c);
54 }
55