Skip to content

Commit

Permalink
tty/serial: convert 8250 to generic earlycon
Browse files Browse the repository at this point in the history
With the generic earlycon infrastructure in place, convert the 8250
early console to use it.

Signed-off-by: Rob Herring <robh@kernel.org>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rob Herring authored and Greg Kroah-Hartman committed Apr 24, 2014
1 parent 9aac588 commit d2fd681
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 123 deletions.
138 changes: 15 additions & 123 deletions drivers/tty/serial/8250/8250_early.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,8 @@
#include <linux/serial_8250.h>
#include <asm/io.h>
#include <asm/serial.h>
#ifdef CONFIG_FIX_EARLYCON_MEM
#include <asm/pgtable.h>
#include <asm/fixmap.h>
#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)
{
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -284,5 +178,3 @@ int serial8250_find_port_for_earlycon(void)

return ret;
}

early_param("earlycon", setup_early_serial8250_console);
1 change: 1 addition & 0 deletions drivers/tty/serial/8250/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit d2fd681

Please sign in to comment.