blob: 33a795e7bb426d221246c8253a7472bad38dd5a3 [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>
Heiko Schocherea818db2013-01-29 08:53:15 +010021
Simon Glass69153982017-05-12 21:09:56 -060022#if defined(CONFIG_SYS_I2C)
wdenk91d32562002-09-18 21:21:13 +000023#include <i2c.h>
wdenk7f6c2cb2002-11-10 22:06:23 +000024#endif
wdenk91d32562002-09-18 21:21:13 +000025
Simon Glassb206cd72015-10-18 21:17:15 -060026#include <dm/device-internal.h>
27
Wolfgang Denkd87080b2006-03-31 18:32:53 +020028DECLARE_GLOBAL_DATA_PTR;
29
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-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
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020034static void nulldev_putc(struct stdio_dev *dev, const char c)
wdenk91d32562002-09-18 21:21:13 +000035{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020036 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000037}
38
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020039static void nulldev_puts(struct stdio_dev *dev, const char *s)
wdenk91d32562002-09-18 21:21:13 +000040{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020041 /* nulldev is empty! */
wdenk91d32562002-09-18 21:21:13 +000042}
43
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020044static int nulldev_input(struct stdio_dev *dev)
wdenk91d32562002-09-18 21:21:13 +000045{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +020046 /* nulldev is empty! */
47 return 0;
wdenk91d32562002-09-18 21:21:13 +000048}
wdenk91d32562002-09-18 21:21:13 +000049
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020050static void stdio_serial_putc(struct stdio_dev *dev, const char c)
Simon Glass709ea542014-07-23 06:54:59 -060051{
52 serial_putc(c);
53}
54
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020055static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
Simon Glass709ea542014-07-23 06:54:59 -060056{
57 serial_puts(s);
58}
59
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020060static int stdio_serial_getc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060061{
62 return serial_getc();
63}
64
Jeroen Hofstee654f8d02014-10-08 22:57:44 +020065static int stdio_serial_tstc(struct stdio_dev *dev)
Simon Glass709ea542014-07-23 06:54:59 -060066{
67 return serial_tstc();
68}
69
wdenk91d32562002-09-18 21:21:13 +000070/**************************************************************************
71 * SYSTEM DRIVERS
72 **************************************************************************
73 */
74
75static void drv_system_init (void)
76{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020077 struct stdio_dev dev;
wdenk91d32562002-09-18 21:21:13 +000078
79 memset (&dev, 0, sizeof (dev));
80
81 strcpy (dev.name, "serial");
Bin Meng1caf9342015-11-03 23:23:37 -080082 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
Simon Glass709ea542014-07-23 06:54:59 -060083 dev.putc = stdio_serial_putc;
84 dev.puts = stdio_serial_puts;
85 dev.getc = stdio_serial_getc;
86 dev.tstc = stdio_serial_tstc;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020087 stdio_register (&dev);
wdenk91d32562002-09-18 21:21:13 +000088
Simon Glass3ca06092020-08-11 11:23:37 -060089 if (CONFIG_IS_ENABLED(SYS_DEVICE_NULLDEV)) {
90 memset(&dev, '\0', sizeof(dev));
wdenk91d32562002-09-18 21:21:13 +000091
Simon Glass3ca06092020-08-11 11:23:37 -060092 strcpy(dev.name, "nulldev");
93 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
94 dev.putc = nulldev_putc;
95 dev.puts = nulldev_puts;
96 dev.getc = nulldev_input;
97 dev.tstc = nulldev_input;
wdenk91d32562002-09-18 21:21:13 +000098
Simon Glass3ca06092020-08-11 11:23:37 -060099 stdio_register(&dev);
100 }
wdenk91d32562002-09-18 21:21:13 +0000101}
102
103/**************************************************************************
104 * DEVICES
105 **************************************************************************
106 */
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200107struct list_head* stdio_get_list(void)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200108{
109 return &(devs.list);
110}
111
Simon Glassd8441ea2016-10-05 20:42:16 -0600112#ifdef CONFIG_DM_VIDEO
113/**
114 * stdio_probe_device() - Find a device which provides the given stdio device
115 *
116 * This looks for a device of the given uclass which provides a particular
117 * stdio device. It is currently really only useful for UCLASS_VIDEO.
118 *
119 * Ultimately we want to be able to probe a device by its stdio name. At
120 * present devices register in their probe function (for video devices this
121 * is done in vidconsole_post_probe()) and we don't know what name they will
122 * use until they do so.
123 * TODO(sjg@chromium.org): We should be able to determine the name before
124 * probing, and probe the required device.
125 *
126 * @name: stdio device name (e.g. "vidconsole")
127 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
128 * @sdevp: Returns stdout device, if found, else NULL
129 * @return 0 if found, -ENOENT if no device found with that name, other -ve
130 * on other error
131 */
132static int stdio_probe_device(const char *name, enum uclass_id id,
133 struct stdio_dev **sdevp)
134{
135 struct stdio_dev *sdev;
136 struct udevice *dev;
137 int seq, ret;
138
139 *sdevp = NULL;
140 seq = trailing_strtoln(name, NULL);
141 if (seq == -1)
Simon Glassd844efe2016-11-13 14:22:00 -0700142 seq = 0;
143 ret = uclass_get_device_by_seq(id, seq, &dev);
144 if (ret == -ENODEV)
Simon Glassd8441ea2016-10-05 20:42:16 -0600145 ret = uclass_first_device_err(id, &dev);
Simon Glassd8441ea2016-10-05 20:42:16 -0600146 if (ret) {
147 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
148 seq, name);
149 return ret;
150 }
151 /* The device should be be the last one registered */
152 sdev = list_empty(&devs.list) ? NULL :
153 list_last_entry(&devs.list, struct stdio_dev, list);
154 if (!sdev || strcmp(sdev->name, name)) {
155 debug("Device '%s' did not register with stdio as '%s'\n",
156 dev->name, name);
157 return -ENOENT;
158 }
159 *sdevp = sdev;
160
161 return 0;
162}
163#endif
164
Simon Glassab29a342016-11-13 14:21:59 -0700165struct stdio_dev *stdio_get_by_name(const char *name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200166{
167 struct list_head *pos;
Simon Glassd8441ea2016-10-05 20:42:16 -0600168 struct stdio_dev *sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200169
Simon Glassab29a342016-11-13 14:21:59 -0700170 if (!name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200171 return NULL;
172
173 list_for_each(pos, &(devs.list)) {
Simon Glassd8441ea2016-10-05 20:42:16 -0600174 sdev = list_entry(pos, struct stdio_dev, list);
175 if (strcmp(sdev->name, name) == 0)
176 return sdev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200177 }
Simon Glassd8441ea2016-10-05 20:42:16 -0600178#ifdef CONFIG_DM_VIDEO
179 /*
180 * We did not find a suitable stdio device. If there is a video
181 * driver with a name starting with 'vidconsole', we can try probing
182 * that in the hope that it will produce the required stdio device.
183 *
184 * This function is sometimes called with the entire value of
185 * 'stdout', which may include a list of devices separate by commas.
186 * Obviously this is not going to work, so we ignore that case. The
187 * call path in that case is console_init_r() -> search_device() ->
188 * stdio_get_by_name().
189 */
190 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
191 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
192 return sdev;
193#endif
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200194
195 return NULL;
196}
197
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200198struct stdio_dev* stdio_clone(struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200199{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200200 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200201
202 if(!dev)
203 return NULL;
204
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200205 _dev = calloc(1, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200206
207 if(!_dev)
208 return NULL;
209
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200210 memcpy(_dev, dev, sizeof(struct stdio_dev));
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200211
212 return _dev;
213}
wdenk91d32562002-09-18 21:21:13 +0000214
Simon Glassd97143a2014-07-23 06:55:05 -0600215int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
wdenk91d32562002-09-18 21:21:13 +0000216{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200217 struct stdio_dev *_dev;
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200218
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200219 _dev = stdio_clone(dev);
Jean-Christophe PLAGNIOL-VILLARD628ffd72008-09-01 17:11:26 +0200220 if(!_dev)
Simon Glassd97143a2014-07-23 06:55:05 -0600221 return -ENODEV;
Stefan Roese3e3c0262008-09-05 10:47:46 +0200222 list_add_tail(&(_dev->list), &(devs.list));
Simon Glassd97143a2014-07-23 06:55:05 -0600223 if (devp)
224 *devp = _dev;
225
wdenk91d32562002-09-18 21:21:13 +0000226 return 0;
227}
228
Simon Glassd97143a2014-07-23 06:55:05 -0600229int stdio_register(struct stdio_dev *dev)
230{
231 return stdio_register_dev(dev, NULL);
232}
233
wdenk91d32562002-09-18 21:21:13 +0000234/* deregister the device "devname".
235 * returns 0 if success, -1 if device is assigned and 1 if devname not found
236 */
Simon Glass869588d2016-10-17 20:13:02 -0600237#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
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 int l;
241 struct list_head *pos;
Bradley Bolen03bf22f2011-08-22 11:48:05 +0000242 char temp_names[3][16];
wdenk91d32562002-09-18 21:21:13 +0000243
wdenk91d32562002-09-18 21:21:13 +0000244 /* get stdio devices (ListRemoveItem changes the dev list) */
245 for (l=0 ; l< MAX_FILES; l++) {
246 if (stdio_devices[l] == dev) {
Hans de Goede32d01922014-09-20 16:54:37 +0200247 if (force) {
248 strcpy(temp_names[l], "nulldev");
249 continue;
250 }
wdenk91d32562002-09-18 21:21:13 +0000251 /* Device is assigned -> report error */
252 return -1;
253 }
254 memcpy (&temp_names[l][0],
255 stdio_devices[l]->name,
Bradley Bolen03bf22f2011-08-22 11:48:05 +0000256 sizeof(temp_names[l]));
wdenk91d32562002-09-18 21:21:13 +0000257 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200258
259 list_del(&(dev->list));
Hans de Goede88274b62014-09-24 14:06:09 +0200260 free(dev);
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200261
wdenk91d32562002-09-18 21:21:13 +0000262 /* reassign Device list */
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200263 list_for_each(pos, &(devs.list)) {
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200264 dev = list_entry(pos, struct stdio_dev, list);
wdenk91d32562002-09-18 21:21:13 +0000265 for (l=0 ; l< MAX_FILES; l++) {
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200266 if(strcmp(dev->name, temp_names[l]) == 0)
wdenk91d32562002-09-18 21:21:13 +0000267 stdio_devices[l] = dev;
wdenk91d32562002-09-18 21:21:13 +0000268 }
269 }
270 return 0;
271}
Simon Glassd97143a2014-07-23 06:55:05 -0600272
Hans de Goede32d01922014-09-20 16:54:37 +0200273int stdio_deregister(const char *devname, int force)
Simon Glassd97143a2014-07-23 06:55:05 -0600274{
275 struct stdio_dev *dev;
276
277 dev = stdio_get_by_name(devname);
278
279 if (!dev) /* device not found */
280 return -ENODEV;
281
Hans de Goede32d01922014-09-20 16:54:37 +0200282 return stdio_deregister_dev(dev, force);
Simon Glassd97143a2014-07-23 06:55:05 -0600283}
Simon Glass869588d2016-10-17 20:13:02 -0600284#endif /* CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) */
wdenk91d32562002-09-18 21:21:13 +0000285
Simon Glass9fb02492014-09-03 17:37:01 -0600286int stdio_init_tables(void)
wdenk91d32562002-09-18 21:21:13 +0000287{
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200288#if defined(CONFIG_NEEDS_MANUAL_RELOC)
Peter Tyser521af042009-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;
wdenk3595ac42003-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 Denk2e5167c2010-10-28 20:00:11 +0200298#endif /* CONFIG_NEEDS_MANUAL_RELOC */
wdenk91d32562002-09-18 21:21:13 +0000299
300 /* Initialize the list */
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200301 INIT_LIST_HEAD(&(devs.list));
wdenk91d32562002-09-18 21:21:13 +0000302
Simon Glass9fb02492014-09-03 17:37:01 -0600303 return 0;
304}
305
306int stdio_add_devices(void)
307{
Simon Glassb206cd72015-10-18 21:17:15 -0600308#ifdef CONFIG_DM_KEYBOARD
309 struct udevice *dev;
310 struct uclass *uc;
311 int ret;
312
313 /*
314 * For now we probe all the devices here. At some point this should be
315 * done only when the devices are required - e.g. we have a list of
316 * input devices to start up in the stdin environment variable. That
317 * work probably makes more sense when stdio itself is converted to
318 * driver model.
319 *
320 * TODO(sjg@chromium.org): Convert changing uclass_first_device() etc.
321 * to return the device even on error. Then we could use that here.
322 */
323 ret = uclass_get(UCLASS_KEYBOARD, &uc);
324 if (ret)
325 return ret;
326
327 /* Don't report errors to the caller - assume that they are non-fatal */
328 uclass_foreach_dev(dev, uc) {
329 ret = device_probe(dev);
330 if (ret)
331 printf("Failed to probe keyboard '%s'\n", dev->name);
332 }
333#endif
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000334#ifdef CONFIG_SYS_I2C
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000335 i2c_init_all();
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000336#else
Heiko Schocher3f4978c2012-01-16 21:12:24 +0000337#endif
Simon Glasse3b81c12016-01-18 19:52:23 -0700338#ifdef CONFIG_DM_VIDEO
Simon Glassd8441ea2016-10-05 20:42:16 -0600339 /*
340 * If the console setting is not in environment variables then
341 * console_init_r() will not be calling iomux_doenv() (which calls
342 * search_device()). So we will not dynamically add devices by
343 * calling stdio_probe_device().
344 *
345 * So just probe all video devices now so that whichever one is
346 * required will be available.
347 */
348#ifndef CONFIG_SYS_CONSOLE_IS_IN_ENV
Simon Glasse3b81c12016-01-18 19:52:23 -0700349 struct udevice *vdev;
Simon Glass35a1f0d2016-01-21 19:44:49 -0700350# ifndef CONFIG_DM_KEYBOARD
351 int ret;
352# endif
Simon Glasse3b81c12016-01-18 19:52:23 -0700353
354 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
355 vdev;
356 ret = uclass_next_device(&vdev))
357 ;
358 if (ret)
359 printf("%s: Video device failed (ret=%d)\n", __func__, ret);
Simon Glassd8441ea2016-10-05 20:42:16 -0600360#endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */
Igor Opaniuk5eb83c02019-05-29 09:01:43 +0000361#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
362 splash_display();
363#endif /* CONFIG_SPLASH_SCREEN && CONFIG_CMD_BMP */
Simon Glasse3b81c12016-01-18 19:52:23 -0700364#else
365# if defined(CONFIG_LCD)
wdenk91d32562002-09-18 21:21:13 +0000366 drv_lcd_init ();
Simon Glasse3b81c12016-01-18 19:52:23 -0700367# endif
368# if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
wdenk91d32562002-09-18 21:21:13 +0000369 drv_video_init ();
Simon Glasse3b81c12016-01-18 19:52:23 -0700370# endif
371#endif /* CONFIG_DM_VIDEO */
Simon Glassb206cd72015-10-18 21:17:15 -0600372#if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
wdenk682011f2003-06-03 23:54:09 +0000373 drv_keyboard_init ();
wdenk91d32562002-09-18 21:21:13 +0000374#endif
wdenk91d32562002-09-18 21:21:13 +0000375 drv_system_init ();
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200376 serial_stdio_init ();
wdenk232c1502004-03-12 00:14:09 +0000377#ifdef CONFIG_USB_TTY
378 drv_usbtty_init ();
379#endif
wdenk68ceb292004-08-02 21:11:11 +0000380#ifdef CONFIG_NETCONSOLE
381 drv_nc_init ();
382#endif
Mike Frysinger36ea8e92008-10-11 21:51:20 -0400383#ifdef CONFIG_JTAG_CONSOLE
384 drv_jtag_console_init ();
385#endif
Vadim Bendebury98ab4352012-10-12 18:48:47 +0000386#ifdef CONFIG_CBMEM_CONSOLE
387 cbmemc_init();
388#endif
Simon Glass9fb02492014-09-03 17:37:01 -0600389
390 return 0;
391}
392
393int stdio_init(void)
394{
395 stdio_init_tables();
396 stdio_add_devices();
397
398 return 0;
wdenk91d32562002-09-18 21:21:13 +0000399}