2014-06-12 10:32:39

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 0/9] Generic earlyconsole for ARC UART Driver

Hi,

This series switches ARC UART from custom earlyprintk support to generic
earlycon (many thanks to Rob for doing that).

The motivation is to get rid of the early platform code, which in turn
would help consolidate the init code across several ARC platforms.

First 3 patches are general cleanup/refactoring, not necesarily related to
earlycon.

Also the ARC platform change (8/9) is bundled in to keep series bisectable
w/o timing hassles. However it can be dropped if tty maintainers deem so.

Please review.

Thx,
-Vineet

Vineet Gupta (9):
serial/arc: use uart_console_write() helper
serial/arc: Refactor by referencing to uart_port where possible
serial/arc: Remove the workaround for legacy ISS
serial/arc: Use generic earlycon infrastructure
serial/arc: remove earlyprintk support and switch to earlycon
serial/arc: remove last remanants of platform data
serial/arc: inline the probe helper
ARC: [arcfpga] RIP early uart platform device stuff
serial/arc: Add DT based earlycon support

arch/arc/boot/dts/angel4.dts | 3 +-
arch/arc/plat-arcfpga/Kconfig | 7 -
arch/arc/plat-arcfpga/platform.c | 97 +-----------
drivers/tty/serial/Kconfig | 1 +
drivers/tty/serial/arc_uart.c | 329 ++++++++++++++-------------------------
5 files changed, 123 insertions(+), 314 deletions(-)

--
1.8.3.2


2014-06-12 10:32:42

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 2/9] serial/arc: Refactor by referencing to uart_port where possible

The ARC UART MMIO helpers would take arc_uart_port and then reference
generic uart_port->membase member. So change them to difrectly refer to
uart_port and fix call sites accordingly.

This removes the need for to_arc_port() converion almost eveeywhere and
makes code a bit easier to read.

Signed-off-by: Vineet Gupta <[email protected]>
---
drivers/tty/serial/arc_uart.c | 155 +++++++++++++++++++-----------------------
1 file changed, 69 insertions(+), 86 deletions(-)

diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 32fb8b94ff7c..4d971281e3d9 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -72,7 +72,7 @@
#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */

/* Uart bit fiddling helpers: lowest level */
-#define RBASE(uart, reg) (uart->port.membase + reg)
+#define RBASE(port, reg) (port->membase + reg)
#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
#define UART_REG_GET(u, r) readb(RBASE(u, r))

