xref: /OK3568_Linux_fs/u-boot/drivers/serial/serial_ns16550.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000
3*4882a593Smuzhiyun  * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <linux/compiler.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <ns16550.h>
12*4882a593Smuzhiyun #ifdef CONFIG_NS87308
13*4882a593Smuzhiyun #include <ns87308.h>
14*4882a593Smuzhiyun #endif
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <serial.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #ifndef CONFIG_NS16550_MIN_FUNCTIONS
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #if !defined(CONFIG_CONS_INDEX)
23*4882a593Smuzhiyun #elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6)
24*4882a593Smuzhiyun #error	"Invalid console index value."
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
28*4882a593Smuzhiyun #error	"Console port 1 defined but not configured."
29*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
30*4882a593Smuzhiyun #error	"Console port 2 defined but not configured."
31*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
32*4882a593Smuzhiyun #error	"Console port 3 defined but not configured."
33*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
34*4882a593Smuzhiyun #error	"Console port 4 defined but not configured."
35*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5)
36*4882a593Smuzhiyun #error	"Console port 5 defined but not configured."
37*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6)
38*4882a593Smuzhiyun #error	"Console port 6 defined but not configured."
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /* Note: The port number specified in the functions is 1 based.
42*4882a593Smuzhiyun  *	 the array is 0 based.
43*4882a593Smuzhiyun  */
44*4882a593Smuzhiyun static NS16550_t serial_ports[6] = {
45*4882a593Smuzhiyun #ifdef CONFIG_SYS_NS16550_COM1
46*4882a593Smuzhiyun 	(NS16550_t)CONFIG_SYS_NS16550_COM1,
47*4882a593Smuzhiyun #else
48*4882a593Smuzhiyun 	NULL,
49*4882a593Smuzhiyun #endif
50*4882a593Smuzhiyun #ifdef CONFIG_SYS_NS16550_COM2
51*4882a593Smuzhiyun 	(NS16550_t)CONFIG_SYS_NS16550_COM2,
52*4882a593Smuzhiyun #else
53*4882a593Smuzhiyun 	NULL,
54*4882a593Smuzhiyun #endif
55*4882a593Smuzhiyun #ifdef CONFIG_SYS_NS16550_COM3
56*4882a593Smuzhiyun 	(NS16550_t)CONFIG_SYS_NS16550_COM3,
57*4882a593Smuzhiyun #else
58*4882a593Smuzhiyun 	NULL,
59*4882a593Smuzhiyun #endif
60*4882a593Smuzhiyun #ifdef CONFIG_SYS_NS16550_COM4
61*4882a593Smuzhiyun 	(NS16550_t)CONFIG_SYS_NS16550_COM4,
62*4882a593Smuzhiyun #else
63*4882a593Smuzhiyun 	NULL,
64*4882a593Smuzhiyun #endif
65*4882a593Smuzhiyun #ifdef CONFIG_SYS_NS16550_COM5
66*4882a593Smuzhiyun 	(NS16550_t)CONFIG_SYS_NS16550_COM5,
67*4882a593Smuzhiyun #else
68*4882a593Smuzhiyun 	NULL,
69*4882a593Smuzhiyun #endif
70*4882a593Smuzhiyun #ifdef CONFIG_SYS_NS16550_COM6
71*4882a593Smuzhiyun 	(NS16550_t)CONFIG_SYS_NS16550_COM6
72*4882a593Smuzhiyun #else
73*4882a593Smuzhiyun 	NULL
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define PORT	serial_ports[port-1]
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* Multi serial device functions */
80*4882a593Smuzhiyun #define DECLARE_ESERIAL_FUNCTIONS(port) \
81*4882a593Smuzhiyun 	static int  eserial##port##_init(void) \
82*4882a593Smuzhiyun 	{ \
83*4882a593Smuzhiyun 		int clock_divisor; \
84*4882a593Smuzhiyun 		clock_divisor = ns16550_calc_divisor(serial_ports[port-1], \
85*4882a593Smuzhiyun 				CONFIG_SYS_NS16550_CLK, gd->baudrate); \
86*4882a593Smuzhiyun 		NS16550_init(serial_ports[port-1], clock_divisor); \
87*4882a593Smuzhiyun 		return 0 ; \
88*4882a593Smuzhiyun 	} \
89*4882a593Smuzhiyun 	static void eserial##port##_setbrg(void) \
90*4882a593Smuzhiyun 	{ \
91*4882a593Smuzhiyun 		serial_setbrg_dev(port); \
92*4882a593Smuzhiyun 	} \
93*4882a593Smuzhiyun 	static int  eserial##port##_getc(void) \
94*4882a593Smuzhiyun 	{ \
95*4882a593Smuzhiyun 		return serial_getc_dev(port); \
96*4882a593Smuzhiyun 	} \
97*4882a593Smuzhiyun 	static int  eserial##port##_tstc(void) \
98*4882a593Smuzhiyun 	{ \
99*4882a593Smuzhiyun 		return serial_tstc_dev(port); \
100*4882a593Smuzhiyun 	} \
101*4882a593Smuzhiyun 	static void eserial##port##_putc(const char c) \
102*4882a593Smuzhiyun 	{ \
103*4882a593Smuzhiyun 		serial_putc_dev(port, c); \
104*4882a593Smuzhiyun 	} \
105*4882a593Smuzhiyun 	static void eserial##port##_puts(const char *s) \
106*4882a593Smuzhiyun 	{ \
107*4882a593Smuzhiyun 		serial_puts_dev(port, s); \
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /* Serial device descriptor */
111*4882a593Smuzhiyun #define INIT_ESERIAL_STRUCTURE(port, __name) {	\
112*4882a593Smuzhiyun 	.name	= __name,			\
113*4882a593Smuzhiyun 	.start	= eserial##port##_init,		\
114*4882a593Smuzhiyun 	.stop	= NULL,				\
115*4882a593Smuzhiyun 	.setbrg	= eserial##port##_setbrg,	\
116*4882a593Smuzhiyun 	.getc	= eserial##port##_getc,		\
117*4882a593Smuzhiyun 	.tstc	= eserial##port##_tstc,		\
118*4882a593Smuzhiyun 	.putc	= eserial##port##_putc,		\
119*4882a593Smuzhiyun 	.puts	= eserial##port##_puts,		\
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
_serial_putc(const char c,const int port)122*4882a593Smuzhiyun static void _serial_putc(const char c, const int port)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	if (c == '\n')
125*4882a593Smuzhiyun 		NS16550_putc(PORT, '\r');
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	NS16550_putc(PORT, c);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
_serial_puts(const char * s,const int port)130*4882a593Smuzhiyun static void _serial_puts(const char *s, const int port)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	while (*s) {
133*4882a593Smuzhiyun 		_serial_putc(*s++, port);
134*4882a593Smuzhiyun 	}
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
_serial_getc(const int port)137*4882a593Smuzhiyun static int _serial_getc(const int port)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	return NS16550_getc(PORT);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
_serial_tstc(const int port)142*4882a593Smuzhiyun static int _serial_tstc(const int port)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	return NS16550_tstc(PORT);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
_serial_setbrg(const int port)147*4882a593Smuzhiyun static void _serial_setbrg(const int port)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	int clock_divisor;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	clock_divisor = ns16550_calc_divisor(PORT, CONFIG_SYS_NS16550_CLK,
152*4882a593Smuzhiyun 					     gd->baudrate);
153*4882a593Smuzhiyun 	NS16550_reinit(PORT, clock_divisor);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun static inline void
serial_putc_dev(unsigned int dev_index,const char c)157*4882a593Smuzhiyun serial_putc_dev(unsigned int dev_index,const char c)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun 	_serial_putc(c,dev_index);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun static inline void
serial_puts_dev(unsigned int dev_index,const char * s)163*4882a593Smuzhiyun serial_puts_dev(unsigned int dev_index,const char *s)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	_serial_puts(s,dev_index);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static inline int
serial_getc_dev(unsigned int dev_index)169*4882a593Smuzhiyun serial_getc_dev(unsigned int dev_index)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	return _serial_getc(dev_index);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun static inline int
serial_tstc_dev(unsigned int dev_index)175*4882a593Smuzhiyun serial_tstc_dev(unsigned int dev_index)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	return _serial_tstc(dev_index);
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun static inline void
serial_setbrg_dev(unsigned int dev_index)181*4882a593Smuzhiyun serial_setbrg_dev(unsigned int dev_index)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	_serial_setbrg(dev_index);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM1)
187*4882a593Smuzhiyun DECLARE_ESERIAL_FUNCTIONS(1);
188*4882a593Smuzhiyun struct serial_device eserial1_device =
189*4882a593Smuzhiyun 	INIT_ESERIAL_STRUCTURE(1, "eserial0");
190*4882a593Smuzhiyun #endif
191*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM2)
192*4882a593Smuzhiyun DECLARE_ESERIAL_FUNCTIONS(2);
193*4882a593Smuzhiyun struct serial_device eserial2_device =
194*4882a593Smuzhiyun 	INIT_ESERIAL_STRUCTURE(2, "eserial1");
195*4882a593Smuzhiyun #endif
196*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM3)
197*4882a593Smuzhiyun DECLARE_ESERIAL_FUNCTIONS(3);
198*4882a593Smuzhiyun struct serial_device eserial3_device =
199*4882a593Smuzhiyun 	INIT_ESERIAL_STRUCTURE(3, "eserial2");
200*4882a593Smuzhiyun #endif
201*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM4)
202*4882a593Smuzhiyun DECLARE_ESERIAL_FUNCTIONS(4);
203*4882a593Smuzhiyun struct serial_device eserial4_device =
204*4882a593Smuzhiyun 	INIT_ESERIAL_STRUCTURE(4, "eserial3");
205*4882a593Smuzhiyun #endif
206*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM5)
207*4882a593Smuzhiyun DECLARE_ESERIAL_FUNCTIONS(5);
208*4882a593Smuzhiyun struct serial_device eserial5_device =
209*4882a593Smuzhiyun 	INIT_ESERIAL_STRUCTURE(5, "eserial4");
210*4882a593Smuzhiyun #endif
211*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM6)
212*4882a593Smuzhiyun DECLARE_ESERIAL_FUNCTIONS(6);
213*4882a593Smuzhiyun struct serial_device eserial6_device =
214*4882a593Smuzhiyun 	INIT_ESERIAL_STRUCTURE(6, "eserial5");
215*4882a593Smuzhiyun #endif
216*4882a593Smuzhiyun 
default_serial_console(void)217*4882a593Smuzhiyun __weak struct serial_device *default_serial_console(void)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun #if CONFIG_CONS_INDEX == 1
220*4882a593Smuzhiyun 	return &eserial1_device;
221*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 2
222*4882a593Smuzhiyun 	return &eserial2_device;
223*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 3
224*4882a593Smuzhiyun 	return &eserial3_device;
225*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 4
226*4882a593Smuzhiyun 	return &eserial4_device;
227*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 5
228*4882a593Smuzhiyun 	return &eserial5_device;
229*4882a593Smuzhiyun #elif CONFIG_CONS_INDEX == 6
230*4882a593Smuzhiyun 	return &eserial6_device;
231*4882a593Smuzhiyun #else
232*4882a593Smuzhiyun #error "Bad CONFIG_CONS_INDEX."
233*4882a593Smuzhiyun #endif
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
ns16550_serial_initialize(void)236*4882a593Smuzhiyun void ns16550_serial_initialize(void)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM1)
239*4882a593Smuzhiyun 	serial_register(&eserial1_device);
240*4882a593Smuzhiyun #endif
241*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM2)
242*4882a593Smuzhiyun 	serial_register(&eserial2_device);
243*4882a593Smuzhiyun #endif
244*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM3)
245*4882a593Smuzhiyun 	serial_register(&eserial3_device);
246*4882a593Smuzhiyun #endif
247*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM4)
248*4882a593Smuzhiyun 	serial_register(&eserial4_device);
249*4882a593Smuzhiyun #endif
250*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM5)
251*4882a593Smuzhiyun 	serial_register(&eserial5_device);
252*4882a593Smuzhiyun #endif
253*4882a593Smuzhiyun #if defined(CONFIG_SYS_NS16550_COM6)
254*4882a593Smuzhiyun 	serial_register(&eserial6_device);
255*4882a593Smuzhiyun #endif
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun #endif /* !CONFIG_NS16550_MIN_FUNCTIONS */
259