1 /* 2 * Actions Semi Owl family serial console 3 * 4 * Copyright 2013 Actions Semi Inc. 5 * Author: Actions Semi, Inc. 6 * 7 * Copyright (c) 2016-2017 Andreas Färber 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #include <linux/console.h> 24 #include <linux/delay.h> 25 #include <linux/io.h> 26 #include <linux/module.h> 27 #include <linux/of.h> 28 #include <linux/platform_device.h> 29 #include <linux/serial.h> 30 #include <linux/serial_core.h> 31 32 #define OWL_UART_CTL 0x000 33 #define OWL_UART_TXDAT 0x008 34 #define OWL_UART_STAT 0x00c 35 36 #define OWL_UART_CTL_TRFS_TX BIT(14) 37 #define OWL_UART_CTL_EN BIT(15) 38 #define OWL_UART_CTL_RXIE BIT(18) 39 #define OWL_UART_CTL_TXIE BIT(19) 40 41 #define OWL_UART_STAT_RIP BIT(0) 42 #define OWL_UART_STAT_TIP BIT(1) 43 #define OWL_UART_STAT_TFFU BIT(6) 44 #define OWL_UART_STAT_TRFL_MASK (0x1f << 11) 45 #define OWL_UART_STAT_UTBB BIT(17) 46 47 static inline void owl_uart_write(struct uart_port *port, u32 val, unsigned int off) 48 { 49 writel(val, port->membase + off); 50 } 51 52 static inline u32 owl_uart_read(struct uart_port *port, unsigned int off) 53 { 54 return readl(port->membase + off); 55 } 56 57 #ifdef CONFIG_SERIAL_OWL_CONSOLE 58 59 static void owl_console_putchar(struct uart_port *port, int ch) 60 { 61 if (!port->membase) 62 return; 63 64 while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TFFU) 65 cpu_relax(); 66 67 owl_uart_write(port, ch, OWL_UART_TXDAT); 68 } 69 70 static void owl_uart_port_write(struct uart_port *port, const char *s, 71 u_int count) 72 { 73 u32 old_ctl, val; 74 unsigned long flags; 75 int locked; 76 77 local_irq_save(flags); 78 79 if (port->sysrq) 80 locked = 0; 81 else if (oops_in_progress) 82 locked = spin_trylock(&port->lock); 83 else { 84 spin_lock(&port->lock); 85 locked = 1; 86 } 87 88 old_ctl = owl_uart_read(port, OWL_UART_CTL); 89 val = old_ctl | OWL_UART_CTL_TRFS_TX; 90 /* disable IRQ */ 91 val &= ~(OWL_UART_CTL_RXIE | OWL_UART_CTL_TXIE); 92 owl_uart_write(port, val, OWL_UART_CTL); 93 94 uart_console_write(port, s, count, owl_console_putchar); 95 96 /* wait until all contents have been sent out */ 97 while (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_TRFL_MASK) 98 cpu_relax(); 99 100 /* clear IRQ pending */ 101 val = owl_uart_read(port, OWL_UART_STAT); 102 val |= OWL_UART_STAT_TIP | OWL_UART_STAT_RIP; 103 owl_uart_write(port, val, OWL_UART_STAT); 104 105 owl_uart_write(port, old_ctl, OWL_UART_CTL); 106 107 if (locked) 108 spin_unlock(&port->lock); 109 110 local_irq_restore(flags); 111 } 112 113 static void owl_uart_early_console_write(struct console *co, 114 const char *s, 115 u_int count) 116 { 117 struct earlycon_device *dev = co->data; 118 119 owl_uart_port_write(&dev->port, s, count); 120 } 121 122 static int __init 123 owl_uart_early_console_setup(struct earlycon_device *device, const char *opt) 124 { 125 if (!device->port.membase) 126 return -ENODEV; 127 128 device->con->write = owl_uart_early_console_write; 129 130 return 0; 131 } 132 OF_EARLYCON_DECLARE(owl, "actions,owl-uart", 133 owl_uart_early_console_setup); 134 135 #endif /* CONFIG_SERIAL_OWL_CONSOLE */ 136