timbuart.c revision 7d55deaf50182c47c1e805dc8cc85f2769f0673e
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> 2634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/kernel.h> 2734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/platform_device.h> 2834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include <linux/ioport.h> 2934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 3034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors#include "timbuart.h" 3134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 3234aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstruct timbuart_port { 3334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct uart_port port; 3434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct tasklet_struct tasklet; 3534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int usedma; 3634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 last_ier; 3734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct platform_device *dev; 3834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 3934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800, 4134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 921600, 1843200, 3250000}; 4234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_mctrl_check(struct uart_port *port, u8 isr, u8 *ier); 4434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic irqreturn_t timbuart_handleinterrupt(int irq, void *devid); 4634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 4734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_stop_rx(struct uart_port *port) 4834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 4934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* spin lock held by upper layer, disable all RX interrupts */ 5034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ier = ioread8(port->membase + TIMBUART_IER) & ~RXFLAGS; 5134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(ier, port->membase + TIMBUART_IER); 5234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 5334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 5434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_stop_tx(struct uart_port *port) 5534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 5634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* spinlock held by upper layer, disable TX interrupt */ 5734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ier = ioread8(port->membase + TIMBUART_IER) & ~TXBAE; 5834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(ier, port->membase + TIMBUART_IER); 5934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 6034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 6134aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_start_tx(struct uart_port *port) 6234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 6334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 6434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 6534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 6634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* do not transfer anything here -> fire off the tasklet */ 6734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_schedule(&uart->tasklet); 6834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 6934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 7034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_flush_buffer(struct uart_port *port) 7134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 7234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | TIMBUART_CTRL_FLSHTX; 7334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 7434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(ctl, port->membase + TIMBUART_CTRL); 7534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TXBF, port->membase + TIMBUART_ISR); 7634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 7734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 7834aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_rx_chars(struct uart_port *port) 7934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 8034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct tty_struct *tty = port->info->port.tty; 8134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 8234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors while (ioread8(port->membase + TIMBUART_ISR) & RXDP) { 8334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ch = ioread8(port->membase + TIMBUART_RXFIFO); 8434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.rx++; 8534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tty_insert_flip_char(tty, ch, TTY_NORMAL); 8634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 8734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 8834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_unlock(&port->lock); 8934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tty_flip_buffer_push(port->info->port.tty); 9034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_lock(&port->lock); 9134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 9234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - total read %d bytes\n", 9334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors __func__, port->icount.rx); 9434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 9534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 9634aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_tx_chars(struct uart_port *port) 9734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 9834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct circ_buf *xmit = &port->info->xmit; 9934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 10034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors while (!(ioread8(port->membase + TIMBUART_ISR) & TXBF) && 10134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors !uart_circ_empty(xmit)) { 10234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(xmit->buf[xmit->tail], 10334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase + TIMBUART_TXFIFO); 10434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 10534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.tx++; 10634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 10734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 10834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, 10934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n", 11034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors __func__, 11134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.tx, 11234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors ioread8(port->membase + TIMBUART_CTRL), 11334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->mctrl & TIOCM_RTS, 11434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors ioread8(port->membase + TIMBUART_BAUDRATE)); 11534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 11634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 11734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_handle_tx_port(struct uart_port *port, u8 isr, u8 *ier) 11834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 11934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 12034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 12134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct circ_buf *xmit = &port->info->xmit; 12234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 12334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (uart_circ_empty(xmit) || uart_tx_stopped(port)) 12434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return; 12534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 12634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->x_char) 12734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return; 12834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 12934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & TXFLAGS) { 13034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_tx_chars(port); 13134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* clear all TX interrupts */ 13234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TXFLAGS, port->membase + TIMBUART_ISR); 13334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 13434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 13534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_write_wakeup(port); 13634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } else 13734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* Re-enable any tx interrupt */ 13834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= uart->last_ier & TXFLAGS; 13934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 14034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* enable interrupts if there are chars in the transmit buffer, 14134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Or if we delivered some bytes and want the almost empty interrupt 14234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * we wake up the upper layer later when we got the interrupt 14334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * to give it some time to go out... 14434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 14534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart_circ_empty(xmit)) 14634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= TXBAE; 14734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 14834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - leaving\n", __func__); 14934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 15034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 15134aec591847c696339189b070cce2a11f901cfeaRichard Röjforsvoid timbuart_handle_rx_port(struct uart_port *port, u8 isr, u8 *ier) 15234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 15334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & RXFLAGS) { 15434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* Some RX status is set */ 15534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & RXBF) { 15634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | 15734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors TIMBUART_CTRL_FLSHRX; 15834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(ctl, port->membase + TIMBUART_CTRL); 15934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->icount.overrun++; 16034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } else if (isr & (RXDP)) 16134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_rx_chars(port); 16234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 16334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* ack all RX interrupts */ 16434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(RXFLAGS, port->membase + TIMBUART_ISR); 16534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 16634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 16734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* always have the RX interrupts enabled */ 16834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= RXBAF | RXBF | RXTT; 16934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 17034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - leaving\n", __func__); 17134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 17234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 17334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsvoid timbuart_tasklet(unsigned long arg) 17434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 17534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = (struct timbuart_port *)arg; 17634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 isr, ier = 0; 17734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 17834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_lock(&uart->port.lock); 17934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors isr = ioread8(uart->port.membase + TIMBUART_ISR); 18134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr); 18234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart->usedma) 18434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_handle_tx_port(&uart->port, isr, &ier); 18534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_mctrl_check(&uart->port, isr, &ier); 18734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 18834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart->usedma) 18934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_handle_rx_port(&uart->port, isr, &ier); 19034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 19134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(ier, uart->port.membase + TIMBUART_IER); 19234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 19334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors spin_unlock(&uart->port.lock); 19434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(uart->port.dev, "%s leaving\n", __func__); 19534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 19634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 19734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic unsigned int timbuart_tx_empty(struct uart_port *port) 19834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 19934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 isr = ioread8(port->membase + TIMBUART_ISR); 20034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 20134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return (isr & TXBAE) ? TIOCSER_TEMT : 0; 20234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 20334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 20434aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic unsigned int timbuart_get_mctrl(struct uart_port *port) 20534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 20634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors u8 cts = ioread8(port->membase + TIMBUART_CTRL); 20734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - cts %x\n", __func__, cts); 20834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 20934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (cts & TIMBUART_CTRL_CTS) 21034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; 21134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors else 21234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return TIOCM_DSR | TIOCM_CAR; 21334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 21434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 21534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl) 21634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 21734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - %x\n", __func__, mctrl); 21834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 21934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (mctrl & TIOCM_RTS) 22034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL); 22134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors else 22234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL); 22334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 22434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 22534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_mctrl_check(struct uart_port *port, u8 isr, u8 *ier) 22634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 22734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors unsigned int cts; 22834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 22934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (isr & CTS_DELTA) { 23034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* ack */ 23134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(CTS_DELTA, port->membase + TIMBUART_ISR); 23234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors cts = timbuart_get_mctrl(port); 23334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_handle_cts_change(port, cts & TIOCM_CTS); 23434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors wake_up_interruptible(&port->info->delta_msr_wait); 23534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 23634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 23734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors *ier |= CTS_DELTA; 23834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 23934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 24034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_enable_ms(struct uart_port *port) 24134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 24234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* N/A */ 24334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 24434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 24534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_break_ctl(struct uart_port *port, int ctl) 24634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 24734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* N/A */ 24834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 24934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 25034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_startup(struct uart_port *port) 25134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 25234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 25334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 25434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 25534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s\n", __func__); 25634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 25734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL); 25834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(0xff, port->membase + TIMBUART_ISR); 25934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* Enable all but TX interrupts */ 26034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(RXBAF | RXBF | RXTT | CTS_DELTA, 26134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase + TIMBUART_IER); 26234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 26334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED, 26434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors "timb-uart", uart); 26534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 26634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 26734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_shutdown(struct uart_port *port) 26834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 26934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = 27034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors container_of(port, struct timbuart_port, port); 27134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s\n", __func__); 27234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors free_irq(port->irq, uart); 27334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(0, port->membase + TIMBUART_IER); 27434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 27534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 27634aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int get_bindex(int baud) 27734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 27834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int i; 27934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 28034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors for (i = 0; i < ARRAY_SIZE(baudrates); i++) 2817d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox if (baud <= baudrates[i]) 28234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return i; 28334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 28434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -1; 28534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 28634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 28734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_set_termios(struct uart_port *port, 28834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct ktermios *termios, 28934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct ktermios *old) 29034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 29134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors unsigned int baud; 29234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors short bindex; 29334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors unsigned long flags; 29434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 29534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); 29634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors bindex = get_bindex(baud); 29734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex); 29834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 2997d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox if (bindex < 0) 3007d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox bindex = 0; 3017d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox baud = baudrates[bindex]; 3027d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox 3037d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox /* The serial layer calls into this once with old = NULL when setting 3047d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox up initially */ 3057d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox if (old) 3067d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox tty_termios_copy_hw(termios, old); 3077d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox tty_termios_encode_baud_rate(termios, baud, baud); 3087d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox 3097d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox spin_lock_irqsave(&port->lock, flags); 3107d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE); 3117d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox uart_update_timeout(port, termios->c_cflag, baud); 3127d55deaf50182c47c1e805dc8cc85f2769f0673eAlan Cox spin_unlock_irqrestore(&port->lock, flags); 31334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 31434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 31534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic const char *timbuart_type(struct uart_port *port) 31634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 31734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return port->type == PORT_UNKNOWN ? "timbuart" : NULL; 31834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 31934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 32034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/* We do not request/release mappings of the registers here, 32134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * currently it's done in the proble function. 32234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 32334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_release_port(struct uart_port *port) 32434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 32534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct platform_device *pdev = to_platform_device(port->dev); 32634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int size = 32734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); 32834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 32934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->flags & UPF_IOREMAP) { 33034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iounmap(port->membase); 33134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase = NULL; 33234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 33334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 33434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors release_mem_region(port->mapbase, size); 33534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 33634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 33734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_request_port(struct uart_port *port) 33834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 33934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct platform_device *pdev = to_platform_device(port->dev); 34034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int size = 34134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); 34234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 34334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!request_mem_region(port->mapbase, size, "timb-uart")) 34434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -EBUSY; 34534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 34634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->flags & UPF_IOREMAP) { 34734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->membase = ioremap(port->mapbase, size); 34834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (port->membase == NULL) { 34934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors release_mem_region(port->mapbase, size); 35034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -ENOMEM; 35134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 35234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 35334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 35434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return 0; 35534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 35634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 35734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic irqreturn_t timbuart_handleinterrupt(int irq, void *devid) 35834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 35934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = (struct timbuart_port *)devid; 36034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 36134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (ioread8(uart->port.membase + TIMBUART_IPR)) { 36234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->last_ier = ioread8(uart->port.membase + TIMBUART_IER); 36334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 36434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* disable interrupts, the tasklet enables them again */ 36534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iowrite8(0, uart->port.membase + TIMBUART_IER); 36634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 36734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* fire off bottom half */ 36834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_schedule(&uart->tasklet); 36934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 37034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return IRQ_HANDLED; 37134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } else 37234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return IRQ_NONE; 37334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 37434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 37534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/* 37634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors * Configure/autoconfigure the port. 37734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors */ 37834aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void timbuart_config_port(struct uart_port *port, int flags) 37934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 38034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (flags & UART_CONFIG_TYPE) { 38134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors port->type = PORT_TIMBUART; 38234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors timbuart_request_port(port); 38334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 38434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 38534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 38634aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_verify_port(struct uart_port *port, 38734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct serial_struct *ser) 38834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 38934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors /* we don't want the core code to modify any port params */ 39034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return -EINVAL; 39134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 39234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 39334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic struct uart_ops timbuart_ops = { 39434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .tx_empty = timbuart_tx_empty, 39534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .set_mctrl = timbuart_set_mctrl, 39634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .get_mctrl = timbuart_get_mctrl, 39734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .stop_tx = timbuart_stop_tx, 39834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .start_tx = timbuart_start_tx, 39934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .flush_buffer = timbuart_flush_buffer, 40034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .stop_rx = timbuart_stop_rx, 40134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .enable_ms = timbuart_enable_ms, 40234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .break_ctl = timbuart_break_ctl, 40334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .startup = timbuart_startup, 40434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .shutdown = timbuart_shutdown, 40534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .set_termios = timbuart_set_termios, 40634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .type = timbuart_type, 40734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .release_port = timbuart_release_port, 40834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .request_port = timbuart_request_port, 40934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .config_port = timbuart_config_port, 41034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .verify_port = timbuart_verify_port 41134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 41234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 41334aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic struct uart_driver timbuart_driver = { 41434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .owner = THIS_MODULE, 41534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .driver_name = "timberdale_uart", 41634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .dev_name = "ttyTU", 41734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .major = TIMBUART_MAJOR, 41834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .minor = TIMBUART_MINOR, 41934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .nr = 1 42034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 42134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 42234aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_probe(struct platform_device *dev) 42334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 42434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors int err; 42534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart; 42634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct resource *iomem; 42734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 42834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors dev_dbg(&dev->dev, "%s\n", __func__); 42934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 43034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart = kzalloc(sizeof(*uart), GFP_KERNEL); 43134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!uart) { 43234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = -EINVAL; 43334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_mem; 43434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 43534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 43634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->usedma = 0; 43734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 43834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.uartclk = 3250000 * 16; 43934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.fifosize = TIMBUART_FIFO_SIZE; 44034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.regshift = 2; 44134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.iotype = UPIO_MEM; 44234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.ops = &timbuart_ops; 44334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.irq = 0; 44434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; 44534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.line = 0; 44634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.dev = &dev->dev; 44734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 44834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); 44934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (!iomem) { 45034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = -ENOMEM; 45134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_register; 45234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 45334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.mapbase = iomem->start; 45434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.membase = NULL; 45534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 45634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart->port.irq = platform_get_irq(dev, 0); 45734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (uart->port.irq < 0) { 45834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = -EINVAL; 45934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_register; 46034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors } 46134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 46234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); 46334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 46434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = uart_register_driver(&timbuart_driver); 46534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (err) 46634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_register; 46734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 46834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err = uart_add_one_port(&timbuart_driver, &uart->port); 46934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors if (err) 47034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors goto err_add_port; 47134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 47234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors platform_set_drvdata(dev, uart); 47334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 47434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return 0; 47534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 47634aec591847c696339189b070cce2a11f901cfeaRichard Röjforserr_add_port: 47734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_unregister_driver(&timbuart_driver); 47834aec591847c696339189b070cce2a11f901cfeaRichard Röjforserr_register: 47934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors kfree(uart); 48034aec591847c696339189b070cce2a11f901cfeaRichard Röjforserr_mem: 48134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n", 48234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors err); 48334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 48434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return err; 48534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 48634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 48734aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int timbuart_remove(struct platform_device *dev) 48834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 48934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors struct timbuart_port *uart = platform_get_drvdata(dev); 49034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 49134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors tasklet_kill(&uart->tasklet); 49234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_remove_one_port(&timbuart_driver, &uart->port); 49334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors uart_unregister_driver(&timbuart_driver); 49434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors kfree(uart); 49534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 49634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return 0; 49734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 49834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 49934aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic struct platform_driver timbuart_platform_driver = { 50034aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .driver = { 50134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .name = "timb-uart", 50234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .owner = THIS_MODULE, 50334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors }, 50434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .probe = timbuart_probe, 50534aec591847c696339189b070cce2a11f901cfeaRichard Röjfors .remove = timbuart_remove, 50634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors}; 50734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 50834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors/*--------------------------------------------------------------------------*/ 50934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 51034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic int __init timbuart_init(void) 51134aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 51234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors return platform_driver_register(&timbuart_platform_driver); 51334aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 51434aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 51534aec591847c696339189b070cce2a11f901cfeaRichard Röjforsstatic void __exit timbuart_exit(void) 51634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors{ 51734aec591847c696339189b070cce2a11f901cfeaRichard Röjfors platform_driver_unregister(&timbuart_platform_driver); 51834aec591847c696339189b070cce2a11f901cfeaRichard Röjfors} 51934aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 52034aec591847c696339189b070cce2a11f901cfeaRichard Röjforsmodule_init(timbuart_init); 52134aec591847c696339189b070cce2a11f901cfeaRichard Röjforsmodule_exit(timbuart_exit); 52234aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 52334aec591847c696339189b070cce2a11f901cfeaRichard RöjforsMODULE_DESCRIPTION("Timberdale UART driver"); 52434aec591847c696339189b070cce2a11f901cfeaRichard RöjforsMODULE_LICENSE("GPL v2"); 52534aec591847c696339189b070cce2a11f901cfeaRichard RöjforsMODULE_ALIAS("platform:timb-uart"); 52634aec591847c696339189b070cce2a11f901cfeaRichard Röjfors 527