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 <errno.h> 15 #include <stdarg.h> 16 #include <malloc.h> 17 #include <stdio_dev.h> 18 #include <serial.h> 19 #ifdef CONFIG_LOGBUFFER 20 #include <logbuff.h> 21 #endif 22 23 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) 24 #include <i2c.h> 25 #endif 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 #ifdef CONFIG_SYS_STDIO_DEREGISTER 38 #define CONFIG_SYS_DEVICE_NULLDEV 1 39 #endif 40 41 #ifdef CONFIG_SYS_DEVICE_NULLDEV 42 static void nulldev_putc(struct stdio_dev *dev, const char c) 43 { 44 /* nulldev is empty! */ 45 } 46 47 static void nulldev_puts(struct stdio_dev *dev, const char *s) 48 { 49 /* nulldev is empty! */ 50 } 51 52 static int nulldev_input(struct stdio_dev *dev) 53 { 54 /* nulldev is empty! */ 55 return 0; 56 } 57 #endif 58 59 static void stdio_serial_putc(struct stdio_dev *dev, const char c) 60 { 61 serial_putc(c); 62 } 63 64 static void stdio_serial_puts(struct stdio_dev *dev, const char *s) 65 { 66 serial_puts(s); 67 } 68 69 static int stdio_serial_getc(struct stdio_dev *dev) 70 { 71 return serial_getc(); 72 } 73 74 static int stdio_serial_tstc(struct stdio_dev *dev) 75 { 76 return serial_tstc(); 77 } 78 79 /************************************************************************** 80 * SYSTEM DRIVERS 81 ************************************************************************** 82 */ 83 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 | DEV_FLAGS_SYSTEM; 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 | DEV_FLAGS_SYSTEM; 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 */ 116 struct list_head* stdio_get_list(void) 117 { 118 return &(devs.list); 119 } 120 121 struct stdio_dev* stdio_get_by_name(const char *name) 122 { 123 struct list_head *pos; 124 struct stdio_dev *dev; 125 126 if(!name) 127 return NULL; 128 129 list_for_each(pos, &(devs.list)) { 130 dev = list_entry(pos, struct stdio_dev, list); 131 if(strcmp(dev->name, name) == 0) 132 return dev; 133 } 134 135 return NULL; 136 } 137 138 struct stdio_dev* stdio_clone(struct stdio_dev *dev) 139 { 140 struct stdio_dev *_dev; 141 142 if(!dev) 143 return NULL; 144 145 _dev = calloc(1, sizeof(struct stdio_dev)); 146 147 if(!_dev) 148 return NULL; 149 150 memcpy(_dev, dev, sizeof(struct stdio_dev)); 151 152 return _dev; 153 } 154 155 int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp) 156 { 157 struct stdio_dev *_dev; 158 159 _dev = stdio_clone(dev); 160 if(!_dev) 161 return -ENODEV; 162 list_add_tail(&(_dev->list), &(devs.list)); 163 if (devp) 164 *devp = _dev; 165 166 return 0; 167 } 168 169 int stdio_register(struct stdio_dev *dev) 170 { 171 return stdio_register_dev(dev, NULL); 172 } 173 174 /* deregister the device "devname". 175 * returns 0 if success, -1 if device is assigned and 1 if devname not found 176 */ 177 #ifdef CONFIG_SYS_STDIO_DEREGISTER 178 int stdio_deregister_dev(struct stdio_dev *dev, int force) 179 { 180 int l; 181 struct list_head *pos; 182 char temp_names[3][16]; 183 184 /* get stdio devices (ListRemoveItem changes the dev list) */ 185 for (l=0 ; l< MAX_FILES; l++) { 186 if (stdio_devices[l] == dev) { 187 if (force) { 188 strcpy(temp_names[l], "nulldev"); 189 continue; 190 } 191 /* Device is assigned -> report error */ 192 return -1; 193 } 194 memcpy (&temp_names[l][0], 195 stdio_devices[l]->name, 196 sizeof(temp_names[l])); 197 } 198 199 list_del(&(dev->list)); 200 free(dev); 201 202 /* reassign Device list */ 203 list_for_each(pos, &(devs.list)) { 204 dev = list_entry(pos, struct stdio_dev, list); 205 for (l=0 ; l< MAX_FILES; l++) { 206 if(strcmp(dev->name, temp_names[l]) == 0) 207 stdio_devices[l] = dev; 208 } 209 } 210 return 0; 211 } 212 213 int stdio_deregister(const char *devname, int force) 214 { 215 struct stdio_dev *dev; 216 217 dev = stdio_get_by_name(devname); 218 219 if (!dev) /* device not found */ 220 return -ENODEV; 221 222 return stdio_deregister_dev(dev, force); 223 } 224 #endif /* CONFIG_SYS_STDIO_DEREGISTER */ 225 226 int stdio_init_tables(void) 227 { 228 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 229 /* already relocated for current ARM implementation */ 230 ulong relocation_offset = gd->reloc_off; 231 int i; 232 233 /* relocate device name pointers */ 234 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { 235 stdio_names[i] = (char *) (((ulong) stdio_names[i]) + 236 relocation_offset); 237 } 238 #endif /* CONFIG_NEEDS_MANUAL_RELOC */ 239 240 /* Initialize the list */ 241 INIT_LIST_HEAD(&(devs.list)); 242 243 return 0; 244 } 245 246 int stdio_add_devices(void) 247 { 248 #ifdef CONFIG_SYS_I2C 249 i2c_init_all(); 250 #else 251 #if defined(CONFIG_HARD_I2C) 252 i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 253 #endif 254 #endif 255 #ifdef CONFIG_LCD 256 drv_lcd_init (); 257 #endif 258 #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) 259 drv_video_init (); 260 #endif 261 #ifdef CONFIG_KEYBOARD 262 drv_keyboard_init (); 263 #endif 264 #ifdef CONFIG_LOGBUFFER 265 drv_logbuff_init (); 266 #endif 267 drv_system_init (); 268 serial_stdio_init (); 269 #ifdef CONFIG_USB_TTY 270 drv_usbtty_init (); 271 #endif 272 #ifdef CONFIG_NETCONSOLE 273 drv_nc_init (); 274 #endif 275 #ifdef CONFIG_JTAG_CONSOLE 276 drv_jtag_console_init (); 277 #endif 278 #ifdef CONFIG_CBMEM_CONSOLE 279 cbmemc_init(); 280 #endif 281 282 return 0; 283 } 284 285 int stdio_init(void) 286 { 287 stdio_init_tables(); 288 stdio_add_devices(); 289 290 return 0; 291 } 292