xref: /openbmc/u-boot/drivers/serial/serial.c (revision af2a4093)
1 /*
2  * (C) Copyright 2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 #include <serial.h>
26 #include <stdio_dev.h>
27 #include <post.h>
28 #include <linux/compiler.h>
29 
30 DECLARE_GLOBAL_DATA_PTR;
31 
32 static struct serial_device *serial_devices;
33 static struct serial_device *serial_current;
34 
35 static void serial_null(void)
36 {
37 }
38 
39 #define serial_initfunc(name)					\
40 	void name(void)						\
41 		__attribute__((weak, alias("serial_null")));
42 
43 serial_initfunc(mpc8xx_serial_initialize);
44 serial_initfunc(ns16550_serial_initialize);
45 serial_initfunc(pxa_serial_initialize);
46 serial_initfunc(s3c24xx_serial_initialize);
47 serial_initfunc(s5p_serial_initialize);
48 serial_initfunc(zynq_serial_initalize);
49 serial_initfunc(bfin_serial_initialize);
50 serial_initfunc(bfin_jtag_initialize);
51 serial_initfunc(mpc512x_serial_initialize);
52 serial_initfunc(uartlite_serial_initialize);
53 serial_initfunc(au1x00_serial_initialize);
54 serial_initfunc(asc_serial_initialize);
55 serial_initfunc(jz_serial_initialize);
56 serial_initfunc(mpc5xx_serial_initialize);
57 serial_initfunc(mpc8220_serial_initialize);
58 serial_initfunc(mpc8260_scc_serial_initialize);
59 serial_initfunc(mpc8260_smc_serial_initialize);
60 serial_initfunc(mpc85xx_serial_initialize);
61 serial_initfunc(iop480_serial_initialize);
62 serial_initfunc(leon2_serial_initialize);
63 serial_initfunc(leon3_serial_initialize);
64 serial_initfunc(marvell_serial_initialize);
65 serial_initfunc(amirix_serial_initialize);
66 serial_initfunc(bmw_serial_initialize);
67 serial_initfunc(cogent_serial_initialize);
68 serial_initfunc(cpci750_serial_initialize);
69 serial_initfunc(evb64260_serial_initialize);
70 serial_initfunc(ml2_serial_initialize);
71 serial_initfunc(sconsole_serial_initialize);
72 serial_initfunc(p3mx_serial_initialize);
73 serial_initfunc(altera_jtag_serial_initialize);
74 serial_initfunc(altera_serial_initialize);
75 serial_initfunc(atmel_serial_initialize);
76 serial_initfunc(lpc32xx_serial_initialize);
77 serial_initfunc(mcf_serial_initialize);
78 serial_initfunc(ns9750_serial_initialize);
79 serial_initfunc(oc_serial_initialize);
80 serial_initfunc(s3c4510b_serial_initialize);
81 serial_initfunc(s3c64xx_serial_initialize);
82 serial_initfunc(sandbox_serial_initialize);
83 serial_initfunc(clps7111_serial_initialize);
84 serial_initfunc(imx_serial_initialize);
85 serial_initfunc(ixp_serial_initialize);
86 serial_initfunc(ks8695_serial_initialize);
87 serial_initfunc(lh7a40x_serial_initialize);
88 serial_initfunc(lpc2292_serial_initialize);
89 serial_initfunc(max3100_serial_initialize);
90 serial_initfunc(mxc_serial_initialize);
91 serial_initfunc(netarm_serial_initialize);
92 serial_initfunc(pl01x_serial_initialize);
93 serial_initfunc(s3c44b0_serial_initialize);
94 serial_initfunc(sa1100_serial_initialize);
95 serial_initfunc(sh_serial_initialize);
96 
97 void serial_register(struct serial_device *dev)
98 {
99 #ifdef CONFIG_NEEDS_MANUAL_RELOC
100 	if (dev->start)
101 		dev->start += gd->reloc_off;
102 	if (dev->stop)
103 		dev->stop += gd->reloc_off;
104 	if (dev->setbrg)
105 		dev->setbrg += gd->reloc_off;
106 	if (dev->getc)
107 		dev->getc += gd->reloc_off;
108 	if (dev->tstc)
109 		dev->tstc += gd->reloc_off;
110 	if (dev->putc)
111 		dev->putc += gd->reloc_off;
112 	if (dev->puts)
113 		dev->puts += gd->reloc_off;
114 #endif
115 
116 	dev->next = serial_devices;
117 	serial_devices = dev;
118 }
119 
120 void serial_initialize(void)
121 {
122 	mpc8xx_serial_initialize();
123 	ns16550_serial_initialize();
124 	pxa_serial_initialize();
125 	s3c24xx_serial_initialize();
126 	s5p_serial_initialize();
127 	mpc512x_serial_initialize();
128 	bfin_serial_initialize();
129 	bfin_jtag_initialize();
130 	uartlite_serial_initialize();
131 	zynq_serial_initalize();
132 	au1x00_serial_initialize();
133 	asc_serial_initialize();
134 	jz_serial_initialize();
135 	mpc5xx_serial_initialize();
136 	mpc8220_serial_initialize();
137 	mpc8260_scc_serial_initialize();
138 	mpc8260_smc_serial_initialize();
139 	mpc85xx_serial_initialize();
140 	iop480_serial_initialize();
141 	leon2_serial_initialize();
142 	leon3_serial_initialize();
143 	marvell_serial_initialize();
144 	amirix_serial_initialize();
145 	bmw_serial_initialize();
146 	cogent_serial_initialize();
147 	cpci750_serial_initialize();
148 	evb64260_serial_initialize();
149 	ml2_serial_initialize();
150 	sconsole_serial_initialize();
151 	p3mx_serial_initialize();
152 	altera_jtag_serial_initialize();
153 	altera_serial_initialize();
154 	atmel_serial_initialize();
155 	lpc32xx_serial_initialize();
156 	mcf_serial_initialize();
157 	ns9750_serial_initialize();
158 	oc_serial_initialize();
159 	s3c4510b_serial_initialize();
160 	s3c64xx_serial_initialize();
161 	sandbox_serial_initialize();
162 	clps7111_serial_initialize();
163 	imx_serial_initialize();
164 	ixp_serial_initialize();
165 	ks8695_serial_initialize();
166 	lh7a40x_serial_initialize();
167 	lpc2292_serial_initialize();
168 	max3100_serial_initialize();
169 	mxc_serial_initialize();
170 	netarm_serial_initialize();
171 	pl01x_serial_initialize();
172 	s3c44b0_serial_initialize();
173 	sa1100_serial_initialize();
174 	sh_serial_initialize();
175 
176 	serial_assign(default_serial_console()->name);
177 }
178 
179 void serial_stdio_init(void)
180 {
181 	struct stdio_dev dev;
182 	struct serial_device *s = serial_devices;
183 
184 	while (s) {
185 		memset(&dev, 0, sizeof(dev));
186 
187 		strcpy(dev.name, s->name);
188 		dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
189 
190 		dev.start = s->start;
191 		dev.stop = s->stop;
192 		dev.putc = s->putc;
193 		dev.puts = s->puts;
194 		dev.getc = s->getc;
195 		dev.tstc = s->tstc;
196 
197 		stdio_register(&dev);
198 
199 		s = s->next;
200 	}
201 }
202 
203 int serial_assign(const char *name)
204 {
205 	struct serial_device *s;
206 
207 	for (s = serial_devices; s; s = s->next) {
208 		if (strcmp(s->name, name) == 0) {
209 			serial_current = s;
210 			return 0;
211 		}
212 	}
213 
214 	return 1;
215 }
216 
217 void serial_reinit_all(void)
218 {
219 	struct serial_device *s;
220 
221 	for (s = serial_devices; s; s = s->next)
222 		s->start();
223 }
224 
225 static struct serial_device *get_current(void)
226 {
227 	struct serial_device *dev;
228 
229 	if (!(gd->flags & GD_FLG_RELOC) || !serial_current) {
230 		dev = default_serial_console();
231 
232 		/* We must have a console device */
233 		if (!dev) {
234 #ifdef CONFIG_SPL_BUILD
235 			puts("Cannot find console\n");
236 			hang();
237 #else
238 			panic("Cannot find console\n");
239 #endif
240 		}
241 	} else
242 		dev = serial_current;
243 	return dev;
244 }
245 
246 int serial_init(void)
247 {
248 	return get_current()->start();
249 }
250 
251 void serial_setbrg(void)
252 {
253 	get_current()->setbrg();
254 }
255 
256 int serial_getc(void)
257 {
258 	return get_current()->getc();
259 }
260 
261 int serial_tstc(void)
262 {
263 	return get_current()->tstc();
264 }
265 
266 void serial_putc(const char c)
267 {
268 	get_current()->putc(c);
269 }
270 
271 void serial_puts(const char *s)
272 {
273 	get_current()->puts(s);
274 }
275 
276 #if CONFIG_POST & CONFIG_SYS_POST_UART
277 static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE;
278 
279 /* Mark weak until post/cpu/.../uart.c migrate over */
280 __weak
281 int uart_post_test(int flags)
282 {
283 	unsigned char c;
284 	int ret, saved_baud, b;
285 	struct serial_device *saved_dev, *s;
286 	bd_t *bd = gd->bd;
287 
288 	/* Save current serial state */
289 	ret = 0;
290 	saved_dev = serial_current;
291 	saved_baud = bd->bi_baudrate;
292 
293 	for (s = serial_devices; s; s = s->next) {
294 		/* If this driver doesn't support loop back, skip it */
295 		if (!s->loop)
296 			continue;
297 
298 		/* Test the next device */
299 		serial_current = s;
300 
301 		ret = serial_init();
302 		if (ret)
303 			goto done;
304 
305 		/* Consume anything that happens to be queued */
306 		while (serial_tstc())
307 			serial_getc();
308 
309 		/* Enable loop back */
310 		s->loop(1);
311 
312 		/* Test every available baud rate */
313 		for (b = 0; b < ARRAY_SIZE(bauds); ++b) {
314 			bd->bi_baudrate = bauds[b];
315 			serial_setbrg();
316 
317 			/*
318 			 * Stick to printable chars to avoid issues:
319 			 *  - terminal corruption
320 			 *  - serial program reacting to sequences and sending
321 			 *    back random extra data
322 			 *  - most serial drivers add in extra chars (like \r\n)
323 			 */
324 			for (c = 0x20; c < 0x7f; ++c) {
325 				/* Send it out */
326 				serial_putc(c);
327 
328 				/* Make sure it's the same one */
329 				ret = (c != serial_getc());
330 				if (ret) {
331 					s->loop(0);
332 					goto done;
333 				}
334 
335 				/* Clean up the output in case it was sent */
336 				serial_putc('\b');
337 				ret = ('\b' != serial_getc());
338 				if (ret) {
339 					s->loop(0);
340 					goto done;
341 				}
342 			}
343 		}
344 
345 		/* Disable loop back */
346 		s->loop(0);
347 
348 		/* XXX: There is no serial_stop() !? */
349 		if (s->stop)
350 			s->stop();
351 	}
352 
353  done:
354 	/* Restore previous serial state */
355 	serial_current = saved_dev;
356 	bd->bi_baudrate = saved_baud;
357 	serial_reinit_all();
358 	serial_setbrg();
359 
360 	return ret;
361 }
362 #endif
363