@@ -129,19 +129,15 @@ static struct uart_driver arc_uart_driver = {

static void arc_serial_stop_rx(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
- UART_RX_IRQ_DISABLE(uart);
+ UART_RX_IRQ_DISABLE(port);
}

static void arc_serial_stop_tx(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
- while (!(UART_GET_STATUS(uart) & TXEMPTY))
+ while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();

- UART_TX_IRQ_DISABLE(uart);
+ UART_TX_IRQ_DISABLE(port);
}

/*
@@ -149,10 +145,9 @@ static void arc_serial_stop_tx(struct uart_port *port)
*/
static unsigned int arc_serial_tx_empty(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
unsigned int stat;

- stat = UART_GET_STATUS(uart);
+ stat = UART_GET_STATUS(port);
if (stat & TXEMPTY)
return TIOCSER_TEMT;

@@ -166,24 +161,24 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
* = by uart_start( ) before calling us
* = tx_ist checks that too before calling
*/
-static void arc_serial_tx_chars(struct arc_uart_port *uart)
+static void arc_serial_tx_chars(struct uart_port *port)
{
- struct circ_buf *xmit = &uart->port.state->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
int sent = 0;
unsigned char ch;

- if (unlikely(uart->port.x_char)) {
- UART_SET_DATA(uart, uart->port.x_char);
- uart->port.icount.tx++;
- uart->port.x_char = 0;
+ if (unlikely(port->x_char)) {
+ UART_SET_DATA(port, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
sent = 1;
} else if (xmit->tail != xmit->head) { /* TODO: uart_circ_empty */
ch = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- uart->port.icount.tx++;
- while (!(UART_GET_STATUS(uart) & TXEMPTY))
+ port->icount.tx++;
+ while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();
- UART_SET_DATA(uart, ch);
+ UART_SET_DATA(port, ch);
sent = 1;
}

@@ -192,10 +187,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
* By Hard ISR to schedule processing in software interrupt part
*/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&uart->port);
+ uart_write_wakeup(port);

if (sent)
- UART_TX_IRQ_ENABLE(uart);
+ UART_TX_IRQ_ENABLE(port);
}

/*
@@ -204,12 +199,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
*/
static void arc_serial_start_tx(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
- arc_serial_tx_chars(uart);
+ arc_serial_tx_chars(port);
}

-static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
+static void arc_serial_rx_chars(struct uart_port *port, unsigned int status)
{
unsigned int ch, flg = 0;

@@ -229,15 +222,15 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
*/
if (unlikely(status & (RXOERR | RXFERR))) {
if (status & RXOERR) {
- uart->port.icount.overrun++;
+ port->icount.overrun++;
flg = TTY_OVERRUN;
- UART_CLR_STATUS(uart, RXOERR);
+ UART_CLR_STATUS(port, RXOERR);
}

if (status & RXFERR) {
- uart->port.icount.frame++;
+ port->icount.frame++;
flg = TTY_FRAME;
- UART_CLR_STATUS(uart, RXFERR);
+ UART_CLR_STATUS(port, RXFERR);
}
} else
flg = TTY_NORMAL;
@@ -245,16 +238,16 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
if (status & RXEMPTY)
continue;

- ch = UART_GET_DATA(uart);
- uart->port.icount.rx++;
+ ch = UART_GET_DATA(port);
+ port->icount.rx++;

- if (!(uart_handle_sysrq_char(&uart->port, ch)))
- uart_insert_char(&uart->port, status, RXOERR, ch, flg);
+ if (!(uart_handle_sysrq_char(port, ch)))
+ uart_insert_char(port, status, RXOERR, ch, flg);

- spin_unlock(&uart->port.lock);
- tty_flip_buffer_push(&uart->port.state->port);
- spin_lock(&uart->port.lock);
- } while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
+ spin_unlock(&port->lock);
+ tty_flip_buffer_push(&port->state->port);
+ spin_lock(&port->lock);
+ } while (!((status = UART_GET_STATUS(port)) & RXEMPTY));
}

/*
@@ -287,10 +280,10 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)

static irqreturn_t arc_serial_isr(int irq, void *dev_id)
{
- struct arc_uart_port *uart = dev_id;
+ struct uart_port *port = dev_id;
unsigned int status;

- status = UART_GET_STATUS(uart);
+ status = UART_GET_STATUS(port);

/*
* Single IRQ for both Rx (data available) Tx (room available) Interrupt
@@ -300,9 +293,9 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
if (status & RXIENB) {

/* already in ISR, no need of xx_irqsave */
- spin_lock(&uart->port.lock);
- arc_serial_rx_chars(uart, status);
- spin_unlock(&uart->port.lock);
+ spin_lock(&port->lock);
+ arc_serial_rx_chars(port, status);
+ spin_unlock(&port->lock);
}

if ((status & TXIENB) && (status & TXEMPTY)) {
@@ -310,14 +303,14 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
/* Unconditionally disable further Tx-Interrupts.
* will be enabled by tx_chars() if needed.
*/
- UART_TX_IRQ_DISABLE(uart);
+ UART_TX_IRQ_DISABLE(port);

- spin_lock(&uart->port.lock);
+ spin_lock(&port->lock);

- if (!uart_tx_stopped(&uart->port))
- arc_serial_tx_chars(uart);
+ if (!uart_tx_stopped(port))
+ arc_serial_tx_chars(port);

- spin_unlock(&uart->port.lock);
+ spin_unlock(&port->lock);
}

return IRQ_HANDLED;
@@ -354,18 +347,15 @@ static void arc_serial_break_ctl(struct uart_port *port, int break_state)

static int arc_serial_startup(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
/* Before we hook up the ISR, Disable all UART Interrupts */
- UART_ALL_IRQ_DISABLE(uart);
+ UART_ALL_IRQ_DISABLE(port);

- if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
- uart)) {
- dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
+ if (request_irq(port->irq, arc_serial_isr, 0, "arc uart rx-tx", port)) {
+ dev_warn(port->dev, "Unable to attach ARC UART intr\n");
return -EBUSY;
}

- UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
+ UART_RX_IRQ_ENABLE(port); /* Only Rx IRQ enabled to begin with */

return 0;
}
@@ -373,8 +363,7 @@ static int arc_serial_startup(struct uart_port *port)
/* This is not really needed */
static void arc_serial_shutdown(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
- free_irq(uart->port.irq, uart);
+ free_irq(port->irq, port);
}

