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 #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/mod_devicetable.h> 20 21 #ifdef CONFIG_FIX_EARLYCON_MEM 22 #include <asm/fixmap.h> 23 #endif 24 25 #include <asm/serial.h> 26 27 static struct console early_con = { 28 .name = "uart", /* 8250 console switch requires this name */ 29 .flags = CON_PRINTBUFFER | CON_BOOT, 30 .index = -1, 31 }; 32 33 static struct earlycon_device early_console_dev = { 34 .con = &early_con, 35 }; 36 37 static const struct of_device_id __earlycon_of_table_sentinel 38 __used __section(__earlycon_of_table_end); 39 40 static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) 41 { 42 void __iomem *base; 43 #ifdef CONFIG_FIX_EARLYCON_MEM 44 set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); 45 base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); 46 base += paddr & ~PAGE_MASK; 47 #else 48 base = ioremap(paddr, size); 49 #endif 50 if (!base) 51 pr_err("%s: Couldn't map 0x%llx\n", __func__, 52 (unsigned long long)paddr); 53 54 return base; 55 } 56 57 static int __init parse_options(struct earlycon_device *device, 58 char *options) 59 { 60 struct uart_port *port = &device->port; 61 int mmio, mmio32, length; 62 unsigned long addr; 63 64 if (!options) 65 return -ENODEV; 66 67 mmio = !strncmp(options, "mmio,", 5); 68 mmio32 = !strncmp(options, "mmio32,", 7); 69 if (mmio || mmio32) { 70 port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32); 71 options += mmio ? 5 : 7; 72 addr = simple_strtoul(options, NULL, 0); 73 port->mapbase = addr; 74 if (mmio32) 75 port->regshift = 2; 76 } else if (!strncmp(options, "io,", 3)) { 77 port->iotype = UPIO_PORT; 78 options += 3; 79 addr = simple_strtoul(options, NULL, 0); 80 port->iobase = addr; 81 mmio = 0; 82 } else if (!strncmp(options, "0x", 2)) { 83 port->iotype = UPIO_MEM; 84 addr = simple_strtoul(options, NULL, 0); 85 port->mapbase = addr; 86 } else { 87 return -EINVAL; 88 } 89 90 port->uartclk = BASE_BAUD * 16; 91 92 options = strchr(options, ','); 93 if (options) { 94 options++; 95 device->baud = simple_strtoul(options, NULL, 0); 96 length = min(strcspn(options, " ") + 1, 97 (size_t)(sizeof(device->options))); 98 strlcpy(device->options, options, length); 99 } 100 101 if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32) 102 pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", 103 mmio32 ? "32" : "", 104 (unsigned long long)port->mapbase, 105 device->options); 106 else 107 pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", 108 port->iobase, 109 device->options); 110 111 return 0; 112 } 113 114 int __init setup_earlycon(char *buf, const char *match, 115 int (*setup)(struct earlycon_device *, const char *)) 116 { 117 int err; 118 size_t len; 119 struct uart_port *port = &early_console_dev.port; 120 121 if (!buf || !match || !setup) 122 return 0; 123 124 len = strlen(match); 125 if (strncmp(buf, match, len)) 126 return 0; 127 if (buf[len] && (buf[len] != ',')) 128 return 0; 129 130 buf += len + 1; 131 132 err = parse_options(&early_console_dev, buf); 133 /* On parsing error, pass the options buf to the setup function */ 134 if (!err) 135 buf = NULL; 136 137 if (port->mapbase) 138 port->membase = earlycon_map(port->mapbase, 64); 139 140 early_console_dev.con->data = &early_console_dev; 141 err = setup(&early_console_dev, buf); 142 if (err < 0) 143 return err; 144 if (!early_console_dev.con->write) 145 return -ENODEV; 146 147 register_console(early_console_dev.con); 148 return 0; 149 } 150 151 int __init of_setup_earlycon(unsigned long addr, 152 int (*setup)(struct earlycon_device *, const char *)) 153 { 154 int err; 155 struct uart_port *port = &early_console_dev.port; 156 157 port->iotype = UPIO_MEM; 158 port->mapbase = addr; 159 port->uartclk = BASE_BAUD * 16; 160 port->membase = earlycon_map(addr, SZ_4K); 161 162 early_console_dev.con->data = &early_console_dev; 163 err = setup(&early_console_dev, NULL); 164 if (err < 0) 165 return err; 166 if (!early_console_dev.con->write) 167 return -ENODEV; 168 169 170 register_console(early_console_dev.con); 171 return 0; 172 } 173