From patchwork Fri Mar 21 21:08:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 3876471 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id BADC69F334 for ; Fri, 21 Mar 2014 21:13:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B689420212 for ; Fri, 21 Mar 2014 21:13:07 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 98FDC20203 for ; Fri, 21 Mar 2014 21:13:06 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WR6ih-0004mm-QG; Fri, 21 Mar 2014 21:11:17 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WR6iJ-00026h-6J; Fri, 21 Mar 2014 21:10:51 +0000 Received: from mail-oa0-x236.google.com ([2607:f8b0:4003:c02::236]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WR6ha-000203-Bd for linux-arm-kernel@lists.infradead.org; Fri, 21 Mar 2014 21:10:10 +0000 Received: by mail-oa0-f54.google.com with SMTP id n16so3206407oag.13 for ; Fri, 21 Mar 2014 14:09:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BFMqdTrsSgE61cuE3Fbf/jYbzsZuQYv/5seGMQ9SXks=; b=R88oS+wVo41UmYvVNE4S2bp5r8ij3m+/laeAtXuAvvOYWLCefkDI08XsbmH3FMFUkD YU2tcgaJqKkRzygrfVo109EOMogHZ1BNbN1Snv7z7fqpkTs4JhAd74mVN0UcBY0t2wcd 2jqQI8V/wjk2sOGeO88Fm3J4Mmc9RcPiEgU+mya2Wmwc33jcumv0SzcTx3EqvoTJPYWa PY4hF/nouorvWXKZoY4Z2QO9BxHW6p0b6PcgJVHf57/v14o73MNrPITi8i7IY9eY8HOL BS007etaQgAHa8ahqP3cQDhCNbizSiuOXx/vGLfOy8t0ZP4SODyJBbKuiMqJGReulDTu z7pQ== X-Received: by 10.60.159.137 with SMTP id xc9mr44930659oeb.31.1395436184077; Fri, 21 Mar 2014 14:09:44 -0700 (PDT) Received: from localhost.localdomain (72-48-77-163.dyn.grandenetworks.net. [72.48.77.163]) by mx.google.com with ESMTPSA id tz6sm9859086obc.10.2014.03.21.14.09.42 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 21 Mar 2014 14:09:43 -0700 (PDT) From: Rob Herring To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH 4/8] tty/serial: add generic serial earlycon Date: Fri, 21 Mar 2014 16:08:44 -0500 Message-Id: <1395436128-11244-5-git-send-email-robherring2@gmail.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1395436128-11244-1-git-send-email-robherring2@gmail.com> References: <1395436128-11244-1-git-send-email-robherring2@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140321_171006_544647_219C0880 X-CRM114-Status: GOOD ( 22.51 ) X-Spam-Score: -1.8 (-) Cc: Rob Herring , Russell King , Arnd Bergmann , Greg Kroah-Hartman , x86@kernel.org, Will Deacon , Catalin Marinas , Jiri Slaby X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rob Herring This introduces generic earlycon infrastructure for serial devices based on the 8250 earlycon. This allows for supporting earlycon option with other serial devices. The earlycon output is enabled at the time early_params are processed. Only architectures that have fixmap support or have functional ioremap when early_params are processed are supported. This is the same restriction that the 8250 driver had. Signed-off-by: Rob Herring Cc: Greg Kroah-Hartman Cc: Jiri Slaby --- drivers/tty/serial/Kconfig | 7 ++ drivers/tty/serial/Makefile | 2 + drivers/tty/serial/earlycon.c | 148 ++++++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 16 +++++ 4 files changed, 173 insertions(+) create mode 100644 drivers/tty/serial/earlycon.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2e6d8dd..1685189 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -7,6 +7,13 @@ if TTY menu "Serial drivers" depends on HAS_IOMEM +config SERIAL_EARLYCON + bool "Early console for serial ports" + help + Support for early consoles with the earlycon parameter. This enables + the console before standard serial driver is probed. The console is + enabled when early_param is processed. + source "drivers/tty/serial/8250/Kconfig" comment "Non-8250 serial port support" diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 3680854..8af1415 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o +obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o + # These Sparc drivers have to appear before others such as 8250 # which share ttySx minor node space. Otherwise console device # names change and other unplesantries. diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c new file mode 100644 index 0000000..241757a --- /dev/null +++ b/drivers/tty/serial/earlycon.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * Author: Rob Herring + * + * Based on 8250 earlycon: + * (c) Copyright 2004 Hewlett-Packard Development Company, L.P. + * Bjorn Helgaas + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include +#include + +static struct console early_con = { + .name = "earlycon", + .flags = CON_PRINTBUFFER | CON_BOOT, + .index = -1, +}; + +static struct earlycon_device early_console_dev = { + .con = &early_con, +}; + +static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) +{ + void __iomem *base; +#ifdef CONFIG_FIX_EARLYCON_MEM + set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, paddr & PAGE_MASK); + base = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); + base += paddr & ~PAGE_MASK; +#else + base = ioremap_nocache(paddr, size); +#endif + if (!base) + pr_err("%s: Couldn't map 0x%llx\n", __func__, + (unsigned long long)paddr); + + return base; +} + +static int __init parse_options(struct earlycon_device *device, + char *options) +{ + struct uart_port *port = &device->port; + int mmio, mmio32, length, ret; + unsigned long addr; + + if (!options) + return -ENODEV; + + mmio = !strncmp(options, "mmio,", 5); + mmio32 = !strncmp(options, "mmio32,", 7); + if (mmio || mmio32) { + port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32); + options += mmio ? 5 : 7; + ret = kstrtoul(options, 0, &addr); + if (ret) + return ret; + port->mapbase = addr; + if (mmio32) + port->regshift = 2; + } else if (!strncmp(options, "io,", 3)) { + port->iotype = UPIO_PORT; + options += 3; + ret = kstrtoul(options, 0, &addr); + if (ret) + return ret; + port->iobase = addr; + mmio = 0; + } else if (!strncmp(options, "0x", 2)) { + port->iotype = UPIO_MEM; + ret = kstrtoul(options, 0, &addr); + if (ret) + return ret; + port->mapbase = addr; + } else { + return -EINVAL; + } + + if (port->mapbase) + port->membase = earlycon_map(port->mapbase, 64); + + port->uartclk = BASE_BAUD * 16; + + options = strchr(options, ','); + if (options) { + options++; + ret = kstrtouint(options, 0, &device->baud); + if (ret) + return ret; + length = min(strcspn(options, " ") + 1, + (size_t)(sizeof(device->options))); + strlcpy(device->options, options, length); + } + + if (mmio || mmio32) + pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", + mmio32 ? "32" : "", + (unsigned long long)port->mapbase, + device->options); + else + pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", + port->iobase, + device->options); + + return 0; +} + +int __init setup_earlycon(char *buf, const char *match, + int (*setup)(struct earlycon_device *, const char *)) +{ + int err; + size_t len; + + if (!buf || !match || !setup) + return -EINVAL; + + len = strlen(match); + if (strncmp(buf, match, len)) + return 0; + if (buf[len] && (buf[len] != ',')) + return 0; + + buf += len + 1; + + err = parse_options(&early_console_dev, buf); + /* On parsing error, pass the options buf to the setup function */ + if (!err) + buf = NULL; + + early_console_dev.con->data = &early_console_dev; + err = setup(&early_console_dev, buf); + if (err < 0) + return err; + if (!early_console_dev.con->write) + return -ENODEV; + + register_console(early_console_dev.con); + return 0; +} diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f729be9..7a15b5b 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -285,6 +285,22 @@ static inline int uart_poll_timeout(struct uart_port *port) /* * Console helpers. */ +struct earlycon_device { + struct console *con; + struct uart_port port; + char options[16]; /* e.g., 115200n8 */ + unsigned int baud; +}; +int setup_earlycon(char *buf, const char *match, + int (*setup)(struct earlycon_device *, const char *)); + +#define EARLYCON_DECLARE(name, func) \ +static int __init name ## _setup_earlycon(char *buf) \ +{ \ + return setup_earlycon(buf, __stringify(name), func); \ +} \ +early_param("earlycon", name ## _setup_earlycon); + struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); void uart_parse_options(char *options, int *baud, int *parity, int *bits,