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