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 201 /* reassign Device list */ 202 list_for_each(pos, &(devs.list)) { 203 dev = list_entry(pos, struct stdio_dev, list); 204 for (l=0 ; l< MAX_FILES; l++) { 205 if(strcmp(dev->name, temp_names[l]) == 0) 206 stdio_devices[l] = dev; 207 } 208 } 209 return 0; 210 } 211 212 int stdio_deregister(const char *devname, int force) 213 { 214 struct stdio_dev *dev; 215 216 dev = stdio_get_by_name(devname); 217 218 if (!dev) /* device not found */ 219 return -ENODEV; 220 221 return stdio_deregister_dev(dev, force); 222 } 223 #endif /* CONFIG_SYS_STDIO_DEREGISTER */ 224 225 int stdio_init_tables(void) 226 { 227 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 228 /* already relocated for current ARM implementation */ 229 ulong relocation_offset = gd->reloc_off; 230 int i; 231 232 /* relocate device name pointers */ 233 for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { 234 stdio_names[i] = (char *) (((ulong) stdio_names[i]) + 235 relocation_offset); 236 } 237 #endif /* CONFIG_NEEDS_MANUAL_RELOC */ 238 239 /* Initialize the list */ 240 INIT_LIST_HEAD(&(devs.list)); 241 242 return 0; 243 } 244 245 int stdio_add_devices(void) 246 { 247 #ifdef CONFIG_SYS_I2C 248 i2c_init_all(); 249 #else 250 #if defined(CONFIG_HARD_I2C) 251 i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 252 #endif 253 #endif 254 #ifdef CONFIG_LCD 255 drv_lcd_init (); 256 #endif 257 #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) 258 drv_video_init (); 259 #endif 260 #ifdef CONFIG_KEYBOARD 261 drv_keyboard_init (); 262 #endif 263 #ifdef CONFIG_LOGBUFFER 264 drv_logbuff_init (); 265 #endif 266 drv_system_init (); 267 serial_stdio_init (); 268 #ifdef CONFIG_USB_TTY 269 drv_usbtty_init (); 270 #endif 271 #ifdef CONFIG_NETCONSOLE 272 drv_nc_init (); 273 #endif 274 #ifdef CONFIG_JTAG_CONSOLE 275 drv_jtag_console_init (); 276 #endif 277 #ifdef CONFIG_CBMEM_CONSOLE 278 cbmemc_init(); 279 #endif 280 281 return 0; 282 } 283 284 int stdio_init(void) 285 { 286 stdio_init_tables(); 287 stdio_add_devices(); 288 289 return 0; 290 } 291