blob: 1921dc671946c4ac17862dc2d7c314107566de55 [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>
22
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;
28struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
wdenk91d32562002-09-18 21:21:13 +000029char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
30
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020031static void nulldev_putc(struct stdio_dev *dev, const char c)
wdenk91d32562002-09-18 21:21:13 +000032{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020033 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000034}
35
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020036static void nulldev_puts(struct stdio_dev *dev, const char *s)
wdenk91d32562002-09-18 21:21:13 +000037{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020038 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000039}
40
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020041static int nulldev_input(struct stdio_dev *dev)
wdenk91d32562002-09-18 21:21:13 +000042{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020043 /* nulldev is empty! */
44 return 0;
wdenk91d32562002-09-18 21:21:13 +000045}
wdenk91d32562002-09-18 21:21:13 +000046
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020047static void stdio_serial_putc(struct stdio_dev *dev, const char c)
Simon Glass709ea542014-07-23 06:54:59 -060048{
49 serial_putc(c);
50}
51
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020052static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
Simon Glass709ea542014-07-23 06:54:59 -060053{
54 serial_puts(s);
55}
56
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020057static int stdio_serial_getc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060058{
59 return serial_getc();
60}
61
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020062static int stdio_serial_tstc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060063{
64 return serial_tstc();
65}
66
wdenk91d32562002-09-18 21:21:13 +000067/**************************************************************************
68 * SYSTEM DRIVERS
69 **************************************************************************
70 */
71
72static void drv_system_init (void)
73{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020074 struct stdio_dev dev;
wdenk91d32562002-09-18 21:21:13 +000075
76 memset (&dev, 0, sizeof (dev));
77
78 strcpy (dev.name, "serial");
Bin Meng1caf9342015-11-03 23:23:37 -080079 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
Simon Glass709ea542014-07-23 06:54:59 -060080 dev.putc = stdio_serial_putc;
81 dev.puts = stdio_serial_puts;
82 dev.getc = stdio_serial_getc;
83 dev.tstc = stdio_serial_tstc;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020084 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +000085
Simon Glass3ca06092020-08-11 11:23:37 -060086 if (CONFIG_IS_ENABLED(SYS_DEVICE_NULLDEV)) {
87 memset(&dev, '\0', sizeof(dev));
wdenk91d32562002-09-18 21:21:13 +000088
Simon Glass3ca06092020-08-11 11:23:37 -060089 strcpy(dev.name, "nulldev");
90 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
91 dev.putc = nulldev_putc;
92 dev.puts = nulldev_puts;
93 dev.getc = nulldev_input;
94 dev.tstc = nulldev_input;
wdenk91d32562002-09-18 21:21:13 +000095
Simon Glass3ca06092020-08-11 11:23:37 -060096 stdio_register(&dev);
97 }
wdenk91d32562002-09-18 21:21:13 +000098}
99
100/**************************************************************************
101 * DEVICES
102 **************************************************************************
103 */
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200104struct list_head* stdio_get_list(void)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200105{
106 return &(devs.list);
107}
108
Simon Glassd8441ea2016-10-05 20:42:16 -0600109/**
110 * stdio_probe_device() - Find a device which provides the given stdio device
111 *
112 * This looks for a device of the given uclass which provides a particular
113 * stdio device. It is currently really only useful for UCLASS_VIDEO.
114 *
115 * Ultimately we want to be able to probe a device by its stdio name. At
116 * present devices register in their probe function (for video devices this
117 * is done in vidconsole_post_probe()) and we don't know what name they will
118 * use until they do so.
119 * TODO(sjg@chromium.org): We should be able to determine the name before
120 * probing, and probe the required device.
121 *
122 * @name: stdio device name (e.g. "vidconsole")
123 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
124 * @sdevp: Returns stdout device, if found, else NULL
125 * @return 0 if found, -ENOENT if no device found with that name, other -ve
126 * on other error
127 */
128static int stdio_probe_device(const char *name, enum uclass_id id,
129 struct stdio_dev **sdevp)
130{
131 struct stdio_dev *sdev;
132 struct udevice *dev;
133 int seq, ret;
134
135 *sdevp = NULL;
136 seq = trailing_strtoln(name, NULL);
137 if (seq == -1)
Simon Glassd844efe2016-11-13 14:22:00 -0700138 seq = 0;
139 ret = uclass_get_device_by_seq(id, seq, &dev);
140 if (ret == -ENODEV)
Simon Glassd8441ea2016-10-05 20:42:16 -0600141 ret = uclass_first_device_err(id, &dev);
Simon Glassd8441ea2016-10-05 20:42:16 -0600142 if (ret) {
143 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
144 seq, name);
145 return ret;
146 }
147 /* The device should be be the last one registered */
148 sdev = list_empty(&devs.list) ? NULL :
149 list_last_entry(&devs.list, struct stdio_dev, list);
150 if (!sdev || strcmp(sdev->name, name)) {
151 debug("Device '%s' did not register with stdio as '%s'\n",
152 dev->name, name);
153 return -ENOENT;
154 }
155 *sdevp = sdev;
156
157 return 0;
158}
Simon Glassd8441ea2016-10-05 20:42:16 -0600159
Simon Glassab29a342016-11-13 14:21:59 -0700160struct stdio_dev *stdio_get_by_name(const char *name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200161{
162 struct list_head *pos;
Simon Glassd8441ea2016-10-05 20:42:16 -0600163 struct stdio_dev *sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200164
Simon Glassab29a342016-11-13 14:21:59 -0700165 if (!name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200166 return NULL;
167
168 list_for_each(pos, &(devs.list)) {
Simon Glassd8441ea2016-10-05 20:42:16 -0600169 sdev = list_entry(pos, struct stdio_dev, list);
170 if (strcmp(sdev->name, name) == 0)
171 return sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200172 }
Simon Glass5d4b6b12020-08-11 11:23:39 -0600173 if (IS_ENABLED(CONFIG_DM_VIDEO)) {
174 /*
175 * We did not find a suitable stdio device. If there is a video
176 * driver with a name starting with 'vidconsole', we can try
177 * probing that in the hope that it will produce the required
178 * stdio device.
179 *
180 * This function is sometimes called with the entire value of
181 * 'stdout', which may include a list of devices separate by
182 * commas. Obviously this is not going to work, so we ignore
183 * that case. The call path in that case is
184 * console_init_r() -> search_device() -> stdio_get_by_name()
185 */
186 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
187 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
188 return sdev;
189 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200190
191 return NULL;
192}
193
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200194struct stdio_dev* stdio_clone(struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200195{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200196 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200197
198 if(!dev)
199 return NULL;
200
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200201 _dev = calloc(1, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200202
203 if(!_dev)
204 return NULL;
205
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200206 memcpy(_dev, dev, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200207
208 return _dev;
209}
wdenk91d32562002-09-18 21:21:13 +0000210
Simon Glassd97143a2014-07-23 06:55:05 -0600211int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
wdenk91d32562002-09-18 21:21:13 +0000212{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200213 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200214
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200215 _dev = stdio_clone(dev);
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200216 if(!_dev)
Simon Glassd97143a2014-07-23 06:55:05 -0600217 return -ENODEV;
Stefan Roese3e3c0262008-09-05 10:47:46 +0200218 list_add_tail(&(_dev->list), &(devs.list));
Simon Glassd97143a2014-07-23 06:55:05 -0600219 if (devp)
220 *devp = _dev;
221
wdenk91d32562002-09-18 21:21:13 +0000222 return 0;
223}
224
Simon Glassd97143a2014-07-23 06:55:05 -0600225int stdio_register(struct stdio_dev *dev)
226{
227 return stdio_register_dev(dev, NULL);
228}
229
wdenk91d32562002-09-18 21:21:13 +0000230/* deregister the device "devname".
231 * returns 0 if success, -1 if device is assigned and 1 if devname not found
232 */
Hans de Goede32d01922014-09-20 16:54:37 +0200233int stdio_deregister_dev(struct stdio_dev *dev, int force)
wdenk91d32562002-09-18 21:21:13 +0000234{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200235 int l;
236 struct list_head *pos;
Bradley Bolen03bf22f2011-08-22 11:48:05 +0000237 char temp_names[3][16];
wdenk91d32562002-09-18 21:21:13 +0000238
wdenk91d32562002-09-18 21:21:13 +0000239 /* get stdio devices (ListRemoveItem changes the dev list) */
240 for (l=0 ; l< MAX_FILES; l++) {
241 if (stdio_devices[l] == dev) {
Hans de Goede32d01922014-09-20 16:54:37 +0200242 if (force) {
243 strcpy(temp_names[l], "nulldev");
244 continue;
245 }
wdenk91d32562002-09-18 21:21:13 +0000246 /* Device is assigned -> report error */
247 return -1;
248 }
249 memcpy (&temp_names[l][0],
250 stdio_devices[l]->name,
Bradley Bolen03bf22f2011-08-22 11:48:05 +0000251 sizeof(temp_names[l]));
wdenk91d32562002-09-18 21:21:13 +0000252 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200253
254 list_del(&(dev->list));
Hans de Goede88274b62014-09-24 14:06:09 +0200255 free(dev);
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200256
wdenk91d32562002-09-18 21:21:13 +0000257 /* reassign Device list */
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200258 list_for_each(pos, &(devs.list)) {
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200259 dev = list_entry(pos, struct stdio_dev, list);
wdenk91d32562002-09-18 21:21:13 +0000260 for (l=0 ; l< MAX_FILES; l++) {
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200261 if(strcmp(dev->name, temp_names[l]) == 0)
wdenk91d32562002-09-18 21:21:13 +0000262 stdio_devices[l] = dev;
wdenk91d32562002-09-18 21:21:13 +0000263 }
264 }
265 return 0;
266}
Simon Glassd97143a2014-07-23 06:55:05 -0600267
Hans de Goede32d01922014-09-20 16:54:37 +0200268int stdio_deregister(const char *devname, int force)
Simon Glassd97143a2014-07-23 06:55:05 -0600269{
270 struct stdio_dev *dev;
271
272 dev = stdio_get_by_name(devname);
273
274 if (!dev) /* device not found */
275 return -ENODEV;
276
Hans de Goede32d01922014-09-20 16:54:37 +0200277 return stdio_deregister_dev(dev, force);
Simon Glassd97143a2014-07-23 06:55:05 -0600278}
wdenk91d32562002-09-18 21:21:13 +0000279
Simon Glass9fb02492014-09-03 17:37:01 -0600280int stdio_init_tables(void)
wdenk91d32562002-09-18 21:21:13 +0000281{
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200282#if defined(CONFIG_NEEDS_MANUAL_RELOC)
Peter Tyser521af042009-09-21 11:20:36 -0500283 /* already relocated for current ARM implementation */
wdenk91d32562002-09-18 21:21:13 +0000284 ulong relocation_offset = gd->reloc_off;
wdenk3595ac42003-06-22 17:18:28 +0000285 int i;
wdenk91d32562002-09-18 21:21:13 +0000286
287 /* relocate device name pointers */
288 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
289 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
290 relocation_offset);
291 }
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200292#endif /* CONFIG_NEEDS_MANUAL_RELOC */
wdenk91d32562002-09-18 21:21:13 +0000293
294 /* Initialize the list */
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200295 INIT_LIST_HEAD(&(devs.list));
wdenk91d32562002-09-18 21:21:13 +0000296
Simon Glass9fb02492014-09-03 17:37:01 -0600297 return 0;
298}
299
300int stdio_add_devices(void)
301{
Simon Glassb206cd72015-10-18 21:17:15 -0600302 struct udevice *dev;
303 struct uclass *uc;
304 int ret;
305
Simon Glass5d4b6b12020-08-11 11:23:39 -0600306 if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
307 /*
308 * For now we probe all the devices here. At some point this
309 * should be done only when the devices are required - e.g. we
310 * have a list of input devices to start up in the stdin
311 * environment variable. That work probably makes more sense
312 * when stdio itself is converted to driver model.
313 *
314 * TODO(sjg@chromium.org): Convert changing
315 * uclass_first_device() etc. to return the device even on
316 * error. Then we could use that here.
317 */
318 ret = uclass_get(UCLASS_KEYBOARD, &uc);
Simon Glassb206cd72015-10-18 21:17:15 -0600319 if (ret)
Simon Glass5d4b6b12020-08-11 11:23:39 -0600320 return ret;
321
322 /*
323 * Don't report errors to the caller - assume that they are
324 * non-fatal
325 */
326 uclass_foreach_dev(dev, uc) {
327 ret = device_probe(dev);
328 if (ret)
329 printf("Failed to probe keyboard '%s'\n",
330 dev->name);
331 }
Simon Glassb206cd72015-10-18 21:17:15 -0600332 }
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000333#ifdef CONFIG_SYS_I2C
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000334 i2c_init_all();
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000335#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600336 if (IS_ENABLED(CONFIG_DM_VIDEO)) {
337 /*
338 * If the console setting is not in environment variables then
339 * console_init_r() will not be calling iomux_doenv() (which
340 * calls search_device()). So we will not dynamically add
341 * devices by calling stdio_probe_device().
342 *
343 * So just probe all video devices now so that whichever one is
344 * required will be available.
345 */
346 struct udevice *vdev;
347 int ret;
Simon Glasse3b81c12016-01-18 19:52:23 -0700348
Simon Glass5d4b6b12020-08-11 11:23:39 -0600349 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
350 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
351 vdev;
352 ret = uclass_next_device(&vdev))
353 ;
354 if (ret)
355 printf("%s: Video device failed (ret=%d)\n",
356 __func__, ret);
357 }
358 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
359 IS_ENABLED(CONFIG_CMD_BMP))
360 splash_display();
361 } else {
362 if (IS_ENABLED(CONFIG_LCD))
363 drv_lcd_init();
364 if (IS_ENABLED(CONFIG_VIDEO) || IS_ENABLED(CONFIG_CFB_CONSOLE))
365 drv_video_init();
366 }
367
Simon Glassb206cd72015-10-18 21:17:15 -0600368#if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
Simon Glass5d4b6b12020-08-11 11:23:39 -0600369 drv_keyboard_init();
wdenk91d32562002-09-18 21:21:13 +0000370#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600371 drv_system_init();
372 serial_stdio_init();
wdenk232c1502004-03-12 00:14:09 +0000373#ifdef CONFIG_USB_TTY
Simon Glass5d4b6b12020-08-11 11:23:39 -0600374 drv_usbtty_init();
wdenk232c1502004-03-12 00:14:09 +0000375#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600376 if (IS_ENABLED(CONFIG_NETCONSOLE))
377 drv_nc_init();
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400378#ifdef CONFIG_JTAG_CONSOLE
Simon Glass5d4b6b12020-08-11 11:23:39 -0600379 drv_jtag_console_init();
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400380#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600381 if (IS_ENABLED(CONFIG_CBMEM_CONSOLE))
382 cbmemc_init();
Simon Glass9fb02492014-09-03 17:37:01 -0600383
384 return 0;
385}
386
387int stdio_init(void)
388{
389 stdio_init_tables();
390 stdio_add_devices();
391
392 return 0;
wdenk91d32562002-09-18 21:21:13 +0000393}