xref: /OK3568_Linux_fs/u-boot/drivers/serial/serial-uclass.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2014 The Chromium OS Authors.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <debug_uart.h>
9*4882a593Smuzhiyun #include <dm.h>
10*4882a593Smuzhiyun #include <environment.h>
11*4882a593Smuzhiyun #include <errno.h>
12*4882a593Smuzhiyun #include <os.h>
13*4882a593Smuzhiyun #include <serial.h>
14*4882a593Smuzhiyun #include <stdio_dev.h>
15*4882a593Smuzhiyun #include <watchdog.h>
16*4882a593Smuzhiyun #include <dm/lists.h>
17*4882a593Smuzhiyun #include <dm/device-internal.h>
18*4882a593Smuzhiyun #include <dm/of_access.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #if !CONFIG_VAL(SYS_MALLOC_F_LEN)
23*4882a593Smuzhiyun #error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work"
24*4882a593Smuzhiyun #endif
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #ifndef CONFIG_DEBUG_UART_ALWAYS
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun  * Table with supported baudrates (defined in config_xyz.h)
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
31*4882a593Smuzhiyun 
serial_check_stdout(const void * blob,struct udevice ** devp)32*4882a593Smuzhiyun static int serial_check_stdout(const void *blob, struct udevice **devp)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	int node;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	/* Check for a chosen console */
37*4882a593Smuzhiyun 	node = fdtdec_get_chosen_node(blob, "stdout-path");
38*4882a593Smuzhiyun 	if (node < 0) {
39*4882a593Smuzhiyun 		const char *str, *p, *name;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 		/*
42*4882a593Smuzhiyun 		 * Deal with things like
43*4882a593Smuzhiyun 		 *	stdout-path = "serial0:115200n8";
44*4882a593Smuzhiyun 		 *
45*4882a593Smuzhiyun 		 * We need to look up the alias and then follow it to the
46*4882a593Smuzhiyun 		 * correct node.
47*4882a593Smuzhiyun 		 */
48*4882a593Smuzhiyun 		str = fdtdec_get_chosen_prop(blob, "stdout-path");
49*4882a593Smuzhiyun 		if (str) {
50*4882a593Smuzhiyun 			p = strchr(str, ':');
51*4882a593Smuzhiyun 			name = fdt_get_alias_namelen(blob, str,
52*4882a593Smuzhiyun 					p ? p - str : strlen(str));
53*4882a593Smuzhiyun 			if (name)
54*4882a593Smuzhiyun 				node = fdt_path_offset(blob, name);
55*4882a593Smuzhiyun 		}
56*4882a593Smuzhiyun 	}
57*4882a593Smuzhiyun 	if (node < 0)
58*4882a593Smuzhiyun 		node = fdt_path_offset(blob, "console");
59*4882a593Smuzhiyun 	if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp))
60*4882a593Smuzhiyun 		return 0;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	/*
63*4882a593Smuzhiyun 	 * If the console is not marked to be bound before relocation, bind it
64*4882a593Smuzhiyun 	 * anyway.
65*4882a593Smuzhiyun 	 */
66*4882a593Smuzhiyun 	if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
67*4882a593Smuzhiyun 					devp)) {
68*4882a593Smuzhiyun 		if (!device_probe(*devp))
69*4882a593Smuzhiyun 			return 0;
70*4882a593Smuzhiyun 	}
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	return -ENODEV;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
serial_find_console_or_panic(void)75*4882a593Smuzhiyun static void serial_find_console_or_panic(void)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	const void *blob = gd->fdt_blob;
78*4882a593Smuzhiyun 	struct udevice *dev;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
81*4882a593Smuzhiyun 		uclass_first_device(UCLASS_SERIAL, &dev);
82*4882a593Smuzhiyun 		if (dev) {
83*4882a593Smuzhiyun 			gd->cur_serial_dev = dev;
84*4882a593Smuzhiyun 			return;
85*4882a593Smuzhiyun 		}
86*4882a593Smuzhiyun 	} else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
87*4882a593Smuzhiyun 		/* Live tree has support for stdout */
88*4882a593Smuzhiyun 		if (of_live_active()) {
89*4882a593Smuzhiyun 			struct device_node *np = of_get_stdout();
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 			if (np && !uclass_get_device_by_ofnode(UCLASS_SERIAL,
92*4882a593Smuzhiyun 					np_to_ofnode(np), &dev)) {
93*4882a593Smuzhiyun 				gd->cur_serial_dev = dev;
94*4882a593Smuzhiyun 				return;
95*4882a593Smuzhiyun 			}
96*4882a593Smuzhiyun 		} else {
97*4882a593Smuzhiyun 			if (!serial_check_stdout(blob, &dev)) {
98*4882a593Smuzhiyun 				gd->cur_serial_dev = dev;
99*4882a593Smuzhiyun 				return;
100*4882a593Smuzhiyun 			}
101*4882a593Smuzhiyun 		}
102*4882a593Smuzhiyun 	}
103*4882a593Smuzhiyun 	if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !blob) {
104*4882a593Smuzhiyun 		/*
105*4882a593Smuzhiyun 		 * Try to use CONFIG_CONS_INDEX if available (it is numbered
106*4882a593Smuzhiyun 		 * from 1!).
107*4882a593Smuzhiyun 		 *
108*4882a593Smuzhiyun 		 * Failing that, get the device with sequence number 0, or in
109*4882a593Smuzhiyun 		 * extremis just the first serial device we can find. But we
110*4882a593Smuzhiyun 		 * insist on having a console (even if it is silent).
111*4882a593Smuzhiyun 		 */
112*4882a593Smuzhiyun #ifdef CONFIG_CONS_INDEX
113*4882a593Smuzhiyun #define INDEX (CONFIG_CONS_INDEX - 1)
114*4882a593Smuzhiyun #else
115*4882a593Smuzhiyun #define INDEX 0
116*4882a593Smuzhiyun #endif
117*4882a593Smuzhiyun 		if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
118*4882a593Smuzhiyun 		    !uclass_get_device(UCLASS_SERIAL, INDEX, &dev) ||
119*4882a593Smuzhiyun 		    (!uclass_first_device(UCLASS_SERIAL, &dev) && dev)) {
120*4882a593Smuzhiyun 			gd->cur_serial_dev = dev;
121*4882a593Smuzhiyun 			return;
122*4882a593Smuzhiyun 		}
123*4882a593Smuzhiyun #undef INDEX
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun #ifdef CONFIG_REQUIRE_SERIAL_CONSOLE
127*4882a593Smuzhiyun 	panic_str("No serial driver found");
128*4882a593Smuzhiyun #endif
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun /* Called prior to relocation */
serial_init(void)132*4882a593Smuzhiyun int serial_init(void)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	serial_find_console_or_panic();
135*4882a593Smuzhiyun 	gd->flags |= GD_FLG_SERIAL_READY;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun #else
serial_init(void)140*4882a593Smuzhiyun int serial_init(void) { return 0; }
141*4882a593Smuzhiyun #endif
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /* Called after relocation */
serial_initialize(void)144*4882a593Smuzhiyun void serial_initialize(void)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	serial_init();
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
_serial_putc(struct udevice * dev,char ch)149*4882a593Smuzhiyun static void _serial_putc(struct udevice *dev, char ch)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	struct dm_serial_ops *ops = serial_get_ops(dev);
152*4882a593Smuzhiyun 	int err;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	if (ch == '\n')
155*4882a593Smuzhiyun 		_serial_putc(dev, '\r');
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	do {
158*4882a593Smuzhiyun 		err = ops->putc(dev, ch);
159*4882a593Smuzhiyun 	} while (err == -EAGAIN);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
_serial_puts(struct udevice * dev,const char * str)162*4882a593Smuzhiyun static void _serial_puts(struct udevice *dev, const char *str)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	while (*str)
165*4882a593Smuzhiyun 		_serial_putc(dev, *str++);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
__serial_getc(struct udevice * dev)168*4882a593Smuzhiyun static int __serial_getc(struct udevice *dev)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	struct dm_serial_ops *ops = serial_get_ops(dev);
171*4882a593Smuzhiyun 	int err;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	do {
174*4882a593Smuzhiyun 		err = ops->getc(dev);
175*4882a593Smuzhiyun 		if (err == -EAGAIN)
176*4882a593Smuzhiyun 			WATCHDOG_RESET();
177*4882a593Smuzhiyun 	} while (err == -EAGAIN);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	return err >= 0 ? err : 0;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
__serial_tstc(struct udevice * dev)182*4882a593Smuzhiyun static int __serial_tstc(struct udevice *dev)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	struct dm_serial_ops *ops = serial_get_ops(dev);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	if (ops->pending)
187*4882a593Smuzhiyun 		return ops->pending(dev, true);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	return 1;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
__serial_clear(struct udevice * dev)192*4882a593Smuzhiyun static void __serial_clear(struct udevice *dev)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	struct dm_serial_ops *ops = serial_get_ops(dev);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (ops->clear)
197*4882a593Smuzhiyun 		ops->clear(dev);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
_serial_tstc(struct udevice * dev)201*4882a593Smuzhiyun static int _serial_tstc(struct udevice *dev)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* Read all available chars into the RX buffer */
206*4882a593Smuzhiyun 	while (__serial_tstc(dev)) {
207*4882a593Smuzhiyun 		upriv->buf[upriv->wr_ptr++] = __serial_getc(dev);
208*4882a593Smuzhiyun 		upriv->wr_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
209*4882a593Smuzhiyun 	}
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	return upriv->rd_ptr != upriv->wr_ptr ? 1 : 0;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
_serial_getc(struct udevice * dev)214*4882a593Smuzhiyun static int _serial_getc(struct udevice *dev)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
217*4882a593Smuzhiyun 	char val;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	val = upriv->buf[upriv->rd_ptr++];
220*4882a593Smuzhiyun 	upriv->rd_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	return val;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun #else /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
226*4882a593Smuzhiyun 
_serial_getc(struct udevice * dev)227*4882a593Smuzhiyun static int _serial_getc(struct udevice *dev)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun 	return __serial_getc(dev);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
_serial_tstc(struct udevice * dev)232*4882a593Smuzhiyun static int _serial_tstc(struct udevice *dev)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	return __serial_tstc(dev);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun #endif /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
237*4882a593Smuzhiyun 
serial_putc(char ch)238*4882a593Smuzhiyun void serial_putc(char ch)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	if (gd->cur_serial_dev)
241*4882a593Smuzhiyun 		_serial_putc(gd->cur_serial_dev, ch);
242*4882a593Smuzhiyun 	else
243*4882a593Smuzhiyun 		printch(ch);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
serial_puts(const char * str)246*4882a593Smuzhiyun void serial_puts(const char *str)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun 	if (gd->cur_serial_dev)
249*4882a593Smuzhiyun 		_serial_puts(gd->cur_serial_dev, str);
250*4882a593Smuzhiyun 	else
251*4882a593Smuzhiyun 		printascii(str);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
serial_getc(void)254*4882a593Smuzhiyun int serial_getc(void)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	if (gd->cur_serial_dev)
257*4882a593Smuzhiyun 		return _serial_getc(gd->cur_serial_dev);
258*4882a593Smuzhiyun 	else
259*4882a593Smuzhiyun 		return debug_uart_getc();
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun 
serial_tstc(void)262*4882a593Smuzhiyun int serial_tstc(void)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	if (gd->cur_serial_dev)
265*4882a593Smuzhiyun 		return _serial_tstc(gd->cur_serial_dev);
266*4882a593Smuzhiyun 	else
267*4882a593Smuzhiyun 		return debug_uart_tstc();
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
serial_setbrg(void)270*4882a593Smuzhiyun void serial_setbrg(void)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct dm_serial_ops *ops;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	if (!gd->cur_serial_dev) {
275*4882a593Smuzhiyun 		debug_uart_setbrg();
276*4882a593Smuzhiyun 		return;
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	ops = serial_get_ops(gd->cur_serial_dev);
280*4882a593Smuzhiyun 	if (ops->setbrg)
281*4882a593Smuzhiyun 		ops->setbrg(gd->cur_serial_dev, gd->baudrate);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
serial_clear(void)284*4882a593Smuzhiyun void serial_clear(void)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	if (gd->cur_serial_dev)
287*4882a593Smuzhiyun 		__serial_clear(gd->cur_serial_dev);
288*4882a593Smuzhiyun 	else
289*4882a593Smuzhiyun 		debug_uart_clrc();
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
serial_dev_putc(struct udevice * dev,char ch)292*4882a593Smuzhiyun void serial_dev_putc(struct udevice *dev, char ch)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun 	if (!dev)
295*4882a593Smuzhiyun 		return;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	_serial_putc(dev, ch);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
serial_dev_puts(struct udevice * dev,const char * str)300*4882a593Smuzhiyun void serial_dev_puts(struct udevice *dev, const char *str)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	if (!dev)
303*4882a593Smuzhiyun 		return;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	_serial_puts(dev, str);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
serial_dev_getc(struct udevice * dev)308*4882a593Smuzhiyun int serial_dev_getc(struct udevice *dev)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	if (!dev)
311*4882a593Smuzhiyun 		return 0;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return _serial_getc(dev);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
serial_dev_tstc(struct udevice * dev)316*4882a593Smuzhiyun int serial_dev_tstc(struct udevice *dev)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun 	if (!dev)
319*4882a593Smuzhiyun 		return 0;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	return _serial_tstc(dev);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
serial_dev_setbrg(struct udevice * dev,int baudrate)324*4882a593Smuzhiyun void serial_dev_setbrg(struct udevice *dev, int baudrate)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun 	struct dm_serial_ops *ops;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	if (!dev)
329*4882a593Smuzhiyun 		return;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	ops = serial_get_ops(dev);
332*4882a593Smuzhiyun 	if (ops->setbrg)
333*4882a593Smuzhiyun 		ops->setbrg(dev, baudrate);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
serial_dev_clear(struct udevice * dev)336*4882a593Smuzhiyun void serial_dev_clear(struct udevice *dev)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	if (!dev)
339*4882a593Smuzhiyun 		return;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	__serial_clear(dev);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
serial_stdio_init(void)344*4882a593Smuzhiyun void serial_stdio_init(void)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun #if defined(CONFIG_DM_STDIO)
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(SERIAL_PRESENT)
serial_stub_putc(struct stdio_dev * sdev,const char ch)351*4882a593Smuzhiyun static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	_serial_putc(sdev->priv, ch);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun #endif
356*4882a593Smuzhiyun 
serial_stub_puts(struct stdio_dev * sdev,const char * str)357*4882a593Smuzhiyun static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	_serial_puts(sdev->priv, str);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
serial_stub_getc(struct stdio_dev * sdev)362*4882a593Smuzhiyun static int serial_stub_getc(struct stdio_dev *sdev)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	return _serial_getc(sdev->priv);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
serial_stub_tstc(struct stdio_dev * sdev)367*4882a593Smuzhiyun static int serial_stub_tstc(struct stdio_dev *sdev)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	return _serial_tstc(sdev->priv);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun #endif
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun #ifndef CONFIG_DEBUG_UART_ALWAYS
374*4882a593Smuzhiyun /**
375*4882a593Smuzhiyun  * on_baudrate() - Update the actual baudrate when the env var changes
376*4882a593Smuzhiyun  *
377*4882a593Smuzhiyun  * This will check for a valid baudrate and only apply it if valid.
378*4882a593Smuzhiyun  */
on_baudrate(const char * name,const char * value,enum env_op op,int flags)379*4882a593Smuzhiyun static int on_baudrate(const char *name, const char *value, enum env_op op,
380*4882a593Smuzhiyun 	int flags)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	int i;
383*4882a593Smuzhiyun 	int baudrate;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	switch (op) {
386*4882a593Smuzhiyun 	case env_op_create:
387*4882a593Smuzhiyun 	case env_op_overwrite:
388*4882a593Smuzhiyun 		/*
389*4882a593Smuzhiyun 		 * Switch to new baudrate if new baudrate is supported
390*4882a593Smuzhiyun 		 */
391*4882a593Smuzhiyun 		baudrate = simple_strtoul(value, NULL, 10);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 		/* Not actually changing */
394*4882a593Smuzhiyun 		if (gd->baudrate == baudrate)
395*4882a593Smuzhiyun 			return 0;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
398*4882a593Smuzhiyun 			if (baudrate == baudrate_table[i])
399*4882a593Smuzhiyun 				break;
400*4882a593Smuzhiyun 		}
401*4882a593Smuzhiyun 		if (i == ARRAY_SIZE(baudrate_table)) {
402*4882a593Smuzhiyun 			if ((flags & H_FORCE) == 0)
403*4882a593Smuzhiyun 				printf("## Baudrate %d bps not supported\n",
404*4882a593Smuzhiyun 				       baudrate);
405*4882a593Smuzhiyun 			return 1;
406*4882a593Smuzhiyun 		}
407*4882a593Smuzhiyun 		if ((flags & H_INTERACTIVE) != 0) {
408*4882a593Smuzhiyun 			printf("## Switch baudrate to %d bps and press ENTER ...\n",
409*4882a593Smuzhiyun 			       baudrate);
410*4882a593Smuzhiyun 			udelay(50000);
411*4882a593Smuzhiyun 		}
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 		gd->baudrate = baudrate;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 		serial_setbrg();
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 		udelay(50000);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 		if ((flags & H_INTERACTIVE) != 0)
420*4882a593Smuzhiyun 			while (1) {
421*4882a593Smuzhiyun 				if (getc() == '\r')
422*4882a593Smuzhiyun 					break;
423*4882a593Smuzhiyun 			}
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 		return 0;
426*4882a593Smuzhiyun 	case env_op_delete:
427*4882a593Smuzhiyun 		printf("## Baudrate may not be deleted\n");
428*4882a593Smuzhiyun 		return 1;
429*4882a593Smuzhiyun 	default:
430*4882a593Smuzhiyun 		return 0;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
434*4882a593Smuzhiyun #endif
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(SERIAL_PRESENT)
serial_post_probe(struct udevice * dev)437*4882a593Smuzhiyun static int serial_post_probe(struct udevice *dev)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	struct dm_serial_ops *ops = serial_get_ops(dev);
440*4882a593Smuzhiyun #ifdef CONFIG_DM_STDIO
441*4882a593Smuzhiyun 	struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
442*4882a593Smuzhiyun 	struct stdio_dev sdev;
443*4882a593Smuzhiyun #endif
444*4882a593Smuzhiyun 	int ret;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun #if defined(CONFIG_NEEDS_MANUAL_RELOC)
447*4882a593Smuzhiyun 	if (ops->setbrg)
448*4882a593Smuzhiyun 		ops->setbrg += gd->reloc_off;
449*4882a593Smuzhiyun 	if (ops->getc)
450*4882a593Smuzhiyun 		ops->getc += gd->reloc_off;
451*4882a593Smuzhiyun 	if (ops->putc)
452*4882a593Smuzhiyun 		ops->putc += gd->reloc_off;
453*4882a593Smuzhiyun 	if (ops->pending)
454*4882a593Smuzhiyun 		ops->pending += gd->reloc_off;
455*4882a593Smuzhiyun 	if (ops->clear)
456*4882a593Smuzhiyun 		ops->clear += gd->reloc_off;
457*4882a593Smuzhiyun #if CONFIG_POST & CONFIG_SYS_POST_UART
458*4882a593Smuzhiyun 	if (ops->loop)
459*4882a593Smuzhiyun 		ops->loop += gd->reloc_off
460*4882a593Smuzhiyun #endif
461*4882a593Smuzhiyun #endif
462*4882a593Smuzhiyun 	/* Set the baud rate */
463*4882a593Smuzhiyun 	if (ops->setbrg) {
464*4882a593Smuzhiyun 		ret = ops->setbrg(dev, gd->baudrate);
465*4882a593Smuzhiyun 		if (ret)
466*4882a593Smuzhiyun 			return ret;
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun #ifdef CONFIG_DM_STDIO
470*4882a593Smuzhiyun 	if (!(gd->flags & GD_FLG_RELOC))
471*4882a593Smuzhiyun 		return 0;
472*4882a593Smuzhiyun 	memset(&sdev, '\0', sizeof(sdev));
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	strncpy(sdev.name, dev->name, sizeof(sdev.name));
475*4882a593Smuzhiyun 	sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_DM;
476*4882a593Smuzhiyun 	sdev.priv = dev;
477*4882a593Smuzhiyun 	sdev.putc = serial_stub_putc;
478*4882a593Smuzhiyun 	sdev.puts = serial_stub_puts;
479*4882a593Smuzhiyun 	sdev.getc = serial_stub_getc;
480*4882a593Smuzhiyun 	sdev.tstc = serial_stub_tstc;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
483*4882a593Smuzhiyun 	/* Allocate the RX buffer */
484*4882a593Smuzhiyun 	upriv->buf = malloc(CONFIG_SERIAL_RX_BUFFER_SIZE);
485*4882a593Smuzhiyun #endif
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	stdio_register_dev(&sdev, &upriv->sdev);
488*4882a593Smuzhiyun #endif
489*4882a593Smuzhiyun 	return 0;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
serial_pre_remove(struct udevice * dev)492*4882a593Smuzhiyun static int serial_pre_remove(struct udevice *dev)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
495*4882a593Smuzhiyun 	struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	if (stdio_deregister_dev(upriv->sdev, true))
498*4882a593Smuzhiyun 		return -EPERM;
499*4882a593Smuzhiyun #endif
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	return 0;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun UCLASS_DRIVER(serial) = {
505*4882a593Smuzhiyun 	.id		= UCLASS_SERIAL,
506*4882a593Smuzhiyun 	.name		= "serial",
507*4882a593Smuzhiyun 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
508*4882a593Smuzhiyun 	.post_probe	= serial_post_probe,
509*4882a593Smuzhiyun 	.pre_remove	= serial_pre_remove,
510*4882a593Smuzhiyun 	.per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
511*4882a593Smuzhiyun };
512*4882a593Smuzhiyun #endif
513