15bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser/* 25bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * altera_jtaguart.c -- Altera JTAG UART driver 35bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * 45bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * Based on mcf.c -- Freescale ColdFire UART driver 55bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * 65bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com> 75bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw> 85bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch> 95bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * 105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * This program is free software; you can redistribute it and/or modify 115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * it under the terms of the GNU General Public License as published by 125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * the Free Software Foundation; either version 2 of the License, or 135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * (at your option) any later version. 145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser */ 155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/kernel.h> 175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/init.h> 185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/interrupt.h> 195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/module.h> 205bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/console.h> 216b3754d6183797263bc6b28884323cf7842a8961Grant Likely#include <linux/of.h> 225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/tty.h> 235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/tty_flip.h> 245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/serial.h> 255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/serial_core.h> 265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/platform_device.h> 275bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/io.h> 285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#include <linux/altera_jtaguart.h> 295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define DRV_NAME "altera_jtaguart" 315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser/* 335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * Altera JTAG UART register definitions according to the Altera JTAG UART 345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf 355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser */ 365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_SIZE 8 385bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 395bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_DATA_REG 0 405bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_DATA_DATA_MSK 0x000000FF 425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_DATA_RVALID_MSK 0x00008000 435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_DATA_RAVAIL_MSK 0xFFFF0000 445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_DATA_RAVAIL_OFF 16 455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_REG 4 475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_RE_MSK 0x00000001 495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_WE_MSK 0x00000002 505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_RI_MSK 0x00000100 515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_RI_OFF 8 525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200 535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400 545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000 555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16 565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser/* 585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * Local per-uart structure. 595bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser */ 605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstruct altera_jtaguart { 615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port port; 625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int sigs; /* Local copy of line sigs */ 635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long imr; /* Local IMR mirror */ 645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic unsigned int altera_jtaguart_tx_empty(struct uart_port *port) 675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) & 695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) ? TIOCSER_TEMT : 0; 705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic unsigned int altera_jtaguart_get_mctrl(struct uart_port *port) 735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; 755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs) 785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_start_tx(struct uart_port *port) 825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr |= ALTERA_JTAGUART_CONTROL_WE_MSK; 875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_stop_tx(struct uart_port *port) 915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK; 965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_stop_rx(struct uart_port *port) 1005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 1025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 1035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr &= ~ALTERA_JTAGUART_CONTROL_RE_MSK; 1055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 1065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_break_ctl(struct uart_port *port, int break_state) 1095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_set_termios(struct uart_port *port, 1135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct ktermios *termios, 1145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct ktermios *old) 1155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Just copy the old termios settings back */ 1175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (old) 1185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser tty_termios_copy_hw(termios, old); 1195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1205bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1215bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_rx_chars(struct altera_jtaguart *pp) 1225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = &pp->port; 1245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned char ch, flag; 1255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long status; 1265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1275bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) & 1285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_DATA_RVALID_MSK) { 1295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ch = status & ALTERA_JTAGUART_DATA_DATA_MSK; 1305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser flag = TTY_NORMAL; 1315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->icount.rx++; 1325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (uart_handle_sysrq_char(port, ch)) 1345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser continue; 1355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_insert_char(port, 0, 0, ch, flag); 1365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 13853dd0ba7a6f48ddc7ee044dcef838a0f8e7fec9bViresh Kumar spin_unlock(&port->lock); 1392e124b4a390ca85325fae75764bef92f0547fa25Jiri Slaby tty_flip_buffer_push(&port->state->port); 14053dd0ba7a6f48ddc7ee044dcef838a0f8e7fec9bViresh Kumar spin_lock(&port->lock); 1415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_tx_chars(struct altera_jtaguart *pp) 1445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = &pp->port; 1465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct circ_buf *xmit = &port->state->xmit; 1475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int pending, count; 1485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (port->x_char) { 1505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Send special char - probably flow control */ 1515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG); 1525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->x_char = 0; 1535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->icount.tx++; 1545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return; 1555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pending = uart_circ_chars_pending(xmit); 1585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (pending > 0) { 1595bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) & 1605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >> 1615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_OFF; 1625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (count > pending) 1635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser count = pending; 1645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (count > 0) { 1655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pending -= count; 1665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while (count--) { 1675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(xmit->buf[xmit->tail], 1685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->membase + ALTERA_JTAGUART_DATA_REG); 1695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 1705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->icount.tx++; 1715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (pending < WAKEUP_CHARS) 1735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_write_wakeup(port); 1745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (pending == 0) { 1785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK; 1795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 1805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic irqreturn_t altera_jtaguart_interrupt(int irq, void *data) 1845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = data; 1865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 1875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 1885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int isr; 1895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >> 1915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_RI_OFF) & pp->imr; 1925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock(&port->lock); 1945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK) 1965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser altera_jtaguart_rx_chars(pp); 1975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK) 1985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser altera_jtaguart_tx_chars(pp); 1995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock(&port->lock); 2015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return IRQ_RETVAL(isr); 2035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_config_port(struct uart_port *port, int flags) 2065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->type = PORT_ALTERA_JTAGUART; 2085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Clear mask, so no surprise interrupts. */ 2105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG); 2115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int altera_jtaguart_startup(struct uart_port *port) 2145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 2165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 2175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 2185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser int ret; 2195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2209cfb5c05fee914cc65d4706801f6bc424082b5f5Yong Zhang ret = request_irq(port->irq, altera_jtaguart_interrupt, 0, 2215bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser DRV_NAME, port); 2225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (ret) { 2235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d " 2245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser "interrupt vector=%d\n", port->line, port->irq); 2255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return ret; 2265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 2275bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 2295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Enable RX interrupts now */ 2315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr = ALTERA_JTAGUART_CONTROL_RE_MSK; 2325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 2335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 2355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 2375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2385bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2395bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_shutdown(struct uart_port *port) 2405bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 2425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 2435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 2445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 2465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Disable all interrupts now */ 2485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr = 0; 2495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 2505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 2525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser free_irq(port->irq, port); 2545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic const char *altera_jtaguart_type(struct uart_port *port) 2575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL; 2595bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int altera_jtaguart_request_port(struct uart_port *port) 2625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* UARTs always present */ 2645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 2655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_release_port(struct uart_port *port) 2685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Nothing to release... */ 2705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int altera_jtaguart_verify_port(struct uart_port *port, 2735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct serial_struct *ser) 2745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART) 2765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return -EINVAL; 2775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 2785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser/* 2815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * Define the basic serial functions we support. 2825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser */ 2835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct uart_ops altera_jtaguart_ops = { 2845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .tx_empty = altera_jtaguart_tx_empty, 2855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .get_mctrl = altera_jtaguart_get_mctrl, 2865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .set_mctrl = altera_jtaguart_set_mctrl, 2875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .start_tx = altera_jtaguart_start_tx, 2885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .stop_tx = altera_jtaguart_stop_tx, 2895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .stop_rx = altera_jtaguart_stop_rx, 2905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .break_ctl = altera_jtaguart_break_ctl, 2915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .startup = altera_jtaguart_startup, 2925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .shutdown = altera_jtaguart_shutdown, 2935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .set_termios = altera_jtaguart_set_termios, 2945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .type = altera_jtaguart_type, 2955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .request_port = altera_jtaguart_request_port, 2965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .release_port = altera_jtaguart_release_port, 2975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .config_port = altera_jtaguart_config_port, 2985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .verify_port = altera_jtaguart_verify_port, 2995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 3005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_MAXPORTS 1 3025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS]; 3035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) 3055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) 3072fbe6c5e3e7f8d698d97984a9dce4f05c3d940edTobias Klauserstatic void altera_jtaguart_console_putc(struct uart_port *port, int c) 3085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long status; 3105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 3115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) & 3145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { 3155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) { 3165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return; /* no connection activity */ 3185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3205bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser cpu_relax(); 3215bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(c, port->membase + ALTERA_JTAGUART_DATA_REG); 3245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#else 3272fbe6c5e3e7f8d698d97984a9dce4f05c3d940edTobias Klauserstatic void altera_jtaguart_console_putc(struct uart_port *port, int c) 3285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 3305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) & 3335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { 3345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser cpu_relax(); 3365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3385bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(c, port->membase + ALTERA_JTAGUART_DATA_REG); 3395bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3405bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#endif 3425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_console_write(struct console *co, const char *s, 3445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int count) 3455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3463d1c90d48cbe335a47a6a5a05ff731a86eacf6fbTobias Klauser struct uart_port *port = &(altera_jtaguart_ports + co->index)->port; 3473d1c90d48cbe335a47a6a5a05ff731a86eacf6fbTobias Klauser 3483d1c90d48cbe335a47a6a5a05ff731a86eacf6fbTobias Klauser uart_console_write(port, s, count, altera_jtaguart_console_putc); 3495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int __init altera_jtaguart_console_setup(struct console *co, 3525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser char *options) 3535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port; 3555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS) 3575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return -EINVAL; 3585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port = &altera_jtaguart_ports[co->index].port; 3592314a0f667352748a48753bf903f8c50fd2a756dTobias Klauser if (port->membase == NULL) 3605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return -ENODEV; 3615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 3625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct uart_driver altera_jtaguart_driver; 3655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct console altera_jtaguart_console = { 3675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .name = "ttyJ", 3685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .write = altera_jtaguart_console_write, 3695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .device = uart_console_device, 3705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .setup = altera_jtaguart_console_setup, 3715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .flags = CON_PRINTBUFFER, 3725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .index = -1, 3735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .data = &altera_jtaguart_driver, 3745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 3755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int __init altera_jtaguart_console_init(void) 3775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser register_console(&altera_jtaguart_console); 3795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 3805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserconsole_initcall(altera_jtaguart_console_init); 3835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console) 3855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#else 3875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONSOLE NULL 3895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */ 3915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct uart_driver altera_jtaguart_driver = { 3935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .owner = THIS_MODULE, 3945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .driver_name = "altera_jtaguart", 3955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .dev_name = "ttyJ", 3965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .major = ALTERA_JTAGUART_MAJOR, 3975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .minor = ALTERA_JTAGUART_MINOR, 3985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .nr = ALTERA_JTAGUART_MAXPORTS, 3995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .cons = ALTERA_JTAGUART_CONSOLE, 4005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 4015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4029671f09921d93e722a28ae9610d478e092ac5466Bill Pembertonstatic int altera_jtaguart_probe(struct platform_device *pdev) 4035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 404574de559c1797618fd8ed03576837eb3113c5d26Jingoo Han struct altera_jtaguart_platform_uart *platp = 405574de559c1797618fd8ed03576837eb3113c5d26Jingoo Han dev_get_platdata(&pdev->dev); 4065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port; 40772af4762ee640b717a30761e27fc55126c686568Tobias Klauser struct resource *res_irq, *res_mem; 40872af4762ee640b717a30761e27fc55126c686568Tobias Klauser int i = pdev->id; 4095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 41072af4762ee640b717a30761e27fc55126c686568Tobias Klauser /* -1 emphasizes that the platform must have one port, no .N suffix */ 41172af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (i == -1) 41272af4762ee640b717a30761e27fc55126c686568Tobias Klauser i = 0; 4135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 41472af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (i >= ALTERA_JTAGUART_MAXPORTS) 41572af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -EINVAL; 4165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 41772af4762ee640b717a30761e27fc55126c686568Tobias Klauser port = &altera_jtaguart_ports[i].port; 41872af4762ee640b717a30761e27fc55126c686568Tobias Klauser 41972af4762ee640b717a30761e27fc55126c686568Tobias Klauser res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 42072af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (res_mem) 42172af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->mapbase = res_mem->start; 42272af4762ee640b717a30761e27fc55126c686568Tobias Klauser else if (platp) 42372af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->mapbase = platp->mapbase; 42472af4762ee640b717a30761e27fc55126c686568Tobias Klauser else 42572af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -ENODEV; 42672af4762ee640b717a30761e27fc55126c686568Tobias Klauser 42772af4762ee640b717a30761e27fc55126c686568Tobias Klauser res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 42872af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (res_irq) 42972af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->irq = res_irq->start; 43072af4762ee640b717a30761e27fc55126c686568Tobias Klauser else if (platp) 43172af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->irq = platp->irq; 43272af4762ee640b717a30761e27fc55126c686568Tobias Klauser else 43372af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -ENODEV; 43472af4762ee640b717a30761e27fc55126c686568Tobias Klauser 43572af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE); 43672af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (!port->membase) 43772af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -ENOMEM; 43872af4762ee640b717a30761e27fc55126c686568Tobias Klauser 43972af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->line = i; 44072af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->type = PORT_ALTERA_JTAGUART; 44172af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->iotype = SERIAL_IO_MEM; 44272af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->ops = &altera_jtaguart_ops; 44344ed76b78e158d852f640d533b7acc08b91f2132Tobias Klauser port->flags = UPF_BOOT_AUTOCONF; 44472af4762ee640b717a30761e27fc55126c686568Tobias Klauser 44572af4762ee640b717a30761e27fc55126c686568Tobias Klauser uart_add_one_port(&altera_jtaguart_driver, port); 4465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 4485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 4495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 450ae8d8a146725a966bd7c59c94f4d0016dcf7a04fBill Pembertonstatic int altera_jtaguart_remove(struct platform_device *pdev) 4515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 4525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port; 45372af4762ee640b717a30761e27fc55126c686568Tobias Klauser int i = pdev->id; 4545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 45572af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (i == -1) 45672af4762ee640b717a30761e27fc55126c686568Tobias Klauser i = 0; 45772af4762ee640b717a30761e27fc55126c686568Tobias Klauser 45872af4762ee640b717a30761e27fc55126c686568Tobias Klauser port = &altera_jtaguart_ports[i].port; 45972af4762ee640b717a30761e27fc55126c686568Tobias Klauser uart_remove_one_port(&altera_jtaguart_driver, port); 4605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 4625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 4635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4649f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser#ifdef CONFIG_OF 4654d199a55c41b25f4255eaeea358f944e33e91a4bTobias Klauserstatic const struct of_device_id altera_jtaguart_match[] = { 4669f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser { .compatible = "ALTR,juart-1.0", }, 46713960b47dc1df695f8537c32a0e0ce5ae5d4eee4Dinh Nguyen { .compatible = "altr,juart-1.0", }, 4689f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser {}, 4699f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser}; 4709f15444fefdb33509132ff5c9be60cb315c44cb2Tobias KlauserMODULE_DEVICE_TABLE(of, altera_jtaguart_match); 4719f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser#endif /* CONFIG_OF */ 4729f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser 4735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct platform_driver altera_jtaguart_platform_driver = { 4745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .probe = altera_jtaguart_probe, 4752d47b7160243b1422006b91debf438484a4fde58Bill Pemberton .remove = altera_jtaguart_remove, 4765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .driver = { 4779f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser .name = DRV_NAME, 4789f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser .owner = THIS_MODULE, 47985888069cf5d0f21312e3ee730458a5e3a553509Ben Dooks .of_match_table = of_match_ptr(altera_jtaguart_match), 4805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser }, 4815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 4825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int __init altera_jtaguart_init(void) 4845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 4855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser int rc; 4865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser rc = uart_register_driver(&altera_jtaguart_driver); 4885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (rc) 4895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return rc; 4905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser rc = platform_driver_register(&altera_jtaguart_platform_driver); 491b16ea4b04c3b74524805a409ee2747b751b7a138Tobias Klauser if (rc) 4925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_unregister_driver(&altera_jtaguart_driver); 493b16ea4b04c3b74524805a409ee2747b751b7a138Tobias Klauser return rc; 4945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 4955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void __exit altera_jtaguart_exit(void) 4975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 4985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser platform_driver_unregister(&altera_jtaguart_platform_driver); 4995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_unregister_driver(&altera_jtaguart_driver); 5005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 5015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 5025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klausermodule_init(altera_jtaguart_init); 5035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klausermodule_exit(altera_jtaguart_exit); 5045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 5055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_DESCRIPTION("Altera JTAG UART driver"); 5065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); 5075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_LICENSE("GPL"); 5085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_ALIAS("platform:" DRV_NAME); 509