altera_jtaguart.c revision ae8d8a146725a966bd7c59c94f4d0016dcf7a04f
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_enable_ms(struct uart_port *port) 1135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_set_termios(struct uart_port *port, 1175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct ktermios *termios, 1185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct ktermios *old) 1195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1205bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Just copy the old termios settings back */ 1215bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (old) 1225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser tty_termios_copy_hw(termios, old); 1235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_rx_chars(struct altera_jtaguart *pp) 1265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1275bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = &pp->port; 1285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned char ch, flag; 1295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long status; 1305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) & 1325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_DATA_RVALID_MSK) { 1335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ch = status & ALTERA_JTAGUART_DATA_DATA_MSK; 1345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser flag = TTY_NORMAL; 1355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->icount.rx++; 1365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (uart_handle_sysrq_char(port, ch)) 1385bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser continue; 1395bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_insert_char(port, 0, 0, ch, flag); 1405bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser tty_flip_buffer_push(port->state->port.tty); 1435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_tx_chars(struct altera_jtaguart *pp) 1465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = &pp->port; 1485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct circ_buf *xmit = &port->state->xmit; 1495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int pending, count; 1505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (port->x_char) { 1525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Send special char - probably flow control */ 1535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG); 1545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->x_char = 0; 1555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->icount.tx++; 1565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return; 1575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1595bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pending = uart_circ_chars_pending(xmit); 1605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (pending > 0) { 1615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) & 1625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >> 1635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_OFF; 1645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (count > pending) 1655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser count = pending; 1665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (count > 0) { 1675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pending -= count; 1685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while (count--) { 1695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(xmit->buf[xmit->tail], 1705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->membase + ALTERA_JTAGUART_DATA_REG); 1715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 1725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->icount.tx++; 1735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (pending < WAKEUP_CHARS) 1755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_write_wakeup(port); 1765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (pending == 0) { 1805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK; 1815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 1825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 1835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 1845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic irqreturn_t altera_jtaguart_interrupt(int irq, void *data) 1865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 1875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = data; 1885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 1895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 1905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int isr; 1915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >> 1935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_RI_OFF) & pp->imr; 1945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock(&port->lock); 1965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 1975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK) 1985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser altera_jtaguart_rx_chars(pp); 1995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK) 2005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser altera_jtaguart_tx_chars(pp); 2015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock(&port->lock); 2035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return IRQ_RETVAL(isr); 2055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_config_port(struct uart_port *port, int flags) 2085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port->type = PORT_ALTERA_JTAGUART; 2105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Clear mask, so no surprise interrupts. */ 2125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG); 2135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int altera_jtaguart_startup(struct uart_port *port) 2165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 2185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 2195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 2205bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser int ret; 2215bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2229cfb5c05fee914cc65d4706801f6bc424082b5f5Yong Zhang ret = request_irq(port->irq, altera_jtaguart_interrupt, 0, 2235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser DRV_NAME, port); 2245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (ret) { 2255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d " 2265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser "interrupt vector=%d\n", port->line, port->irq); 2275bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return ret; 2285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 2295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 2315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Enable RX interrupts now */ 2335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr = ALTERA_JTAGUART_CONTROL_RE_MSK; 2345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 2355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 2375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2385bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 2395bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2405bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_shutdown(struct uart_port *port) 2425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart *pp = 2445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser container_of(port, struct altera_jtaguart, port); 2455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 2465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 2485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Disable all interrupts now */ 2505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser pp->imr = 0; 2515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG); 2525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 2545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser free_irq(port->irq, port); 2565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic const char *altera_jtaguart_type(struct uart_port *port) 2595bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL; 2615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int altera_jtaguart_request_port(struct uart_port *port) 2645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* UARTs always present */ 2665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 2675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_release_port(struct uart_port *port) 2705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser /* Nothing to release... */ 2725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int altera_jtaguart_verify_port(struct uart_port *port, 2755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct serial_struct *ser) 2765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 2775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART) 2785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return -EINVAL; 2795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 2805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 2815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 2825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser/* 2835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser * Define the basic serial functions we support. 2845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser */ 2855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct uart_ops altera_jtaguart_ops = { 2865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .tx_empty = altera_jtaguart_tx_empty, 2875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .get_mctrl = altera_jtaguart_get_mctrl, 2885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .set_mctrl = altera_jtaguart_set_mctrl, 2895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .start_tx = altera_jtaguart_start_tx, 2905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .stop_tx = altera_jtaguart_stop_tx, 2915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .stop_rx = altera_jtaguart_stop_rx, 2925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .enable_ms = altera_jtaguart_enable_ms, 2935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .break_ctl = altera_jtaguart_break_ctl, 2945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .startup = altera_jtaguart_startup, 2955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .shutdown = altera_jtaguart_shutdown, 2965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .set_termios = altera_jtaguart_set_termios, 2975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .type = altera_jtaguart_type, 2985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .request_port = altera_jtaguart_request_port, 2995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .release_port = altera_jtaguart_release_port, 3005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .config_port = altera_jtaguart_config_port, 3015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .verify_port = altera_jtaguart_verify_port, 3025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 3035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_MAXPORTS 1 3055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS]; 3065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) 3085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) 3105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_console_putc(struct console *co, const char c) 3115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = &(altera_jtaguart_ports + co->index)->port; 3135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long status; 3145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 3155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3165bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3175bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) & 3185bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { 3195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) { 3205bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3215bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return; /* no connection activity */ 3225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3235bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3245bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser cpu_relax(); 3255bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3265bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3275bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(c, port->membase + ALTERA_JTAGUART_DATA_REG); 3285bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3295bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3305bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#else 3315bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_console_putc(struct console *co, const char c) 3325bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3335bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port = &(altera_jtaguart_ports + co->index)->port; 3345bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned long flags; 3355bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3365bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3375bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) & 3385bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { 3395bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3405bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser cpu_relax(); 3415bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_lock_irqsave(&port->lock, flags); 3425bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3435bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser writel(c, port->membase + ALTERA_JTAGUART_DATA_REG); 3445bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser spin_unlock_irqrestore(&port->lock, flags); 3455bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3465bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#endif 3475bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3485bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void altera_jtaguart_console_write(struct console *co, const char *s, 3495bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser unsigned int count) 3505bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3515bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser for (; count; count--, s++) { 3525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser altera_jtaguart_console_putc(co, *s); 3535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (*s == '\n') 3545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser altera_jtaguart_console_putc(co, '\r'); 3555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 3565bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int __init altera_jtaguart_console_setup(struct console *co, 3595bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser char *options) 3605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3615bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port; 3625bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3635bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS) 3645bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return -EINVAL; 3655bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser port = &altera_jtaguart_ports[co->index].port; 3662314a0f667352748a48753bf903f8c50fd2a756dTobias Klauser if (port->membase == NULL) 3675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return -ENODEV; 3685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 3695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3705bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3715bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct uart_driver altera_jtaguart_driver; 3725bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3735bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct console altera_jtaguart_console = { 3745bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .name = "ttyJ", 3755bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .write = altera_jtaguart_console_write, 3765bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .device = uart_console_device, 3775bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .setup = altera_jtaguart_console_setup, 3785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .flags = CON_PRINTBUFFER, 3795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .index = -1, 3805bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .data = &altera_jtaguart_driver, 3815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 3825bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3835bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int __init altera_jtaguart_console_init(void) 3845bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 3855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser register_console(&altera_jtaguart_console); 3865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 3875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 3885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserconsole_initcall(altera_jtaguart_console_init); 3905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console) 3925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#else 3945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#define ALTERA_JTAGUART_CONSOLE NULL 3965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser#endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */ 3985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 3995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct uart_driver altera_jtaguart_driver = { 4005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .owner = THIS_MODULE, 4015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .driver_name = "altera_jtaguart", 4025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .dev_name = "ttyJ", 4035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .major = ALTERA_JTAGUART_MAJOR, 4045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .minor = ALTERA_JTAGUART_MINOR, 4055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .nr = ALTERA_JTAGUART_MAXPORTS, 4065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .cons = ALTERA_JTAGUART_CONSOLE, 4075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 4085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4099671f09921d93e722a28ae9610d478e092ac5466Bill Pembertonstatic int altera_jtaguart_probe(struct platform_device *pdev) 4105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 4115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data; 4125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port; 41372af4762ee640b717a30761e27fc55126c686568Tobias Klauser struct resource *res_irq, *res_mem; 41472af4762ee640b717a30761e27fc55126c686568Tobias Klauser int i = pdev->id; 4155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 41672af4762ee640b717a30761e27fc55126c686568Tobias Klauser /* -1 emphasizes that the platform must have one port, no .N suffix */ 41772af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (i == -1) 41872af4762ee640b717a30761e27fc55126c686568Tobias Klauser i = 0; 4195bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 42072af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (i >= ALTERA_JTAGUART_MAXPORTS) 42172af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -EINVAL; 4225bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 42372af4762ee640b717a30761e27fc55126c686568Tobias Klauser port = &altera_jtaguart_ports[i].port; 42472af4762ee640b717a30761e27fc55126c686568Tobias Klauser 42572af4762ee640b717a30761e27fc55126c686568Tobias Klauser res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 42672af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (res_mem) 42772af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->mapbase = res_mem->start; 42872af4762ee640b717a30761e27fc55126c686568Tobias Klauser else if (platp) 42972af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->mapbase = platp->mapbase; 43072af4762ee640b717a30761e27fc55126c686568Tobias Klauser else 43172af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -ENODEV; 43272af4762ee640b717a30761e27fc55126c686568Tobias Klauser 43372af4762ee640b717a30761e27fc55126c686568Tobias Klauser res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 43472af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (res_irq) 43572af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->irq = res_irq->start; 43672af4762ee640b717a30761e27fc55126c686568Tobias Klauser else if (platp) 43772af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->irq = platp->irq; 43872af4762ee640b717a30761e27fc55126c686568Tobias Klauser else 43972af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -ENODEV; 44072af4762ee640b717a30761e27fc55126c686568Tobias Klauser 44172af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE); 44272af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (!port->membase) 44372af4762ee640b717a30761e27fc55126c686568Tobias Klauser return -ENOMEM; 44472af4762ee640b717a30761e27fc55126c686568Tobias Klauser 44572af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->line = i; 44672af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->type = PORT_ALTERA_JTAGUART; 44772af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->iotype = SERIAL_IO_MEM; 44872af4762ee640b717a30761e27fc55126c686568Tobias Klauser port->ops = &altera_jtaguart_ops; 44944ed76b78e158d852f640d533b7acc08b91f2132Tobias Klauser port->flags = UPF_BOOT_AUTOCONF; 45072af4762ee640b717a30761e27fc55126c686568Tobias Klauser 45172af4762ee640b717a30761e27fc55126c686568Tobias Klauser uart_add_one_port(&altera_jtaguart_driver, port); 4525bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4535bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 4545bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 4555bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 456ae8d8a146725a966bd7c59c94f4d0016dcf7a04fBill Pembertonstatic int altera_jtaguart_remove(struct platform_device *pdev) 4575bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 4585bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser struct uart_port *port; 45972af4762ee640b717a30761e27fc55126c686568Tobias Klauser int i = pdev->id; 4605bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 46172af4762ee640b717a30761e27fc55126c686568Tobias Klauser if (i == -1) 46272af4762ee640b717a30761e27fc55126c686568Tobias Klauser i = 0; 46372af4762ee640b717a30761e27fc55126c686568Tobias Klauser 46472af4762ee640b717a30761e27fc55126c686568Tobias Klauser port = &altera_jtaguart_ports[i].port; 46572af4762ee640b717a30761e27fc55126c686568Tobias Klauser uart_remove_one_port(&altera_jtaguart_driver, port); 4665bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4675bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 4685bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 4695bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4709f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser#ifdef CONFIG_OF 4719f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauserstatic struct of_device_id altera_jtaguart_match[] = { 4729f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser { .compatible = "ALTR,juart-1.0", }, 4739f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser {}, 4749f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser}; 4759f15444fefdb33509132ff5c9be60cb315c44cb2Tobias KlauserMODULE_DEVICE_TABLE(of, altera_jtaguart_match); 4769f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser#endif /* CONFIG_OF */ 4779f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser 4785bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic struct platform_driver altera_jtaguart_platform_driver = { 4795bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .probe = altera_jtaguart_probe, 4802d47b7160243b1422006b91debf438484a4fde58Bill Pemberton .remove = altera_jtaguart_remove, 4815bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser .driver = { 4829f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser .name = DRV_NAME, 4839f15444fefdb33509132ff5c9be60cb315c44cb2Tobias Klauser .owner = THIS_MODULE, 48485888069cf5d0f21312e3ee730458a5e3a553509Ben Dooks .of_match_table = of_match_ptr(altera_jtaguart_match), 4855bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser }, 4865bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser}; 4875bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4885bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic int __init altera_jtaguart_init(void) 4895bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 4905bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser int rc; 4915bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 4925bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser rc = uart_register_driver(&altera_jtaguart_driver); 4935bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (rc) 4945bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return rc; 4955bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser rc = platform_driver_register(&altera_jtaguart_platform_driver); 4965bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser if (rc) { 4975bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_unregister_driver(&altera_jtaguart_driver); 4985bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return rc; 4995bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser } 5005bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser return 0; 5015bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 5025bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 5035bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauserstatic void __exit altera_jtaguart_exit(void) 5045bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser{ 5055bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser platform_driver_unregister(&altera_jtaguart_platform_driver); 5065bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser uart_unregister_driver(&altera_jtaguart_driver); 5075bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser} 5085bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 5095bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klausermodule_init(altera_jtaguart_init); 5105bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klausermodule_exit(altera_jtaguart_exit); 5115bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias Klauser 5125bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_DESCRIPTION("Altera JTAG UART driver"); 5135bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); 5145bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_LICENSE("GPL"); 5155bcd601049c6b2ad52733d4cd2794bfbaf1b9314Tobias KlauserMODULE_ALIAS("platform:" DRV_NAME); 516