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