]> git.sur5r.net Git - u-boot/blob - common/stdio.c
log: Add a test command
[u-boot] / common / stdio.c
1 /*
2  * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net>
3  *
4  * Changes for multibus/multiadapter I2C support.
5  *
6  * (C) Copyright 2000
7  * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include <config.h>
13 #include <common.h>
14 #include <dm.h>
15 #include <errno.h>
16 #include <stdarg.h>
17 #include <malloc.h>
18 #include <stdio_dev.h>
19 #include <serial.h>
20
21 #if defined(CONFIG_SYS_I2C)
22 #include <i2c.h>
23 #endif
24
25 #include <dm/device-internal.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 static struct stdio_dev devs;
30 struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
31 char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
32
33 #if defined(CONFIG_SPLASH_SCREEN) && !defined(CONFIG_SYS_DEVICE_NULLDEV)
34 #define CONFIG_SYS_DEVICE_NULLDEV       1
35 #endif
36
37 #if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
38 #define CONFIG_SYS_DEVICE_NULLDEV       1
39 #endif
40
41 #ifdef CONFIG_SYS_DEVICE_NULLDEV
42 static void nulldev_putc(struct stdio_dev *dev, const char c)
43 {
44         /* nulldev is empty! */
45 }
46
47 static void nulldev_puts(struct stdio_dev *dev, const char *s)
48 {
49         /* nulldev is empty! */
50 }
51
52 static int nulldev_input(struct stdio_dev *dev)
53 {
54         /* nulldev is empty! */
55         return 0;
56 }
57 #endif
58
59 static void stdio_serial_putc(struct stdio_dev *dev, const char c)
60 {
61         serial_putc(c);
62 }
63
64 static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
65 {
66         serial_puts(s);
67 }
68
69 static int stdio_serial_getc(struct stdio_dev *dev)
70 {
71         return serial_getc();
72 }
73
74 static int stdio_serial_tstc(struct stdio_dev *dev)
75 {
76         return serial_tstc();
77 }
78
79 /**************************************************************************
80  * SYSTEM DRIVERS
81  **************************************************************************
82  */
83
84 static void drv_system_init (void)
85 {
86         struct stdio_dev dev;
87
88         memset (&dev, 0, sizeof (dev));
89
90         strcpy (dev.name, "serial");
91         dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
92         dev.putc = stdio_serial_putc;
93         dev.puts = stdio_serial_puts;
94         dev.getc = stdio_serial_getc;
95         dev.tstc = stdio_serial_tstc;
96         stdio_register (&dev);
97
98 #ifdef CONFIG_SYS_DEVICE_NULLDEV
99         memset (&dev, 0, sizeof (dev));
100
101         strcpy (dev.name, "nulldev");
102         dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
103         dev.putc = nulldev_putc;
104         dev.puts = nulldev_puts;
105         dev.getc = nulldev_input;
106         dev.tstc = nulldev_input;
107
108         stdio_register (&dev);
109 #endif
110 }
111
112 /**************************************************************************
113  * DEVICES
114  **************************************************************************
115  */
116 struct list_head* stdio_get_list(void)
117 {
118         return &(devs.list);
119 }
120
121 #ifdef CONFIG_DM_VIDEO
122 /**
123  * stdio_probe_device() - Find a device which provides the given stdio device
124  *
125  * This looks for a device of the given uclass which provides a particular
126  * stdio device. It is currently really only useful for UCLASS_VIDEO.
127  *
128  * Ultimately we want to be able to probe a device by its stdio name. At
129  * present devices register in their probe function (for video devices this
130  * is done in vidconsole_post_probe()) and we don't know what name they will
131  * use until they do so.
132  * TODO(sjg@chromium.org): We should be able to determine the name before
133  * probing, and probe the required device.
134  *
135  * @name:       stdio device name (e.g. "vidconsole")
136  * id:          Uclass ID of device to look for (e.g. UCLASS_VIDEO)
137  * @sdevp:      Returns stdout device, if found, else NULL
138  * @return 0 if found, -ENOENT if no device found with that name, other -ve
139  *         on other error
140  */
141 static int stdio_probe_device(const char *name, enum uclass_id id,
142                               struct stdio_dev **sdevp)
143 {
144         struct stdio_dev *sdev;
145         struct udevice *dev;
146         int seq, ret;
147
148         *sdevp = NULL;
149         seq = trailing_strtoln(name, NULL);
150         if (seq == -1)
151                 seq = 0;
152         ret = uclass_get_device_by_seq(id, seq, &dev);
153         if (ret == -ENODEV)
154                 ret = uclass_first_device_err(id, &dev);
155         if (ret) {
156                 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
157                       seq, name);
158                 return ret;
159         }
160         /* The device should be be the last one registered */
161         sdev = list_empty(&devs.list) ? NULL :
162                         list_last_entry(&devs.list, struct stdio_dev, list);
163         if (!sdev || strcmp(sdev->name, name)) {
164                 debug("Device '%s' did not register with stdio as '%s'\n",
165                       dev->name, name);
166                 return -ENOENT;
167         }
168         *sdevp = sdev;
169
170         return 0;
171 }
172 #endif
173
174 struct stdio_dev *stdio_get_by_name(const char *name)
175 {
176         struct list_head *pos;
177         struct stdio_dev *sdev;
178
179         if (!name)
180                 return NULL;
181
182         list_for_each(pos, &(devs.list)) {
183                 sdev = list_entry(pos, struct stdio_dev, list);
184                 if (strcmp(sdev->name, name) == 0)
185                         return sdev;
186         }
187 #ifdef CONFIG_DM_VIDEO
188         /*
189          * We did not find a suitable stdio device. If there is a video
190          * driver with a name starting with 'vidconsole', we can try probing
191          * that in the hope that it will produce the required stdio device.
192          *
193          * This function is sometimes called with the entire value of
194          * 'stdout', which may include a list of devices separate by commas.
195          * Obviously this is not going to work, so we ignore that case. The
196          * call path in that case is console_init_r() -> search_device() ->
197          * stdio_get_by_name().
198          */
199         if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
200             !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
201                 return sdev;
202 #endif
203
204         return NULL;
205 }
206
207 struct stdio_dev* stdio_clone(struct stdio_dev *dev)
208 {
209         struct stdio_dev *_dev;
210
211         if(!dev)
212                 return NULL;
213
214         _dev = calloc(1, sizeof(struct stdio_dev));
215
216         if(!_dev)
217                 return NULL;
218
219         memcpy(_dev, dev, sizeof(struct stdio_dev));
220
221         return _dev;
222 }
223
224 int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
225 {
226         struct stdio_dev *_dev;
227
228         _dev = stdio_clone(dev);
229         if(!_dev)
230                 return -ENODEV;
231         list_add_tail(&(_dev->list), &(devs.list));
232         if (devp)
233                 *devp = _dev;
234
235         return 0;
236 }
237
238 int stdio_register(struct stdio_dev *dev)
239 {
240         return stdio_register_dev(dev, NULL);
241 }
242
243 /* deregister the device "devname".
244  * returns 0 if success, -1 if device is assigned and 1 if devname not found
245  */
246 #if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
247 int stdio_deregister_dev(struct stdio_dev *dev, int force)
248 {
249         int l;
250         struct list_head *pos;
251         char temp_names[3][16];
252
253         /* get stdio devices (ListRemoveItem changes the dev list) */
254         for (l=0 ; l< MAX_FILES; l++) {
255                 if (stdio_devices[l] == dev) {
256                         if (force) {
257                                 strcpy(temp_names[l], "nulldev");
258                                 continue;
259                         }
260                         /* Device is assigned -> report error */
261                         return -1;
262                 }
263                 memcpy (&temp_names[l][0],
264                         stdio_devices[l]->name,
265                         sizeof(temp_names[l]));
266         }
267
268         list_del(&(dev->list));
269         free(dev);
270
271         /* reassign Device list */
272         list_for_each(pos, &(devs.list)) {
273                 dev = list_entry(pos, struct stdio_dev, list);
274                 for (l=0 ; l< MAX_FILES; l++) {
275                         if(strcmp(dev->name, temp_names[l]) == 0)
276                                 stdio_devices[l] = dev;
277                 }
278         }
279         return 0;
280 }
281
282 int stdio_deregister(const char *devname, int force)
283 {
284         struct stdio_dev *dev;
285
286         dev = stdio_get_by_name(devname);
287
288         if (!dev) /* device not found */
289                 return -ENODEV;
290
291         return stdio_deregister_dev(dev, force);
292 }
293 #endif /* CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) */
294
295 int stdio_init_tables(void)
296 {
297 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
298         /* already relocated for current ARM implementation */
299         ulong relocation_offset = gd->reloc_off;
300         int i;
301
302         /* relocate device name pointers */
303         for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
304                 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
305                                                 relocation_offset);
306         }
307 #endif /* CONFIG_NEEDS_MANUAL_RELOC */
308
309         /* Initialize the list */
310         INIT_LIST_HEAD(&(devs.list));
311
312         return 0;
313 }
314
315 int stdio_add_devices(void)
316 {
317 #ifdef CONFIG_DM_KEYBOARD
318         struct udevice *dev;
319         struct uclass *uc;
320         int ret;
321
322         /*
323          * For now we probe all the devices here. At some point this should be
324          * done only when the devices are required - e.g. we have a list of
325          * input devices to start up in the stdin environment variable. That
326          * work probably makes more sense when stdio itself is converted to
327          * driver model.
328          *
329          * TODO(sjg@chromium.org): Convert changing uclass_first_device() etc.
330          * to return the device even on error. Then we could use that here.
331          */
332         ret = uclass_get(UCLASS_KEYBOARD, &uc);
333         if (ret)
334                 return ret;
335
336         /* Don't report errors to the caller - assume that they are non-fatal */
337         uclass_foreach_dev(dev, uc) {
338                 ret = device_probe(dev);
339                 if (ret)
340                         printf("Failed to probe keyboard '%s'\n", dev->name);
341         }
342 #endif
343 #ifdef CONFIG_SYS_I2C
344         i2c_init_all();
345 #else
346 #endif
347 #ifdef CONFIG_DM_VIDEO
348         /*
349          * If the console setting is not in environment variables then
350          * console_init_r() will not be calling iomux_doenv() (which calls
351          * search_device()). So we will not dynamically add devices by
352          * calling stdio_probe_device().
353          *
354          * So just probe all video devices now so that whichever one is
355          * required will be available.
356          */
357 #ifndef CONFIG_SYS_CONSOLE_IS_IN_ENV
358         struct udevice *vdev;
359 # ifndef CONFIG_DM_KEYBOARD
360         int ret;
361 # endif
362
363         for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
364              vdev;
365              ret = uclass_next_device(&vdev))
366                 ;
367         if (ret)
368                 printf("%s: Video device failed (ret=%d)\n", __func__, ret);
369 #endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */
370 #else
371 # if defined(CONFIG_LCD)
372         drv_lcd_init ();
373 # endif
374 # if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
375         drv_video_init ();
376 # endif
377 #endif /* CONFIG_DM_VIDEO */
378 #if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
379         drv_keyboard_init ();
380 #endif
381         drv_system_init ();
382         serial_stdio_init ();
383 #ifdef CONFIG_USB_TTY
384         drv_usbtty_init ();
385 #endif
386 #ifdef CONFIG_NETCONSOLE
387         drv_nc_init ();
388 #endif
389 #ifdef CONFIG_JTAG_CONSOLE
390         drv_jtag_console_init ();
391 #endif
392 #ifdef CONFIG_CBMEM_CONSOLE
393         cbmemc_init();
394 #endif
395
396         return 0;
397 }
398
399 int stdio_init(void)
400 {
401         stdio_init_tables();
402         stdio_add_devices();
403
404         return 0;
405 }