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