static void
@@ -411,12 +400,12 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,

spin_lock_irqsave(&port->lock, flags);

- UART_ALL_IRQ_DISABLE(uart);
+ UART_ALL_IRQ_DISABLE(port);

- UART_SET_BAUDL(uart, uartl);
- UART_SET_BAUDH(uart, uarth);
+ UART_SET_BAUDL(port, uartl);
+ UART_SET_BAUDH(port, uarth);

- UART_RX_IRQ_ENABLE(uart);
+ UART_RX_IRQ_ENABLE(port);

/*
* UART doesn't support Parity/Hardware Flow Control;
@@ -439,9 +428,7 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,

static const char *arc_serial_type(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
- return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
+ return port->type == PORT_ARC ? DRIVER_NAME : NULL;
}

static void arc_serial_release_port(struct uart_port *port)
@@ -470,35 +457,30 @@ arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
*/
static void arc_serial_config_port(struct uart_port *port, int flags)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
if (flags & UART_CONFIG_TYPE)
- uart->port.type = PORT_ARC;
+ port->type = PORT_ARC;
}

#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)

static void arc_serial_poll_putchar(struct uart_port *port, int chr)
{
- struct arc_uart_port *uart = to_arc_port(port);
-
- while (!(UART_GET_STATUS(uart) & TXEMPTY))
+ while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();

- UART_SET_DATA(uart, (unsigned char)chr);
+ UART_SET_DATA(port, (unsigned char)chr);
}
#endif

#ifdef CONFIG_CONSOLE_POLL
static int arc_serial_poll_getchar(struct uart_port *port)
{
- struct arc_uart_port *uart = to_arc_port(port);
unsigned char chr;

- while (!(UART_GET_STATUS(uart) & RXEMPTY))
+ while (!(UART_GET_STATUS(port) & RXEMPTY))
cpu_relax();

- chr = UART_GET_DATA(uart);
+ chr = UART_GET_DATA(port);
return chr;
}
#endif
@@ -532,6 +514,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
struct resource *res, *res2;
unsigned long *plat_data;
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
+ struct uart_port *port = &uart->port;

plat_data = dev_get_platdata(&pdev->dev);
if (!plat_data)
@@ -540,7 +523,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
uart->is_emulated = !!plat_data[0]; /* workaround ISS bug */

if (is_early_platform_device(pdev)) {
- uart->port.uartclk = plat_data[1];
+ port->uartclk = plat_data[1];
uart->baud = plat_data[2];
} else {
struct device_node *np = pdev->dev.of_node;
@@ -550,7 +533,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
dev_err(&pdev->dev, "clock-frequency property NOTset\n");
return -EINVAL;
}
- uart->port.uartclk = val;
+ port->uartclk = val;

if (of_property_read_u32(np, "current-speed", &val)) {
dev_err(&pdev->dev, "current-speed property NOT set\n");
@@ -567,26 +550,26 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
if (!res2)
return -ENODEV;

- uart->port.mapbase = res->start;
- uart->port.membase = ioremap_nocache(res->start, resource_size(res));
- if (!uart->port.membase)
+ port->mapbase = res->start;
+ port->membase = ioremap_nocache(res->start, resource_size(res));
+ if (!port->membase)
/* No point of dev_err since UART itself is hosed here */
return -ENXIO;

- uart->port.irq = res2->start;
- uart->port.dev = &pdev->dev;
- uart->port.iotype = UPIO_MEM;
- uart->port.flags = UPF_BOOT_AUTOCONF;
- uart->port.line = dev_id;
- uart->port.ops = &arc_serial_pops;
+ port->irq = res2->start;
+ port->dev = &pdev->dev;
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->line = dev_id;
+ port->ops = &arc_serial_pops;

- uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
+ port->fifosize = ARC_UART_TX_FIFO_SIZE;

/*
* uart_insert_char( ) uses it in decideding whether to ignore a
* char or not. Explicitly setting it here, removes the subtelty
*/
- uart->port.ignore_status_mask = 0;
+ port->ignore_status_mask = 0;

return 0;
}
--
1.8.3.2

2014-06-12 10:32:47

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 3/9] serial/arc: Remove the workaround for legacy ISS

Signed-off-by: Vineet Gupta <[email protected]>
---
drivers/tty/serial/arc_uart.c | 14 --------------
1 file changed, 14 deletions(-)

diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 4d971281e3d9..a6da10f84293 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -102,7 +102,6 @@
struct arc_uart_port {
struct uart_port port;
unsigned long baud;
- int is_emulated; /* H/w vs. Instruction Set Simulator */
};

#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
@@ -387,17 +386,6 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
uartl = hw_val & 0xFF;
uarth = (hw_val >> 8) & 0xFF;

- /*
- * UART ISS(Instruction Set simulator) emulation has a subtle bug:
- * A existing value of Baudh = 0 is used as a indication to startup
- * it's internal state machine.
- * Thus if baudh is set to 0, 2 times, it chokes.
- * This happens with BAUD=115200 and the formaula above
- * Until that is fixed, when running on ISS, we will set baudh to !0
- */
- if (uart->is_emulated)
- uarth = 1;
-
spin_lock_irqsave(&port->lock, flags);

UART_ALL_IRQ_DISABLE(port);
@@ -520,8 +508,6 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
if (!plat_data)
return -ENODEV;

- uart->is_emulated = !!plat_data[0]; /* workaround ISS bug */
-
if (is_early_platform_device(pdev)) {
port->uartclk = plat_data[1];
uart->baud = plat_data[2];
--
1.8.3.2

2014-06-12 10:33:16

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 5/9] serial/arc: remove earlyprintk support and switch to earlycon

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/boot/dts/angel4.dts | 2 +-
drivers/tty/serial/arc_uart.c | 87 ++++++-------------------------------------
2 files changed, 13 insertions(+), 76 deletions(-)

diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
index 5bb2fdaca02f..6b57475967a6 100644
--- a/arch/arc/boot/dts/angel4.dts
+++ b/arch/arc/boot/dts/angel4.dts
@@ -17,7 +17,7 @@
interrupt-parent = <&intc>;

chosen {
- bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
+ bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
};

