summaryrefslogtreecommitdiff
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2015-10-28 03:46:05 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-12-14 03:59:48 (GMT)
commitbd94c4077a0b2ecc35562c294f80f3659ecd8499 (patch)
tree939d81f6945ce1b0925ab4bf6f7e40c399057e17 /drivers/tty/serial
parent004e2ed5cc6d89201140ca96693bf9c0b2945f43 (diff)
downloadlinux-bd94c4077a0b2ecc35562c294f80f3659ecd8499.tar.xz
serial: support 16-bit register interface for console
Currently, 8-bit (MMIO) and 32-bit (MMIO32) register interfaces are supported for the 8250 console, but the 16-bit (MMIO16) is not. The 8250 UART device on my board is connected to a 16-bit bus and my main motivation is to use earlycon with it. (Refer to arch/arm/boot/dts/uniphier-support-card.dtsi) Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Reviewed-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/8250/8250_core.c7
-rw-r--r--drivers/tty/serial/8250/8250_early.c5
-rw-r--r--drivers/tty/serial/8250/8250_port.c20
-rw-r--r--drivers/tty/serial/earlycon.c15
-rw-r--r--drivers/tty/serial/of_serial.c3
-rw-r--r--drivers/tty/serial/serial_core.c9
6 files changed, 50 insertions, 9 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 3912646..c9720a9 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -620,7 +620,7 @@ static int univ8250_console_setup(struct console *co, char *options)
* @options: ptr to option string from console command line
*
* Only attempts to match console command lines of the form:
- * console=uart[8250],io|mmio|mmio32,<addr>[,<options>]
+ * console=uart[8250],io|mmio|mmio16|mmio32,<addr>[,<options>]
* console=uart[8250],0x<addr>[,<options>]
* This form is used to register an initial earlycon boot console and
* replace it with the serial8250_console at 8250 driver init.
@@ -650,8 +650,9 @@ static int univ8250_console_match(struct console *co, char *name, int idx,
if (port->iotype != iotype)
continue;
- if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) &&
- (port->mapbase != addr))
+ if ((iotype == UPIO_MEM || iotype == UPIO_MEM16 ||
+ iotype == UPIO_MEM32 || iotype == UPIO_MEM32BE)
+ && (port->mapbase != addr))
continue;
if (iotype == UPIO_PORT && port->iobase != addr)
continue;
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index ca16195..af62131 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -42,6 +42,8 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
switch (port->iotype) {
case UPIO_MEM:
return readb(port->membase + offset);
+ case UPIO_MEM16:
+ return readw(port->membase + (offset << 1));
case UPIO_MEM32:
return readl(port->membase + (offset << 2));
case UPIO_MEM32BE:
@@ -59,6 +61,9 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
case UPIO_MEM:
writeb(value, port->membase + offset);
break;
+ case UPIO_MEM16:
+ writew(value, port->membase + (offset << 1));
+ break;
case UPIO_MEM32:
writel(value, port->membase + (offset << 2));
break;
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 52d82d2..8d262bc 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -368,6 +368,18 @@ static void mem_serial_out(struct uart_port *p, int offset, int value)
writeb(value, p->membase + offset);
}
+static void mem16_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = offset << p->regshift;
+ writew(value, p->membase + offset);
+}
+
+static unsigned int mem16_serial_in(struct uart_port *p, int offset)
+{
+ offset = offset << p->regshift;
+ return readw(p->membase + offset);
+}
+
static void mem32_serial_out(struct uart_port *p, int offset, int value)
{
offset = offset << p->regshift;
@@ -425,6 +437,11 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_out = mem_serial_out;
break;
+ case UPIO_MEM16:
+ p->serial_in = mem16_serial_in;
+ p->serial_out = mem16_serial_out;
+ break;
+
case UPIO_MEM32:
p->serial_in = mem32_serial_in;
p->serial_out = mem32_serial_out;
@@ -459,6 +476,7 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
{
switch (p->iotype) {
case UPIO_MEM:
+ case UPIO_MEM16:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU:
@@ -2462,6 +2480,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
+ case UPIO_MEM16:
case UPIO_MEM:
if (!port->mapbase)
break;
@@ -2499,6 +2518,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
case UPIO_TSI:
case UPIO_MEM32:
case UPIO_MEM32BE:
+ case UPIO_MEM16:
case UPIO_MEM:
if (!port->mapbase)
break;
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index f096360..07f7393 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -71,10 +71,16 @@ static int __init parse_options(struct earlycon_device *device, char *options)
return -EINVAL;
switch (port->iotype) {
+ case UPIO_MEM:
+ port->mapbase = addr;
+ break;
+ case UPIO_MEM16:
+ port->regshift = 1;
+ port->mapbase = addr;
+ break;
case UPIO_MEM32:
case UPIO_MEM32BE:
- port->regshift = 2; /* fall-through */
- case UPIO_MEM:
+ port->regshift = 2;
port->mapbase = addr;
break;
case UPIO_PORT:
@@ -91,10 +97,11 @@ static int __init parse_options(struct earlycon_device *device, char *options)
strlcpy(device->options, options, length);
}
- if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32 ||
- port->iotype == UPIO_MEM32BE)
+ if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 ||
+ port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE)
pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
(port->iotype == UPIO_MEM) ? "" :
+ (port->iotype == UPIO_MEM16) ? "16" :
(port->iotype == UPIO_MEM32) ? "32" : "32be",
(unsigned long long)port->mapbase,
device->options);
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index de50296..6d002ee 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -122,6 +122,9 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
case 1:
port->iotype = UPIO_MEM;
break;
+ case 2:
+ port->iotype = UPIO_MEM16;
+ break;
case 4:
port->iotype = of_device_is_big_endian(np) ?
UPIO_MEM32BE : UPIO_MEM32;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 22cfc32..b1f54ab 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1818,8 +1818,8 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
* @options: ptr for <options> field; NULL if not present (out)
*
* Decodes earlycon kernel command line parameters of the form
- * earlycon=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
- * console=<name>,io|mmio|mmio32|mmio32be|mmio32native,<addr>,<options>
+ * earlycon=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
+ * console=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
*
* The optional form
* earlycon=<name>,0x<addr>,<options>
@@ -1834,6 +1834,9 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
if (strncmp(p, "mmio,", 5) == 0) {
*iotype = UPIO_MEM;
p += 5;
+ } else if (strncmp(p, "mmio16,", 7) == 0) {
+ *iotype = UPIO_MEM16;
+ p += 7;
} else if (strncmp(p, "mmio32,", 7) == 0) {
*iotype = UPIO_MEM32;
p += 7;
@@ -2186,6 +2189,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
"I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
break;
case UPIO_MEM:
+ case UPIO_MEM16:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU:
@@ -2831,6 +2835,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
return (port1->iobase == port2->iobase) &&
(port1->hub6 == port2->hub6);
case UPIO_MEM:
+ case UPIO_MEM16:
case UPIO_MEM32:
case UPIO_MEM32BE:
case UPIO_AU: