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 25 #ifdef CONFIG_FIX_EARLYCON_MEM 26 #include <asm/fixmap.h> 27 #endif 28 29 #include <asm/serial.h> 30 31 static struct console early_con = { 32 .name = "uart", /* fixed up at earlycon registration */ 33 .flags = CON_PRINTBUFFER | CON_BOOT, 34 .index = 0, 35 }; 36 37 static struct earlycon_device early_console_dev = { 38 .con = &early_con, 39 }; 40 41 static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) 42 { 43 void __iomem *base; 44 #ifdef CONFIG_FIX_EARLYCON_MEM 45 set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); 46 base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); 47 base += paddr & ~PAGE_MASK; 48 #else 49 base = ioremap(paddr, size); 50 #endif 51 if (!base) 52 pr_err("%s: Couldn't map 0x%llx\n", __func__, 53 (unsigned long long)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 unsigned long 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 /* early_param wrapper for setup_earlycon() */ 203 static int __init param_setup_earlycon(char *buf) 204 { 205 int err; 206 207 /* 208 * Just 'earlycon' is a valid param for devicetree earlycons; 209 * don't generate a warning from parse_early_params() in that case 210 */ 211 if (!buf || !buf[0]) 212 return 0; 213 214 err = setup_earlycon(buf); 215 if (err == -ENOENT || err == -EALREADY) 216 return 0; 217 return err; 218 } 219 early_param("earlycon", param_setup_earlycon); 220 221 #ifdef CONFIG_OF_EARLY_FLATTREE 222 223 int __init of_setup_earlycon(const struct earlycon_id *match, 224 unsigned long node, 225 const char *options) 226 { 227 int err; 228 struct uart_port *port = &early_console_dev.port; 229 const __be32 *val; 230 bool big_endian; 231 u64 addr; 232 233 spin_lock_init(&port->lock); 234 port->iotype = UPIO_MEM; 235 addr = of_flat_dt_translate_address(node); 236 if (addr == OF_BAD_ADDR) { 237 pr_warn("[%s] bad address\n", match->name); 238 return -ENXIO; 239 } 240 port->mapbase = addr; 241 port->uartclk = BASE_BAUD * 16; 242 port->membase = earlycon_map(port->mapbase, SZ_4K); 243 244 val = of_get_flat_dt_prop(node, "reg-offset", NULL); 245 if (val) 246 port->mapbase += be32_to_cpu(*val); 247 val = of_get_flat_dt_prop(node, "reg-shift", NULL); 248 if (val) 249 port->regshift = be32_to_cpu(*val); 250 big_endian = of_get_flat_dt_prop(node, "big-endian", NULL) != NULL || 251 (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 252 of_get_flat_dt_prop(node, "native-endian", NULL) != NULL); 253 val = of_get_flat_dt_prop(node, "reg-io-width", NULL); 254 if (val) { 255 switch (be32_to_cpu(*val)) { 256 case 1: 257 port->iotype = UPIO_MEM; 258 break; 259 case 2: 260 port->iotype = UPIO_MEM16; 261 break; 262 case 4: 263 port->iotype = (big_endian) ? UPIO_MEM32BE : UPIO_MEM32; 264 break; 265 default: 266 pr_warn("[%s] unsupported reg-io-width\n", match->name); 267 return -EINVAL; 268 } 269 } 270 271 if (options) { 272 strlcpy(early_console_dev.options, options, 273 sizeof(early_console_dev.options)); 274 } 275 earlycon_init(&early_console_dev, match->name); 276 err = match->setup(&early_console_dev, options); 277 if (err < 0) 278 return err; 279 if (!early_console_dev.con->write) 280 return -ENODEV; 281 282 283 register_console(early_console_dev.con); 284 return 0; 285 } 286 287 #endif /* CONFIG_OF_EARLY_FLATTREE */ 288