[PATCH v3 16/25] tty: serial: owl: Implement console driver

2017-02-27 Thread Andreas Färber
Implement serial console driver to complement earlycon.

Based on LeMaker linux-actions tree.

Signed-off-by: Andreas Färber 
---
 v2 -> v3:
 * Adopted BIT() macro
 * Implemented baudrate setting
 
 v2: new
 
 drivers/tty/serial/Kconfig   |   4 +-
 drivers/tty/serial/owl-uart.c| 591 ++-
 include/uapi/linux/serial_core.h |   3 +
 3 files changed, 595 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index e145822..ef232ac 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1678,7 +1678,7 @@ config SERIAL_MVEBU_CONSOLE
  Otherwise, say 'N'.
 
 config SERIAL_OWL
-   bool "Actions Semi Owl serial port support"
+   tristate "Actions Semi Owl serial port support"
depends on ARCH_ACTIONS || COMPILE_TEST
select SERIAL_CORE
help
@@ -1694,7 +1694,7 @@ config SERIAL_OWL_CONSOLE
default y
help
  Say 'Y' here if you wish to use Actions Semiconductor S500/S900 UART
- as the system console. Only earlycon is implemented currently.
+ as the system console.
 
 endmenu
 
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index 1b80087..14e0324 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -20,6 +20,7 @@
  * along with this program. If not, see .
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -28,22 +29,59 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+#define OWL_UART_PORT_NUM 7
+#define OWL_UART_DEV_NAME "ttyOWL"
 
 #define OWL_UART_CTL   0x000
+#define OWL_UART_RXDAT 0x004
 #define OWL_UART_TXDAT 0x008
 #define OWL_UART_STAT  0x00c
 
+#define OWL_UART_CTL_DWLS_MASK (0x3 << 0)
+#define OWL_UART_CTL_DWLS_5BITS(0x0 << 0)
+#define OWL_UART_CTL_DWLS_6BITS(0x1 << 0)
+#define OWL_UART_CTL_DWLS_7BITS(0x2 << 0)
+#define OWL_UART_CTL_DWLS_8BITS(0x3 << 0)
+#define OWL_UART_CTL_STPS_2BITSBIT(2)
+#define OWL_UART_CTL_PRS_MASK  (0x7 << 4)
+#define OWL_UART_CTL_PRS_NONE  (0x0 << 4)
+#define OWL_UART_CTL_PRS_ODD   (0x4 << 4)
+#define OWL_UART_CTL_PRS_MARK  (0x5 << 4)
+#define OWL_UART_CTL_PRS_EVEN  (0x6 << 4)
+#define OWL_UART_CTL_PRS_SPACE (0x7 << 4)
+#define OWL_UART_CTL_AFE   BIT(12)
 #define OWL_UART_CTL_TRFS_TX   BIT(14)
 #define OWL_UART_CTL_ENBIT(15)
+#define OWL_UART_CTL_RXDE  BIT(16)
+#define OWL_UART_CTL_TXDE  BIT(17)
 #define OWL_UART_CTL_RXIE  BIT(18)
 #define OWL_UART_CTL_TXIE  BIT(19)
 
 #define OWL_UART_STAT_RIP  BIT(0)
 #define OWL_UART_STAT_TIP  BIT(1)
+#define OWL_UART_STAT_RXER BIT(2)
+#define OWL_UART_STAT_TFER BIT(3)
+#define OWL_UART_STAT_RXST BIT(4)
+#define OWL_UART_STAT_RFEM BIT(5)
 #define OWL_UART_STAT_TFFU BIT(6)
+#define OWL_UART_STAT_TFES BIT(10)
 #define OWL_UART_STAT_TRFL_MASK(0x1f << 11)
 #define OWL_UART_STAT_UTBB BIT(17)
 
+static struct uart_driver owl_uart_driver;
+
+struct owl_uart_port {
+   struct uart_port port;
+   struct clk *clk;
+};
+
+#define to_owl_uart_port(prt) container_of(prt, struct owl_uart_port, prt)
+
+static struct owl_uart_port *owl_uart_ports[OWL_UART_PORT_NUM];
+
 static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned 
int off)
 {
writel(val, port->membase + off);
@@ -54,6 +92,380 @@ static inline u32 owl_uart_read(struct uart_port *port, 
unsigned int off)
return readl(port->membase + off);
 }
 
