blob: 61fc08736841411630631f1141bcee601b523697 [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;
28struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
wdenk91d32562002-09-18 21:21:13 +000029char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
30
Andy Shevchenko99cb2b92021-02-11 17:09:35 +020031#if CONFIG_IS_ENABLED(SYS_DEVICE_NULLDEV)
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020032static void nulldev_putc(struct stdio_dev *dev, const char c)
wdenk91d32562002-09-18 21:21:13 +000033{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020034 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000035}
36
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020037static void nulldev_puts(struct stdio_dev *dev, const char *s)
wdenk91d32562002-09-18 21:21:13 +000038{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020039 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000040}
41
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020042static int nulldev_input(struct stdio_dev *dev)
wdenk91d32562002-09-18 21:21:13 +000043{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020044 /* nulldev is empty! */
45 return 0;
wdenk91d32562002-09-18 21:21:13 +000046}
wdenk91d32562002-09-18 21:21:13 +000047
Andy Shevchenko99cb2b92021-02-11 17:09:35 +020048static void nulldev_register(void)
49{
50 struct stdio_dev dev;
51
52 memset(&dev, '\0', sizeof(dev));
53
54 strcpy(dev.name, "nulldev");
55 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
56 dev.putc = nulldev_putc;
57 dev.puts = nulldev_puts;
58 dev.getc = nulldev_input;
59 dev.tstc = nulldev_input;
60
61 stdio_register(&dev);
62}
63#else
64static inline void nulldev_register(void) {}
65#endif /* SYS_DEVICE_NULLDEV */
66
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020067static void stdio_serial_putc(struct stdio_dev *dev, const char c)
Simon Glass709ea542014-07-23 06:54:59 -060068{
69 serial_putc(c);
70}
71
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020072static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
Simon Glass709ea542014-07-23 06:54:59 -060073{
74 serial_puts(s);
75}
76
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020077static int stdio_serial_getc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060078{
79 return serial_getc();
80}
81
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020082static int stdio_serial_tstc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060083{
84 return serial_tstc();
85}
86
wdenk91d32562002-09-18 21:21:13 +000087/**************************************************************************
88 * SYSTEM DRIVERS
89 **************************************************************************
90 */
91
92static void drv_system_init (void)
93{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020094 struct stdio_dev dev;
wdenk91d32562002-09-18 21:21:13 +000095
96 memset (&dev, 0, sizeof (dev));
97
98 strcpy (dev.name, "serial");
Bin Meng1caf9342015-11-03 23:23:37 -080099 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
Simon Glass709ea542014-07-23 06:54:59 -0600100 dev.putc = stdio_serial_putc;
101 dev.puts = stdio_serial_puts;
102 dev.getc = stdio_serial_getc;
103 dev.tstc = stdio_serial_tstc;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200104 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +0000105
Andy Shevchenko99cb2b92021-02-11 17:09:35 +0200106 nulldev_register();
wdenk91d32562002-09-18 21:21:13 +0000107}
108
109/**************************************************************************
110 * DEVICES
111 **************************************************************************
112 */
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200113struct list_head* stdio_get_list(void)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200114{
Simon Glass18c587d2020-08-11 11:23:40 -0600115 return &devs.list;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200116}
117
Simon Glassd8441ea2016-10-05 20:42:16 -0600118/**
119 * stdio_probe_device() - Find a device which provides the given stdio device
120 *
121 * This looks for a device of the given uclass which provides a particular
122 * stdio device. It is currently really only useful for UCLASS_VIDEO.
123 *
124 * Ultimately we want to be able to probe a device by its stdio name. At
125 * present devices register in their probe function (for video devices this
126 * is done in vidconsole_post_probe()) and we don't know what name they will
127 * use until they do so.
128 * TODO(sjg@chromium.org): We should be able to determine the name before
129 * probing, and probe the required device.
130 *
131 * @name: stdio device name (e.g. "vidconsole")
132 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
133 * @sdevp: Returns stdout device, if found, else NULL
134 * @return 0 if found, -ENOENT if no device found with that name, other -ve
135 * on other error
136 */
137static int stdio_probe_device(const char *name, enum uclass_id id,
138 struct stdio_dev **sdevp)
139{
140 struct stdio_dev *sdev;
141 struct udevice *dev;
142 int seq, ret;
143
144 *sdevp = NULL;
145 seq = trailing_strtoln(name, NULL);
146 if (seq == -1)
Simon Glassd844efe2016-11-13 14:22:00 -0700147 seq = 0;
148 ret = uclass_get_device_by_seq(id, seq, &dev);
149 if (ret == -ENODEV)
Simon Glassd8441ea2016-10-05 20:42:16 -0600150 ret = uclass_first_device_err(id, &dev);
Simon Glassd8441ea2016-10-05 20:42:16 -0600151 if (ret) {
152 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
153 seq, name);
154 return ret;
155 }
156 /* The device should be be the last one registered */
157 sdev = list_empty(&devs.list) ? NULL :
158 list_last_entry(&devs.list, struct stdio_dev, list);
159 if (!sdev || strcmp(sdev->name, name)) {
160 debug("Device '%s' did not register with stdio as '%s'\n",
161 dev->name, name);
162 return -ENOENT;
163 }
164 *sdevp = sdev;
165
166 return 0;
167}
Simon Glassd8441ea2016-10-05 20:42:16 -0600168
Simon Glassab29a342016-11-13 14:21:59 -0700169struct stdio_dev *stdio_get_by_name(const char *name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200170{
171 struct list_head *pos;
Simon Glassd8441ea2016-10-05 20:42:16 -0600172 struct stdio_dev *sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200173
Simon Glassab29a342016-11-13 14:21:59 -0700174 if (!name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200175 return NULL;
176
Simon Glass18c587d2020-08-11 11:23:40 -0600177 list_for_each(pos, &devs.list) {
Simon Glassd8441ea2016-10-05 20:42:16 -0600178 sdev = list_entry(pos, struct stdio_dev, list);
179 if (strcmp(sdev->name, name) == 0)
180 return sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200181 }
Simon Glass5d4b6b12020-08-11 11:23:39 -0600182 if (IS_ENABLED(CONFIG_DM_VIDEO)) {
183 /*
184 * We did not find a suitable stdio device. If there is a video
185 * driver with a name starting with 'vidconsole', we can try
186 * probing that in the hope that it will produce the required
187 * stdio device.
188 *
189 * This function is sometimes called with the entire value of
190 * 'stdout', which may include a list of devices separate by
191 * commas. Obviously this is not going to work, so we ignore
192 * that case. The call path in that case is
Andy Shevchenko32324872020-12-21 14:30:03 +0200193 * console_init_r() -> console_search_dev() -> stdio_get_by_name()
Simon Glass5d4b6b12020-08-11 11:23:39 -0600194 */
195 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
196 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
197 return sdev;
198 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200199
200 return NULL;
201}
202
Simon Glass4225f2f2020-08-11 11:23:41 -0600203struct stdio_dev *stdio_clone(struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200204{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200205 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200206
Simon Glass4225f2f2020-08-11 11:23:41 -0600207 if (!dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200208 return NULL;
209
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200210 _dev = calloc(1, sizeof(struct stdio_dev));
Simon Glass4225f2f2020-08-11 11:23:41 -0600211 if (!_dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200212 return NULL;
213
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200214 memcpy(_dev, dev, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200215
216 return _dev;
217}
wdenk91d32562002-09-18 21:21:13 +0000218
Simon Glassd97143a2014-07-23 06:55:05 -0600219int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
wdenk91d32562002-09-18 21:21:13 +0000220{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200221 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200222
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200223 _dev = stdio_clone(dev);
Simon Glass4225f2f2020-08-11 11:23:41 -0600224 if (!_dev)
Simon Glassd97143a2014-07-23 06:55:05 -0600225 return -ENODEV;
Simon Glass18c587d2020-08-11 11:23:40 -0600226 list_add_tail(&_dev->list, &devs.list);
Simon Glassd97143a2014-07-23 06:55:05 -0600227 if (devp)
228 *devp = _dev;
229
wdenk91d32562002-09-18 21:21:13 +0000230 return 0;
231}
232
Simon Glassd97143a2014-07-23 06:55:05 -0600233int stdio_register(struct stdio_dev *dev)
234{
235 return stdio_register_dev(dev, NULL);
236}
237
Hans de Goede32d01922014-09-20 16:54:37 +0200238int stdio_deregister_dev(struct stdio_dev *dev, int force)
wdenk91d32562002-09-18 21:21:13 +0000239{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200240 struct list_head *pos;
Bradley Bolen03bf22f2011-08-22 11:48:05 +0000241 char temp_names[3][16];
Simon Glass4225f2f2020-08-11 11:23:41 -0600242 int i;
wdenk91d32562002-09-18 21:21:13 +0000243
wdenk91d32562002-09-18 21:21:13 +0000244 /* get stdio devices (ListRemoveItem changes the dev list) */
Simon Glass4225f2f2020-08-11 11:23:41 -0600245 for (i = 0 ; i < MAX_FILES; i++) {
246 if (stdio_devices[i] == dev) {
Hans de Goede32d01922014-09-20 16:54:37 +0200247 if (force) {
Simon Glass4225f2f2020-08-11 11:23:41 -0600248 strcpy(temp_names[i], "nulldev");
Hans de Goede32d01922014-09-20 16:54:37 +0200249 continue;
250 }
wdenk91d32562002-09-18 21:21:13 +0000251 /* Device is assigned -> report error */
Simon Glass4225f2f2020-08-11 11:23:41 -0600252 return -EBUSY;
wdenk91d32562002-09-18 21:21:13 +0000253 }
Simon Glass4225f2f2020-08-11 11:23:41 -0600254 memcpy(&temp_names[i][0], stdio_devices[i]->name,
255 sizeof(temp_names[i]));
wdenk91d32562002-09-18 21:21:13 +0000256 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200257
Simon Glass18c587d2020-08-11 11:23:40 -0600258 list_del(&dev->list);
Hans de Goede88274b62014-09-24 14:06:09 +0200259 free(dev);
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200260
Simon Glass4225f2f2020-08-11 11:23:41 -0600261 /* reassign device list */
Simon Glass18c587d2020-08-11 11:23:40 -0600262 list_for_each(pos, &devs.list) {
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200263 dev = list_entry(pos, struct stdio_dev, list);
Simon Glass4225f2f2020-08-11 11:23:41 -0600264 for (i = 0 ; i < MAX_FILES; i++) {
265 if (strcmp(dev->name, temp_names[i]) == 0)
266 stdio_devices[i] = dev;
wdenk91d32562002-09-18 21:21:13 +0000267 }
268 }
Simon Glass4225f2f2020-08-11 11:23:41 -0600269
wdenk91d32562002-09-18 21:21:13 +0000270 return 0;
271}
Simon Glassd97143a2014-07-23 06:55:05 -0600272
Simon Glass9fb02492014-09-03 17:37:01 -0600273int stdio_init_tables(void)
wdenk91d32562002-09-18 21:21:13 +0000274{
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200275#if defined(CONFIG_NEEDS_MANUAL_RELOC)
Peter Tyser521af042009-09-21 11:20:36 -0500276 /* already relocated for current ARM implementation */
wdenk91d32562002-09-18 21:21:13 +0000277 ulong relocation_offset = gd->reloc_off;
wdenk3595ac42003-06-22 17:18:28 +0000278 int i;
wdenk91d32562002-09-18 21:21:13 +0000279
280 /* relocate device name pointers */
281 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
282 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
283 relocation_offset);
284 }
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200285#endif /* CONFIG_NEEDS_MANUAL_RELOC */
wdenk91d32562002-09-18 21:21:13 +0000286
287 /* Initialize the list */
Simon Glass18c587d2020-08-11 11:23:40 -0600288 INIT_LIST_HEAD(&devs.list);
wdenk91d32562002-09-18 21:21:13 +0000289
Simon Glass9fb02492014-09-03 17:37:01 -0600290 return 0;
291}
292
293int stdio_add_devices(void)
294{
Simon Glassb206cd72015-10-18 21:17:15 -0600295 struct udevice *dev;
296 struct uclass *uc;
297 int ret;
298
Simon Glass5d4b6b12020-08-11 11:23:39 -0600299 if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
300 /*
301 * For now we probe all the devices here. At some point this
302 * should be done only when the devices are required - e.g. we
303 * have a list of input devices to start up in the stdin
304 * environment variable. That work probably makes more sense
305 * when stdio itself is converted to driver model.
306 *
307 * TODO(sjg@chromium.org): Convert changing
308 * uclass_first_device() etc. to return the device even on
309 * error. Then we could use that here.
310 */
311 ret = uclass_get(UCLASS_KEYBOARD, &uc);
Simon Glassb206cd72015-10-18 21:17:15 -0600312 if (ret)
Simon Glass5d4b6b12020-08-11 11:23:39 -0600313 return ret;
314
315 /*
316 * Don't report errors to the caller - assume that they are
317 * non-fatal
318 */
319 uclass_foreach_dev(dev, uc) {
320 ret = device_probe(dev);
321 if (ret)
322 printf("Failed to probe keyboard '%s'\n",
323 dev->name);
324 }
Simon Glassb206cd72015-10-18 21:17:15 -0600325 }
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000326#ifdef CONFIG_SYS_I2C
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000327 i2c_init_all();
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000328#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600329 if (IS_ENABLED(CONFIG_DM_VIDEO)) {
330 /*
331 * If the console setting is not in environment variables then
332 * console_init_r() will not be calling iomux_doenv() (which
Andy Shevchenko32324872020-12-21 14:30:03 +0200333 * calls console_search_dev()). So we will not dynamically add
Simon Glass5d4b6b12020-08-11 11:23:39 -0600334 * devices by calling stdio_probe_device().
335 *
336 * So just probe all video devices now so that whichever one is
337 * required will be available.
338 */
339 struct udevice *vdev;
340 int ret;
Simon Glasse3b81c12016-01-18 19:52:23 -0700341
Simon Glass5d4b6b12020-08-11 11:23:39 -0600342 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
343 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
344 vdev;
345 ret = uclass_next_device(&vdev))
346 ;
347 if (ret)
348 printf("%s: Video device failed (ret=%d)\n",
349 __func__, ret);
350 }
351 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
352 IS_ENABLED(CONFIG_CMD_BMP))
353 splash_display();
354 } else {
355 if (IS_ENABLED(CONFIG_LCD))
356 drv_lcd_init();
Anatolij Gustschin8c9940d2020-10-18 20:32:35 +0200357 if (IS_ENABLED(CONFIG_VIDEO) ||
358 IS_ENABLED(CONFIG_CFB_CONSOLE) ||
359 IS_ENABLED(CONFIG_VIDEO_VCXK))
Simon Glass5d4b6b12020-08-11 11:23:39 -0600360 drv_video_init();
361 }
362
Simon Glassb206cd72015-10-18 21:17:15 -0600363#if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
Simon Glass5d4b6b12020-08-11 11:23:39 -0600364 drv_keyboard_init();
wdenk91d32562002-09-18 21:21:13 +0000365#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600366 drv_system_init();
367 serial_stdio_init();
wdenk232c1502004-03-12 00:14:09 +0000368#ifdef CONFIG_USB_TTY
Simon Glass5d4b6b12020-08-11 11:23:39 -0600369 drv_usbtty_init();
wdenk232c1502004-03-12 00:14:09 +0000370#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600371 if (IS_ENABLED(CONFIG_NETCONSOLE))
372 drv_nc_init();
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400373#ifdef CONFIG_JTAG_CONSOLE
Simon Glass5d4b6b12020-08-11 11:23:39 -0600374 drv_jtag_console_init();
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400375#endif
Simon Glass5d4b6b12020-08-11 11:23:39 -0600376 if (IS_ENABLED(CONFIG_CBMEM_CONSOLE))
377 cbmemc_init();
Simon Glass9fb02492014-09-03 17:37:01 -0600378
379 return 0;
380}
381
382int stdio_init(void)
383{
384 stdio_init_tables();
385 stdio_add_devices();
386
387 return 0;
wdenk91d32562002-09-18 21:21:13 +0000388}