1d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* 2d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Driver for GRLIB serial ports (APBUART) 3d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * 4d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Based on linux/drivers/serial/amba.c 5d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * 6d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Copyright (C) 2000 Deep Blue Solutions Ltd. 7d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Copyright (C) 2003 Konrad Eisele <eiselekd@web.de> 8d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Copyright (C) 2006 Daniel Hellstrom <daniel@gaisler.com>, Aeroflex Gaisler AB 9d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Copyright (C) 2008 Gilead Kutnick <kutnickg@zin-tech.com> 10d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Copyright (C) 2009 Kristoffer Glembo <kristoffer@gaisler.com>, Aeroflex Gaisler AB 11d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo */ 12d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 13d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#if defined(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 14d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#define SUPPORT_SYSRQ 15d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#endif 16d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 17d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/module.h> 18d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/tty.h> 19ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty_flip.h> 20d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/ioport.h> 21d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/init.h> 22d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/serial.h> 23d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/console.h> 24d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/sysrq.h> 25d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/kthread.h> 26d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/device.h> 27d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/of.h> 28d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/of_device.h> 29ddaf1b27edf72372242d752730d526b79312a44eDavid S. Miller#include <linux/of_platform.h> 30f28f3313aa97dcb46954f90f596d75f8faf4626eDaniel Hellstrom#include <linux/of_irq.h> 31d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/platform_device.h> 32d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/io.h> 33d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <linux/serial_core.h> 34d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include <asm/irq.h> 35d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 36d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#include "apbuart.h" 37d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 38d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#define SERIAL_APBUART_MAJOR TTY_MAJOR 39d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#define SERIAL_APBUART_MINOR 64 40d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#define UART_DUMMY_RSR_RX 0x8000 /* for ignore all read */ 41d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 42d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_tx_chars(struct uart_port *port); 43d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 44d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_stop_tx(struct uart_port *port) 45d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 46d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int cr; 47d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 48d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr = UART_GET_CTRL(port); 49d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr &= ~UART_CTRL_TI; 50d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, cr); 51d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 52d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 53d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_start_tx(struct uart_port *port) 54d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 55d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int cr; 56d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 57d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr = UART_GET_CTRL(port); 58d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr |= UART_CTRL_TI; 59d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, cr); 60d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 61d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (UART_GET_STATUS(port) & UART_STATUS_THE) 62d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_tx_chars(port); 63d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 64d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 65d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_stop_rx(struct uart_port *port) 66d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 67d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int cr; 68d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 69d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr = UART_GET_CTRL(port); 70d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr &= ~(UART_CTRL_RI); 71d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, cr); 72d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 73d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 74d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_rx_chars(struct uart_port *port) 75d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 76d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int status, ch, rsr, flag; 77d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int max_chars = port->fifosize; 78d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 79d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 80d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 81d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo while (UART_RX_DATA(status) && (max_chars--)) { 82d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 83d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ch = UART_GET_CHAR(port); 84d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo flag = TTY_NORMAL; 85d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 86d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.rx++; 87d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 88d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX; 89d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_STATUS(port, 0); 90d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (rsr & UART_STATUS_ERR) { 91d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 92d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (rsr & UART_STATUS_BR) { 93d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo rsr &= ~(UART_STATUS_FE | UART_STATUS_PE); 94d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.brk++; 95d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (uart_handle_break(port)) 96d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo goto ignore_char; 97d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } else if (rsr & UART_STATUS_PE) { 98d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.parity++; 99d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } else if (rsr & UART_STATUS_FE) { 100d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.frame++; 101d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 102d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (rsr & UART_STATUS_OE) 103d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.overrun++; 104d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 105d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo rsr &= port->read_status_mask; 106d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 107d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (rsr & UART_STATUS_PE) 108d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo flag = TTY_PARITY; 109d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo else if (rsr & UART_STATUS_FE) 110d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo flag = TTY_FRAME; 111d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 112d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 113d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (uart_handle_sysrq_char(port, ch)) 114d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo goto ignore_char; 115d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 116d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_insert_char(port, rsr, UART_STATUS_OE, ch, flag); 117d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 118d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 119d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ignore_char: 120d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 121d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 122d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 12378d34d75c84d99ad61f6677a34c136f0adc6d78dViresh Kumar spin_unlock(&port->lock); 1242e124b4a390ca85325fae75764bef92f0547fa25Jiri Slaby tty_flip_buffer_push(&port->state->port); 12578d34d75c84d99ad61f6677a34c136f0adc6d78dViresh Kumar spin_lock(&port->lock); 126d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 127d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 128d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_tx_chars(struct uart_port *port) 129d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 130d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct circ_buf *xmit = &port->state->xmit; 131d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int count; 132d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 133d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (port->x_char) { 134d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CHAR(port, port->x_char); 135d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.tx++; 136d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->x_char = 0; 137d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return; 138d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 139d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 140d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { 141d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_stop_tx(port); 142d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return; 143d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 144d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 145d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* amba: fill FIFO */ 146d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo count = port->fifosize >> 1; 147d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo do { 148d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CHAR(port, xmit->buf[xmit->tail]); 149d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 150d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->icount.tx++; 151d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (uart_circ_empty(xmit)) 152d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo break; 153d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } while (--count > 0); 154d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 155d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 156d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_write_wakeup(port); 157d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 158d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (uart_circ_empty(xmit)) 159d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_stop_tx(port); 160d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 161d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 162d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic irqreturn_t apbuart_int(int irq, void *dev_id) 163d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 164d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct uart_port *port = dev_id; 165d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int status; 166d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 167d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo spin_lock(&port->lock); 168d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 169d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 170d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (status & UART_STATUS_DR) 171d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_rx_chars(port); 172d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (status & UART_STATUS_THE) 173d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_tx_chars(port); 174d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 175d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo spin_unlock(&port->lock); 176d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 177d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return IRQ_HANDLED; 178d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 179d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 180d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic unsigned int apbuart_tx_empty(struct uart_port *port) 181d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 182d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int status = UART_GET_STATUS(port); 183d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return status & UART_STATUS_THE ? TIOCSER_TEMT : 0; 184d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 185d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 186d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic unsigned int apbuart_get_mctrl(struct uart_port *port) 187d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 188d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* The GRLIB APBUART handles flow control in hardware */ 189d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; 190d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 191d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 192d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_set_mctrl(struct uart_port *port, unsigned int mctrl) 193d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 194d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* The GRLIB APBUART handles flow control in hardware */ 195d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 196d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 197d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_break_ctl(struct uart_port *port, int break_state) 198d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 199d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* We don't support sending break */ 200d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 201d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 202d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int apbuart_startup(struct uart_port *port) 203d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 204d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int retval; 205d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int cr; 206d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 207d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Allocate the IRQ */ 208d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo retval = request_irq(port->irq, apbuart_int, 0, "apbuart", port); 209d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (retval) 210d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return retval; 211d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 212d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Finally, enable interrupts */ 213d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr = UART_GET_CTRL(port); 214d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, 215d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr | UART_CTRL_RE | UART_CTRL_TE | 216d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_CTRL_RI | UART_CTRL_TI); 217d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 218d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return 0; 219d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 220d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 221d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_shutdown(struct uart_port *port) 222d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 223d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int cr; 224d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 225d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* disable all interrupts, disable the port */ 226d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr = UART_GET_CTRL(port); 227d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, 228d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr & ~(UART_CTRL_RE | UART_CTRL_TE | 229d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_CTRL_RI | UART_CTRL_TI)); 230d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 231d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Free the interrupt */ 232d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo free_irq(port->irq, port); 233d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 234d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 235d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_set_termios(struct uart_port *port, 236d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct ktermios *termios, struct ktermios *old) 237d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 238d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int cr; 239d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned long flags; 240d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int baud, quot; 241d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 242d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Ask the core to calculate the divisor for us. */ 243d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); 244d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (baud == 0) 245d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo panic("invalid baudrate %i\n", port->uartclk / 16); 246d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 247d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* uart_get_divisor calc a *16 uart freq, apbuart is *8 */ 248d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo quot = (uart_get_divisor(port, baud)) * 2; 249d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr = UART_GET_CTRL(port); 250d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr &= ~(UART_CTRL_PE | UART_CTRL_PS); 251d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 252d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (termios->c_cflag & PARENB) { 253d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr |= UART_CTRL_PE; 254d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if ((termios->c_cflag & PARODD)) 255d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr |= UART_CTRL_PS; 256d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 257d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 258d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Enable flow control. */ 259d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (termios->c_cflag & CRTSCTS) 260d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo cr |= UART_CTRL_FL; 261d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 262d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo spin_lock_irqsave(&port->lock, flags); 263d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 264d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Update the per-port timeout. */ 265d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_update_timeout(port, termios->c_cflag, baud); 266d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 267d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->read_status_mask = UART_STATUS_OE; 268d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (termios->c_iflag & INPCK) 269d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->read_status_mask |= UART_STATUS_FE | UART_STATUS_PE; 270d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 271d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Characters to ignore */ 272d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->ignore_status_mask = 0; 273d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (termios->c_iflag & IGNPAR) 274d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->ignore_status_mask |= UART_STATUS_FE | UART_STATUS_PE; 275d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 276d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Ignore all characters if CREAD is not set. */ 277d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if ((termios->c_cflag & CREAD) == 0) 278d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->ignore_status_mask |= UART_DUMMY_RSR_RX; 279d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 280d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Set baud rate */ 281d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo quot -= 1; 282d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_SCAL(port, quot); 283d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, cr); 284d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 285d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo spin_unlock_irqrestore(&port->lock, flags); 286d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 287d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 288d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic const char *apbuart_type(struct uart_port *port) 289d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 290d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return port->type == PORT_APBUART ? "GRLIB/APBUART" : NULL; 291d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 292d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 293d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_release_port(struct uart_port *port) 294d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 295d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo release_mem_region(port->mapbase, 0x100); 296d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 297d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 298d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int apbuart_request_port(struct uart_port *port) 299d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 300d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return request_mem_region(port->mapbase, 0x100, "grlib-apbuart") 301d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo != NULL ? 0 : -EBUSY; 302d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return 0; 303d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 304d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 305d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* Configure/autoconfigure the port */ 306d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_config_port(struct uart_port *port, int flags) 307d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 308d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (flags & UART_CONFIG_TYPE) { 309d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->type = PORT_APBUART; 310d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_request_port(port); 311d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 312d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 313d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 314d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* Verify the new serial_struct (for TIOCSSERIAL) */ 315d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int apbuart_verify_port(struct uart_port *port, 316d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct serial_struct *ser) 317d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 318d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int ret = 0; 319d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (ser->type != PORT_UNKNOWN && ser->type != PORT_APBUART) 320d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ret = -EINVAL; 321d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (ser->irq < 0 || ser->irq >= NR_IRQS) 322d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ret = -EINVAL; 323d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (ser->baud_base < 9600) 324d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ret = -EINVAL; 325d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return ret; 326d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 327d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 328d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic struct uart_ops grlib_apbuart_ops = { 329d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .tx_empty = apbuart_tx_empty, 330d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .set_mctrl = apbuart_set_mctrl, 331d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .get_mctrl = apbuart_get_mctrl, 332d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .stop_tx = apbuart_stop_tx, 333d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .start_tx = apbuart_start_tx, 334d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .stop_rx = apbuart_stop_rx, 335d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .break_ctl = apbuart_break_ctl, 336d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .startup = apbuart_startup, 337d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .shutdown = apbuart_shutdown, 338d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .set_termios = apbuart_set_termios, 339d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .type = apbuart_type, 340d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .release_port = apbuart_release_port, 341d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .request_port = apbuart_request_port, 342d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .config_port = apbuart_config_port, 343d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .verify_port = apbuart_verify_port, 344d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo}; 345d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 346d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic struct uart_port grlib_apbuart_ports[UART_NR]; 347d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic struct device_node *grlib_apbuart_nodes[UART_NR]; 348d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 349d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int apbuart_scan_fifo_size(struct uart_port *port, int portnumber) 350d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 351d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int ctrl, loop = 0; 352d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int status; 353d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int fifosize; 354d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned long flags; 355d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 356d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ctrl = UART_GET_CTRL(port); 357d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 358d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* 359d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Enable the transceiver and wait for it to be ready to send data. 360d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Clear interrupts so that this process will not be externally 361d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * interrupted in the middle (which can cause the transceiver to 362d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * drain prematurely). 363d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo */ 364d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 365d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo local_irq_save(flags); 366d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 367d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, ctrl | UART_CTRL_TE); 368d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 369d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo while (!UART_TX_READY(UART_GET_STATUS(port))) 370d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo loop++; 371d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 372d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* 373d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Disable the transceiver so data isn't actually sent during the 374d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * actual test. 375d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo */ 376d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 377d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, ctrl & ~(UART_CTRL_TE)); 378d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 379d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo fifosize = 1; 380d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CHAR(port, 0); 381d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 382d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* 383d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * So long as transmitting a character increments the tranceivier FIFO 384d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * length the FIFO must be at least that big. These bytes will 385d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * automatically drain off of the FIFO. 386d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo */ 387d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 388d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 389d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo while (((status >> 20) & 0x3F) == fifosize) { 390d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo fifosize++; 391d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CHAR(port, 0); 392d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 393d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 394d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 395d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo fifosize--; 396d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 397d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, ctrl); 398d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo local_irq_restore(flags); 399d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 400d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (fifosize == 0) 401d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo fifosize = 1; 402d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 403d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return fifosize; 404d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 405d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 406d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_flush_fifo(struct uart_port *port) 407d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 408d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int i; 409d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 410d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo for (i = 0; i < port->fifosize; i++) 411d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_GET_CHAR(port); 412d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 413d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 414d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 415d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* ======================================================================== */ 416d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* Console driver, if enabled */ 417d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* ======================================================================== */ 418d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 419d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE 420d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 421d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void apbuart_console_putchar(struct uart_port *port, int ch) 422d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 423d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int status; 424d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo do { 425d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 426d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } while (!UART_TX_READY(status)); 427d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CHAR(port, ch); 428d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 429d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 430d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void 431d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glemboapbuart_console_write(struct console *co, const char *s, unsigned int count) 432d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 433d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct uart_port *port = &grlib_apbuart_ports[co->index]; 434d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int status, old_cr, new_cr; 435d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 436d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* First save the CR then disable the interrupts */ 437d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo old_cr = UART_GET_CTRL(port); 438d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo new_cr = old_cr & ~(UART_CTRL_RI | UART_CTRL_TI); 439d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, new_cr); 440d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 441d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_console_write(port, s, count, apbuart_console_putchar); 442d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 443d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* 444d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Finally, wait for transmitter to become empty 445d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * and restore the TCR 446d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo */ 447d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo do { 448d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 449d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } while (!UART_TX_READY(status)); 450d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo UART_PUT_CTRL(port, old_cr); 451d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 452d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 453d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void __init 454d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glemboapbuart_console_get_options(struct uart_port *port, int *baud, 455d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int *parity, int *bits) 456d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 457d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (UART_GET_CTRL(port) & (UART_CTRL_RE | UART_CTRL_TE)) { 458d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 459d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo unsigned int quot, status; 460d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo status = UART_GET_STATUS(port); 461d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 462d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo *parity = 'n'; 463d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (status & UART_CTRL_PE) { 464d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if ((status & UART_CTRL_PS) == 0) 465d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo *parity = 'e'; 466d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo else 467d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo *parity = 'o'; 468d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 469d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 470d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo *bits = 8; 471d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo quot = UART_GET_SCAL(port) / 8; 472d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo *baud = port->uartclk / (16 * (quot + 1)); 473d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 474d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 475d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 476d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int __init apbuart_console_setup(struct console *co, char *options) 477d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 478d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct uart_port *port; 479d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int baud = 38400; 480d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int bits = 8; 481d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int parity = 'n'; 482d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int flow = 'n'; 483d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 484d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo pr_debug("apbuart_console_setup co=%p, co->index=%i, options=%s\n", 485d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo co, co->index, options); 486d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 487d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* 488d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * Check whether an invalid uart number has been specified, and 489d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * if so, search for the first available port that does have 490d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo * console support. 491d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo */ 492d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (co->index >= grlib_apbuart_port_nr) 493d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo co->index = 0; 494d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 495d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port = &grlib_apbuart_ports[co->index]; 496d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 497d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo spin_lock_init(&port->lock); 498d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 499d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (options) 500d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_parse_options(options, &baud, &parity, &bits, &flow); 501d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo else 502d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_console_get_options(port, &baud, &parity, &bits); 503d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 504d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return uart_set_options(port, co, baud, parity, bits, flow); 505d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 506d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 507d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic struct uart_driver grlib_apbuart_driver; 508d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 509d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic struct console grlib_apbuart_console = { 510d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .name = "ttyS", 511d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .write = apbuart_console_write, 512d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .device = uart_console_device, 513d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .setup = apbuart_console_setup, 514d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .flags = CON_PRINTBUFFER, 515d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .index = -1, 516d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .data = &grlib_apbuart_driver, 517d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo}; 518d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 519d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 520568389c257fa7d74ce36c2f78bad31965fded4cfThomas Gleixnerstatic int grlib_apbuart_configure(void); 521d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 522d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int __init apbuart_console_init(void) 523d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 524568389c257fa7d74ce36c2f78bad31965fded4cfThomas Gleixner if (grlib_apbuart_configure()) 525568389c257fa7d74ce36c2f78bad31965fded4cfThomas Gleixner return -ENODEV; 526d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo register_console(&grlib_apbuart_console); 527d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return 0; 528d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 529d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 530d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glemboconsole_initcall(apbuart_console_init); 531d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 532d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#define APBUART_CONSOLE (&grlib_apbuart_console) 533d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#else 534d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#define APBUART_CONSOLE NULL 535d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo#endif 536d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 537d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic struct uart_driver grlib_apbuart_driver = { 538d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .owner = THIS_MODULE, 539d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .driver_name = "serial", 540d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .dev_name = "ttyS", 541d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .major = SERIAL_APBUART_MAJOR, 542d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .minor = SERIAL_APBUART_MINOR, 543d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .nr = UART_NR, 544d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .cons = APBUART_CONSOLE, 545d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo}; 546d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 547d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 548d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* ======================================================================== */ 549d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* OF Platform Driver */ 550d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo/* ======================================================================== */ 551d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 5529671f09921d93e722a28ae9610d478e092ac5466Bill Pembertonstatic int apbuart_probe(struct platform_device *op) 553d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 55410544f128c338aeb7f63c002ad7eee67aa0e6acfDaniel Hellstrom int i; 555d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo struct uart_port *port = NULL; 556d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 557d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo for (i = 0; i < grlib_apbuart_port_nr; i++) { 55861c7a080a5a061c976988fd4b844dfb468dda255Grant Likely if (op->dev.of_node == grlib_apbuart_nodes[i]) 559d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo break; 560d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 561d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 562d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port = &grlib_apbuart_ports[i]; 563d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->dev = &op->dev; 56410544f128c338aeb7f63c002ad7eee67aa0e6acfDaniel Hellstrom port->irq = op->archdata.irqs[0]; 565d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 566d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_add_one_port(&grlib_apbuart_driver, (struct uart_port *) port); 567d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 568d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo apbuart_flush_fifo((struct uart_port *) port); 569d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 570384a17b284b9dc92b480cf388310a25e255bac8aDavid S. Miller printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n", 571384a17b284b9dc92b480cf388310a25e255bac8aDavid S. Miller (unsigned long long) port->mapbase, port->irq); 572d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return 0; 573d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 574d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 575ab17da5cb9d4aaf9f04c706761d3a8024897beddSam Ravnborgstatic struct of_device_id apbuart_match[] = { 576d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo { 577d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .name = "GAISLER_APBUART", 578d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo }, 579d89ddf0da8f0a140d4dc2e2dbc594fb278e33db5Daniel Hellstrom { 580d89ddf0da8f0a140d4dc2e2dbc594fb278e33db5Daniel Hellstrom .name = "01_00c", 581d89ddf0da8f0a140d4dc2e2dbc594fb278e33db5Daniel Hellstrom }, 582d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo {}, 583d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo}; 584d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 585793218dfea146946a076f4fe51e574db61034a3eGrant Likelystatic struct platform_driver grlib_apbuart_of_driver = { 586d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .probe = apbuart_probe, 587d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo .driver = { 5884018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .owner = THIS_MODULE, 5894018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .name = "grlib-apbuart", 5904018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .of_match_table = apbuart_match, 5914018294b53d1dae026880e45f174c1cc63b5d435Grant Likely }, 592d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo}; 593d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 594d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 595ab17da5cb9d4aaf9f04c706761d3a8024897beddSam Ravnborgstatic int __init grlib_apbuart_configure(void) 596d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 597c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom struct device_node *np; 598c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom int line = 0; 599d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 600d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo for_each_matching_node(np, apbuart_match) { 60110544f128c338aeb7f63c002ad7eee67aa0e6acfDaniel Hellstrom const int *ampopts; 602c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom const u32 *freq_hz; 60335c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner const struct amba_prom_registers *regs; 60435c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner struct uart_port *port; 60535c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner unsigned long addr; 606d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 60756b85f32d530d09d6805488ad00775d4e0e3baabLinus Torvalds ampopts = of_get_property(np, "ampopts", NULL); 608f28f3313aa97dcb46954f90f596d75f8faf4626eDaniel Hellstrom if (ampopts && (*ampopts == 0)) 609f28f3313aa97dcb46954f90f596d75f8faf4626eDaniel Hellstrom continue; /* Ignore if used by another OS instance */ 61035c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner regs = of_get_property(np, "reg", NULL); 611c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom /* Frequency of APB Bus is frequency of UART */ 612c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom freq_hz = of_get_property(np, "freq", NULL); 613d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 614c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom if (!regs || !freq_hz || (*freq_hz == 0)) 61556b85f32d530d09d6805488ad00775d4e0e3baabLinus Torvalds continue; 616d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 617d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo grlib_apbuart_nodes[line] = np; 618d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 619d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo addr = regs->phys_addr; 620d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 621d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port = &grlib_apbuart_ports[line]; 622d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 623d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->mapbase = addr; 624d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map)); 62510544f128c338aeb7f63c002ad7eee67aa0e6acfDaniel Hellstrom port->irq = 0; 626d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->iotype = UPIO_MEM; 627d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->ops = &grlib_apbuart_ops; 628d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->flags = UPF_BOOT_AUTOCONF; 629d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->line = line; 630c897dcf6311ea9c8d24e96cc7f7fe9de58a0a6a2Daniel Hellstrom port->uartclk = *freq_hz; 631d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo port->fifosize = apbuart_scan_fifo_size((struct uart_port *) port, line); 632d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo line++; 633d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 634d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* We support maximum UART_NR uarts ... */ 635d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (line == UART_NR) 636d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo break; 637d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 638d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 639d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line; 64035c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner return line ? 0 : -ENODEV; 641d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 642d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 643d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic int __init grlib_apbuart_init(void) 644d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 645d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int ret; 646d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 647d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo /* Find all APBUARTS in device the tree and initialize their ports */ 64835c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner ret = grlib_apbuart_configure(); 64935c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner if (ret) 65035c64e5d13c3d7d8c4ad061ad5e20498b9160c24Thomas Gleixner return ret; 651d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 652d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo printk(KERN_INFO "Serial: GRLIB APBUART driver\n"); 653d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 654d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo ret = uart_register_driver(&grlib_apbuart_driver); 655d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 656d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (ret) { 657d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo printk(KERN_ERR "%s: uart_register_driver failed (%i)\n", 658d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo __FILE__, ret); 659d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return ret; 660d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 661d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 662793218dfea146946a076f4fe51e574db61034a3eGrant Likely ret = platform_driver_register(&grlib_apbuart_of_driver); 663d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo if (ret) { 664d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo printk(KERN_ERR 665793218dfea146946a076f4fe51e574db61034a3eGrant Likely "%s: platform_driver_register failed (%i)\n", 666d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo __FILE__, ret); 667d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_unregister_driver(&grlib_apbuart_driver); 668d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return ret; 669d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo } 670d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 671d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo return ret; 672d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 673d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 674d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembostatic void __exit grlib_apbuart_exit(void) 675d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo{ 676d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo int i; 677d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 678d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo for (i = 0; i < grlib_apbuart_port_nr; i++) 679d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_remove_one_port(&grlib_apbuart_driver, 680d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo &grlib_apbuart_ports[i]); 681d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 682d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo uart_unregister_driver(&grlib_apbuart_driver); 683793218dfea146946a076f4fe51e574db61034a3eGrant Likely platform_driver_unregister(&grlib_apbuart_of_driver); 684d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo} 685d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 686d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembomodule_init(grlib_apbuart_init); 687d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembomodule_exit(grlib_apbuart_exit); 688d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer Glembo 689d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer GlemboMODULE_AUTHOR("Aeroflex Gaisler AB"); 690d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer GlemboMODULE_DESCRIPTION("GRLIB APBUART serial driver"); 691d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer GlemboMODULE_VERSION("2.1"); 692d4ac42a582e46d7f86f0acb4253a310423c72c4cKristoffer GlemboMODULE_LICENSE("GPL"); 693