blob: 2119204b9829497ca07fbafa802e6870f1218212 [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>
Heiko Schocher479a4cf2013-01-29 08:53:15 +010021
Simon Glass1a46a722017-05-12 21:09:56 -060022#if defined(CONFIG_SYS_I2C)
wdenk91d32562002-09-18 21:21:13 +000023#include <i2c.h>
wdenk1272e232002-11-10 22:06:23 +000024#endif
wdenk91d32562002-09-18 21:21:13 +000025
Simon Glassd3d40352015-10-18 21:17:15 -060026#include <dm/device-internal.h>
27
Wolfgang Denk6405a152006-03-31 18:32:53 +020028DECLARE_GLOBAL_DATA_PTR;
29
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +020030static struct stdio_dev devs;
31struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
wdenk91d32562002-09-18 21:21:13 +000032char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
33
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020034#if defined(CONFIG_SPLASH_SCREEN) && !defined(CONFIG_SYS_DEVICE_NULLDEV)
35#define CONFIG_SYS_DEVICE_NULLDEV 1
wdenk92bbe3f2003-04-20 14:04:18 +000036#endif
37
Simon Glass3110ece2016-10-17 20:13:02 -060038#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
Hans de Goede1a586382014-09-20 16:54:37 +020039#define CONFIG_SYS_DEVICE_NULLDEV 1
40#endif
wdenk92bbe3f2003-04-20 14:04:18 +000041
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020042#ifdef CONFIG_SYS_DEVICE_NULLDEV
Jeroen Hofstee169eda62014-10-08 22:57:44 +020043static void nulldev_putc(struct stdio_dev *dev, const char c)
wdenk91d32562002-09-18 21:21:13 +000044{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +020045 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000046}
47
Jeroen Hofstee169eda62014-10-08 22:57:44 +020048static void nulldev_puts(struct stdio_dev *dev, const char *s)
wdenk91d32562002-09-18 21:21:13 +000049{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +020050 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000051}
52
Jeroen Hofstee169eda62014-10-08 22:57:44 +020053static int nulldev_input(struct stdio_dev *dev)
wdenk91d32562002-09-18 21:21:13 +000054{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +020055 /* nulldev is empty! */
56 return 0;
wdenk91d32562002-09-18 21:21:13 +000057}
58#endif
59
Jeroen Hofstee169eda62014-10-08 22:57:44 +020060static void stdio_serial_putc(struct stdio_dev *dev, const char c)
Simon Glass0d1e1f72014-07-23 06:54:59 -060061{
62 serial_putc(c);
63}
64
Jeroen Hofstee169eda62014-10-08 22:57:44 +020065static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
Simon Glass0d1e1f72014-07-23 06:54:59 -060066{
67 serial_puts(s);
68}
69
Jeroen Hofstee169eda62014-10-08 22:57:44 +020070static int stdio_serial_getc(struct stdio_dev *dev)
Simon Glass0d1e1f72014-07-23 06:54:59 -060071{
72 return serial_getc();
73}
74
Jeroen Hofstee169eda62014-10-08 22:57:44 +020075static int stdio_serial_tstc(struct stdio_dev *dev)
Simon Glass0d1e1f72014-07-23 06:54:59 -060076{
77 return serial_tstc();
78}
79
wdenk91d32562002-09-18 21:21:13 +000080/**************************************************************************
81 * SYSTEM DRIVERS
82 **************************************************************************
83 */
84
85static void drv_system_init (void)
86{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +020087 struct stdio_dev dev;
wdenk91d32562002-09-18 21:21:13 +000088
89 memset (&dev, 0, sizeof (dev));
90
91 strcpy (dev.name, "serial");
Bin Meng6abe4b62015-11-03 23:23:37 -080092 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
Simon Glass0d1e1f72014-07-23 06:54:59 -060093 dev.putc = stdio_serial_putc;
94 dev.puts = stdio_serial_puts;
95 dev.getc = stdio_serial_getc;
96 dev.tstc = stdio_serial_tstc;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +020097 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +000098
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020099#ifdef CONFIG_SYS_DEVICE_NULLDEV
wdenk91d32562002-09-18 21:21:13 +0000100 memset (&dev, 0, sizeof (dev));
101
102 strcpy (dev.name, "nulldev");
Bin Meng6abe4b62015-11-03 23:23:37 -0800103 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
wdenk91d32562002-09-18 21:21:13 +0000104 dev.putc = nulldev_putc;
105 dev.puts = nulldev_puts;
106 dev.getc = nulldev_input;
107 dev.tstc = nulldev_input;
108
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200109 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +0000110#endif
111}
112
113/**************************************************************************
114 * DEVICES
115 **************************************************************************
116 */
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200117struct list_head* stdio_get_list(void)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200118{
119 return &(devs.list);
120}
121
Simon Glass4af407f2016-10-05 20:42:16 -0600122#ifdef CONFIG_DM_VIDEO
123/**
124 * stdio_probe_device() - Find a device which provides the given stdio device
125 *
126 * This looks for a device of the given uclass which provides a particular
127 * stdio device. It is currently really only useful for UCLASS_VIDEO.
128 *
129 * Ultimately we want to be able to probe a device by its stdio name. At
130 * present devices register in their probe function (for video devices this
131 * is done in vidconsole_post_probe()) and we don't know what name they will
132 * use until they do so.
133 * TODO(sjg@chromium.org): We should be able to determine the name before
134 * probing, and probe the required device.
135 *
136 * @name: stdio device name (e.g. "vidconsole")
137 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
138 * @sdevp: Returns stdout device, if found, else NULL
139 * @return 0 if found, -ENOENT if no device found with that name, other -ve
140 * on other error
141 */
142static int stdio_probe_device(const char *name, enum uclass_id id,
143 struct stdio_dev **sdevp)
144{
145 struct stdio_dev *sdev;
146 struct udevice *dev;
147 int seq, ret;
148
149 *sdevp = NULL;
150 seq = trailing_strtoln(name, NULL);
151 if (seq == -1)
Simon Glass927e6312016-11-13 14:22:00 -0700152 seq = 0;
153 ret = uclass_get_device_by_seq(id, seq, &dev);
154 if (ret == -ENODEV)
Simon Glass4af407f2016-10-05 20:42:16 -0600155 ret = uclass_first_device_err(id, &dev);
Simon Glass4af407f2016-10-05 20:42:16 -0600156 if (ret) {
157 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
158 seq, name);
159 return ret;
160 }
161 /* The device should be be the last one registered */
162 sdev = list_empty(&devs.list) ? NULL :
163 list_last_entry(&devs.list, struct stdio_dev, list);
164 if (!sdev || strcmp(sdev->name, name)) {
165 debug("Device '%s' did not register with stdio as '%s'\n",
166 dev->name, name);
167 return -ENOENT;
168 }
169 *sdevp = sdev;
170
171 return 0;
172}
173#endif
174
Simon Glass913d7612016-11-13 14:21:59 -0700175struct stdio_dev *stdio_get_by_name(const char *name)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200176{
177 struct list_head *pos;
Simon Glass4af407f2016-10-05 20:42:16 -0600178 struct stdio_dev *sdev;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200179
Simon Glass913d7612016-11-13 14:21:59 -0700180 if (!name)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200181 return NULL;
182
183 list_for_each(pos, &(devs.list)) {
Simon Glass4af407f2016-10-05 20:42:16 -0600184 sdev = list_entry(pos, struct stdio_dev, list);
185 if (strcmp(sdev->name, name) == 0)
186 return sdev;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200187 }
Simon Glass4af407f2016-10-05 20:42:16 -0600188#ifdef CONFIG_DM_VIDEO
189 /*
190 * We did not find a suitable stdio device. If there is a video
191 * driver with a name starting with 'vidconsole', we can try probing
192 * that in the hope that it will produce the required stdio device.
193 *
194 * This function is sometimes called with the entire value of
195 * 'stdout', which may include a list of devices separate by commas.
196 * Obviously this is not going to work, so we ignore that case. The
197 * call path in that case is console_init_r() -> search_device() ->
198 * stdio_get_by_name().
199 */
200 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
201 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
202 return sdev;
203#endif
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200204
205 return NULL;
206}
207
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200208struct stdio_dev* stdio_clone(struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200209{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200210 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200211
212 if(!dev)
213 return NULL;
214
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200215 _dev = calloc(1, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200216
217 if(!_dev)
218 return NULL;
219
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200220 memcpy(_dev, dev, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200221
222 return _dev;
223}
wdenk91d32562002-09-18 21:21:13 +0000224
Simon Glass5d609ce2014-07-23 06:55:05 -0600225int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
wdenk91d32562002-09-18 21:21:13 +0000226{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200227 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200228
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200229 _dev = stdio_clone(dev);
Jean-Christophe PLAGNIOL-VILLARD3d85c432008-09-01 17:11:26 +0200230 if(!_dev)
Simon Glass5d609ce2014-07-23 06:55:05 -0600231 return -ENODEV;
Stefan Roesec3be13b2008-09-05 10:47:46 +0200232 list_add_tail(&(_dev->list), &(devs.list));
Simon Glass5d609ce2014-07-23 06:55:05 -0600233 if (devp)
234 *devp = _dev;
235
wdenk91d32562002-09-18 21:21:13 +0000236 return 0;
237}
238
Simon Glass5d609ce2014-07-23 06:55:05 -0600239int stdio_register(struct stdio_dev *dev)
240{
241 return stdio_register_dev(dev, NULL);
242}
243
wdenk91d32562002-09-18 21:21:13 +0000244/* deregister the device "devname".
245 * returns 0 if success, -1 if device is assigned and 1 if devname not found
246 */
Simon Glass3110ece2016-10-17 20:13:02 -0600247#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
Hans de Goede1a586382014-09-20 16:54:37 +0200248int stdio_deregister_dev(struct stdio_dev *dev, int force)
wdenk91d32562002-09-18 21:21:13 +0000249{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200250 int l;
251 struct list_head *pos;
Bradley Bolen466d7392011-08-22 11:48:05 +0000252 char temp_names[3][16];
wdenk91d32562002-09-18 21:21:13 +0000253
wdenk91d32562002-09-18 21:21:13 +0000254 /* get stdio devices (ListRemoveItem changes the dev list) */
255 for (l=0 ; l< MAX_FILES; l++) {
256 if (stdio_devices[l] == dev) {
Hans de Goede1a586382014-09-20 16:54:37 +0200257 if (force) {
258 strcpy(temp_names[l], "nulldev");
259 continue;
260 }
wdenk91d32562002-09-18 21:21:13 +0000261 /* Device is assigned -> report error */
262 return -1;
263 }
264 memcpy (&temp_names[l][0],
265 stdio_devices[l]->name,
Bradley Bolen466d7392011-08-22 11:48:05 +0000266 sizeof(temp_names[l]));
wdenk91d32562002-09-18 21:21:13 +0000267 }
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200268
269 list_del(&(dev->list));
Hans de Goede35e116c2014-09-24 14:06:09 +0200270 free(dev);
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200271
wdenk91d32562002-09-18 21:21:13 +0000272 /* reassign Device list */
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200273 list_for_each(pos, &(devs.list)) {
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200274 dev = list_entry(pos, struct stdio_dev, list);
wdenk91d32562002-09-18 21:21:13 +0000275 for (l=0 ; l< MAX_FILES; l++) {
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200276 if(strcmp(dev->name, temp_names[l]) == 0)
wdenk91d32562002-09-18 21:21:13 +0000277 stdio_devices[l] = dev;
wdenk91d32562002-09-18 21:21:13 +0000278 }
279 }
280 return 0;
281}
Simon Glass5d609ce2014-07-23 06:55:05 -0600282
Hans de Goede1a586382014-09-20 16:54:37 +0200283int stdio_deregister(const char *devname, int force)
Simon Glass5d609ce2014-07-23 06:55:05 -0600284{
285 struct stdio_dev *dev;
286
287 dev = stdio_get_by_name(devname);
288
289 if (!dev) /* device not found */
290 return -ENODEV;
291
Hans de Goede1a586382014-09-20 16:54:37 +0200292 return stdio_deregister_dev(dev, force);
Simon Glass5d609ce2014-07-23 06:55:05 -0600293}
Simon Glass3110ece2016-10-17 20:13:02 -0600294#endif /* CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) */
wdenk91d32562002-09-18 21:21:13 +0000295
Simon Glass712da5e2014-09-03 17:37:01 -0600296int stdio_init_tables(void)
wdenk91d32562002-09-18 21:21:13 +0000297{
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200298#if defined(CONFIG_NEEDS_MANUAL_RELOC)
Peter Tyser9057cbf2009-09-21 11:20:36 -0500299 /* already relocated for current ARM implementation */
wdenk91d32562002-09-18 21:21:13 +0000300 ulong relocation_offset = gd->reloc_off;
wdenk56958612003-06-22 17:18:28 +0000301 int i;
wdenk91d32562002-09-18 21:21:13 +0000302
303 /* relocate device name pointers */
304 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
305 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
306 relocation_offset);
307 }
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200308#endif /* CONFIG_NEEDS_MANUAL_RELOC */
wdenk91d32562002-09-18 21:21:13 +0000309
310 /* Initialize the list */
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200311 INIT_LIST_HEAD(&(devs.list));
wdenk91d32562002-09-18 21:21:13 +0000312
Simon Glass712da5e2014-09-03 17:37:01 -0600313 return 0;
314}
315
316int stdio_add_devices(void)
317{
Simon Glassd3d40352015-10-18 21:17:15 -0600318#ifdef CONFIG_DM_KEYBOARD
319 struct udevice *dev;
320 struct uclass *uc;
321 int ret;
322
323 /*
324 * For now we probe all the devices here. At some point this should be
325 * done only when the devices are required - e.g. we have a list of
326 * input devices to start up in the stdin environment variable. That
327 * work probably makes more sense when stdio itself is converted to
328 * driver model.
329 *
330 * TODO(sjg@chromium.org): Convert changing uclass_first_device() etc.
331 * to return the device even on error. Then we could use that here.
332 */
333 ret = uclass_get(UCLASS_KEYBOARD, &uc);
334 if (ret)
335 return ret;
336
337 /* Don't report errors to the caller - assume that they are non-fatal */
338 uclass_foreach_dev(dev, uc) {
339 ret = device_probe(dev);
340 if (ret)
341 printf("Failed to probe keyboard '%s'\n", dev->name);
342 }
343#endif
Heiko Schochere0e55bc2012-01-16 21:12:24 +0000344#ifdef CONFIG_SYS_I2C
Heiko Schochere0e55bc2012-01-16 21:12:24 +0000345 i2c_init_all();
Heiko Schochere0e55bc2012-01-16 21:12:24 +0000346#else
Heiko Schochere0e55bc2012-01-16 21:12:24 +0000347#endif
Simon Glass0005cb22016-01-18 19:52:23 -0700348#ifdef CONFIG_DM_VIDEO
Simon Glass4af407f2016-10-05 20:42:16 -0600349 /*
350 * If the console setting is not in environment variables then
351 * console_init_r() will not be calling iomux_doenv() (which calls
352 * search_device()). So we will not dynamically add devices by
353 * calling stdio_probe_device().
354 *
355 * So just probe all video devices now so that whichever one is
356 * required will be available.
357 */
358#ifndef CONFIG_SYS_CONSOLE_IS_IN_ENV
Simon Glass0005cb22016-01-18 19:52:23 -0700359 struct udevice *vdev;
Simon Glassc5667f42016-01-21 19:44:49 -0700360# ifndef CONFIG_DM_KEYBOARD
361 int ret;
362# endif
Simon Glass0005cb22016-01-18 19:52:23 -0700363
364 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
365 vdev;
366 ret = uclass_next_device(&vdev))
367 ;
368 if (ret)
369 printf("%s: Video device failed (ret=%d)\n", __func__, ret);
Simon Glass4af407f2016-10-05 20:42:16 -0600370#endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */
Igor Opaniuk1f6bfad2019-05-29 09:01:43 +0000371#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
372 splash_display();
373#endif /* CONFIG_SPLASH_SCREEN && CONFIG_CMD_BMP */
Simon Glass0005cb22016-01-18 19:52:23 -0700374#else
375# if defined(CONFIG_LCD)
wdenk91d32562002-09-18 21:21:13 +0000376 drv_lcd_init ();
Simon Glass0005cb22016-01-18 19:52:23 -0700377# endif
378# if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
wdenk91d32562002-09-18 21:21:13 +0000379 drv_video_init ();
Simon Glass0005cb22016-01-18 19:52:23 -0700380# endif
381#endif /* CONFIG_DM_VIDEO */
Simon Glassd3d40352015-10-18 21:17:15 -0600382#if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
wdenk4e112c12003-06-03 23:54:09 +0000383 drv_keyboard_init ();
wdenk91d32562002-09-18 21:21:13 +0000384#endif
wdenk91d32562002-09-18 21:21:13 +0000385 drv_system_init ();
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200386 serial_stdio_init ();
wdenk29e7f5a2004-03-12 00:14:09 +0000387#ifdef CONFIG_USB_TTY
388 drv_usbtty_init ();
389#endif
wdenkb8fb6192004-08-02 21:11:11 +0000390#ifdef CONFIG_NETCONSOLE
391 drv_nc_init ();
392#endif
Mike Frysinger7504e972008-10-11 21:51:20 -0400393#ifdef CONFIG_JTAG_CONSOLE
394 drv_jtag_console_init ();
395#endif
Vadim Bendebury263a8bd2012-10-12 18:48:47 +0000396#ifdef CONFIG_CBMEM_CONSOLE
397 cbmemc_init();
398#endif
Simon Glass712da5e2014-09-03 17:37:01 -0600399
400 return 0;
401}
402
403int stdio_init(void)
404{
405 stdio_init_tables();
406 stdio_add_devices();
407
408 return 0;
wdenk91d32562002-09-18 21:21:13 +0000409}