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