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 #ifndef CONFIG_SYS_MALLOC_F_LEN 2357d92753SSimon Glass #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" 2457d92753SSimon Glass #endif 2557d92753SSimon Glass 2657d92753SSimon Glass static void serial_find_console_or_panic(void) 2757d92753SSimon Glass { 28*469a579dSSimon Glass struct udevice *dev; 29*469a579dSSimon Glass 3059990bf0SSimon Glass #ifdef CONFIG_OF_CONTROL 3157d92753SSimon Glass int node; 3257d92753SSimon Glass 3357d92753SSimon Glass /* Check for a chosen console */ 3457d92753SSimon Glass node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); 3557d92753SSimon Glass if (node < 0) 3657d92753SSimon Glass node = fdtdec_get_alias_node(gd->fdt_blob, "console"); 37*469a579dSSimon Glass if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) { 38*469a579dSSimon Glass gd->cur_serial_dev = dev; 3957d92753SSimon Glass return; 40*469a579dSSimon Glass } 4157d92753SSimon Glass 4257d92753SSimon Glass /* 4357d92753SSimon Glass * If the console is not marked to be bound before relocation, bind 4457d92753SSimon Glass * it anyway. 4557d92753SSimon Glass */ 4657d92753SSimon Glass if (node > 0 && 47*469a579dSSimon Glass !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) { 48*469a579dSSimon Glass if (!device_probe(dev)) { 49*469a579dSSimon Glass gd->cur_serial_dev = dev; 5057d92753SSimon Glass return; 51*469a579dSSimon Glass } 5257d92753SSimon Glass } 5359990bf0SSimon Glass #endif 5457d92753SSimon Glass /* 5591155c65SSimon Glass * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!). 5691155c65SSimon Glass * 5757d92753SSimon Glass * Failing that, get the device with sequence number 0, or in extremis 5857d92753SSimon Glass * just the first serial device we can find. But we insist on having 5957d92753SSimon Glass * a console (even if it is silent). 6057d92753SSimon Glass */ 6191155c65SSimon Glass #ifdef CONFIG_CONS_INDEX 6291155c65SSimon Glass #define INDEX (CONFIG_CONS_INDEX - 1) 6391155c65SSimon Glass #else 6491155c65SSimon Glass #define INDEX 0 6591155c65SSimon Glass #endif 66*469a579dSSimon Glass if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) && 67*469a579dSSimon Glass uclass_get_device(UCLASS_SERIAL, INDEX, &dev) && 68*469a579dSSimon Glass (uclass_first_device(UCLASS_SERIAL, &dev) || !dev)) 6957d92753SSimon Glass panic("No serial driver found"); 7091155c65SSimon Glass #undef INDEX 71*469a579dSSimon Glass gd->cur_serial_dev = dev; 7257d92753SSimon Glass } 7357d92753SSimon Glass 7457d92753SSimon Glass /* Called prior to relocation */ 7557d92753SSimon Glass int serial_init(void) 7657d92753SSimon Glass { 7757d92753SSimon Glass serial_find_console_or_panic(); 7857d92753SSimon Glass gd->flags |= GD_FLG_SERIAL_READY; 7957d92753SSimon Glass 8057d92753SSimon Glass return 0; 8157d92753SSimon Glass } 8257d92753SSimon Glass 8357d92753SSimon Glass /* Called after relocation */ 8457d92753SSimon Glass void serial_initialize(void) 8557d92753SSimon Glass { 8657d92753SSimon Glass serial_find_console_or_panic(); 8757d92753SSimon Glass } 8857d92753SSimon Glass 89eea5a4ccSMasahiro Yamada static void _serial_putc(struct udevice *dev, char ch) 9057d92753SSimon Glass { 91bac64467SMasahiro Yamada struct dm_serial_ops *ops = serial_get_ops(dev); 9257d92753SSimon Glass int err; 9357d92753SSimon Glass 9457d92753SSimon Glass do { 95bac64467SMasahiro Yamada err = ops->putc(dev, ch); 9657d92753SSimon Glass } while (err == -EAGAIN); 9757d92753SSimon Glass if (ch == '\n') 98eea5a4ccSMasahiro Yamada _serial_putc(dev, '\r'); 9957d92753SSimon Glass } 10057d92753SSimon Glass 101eea5a4ccSMasahiro Yamada static void _serial_puts(struct udevice *dev, const char *str) 10257d92753SSimon Glass { 10357d92753SSimon Glass while (*str) 104eea5a4ccSMasahiro Yamada _serial_putc(dev, *str++); 10557d92753SSimon Glass } 10657d92753SSimon Glass 107eea5a4ccSMasahiro Yamada static int _serial_getc(struct udevice *dev) 10857d92753SSimon Glass { 109b8893327SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 11057d92753SSimon Glass int err; 11157d92753SSimon Glass 11257d92753SSimon Glass do { 113b8893327SSimon Glass err = ops->getc(dev); 114c487fd47SSimon Glass if (err == -EAGAIN) 115c487fd47SSimon Glass WATCHDOG_RESET(); 11657d92753SSimon Glass } while (err == -EAGAIN); 11757d92753SSimon Glass 11857d92753SSimon Glass return err >= 0 ? err : 0; 11957d92753SSimon Glass } 12057d92753SSimon Glass 121eea5a4ccSMasahiro Yamada static int _serial_tstc(struct udevice *dev) 122eea5a4ccSMasahiro Yamada { 123eea5a4ccSMasahiro Yamada struct dm_serial_ops *ops = serial_get_ops(dev); 124eea5a4ccSMasahiro Yamada 125eea5a4ccSMasahiro Yamada if (ops->pending) 126eea5a4ccSMasahiro Yamada return ops->pending(dev, true); 127eea5a4ccSMasahiro Yamada 128eea5a4ccSMasahiro Yamada return 1; 129eea5a4ccSMasahiro Yamada } 130eea5a4ccSMasahiro Yamada 131eea5a4ccSMasahiro Yamada void serial_putc(char ch) 132eea5a4ccSMasahiro Yamada { 133*469a579dSSimon Glass _serial_putc(gd->cur_serial_dev, ch); 134eea5a4ccSMasahiro Yamada } 135eea5a4ccSMasahiro Yamada 136eea5a4ccSMasahiro Yamada void serial_puts(const char *str) 137eea5a4ccSMasahiro Yamada { 138*469a579dSSimon Glass _serial_puts(gd->cur_serial_dev, str); 139eea5a4ccSMasahiro Yamada } 140eea5a4ccSMasahiro Yamada 141b8893327SSimon Glass int serial_getc(void) 142b8893327SSimon Glass { 143*469a579dSSimon Glass return _serial_getc(gd->cur_serial_dev); 144eea5a4ccSMasahiro Yamada } 145eea5a4ccSMasahiro Yamada 146eea5a4ccSMasahiro Yamada int serial_tstc(void) 147eea5a4ccSMasahiro Yamada { 148*469a579dSSimon Glass return _serial_tstc(gd->cur_serial_dev); 149eea5a4ccSMasahiro Yamada } 150eea5a4ccSMasahiro Yamada 151eea5a4ccSMasahiro Yamada void serial_setbrg(void) 152eea5a4ccSMasahiro Yamada { 153*469a579dSSimon Glass struct dm_serial_ops *ops = serial_get_ops(gd->cur_serial_dev); 154eea5a4ccSMasahiro Yamada 155eea5a4ccSMasahiro Yamada if (ops->setbrg) 156*469a579dSSimon Glass ops->setbrg(gd->cur_serial_dev, gd->baudrate); 157b8893327SSimon Glass } 158b8893327SSimon Glass 15957d92753SSimon Glass void serial_stdio_init(void) 16057d92753SSimon Glass { 16157d92753SSimon Glass } 16257d92753SSimon Glass 163b8893327SSimon Glass static void serial_stub_putc(struct stdio_dev *sdev, const char ch) 16457d92753SSimon Glass { 165eea5a4ccSMasahiro Yamada _serial_putc(sdev->priv, ch); 16657d92753SSimon Glass } 16757d92753SSimon Glass 16857d92753SSimon Glass void serial_stub_puts(struct stdio_dev *sdev, const char *str) 16957d92753SSimon Glass { 170eea5a4ccSMasahiro Yamada _serial_puts(sdev->priv, str); 17157d92753SSimon Glass } 17257d92753SSimon Glass 17357d92753SSimon Glass int serial_stub_getc(struct stdio_dev *sdev) 17457d92753SSimon Glass { 175eea5a4ccSMasahiro Yamada return _serial_getc(sdev->priv); 17657d92753SSimon Glass } 17757d92753SSimon Glass 17857d92753SSimon Glass int serial_stub_tstc(struct stdio_dev *sdev) 17957d92753SSimon Glass { 180eea5a4ccSMasahiro Yamada return _serial_tstc(sdev->priv); 18157d92753SSimon Glass } 18257d92753SSimon Glass 18357d92753SSimon Glass static int serial_post_probe(struct udevice *dev) 18457d92753SSimon Glass { 18557d92753SSimon Glass struct stdio_dev sdev; 18657d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 18757d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 18857d92753SSimon Glass int ret; 18957d92753SSimon Glass 19057d92753SSimon Glass /* Set the baud rate */ 19157d92753SSimon Glass if (ops->setbrg) { 19257d92753SSimon Glass ret = ops->setbrg(dev, gd->baudrate); 19357d92753SSimon Glass if (ret) 19457d92753SSimon Glass return ret; 19557d92753SSimon Glass } 19657d92753SSimon Glass 19757d92753SSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 19857d92753SSimon Glass return 0; 19957d92753SSimon Glass 20057d92753SSimon Glass memset(&sdev, '\0', sizeof(sdev)); 20157d92753SSimon Glass 20257d92753SSimon Glass strncpy(sdev.name, dev->name, sizeof(sdev.name)); 20357d92753SSimon Glass sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 20457d92753SSimon Glass sdev.priv = dev; 20557d92753SSimon Glass sdev.putc = serial_stub_putc; 20657d92753SSimon Glass sdev.puts = serial_stub_puts; 20757d92753SSimon Glass sdev.getc = serial_stub_getc; 20857d92753SSimon Glass sdev.tstc = serial_stub_tstc; 20957d92753SSimon Glass stdio_register_dev(&sdev, &upriv->sdev); 21057d92753SSimon Glass 21157d92753SSimon Glass return 0; 21257d92753SSimon Glass } 21357d92753SSimon Glass 21457d92753SSimon Glass static int serial_pre_remove(struct udevice *dev) 21557d92753SSimon Glass { 21657d92753SSimon Glass #ifdef CONFIG_SYS_STDIO_DEREGISTER 21757d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 21857d92753SSimon Glass 2194a74298cSHans de Goede if (stdio_deregister_dev(upriv->sdev, 0)) 22057d92753SSimon Glass return -EPERM; 22157d92753SSimon Glass #endif 22257d92753SSimon Glass 22357d92753SSimon Glass return 0; 22457d92753SSimon Glass } 22557d92753SSimon Glass 22657d92753SSimon Glass UCLASS_DRIVER(serial) = { 22757d92753SSimon Glass .id = UCLASS_SERIAL, 22857d92753SSimon Glass .name = "serial", 22957d92753SSimon Glass .post_probe = serial_post_probe, 23057d92753SSimon Glass .pre_remove = serial_pre_remove, 23157d92753SSimon Glass .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), 23257d92753SSimon Glass }; 233