• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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