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/mod_devicetable.h> 23 24#ifdef CONFIG_FIX_EARLYCON_MEM 25#include <asm/fixmap.h> 26#endif 27 28#include <asm/serial.h> 29 30static struct console early_con = { 31 .name = "uart", /* 8250 console switch requires this name */ 32 .flags = CON_PRINTBUFFER | CON_BOOT, 33 .index = -1, 34}; 35 36static struct earlycon_device early_console_dev = { 37 .con = &early_con, 38}; 39 40extern struct earlycon_id __earlycon_table[]; 41static const struct earlycon_id __earlycon_table_sentinel 42 __used __section(__earlycon_table_end); 43 44static const struct of_device_id __earlycon_of_table_sentinel 45 __used __section(__earlycon_of_table_end); 46 47static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) 48{ 49 void __iomem *base; 50#ifdef CONFIG_FIX_EARLYCON_MEM 51 set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); 52 base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); 53 base += paddr & ~PAGE_MASK; 54#else 55 base = ioremap(paddr, size); 56#endif 57 if (!base) 58 pr_err("%s: Couldn't map 0x%llx\n", __func__, 59 (unsigned long long)paddr); 60 61 return base; 62} 63 64static int __init parse_options(struct earlycon_device *device, char *options) 65{ 66 struct uart_port *port = &device->port; 67 int length; 68 unsigned long addr; 69 70 if (uart_parse_earlycon(options, &port->iotype, &addr, &options)) 71 return -EINVAL; 72 73 switch (port->iotype) { 74 case UPIO_MEM32: 75 case UPIO_MEM32BE: 76 port->regshift = 2; /* fall-through */ 77 case UPIO_MEM: 78 port->mapbase = addr; 79 break; 80 case UPIO_PORT: 81 port->iobase = addr; 82 break; 83 default: 84 return -EINVAL; 85 } 86 87 if (options) { 88 device->baud = simple_strtoul(options, NULL, 0); 89 length = min(strcspn(options, " ") + 1, 90 (size_t)(sizeof(device->options))); 91 strlcpy(device->options, options, length); 92 } 93 94 if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32 || 95 port->iotype == UPIO_MEM32BE) 96 pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", 97 (port->iotype == UPIO_MEM) ? "" : 98 (port->iotype == UPIO_MEM32) ? "32" : "32be", 99 (unsigned long long)port->mapbase, 100 device->options); 101 else 102 pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", 103 port->iobase, 104 device->options); 105 106 return 0; 107} 108 109static int __init register_earlycon(char *buf, const struct earlycon_id *match) 110{ 111 int err; 112 struct uart_port *port = &early_console_dev.port; 113 114 /* On parsing error, pass the options buf to the setup function */ 115 if (buf && !parse_options(&early_console_dev, buf)) 116 buf = NULL; 117 118 spin_lock_init(&port->lock); 119 port->uartclk = BASE_BAUD * 16; 120 if (port->mapbase) 121 port->membase = earlycon_map(port->mapbase, 64); 122 123 early_console_dev.con->data = &early_console_dev; 124 err = match->setup(&early_console_dev, buf); 125 if (err < 0) 126 return err; 127 if (!early_console_dev.con->write) 128 return -ENODEV; 129 130 register_console(early_console_dev.con); 131 return 0; 132} 133 134/** 135 * setup_earlycon - match and register earlycon console 136 * @buf: earlycon param string 137 * 138 * Registers the earlycon console matching the earlycon specified 139 * in the param string @buf. Acceptable param strings are of the form 140 * <name>,io|mmio|mmio32|mmio32be,<addr>,<options> 141 * <name>,0x<addr>,<options> 142 * <name>,<options> 143 * <name> 144 * 145 * Only for the third form does the earlycon setup() method receive the 146 * <options> string in the 'options' parameter; all other forms set 147 * the parameter to NULL. 148 * 149 * Returns 0 if an attempt to register the earlycon was made, 150 * otherwise negative error code 151 */ 152int __init setup_earlycon(char *buf) 153{ 154 const struct earlycon_id *match; 155 156 if (!buf || !buf[0]) 157 return -EINVAL; 158 159 if (early_con.flags & CON_ENABLED) 160 return -EALREADY; 161 162 for (match = __earlycon_table; match->name[0]; match++) { 163 size_t len = strlen(match->name); 164 165 if (strncmp(buf, match->name, len)) 166 continue; 167 168 if (buf[len]) { 169 if (buf[len] != ',') 170 continue; 171 buf += len + 1; 172 } else 173 buf = NULL; 174 175 return register_earlycon(buf, match); 176 } 177 178 return -ENOENT; 179} 180 181/* early_param wrapper for setup_earlycon() */ 182static int __init param_setup_earlycon(char *buf) 183{ 184 int err; 185 186 /* 187 * Just 'earlycon' is a valid param for devicetree earlycons; 188 * don't generate a warning from parse_early_params() in that case 189 */ 190 if (!buf || !buf[0]) 191 return 0; 192 193 err = setup_earlycon(buf); 194 if (err == -ENOENT || err == -EALREADY) 195 return 0; 196 return err; 197} 198early_param("earlycon", param_setup_earlycon); 199 200int __init of_setup_earlycon(unsigned long addr, 201 int (*setup)(struct earlycon_device *, const char *)) 202{ 203 int err; 204 struct uart_port *port = &early_console_dev.port; 205 206 spin_lock_init(&port->lock); 207 port->iotype = UPIO_MEM; 208 port->mapbase = addr; 209 port->uartclk = BASE_BAUD * 16; 210 port->membase = earlycon_map(addr, SZ_4K); 211 212 early_console_dev.con->data = &early_console_dev; 213 err = setup(&early_console_dev, NULL); 214 if (err < 0) 215 return err; 216 if (!early_console_dev.con->write) 217 return -ENODEV; 218 219 220 register_console(early_console_dev.con); 221 return 0; 222} 223