Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd94c407 authored by Masahiro Yamada's avatar Masahiro Yamada Committed by Greg Kroah-Hartman
Browse files

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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 004e2ed5
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -721,16 +721,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.

		uart[8250],io,<addr>[,options]
		uart[8250],mmio,<addr>[,options]
		uart[8250],mmio16,<addr>[,options]
		uart[8250],mmio32,<addr>[,options]
		uart[8250],0x<addr>[,options]
			Start an early, polled-mode console on the 8250/16550
			UART at the specified I/O port or MMIO address,
			switching to the matching ttyS device later.
			MMIO inter-register address stride is either 8-bit
			(mmio) or 32-bit (mmio32).
			If none of [io|mmio|mmio32], <addr> is assumed to be
			equivalent to 'mmio'. 'options' are specified in the
			same format described for ttyS above; if unspecified,
			(mmio), 16-bit (mmio16), or 32-bit (mmio32).
			If none of [io|mmio|mmio16|mmio32], <addr> is assumed
			to be equivalent to 'mmio'. 'options' are specified in
			the same format described for ttyS above; if unspecified,
			the h/w is not re-initialized.

		hvc<n>	Use the hypervisor console device <n>. This is for
+4 −3
Original line number Diff line number Diff line
@@ -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;
+5 −0
Original line number Diff line number Diff line
@@ -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;
+20 −0
Original line number Diff line number Diff line
@@ -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;
+11 −4
Original line number Diff line number Diff line
@@ -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);
Loading