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