1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net>
4 *
5 * Changes for multibus/multiadapter I2C support.
6 *
7 * (C) Copyright 2000
8 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
9 */
10
11 #include <config.h>
12 #include <common.h>
13 #include <dm.h>
14 #include <errno.h>
15 #include <stdarg.h>
16 #include <malloc.h>
17 #include <stdio_dev.h>
18 #include <serial.h>
19 #include <splash.h>
20
21 #if defined(CONFIG_SYS_I2C)
22 #include <i2c.h>
23 #endif
24
25 #include <dm/device-internal.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 static struct stdio_dev devs;
30 struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
31 char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
32
33 #if defined(CONFIG_SPLASH_SCREEN) && !defined(CONFIG_SYS_DEVICE_NULLDEV)
34 #define CONFIG_SYS_DEVICE_NULLDEV 1
35 #endif
36
37 #if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
38 #define CONFIG_SYS_DEVICE_NULLDEV 1
39 #endif
40
41 #ifdef CONFIG_SYS_DEVICE_NULLDEV
nulldev_putc(struct stdio_dev * dev,const char c)42 static void nulldev_putc(struct stdio_dev *dev, const char c)
43 {
44 /* nulldev is empty! */
45 }
46
nulldev_puts(struct stdio_dev * dev,const char * s)47 static void nulldev_puts(struct stdio_dev *dev, const char *s)
48 {
49 /* nulldev is empty! */
50 }
51
nulldev_input(struct stdio_dev * dev)52 static int nulldev_input(struct stdio_dev *dev)
53 {
54 /* nulldev is empty! */
55 return 0;
56 }
57 #endif
58
stdio_serial_putc(struct stdio_dev * dev,const char c)59 static void stdio_serial_putc(struct stdio_dev *dev, const char c)
60 {
61 serial_putc(c);
62 }
63
stdio_serial_puts(struct stdio_dev * dev,const char * s)64 static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
65 {
66 serial_puts(s);
67 }
68
stdio_serial_getc(struct stdio_dev * dev)69 static int stdio_serial_getc(struct stdio_dev *dev)
70 {
71 return serial_getc();
72 }
73
stdio_serial_tstc(struct stdio_dev * dev)74 static int stdio_serial_tstc(struct stdio_dev *dev)
75 {
76 return serial_tstc();
77 }
78
79 /**************************************************************************
80 * SYSTEM DRIVERS
81 **************************************************************************
82 */
83
drv_system_init(void)84 static void drv_system_init (void)
85 {
86 struct stdio_dev dev;
87
88 memset (&dev, 0, sizeof (dev));
89
90 strcpy (dev.name, "serial");
91 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
92 dev.putc = stdio_serial_putc;
93 dev.puts = stdio_serial_puts;
94 dev.getc = stdio_serial_getc;
95 dev.tstc = stdio_serial_tstc;
96 stdio_register (&dev);
97
98 #ifdef CONFIG_SYS_DEVICE_NULLDEV
99 memset (&dev, 0, sizeof (dev));
100
101 strcpy (dev.name, "nulldev");
102 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
103 dev.putc = nulldev_putc;
104 dev.puts = nulldev_puts;
105 dev.getc = nulldev_input;
106 dev.tstc = nulldev_input;
107
108 stdio_register (&dev);
109 #endif
110 }
111
112 /**************************************************************************
113 * DEVICES
114 **************************************************************************
115 */
stdio_get_list(void)116 struct list_head* stdio_get_list(void)
117 {
118 return &(devs.list);
119 }
120
121 #ifdef CONFIG_DM_VIDEO
122 /**
123 * stdio_probe_device() - Find a device which provides the given stdio device
124 *
125 * This looks for a device of the given uclass which provides a particular
126 * stdio device. It is currently really only useful for UCLASS_VIDEO.
127 *
128 * Ultimately we want to be able to probe a device by its stdio name. At
129 * present devices register in their probe function (for video devices this
130 * is done in vidconsole_post_probe()) and we don't know what name they will
131 * use until they do so.
132 * TODO(sjg@chromium.org): We should be able to determine the name before
133 * probing, and probe the required device.
134 *
135 * @name: stdio device name (e.g. "vidconsole")
136 * id: Uclass ID of device to look for (e.g. UCLASS_VIDEO)
137 * @sdevp: Returns stdout device, if found, else NULL
138 * @return 0 if found, -ENOENT if no device found with that name, other -ve
139 * on other error
140 */
stdio_probe_device(const char * name,enum uclass_id id,struct stdio_dev ** sdevp)141 static int stdio_probe_device(const char *name, enum uclass_id id,
142 struct stdio_dev **sdevp)
143 {
144 struct stdio_dev *sdev;
145 struct udevice *dev;
146 int seq, ret;
147
148 *sdevp = NULL;
149 seq = trailing_strtoln(name, NULL);
150 if (seq == -1)
151 seq = 0;
152 ret = uclass_get_device_by_seq(id, seq, &dev);
153 if (ret == -ENODEV)
154 ret = uclass_first_device_err(id, &dev);
155 if (ret) {
156 debug("No %s device for seq %d (%s)\n", uclass_get_name(id),
157 seq, name);
158 return ret;
159 }
160 /* The device should be be the last one registered */
161 sdev = list_empty(&devs.list) ? NULL :
162 list_last_entry(&devs.list, struct stdio_dev, list);
163 if (!sdev || strcmp(sdev->name, name)) {
164 debug("Device '%s' did not register with stdio as '%s'\n",
165 dev->name, name);
166 return -ENOENT;
167 }
168 *sdevp = sdev;
169
170 return 0;
171 }
172 #endif
173
stdio_get_by_name(const char * name)174 struct stdio_dev *stdio_get_by_name(const char *name)
175 {
176 struct list_head *pos;
177 struct stdio_dev *sdev;
178
179 if (!name)
180 return NULL;
181
182 list_for_each(pos, &(devs.list)) {
183 sdev = list_entry(pos, struct stdio_dev, list);
184 if (strcmp(sdev->name, name) == 0)
185 return sdev;
186 }
187 #ifdef CONFIG_DM_VIDEO
188 /*
189 * We did not find a suitable stdio device. If there is a video
190 * driver with a name starting with 'vidconsole', we can try probing
191 * that in the hope that it will produce the required stdio device.
192 *
193 * This function is sometimes called with the entire value of
194 * 'stdout', which may include a list of devices separate by commas.
195 * Obviously this is not going to work, so we ignore that case. The
196 * call path in that case is console_init_r() -> search_device() ->
197 * stdio_get_by_name().
198 */
199 if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
200 !stdio_probe_device(name, UCLASS_VIDEO, &sdev))
201 return sdev;
202 #endif
203
204 return NULL;
205 }
206
stdio_clone(struct stdio_dev * dev)207 struct stdio_dev* stdio_clone(struct stdio_dev *dev)
208 {
209 struct stdio_dev *_dev;
210
211 if(!dev)
212 return NULL;
213
214 _dev = calloc(1, sizeof(struct stdio_dev));
215
216 if(!_dev)
217 return NULL;
218
219 memcpy(_dev, dev, sizeof(struct stdio_dev));
220
221 return _dev;
222 }
223
stdio_register_dev(struct stdio_dev * dev,struct stdio_dev ** devp)224 int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp)
225 {
226 struct stdio_dev *_dev;
227
228 _dev = stdio_clone(dev);
229 if(!_dev)
230 return -ENODEV;
231 list_add_tail(&(_dev->list), &(devs.list));
232 if (devp)
233 *devp = _dev;
234
235 return 0;
236 }
237
stdio_register(struct stdio_dev * dev)238 int stdio_register(struct stdio_dev *dev)
239 {
240 return stdio_register_dev(dev, NULL);
241 }
242
243 /* deregister the device "devname".
244 * returns 0 if success, -1 if device is assigned and 1 if devname not found
245 */
246 #if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
stdio_deregister_dev(struct stdio_dev * dev,int force)247 int stdio_deregister_dev(struct stdio_dev *dev, int force)
248 {
249 int l;
250 struct list_head *pos;
251 char temp_names[3][16];
252
253 /* get stdio devices (ListRemoveItem changes the dev list) */
254 for (l=0 ; l< MAX_FILES; l++) {
255 if (stdio_devices[l] == dev) {
256 if (force) {
257 strcpy(temp_names[l], "nulldev");
258 continue;
259 }
260 /* Device is assigned -> report error */
261 return -1;
262 }
263 memcpy (&temp_names[l][0],
264 stdio_devices[l]->name,
265 sizeof(temp_names[l]));
266 }
267
268 list_del(&(dev->list));
269 free(dev);
270
271 /* reassign Device list */
272 list_for_each(pos, &(devs.list)) {
273 dev = list_entry(pos, struct stdio_dev, list);
274 for (l=0 ; l< MAX_FILES; l++) {
275 if(strcmp(dev->name, temp_names[l]) == 0)
276 stdio_devices[l] = dev;
277 }
278 }
279 return 0;
280 }
281
stdio_deregister(const char * devname,int force)282 int stdio_deregister(const char *devname, int force)
283 {
284 struct stdio_dev *dev;
285
286 dev = stdio_get_by_name(devname);
287
288 if (!dev) /* device not found */
289 return -ENODEV;
290
291 return stdio_deregister_dev(dev, force);
292 }
293 #endif /* CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) */
294
stdio_init_tables(void)295 int stdio_init_tables(void)
296 {
297 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
298 /* already relocated for current ARM implementation */
299 ulong relocation_offset = gd->reloc_off;
300 int i;
301
302 /* relocate device name pointers */
303 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
304 stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
305 relocation_offset);
306 }
307 #endif /* CONFIG_NEEDS_MANUAL_RELOC */
308
309 /* Initialize the list */
310 INIT_LIST_HEAD(&(devs.list));
311
312 return 0;
313 }
314
stdio_add_devices(void)315 int stdio_add_devices(void)
316 {
317 #ifdef CONFIG_DM_KEYBOARD
318 struct udevice *dev;
319 struct uclass *uc;
320 int ret;
321
322 /*
323 * For now we probe all the devices here. At some point this should be
324 * done only when the devices are required - e.g. we have a list of
325 * input devices to start up in the stdin environment variable. That
326 * work probably makes more sense when stdio itself is converted to
327 * driver model.
328 *
329 * TODO(sjg@chromium.org): Convert changing uclass_first_device() etc.
330 * to return the device even on error. Then we could use that here.
331 */
332 ret = uclass_get(UCLASS_KEYBOARD, &uc);
333 if (ret)
334 return ret;
335
336 /* Don't report errors to the caller - assume that they are non-fatal */
337 uclass_foreach_dev(dev, uc) {
338 ret = device_probe(dev);
339 if (ret)
340 printf("Failed to probe keyboard '%s'\n", dev->name);
341 }
342 #endif
343 #ifdef CONFIG_SYS_I2C
344 i2c_init_all();
345 #else
346 #endif
347 #ifdef CONFIG_DM_VIDEO
348 /*
349 * If the console setting is not in environment variables then
350 * console_init_r() will not be calling iomux_doenv() (which calls
351 * search_device()). So we will not dynamically add devices by
352 * calling stdio_probe_device().
353 *
354 * So just probe all video devices now so that whichever one is
355 * required will be available.
356 */
357 #ifndef CONFIG_SYS_CONSOLE_IS_IN_ENV
358 struct udevice *vdev;
359 # ifndef CONFIG_DM_KEYBOARD
360 int ret;
361 # endif
362
363 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev);
364 vdev;
365 ret = uclass_next_device(&vdev))
366 ;
367 if (ret)
368 printf("%s: Video device failed (ret=%d)\n", __func__, ret);
369 #endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */
370 #if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
371 splash_display();
372 #endif /* CONFIG_SPLASH_SCREEN && CONFIG_CMD_BMP */
373 #else
374 # if defined(CONFIG_LCD)
375 drv_lcd_init ();
376 # endif
377 # if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
378 drv_video_init ();
379 # endif
380 #endif /* CONFIG_DM_VIDEO */
381 #if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD)
382 drv_keyboard_init ();
383 #endif
384 drv_system_init ();
385 serial_stdio_init ();
386 #ifdef CONFIG_USB_TTY
387 drv_usbtty_init ();
388 #endif
389 #ifdef CONFIG_NETCONSOLE
390 drv_nc_init ();
391 #endif
392 #ifdef CONFIG_JTAG_CONSOLE
393 drv_jtag_console_init ();
394 #endif
395 #ifdef CONFIG_CBMEM_CONSOLE
396 cbmemc_init();
397 #endif
398
399 return 0;
400 }
401
stdio_init(void)402 int stdio_init(void)
403 {
404 stdio_init_tables();
405 stdio_add_devices();
406
407 return 0;
408 }
409