1 /* 2 * Copyright (c) 2014 The Chromium OS Authors. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <environment.h> 10 #include <errno.h> 11 #include <fdtdec.h> 12 #include <os.h> 13 #include <serial.h> 14 #include <stdio_dev.h> 15 #include <watchdog.h> 16 #include <dm/lists.h> 17 #include <dm/device-internal.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 /* 22 * Table with supported baudrates (defined in config_xyz.h) 23 */ 24 static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; 25 26 #ifndef CONFIG_SYS_MALLOC_F_LEN 27 #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" 28 #endif 29 30 static void serial_find_console_or_panic(void) 31 { 32 struct udevice *dev; 33 34 #ifdef CONFIG_OF_CONTROL 35 int node; 36 37 /* Check for a chosen console */ 38 node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); 39 if (node < 0) 40 node = fdt_path_offset(gd->fdt_blob, "console"); 41 if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) { 42 gd->cur_serial_dev = dev; 43 return; 44 } 45 46 /* 47 * If the console is not marked to be bound before relocation, bind 48 * it anyway. 49 */ 50 if (node > 0 && 51 !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) { 52 if (!device_probe(dev)) { 53 gd->cur_serial_dev = dev; 54 return; 55 } 56 } 57 #endif 58 /* 59 * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!). 60 * 61 * Failing that, get the device with sequence number 0, or in extremis 62 * just the first serial device we can find. But we insist on having 63 * a console (even if it is silent). 64 */ 65 #ifdef CONFIG_CONS_INDEX 66 #define INDEX (CONFIG_CONS_INDEX - 1) 67 #else 68 #define INDEX 0 69 #endif 70 if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) && 71 uclass_get_device(UCLASS_SERIAL, INDEX, &dev) && 72 (uclass_first_device(UCLASS_SERIAL, &dev) || !dev)) 73 panic("No serial driver found"); 74 #undef INDEX 75 gd->cur_serial_dev = dev; 76 } 77 78 /* Called prior to relocation */ 79 int serial_init(void) 80 { 81 serial_find_console_or_panic(); 82 gd->flags |= GD_FLG_SERIAL_READY; 83 84 return 0; 85 } 86 87 /* Called after relocation */ 88 void serial_initialize(void) 89 { 90 serial_find_console_or_panic(); 91 } 92 93 static void _serial_putc(struct udevice *dev, char ch) 94 { 95 struct dm_serial_ops *ops = serial_get_ops(dev); 96 int err; 97 98 do { 99 err = ops->putc(dev, ch); 100 } while (err == -EAGAIN); 101 if (ch == '\n') 102 _serial_putc(dev, '\r'); 103 } 104 105 static void _serial_puts(struct udevice *dev, const char *str) 106 { 107 while (*str) 108 _serial_putc(dev, *str++); 109 } 110 111 static int _serial_getc(struct udevice *dev) 112 { 113 struct dm_serial_ops *ops = serial_get_ops(dev); 114 int err; 115 116 do { 117 err = ops->getc(dev); 118 if (err == -EAGAIN) 119 WATCHDOG_RESET(); 120 } while (err == -EAGAIN); 121 122 return err >= 0 ? err : 0; 123 } 124 125 static int _serial_tstc(struct udevice *dev) 126 { 127 struct dm_serial_ops *ops = serial_get_ops(dev); 128 129 if (ops->pending) 130 return ops->pending(dev, true); 131 132 return 1; 133 } 134 135 void serial_putc(char ch) 136 { 137 _serial_putc(gd->cur_serial_dev, ch); 138 } 139 140 void serial_puts(const char *str) 141 { 142 _serial_puts(gd->cur_serial_dev, str); 143 } 144 145 int serial_getc(void) 146 { 147 return _serial_getc(gd->cur_serial_dev); 148 } 149 150 int serial_tstc(void) 151 { 152 return _serial_tstc(gd->cur_serial_dev); 153 } 154 155 void serial_setbrg(void) 156 { 157 struct dm_serial_ops *ops = serial_get_ops(gd->cur_serial_dev); 158 159 if (ops->setbrg) 160 ops->setbrg(gd->cur_serial_dev, gd->baudrate); 161 } 162 163 void serial_stdio_init(void) 164 { 165 } 166 167 #ifdef CONFIG_DM_STDIO 168 static void serial_stub_putc(struct stdio_dev *sdev, const char ch) 169 { 170 _serial_putc(sdev->priv, ch); 171 } 172 #endif 173 174 void serial_stub_puts(struct stdio_dev *sdev, const char *str) 175 { 176 _serial_puts(sdev->priv, str); 177 } 178 179 int serial_stub_getc(struct stdio_dev *sdev) 180 { 181 return _serial_getc(sdev->priv); 182 } 183 184 int serial_stub_tstc(struct stdio_dev *sdev) 185 { 186 return _serial_tstc(sdev->priv); 187 } 188 189 /** 190 * on_baudrate() - Update the actual baudrate when the env var changes 191 * 192 * This will check for a valid baudrate and only apply it if valid. 193 */ 194 static int on_baudrate(const char *name, const char *value, enum env_op op, 195 int flags) 196 { 197 int i; 198 int baudrate; 199 200 switch (op) { 201 case env_op_create: 202 case env_op_overwrite: 203 /* 204 * Switch to new baudrate if new baudrate is supported 205 */ 206 baudrate = simple_strtoul(value, NULL, 10); 207 208 /* Not actually changing */ 209 if (gd->baudrate == baudrate) 210 return 0; 211 212 for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) { 213 if (baudrate == baudrate_table[i]) 214 break; 215 } 216 if (i == ARRAY_SIZE(baudrate_table)) { 217 if ((flags & H_FORCE) == 0) 218 printf("## Baudrate %d bps not supported\n", 219 baudrate); 220 return 1; 221 } 222 if ((flags & H_INTERACTIVE) != 0) { 223 printf("## Switch baudrate to %d bps and press ENTER ...\n", 224 baudrate); 225 udelay(50000); 226 } 227 228 gd->baudrate = baudrate; 229 230 serial_setbrg(); 231 232 udelay(50000); 233 234 if ((flags & H_INTERACTIVE) != 0) 235 while (1) { 236 if (getc() == '\r') 237 break; 238 } 239 240 return 0; 241 case env_op_delete: 242 printf("## Baudrate may not be deleted\n"); 243 return 1; 244 default: 245 return 0; 246 } 247 } 248 U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); 249 250 static int serial_post_probe(struct udevice *dev) 251 { 252 struct dm_serial_ops *ops = serial_get_ops(dev); 253 #ifdef CONFIG_DM_STDIO 254 struct serial_dev_priv *upriv = dev->uclass_priv; 255 struct stdio_dev sdev; 256 #endif 257 int ret; 258 259 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 260 if (ops->setbrg) 261 ops->setbrg += gd->reloc_off; 262 if (ops->getc) 263 ops->getc += gd->reloc_off; 264 if (ops->putc) 265 ops->putc += gd->reloc_off; 266 if (ops->pending) 267 ops->pending += gd->reloc_off; 268 if (ops->clear) 269 ops->clear += gd->reloc_off; 270 #if CONFIG_POST & CONFIG_SYS_POST_UART 271 if (ops->loop) 272 ops->loop += gd->reloc_off 273 #endif 274 #endif 275 /* Set the baud rate */ 276 if (ops->setbrg) { 277 ret = ops->setbrg(dev, gd->baudrate); 278 if (ret) 279 return ret; 280 } 281 282 #ifdef CONFIG_DM_STDIO 283 if (!(gd->flags & GD_FLG_RELOC)) 284 return 0; 285 memset(&sdev, '\0', sizeof(sdev)); 286 287 strncpy(sdev.name, dev->name, sizeof(sdev.name)); 288 sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 289 sdev.priv = dev; 290 sdev.putc = serial_stub_putc; 291 sdev.puts = serial_stub_puts; 292 sdev.getc = serial_stub_getc; 293 sdev.tstc = serial_stub_tstc; 294 stdio_register_dev(&sdev, &upriv->sdev); 295 #endif 296 return 0; 297 } 298 299 static int serial_pre_remove(struct udevice *dev) 300 { 301 #ifdef CONFIG_SYS_STDIO_DEREGISTER 302 struct serial_dev_priv *upriv = dev->uclass_priv; 303 304 if (stdio_deregister_dev(upriv->sdev, 0)) 305 return -EPERM; 306 #endif 307 308 return 0; 309 } 310 311 UCLASS_DRIVER(serial) = { 312 .id = UCLASS_SERIAL, 313 .name = "serial", 314 .flags = DM_UC_FLAG_SEQ_ALIAS, 315 .post_probe = serial_post_probe, 316 .pre_remove = serial_pre_remove, 317 .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), 318 }; 319