summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2014-05-20 14:22:54 -0500
committerRob Herring <robh@kernel.org>2014-05-20 14:22:54 -0500
commit6e87b7030e3ef2c7ad01fcaa1b46d3ebe6c261e7 (patch)
treee01eaf5fcfed6767da9fcfd8f5120ef667c81bb8
parenteafd370dfe487facfdef499057f4eac9aa0b4bf5 (diff)
parente26f1db9b8d74617519e50b41749900d0a257406 (diff)
downloadlinux-6e87b7030e3ef2c7ad01fcaa1b46d3ebe6c261e7.tar.gz
linux-6e87b7030e3ef2c7ad01fcaa1b46d3ebe6c261e7.tar.bz2
linux-6e87b7030e3ef2c7ad01fcaa1b46d3ebe6c261e7.zip
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty into for-next
Conflicts: arch/arm64/kernel/early_printk.c
-rw-r--r--Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt33
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--arch/arm64/Kconfig3
-rw-r--r--arch/arm64/Kconfig.debug9
-rw-r--r--arch/arm64/kernel/Makefile1
-rw-r--r--arch/arm64/kernel/early_printk.c156
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--drivers/bluetooth/hci_ldisc.c24
-rw-r--r--drivers/bluetooth/hci_uart.h1
-rw-r--r--drivers/tty/serial/8250/8250_core.c5
-rw-r--r--drivers/tty/serial/8250/8250_dw.c81
-rw-r--r--drivers/tty/serial/8250/8250_early.c138
-rw-r--r--drivers/tty/serial/8250/Kconfig6
-rw-r--r--drivers/tty/serial/Kconfig47
-rw-r--r--drivers/tty/serial/Makefile5
-rw-r--r--drivers/tty/serial/amba-pl011.c30
-rw-r--r--drivers/tty/serial/earlycon-arm-semihost.c61
-rw-r--r--drivers/tty/serial/earlycon.c144
-rw-r--r--drivers/tty/serial/men_z135_uart.c866
-rw-r--r--drivers/tty/serial/mux.c4
-rw-r--r--drivers/tty/serial/omap-serial.c94
-rw-r--r--drivers/tty/serial/pch_uart.c13
-rw-r--r--drivers/tty/serial/pxa.c5
-rw-r--r--drivers/tty/serial/sc16is7xx.c1280
-rw-r--r--drivers/tty/serial/serial_core.c3
-rw-r--r--drivers/tty/serial/serial_txx9.c5
-rw-r--r--drivers/tty/serial/xilinx_uartps.c1129
-rw-r--r--include/linux/serial_core.h16
-rw-r--r--include/linux/tty_ldisc.h5
-rw-r--r--include/uapi/linux/serial_core.h8
-rw-r--r--include/uapi/linux/serial_reg.h2
31 files changed, 3193 insertions, 993 deletions
diff --git a/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt
new file mode 100644
index 000000000000..246c795668dc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt
@@ -0,0 +1,33 @@
+* NXP SC16IS7xx advanced Universal Asynchronous Receiver-Transmitter (UART)
+
+Required properties:
+- compatible: Should be one of the following:
+ - "nxp,sc16is740" for NXP SC16IS740,
+ - "nxp,sc16is741" for NXP SC16IS741,
+ - "nxp,sc16is750" for NXP SC16IS750,
+ - "nxp,sc16is752" for NXP SC16IS752,
+ - "nxp,sc16is760" for NXP SC16IS760,
+ - "nxp,sc16is762" for NXP SC16IS762.
+- reg: I2C address of the SC16IS7xx device.
+- interrupt-parent: The phandle for the interrupt controller that
+ services interrupts for this IC.
+- interrupts: Should contain the UART interrupt
+- clocks: Reference to the IC source clock.
+
+Optional properties:
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells: Should be two. The first cell is the GPIO number and
+ the second cell is used to specify the GPIO polarity:
+ 0 = active high,
+ 1 = active low.
+
+Example:
+ sc16is750: sc16is750@51 {
+ compatible = "nxp,sc16is750";
+ reg = <0x51>;
+ clocks = <&clk20m>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 43842177b771..4946d8e58d53 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -883,6 +883,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
which are not unmapped.
earlycon= [KNL] Output early console device and options.
+
uart[8250],io,<addr>[,options]
uart[8250],mmio,<addr>[,options]
uart[8250],mmio32,<addr>[,options]
@@ -892,6 +893,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
(mmio) or 32-bit (mmio32).
The options are the same as for ttyS, above.
+ pl011,<addr>
+ Start an early, polled-mode console on a pl011 serial
+ port at the specified address. The pl011 serial port
+ must already be setup and configured. Options are not
+ yet supported.
+
+ smh Use ARM semihosting calls for early console.
+
earlyprintk= [X86,SH,BLACKFIN,ARM]
earlyprintk=vga
earlyprintk=efi
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index e759af5d7098..f5f63b715d91 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -112,6 +112,9 @@ config IOMMU_HELPER
config KERNEL_MODE_NEON
def_bool y
+config FIX_EARLYCON_MEM
+ def_bool y
+
source "init/Kconfig"
source "kernel/Kconfig.freezer"
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index d10ec334c93b..1c1b75629842 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -20,15 +20,6 @@ config STRICT_DEVMEM
If in doubt, say Y.
-config EARLY_PRINTK
- bool "Early printk support"
- default y
- help
- Say Y here if you want to have an early console using the
- earlyprintk=<name>[,<addr>][,<options>] kernel parameter. It
- is assumed that the early console device has been initialised
- by the boot loader prior to starting the Linux kernel.
-
config PID_IN_CONTEXTIDR
bool "Write the current PID to the CONTEXTIDR register"
help
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d811d9522bc..7a6fce5167e9 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -18,7 +18,6 @@ arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
-arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o
arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
arm64-obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c
deleted file mode 100644
index 2dc36d00addf..000000000000
--- a/arch/arm64/kernel/early_printk.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Earlyprintk support.
- *
- * Copyright (C) 2012 ARM Ltd.
- * Author: Catalin Marinas <catalin.marinas@arm.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-
-#include <linux/amba/serial.h>
-#include <linux/serial_reg.h>
-
-#include <asm/fixmap.h>
-
-static void __iomem *early_base;
-static void (*printch)(char ch);
-
-/*
- * PL011 single character TX.
- */
-static void pl011_printch(char ch)
-{
- while (readl_relaxed(early_base + UART01x_FR) & UART01x_FR_TXFF)
- ;
- writeb_relaxed(ch, early_base + UART01x_DR);
- while (readl_relaxed(early_base + UART01x_FR) & UART01x_FR_BUSY)
- ;
-}
-
-/*
- * Semihosting-based debug console
- */
-static void smh_printch(char ch)
-{
- asm volatile("mov x1, %0\n"
- "mov x0, #3\n"
- "hlt 0xf000\n"
- : : "r" (&ch) : "x0", "x1", "memory");
-}
-
-/*
- * 8250/16550 (8-bit aligned registers) single character TX.
- */
-static void uart8250_8bit_printch(char ch)
-{
- while (!(readb_relaxed(early_base + UART_LSR) & UART_LSR_THRE))
- ;
- writeb_relaxed(ch, early_base + UART_TX);
-}
-
-/*
- * 8250/16550 (32-bit aligned registers) single character TX.
- */
-static void uart8250_32bit_printch(char ch)
-{
- while (!(readl_relaxed(early_base + (UART_LSR << 2)) & UART_LSR_THRE))
- ;
- writel_relaxed(ch, early_base + (UART_TX << 2));
-}
-
-struct earlycon_match {
- const char *name;
- void (*printch)(char ch);
-};
-
-static const struct earlycon_match earlycon_match[] __initconst = {
- { .name = "pl011", .printch = pl011_printch, },
- { .name = "smh", .printch = smh_printch, },
- { .name = "uart8250-8bit", .printch = uart8250_8bit_printch, },
- { .name = "uart8250-32bit", .printch = uart8250_32bit_printch, },
- {}
-};
-
-static void early_write(struct console *con, const char *s, unsigned n)
-{
- while (n-- > 0) {
- if (*s == '\n')
- printch('\r');
- printch(*s);
- s++;
- }
-}
-
-static struct console early_console_dev = {
- .name = "earlycon",
- .write = early_write,
- .flags = CON_PRINTBUFFER | CON_BOOT,
- .index = -1,
-};
-
-/*
- * Parse earlyprintk=... parameter in the format:
- *
- * <name>[,<addr>][,<options>]
- *
- * and register the early console. It is assumed that the UART has been
- * initialised by the bootloader already.
- */
-static int __init setup_early_printk(char *buf)
-{
- const struct earlycon_match *match = earlycon_match;
- phys_addr_t paddr = 0;
-
- if (!buf) {
- pr_warning("No earlyprintk arguments passed.\n");
- return 0;
- }
-
- while (match->name) {
- size_t len = strlen(match->name);
- if (!strncmp(buf, match->name, len)) {
- buf += len;
- break;
- }
- match++;
- }
- if (!match->name) {
- pr_warning("Unknown earlyprintk arguments: %s\n", buf);
- return 0;
- }
-
- /* I/O address */
- if (!strncmp(buf, ",0x", 3)) {
- char *e;
- paddr = simple_strtoul(buf + 1, &e, 16);
- buf = e;
- }
- /* no options parsing yet */
-
- if (paddr)
- early_base = (void __iomem *)set_fixmap_offset_io(FIX_EARLYCON_MEM_BASE, paddr);
-
- printch = match->printch;
- early_console = &early_console_dev;
- register_console(&early_console_dev);
-
- return 0;
-}
-
-early_param("earlyprintk", setup_early_printk);
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 25d2c6f7325e..0fb6cfd50e75 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -261,6 +261,9 @@ config ARCH_HWEIGHT_CFLAGS
config ARCH_SUPPORTS_UPROBES
def_bool y
+config FIX_EARLYCON_MEM
+ def_bool y
+
source "init/Kconfig"
source "kernel/Kconfig.freezer"
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index f1fbf4f1e5be..e00f8f5b5c8e 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -118,10 +118,6 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
int hci_uart_tx_wakeup(struct hci_uart *hu)
{
- struct tty_struct *tty = hu->tty;
- struct hci_dev *hdev = hu->hdev;
- struct sk_buff *skb;
-
if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
return 0;
@@ -129,6 +125,22 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
BT_DBG("");
+ schedule_work(&hu->write_work);
+
+ return 0;
+}
+
+static void hci_uart_write_work(struct work_struct *work)
+{
+ struct hci_uart *hu = container_of(work, struct hci_uart, write_work);
+ struct tty_struct *tty = hu->tty;
+ struct hci_dev *hdev = hu->hdev;
+ struct sk_buff *skb;
+
+ /* REVISIT: should we cope with bad skbs or ->write() returning
+ * and error value ?
+ */
+
restart:
clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
@@ -153,7 +165,6 @@ restart:
goto restart;
clear_bit(HCI_UART_SENDING, &hu->tx_state);
- return 0;
}
static void hci_uart_init_work(struct work_struct *work)
@@ -282,6 +293,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->receive_room = 65536;
INIT_WORK(&hu->init_ready, hci_uart_init_work);
+ INIT_WORK(&hu->write_work, hci_uart_write_work);
spin_lock_init(&hu->rx_lock);
@@ -319,6 +331,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);
+ cancel_work_sync(&hu->write_work);
+
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index fffa61ff5cb1..12df101ca942 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -68,6 +68,7 @@ struct hci_uart {
unsigned long hdev_flags;
struct work_struct init_ready;
+ struct work_struct write_work;
struct hci_uart_proto *proto;
void *priv;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 2d4bd3929e50..053c2007b054 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1926,13 +1926,8 @@ static void serial8250_put_poll_char(struct uart_port *port,
wait_for_xmitr(up, BOTH_EMPTY);
/*
* Send the character out.
- * If a LF, also do CR...
*/
serial_port_out(port, UART_TX, c);
- if (c == 10) {
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_port_out(port, UART_TX, 13);
- }
/*
* Finally, wait for transmitter to become empty
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index ed3113576740..51b307aab75e 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -62,6 +62,70 @@ struct dw8250_data {
struct uart_8250_dma dma;
};
+struct dw8250_acpi_desc {
+ void (*set_termios)(struct uart_port *p, struct ktermios *termios,
+ struct ktermios *old);
+};
+
+#define BYT_PRV_CLK 0x800
+#define BYT_PRV_CLK_EN (1 << 0)
+#define BYT_PRV_CLK_M_VAL_SHIFT 1
+#define BYT_PRV_CLK_N_VAL_SHIFT 16
+#define BYT_PRV_CLK_UPDATE (1 << 31)
+
+static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned int baud = tty_termios_baud_rate(termios);
+ unsigned int m, n;
+ u32 reg;
+
+ /*
+ * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
+ * dividers must be adjusted.
+ *
+ * uartclk = (m / n) * 100 MHz, where m <= n
+ */
+ switch (baud) {
+ case 500000:
+ case 1000000:
+ case 2000000:
+ case 4000000:
+ m = 64;
+ n = 100;
+ p->uartclk = 64000000;
+ break;
+ case 3500000:
+ m = 56;
+ n = 100;
+ p->uartclk = 56000000;
+ break;
+ case 1500000:
+ case 3000000:
+ m = 48;
+ n = 100;
+ p->uartclk = 48000000;
+ break;
+ case 2500000:
+ m = 40;
+ n = 100;
+ p->uartclk = 40000000;
+ break;
+ default:
+ m = 2304;
+ n = 3125;
+ p->uartclk = 73728000;
+ }
+
+ /* Reset the clock */
+ reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
+ writel(reg, p->membase + BYT_PRV_CLK);
+ reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
+ writel(reg, p->membase + BYT_PRV_CLK);
+
+ serial8250_do_set_termios(p, termios, old);
+}
+
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
@@ -278,6 +342,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
{
const struct acpi_device_id *id;
struct uart_port *p = &up->port;
+ struct dw8250_acpi_desc *acpi_desc;
dw8250_setup_port(up);
@@ -290,14 +355,18 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
p->serial_out = dw8250_serial_out32;
p->regshift = 2;
- if (!p->uartclk)
- p->uartclk = (unsigned int)id->driver_data;
-
up->dma = &data->dma;
up->dma->rxconf.src_maxburst = p->fifosize / 4;
up->dma->txconf.dst_maxburst = p->fifosize / 4;
+ acpi_desc = (struct dw8250_acpi_desc *)id->driver_data;
+ if (!acpi_desc)
+ return 0;
+
+ if (acpi_desc->set_termios)
+ p->set_termios = acpi_desc->set_termios;
+
return 0;
}
@@ -445,12 +514,16 @@ static const struct of_device_id dw8250_of_match[] = {
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
+static struct dw8250_acpi_desc byt_8250_desc = {
+ .set_termios = byt_set_termios,
+};
+
static const struct acpi_device_id dw8250_acpi_match[] = {
{ "INT33C4", 0 },
{ "INT33C5", 0 },
{ "INT3434", 0 },
{ "INT3435", 0 },
- { "80860F0A", 0 },
+ { "80860F0A", (kernel_ulong_t)&byt_8250_desc},
{ },
};
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index c100d6343d50..cfef801a49d4 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -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)
{
@@ -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,42 @@ 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)
+static int __init early_serial8250_setup(struct earlycon_device *device,
+ const 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)
-{
- 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);
+
+ early_device = device;
+ device->con->write = early_serial8250_write;
return 0;
}
+EARLYCON_DECLARE(uart8250, early_serial8250_setup);
+EARLYCON_DECLARE(uart, early_serial8250_setup);
int __init setup_early_serial8250_console(char *cmdline)
{
- char *options;
- int err;
+ char match[] = "uart8250";
- options = strstr(cmdline, "uart8250,");
- if (!options) {
- options = strstr(cmdline, "uart,");
- if (!options)
- return 0;
- }
+ if (cmdline && cmdline[4] == ',')
+ match[4] = '\0';
- options = strchr(cmdline, ',') + 1;
- err = early_serial8250_setup(options);
- if (err < 0)
- return err;
-
- register_console(&early_serial8250_console);
-
- return 0;
+ return setup_earlycon(cmdline, match, 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 +188,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..349ee598b34c 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
@@ -90,11 +91,6 @@ config SERIAL_8250_CONSOLE
If unsure, say N.
-config FIX_EARLYCON_MEM
- bool
- depends on X86
- default y
-
config SERIAL_8250_GSC
tristate
depends on SERIAL_8250 && GSC
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 5d9b01aa54f4..64c565945ac3 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
+ 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"
@@ -53,6 +60,7 @@ config SERIAL_AMBA_PL011_CONSOLE
bool "Support for console on AMBA serial port"
depends on SERIAL_AMBA_PL011=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
---help---
Say Y here if you wish to use an AMBA PrimeCell UART as the system
console (the system console is the device which receives all kernel
@@ -65,6 +73,16 @@ config SERIAL_AMBA_PL011_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
+config SERIAL_EARLYCON_ARM_SEMIHOST
+ bool "Early console using ARM semihosting"
+ depends on ARM64 || ARM
+ select SERIAL_EARLYCON
+ help
+ Support for early debug console using ARM semihosting. This enables
+ the console before standard serial driver is probed. This is enabled
+ with "earlycon=smh" on the kernel command line. The console is
+ enabled when early_param is processed.
+
config SERIAL_SB1250_DUART
tristate "BCM1xxx on-chip DUART serial support"
depends on SIBYTE_SB1xxx_SOC=y
@@ -1160,6 +1178,16 @@ config SERIAL_SCCNXP_CONSOLE
help
Support for console on SCCNXP serial ports.
+config SERIAL_SC16IS7XX
+ tristate "SC16IS7xx serial support"
+ depends on I2C
+ select SERIAL_CORE
+ select REGMAP_I2C if I2C
+ help
+ This selects support for SC16IS7xx serial ports.
+ Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
+ SC16IS760 and SC16IS762.
+
config SERIAL_BFIN_SPORT
tristate "Blackfin SPORT emulate UART"
depends on BLACKFIN
@@ -1369,18 +1397,19 @@ config SERIAL_MXS_AUART_CONSOLE
Enable a MXS AUART port to be the system console.
config SERIAL_XILINX_PS_UART
- tristate "Xilinx PS UART support"
+ tristate "Cadence (Xilinx Zynq) UART support"
depends on OF
select SERIAL_CORE
help
- This driver supports the Xilinx PS UART port.
+ This driver supports the Cadence UART. It is found e.g. in Xilinx
+ Zynq.
config SERIAL_XILINX_PS_UART_CONSOLE
- bool "Xilinx PS UART console support"
+ bool "Cadence UART console support"
depends on SERIAL_XILINX_PS_UART=y
select SERIAL_CORE_CONSOLE
help
- Enable a Xilinx PS UART port to be the system console.
+ Enable a Cadence UART port to be the system console.
config SERIAL_AR933X
tristate "AR933X serial port support"
@@ -1508,6 +1537,16 @@ config SERIAL_ST_ASC_CONSOLE
depends on SERIAL_ST_ASC=y
select SERIAL_CORE_CONSOLE
+config SERIAL_MEN_Z135
+ tristate "MEN 16z135 Support"
+ depends on MCB
+ help
+ Say yes here to enable support for the MEN 16z135 High Speed UART IP-Core
+ on a MCB carrier.
+
+ This driver can also be build as a module. If so, the module will be called
+ men_z135_uart.ko
+
endmenu
endif # TTY
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 3680854fef41..712732b43917 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -5,6 +5,9 @@
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
+obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
+obj-$(CO