1 /* 2 * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net> 3 * 4 * Changes for multibus/multiadapter I2C support. 5 * 6 * (C) Copyright 2000 7 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include <config.h> 13 #include <common.h> 14 #include <dm.h> 15 #include <errno.h> 16 #include <stdarg.h> 17 #include <malloc.h> 18 #include <stdio_dev.h> 19 #include <serial.h> 20 #ifdef CONFIG_LOGBUFFER 21 #include <logbuff.h> 22 #endif 23 24 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) 25 #include <i2c.h> 26 #endif 27 28 #include <dm/device-internal.h> 29 30 DECLARE_GLOBAL_DATA_PTR; 31 32 static struct stdio_dev devs; 33 struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL }; 34 char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" }; 35 36 #if defined(CONFIG_SPLASH_SCREEN) && !defined(CONFIG_SYS_DEVICE_NULLDEV) 37 #define CONFIG_SYS_DEVICE_NULLDEV 1 38 #endif 39 40 #ifdef CONFIG_SYS_STDIO_DEREGISTER 41 #define CONFIG_SYS_DEVICE_NULLDEV 1 42 #endif 43 44 #ifdef CONFIG_SYS_DEVICE_NULLDEV 45 static void nulldev_putc(struct stdio_dev *dev, const char c) 46 { 47 /* nulldev is empty! */ 48 } 49 50 static void nulldev_puts(struct stdio_dev *dev, const char *s) 51 { 52 /* nulldev is empty! */ 53 } 54 55 static int nulldev_input(struct stdio_dev *dev) 56 { 57 /* nulldev is empty! */ 58 return 0; 59 } 60 #endif 61 62 static void stdio_serial_putc(struct stdio_dev *dev, const char c) 63 { 64 serial_putc(c); 65 } 66 67 static void stdio_serial_puts(struct stdio_dev *dev, const char *s) 68 { 69 serial_puts(s); 70 } 71 72 static int stdio_serial_getc(struct stdio_dev *dev) 73 { 74 return serial_getc(); 75 } 76 77 static int stdio_serial_tstc(struct stdio_dev *dev) 78 { 79 return serial_tstc(); 80 } 81 82 /************************************************************************** 83 * SYSTEM DRIVERS 84 ************************************************************************** 85 */ 86 87 static void drv_system_init (void) 88 { 89 struct stdio_dev dev; 90 91 memset (&dev, 0, sizeof (dev)); 92 93 strcpy (dev.name, "serial"); 94 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 95 dev.putc = stdio_serial_putc; 96 dev.puts = stdio_serial_puts; 97 dev.getc = stdio_serial_getc; 98 dev.tstc = stdio_serial_tstc; 99 stdio_register (&dev); 100 101 #ifdef CONFIG_SYS_DEVICE_NULLDEV 102 memset (&dev, 0, sizeof (dev)); 103 104 strcpy (dev.name, "nulldev"); 105 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 106 dev.putc = nulldev_putc; 107 dev.puts = nulldev_puts; 108 dev.getc = nulldev_input; 109 dev.tstc = nulldev_input; 110 111 stdio_register (&dev); 112 #endif 113 } 114 115 /************************************************************************** 116 * DEVICES 117 ************************************************************************** 118 */ 119 struct list_head* stdio_get_list(void) 120 { 121 return &(devs.list); 122 } 123 124 struct stdio_dev* stdio_get_by_name(const char *name) 125 { 126 struct list_head *pos; 127 struct stdio_dev *dev; 128 129 if(!name) 130 return NULL; 131 132 list_for_each(pos, &(devs.list)) { 133 dev = list_entry(pos, struct stdio_dev, list); 134 if(strcmp(dev->name, name) == 0) 135 return dev; 136 } 137 138 return NULL; 139 } 140 141 struct stdio_dev* stdio_clone(struct stdio_dev *dev) 142 { 143 struct stdio_dev *_dev; 144 145 if(!dev) 146 return NULL; 147 148 _dev = calloc(1, sizeof(struct stdio_dev)); 149 150 if(!_dev) 151 return NULL; 152 153 memcpy(_dev, dev, sizeof(struct stdio_dev)); 154 155 return _dev; 156 } 157 158 int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp) 159 { 160 struct stdio_dev *_dev; 161 162 _dev = stdio_clone(dev); 163 if(!_dev) 164 return -ENODEV; 165 list_add_tail(&(_dev->list), &(devs.list)); 166 if (devp) 167 *devp = _dev; 168 169 return 0; 170 } 171 172 int stdio_register(struct stdio_dev *dev) 173 { 174 return stdio_register_dev(dev, NULL); 175 } 176 177 /* deregister the device "devname". 178 * returns 0 if success, -1 if device is assigned and 1 if devname not found 179 */ 180 #ifdef CONFIG_SYS_STDIO_DEREGISTER 181 int stdio_deregister_dev(struct stdio_dev *dev, int force) 182 { 183 int l; 184 struct list_head *pos; 185 char temp_names[3][16]; 186 187 /* get stdio devices (ListRemoveItem changes the dev list) */ 188 for (l=0 ; l< MAX_FILES; l++) { 189 if (stdio_devices[l] == dev) { 190 if (force) { 191 strcpy(temp_names[l], "nulldev"); 192 continue; 193 } 194 /* Device is assigned -> report error */ 195 return -1; 196 } 197 memcpy (&temp_names[l][0], 198 stdio_devices[l]->name, 199 sizeof(temp_names[l])); 200 } 201 202 list_del(&(dev->list)); 203 free(dev); 204 205 /* reassign Device list */ 206 list_for_each(pos, &(devs.list)) { 207 dev = list_entry(pos, struct stdio_dev, list); 208 for (l=0 ; l< MAX_FILES; l++) { 209 if(strcmp(dev->name, temp_names[l]) == 0) 210 stdio_devices[l] = dev; 211 } 212 } 213 return 0; 214 } 215 216 int stdio_deregister(const char *devname, int force) 217 { 218 struct stdio_dev *dev; 219 220 dev = stdio_get_by_name(devname); 221 222 if (!dev) /* device not found */ 223 return -ENODEV; 224 225 return stdio_deregister_dev(dev, force); 226 } 227 #endif /* CONFIG_SYS_STDIO_DEREGISTER */ 228 229 int stdio_init_tables(void) 230 { 231 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 232 /* already relocated for current ARM implementation */ 233 ulong relocation_offset = gd->reloc_off; 234 int i; 235 236 /* relocate device name pointers */ 237 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { 238 stdio_names[i] = (char *) (((ulong) stdio_names[i]) + 239 relocation_offset); 240 } 241 #endif /* CONFIG_NEEDS_MANUAL_RELOC */ 242 243 /* Initialize the list */ 244 INIT_LIST_HEAD(&(devs.list)); 245 246 return 0; 247 } 248 249 int stdio_add_devices(void) 250 { 251 #ifdef CONFIG_DM_KEYBOARD 252 struct udevice *dev; 253 struct uclass *uc; 254 int ret; 255 256 /* 257 * For now we probe all the devices here. At some point this should be 258 * done only when the devices are required - e.g. we have a list of 259 * input devices to start up in the stdin environment variable. That 260 * work probably makes more sense when stdio itself is converted to 261 * driver model. 262 * 263 * TODO(sjg@chromium.org): Convert changing uclass_first_device() etc. 264 * to return the device even on error. Then we could use that here. 265 */ 266 ret = uclass_get(UCLASS_KEYBOARD, &uc); 267 if (ret) 268 return ret; 269 270 /* Don't report errors to the caller - assume that they are non-fatal */ 271 uclass_foreach_dev(dev, uc) { 272 ret = device_probe(dev); 273 if (ret) 274 printf("Failed to probe keyboard '%s'\n", dev->name); 275 } 276 #endif 277 #ifdef CONFIG_SYS_I2C 278 i2c_init_all(); 279 #else 280 #if defined(CONFIG_HARD_I2C) 281 i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 282 #endif 283 #endif 284 #ifdef CONFIG_DM_VIDEO 285 struct udevice *vdev; 286 # ifndef CONFIG_DM_KEYBOARD 287 int ret; 288 # endif 289 290 for (ret = uclass_first_device(UCLASS_VIDEO, &vdev); 291 vdev; 292 ret = uclass_next_device(&vdev)) 293 ; 294 if (ret) 295 printf("%s: Video device failed (ret=%d)\n", __func__, ret); 296 #else 297 # if defined(CONFIG_LCD) 298 drv_lcd_init (); 299 # endif 300 # if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) 301 drv_video_init (); 302 # endif 303 #endif /* CONFIG_DM_VIDEO */ 304 #if defined(CONFIG_KEYBOARD) && !defined(CONFIG_DM_KEYBOARD) 305 drv_keyboard_init (); 306 #endif 307 #ifdef CONFIG_LOGBUFFER 308 drv_logbuff_init (); 309 #endif 310 drv_system_init (); 311 serial_stdio_init (); 312 #ifdef CONFIG_USB_TTY 313 drv_usbtty_init (); 314 #endif 315 #ifdef CONFIG_NETCONSOLE 316 drv_nc_init (); 317 #endif 318 #ifdef CONFIG_JTAG_CONSOLE 319 drv_jtag_console_init (); 320 #endif 321 #ifdef CONFIG_CBMEM_CONSOLE 322 cbmemc_init(); 323 #endif 324 325 return 0; 326 } 327 328 int stdio_init(void) 329 { 330 stdio_init_tables(); 331 stdio_add_devices(); 332 333 return 0; 334 } 335