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