134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/* 234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * timbuart.c timberdale FPGA UART driver 334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Copyright (c) 2009 Intel Corporation 434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * 534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * This program is free software; you can redistribute it and/or modify 634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * it under the terms of the GNU General Public License version 2 as 734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * published by the Free Software Foundation. 834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * 934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * This program is distributed in the hope that it will be useful, 1034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * but WITHOUT ANY WARRANTY; without even the implied warranty of 1134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * GNU General Public License for more details. 1334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * 1434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * You should have received a copy of the GNU General Public License 1534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * along with this program; if not, write to the Free Software 1634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 1834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 1934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/* Supports: 2034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Timberdale FPGA UART 2134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 2234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 2334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/pci.h> 2434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/interrupt.h> 2534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/serial_core.h> 26ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty.h> 27ee160a38eee357ed2572cf41437d5814ce53c839Jiri Slaby#include <linux/tty_flip.h> 2834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/kernel.h> 2934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/platform_device.h> 3034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/ioport.h> 315a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 32578b9ce0095ff3dd2c3b94508407c3be8fcce68dPaul Gortmaker#include <linux/module.h> 3334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 3434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include "timbuart.h" 3534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 3634aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstruct timbuart_port { 3734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct uart_port port; 3834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct tasklet_struct tasklet; 3934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int usedma; 402421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors u32 last_ier; 4134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct platform_device *dev; 4234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 4334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800, 4534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 921600, 1843200, 3250000}; 4634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 472421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjforsstatic void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier); 4834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4934aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic irqreturn_t timbuart_handleinterrupt(int irq, void *devid); 5034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 5134aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_stop_rx(struct uart_port *port) 5234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 5334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* spin lock held by upper layer, disable all RX interrupts */ 542421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors u32 ier = ioread32(port->membase + TIMBUART_IER) & ~RXFLAGS; 552421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(ier, port->membase + TIMBUART_IER); 5634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 5734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 5834aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_stop_tx(struct uart_port *port) 5934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 6034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* spinlock held by upper layer, disable TX interrupt */ 612421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors u32 ier = ioread32(port->membase + TIMBUART_IER) & ~TXBAE; 622421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(ier, port->membase + TIMBUART_IER); 6334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 6434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 6534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_start_tx(struct uart_port *port) 6634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 6734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 6834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 6934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 7034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* do not transfer anything here -> fire off the tasklet */ 7134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_schedule(&uart->tasklet); 7234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 7334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 7424cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjforsstatic unsigned int timbuart_tx_empty(struct uart_port *port) 7524cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors{ 7624cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors u32 isr = ioread32(port->membase + TIMBUART_ISR); 7724cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors 7824cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors return (isr & TXBE) ? TIOCSER_TEMT : 0; 7924cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors} 8024cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors 8134aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_flush_buffer(struct uart_port *port) 8234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 8324cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors if (!timbuart_tx_empty(port)) { 8424cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | 8524cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors TIMBUART_CTRL_FLSHTX; 8634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 8724cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors iowrite8(ctl, port->membase + TIMBUART_CTRL); 8824cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors iowrite32(TXBF, port->membase + TIMBUART_ISR); 8924cd73a3942f3df214d7953f0cfd65d5085fa583Richard Röjfors } 9034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 9134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 9234aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_rx_chars(struct uart_port *port) 9334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 94ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox struct tty_struct *tty = port->state->port.tty; 9534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 962421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors while (ioread32(port->membase + TIMBUART_ISR) & RXDP) { 9734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ch = ioread8(port->membase + TIMBUART_RXFIFO); 9834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.rx++; 9934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tty_insert_flip_char(tty, ch, TTY_NORMAL); 10034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 10134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 10234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_unlock(&port->lock); 103ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox tty_flip_buffer_push(port->state->port.tty); 10434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_lock(&port->lock); 10534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 10634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - total read %d bytes\n", 10734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors __func__, port->icount.rx); 10834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 10934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 11034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_tx_chars(struct uart_port *port) 11134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 112ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox struct circ_buf *xmit = &port->state->xmit; 11334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 1142421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) && 11534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors !uart_circ_empty(xmit)) { 11634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(xmit->buf[xmit->tail], 11734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase + TIMBUART_TXFIFO); 11834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 11934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.tx++; 12034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 12134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 12234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, 12334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n", 12434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors __func__, 12534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.tx, 12634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors ioread8(port->membase + TIMBUART_CTRL), 12734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->mctrl & TIOCM_RTS, 12834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors ioread8(port->membase + TIMBUART_BAUDRATE)); 12934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 13034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 1312421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjforsstatic void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier) 13234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 13334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 13434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 135ebd2c8f6d2ec4012c267ecb95e72a57b8355a705Alan Cox struct circ_buf *xmit = &port->state->xmit; 13634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 13734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (uart_circ_empty(xmit) || uart_tx_stopped(port)) 13834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return; 13934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 14034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->x_char) 14134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return; 14234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 14334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & TXFLAGS) { 14434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_tx_chars(port); 14534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* clear all TX interrupts */ 1462421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(TXFLAGS, port->membase + TIMBUART_ISR); 14734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 14834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 14934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_write_wakeup(port); 15034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } else 15134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* Re-enable any tx interrupt */ 15234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= uart->last_ier & TXFLAGS; 15334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 15434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* enable interrupts if there are chars in the transmit buffer, 15534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Or if we delivered some bytes and want the almost empty interrupt 15634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * we wake up the upper layer later when we got the interrupt 15734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * to give it some time to go out... 15834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 15934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart_circ_empty(xmit)) 16034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= TXBAE; 16134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 16234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - leaving\n", __func__); 16334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 16434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 1652421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjforsvoid timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier) 16634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 16734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & RXFLAGS) { 16834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* Some RX status is set */ 16934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & RXBF) { 17034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | 17134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors TIMBUART_CTRL_FLSHRX; 17234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(ctl, port->membase + TIMBUART_CTRL); 17334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.overrun++; 17434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } else if (isr & (RXDP)) 17534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_rx_chars(port); 17634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 17734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* ack all RX interrupts */ 1782421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(RXFLAGS, port->membase + TIMBUART_ISR); 17934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 18034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* always have the RX interrupts enabled */ 18234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= RXBAF | RXBF | RXTT; 18334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - leaving\n", __func__); 18534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 18634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsvoid timbuart_tasklet(unsigned long arg) 18834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 18934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = (struct timbuart_port *)arg; 1902421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors u32 isr, ier = 0; 19134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 19234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_lock(&uart->port.lock); 19334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 1942421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors isr = ioread32(uart->port.membase + TIMBUART_ISR); 19534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr); 19634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 19734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart->usedma) 19834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_handle_tx_port(&uart->port, isr, &ier); 19934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 20034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_mctrl_check(&uart->port, isr, &ier); 20134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 20234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart->usedma) 20334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_handle_rx_port(&uart->port, isr, &ier); 20434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 2052421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(ier, uart->port.membase + TIMBUART_IER); 20634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 20734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_unlock(&uart->port.lock); 20834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(uart->port.dev, "%s leaving\n", __func__); 20934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 21034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 21134aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic unsigned int timbuart_get_mctrl(struct uart_port *port) 21234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 21334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 cts = ioread8(port->membase + TIMBUART_CTRL); 21434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - cts %x\n", __func__, cts); 21534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 21634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (cts & TIMBUART_CTRL_CTS) 21734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; 21834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors else 21934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return TIOCM_DSR | TIOCM_CAR; 22034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 22134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 22234aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl) 22334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 22434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - %x\n", __func__, mctrl); 22534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 22634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (mctrl & TIOCM_RTS) 22734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL); 22834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors else 22944051996230510ccb125cfa552d464950d1767b9Roel Kluin iowrite8(0, port->membase + TIMBUART_CTRL); 23034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 23134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 2322421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjforsstatic void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier) 23334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 23434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors unsigned int cts; 23534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 23634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & CTS_DELTA) { 23734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* ack */ 2382421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(CTS_DELTA, port->membase + TIMBUART_ISR); 23934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors cts = timbuart_get_mctrl(port); 24034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_handle_cts_change(port, cts & TIOCM_CTS); 241bdc04e3174e18f475289fa8f4144f66686326b7eAlan Cox wake_up_interruptible(&port->state->port.delta_msr_wait); 24234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 24334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 24434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= CTS_DELTA; 24534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 24634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 24734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_enable_ms(struct uart_port *port) 24834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 24934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* N/A */ 25034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 25134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 25234aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_break_ctl(struct uart_port *port, int ctl) 25334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 25434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* N/A */ 25534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 25634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 25734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_startup(struct uart_port *port) 25834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 25934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 26034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 26134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 26234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s\n", __func__); 26334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 26434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL); 2652421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(0x1ff, port->membase + TIMBUART_ISR); 26634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* Enable all but TX interrupts */ 2672421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(RXBAF | RXBF | RXTT | CTS_DELTA, 26834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase + TIMBUART_IER); 26934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 27034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED, 27134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors "timb-uart", uart); 27234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 27334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 27434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_shutdown(struct uart_port *port) 27534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 27634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 27734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 27834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s\n", __func__); 27934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors free_irq(port->irq, uart); 2802421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(0, port->membase + TIMBUART_IER); 28134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 28234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 28334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int get_bindex(int baud) 28434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 28534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int i; 28634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 28734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors for (i = 0; i < ARRAY_SIZE(baudrates); i++) 2887d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox if (baud <= baudrates[i]) 28934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return i; 29034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 29134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -1; 29234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 29334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 29434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_set_termios(struct uart_port *port, 29534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct ktermios *termios, 29634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct ktermios *old) 29734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 29834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors unsigned int baud; 29934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors short bindex; 30034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors unsigned long flags; 30134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 30234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); 30334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors bindex = get_bindex(baud); 30434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex); 30534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 3067d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox if (bindex < 0) 3077d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox bindex = 0; 3087d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox baud = baudrates[bindex]; 3097d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox 3107d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox /* The serial layer calls into this once with old = NULL when setting 3117d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox up initially */ 3127d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox if (old) 3137d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox tty_termios_copy_hw(termios, old); 3147d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox tty_termios_encode_baud_rate(termios, baud, baud); 3157d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox 3167d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox spin_lock_irqsave(&port->lock, flags); 3177d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE); 3187d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox uart_update_timeout(port, termios->c_cflag, baud); 3197d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox spin_unlock_irqrestore(&port->lock, flags); 32034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 32134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 32234aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic const char *timbuart_type(struct uart_port *port) 32334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 32434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return port->type == PORT_UNKNOWN ? "timbuart" : NULL; 32534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 32634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 32734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/* We do not request/release mappings of the registers here, 32834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * currently it's done in the proble function. 32934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 33034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_release_port(struct uart_port *port) 33134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 33234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct platform_device *pdev = to_platform_device(port->dev); 33334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int size = 33434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); 33534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 33634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->flags & UPF_IOREMAP) { 33734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iounmap(port->membase); 33834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase = NULL; 33934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 34034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 34134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors release_mem_region(port->mapbase, size); 34234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 34334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 34434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_request_port(struct uart_port *port) 34534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 34634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct platform_device *pdev = to_platform_device(port->dev); 34734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int size = 34834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); 34934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 35034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!request_mem_region(port->mapbase, size, "timb-uart")) 35134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -EBUSY; 35234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 35334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->flags & UPF_IOREMAP) { 35434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase = ioremap(port->mapbase, size); 35534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->membase == NULL) { 35634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors release_mem_region(port->mapbase, size); 35734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -ENOMEM; 35834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 35934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 36034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 36134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return 0; 36234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 36334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 36434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic irqreturn_t timbuart_handleinterrupt(int irq, void *devid) 36534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 36634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = (struct timbuart_port *)devid; 36734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 36834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (ioread8(uart->port.membase + TIMBUART_IPR)) { 3692421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors uart->last_ier = ioread32(uart->port.membase + TIMBUART_IER); 37034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 37134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* disable interrupts, the tasklet enables them again */ 3722421c48bd74debb537de94c1bd15cbabab272aa1Richard Röjfors iowrite32(0, uart->port.membase + TIMBUART_IER); 37334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 37434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* fire off bottom half */ 37534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_schedule(&uart->tasklet); 37634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 37734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return IRQ_HANDLED; 37834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } else 37934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return IRQ_NONE; 38034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 38134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 38234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/* 38334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Configure/autoconfigure the port. 38434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 38534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_config_port(struct uart_port *port, int flags) 38634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 38734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (flags & UART_CONFIG_TYPE) { 38834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->type = PORT_TIMBUART; 38934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_request_port(port); 39034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 39134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 39234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 39334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_verify_port(struct uart_port *port, 39434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct serial_struct *ser) 39534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 39634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* we don't want the core code to modify any port params */ 39734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -EINVAL; 39834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 39934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 40034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic struct uart_ops timbuart_ops = { 40134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .tx_empty = timbuart_tx_empty, 40234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .set_mctrl = timbuart_set_mctrl, 40334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .get_mctrl = timbuart_get_mctrl, 40434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .stop_tx = timbuart_stop_tx, 40534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .start_tx = timbuart_start_tx, 40634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .flush_buffer = timbuart_flush_buffer, 40734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .stop_rx = timbuart_stop_rx, 40834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .enable_ms = timbuart_enable_ms, 40934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .break_ctl = timbuart_break_ctl, 41034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .startup = timbuart_startup, 41134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .shutdown = timbuart_shutdown, 41234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .set_termios = timbuart_set_termios, 41334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .type = timbuart_type, 41434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .release_port = timbuart_release_port, 41534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .request_port = timbuart_request_port, 41634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .config_port = timbuart_config_port, 41734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .verify_port = timbuart_verify_port 41834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 41934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 42034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic struct uart_driver timbuart_driver = { 42134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .owner = THIS_MODULE, 42234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .driver_name = "timberdale_uart", 42334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .dev_name = "ttyTU", 42434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .major = TIMBUART_MAJOR, 42534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .minor = TIMBUART_MINOR, 42634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .nr = 1 42734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 42834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 429b1a6f24394d44b7bd2c8ec3f301a5eda72ce462fRichard Röjforsstatic int __devinit timbuart_probe(struct platform_device *dev) 43034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 4311e091751cdb2c28f9f25041be0dcb4d33e4a833dRoel Kluin int err, irq; 43234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart; 43334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct resource *iomem; 43434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 43534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(&dev->dev, "%s\n", __func__); 43634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 43734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart = kzalloc(sizeof(*uart), GFP_KERNEL); 43834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart) { 43934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = -EINVAL; 44034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_mem; 44134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 44234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 44334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->usedma = 0; 44434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 44534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.uartclk = 3250000 * 16; 44634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.fifosize = TIMBUART_FIFO_SIZE; 44734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.regshift = 2; 44834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.iotype = UPIO_MEM; 44934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.ops = &timbuart_ops; 45034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.irq = 0; 45134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; 45234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.line = 0; 45334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.dev = &dev->dev; 45434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 45534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); 45634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!iomem) { 45734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = -ENOMEM; 45834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_register; 45934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 46034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.mapbase = iomem->start; 46134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.membase = NULL; 46234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4631e091751cdb2c28f9f25041be0dcb4d33e4a833dRoel Kluin irq = platform_get_irq(dev, 0); 4641e091751cdb2c28f9f25041be0dcb4d33e4a833dRoel Kluin if (irq < 0) { 46534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = -EINVAL; 46634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_register; 46734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 4681e091751cdb2c28f9f25041be0dcb4d33e4a833dRoel Kluin uart->port.irq = irq; 46934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 47034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); 47134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 47234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = uart_register_driver(&timbuart_driver); 47334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (err) 47434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_register; 47534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 47634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = uart_add_one_port(&timbuart_driver, &uart->port); 47734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (err) 47834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_add_port; 47934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 48034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors platform_set_drvdata(dev, uart); 48134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 48234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return 0; 48334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 48434aec591847c696339189b070cce2a11f901cfeaRichard Röjforserr_add_port: 48534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_unregister_driver(&timbuart_driver); 48634aec591847c696339189b070cce2a11f901cfeaRichard Röjforserr_register: 48734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors kfree(uart); 48834aec591847c696339189b070cce2a11f901cfeaRichard Röjforserr_mem: 48934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n", 49034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err); 49134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 49234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return err; 49334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 49434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 495b1a6f24394d44b7bd2c8ec3f301a5eda72ce462fRichard Röjforsstatic int __devexit timbuart_remove(struct platform_device *dev) 49634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 49734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = platform_get_drvdata(dev); 49834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 49934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_kill(&uart->tasklet); 50034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_remove_one_port(&timbuart_driver, &uart->port); 50134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_unregister_driver(&timbuart_driver); 50234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors kfree(uart); 50334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 50434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return 0; 50534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 50634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 50734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic struct platform_driver timbuart_platform_driver = { 50834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .driver = { 50934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .name = "timb-uart", 51034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .owner = THIS_MODULE, 51134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors }, 51234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .probe = timbuart_probe, 513b1a6f24394d44b7bd2c8ec3f301a5eda72ce462fRichard Röjfors .remove = __devexit_p(timbuart_remove), 51434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 51534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 516c8381c15b14b7c2d212c182d3b9b3fa7217994daAxel Linmodule_platform_driver(timbuart_platform_driver); 51734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 51834aec591847c696339189b070cce2a11f901cfeaRichard RöjforsMODULE_DESCRIPTION("Timberdale UART driver"); 51934aec591847c696339189b070cce2a11f901cfeaRichard RöjforsMODULE_LICENSE("GPL v2"); 52034aec591847c696339189b070cce2a11f901cfeaRichard RöjforsMODULE_ALIAS("platform:timb-uart"); 52134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 522