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