1 /* 2 * Copyright (C) 2014 Linaro Ltd. 3 * Author: Rob Herring <robh@kernel.org> 4 * 5 * Based on 8250 earlycon: 6 * (c) Copyright 2004 Hewlett-Packard Development Company, L.P. 7 * Bjorn Helgaas <bjorn.helgaas@hp.com> 8 * 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 16 #include <linux/console.h> 17 #include <linux/kernel.h> 18 #include <linux/init.h> 19 #include <linux/io.h> 20 #include <linux/serial_core.h> 21 #include <linux/sizes.h> 22 #include <linux/of.h> 23 #include <linux/of_fdt.h> 24 #include <linux/acpi.h> 25 26 #ifdef CONFIG_FIX_EARLYCON_MEM 27 #include <asm/fixmap.h> 28 #endif 29 30 #include <asm/serial.h> 31 32 static struct console early_con = { 33 .name = "uart", /* fixed up at earlycon registration */ 34 .flags = CON_PRINTBUFFER | CON_BOOT, 35 .index = 0, 36 }; 37 38 static struct earlycon_device early_console_dev = { 39 .con = &early_con, 40 }; 41 42 static void __iomem * __init earlycon_map(resource_size_t paddr, size_t size) 43 { 44 void __iomem *base; 45 #ifdef CONFIG_FIX_EARLYCON_MEM 46 set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); 47 base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); 48 base += paddr & ~PAGE_MASK; 49 #else 50 base = ioremap(paddr, size); 51 #endif 52 if (!base) 53 pr_err("%s: Couldn't map %pa\n", __func__, &paddr); 54 55 return base; 56 } 57 58 static void __init earlycon_init(struct earlycon_device *device, 59 const char *name) 60 { 61 struct console *earlycon = device->con; 62 struct uart_port *port = &device->port; 63 const char *s; 64 size_t len; 65 66 /* scan backwards from end of string for first non-numeral */ 67 for (s = name + strlen(name); 68 s > name && s[-1] >= '0' && s[-1] <= '9'; 69 s--) 70 ; 71 if (*s) 72 earlycon->index = simple_strtoul(s, NULL, 10); 73 len = s - name; 74 strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name))); 75 earlycon->data = &early_console_dev; 76 77 if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || 78 port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) 79 pr_info("%s%d at MMIO%s %pa (options '%s')\n", 80 earlycon->name, earlycon->index, 81 (port->iotype == UPIO_MEM) ? "" : 82 (port->iotype == UPIO_MEM16) ? "16" : 83 (port->iotype == UPIO_MEM32) ? "32" : "32be", 84 &port->mapbase, device->options); 85 else 86 pr_info("%s%d at I/O port 0x%lx (options '%s')\n", 87 earlycon->name, earlycon->index, 88 port->iobase, device->options); 89 } 90 91 static int __init parse_options(struct earlycon_device *device, char *options) 92 { 93 struct uart_port *port = &device->port; 94 int length; 95 resource_size_t addr; 96 97 if (uart_parse_earlycon(options, &port->iotype, &addr, &options)) 98 return -EINVAL; 99 100 switch (port->iotype) { 101 case UPIO_MEM: 102 port->mapbase = addr; 103 break; 104 case UPIO_MEM16: 105 port->regshift = 1; 106 port->mapbase = addr; 107 break; 108 case UPIO_MEM32: 109 case UPIO_MEM32BE: 110 port->regshift = 2; 111 port->mapbase = addr; 112 break; 113 case UPIO_PORT: 114 port->iobase = addr; 115 break; 116 default: 117 return -EINVAL; 118 } 119 120 if (options) { 121 device->baud = simple_strtoul(options, NULL, 0); 122 length = min(strcspn(options, " ") + 1, 123 (size_t)(sizeof(device->options))); 124 strlcpy(device->options, options, length); 125 } 126 127 return 0; 128 } 129 130 static int __init register_earlycon(char *buf, const struct earlycon_id *match) 131 { 132 int err; 133 struct uart_port *port = &early_console_dev.port; 134 135 /* On parsing error, pass the options buf to the setup function */ 136 if (buf && !parse_options(&early_console_dev, buf)) 137 buf = NULL; 138 139 spin_lock_init(&port->lock); 140 port->uartclk = BASE_BAUD * 16; 141 if (port->mapbase) 142 port->membase = earlycon_map(port->mapbase, 64); 143 144 earlycon_init(&early_console_dev, match->name); 145 err = match->setup(&early_console_dev, buf); 146 if (err < 0) 147 return err; 148 if (!early_console_dev.con->write) 149 return -ENODEV; 150 151 register_console(early_console_dev.con); 152 return 0; 153 } 154 155 /** 156 * setup_earlycon - match and register earlycon console 157 * @buf: earlycon param string 158 * 159 * Registers the earlycon console matching the earlycon specified 160 * in the param string @buf. Acceptable param strings are of the form 161 * <name>,io|mmio|mmio32|mmio32be,<addr>,<options> 162 * <name>,0x<addr>,<options> 163 * <name>,<options> 164 * <name> 165 * 166 * Only for the third form does the earlycon setup() method receive the 167 * <options> string in the 'options' parameter; all other forms set 168 * the parameter to NULL. 169 * 170 * Returns 0 if an attempt to register the earlycon was made, 171 * otherwise negative error code 172 */ 173 int __init setup_earlycon(char *buf) 174 { 175 const struct earlycon_id *match; 176 177 if (!buf || !buf[0]) 178 return -EINVAL; 179 180 if (early_con.flags & CON_ENABLED) 181 return -EALREADY; 182 183 for (match = __earlycon_table; match < __earlycon_table_end; match++) { 184 size_t len = strlen(match->name); 185 186 if (strncmp(buf, match->name, len)) 187 continue; 188 189 if (buf[len]) { 190 if (buf[len] != ',') 191 continue; 192 buf += len + 1; 193 } else 194 buf = NULL; 195 196 return register_earlycon(buf, match); 197 } 198 199 return -ENOENT; 200 } 201 202 /* 203 * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in 204 * command line does not start DT earlycon immediately, instead it defers 205 * starting it until DT/ACPI decision is made. At that time if ACPI is enabled 206 * call parse_spcr(), else call early_init_dt_scan_chosen_stdout() 207 */ 208 bool earlycon_init_is_deferred __initdata; 209 210 /* early_param wrapper for setup_earlycon() */ 211 static int __init param_setup_earlycon(char *buf) 212 { 213 int err; 214 215 /* 216 * Just 'earlycon' is a valid param for devicetree earlycons; 217 * don't generate a warning from parse_early_params() in that case 218 */ 219 if (!buf || !buf[0]) { 220 if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { 221 earlycon_init_is_deferred = true; 222 return 0; 223 } else if (!buf) { 224 return early_init_dt_scan_chosen_stdout(); 225 } 226 } 227 228 err = setup_earlycon(buf); 229 if (err == -ENOENT || err == -EALREADY) 230 return 0; 231 return err; 232 } 233 early_param("earlycon", param_setup_earlycon); 234 235 #ifdef CONFIG_OF_EARLY_FLATTREE 236 237 int __init of_setup_earlycon(const struct earlycon_id *match, 238 unsigned long node, 239 const char *options) 240 { 241 int err; 242 struct uart_port *port = &early_console_dev.port; 243 const __be32 *val; 244 bool big_endian; 245 u64 addr; 246 247 spin_lock_init(&port->lock); 248 port->iotype = UPIO_MEM; 249 addr = of_flat_dt_translate_address(node); 250 if (addr == OF_BAD_ADDR) { 251 pr_warn("[%s] bad address\n", match->name); 252 return -ENXIO; 253 } 254 port->mapbase = addr; 255 port->uartclk = BASE_BAUD * 16; 256 port->membase = earlycon_map(port->mapbase, SZ_4K); 257 258 val = of_get_flat_dt_prop(node, "reg-offset", NULL); 259 if (val) 260 port->mapbase += be32_to_cpu(*val); 261 val = of_get_flat_dt_prop(node, "reg-shift", NULL); 262 if (val) 263 port->regshift = be32_to_cpu(*val); 264 big_endian = of_get_flat_dt_prop(node, "big-endian", NULL) != NULL || 265 (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 266 of_get_flat_dt_prop(node, "native-endian", NULL) != NULL); 267 val = of_get_flat_dt_prop(node, "reg-io-width", NULL); 268 if (val) { 269 switch (be32_to_cpu(*val)) { 270 case 1: 271 port->iotype = UPIO_MEM; 272 break; 273 case 2: 274 port->iotype = UPIO_MEM16; 275 break; 276 case 4: 277 port->iotype = (big_endian) ? UPIO_MEM32BE : UPIO_MEM32; 278 break; 279 default: 280 pr_warn("[%s] unsupported reg-io-width\n", match->name); 281 return -EINVAL; 282 } 283 } 284 285 val = of_get_flat_dt_prop(node, "current-speed", NULL); 286 if (val) 287 early_console_dev.baud = be32_to_cpu(*val); 288 289 if (options) { 290 early_console_dev.baud = simple_strtoul(options, NULL, 0); 291 strlcpy(early_console_dev.options, options, 292 sizeof(early_console_dev.options)); 293 } 294 earlycon_init(&early_console_dev, match->name); 295 err = match->setup(&early_console_dev, options); 296 if (err < 0) 297 return err; 298 if (!early_console_dev.con->write) 299 return -ENODEV; 300 301 302 register_console(early_console_dev.con); 303 return 0; 304 } 305 306 #endif /* CONFIG_OF_EARLY_FLATTREE */ 307