diff mbox

[06/11] tty: serial: Add Actions Semi Owl UART earlycon

Message ID 20170215165528.10052-7-afaerber@suse.de
State New
Headers show

Commit Message

Andreas Färber Feb. 15, 2017, 4:55 p.m. UTC
This implements an earlycon for Actions Semi S500/S900 SoCs.

Based on LeMaker linux-actions tree.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 drivers/tty/serial/Kconfig    |  19 ++++++
 drivers/tty/serial/Makefile   |   1 +
 drivers/tty/serial/owl-uart.c | 135 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 drivers/tty/serial/owl-uart.c

Comments

Arnd Bergmann Feb. 16, 2017, 1:41 p.m. UTC | #1
On Wednesday, February 15, 2017 5:55:23 PM CET Andreas Färber wrote:
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 6117ac8..9d4213c 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1677,6 +1677,25 @@ config SERIAL_MVEBU_CONSOLE
>           and warnings and which allows logins in single user mode)
>           Otherwise, say 'N'.
>  
> +config SERIAL_OWL
> +       bool "Actions Semi Owl serial port support"
> +       depends on ARCH_OWL || COMPILE_TEST
> +       select SERIAL_CORE
> +       help
> +         This driver is for Actions Semi S500/S900 SoC's UART.
> +         Say 'Y' here if you wish to use the on-board serial port.
> +         Otherwise, say 'N'.
> +
> 

This could maybe use a word of information about how there isn't
actually a uart driver in this series, only an earlycon driver.

Do you plan to add the actual tty driver soon? If not, maybe
only add one Kconfig symbol for the earlycon support.

	Arnd
Andreas Färber Feb. 20, 2017, 1:40 p.m. UTC | #2
Am 16.02.2017 um 14:41 schrieb Arnd Bergmann:
> On Wednesday, February 15, 2017 5:55:23 PM CET Andreas Färber wrote:
>> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
>> index 6117ac8..9d4213c 100644
>> --- a/drivers/tty/serial/Kconfig
>> +++ b/drivers/tty/serial/Kconfig
>> @@ -1677,6 +1677,25 @@ config SERIAL_MVEBU_CONSOLE
>>           and warnings and which allows logins in single user mode)
>>           Otherwise, say 'N'.
>>  
>> +config SERIAL_OWL
>> +       bool "Actions Semi Owl serial port support"
>> +       depends on ARCH_OWL || COMPILE_TEST
>> +       select SERIAL_CORE
>> +       help
>> +         This driver is for Actions Semi S500/S900 SoC's UART.
>> +         Say 'Y' here if you wish to use the on-board serial port.
>> +         Otherwise, say 'N'.
>> +
>>
> 
> This could maybe use a word of information about how there isn't
> actually a uart driver in this series, only an earlycon driver.

Yeah, I have added a sentence to the other one. Maybe also add a select?

> Do you plan to add the actual tty driver soon? If not, maybe
> only add one Kconfig symbol for the earlycon support.

So, I completed the driver the weekend and can see the full console
output, but there are still output glitches, possible locking issues up
to RCU stalls and soft lockups, and only stubbed out baudrate support.

Therefore I would rather keep the full driver as follow-up RFC in v2,
unless I get it fixed during Hackweek. In the earlycon I am confident,
and the only Kconfig change then is to switch from bool to tristate and
to drop the newly added sentence again.

Regards,
Andreas
Arnd Bergmann Feb. 20, 2017, 3:17 p.m. UTC | #3
On Mon, Feb 20, 2017 at 2:40 PM, Andreas Färber <afaerber@suse.de> wrote:
> Am 16.02.2017 um 14:41 schrieb Arnd Bergmann:
>> On Wednesday, February 15, 2017 5:55:23 PM CET Andreas Färber wrote:
>>> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
>>> index 6117ac8..9d4213c 100644
>>> --- a/drivers/tty/serial/Kconfig
>>> +++ b/drivers/tty/serial/Kconfig
>>> @@ -1677,6 +1677,25 @@ config SERIAL_MVEBU_CONSOLE
>>>           and warnings and which allows logins in single user mode)
>>>           Otherwise, say 'N'.
>>>
>>> +config SERIAL_OWL
>>> +       bool "Actions Semi Owl serial port support"
>>> +       depends on ARCH_OWL || COMPILE_TEST
>>> +       select SERIAL_CORE
>>> +       help
>>> +         This driver is for Actions Semi S500/S900 SoC's UART.
>>> +         Say 'Y' here if you wish to use the on-board serial port.
>>> +         Otherwise, say 'N'.
>>> +
>>>
>>
>> This could maybe use a word of information about how there isn't
>> actually a uart driver in this series, only an earlycon driver.
>
> Yeah, I have added a sentence to the other one. Maybe also add a select?

I generally only use 'select' to avoid build failures, not to save the user
the time to make a choice.

>> Do you plan to add the actual tty driver soon? If not, maybe
>> only add one Kconfig symbol for the earlycon support.
>
> So, I completed the driver the weekend and can see the full console
> output, but there are still output glitches, possible locking issues up
> to RCU stalls and soft lockups, and only stubbed out baudrate support.
>
> Therefore I would rather keep the full driver as follow-up RFC in v2,
> unless I get it fixed during Hackweek. In the earlycon I am confident,
> and the only Kconfig change then is to switch from bool to tristate and
> to drop the newly added sentence again.

