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 { 28*59990bf0SSimon 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 } 48*59990bf0SSimon 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 7457d92753SSimon Glass void serial_putc(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 8657d92753SSimon Glass void serial_setbrg(void) 8757d92753SSimon Glass { 8857d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 8957d92753SSimon Glass 9057d92753SSimon Glass if (ops->setbrg) 9157d92753SSimon Glass ops->setbrg(cur_dev, gd->baudrate); 9257d92753SSimon Glass } 9357d92753SSimon Glass 9457d92753SSimon Glass void serial_puts(const char *str) 9557d92753SSimon Glass { 9657d92753SSimon Glass while (*str) 9757d92753SSimon Glass serial_putc(*str++); 9857d92753SSimon Glass } 9957d92753SSimon Glass 10057d92753SSimon Glass int serial_tstc(void) 10157d92753SSimon Glass { 10257d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 10357d92753SSimon Glass 10457d92753SSimon Glass if (ops->pending) 10557d92753SSimon Glass return ops->pending(cur_dev, true); 10657d92753SSimon Glass 10757d92753SSimon Glass return 1; 10857d92753SSimon Glass } 10957d92753SSimon Glass 11057d92753SSimon Glass int serial_getc(void) 11157d92753SSimon Glass { 11257d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 11357d92753SSimon Glass int err; 11457d92753SSimon Glass 11557d92753SSimon Glass do { 11657d92753SSimon Glass err = ops->getc(cur_dev); 11757d92753SSimon Glass } while (err == -EAGAIN); 11857d92753SSimon Glass 11957d92753SSimon Glass return err >= 0 ? err : 0; 12057d92753SSimon Glass } 12157d92753SSimon Glass 12257d92753SSimon Glass void serial_stdio_init(void) 12357d92753SSimon Glass { 12457d92753SSimon Glass } 12557d92753SSimon Glass 12657d92753SSimon Glass void serial_stub_putc(struct stdio_dev *sdev, const char ch) 12757d92753SSimon Glass { 12857d92753SSimon Glass struct udevice *dev = sdev->priv; 12957d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 13057d92753SSimon Glass 13157d92753SSimon Glass ops->putc(dev, ch); 13257d92753SSimon Glass } 13357d92753SSimon Glass 13457d92753SSimon Glass void serial_stub_puts(struct stdio_dev *sdev, const char *str) 13557d92753SSimon Glass { 13657d92753SSimon Glass while (*str) 13757d92753SSimon Glass serial_stub_putc(sdev, *str++); 13857d92753SSimon Glass } 13957d92753SSimon Glass 14057d92753SSimon Glass int serial_stub_getc(struct stdio_dev *sdev) 14157d92753SSimon Glass { 14257d92753SSimon Glass struct udevice *dev = sdev->priv; 14357d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 14457d92753SSimon Glass 14557d92753SSimon Glass int err; 14657d92753SSimon Glass 14757d92753SSimon Glass do { 14857d92753SSimon Glass err = ops->getc(dev); 14957d92753SSimon Glass } while (err == -EAGAIN); 15057d92753SSimon Glass 15157d92753SSimon Glass return err >= 0 ? err : 0; 15257d92753SSimon Glass } 15357d92753SSimon Glass 15457d92753SSimon Glass int serial_stub_tstc(struct stdio_dev *sdev) 15557d92753SSimon Glass { 15657d92753SSimon Glass struct udevice *dev = sdev->priv; 15757d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 15857d92753SSimon Glass 15957d92753SSimon Glass if (ops->pending) 16057d92753SSimon Glass return ops->pending(dev, true); 16157d92753SSimon Glass 16257d92753SSimon Glass return 1; 16357d92753SSimon Glass } 16457d92753SSimon Glass 16557d92753SSimon Glass static int serial_post_probe(struct udevice *dev) 16657d92753SSimon Glass { 16757d92753SSimon Glass struct stdio_dev sdev; 16857d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 16957d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 17057d92753SSimon Glass int ret; 17157d92753SSimon Glass 17257d92753SSimon Glass /* Set the baud rate */ 17357d92753SSimon Glass if (ops->setbrg) { 17457d92753SSimon Glass ret = ops->setbrg(dev, gd->baudrate); 17557d92753SSimon Glass if (ret) 17657d92753SSimon Glass return ret; 17757d92753SSimon Glass } 17857d92753SSimon Glass 17957d92753SSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 18057d92753SSimon Glass return 0; 18157d92753SSimon Glass 18257d92753SSimon Glass memset(&sdev, '\0', sizeof(sdev)); 18357d92753SSimon Glass 18457d92753SSimon Glass strncpy(sdev.name, dev->name, sizeof(sdev.name)); 18557d92753SSimon Glass sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 18657d92753SSimon Glass sdev.priv = dev; 18757d92753SSimon Glass sdev.putc = serial_stub_putc; 18857d92753SSimon Glass sdev.puts = serial_stub_puts; 18957d92753SSimon Glass sdev.getc = serial_stub_getc; 19057d92753SSimon Glass sdev.tstc = serial_stub_tstc; 19157d92753SSimon Glass stdio_register_dev(&sdev, &upriv->sdev); 19257d92753SSimon Glass 19357d92753SSimon Glass return 0; 19457d92753SSimon Glass } 19557d92753SSimon Glass 19657d92753SSimon Glass static int serial_pre_remove(struct udevice *dev) 19757d92753SSimon Glass { 19857d92753SSimon Glass #ifdef CONFIG_SYS_STDIO_DEREGISTER 19957d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 20057d92753SSimon Glass 20157d92753SSimon Glass if (stdio_deregister_dev(upriv->sdev)) 20257d92753SSimon Glass return -EPERM; 20357d92753SSimon Glass #endif 20457d92753SSimon Glass 20557d92753SSimon Glass return 0; 20657d92753SSimon Glass } 20757d92753SSimon Glass 20857d92753SSimon Glass UCLASS_DRIVER(serial) = { 20957d92753SSimon Glass .id = UCLASS_SERIAL, 21057d92753SSimon Glass .name = "serial", 21157d92753SSimon Glass .post_probe = serial_post_probe, 21257d92753SSimon Glass .pre_remove = serial_pre_remove, 21357d92753SSimon Glass .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), 21457d92753SSimon Glass }; 215