blob: 063c659bbc371a7daa03cbd9f6b7c70ab5b892e9 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk91d32562002-09-18 21:21:13 +00002/*
Heiko Schochere0e55bc2012-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 Glassd3d40352015-10-18 21:17:15 -060013#include <dm.h>
Simon Glass5d609ce2014-07-23 06:55:05 -060014#include <errno.h>
Simon Glass0f2af882020-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-VILLARD2a7a0312009-05-16 12:14:54 +020018#include <stdio_dev.h>
wdenk7ac16102004-08-01 22:48:16 +000019#include <serial.h>
Igor Opaniuk1f6bfad2019-05-29 09:01:43 +000020#include <splash.h>
wdenk91d32562002-09-18 21:21:13 +000021#include <i2c.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060022#include <asm/global_data.h>
Simon Glassd3d40352015-10-18 21:17:15 -060023#include <dm/device-internal.h>
24
Wolfgang Denk6405a152006-03-31 18:32:53 +020025DECLARE_GLOBAL_DATA_PTR;
26
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-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 Shevchenko94331022021-02-11 17:09:36 +020031int stdio_file_to_flags(const int file)
32{
33 switch (file) {
34 case stdin:
35 return DEV_FLAGS_INPUT;
36 case stdout:
37 case stderr:
38 return DEV_FLAGS_OUTPUT;
39 default:
40 return -EINVAL;
41 }
42}
43
Andy Shevchenko2066f392021-02-11 17:09:35 +020044#if CONFIG_IS_ENABLED(SYS_DEVICE_NULLDEV)
Jeroen Hofstee169eda62014-10-08 22:57:44 +020045static void nulldev_putc(struct stdio_dev *dev, const char c)
wdenk91d32562002-09-18 21:21:13 +000046{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +020047 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000048}
49
Jeroen Hofstee169eda62014-10-08 22:57:44 +020050static void nulldev_puts(struct stdio_dev *dev, const char *s)
wdenk91d32562002-09-18 21:21:13 +000051{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +020052 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000053}
54
Jeroen Hofstee169eda62014-10-08 22:57:44 +020055static int nulldev_input(struct stdio_dev *dev)
wdenk91d32562002-09-18 21:21:13 +000056{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +020057 /* nulldev is empty! */
58 return 0;
wdenk91d32562002-09-18 21:21:13 +000059}
wdenk91d32562002-09-18 21:21:13 +000060
Andy Shevchenko2066f392021-02-11 17:09:35 +020061static void nulldev_register(void)
62{
63 struct stdio_dev dev;
64
65 memset(&dev, '\0', sizeof(dev));
66
67 strcpy(dev.name, "nulldev");
68 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
69 dev.putc = nulldev_putc;
70 dev.puts = nulldev_puts;
71 dev.getc = nulldev_input;
72 dev.tstc = nulldev_input;
73
74 stdio_register(&dev);
75}
76#else
77static inline void nulldev_register(void) {}
78#endif /* SYS_DEVICE_NULLDEV */
79
Jeroen Hofstee169eda62014-10-08 22:57:44 +020080static void stdio_serial_putc(struct stdio_dev *dev, const char c)
Simon Glass0d1e1f72014-07-23 06:54:59 -060081{
82 serial_putc(c);
83}
84
Jeroen Hofstee169eda62014-10-08 22:57:44 +020085static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
Simon Glass0d1e1f72014-07-23 06:54:59 -060086{
87 serial_puts(s);
88}
89
Jeroen Hofstee169eda62014-10-08 22:57:44 +020090static int stdio_serial_getc(struct stdio_dev *dev)
Simon Glass0d1e1f72014-07-23 06:54:59 -060091{
92 return serial_getc();
93}
94
Jeroen Hofstee169eda62014-10-08 22:57:44 +020095static int stdio_serial_tstc(struct stdio_dev *dev)
Simon Glass0d1e1f72014-07-23 06:54:59 -060096{
97 return serial_tstc();
98}
99
wdenk91d32562002-09-18 21:21:13 +0000100/**************************************************************************
101 * SYSTEM DRIVERS
102 **************************************************************************
103 */
104
105static void drv_system_init (void)
106{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200107 struct stdio_dev dev;
wdenk91d32562002-09-18 21:21:13 +0000108
109 memset (&dev, 0, sizeof (dev));
110
111 strcpy (dev.name, "serial");
Bin Meng6abe4b62015-11-03 23:23:37 -0800112 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600113 dev.putc = stdio_serial_putc;
114 dev.puts = stdio_serial_puts;
115 dev.getc = stdio_serial_getc;
116 dev.tstc = stdio_serial_tstc;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200117 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +0000118
Andy Shevchenko2066f392021-02-11 17:09:35 +0200119 nulldev_register();
wdenk91d32562002-09-18 21:21:13 +0000120}
121
122/**************************************************************************
123 * DEVICES
124 **************************************************************************
125 */
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200126struct list_head* stdio_get_list(void)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200127{
Simon Glass4b1e3092020-08-11 11:23:40 -0600128 return &devs.list;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200129}
130
Simon Glass4af407f2016-10-05 20:42:16 -0600131/**
132 * stdio_probe_device() - Find a device which provides the given stdio device
133 *
134 * This looks for a device of the given uclass which provides a particular
135 * stdio device. It is currently really only useful for UCLASS_VIDEO.
136 *
137 * Ultimately we want to be able to probe a device by its stdio name. At
138 * present devices register in their probe function (for video devices this
139 * is done in vidconsole_post_probe()) and we don't know what name they will
140 * use until they do so.
141 * TODO(sjg@chromium.org): We should be able to determine the name before
142 * probing, and probe the required device.
143 *
144 * @name: stdio device name (e.g. "vidconsole")
145 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
146 * @sdevp: Returns stdout device, if found, else NULL
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100147 * Return: 0 if found, -ENOENT if no device found with that name, other -ve
Simon Glass4af407f2016-10-05 20:42:16 -0600148 * on other error
149 */
150static int stdio_probe_device(const char *name, enum uclass_id id,
151 struct stdio_dev **sdevp)
152{
153 struct stdio_dev *sdev;
154 struct udevice *dev;
155 int seq, ret;
156
157 *sdevp = NULL;
158 seq = trailing_strtoln(name, NULL);
159 if (seq == -1)
Simon Glass927e6312016-11-13 14:22:00 -0700160 seq = 0;
161 ret = uclass_get_device_by_seq(id, seq, &dev);
162 if (ret == -ENODEV)
Simon Glass4af407f2016-10-05 20:42:16 -0600163 ret = uclass_first_device_err(id, &dev);
Simon Glass4af407f2016-10-05 20:42:16 -0600164 if (ret) {
165 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
166 seq, name);
167 return ret;
168 }
169 /* The device should be be the last one registered */
170 sdev = list_empty(&devs.list) ? NULL :
171 list_last_entry(&devs.list, struct stdio_dev, list);
172 if (!sdev || strcmp(sdev->name, name)) {
173 debug("Device '%s' did not register with stdio as '%s'\n",
174 dev->name, name);
175 return -ENOENT;
176 }
177 *sdevp = sdev;
178
179 return 0;
180}
Simon Glass4af407f2016-10-05 20:42:16 -0600181
Simon Glass913d7612016-11-13 14:21:59 -0700182struct stdio_dev *stdio_get_by_name(const char *name)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200183{
184 struct list_head *pos;
Simon Glass4af407f2016-10-05 20:42:16 -0600185 struct stdio_dev *sdev;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200186
Simon Glass913d7612016-11-13 14:21:59 -0700187 if (!name)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200188 return NULL;
189
Simon Glass4b1e3092020-08-11 11:23:40 -0600190 list_for_each(pos, &devs.list) {
Simon Glass4af407f2016-10-05 20:42:16 -0600191 sdev = list_entry(pos, struct stdio_dev, list);
192 if (strcmp(sdev->name, name) == 0)
193 return sdev;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200194 }
Simon Glass5a36d822020-08-11 11:23:39 -0600195 if (IS_ENABLED(CONFIG_DM_VIDEO)) {
196 /*
197 * We did not find a suitable stdio device. If there is a video
198 * driver with a name starting with 'vidconsole', we can try
199 * probing that in the hope that it will produce the required
200 * stdio device.
201 *
202 * This function is sometimes called with the entire value of
203 * 'stdout', which may include a list of devices separate by
204 * commas. Obviously this is not going to work, so we ignore
205 * that case. The call path in that case is
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +0200206 * console_init_r() -> console_search_dev() -> stdio_get_by_name()
Simon Glass5a36d822020-08-11 11:23:39 -0600207 */
208 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
209 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
210 return sdev;
211 }
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200212
213 return NULL;
214}
215
Simon Glass5b4c1222020-08-11 11:23:41 -0600216struct stdio_dev *stdio_clone(struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200217{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200218 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200219
Simon Glass5b4c1222020-08-11 11:23:41 -0600220 if (!dev)
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200221 return NULL;
222
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200223 _dev = calloc(1, sizeof(struct stdio_dev));
Simon Glass5b4c1222020-08-11 11:23:41 -0600224 if (!_dev)
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200225 return NULL;
226
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200227 memcpy(_dev, dev, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200228
229 return _dev;
230}
wdenk91d32562002-09-18 21:21:13 +0000231
Simon Glass5d609ce2014-07-23 06:55:05 -0600232int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
wdenk91d32562002-09-18 21:21:13 +0000233{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200234 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200235
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200236 _dev = stdio_clone(dev);
Simon Glass5b4c1222020-08-11 11:23:41 -0600237 if (!_dev)
Simon Glass5d609ce2014-07-23 06:55:05 -0600238 return -ENODEV;
Simon Glass4b1e3092020-08-11 11:23:40 -0600239 list_add_tail(&_dev->list, &devs.list);
Simon Glass5d609ce2014-07-23 06:55:05 -0600240 if (devp)
241 *devp = _dev;
242
wdenk91d32562002-09-18 21:21:13 +0000243 return 0;
244}
245
Simon Glass5d609ce2014-07-23 06:55:05 -0600246int stdio_register(struct stdio_dev *dev)
247{
248 return stdio_register_dev(dev, NULL);
249}
250
Hans de Goede1a586382014-09-20 16:54:37 +0200251int stdio_deregister_dev(struct stdio_dev *dev, int force)
wdenk91d32562002-09-18 21:21:13 +0000252{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200253 struct list_head *pos;
Bradley Bolen466d7392011-08-22 11:48:05 +0000254 char temp_names[3][16];
Simon Glass5b4c1222020-08-11 11:23:41 -0600255 int i;
wdenk91d32562002-09-18 21:21:13 +0000256
wdenk91d32562002-09-18 21:21:13 +0000257 /* get stdio devices (ListRemoveItem changes the dev list) */
Simon Glass5b4c1222020-08-11 11:23:41 -0600258 for (i = 0 ; i < MAX_FILES; i++) {
259 if (stdio_devices[i] == dev) {
Hans de Goede1a586382014-09-20 16:54:37 +0200260 if (force) {
Simon Glass5b4c1222020-08-11 11:23:41 -0600261 strcpy(temp_names[i], "nulldev");
Hans de Goede1a586382014-09-20 16:54:37 +0200262 continue;
263 }
wdenk91d32562002-09-18 21:21:13 +0000264 /* Device is assigned -> report error */
Simon Glass5b4c1222020-08-11 11:23:41 -0600265 return -EBUSY;
wdenk91d32562002-09-18 21:21:13 +0000266 }
Simon Glass5b4c1222020-08-11 11:23:41 -0600267 memcpy(&temp_names[i][0], stdio_devices[i]->name,
268 sizeof(temp_names[i]));
wdenk91d32562002-09-18 21:21:13 +0000269 }
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200270
Simon Glass4b1e3092020-08-11 11:23:40 -0600271 list_del(&dev->list);
Hans de Goede35e116c2014-09-24 14:06:09 +0200272 free(dev);
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200273
Simon Glass5b4c1222020-08-11 11:23:41 -0600274 /* reassign device list */
Simon Glass4b1e3092020-08-11 11:23:40 -0600275 list_for_each(pos, &devs.list) {
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200276 dev = list_entry(pos, struct stdio_dev, list);
Simon Glass5b4c1222020-08-11 11:23:41 -0600277 for (i = 0 ; i < MAX_FILES; i++) {
278 if (strcmp(dev->name, temp_names[i]) == 0)
279 stdio_devices[i] = dev;
wdenk91d32562002-09-18 21:21:13 +0000280 }
281 }
Simon Glass5b4c1222020-08-11 11:23:41 -0600282
wdenk91d32562002-09-18 21:21:13 +0000283 return 0;
284}
Simon Glass5d609ce2014-07-23 06:55:05 -0600285
Simon Glass712da5e2014-09-03 17:37:01 -0600286int stdio_init_tables(void)
wdenk91d32562002-09-18 21:21:13 +0000287{
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200288#if defined(CONFIG_NEEDS_MANUAL_RELOC)
Peter Tyser9057cbf2009-09-21 11:20:36 -0500289 /* already relocated for current ARM implementation */
wdenk91d32562002-09-18 21:21:13 +0000290 ulong relocation_offset = gd->reloc_off;
wdenk56958612003-06-22 17:18:28 +0000291 int i;
wdenk91d32562002-09-18 21:21:13 +0000292
293 /* relocate device name pointers */
294 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
295 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
296 relocation_offset);
297 }
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200298#endif /* CONFIG_NEEDS_MANUAL_RELOC */
wdenk91d32562002-09-18 21:21:13 +0000299
300 /* Initialize the list */
Simon Glass4b1e3092020-08-11 11:23:40 -0600301 INIT_LIST_HEAD(&devs.list);
wdenk91d32562002-09-18 21:21:13 +0000302
Simon Glass712da5e2014-09-03 17:37:01 -0600303 return 0;
304}
305
306int stdio_add_devices(void)
307{
Simon Glassd3d40352015-10-18 21:17:15 -0600308 struct udevice *dev;
309 struct uclass *uc;
310 int ret;
311
Simon Glass5a36d822020-08-11 11:23:39 -0600312 if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
313 /*
314 * For now we probe all the devices here. At some point this
315 * should be done only when the devices are required - e.g. we
316 * have a list of input devices to start up in the stdin
317 * environment variable. That work probably makes more sense
318 * when stdio itself is converted to driver model.
319 *
320 * TODO(sjg@chromium.org): Convert changing
321 * uclass_first_device() etc. to return the device even on
322 * error. Then we could use that here.
323 */
324 ret = uclass_get(UCLASS_KEYBOARD, &uc);
Simon Glassd3d40352015-10-18 21:17:15 -0600325 if (ret)
Simon Glass5a36d822020-08-11 11:23:39 -0600326 return ret;
327
328 /*
329 * Don't report errors to the caller - assume that they are
330 * non-fatal
331 */
332 uclass_foreach_dev(dev, uc) {
333 ret = device_probe(dev);
334 if (ret)
335 printf("Failed to probe keyboard '%s'\n",
336 dev->name);
337 }
Simon Glassd3d40352015-10-18 21:17:15 -0600338 }
Tom Rini52b2e262021-08-18 23:12:24 -0400339#if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
Heiko Schochere0e55bc2012-01-16 21:12:24 +0000340 i2c_init_all();
Heiko Schochere0e55bc2012-01-16 21:12:24 +0000341#endif
Simon Glass5a36d822020-08-11 11:23:39 -0600342 if (IS_ENABLED(CONFIG_DM_VIDEO)) {
343 /*
344 * If the console setting is not in environment variables then
345 * console_init_r() will not be calling iomux_doenv() (which
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +0200346 * calls console_search_dev()). So we will not dynamically add
Simon Glass5a36d822020-08-11 11:23:39 -0600347 * devices by calling stdio_probe_device().
348 *
349 * So just probe all video devices now so that whichever one is
350 * required will be available.
351 */
352 struct udevice *vdev;
353 int ret;
354
355 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
356 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
357 vdev;
358 ret = uclass_next_device(&vdev))
359 ;
360 if (ret)
361 printf("%s: Video device failed (ret=%d)\n",
362 __func__, ret);
363 }
364 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
365 IS_ENABLED(CONFIG_CMD_BMP))
366 splash_display();
367 } else {
368 if (IS_ENABLED(CONFIG_LCD))
369 drv_lcd_init();
Anatolij Gustschin3d471a12020-10-18 20:32:35 +0200370 if (IS_ENABLED(CONFIG_VIDEO) ||
371 IS_ENABLED(CONFIG_CFB_CONSOLE) ||
372 IS_ENABLED(CONFIG_VIDEO_VCXK))
Simon Glass5a36d822020-08-11 11:23:39 -0600373 drv_video_init();
374 }
Simon Glass0005cb22016-01-18 19:52:23 -0700375
Simon Glassd3d40352015-10-18 21:17:15 -0600376#if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
Simon Glass5a36d822020-08-11 11:23:39 -0600377 drv_keyboard_init();
wdenk91d32562002-09-18 21:21:13 +0000378#endif
Simon Glass5a36d822020-08-11 11:23:39 -0600379 drv_system_init();
380 serial_stdio_init();
wdenk29e7f5a2004-03-12 00:14:09 +0000381#ifdef CONFIG_USB_TTY
Simon Glass5a36d822020-08-11 11:23:39 -0600382 drv_usbtty_init();
wdenk29e7f5a2004-03-12 00:14:09 +0000383#endif
Loic Poulaineb78f832021-11-25 18:16:15 +0100384#ifdef CONFIG_USB_FUNCTION_ACM
385 drv_usbacm_init ();
386#endif
Simon Glass5a36d822020-08-11 11:23:39 -0600387 if (IS_ENABLED(CONFIG_NETCONSOLE))
388 drv_nc_init();
Mike Frysinger7504e972008-10-11 21:51:20 -0400389#ifdef CONFIG_JTAG_CONSOLE
Simon Glass5a36d822020-08-11 11:23:39 -0600390 drv_jtag_console_init();
Vadim Bendebury263a8bd2012-10-12 18:48:47 +0000391#endif
Simon Glass5a36d822020-08-11 11:23:39 -0600392 if (IS_ENABLED(CONFIG_CBMEM_CONSOLE))
393 cbmemc_init();
Simon Glass712da5e2014-09-03 17:37:01 -0600394
395 return 0;
396}
397
398int stdio_init(void)
399{
400 stdio_init_tables();
401 stdio_add_devices();
402
403 return 0;
wdenk91d32562002-09-18 21:21:13 +0000404}