Ok, sounds good.

     Arnd
diff mbox

Patch

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 6117ac8..9d4213c 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1677,6 +1677,25 @@  config SERIAL_MVEBU_CONSOLE
 	  and warnings and which allows logins in single user mode)
 	  Otherwise, say 'N'.
 
+config SERIAL_OWL
+	bool "Actions Semi Owl serial port support"
+	depends on ARCH_OWL || COMPILE_TEST
+	select SERIAL_CORE
+	help
+	  This driver is for Actions Semi S500/S900 SoC's UART.
+	  Say 'Y' here if you wish to use the on-board serial port.
+	  Otherwise, say 'N'.
+
+config SERIAL_OWL_CONSOLE
+	bool "Console on Actions Semi Owl serial port"
+	depends on SERIAL_OWL=y
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
+	default y
+	help
+	  Say 'Y' here if you wish to use Actions Semi S500/S900 UART as the
+	  system console.
+
 endmenu
 
 config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 2d6288b..91f3571 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -91,6 +91,7 @@  obj-$(CONFIG_SERIAL_STM32)	+= stm32-usart.o
 obj-$(CONFIG_SERIAL_MVEBU_UART)	+= mvebu-uart.o
 obj-$(CONFIG_SERIAL_PIC32)	+= pic32_uart.o
 obj-$(CONFIG_SERIAL_MPS2_UART)	+= mps2-uart.o
+obj-$(CONFIG_SERIAL_OWL)	+= owl-uart.o
 
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
new file mode 100644
index 0000000..f8b1bb6
--- /dev/null
+++ b/drivers/tty/serial/owl-uart.c
@@ -0,0 +1,135 @@ 
+/*
+ * Actions Semi Owl family serial console
+ *
+ * Copyright 2013 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2016-2017 Andreas Färber
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * 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/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#define OWL_UART_CTL	0x000
+#define OWL_UART_TXDAT	0x008
+#define OWL_UART_STAT	0x00c
+
+#define OWL_UART_CTL_TRFS_TX		(1 << 14)
+#define OWL_UART_CTL_EN			(1 << 15)
+#define OWL_UART_CTL_RXIE		(1 << 18)
+#define OWL_UART_CTL_TXIE		(1 << 19)
+
+#define OWL_UART_STAT_RIP		(1 << 0)
+#define OWL_UART_STAT_TIP		(1 << 1)
+#define OWL_UART_STAT_TFFU		(1 << 6)
+#define OWL_UART_STAT_TRFL_MASK		(0x1f << 11)
+#define OWL_UART_STAT_UTBB		(1 << 17)
+
+static inline void owl_serial_write(struct uart_port *port, u32 val, unsigned int off)
+{
+	writel(val, port->membase + off);
+}
+
+static inline u32 owl_serial_read(struct uart_port *port, unsigned int off)
+{
+	return readl(port->membase + off);
+}
+
+#ifdef CONFIG_SERIAL_OWL_CONSOLE
+
+static void owl_console_putchar(struct uart_port *port, int ch)
+{
+	if (!port->membase)
+		return;
+
+	while (owl_serial_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU)
+		cpu_relax();
+
+	owl_serial_write(port, ch, OWL_UART_TXDAT);
+}
+
+static void owl_serial_port_write(struct uart_port *port, const char *s,
+				  u_int count)
+{
+	u32 old_ctl, val;
+	unsigned long flags;
+	int locked;
+
+	local_irq_save(flags);
+
+	if (port->sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&port->lock);
+	else {
+		spin_lock(&port->lock);
+		locked = 1;
+	}
+
+	old_ctl = owl_serial_read(port, OWL_UART_CTL);
+	val = old_ctl | OWL_UART_CTL_TRFS_TX;
+	/* disable IRQ */
+	val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE);
+	owl_serial_write(port, val, OWL_UART_CTL);
+
+	uart_console_write(port, s, count, owl_console_putchar);
+
+	/* wait until all contents have been sent out */
+	while (owl_serial_read(port, OWL_UART_STAT) & OWL_UART_STAT_TRFL_MASK)
+		cpu_relax();
+
+	/* clear IRQ pending */
+	val = owl_serial_read(port, OWL_UART_STAT);
+	val |= OWL_UART_STAT_TIP | OWL_UART_STAT_RIP;
+	owl_serial_write(port, val, OWL_UART_STAT);
+
+	owl_serial_write(port, old_ctl, OWL_UART_CTL);
+
+	if (locked)
+		spin_unlock(&port->lock);
+
+	local_irq_restore(flags);
+}
+
+static void owl_serial_early_console_write(struct console *co,
+					   const char *s,
+					   u_int count)
+{
+	struct earlycon_device *dev = co->data;
+
+	owl_serial_port_write(&dev->port, s, count);
+}
+
+static int __init
+owl_serial_early_console_setup(struct earlycon_device *device, const char *opt)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->con->write = owl_serial_early_console_write;
+
+	return 0;
+}
+OF_EARLYCON_DECLARE(owl, "acts,owl-uart",
+		    owl_serial_early_console_setup);
+
+#endif /* CONFIG_SERIAL_OWL_CONSOLE */