+static void owl_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static unsigned int owl_uart_get_mctrl(struct uart_port *port)
+{
+   return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+static unsigned int owl_uart_tx_empty(struct uart_port *port)
+{
+   unsigned long flags;
+   u32 val;
+   unsigned int ret;
+
+   spin_lock_irqsave(>lock, flags);
+
+   val = owl_uart_read(port, OWL_UART_STAT);
+   ret = (val & OWL_UART_STAT_TFES) ? TIOCSER_TEMT : 0;
+
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+static void owl_uart_stop_rx(struct uart_port *port)
+{
+   u32 val;
+
+   val = owl_uart_read(port, OWL_UART_CTL);
+   val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_RXDE);
+   owl_uart_write(port, val, OWL_UART_CTL);
+
+   val = owl_uart_read(port, OWL_UART_STAT);
+   val |= OWL_UART_STAT_RIP;
+   owl_uart_write(port, val, OWL_UART_STAT);
+}
+
+static void owl_uart_stop_tx(struct uart_port *port)
+{
+   u32 val;
+
+   val = owl_uart_read(port, OWL_UART_CTL);
+   val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_TXDE);
+   owl_uart_write(port, val, OWL_UART_CTL);
+
+   val = 

[PATCH v3 16/25] tty: serial: owl: Implement console driver

2017-02-27 Thread Andreas Färber
Implement serial console driver to complement earlycon.

Based on LeMaker linux-actions tree.

Signed-off-by: Andreas Färber 
---
 v2 -> v3:
 * Adopted BIT() macro
 * Implemented baudrate setting
 
 v2: new
 
 drivers/tty/serial/Kconfig   |   4 +-
 drivers/tty/serial/owl-uart.c| 591 ++-
 include/uapi/linux/serial_core.h |   3 +
 3 files changed, 595 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index e145822..ef232ac 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1678,7 +1678,7 @@ config SERIAL_MVEBU_CONSOLE
  Otherwise, say 'N'.
 
 config SERIAL_OWL
-   bool "Actions Semi Owl serial port support"
+   tristate "Actions Semi Owl serial port support"
depends on ARCH_ACTIONS || COMPILE_TEST
select SERIAL_CORE
help
@@ -1694,7 +1694,7 @@ config SERIAL_OWL_CONSOLE
default y
help
  Say 'Y' here if you wish to use Actions Semiconductor S500/S900 UART
- as the system console. Only earlycon is implemented currently.
+ as the system console.
 
 endmenu
 
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index 1b80087..14e0324 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -20,6 +20,7 @@
  * along with this program. If not, see .
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -28,22 +29,59 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+#define OWL_UART_PORT_NUM 7
+#define OWL_UART_DEV_NAME "ttyOWL"
 
 #define OWL_UART_CTL   0x000
+#define OWL_UART_RXDAT 0x004
 #define OWL_UART_TXDAT 0x008
 #define OWL_UART_STAT  0x00c
 
+#define OWL_UART_CTL_DWLS_MASK (0x3 << 0)
+#define OWL_UART_CTL_DWLS_5BITS(0x0 << 0)
+#define OWL_UART_CTL_DWLS_6BITS(0x1 << 0)
+#define OWL_UART_CTL_DWLS_7BITS(0x2 << 0)
+#define OWL_UART_CTL_DWLS_8BITS(0x3 << 0)
+#define OWL_UART_CTL_STPS_2BITSBIT(2)
+#define OWL_UART_CTL_PRS_MASK  (0x7 << 4)
+#define OWL_UART_CTL_PRS_NONE  (0x0 << 4)
+#define OWL_UART_CTL_PRS_ODD   (0x4 << 4)
+#define OWL_UART_CTL_PRS_MARK  (0x5 << 4)
+#define OWL_UART_CTL_PRS_EVEN  (0x6 << 4)
+#define OWL_UART_CTL_PRS_SPACE (0x7 << 4)
+#define OWL_UART_CTL_AFE   BIT(12)
 #define OWL_UART_CTL_TRFS_TX   BIT(14)
 #define OWL_UART_CTL_ENBIT(15)
+#define OWL_UART_CTL_RXDE  BIT(16)
+#define OWL_UART_CTL_TXDE  BIT(17)
 #define OWL_UART_CTL_RXIE  BIT(18)
 #define OWL_UART_CTL_TXIE  BIT(19)
 
 #define OWL_UART_STAT_RIP  BIT(0)
 #define OWL_UART_STAT_TIP  BIT(1)
+#define OWL_UART_STAT_RXER BIT(2)
+#define OWL_UART_STAT_TFER BIT(3)
+#define OWL_UART_STAT_RXST BIT(4)
+#define OWL_UART_STAT_RFEM BIT(5)
 #define OWL_UART_STAT_TFFU BIT(6)
+#define OWL_UART_STAT_TFES BIT(10)
 #define OWL_UART_STAT_TRFL_MASK(0x1f << 11)
 #define OWL_UART_STAT_UTBB BIT(17)
 
+static struct uart_driver owl_uart_driver;
+
+struct owl_uart_port {
+   struct uart_port port;
+   struct clk *clk;
+};
+
+#define to_owl_uart_port(prt) container_of(prt, struct owl_uart_port, prt)
+
+static struct owl_uart_port *owl_uart_ports[OWL_UART_PORT_NUM];
+
 static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned 
int off)
 {
writel(val, port->membase + off);
@@ -54,6 +92,380 @@ static inline u32 owl_uart_read(struct uart_port *port, 
unsigned int off)
return readl(port->membase + off);
 }
 
+static void owl_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static unsigned int owl_uart_get_mctrl(struct uart_port *port)
+{
+   return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+static unsigned int owl_uart_tx_empty(struct uart_port *port)
+{
+   unsigned long flags;
+   u32 val;
+   unsigned int ret;
+
+   spin_lock_irqsave(>lock, flags);
+
+   val = owl_uart_read(port, OWL_UART_STAT);
+   ret = (val & OWL_UART_STAT_TFES) ? TIOCSER_TEMT : 0;
+
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+static void owl_uart_stop_rx(struct uart_port *port)
+{
+   u32 val;
+
+   val = owl_uart_read(port, OWL_UART_CTL);
+   val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_RXDE);
+   owl_uart_write(port, val, OWL_UART_CTL);
+
+   val = owl_uart_read(port, OWL_UART_STAT);
+   val |= OWL_UART_STAT_RIP;
+   owl_uart_write(port, val, OWL_UART_STAT);
+}
+
+static void owl_uart_stop_tx(struct uart_port *port)
+{
+   u32 val;
+
+   val = owl_uart_read(port, OWL_UART_CTL);
+   val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_TXDE);
+   owl_uart_write(port, val, OWL_UART_CTL);
+
+   val = owl_uart_read(port,