blob: ac180029d05c9be2d7b89d4f56a00382a0e556f5 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk91d32562002-09-18 21:21:13 +00002/*
Heiko Schocher3f4978c2012-01-16 21:12:24 +00003 * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net>
4 *
5 * Changes for multibus/multiadapter I2C support.
6 *
wdenk91d32562002-09-18 21:21:13 +00007 * (C) Copyright 2000
8 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
wdenk91d32562002-09-18 21:21:13 +00009 */
10
11#include <config.h>
12#include <common.h>
Simon Glassb206cd72015-10-18 21:17:15 -060013#include <dm.h>
Simon Glassd97143a2014-07-23 06:55:05 -060014#include <errno.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060015#include <log.h>
wdenk91d32562002-09-18 21:21:13 +000016#include <stdarg.h>
17#include <malloc.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020018#include <stdio_dev.h>
wdenk281e00a2004-08-01 22:48:16 +000019#include <serial.h>
Igor Opaniuk5eb83c02019-05-29 09:01:43 +000020#include <splash.h>
wdenk91d32562002-09-18 21:21:13 +000021#include <i2c.h>
Simon Glass401d1c42020-10-30 21:38:53 -060022#include <asm/global_data.h>
Simon Glassb206cd72015-10-18 21:17:15 -060023#include <dm/device-internal.h>
24
Wolfgang Denkd87080b2006-03-31 18:32:53 +020025DECLARE_GLOBAL_DATA_PTR;
26
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020027static struct stdio_dev devs;
benlong.zhou7940f772023-07-21 09:21:09 +080028static int stdio_dev_devs_flag = 0;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020029struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
wdenk91d32562002-09-18 21:21:13 +000030char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
31
Andy Shevchenkod9b0ac92021-02-11 17:09:36 +020032int stdio_file_to_flags(const int file)
33{
34 switch (file) {
35 case stdin:
36 return DEV_FLAGS_INPUT;
37 case stdout:
38 case stderr:
39 return DEV_FLAGS_OUTPUT;
40 default:
41 return -EINVAL;
42 }
43}
44
Andy Shevchenko99cb2b92021-02-11 17:09:35 +020045#if CONFIG_IS_ENABLED(SYS_DEVICE_NULLDEV)
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020046static void nulldev_putc(struct stdio_dev *dev, const char c)
wdenk91d32562002-09-18 21:21:13 +000047{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020048 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000049}
50
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020051static void nulldev_puts(struct stdio_dev *dev, const char *s)
wdenk91d32562002-09-18 21:21:13 +000052{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020053 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000054}
55
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020056static int nulldev_input(struct stdio_dev *dev)
wdenk91d32562002-09-18 21:21:13 +000057{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020058 /* nulldev is empty! */
59 return 0;
wdenk91d32562002-09-18 21:21:13 +000060}
wdenk91d32562002-09-18 21:21:13 +000061
Andy Shevchenko99cb2b92021-02-11 17:09:35 +020062static void nulldev_register(void)
63{
64 struct stdio_dev dev;
65
66 memset(&dev, '\0', sizeof(dev));
67
68 strcpy(dev.name, "nulldev");
69 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
70 dev.putc = nulldev_putc;
71 dev.puts = nulldev_puts;
72 dev.getc = nulldev_input;
73 dev.tstc = nulldev_input;
74
75 stdio_register(&dev);
76}
77#else
78static inline void nulldev_register(void) {}
79#endif /* SYS_DEVICE_NULLDEV */
80
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020081static void stdio_serial_putc(struct stdio_dev *dev, const char c)
Simon Glass709ea542014-07-23 06:54:59 -060082{
83 serial_putc(c);
84}
85
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020086static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
Simon Glass709ea542014-07-23 06:54:59 -060087{
88 serial_puts(s);
89}
90
Pali Rohár78b52432022-09-05 11:31:19 +020091#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
92static void stdio_serial_flush(struct stdio_dev *dev)
93{
94 serial_flush();
95}
96#endif
97
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020098static int stdio_serial_getc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060099{
100 return serial_getc();
101}
102
Jeroen Hofstee654f8d02014-10-08 22:57:44 +0200103static int stdio_serial_tstc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -0600104{
105 return serial_tstc();
106}
107
wdenk91d32562002-09-18 21:21:13 +0000108/**************************************************************************
109 * SYSTEM DRIVERS
110 **************************************************************************
111 */
112
113static void drv_system_init (void)
114{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200115 struct stdio_dev dev;
wdenk91d32562002-09-18 21:21:13 +0000116
117 memset (&dev, 0, sizeof (dev));
118
119 strcpy (dev.name, "serial");
Bin Meng1caf9342015-11-03 23:23:37 -0800120 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
Simon Glass709ea542014-07-23 06:54:59 -0600121 dev.putc = stdio_serial_putc;
122 dev.puts = stdio_serial_puts;
Pali Rohár78b52432022-09-05 11:31:19 +0200123 STDIO_DEV_ASSIGN_FLUSH(&dev, stdio_serial_flush);
Simon Glass709ea542014-07-23 06:54:59 -0600124 dev.getc = stdio_serial_getc;
125 dev.tstc = stdio_serial_tstc;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200126 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +0000127
Andy Shevchenko99cb2b92021-02-11 17:09:35 +0200128 nulldev_register();
wdenk91d32562002-09-18 21:21:13 +0000129}
130
131/**************************************************************************
132 * DEVICES
133 **************************************************************************
134 */
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200135struct list_head* stdio_get_list(void)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200136{
Simon Glass18c587d2020-08-11 11:23:40 -0600137 return &devs.list;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200138}
139
Simon Glassd8441ea2016-10-05 20:42:16 -0600140/**
141 * stdio_probe_device() - Find a device which provides the given stdio device
142 *
143 * This looks for a device of the given uclass which provides a particular
144 * stdio device. It is currently really only useful for UCLASS_VIDEO.
145 *
146 * Ultimately we want to be able to probe a device by its stdio name. At
147 * present devices register in their probe function (for video devices this
148 * is done in vidconsole_post_probe()) and we don't know what name they will
149 * use until they do so.
150 * TODO(sjg@chromium.org): We should be able to determine the name before
151 * probing, and probe the required device.
152 *
153 * @name: stdio device name (e.g. "vidconsole")
154 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
155 * @sdevp: Returns stdout device, if found, else NULL
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100156 * Return: 0 if found, -ENOENT if no device found with that name, other -ve
Simon Glassd8441ea2016-10-05 20:42:16 -0600157 * on other error
158 */
159static int stdio_probe_device(const char *name, enum uclass_id id,
160 struct stdio_dev **sdevp)
161{
162 struct stdio_dev *sdev;
163 struct udevice *dev;
164 int seq, ret;
165
166 *sdevp = NULL;
167 seq = trailing_strtoln(name, NULL);
168 if (seq == -1)
Simon Glassd844efe2016-11-13 14:22:00 -0700169 seq = 0;
170 ret = uclass_get_device_by_seq(id, seq, &dev);
171 if (ret == -ENODEV)
Simon Glassd8441ea2016-10-05 20:42:16 -0600172 ret = uclass_first_device_err(id, &dev);
Simon Glassd8441ea2016-10-05 20:42:16 -0600173 if (ret) {
174 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
175 seq, name);
176 return ret;
177 }
178 /* The device should be be the last one registered */
179 sdev = list_empty(&devs.list) ? NULL :
180 list_last_entry(&devs.list, struct stdio_dev, list);
181 if (!sdev || strcmp(sdev->name, name)) {
182 debug("Device '%s' did not register with stdio as '%s'\n",
183 dev->name, name);
184 return -ENOENT;
185 }
186 *sdevp = sdev;
187
188 return 0;
189}
Simon Glassd8441ea2016-10-05 20:42:16 -0600190
Simon Glassab29a342016-11-13 14:21:59 -0700191struct stdio_dev *stdio_get_by_name(const char *name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200192{
193 struct list_head *pos;
Simon Glassd8441ea2016-10-05 20:42:16 -0600194 struct stdio_dev *sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200195
Simon Glassab29a342016-11-13 14:21:59 -0700196 if (!name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200197 return NULL;
198
Simon Glass18c587d2020-08-11 11:23:40 -0600199 list_for_each(pos, &devs.list) {
Simon Glassd8441ea2016-10-05 20:42:16 -0600200 sdev = list_entry(pos, struct stdio_dev, list);
201 if (strcmp(sdev->name, name) == 0)
202 return sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200203 }
Simon Glassb86986c2022-10-18 07:46:31 -0600204 if (IS_ENABLED(CONFIG_VIDEO)) {
Simon Glass5d4b6b12020-08-11 11:23:39 -0600205 /*
206 * We did not find a suitable stdio device. If there is a video
207 * driver with a name starting with 'vidconsole', we can try
208 * probing that in the hope that it will produce the required
209 * stdio device.
210 *
211 * This function is sometimes called with the entire value of
212 * 'stdout', which may include a list of devices separate by
213 * commas. Obviously this is not going to work, so we ignore
214 * that case. The call path in that case is
Andy Shevchenko32324872020-12-21 14:30:03 +0200215 * console_init_r() -> console_search_dev() -> stdio_get_by_name()
Simon Glass5d4b6b12020-08-11 11:23:39 -0600216 */
217 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
218 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
219 return sdev;
220 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200221
222 return NULL;
223}
224
Simon Glass4225f2f2020-08-11 11:23:41 -0600225struct stdio_dev *stdio_clone(struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200226{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200227 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200228
Simon Glass4225f2f2020-08-11 11:23:41 -0600229 if (!dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200230 return NULL;
231
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200232 _dev = calloc(1, sizeof(struct stdio_dev));
Simon Glass4225f2f2020-08-11 11:23:41 -0600233 if (!_dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200234 return NULL;
235
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200236 memcpy(_dev, dev, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200237
238 return _dev;
239}
wdenk91d32562002-09-18 21:21:13 +0000240
Simon Glassd97143a2014-07-23 06:55:05 -0600241int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
wdenk91d32562002-09-18 21:21:13 +0000242{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200243 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200244
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200245 _dev = stdio_clone(dev);
Simon Glass4225f2f2020-08-11 11:23:41 -0600246 if (!_dev)
Simon Glassd97143a2014-07-23 06:55:05 -0600247 return -ENODEV;
benlong.zhou7940f772023-07-21 09:21:09 +0800248 if (!stdio_dev_devs_flag) {
249 INIT_LIST_HEAD(&(devs.list));
250 stdio_dev_devs_flag = 1;
251 }
Simon Glass18c587d2020-08-11 11:23:40 -0600252 list_add_tail(&_dev->list, &devs.list);
Simon Glassd97143a2014-07-23 06:55:05 -0600253 if (devp)
254 *devp = _dev;
255
wdenk91d32562002-09-18 21:21:13 +0000256 return 0;
257}
258
Simon Glassd97143a2014-07-23 06:55:05 -0600259int stdio_register(struct stdio_dev *dev)
260{
261 return stdio_register_dev(dev, NULL);
262}
263
Hans de Goede32d01922014-09-20 16:54:37 +0200264int stdio_deregister_dev(struct stdio_dev *dev, int force)
wdenk91d32562002-09-18 21:21:13 +0000265{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200266 struct list_head *pos;
Bradley Bolen03bf22f2011-08-22 11:48:05 +0000267 char temp_names[3][16];
Simon Glass4225f2f2020-08-11 11:23:41 -0600268 int i;
wdenk91d32562002-09-18 21:21:13 +0000269
wdenk91d32562002-09-18 21:21:13 +0000270 /* get stdio devices (ListRemoveItem changes the dev list) */
Simon Glass4225f2f2020-08-11 11:23:41 -0600271 for (i = 0 ; i < MAX_FILES; i++) {
272 if (stdio_devices[i] == dev) {
Hans de Goede32d01922014-09-20 16:54:37 +0200273 if (force) {
Simon Glass4225f2f2020-08-11 11:23:41 -0600274 strcpy(temp_names[i], "nulldev");
Hans de Goede32d01922014-09-20 16:54:37 +0200275 continue;
276 }
wdenk91d32562002-09-18 21:21:13 +0000277 /* Device is assigned -> report error */
Simon Glass4225f2f2020-08-11 11:23:41 -0600278 return -EBUSY;
wdenk91d32562002-09-18 21:21:13 +0000279 }
Simon Glass4225f2f2020-08-11 11:23:41 -0600280 memcpy(&temp_names[i][0], stdio_devices[i]->name,
281 sizeof(temp_names[i]));
wdenk91d32562002-09-18 21:21:13 +0000282 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200283
Simon Glass18c587d2020-08-11 11:23:40 -0600284 list_del(&dev->list);
Hans de Goede88274b62014-09-24 14:06:09 +0200285 free(dev);
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200286
Simon Glass4225f2f2020-08-11 11:23:41 -0600287 /* reassign device list */
Simon Glass18c587d2020-08-11 11:23:40 -0600288 list_for_each(pos, &devs.list) {
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200289 dev = list_entry(pos, struct stdio_dev, list);
Simon Glass4225f2f2020-08-11 11:23:41 -0600290 for (i = 0 ; i < MAX_FILES; i++) {
291 if (strcmp(dev->name, temp_names[i]) == 0)
292 stdio_devices[i] = dev;
wdenk91d32562002-09-18 21:21:13 +0000293 }
294 }
Simon Glass4225f2f2020-08-11 11:23:41 -0600295
wdenk91d32562002-09-18 21:21:13 +0000296 return 0;
297}
Simon Glassd97143a2014-07-23 06:55:05 -0600298
Simon Glass9fb02492014-09-03 17:37:01 -0600299int stdio_init_tables(void)
wdenk91d32562002-09-18 21:21:13 +0000300{
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200301#if defined(CONFIG_NEEDS_MANUAL_RELOC)
Peter Tyser521af042009-09-21 11:20:36 -0500302 /* already relocated for current ARM implementation */
wdenk91d32562002-09-18 21:21:13 +0000303 ulong relocation_offset = gd->reloc_off;
wdenk3595ac42003-06-22 17:18:28 +0000304 int i;
wdenk91d32562002-09-18 21:21:13 +0000305
306 /* relocate device name pointers */
307 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
308 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
309 relocation_offset);
310 }
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200311#endif /* CONFIG_NEEDS_MANUAL_RELOC */
wdenk91d32562002-09-18 21:21:13 +0000312
313 /* Initialize the list */
Simon Glass18c587d2020-08-11 11:23:40 -0600314 INIT_LIST_HEAD(&devs.list);
benlong.zhou7940f772023-07-21 09:21:09 +0800315 stdio_dev_devs_flag = 1;
wdenk91d32562002-09-18 21:21:13 +0000316
Simon Glass9fb02492014-09-03 17:37:01 -0600317 return 0;
318}
319
320int stdio_add_devices(void)
321{
Simon Glassb206cd72015-10-18 21:17:15 -0600322 struct udevice *dev;
Simon Glassb206cd72015-10-18 21:17:15 -0600323 int ret;
324
Simon Glass5d4b6b12020-08-11 11:23:39 -0600325 if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
326 /*
327 * For now we probe all the devices here. At some point this
328 * should be done only when the devices are required - e.g. we
329 * have a list of input devices to start up in the stdin
330 * environment variable. That work probably makes more sense
331 * when stdio itself is converted to driver model.
Simon Glass5d4b6b12020-08-11 11:23:39 -0600332 */
Simon Glass5d4b6b12020-08-11 11:23:39 -0600333
334 /*
335 * Don't report errors to the caller - assume that they are
336 * non-fatal
337 */
Michal Suchanek7ff12632022-10-12 21:57:55 +0200338 for (ret = uclass_first_device_check(UCLASS_KEYBOARD, &dev);
339 dev;
340 ret = uclass_next_device_check(&dev)) {
Simon Glass5d4b6b12020-08-11 11:23:39 -0600341 if (ret)
Michal Suchanek7ff12632022-10-12 21:57:55 +0200342 printf("%s: Failed to probe keyboard '%s' (ret=%d)\n",
343 __func__, dev->name, ret);
Simon Glass5d4b6b12020-08-11 11:23:39 -0600344 }
Simon Glassb206cd72015-10-18 21:17:15 -0600345 }
Tom Rini55dabcc2021-08-18 23:12:24 -0400346#if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000347 i2c_init_all();
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000348#endif
Simon Glassb86986c2022-10-18 07:46:31 -0600349 if (IS_ENABLED(CONFIG_VIDEO)) {
Simon Glass5d4b6b12020-08-11 11:23:39 -0600350 /*
351 * If the console setting is not in environment variables then
352 * console_init_r() will not be calling iomux_doenv() (which
Andy Shevchenko32324872020-12-21 14:30:03 +0200353 * calls console_search_dev()). So we will not dynamically add
Simon Glass5d4b6b12020-08-11 11:23:39 -0600354 * devices by calling stdio_probe_device().
355 *
356 * So just probe all video devices now so that whichever one is
357 * required will be available.
358 */
359 struct udevice *vdev;
360 int ret;
Simon Glasse3b81c12016-01-18 19:52:23 -0700361
Simon Glass5d4b6b12020-08-11 11:23:39 -0600362 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
Michal Suchanek7ff12632022-10-12 21:57:55 +0200363 for (ret = uclass_first_device_check(UCLASS_VIDEO,
364 &vdev);
365 vdev;
366 ret = uclass_next_device_check(&vdev)) {
367 if (ret)
368 printf("%s: Failed to probe video device '%s' (ret=%d)\n",
369 __func__, vdev->name, ret);
370 }
Simon Glass5d4b6b12020-08-11 11:23:39 -0600371 }
372 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
373 IS_ENABLED(CONFIG_CMD_BMP))
374 splash_display();
Simon Glass5d4b6b12020-08-11 11:23:39 -0600375 }
376
Simon Glass5d4b6b12020-08-11 11:23:39 -0600377 drv_system_init();
378 serial_stdio_init();
wdenk232c1502004-03-12 00:14:09 +0000379#ifdef CONFIG_USB_TTY
Simon Glass5d4b6b12020-08-11 11:23:39 -0600380 drv_usbtty_init();
wdenk232c1502004-03-12 00:14:09 +0000381#endif
Loic Poulainfc2b3992021-11-25 18:16:15 +0100382#ifdef CONFIG_USB_FUNCTION_ACM
383 drv_usbacm_init ();
384#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600385 if (IS_ENABLED(CONFIG_NETCONSOLE))
386 drv_nc_init();
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400387#ifdef CONFIG_JTAG_CONSOLE
Simon Glass5d4b6b12020-08-11 11:23:39 -0600388 drv_jtag_console_init();
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400389#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600390 if (IS_ENABLED(CONFIG_CBMEM_CONSOLE))
391 cbmemc_init();
Simon Glass9fb02492014-09-03 17:37:01 -0600392
393 return 0;
394}
395
396int stdio_init(void)
397{
398 stdio_init_tables();
399 stdio_add_devices();
400
401 return 0;
wdenk91d32562002-09-18 21:21:13 +0000402}