aliases {
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 0c8ba5bb97c7..2ffaf099691a 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -500,33 +500,23 @@ static int
arc_uart_init_one(struct platform_device *pdev, int dev_id)
{
struct resource *res, *res2;
- unsigned long *plat_data;
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
struct uart_port *port = &uart->port;

- plat_data = dev_get_platdata(&pdev->dev);
- if (!plat_data)
- return -ENODEV;
+ struct device_node *np = pdev->dev.of_node;
+ u32 val;

- if (is_early_platform_device(pdev)) {
- port->uartclk = plat_data[1];
- uart->baud = plat_data[2];
- } else {
- struct device_node *np = pdev->dev.of_node;
- u32 val;
-
- if (of_property_read_u32(np, "clock-frequency", &val)) {
- dev_err(&pdev->dev, "clock-frequency property NOTset\n");
- return -EINVAL;
- }
- port->uartclk = val;
-
- if (of_property_read_u32(np, "current-speed", &val)) {
- dev_err(&pdev->dev, "current-speed property NOT set\n");
- return -EINVAL;
- }
- uart->baud = val;
+ if (of_property_read_u32(np, "clock-frequency", &val)) {
+ dev_err(&pdev->dev, "clock-frequency property NOTset\n");
+ return -EINVAL;
}
+ port->uartclk = val;
+
+ if (of_property_read_u32(np, "current-speed", &val)) {
+ dev_err(&pdev->dev, "current-speed property NOT set\n");
+ return -EINVAL;
+ }
+ uart->baud = val;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -615,38 +605,6 @@ static struct console arc_console = {
.data = &arc_uart_driver
};

-static __init void early_serial_write(struct console *con, const char *s,
- unsigned int n)
-{
- struct uart_port *port = &arc_uart_ports[con->index].port;
-
- uart_console_write(port, s, n, arc_serial_poll_putchar);
-}
-
-static struct console arc_early_serial_console __initdata = {
- .name = "early_ARCuart",
- .write = early_serial_write,
- .flags = CON_PRINTBUFFER | CON_BOOT,
- .index = -1
-};
-
-static int __init arc_serial_probe_earlyprintk(struct platform_device *pdev)
-{
- int dev_id = pdev->id < 0 ? 0 : pdev->id;
- int rc;
-
- arc_early_serial_console.index = dev_id;
-
- rc = arc_uart_init_one(pdev, dev_id);
- if (rc)
- panic("early console init failed\n");
-
- arc_serial_console_setup(&arc_early_serial_console, NULL);
-
- register_console(&arc_early_serial_console);
- return 0;
-}
-
static __init void arc_early_serial_write(struct console *con, const char *s,
unsigned int n)
{
@@ -721,27 +679,6 @@ static struct platform_driver arc_platform_driver = {
},
};

-#ifdef CONFIG_SERIAL_ARC_CONSOLE
-
-static struct platform_driver early_arc_platform_driver __initdata = {
- .probe = arc_serial_probe_earlyprintk,
- .remove = arc_serial_remove,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-/*
- * Register an early platform driver of "earlyprintk" class.
- * ARCH platform code installs the driver and probes the early devices
- * The installation could rely on user specifying earlyprintk=xyx in cmd line
- * or it could be done independently, for all "earlyprintk" class drivers.
- * [see arch/arc/plat-arcfpga/platform.c]
- */
-early_platform_init("earlyprintk", &early_arc_platform_driver);
-
-#endif /* CONFIG_SERIAL_ARC_CONSOLE */
-
static int __init arc_serial_init(void)
{
int ret;
--
1.8.3.2

2014-06-12 10:33:27

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 6/9] serial/arc: remove last remanants of platform data

Signed-off-by: Vineet Gupta <[email protected]>
---
drivers/tty/serial/arc_uart.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 2ffaf099691a..dc3d5db37dc4 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -37,8 +37,8 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>

/*************************************
* ARC UART Hardware Specs
@@ -499,11 +499,9 @@ static struct uart_ops arc_serial_pops = {
static int
arc_uart_init_one(struct platform_device *pdev, int dev_id)
{
- struct resource *res, *res2;
+ struct device_node *np = pdev->dev.of_node;
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
struct uart_port *port = &uart->port;
-
- struct device_node *np = pdev->dev.of_node;
u32 val;

if (of_property_read_u32(np, "clock-frequency", &val)) {
@@ -518,21 +516,13 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
}
uart->baud = val;

- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res2)
- return -ENODEV;
-
- port->mapbase = res->start;
- port->membase = ioremap_nocache(res->start, resource_size(res));
+ port->membase = of_iomap(np, 0);
if (!port->membase)
/* No point of dev_err since UART itself is hosed here */
return -ENXIO;

- port->irq = res2->start;
+ port->irq = irq_of_parse_and_map(np, 0);
+
port->dev = &pdev->dev;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
--
1.8.3.2

2014-06-12 10:33:12

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 1/9] serial/arc: use uart_console_write() helper

Signed-off-by: Vineet Gupta <[email protected]>
---
drivers/tty/serial/arc_uart.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index c9f5c9dcc15c..32fb8b94ff7c 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -478,14 +478,14 @@ static void arc_serial_config_port(struct uart_port *port, int flags)

#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)

-static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
+static void arc_serial_poll_putchar(struct uart_port *port, int chr)
{
struct arc_uart_port *uart = to_arc_port(port);

while (!(UART_GET_STATUS(uart) & TXEMPTY))
cpu_relax();

- UART_SET_DATA(uart, chr);
+ UART_SET_DATA(uart, (unsigned char)chr);
}
#endif

@@ -622,11 +622,6 @@ static int arc_serial_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}

-static void arc_serial_console_putchar(struct uart_port *port, int ch)
-{
- arc_serial_poll_putchar(port, (unsigned char)ch);
-}
-
/*
* Interrupts are disabled on entering
*/
@@ -637,7 +632,7 @@ static void arc_serial_console_write(struct console *co, const char *s,
unsigned long flags;

spin_lock_irqsave(&port->lock, flags);
- uart_console_write(port, s, count, arc_serial_console_putchar);
+ uart_console_write(port, s, count, arc_serial_poll_putchar);
spin_unlock_irqrestore(&port->lock, flags);
}

@@ -655,13 +650,8 @@ static __init void early_serial_write(struct console *con, const char *s,
unsigned int n)
{
struct uart_port *port = &arc_uart_ports[con->index].port;
- unsigned int i;

- for (i = 0; i < n; i++, s++) {
- if (*s == '\n')
- arc_serial_poll_putchar(port, '\r');
- arc_serial_poll_putchar(port, *s);
- }
+ uart_console_write(port, s, n, arc_serial_poll_putchar);
}

static struct console arc_early_serial_console __initdata = {
--
1.8.3.2

2014-06-12 10:33:58

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 8/9] ARC: [arcfpga] RIP early uart platform device stuff

With ARC uart driver switching to generic earlycon, we no longer need
this ugliness. You won't be missed.

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/plat-arcfpga/Kconfig | 7 ---
arch/arc/plat-arcfpga/platform.c | 97 +---------------------------------------
2 files changed, 2 insertions(+), 102 deletions(-)

diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index e27bb5cc3c1e..b9f34cf55acf 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -41,11 +41,4 @@ config ISS_SMP_EXTN
-XTL (To enable CPU start/stop/set-PC for another CPU)
It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)

-config ARC_SERIAL_BAUD
- int "UART Baud rate"
- default "115200"
- depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
- help
- Baud rate for the ARC UART
-
endif
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
index 61c7e5997387..b8d0d456627f 100644
--- a/arch/arc/plat-arcfpga/platform.c
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -22,115 +22,22 @@
#include <plat/smp.h>
#include <plat/irq.h>

-/*----------------------- Platform Devices -----------------------------*/
-
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
-static unsigned long arc_uart_info[] = {
- 0, /* uart->is_emulated (runtime @running_on_hw) */
- 0, /* uart->port.uartclk */
- 0, /* uart->baud */
- 0
-};
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
-/*
- * static platform data - but only for early serial
- * TBD: derive this from a special DT node
- */
-static struct resource arc_uart0_res[] = {
- {
- .start = UART0_BASE,
- .end = UART0_BASE + 0xFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = UART0_IRQ,
- .end = UART0_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device arc_uart0_dev = {
- .name = "arc-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(arc_uart0_res),
- .resource = arc_uart0_res,
- .dev = {
- .platform_data = &arc_uart_info,
- },
-};
-
-static struct platform_device *fpga_early_devs[] __initdata = {
- &arc_uart0_dev,
-};
-#endif /* CONFIG_SERIAL_ARC_CONSOLE */
-
-static void arc_fpga_serial_init(void)
-{
- /* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
- arc_uart_info[0] = !running_on_hw;
-
- arc_uart_info[1] = arc_get_core_freq();
-
- arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
- early_platform_add_devices(fpga_early_devs,
- ARRAY_SIZE(fpga_early_devs));
-
- /*
- * ARC console driver registers (build time) as an early platform driver
- * of class "earlyprintk". However it needs explicit cmdline toggle
- * "earlyprintk=ttyARC0" to be successfuly runtime registered.
- * Otherwise the early probe below fails to find the driver
- */
- early_platform_driver_probe("earlyprintk", 1, 0);
-
- /*
- * This is to make sure that arc uart would be preferred console
- * despite one/more of following:
- * -command line lacked "console=ttyARC0" or
- * -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
- * Note that this needs to be done after above early console is reg,
- * otherwise the early console never gets a chance to run.
- */
- add_preferred_console("ttyARC", 0, "115200");
-#endif /* CONFIG_SERIAL_ARC_CONSOLE */
-}
-#else /* !IS_ENABLED(CONFIG_SERIAL_ARC) */
-static void arc_fpga_serial_init(void)
-{
-}
-#endif
-
static void __init plat_fpga_early_init(void)
{
pr_info("[plat-arcfpga]: registering early dev resources\n");

- arc_fpga_serial_init();
-
#ifdef CONFIG_ISS_SMP_EXTN
iss_model_init_early_smp();
#endif
}

-static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
- OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
-#endif
- {}
-};
-
static void __init plat_fpga_populate_dev(void)
{
- pr_info("[plat-arcfpga]: registering device resources\n");
-
/*
* Traverses flattened DeviceTree - registering platform devices
- * complete with their resources
+ * (if any) complete with their resources
*/
- of_platform_populate(NULL, of_default_bus_match_table,
- plat_auxdata_lookup, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}

/*----------------------- Machine Descriptions ------------------------------
--
1.8.3.2

2014-06-12 10:34:11

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 9/9] serial/arc: Add DT based earlycon support

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/boot/dts/angel4.dts | 3 ++-
drivers/tty/serial/arc_uart.c | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
index 6b57475967a6..e9fc270d1e0b 100644
--- a/arch/arc/boot/dts/angel4.dts
+++ b/arch/arc/boot/dts/angel4.dts
@@ -17,7 +17,8 @@
interrupt-parent = <&intc>;

chosen {
- bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
+ bootargs = "earlycon console=ttyARC0,115200n8";
+ stdout-path = &arcuart0;
};

aliases {
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 435de4f2af3b..d9900cb3e7b6 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -579,6 +579,7 @@ static int __init arc_early_console_setup(struct earlycon_device *dev,
return 0;
}
EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
+OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);

#endif /* CONFIG_SERIAL_ARC_CONSOLE */

--
1.8.3.2

2014-06-12 10:33:07

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 4/9] serial/arc: Use generic earlycon infrastructure

With this change both earlyprintk and earlycon coexist
We switch over to latter in next patch

Signed-off-by: Vineet Gupta <[email protected]>
---
drivers/tty/serial/Kconfig | 1 +
drivers/tty/serial/arc_uart.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 31 insertions(+)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index fb57159bad3a..2311443be7dc 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1473,6 +1473,7 @@ config SERIAL_ARC_CONSOLE
bool "Console on ARC UART"
depends on SERIAL_ARC=y
select SERIAL_CORE_CONSOLE
+ select SERIAL_EARLYCON
help
Enable system Console on ARC UART

diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index a6da10f84293..0c8ba5bb97c7 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -646,6 +646,36 @@ static int __init arc_serial_probe_earlyprintk(struct platform_device *pdev)
register_console(&arc_early_serial_console);
return 0;
}
+
+static __init void arc_early_serial_write(struct console *con, const char *s,
+ unsigned int n)
+{
+ struct earlycon_device *dev = con->data;
+
+ uart_console_write(&dev->port, s, n, arc_serial_poll_putchar);
+}
+
+static int __init arc_early_console_setup(struct earlycon_device *dev,
+ const char *opt)
+{
+ struct uart_port *port = &dev->port;
+ unsigned int l, h, hw_val;
+
+ if (!dev->port.membase)
+ return -ENODEV;
+
+ hw_val = port->uartclk / (dev->baud * 4) - 1;
+ l = hw_val & 0xFF;
+ h = (hw_val >> 8) & 0xFF;
+
+ UART_SET_BAUDL(port, l);
+ UART_SET_BAUDH(port, h);
+
+ dev->con->write = arc_early_serial_write;
+ return 0;
+}
+EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
+
#endif /* CONFIG_SERIAL_ARC_CONSOLE */

static int arc_serial_probe(struct platform_device *pdev)
--
1.8.3.2

2014-06-12 10:38:48

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH 7/9] serial/arc: inline the probe helper

