diff options
Diffstat (limited to 'drivers/serial')
45 files changed, 1324 insertions, 1251 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 76d83ade9857..6a1a568ca649 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -85,7 +85,7 @@ static void serial21285_enable_ms(struct uart_port *port) { } -static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial21285_rx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->tty; @@ -123,7 +123,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r return IRQ_HANDLED; } -static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial21285_tx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; struct circ_buf *xmit = &port->info->xmit; diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index bac853c5abb5..9b8b585513ec 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -275,8 +275,7 @@ static void status_handle(struct m68k_serial *info, unsigned short status) return; } -static void receive_chars(struct m68k_serial *info, struct pt_regs *regs, - unsigned short rx) +static void receive_chars(struct m68k_serial *info, unsigned short rx) { struct tty_struct *tty = info->tty; m68328_uart *uart = &uart_addr[info->line]; @@ -377,7 +376,7 @@ clear_and_return: /* * This is the serial driver's generic interrupt routine */ -irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t rs_interrupt(int irq, void *dev_id) { struct m68k_serial * info; m68328_uart *uart; @@ -394,10 +393,10 @@ irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) #ifdef USE_INTS tx = uart->utx.w; - if (rx & URX_DATA_READY) receive_chars(info, regs, rx); + if (rx & URX_DATA_READY) receive_chars(info, rx); if (tx & UTX_TX_AVAIL) transmit_chars(info); #else - receive_chars(info, regs, rx); + receive_chars(info, rx); #endif return IRQ_HANDLED; } diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 1b299e8c57cd..634ecca36a77 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -612,7 +612,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info) * This is the serial driver's interrupt routine for a single port */ /* static void rs_360_interrupt(void *dev_id) */ /* until and if we start servicing irqs here */ -static void rs_360_interrupt(int vec, void *dev_id, struct pt_regs *fp) +static void rs_360_interrupt(int vec, void *dev_id) { u_char events; int idx; @@ -620,7 +620,7 @@ static void rs_360_interrupt(int vec, void *dev_id, struct pt_regs *fp) volatile struct smc_regs *smcp; volatile struct scc_regs *sccp; - info = (ser_info_t *)dev_id; + info = dev_id; idx = PORT_NUM(info->state->smc_scc_num); if (info->state->smc_scc_num & NUM_IS_SCC) { diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index cc2a205d4230..e34bd03cfce7 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1175,7 +1175,7 @@ static void serial8250_enable_ms(struct uart_port *port) } static void -receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) +receive_chars(struct uart_8250_port *up, int *status) { struct tty_struct *tty = up->port.info->tty; unsigned char ch, lsr = *status; @@ -1233,7 +1233,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) else if (lsr & UART_LSR_FE) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); @@ -1309,7 +1309,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up) * This handles the interrupt from one port. */ static inline void -serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) +serial8250_handle_port(struct uart_8250_port *up) { unsigned int status; @@ -1320,7 +1320,7 @@ serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) DEBUG_INTR("status = %x...", status); if (status & UART_LSR_DR) - receive_chars(up, &status, regs); + receive_chars(up, &status); check_modem_status(up); if (status & UART_LSR_THRE) transmit_chars(up); @@ -1342,7 +1342,7 @@ serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) * This means we need to loop through all ports. checking that they * don't have an interrupt pending. */ -static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial8250_interrupt(int irq, void *dev_id) { struct irq_info *i = dev_id; struct list_head *l, *end = NULL; @@ -1361,7 +1361,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r iir = serial_in(up, UART_IIR); if (!(iir & UART_IIR_NO_INT)) { - serial8250_handle_port(up, regs); + serial8250_handle_port(up); handled = 1; @@ -1461,7 +1461,7 @@ static void serial8250_timeout(unsigned long data) iir = serial_in(up, UART_IIR); if (!(iir & UART_IIR_NO_INT)) - serial8250_handle_port(up, NULL); + serial8250_handle_port(up); timeout = up->port.timeout; timeout = timeout > 6 ? (timeout / 2 - 2) : 1; diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index 1ebe6b585d2d..c5d0addfda4f 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c @@ -22,7 +22,6 @@ #include <asm/hardware.h> #include <asm/parisc-device.h> #include <asm/io.h> -#include <asm/serial.h> /* for LASI_BASE_BAUD */ #include "8250.h" @@ -54,7 +53,8 @@ serial_init_chip(struct parisc_device *dev) memset(&port, 0, sizeof(port)); port.iotype = UPIO_MEM; - port.uartclk = LASI_BASE_BAUD * 16; + /* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */ + port.uartclk = 7272727; port.mapbase = address; port.membase = ioremap_nocache(address, 16); port.irq = dev->irq; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 653098bc2dd5..0b71e7d18903 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -299,33 +299,33 @@ config SERIAL_AMBA_PL011_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_AT91 - bool "AT91RM9200 / AT91SAM9261 serial port support" - depends on ARM && (ARCH_AT91RM9200 || ARCH_AT91SAM9261) +config SERIAL_ATMEL + bool "AT91 / AT32 on-chip serial port support" + depends on (ARM && ARCH_AT91) || AVR32 select SERIAL_CORE help This enables the driver for the on-chip UARTs of the Atmel - AT91RM9200 and AT91SAM926 processor. + AT91 and AT32 processors. -config SERIAL_AT91_CONSOLE - bool "Support for console on AT91RM9200 / AT91SAM9261 serial port" - depends on SERIAL_AT91=y +config SERIAL_ATMEL_CONSOLE + bool "Support for console on AT91 / AT32 serial port" + depends on SERIAL_ATMEL=y select SERIAL_CORE_CONSOLE help - Say Y here if you wish to use a UART on the Atmel AT91RM9200 or - AT91SAM9261 as the system console (the system console is the device - which receives all kernel messages and warnings and which allows - logins in single user mode). + Say Y here if you wish to use an on-chip UART on a Atmel + AT91 or AT32 processor as the system console (the system + console is the device which receives all kernel messages and + warnings and which allows logins in single user mode). -config SERIAL_AT91_TTYAT - bool "Install as device ttyAT0-4 instead of ttyS0-4" - depends on SERIAL_AT91=y +config SERIAL_ATMEL_TTYAT + bool "Install as device ttyATn instead of ttySn" + depends on SERIAL_ATMEL=y help - Say Y here if you wish to have the five internal AT91RM9200 UARTs - appear as /dev/ttyAT0-4 (major 204, minor 154-158) instead of the - normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if - you also want other UARTs, such as external 8250/16C550 compatible - UARTs. + Say Y here if you wish to have the internal AT91 / AT32 UARTs + appear as /dev/ttyATn (major 204, minor starting at 154) + instead of the normal /dev/ttySn (major 4, minor starting at + 64). This is necessary if you also want other UARTs, such as + external 8250/16C550 compatible UARTs. The ttySn nodes are legally reserved for the 8250 serial driver but are often misused by other serial drivers. @@ -556,10 +556,11 @@ config SERIAL_MUX default y ---help--- Saying Y here will enable the hardware MUX serial driver for - the Nova and K class systems. The hardware MUX is not 8250/16550 - compatible therefore the /dev/ttyB0 device is shared between the - Serial MUX and the PDC software console. The following steps - need to be completed to use the Serial MUX: + the Nova, K class systems and D class with a 'remote control card'. + The hardware MUX is not 8250/16550 compatible therefore the + /dev/ttyB0 device is shared between the Serial MUX and the PDC + software console. The following steps need to be completed to use + the Serial MUX: 1. create the device entry (mknod /dev/ttyB0 c 11 0) 2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0 @@ -766,37 +767,37 @@ config SERIAL_CPM_SCC1 bool "Support for SCC1 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC1 as a serial port + Select this option to use SCC1 as a serial port config SERIAL_CPM_SCC2 bool "Support for SCC2 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC2 as a serial port + Select this option to use SCC2 as a serial port config SERIAL_CPM_SCC3 bool "Support for SCC3 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC3 as a serial port + Select this option to use SCC3 as a serial port config SERIAL_CPM_SCC4 bool "Support for SCC4 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC4 as a serial port + Select this option to use SCC4 as a serial port config SERIAL_CPM_SMC1 bool "Support for SMC1 serial port" depends on SERIAL_CPM=y help - Select the is option to use SMC1 as a serial port + Select this option to use SMC1 as a serial port config SERIAL_CPM_SMC2 bool "Support for SMC2 serial port" depends on SERIAL_CPM=y help - Select the is option to use SMC2 as a serial port + Select this option to use SMC2 as a serial port config SERIAL_SGI_L1_CONSOLE bool "SGI Altix L1 serial console support" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 927faee0362e..b4d8a7c182e3 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -54,5 +54,5 @@ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o -obj-$(CONFIG_SERIAL_AT91) += at91_serial.o +obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 7311d8487c96..4213fabc62bf 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -111,12 +111,7 @@ static void pl010_enable_ms(struct uart_port *port) writel(cr, port->membase + UART010_CR); } -static void -#ifdef SUPPORT_SYSRQ -pl010_rx_chars(struct uart_port *port, struct pt_regs *regs) -#else -pl010_rx_chars(struct uart_port *port) -#endif +static void pl010_rx_chars(struct uart_port *port) { struct tty_struct *tty = port->info->tty; unsigned int status, ch, flag, rsr, max_count = 256; @@ -156,7 +151,7 @@ pl010_rx_chars(struct uart_port *port) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, ch, regs)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); @@ -227,7 +222,7 @@ static void pl010_modem_status(struct uart_port *port) wake_up_interruptible(&uap->port.info->delta_msr_wait); } -static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pl010_int(int irq, void *dev_id) { struct uart_port *port = dev_id; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; @@ -239,11 +234,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) if (status) { do { if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) -#ifdef SUPPORT_SYSRQ - pl010_rx_chars(port, regs); -#else pl010_rx_chars(port); -#endif if (status & UART010_IIR_MIS) pl010_modem_status(port); if (status & UART010_IIR_TIS) diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index a8d7124e84a1..d503625730df 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -107,12 +107,7 @@ static void pl011_enable_ms(struct uart_port *port) writew(uap->im, uap->port.membase + UART011_IMSC); } -static void -#ifdef SUPPORT_SYSRQ -pl011_rx_chars(struct uart_amba_port *uap, struct pt_regs *regs) -#else -pl011_rx_chars(struct uart_amba_port *uap) -#endif +static void pl011_rx_chars(struct uart_amba_port *uap) { struct tty_struct *tty = uap->port.info->tty; unsigned int status, ch, flag, max_count = 256; @@ -150,7 +145,7 @@ pl011_rx_chars(struct uart_amba_port *uap) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&uap->port, ch & 255, regs)) + if (uart_handle_sysrq_char(&uap->port, ch & 255)) goto ignore_char; uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); @@ -218,7 +213,7 @@ static void pl011_modem_status(struct uart_amba_port *uap) wake_up_interruptible(&uap->port.info->delta_msr_wait); } -static irqreturn_t pl011_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pl011_int(int irq, void *dev_id) { struct uart_amba_port *uap = dev_id; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; @@ -234,11 +229,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id, struct pt_regs *regs) uap->port.membase + UART011_ICR); if (status & (UART011_RTIS|UART011_RXIS)) -#ifdef SUPPORT_SYSRQ - pl011_rx_chars(uap, regs); -#else pl011_rx_chars(uap); -#endif if (status & (UART011_DSRMIS|UART011_DCDMIS| UART011_CTSMIS|UART011_RIMIS)) pl011_modem_status(uap); diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c deleted file mode 100644 index bf4bf103e5a0..000000000000 --- a/drivers/serial/at91_serial.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - * linux/drivers/char/at91_serial.c - * - * Driver for Atmel AT91RM9200 Serial ports - * Copyright (C) 2003 Rick Bronson - * - * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/serial.h> -#include <linux/clk.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/tty_flip.h> -#include <linux/platform_device.h> - -#include <asm/io.h> - -#include <asm/arch/at91rm9200_usart.h> -#include <asm/arch/at91rm9200_pdc.h> -#include <asm/mach/serial_at91.h> -#include <asm/arch/board.h> -#include <asm/arch/system.h> -#include <asm/arch/gpio.h> - -#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/serial_core.h> - -#ifdef CONFIG_SERIAL_AT91_TTYAT - -/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we - * should coexist with the 8250 driver, such as if we have an external 16C550 - * UART. */ -#define SERIAL_AT91_MAJOR 204 -#define MINOR_START 154 -#define AT91_DEVICENAME "ttyAT" - -#else - -/* Use device name ttyS, major 4, minor 64-68. This is the usual serial port - * name, but it is legally reserved for the 8250 driver. */ -#define SERIAL_AT91_MAJOR TTY_MAJOR -#define MINOR_START 64 -#define AT91_DEVICENAME "ttyS" - -#endif - -#define AT91_ISR_PASS_LIMIT 256 - -#define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR) -#define UART_GET_MR(port) readl((port)->membase + AT91_US_MR) -#define UART_PUT_MR(port,v) writel(v, (port)->membase + AT91_US_MR) -#define UART_PUT_IER(port,v) writel(v, (port)->membase + AT91_US_IER) -#define UART_PUT_IDR(port,v) writel(v, (port)->membase + AT91_US_IDR) -#define UART_GET_IMR(port) readl((port)->membase + AT91_US_IMR) -#define UART_GET_CSR(port) readl((port)->membase + AT91_US_CSR) -#define UART_GET_CHAR(port) readl((port)->membase + AT91_US_RHR) -#define UART_PUT_CHAR(port,v) writel(v, (port)->membase + AT91_US_THR) -#define UART_GET_BRGR(port) readl((port)->membase + AT91_US_BRGR) -#define UART_PUT_BRGR(port,v) writel(v, (port)->membase + AT91_US_BRGR) -#define UART_PUT_RTOR(port,v) writel(v, (port)->membase + AT91_US_RTOR) - -// #define UART_GET_CR(port) readl((port)->membase + AT91_US_CR) // is write-only - - /* PDC registers */ -#define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR) -#define UART_GET_PTSR(port) readl((port)->membase + AT91_PDC_PTSR) - -#define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR) -#define UART_GET_RPR(port) readl((port)->membase + AT91_PDC_RPR) -#define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR) -#define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR) -#define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR) - -#define UART_PUT_TPR(port,v) writel(v, (port)->membase + AT91_PDC_TPR) -#define UART_PUT_TCR(port,v) writel(v, (port)->membase + AT91_PDC_TCR) -//#define UART_PUT_TNPR(port,v) writel(v, (port)->membase + AT91_PDC_TNPR) -//#define UART_PUT_TNCR(port,v) writel(v, (port)->membase + AT91_PDC_TNCR) - -static int (*at91_open)(struct uart_port *); -static void (*at91_close)(struct uart_port *); - -/* - * We wrap our port structure around the generic uart_port. - */ -struct at91_uart_port { - struct uart_port uart; /* uart */ - struct clk *clk; /* uart clock */ - unsigned short suspended; /* is port suspended? */ -}; - -static struct at91_uart_port at91_ports[AT91_NR_UART]; - -#ifdef SUPPORT_SYSRQ -static struct console at91_console; -#endif - -/* - * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. - */ -static u_int at91_tx_empty(struct uart_port *port) -{ - return (UART_GET_CSR(port) & AT91_US_TXEMPTY) ? TIOCSER_TEMT : 0; -} - -/* - * Set state of the modem control output lines - */ -static void at91_set_mctrl(struct uart_port *port, u_int mctrl) -{ - unsigned int control = 0; - unsigned int mode; - - if (arch_identify() == ARCH_ID_AT91RM9200) { - /* - * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. - * We need to drive the pin manually. - */ - if (port->mapbase == AT91RM9200_BASE_US0) { - if (mctrl & TIOCM_RTS) - at91_set_gpio_value(AT91_PIN_PA21, 0); - else - at91_set_gpio_value(AT91_PIN_PA21, 1); - } - } - - if (mctrl & TIOCM_RTS) - control |= AT91_US_RTSEN; - else - control |= AT91_US_RTSDIS; - - if (mctrl & TIOCM_DTR) - control |= AT91_US_DTREN; - else - control |= AT91_US_DTRDIS; - - UART_PUT_CR(port, control); - - /* Local loopback mode? */ - mode = UART_GET_MR(port) & ~AT91_US_CHMODE; - if (mctrl & TIOCM_LOOP) - mode |= AT91_US_CHMODE_LOC_LOOP; - else - mode |= AT91_US_CHMODE_NORMAL; - UART_PUT_MR(port, mode); -} - -/* - * Get state of the modem control input lines - */ -static u_int at91_get_mctrl(struct uart_port *port) -{ - unsigned int status, ret = 0; - - status = UART_GET_CSR(port); - - /* - * The control signals are active low. - */ - if (!(status & AT91_US_DCD)) - ret |= TIOCM_CD; - if (!(status & AT91_US_CTS)) - ret |= TIOCM_CTS; - if (!(status & AT91_US_DSR)) - ret |= TIOCM_DSR; - if (!(status & AT91_US_RI)) - ret |= TIOCM_RI; - - return ret; -} - -/* - * Stop transmitting. - */ -static void at91_stop_tx(struct uart_port *port) -{ - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - UART_PUT_IDR(port, AT91_US_TXRDY); -} - -/* - * Start transmitting. - */ -static void at91_start_tx(struct uart_port *port) -{ - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - UART_PUT_IER(port, AT91_US_TXRDY); -} - -/* - * Stop receiving - port is in process of being closed. - */ -static void at91_stop_rx(struct uart_port *port) -{ - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - UART_PUT_IDR(port, AT91_US_RXRDY); -} - -/* - * Enable modem status interrupts - */ -static void at91_enable_ms(struct uart_port *port) -{ - UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); -} - -/* - * Control the transmission of a break signal - */ -static void at91_break_ctl(struct uart_port *port, int break_state) -{ - if (break_state != 0) - UART_PUT_CR(port, AT91_US_STTBRK); /* start break */ - else - UART_PUT_CR(port, AT91_US_STPBRK); /* stop break */ -} - -/* - * Characters received (called from interrupt handler) - */ -static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) -{ - struct tty_struct *tty = port->info->tty; - unsigned int status, ch, flg; - - status = UART_GET_CSR(port); - while (status & AT91_US_RXRDY) { - ch = UART_GET_CHAR(port); - - port->icount.rx++; - - flg = TTY_NORMAL; - - /* - * note that the error handling code is - * out of the main execution path - */ - if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE | AT91_US_RXBRK))) { - UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */ - if (status & AT91_US_RXBRK) { - status &= ~(AT91_US_PARE | AT91_US_FRAME); /* ignore side-effect */ - port->icount.brk++; - if (uart_handle_break(port)) - goto ignore_char; - } - if (status & AT91_US_PARE) - port->icount.parity++; - if (status & AT91_US_FRAME) - port->icount.frame++; - if (status & AT91_US_OVRE) - port->icount.overrun++; - - status &= port->read_status_mask; - - if (status & AT91_US_RXBRK) - flg = TTY_BREAK; - else if (status & AT91_US_PARE) - flg = TTY_PARITY; - else if (status & AT91_US_FRAME) - flg = TTY_FRAME; - } - - if (uart_handle_sysrq_char(port, ch, regs)) - goto ignore_char; - - uart_insert_char(port, status, AT91_US_OVRE, ch, flg); - - ignore_char: - status = UART_GET_CSR(port); - } - - tty_flip_buffer_push(tty); -} - -/* - * Transmit characters (called from interrupt handler) - */ -static void at91_tx_chars(struct uart_port *port) -{ - struct circ_buf *xmit = &port->info->xmit; - - if (port->x_char) { - UART_PUT_CHAR(port, port->x_char); - port->icount.tx++; - port->x_char = 0; - return; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - at91_stop_tx(port); - return; - } - - while (UART_GET_CSR(port) & AT91_US_TXRDY) { - UART_PUT_CHAR(port, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - if (uart_circ_empty(xmit)) - break; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - if (uart_circ_empty(xmit)) - at91_stop_tx(port); -} - -/* - * Interrupt handler - */ -static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct uart_port *port = dev_id; - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - unsigned int status, pending, pass_counter = 0; - - status = UART_GET_CSR(port); - pending = status & UART_GET_IMR(port); - while (pending) { - /* Interrupt receive */ - if (pending & AT91_US_RXRDY) - at91_rx_chars(port, regs); - - // TODO: All reads to CSR will clear these interrupts! - if (pending & AT91_US_RIIC) port->icount.rng++; - if (pending & AT91_US_DSRIC) port->icount.dsr++; - if (pending & AT91_US_DCDIC) - uart_handle_dcd_change(port, !(status & AT91_US_DCD)); - if (pending & AT91_US_CTSIC) - uart_handle_cts_change(port, !(status & AT91_US_CTS)); - if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) - wake_up_interruptible(&port->info->delta_msr_wait); - - /* Interrupt transmit */ - if (pending & AT91_US_TXRDY) - at91_tx_chars(port); - - if (pass_counter++ > AT91_ISR_PASS_LIMIT) - break; - - status = UART_GET_CSR(port); - pending = status & UART_GET_IMR(port); - } - return IRQ_HANDLED; -} - -/* - * Perform initialization and enable port for reception - */ -static int at91_startup(struct uart_port *port) -{ - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - int retval; - - /* - * Ensure that no interrupts are enabled otherwise when - * request_irq() is called we could get stuck trying to - * handle an unexpected interrupt - */ - UART_PUT_IDR(port, -1); - - /* - * Allocate the IRQ - */ - retval = request_irq(port->irq, at91_interrupt, IRQF_SHARED, "at91_serial", port); - if (retval) { - printk("at91_serial: at91_startup - Can't get irq\n"); - return retval; - } - - /* - * If there is a specific "open" function (to register - * control line interrupts) - */ - if (at91_open) { - retval = at91_open(port); - if (retval) { - free_irq(port->irq, port); - return retval; - } - } - - /* - * Finally, enable the serial port - */ - UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); - UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */ - - UART_PUT_IER(port, AT91_US_RXRDY); /* enable receive only */ - - return 0; -} - -/* - * Disable the port - */ -static void at91_shutdown(struct uart_port *port) -{ - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - /* - * Disable all interrupts, port and break condition. - */ - UART_PUT_CR(port, AT91_US_RSTSTA); - UART_PUT_IDR(port, -1); - - /* - * Free the interrupt - */ - free_irq(port->irq, port); - - /* - * If there is a specific "close" function (to unregister - * control line interrupts) - */ - if (at91_close) - at91_close(port); -} - -/* - * Power / Clock management. - */ -static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) -{ - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - switch (state) { - case 0: - /* - * Enable the peripheral clock for this serial port. - * This is called on uart_open() or a resume event. - */ - clk_enable(at91_port->clk); - break; - case 3: - /* - * Disable the peripheral clock for this serial port. - * This is called on uart_close() or a suspend event. - */ - clk_disable(at91_port->clk); - break; - default: - printk(KERN_ERR "at91_serial: unknown pm %d\n", state); - } -} - -/* - * Change the port parameters - */ -static void at91_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) -{ - unsigned long flags; - unsigned int mode, imr, quot, baud; - - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); - - /* Get current mode register */ - mode = UART_GET_MR(port) & ~(AT91_US_CHRL | AT91_US_NBSTOP | AT91_US_PAR); - - /* byte size */ - switch (termios->c_cflag & CSIZE) { - case CS5: - mode |= AT91_US_CHRL_5; - break; - case CS6: - mode |= AT91_US_CHRL_6; - break; - case CS7: - mode |= AT91_US_CHRL_7; - break; - default: - mode |= AT91_US_CHRL_8; - break; - } - - /* stop bits */ - if (termios->c_cflag & CSTOPB) - mode |= AT91_US_NBSTOP_2; - - /* parity */ - if (termios->c_cflag & PARENB) { - if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ - if (termios->c_cflag & PARODD) - mode |= AT91_US_PAR_MARK; - else - mode |= AT91_US_PAR_SPACE; - } - else if (termios->c_cflag & PARODD) - mode |= AT91_US_PAR_ODD; - else - mode |= AT91_US_PAR_EVEN; - } - else - mode |= AT91_US_PAR_NONE; - - spin_lock_irqsave(&port->lock, flags); - - port->read_status_mask = AT91_US_OVRE; - if (termios->c_iflag & INPCK) - port->read_status_mask |= (AT91_US_FRAME | AT91_US_PARE); - if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= AT91_US_RXBRK; - - /* - * Characters to ignore - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= (AT91_US_FRAME | AT91_US_PARE); - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= AT91_US_RXBRK; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= AT91_US_OVRE; - } - - // TODO: Ignore all characters if CREAD is set. - - /* update the per-port timeout */ - uart_update_timeout(port, termios->c_cflag, baud); - - /* disable interrupts and drain transmitter */ - imr = UART_GET_IMR(port); /* get interrupt mask */ - UART_PUT_IDR(port, -1); /* disable all interrupts */ - while (!(UART_GET_CSR(port) & AT91_US_TXEMPTY)) { barrier(); } - - /* disable receiver and transmitter */ - UART_PUT_CR(port, AT91_US_TXDIS | AT91_US_RXDIS); - - /* set the parity, stop bits and data size */ - UART_PUT_MR(port, mode); - - /* set the baud rate */ - UART_PUT_BRGR(port, quot); - UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); - UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); - - /* restore interrupts */ - UART_PUT_IER(port, imr); - - /* CTS flow-control and modem-status interrupts */ - if (UART_ENABLE_MS(port, termios->c_cflag)) - port->ops->enable_ms(port); - - spin_unlock_irqrestore(&port->lock, flags); -} - -/* - * Return string describing the specified port - */ -static const char *at91_type(struct uart_port *port) -{ - return (port->type == PORT_AT91) ? "AT91_SERIAL" : NULL; -} - -/* - * Release the memory region(s) being used by 'port'. - */ -static void at91_release_port(struct uart_port *port) -{ - struct platform_device *pdev = to_platform_device(port->dev); - int size = pdev->resource[0].end - pdev->resource[0].start + 1; - - release_mem_region(port->mapbase, size); - - if (port->flags & UPF_IOREMAP) { - iounmap(port->membase); - port->membase = NULL; - } -} - -/* - * Request the memory region(s) being used by 'port'. - */ -static int at91_request_port(struct uart_port *port) -{ - struct platform_device *pdev = to_platform_device(port->dev); - int size = pdev->resource[0].end - pdev->resource[0].start + 1; - - if (!request_mem_region(port->mapbase, size, "at91_serial")) - return -EBUSY; - - if (port->flags & UPF_IOREMAP) { - port->membase = ioremap(port->mapbase, size); - if (port->membase == NULL) { - release_mem_region(port->mapbase, size); - return -ENOMEM; - } - } - - return 0; -} - -/* - * Configure/autoconfigure the port. - */ -static void at91_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) { - port->type = PORT_AT91; - at91_request_port(port); - } -} - -/* - * Verify the new serial_struct (for TIOCSSERIAL). - */ -static int at91_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - int ret = 0; - if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91) - ret = -EINVAL; - if (port->irq != ser->irq) - ret = -EINVAL; - if (ser->io_type != SERIAL_IO_MEM) - ret = -EINVAL; - if (port->uartclk / 16 != ser->baud_base) - ret = -EINVAL; - if ((void *)port->mapbase != ser->iomem_base) - ret = -EINVAL; - if (port->iobase != ser->port) - ret = -EINVAL; - if (ser->hub6 != 0) - ret = -EINVAL; - return ret; -} - -static struct uart_ops at91_pops = { - .tx_empty = at91_tx_empty, - .set_mctrl = at91_set_mctrl, - .get_mctrl = at91_get_mctrl, - .stop_tx = at91_stop_tx, - .start_tx = at91_start_tx, - .stop_rx = at91_stop_rx, - .enable_ms = at91_enable_ms, - .break_ctl = at91_break_ctl, - .startup = at91_startup, - .shutdown = at91_shutdown, - .set_termios = at91_set_termios, - .type = at91_type, - .release_port = at91_release_port, - .request_port = at91_request_port, - .config_port = at91_config_port, - .verify_port = at91_verify_port, - .pm = at91_serial_pm, -}; - -/* - * Configure the port from the platform device resource info. - */ -static void __devinit at91_init_port(struct at91_uart_port *at91_port, struct platform_device *pdev) -{ - struct uart_port *port = &at91_port->uart; - struct at91_uart_data *data = pdev->dev.platform_data; - - port->iotype = UPIO_MEM; - port->flags = UPF_BOOT_AUTOCONF; - port->ops = &at91_pops; - port->fifosize = 1; - port->line = pdev->id; - port->dev = &pdev->dev; - - port->mapbase = pdev->resource[0].start; - port->irq = pdev->resource[1].start; - - if (port->mapbase == AT91_VA_BASE_SYS + AT91_DBGU) /* Part of system perpherals - already mapped */ - port->membase = (void __iomem *) port->mapbase; - else { - port->flags |= UPF_IOREMAP; - port->membase = NULL; - } - - if (!at91_port->clk) { /* for console, the clock could already be configured */ - at91_port->clk = clk_get(&pdev->dev, "usart"); - clk_enable(at91_port->clk); - port->uartclk = clk_get_rate(at91_port->clk); - } -} - -/* - * Register board-specific modem-control line handlers. - */ -void __init at91_register_uart_fns(struct at91_port_fns *fns) -{ - if (fns->enable_ms) - at91_pops.enable_ms = fns->enable_ms; - if (fns->get_mctrl) - at91_pops.get_mctrl = fns->get_mctrl; - if (fns->set_mctrl) - at91_pops.set_mctrl = fns->set_mctrl; - at91_open = fns->open; - at91_close = fns->close; - at91_pops.pm = fns->pm; - at91_pops.set_wake = fns->set_wake; -} - - -#ifdef CONFIG_SERIAL_AT91_CONSOLE -static void at91_console_putchar(struct uart_port *port, int ch) -{ - while (!(UART_GET_CSR(port) & AT91_US_TXRDY)) - barrier(); - UART_PUT_CHAR(port, ch); -} - -/* - * Interrupts are disabled on entering - */ -static void at91_console_write(struct console *co, const char *s, u_int count) -{ - struct uart_port *port = &at91_ports[co->index].uart; - unsigned int status, imr; - - /* - * First, save IMR and then disable interrupts - */ - imr = UART_GET_IMR(port); /* get interrupt mask */ - UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); - - uart_console_write(port, s, count, at91_console_putchar); - - /* - * Finally, wait for transmitter to become empty - * and restore IMR - */ - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_IER(port, imr); /* set interrupts back the way they were */ -} - -/* - * If the port was already initialised (eg, by a boot loader), try to determine - * the current setup. - */ -static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) -{ - unsigned int mr, quot; - -// TODO: CR is a write-only register -// unsigned int cr; -// -// cr = UART_GET_CR(port) & (AT91_US_RXEN | AT91_US_TXEN); -// if (cr == (AT91_US_RXEN | AT91_US_TXEN)) { -// /* ok, the port was enabled */ -// } - - mr = UART_GET_MR(port) & AT91_US_CHRL; - if (mr == AT91_US_CHRL_8) - *bits = 8; - else - *bits = 7; - - mr = UART_GET_MR(port) & AT91_US_PAR; - if (mr == AT91_US_PAR_EVEN) - *parity = 'e'; - else if (mr == AT91_US_PAR_ODD) - *parity = 'o'; - - quot = UART_GET_BRGR(port); - *baud = port->uartclk / (16 * (quot)); -} - -static int __init at91_console_setup(struct console *co, char *options) -{ - struct uart_port *port = &at91_ports[co->index].uart; - int baud = 115200; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - if (port->membase == 0) /* Port not initialized yet - delay setup */ - return -ENODEV; - - UART_PUT_IDR(port, -1); /* disable interrupts */ - UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); - UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else - at91_console_get_options(port, &baud, &parity, &bits); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -static struct uart_driver at91_uart; - -static struct console at91_console = { - .name = AT91_DEVICENAME, - .write = at91_console_write, - .device = uart_console_device, - .setup = at91_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &at91_uart, -}; - -#define AT91_CONSOLE_DEVICE &at91_console - -/* - * Early console initialization (before VM subsystem initialized). - */ -static int __init at91_console_init(void) -{ - if (at91_default_console_device) { - add_preferred_console(AT91_DEVICENAME, at91_default_console_device->id, NULL); - at91_init_port(&(at91_ports[at91_default_console_device->id]), at91_default_console_device); - register_console(&at91_console); - } - - return 0; -} -console_initcall(at91_console_init); - -/* - * Late console initialization. - */ -static int __init at91_late_console_init(void) -{ - if (at91_default_console_device && !(at91_console.flags & CON_ENABLED)) - register_console(&at91_console); - - return 0; -} -core_initcall(at91_late_console_init); - -#else -#define AT91_CONSOLE_DEVICE NULL -#endif - -static struct uart_driver at91_uart = { - .owner = THIS_MODULE, - .driver_name = "at91_serial", - .dev_name = AT91_DEVICENAME, - .major = SERIAL_AT91_MAJOR, - .minor = MINOR_START, - .nr = AT91_NR_UART, - .cons = AT91_CONSOLE_DEVICE, -}; - -#ifdef CONFIG_PM -static int at91_serial_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct uart_port *port = platform_get_drvdata(pdev); - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock()) - enable_irq_wake(port->irq); - else { - disable_irq_wake(port->irq); - uart_suspend_port(&at91_uart, port); - at91_port->suspended = 1; - } - - return 0; -} - -static int at91_serial_resume(struct platform_device *pdev) -{ - struct uart_port *port = platform_get_drvdata(pdev); - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - - if (at91_port->suspended) { - uart_resume_port(&at91_uart, port); - at91_port->suspended = 0; - } - - return 0; -} -#else -#define at91_serial_suspend NULL -#define at91_serial_resume NULL -#endif - -static int __devinit at91_serial_probe(struct platform_device *pdev) -{ - struct at91_uart_port *port; - int ret; - - port = &at91_ports[pdev->id]; - at91_init_port(port, pdev); - - ret = uart_add_one_port(&at91_uart, &port->uart); - if (!ret) { - device_init_wakeup(&pdev->dev, 1); - platform_set_drvdata(pdev, port); - } - - return ret; -} - -static int __devexit at91_serial_remove(struct platform_device *pdev) -{ - struct uart_port *port = platform_get_drvdata(pdev); - struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - int ret = 0; - - clk_disable(at91_port->clk); - clk_put(at91_port->clk); - - device_init_wakeup(&pdev->dev, 0); - platform_set_drvdata(pdev, NULL); - - if (port) { - ret = uart_remove_one_port(&at91_uart, port); - kfree(port); - } - - return ret; -} - -static struct platform_driver at91_serial_driver = { - .probe = at91_serial_probe, - .remove = __devexit_p(at91_serial_remove), - .suspend = at91_serial_suspend, - .resume = at91_serial_resume, - .driver = { - .name = "at91_usart", - .owner = THIS_MODULE, - }, -}; - -static int __init at91_serial_init(void) -{ - int ret; - - ret = uart_register_driver(&at91_uart); - if (ret) - return ret; - - ret = platform_driver_register(&at91_serial_driver); - if (ret) - uart_unregister_driver(&at91_uart); - - return ret; -} - -static void __exit at91_serial_exit(void) -{ - platform_driver_unregister(&at91_serial_driver); - uart_unregister_driver(&at91_uart); -} - -module_init(at91_serial_init); -module_exit(at91_serial_exit); - -MODULE_AUTHOR("Rick Bronson"); -MODULE_DESCRIPTION("AT91 generic serial port driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c new file mode 100644 index 000000000000..391a1f4167a4 --- /dev/null +++ b/drivers/serial/atmel_serial.c @@ -0,0 +1,992 @@ +/* + * linux/drivers/char/at91_serial.c + * + * Driver for Atmel AT91 / AT32 Serial ports + * Copyright (C) 2003 Rick Bronson + * + * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/serial.h> +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/sysrq.h> +#include <linux/tty_flip.h> +#include <linux/platform_device.h> + +#include <asm/io.h> + +#include <asm/arch/at91rm9200_pdc.h> +#include <asm/mach/serial_at91.h> +#include <asm/arch/board.h> +#ifdef CONFIG_ARM +#include <asm/arch/system.h> +#include <asm/arch/gpio.h> +#endif + +#include "atmel_serial.h" + +#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/serial_core.h> + +#ifdef CONFIG_SERIAL_ATMEL_TTYAT + +/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we + * should coexist with the 8250 driver, such as if we have an external 16C550 + * UART. */ +#define SERIAL_ATMEL_MAJOR 204 +#define MINOR_START 154 +#define ATMEL_DEVICENAME "ttyAT" + +#else + +/* Use device name ttyS, major 4, minor 64-68. This is the usual serial port + * name, but it is legally reserved for the 8250 driver. */ +#define SERIAL_ATMEL_MAJOR TTY_MAJOR +#define MINOR_START 64 +#define ATMEL_DEVICENAME "ttyS" + +#endif + +#define ATMEL_ISR_PASS_LIMIT 256 + +#define UART_PUT_CR(port,v) writel(v, (port)->membase + ATMEL_US_CR) +#define UART_GET_MR(port) readl((port)->membase + ATMEL_US_MR) +#define UART_PUT_MR(port,v) writel(v, (port)->membase + ATMEL_US_MR) +#define UART_PUT_IER(port,v) writel(v, (port)->membase + ATMEL_US_IER) +#define UART_PUT_IDR(port,v) writel(v, (port)->membase + ATMEL_US_IDR) +#define UART_GET_IMR(port) readl((port)->membase + ATMEL_US_IMR) +#define UART_GET_CSR(port) readl((port)->membase + ATMEL_US_CSR) +#define UART_GET_CHAR(port) readl((port)->membase + ATMEL_US_RHR) +#define UART_PUT_CHAR(port,v) writel(v, (port)->membase + ATMEL_US_THR) +#define UART_GET_BRGR(port) readl((port)->membase + ATMEL_US_BRGR) +#define UART_PUT_BRGR(port,v) writel(v, (port)->membase + ATMEL_US_BRGR) +#define UART_PUT_RTOR(port,v) writel(v, (port)->membase + ATMEL_US_RTOR) + +// #define UART_GET_CR(port) readl((port)->membase + ATMEL_US_CR) // is write-only + + /* PDC registers */ +#define UART_PUT_PTCR(port,v) writel(v, (port)->membase + ATMEL_PDC_PTCR) +#define UART_GET_PTSR(port) readl((port)->membase + ATMEL_PDC_PTSR) + +#define UART_PUT_RPR(port,v) writel(v, (port)->membase + ATMEL_PDC_RPR) +#define UART_GET_RPR(port) readl((port)->membase + ATMEL_PDC_RPR) +#define UART_PUT_RCR(port,v) writel(v, (port)->membase + ATMEL_PDC_RCR) +#define UART_PUT_RNPR(port,v) writel(v, (port)->membase + ATMEL_PDC_RNPR) +#define UART_PUT_RNCR(port,v) writel(v, (port)->membase + ATMEL_PDC_RNCR) + +#define UART_PUT_TPR(port,v) writel(v, (port)->membase + ATMEL_PDC_TPR) +#define UART_PUT_TCR(port,v) writel(v, (port)->membase + ATMEL_PDC_TCR) +//#define UART_PUT_TNPR(port,v) writel(v, (port)->membase + ATMEL_PDC_TNPR) +//#define UART_PUT_TNCR(port,v) writel(v, (port)->membase + ATMEL_PDC_TNCR) + +static int (*atmel_open_hook)(struct uart_port *); +static void (*atmel_close_hook)(struct uart_port *); + +/* + * We wrap our port structure around the generic uart_port. + */ +struct atmel_uart_port { + struct uart_port uart; /* uart */ + struct clk *clk; /* uart clock */ + unsigned short suspended; /* is port suspended? */ +}; + +static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; + +#ifdef SUPPORT_SYSRQ +static struct console atmel_console; +#endif + +/* + * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. + */ +static u_int atmel_tx_empty(struct uart_port *port) +{ + return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0; +} + +/* + * Set state of the modem control output lines + */ +static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) +{ + unsigned int control = 0; + unsigned int mode; + +#ifdef CONFIG_ARM + if (arch_identify() == ARCH_ID_AT91RM9200) { + /* + * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. + * We need to drive the pin manually. + */ + if (port->mapbase == AT91RM9200_BASE_US0) { + if (mctrl & TIOCM_RTS) + at91_set_gpio_value(AT91_PIN_PA21, 0); + else + at91_set_gpio_value(AT91_PIN_PA21, 1); + } + } +#endif + + if (mctrl & TIOCM_RTS) + control |= ATMEL_US_RTSEN; + else + control |= ATMEL_US_RTSDIS; + + if (mctrl & TIOCM_DTR) + control |= ATMEL_US_DTREN; + else + control |= ATMEL_US_DTRDIS; + + UART_PUT_CR(port, control); + + /* Local loopback mode? */ + mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE; + if (mctrl & TIOCM_LOOP) + mode |= ATMEL_US_CHMODE_LOC_LOOP; + else + mode |= ATMEL_US_CHMODE_NORMAL; + UART_PUT_MR(port, mode); +} + +/* + * Get state of the modem control input lines + */ +static u_int atmel_get_mctrl(struct uart_port *port) +{ + unsigned int status, ret = 0; + + status = UART_GET_CSR(port); + + /* + * The control signals are active low. + */ + if (!(status & ATMEL_US_DCD)) + ret |= TIOCM_CD; + if (!(status & ATMEL_US_CTS)) + ret |= TIOCM_CTS; + if (!(status & ATMEL_US_DSR)) + ret |= TIOCM_DSR; + if (!(status & ATMEL_US_RI)) + ret |= TIOCM_RI; + + return ret; +} + +/* + * Stop transmitting. + */ +static void atmel_stop_tx(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + UART_PUT_IDR(port, ATMEL_US_TXRDY); +} + +/* + * Start transmitting. + */ +static void atmel_start_tx(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + UART_PUT_IER(port, ATMEL_US_TXRDY); +} + +/* + * Stop receiving - port is in process of being closed. + */ +static void atmel_stop_rx(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + UART_PUT_IDR(port, ATMEL_US_RXRDY); +} + +/* + * Enable modem status interrupts + */ +static void atmel_enable_ms(struct uart_port *port) +{ + UART_PUT_IER(port, ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC | ATMEL_US_CTSIC); +} + +/* + * Control the transmission of a break signal + */ +static void atmel_break_ctl(struct uart_port *port, int break_state) +{ + if (break_state != 0) + UART_PUT_CR(port, ATMEL_US_STTBRK); /* start break */ + else + UART_PUT_CR(port, ATMEL_US_STPBRK); /* stop break */ +} + +/* + * Characters received (called from interrupt handler) + */ +static void atmel_rx_chars(struct uart_port *port) +{ + struct tty_struct *tty = port->info->tty; + unsigned int status, ch, flg; + + status = UART_GET_CSR(port); + while (status & ATMEL_US_RXRDY) { + ch = UART_GET_CHAR(port); + + port->icount.rx++; + + flg = TTY_NORMAL; + + /* + * note that the error handling code is + * out of the main execution path + */ + if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) { + UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */ + if (status & ATMEL_US_RXBRK) { + status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */ + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } + if (status & ATMEL_US_PARE) + port->icount.parity++; + if (status & ATMEL_US_FRAME) + port->icount.frame++; + if (status & ATMEL_US_OVRE) + port->icount.overrun++; + + status &= port->read_status_mask; + + if (status & ATMEL_US_RXBRK) + flg = TTY_BREAK; + else if (status & ATMEL_US_PARE) + flg = TTY_PARITY; + else if (status & ATMEL_US_FRAME) + flg = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, ch)) + goto ignore_char; + + uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg); + + ignore_char: + status = UART_GET_CSR(port); + } + + tty_flip_buffer_push(tty); +} + +/* + * Transmit characters (called from interrupt handler) + */ +static void atmel_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (port->x_char) { + UART_PUT_CHAR(port, port->x_char); + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + atmel_stop_tx(port); + return; + } + + while (UART_GET_CSR(port) & ATMEL_US_TXRDY) { + UART_PUT_CHAR(port, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (uart_circ_empty(xmit)) + atmel_stop_tx(port); +} + +/* + * Interrupt handler + */ +static irqreturn_t atmel_interrupt(int irq, void *dev_id) +{ + struct uart_port *port = dev_id; + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + unsigned int status, pending, pass_counter = 0; + + status = UART_GET_CSR(port); + pending = status & UART_GET_IMR(port); + while (pending) { + /* Interrupt receive */ + if (pending & ATMEL_US_RXRDY) + atmel_rx_chars(port); + + // TODO: All reads to CSR will clear these interrupts! + if (pending & ATMEL_US_RIIC) port->icount.rng++; + if (pending & ATMEL_US_DSRIC) port->icount.dsr++; + if (pending & ATMEL_US_DCDIC) + uart_handle_dcd_change(port, !(status & ATMEL_US_DCD)); + if (pending & ATMEL_US_CTSIC) + uart_handle_cts_change(port, !(status & ATMEL_US_CTS)); + if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC | ATMEL_US_CTSIC)) + wake_up_interruptible(&port->info->delta_msr_wait); + + /* Interrupt transmit */ + if (pending & ATMEL_US_TXRDY) + atmel_tx_chars(port); + + if (pass_counter++ > ATMEL_ISR_PASS_LIMIT) + break; + + status = UART_GET_CSR(port); + pending = status & UART_GET_IMR(port); + } + return IRQ_HANDLED; +} + +/* + * Perform initialization and enable port for reception + */ +static int atmel_startup(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + int retval; + + /* + * Ensure that no interrupts are enabled otherwise when + * request_irq() is called we could get stuck trying to + * handle an unexpected interrupt + */ + UART_PUT_IDR(port, -1); + + /* + * Allocate the IRQ + */ + retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED, "atmel_serial", port); + if (retval) { + printk("atmel_serial: atmel_startup - Can't get irq\n"); + return retval; + } + + /* + * If there is a specific "open" function (to register + * control line interrupts) + */ + if (atmel_open_hook) { + retval = atmel_open_hook(port); + if (retval) { + free_irq(port->irq, port); + return retval; + } + } + + /* + * Finally, enable the serial port + */ + UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); + UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); /* enable xmit & rcvr */ + + UART_PUT_IER(port, ATMEL_US_RXRDY); /* enable receive only */ + + return 0; +} + +/* + * Disable the port + */ +static void atmel_shutdown(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + /* + * Disable all interrupts, port and break condition. + */ + UART_PUT_CR(port, ATMEL_US_RSTSTA); + UART_PUT_IDR(port, -1); + + /* + * Free the interrupt + */ + free_irq(port->irq, port); + + /* + * If there is a specific "close" function (to unregister + * control line interrupts) + */ + if (atmel_close_hook) + atmel_close_hook(port); +} + +/* + * Power / Clock management. + */ +static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) +{ + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + switch (state) { + case 0: + /* + * Enable the peripheral clock for this serial port. + * This is called on uart_open() or a resume event. + */ + clk_enable(atmel_port->clk); + break; + case 3: + /* + * Disable the peripheral clock for this serial port. + * This is called on uart_close() or a suspend event. + */ + clk_disable(atmel_port->clk); + break; + default: + printk(KERN_ERR "atmel_serial: unknown pm %d\n", state); + } +} + +/* + * Change the port parameters + */ +static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) +{ + unsigned long flags; + unsigned int mode, imr, quot, baud; + + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = uart_get_divisor(port, baud); + + /* Get current mode register */ + mode = UART_GET_MR(port) & ~(ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR); + + /* byte size */ + switch (termios->c_cflag & CSIZE) { + case CS5: + mode |= ATMEL_US_CHRL_5; + break; + case CS6: + mode |= ATMEL_US_CHRL_6; + break; + case CS7: + mode |= ATMEL_US_CHRL_7; + break; + default: + mode |= ATMEL_US_CHRL_8; + break; + } + + /* stop bits */ + if (termios->c_cflag & CSTOPB) + mode |= ATMEL_US_NBSTOP_2; + + /* parity */ + if (termios->c_cflag & PARENB) { + if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ + if (termios->c_cflag & PARODD) + mode |= ATMEL_US_PAR_MARK; + else + mode |= ATMEL_US_PAR_SPACE; + } + else if (termios->c_cflag & PARODD) + mode |= ATMEL_US_PAR_ODD; + else + mode |= ATMEL_US_PAR_EVEN; + } + else + mode |= ATMEL_US_PAR_NONE; + + spin_lock_irqsave(&port->lock, flags); + + port->read_status_mask = ATMEL_US_OVRE; + if (termios->c_iflag & INPCK) + port->read_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE); + if (termios->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= ATMEL_US_RXBRK; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE); + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= ATMEL_US_RXBRK; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= ATMEL_US_OVRE; + } + + // TODO: Ignore all characters if CREAD is set. + + /* update the per-port timeout */ + uart_update_timeout(port, termios->c_cflag, baud); + + /* disable interrupts and drain transmitter */ + imr = UART_GET_IMR(port); /* get interrupt mask */ + UART_PUT_IDR(port, -1); /* disable all interrupts */ + while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY)) { barrier(); } + + /* disable receiver and transmitter */ + UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); + + /* set the parity, stop bits and data size */ + UART_PUT_MR(port, mode); + + /* set the baud rate */ + UART_PUT_BRGR(port, quot); + UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); + UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); + + /* restore interrupts */ + UART_PUT_IER(port, imr); + + /* CTS flow-control and modem-status interrupts */ + if (UART_ENABLE_MS(port, termios->c_cflag)) + port->ops->enable_ms(port); + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* + * Return string describing the specified port + */ +static const char *atmel_type(struct uart_port *port) +{ + return (port->type == PORT_ATMEL) ? "ATMEL_SERIAL" : NULL; +} + +/* + * Release the memory region(s) being used by 'port'. + */ +static void atmel_release_port(struct uart_port *port) +{ + struct platform_device *pdev = to_platform_device(port->dev); + int size = pdev->resource[0].end - pdev->resource[0].start + 1; + + release_mem_region(port->mapbase, size); + + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; + } +} + +/* + * Request the memory region(s) being used by 'port'. + */ +static int atmel_request_port(struct uart_port *port) +{ + struct platform_device *pdev = to_platform_device(port->dev); + int size = pdev->resource[0].end - pdev->resource[0].start + 1; + + if (!request_mem_region(port->mapbase, size, "atmel_serial")) + return -EBUSY; + + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap(port->mapbase, size); + if (port->membase == NULL) { + release_mem_region(port->mapbase, size); + return -ENOMEM; + } + } + + return 0; +} + +/* + * Configure/autoconfigure the port. + */ +static void atmel_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + port->type = PORT_ATMEL; + atmel_request_port(port); + } +} + +/* + * Verify the new serial_struct (for TIOCSSERIAL). + */ +static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_ATMEL) + ret = -EINVAL; + if (port->irq != ser->irq) + ret = -EINVAL; + if (ser->io_type != SERIAL_IO_MEM) + ret = -EINVAL; + if (port->uartclk / 16 != ser->baud_base) + ret = -EINVAL; + if ((void *)port->mapbase != ser->iomem_base) + ret = -EINVAL; + if (port->iobase != ser->port) + ret = -EINVAL; + if (ser->hub6 != 0) + ret = -EINVAL; + return ret; +} + +static struct uart_ops atmel_pops = { + .tx_empty = atmel_tx_empty, + .set_mctrl = atmel_set_mctrl, + .get_mctrl = atmel_get_mctrl, + .stop_tx = atmel_stop_tx, + .start_tx = atmel_start_tx, + .stop_rx = atmel_stop_rx, + .enable_ms = atmel_enable_ms, + .break_ctl = atmel_break_ctl, + .startup = atmel_startup, + .shutdown = atmel_shutdown, + .set_termios = atmel_set_termios, + .type = atmel_type, + .release_port = atmel_release_port, + .request_port = atmel_request_port, + .config_port = atmel_config_port, + .verify_port = atmel_verify_port, + .pm = atmel_serial_pm, +}; + +/* + * Configure the port from the platform device resource info. + */ +static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct platform_device *pdev) +{ + struct uart_port *port = &atmel_port->uart; + struct atmel_uart_data *data = pdev->dev.platform_data; + + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &atmel_pops; + port->fifosize = 1; + port->line = pdev->id; + port->dev = &pdev->dev; + + port->mapbase = pdev->resource[0].start; + port->irq = pdev->resource[1].start; + + if (data->regs) + /* Already mapped by setup code */ + port->membase = data->regs; + else { + port->flags |= UPF_IOREMAP; + port->membase = NULL; + } + + if (!atmel_port->clk) { /* for console, the clock could already be configured */ + atmel_port->clk = clk_get(&pdev->dev, "usart"); + clk_enable(atmel_port->clk); + port->uartclk = clk_get_rate(atmel_port->clk); + } +} + +/* + * Register board-specific modem-control line handlers. + */ +void __init atmel_register_uart_fns(struct atmel_port_fns *fns) +{ + if (fns->enable_ms) + atmel_pops.enable_ms = fns->enable_ms; + if (fns->get_mctrl) + atmel_pops.get_mctrl = fns->get_mctrl; + if (fns->set_mctrl) + atmel_pops.set_mctrl = fns->set_mctrl; + atmel_open_hook = fns->open; + atmel_close_hook = fns->close; + atmel_pops.pm = fns->pm; + atmel_pops.set_wake = fns->set_wake; +} + + +#ifdef CONFIG_SERIAL_ATMEL_CONSOLE +static void atmel_console_putchar(struct uart_port *port, int ch) +{ + while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY)) + barrier(); + UART_PUT_CHAR(port, ch); +} + +/* + * Interrupts are disabled on entering + */ +static void atmel_console_write(struct console *co, const char *s, u_int count) +{ + struct uart_port *port = &atmel_ports[co->index].uart; + unsigned int status, imr; + + /* + * First, save IMR and then disable interrupts + */ + imr = UART_GET_IMR(port); /* get interrupt mask */ + UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY); + + uart_console_write(port, s, count, atmel_console_putchar); + + /* + * Finally, wait for transmitter to become empty + * and restore IMR + */ + do { + status = UART_GET_CSR(port); + } while (!(status & ATMEL_US_TXRDY)); + UART_PUT_IER(port, imr); /* set interrupts back the way they were */ +} + +/* + * If the port was already initialised (eg, by a boot loader), try to determine + * the current setup. + */ +static void __init atmel_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) +{ + unsigned int mr, quot; + +// TODO: CR is a write-only register +// unsigned int cr; +// +// cr = UART_GET_CR(port) & (ATMEL_US_RXEN | ATMEL_US_TXEN); +// if (cr == (ATMEL_US_RXEN | ATMEL_US_TXEN)) { +// /* ok, the port was enabled */ +// } + + mr = UART_GET_MR(port) & ATMEL_US_CHRL; + if (mr == ATMEL_US_CHRL_8) + *bits = 8; + else + *bits = 7; + + mr = UART_GET_MR(port) & ATMEL_US_PAR; + if (mr == ATMEL_US_PAR_EVEN) + *parity = 'e'; + else if (mr == ATMEL_US_PAR_ODD) + *parity = 'o'; + + /* + * The serial core only rounds down when matching this to a + * supported baud rate. Make sure we don't end up slightly + * lower than one of those, as it would make us fall through + * to a much lower baud rate than we really want. + */ + quot = UART_GET_BRGR(port); + *baud = port->uartclk / (16 * (quot - 1)); +} + +static int __init atmel_console_setup(struct console *co, char *options) +{ + struct uart_port *port = &atmel_ports[co->index].uart; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (port->membase == 0) /* Port not initialized yet - delay setup */ + return -ENODEV; + + UART_PUT_IDR(port, -1); /* disable interrupts */ + UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); + UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + atmel_console_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct uart_driver atmel_uart; + +static struct console atmel_console = { + .name = ATMEL_DEVICENAME, + .write = atmel_console_write, + .device = uart_console_device, + .setup = atmel_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &atmel_uart, +}; + +#define ATMEL_CONSOLE_DEVICE &atmel_console + +/* + * Early console initialization (before VM subsystem initialized). + */ +static int __init atmel_console_init(void) +{ + if (atmel_default_console_device) { + add_preferred_console(ATMEL_DEVICENAME, atmel_default_console_device->id, NULL); + atmel_init_port(&(atmel_ports[atmel_default_console_device->id]), atmel_default_console_device); + register_console(&atmel_console); + } + + return 0; +} +console_initcall(atmel_console_init); + +/* + * Late console initialization. + */ +static int __init atmel_late_console_init(void) +{ + if (atmel_default_console_device && !(atmel_console.flags & CON_ENABLED)) + register_console(&atmel_console); + + return 0; +} +core_initcall(atmel_late_console_init); + +#else +#define ATMEL_CONSOLE_DEVICE NULL +#endif + +static struct uart_driver atmel_uart = { + .owner = THIS_MODULE, + .driver_name = "atmel_serial", + .dev_name = ATMEL_DEVICENAME, + .major = SERIAL_ATMEL_MAJOR, + .minor = MINOR_START, + .nr = ATMEL_MAX_UART, + .cons = ATMEL_CONSOLE_DEVICE, +}; + +#ifdef CONFIG_PM +static int atmel_serial_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock()) + enable_irq_wake(port->irq); + else { + disable_irq_wake(port->irq); + uart_suspend_port(&atmel_uart, port); + atmel_port->suspended = 1; + } + + return 0; +} + +static int atmel_serial_resume(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + + if (atmel_port->suspended) { + uart_resume_port(&atmel_uart, port); + atmel_port->suspended = 0; + } + + return 0; +} +#else +#define atmel_serial_suspend NULL +#define atmel_serial_resume NULL +#endif + +static int __devinit atmel_serial_probe(struct platform_device *pdev) +{ + struct atmel_uart_port *port; + int ret; + + port = &atmel_ports[pdev->id]; + atmel_init_port(port, pdev); + + ret = uart_add_one_port(&atmel_uart, &port->uart); + if (!ret) { + device_init_wakeup(&pdev->dev, 1); + platform_set_drvdata(pdev, port); + } + + return ret; +} + +static int __devexit atmel_serial_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; + int ret = 0; + + clk_disable(atmel_port->clk); + clk_put(atmel_port->clk); + + device_init_wakeup(&pdev->dev, 0); + platform_set_drvdata(pdev, NULL); + + if (port) { + ret = uart_remove_one_port(&atmel_uart, port); + kfree(port); + } + + return ret; +} + +static struct platform_driver atmel_serial_driver = { + .probe = atmel_serial_probe, + .remove = __devexit_p(atmel_serial_remove), + .suspend = atmel_serial_suspend, + .resume = atmel_serial_resume, + .driver = { + .name = "atmel_usart", + .owner = THIS_MODULE, + }, +}; + +static int __init atmel_serial_init(void) +{ + int ret; + + ret = uart_register_driver(&atmel_uart); + if (ret) + return ret; + + ret = platform_driver_register(&atmel_serial_driver); + if (ret) + uart_unregister_driver(&atmel_uart); + + return ret; +} + +static void __exit atmel_serial_exit(void) +{ + platform_driver_unregister(&atmel_serial_driver); + uart_unregister_driver(&atmel_uart); +} + +module_init(atmel_serial_init); +module_exit(atmel_serial_exit); + +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/atmel_serial.h b/drivers/serial/atmel_serial.h new file mode 100644 index 000000000000..eced2ad1a8d9 --- /dev/null +++ b/drivers/serial/atmel_serial.h @@ -0,0 +1,123 @@ +/* + * drivers/serial/atmel_serial.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * USART registers. + * Based on AT91RM9200 datasheet revision E. + * + * 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. + */ + +#ifndef ATMEL_SERIAL_H +#define ATMEL_SERIAL_H + +#define ATMEL_US_CR 0x00 /* Control Register */ +#define ATMEL_US_RSTRX (1 << 2) /* Reset Receiver */ +#define ATMEL_US_RSTTX (1 << 3) /* Reset Transmitter */ +#define ATMEL_US_RXEN (1 << 4) /* Receiver Enable */ +#define ATMEL_US_RXDIS (1 << 5) /* Receiver Disable */ +#define ATMEL_US_TXEN (1 << 6) /* Transmitter Enable */ +#define ATMEL_US_TXDIS (1 << 7) /* Transmitter Disable */ +#define ATMEL_US_RSTSTA (1 << 8) /* Reset Status Bits */ +#define ATMEL_US_STTBRK (1 << 9) /* Start Break */ +#define ATMEL_US_STPBRK (1 << 10) /* Stop Break */ +#define ATMEL_US_STTTO (1 << 11) /* Start Time-out */ +#define ATMEL_US_SENDA (1 << 12) /* Send Address */ +#define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */ +#define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */ +#define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */ +#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable */ +#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable */ +#define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */ +#define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */ + +#define ATMEL_US_MR 0x04 /* Mode Register */ +#define ATMEL_US_USMODE (0xf << 0) /* Mode of the USART */ +#define ATMEL_US_USMODE_NORMAL 0 +#define ATMEL_US_USMODE_RS485 1 +#define ATMEL_US_USMODE_HWHS 2 +#define ATMEL_US_USMODE_MODEM 3 +#define ATMEL_US_USMODE_ISO7816_T0 4 +#define ATMEL_US_USMODE_ISO7816_T1 6 +#define ATMEL_US_USMODE_IRDA 8 +#define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */ +#define ATMEL_US_CHRL (3 << 6) /* Character Length */ +#define ATMEL_US_CHRL_5 (0 << 6) +#define ATMEL_US_CHRL_6 (1 << 6) +#define ATMEL_US_CHRL_7 (2 << 6) +#define ATMEL_US_CHRL_8 (3 << 6) +#define ATMEL_US_SYNC (1 << 8) /* Synchronous Mode Select */ +#define ATMEL_US_PAR (7 << 9) /* Parity Type */ +#define ATMEL_US_PAR_EVEN (0 << 9) +#define ATMEL_US_PAR_ODD (1 << 9) +#define ATMEL_US_PAR_SPACE (2 << 9) +#define ATMEL_US_PAR_MARK (3 << 9) +#define ATMEL_US_PAR_NONE (4 << 9) +#define ATMEL_US_PAR_MULTI_DROP (6 << 9) +#define ATMEL_US_NBSTOP (3 << 12) /* Number of Stop Bits */ +#define ATMEL_US_NBSTOP_1 (0 << 12) +#define ATMEL_US_NBSTOP_1_5 (1 << 12) +#define ATMEL_US_NBSTOP_2 (2 << 12) +#define ATMEL_US_CHMODE (3 << 14) /* Channel Mode */ +#define ATMEL_US_CHMODE_NORMAL (0 << 14) +#define ATMEL_US_CHMODE_ECHO (1 << 14) +#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14) +#define ATMEL_US_CHMODE_REM_LOOP (3 << 14) +#define ATMEL_US_MSBF (1 << 16) /* Bit Order */ +#define ATMEL_US_MODE9 (1 << 17) /* 9-bit Character Length */ +#define ATMEL_US_CLKO (1 << 18) /* Clock Output Select */ +#define ATMEL_US_OVER (1 << 19) /* Oversampling Mode */ +#define ATMEL_US_INACK (1 << 20) /* Inhibit Non Acknowledge */ +#define ATMEL_US_DSNACK (1 << 21) /* Disable Successive NACK */ +#define ATMEL_US_MAX_ITER (7 << 24) /* Max Iterations */ +#define ATMEL_US_FILTER (1 << 28) /* Infrared Receive Line Filter */ + +#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */ +#define ATMEL_US_RXRDY (1 << 0) /* Receiver Ready */ +#define ATMEL_US_TXRDY (1 << 1) /* Transmitter Ready */ +#define ATMEL_US_RXBRK (1 << 2) /* Break Received / End of Break */ +#define ATMEL_US_ENDRX (1 << 3) /* End of Receiver Transfer */ +#define ATMEL_US_ENDTX (1 << 4) /* End of Transmitter Transfer */ +#define ATMEL_US_OVRE (1 << 5) /* Overrun Error */ +#define ATMEL_US_FRAME (1 << 6) /* Framing Error */ +#define ATMEL_US_PARE (1 << 7) /* Parity Error */ +#define ATMEL_US_TIMEOUT (1 << 8) /* Receiver Time-out */ +#define ATMEL_US_TXEMPTY (1 << 9) /* Transmitter Empty */ +#define ATMEL_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */ +#define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */ +#define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */ +#define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */ +#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change */ +#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change */ +#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change */ +#define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */ +#define ATMEL_US_RI (1 << 20) /* RI */ +#define ATMEL_US_DSR (1 << 21) /* DSR */ +#define ATMEL_US_DCD (1 << 22) /* DCD */ +#define ATMEL_US_CTS (1 << 23) /* CTS */ + +#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */ +#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */ +#define ATMEL_US_CSR 0x14 /* Channel Status Register */ +#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */ +#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */ + +#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */ +#define ATMEL_US_CD (0xffff << 0) /* Clock Divider */ + +#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */ +#define ATMEL_US_TO (0xffff << 0) /* Time-out Value */ + +#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */ +#define ATMEL_US_TG (0xff << 0) /* Timeguard Value */ + +#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */ +#define ATMEL_US_NER 0x44 /* Number of Errors Register */ +#define ATMEL_US_IF 0x4c /* IrDA Filter Register */ + +#endif diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index f27d852ce50d..598012714882 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -93,7 +93,7 @@ static void clps711xuart_enable_ms(struct uart_port *port) { } -static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id) { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->tty; @@ -131,7 +131,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re #endif } - if (uart_handle_sysrq_char(port, ch, regs)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; /* @@ -147,7 +147,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re return IRQ_HANDLED; } -static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id) { struct uart_port *port = dev_id; struct circ_buf *xmit = &port->info->xmit; diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 3b35cb779539..a8f894c78194 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -16,7 +16,6 @@ #ifndef CPM_UART_H #define CPM_UART_H -#include <linux/config.h> #include <linux/platform_device.h> #include <linux/fs_uart_pd.h> diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index a0d6136deb9b..0abb544ae63d 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -248,7 +248,7 @@ static void cpm_uart_break_ctl(struct uart_port *port, int break_state) /* * Transmit characters, refill buffer descriptor, if possible */ -static void cpm_uart_int_tx(struct uart_port *port, struct pt_regs *regs) +static void cpm_uart_int_tx(struct uart_port *port) { pr_debug("CPM uart[%d]:TX INT\n", port->line); @@ -258,7 +258,7 @@ static void cpm_uart_int_tx(struct uart_port *port, struct pt_regs *regs) /* * Receive characters */ -static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) +static void cpm_uart_int_rx(struct uart_port *port) { int i; unsigned char ch, *cp; @@ -304,7 +304,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) if (status & (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV)) goto handle_error; - if (uart_handle_sysrq_char(port, ch, regs)) + if (uart_handle_sysrq_char(port, ch)) continue; error_return: @@ -373,7 +373,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) /* * Asynchron mode interrupt handler */ -static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) +static irqreturn_t cpm_uart_int(int irq, void *data) { u8 events; struct uart_port *port = (struct uart_port *)data; @@ -389,18 +389,18 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) if (events & SMCM_BRKE) uart_handle_break(port); if (events & SMCM_RX) - cpm_uart_int_rx(port, regs); + cpm_uart_int_rx(port); if (events & SMCM_TX) - cpm_uart_int_tx(port, regs); + cpm_uart_int_tx(port); } else { events = sccp->scc_scce; sccp->scc_scce = events; if (events & UART_SCCM_BRKE) uart_handle_break(port); if (events & UART_SCCM_RX) - cpm_uart_int_rx(port, regs); + cpm_uart_int_rx(port); if (events & UART_SCCM_TX) - cpm_uart_int_tx(port, regs); + cpm_uart_int_tx(port); } return (events) ? IRQ_HANDLED : IRQ_NONE; } diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 9851d9eff022..7a24e53546c7 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -2346,7 +2346,7 @@ start_receive(struct e100_serial *info) */ static irqreturn_t -tr_interrupt(int irq, void *dev_id, struct pt_regs * regs) +tr_interrupt(int irq, void *dev_id) { struct e100_serial *info; unsigned long ireg; @@ -2395,7 +2395,7 @@ tr_interrupt(int irq, void *dev_id, struct pt_regs * regs) /* dma input channel interrupt handler */ static irqreturn_t -rec_interrupt(int irq, void *dev_id, struct pt_regs * regs) +rec_interrupt(int irq, void *dev_id) { struct e100_serial *info; unsigned long ireg; @@ -3054,7 +3054,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) * ser_int duration: just sending: 8-15 us normally, up to 73 us */ static irqreturn_t -ser_interrupt(int irq, void *dev_id, struct pt_regs *regs) +ser_interrupt(int irq, void *dev_id) { static volatile int tx_started = 0; struct e100_serial *info; diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 8a98aae80e22..53662b33b841 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -339,7 +339,7 @@ static inline void check_modem_status(struct dz_port *dport) * It deals with the multiple ports. * ------------------------------------------------------------ */ -static irqreturn_t dz_interrupt(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t dz_interrupt(int irq, void *dev) { struct dz_port *dport; unsigned short status; diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index a3c00a252149..8aa0f641866b 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -844,8 +844,7 @@ static void process_interrupt(u16 port_int_reg, spin_unlock(&icom_port->uart_port.lock); } -static irqreturn_t icom_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t icom_interrupt(int irq, void *dev_id) { void __iomem * int_reg; u32 adapter_interrupts; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4a142d6b8f38..ee5c782597dd 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -182,7 +182,7 @@ static void imx_start_tx(struct uart_port *port) imx_transmit_buffer(sport); } -static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = (struct imx_port *)dev_id; unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS; @@ -198,7 +198,7 @@ static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t imx_txint(int irq, void *dev_id) { struct imx_port *sport = (struct imx_port *)dev_id; struct circ_buf *xmit = &sport->port.info->xmit; @@ -227,7 +227,7 @@ out: return IRQ_HANDLED; } -static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t imx_rxint(int irq, void *dev_id) { struct imx_port *sport = dev_id; unsigned int rx,flg,ignored = 0; @@ -248,7 +248,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs) } if (uart_handle_sysrq_char - (&sport->port, (unsigned char)rx, regs)) + (&sport->port, (unsigned char)rx)) goto ignore_char; if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 8097cd91f16b..2308d26c8629 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -1428,13 +1428,12 @@ static int receive_chars(struct uart_port *the_port) * @is : submodule * @idd: driver data * @pending: interrupts to handle - * @regs: pt_regs */ static int inline ioc3uart_intr_one(struct ioc3_submodule *is, struct ioc3_driver_data *idd, - unsigned int pending, struct pt_regs *regs) + unsigned int pending) { int port_num = GET_PORT_FROM_SIO_IR(pending); struct port_hooks *hooks; @@ -1628,13 +1627,12 @@ ioc3uart_intr_one(struct ioc3_submodule *is, * @is : submodule * @idd: driver data * @pending: interrupts to handle - * @regs: pt_regs * */ static int ioc3uart_intr(struct ioc3_submodule *is, struct ioc3_driver_data *idd, - unsigned int pending, struct pt_regs *regs) + unsigned int pending) { int ret = 0; @@ -1644,9 +1642,9 @@ static int ioc3uart_intr(struct ioc3_submodule *is, */ if (pending & SIO_IR_SA) - ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs); + ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA); if (pending & SIO_IR_SB) - ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs); + ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB); return ret; } diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 5ec4716c99bf..ff4fa25f9fd1 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -987,10 +987,9 @@ intr_connect(struct ioc4_soft *soft, int type, * ioc4_intr - Top level IOC4 interrupt handler. * @irq: irq value * @arg: handler arg - * @regs: registers */ -static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) +static irqreturn_t ioc4_intr(int irq, void *arg) { struct ioc4_soft *soft; uint32_t this_ir, this_mir; @@ -2936,7 +2935,7 @@ static void __devexit ioc4_serial_exit(void) uart_unregister_driver(&ioc4_uart_rs422); } -module_init(ioc4_serial_init); +late_initcall(ioc4_serial_init); /* Call only after tty init is done */ module_exit(ioc4_serial_exit); MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index dbf13c03a1bb..dca6c1bde8f9 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -252,8 +252,7 @@ static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up, } static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, - struct zilog_channel *channel, - struct pt_regs *regs) + struct zilog_channel *channel) { struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ @@ -319,7 +318,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, else if (r1 & CRC_ERR) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) goto next_char; if (up->port.ignore_status_mask == 0xff || @@ -339,8 +338,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, } static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, - struct zilog_channel *channel, - struct pt_regs *regs) + struct zilog_channel *channel) { unsigned char status; @@ -443,7 +441,7 @@ ack_tx_int: ZS_WSYNC(channel); } -static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) { struct uart_ip22zilog_port *up = dev_id; @@ -462,9 +460,9 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *re ZS_WSYNC(channel); if (r3 & CHARxIP) - ip22zilog_receive_chars(up, channel, regs); + ip22zilog_receive_chars(up, channel); if (r3 & CHAEXT) - ip22zilog_status_handle(up, channel, regs); + ip22zilog_status_handle(up, channel); if (r3 & CHATxIP) ip22zilog_transmit_chars(up, channel); } @@ -481,9 +479,9 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *re ZS_WSYNC(channel); if (r3 & CHBRxIP) - ip22zilog_receive_chars(up, channel, regs); + ip22zilog_receive_chars(up, channel); if (r3 & CHBEXT) - ip22zilog_status_handle(up, channel, regs); + ip22zilog_status_handle(up, channel); if (r3 & CHBTxIP) ip22zilog_transmit_chars(up, channel); } diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 043f50b1d10c..12c934a1f274 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -99,7 +99,7 @@ struct jsm_channel; * Per board operations structure * ************************************************************************/ struct board_ops { - irqreturn_t (*intr) (int irq, void *voidbrd, struct pt_regs *regs); + irq_handler_t intr; void (*uart_init) (struct jsm_channel *ch); void (*uart_off) (struct jsm_channel *ch); void (*param) (struct jsm_channel *ch); diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index a5fc589d6ef5..8be8da37f629 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -1114,9 +1114,9 @@ static void neo_param(struct jsm_channel *ch) * * Neo specific interrupt handler. */ -static irqreturn_t neo_intr(int irq, void *voidbrd, struct pt_regs *regs) +static irqreturn_t neo_intr(int irq, void *voidbrd) { - struct jsm_board *brd = (struct jsm_board *) voidbrd; + struct jsm_board *brd = voidbrd; struct jsm_channel *ch; int port = 0; int type = 0; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 28c9ce6f0bdc..7656a35f5e2f 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -323,8 +323,7 @@ static void m32r_sio_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static void receive_chars(struct uart_sio_port *up, int *status, - struct pt_regs *regs) +static void receive_chars(struct uart_sio_port *up, int *status) { struct tty_struct *tty = up->port.info->tty; unsigned char ch; @@ -378,7 +377,7 @@ static void receive_chars(struct uart_sio_port *up, int *status, else if (*status & UART_LSR_FE) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; if ((*status & up->port.ignore_status_mask) == 0) tty_insert_flip_char(tty, ch, flag); @@ -439,12 +438,12 @@ static void transmit_chars(struct uart_sio_port *up) * This handles the interrupt from one port. */ static inline void m32r_sio_handle_port(struct uart_sio_port *up, - unsigned int status, struct pt_regs *regs) + unsigned int status) { DEBUG_INTR("status = %x...", status); if (status & 0x04) - receive_chars(up, &status, regs); + receive_chars(up, &status); if (status & 0x01) transmit_chars(up); } @@ -463,8 +462,7 @@ static inline void m32r_sio_handle_port(struct uart_sio_port *up, * This means we need to loop through all ports. checking that they * don't have an interrupt pending. */ -static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) { struct irq_info *i = dev_id; struct list_head *l, *end = NULL; @@ -492,7 +490,7 @@ static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id, sts = sio_in(up, SIOSTS); if (sts & 0x5) { spin_lock(&up->port.lock); - m32r_sio_handle_port(up, sts, regs); + m32r_sio_handle_port(up, sts); spin_unlock(&up->port.lock); end = NULL; @@ -592,7 +590,7 @@ static void m32r_sio_timeout(unsigned long data) sts = sio_in(up, SIOSTS); if (sts & 0x5) { spin_lock(&up->port.lock); - m32r_sio_handle_port(up, sts, NULL); + m32r_sio_handle_port(up, sts); spin_unlock(&up->port.lock); } diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 00d7859c167e..aee1b31f1a1c 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -385,7 +385,7 @@ static inline void transmit_chars(struct mcf_serial *info) /* * This is the serial driver's generic interrupt routine */ -irqreturn_t mcfrs_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t mcfrs_interrupt(int irq, void *dev_id) { struct mcf_serial *info; unsigned char isr; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index dbad0e31e005..4f80c5b4a753 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -85,7 +85,7 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM]; /* Forward declaration of the interruption handling routine */ -static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id,struct pt_regs *regs); +static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id); /* Simple macro to test if a port is console or not. This one is taken @@ -410,7 +410,7 @@ static struct uart_ops mpc52xx_uart_ops = { /* ======================================================================== */ static inline int -mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs) +mpc52xx_uart_int_rx_chars(struct uart_port *port) { struct tty_struct *tty = port->info->tty; unsigned char ch, flag; @@ -425,7 +425,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs) /* Handle sysreq char */ #ifdef SUPPORT_SYSRQ - if (uart_handle_sysrq_char(port, ch, regs)) { + if (uart_handle_sysrq_char(port, ch)) { port->sysrq = 0; continue; } @@ -510,21 +510,13 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) } static irqreturn_t -mpc52xx_uart_int(int irq, void *dev_id, struct pt_regs *regs) +mpc52xx_uart_int(int irq, void *dev_id) { - struct uart_port *port = (struct uart_port *) dev_id; + struct uart_port *port = dev_id; unsigned long pass = ISR_PASS_LIMIT; unsigned int keepgoing; unsigned short status; - if ( irq != port->irq ) { - printk( KERN_WARNING - "mpc52xx_uart_int : " \ - "Received wrong int %d. Waiting for %d\n", - irq, port->irq); - return IRQ_NONE; - } - spin_lock(&port->lock); /* While we have stuff to do, we continue */ @@ -539,7 +531,7 @@ mpc52xx_uart_int(int irq, void *dev_id, struct pt_regs *regs) /* Do we need to receive chars ? */ /* For this RX interrupts must be on and some chars waiting */ if ( status & MPC52xx_PSC_IMR_RXRDY ) - keepgoing |= mpc52xx_uart_int_rx_chars(port, regs); + keepgoing |= mpc52xx_uart_int_rx_chars(port); /* Do we need to send chars ? */ /* For this, TX must be ready and TX interrupt enabled */ diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 704243c9f78a..8eea69f29989 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -992,7 +992,7 @@ mpsc_make_ready(struct mpsc_port_info *pi) */ static inline int -mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs) +mpsc_rx_intr(struct mpsc_port_info *pi) { struct mpsc_rx_desc *rxre; struct tty_struct *tty = pi->port.info->tty; @@ -1072,7 +1072,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs) flag = TTY_PARITY; } - if (uart_handle_sysrq_char(&pi->port, *bp, regs)) { + if (uart_handle_sysrq_char(&pi->port, *bp)) { bp++; bytes_in--; goto next_frame; @@ -1257,7 +1257,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) * handling those descriptors, we restart the Rx/Tx engines if they're stopped. */ static irqreturn_t -mpsc_sdma_intr(int irq, void *dev_id, struct pt_regs *regs) +mpsc_sdma_intr(int irq, void *dev_id) { struct mpsc_port_info *pi = dev_id; ulong iflags; @@ -1267,7 +1267,7 @@ mpsc_sdma_intr(int irq, void *dev_id, struct pt_regs *regs) spin_lock_irqsave(&pi->port.lock, iflags); mpsc_sdma_intr_ack(pi); - if (mpsc_rx_intr(pi, regs)) + if (mpsc_rx_intr(pi)) rc = IRQ_HANDLED; if (mpsc_tx_intr(pi)) rc = IRQ_HANDLED; diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index aa819d3f8ee5..8ad1b8c5ec5d 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -230,7 +230,7 @@ static void mux_read(struct uart_port *port) continue; } - if (uart_handle_sysrq_char(port, data & 0xffu, NULL)) + if (uart_handle_sysrq_char(port, data & 0xffu)) continue; tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL); diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index c1adc9e4b239..062bad457b1a 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -17,8 +17,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/config.h> - #if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif @@ -202,7 +200,7 @@ static void netx_txint(struct uart_port *port) uart_write_wakeup(port); } -static void netx_rxint(struct uart_port *port, struct pt_regs *regs) +static void netx_rxint(struct uart_port *port) { unsigned char rx, flg, status; struct tty_struct *tty = port->info->tty; @@ -237,7 +235,7 @@ static void netx_rxint(struct uart_port *port, struct pt_regs *regs) flg = TTY_FRAME; } - if (uart_handle_sysrq_char(port, rx, regs)) + if (uart_handle_sysrq_char(port, rx)) continue; uart_insert_char(port, status, SR_OE, rx, flg); @@ -247,9 +245,9 @@ static void netx_rxint(struct uart_port *port, struct pt_regs *regs) return; } -static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t netx_int(int irq, void *dev_id) { - struct uart_port *port = (struct uart_port *)dev_id; + struct uart_port *port = dev_id; unsigned long flags; unsigned char status; @@ -258,7 +256,7 @@ static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs) status = readl(port->membase + UART_IIR) & IIR_MASK; while (status) { if (status & IIR_RIS) - netx_rxint(port, regs); + netx_rxint(port); if (status & IIR_TIS) netx_txint(port); if (status & IIR_MIS) { diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index a3b99caf80e6..bf9809ed9c0b 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -204,8 +204,7 @@ static void pmz_maybe_update_regs(struct uart_pmac_port *uap) } } -static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, - struct pt_regs *regs) +static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) { struct tty_struct *tty = NULL; unsigned char ch, r1, drop, error, flag; @@ -267,7 +266,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, if (uap->port.sysrq) { int swallow; spin_unlock(&uap->port.lock); - swallow = uart_handle_sysrq_char(&uap->port, ch, regs); + swallow = uart_handle_sysrq_char(&uap->port, ch); spin_lock(&uap->port.lock); if (swallow) goto next_char; @@ -335,7 +334,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, return tty; } -static void pmz_status_handle(struct uart_pmac_port *uap, struct pt_regs *regs) +static void pmz_status_handle(struct uart_pmac_port *uap) { unsigned char status; @@ -438,7 +437,7 @@ ack_tx_int: } /* Hrm... we register that twice, fixme later.... */ -static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pmz_interrupt(int irq, void *dev_id) { struct uart_pmac_port *uap = dev_id; struct uart_pmac_port *uap_a; @@ -462,9 +461,9 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_zsreg(uap_a, R0, RES_H_IUS); zssync(uap_a); if (r3 & CHAEXT) - pmz_status_handle(uap_a, regs); + pmz_status_handle(uap_a); if (r3 & CHARxIP) - tty = pmz_receive_chars(uap_a, regs); + tty = pmz_receive_chars(uap_a); if (r3 & CHATxIP) pmz_transmit_chars(uap_a); rc = IRQ_HANDLED; @@ -482,9 +481,9 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_zsreg(uap_b, R0, RES_H_IUS); zssync(uap_b); if (r3 & CHBEXT) - pmz_status_handle(uap_b, regs); + pmz_status_handle(uap_b); if (r3 & CHBRxIP) - tty = pmz_receive_chars(uap_b, regs); + tty = pmz_receive_chars(uap_b); if (r3 & CHBTxIP) pmz_transmit_chars(uap_b); rc = IRQ_HANDLED; diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index a720953a404e..415fe9633a9b 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -98,8 +98,7 @@ static void serial_pxa_stop_rx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static inline void -receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) +static inline void receive_chars(struct uart_pxa_port *up, int *status) { struct tty_struct *tty = up->port.info->tty; unsigned int ch, flag; @@ -153,7 +152,7 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); @@ -231,10 +230,9 @@ static inline void check_modem_status(struct uart_pxa_port *up) /* * This handles the interrupt from one port. */ -static inline irqreturn_t -serial_pxa_irq(int irq, void *dev_id, struct pt_regs *regs) +static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id) { - struct uart_pxa_port *up = (struct uart_pxa_port *)dev_id; + struct uart_pxa_port *up = dev_id; unsigned int iir, lsr; iir = serial_in(up, UART_IIR); @@ -242,7 +240,7 @@ serial_pxa_irq(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; lsr = serial_in(up, UART_LSR); if (lsr & UART_LSR_DR) - receive_chars(up, &lsr, regs); + receive_chars(up, &lsr); check_modem_status(up); if (lsr & UART_LSR_THRE) transmit_chars(up); diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 95738a19cde7..8dfc2dd058ca 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -310,7 +310,7 @@ static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, #define S3C2410_UERSTAT_PARITY (0x1000) static irqreturn_t -s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) +s3c24xx_serial_rx_chars(int irq, void *dev_id) { struct s3c24xx_uart_port *ourport = dev_id; struct uart_port *port = &ourport->port; @@ -379,7 +379,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, ch, regs)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag); @@ -393,7 +393,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *regs) +static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) { struct s3c24xx_uart_port *ourport = id; struct uart_port *port = &ourport->port; diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index db3486d33870..d4065266b6fc 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -190,7 +190,7 @@ static void sa1100_enable_ms(struct uart_port *port) } static void -sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) +sa1100_rx_chars(struct sa1100_port *sport) { struct tty_struct *tty = sport->port.info->tty; unsigned int status, ch, flg; @@ -228,7 +228,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) #endif } - if (uart_handle_sysrq_char(&sport->port, ch, regs)) + if (uart_handle_sysrq_char(&sport->port, ch)) goto ignore_char; uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); @@ -281,7 +281,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport) sa1100_stop_tx(&sport->port); } -static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sa1100_int(int irq, void *dev_id) { struct sa1100_port *sport = dev_id; unsigned int status, pass_counter = 0; @@ -294,7 +294,7 @@ static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs) /* Clear the receiver idle bit, if set */ if (status & UTSR0_RID) UART_PUT_UTSR0(sport, UTSR0_RID); - sa1100_rx_chars(sport, regs); + sa1100_rx_chars(sport); } /* Clear the relevant break bits */ diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 23ddedbaec08..5e1ac356bbb0 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -135,12 +135,7 @@ static void lh7a40xuart_enable_ms (struct uart_port* port) BIT_SET (port, UART_R_INTEN, ModemInt); } -static void -#ifdef SUPPORT_SYSRQ -lh7a40xuart_rx_chars (struct uart_port* port, struct pt_regs* regs) -#else -lh7a40xuart_rx_chars (struct uart_port* port) -#endif +static void lh7a40xuart_rx_chars (struct uart_port* port) { struct tty_struct* tty = port->info->tty; int cbRxMax = 256; /* (Gross) limit on receive */ @@ -177,7 +172,7 @@ lh7a40xuart_rx_chars (struct uart_port* port) flag = TTY_FRAME; } - if (uart_handle_sysrq_char (port, (unsigned char) data, regs)) + if (uart_handle_sysrq_char (port, (unsigned char) data)) continue; uart_insert_char(port, data, RxOverrunError, data, flag); @@ -248,8 +243,7 @@ static void lh7a40xuart_modem_status (struct uart_port* port) wake_up_interruptible (&port->info->delta_msr_wait); } -static irqreturn_t lh7a40xuart_int (int irq, void* dev_id, - struct pt_regs* regs) +static irqreturn_t lh7a40xuart_int (int irq, void* dev_id) { struct uart_port* port = dev_id; unsigned int cLoopLimit = ISR_LOOP_LIMIT; @@ -258,11 +252,7 @@ static irqreturn_t lh7a40xuart_int (int irq, void* dev_id, do { if (isr & (RxInt | RxTimeoutInt)) -#ifdef SUPPORT_SYSRQ - lh7a40xuart_rx_chars(port, regs); -#else lh7a40xuart_rx_chars(port); -#endif if (isr & ModemInt) lh7a40xuart_modem_status (port); if (isr & TxInt) diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index ebd8d2bb17fd..2a48289ac722 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -283,7 +283,7 @@ static void serial_txx9_enable_ms(struct uart_port *port) } static inline void -receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *regs) +receive_chars(struct uart_txx9_port *up, unsigned int *status) { struct tty_struct *tty = up->port.info->tty; unsigned char ch; @@ -344,7 +344,7 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r else if (disr & TXX9_SIDISR_UFER) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag); @@ -391,7 +391,7 @@ static inline void transmit_chars(struct uart_txx9_port *up) serial_txx9_stop_tx(&up->port); } -static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id) { int pass_counter = 0; struct uart_txx9_port *up = dev_id; @@ -409,7 +409,7 @@ static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs * } if (status & TXX9_SIDISR_RDIS) - receive_chars(up, &status, regs); + receive_chars(up, &status); if (status & TXX9_SIDISR_TDIS) transmit_chars(up); /* Clear TX/RX Int. Status */ diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index f336ba6778dd..cfcc3caf49d8 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -20,7 +20,6 @@ #undef DEBUG -#include <linux/config.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/timer.h> @@ -447,8 +446,7 @@ static void sci_transmit_chars(struct uart_port *port) /* On SH3, SCIF may read end-of-break as a space->mark char */ #define STEPFN(c) ({int __c=(c); (((__c-1)|(__c)) == -1); }) -static inline void sci_receive_chars(struct uart_port *port, - struct pt_regs *regs) +static inline void sci_receive_chars(struct uart_port *port) { struct sci_port *sci_port = (struct sci_port *)port; struct tty_struct *tty = port->info->tty; @@ -477,7 +475,7 @@ static inline void sci_receive_chars(struct uart_port *port, if (port->type == PORT_SCI) { char c = sci_in(port, SCxRDR); - if (uart_handle_sysrq_char(port, c, regs) || sci_port->break_flag) + if (uart_handle_sysrq_char(port, c) || sci_port->break_flag) count = 0; else { tty_insert_flip_char(tty, c, TTY_NORMAL); @@ -505,7 +503,7 @@ static inline void sci_receive_chars(struct uart_port *port, } } #endif /* CONFIG_CPU_SH3 */ - if (uart_handle_sysrq_char(port, c, regs)) { + if (uart_handle_sysrq_char(port, c)) { count--; i--; continue; } @@ -653,18 +651,18 @@ static inline int sci_handle_breaks(struct uart_port *port) return copied; } -static irqreturn_t sci_rx_interrupt(int irq, void *port, struct pt_regs *regs) +static irqreturn_t sci_rx_interrupt(int irq, void *port) { /* I think sci_receive_chars has to be called irrespective * of whether the I_IXOFF is set, otherwise, how is the interrupt * to be disabled? */ - sci_receive_chars(port, regs); + sci_receive_chars(port); return IRQ_HANDLED; } -static irqreturn_t sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs) +static irqreturn_t sci_tx_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; @@ -675,7 +673,7 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs) +static irqreturn_t sci_er_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; @@ -697,18 +695,18 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs) pr_debug("scif: overrun error\n"); } #endif - sci_rx_interrupt(irq, ptr, regs); + sci_rx_interrupt(irq, ptr); } sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Kick the transmission */ - sci_tx_interrupt(irq, ptr, regs); + sci_tx_interrupt(irq, ptr); return IRQ_HANDLED; } -static irqreturn_t sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs) +static irqreturn_t sci_br_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; @@ -725,7 +723,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs) +static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) { unsigned short ssr_status, scr_status; struct uart_port *port = ptr; @@ -735,16 +733,16 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs) /* Tx Interrupt */ if ((ssr_status & 0x0020) && (scr_status & 0x0080)) - sci_tx_interrupt(irq, ptr, regs); + sci_tx_interrupt(irq, ptr); /* Rx Interrupt */ if ((ssr_status & 0x0002) && (scr_status & 0x0040)) - sci_rx_interrupt(irq, ptr, regs); + sci_rx_interrupt(irq, ptr); /* Error Interrupt */ if ((ssr_status & 0x0080) && (scr_status & 0x0400)) - sci_er_interrupt(irq, ptr, regs); + sci_er_interrupt(irq, ptr); /* Break Interrupt */ if ((ssr_status & 0x0010) && (scr_status & 0x0200)) - sci_br_interrupt(irq, ptr, regs); + sci_br_interrupt(irq, ptr); return IRQ_HANDLED; } @@ -796,7 +794,7 @@ static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 }; static int sci_request_irq(struct sci_port *port) { int i; - irqreturn_t (*handlers[4])(int irq, void *ptr, struct pt_regs *regs) = { + irqreturn_t (*handlers[4])(int irq, void *ptr) = { sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt, sci_br_interrupt, }; @@ -810,7 +808,7 @@ static int sci_request_irq(struct sci_port *port) } if (request_irq(port->irqs[0], sci_mpxed_interrupt, - SA_INTERRUPT, "sci", port)) { + IRQF_DISABLED, "sci", port)) { printk(KERN_ERR "sci: Cannot allocate irq.\n"); return -ENODEV; } @@ -819,7 +817,7 @@ static int sci_request_irq(struct sci_port *port) if (!port->irqs[i]) continue; if (request_irq(port->irqs[i], handlers[i], - SA_INTERRUPT, desc[i], port)) { + IRQF_DISABLED, desc[i], port)) { printk(KERN_ERR "sci: Cannot allocate irq.\n"); return -ENODEV; } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 28643c4dc850..7ee992146ae9 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -10,7 +10,6 @@ * Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003). * Modified to support H8/300 Series Yoshinori Sato (Feb 2004). */ -#include <linux/config.h> #include <linux/serial_core.h> #include <asm/io.h> diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 2f148e5b9255..956b2cf08e1e 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -447,7 +447,6 @@ static int sn_debug_printf(const char *fmt, ...) /** * sn_receive_chars - Grab characters, pass them to tty layer * @port: Port to operate on - * @regs: Saved registers (needed by uart_handle_sysrq_char) * @flags: irq flags * * Note: If we're not registered with the serial core infrastructure yet, @@ -455,8 +454,7 @@ static int sn_debug_printf(const char *fmt, ...) * */ static void -sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs, - unsigned long flags) +sn_receive_chars(struct sn_cons_port *port, unsigned long flags) { int ch; struct tty_struct *tty; @@ -494,7 +492,7 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs, sysrq_requested = 0; if (ch && time_before(jiffies, sysrq_timeout)) { spin_unlock_irqrestore(&port->sc_port.lock, flags); - handle_sysrq(ch, regs, NULL); + handle_sysrq(ch, NULL); spin_lock_irqsave(&port->sc_port.lock, flags); /* ignore actual sysrq command char */ continue; @@ -615,10 +613,9 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw) * sn_sal_interrupt - Handle console interrupts * @irq: irq #, useful for debug statements * @dev_id: our pointer to our port (sn_cons_port which contains the uart port) - * @regs: Saved registers, used by sn_receive_chars for uart_handle_sysrq_char * */ -static irqreturn_t sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sn_sal_interrupt(int irq, void *dev_id) { struct sn_cons_port *port = (struct sn_cons_port *)dev_id; unsigned long flags; @@ -629,7 +626,7 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_lock_irqsave(&port->sc_port.lock, flags); if (status & SAL_CONSOLE_INTR_RECV) { - sn_receive_chars(port, regs, flags); + sn_receive_chars(port, flags); } if (status & SAL_CONSOLE_INTR_XMIT) { sn_transmit_chars(port, TRANSMIT_BUFFERED); @@ -677,7 +674,7 @@ static void sn_sal_timer_poll(unsigned long data) if (!port->sc_port.irq) { spin_lock_irqsave(&port->sc_port.lock, flags); if (sn_process_input) - sn_receive_chars(port, NULL, flags); + sn_receive_chars(port, flags); sn_transmit_chars(port, TRANSMIT_RAW); spin_unlock_irqrestore(&port->sc_port.lock, flags); mod_timer(&port->sc_timer, diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index f851f0f44f9b..03941d27d15d 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -73,7 +73,7 @@ static inline long hypervisor_con_putchar(long ch) static int hung_up = 0; -static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs *regs) +static struct tty_struct *receive_chars(struct uart_port *port) { struct tty_struct *tty = NULL; int saw_console_brk = 0; @@ -106,7 +106,7 @@ static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs * } if (tty == NULL) { - uart_handle_sysrq_char(port, c, regs); + uart_handle_sysrq_char(port, c); continue; } @@ -119,7 +119,7 @@ static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs * flag = TTY_BREAK; } - if (uart_handle_sysrq_char(port, c, regs)) + if (uart_handle_sysrq_char(port, c)) continue; if ((port->ignore_status_mask & IGNORE_ALL) || @@ -161,14 +161,14 @@ static void transmit_chars(struct uart_port *port) uart_write_wakeup(port); } -static irqreturn_t sunhv_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sunhv_interrupt(int irq, void *dev_id) { struct uart_port *port = dev_id; struct tty_struct *tty; unsigned long flags; spin_lock_irqsave(&port->lock, flags); - tty = receive_chars(port, regs); + tty = receive_chars(port); transmit_chars(port); spin_unlock_irqrestore(&port->lock, flags); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index cfe20f730436..08a7cd6a3a0c 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -108,8 +108,7 @@ static __inline__ void sunsab_cec_wait(struct uart_sunsab_port *up) static struct tty_struct * receive_chars(struct uart_sunsab_port *up, - union sab82532_irq_status *stat, - struct pt_regs *regs) + union sab82532_irq_status *stat) { struct tty_struct *tty = NULL; unsigned char buf[32]; @@ -161,7 +160,7 @@ receive_chars(struct uart_sunsab_port *up, unsigned char ch = buf[i], flag; if (tty == NULL) { - uart_handle_sysrq_char(&up->port, ch, regs); + uart_handle_sysrq_char(&up->port, ch); continue; } @@ -208,7 +207,7 @@ receive_chars(struct uart_sunsab_port *up, flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) continue; if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 && @@ -301,7 +300,7 @@ static void check_status(struct uart_sunsab_port *up, wake_up_interruptible(&up->port.info->delta_msr_wait); } -static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sunsab_interrupt(int irq, void *dev_id) { struct uart_sunsab_port *up = dev_id; struct tty_struct *tty; @@ -321,7 +320,7 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs) if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || (status.sreg.isr1 & SAB82532_ISR1_BRK)) - tty = receive_chars(up, &status, regs); + tty = receive_chars(up, &status); if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || (status.sreg.isr1 & SAB82532_ISR1_CSC)) check_status(up, &status); @@ -350,7 +349,7 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs) SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || (status.sreg.isr1 & SAB82532_ISR1_BRK)) - tty = receive_chars(up, &status, regs); + tty = receive_chars(up, &status); if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC))) check_status(up, &status); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 9b3b9aaa6b90..c577faea60e8 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -310,7 +310,7 @@ static void sunsu_enable_ms(struct uart_port *port) } static struct tty_struct * -receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs) +receive_chars(struct uart_sunsu_port *up, unsigned char *status) { struct tty_struct *tty = up->port.info->tty; unsigned char ch, flag; @@ -367,7 +367,7 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs else if (*status & UART_LSR_FE) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; if ((*status & up->port.ignore_status_mask) == 0) tty_insert_flip_char(tty, ch, flag); @@ -445,7 +445,7 @@ static void check_modem_status(struct uart_sunsu_port *up) wake_up_interruptible(&up->port.info->delta_msr_wait); } -static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) { struct uart_sunsu_port *up = dev_id; unsigned long flags; @@ -459,7 +459,7 @@ static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id, struct pt_regs status = serial_inp(up, UART_LSR); tty = NULL; if (status & UART_LSR_DR) - tty = receive_chars(up, &status, regs); + tty = receive_chars(up, &status); check_modem_status(up); if (status & UART_LSR_THRE) transmit_chars(up); @@ -497,7 +497,7 @@ static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) sunsu_change_speed(&up->port, up->cflag, 0, quot); } -static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *regs, int is_break) +static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) { do { unsigned char ch = serial_inp(up, UART_RX); @@ -505,7 +505,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg /* Stop-A is handled by drivers/char/keyboard.c now. */ if (up->su_type == SU_PORT_KBD) { #ifdef CONFIG_SERIO - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(&up->serio, ch, 0); #endif } else if (up->su_type == SU_PORT_MS) { int ret = suncore_mouse_baud_detection(ch, is_break); @@ -519,7 +519,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg case 0: #ifdef CONFIG_SERIO - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(&up->serio, ch, 0); #endif break; }; @@ -527,7 +527,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg } while (serial_in(up, UART_LSR) & UART_LSR_DR); } -static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id) { struct uart_sunsu_port *up = dev_id; @@ -535,8 +535,7 @@ static irqreturn_t sunsu_kbd_ms_interrupt(int irq, void *dev_id, struct pt_regs unsigned char status = serial_inp(up, UART_LSR); if ((status & UART_LSR_DR) || (status & UART_LSR_BI)) - receive_kbd_ms_chars(up, regs, - (status & UART_LSR_BI) != 0); + receive_kbd_ms_chars(up, (status & UART_LSR_BI) != 0); } return IRQ_HANDLED; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 0da3ebfff82d..b2cc703b2b9e 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -277,14 +277,13 @@ static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up) } static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, - unsigned char ch, int is_break, - struct pt_regs *regs) + unsigned char ch, int is_break) { if (ZS_IS_KEYB(up)) { /* Stop-A is handled by drivers/char/keyboard.c now. */ #ifdef CONFIG_SERIO if (up->serio_open) - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(&up->serio, ch, 0); #endif } else if (ZS_IS_MOUSE(up)) { int ret = suncore_mouse_baud_detection(ch, is_break); @@ -299,7 +298,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, case 0: #ifdef CONFIG_SERIO if (up->serio_open) - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(&up->serio, ch, 0); #endif break; }; @@ -308,8 +307,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, static struct tty_struct * sunzilog_receive_chars(struct uart_sunzilog_port *up, - struct zilog_channel __iomem *channel, - struct pt_regs *regs) + struct zilog_channel __iomem *channel) { struct tty_struct *tty; unsigned char ch, r1, flag; @@ -346,12 +344,12 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, ch &= up->parity_mask; if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) { - sunzilog_kbdms_receive_chars(up, ch, 0, regs); + sunzilog_kbdms_receive_chars(up, ch, 0); continue; } if (tty == NULL) { - uart_handle_sysrq_char(&up->port, ch, regs); + uart_handle_sysrq_char(&up->port, ch); continue; } @@ -379,7 +377,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, else if (r1 & CRC_ERR) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&up->port, ch)) continue; if (up->port.ignore_status_mask == 0xff || @@ -394,8 +392,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, } static void sunzilog_status_handle(struct uart_sunzilog_port *up, - struct zilog_channel __iomem *channel, - struct pt_regs *regs) + struct zilog_channel __iomem *channel) { unsigned char status; @@ -408,7 +405,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up, if (status & BRK_ABRT) { if (ZS_IS_MOUSE(up)) - sunzilog_kbdms_receive_chars(up, 0, 1, regs); + sunzilog_kbdms_receive_chars(up, 0, 1); if (ZS_IS_CONS(up)) { /* Wait for BREAK to deassert to avoid potentially * confusing the PROM. @@ -517,7 +514,7 @@ ack_tx_int: ZS_WSYNC(channel); } -static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) { struct uart_sunzilog_port *up = dev_id; @@ -538,9 +535,9 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg ZS_WSYNC(channel); if (r3 & CHARxIP) - tty = sunzilog_receive_chars(up, channel, regs); + tty = sunzilog_receive_chars(up, channel); if (r3 & CHAEXT) - sunzilog_status_handle(up, channel, regs); + sunzilog_status_handle(up, channel); if (r3 & CHATxIP) sunzilog_transmit_chars(up, channel); } @@ -561,9 +558,9 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg ZS_WSYNC(channel); if (r3 & CHBRxIP) - tty = sunzilog_receive_chars(up, channel, regs); + tty = sunzilog_receive_chars(up, channel); if (r3 & CHBEXT) - sunzilog_status_handle(up, channel, regs); + sunzilog_status_handle(up, channel); if (r3 & CHBTxIP) sunzilog_transmit_chars(up, channel); } @@ -1060,7 +1057,7 @@ static void sunzilog_free_tables(void) static void sunzilog_putchar(struct uart_port *port, int ch) { - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -1185,7 +1182,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) return 0; } -static struct console sunzilog_console = { +static struct console sunzilog_console_ops = { .name = "ttyS", .write = sunzilog_console_write, .device = uart_console_device, @@ -1211,10 +1208,10 @@ static inline struct console *SUNZILOG_CONSOLE(void) if (i == NUM_CHANNELS) return NULL; - sunzilog_console.index = i; + sunzilog_console_ops.index = i; sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS; - return &sunzilog_console; + return &sunzilog_console_ops; } #else diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index f802867c95c5..28f3bbff87bf 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c @@ -271,14 +271,14 @@ void v850e_uart_tx (struct uart_port *port) v850e_uart_stop_tx (port, stopped); } -static irqreturn_t v850e_uart_tx_irq(int irq, void *data, struct pt_regs *regs) +static irqreturn_t v850e_uart_tx_irq(int irq, void *data) { struct uart_port *port = data; v850e_uart_tx (port); return IRQ_HANDLED; } -static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs) +static irqreturn_t v850e_uart_rx_irq(int irq, void *data) { struct uart_port *port = data; unsigned ch_stat = TTY_NORMAL; diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 6c8b0ea83c3c..fd51f8182dec 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -359,8 +359,7 @@ static void siu_break_ctl(struct uart_port *port, int ctl) spin_unlock_irqrestore(&port->lock, flags); } -static inline void receive_chars(struct uart_port *port, uint8_t *status, - struct pt_regs *regs) +static inline void receive_chars(struct uart_port *port, uint8_t *status) { struct tty_struct *tty; uint8_t lsr, ch; @@ -405,7 +404,7 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status, flag = TTY_PARITY; } - if (uart_handle_sysrq_char(port, ch, regs)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); @@ -472,7 +471,7 @@ static inline void transmit_chars(struct uart_port *port) siu_stop_tx(port); } -static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t siu_interrupt(int irq, void *dev_id) { struct uart_port *port; uint8_t iir, lsr; @@ -485,7 +484,7 @@ static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs) lsr = siu_read(port, UART_LSR); if (lsr & UART_LSR_DR) - receive_chars(port, &lsr, regs); + receive_chars(port, &lsr); check_modem_status(port); |