diff options
| -rw-r--r-- | target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h | 13 | ||||
| -rw-r--r-- | target/linux/ar71xx/files/drivers/serial/ar933x_uart.c | 622 | 
2 files changed, 152 insertions, 483 deletions
diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h index edb13cd01..527305559 100644 --- a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h +++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar933x_uart.h @@ -11,6 +11,9 @@  #ifndef __AR933X_UART_H  #define __AR933X_UART_H +#define AR933X_UART_REGS_SIZE		20 +#define AR933X_UART_FIFO_SIZE		16 +  #define AR933X_UART_DATA_REG		0x00  #define AR933X_UART_CS_REG		0x04  #define AR933X_UART_CLOCK_REG		0x08 @@ -23,9 +26,14 @@  #define AR933X_UART_CS_PARITY_S		0  #define AR933X_UART_CS_PARITY_M		0x3 -#define AR933X_UART_CS_PARITY_M		0x3 +#define   AR933X_UART_CS_PARITY_NONE	0 +#define   AR933X_UART_CS_PARITY_ODD	1 +#define   AR933X_UART_CS_PARITY_EVEN	2  #define AR933X_UART_CS_IF_MODE_S	2  #define AR933X_UART_CS_IF_MODE_M	0x3 +#define   AR933X_UART_CS_IF_MODE_NONE	0 +#define   AR933X_UART_CS_IF_MODE_DTE	1 +#define   AR933X_UART_CS_IF_MODE_DCE	2  #define AR933X_UART_CS_FLOW_CTRL_S	4  #define AR933X_UART_CS_FLOW_CTRL_M	0x3  #define AR933X_UART_CS_DMA_EN		BIT(6) @@ -41,7 +49,8 @@  #define AR933X_UART_CLOCK_STEP_M	0xffff  #define AR933X_UART_CLOCK_SCALE_M	0xfff -#define AR933X_UART_CLCOK_SCALE_S	16 +#define AR933X_UART_CLOCK_SCALE_S	16 +#define AR933X_UART_CLOCK_STEP_M	0xffff  #define AR933X_UART_INT_RX_VALID	BIT(0)  #define AR933X_UART_INT_TX_READY	BIT(1) diff --git a/target/linux/ar71xx/files/drivers/serial/ar933x_uart.c b/target/linux/ar71xx/files/drivers/serial/ar933x_uart.c index 66925c99b..ea12e405c 100644 --- a/target/linux/ar71xx/files/drivers/serial/ar933x_uart.c +++ b/target/linux/ar71xx/files/drivers/serial/ar933x_uart.c @@ -1,27 +1,16 @@  /* - *  linux/drivers/serial/hornet_serial.c + *  Atheros AR933X SoC built-in UART driver   * - *  Driver for hornet serial ports + *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>   *   *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.   * - *  Copyright (C) 2010 Ryan Hsu. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - *  $Id$ - * - * A note about mapbase / membase - * - *  mapbase is the physical address of the IO port. - *  membase is an 'ioremapped' cookie. + *  This program is free software; you can redistribute it and/or modify it + *  under the terms of the GNU General Public License version 2 as published + *  by the Free Software Foundation.   */  #include <linux/module.h> -#include <linux/moduleparam.h>  #include <linux/ioport.h>  #include <linux/init.h>  #include <linux/console.h> @@ -30,77 +19,26 @@  #include <linux/platform_device.h>  #include <linux/tty.h>  #include <linux/tty_flip.h> -#include <linux/serial_reg.h>  #include <linux/serial_core.h>  #include <linux/serial.h> -#include <linux/serial_8250.h> -#include <linux/nmi.h> -#include <linux/mutex.h>  #include <linux/slab.h> +#include <linux/io.h> +#include <linux/irq.h>  #include <asm/mach-ar71xx/ar933x_uart.h>  #include <asm/mach-ar71xx/ar933x_uart_platform.h> -#include <asm/io.h> -#include <asm/irq.h> - -#include "8250.h" -#define ar7240_reg_rmw_clear(_reg, _val)	do {} while (0) -  #define DRIVER_NAME "ar933x-uart" -#define AR933X_UART_REGS_SIZE	20 -#define AR933X_UART_FIFO_SIZE	16 - -/* - * uncomment below to enable WAR for EV81847. - */ -//#define AR933X_EV81847_WAR +#define AR933X_DUMMY_STATUS_RD	0x01  static struct uart_driver ar933x_uart_driver; -/* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...)	printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...)	do { } while (0) -#endif - -#if 0 -#define DEBUG_INTR(fmt...)	printk(fmt) -#else -#define DEBUG_INTR(fmt...)	do { } while (0) -#endif - -/* - * We default to IRQ0 for the "no irq" hack.   Some - * machine types want others as well - they're free - * to redefine this in their header file. - */ -#define is_real_interrupt(irq)	((irq) != 0) - -#include <asm/serial.h> -  struct ar933x_uart_port {  	struct uart_port	port; -	struct timer_list	timer;		/* "no irq" timer */ -	unsigned char		acr; -	unsigned char		ier; -	unsigned char		lcr; -	unsigned char		mcr; +	unsigned int 		ier;	/* shadow Interrupt Enable Register */  }; -static inline int ar933x_ev81847_war(void) -{ -#if defined(AR933X_EV81847_WAR) -	return 1; -#else -	return 0; -#endif -} -  static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,  					    int offset)  { @@ -142,19 +80,23 @@ static inline void ar933x_uart_rmw_clear(struct ar933x_uart_port *up,  static inline void ar933x_uart_start_tx_interrupt(struct ar933x_uart_port *up)  { -	ar933x_uart_rmw_set(up, AR933X_UART_INT_EN_REG, -			    AR933X_UART_INT_TX_EMPTY); +	up->ier |= AR933X_UART_INT_TX_EMPTY; +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);  }  static inline void ar933x_uart_stop_tx_interrupt(struct ar933x_uart_port *up)  { -	if (up->ier & UART_IER_THRI) { -		up->ier &= ~UART_IER_THRI; +	up->ier &= ~AR933X_UART_INT_TX_EMPTY; +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG,up->ier); +} -		/* FIXME: why this uses RXVALIDINTEN? */ -		ar933x_uart_rmw_clear(up, AR933X_UART_INT_EN_REG, -				      AR933X_UART_INT_RX_VALID); -	} +static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch) +{ +	unsigned int rdata; + +	rdata = ch & AR933X_UART_DATA_TX_RX_MASK; +	rdata |= AR933X_UART_DATA_TX_CSR; +	ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata);  }  static unsigned int ar933x_uart_tx_empty(struct uart_port *port) @@ -197,34 +139,22 @@ static void ar933x_uart_stop_rx(struct uart_port *port)  {  	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; -	up->ier &= ~UART_IER_RLSI; -	up->port.read_status_mask &= ~UART_LSR_DR; - -	ar933x_uart_rmw_clear(up, AR933X_UART_INT_EN_REG, -			      AR933X_UART_INT_RX_VALID); +	up->ier &= ~AR933X_UART_INT_RX_VALID; +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);  }  static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)  {  	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;  	unsigned long flags; -	unsigned long rdata;  	spin_lock_irqsave(&up->port.lock, flags); -  	if (break_state == -1) -		up->lcr |= UART_LCR_SBC; -	else -		up->lcr &= ~UART_LCR_SBC; - -	rdata = ar933x_uart_read(up, AR933X_UART_CS_REG); -	if (up->lcr & UART_LCR_SBC) -		rdata |= AR933X_UART_CS_TX_BREAK; +		ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, +				    AR933X_UART_CS_TX_BREAK);  	else -		rdata &= ~AR933X_UART_CS_TX_BREAK; - -	ar933x_uart_write(up, AR933X_UART_CS_REG, rdata); - +		ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG, +				      AR933X_UART_CS_TX_BREAK);  	spin_unlock_irqrestore(&up->port.lock, flags);  } @@ -232,395 +162,170 @@ static void ar933x_uart_enable_ms(struct uart_port *port)  {  } -static inline unsigned int ar933x_uart_get_divisor(struct uart_port *port, -						   unsigned int baud) -{ -	return (port->uartclk / (16 * baud)) - 1; -} -  static void ar933x_uart_set_termios(struct uart_port *port, -				    struct ktermios *termios, +				    struct ktermios *new,  				    struct ktermios *old)  {  	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; -	unsigned char cval; +	unsigned int cs;  	unsigned long flags; -	unsigned int baud, quot; - -	switch (termios->c_cflag & CSIZE) { -	case CS5: -		cval = UART_LCR_WLEN5; -		break; -	case CS6: -		cval = UART_LCR_WLEN6; -		break; -	case CS7: -		cval = UART_LCR_WLEN7; -		break; -	default: -	case CS8: -		cval = UART_LCR_WLEN8; -		break; -	} +	unsigned int baud, scale; -	if (termios->c_cflag & CSTOPB) -		cval |= UART_LCR_STOP; -	if (termios->c_cflag & PARENB) -		cval |= UART_LCR_PARITY; -	if (!(termios->c_cflag & PARODD)) -		cval |= UART_LCR_EPAR; -#ifdef CMSPAR -	if (termios->c_cflag & CMSPAR) -		cval |= UART_LCR_SPAR; -#endif +	/* Only CS8 is supported */ +	new->c_cflag &= ~CSIZE; +	new->c_cflag |= CS8; -	/* -	 * Ask the core to calculate the divisor for us. -	 */ -	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); -	quot = ar933x_uart_get_divisor(port, baud); +	/* Only one stop bit is supported */ +	new->c_cflag &= ~CSTOPB; -#if 0 -	if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { -		if (baud < 2400) -			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; +	cs = 0; +	if (new->c_cflag & PARENB) { +		if (!(new->c_cflag & PARODD)) +			cs |= AR933X_UART_CS_PARITY_EVEN;  		else -			fcr = uart_config[up->port.type].fcr; +			cs |= AR933X_UART_CS_PARITY_ODD; +	} else { +		cs |= AR933X_UART_CS_PARITY_NONE;  	} -	/* -	 * MCR-based auto flow control.  When AFE is enabled, RTS will be -	 * deasserted when the receive FIFO contains more characters than -	 * the trigger, or the MCR RTS bit is cleared.  In the case where -	 * the remote UART is not using CTS auto flow control, we must -	 * have sufficient FIFO entries for the latency of the remote -	 * UART to respond.  IOW, at least 32 bytes of FIFO. -	 */ -	if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) { -		up->mcr &= ~UART_MCR_AFE; -		if (termios->c_cflag & CRTSCTS) -			up->mcr |= UART_MCR_AFE; -	} -#endif +	/* Mark/space parity is not supported */ +	new->c_cflag &= ~CMSPAR; + +	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); +	scale = (port->uartclk / (16 * baud)) - 1;  	/* -	 * Ok, we're now changing the port state.  Do it with +	 * Ok, we're now changing the port state. Do it with  	 * interrupts disabled.  	 */  	spin_lock_irqsave(&up->port.lock, flags); -	/* -	 * Update the per-port timeout. -	 */ -	uart_update_timeout(port, termios->c_cflag, baud); +	/* Update the per-port timeout. */ +	uart_update_timeout(port, new->c_cflag, baud); -	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; -	if (termios->c_iflag & INPCK) -		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; -	if (termios->c_iflag & (BRKINT | PARMRK)) -		up->port.read_status_mask |= UART_LSR_BI; - -	/* -	 * Characteres to ignore -	 */  	up->port.ignore_status_mask = 0; -	if (termios->c_iflag & IGNPAR) -		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; -	if (termios->c_iflag & IGNBRK) { -		up->port.ignore_status_mask |= UART_LSR_BI; -		/* -		 * If we're ignoring parity and break indicators, -		 * ignore overruns too (for real raw support). -		 */ -		if (termios->c_iflag & IGNPAR) -			up->port.ignore_status_mask |= UART_LSR_OE; -	} -	/* -	 * ignore all characters if CREAD is not set -	 */ -	if ((termios->c_cflag & CREAD) == 0) -		up->port.ignore_status_mask |= UART_LSR_DR; +	/* ignore all characters if CREAD is not set */ +	if ((new->c_cflag & CREAD) == 0) +		up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD; -	/* -	 * CTS flow control flag and modem status interrupts -	 */ -	up->ier &= ~UART_IER_MSI; -	if (UART_ENABLE_MS(&up->port, termios->c_cflag)) -		up->ier |= UART_IER_MSI; +	ar933x_uart_write(up, AR933X_UART_CLOCK_REG, +			  scale << AR933X_UART_CLOCK_SCALE_S | 8192); + +	/* setup configuration register */ +	ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs); +	/* enable host interrupt */  	ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,  			    AR933X_UART_CS_HOST_INT_EN); -	/* Save LCR */ -	up->lcr = cval; - -	ar933x_uart_set_mctrl(&up->port, up->port.mctrl);  	spin_unlock_irqrestore(&up->port.lock, flags); + +	if (tty_termios_baud_rate(new)) +		tty_termios_encode_baud_rate(new, baud, baud);  } -static void ar933x_uart_rx_chars(struct ar933x_uart_port *up, int *status) +static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)  {  	struct tty_struct *tty = up->port.state->port.tty; -	unsigned int lsr = *status; -	unsigned char ch;  	int max_count = 256; -	char flag;  	do { -		ch = lsr & AR933X_UART_DATA_TX_RX_MASK; +		unsigned int rdata; +		unsigned char ch; -		flag = TTY_NORMAL; -		up->port.icount.rx++; +		rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG); +		if ((rdata & AR933X_UART_DATA_RX_CSR) == 0) +			break; -		lsr = AR933X_UART_DATA_RX_CSR; -		ar933x_uart_write(up, AR933X_UART_DATA_REG, lsr); - -		if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | -				    UART_LSR_FE | UART_LSR_OE))) { -			/* -			 * For statistics only -			 */ -			if (lsr & UART_LSR_BI) { -				lsr &= ~(UART_LSR_FE | UART_LSR_PE); -				up->port.icount.brk++; -				/* -				 * We do the SysRQ and SAK checking -				 * here because otherwise the break -				 * may get masked by ignore_status_mask -				 * or read_status_mask. -				 */ -				if (uart_handle_break(&up->port)) -					goto ignore_char; -			} else if (lsr & UART_LSR_PE) -				up->port.icount.parity++; -			else if (lsr & UART_LSR_FE) -				up->port.icount.frame++; -			if (lsr & UART_LSR_OE) -				up->port.icount.overrun++; - -			/* -			 * Mask off conditions which should be ignored. -			 */ -			lsr &= up->port.read_status_mask; - -			if (lsr & UART_LSR_BI) { -				DEBUG_INTR("handling break...."); -				flag = TTY_BREAK; -			} else if (lsr & UART_LSR_PE) -				flag = TTY_PARITY; -			else if (lsr & UART_LSR_FE) -				flag = TTY_FRAME; -		} +		/* remove the character from the FIFO */ +		ar933x_uart_write(up, AR933X_UART_DATA_REG, +				  AR933X_UART_DATA_RX_CSR); -		if (uart_handle_sysrq_char(&up->port, ch)) -			goto ignore_char; +		up->port.icount.rx++; +		ch = rdata & AR933X_UART_DATA_TX_RX_MASK; -		uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); +		if (uart_handle_sysrq_char(&up->port, ch)) +			continue; -ignore_char: -		lsr = ar933x_uart_read(up, AR933X_UART_DATA_REG); -	} while ((lsr & AR933X_UART_DATA_RX_CSR) && (max_count-- > 0)); +		if ((up->port.ignore_status_mask & AR933X_DUMMY_STATUS_RD) == 0) +			tty_insert_flip_char(tty, ch, TTY_NORMAL); +	} while (max_count-- > 0); -	spin_unlock(&up->port.lock);  	tty_flip_buffer_push(tty); -	spin_lock(&up->port.lock); - -	*status = lsr;  }  static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)  {  	struct circ_buf *xmit = &up->port.state->xmit;  	int count; -	unsigned int rdata; - -	rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG); -	if ((rdata & AR933X_UART_DATA_TX_CSR) == 0) { -		ar933x_uart_start_tx_interrupt(up); -		return; -	} -	if (up->port.x_char) { -		rdata = up->port.x_char & AR933X_UART_DATA_TX_RX_MASK; -		rdata |= AR933X_UART_DATA_TX_CSR; -		ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata); -		up->port.icount.tx++; -		up->port.x_char = 0; -		ar933x_uart_start_tx_interrupt(up); +	if (uart_tx_stopped(&up->port))  		return; -	} -	if (uart_tx_stopped(&up->port)) { -		ar933x_uart_stop_tx(&up->port); -		return; -	} - -	if (uart_circ_empty(xmit)) { -		ar933x_uart_stop_tx_interrupt(up); -		return; -	} - -	count = up->port.fifosize / 4; +	count = up->port.fifosize;  	do { +		unsigned int rdata; +  		rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG); -		if ((rdata & AR933X_UART_DATA_TX_CSR) == 0) { -			ar933x_uart_start_tx_interrupt(up); -			return; +		if ((rdata & AR933X_UART_DATA_TX_CSR) == 0) +			break; + +		if (up->port.x_char) { +			ar933x_uart_putc(up, up->port.x_char); +			up->port.icount.tx++; +			up->port.x_char = 0; +			continue;  		} -		rdata = xmit->buf[xmit->tail] & AR933X_UART_DATA_TX_RX_MASK; -		rdata |= AR933X_UART_DATA_TX_CSR; -		ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata); +		if (uart_circ_empty(xmit)) +			break; + +		ar933x_uart_putc(up, xmit->buf[xmit->tail]);  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);  		up->port.icount.tx++; -		if (uart_circ_empty(xmit)) -			break;  	} while (--count > 0); -	rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG); -	if ((rdata & AR933X_UART_DATA_TX_CSR) == 0) { -		ar933x_uart_start_tx_interrupt(up); -		return; -	} - -	/* Re-enable TX Empty Interrupt to transmit pending chars */ -	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { +	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)  		uart_write_wakeup(&up->port); -		ar933x_uart_start_tx_interrupt(up); -	} -	DEBUG_INTR("THRE..."); - -	if (uart_circ_empty(xmit)) -		ar933x_uart_stop_tx_interrupt(up); -	else +	if (!uart_circ_empty(xmit))  		ar933x_uart_start_tx_interrupt(up);  } -/*! Hornet's interrupt status is not read clear, so that we have to... - * a. read out the interrupt status - * b. clear the interrupt mask to reset the interrupt status - * c. enable the interrupt to reactivate interrupt - * - * Disable and clear the interrupt status - */ -static inline void ar933x_uart_clear_int(struct ar933x_uart_port *up) -{ -#define BIT3 (0x1>>3) - -	/* 1. clear MISC interrupt mask */ -	//ar7240_reg_rmw_clear(AR7240_MISC_INT_MASK, BIT3); - -	/* 2. clear uartcs hostinten mask, bit13 */ -	ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG, -			      AR933X_UART_CS_HOST_INT_EN); - -	/* 3. clear rx uartint */ -	ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID); - -	/* 4. clear misc interrupt status  */ -	ar7240_reg_rmw_clear(AR7240_MISC_INT_STATUS, BIT3); - -	/* 5. clear rx uartinten*/ -	ar933x_uart_rmw_clear(up, AR933X_UART_INT_EN_REG, -			      AR933X_UART_INT_RX_VALID); - -	/* 6. enable rx int*/ -	ar933x_uart_rmw_set(up, AR933X_UART_INT_EN_REG, -			    AR933X_UART_INT_RX_VALID); - -	/* 7. set uartcs hostinten mask */ -	ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, -			    AR933X_UART_CS_HOST_INT_EN); - -	/* 8. set misc int mask */ -	//ar7240_reg_wr(AR7240_MISC_INT_MASK, BIT3); -} - -static inline void ar933x_uart_handle_port(struct ar933x_uart_port *up) +static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)  { +	struct ar933x_uart_port *up = dev_id;  	unsigned int status; -	unsigned int int_status; -	unsigned int en_status; -	unsigned long flags; -	status = ar933x_uart_read(up, AR933X_UART_DATA_REG); -	int_status = ar933x_uart_read(up, AR933X_UART_INT_REG); -	en_status = ar933x_uart_read(up, AR933X_UART_INT_EN_REG); +	status = ar933x_uart_read(up, AR933X_UART_CS_REG); +	if ((status & AR933X_UART_CS_HOST_INT) == 0) +		return IRQ_NONE; -	spin_lock_irqsave(&up->port.lock, flags); +	spin_lock(&up->port.lock); -	if( (int_status & en_status) & AR933X_UART_INT_RX_VALID ) -		ar933x_uart_rx_chars(up, &status); +	status = ar933x_uart_read(up, AR933X_UART_INT_REG); +	status &= ar933x_uart_read(up, AR933X_UART_INT_EN_REG); -	if (((int_status & en_status) & AR933X_UART_INT_TX_EMPTY)) { -		/* clear TX empty interrupts */ +	if (status & AR933X_UART_INT_RX_VALID) {  		ar933x_uart_write(up, AR933X_UART_INT_REG, -				  AR933X_UART_INT_TX_EMPTY); - -		/* disable TX empty interrupts */ -		ar933x_uart_rmw_clear(up, AR933X_UART_INT_EN_REG, -				      AR933X_UART_INT_TX_EMPTY); - -		if (!uart_circ_empty(&up->port.state->xmit)) -			ar933x_uart_tx_chars(up); +				  AR933X_UART_INT_RX_VALID); +		ar933x_uart_rx_chars(up);  	} -	spin_unlock_irqrestore(&up->port.lock, flags); -} - -static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id) -{ -	struct ar933x_uart_port *up; -	unsigned int iir; - -	up = (struct ar933x_uart_port *) dev_id; - -	iir = ar933x_uart_read(up, AR933X_UART_CS_REG); -	if ((iir & AR933X_UART_CS_HOST_INT) == 0) -		return IRQ_NONE; - -	DEBUG_INTR("ar933x_uart_interrupt(%d)...", irq); +	if (status & AR933X_UART_INT_TX_EMPTY) { +		ar933x_uart_write(up, AR933X_UART_INT_REG, +				  AR933X_UART_INT_TX_EMPTY); +		ar933x_uart_stop_tx_interrupt(up); +		ar933x_uart_tx_chars(up); +	} -	spin_lock(&up->port.lock); -	ar933x_uart_handle_port(up); -	ar933x_uart_clear_int(up);  	spin_unlock(&up->port.lock); -	DEBUG_INTR("end.\n"); -  	return IRQ_HANDLED;  } -static void ar933x_uart_timer(unsigned long data) -{ -	struct uart_port *port = (void *)data; -	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; -	unsigned int iir; - -	if (ar933x_ev81847_war()) { -		struct circ_buf *xmit = &up->port.state->xmit; -		unsigned long flags; - -		if (!uart_circ_empty(xmit)) { -			spin_lock_irqsave(&up->port.lock, flags); -			ar933x_uart_tx_chars(up); -			spin_unlock_irqrestore(&up->port.lock, flags); -		} -	} else { -		iir = ar933x_uart_read(up, AR933X_UART_CS_REG); -		if (iir & AR933X_UART_CS_HOST_INT) { -			spin_lock(&up->port.lock); -			ar933x_uart_handle_port(up); -			spin_unlock(&up->port.lock); -		} -	} - -	mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); -} -  static int ar933x_uart_startup(struct uart_port *port)  {  	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; @@ -632,39 +337,15 @@ static int ar933x_uart_startup(struct uart_port *port)  	if (ret)  		return ret; -	up->mcr = 0; - -	/* -	 * Clear the interrupt registers. -	 */ -	ar933x_uart_read(up, AR933X_UART_CS_REG); -	ar933x_uart_read(up, AR933X_UART_INT_REG); - -	if (!is_real_interrupt(up->port.irq) || ar933x_ev81847_war()) { -		setup_timer(&up->timer, ar933x_uart_timer, (unsigned long)port); -		mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); -		return 0; -	} -  	spin_lock_irqsave(&up->port.lock, flags); -	/* -	 * Enable host interrupts -	 */ +	/* Enable HOST interrupts */  	ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,  			    AR933X_UART_CS_HOST_INT_EN); -	/* -	 * Enable RX interrupts -	 */ -	up->ier = UART_IER_RLSI | UART_IER_RDI; -	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, -			  AR933X_UART_INT_RX_VALID); - -	/* -	 * And clear the interrupt registers again for luck. -	 */ -	ar933x_uart_read(up, AR933X_UART_INT_REG); +	/* Enable RX interrupts */ +	up->ier = AR933X_UART_INT_RX_VALID; +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);  	spin_unlock_irqrestore(&up->port.lock, flags); @@ -674,29 +355,15 @@ static int ar933x_uart_startup(struct uart_port *port)  static void ar933x_uart_shutdown(struct uart_port *port)  {  	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; -	unsigned long flags; -	/* -	 * Disable all interrupts from this port -	 */ +	/* Disable all interrupts */  	up->ier = 0; -	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, 0); - -	spin_lock_irqsave(&up->port.lock, flags); -	up->port.mctrl &= ~TIOCM_OUT2; -	ar933x_uart_set_mctrl(&up->port, up->port.mctrl); -	spin_unlock_irqrestore(&up->port.lock, flags); +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); -	/* -	 * Disable break condition -	 */ +	/* Disable break condition */  	ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,  			      AR933X_UART_CS_TX_BREAK); -	if (!is_real_interrupt(up->port.irq) || -	    ar933x_ev81847_war()) -		del_timer_sync(&up->timer); -  	free_irq(up->port.irq, up);  } @@ -718,20 +385,24 @@ static int ar933x_uart_request_port(struct uart_port *port)  static void ar933x_uart_config_port(struct uart_port *port, int flags)  { -	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; - -	port->type = PORT_AR933X; - -	/* Clear mask, so no surprise interrupts. */ -	ar933x_uart_read(up, AR933X_UART_CS_REG); -	/* Clear interrupts status register */ -	ar933x_uart_read(up, AR933X_UART_INT_REG); +	if (flags & UART_CONFIG_TYPE) +		port->type = PORT_AR933X;  }  static int ar933x_uart_verify_port(struct uart_port *port,  				   struct serial_struct *ser)  { -	return -EINVAL; +	if (ser->type != PORT_UNKNOWN && +	    ser->type != PORT_AR933X) +		return -EINVAL; + +	if (ser->irq < 0 || ser->irq >= NR_IRQS) +		return -EINVAL; + +	if (ser->baud_base < 28800) +		return -EINVAL; + +	return 0;  }  static struct uart_ops ar933x_uart_ops = { @@ -774,13 +445,9 @@ static void ar933x_uart_wait_xmitr(struct ar933x_uart_port *up)  static void ar933x_uart_console_putchar(struct uart_port *port, int ch)  {  	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; -	unsigned int rdata;  	ar933x_uart_wait_xmitr(up); - -	rdata = ch & AR933X_UART_DATA_TX_RX_MASK; -	rdata |= AR933X_UART_DATA_TX_CSR; -	ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata); +	ar933x_uart_putc(up, ch);  }  static void ar933x_uart_console_write(struct console *co, const char *s, @@ -788,22 +455,22 @@ static void ar933x_uart_console_write(struct console *co, const char *s,  {  	struct ar933x_uart_port *up = ar933x_console_ports[co->index];  	unsigned long flags; -	unsigned int ier; +	unsigned int int_en;  	int locked = 1;  	local_irq_save(flags); -	if (up->port.sysrq) { +	if (up->port.sysrq)  		locked = 0; -	} else if (oops_in_progress) { +	else if (oops_in_progress)  		locked = spin_trylock(&up->port.lock); -	} else +	else  		spin_lock(&up->port.lock);  	/*  	 * First save the IER then disable the interrupts  	 */ -	ier = ar933x_uart_read(up, AR933X_UART_INT_EN_REG); +	int_en = ar933x_uart_read(up, AR933X_UART_INT_EN_REG);  	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, 0);  	uart_console_write(&up->port, s, count, ar933x_uart_console_putchar); @@ -813,8 +480,8 @@ static void ar933x_uart_console_write(struct console *co, const char *s,  	 * and restore the IER  	 */  	ar933x_uart_wait_xmitr(up); +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, int_en); -	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, ier);  	ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS);  	if (locked) @@ -854,13 +521,6 @@ static struct console ar933x_uart_console = {  	.data		= &ar933x_uart_driver,  }; -static int __init ar933x_uart_console_init(void) -{ -	register_console(&ar933x_uart_console); -	return 0; -} -console_initcall(ar933x_uart_console_init); -  static void ar933x_uart_add_console_port(struct ar933x_uart_port *up)  {  	ar933x_console_ports[up->port.line] = up; @@ -1015,4 +675,4 @@ module_exit(ar933x_uart_exit);  MODULE_DESCRIPTION("Atheros AR933X UART driver");  MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");  MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRV_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME);  | 
