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(resource_size_t 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 %pa\n", __func__, &paddr); 53 54 return base; 55 } 56 57 static void __init earlycon_init(struct earlycon_device *device, 58 const char *name) 59 { 60 struct console *earlycon = device->con; 61 struct uart_port *port = &device->port; 62 const char *s; 63 size_t len; 64 65 /* scan backwards from end of string for first non-numeral */ 66 for (s = name + strlen(name); 67 s > name && s[-1] >= '0' && s[-1] <= '9'; 68 s--) 69 ; 70 if (*s) 71 earlycon->index = simple_strtoul(s, NULL, 10); 72 len = s - name; 73 strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name))); 74 earlycon->data = &early_console_dev; 75 76 if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || 77 port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) 78 pr_info("%s%d at MMIO%s %pa (options '%s')\n", 79 earlycon->name, earlycon->index, 80 (port->iotype == UPIO_MEM) ? "" : 81 (port->iotype == UPIO_MEM16) ? "16" : 82 (port->iotype == UPIO_MEM32) ? "32" : "32be", 83 &port->mapbase, device->options); 84 else 85 pr_info("%s%d at I/O port 0x%lx (options '%s')\n", 86 earlycon->name, earlycon->index, 87 port->iobase, device->options); 88 } 89 90 static int __init parse_options(struct earlycon_device *device, char *options) 91 { 92 struct uart_port *port = &device->port; 93 int length; 94 resource_size_t addr; 95 96 if (uart_parse_earlycon(options, &port->iotype, &addr, &options)) 97 return -EINVAL; 98 99 switch (port->iotype) { 100 case UPIO_MEM: 101 port->mapbase = addr; 102 break; 103 case UPIO_MEM16: 104 port->regshift = 1; 105 port->mapbase = addr; 106 break; 107 case UPIO_MEM32: 108 case UPIO_MEM32BE: 109 port->regshift = 2; 110 port->mapbase = addr; 111 break; 112 case UPIO_PORT: 113 port->iobase = addr; 114 break; 115 default: 116 return -EINVAL; 117 } 118 119 if (options) { 120 device->baud = simple_strtoul(options, NULL, 0); 121 length = min(strcspn(options, " ") + 1, 122 (size_t)(sizeof(device->options))); 123 strlcpy(device->options, options, length); 124 } 125 126 return 0; 127 } 128 129 static int __init register_earlycon(char *buf, const struct earlycon_id *match) 130 { 131 int err; 132 struct uart_port *port = &early_console_dev.port; 133 134 /* On parsing error, pass the options buf to the setup function */ 135 if (buf && !parse_options(&early_console_dev, buf)) 136 buf = NULL; 137 138 spin_lock_init(&port->lock); 139 port->uartclk = BASE_BAUD * 16; 140 if (port->mapbase) 141 port->membase = earlycon_map(port->mapbase, 64); 142 143 earlycon_init(&early_console_dev, match->name); 144 err = match->setup(&early_console_dev, buf); 145 if (err < 0) 146 return err; 147 if (!early_console_dev.con->write) 148 return -ENODEV; 149 150 register_console(early_console_dev.con); 151 return 0; 152 } 153 154 /** 155 * setup_earlycon - match and register earlycon console 156 * @buf: earlycon param string 157 * 158 * Registers the earlycon console matching the earlycon specified 159 * in the param string @buf. Acceptable param strings are of the form 160 * <name>,io|mmio|mmio32|mmio32be,<addr>,<options> 161 * <name>,0x<addr>,<options> 162 * <name>,<options> 163 * <name> 164 * 165 * Only for the third form does the earlycon setup() method receive the 166 * <options> string in the 'options' parameter; all other forms set 167 * the parameter to NULL. 168 * 169 * Returns 0 if an attempt to register the earlycon was made, 170 * otherwise negative error code 171 */ 172 int __init setup_earlycon(char *buf) 173 { 174 const struct earlycon_id *match; 175 176 if (!buf || !buf[0]) 177 return -EINVAL; 178 179 if (early_con.flags & CON_ENABLED) 180 return -EALREADY; 181 182 for (match = __earlycon_table; match < __earlycon_table_end; match++) { 183 size_t len = strlen(match->name); 184 185 if (strncmp(buf, match->name, len)) 186 continue; 187 188 if (buf[len]) { 189 if (buf[len] != ',') 190 continue; 191 buf += len + 1; 192 } else 193 buf = NULL; 194 195 return register_earlycon(buf, match); 196 } 197 198 return -ENOENT; 199 } 200 201 /* early_param wrapper for setup_earlycon() */ 202 static int __init param_setup_earlycon(char *buf) 203 { 204 int err; 205 206 /* 207 * Just 'earlycon' is a valid param for devicetree earlycons; 208 * don't generate a warning from parse_early_params() in that case 209 */ 210 if (!buf || !buf[0]) 211 return 0; 212 213 err = setup_earlycon(buf); 214 if (err == -ENOENT || err == -EALREADY) 215 return 0; 216 return err; 217 } 218 early_param("earlycon", param_setup_earlycon); 219 220 #ifdef CONFIG_OF_EARLY_FLATTREE 221 222 int __init of_setup_earlycon(const struct earlycon_id *match, 223 unsigned long node, 224 const char *options) 225 { 226 int err; 227 struct uart_port *port = &early_console_dev.port; 228 const __be32 *val; 229 bool big_endian; 230 u64 addr; 231 232 spin_lock_init(&port->lock); 233 port->iotype = UPIO_MEM; 234 addr = of_flat_dt_translate_address(node); 235 if (addr == OF_BAD_ADDR) { 236 pr_warn("[%s] bad address\n", match->name); 237 return -ENXIO; 238 } 239 port->mapbase = addr; 240 port->uartclk = BASE_BAUD * 16; 241 port->membase = earlycon_map(port->mapbase, SZ_4K); 242 243 val = of_get_flat_dt_prop(node, "reg-offset", NULL); 244 if (val) 245 port->mapbase += be32_to_cpu(*val); 246 val = of_get_flat_dt_prop(node, "reg-shift", NULL); 247 if (val) 248 port->regshift = be32_to_cpu(*val); 249 big_endian = of_get_flat_dt_prop(node, "big-endian", NULL) != NULL || 250 (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 251 of_get_flat_dt_prop(node, "native-endian", NULL) != NULL); 252 val = of_get_flat_dt_prop(node, "reg-io-width", NULL); 253 if (val) { 254 switch (be32_to_cpu(*val)) { 255 case 1: 256 port->iotype = UPIO_MEM; 257 break; 258 case 2: 259 port->iotype = UPIO_MEM16; 260 break; 261 case 4: 262 port->iotype = (big_endian) ? UPIO_MEM32BE : UPIO_MEM32; 263 break; 264 default: 265 pr_warn("[%s] unsupported reg-io-width\n", match->name); 266 return -EINVAL; 267 } 268 } 269 270 if (options) { 271 strlcpy(early_console_dev.options, options, 272 sizeof(early_console_dev.options)); 273 } 274 earlycon_init(&early_console_dev, match->name); 275 err = match->setup(&early_console_dev, options); 276 if (err < 0) 277 return err; 278 if (!early_console_dev.con->write) 279 return -ENODEV; 280 281 282 register_console(early_console_dev.con); 283 return 0; 284 } 285 286 #endif /* CONFIG_OF_EARLY_FLATTREE */ 287