Signed-off-by: Vineet Gupta <[email protected]>
---
drivers/tty/serial/arc_uart.c | 90 +++++++++++++++++++------------------------
1 file changed, 40 insertions(+), 50 deletions(-)

diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index dc3d5db37dc4..435de4f2af3b 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -496,50 +496,6 @@ static struct uart_ops arc_serial_pops = {
#endif
};

-static int
-arc_uart_init_one(struct platform_device *pdev, int dev_id)
-{
- struct device_node *np = pdev->dev.of_node;
- struct arc_uart_port *uart = &arc_uart_ports[dev_id];
- struct uart_port *port = &uart->port;
- u32 val;
-
- if (of_property_read_u32(np, "clock-frequency", &val)) {
- dev_err(&pdev->dev, "clock-frequency property NOTset\n");
- return -EINVAL;
- }
- port->uartclk = val;
-
- if (of_property_read_u32(np, "current-speed", &val)) {
- dev_err(&pdev->dev, "current-speed property NOT set\n");
- return -EINVAL;
- }
- uart->baud = val;
-
- port->membase = of_iomap(np, 0);
- if (!port->membase)
- /* No point of dev_err since UART itself is hosed here */
- return -ENXIO;
-
- port->irq = irq_of_parse_and_map(np, 0);
-
- port->dev = &pdev->dev;
- port->iotype = UPIO_MEM;
- port->flags = UPF_BOOT_AUTOCONF;
- port->line = dev_id;
- port->ops = &arc_serial_pops;
-
- port->fifosize = ARC_UART_TX_FIFO_SIZE;
-
- /*
- * uart_insert_char( ) uses it in decideding whether to ignore a
- * char or not. Explicitly setting it here, removes the subtelty
- */
- port->ignore_status_mask = 0;
-
- return 0;
-}
-
#ifdef CONFIG_SERIAL_ARC_CONSOLE

