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> 1457d92753SSimon Glass #include <dm/lists.h> 1557d92753SSimon Glass #include <dm/device-internal.h> 1657d92753SSimon Glass 1757d92753SSimon Glass DECLARE_GLOBAL_DATA_PTR; 1857d92753SSimon Glass 1957d92753SSimon Glass /* The currently-selected console serial device */ 2057d92753SSimon Glass struct udevice *cur_dev __attribute__ ((section(".data"))); 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 { 2859990bf0SSimon Glass #ifdef CONFIG_OF_CONTROL 2957d92753SSimon Glass int node; 3057d92753SSimon Glass 3157d92753SSimon Glass /* Check for a chosen console */ 3257d92753SSimon Glass node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); 3357d92753SSimon Glass if (node < 0) 3457d92753SSimon Glass node = fdtdec_get_alias_node(gd->fdt_blob, "console"); 3557d92753SSimon Glass if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) 3657d92753SSimon Glass return; 3757d92753SSimon Glass 3857d92753SSimon Glass /* 3957d92753SSimon Glass * If the console is not marked to be bound before relocation, bind 4057d92753SSimon Glass * it anyway. 4157d92753SSimon Glass */ 4257d92753SSimon Glass if (node > 0 && 4357d92753SSimon Glass !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { 4457d92753SSimon Glass if (!device_probe(cur_dev)) 4557d92753SSimon Glass return; 4657d92753SSimon Glass cur_dev = NULL; 4757d92753SSimon Glass } 4859990bf0SSimon Glass #endif 4957d92753SSimon Glass /* 5057d92753SSimon Glass * Failing that, get the device with sequence number 0, or in extremis 5157d92753SSimon Glass * just the first serial device we can find. But we insist on having 5257d92753SSimon Glass * a console (even if it is silent). 5357d92753SSimon Glass */ 5457d92753SSimon Glass if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) && 5557d92753SSimon Glass (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) 5657d92753SSimon Glass panic("No serial driver found"); 5757d92753SSimon Glass } 5857d92753SSimon Glass 5957d92753SSimon Glass /* Called prior to relocation */ 6057d92753SSimon Glass int serial_init(void) 6157d92753SSimon Glass { 6257d92753SSimon Glass serial_find_console_or_panic(); 6357d92753SSimon Glass gd->flags |= GD_FLG_SERIAL_READY; 6457d92753SSimon Glass 6557d92753SSimon Glass return 0; 6657d92753SSimon Glass } 6757d92753SSimon Glass 6857d92753SSimon Glass /* Called after relocation */ 6957d92753SSimon Glass void serial_initialize(void) 7057d92753SSimon Glass { 7157d92753SSimon Glass serial_find_console_or_panic(); 7257d92753SSimon Glass } 7357d92753SSimon Glass 74*b8893327SSimon Glass static void serial_putc_dev(struct udevice *dev, char ch) 7557d92753SSimon Glass { 7657d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 7757d92753SSimon Glass int err; 7857d92753SSimon Glass 7957d92753SSimon Glass do { 8057d92753SSimon Glass err = ops->putc(cur_dev, ch); 8157d92753SSimon Glass } while (err == -EAGAIN); 8257d92753SSimon Glass if (ch == '\n') 8357d92753SSimon Glass serial_putc('\r'); 8457d92753SSimon Glass } 8557d92753SSimon Glass 86*b8893327SSimon Glass void serial_putc(char ch) 87*b8893327SSimon Glass { 88*b8893327SSimon Glass serial_putc_dev(cur_dev, ch); 89*b8893327SSimon Glass } 90*b8893327SSimon Glass 9157d92753SSimon Glass void serial_setbrg(void) 9257d92753SSimon Glass { 9357d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 9457d92753SSimon Glass 9557d92753SSimon Glass if (ops->setbrg) 9657d92753SSimon Glass ops->setbrg(cur_dev, gd->baudrate); 9757d92753SSimon Glass } 9857d92753SSimon Glass 9957d92753SSimon Glass void serial_puts(const char *str) 10057d92753SSimon Glass { 10157d92753SSimon Glass while (*str) 10257d92753SSimon Glass serial_putc(*str++); 10357d92753SSimon Glass } 10457d92753SSimon Glass 10557d92753SSimon Glass int serial_tstc(void) 10657d92753SSimon Glass { 10757d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 10857d92753SSimon Glass 10957d92753SSimon Glass if (ops->pending) 11057d92753SSimon Glass return ops->pending(cur_dev, true); 11157d92753SSimon Glass 11257d92753SSimon Glass return 1; 11357d92753SSimon Glass } 11457d92753SSimon Glass 115*b8893327SSimon Glass static int serial_getc_dev(struct udevice *dev) 11657d92753SSimon Glass { 117*b8893327SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 11857d92753SSimon Glass int err; 11957d92753SSimon Glass 12057d92753SSimon Glass do { 121*b8893327SSimon Glass err = ops->getc(dev); 12257d92753SSimon Glass } while (err == -EAGAIN); 12357d92753SSimon Glass 12457d92753SSimon Glass return err >= 0 ? err : 0; 12557d92753SSimon Glass } 12657d92753SSimon Glass 127*b8893327SSimon Glass int serial_getc(void) 128*b8893327SSimon Glass { 129*b8893327SSimon Glass return serial_getc_dev(cur_dev); 130*b8893327SSimon Glass } 131*b8893327SSimon Glass 13257d92753SSimon Glass void serial_stdio_init(void) 13357d92753SSimon Glass { 13457d92753SSimon Glass } 13557d92753SSimon Glass 136*b8893327SSimon Glass static void serial_stub_putc(struct stdio_dev *sdev, const char ch) 13757d92753SSimon Glass { 13857d92753SSimon Glass struct udevice *dev = sdev->priv; 13957d92753SSimon Glass 140*b8893327SSimon Glass serial_putc_dev(dev, ch); 14157d92753SSimon Glass } 14257d92753SSimon Glass 14357d92753SSimon Glass void serial_stub_puts(struct stdio_dev *sdev, const char *str) 14457d92753SSimon Glass { 14557d92753SSimon Glass while (*str) 14657d92753SSimon Glass serial_stub_putc(sdev, *str++); 14757d92753SSimon Glass } 14857d92753SSimon Glass 14957d92753SSimon Glass int serial_stub_getc(struct stdio_dev *sdev) 15057d92753SSimon Glass { 15157d92753SSimon Glass struct udevice *dev = sdev->priv; 15257d92753SSimon Glass 153*b8893327SSimon Glass return serial_getc_dev(dev); 15457d92753SSimon Glass } 15557d92753SSimon Glass 15657d92753SSimon Glass int serial_stub_tstc(struct stdio_dev *sdev) 15757d92753SSimon Glass { 15857d92753SSimon Glass struct udevice *dev = sdev->priv; 15957d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 16057d92753SSimon Glass 16157d92753SSimon Glass if (ops->pending) 16257d92753SSimon Glass return ops->pending(dev, true); 16357d92753SSimon Glass 16457d92753SSimon Glass return 1; 16557d92753SSimon Glass } 16657d92753SSimon Glass 16757d92753SSimon Glass static int serial_post_probe(struct udevice *dev) 16857d92753SSimon Glass { 16957d92753SSimon Glass struct stdio_dev sdev; 17057d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 17157d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 17257d92753SSimon Glass int ret; 17357d92753SSimon Glass 17457d92753SSimon Glass /* Set the baud rate */ 17557d92753SSimon Glass if (ops->setbrg) { 17657d92753SSimon Glass ret = ops->setbrg(dev, gd->baudrate); 17757d92753SSimon Glass if (ret) 17857d92753SSimon Glass return ret; 17957d92753SSimon Glass } 18057d92753SSimon Glass 18157d92753SSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 18257d92753SSimon Glass return 0; 18357d92753SSimon Glass 18457d92753SSimon Glass memset(&sdev, '\0', sizeof(sdev)); 18557d92753SSimon Glass 18657d92753SSimon Glass strncpy(sdev.name, dev->name, sizeof(sdev.name)); 18757d92753SSimon Glass sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 18857d92753SSimon Glass sdev.priv = dev; 18957d92753SSimon Glass sdev.putc = serial_stub_putc; 19057d92753SSimon Glass sdev.puts = serial_stub_puts; 19157d92753SSimon Glass sdev.getc = serial_stub_getc; 19257d92753SSimon Glass sdev.tstc = serial_stub_tstc; 19357d92753SSimon Glass stdio_register_dev(&sdev, &upriv->sdev); 19457d92753SSimon Glass 19557d92753SSimon Glass return 0; 19657d92753SSimon Glass } 19757d92753SSimon Glass 19857d92753SSimon Glass static int serial_pre_remove(struct udevice *dev) 19957d92753SSimon Glass { 20057d92753SSimon Glass #ifdef CONFIG_SYS_STDIO_DEREGISTER 20157d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 20257d92753SSimon Glass 2034a74298cSHans de Goede if (stdio_deregister_dev(upriv->sdev, 0)) 20457d92753SSimon Glass return -EPERM; 20557d92753SSimon Glass #endif 20657d92753SSimon Glass 20757d92753SSimon Glass return 0; 20857d92753SSimon Glass } 20957d92753SSimon Glass 21057d92753SSimon Glass UCLASS_DRIVER(serial) = { 21157d92753SSimon Glass .id = UCLASS_SERIAL, 21257d92753SSimon Glass .name = "serial", 21357d92753SSimon Glass .post_probe = serial_post_probe, 21457d92753SSimon Glass .pre_remove = serial_pre_remove, 21557d92753SSimon Glass .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), 21657d92753SSimon Glass }; 217