From 97e7091e469ac45fc21def96705c3b975e0d8ebe Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 18 Apr 2014 17:19:56 -0500 Subject: tty/serial: convert 8250 to generic earlycon With the generic earlycon infrastructure in place, convert the 8250 early console to use it. Signed-off-by: Rob Herring Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman (cherry picked from commit d2fd6810a823bcde1ee232668f5689837aafa772) Signed-off-by: Alex Shi --- drivers/tty/serial/8250/8250_early.c | 138 ++++------------------------------- drivers/tty/serial/8250/Kconfig | 1 + 2 files changed, 16 insertions(+), 123 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index c100d6343d50..e83c9db3300c 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -35,18 +35,8 @@ #include #include #include -#ifdef CONFIG_FIX_EARLYCON_MEM -#include -#include -#endif -struct early_serial8250_device { - struct uart_port port; - char options[16]; /* e.g., 115200n8 */ - unsigned int baud; -}; - -static struct early_serial8250_device early_device; +static struct earlycon_device *early_device; unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset) { @@ -100,7 +90,7 @@ static void __init serial_putc(struct uart_port *port, int c) static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count) { - struct uart_port *port = &early_device.port; + struct uart_port *port = &early_device->port; unsigned int ier; /* Save the IER and disable interrupts */ @@ -129,7 +119,7 @@ static unsigned int __init probe_baud(struct uart_port *port) return (port->uartclk / 16) / quot; } -static void __init init_port(struct early_serial8250_device *device) +static void __init init_port(struct earlycon_device *device) { struct uart_port *port = &device->port; unsigned int divisor; @@ -148,128 +138,32 @@ static void __init init_port(struct early_serial8250_device *device) serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB); } -static int __init parse_options(struct early_serial8250_device *device, - char *options) -{ - struct uart_port *port = &device->port; - int mmio, mmio32, length; - - if (!options) - return -ENODEV; - - port->uartclk = BASE_BAUD * 16; - - mmio = !strncmp(options, "mmio,", 5); - mmio32 = !strncmp(options, "mmio32,", 7); - if (mmio || mmio32) { - port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32); - port->mapbase = simple_strtoul(options + (mmio ? 5 : 7), - &options, 0); - if (mmio32) - port->regshift = 2; -#ifdef CONFIG_FIX_EARLYCON_MEM - set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, - port->mapbase & PAGE_MASK); - port->membase = - (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); - port->membase += port->mapbase & ~PAGE_MASK; -#else - port->membase = ioremap_nocache(port->mapbase, 64); - if (!port->membase) { - printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", - __func__, - (unsigned long long) port->mapbase); - return -ENOMEM; - } -#endif - } else if (!strncmp(options, "io,", 3)) { - port->iotype = UPIO_PORT; - port->iobase = simple_strtoul(options + 3, &options, 0); - mmio = 0; - } else - return -EINVAL; - - options = strchr(options, ','); - if (options) { - options++; - device->baud = simple_strtoul(options, NULL, 0); - length = min(strcspn(options, " ") + 1, - (size_t)(sizeof(device->options))); - strlcpy(device->options, options, length); - } else { - device->baud = probe_baud(port); - snprintf(device->options, sizeof(device->options), "%u", - device->baud); - } - - if (mmio || mmio32) - printk(KERN_INFO - "Early serial console at MMIO%s 0x%llx (options '%s')\n", - mmio32 ? "32" : "", - (unsigned long long)port->mapbase, - device->options); - else - printk(KERN_INFO - "Early serial console at I/O port 0x%lx (options '%s')\n", - port->iobase, - device->options); - - return 0; -} - -static struct console early_serial8250_console __initdata = { - .name = "uart", - .write = early_serial8250_write, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1, -}; - -static int __init early_serial8250_setup(char *options) +static int __init early_serial8250_setup(struct earlycon_device *device, + const char *options) { - struct early_serial8250_device *device = &early_device; - int err; - - if (device->port.membase || device->port.iobase) + if (!(device->port.membase || device->port.iobase)) return 0; - err = parse_options(device, options); - if (err < 0) - return err; + if (!device->baud) + device->baud = probe_baud(&device->port); init_port(device); - return 0; -} - -int __init setup_early_serial8250_console(char *cmdline) -{ - char *options; - int err; - - options = strstr(cmdline, "uart8250,"); - if (!options) { - options = strstr(cmdline, "uart,"); - if (!options) - return 0; - } - - options = strchr(cmdline, ',') + 1; - err = early_serial8250_setup(options); - if (err < 0) - return err; - - register_console(&early_serial8250_console); + early_device = device; + device->con->write = early_serial8250_write; return 0; } +EARLYCON_DECLARE(uart8250, early_serial8250_setup); +EARLYCON_DECLARE(uart, early_serial8250_setup); int serial8250_find_port_for_earlycon(void) { - struct early_serial8250_device *device = &early_device; - struct uart_port *port = &device->port; + struct earlycon_device *device = early_device; + struct uart_port *port = device ? &device->port : NULL; int line; int ret; - if (!device->port.membase && !device->port.iobase) + if (!port || (!port->membase && !port->iobase)) return -ENODEV; line = serial8250_find_port(port); @@ -284,5 +178,3 @@ int serial8250_find_port_for_earlycon(void) return ret; } - -early_param("earlycon", setup_early_serial8250_console); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 23329918f229..7f96b50a3ce2 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -61,6 +61,7 @@ config SERIAL_8250_CONSOLE bool "Console on 8250/16550 and compatible serial port" depends on SERIAL_8250=y select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON ---help--- If you say Y here, it will be possible to use a serial port as the system console (the system console is the device which receives all -- cgit v1.2.3 From bd3132993d81a28b3a165ef6cc1abe0c4a0c6ac6 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 30 Apr 2014 19:48:28 -0500 Subject: tty/serial: add back missing setup_early_serial8250_console Commit d2fd6810a823bcd (tty/serial: convert 8250 to generic earlycon) removed setup_early_serial8250_console, but there are still 2 callers in: arch/mips/mti-malta/malta-init.c drivers/firmware/pcdp.c Add back the function implemented as a wrapper to setup_earlycon. Reported-by: Yinghai Lu Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org Signed-off-by: Greg Kroah-Hartman (cherry picked from commit fe1cf8af918af3ff0dd58ce92e5a5da117cb1d92) Signed-off-by: Alex Shi --- drivers/tty/serial/8250/8250_early.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index e83c9db3300c..cfef801a49d4 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -156,6 +156,16 @@ static int __init early_serial8250_setup(struct earlycon_device *device, EARLYCON_DECLARE(uart8250, early_serial8250_setup); EARLYCON_DECLARE(uart, early_serial8250_setup); +int __init setup_early_serial8250_console(char *cmdline) +{ + char match[] = "uart8250"; + + if (cmdline && cmdline[4] == ',') + match[4] = '\0'; + + return setup_earlycon(cmdline, match, early_serial8250_setup); +} + int serial8250_find_port_for_earlycon(void) { struct earlycon_device *device = early_device; -- cgit v1.2.3 From 5eb6ba4882c9c0b3b83486ab66b0c9e68189de4b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 12 Jun 2014 12:52:44 -0500 Subject: tty/serial: fix 8250 early console option passing to regular console In the conversion to generic early console, the passing of options from the early 8250 console to the regular ttyS console was broken. This resulted in the baud rate changing when switching consoles during boot. This feature allows specifying a single console option on the kernel command line rather than both an early console and regular serial tty console. It would be nice to generalize this feature. However, it only works if the correct baud rate can be probed early which is not the case on many platforms which have non-standard UART clock rates. So for now, this is left as an 8250 specific feature. Reported-and-tested-by: Tony Luck Signed-off-by: Rob Herring Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 60efcf0414be5876d81276e3c1fd12680ba2ce71) Signed-off-by: Alex Shi --- drivers/tty/serial/8250/8250_early.c | 5 ++++- drivers/tty/serial/earlycon.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index cfef801a49d4..4858b8a99d3b 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -144,8 +144,11 @@ static int __init early_serial8250_setup(struct earlycon_device *device, if (!(device->port.membase || device->port.iobase)) return 0; - if (!device->baud) + if (!device->baud) { device->baud = probe_baud(&device->port); + snprintf(device->options, sizeof(device->options), "%u", + device->baud); + } init_port(device); diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 73bf1e21aae0..4f27f788ac6f 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -23,7 +23,7 @@ #include static struct console early_con = { - .name = "earlycon", + .name = "uart", /* 8250 console switch requires this name */ .flags = CON_PRINTBUFFER | CON_BOOT, .index = -1, }; -- cgit v1.2.3