uboot/drivers/serial/serial-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2014 The Chromium OS Authors.
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <env_internal.h>
   9#include <errno.h>
  10#include <os.h>
  11#include <serial.h>
  12#include <stdio_dev.h>
  13#include <watchdog.h>
  14#include <dm/lists.h>
  15#include <dm/device-internal.h>
  16#include <dm/of_access.h>
  17
  18DECLARE_GLOBAL_DATA_PTR;
  19
  20/*
  21 * Table with supported baudrates (defined in config_xyz.h)
  22 */
  23static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
  24
  25#if !CONFIG_VAL(SYS_MALLOC_F_LEN)
  26#error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work"
  27#endif
  28
  29#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
  30static int serial_check_stdout(const void *blob, struct udevice **devp)
  31{
  32        int node = -1;
  33        const char *str, *p, *name;
  34        int namelen;
  35
  36        /* Check for a chosen console */
  37        str = fdtdec_get_chosen_prop(blob, "stdout-path");
  38        if (str) {
  39                p = strchr(str, ':');
  40                namelen = p ? p - str : strlen(str);
  41                node = fdt_path_offset_namelen(blob, str, namelen);
  42
  43                if (node < 0) {
  44                        /*
  45                         * Deal with things like
  46                         *      stdout-path = "serial0:115200n8";
  47                         *
  48                         * We need to look up the alias and then follow it to
  49                         * the correct node.
  50                         */
  51                        name = fdt_get_alias_namelen(blob, str, namelen);
  52                        if (name)
  53                                node = fdt_path_offset(blob, name);
  54                }
  55        }
  56
  57        if (node < 0)
  58                node = fdt_path_offset(blob, "console");
  59        if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp))
  60                return 0;
  61
  62        /*
  63         * If the console is not marked to be bound before relocation, bind it
  64         * anyway.
  65         */
  66        if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
  67                                        devp, false)) {
  68                if (!device_probe(*devp))
  69                        return 0;
  70        }
  71
  72        return -ENODEV;
  73}
  74
  75static void serial_find_console_or_panic(void)
  76{
  77        const void *blob = gd->fdt_blob;
  78        struct udevice *dev;
  79#ifdef CONFIG_SERIAL_SEARCH_ALL
  80        int ret;
  81#endif
  82
  83        if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
  84                uclass_first_device(UCLASS_SERIAL, &dev);
  85                if (dev) {
  86                        gd->cur_serial_dev = dev;
  87                        return;
  88                }
  89        } else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
  90                /* Live tree has support for stdout */
  91                if (of_live_active()) {
  92                        struct device_node *np = of_get_stdout();
  93
  94                        if (np && !uclass_get_device_by_ofnode(UCLASS_SERIAL,
  95                                        np_to_ofnode(np), &dev)) {
  96                                gd->cur_serial_dev = dev;
  97                                return;
  98                        }
  99                } else {
 100                        if (!serial_check_stdout(blob, &dev)) {
 101                                gd->cur_serial_dev = dev;
 102                                return;
 103                        }
 104                }
 105        }
 106        if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !blob) {
 107                /*
 108                 * Try to use CONFIG_CONS_INDEX if available (it is numbered
 109                 * from 1!).
 110                 *
 111                 * Failing that, get the device with sequence number 0, or in
 112                 * extremis just the first working serial device we can find.
 113                 * But we insist on having a console (even if it is silent).
 114                 */
 115#ifdef CONFIG_CONS_INDEX
 116#define INDEX (CONFIG_CONS_INDEX - 1)
 117#else
 118#define INDEX 0
 119#endif
 120
 121#ifdef CONFIG_SERIAL_SEARCH_ALL
 122                if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
 123                    !uclass_get_device(UCLASS_SERIAL, INDEX, &dev)) {
 124                        if (dev->flags & DM_FLAG_ACTIVATED) {
 125                                gd->cur_serial_dev = dev;
 126                                return;
 127                        }
 128                }
 129
 130                /* Search for any working device */
 131                for (ret = uclass_first_device_check(UCLASS_SERIAL, &dev);
 132                     dev;
 133                     ret = uclass_next_device_check(&dev)) {
 134                        if (!ret) {
 135                                /* Device did succeed probing */
 136                                gd->cur_serial_dev = dev;
 137                                return;
 138                        }
 139                }
 140#else
 141                if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
 142                    !uclass_get_device(UCLASS_SERIAL, INDEX, &dev) ||
 143                    (!uclass_first_device(UCLASS_SERIAL, &dev) && dev)) {
 144                        gd->cur_serial_dev = dev;
 145                        return;
 146                }
 147#endif
 148
 149#undef INDEX
 150        }
 151
 152#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE
 153        panic_str("No serial driver found");
 154#endif
 155}
 156#endif /* CONFIG_SERIAL_PRESENT */
 157
 158/* Called prior to relocation */
 159int serial_init(void)
 160{
 161#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
 162        serial_find_console_or_panic();
 163        gd->flags |= GD_FLG_SERIAL_READY;
 164#endif
 165
 166        return 0;
 167}
 168
 169/* Called after relocation */
 170void serial_initialize(void)
 171{
 172        serial_init();
 173}
 174
 175static void _serial_putc(struct udevice *dev, char ch)
 176{
 177        struct dm_serial_ops *ops = serial_get_ops(dev);
 178        int err;
 179
 180        if (ch == '\n')
 181                _serial_putc(dev, '\r');
 182
 183        do {
 184                err = ops->putc(dev, ch);
 185        } while (err == -EAGAIN);
 186}
 187
 188static void _serial_puts(struct udevice *dev, const char *str)
 189{
 190        while (*str)
 191                _serial_putc(dev, *str++);
 192}
 193
 194static int __serial_getc(struct udevice *dev)
 195{
 196        struct dm_serial_ops *ops = serial_get_ops(dev);
 197        int err;
 198
 199        do {
 200                err = ops->getc(dev);
 201                if (err == -EAGAIN)
 202                        WATCHDOG_RESET();
 203        } while (err == -EAGAIN);
 204
 205        return err >= 0 ? err : 0;
 206}
 207
 208static int __serial_tstc(struct udevice *dev)
 209{
 210        struct dm_serial_ops *ops = serial_get_ops(dev);
 211
 212        if (ops->pending)
 213                return ops->pending(dev, true);
 214
 215        return 1;
 216}
 217
 218#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
 219static int _serial_tstc(struct udevice *dev)
 220{
 221        struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
 222
 223        /* Read all available chars into the RX buffer */
 224        while (__serial_tstc(dev)) {
 225                upriv->buf[upriv->wr_ptr++] = __serial_getc(dev);
 226                upriv->wr_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
 227        }
 228
 229        return upriv->rd_ptr != upriv->wr_ptr ? 1 : 0;
 230}
 231
 232static int _serial_getc(struct udevice *dev)
 233{
 234        struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
 235        char val;
 236
 237        if (upriv->rd_ptr == upriv->wr_ptr)
 238                return __serial_getc(dev);
 239
 240        val = upriv->buf[upriv->rd_ptr++];
 241        upriv->rd_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
 242
 243        return val;
 244}
 245
 246#else /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
 247
 248static int _serial_getc(struct udevice *dev)
 249{
 250        return __serial_getc(dev);
 251}
 252
 253static int _serial_tstc(struct udevice *dev)
 254{
 255        return __serial_tstc(dev);
 256}
 257#endif /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
 258
 259void serial_putc(char ch)
 260{
 261        if (gd->cur_serial_dev)
 262                _serial_putc(gd->cur_serial_dev, ch);
 263}
 264
 265void serial_puts(const char *str)
 266{
 267        if (gd->cur_serial_dev)
 268                _serial_puts(gd->cur_serial_dev, str);
 269}
 270
 271int serial_getc(void)
 272{
 273        if (!gd->cur_serial_dev)
 274                return 0;
 275
 276        return _serial_getc(gd->cur_serial_dev);
 277}
 278
 279int serial_tstc(void)
 280{
 281        if (!gd->cur_serial_dev)
 282                return 0;
 283
 284        return _serial_tstc(gd->cur_serial_dev);
 285}
 286
 287void serial_setbrg(void)
 288{
 289        struct dm_serial_ops *ops;
 290
 291        if (!gd->cur_serial_dev)
 292                return;
 293
 294        ops = serial_get_ops(gd->cur_serial_dev);
 295        if (ops->setbrg)
 296                ops->setbrg(gd->cur_serial_dev, gd->baudrate);
 297}
 298
 299int serial_getconfig(struct udevice *dev, uint *config)
 300{
 301        struct dm_serial_ops *ops;
 302
 303        ops = serial_get_ops(dev);
 304        if (ops->getconfig)
 305                return ops->getconfig(dev, config);
 306
 307        return 0;
 308}
 309
 310int serial_setconfig(struct udevice *dev, uint config)
 311{
 312        struct dm_serial_ops *ops;
 313
 314        ops = serial_get_ops(dev);
 315        if (ops->setconfig)
 316                return ops->setconfig(dev, config);
 317
 318        return 0;
 319}
 320
 321int serial_getinfo(struct udevice *dev, struct serial_device_info *info)
 322{
 323        struct dm_serial_ops *ops;
 324
 325        if (!info)
 326                return -EINVAL;
 327
 328        info->baudrate = gd->baudrate;
 329
 330        ops = serial_get_ops(dev);
 331        if (ops->getinfo)
 332                return ops->getinfo(dev, info);
 333
 334        return -EINVAL;
 335}
 336
 337void serial_stdio_init(void)
 338{
 339}
 340
 341#if defined(CONFIG_DM_STDIO)
 342
 343#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
 344static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
 345{
 346        _serial_putc(sdev->priv, ch);
 347}
 348#endif
 349
 350static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
 351{
 352        _serial_puts(sdev->priv, str);
 353}
 354
 355static int serial_stub_getc(struct stdio_dev *sdev)
 356{
 357        return _serial_getc(sdev->priv);
 358}
 359
 360static int serial_stub_tstc(struct stdio_dev *sdev)
 361{
 362        return _serial_tstc(sdev->priv);
 363}
 364#endif
 365
 366/**
 367 * on_baudrate() - Update the actual baudrate when the env var changes
 368 *
 369 * This will check for a valid baudrate and only apply it if valid.
 370 */
 371static int on_baudrate(const char *name, const char *value, enum env_op op,
 372        int flags)
 373{
 374        int i;
 375        int baudrate;
 376
 377        switch (op) {
 378        case env_op_create:
 379        case env_op_overwrite:
 380                /*
 381                 * Switch to new baudrate if new baudrate is supported
 382                 */
 383                baudrate = simple_strtoul(value, NULL, 10);
 384
 385                /* Not actually changing */
 386                if (gd->baudrate == baudrate)
 387                        return 0;
 388
 389                for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
 390                        if (baudrate == baudrate_table[i])
 391                                break;
 392                }
 393                if (i == ARRAY_SIZE(baudrate_table)) {
 394                        if ((flags & H_FORCE) == 0)
 395                                printf("## Baudrate %d bps not supported\n",
 396                                       baudrate);
 397                        return 1;
 398                }
 399                if ((flags & H_INTERACTIVE) != 0) {
 400                        printf("## Switch baudrate to %d bps and press ENTER ...\n",
 401                               baudrate);
 402                        udelay(50000);
 403                }
 404
 405                gd->baudrate = baudrate;
 406
 407                serial_setbrg();
 408
 409                udelay(50000);
 410
 411                if ((flags & H_INTERACTIVE) != 0)
 412                        while (1) {
 413                                if (getc() == '\r')
 414                                        break;
 415                        }
 416
 417                return 0;
 418        case env_op_delete:
 419                printf("## Baudrate may not be deleted\n");
 420                return 1;
 421        default:
 422                return 0;
 423        }
 424}
 425U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
 426
 427#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
 428static int serial_post_probe(struct udevice *dev)
 429{
 430        struct dm_serial_ops *ops = serial_get_ops(dev);
 431#ifdef CONFIG_DM_STDIO
 432        struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
 433        struct stdio_dev sdev;
 434#endif
 435        int ret;
 436
 437#if defined(CONFIG_NEEDS_MANUAL_RELOC)
 438        if (ops->setbrg)
 439                ops->setbrg += gd->reloc_off;
 440        if (ops->getc)
 441                ops->getc += gd->reloc_off;
 442        if (ops->putc)
 443                ops->putc += gd->reloc_off;
 444        if (ops->pending)
 445                ops->pending += gd->reloc_off;
 446        if (ops->clear)
 447                ops->clear += gd->reloc_off;
 448        if (ops->getconfig)
 449                ops->getconfig += gd->reloc_off;
 450        if (ops->setconfig)
 451                ops->setconfig += gd->reloc_off;
 452#if CONFIG_POST & CONFIG_SYS_POST_UART
 453        if (ops->loop)
 454                ops->loop += gd->reloc_off;
 455#endif
 456        if (ops->getinfo)
 457                ops->getinfo += gd->reloc_off;
 458#endif
 459        /* Set the baud rate */
 460        if (ops->setbrg) {
 461                ret = ops->setbrg(dev, gd->baudrate);
 462                if (ret)
 463                        return ret;
 464        }
 465
 466#ifdef CONFIG_DM_STDIO
 467        if (!(gd->flags & GD_FLG_RELOC))
 468                return 0;
 469        memset(&sdev, '\0', sizeof(sdev));
 470
 471        strncpy(sdev.name, dev->name, sizeof(sdev.name));
 472        sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_DM;
 473        sdev.priv = dev;
 474        sdev.putc = serial_stub_putc;
 475        sdev.puts = serial_stub_puts;
 476        sdev.getc = serial_stub_getc;
 477        sdev.tstc = serial_stub_tstc;
 478
 479#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
 480        /* Allocate the RX buffer */
 481        upriv->buf = malloc(CONFIG_SERIAL_RX_BUFFER_SIZE);
 482#endif
 483
 484        stdio_register_dev(&sdev, &upriv->sdev);
 485#endif
 486        return 0;
 487}
 488
 489static int serial_pre_remove(struct udevice *dev)
 490{
 491#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
 492        struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
 493
 494        if (stdio_deregister_dev(upriv->sdev, true))
 495                return -EPERM;
 496#endif
 497
 498        return 0;
 499}
 500
 501UCLASS_DRIVER(serial) = {
 502        .id             = UCLASS_SERIAL,
 503        .name           = "serial",
 504        .flags          = DM_UC_FLAG_SEQ_ALIAS,
 505        .post_probe     = serial_post_probe,
 506        .pre_remove     = serial_pre_remove,
 507        .per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
 508};
 509#endif
 510