1 /*
2  * Copyright (C) 2012-2014 Panasonic Corporation
3  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
4  *
5  * Based on serial_ns16550.c
6  * (C) Copyright 2000
7  * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  */
11 
12 #include <common.h>
13 #include <serial.h>
14 
15 #define UART_REG(x)					\
16 	u8 x;						\
17 	u8 postpad_##x[3];
18 
19 /*
20  * Note: Register map is slightly different from that of 16550.
21  */
22 struct uniphier_serial {
23 	UART_REG(rbr);		/* 0x00 */
24 	UART_REG(ier);		/* 0x04 */
25 	UART_REG(iir);		/* 0x08 */
26 	UART_REG(fcr);		/* 0x0c */
27 	u8 mcr;			/* 0x10 */
28 	u8 lcr;
29 	u16 __postpad;
30 	UART_REG(lsr);		/* 0x14 */
31 	UART_REG(msr);		/* 0x18 */
32 	u32 __none1;
33 	u32 __none2;
34 	u16 dlr;
35 	u16 __postpad2;
36 };
37 
38 #define thr rbr
39 
40 /*
41  * These are the definitions for the Line Control Register
42  */
43 #define UART_LCR_WLS_8	0x03		/* 8 bit character length */
44 
45 /*
46  * These are the definitions for the Line Status Register
47  */
48 #define UART_LSR_DR	0x01		/* Data ready */
49 #define UART_LSR_THRE	0x20		/* Xmit holding register empty */
50 
51 DECLARE_GLOBAL_DATA_PTR;
52 
53 static void uniphier_serial_init(struct uniphier_serial *port)
54 {
55 	const unsigned int mode_x_div = 16;
56 	unsigned int divisor;
57 
58 	writeb(UART_LCR_WLS_8, &port->lcr);
59 
60 	divisor = DIV_ROUND_CLOSEST(CONFIG_SYS_UNIPHIER_UART_CLK,
61 						mode_x_div * gd->baudrate);
62 
63 	writew(divisor, &port->dlr);
64 }
65 
66 static void uniphier_serial_setbrg(struct uniphier_serial *port)
67 {
68 	uniphier_serial_init(port);
69 }
70 
71 static int uniphier_serial_tstc(struct uniphier_serial *port)
72 {
73 	return (readb(&port->lsr) & UART_LSR_DR) != 0;
74 }
75 
76 static int uniphier_serial_getc(struct uniphier_serial *port)
77 {
78 	while (!uniphier_serial_tstc(port))
79 		;
80 
81 	return readb(&port->rbr);
82 }
83 
84 static void uniphier_serial_putc(struct uniphier_serial *port, const char c)
85 {
86 	if (c == '\n')
87 		uniphier_serial_putc(port, '\r');
88 
89 	while (!(readb(&port->lsr) & UART_LSR_THRE))
90 		;
91 
92 	writeb(c, &port->thr);
93 }
94 
95 static struct uniphier_serial *serial_ports[4] = {
96 #ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE0
97 	(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE0,
98 #else
99 	NULL,
100 #endif
101 #ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE1
102 	(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE1,
103 #else
104 	NULL,
105 #endif
106 #ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE2
107 	(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE2,
108 #else
109 	NULL,
110 #endif
111 #ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE3
112 	(struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE3,
113 #else
114 	NULL,
115 #endif
116 };
117 
118 /* Multi serial device functions */
119 #define DECLARE_ESERIAL_FUNCTIONS(port) \
120 	static int  eserial##port##_init(void) \
121 	{ \
122 		uniphier_serial_init(serial_ports[port]); \
123 		return 0 ; \
124 	} \
125 	static void eserial##port##_setbrg(void) \
126 	{ \
127 		uniphier_serial_setbrg(serial_ports[port]); \
128 	} \
129 	static int  eserial##port##_getc(void) \
130 	{ \
131 		return uniphier_serial_getc(serial_ports[port]); \
132 	} \
133 	static int  eserial##port##_tstc(void) \
134 	{ \
135 		return uniphier_serial_tstc(serial_ports[port]); \
136 	} \
137 	static void eserial##port##_putc(const char c) \
138 	{ \
139 		uniphier_serial_putc(serial_ports[port], c); \
140 	}
141 
142 /* Serial device descriptor */
143 #define INIT_ESERIAL_STRUCTURE(port, __name) {	\
144 	.name	= __name,			\
145 	.start	= eserial##port##_init,		\
146 	.stop	= NULL,				\
147 	.setbrg	= eserial##port##_setbrg,	\
148 	.getc	= eserial##port##_getc,		\
149 	.tstc	= eserial##port##_tstc,		\
150 	.putc	= eserial##port##_putc,		\
151 	.puts	= default_serial_puts,		\
152 }
153 
154 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
155 DECLARE_ESERIAL_FUNCTIONS(0);
156 struct serial_device uniphier_serial0_device =
157 	INIT_ESERIAL_STRUCTURE(0, "ttyS0");
158 #endif
159 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
160 DECLARE_ESERIAL_FUNCTIONS(1);
161 struct serial_device uniphier_serial1_device =
162 	INIT_ESERIAL_STRUCTURE(1, "ttyS1");
163 #endif
164 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
165 DECLARE_ESERIAL_FUNCTIONS(2);
166 struct serial_device uniphier_serial2_device =
167 	INIT_ESERIAL_STRUCTURE(2, "ttyS2");
168 #endif
169 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
170 DECLARE_ESERIAL_FUNCTIONS(3);
171 struct serial_device uniphier_serial3_device =
172 	INIT_ESERIAL_STRUCTURE(3, "ttyS3");
173 #endif
174 
175 __weak struct serial_device *default_serial_console(void)
176 {
177 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
178 	return &uniphier_serial0_device;
179 #elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
180 	return &uniphier_serial1_device;
181 #elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
182 	return &uniphier_serial2_device;
183 #elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
184 	return &uniphier_serial3_device;
185 #else
186 #error "No uniphier serial ports configured."
187 #endif
188 }
189 
190 void uniphier_serial_initialize(void)
191 {
192 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
193 	serial_register(&uniphier_serial0_device);
194 #endif
195 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
196 	serial_register(&uniphier_serial1_device);
197 #endif
198 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
199 	serial_register(&uniphier_serial2_device);
200 #endif
201 #if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
202 	serial_register(&uniphier_serial3_device);
203 #endif
204 }
205