1*57d92753SSimon Glass /* 2*57d92753SSimon Glass * Copyright (c) 2014 The Chromium OS Authors. 3*57d92753SSimon Glass * 4*57d92753SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 5*57d92753SSimon Glass */ 6*57d92753SSimon Glass 7*57d92753SSimon Glass #include <common.h> 8*57d92753SSimon Glass #include <dm.h> 9*57d92753SSimon Glass #include <errno.h> 10*57d92753SSimon Glass #include <fdtdec.h> 11*57d92753SSimon Glass #include <os.h> 12*57d92753SSimon Glass #include <serial.h> 13*57d92753SSimon Glass #include <stdio_dev.h> 14*57d92753SSimon Glass #include <dm/lists.h> 15*57d92753SSimon Glass #include <dm/device-internal.h> 16*57d92753SSimon Glass 17*57d92753SSimon Glass DECLARE_GLOBAL_DATA_PTR; 18*57d92753SSimon Glass 19*57d92753SSimon Glass /* The currently-selected console serial device */ 20*57d92753SSimon Glass struct udevice *cur_dev __attribute__ ((section(".data"))); 21*57d92753SSimon Glass 22*57d92753SSimon Glass #ifndef CONFIG_SYS_MALLOC_F_LEN 23*57d92753SSimon Glass #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" 24*57d92753SSimon Glass #endif 25*57d92753SSimon Glass 26*57d92753SSimon Glass static void serial_find_console_or_panic(void) 27*57d92753SSimon Glass { 28*57d92753SSimon Glass int node; 29*57d92753SSimon Glass 30*57d92753SSimon Glass /* Check for a chosen console */ 31*57d92753SSimon Glass node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); 32*57d92753SSimon Glass if (node < 0) 33*57d92753SSimon Glass node = fdtdec_get_alias_node(gd->fdt_blob, "console"); 34*57d92753SSimon Glass if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) 35*57d92753SSimon Glass return; 36*57d92753SSimon Glass 37*57d92753SSimon Glass /* 38*57d92753SSimon Glass * If the console is not marked to be bound before relocation, bind 39*57d92753SSimon Glass * it anyway. 40*57d92753SSimon Glass */ 41*57d92753SSimon Glass if (node > 0 && 42*57d92753SSimon Glass !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { 43*57d92753SSimon Glass if (!device_probe(cur_dev)) 44*57d92753SSimon Glass return; 45*57d92753SSimon Glass cur_dev = NULL; 46*57d92753SSimon Glass } 47*57d92753SSimon Glass 48*57d92753SSimon Glass /* 49*57d92753SSimon Glass * Failing that, get the device with sequence number 0, or in extremis 50*57d92753SSimon Glass * just the first serial device we can find. But we insist on having 51*57d92753SSimon Glass * a console (even if it is silent). 52*57d92753SSimon Glass */ 53*57d92753SSimon Glass if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) && 54*57d92753SSimon Glass (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) 55*57d92753SSimon Glass panic("No serial driver found"); 56*57d92753SSimon Glass } 57*57d92753SSimon Glass 58*57d92753SSimon Glass /* Called prior to relocation */ 59*57d92753SSimon Glass int serial_init(void) 60*57d92753SSimon Glass { 61*57d92753SSimon Glass serial_find_console_or_panic(); 62*57d92753SSimon Glass gd->flags |= GD_FLG_SERIAL_READY; 63*57d92753SSimon Glass 64*57d92753SSimon Glass return 0; 65*57d92753SSimon Glass } 66*57d92753SSimon Glass 67*57d92753SSimon Glass /* Called after relocation */ 68*57d92753SSimon Glass void serial_initialize(void) 69*57d92753SSimon Glass { 70*57d92753SSimon Glass serial_find_console_or_panic(); 71*57d92753SSimon Glass } 72*57d92753SSimon Glass 73*57d92753SSimon Glass void serial_putc(char ch) 74*57d92753SSimon Glass { 75*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 76*57d92753SSimon Glass int err; 77*57d92753SSimon Glass 78*57d92753SSimon Glass do { 79*57d92753SSimon Glass err = ops->putc(cur_dev, ch); 80*57d92753SSimon Glass } while (err == -EAGAIN); 81*57d92753SSimon Glass if (ch == '\n') 82*57d92753SSimon Glass serial_putc('\r'); 83*57d92753SSimon Glass } 84*57d92753SSimon Glass 85*57d92753SSimon Glass void serial_setbrg(void) 86*57d92753SSimon Glass { 87*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 88*57d92753SSimon Glass 89*57d92753SSimon Glass if (ops->setbrg) 90*57d92753SSimon Glass ops->setbrg(cur_dev, gd->baudrate); 91*57d92753SSimon Glass } 92*57d92753SSimon Glass 93*57d92753SSimon Glass void serial_puts(const char *str) 94*57d92753SSimon Glass { 95*57d92753SSimon Glass while (*str) 96*57d92753SSimon Glass serial_putc(*str++); 97*57d92753SSimon Glass } 98*57d92753SSimon Glass 99*57d92753SSimon Glass int serial_tstc(void) 100*57d92753SSimon Glass { 101*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 102*57d92753SSimon Glass 103*57d92753SSimon Glass if (ops->pending) 104*57d92753SSimon Glass return ops->pending(cur_dev, true); 105*57d92753SSimon Glass 106*57d92753SSimon Glass return 1; 107*57d92753SSimon Glass } 108*57d92753SSimon Glass 109*57d92753SSimon Glass int serial_getc(void) 110*57d92753SSimon Glass { 111*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(cur_dev); 112*57d92753SSimon Glass int err; 113*57d92753SSimon Glass 114*57d92753SSimon Glass do { 115*57d92753SSimon Glass err = ops->getc(cur_dev); 116*57d92753SSimon Glass } while (err == -EAGAIN); 117*57d92753SSimon Glass 118*57d92753SSimon Glass return err >= 0 ? err : 0; 119*57d92753SSimon Glass } 120*57d92753SSimon Glass 121*57d92753SSimon Glass void serial_stdio_init(void) 122*57d92753SSimon Glass { 123*57d92753SSimon Glass } 124*57d92753SSimon Glass 125*57d92753SSimon Glass void serial_stub_putc(struct stdio_dev *sdev, const char ch) 126*57d92753SSimon Glass { 127*57d92753SSimon Glass struct udevice *dev = sdev->priv; 128*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 129*57d92753SSimon Glass 130*57d92753SSimon Glass ops->putc(dev, ch); 131*57d92753SSimon Glass } 132*57d92753SSimon Glass 133*57d92753SSimon Glass void serial_stub_puts(struct stdio_dev *sdev, const char *str) 134*57d92753SSimon Glass { 135*57d92753SSimon Glass while (*str) 136*57d92753SSimon Glass serial_stub_putc(sdev, *str++); 137*57d92753SSimon Glass } 138*57d92753SSimon Glass 139*57d92753SSimon Glass int serial_stub_getc(struct stdio_dev *sdev) 140*57d92753SSimon Glass { 141*57d92753SSimon Glass struct udevice *dev = sdev->priv; 142*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 143*57d92753SSimon Glass 144*57d92753SSimon Glass int err; 145*57d92753SSimon Glass 146*57d92753SSimon Glass do { 147*57d92753SSimon Glass err = ops->getc(dev); 148*57d92753SSimon Glass } while (err == -EAGAIN); 149*57d92753SSimon Glass 150*57d92753SSimon Glass return err >= 0 ? err : 0; 151*57d92753SSimon Glass } 152*57d92753SSimon Glass 153*57d92753SSimon Glass int serial_stub_tstc(struct stdio_dev *sdev) 154*57d92753SSimon Glass { 155*57d92753SSimon Glass struct udevice *dev = sdev->priv; 156*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 157*57d92753SSimon Glass 158*57d92753SSimon Glass if (ops->pending) 159*57d92753SSimon Glass return ops->pending(dev, true); 160*57d92753SSimon Glass 161*57d92753SSimon Glass return 1; 162*57d92753SSimon Glass } 163*57d92753SSimon Glass 164*57d92753SSimon Glass static int serial_post_probe(struct udevice *dev) 165*57d92753SSimon Glass { 166*57d92753SSimon Glass struct stdio_dev sdev; 167*57d92753SSimon Glass struct dm_serial_ops *ops = serial_get_ops(dev); 168*57d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 169*57d92753SSimon Glass int ret; 170*57d92753SSimon Glass 171*57d92753SSimon Glass /* Set the baud rate */ 172*57d92753SSimon Glass if (ops->setbrg) { 173*57d92753SSimon Glass ret = ops->setbrg(dev, gd->baudrate); 174*57d92753SSimon Glass if (ret) 175*57d92753SSimon Glass return ret; 176*57d92753SSimon Glass } 177*57d92753SSimon Glass 178*57d92753SSimon Glass if (!(gd->flags & GD_FLG_RELOC)) 179*57d92753SSimon Glass return 0; 180*57d92753SSimon Glass 181*57d92753SSimon Glass memset(&sdev, '\0', sizeof(sdev)); 182*57d92753SSimon Glass 183*57d92753SSimon Glass strncpy(sdev.name, dev->name, sizeof(sdev.name)); 184*57d92753SSimon Glass sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 185*57d92753SSimon Glass sdev.priv = dev; 186*57d92753SSimon Glass sdev.putc = serial_stub_putc; 187*57d92753SSimon Glass sdev.puts = serial_stub_puts; 188*57d92753SSimon Glass sdev.getc = serial_stub_getc; 189*57d92753SSimon Glass sdev.tstc = serial_stub_tstc; 190*57d92753SSimon Glass stdio_register_dev(&sdev, &upriv->sdev); 191*57d92753SSimon Glass 192*57d92753SSimon Glass return 0; 193*57d92753SSimon Glass } 194*57d92753SSimon Glass 195*57d92753SSimon Glass static int serial_pre_remove(struct udevice *dev) 196*57d92753SSimon Glass { 197*57d92753SSimon Glass #ifdef CONFIG_SYS_STDIO_DEREGISTER 198*57d92753SSimon Glass struct serial_dev_priv *upriv = dev->uclass_priv; 199*57d92753SSimon Glass 200*57d92753SSimon Glass if (stdio_deregister_dev(upriv->sdev)) 201*57d92753SSimon Glass return -EPERM; 202*57d92753SSimon Glass #endif 203*57d92753SSimon Glass 204*57d92753SSimon Glass return 0; 205*57d92753SSimon Glass } 206*57d92753SSimon Glass 207*57d92753SSimon Glass UCLASS_DRIVER(serial) = { 208*57d92753SSimon Glass .id = UCLASS_SERIAL, 209*57d92753SSimon Glass .name = "serial", 210*57d92753SSimon Glass .post_probe = serial_post_probe, 211*57d92753SSimon Glass .pre_remove = serial_pre_remove, 212*57d92753SSimon Glass .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), 213*57d92753SSimon Glass }; 214