static int arc_serial_console_setup(struct console *co, char *options)
@@ -628,8 +584,11 @@ EARLYCON_DECLARE(arc_uart, arc_early_console_setup);

static int arc_serial_probe(struct platform_device *pdev)
{
- int rc, dev_id;
struct device_node *np = pdev->dev.of_node;
+ struct arc_uart_port *uart;
+ struct uart_port *port;
+ int dev_id;
+ u32 val;

/* no device tree device */
if (!np)
@@ -639,12 +598,43 @@ static int arc_serial_probe(struct platform_device *pdev)
if (dev_id < 0)
dev_id = 0;

- rc = arc_uart_init_one(pdev, dev_id);
- if (rc)
- return rc;
+ uart = &arc_uart_ports[dev_id];
+ port = &uart->port;
+
+ if (of_property_read_u32(np, "clock-frequency", &val)) {
+ dev_err(&pdev->dev, "clock-frequency property NOTset\n");
+ return -EINVAL;
+ }
+ port->uartclk = val;
+
+ if (of_property_read_u32(np, "current-speed", &val)) {
+ dev_err(&pdev->dev, "current-speed property NOT set\n");
+ return -EINVAL;
+ }
+ uart->baud = val;
+
+ port->membase = of_iomap(np, 0);
+ if (!port->membase)
+ /* No point of dev_err since UART itself is hosed here */
+ return -ENXIO;
+
+ port->irq = irq_of_parse_and_map(np, 0);
+
+ port->dev = &pdev->dev;
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->line = dev_id;
+ port->ops = &arc_serial_pops;
+
+ port->fifosize = ARC_UART_TX_FIFO_SIZE;
+
+ /*
+ * uart_insert_char( ) uses it in decideding whether to ignore a
+ * char or not. Explicitly setting it here, removes the subtelty
+ */
+ port->ignore_status_mask = 0;

- rc = uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
- return rc;
+ return uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
}

