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