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