static int arc_serial_remove(struct platform_device *pdev)
--
1.8.3.2

2014-06-13 01:27:08

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH 9/9] serial/arc: Add DT based earlycon support

On Thu, Jun 12, 2014 at 5:31 AM, Vineet Gupta
<[email protected]> wrote:
> Signed-off-by: Vineet Gupta <[email protected]>
> ---

Nice series!

> arch/arc/boot/dts/angel4.dts | 3 ++-
> drivers/tty/serial/arc_uart.c | 1 +
> 2 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
> index 6b57475967a6..e9fc270d1e0b 100644
> --- a/arch/arc/boot/dts/angel4.dts
> +++ b/arch/arc/boot/dts/angel4.dts
> @@ -17,7 +17,8 @@
> interrupt-parent = <&intc>;
>
> chosen {
> - bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
> + bootargs = "earlycon console=ttyARC0,115200n8";
> + stdout-path = &arcuart0;

Just FYI, Grant has a series to pickup the normal console from
stdout-path which would mean you can remove console param as well.
I've kicked him to respin it.

Rob

> };
>
> aliases {
> diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
> index 435de4f2af3b..d9900cb3e7b6 100644
> --- a/drivers/tty/serial/arc_uart.c
> +++ b/drivers/tty/serial/arc_uart.c
> @@ -579,6 +579,7 @@ static int __init arc_early_console_setup(struct earlycon_device *dev,
> return 0;
> }
> EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
> +OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);
>
> #endif /* CONFIG_SERIAL_ARC_CONSOLE */
>
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-06-13 14:10:52

by Vineet Gupta

[permalink] [raw]
Subject: Re: [PATCH 9/9] serial/arc: Add DT based earlycon support

On Friday 13 June 2014 06:57 AM, Rob Herring wrote:
> On Thu, Jun 12, 2014 at 5:31 AM, Vineet Gupta
> <[email protected]> wrote:
>> > Signed-off-by: Vineet Gupta <[email protected]>
>> > ---
> Nice series!
>
>> > arch/arc/boot/dts/angel4.dts | 3 ++-
>> > drivers/tty/serial/arc_uart.c | 1 +
>> > 2 files changed, 3 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
>> > index 6b57475967a6..e9fc270d1e0b 100644
>> > --- a/arch/arc/boot/dts/angel4.dts
>> > +++ b/arch/arc/boot/dts/angel4.dts
>> > @@ -17,7 +17,8 @@
>> > interrupt-parent = <&intc>;
>> >
>> > chosen {
>> > - bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
>> > + bootargs = "earlycon console=ttyARC0,115200n8";
>> > + stdout-path = &arcuart0;
> Just FYI, Grant has a series to pickup the normal console from
> stdout-path which would mean you can remove console param as well.
> I've kicked him to respin it.

OK ! I can split up 9/9 into driver chg and DT change.

In the mean time could you take a look at the driver patches which switch to
earlycon and DT earlycon
and possibly provide Ack/Reviewed by.

Thx,
-Vineet