uboot/common/stdio.c
<<
>>
Prefs
   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
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32static struct stdio_dev devs;
  33struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL };
  34char *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
  45static void nulldev_putc(struct stdio_dev *dev, const char c)
  46{
  47        /* nulldev is empty! */
  48}
  49
  50static void nulldev_puts(struct stdio_dev *dev, const char *s)
  51{
  52        /* nulldev is empty! */
  53}
  54
  55static int nulldev_input(struct stdio_dev *dev)
  56{
  57        /* nulldev is empty! */
  58        return 0;
  59}
  60#endif
  61
  62static void stdio_serial_putc(struct stdio_dev *dev, const char c)
  63{
  64        serial_putc(c);
  65}
  66
  67static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
  68{
  69        serial_puts(s);
  70}
  71
  72static int stdio_serial_getc(struct stdio_dev *dev)
  73{
  74        return serial_getc();
  75}
  76
  77static int stdio_serial_tstc(struct stdio_dev *dev)
  78{
  79        return serial_tstc();
  80}
  81
  82/**************************************************************************
  83 * SYSTEM DRIVERS
  84 **************************************************************************
  85 */
  86
  87static 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 */
 119struct list_head* stdio_get_list(void)
 120{
 121        return &(devs.list);
 122}
 123
 124struct 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
 141struct 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
 158int 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
 172int 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
 181int 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
 216int 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
 229int 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
 249int 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
 328int stdio_init(void)
 329{
 330        stdio_init_tables();
 331        stdio_add_devices();
 332
 333        return 0;
 334}
 335