157d92753SSimon Glass /* 257d92753SSimon Glass * Copyright (c) 2014 The Chromium OS Authors. 357d92753SSimon Glass * 457d92753SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 557d92753SSimon Glass */ 657d92753SSimon Glass 757d92753SSimon Glass #include <common.h> 857d92753SSimon Glass #include <dm.h> 957d92753SSimon Glass #include <errno.h> 1057d92753SSimon Glass #include <fdtdec.h> 1157d92753SSimon Glass #include <os.h> 1257d92753SSimon Glass #include <serial.h> 1357d92753SSimon Glass #include <stdio_dev.h> 14c487fd47SSimon Glass #include <watchdog.h> 1557d92753SSimon Glass #include <dm/lists.h> 1657d92753SSimon Glass #include <dm/device-internal.h> 1757d92753SSimon Glass 18c487fd47SSimon Glass #include <ns16550.h> 19c487fd47SSimon Glass 2057d92753SSimon Glass DECLARE_GLOBAL_DATA_PTR; 2157d92753SSimon Glass 2257d92753SSimon Glass /* The currently-selected console serial device */ 2357d92753SSimon Glass struct udevice *cur_dev __attribute__ ((section(".data"))); 2457d92753SSimon Glass 2557d92753SSimon Glass #ifndef CONFIG_SYS_MALLOC_F_LEN 2657d92753SSimon Glass #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" 2757d92753SSimon Glass #endif 2857d92753SSimon Glass 2957d92753SSimon Glass static void serial_find_console_or_panic(void) 3057d92753SSimon Glass { 3159990bf0SSimon Glass #ifdef CONFIG_OF_CONTROL 3257d92753SSimon Glass int node; 3357d92753SSimon Glass 3457d92753SSimon Glass /* Check for a chosen console */ 3557d92753SSimon Glass node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); 3657d92753SSimon Glass if (node < 0) 3757d92753SSimon Glass node = fdtdec_get_alias_node(gd->fdt_blob, "console"); 3857d92753SSimon Glass if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) 3957d92753SSimon Glass return; 4057d92753SSimon Glass 4157d92753SSimon Glass /* 4257d92753SSimon Glass * If the console is not marked to be bound before relocation, bind 4357d92753SSimon Glass * it anyway. 4457d92753SSimon Glass */ 4557d92753SSimon Glass if (node > 0 && 4657d92753SSimon Glass !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { 4757d92753SSimon Glass if (!device_probe(cur_dev)) 4857d92753SSimon Glass return; 4957d92753SSimon Glass cur_dev = NULL; 5057d92753SSimon Glass } 5159990bf0SSimon Glass #endif 5257d92753SSimon Glass /* 5391155c65SSimon Glass * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!). 5491155c65SSimon Glass * 5557d92753SSimon Glass * Failing that, get the device with sequence number 0, or in extremis 5657d92753SSimon Glass * just the first serial device we can find. But we insist on having 5757d92753SSimon Glass * a console (even if it is silent). 5857d92753SSimon Glass */ 5991155c65SSimon Glass #ifdef CONFIG_CONS_INDEX 6091155c65SSimon Glass #define INDEX (CONFIG_CONS_INDEX - 1) 6191155c65SSimon Glass #else 6291155c65SSimon Glass #define INDEX 0 6391155c65SSimon Glass #endif 6491155c65SSimon Glass if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) && 6591155c65SSimon Glass uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) && 6657d92753SSimon Glass (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) 6757d92753SSimon Glass panic("No serial driver found"); 6891155c65SSimon Glass #undef INDEX 6957d92753SSimon Glass } 7057d92753SSimon Glass 7157d92753SSimon Glass /* Called prior to relocation */ 7257d92753SSimon Glass int serial_init(void) 7357d92753SSimon Glass { 7457d92753SSimon Glass serial_find_console_or_panic(); 7557d92753SSimon Glass gd->flags |= GD_FLG_SERIAL_READY; 7657d92753SSimon Glass 7757d92753SSimon Glass return 0; 7857d92753SSimon Glass } 7957d92753SSimon Glass 8057d92753SSimon Glass /* Called after relocation */ 8157d92753SSimon Glass void serial_initialize(void) 8257d92753SSimon Glass { 8357d92753SSimon Glass serial_find_console_or_panic(); 8457d92753SSimon Glass } 8557d92753SSimon Glass 86*eea5a4ccSMasahiro Yamada static void _serial_putc(struct udevice *dev, char ch) 8757d92753SSimon Glass { 88bac64467SMasahiro Yamada struct dm_serial_ops *ops = serial_get_ops(dev); 8957d92753SSimon Glass int err; 9057d92753SSimon Glass 9157d92753SSimon Glass do { 92bac64467SMasahiro Yamada err = ops->putc(dev, ch); 9357d92753SSimon Glass } while (err == -EAGAIN); 9457d92753SSimon Glass if (ch == '\n') 95*eea5a4ccSMasahiro Yamada _serial_putc(dev, '\r'); 9657d92753SSimon Glass } 9757d92753SSimon Glass 98*eea5a4ccSMasahiro Yamada static void _serial_puts(struct udevice *dev, const char *str) 9957d92753SSimon Glass { 10057d92753SSimon Glass while (*str) 101*eea5a4ccSMasahiro Yamada _serial_putc(dev, *str++); 10257d92753SSimon Glass } 10357d92753SSimon Glass 104*eea5a4ccSMasahiro Yamada static int _serial_getc(struct udevice *dev) 10557d92753SSimon Glass { 106b8893327SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 10757d92753SSimon Glass int err; 10857d92753SSimon Glass 10957d92753SSimon Glass do { 110b8893327SSimon Glass err = ops->getc(dev); 111c487fd47SSimon Glass if (err == -EAGAIN) 112c487fd47SSimon Glass WATCHDOG_RESET(); 11357d92753SSimon Glass } while (err == -EAGAIN); 11457d92753SSimon Glass 11557d92753SSimon Glass return err >= 0 ? err : 0; 11657d92753SSimon Glass } 11757d92753SSimon Glass 118*eea5a4ccSMasahiro Yamada static int _serial_tstc(struct udevice *dev) 119*eea5a4ccSMasahiro Yamada { 120*eea5a4ccSMasahiro Yamada struct dm_serial_ops *ops = serial_get_ops(dev); 121*eea5a4ccSMasahiro Yamada 122*eea5a4ccSMasahiro Yamada if (ops->pending) 123*eea5a4ccSMasahiro Yamada return ops->pending(dev, true); 124*eea5a4ccSMasahiro Yamada 125*eea5a4ccSMasahiro Yamada return 1; 126*eea5a4ccSMasahiro Yamada } 127*eea5a4ccSMasahiro Yamada 128*eea5a4ccSMasahiro Yamada void serial_putc(char ch) 129*eea5a4ccSMasahiro Yamada { 130*eea5a4ccSMasahiro Yamada _serial_putc(cur_dev, ch); 131*eea5a4ccSMasahiro Yamada } 132*eea5a4ccSMasahiro Yamada 133*eea5a4ccSMasahiro Yamada void serial_puts(const char *str) 134*eea5a4ccSMasahiro Yamada { 135*eea5a4ccSMasahiro Yamada _serial_puts(cur_dev, str); 136*eea5a4ccSMasahiro Yamada } 137*eea5a4ccSMasahiro Yamada 138b8893327SSimon Glass int serial_getc(void) 139b8893327SSimon Glass { 140*eea5a4ccSMasahiro Yamada return _serial_getc(cur_dev); 141*eea5a4ccSMasahiro Yamada } 142*eea5a4ccSMasahiro Yamada 143*eea5a4ccSMasahiro Yamada int serial_tstc(void) 144*eea5a4ccSMasahiro Yamada { 145*eea5a4ccSMasahiro Yamada return _serial_tstc(cur_dev); 146*eea5a4ccSMasahiro Yamada } 147*eea5a4ccSMasahiro Yamada 148*eea5a4ccSMasahiro Yamada void serial_setbrg(void) 149*eea5a4ccSMasahiro Yamada { 150*eea5a4ccSMasahiro Yamada struct dm_serial_ops *ops = serial_get_ops(cur_dev); 151*eea5a4ccSMasahiro Yamada 152*eea5a4ccSMasahiro Yamada if (ops->setbrg) 153*eea5a4ccSMasahiro Yamada ops->setbrg(cur_dev, gd->baudrate); 154b8893327SSimon Glass } 155b8893327SSimon Glass 15657d92753SSimon Glass void serial_stdio_init(void) 15757d92753SSimon Glass { 15857d92753SSimon Glass } 15957d92753SSimon Glass 160b8893327SSimon Glass static void serial_stub_putc(struct stdio_dev *sdev, const char ch) 16157d92753SSimon Glass { 162*eea5a4ccSMasahiro Yamada _serial_putc(sdev->priv, ch); 16357d92753SSimon Glass } 16457d92753SSimon Glass 16557d92753SSimon Glass void serial_stub_puts(struct stdio_dev *sdev, const char *str) 16657d92753SSimon Glass { 167*eea5a4ccSMasahiro Yamada _serial_puts(sdev->priv, str); 16857d92753SSimon Glass } 16957d92753SSimon Glass 17057d92753SSimon Glass int serial_stub_getc(struct stdio_dev *sdev) 17157d92753SSimon Glass { 172*eea5a4ccSMasahiro Yamada return _serial_getc(sdev->priv); 17357d92753SSimon Glass } 17457d92753SSimon Glass 17557d92753SSimon Glass int serial_stub_tstc(struct stdio_dev *sdev) 17657d92753SSimon Glass { 177*eea5a4ccSMasahiro Yamada return _serial_tstc(sdev->priv); 17857d92753SSimon Glass } 17957d92753SSimon Glass 18057d92753SSimon Glass static int serial_post_probe(struct udevice *dev) 18157d92753SSimon Glass { 18257d92753SSimon Glass struct stdio_dev sdev; 18357d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 18457d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 18557d92753SSimon Glass int ret; 18657d92753SSimon Glass 18757d92753SSimon Glass /* Set the baud rate */ 18857d92753SSimon Glass if (ops->setbrg) { 18957d92753SSimon Glass ret = ops->setbrg(dev, gd->baudrate); 19057d92753SSimon Glass if (ret) 19157d92753SSimon Glass return ret; 19257d92753SSimon Glass } 19357d92753SSimon Glass 19457d92753SSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 19557d92753SSimon Glass return 0; 19657d92753SSimon Glass 19757d92753SSimon Glass memset(&sdev, '\0', sizeof(sdev)); 19857d92753SSimon Glass 19957d92753SSimon Glass strncpy(sdev.name, dev->name, sizeof(sdev.name)); 20057d92753SSimon Glass sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 20157d92753SSimon Glass sdev.priv = dev; 20257d92753SSimon Glass sdev.putc = serial_stub_putc; 20357d92753SSimon Glass sdev.puts = serial_stub_puts; 20457d92753SSimon Glass sdev.getc = serial_stub_getc; 20557d92753SSimon Glass sdev.tstc = serial_stub_tstc; 20657d92753SSimon Glass stdio_register_dev(&sdev, &upriv->sdev); 20757d92753SSimon Glass 20857d92753SSimon Glass return 0; 20957d92753SSimon Glass } 21057d92753SSimon Glass 21157d92753SSimon Glass static int serial_pre_remove(struct udevice *dev) 21257d92753SSimon Glass { 21357d92753SSimon Glass #ifdef CONFIG_SYS_STDIO_DEREGISTER 21457d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 21557d92753SSimon Glass 2164a74298cSHans de Goede if (stdio_deregister_dev(upriv->sdev, 0)) 21757d92753SSimon Glass return -EPERM; 21857d92753SSimon Glass #endif 21957d92753SSimon Glass 22057d92753SSimon Glass return 0; 22157d92753SSimon Glass } 22257d92753SSimon Glass 22357d92753SSimon Glass UCLASS_DRIVER(serial) = { 22457d92753SSimon Glass .id = UCLASS_SERIAL, 22557d92753SSimon Glass .name = "serial", 22657d92753SSimon Glass .post_probe = serial_post_probe, 22757d92753SSimon Glass .pre_remove = serial_pre_remove, 22857d92753SSimon Glass .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), 22957d92753SSimon Glass }; 230