diff options
Diffstat (limited to 'drivers/tty/serial')
49 files changed, 1670 insertions, 759 deletions
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index 1b37626e8f13..a44345a2dbb4 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c @@ -16,6 +16,7 @@ #include <asm/irq.h> #include <asm/mach-types.h> +#include <asm/system_info.h> #include <asm/hardware/dec21285.h> #include <mach/hardware.h> @@ -331,7 +332,7 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285) ret = -EINVAL; - if (ser->irq != NO_IRQ) + if (ser->irq <= 0) ret = -EINVAL; if (ser->baud_base != port->uartclk / 16) ret = -EINVAL; @@ -360,7 +361,7 @@ static struct uart_ops serial21285_ops = { static struct uart_port serial21285_port = { .mapbase = 0x42000160, .iotype = UPIO_MEM, - .irq = NO_IRQ, + .irq = 0, .fifosize = 16, .ops = &serial21285_ops, .flags = UPF_BOOT_AUTOCONF, diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index a88ef9782a4f..5ce782529d65 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -39,7 +39,6 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/system.h> #include <asm/delay.h> #include <asm/uaccess.h> @@ -1190,14 +1189,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, int rs_open(struct tty_struct *tty, struct file * filp) { struct m68k_serial *info; - int retval, line; - - line = tty->index; - - if (line >= NR_PORTS || line < 0) /* we have exactly one */ - return -ENODEV; + int retval; - info = &m68k_soft[line]; + info = &m68k_soft[tty->index]; if (serial_paranoia_check(info, tty->name, "rs_open")) return -ENODEV; diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 9b7336fcfbb3..5c27f7e6c9f1 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -38,16 +38,15 @@ #include <linux/nmi.h> #include <linux/mutex.h> #include <linux/slab.h> +#ifdef CONFIG_SPARC +#include <linux/sunserialcore.h> +#endif #include <asm/io.h> #include <asm/irq.h> #include "8250.h" -#ifdef CONFIG_SPARC -#include "../suncore.h" -#endif - /* * Configuration: * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option @@ -86,13 +85,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -/* - * We default to IRQ0 for the "no irq" hack. Some - * machine types want others as well - they're free - * to redefine this in their header file. - */ -#define is_real_interrupt(irq) ((irq) != 0) - #ifdef CONFIG_SERIAL_8250_DETECT_IRQ #define CONFIG_SERIAL_DETECT_IRQ 1 #endif @@ -475,9 +467,8 @@ static void set_io_from_upio(struct uart_port *p) } static void -serial_out_sync(struct uart_8250_port *up, int offset, int value) +serial_port_out_sync(struct uart_port *p, int offset, int value) { - struct uart_port *p = &up->port; switch (p->iotype) { case UPIO_MEM: case UPIO_MEM32: @@ -490,30 +481,17 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) } } -#define serial_in(up, offset) \ - (up->port.serial_in(&(up)->port, (offset))) -#define serial_out(up, offset, value) \ - (up->port.serial_out(&(up)->port, (offset), (value))) -/* - * We used to support using pause I/O for certain machines. We - * haven't supported this for a while, but just in case it's badly - * needed for certain old 386 machines, I've left these #define's - * in.... - */ -#define serial_inp(up, offset) serial_in(up, offset) -#define serial_outp(up, offset, value) serial_out(up, offset, value) - /* Uart divisor latch read */ static inline int _serial_dl_read(struct uart_8250_port *up) { - return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8; + return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; } /* Uart divisor latch write */ static inline void _serial_dl_write(struct uart_8250_port *up, int value) { - serial_outp(up, UART_DLL, value & 0xff); - serial_outp(up, UART_DLM, value >> 8 & 0xff); + serial_out(up, UART_DLL, value & 0xff); + serial_out(up, UART_DLM, value >> 8 & 0xff); } #if defined(CONFIG_MIPS_ALCHEMY) @@ -583,10 +561,10 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) static void serial8250_clear_fifos(struct uart_8250_port *p) { if (p->capabilities & UART_CAP_FIFO) { - serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO | + serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(p, UART_FCR, 0); + serial_out(p, UART_FCR, 0); } } @@ -599,15 +577,15 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) { if (p->capabilities & UART_CAP_SLEEP) { if (p->capabilities & UART_CAP_EFR) { - serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(p, UART_EFR, UART_EFR_ECB); - serial_outp(p, UART_LCR, 0); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, UART_EFR_ECB); + serial_out(p, UART_LCR, 0); } - serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); + serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); if (p->capabilities & UART_CAP_EFR) { - serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(p, UART_EFR, 0); - serial_outp(p, UART_LCR, 0); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, 0); + serial_out(p, UART_LCR, 0); } } } @@ -622,12 +600,12 @@ static int __enable_rsa(struct uart_8250_port *up) unsigned char mode; int result; - mode = serial_inp(up, UART_RSA_MSR); + mode = serial_in(up, UART_RSA_MSR); result = mode & UART_RSA_MSR_FIFO; if (!result) { - serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); - mode = serial_inp(up, UART_RSA_MSR); + serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); result = mode & UART_RSA_MSR_FIFO; } @@ -646,7 +624,7 @@ static void enable_rsa(struct uart_8250_port *up) spin_unlock_irq(&up->port.lock); } if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) - serial_outp(up, UART_RSA_FRR, 0); + serial_out(up, UART_RSA_FRR, 0); } } @@ -665,12 +643,12 @@ static void disable_rsa(struct uart_8250_port *up) up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { spin_lock_irq(&up->port.lock); - mode = serial_inp(up, UART_RSA_MSR); + mode = serial_in(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); if (!result) { - serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); - mode = serial_inp(up, UART_RSA_MSR); + serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); } @@ -691,28 +669,28 @@ static int size_fifo(struct uart_8250_port *up) unsigned short old_dl; int count; - old_lcr = serial_inp(up, UART_LCR); - serial_outp(up, UART_LCR, 0); - old_fcr = serial_inp(up, UART_FCR); - old_mcr = serial_inp(up, UART_MCR); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + old_lcr = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, 0); + old_fcr = serial_in(up, UART_FCR); + old_mcr = serial_in(up, UART_MCR); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_MCR, UART_MCR_LOOP); - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_MCR, UART_MCR_LOOP); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); old_dl = serial_dl_read(up); serial_dl_write(up, 0x0001); - serial_outp(up, UART_LCR, 0x03); + serial_out(up, UART_LCR, 0x03); for (count = 0; count < 256; count++) - serial_outp(up, UART_TX, count); + serial_out(up, UART_TX, count); mdelay(20);/* FIXME - schedule_timeout */ - for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) && + for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) && (count < 256); count++) - serial_inp(up, UART_RX); - serial_outp(up, UART_FCR, old_fcr); - serial_outp(up, UART_MCR, old_mcr); - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_in(up, UART_RX); + serial_out(up, UART_FCR, old_fcr); + serial_out(up, UART_MCR, old_mcr); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_dl_write(up, old_dl); - serial_outp(up, UART_LCR, old_lcr); + serial_out(up, UART_LCR, old_lcr); return count; } @@ -727,20 +705,20 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) unsigned char old_dll, old_dlm, old_lcr; unsigned int id; - old_lcr = serial_inp(p, UART_LCR); - serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A); + old_lcr = serial_in(p, UART_LCR); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); - old_dll = serial_inp(p, UART_DLL); - old_dlm = serial_inp(p, UART_DLM); + old_dll = serial_in(p, UART_DLL); + old_dlm = serial_in(p, UART_DLM); - serial_outp(p, UART_DLL, 0); - serial_outp(p, UART_DLM, 0); + serial_out(p, UART_DLL, 0); + serial_out(p, UART_DLM, 0); - id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8; + id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; - serial_outp(p, UART_DLL, old_dll); - serial_outp(p, UART_DLM, old_dlm); - serial_outp(p, UART_LCR, old_lcr); + serial_out(p, UART_DLL, old_dll); + serial_out(p, UART_DLM, old_dlm); + serial_out(p, UART_LCR, old_lcr); return id; } @@ -850,11 +828,11 @@ static void autoconfig_8250(struct uart_8250_port *up) up->port.type = PORT_8250; scratch = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, 0xa5); + serial_out(up, UART_SCR, 0xa5); status1 = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, 0x5a); + serial_out(up, UART_SCR, 0x5a); status2 = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, scratch); + serial_out(up, UART_SCR, scratch); if (status1 == 0xa5 && status2 == 0x5a) up->port.type = PORT_16450; @@ -885,7 +863,7 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) } else { status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ - serial_outp(up, 0x04, status); + serial_out(up, 0x04, status); } return 1; } @@ -908,9 +886,9 @@ static void autoconfig_16550a(struct uart_8250_port *up) * Check for presence of the EFR when DLAB is set. * Only ST16C650V1 UARTs pass this test. */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); if (serial_in(up, UART_EFR) == 0) { - serial_outp(up, UART_EFR, 0xA8); + serial_out(up, UART_EFR, 0xA8); if (serial_in(up, UART_EFR) != 0) { DEBUG_AUTOCONF("EFRv1 "); up->port.type = PORT_16650; @@ -918,7 +896,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) } else { DEBUG_AUTOCONF("Motorola 8xxx DUART "); } - serial_outp(up, UART_EFR, 0); + serial_out(up, UART_EFR, 0); return; } @@ -926,7 +904,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) * Maybe it requires 0xbf to be written to the LCR. * (other ST16C650V2 UARTs, TI16C752A, etc) */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) { DEBUG_AUTOCONF("EFRv2 "); autoconfig_has_efr(up); @@ -940,23 +918,23 @@ static void autoconfig_16550a(struct uart_8250_port *up) * switch back to bank 2, read it from EXCR1 again and check * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2 */ - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0); status1 = serial_in(up, UART_MCR); - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0xE0); status2 = serial_in(up, 0x02); /* EXCR1 */ if (!((status2 ^ status1) & UART_MCR_LOOP)) { - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP); - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP); + serial_out(up, UART_LCR, 0xE0); status2 = serial_in(up, 0x02); /* EXCR1 */ - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_MCR, status1); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_MCR, status1); if ((status2 ^ status1) & UART_MCR_LOOP) { unsigned short quot; - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0xE0); quot = serial_dl_read(up); quot <<= 3; @@ -964,7 +942,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (ns16550a_goto_highspeed(up)) serial_dl_write(up, quot); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0); up->port.uartclk = 921600*16; up->port.type = PORT_NS16550A; @@ -979,15 +957,15 @@ static void autoconfig_16550a(struct uart_8250_port *up) * Try setting it with and without DLAB set. Cheap clones * set bit 5 without DLAB set. */ - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); status1 = serial_in(up, UART_IIR) >> 5; - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); status2 = serial_in(up, UART_IIR) >> 5; - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, 0); DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); @@ -1006,13 +984,13 @@ static void autoconfig_16550a(struct uart_8250_port *up) * already a 1 and maybe locked there before we even start start. */ iersave = serial_in(up, UART_IER); - serial_outp(up, UART_IER, iersave & ~UART_IER_UUE); + serial_out(up, UART_IER, iersave & ~UART_IER_UUE); if (!(serial_in(up, UART_IER) & UART_IER_UUE)) { /* * OK it's in a known zero state, try writing and reading * without disturbing the current state of the other bits. */ - serial_outp(up, UART_IER, iersave | UART_IER_UUE); + serial_out(up, UART_IER, iersave | UART_IER_UUE); if (serial_in(up, UART_IER) & UART_IER_UUE) { /* * It's an Xscale. @@ -1030,7 +1008,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) */ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } - serial_outp(up, UART_IER, iersave); + serial_out(up, UART_IER, iersave); /* * Exar uarts have EFR in a weird location @@ -1061,24 +1039,25 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) { unsigned char status1, scratch, scratch2, scratch3; unsigned char save_lcr, save_mcr; + struct uart_port *port = &up->port; unsigned long flags; - if (!up->port.iobase && !up->port.mapbase && !up->port.membase) + if (!port->iobase && !port->mapbase && !port->membase) return; DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ", - serial_index(&up->port), up->port.iobase, up->port.membase); + serial_index(port), port->iobase, port->membase); /* * We really do need global IRQs disabled here - we're going to * be frobbing the chips IRQ enable register to see if it exists. */ - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); up->capabilities = 0; up->bugs = 0; - if (!(up->port.flags & UPF_BUGGY_UART)) { + if (!(port->flags & UPF_BUGGY_UART)) { /* * Do a simple existence test first; if we fail this, * there's no point trying anything else. @@ -1092,8 +1071,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * Note: this is safe as long as MCR bit 4 is clear * and the device is in "PC" mode. */ - scratch = serial_inp(up, UART_IER); - serial_outp(up, UART_IER, 0); + scratch = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); #ifdef __i386__ outb(0xff, 0x080); #endif @@ -1101,13 +1080,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * Mask out IER[7:4] bits for test as some UARTs (e.g. TL * 16C754B) allow only to modify them if an EFR bit is set. */ - scratch2 = serial_inp(up, UART_IER) & 0x0f; - serial_outp(up, UART_IER, 0x0F); + scratch2 = serial_in(up, UART_IER) & 0x0f; + serial_out(up, UART_IER, 0x0F); #ifdef __i386__ outb(0, 0x080); #endif - scratch3 = serial_inp(up, UART_IER) & 0x0f; - serial_outp(up, UART_IER, scratch); + scratch3 = serial_in(up, UART_IER) & 0x0f; + serial_out(up, UART_IER, scratch); if (scratch2 != 0 || scratch3 != 0x0F) { /* * We failed; there's nothing here @@ -1130,10 +1109,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * manufacturer would be stupid enough to design a board * that conflicts with COM 1-4 --- we hope! */ - if (!(up->port.flags & UPF_SKIP_TEST)) { - serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); - status1 = serial_inp(up, UART_MSR) & 0xF0; - serial_outp(up, UART_MCR, save_mcr); + if (!(port->flags & UPF_SKIP_TEST)) { + serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A); + status1 = serial_in(up, UART_MSR) & 0xF0; + serial_out(up, UART_MCR, save_mcr); if (status1 != 0x90) { DEBUG_AUTOCONF("LOOP test failed (%02x) ", status1); @@ -1150,11 +1129,11 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * We also initialise the EFR (if any) to zero for later. The * EFR occupies the same register location as the FCR and IIR. */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(up, UART_EFR, 0); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_EFR, 0); + serial_out(up, UART_LCR, 0); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(up, UART_IIR) >> 6; DEBUG_AUTOCONF("iir=%d ", scratch); @@ -1164,10 +1143,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) autoconfig_8250(up); break; case 1: - up->port.type = PORT_UNKNOWN; + port->type = PORT_UNKNOWN; break; case 2: - up->port.type = PORT_16550; + port->type = PORT_16550; break; case 3: autoconfig_16550a(up); @@ -1178,102 +1157,102 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) /* * Only probe for RSA ports if we got the region. */ - if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) { + if (port->type == PORT_16550A && probeflags & PROBE_RSA) { int i; for (i = 0 ; i < probe_rsa_count; ++i) { - if (probe_rsa[i] == up->port.iobase && - __enable_rsa(up)) { - up->port.type = PORT_RSA; + if (probe_rsa[i] == port->iobase && __enable_rsa(up)) { + port->type = PORT_RSA; break; } } } #endif - serial_outp(up, UART_LCR, save_lcr); + serial_out(up, UART_LCR, save_lcr); - if (up->capabilities != uart_config[up->port.type].flags) { + if (up->capabilities != uart_config[port->type].flags) { printk(KERN_WARNING "ttyS%d: detected caps %08x should be %08x\n", - serial_index(&up->port), up->capabilities, - uart_config[up->port.type].flags); + serial_index(port), up->capabilities, + uart_config[port->type].flags); } - up->port.fifosize = uart_config[up->port.type].fifo_size; - up->capabilities = uart_config[up->port.type].flags; - up->tx_loadsz = uart_config[up->port.type].tx_loadsz; + port->fifosize = uart_config[up->port.type].fifo_size; + up->capabilities = uart_config[port->type].flags; + up->tx_loadsz = uart_config[port->type].tx_loadsz; - if (up->port.type == PORT_UNKNOWN) + if (port->type == PORT_UNKNOWN) goto out; /* * Reset the UART. */ #ifdef CONFIG_SERIAL_8250_RSA - if (up->port.type == PORT_RSA) - serial_outp(up, UART_RSA_FRR, 0); + if (port->type == PORT_RSA) + serial_out(up, UART_RSA_FRR, 0); #endif - serial_outp(up, UART_MCR, save_mcr); + serial_out(up, UART_MCR, save_mcr); serial8250_clear_fifos(up); serial_in(up, UART_RX); if (up->capabilities & UART_CAP_UUE) - serial_outp(up, UART_IER, UART_IER_UUE); + serial_out(up, UART_IER, UART_IER_UUE); else - serial_outp(up, UART_IER, 0); + serial_out(up, UART_IER, 0); out: - spin_unlock_irqrestore(&up->port.lock, flags); - DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); + spin_unlock_irqrestore(&port->lock, flags); + DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); } static void autoconfig_irq(struct uart_8250_port *up) { + struct uart_port *port = &up->port; unsigned char save_mcr, save_ier; unsigned char save_ICP = 0; unsigned int ICP = 0; unsigned long irqs; int irq; - if (up->port.flags & UPF_FOURPORT) { - ICP = (up->port.iobase & 0xfe0) | 0x1f; + if (port->flags & UPF_FOURPORT) { + ICP = (port->iobase & 0xfe0) | 0x1f; save_ICP = inb_p(ICP); outb_p(0x80, ICP); - (void) inb_p(ICP); + inb_p(ICP); } /* forget possible initially masked and pending IRQ */ probe_irq_off(probe_irq_on()); - save_mcr = serial_inp(up, UART_MCR); - save_ier = serial_inp(up, UART_IER); - serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); + save_mcr = serial_in(up, UART_MCR); + save_ier = serial_in(up, UART_IER); + serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); irqs = probe_irq_on(); - serial_outp(up, UART_MCR, 0); + serial_out(up, UART_MCR, 0); udelay(10); - if (up->port.flags & UPF_FOURPORT) { - serial_outp(up, UART_MCR, + if (port->flags & UPF_FOURPORT) { + serial_out(up, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); } else { - serial_outp(up, UART_MCR, + serial_out(up, UART_MCR, UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); } - serial_outp(up, UART_IER, 0x0f); /* enable all intrs */ - (void)serial_inp(up, UART_LSR); - (void)serial_inp(up, UART_RX); - (void)serial_inp(up, UART_IIR); - (void)serial_inp(up, UART_MSR); - serial_outp(up, UART_TX, 0xFF); + serial_out(up, UART_IER, 0x0f); /* enable all intrs */ + serial_in(up, UART_LSR); + serial_in(up, UART_RX); + serial_in(up, UART_IIR); + serial_in(up, UART_MSR); + serial_out(up, UART_TX, 0xFF); udelay(20); irq = probe_irq_off(irqs); - serial_outp(up, UART_MCR, save_mcr); - serial_outp(up, UART_IER, save_ier); + serial_out(up, UART_MCR, save_mcr); + serial_out(up, UART_IER, save_ier); - if (up->port.flags & UPF_FOURPORT) + if (port->flags & UPF_FOURPORT) outb_p(save_ICP, ICP); - up->port.irq = (irq > 0) ? irq : 0; + port->irq = (irq > 0) ? irq : 0; } static inline void __stop_tx(struct uart_8250_port *p) @@ -1294,7 +1273,7 @@ static void serial8250_stop_tx(struct uart_port *port) /* * We really want to stop the transmitter from sending. */ - if (up->port.type == PORT_16C950) { + if (port->type == PORT_16C950) { up->acr |= UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } @@ -1307,13 +1286,13 @@ static void serial8250_start_tx(struct uart_port *port) if (!(up->ier & UART_IER_THRI)) { up->ier |= UART_IER_THRI; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); if (up->bugs & UART_BUG_TXEN) { unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - if ((up->port.type == PORT_RM9000) ? + if ((port->type == PORT_RM9000) ? (lsr & UART_LSR_THRE) : (lsr & UART_LSR_TEMT)) serial8250_tx_chars(up); @@ -1323,7 +1302,7 @@ static void serial8250_start_tx(struct uart_port *port) /* * Re-enable the transmitter if we disabled it. */ - if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { + if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { up->acr &= ~UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } @@ -1336,7 +1315,7 @@ static void serial8250_stop_rx(struct uart_port *port) up->ier &= ~UART_IER_RLSI; up->port.read_status_mask &= ~UART_LSR_DR; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); } static void serial8250_enable_ms(struct uart_port *port) @@ -1349,7 +1328,7 @@ static void serial8250_enable_ms(struct uart_port *port) return; up->ier |= UART_IER_MSI; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); } /* @@ -1381,14 +1360,15 @@ static void clear_rx_fifo(struct uart_8250_port *up) unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { - struct tty_struct *tty = up->port.state->port.tty; + struct uart_port *port = &up->port; + struct tty_struct *tty = port->state->port.tty; unsigned char ch; int max_count = 256; char flag; do { if (likely(lsr & UART_LSR_DR)) - ch = serial_inp(up, UART_RX); + ch = serial_in(up, UART_RX); else /* * Intel 82571 has a Serial Over Lan device that will @@ -1400,7 +1380,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) ch = 0; flag = TTY_NORMAL; - up->port.icount.rx++; + port->icount.rx++; lsr |= up->lsr_saved_flags; up->lsr_saved_flags = 0; @@ -1411,12 +1391,12 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) */ if (lsr & UART_LSR_BI) { lsr &= ~(UART_LSR_FE | UART_LSR_PE); - up->port.icount.brk++; + port->icount.brk++; /* * If tegra port then clear the rx fifo to * accept another break/character. */ - if (up->port.type == PORT_TEGRA) + if (port->type == PORT_TEGRA) clear_rx_fifo(up); /* @@ -1425,19 +1405,19 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) * may get masked by ignore_status_mask * or read_status_mask. */ - if (uart_handle_break(&up->port)) + if (uart_handle_break(port)) goto ignore_char; } else if (lsr & UART_LSR_PE) - up->port.icount.parity++; + port->icount.parity++; else if (lsr & UART_LSR_FE) - up->port.icount.frame++; + port->icount.frame++; if (lsr & UART_LSR_OE) - up->port.icount.overrun++; + port->icount.overrun++; /* * Mask off conditions which should be ignored. */ - lsr &= up->port.read_status_mask; + lsr &= port->read_status_mask; if (lsr & UART_LSR_BI) { DEBUG_INTR("handling break...."); @@ -1447,34 +1427,35 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) else if (lsr & UART_LSR_FE) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; - uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); ignore_char: - lsr = serial_inp(up, UART_LSR); + lsr = serial_in(up, UART_LSR); } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); - spin_unlock(&up->port.lock); + spin_unlock(&port->lock); tty_flip_buffer_push(tty); - spin_lock(&up->port.lock); + spin_lock(&port->lock); return lsr; } EXPORT_SYMBOL_GPL(serial8250_rx_chars); void serial8250_tx_chars(struct uart_8250_port *up) { - struct circ_buf *xmit = &up->port.state->xmit; + struct uart_port *port = &up->port; + struct circ_buf *xmit = &port->state->xmit; int count; - if (up->port.x_char) { - serial_outp(up, UART_TX, up->port.x_char); - up->port.icount.tx++; - up->port.x_char = 0; + if (port->x_char) { + serial_out(up, UART_TX, port->x_char); + port->icount.tx++; + port->x_char = 0; return; } - if (uart_tx_stopped(&up->port)) { - serial8250_stop_tx(&up->port); + if (uart_tx_stopped(port)) { + serial8250_stop_tx(port); return; } if (uart_circ_empty(xmit)) { @@ -1486,13 +1467,13 @@ void serial8250_tx_chars(struct uart_8250_port *up) do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - up->port.icount.tx++; + port->icount.tx++; if (uart_circ_empty(xmit)) break; } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); + uart_write_wakeup(port); DEBUG_INTR("THRE..."); @@ -1503,22 +1484,23 @@ EXPORT_SYMBOL_GPL(serial8250_tx_chars); unsigned int serial8250_modem_status(struct uart_8250_port *up) { + struct uart_port *port = &up->port; unsigned int status = serial_in(up, UART_MSR); status |= up->msr_saved_flags; up->msr_saved_flags = 0; if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && - up->port.state != NULL) { + port->state != NULL) { if (status & UART_MSR_TERI) - up->port.icount.rng++; + port->icount.rng++; if (status & UART_MSR_DDSR) - up->port.icount.dsr++; + port->icount.dsr++; if (status & UART_MSR_DDCD) - uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); + uart_handle_dcd_change(port, status & UART_MSR_DCD); if (status & UART_MSR_DCTS) - uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + uart_handle_cts_change(port, status & UART_MSR_CTS); - wake_up_interruptible(&up->port.state->port.delta_msr_wait); + wake_up_interruptible(&port->state->port.delta_msr_wait); } return status; @@ -1538,9 +1520,9 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) if (iir & UART_IIR_NO_INT) return 0; - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); - status = serial_inp(up, UART_LSR); + status = serial_port_in(port, UART_LSR); DEBUG_INTR("status = %x...", status); @@ -1550,16 +1532,14 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) if (status & UART_LSR_THRE) serial8250_tx_chars(up); - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); return 1; } EXPORT_SYMBOL_GPL(serial8250_handle_irq); static int serial8250_default_handle_irq(struct uart_port *port) { - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); - unsigned int iir = serial_in(up, UART_IIR); + unsigned int iir = serial_port_in(port, UART_IIR); return serial8250_handle_irq(port, iir); } @@ -1592,13 +1572,11 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) do { struct uart_8250_port *up; struct uart_port *port; - bool skip; up = list_entry(l, struct uart_8250_port, list); port = &up->port; - skip = pass_counter && up->port.flags & UPF_IIR_ONCE; - if (!skip && port->handle_irq(port)) { + if (port->handle_irq(port)) { handled = 1; end = NULL; } else if (end == NULL) @@ -1750,7 +1728,7 @@ static void serial8250_backup_timeout(unsigned long data) * Must disable interrupts or else we risk racing with the interrupt * based handler. */ - if (is_real_interrupt(up->port.irq)) { + if (up->port.irq) { ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); } @@ -1775,7 +1753,7 @@ static void serial8250_backup_timeout(unsigned long data) if (!(iir & UART_IIR_NO_INT)) serial8250_tx_chars(up); - if (is_real_interrupt(up->port.irq)) + if (up->port.irq) serial_out(up, UART_IER, ier); spin_unlock_irqrestore(&up->port.lock, flags); @@ -1792,10 +1770,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) unsigned long flags; unsigned int lsr; - spin_lock_irqsave(&up->port.lock, flags); - lsr = serial_in(up, UART_LSR); + spin_lock_irqsave(&port->lock, flags); + lsr = serial_port_in(port, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; } @@ -1840,7 +1818,7 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; - serial_out(up, UART_MCR, mcr); + serial_port_out(port, UART_MCR, mcr); } static void serial8250_break_ctl(struct uart_port *port, int break_state) @@ -1849,13 +1827,13 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) container_of(port, struct uart_8250_port, port); unsigned long flags; - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); if (break_state == -1) up->lcr |= UART_LCR_SBC; else up->lcr &= ~UART_LCR_SBC; - serial_out(up, UART_LCR, up->lcr); - spin_unlock_irqrestore(&up->port.lock, flags); + serial_port_out(port, UART_LCR, up->lcr); + spin_unlock_irqrestore(&port->lock, flags); } /* @@ -1900,14 +1878,12 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) static int serial8250_get_poll_char(struct uart_port *port) { - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); - unsigned char lsr = serial_inp(up, UART_LSR); + unsigned char lsr = serial_port_in(port, UART_LSR); if (!(lsr & UART_LSR_DR)) return NO_POLL_CHAR; - return serial_inp(up, UART_RX); + return serial_port_in(port, UART_RX); } @@ -1921,21 +1897,21 @@ static void serial8250_put_poll_char(struct uart_port *port, /* * First save the IER then disable the interrupts */ - ier = serial_in(up, UART_IER); + ier = serial_port_in(port, UART_IER); if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); + serial_port_out(port, UART_IER, UART_IER_UUE); else - serial_out(up, UART_IER, 0); + serial_port_out(port, UART_IER, 0); wait_for_xmitr(up, BOTH_EMPTY); /* * Send the character out. * If a LF, also do CR... */ - serial_out(up, UART_TX, c); + serial_port_out(port, UART_TX, c); if (c == 10) { wait_for_xmitr(up, BOTH_EMPTY); - serial_out(up, UART_TX, 13); + serial_port_out(port, UART_TX, 13); } /* @@ -1943,7 +1919,7 @@ static void serial8250_put_poll_char(struct uart_port *port, * and restore the IER */ wait_for_xmitr(up, BOTH_EMPTY); - serial_out(up, UART_IER, ier); + serial_port_out(port, UART_IER, ier); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1956,25 +1932,25 @@ static int serial8250_startup(struct uart_port *port) unsigned char lsr, iir; int retval; - up->port.fifosize = uart_config[up->port.type].fifo_size; + port->fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; up->mcr = 0; - if (up->port.iotype != up->cur_iotype) + if (port->iotype != up->cur_iotype) set_io_from_upio(port); - if (up->port.type == PORT_16C950) { + if (port->type == PORT_16C950) { /* Wake up and initialize UART */ up->acr = 0; - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_IER, 0); - serial_outp(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_IER, 0); + serial_port_out(port, UART_LCR, 0); serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_LCR, 0); } #ifdef CONFIG_SERIAL_8250_RSA @@ -1994,41 +1970,43 @@ static int serial8250_startup(struct uart_port *port) /* * Clear the interrupt registers. */ - (void) serial_inp(up, UART_LSR); - (void) serial_inp(up, UART_RX); - (void) serial_inp(up, UART_IIR); - (void) serial_inp(up, UART_MSR); + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); /* * At this point, there's no way the LSR could still be 0xff; * if it is, then bail out, because there's likely no UART * here. */ - if (!(up->port.flags & UPF_BUGGY_UART) && - (serial_inp(up, UART_LSR) == 0xff)) { + if (!(port->flags & UPF_BUGGY_UART) && + (serial_port_in(port, UART_LSR) == 0xff)) { printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", - serial_index(&up->port)); + serial_index(port)); return -ENODEV; } /* * For a XR16C850, we need to set the trigger levels */ - if (up->port.type == PORT_16850) { + if (port->type == PORT_16850) { unsigned char fctr; - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); - serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX); - serial_outp(up, UART_TRG, UART_TRG_96); - serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX); - serial_outp(up, UART_TRG, UART_TRG_96); + fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); + serial_port_out(port, UART_FCTR, + fctr | UART_FCTR_TRGD | UART_FCTR_RX); + serial_port_out(port, UART_TRG, UART_TRG_96); + serial_port_out(port, UART_FCTR, + fctr | UART_FCTR_TRGD | UART_FCTR_TX); + serial_port_out(port, UART_TRG, UART_TRG_96); - serial_outp(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, 0); } - if (is_real_interrupt(up->port.irq)) { + if (port->irq) { unsigned char iir1; /* * Test for UARTs that do not reassert THRE when the @@ -2038,29 +2016,31 @@ static int serial8250_startup(struct uart_port *port) * the interrupt is enabled. Delays are necessary to * allow register changes to become visible. */ - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); if (up->port.irqflags & IRQF_SHARED) - disable_irq_nosync(up->port.irq); + disable_irq_nosync(port->irq); wait_for_xmitr(up, UART_LSR_THRE); - serial_out_sync(up, UART_IER, UART_IER_THRI); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); udelay(1); /* allow THRE to set */ - iir1 = serial_in(up, UART_IIR); - serial_out(up, UART_IER, 0); - serial_out_sync(up, UART_IER, UART_IER_THRI); + iir1 = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); udelay(1); /* allow a working UART time to re-assert THRE */ - iir = serial_in(up, UART_IIR); - serial_out(up, UART_IER, 0); + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); - if (up->port.irqflags & IRQF_SHARED) - enable_irq(up->port.irq); - spin_unlock_irqrestore(&up->port.lock, flags); + if (port->irqflags & IRQF_SHARED) + enable_irq(port->irq); + spin_unlock_irqrestore(&port->lock, flags); /* - * If the interrupt is not reasserted, setup a timer to - * kick the UART on a regular basis. + * If the interrupt is not reasserted, or we otherwise + * don't trust the iir, setup a timer to kick the UART + * on a regular basis. */ - if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { + if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || + up->port.flags & UPF_BUG_THRE) { up->bugs |= UART_BUG_THRE; pr_debug("ttyS%d - using backup timer\n", serial_index(port)); @@ -2083,7 +2063,7 @@ static int serial8250_startup(struct uart_port *port) * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. */ - if (!is_real_interrupt(up->port.irq)) { + if (!port->irq) { up->timer.data = (unsigned long)up; mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); } else { @@ -2095,20 +2075,20 @@ static int serial8250_startup(struct uart_port *port) /* * Now, initialize the UART */ - serial_outp(up, UART_LCR, UART_LCR_WLEN8); + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); if (up->port.flags & UPF_FOURPORT) { - if (!is_real_interrupt(up->port.irq)) + if (!up->port.irq) up->port.mctrl |= TIOCM_OUT1; } else /* * Most PC uarts need OUT2 raised to enable interrupts. */ - if (is_real_interrupt(up->port.irq)) + if (port->irq) up->port.mctrl |= TIOCM_OUT2; - serial8250_set_mctrl(&up->port, up->port.mctrl); + serial8250_set_mctrl(port, port->mctrl); /* Serial over Lan (SoL) hack: Intel 8257x Gigabit ethernet chips have a @@ -2128,10 +2108,10 @@ static int serial8250_startup(struct uart_port *port) * Do a quick test to see if we receive an * interrupt when we enable the TX irq. */ - serial_outp(up, UART_IER, UART_IER_THRI); - lsr = serial_in(up, UART_LSR); - iir = serial_in(up, UART_IIR); - serial_outp(up, UART_IER, 0); + serial_port_out(port, UART_IER, UART_IER_THRI); + lsr = serial_port_in(port, UART_LSR); + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { if (!(up->bugs & UART_BUG_TXEN)) { @@ -2144,17 +2124,17 @@ static int serial8250_startup(struct uart_port *port) } dont_test_tx_en: - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); /* * Clear the interrupt registers again for luck, and clear the * saved flags to avoid getting false values from polling * routines or the previous session. */ - serial_inp(up, UART_LSR); - serial_inp(up, UART_RX); - serial_inp(up, UART_IIR); - serial_inp(up, UART_MSR); + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2164,16 +2144,16 @@ dont_test_tx_en: * anyway, so we don't enable them here. */ up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_outp(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); - if (up->port.flags & UPF_FOURPORT) { + if (port->flags & UPF_FOURPORT) { unsigned int icp; /* * Enable interrupts on the AST Fourport board */ - icp = (up->port.iobase & 0xfe0) | 0x01f; + icp = (port->iobase & 0xfe0) | 0x01f; outb_p(0x80, icp); - (void) inb_p(icp); + inb_p(icp); } return 0; @@ -2189,23 +2169,24 @@ static void serial8250_shutdown(struct uart_port *port) * Disable interrupts from this port */ up->ier = 0; - serial_outp(up, UART_IER, 0); + serial_port_out(port, UART_IER, 0); - spin_lock_irqsave(&up->port.lock, flags); - if (up->port.flags & UPF_FOURPORT) { + spin_lock_irqsave(&port->lock, flags); + if (port->flags & UPF_FOURPORT) { /* reset interrupts on the AST Fourport board */ - inb((up->port.iobase & 0xfe0) | 0x1f); - up->port.mctrl |= TIOCM_OUT1; + inb((port->iobase & 0xfe0) | 0x1f); + port->mctrl |= TIOCM_OUT1; } else - up->port.mctrl &= ~TIOCM_OUT2; + port->mctrl &= ~TIOCM_OUT2; - serial8250_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); + serial8250_set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); /* * Disable break condition and FIFOs */ - serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); + serial_port_out(port, UART_LCR, + serial_port_in(port, UART_LCR) & ~UART_LCR_SBC); serial8250_clear_fifos(up); #ifdef CONFIG_SERIAL_8250_RSA @@ -2219,11 +2200,11 @@ static void serial8250_shutdown(struct uart_port *port) * Read data port to reset things, and then unlink from * the IRQ chain. */ - (void) serial_in(up, UART_RX); + serial_port_in(port, UART_RX); del_timer_sync(&up->timer); up->timer.function = serial8250_timeout; - if (is_real_interrupt(up->port.irq)) + if (port->irq) serial_unlink_irq_chain(up); } @@ -2298,11 +2279,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0) quot++; - if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { + if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { if (baud < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else - fcr = uart_config[up->port.type].fcr; + fcr = uart_config[port->type].fcr; } /* @@ -2313,7 +2294,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * have sufficient FIFO entries for the latency of the remote * UART to respond. IOW, at least 32 bytes of FIFO. */ - if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) { + if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) { up->mcr &= ~UART_MCR_AFE; if (termios->c_cflag & CRTSCTS) up->mcr |= UART_MCR_AFE; @@ -2323,40 +2304,40 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * Ok, we're now changing the port state. Do it with * interrupts disabled. */ - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); - up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) - up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) - up->port.read_status_mask |= UART_LSR_BI; + port->read_status_mask |= UART_LSR_BI; /* * Characteres to ignore */ - up->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { - up->port.ignore_status_mask |= UART_LSR_BI; + port->ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_OE; + port->ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) - up->port.ignore_status_mask |= UART_LSR_DR; + port->ignore_status_mask |= UART_LSR_DR; /* * CTS flow control flag and modem status interrupts @@ -2370,7 +2351,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->capabilities & UART_CAP_RTOIE) up->ier |= UART_IER_RTOIE; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); if (up->capabilities & UART_CAP_EFR) { unsigned char efr = 0; @@ -2382,11 +2363,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CRTSCTS) efr |= UART_EFR_CTS; - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - if (up->port.flags & UPF_EXAR_EFR) - serial_outp(up, UART_XR_EFR, efr); + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + if (port->flags & UPF_EXAR_EFR) + serial_port_out(port, UART_XR_EFR, efr); else - serial_outp(up, UART_EFR, efr); + serial_port_out(port, UART_EFR, efr); } #ifdef CONFIG_ARCH_OMAP @@ -2394,18 +2375,20 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (cpu_is_omap1510() && is_omap_port(up)) { if (baud == 115200) { quot = 1; - serial_out(up, UART_OMAP_OSC_12M_SEL, 1); + serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); } else - serial_out(up, UART_OMAP_OSC_12M_SEL, 0); + serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); } #endif - if (up->capabilities & UART_NATSEMI) { - /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ - serial_outp(up, UART_LCR, 0xe0); - } else { - serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ - } + /* + * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, + * otherwise just set DLAB + */ + if (up->capabilities & UART_NATSEMI) + serial_port_out(port, UART_LCR, 0xe0); + else + serial_port_out(port, UART_LCR, cval | UART_LCR_DLAB); serial_dl_write(up, quot); @@ -2413,20 +2396,19 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. */ - if (up->port.type == PORT_16750) - serial_outp(up, UART_FCR, fcr); + if (port->type == PORT_16750) + serial_port_out(port, UART_FCR, fcr); - serial_outp(up, UART_LCR, cval); /* reset DLAB */ + serial_port_out(port, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ - if (up->port.type != PORT_16750) { - if (fcr & UART_FCR_ENABLE_FIFO) { - /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - } - serial_outp(up, UART_FCR, fcr); /* set fcr */ - } - serial8250_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); + if (port->type != PORT_16750) { + /* emulated UARTs (Lucent Venus 167x) need two steps */ + if (fcr & UART_FCR_ENABLE_FIFO) + serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_port_out(port, UART_FCR, fcr); /* set fcr */ + } + serial8250_set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); @@ -2491,26 +2473,26 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt) static int serial8250_request_std_resource(struct uart_8250_port *up) { unsigned int size = serial8250_port_size(up); + struct uart_port *port = &up->port; int ret = 0; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_AU: case UPIO_TSI: case UPIO_MEM32: case UPIO_MEM: - if (!up->port.mapbase) + if (!port->mapbase) break; - if (!request_mem_region(up->port.mapbase, size, "serial")) { + if (!request_mem_region(port->mapbase, size, "serial")) { ret = -EBUSY; break; } - if (up->port.flags & UPF_IOREMAP) { - up->port.membase = ioremap_nocache(up->port.mapbase, - size); - if (!up->port.membase) { - release_mem_region(up->port.mapbase, size); + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap_nocache(port->mapbase, size); + if (!port->membase) { + release_mem_region(port->mapbase, size); ret = -ENOMEM; } } @@ -2518,7 +2500,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) case UPIO_HUB6: case UPIO_PORT: - if (!request_region(up->port.iobase, size, "serial")) + if (!request_region(port->iobase, size, "serial")) ret = -EBUSY; break; } @@ -2528,26 +2510,27 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) static void serial8250_release_std_resource(struct uart_8250_port *up) { unsigned int size = serial8250_port_size(up); + struct uart_port *port = &up->port; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_AU: case UPIO_TSI: case UPIO_MEM32: case UPIO_MEM: - if (!up->port.mapbase) + if (!port->mapbase) break; - if (up->port.flags & UPF_IOREMAP) { - iounmap(up->port.membase); - up->port.membase = NULL; + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; } - release_mem_region(up->port.mapbase, size); + release_mem_region(port->mapbase, size); break; case UPIO_HUB6: case UPIO_PORT: - release_region(up->port.iobase, size); + release_region(port->iobase, size); break; } } @@ -2556,12 +2539,13 @@ static int serial8250_request_rsa_resource(struct uart_8250_port *up) { unsigned long start = UART_RSA_BASE << up->port.regshift; unsigned int size = 8 << up->port.regshift; + struct uart_port *port = &up->port; int ret = -EINVAL; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_HUB6: case UPIO_PORT: - start += up->port.iobase; + start += port->iobase; if (request_region(start, size, "serial-rsa")) ret = 0; else @@ -2576,11 +2560,12 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up) { unsigned long offset = UART_RSA_BASE << up->port.regshift; unsigned int size = 8 << up->port.regshift; + struct uart_port *port = &up->port; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_HUB6: case UPIO_PORT: - release_region(up->port.iobase + offset, size); + release_region(port->iobase + offset, size); break; } } @@ -2591,7 +2576,7 @@ static void serial8250_release_port(struct uart_port *port) container_of(port, struct uart_8250_port, port); serial8250_release_std_resource(up); - if (up->port.type == PORT_RSA) + if (port->type == PORT_RSA) serial8250_release_rsa_resource(up); } @@ -2602,7 +2587,7 @@ static int serial8250_request_port(struct uart_port *port) int ret = 0; ret = serial8250_request_std_resource(up); - if (ret == 0 && up->port.type == PORT_RSA) { + if (ret == 0 && port->type == PORT_RSA) { ret = serial8250_request_rsa_resource(up); if (ret < 0) serial8250_release_std_resource(up); @@ -2630,22 +2615,22 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (ret < 0) probeflags &= ~PROBE_RSA; - if (up->port.iotype != up->cur_iotype) + if (port->iotype != up->cur_iotype) set_io_from_upio(port); if (flags & UART_CONFIG_TYPE) autoconfig(up, probeflags); /* if access method is AU, it is a 16550 with a quirk */ - if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + if (port->type == PORT_16550A && port->iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR; - if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) + if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) autoconfig_irq(up); - if (up->port.type != PORT_RSA && probeflags & PROBE_RSA) + if (port->type != PORT_RSA && probeflags & PROBE_RSA) serial8250_release_rsa_resource(up); - if (up->port.type == PORT_UNKNOWN) + if (port->type == PORT_UNKNOWN) serial8250_release_std_resource(up); } @@ -2719,9 +2704,10 @@ static void __init serial8250_isa_init_ports(void) for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; + struct uart_port *port = &up->port; - up->port.line = i; - spin_lock_init(&up->port.lock); + port->line = i; + spin_lock_init(&port->lock); init_timer(&up->timer); up->timer.function = serial8250_timeout; @@ -2732,7 +2718,7 @@ static void __init serial8250_isa_init_ports(void) up->mcr_mask = ~ALPHA_KLUDGE_MCR; up->mcr_force = ALPHA_KLUDGE_MCR; - up->port.ops = &serial8250_pops; + port->ops = &serial8250_pops; } if (share_irqs) @@ -2741,17 +2727,19 @@ static void __init serial8250_isa_init_ports(void) for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++, up++) { - up->port.iobase = old_serial_port[i].port; - up->port.irq = irq_canonicalize(old_serial_port[i].irq); - up->port.irqflags = old_serial_port[i].irqflags; - up->port.uartclk = old_serial_port[i].baud_base * 16; - up->port.flags = old_serial_port[i].flags; - up->port.hub6 = old_serial_port[i].hub6; - up->port.membase = old_serial_port[i].iomem_base; - up->port.iotype = old_serial_port[i].io_type; - up->port.regshift = old_serial_port[i].iomem_reg_shift; - set_io_from_upio(&up->port); - up->port.irqflags |= irqflag; + struct uart_port *port = &up->port; + + port->iobase = old_serial_port[i].port; + port->irq = irq_canonicalize(old_serial_port[i].irq); + port->irqflags = old_serial_port[i].irqflags; + port->uartclk = old_serial_port[i].baud_base * 16; + port->flags = old_serial_port[i].flags; + port->hub6 = old_serial_port[i].hub6; + port->membase = old_serial_port[i].iomem_base; + port->iotype = old_serial_port[i].io_type; + port->regshift = old_serial_port[i].iomem_reg_shift; + set_io_from_upio(port); + port->irqflags |= irqflag; if (serial8250_isa_config != NULL) serial8250_isa_config(i, &up->port, &up->capabilities); @@ -2799,7 +2787,7 @@ static void serial8250_console_putchar(struct uart_port *port, int ch) container_of(port, struct uart_8250_port, port); wait_for_xmitr(up, UART_LSR_THRE); - serial_out(up, UART_TX, ch); + serial_port_out(port, UART_TX, ch); } /* @@ -2812,6 +2800,7 @@ static void serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; + struct uart_port *port = &up->port; unsigned long flags; unsigned int ier; int locked = 1; @@ -2819,32 +2808,32 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) touch_nmi_watchdog(); local_irq_save(flags); - if (up->port.sysrq) { + if (port->sysrq) { /* serial8250_handle_irq() already took the lock */ locked = 0; } else if (oops_in_progress) { - locked = spin_trylock(&up->port.lock); + locked = spin_trylock(&port->lock); } else - spin_lock(&up->port.lock); + spin_lock(&port->lock); /* * First save the IER then disable the interrupts */ - ier = serial_in(up, UART_IER); + ier = serial_port_in(port, UART_IER); if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); + serial_port_out(port, UART_IER, UART_IER_UUE); else - serial_out(up, UART_IER, 0); + serial_port_out(port, UART_IER, 0); - uart_console_write(&up->port, s, count, serial8250_console_putchar); + uart_console_write(port, s, count, serial8250_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the IER */ wait_for_xmitr(up, BOTH_EMPTY); - serial_out(up, UART_IER, ier); + serial_port_out(port, UART_IER, ier); /* * The receive handling will happen properly because the @@ -2857,7 +2846,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) serial8250_modem_status(up); if (locked) - spin_unlock(&up->port.lock); + spin_unlock(&port->lock); local_irq_restore(flags); } @@ -3002,17 +2991,18 @@ void serial8250_suspend_port(int line) void serial8250_resume_port(int line) { struct uart_8250_port *up = &serial8250_ports[line]; + struct uart_port *port = &up->port; if (up->capabilities & UART_NATSEMI) { /* Ensure it's still in high speed mode */ - serial_outp(up, UART_LCR, 0xE0); + serial_port_out(port, UART_LCR, 0xE0); ns16550a_goto_highspeed(up); - serial_outp(up, UART_LCR, 0); - up->port.uartclk = 921600*16; + serial_port_out(port, UART_LCR, 0); + port->uartclk = 921600*16; } - uart_resume_port(&serial8250_reg, &up->port); + uart_resume_port(&serial8250_reg, port); } /* diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ae027be57e25..2868a1da254d 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -86,6 +86,16 @@ struct serial8250_config { #define SERIAL8250_SHARE_IRQS 0 #endif +static inline int serial_in(struct uart_8250_port *up, int offset) +{ + return up->port.serial_in(&up->port, offset); +} + +static inline void serial_out(struct uart_8250_port *up, int offset, int value) +{ + up->port.serial_out(&up->port, offset, value); +} + #if defined(__alpha__) && !defined(CONFIG_PCI) /* * Digital did something really horribly wrong with the OUT1 and OUT2 diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index da2b0b0a183f..858dca865d6a 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1096,7 +1096,7 @@ static int kt_serial_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_port *port, int idx) { - port->flags |= UPF_IIR_ONCE; + port->flags |= UPF_BUG_THRE; return skip_tx_en_setup(priv, board, port, idx); } @@ -1118,18 +1118,6 @@ pci_xr17c154_setup(struct serial_private *priv, return pci_default_setup(priv, board, port, idx); } -static int try_enable_msi(struct pci_dev *dev) -{ - /* use msi if available, but fallback to legacy otherwise */ - pci_enable_msi(dev); - return 0; -} - -static void disable_msi(struct pci_dev *dev) -{ - pci_disable_msi(dev); -} - #define PCI_VENDOR_ID_SBSMODULARIO 0x124B #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B #define PCI_DEVICE_ID_OCTPRO 0x0001 @@ -1249,9 +1237,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .init = try_enable_msi, .setup = kt_serial_setup, - .exit = disable_msi, }, /* * ITE diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 86090605a84e..29b695d041ec 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -43,7 +43,6 @@ #include <linux/delay.h> #include <linux/major.h> #include <asm/io.h> -#include <asm/system.h> #include <pcmcia/cistpl.h> #include <pcmcia/ciscode.h> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2de99248dfae..070b442c1f81 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -853,7 +853,7 @@ config SERIAL_MPC52xx_CONSOLE_BAUD config SERIAL_ICOM tristate "IBM Multiport Serial Adapter" - depends on PCI && (PPC_ISERIES || PPC_PSERIES) + depends on PCI && PPC_PSERIES select SERIAL_CORE select FW_LOADER help @@ -1041,7 +1041,7 @@ config SERIAL_OMAP config SERIAL_OMAP_CONSOLE bool "Console on OMAP serial port" - depends on SERIAL_OMAP + depends on SERIAL_OMAP=y select SERIAL_CORE_CONSOLE help Select this option if you would like to use omap serial port as @@ -1347,4 +1347,17 @@ config SERIAL_AR933X_NR_UARTS Set this to the number of serial ports you want the driver to support. +config SERIAL_EFM32_UART + tristate "EFM32 UART/USART port." + depends on ARCH_EFM32 + select SERIAL_CORE + help + This driver support the USART and UART ports on + Energy Micro's efm32 SoCs. + +config SERIAL_EFM32_UART_CONSOLE + bool "EFM32 UART/USART console support" + depends on SERIAL_EFM32_UART=y + select SERIAL_CORE_CONSOLE + endmenu diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index fef32e10c851..7257c5d898ae 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -61,12 +61,12 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o +obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o -obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o @@ -78,3 +78,4 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o +obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 1d04c5037f25..1f0330915d5a 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -377,6 +377,26 @@ static int altera_uart_verify_port(struct uart_port *port, return 0; } +#ifdef CONFIG_CONSOLE_POLL +static int altera_uart_poll_get_char(struct uart_port *port) +{ + while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & + ALTERA_UART_STATUS_RRDY_MSK)) + cpu_relax(); + + return altera_uart_readl(port, ALTERA_UART_RXDATA_REG); +} + +static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c) +{ + while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & + ALTERA_UART_STATUS_TRDY_MSK)) + cpu_relax(); + + altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG); +} +#endif + /* * Define the basic serial functions we support. */ @@ -397,35 +417,16 @@ static struct uart_ops altera_uart_ops = { .release_port = altera_uart_release_port, .config_port = altera_uart_config_port, .verify_port = altera_uart_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = altera_uart_poll_get_char, + .poll_put_char = altera_uart_poll_put_char, +#endif }; static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) -int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) -{ - struct uart_port *port; - int i; - - for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { - port = &altera_uart_ports[i].port; - - port->line = i; - port->type = PORT_ALTERA_UART; - port->mapbase = platp[i].mapbase; - port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); - port->iotype = SERIAL_IO_MEM; - port->irq = platp[i].irq; - port->uartclk = platp[i].uartclk; - port->flags = UPF_BOOT_AUTOCONF; - port->ops = &altera_uart_ops; - port->private_data = platp; - } - - return 0; -} - static void altera_uart_console_putc(struct uart_port *port, const char c) { while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & @@ -555,7 +556,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res_mem) port->mapbase = res_mem->start; - else if (platp->mapbase) + else if (platp) port->mapbase = platp->mapbase; else return -EINVAL; @@ -563,7 +564,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res_irq) port->irq = res_irq->start; - else if (platp->irq) + else if (platp) port->irq = platp->irq; /* Check platform data first so we can override device node data */ diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 6800f5f26241..3d569cd68f58 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -51,6 +51,7 @@ #include <linux/dma-mapping.h> #include <linux/scatterlist.h> #include <linux/delay.h> +#include <linux/types.h> #include <asm/io.h> #include <asm/sizes.h> @@ -271,6 +272,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_MEM_TO_DEV, .dst_maxburst = uap->fifosize >> 1, + .device_fc = false, }; struct dma_chan *chan; dma_cap_mask_t mask; @@ -304,6 +306,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_DEV_TO_MEM, .src_maxburst = uap->fifosize >> 1, + .device_fc = false, }; chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param); @@ -481,7 +484,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) return -EBUSY; } - desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV, + desc = dmaengine_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE); @@ -664,7 +667,6 @@ static void pl011_dma_rx_callback(void *data); static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) { struct dma_chan *rxchan = uap->dmarx.chan; - struct dma_device *dma_dev; struct pl011_dmarx_data *dmarx = &uap->dmarx; struct dma_async_tx_descriptor *desc; struct pl011_sgbuf *sgbuf; @@ -675,8 +677,7 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) /* Start the RX DMA job */ sgbuf = uap->dmarx.use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; - dma_dev = rxchan->device; - desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1, + desc = dmaengine_prep_slave_sg(rxchan, &sgbuf->sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); /* @@ -827,7 +828,12 @@ static void pl011_dma_rx_callback(void *data) { struct uart_amba_port *uap = data; struct pl011_dmarx_data *dmarx = &uap->dmarx; + struct dma_chan *rxchan = dmarx->chan; bool lastbuf = dmarx->use_buf_b; + struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ? + &dmarx->sgbuf_b : &dmarx->sgbuf_a; + size_t pending; + struct dma_tx_state state; int ret; /* @@ -838,11 +844,21 @@ static void pl011_dma_rx_callback(void *data) * we immediately trigger the next DMA job. */ spin_lock_irq(&uap->port.lock); + /* + * Rx data can be taken by the UART interrupts during + * the DMA irq handler. So we check the residue here. + */ + rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state); + pending = sgbuf->sg.length - state.residue; + BUG_ON(pending > PL011_DMA_BUFFER_SIZE); + /* Then we terminate the transfer - we now know our residue */ + dmaengine_terminate_all(rxchan); + uap->dmarx.running = false; dmarx->use_buf_b = !lastbuf; ret = pl011_dma_rx_trigger_dma(uap); - pl011_dma_rx_chars(uap, PL011_DMA_BUFFER_SIZE, lastbuf, false); + pl011_dma_rx_chars(uap, pending, lastbuf, false); spin_unlock_irq(&uap->port.lock); /* * Do this check after we picked the DMA chars so we don't @@ -1381,6 +1397,10 @@ static int pl011_startup(struct uart_port *port) uap->port.uartclk = clk_get_rate(uap->clk); + /* Clear pending error and receive interrupts */ + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + /* * Allocate the IRQ */ @@ -1417,10 +1437,6 @@ static int pl011_startup(struct uart_port *port) cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); - /* Clear pending error interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, - uap->port.membase + UART011_ICR); - /* * initialise the old status of the modem signals */ @@ -1435,6 +1451,9 @@ static int pl011_startup(struct uart_port *port) * as well. */ spin_lock_irq(&uap->port.lock); + /* Clear out any spuriously appearing RX interrupts */ + writew(UART011_RTIS | UART011_RXIS, + uap->port.membase + UART011_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; @@ -1944,6 +1963,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.line = i; pl011_dma_probe(uap); + /* Ensure interrupts from this UART are masked and cleared */ + writew(0, uap->port.membase + UART011_IMSC); + writew(0xffff, uap->port.membase + UART011_ICR); + snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); amba_ports[i] = uap; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 10605ecc99ab..3d7e1ee2fa57 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -389,6 +389,8 @@ static void atmel_start_rx(struct uart_port *port) { UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */ + UART_PUT_CR(port, ATMEL_US_RXEN); + if (atmel_use_dma_rx(port)) { /* enable PDC controller */ UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | @@ -404,6 +406,8 @@ static void atmel_start_rx(struct uart_port *port) */ static void atmel_stop_rx(struct uart_port *port) { + UART_PUT_CR(port, ATMEL_US_RXDIS); + if (atmel_use_dma_rx(port)) { /* disable PDC receive */ UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); @@ -1526,6 +1530,8 @@ void __init atmel_register_uart_fns(struct atmel_port_fns *fns) atmel_pops.set_wake = fns->set_wake; } +struct platform_device *atmel_default_console_device; /* the serial console device */ + #ifdef CONFIG_SERIAL_ATMEL_CONSOLE static void atmel_console_putchar(struct uart_port *port, int ch) { diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 26953bfa6922..5832fdef11e9 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -535,11 +535,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) * when start a new tx. */ UART_CLEAR_IER(uart, ETBEI); - xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); uart->port.icount.tx += uart->tx_count; + if (!uart_circ_empty(xmit)) { + xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uart->port); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&uart->port); + } bfin_serial_dma_tx_chars(uart); } diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index e6c3dbd781d6..836fe2731234 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -154,10 +154,9 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id) port->x_char = 0; return IRQ_HANDLED; } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - clps711xuart_stop_tx(port); - return IRQ_HANDLED; - } + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + goto disable_tx_irq; count = port->fifosize >> 1; do { @@ -171,8 +170,11 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); - if (uart_circ_empty(xmit)) - clps711xuart_stop_tx(port); + if (uart_circ_empty(xmit)) { + disable_tx_irq: + disable_irq_nosync(TX_IRQ(port)); + tx_enabled(port) = 0; + } return IRQ_HANDLED; } diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 1dfba7b779c8..5b07c0c3a10c 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -34,9 +34,9 @@ static char *serial_version = "$Revision: 1.25 $"; #include <asm/irq.h> #include <asm/dma.h> -#include <asm/system.h> #include <arch/svinto.h> +#include <arch/system.h> /* non-arch dependent serial structures are in linux/serial.h */ #include <linux/serial.h> @@ -4105,20 +4105,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) { struct e100_serial *info; - int retval, line; + int retval; unsigned long page; int allocated_resources = 0; - /* find which port we want to open */ - line = tty->index; - - if (line < 0 || line >= NR_PORTS) - return -ENODEV; - - /* find the corresponding e100_serial struct in the table */ - info = rs_table + line; - - /* don't allow the opening of ports that are not enabled in the HW config */ + info = rs_table + tty->index; if (!info->enabled) return -ENODEV; @@ -4131,7 +4122,7 @@ rs_open(struct tty_struct *tty, struct file * filp) tty->driver_data = info; info->port.tty = tty; - info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = !!(info->flags & ASYNC_LOW_LATENCY); if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index e3699a84049f..6491b8644a7f 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -52,7 +52,6 @@ #include <linux/atomic.h> #include <asm/bootinfo.h> #include <asm/io.h> -#include <asm/system.h> #include <asm/dec/interrupts.h> #include <asm/dec/kn01.h> diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c new file mode 100644 index 000000000000..615e46470491 --- /dev/null +++ b/drivers/tty/serial/efm32-uart.c @@ -0,0 +1,830 @@ +#if defined(CONFIG_SERIAL_EFM32_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/console.h> +#include <linux/sysrq.h> +#include <linux/serial_core.h> +#include <linux/tty_flip.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/of.h> +#include <linux/of_device.h> + +#include <linux/platform_data/efm32-uart.h> + +#define DRIVER_NAME "efm32-uart" +#define DEV_NAME "ttyefm" + +#define UARTn_CTRL 0x00 +#define UARTn_CTRL_SYNC 0x0001 +#define UARTn_CTRL_TXBIL 0x1000 + +#define UARTn_FRAME 0x04 +#define UARTn_FRAME_DATABITS__MASK 0x000f +#define UARTn_FRAME_DATABITS(n) ((n) - 3) +#define UARTn_FRAME_PARITY_NONE 0x0000 +#define UARTn_FRAME_PARITY_EVEN 0x0200 +#define UARTn_FRAME_PARITY_ODD 0x0300 +#define UARTn_FRAME_STOPBITS_HALF 0x0000 +#define UARTn_FRAME_STOPBITS_ONE 0x1000 +#define UARTn_FRAME_STOPBITS_TWO 0x3000 + +#define UARTn_CMD 0x0c +#define UARTn_CMD_RXEN 0x0001 +#define UARTn_CMD_RXDIS 0x0002 +#define UARTn_CMD_TXEN 0x0004 +#define UARTn_CMD_TXDIS 0x0008 + +#define UARTn_STATUS 0x10 +#define UARTn_STATUS_TXENS 0x0002 +#define UARTn_STATUS_TXC 0x0020 +#define UARTn_STATUS_TXBL 0x0040 +#define UARTn_STATUS_RXDATAV 0x0080 + +#define UARTn_CLKDIV 0x14 + +#define UARTn_RXDATAX 0x18 +#define UARTn_RXDATAX_RXDATA__MASK 0x01ff +#define UARTn_RXDATAX_PERR 0x4000 +#define UARTn_RXDATAX_FERR 0x8000 +/* + * This is a software only flag used for ignore_status_mask and + * read_status_mask! It's used for breaks that the hardware doesn't report + * explicitly. + */ +#define SW_UARTn_RXDATAX_BERR 0x2000 + +#define UARTn_TXDATA 0x34 + +#define UARTn_IF 0x40 +#define UARTn_IF_TXC 0x0001 +#define UARTn_IF_TXBL 0x0002 +#define UARTn_IF_RXDATAV 0x0004 +#define UARTn_IF_RXOF 0x0010 + +#define UARTn_IFS 0x44 +#define UARTn_IFC 0x48 +#define UARTn_IEN 0x4c + +#define UARTn_ROUTE 0x54 +#define UARTn_ROUTE_LOCATION__MASK 0x0700 +#define UARTn_ROUTE_LOCATION(n) (((n) << 8) & UARTn_ROUTE_LOCATION__MASK) +#define UARTn_ROUTE_RXPEN 0x0001 +#define UARTn_ROUTE_TXPEN 0x0002 + +struct efm32_uart_port { + struct uart_port port; + unsigned int txirq; + struct clk *clk; +}; +#define to_efm_port(_port) container_of(_port, struct efm32_uart_port, port) +#define efm_debug(efm_port, format, arg...) \ + dev_dbg(efm_port->port.dev, format, ##arg) + +static void efm32_uart_write32(struct efm32_uart_port *efm_port, + u32 value, unsigned offset) +{ + writel_relaxed(value, efm_port->port.membase + offset); +} + +static u32 efm32_uart_read32(struct efm32_uart_port *efm_port, + unsigned offset) +{ + return readl_relaxed(efm_port->port.membase + offset); +} + +static unsigned int efm32_uart_tx_empty(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); + + if (status & UARTn_STATUS_TXC) + return TIOCSER_TEMT; + else + return 0; +} + +static void efm32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* sorry, neither handshaking lines nor loop functionallity */ +} + +static unsigned int efm32_uart_get_mctrl(struct uart_port *port) +{ + /* sorry, no handshaking lines available */ + return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; +} + +static void efm32_uart_stop_tx(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 ien = efm32_uart_read32(efm_port, UARTn_IEN); + + efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); + ien &= ~(UARTn_IF_TXC | UARTn_IF_TXBL); + efm32_uart_write32(efm_port, ien, UARTn_IEN); +} + +static void efm32_uart_tx_chars(struct efm32_uart_port *efm_port) +{ + struct uart_port *port = &efm_port->port; + struct circ_buf *xmit = &port->state->xmit; + + while (efm32_uart_read32(efm_port, UARTn_STATUS) & + UARTn_STATUS_TXBL) { + if (port->x_char) { + port->icount.tx++; + efm32_uart_write32(efm_port, port->x_char, + UARTn_TXDATA); + port->x_char = 0; + continue; + } + if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { + port->icount.tx++; + efm32_uart_write32(efm_port, xmit->buf[xmit->tail], + UARTn_TXDATA); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } else + break; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (!port->x_char && uart_circ_empty(xmit) && + efm32_uart_read32(efm_port, UARTn_STATUS) & + UARTn_STATUS_TXC) + efm32_uart_stop_tx(port); +} + +static void efm32_uart_start_tx(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 ien; + + efm32_uart_write32(efm_port, + UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IFC); + ien = efm32_uart_read32(efm_port, UARTn_IEN); + efm32_uart_write32(efm_port, + ien | UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IEN); + efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); + + efm32_uart_tx_chars(efm_port); +} + +static void efm32_uart_stop_rx(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + + efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD); +} + +static void efm32_uart_enable_ms(struct uart_port *port) +{ + /* no handshake lines, no modem status interrupts */ +} + +static void efm32_uart_break_ctl(struct uart_port *port, int ctl) +{ + /* not possible without fiddling with gpios */ +} + +static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port, + struct tty_struct *tty) +{ + struct uart_port *port = &efm_port->port; + + while (efm32_uart_read32(efm_port, UARTn_STATUS) & + UARTn_STATUS_RXDATAV) { + u32 rxdata = efm32_uart_read32(efm_port, UARTn_RXDATAX); + int flag = 0; + + /* + * This is a reserved bit and I only saw it read as 0. But to be + * sure not to be confused too much by new devices adhere to the + * warning in the reference manual that reserverd bits might + * read as 1 in the future. + */ + rxdata &= ~SW_UARTn_RXDATAX_BERR; + + port->icount.rx++; + + if ((rxdata & UARTn_RXDATAX_FERR) && + !(rxdata & UARTn_RXDATAX_RXDATA__MASK)) { + rxdata |= SW_UARTn_RXDATAX_BERR; + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } else if (rxdata & UARTn_RXDATAX_PERR) + port->icount.parity++; + else if (rxdata & UARTn_RXDATAX_FERR) + port->icount.frame++; + + rxdata &= port->read_status_mask; + + if (rxdata & SW_UARTn_RXDATAX_BERR) + flag = TTY_BREAK; + else if (rxdata & UARTn_RXDATAX_PERR) + flag = TTY_PARITY; + else if (rxdata & UARTn_RXDATAX_FERR) + flag = TTY_FRAME; + else if (uart_handle_sysrq_char(port, + rxdata & UARTn_RXDATAX_RXDATA__MASK)) + continue; + + if (tty && (rxdata & port->ignore_status_mask) == 0) + tty_insert_flip_char(tty, + rxdata & UARTn_RXDATAX_RXDATA__MASK, flag); + } +} + +static irqreturn_t efm32_uart_rxirq(int irq, void *data) +{ + struct efm32_uart_port *efm_port = data; + u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); + int handled = IRQ_NONE; + struct uart_port *port = &efm_port->port; + struct tty_struct *tty; + + spin_lock(&port->lock); + + tty = tty_kref_get(port->state->port.tty); + + if (irqflag & UARTn_IF_RXDATAV) { + efm32_uart_write32(efm_port, UARTn_IF_RXDATAV, UARTn_IFC); + efm32_uart_rx_chars(efm_port, tty); + + handled = IRQ_HANDLED; + } + + if (irqflag & UARTn_IF_RXOF) { + efm32_uart_write32(efm_port, UARTn_IF_RXOF, UARTn_IFC); + port->icount.overrun++; + if (tty) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + handled = IRQ_HANDLED; + } + + if (tty) { + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } + + spin_unlock(&port->lock); + + return handled; +} + +static irqreturn_t efm32_uart_txirq(int irq, void *data) +{ + struct efm32_uart_port *efm_port = data; + u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); + + /* TXBL doesn't need to be cleared */ + if (irqflag & UARTn_IF_TXC) + efm32_uart_write32(efm_port, UARTn_IF_TXC, UARTn_IFC); + + if (irqflag & (UARTn_IF_TXC | UARTn_IF_TXBL)) { + efm32_uart_tx_chars(efm_port); + return IRQ_HANDLED; + } else + return IRQ_NONE; +} + +static int efm32_uart_startup(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 location = 0; + struct efm32_uart_pdata *pdata = dev_get_platdata(port->dev); + int ret; + + if (pdata) + location = UARTn_ROUTE_LOCATION(pdata->location); + + ret = clk_enable(efm_port->clk); + if (ret) { + efm_debug(efm_port, "failed to enable clk\n"); + goto err_clk_enable; + } + port->uartclk = clk_get_rate(efm_port->clk); + + /* Enable pins at configured location */ + efm32_uart_write32(efm_port, location | UARTn_ROUTE_RXPEN | UARTn_ROUTE_TXPEN, + UARTn_ROUTE); + + ret = request_irq(port->irq, efm32_uart_rxirq, 0, + DRIVER_NAME, efm_port); + if (ret) { + efm_debug(efm_port, "failed to register rxirq\n"); + goto err_request_irq_rx; + } + + /* disable all irqs */ + efm32_uart_write32(efm_port, 0, UARTn_IEN); + + ret = request_irq(efm_port->txirq, efm32_uart_txirq, 0, + DRIVER_NAME, efm_port); + if (ret) { + efm_debug(efm_port, "failed to register txirq\n"); + free_irq(port->irq, efm_port); +err_request_irq_rx: + + clk_disable(efm_port->clk); + } else { + efm32_uart_write32(efm_port, + UARTn_IF_RXDATAV | UARTn_IF_RXOF, UARTn_IEN); + efm32_uart_write32(efm_port, UARTn_CMD_RXEN, UARTn_CMD); + } + +err_clk_enable: + return ret; +} + +static void efm32_uart_shutdown(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + + efm32_uart_write32(efm_port, 0, UARTn_IEN); + free_irq(port->irq, efm_port); + + clk_disable(efm_port->clk); +} + +static void efm32_uart_set_termios(struct uart_port *port, + struct ktermios *new, struct ktermios *old) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + unsigned long flags; + unsigned baud; + u32 clkdiv; + u32 frame = 0; + + /* no modem control lines */ + new->c_cflag &= ~(CRTSCTS | CMSPAR); + + baud = uart_get_baud_rate(port, new, old, + DIV_ROUND_CLOSEST(port->uartclk, 16 * 8192), + DIV_ROUND_CLOSEST(port->uartclk, 16)); + + switch (new->c_cflag & CSIZE) { + case CS5: + frame |= UARTn_FRAME_DATABITS(5); + break; + case CS6: + frame |= UARTn_FRAME_DATABITS(6); + break; + case CS7: + frame |= UARTn_FRAME_DATABITS(7); + break; + case CS8: + frame |= UARTn_FRAME_DATABITS(8); + break; + } + + if (new->c_cflag & CSTOPB) + /* the receiver only verifies the first stop bit */ + frame |= UARTn_FRAME_STOPBITS_TWO; + else + frame |= UARTn_FRAME_STOPBITS_ONE; + + if (new->c_cflag & PARENB) { + if (new->c_cflag & PARODD) + frame |= UARTn_FRAME_PARITY_ODD; + else + frame |= UARTn_FRAME_PARITY_EVEN; + } else + frame |= UARTn_FRAME_PARITY_NONE; + + /* + * the 6 lowest bits of CLKDIV are dc, bit 6 has value 0.25. + * port->uartclk <= 14e6, so 4 * port->uartclk doesn't overflow. + */ + clkdiv = (DIV_ROUND_CLOSEST(4 * port->uartclk, 16 * baud) - 4) << 6; + + spin_lock_irqsave(&port->lock, flags); + + efm32_uart_write32(efm_port, + UARTn_CMD_TXDIS | UARTn_CMD_RXDIS, UARTn_CMD); + + port->read_status_mask = UARTn_RXDATAX_RXDATA__MASK; + if (new->c_iflag & INPCK) + port->read_status_mask |= + UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; + if (new->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= SW_UARTn_RXDATAX_BERR; + + port->ignore_status_mask = 0; + if (new->c_iflag & IGNPAR) + port->ignore_status_mask |= + UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; + if (new->c_iflag & IGNBRK) + port->ignore_status_mask |= SW_UARTn_RXDATAX_BERR; + + uart_update_timeout(port, new->c_cflag, baud); + + efm32_uart_write32(efm_port, UARTn_CTRL_TXBIL, UARTn_CTRL); + efm32_uart_write32(efm_port, frame, UARTn_FRAME); + efm32_uart_write32(efm_port, clkdiv, UARTn_CLKDIV); + + efm32_uart_write32(efm_port, UARTn_CMD_TXEN | UARTn_CMD_RXEN, + UARTn_CMD); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *efm32_uart_type(struct uart_port *port) +{ + return port->type == PORT_EFMUART ? "efm32-uart" : NULL; +} + +static void efm32_uart_release_port(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + + clk_unprepare(efm_port->clk); + clk_put(efm_port->clk); + iounmap(port->membase); +} + +static int efm32_uart_request_port(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + int ret; + + port->membase = ioremap(port->mapbase, 60); + if (!efm_port->port.membase) { + ret = -ENOMEM; + efm_debug(efm_port, "failed to remap\n"); + goto err_ioremap; + } + + efm_port->clk = clk_get(port->dev, NULL); + if (IS_ERR(efm_port->clk)) { + ret = PTR_ERR(efm_port->clk); + efm_debug(efm_port, "failed to get clock\n"); + goto err_clk_get; + } + + ret = clk_prepare(efm_port->clk); + if (ret) { + clk_put(efm_port->clk); +err_clk_get: + + iounmap(port->membase); +err_ioremap: + return ret; + } + return 0; +} + +static void efm32_uart_config_port(struct uart_port *port, int type) +{ + if (type & UART_CONFIG_TYPE && + !efm32_uart_request_port(port)) + port->type = PORT_EFMUART; +} + +static int efm32_uart_verify_port(struct uart_port *port, + struct serial_struct *serinfo) +{ + int ret = 0; + + if (serinfo->type != PORT_UNKNOWN && serinfo->type != PORT_EFMUART) + ret = -EINVAL; + + return ret; +} + +static struct uart_ops efm32_uart_pops = { + .tx_empty = efm32_uart_tx_empty, + .set_mctrl = efm32_uart_set_mctrl, + .get_mctrl = efm32_uart_get_mctrl, + .stop_tx = efm32_uart_stop_tx, + .start_tx = efm32_uart_start_tx, + .stop_rx = efm32_uart_stop_rx, + .enable_ms = efm32_uart_enable_ms, + .break_ctl = efm32_uart_break_ctl, + .startup = efm32_uart_startup, + .shutdown = efm32_uart_shutdown, + .set_termios = efm32_uart_set_termios, + .type = efm32_uart_type, + .release_port = efm32_uart_release_port, + .request_port = efm32_uart_request_port, + .config_port = efm32_uart_config_port, + .verify_port = efm32_uart_verify_port, +}; + +static struct efm32_uart_port *efm32_uart_ports[5]; + +#ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE +static void efm32_uart_console_putchar(struct uart_port *port, int ch) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + unsigned int timeout = 0x400; + u32 status; + + while (1) { + status = efm32_uart_read32(efm_port, UARTn_STATUS); + + if (status & UARTn_STATUS_TXBL) + break; + if (!timeout--) + return; + } + efm32_uart_write32(efm_port, ch, UARTn_TXDATA); +} + +static void efm32_uart_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct efm32_uart_port *efm_port = efm32_uart_ports[co->index]; + u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); + unsigned int timeout = 0x400; + + if (!(status & UARTn_STATUS_TXENS)) + efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); + + uart_console_write(&efm_port->port, s, count, + efm32_uart_console_putchar); + + /* Wait for the transmitter to become empty */ + while (1) { + u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); + if (status & UARTn_STATUS_TXC) + break; + if (!timeout--) + break; + } + + if (!(status & UARTn_STATUS_TXENS)) + efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); +} + +static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, + int *baud, int *parity, int *bits) +{ + u32 ctrl = efm32_uart_read32(efm_port, UARTn_CTRL); + u32 route, clkdiv, frame; + + if (ctrl & UARTn_CTRL_SYNC) + /* not operating in async mode */ + return; + + route = efm32_uart_read32(efm_port, UARTn_ROUTE); + if (!(route & UARTn_ROUTE_TXPEN)) + /* tx pin not routed */ + return; + + clkdiv = efm32_uart_read32(efm_port, UARTn_CLKDIV); + + *baud = DIV_ROUND_CLOSEST(4 * efm_port->port.uartclk, + 16 * (4 + (clkdiv >> 6))); + + frame = efm32_uart_read32(efm_port, UARTn_FRAME); + if (frame & UARTn_FRAME_PARITY_ODD) + *parity = 'o'; + else if (frame & UARTn_FRAME_PARITY_EVEN) + *parity = 'e'; + else + *parity = 'n'; + + *bits = (frame & UARTn_FRAME_DATABITS__MASK) - + UARTn_FRAME_DATABITS(4) + 4; + + efm_debug(efm_port, "get_opts: options=%d%c%d\n", + *baud, *parity, *bits); +} + +static int efm32_uart_console_setup(struct console *co, char *options) +{ + struct efm32_uart_port *efm_port; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + int ret; + + if (co->index < 0 || co->index >= ARRAY_SIZE(efm32_uart_ports)) { + unsigned i; + for (i = 0; i < ARRAY_SIZE(efm32_uart_ports); ++i) { + if (efm32_uart_ports[i]) { + pr_warn("efm32-console: fall back to console index %u (from %hhi)\n", + i, co->index); + co->index = i; + break; + } + } + } + + efm_port = efm32_uart_ports[co->index]; + if (!efm_port) { + pr_warn("efm32-console: No port at %d\n", co->index); + return -ENODEV; + } + + ret = clk_prepare(efm_port->clk); + if (ret) { + dev_warn(efm_port->port.dev, + "console: clk_prepare failed: %d\n", ret); + return ret; + } + + efm_port->port.uartclk = clk_get_rate(efm_port->clk); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + efm32_uart_console_get_options(efm_port, + &baud, &parity, &bits); + + return uart_set_options(&efm_port->port, co, baud, parity, bits, flow); +} + +static struct uart_driver efm32_uart_reg; + +static struct console efm32_uart_console = { + .name = DEV_NAME, + .write = efm32_uart_console_write, + .device = uart_console_device, + .setup = efm32_uart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &efm32_uart_reg, +}; + +#else +#define efm32_uart_console (*(struct console *)NULL) +#endif /* ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE / else */ + +static struct uart_driver efm32_uart_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = DEV_NAME, + .nr = ARRAY_SIZE(efm32_uart_ports), + .cons = &efm32_uart_console, +}; + +static int efm32_uart_probe_dt(struct platform_device *pdev, + struct efm32_uart_port *efm_port) +{ + struct device_node *np = pdev->dev.of_node; + int ret; + + if (!np) + return 1; + + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); + return ret; + } else { + efm_port->port.line = ret; + return 0; + } + +} + +static int __devinit efm32_uart_probe(struct platform_device *pdev) +{ + struct efm32_uart_port *efm_port; + struct resource *res; + int ret; + + efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL); + if (!efm_port) { + dev_dbg(&pdev->dev, "failed to allocate private data\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + dev_dbg(&pdev->dev, "failed to determine base address\n"); + goto err_get_base; + } + + if (resource_size(res) < 60) { + ret = -EINVAL; + dev_dbg(&pdev->dev, "memory resource too small\n"); + goto err_too_small; + } + + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_dbg(&pdev->dev, "failed to get rx irq\n"); + goto err_get_rxirq; + } + + efm_port->port.irq = ret; + + ret = platform_get_irq(pdev, 1); + if (ret <= 0) + ret = efm_port->port.irq + 1; + + efm_port->txirq = ret; + + efm_port->port.dev = &pdev->dev; + efm_port->port.mapbase = res->start; + efm_port->port.type = PORT_EFMUART; + efm_port->port.iotype = UPIO_MEM32; + efm_port->port.fifosize = 2; + efm_port->port.ops = &efm32_uart_pops; + efm_port->port.flags = UPF_BOOT_AUTOCONF; + + ret = efm32_uart_probe_dt(pdev, efm_port); + if (ret > 0) + /* not created by device tree */ + efm_port->port.line = pdev->id; + + if (efm_port->port.line >= 0 && + efm_port->port.line < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[efm_port->port.line] = efm_port; + + ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port); + if (ret) { + dev_dbg(&pdev->dev, "failed to add port: %d\n", ret); + + if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[pdev->id] = NULL; +err_get_rxirq: +err_too_small: +err_get_base: + kfree(efm_port); + } else { + platform_set_drvdata(pdev, efm_port); + dev_dbg(&pdev->dev, "\\o/\n"); + } + + return ret; +} + +static int __devexit efm32_uart_remove(struct platform_device *pdev) +{ + struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + uart_remove_one_port(&efm32_uart_reg, &efm_port->port); + + if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[pdev->id] = NULL; + + kfree(efm_port); + + return 0; +} + +static struct of_device_id efm32_uart_dt_ids[] = { + { + .compatible = "efm32,uart", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids); + +static struct platform_driver efm32_uart_driver = { + .probe = efm32_uart_probe, + .remove = __devexit_p(efm32_uart_remove), + + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = efm32_uart_dt_ids, + }, +}; + +static int __init efm32_uart_init(void) +{ + int ret; + + ret = uart_register_driver(&efm32_uart_reg); + if (ret) + return ret; + + ret = platform_driver_register(&efm32_uart_driver); + if (ret) + uart_unregister_driver(&efm32_uart_reg); + + pr_info("EFM32 UART/USART driver\n"); + + return ret; +} +module_init(efm32_uart_init); + +static void __exit efm32_uart_exit(void) +{ + platform_driver_unregister(&efm32_uart_driver); + uart_unregister_driver(&efm32_uart_reg); +} + +MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); +MODULE_DESCRIPTION("EFM32 UART/USART driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index d55709a7a75a..defc4e3393a3 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -52,7 +52,6 @@ #include <linux/firmware.h> #include <linux/bitops.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 7e925e20cbaa..144cd3987d4c 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1375,12 +1375,9 @@ static int __init ifx_spi_init(void) return -ENOMEM; } - tty_drv->magic = TTY_DRIVER_MAGIC; - tty_drv->owner = THIS_MODULE; tty_drv->driver_name = DRVNAME; tty_drv->name = TTYNAME; tty_drv->minor_start = IFX_SPI_TTY_ID; - tty_drv->num = 1; tty_drv->type = TTY_DRIVER_TYPE_SERIAL; tty_drv->subtype = SERIAL_TYPE_NORMAL; tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 0b7fed746b27..e7feceeebc2f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1508,7 +1508,7 @@ static int serial_imx_probe(struct platform_device *pdev) ret = PTR_ERR(sport->clk); goto unmap; } - clk_enable(sport->clk); + clk_prepare_enable(sport->clk); sport->port.uartclk = clk_get_rate(sport->clk); @@ -1531,8 +1531,8 @@ deinit: if (pdata && pdata->exit) pdata->exit(pdev); clkput: + clk_disable_unprepare(sport->clk); clk_put(sport->clk); - clk_disable(sport->clk); unmap: iounmap(sport->port.membase); free: @@ -1552,11 +1552,10 @@ static int serial_imx_remove(struct platform_device *pdev) if (sport) { uart_remove_one_port(&imx_reg, &sport->port); + clk_disable_unprepare(sport->clk); clk_put(sport->clk); } - clk_disable(sport->clk); - if (pdata && pdata->exit) pdata->exit(pdev); diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c index 6b36c1554d7e..e16894fb2ca3 100644 --- a/drivers/tty/serial/ioc4_serial.c +++ b/drivers/tty/serial/ioc4_serial.c @@ -16,7 +16,6 @@ #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial.h> -#include <linux/serialP.h> #include <linux/circ_buf.h> #include <linux/serial_reg.h> #include <linux/module.h> @@ -975,7 +974,7 @@ intr_connect(struct ioc4_soft *soft, int type, BUG_ON(!((type == IOC4_SIO_INTR_TYPE) || (type == IOC4_OTHER_INTR_TYPE))); - i = atomic_inc(&soft-> is_intr_type[type].is_num_intrs) - 1; + i = atomic_inc_return(&soft-> is_intr_type[type].is_num_intrs) - 1; BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0))); /* Save off the lower level interrupt handler */ diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 94a6792bf97b..a0703624d5e5 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -38,7 +38,6 @@ #include <linux/console.h> #include <linux/sysrq.h> #include <linux/serial.h> -#include <linux/serialP.h> #include <linux/delay.h> #include <asm/m32r.h> @@ -70,13 +69,6 @@ #define PASS_LIMIT 256 -/* - * We default to IRQ0 for the "no irq" hack. Some - * machine types want others as well - they're free - * to redefine this in their header file. - */ -#define is_real_interrupt(irq) ((irq) != 0) - #define BASE_BAUD 115200 /* Standard COM flags */ @@ -640,7 +632,7 @@ static int m32r_sio_startup(struct uart_port *port) * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. */ - if (!is_real_interrupt(up->port.irq)) { + if (!up->port.irq) { unsigned int timeout = up->port.timeout; timeout = timeout > 6 ? (timeout / 2 - 2) : 1; @@ -687,7 +679,7 @@ static void m32r_sio_shutdown(struct uart_port *port) sio_init(); - if (!is_real_interrupt(up->port.irq)) + if (!up->port.irq) del_timer_sync(&up->timer); else serial_unlink_irq_chain(up); diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/m32r_sio.h index e9b7e11793b1..8129824496c6 100644 --- a/drivers/tty/serial/m32r_sio.h +++ b/drivers/tty/serial/m32r_sio.h @@ -15,6 +15,7 @@ * (at your option) any later version. */ +#include <linux/pci.h> struct m32r_sio_probe { struct module *owner; diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index a9234ba8f8d5..c4b50af46c44 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -127,11 +127,6 @@ static inline void serial_out(struct uart_hsu_port *up, int offset, int value) #define HSU_REGS_BUFSIZE 1024 -static int hsu_show_regs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} static ssize_t port_show_regs(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -231,14 +226,14 @@ static ssize_t dma_show_regs(struct file *file, char __user *user_buf, static const struct file_operations port_regs_ops = { .owner = THIS_MODULE, - .open = hsu_show_regs_open, + .open = simple_open, .read = port_show_regs, .llseek = default_llseek, }; static const struct file_operations dma_regs_ops = { .owner = THIS_MODULE, - .open = hsu_show_regs_open, + .open = simple_open, .read = dma_show_regs, .llseek = default_llseek, }; diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 1093a88a1fe3..bedac0d4c9ce 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -262,8 +262,9 @@ static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port, port->uartclk / 4); divisor = (port->uartclk + 2 * baud) / (4 * baud); - /* select the proper prescaler and set the divisor */ - if (divisor > 0xffff) { + /* select the proper prescaler and set the divisor + * prefer high prescaler for more tolerance on low baudrates */ + if (divisor > 0xffff || baud <= 115200) { divisor = (divisor + 4) / 8; prescaler = 0xdd00; /* /32 */ } else @@ -507,7 +508,7 @@ static int __init mpc512x_psc_fifoc_init(void) psc_fifoc_irq = irq_of_parse_and_map(np, 0); of_node_put(np); - if (psc_fifoc_irq == NO_IRQ) { + if (psc_fifoc_irq == 0) { pr_err("%s: Can't get FIFOC irq\n", __func__); iounmap(psc_fifoc); return -ENODEV; @@ -1354,7 +1355,7 @@ static int __devinit mpc52xx_uart_of_probe(struct platform_device *op) } psc_ops->get_irq(port, op->dev.of_node); - if (port->irq == NO_IRQ) { + if (port->irq == 0) { dev_dbg(&op->dev, "Could not get irq\n"); return -EINVAL; } diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 5e85e1e14c44..fca13dc73e23 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -50,7 +50,6 @@ #include <linux/atomic.h> #include <asm/irq.h> -#include <asm/system.h> #include <mach/hardware.h> #include <mach/dma.h> diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c index 4f41dcdcb771..b25e6ee71443 100644 --- a/drivers/tty/serial/msm_smd_tty.c +++ b/drivers/tty/serial/msm_smd_tty.c @@ -203,7 +203,6 @@ static int __init smd_tty_init(void) if (smd_tty_driver == 0) return -ENOMEM; - smd_tty_driver->owner = THIS_MODULE; smd_tty_driver->driver_name = "smd_tty_driver"; smd_tty_driver->name = "smd"; smd_tty_driver->major = 0; diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 06f6aefd5ba6..7ea8a263fd9e 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -17,7 +17,6 @@ */ #include <linux/module.h> -#include <linux/tty.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/serial.h> @@ -499,7 +498,7 @@ static int __init mux_probe(struct parisc_device *dev) port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); port->iotype = UPIO_MEM; port->type = PORT_MUX; - port->irq = NO_IRQ; + port->irq = 0; port->uartclk = 0; port->fifosize = MUX_FIFO_SIZE; port->ops = &mux_pops; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index f80904145fd4..d00b38eb268e 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -159,7 +159,7 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } - if (!up->use_dma && pdata->set_forceidle) + if (!up->use_dma && pdata && pdata->set_forceidle) pdata->set_forceidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); @@ -298,7 +298,7 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); serial_omap_enable_ier_thri(up); - if (pdata->set_noidle) + if (pdata && pdata->set_noidle) pdata->set_noidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); @@ -1381,29 +1381,24 @@ static int serial_omap_probe(struct platform_device *pdev) return -ENODEV; } - if (!request_mem_region(mem->start, resource_size(mem), + if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), pdev->dev.driver->name)) { dev_err(&pdev->dev, "memory region already claimed\n"); return -EBUSY; } dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); - if (!dma_rx) { - ret = -EINVAL; - goto err; - } + if (!dma_rx) + return -ENXIO; dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); - if (!dma_tx) { - ret = -EINVAL; - goto err; - } + if (!dma_tx) + return -ENXIO; + + up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL); + if (!up) + return -ENOMEM; - up = kzalloc(sizeof(*up), GFP_KERNEL); - if (up == NULL) { - ret = -ENOMEM; - goto do_release_region; - } up->pdev = pdev; up->port.dev = &pdev->dev; up->port.type = PORT_OMAP; @@ -1423,16 +1418,17 @@ static int serial_omap_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", up->port.line); ret = -ENODEV; - goto err; + goto err_port_line; } sprintf(up->name, "OMAP UART%d", up->port.line); up->port.mapbase = mem->start; - up->port.membase = ioremap(mem->start, resource_size(mem)); + up->port.membase = devm_ioremap(&pdev->dev, mem->start, + resource_size(mem)); if (!up->port.membase) { dev_err(&pdev->dev, "can't ioremap UART\n"); ret = -ENOMEM; - goto err; + goto err_ioremap; } up->port.flags = omap_up_info->flags; @@ -1478,16 +1474,19 @@ static int serial_omap_probe(struct platform_device *pdev) ret = uart_add_one_port(&serial_omap_reg, &up->port); if (ret != 0) - goto do_release_region; + goto err_add_port; pm_runtime_put(&pdev->dev); platform_set_drvdata(pdev, up); return 0; -err: + +err_add_port: + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); +err_ioremap: +err_port_line: dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n", pdev->id, __func__, ret); -do_release_region: - release_mem_region(mem->start, resource_size(mem)); return ret; } @@ -1499,8 +1498,6 @@ static int serial_omap_remove(struct platform_device *dev) pm_runtime_disable(&up->pdev->dev); uart_remove_one_port(&serial_omap_reg, &up->port); pm_qos_remove_request(&up->pm_qos_request); - - kfree(up); } platform_set_drvdata(dev, NULL); @@ -1613,7 +1610,7 @@ static int serial_omap_runtime_resume(struct device *dev) struct uart_omap_port *up = dev_get_drvdata(dev); struct omap_uart_port_info *pdata = dev->platform_data; - if (up) { + if (up && pdata) { if (pdata->get_context_loss_count) { u32 loss_cnt = pdata->get_context_loss_count(dev); diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 17ae65762d1a..c2816f494807 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -29,6 +29,7 @@ #include <linux/nmi.h> #include <linux/delay.h> +#include <linux/debugfs.h> #include <linux/dmaengine.h> #include <linux/pch_dma.h> @@ -144,6 +145,8 @@ enum { #define PCH_UART_DLL 0x00 #define PCH_UART_DLM 0x01 +#define PCH_UART_BRCSR 0x0E + #define PCH_UART_IID_RLS (PCH_UART_IIR_REI) #define PCH_UART_IID_RDR (PCH_UART_IIR_RRI) #define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI) @@ -203,7 +206,11 @@ enum { #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -#define DEFAULT_BAUD_RATE 1843200 /* 1.8432MHz */ +#define DEFAULT_UARTCLK 1843200 /* 1.8432 MHz */ +#define CMITC_UARTCLK 192000000 /* 192.0000 MHz */ +#define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */ +#define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */ +#define NTC1_UARTCLK 64000000 /* 64.0000 MHz */ struct pch_uart_buffer { unsigned char *buf; @@ -218,7 +225,7 @@ struct eg20t_port { unsigned int iobase; struct pci_dev *pdev; int fifo_size; - int base_baud; + int uartclk; int start_tx; int start_rx; int tx_empty; @@ -243,6 +250,8 @@ struct eg20t_port { int tx_dma_use; void *rx_buf_virt; dma_addr_t rx_buf_dma; + + struct dentry *debugfs; }; /** @@ -287,26 +296,102 @@ static struct pch_uart_driver_data drv_dat[] = { static struct eg20t_port *pch_uart_ports[PCH_UART_NR]; #endif static unsigned int default_baud = 9600; +static unsigned int user_uartclk = 0; static const int trigger_level_256[4] = { 1, 64, 128, 224 }; static const int trigger_level_64[4] = { 1, 16, 32, 56 }; static const int trigger_level_16[4] = { 1, 4, 8, 14 }; static const int trigger_level_1[4] = { 1, 1, 1, 1 }; -static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize, - int base_baud) +#ifdef CONFIG_DEBUG_FS + +#define PCH_REGS_BUFSIZE 1024 + + +static ssize_t port_show_regs(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) { - struct eg20t_port *priv = pci_get_drvdata(pdev); + struct eg20t_port *priv = file->private_data; + char *buf; + u32 len = 0; + ssize_t ret; + unsigned char lcr; + + buf = kzalloc(PCH_REGS_BUFSIZE, GFP_KERNEL); + if (!buf) + return 0; - priv->trigger_level = 1; - priv->fcr = 0; + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "PCH EG20T port[%d] regs:\n", priv->port.line); + + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "=================================\n"); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "IER: \t0x%02x\n", ioread8(priv->membase + UART_IER)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "BRCSR: \t0x%02x\n", + ioread8(priv->membase + PCH_UART_BRCSR)); + + lcr = ioread8(priv->membase + UART_LCR); + iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM)); + iowrite8(lcr, priv->membase + UART_LCR); + + if (len > PCH_REGS_BUFSIZE) + len = PCH_REGS_BUFSIZE; + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return ret; } -static unsigned int get_msr(struct eg20t_port *priv, void __iomem *base) +static const struct file_operations port_regs_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = port_show_regs, + .llseek = default_llseek, +}; +#endif /* CONFIG_DEBUG_FS */ + +/* Return UART clock, checking for board specific clocks. */ +static int pch_uart_get_uartclk(void) { - unsigned int msr = ioread8(base + UART_MSR); - priv->dmsr |= msr & PCH_UART_MSR_DELTA; + const char *cmp; - return msr; + if (user_uartclk) + return user_uartclk; + + cmp = dmi_get_system_info(DMI_BOARD_NAME); + if (cmp && strstr(cmp, "CM-iTC")) + return CMITC_UARTCLK; + + cmp = dmi_get_system_info(DMI_BIOS_VERSION); + if (cmp && strnstr(cmp, "FRI2", 4)) + return FRI2_64_UARTCLK; + + cmp = dmi_get_system_info(DMI_PRODUCT_NAME); + if (cmp && strstr(cmp, "Fish River Island II")) + return FRI2_48_UARTCLK; + + /* Kontron COMe-mTT10 (nanoETXexpress-TT) */ + cmp = dmi_get_system_info(DMI_BOARD_NAME); + if (cmp && (strstr(cmp, "COMe-mTT") || + strstr(cmp, "nanoETXexpress-TT"))) + return NTC1_UARTCLK; + + return DEFAULT_UARTCLK; } static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, @@ -332,7 +417,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, unsigned int dll, dlm, lcr; int div; - div = DIV_ROUND_CLOSEST(priv->base_baud / 16, baud); + div = DIV_ROUND_CLOSEST(priv->uartclk / 16, baud); if (div < 0 || USHRT_MAX <= div) { dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div); return -EINVAL; @@ -442,8 +527,9 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv, static u8 pch_uart_hal_get_modem(struct eg20t_port *priv) { - priv->dmsr = 0; - return get_msr(priv, priv->membase); + unsigned int msr = ioread8(priv->membase + UART_MSR); + priv->dmsr = msr & PCH_UART_MSR_DELTA; + return (u8)msr; } static void pch_uart_hal_write(struct eg20t_port *priv, @@ -524,7 +610,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf, static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) { - int ret; + int ret = 0; struct uart_port *port = &priv->port; if (port->x_char) { @@ -533,8 +619,6 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) buf[0] = port->x_char; port->x_char = 0; ret = 1; - } else { - ret = 0; } return ret; @@ -763,7 +847,7 @@ static int dma_handle_rx(struct eg20t_port *priv) sg_dma_address(sg) = priv->rx_buf_dma; - desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx, + desc = dmaengine_prep_slave_sg(priv->chan_rx, sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); @@ -922,7 +1006,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) sg_dma_len(sg) = size; } - desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx, + desc = dmaengine_prep_slave_sg(priv->chan_tx, priv->sg_tx_p, nent, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { @@ -1032,14 +1116,12 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) static unsigned int pch_uart_tx_empty(struct uart_port *port) { struct eg20t_port *priv; - int ret; + priv = container_of(port, struct eg20t_port, port); if (priv->tx_empty) - ret = TIOCSER_TEMT; + return TIOCSER_TEMT; else - ret = 0; - - return ret; + return 0; } /* Returns the current state of modem control inputs. */ @@ -1153,9 +1235,9 @@ static int pch_uart_startup(struct uart_port *port) priv->tx_empty = 1; if (port->uartclk) - priv->base_baud = port->uartclk; + priv->uartclk = port->uartclk; else - port->uartclk = priv->base_baud; + port->uartclk = priv->uartclk; pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT); ret = pch_uart_hal_set_line(priv, default_baud, @@ -1273,9 +1355,8 @@ static void pch_uart_set_termios(struct uart_port *port, else parity = PCH_UART_HAL_PARITY_EVEN; - } else { + } else parity = PCH_UART_HAL_PARITY_NONE; - } /* Only UART0 has auto hardware flow function */ if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256)) @@ -1366,9 +1447,11 @@ static int pch_uart_verify_port(struct uart_port *port, __func__); return -EOPNOTSUPP; #endif - priv->use_dma = 1; priv->use_dma_flag = 1; dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n"); + if (!priv->use_dma) + pch_request_dma(port); + priv->use_dma = 1; } return 0; @@ -1447,7 +1530,6 @@ static void pch_console_write(struct console *co, const char *s, unsigned int count) { struct eg20t_port *priv; - unsigned long flags; u8 ier; int locked = 1; @@ -1489,7 +1571,7 @@ pch_console_write(struct console *co, const char *s, unsigned int count) static int __init pch_console_setup(struct console *co, char *options) { struct uart_port *port; - int baud = 9600; + int baud = default_baud; int bits = 8; int parity = 'n'; int flow = 'n'; @@ -1506,8 +1588,7 @@ static int __init pch_console_setup(struct console *co, char *options) if (!port || (!port->iobase && !port->membase)) return -ENODEV; - /* setup uartclock */ - port->uartclk = DEFAULT_BAUD_RATE; + port->uartclk = pch_uart_get_uartclk(); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -1550,10 +1631,10 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, unsigned int iobase; unsigned int mapbase; unsigned char *rxbuf; - int fifosize, base_baud; + int fifosize; int port_type; struct pch_uart_driver_data *board; - const char *board_name; + char name[32]; /* for debugfs file name */ board = &drv_dat[id->driver_data]; port_type = board->port_type; @@ -1566,13 +1647,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, if (!rxbuf) goto init_port_free_txbuf; - base_baud = DEFAULT_BAUD_RATE; - - /* quirk for CM-iTC board */ - board_name = dmi_get_system_info(DMI_BOARD_NAME); - if (board_name && strstr(board_name, "CM-iTC")) - base_baud = 192000000; /* 192.0MHz */ - switch (port_type) { case PORT_UNKNOWN: fifosize = 256; /* EG20T/ML7213: UART0 */ @@ -1586,6 +1660,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, } pci_enable_msi(pdev); + pci_set_master(pdev); iobase = pci_resource_start(pdev, 0); mapbase = pci_resource_start(pdev, 1); @@ -1597,7 +1672,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, priv->rxbuf.size = PAGE_SIZE; priv->fifo_size = fifosize; - priv->base_baud = base_baud; + priv->uartclk = pch_uart_get_uartclk(); priv->port_type = PORT_MAX_8250 + port_type + 1; priv->port.dev = &pdev->dev; priv->port.iobase = iobase; @@ -1614,7 +1689,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, spin_lock_init(&priv->port.lock); pci_set_drvdata(pdev, priv); - pch_uart_hal_request(pdev, fifosize, base_baud); + priv->trigger_level = 1; + priv->fcr = 0; #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE pch_uart_ports[board->line_no] = priv; @@ -1623,6 +1699,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, if (ret < 0) goto init_port_hal_free; +#ifdef CONFIG_DEBUG_FS + snprintf(name, sizeof(name), "uart%d_regs", board->line_no); + priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO, + NULL, priv, &port_regs_ops); +#endif + return priv; init_port_hal_free: @@ -1639,6 +1721,11 @@ init_port_alloc_err: static void pch_uart_exit_port(struct eg20t_port *priv) { + +#ifdef CONFIG_DEBUG_FS + if (priv->debugfs) + debugfs_remove(priv->debugfs); +#endif uart_remove_one_port(&pch_uart_driver, &priv->port); pci_set_drvdata(priv->pdev, NULL); free_page((unsigned long)priv->rxbuf.buf); @@ -1646,9 +1733,7 @@ static void pch_uart_exit_port(struct eg20t_port *priv) static void pch_uart_pci_remove(struct pci_dev *pdev) { - struct eg20t_port *priv; - - priv = (struct eg20t_port *)pci_get_drvdata(pdev); + struct eg20t_port *priv = pci_get_drvdata(pdev); pci_disable_msi(pdev); @@ -1785,3 +1870,8 @@ module_exit(pch_uart_module_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver"); module_param(default_baud, uint, S_IRUGO); +MODULE_PARM_DESC(default_baud, + "Default BAUD for initial driver state and console (default 9600)"); +module_param(user_uartclk, uint, S_IRUGO); +MODULE_PARM_DESC(user_uartclk, + "Override UART default or board specific UART clock"); diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index e9c2dfe471a2..08ebe901bb59 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1506,7 +1506,7 @@ no_dma: * fixed up interrupt info, but we use the device-tree directly * here due to early probing so we need the fixup too. */ - if (uap->port.irq == NO_IRQ && + if (uap->port.irq == 0 && np->parent && np->parent->parent && of_device_is_compatible(np->parent->parent, "gatwick")) { /* IRQs on gatwick are offset by 64 */ diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 5c8e3bba6c84..5847a4b855f7 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -36,6 +36,7 @@ #include <linux/circ_buf.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/tty.h> #include <linux/tty_flip.h> @@ -44,6 +45,8 @@ #include <linux/io.h> #include <linux/slab.h> +#define PXA_NAME_LEN 8 + struct uart_pxa_port { struct uart_port port; unsigned char ier; @@ -51,7 +54,7 @@ struct uart_pxa_port { unsigned char mcr; unsigned int lsr_break_flag; struct clk *clk; - char *name; + char name[PXA_NAME_LEN]; }; static inline unsigned int serial_in(struct uart_pxa_port *up, int offset) @@ -579,9 +582,9 @@ serial_pxa_pm(struct uart_port *port, unsigned int state, struct uart_pxa_port *up = (struct uart_pxa_port *)port; if (!state) - clk_enable(up->clk); + clk_prepare_enable(up->clk); else - clk_disable(up->clk); + clk_disable_unprepare(up->clk); } static void serial_pxa_release_port(struct uart_port *port) @@ -668,7 +671,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) struct uart_pxa_port *up = serial_pxa_ports[co->index]; unsigned int ier; - clk_enable(up->clk); + clk_prepare_enable(up->clk); /* * First save the IER then disable the interrupts @@ -685,7 +688,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) wait_for_xmitr(up); serial_out(up, UART_IER, ier); - clk_disable(up->clk); + clk_disable_unprepare(up->clk); } static int __init @@ -781,6 +784,31 @@ static const struct dev_pm_ops serial_pxa_pm_ops = { }; #endif +static struct of_device_id serial_pxa_dt_ids[] = { + { .compatible = "mrvl,pxa-uart", }, + { .compatible = "mrvl,mmp-uart", }, + {} +}; +MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids); + +static int serial_pxa_probe_dt(struct platform_device *pdev, + struct uart_pxa_port *sport) +{ + struct device_node *np = pdev->dev.of_node; + int ret; + + if (!np) + return 1; + + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); + return ret; + } + sport->port.line = ret; + return 0; +} + static int serial_pxa_probe(struct platform_device *dev) { struct uart_pxa_port *sport; @@ -808,20 +836,16 @@ static int serial_pxa_probe(struct platform_device *dev) sport->port.irq = irqres->start; sport->port.fifosize = 64; sport->port.ops = &serial_pxa_pops; - sport->port.line = dev->id; sport->port.dev = &dev->dev; sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; sport->port.uartclk = clk_get_rate(sport->clk); - switch (dev->id) { - case 0: sport->name = "FFUART"; break; - case 1: sport->name = "BTUART"; break; - case 2: sport->name = "STUART"; break; - case 3: sport->name = "HWUART"; break; - default: - sport->name = "???"; - break; - } + ret = serial_pxa_probe_dt(dev, sport); + if (ret > 0) + sport->port.line = dev->id; + else if (ret < 0) + goto err_clk; + snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1); sport->port.membase = ioremap(mmres->start, resource_size(mmres)); if (!sport->port.membase) { @@ -829,7 +853,7 @@ static int serial_pxa_probe(struct platform_device *dev) goto err_clk; } - serial_pxa_ports[dev->id] = sport; + serial_pxa_ports[sport->port.line] = sport; uart_add_one_port(&serial_pxa_reg, &sport->port); platform_set_drvdata(dev, sport); @@ -866,6 +890,7 @@ static struct platform_driver serial_pxa_driver = { #ifdef CONFIG_PM .pm = &serial_pxa_pm_ops, #endif + .of_match_table = serial_pxa_dt_ids, }, }; diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index ef7a21a6a01b..2ca5959ec3fa 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -38,6 +38,7 @@ #include <asm/irq.h> #include <mach/hardware.h> +#include <mach/irqs.h> #include <asm/mach/serial_sa1100.h> /* We've been assigned a range on the "Low-density serial ports" major */ diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index c55e5fb16fa3..d8b0aee35632 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -982,6 +982,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, ucon &= ucon_mask; wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); /* reset both fifos */ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); @@ -1507,7 +1508,7 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { #endif #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \ - defined(CONFIG_CPU_S3C2443) + defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442) static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { .info = &(struct s3c24xx_uart_info) { .name = "Samsung S3C2440 UART", diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 13056180adf5..9c4c05b2825b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2230,7 +2230,6 @@ int uart_register_driver(struct uart_driver *drv) drv->tty_driver = normal; - normal->owner = drv->owner; normal->driver_name = drv->driver_name; normal->name = drv->dev_name; normal->major = drv->major; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 75085795528e..3158e17b665c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -355,9 +355,6 @@ static void sci_serial_out(struct uart_port *p, int offset, int value) WARN(1, "Invalid register access\n"); } -#define sci_in(up, offset) (up->serial_in(up, offset)) -#define sci_out(up, offset, value) (up->serial_out(up, offset, value)) - static int sci_probe_regmap(struct plat_sci_port *cfg) { switch (cfg->type) { @@ -422,9 +419,9 @@ static int sci_poll_get_char(struct uart_port *port) int c; do { - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); if (status & SCxSR_ERRORS(port)) { - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); continue; } break; @@ -433,11 +430,11 @@ static int sci_poll_get_char(struct uart_port *port) if (!(status & SCxSR_RDxF(port))) return NO_POLL_CHAR; - c = sci_in(port, SCxRDR); + c = serial_port_in(port, SCxRDR); /* Dummy read */ - sci_in(port, SCxSR); - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); return c; } @@ -448,11 +445,11 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) unsigned short status; do { - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); } while (!(status & SCxSR_TDxE(port))); - sci_out(port, SCxTDR, c); - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); + serial_port_out(port, SCxTDR, c); + serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); } #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ @@ -480,10 +477,10 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) ((!(cflag & CRTSCTS)))) { unsigned short status; - status = sci_in(port, SCSPTR); + status = serial_port_in(port, SCSPTR); status &= ~SCSPTR_CTSIO; status |= SCSPTR_RTSIO; - sci_out(port, SCSPTR, status); /* Set RTS = 1 */ + serial_port_out(port, SCSPTR, status); /* Set RTS = 1 */ } } @@ -493,13 +490,13 @@ static int sci_txfill(struct uart_port *port) reg = sci_getreg(port, SCTFDR); if (reg->size) - return sci_in(port, SCTFDR) & 0xff; + return serial_port_in(port, SCTFDR) & 0xff; reg = sci_getreg(port, SCFDR); if (reg->size) - return sci_in(port, SCFDR) >> 8; + return serial_port_in(port, SCFDR) >> 8; - return !(sci_in(port, SCxSR) & SCI_TDRE); + return !(serial_port_in(port, SCxSR) & SCI_TDRE); } static int sci_txroom(struct uart_port *port) @@ -513,13 +510,13 @@ static int sci_rxfill(struct uart_port *port) reg = sci_getreg(port, SCRFDR); if (reg->size) - return sci_in(port, SCRFDR) & 0xff; + return serial_port_in(port, SCRFDR) & 0xff; reg = sci_getreg(port, SCFDR); if (reg->size) - return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1); + return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1); - return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; + return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; } /* @@ -547,14 +544,14 @@ static void sci_transmit_chars(struct uart_port *port) unsigned short ctrl; int count; - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); if (!(status & SCxSR_TDxE(port))) { - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (uart_circ_empty(xmit)) ctrl &= ~SCSCR_TIE; else ctrl |= SCSCR_TIE; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); return; } @@ -573,27 +570,27 @@ static void sci_transmit_chars(struct uart_port *port) break; } - sci_out(port, SCxTDR, c); + serial_port_out(port, SCxTDR, c); port->icount.tx++; } while (--count > 0); - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit)) { sci_stop_tx(port); } else { - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (port->type != PORT_SCI) { - sci_in(port, SCxSR); /* Dummy read */ - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + serial_port_in(port, SCxSR); /* Dummy read */ + serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } ctrl |= SCSCR_TIE; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } } @@ -608,7 +605,7 @@ static void sci_receive_chars(struct uart_port *port) unsigned short status; unsigned char flag; - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); if (!(status & SCxSR_RDxF(port))) return; @@ -621,7 +618,7 @@ static void sci_receive_chars(struct uart_port *port) break; if (port->type == PORT_SCI) { - char c = sci_in(port, SCxRDR); + char c = serial_port_in(port, SCxRDR); if (uart_handle_sysrq_char(port, c) || sci_port->break_flag) count = 0; @@ -629,9 +626,9 @@ static void sci_receive_chars(struct uart_port *port) tty_insert_flip_char(tty, c, TTY_NORMAL); } else { for (i = 0; i < count; i++) { - char c = sci_in(port, SCxRDR); + char c = serial_port_in(port, SCxRDR); - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); #if defined(CONFIG_CPU_SH3) /* Skip "chars" during break */ if (sci_port->break_flag) { @@ -672,8 +669,8 @@ static void sci_receive_chars(struct uart_port *port) } } - sci_in(port, SCxSR); /* dummy read */ - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); /* dummy read */ + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); copied += count; port->icount.rx += count; @@ -683,8 +680,8 @@ static void sci_receive_chars(struct uart_port *port) /* Tell the rest of the system the news. New characters! */ tty_flip_buffer_push(tty); } else { - sci_in(port, SCxSR); /* dummy read */ - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); /* dummy read */ + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } } @@ -726,7 +723,7 @@ static void sci_break_timer(unsigned long data) static int sci_handle_errors(struct uart_port *port) { int copied = 0; - unsigned short status = sci_in(port, SCxSR); + unsigned short status = serial_port_in(port, SCxSR); struct tty_struct *tty = port->state->port.tty; struct sci_port *s = to_sci_port(port); @@ -804,8 +801,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port) if (!reg->size) return 0; - if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { - sci_out(port, SCLSR, 0); + if ((serial_port_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { + serial_port_out(port, SCLSR, 0); port->icount.overrun++; @@ -822,7 +819,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port) static int sci_handle_breaks(struct uart_port *port) { int copied = 0; - unsigned short status = sci_in(port, SCxSR); + unsigned short status = serial_port_in(port, SCxSR); struct tty_struct *tty = port->state->port.tty; struct sci_port *s = to_sci_port(port); @@ -859,8 +856,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) struct sci_port *s = to_sci_port(port); if (s->chan_rx) { - u16 scr = sci_in(port, SCSCR); - u16 ssr = sci_in(port, SCxSR); + u16 scr = serial_port_in(port, SCSCR); + u16 ssr = serial_port_in(port, SCxSR); /* Disable future Rx interrupts */ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { @@ -869,9 +866,9 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) } else { scr &= ~SCSCR_RIE; } - sci_out(port, SCSCR, scr); + serial_port_out(port, SCSCR, scr); /* Clear current interrupt */ - sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); + serial_port_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", jiffies, s->rx_timeout); mod_timer(&s->rx_timer, jiffies + s->rx_timeout); @@ -909,15 +906,15 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr) if (port->type == PORT_SCI) { if (sci_handle_errors(port)) { /* discard character in rx buffer */ - sci_in(port, SCxSR); - sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); + serial_port_in(port, SCxSR); + serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } } else { sci_handle_fifo_overrun(port); sci_rx_interrupt(irq, ptr); } - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Kick the transmission */ sci_tx_interrupt(irq, ptr); @@ -931,7 +928,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) /* Handle BREAKs */ sci_handle_breaks(port); - sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); + serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); return IRQ_HANDLED; } @@ -955,8 +952,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) struct sci_port *s = to_sci_port(port); irqreturn_t ret = IRQ_NONE; - ssr_status = sci_in(port, SCxSR); - scr_status = sci_in(port, SCSCR); + ssr_status = serial_port_in(port, SCxSR); + scr_status = serial_port_in(port, SCSCR); err_enabled = scr_status & port_rx_irq_mask(port); /* Tx Interrupt */ @@ -1170,7 +1167,7 @@ static void sci_free_gpios(struct sci_port *port) static unsigned int sci_tx_empty(struct uart_port *port) { - unsigned short status = sci_in(port, SCxSR); + unsigned short status = serial_port_in(port, SCxSR); unsigned short in_tx_fifo = sci_txfill(port); return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; @@ -1198,7 +1195,7 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) */ reg = sci_getreg(port, SCFCR); if (reg->size) - sci_out(port, SCFCR, sci_in(port, SCFCR) | 1); + serial_port_out(port, SCFCR, serial_port_in(port, SCFCR) | 1); } } @@ -1229,17 +1226,20 @@ static void sci_dma_tx_complete(void *arg) port->icount.tx += sg_dma_len(&s->sg_tx); async_tx_ack(s->desc_tx); - s->cookie_tx = -EINVAL; s->desc_tx = NULL; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (!uart_circ_empty(xmit)) { + s->cookie_tx = 0; schedule_work(&s->work_tx); - } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { - u16 ctrl = sci_in(port, SCSCR); - sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); + } else { + s->cookie_tx = -EINVAL; + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { + u16 ctrl = serial_port_in(port, SCSCR); + serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE); + } } spin_unlock_irqrestore(&port->lock, flags); @@ -1338,7 +1338,7 @@ static void sci_submit_rx(struct sci_port *s) struct scatterlist *sg = &s->sg_rx[i]; struct dma_async_tx_descriptor *desc; - desc = chan->device->device_prep_slave_sg(chan, + desc = dmaengine_prep_slave_sg(chan, sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (desc) { @@ -1453,7 +1453,7 @@ static void work_fn_tx(struct work_struct *work) BUG_ON(!sg_dma_len(sg)); - desc = chan->device->device_prep_slave_sg(chan, + desc = dmaengine_prep_slave_sg(chan, sg, s->sg_len_tx, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { @@ -1491,24 +1491,26 @@ static void sci_start_tx(struct uart_port *port) #ifdef CONFIG_SERIAL_SH_SCI_DMA if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { - u16 new, scr = sci_in(port, SCSCR); + u16 new, scr = serial_port_in(port, SCSCR); if (s->chan_tx) new = scr | 0x8000; else new = scr & ~0x8000; if (new != scr) - sci_out(port, SCSCR, new); + serial_port_out(port, SCSCR, new); } if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && - s->cookie_tx < 0) + s->cookie_tx < 0) { + s->cookie_tx = 0; schedule_work(&s->work_tx); + } #endif if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ - ctrl = sci_in(port, SCSCR); - sci_out(port, SCSCR, ctrl | SCSCR_TIE); + ctrl = serial_port_in(port, SCSCR); + serial_port_out(port, SCSCR, ctrl | SCSCR_TIE); } } @@ -1517,40 +1519,40 @@ static void sci_stop_tx(struct uart_port *port) unsigned short ctrl; /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x8000; ctrl &= ~SCSCR_TIE; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } static void sci_start_rx(struct uart_port *port) { unsigned short ctrl; - ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port); + ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x4000; - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } static void sci_stop_rx(struct uart_port *port) { unsigned short ctrl; - ctrl = sci_in(port, SCSCR); + ctrl = serial_port_in(port, SCSCR); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x4000; ctrl &= ~port_rx_irq_mask(port); - sci_out(port, SCSCR, ctrl); + serial_port_out(port, SCSCR, ctrl); } static void sci_enable_ms(struct uart_port *port) @@ -1584,13 +1586,13 @@ static void rx_timer_fn(unsigned long arg) { struct sci_port *s = (struct sci_port *)arg; struct uart_port *port = &s->port; - u16 scr = sci_in(port, SCSCR); + u16 scr = serial_port_in(port, SCSCR); if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { scr &= ~0x4000; enable_irq(s->cfg->irqs[1]); } - sci_out(port, SCSCR, scr | SCSCR_RIE); + serial_port_out(port, SCSCR, scr | SCSCR_RIE); dev_dbg(port->dev, "DMA Rx timed out\n"); schedule_work(&s->work_rx); } @@ -1710,6 +1712,8 @@ static int sci_startup(struct uart_port *port) dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); + pm_runtime_put_noidle(port->dev); + sci_port_enable(s); ret = sci_request_irq(s); @@ -1737,6 +1741,8 @@ static void sci_shutdown(struct uart_port *port) sci_free_irq(s); sci_port_disable(s); + + pm_runtime_get_noresume(port->dev); } static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, @@ -1767,14 +1773,14 @@ static void sci_reset(struct uart_port *port) unsigned int status; do { - status = sci_in(port, SCxSR); + status = serial_port_in(port, SCxSR); } while (!(status & SCxSR_TEND(port))); - sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ + serial_port_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ reg = sci_getreg(port, SCFCR); if (reg->size) - sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); + serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); } static void sci_set_termios(struct uart_port *port, struct ktermios *termios, @@ -1803,7 +1809,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_reset(port); - smr_val = sci_in(port, SCSMR) & 3; + smr_val = serial_port_in(port, SCSMR) & 3; if ((termios->c_cflag & CSIZE) == CS7) smr_val |= 0x40; @@ -1816,19 +1822,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, uart_update_timeout(port, termios->c_cflag, baud); - sci_out(port, SCSMR, smr_val); + serial_port_out(port, SCSMR, smr_val); dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, s->cfg->scscr); if (t > 0) { if (t >= 256) { - sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); + serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1); t >>= 2; } else - sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3); + serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3); - sci_out(port, SCBRR, t); + serial_port_out(port, SCBRR, t); udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ } @@ -1836,7 +1842,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, reg = sci_getreg(port, SCFCR); if (reg->size) { - unsigned short ctrl = sci_in(port, SCFCR); + unsigned short ctrl = serial_port_in(port, SCFCR); if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) { if (termios->c_cflag & CRTSCTS) @@ -1852,10 +1858,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, */ ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST); - sci_out(port, SCFCR, ctrl); + serial_port_out(port, SCFCR, ctrl); } - sci_out(port, SCSCR, s->cfg->scscr); + serial_port_out(port, SCSCR, s->cfg->scscr); #ifdef CONFIG_SERIAL_SH_SCI_DMA /* @@ -2075,6 +2081,7 @@ static int __devinit sci_init_single(struct platform_device *dev, sci_init_gpios(sci_port); pm_runtime_irq_safe(&dev->dev); + pm_runtime_get_noresume(&dev->dev); pm_runtime_enable(&dev->dev); } @@ -2156,7 +2163,7 @@ static void serial_console_write(struct console *co, const char *s, /* wait until fifo is empty and last bit has been transmitted */ bits = SCxSR_TDxE(port) | SCxSR_TEND(port); - while ((sci_in(port, SCxSR) & bits) != bits) + while ((serial_port_in(port, SCxSR) & bits) != bits) cpu_relax(); sci_port_disable(sci_port); @@ -2250,12 +2257,12 @@ static int sci_runtime_suspend(struct device *dev) if (uart_console(port)) { struct plat_sci_reg *reg; - sci_port->saved_smr = sci_in(port, SCSMR); - sci_port->saved_brr = sci_in(port, SCBRR); + sci_port->saved_smr = serial_port_in(port, SCSMR); + sci_port->saved_brr = serial_port_in(port, SCBRR); reg = sci_getreg(port, SCFCR); if (reg->size) - sci_port->saved_fcr = sci_in(port, SCFCR); + sci_port->saved_fcr = serial_port_in(port, SCFCR); else sci_port->saved_fcr = 0; } @@ -2269,13 +2276,13 @@ static int sci_runtime_resume(struct device *dev) if (uart_console(port)) { sci_reset(port); - sci_out(port, SCSMR, sci_port->saved_smr); - sci_out(port, SCBRR, sci_port->saved_brr); + serial_port_out(port, SCSMR, sci_port->saved_smr); + serial_port_out(port, SCBRR, sci_port->saved_brr); if (sci_port->saved_fcr) - sci_out(port, SCFCR, sci_port->saved_fcr); + serial_port_out(port, SCFCR, sci_port->saved_fcr); - sci_out(port, SCSCR, sci_port->cfg->scscr); + serial_port_out(port, SCSCR, sci_port->cfg->scscr); } return 0; } diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index a1a2d364f92b..4c22a1529aac 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -20,10 +20,10 @@ defined(CONFIG_ARCH_SH7372) || \ defined(CONFIG_ARCH_R8A7740) -# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc) -# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) -# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf) -# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3) +# define SCxSR_RDxF_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfffc) +# define SCxSR_ERROR_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfd73) +# define SCxSR_TDxE_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffdf) +# define SCxSR_BREAK_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffe3) #else # define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc) # define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073) diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index a60523fee11b..5b3eda2024fe 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -22,7 +22,7 @@ #include <linux/io.h> #include <asm/irq.h> #include <asm/mach/irq.h> -#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/consumer.h> #include "sirfsoc_uart.h" @@ -673,12 +673,10 @@ int sirfsoc_uart_probe(struct platform_device *pdev) port->irq = res->start; if (sirfport->hw_flow_ctrl) { - sirfport->pmx = pinmux_get(&pdev->dev, NULL); - ret = IS_ERR(sirfport->pmx); + sirfport->p = pinctrl_get_select_default(&pdev->dev); + ret = IS_ERR(sirfport->p); if (ret) - goto pmx_err; - - pinmux_enable(sirfport->pmx); + goto pin_err; } port->ops = &sirfsoc_uart_ops; @@ -695,11 +693,9 @@ int sirfsoc_uart_probe(struct platform_device *pdev) port_err: platform_set_drvdata(pdev, NULL); - if (sirfport->hw_flow_ctrl) { - pinmux_disable(sirfport->pmx); - pinmux_put(sirfport->pmx); - } -pmx_err: + if (sirfport->hw_flow_ctrl) + pinctrl_put(sirfport->p); +pin_err: irq_err: devm_iounmap(&pdev->dev, port->membase); err: @@ -711,10 +707,8 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); struct uart_port *port = &sirfport->port; platform_set_drvdata(pdev, NULL); - if (sirfport->hw_flow_ctrl) { - pinmux_disable(sirfport->pmx); - pinmux_put(sirfport->pmx); - } + if (sirfport->hw_flow_ctrl) + pinctrl_put(sirfport->p); devm_iounmap(&pdev->dev, port->membase); uart_remove_one_port(&sirfsoc_uart_drv, port); return 0; diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index fc64260fa93c..6e207fdc2fed 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -162,7 +162,7 @@ struct sirfsoc_uart_port { unsigned char ms_enabled; struct uart_port port; - struct pinmux *pmx; + struct pinctrl *p; }; /* Hardware Flow Control */ diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c index 238c7df73ef5..1c6de9f58699 100644 --- a/drivers/tty/serial/sn_console.c +++ b/drivers/tty/serial/sn_console.c @@ -461,12 +461,12 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) struct tty_struct *tty; if (!port) { - printk(KERN_ERR "sn_receive_chars - port NULL so can't receieve\n"); + printk(KERN_ERR "sn_receive_chars - port NULL so can't receive\n"); return; } if (!port->sc_ops) { - printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receieve\n"); + printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receive\n"); return; } @@ -743,6 +743,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) spin_lock_irqsave(&port->sc_port.lock, flags); port->sc_port.irq = SGI_UART_VECTOR; port->sc_ops = &intr_ops; + irq_set_handler(port->sc_port.irq, handle_level_irq); /* turn on receive interrupts */ ia64_sn_console_intr_enable(SAL_CONSOLE_INTR_RECV); diff --git a/drivers/tty/serial/suncore.c b/drivers/tty/serial/suncore.c index 6381a0282ee7..6e4ac8db2d79 100644 --- a/drivers/tty/serial/suncore.c +++ b/drivers/tty/serial/suncore.c @@ -17,11 +17,11 @@ #include <linux/errno.h> #include <linux/string.h> #include <linux/serial_core.h> +#include <linux/sunserialcore.h> #include <linux/init.h> #include <asm/prom.h> -#include "suncore.h" static int sunserial_current_minor = 64; diff --git a/drivers/tty/serial/suncore.h b/drivers/tty/serial/suncore.h deleted file mode 100644 index db2057936c31..000000000000 --- a/drivers/tty/serial/suncore.h +++ /dev/null @@ -1,33 +0,0 @@ -/* suncore.h - * - * Generic SUN serial/kbd/ms layer. Based entirely - * upon drivers/sbus/char/sunserial.h which is: - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * - * Port to new UART layer is: - * - * Copyright (C) 2002 David S. Miller (davem@redhat.com) - */ - -#ifndef _SERIAL_SUN_H -#define _SERIAL_SUN_H - -/* Serial keyboard defines for L1-A processing... */ -#define SUNKBD_RESET 0xff -#define SUNKBD_L1 0x01 -#define SUNKBD_UP 0x80 -#define SUNKBD_A 0x4d - -extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *); -extern int suncore_mouse_baud_detection(unsigned char, int); - -extern int sunserial_register_minors(struct uart_driver *, int); -extern void sunserial_unregister_minors(struct uart_driver *, int); - -extern int sunserial_console_match(struct console *, struct device_node *, - struct uart_driver *, int, bool); -extern void sunserial_console_termios(struct console *, - struct device_node *); - -#endif /* !(_SERIAL_SUN_H) */ diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index c0b7246d7339..505961cfd934 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -23,14 +23,14 @@ #include <asm/spitfire.h> #include <asm/prom.h> #include <asm/irq.h> +#include <asm/setup.h> #if defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif #include <linux/serial_core.h> - -#include "suncore.h" +#include <linux/sunserialcore.h> #define CON_BREAK ((long)-1) #define CON_HUP ((long)-2) diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index b5fa2a57b9da..f0d93eb7e6ec 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -37,14 +37,15 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/prom.h> +#include <asm/setup.h> #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif #include <linux/serial_core.h> +#include <linux/sunserialcore.h> -#include "suncore.h" #include "sunsab.h" struct uart_sunsab_port { diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index ad0f8f5f6ea1..675303b8ed84 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -41,14 +41,14 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/prom.h> +#include <asm/setup.h> #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif #include <linux/serial_core.h> - -#include "suncore.h" +#include <linux/sunserialcore.h> /* We are on a NS PC87303 clocked with 24.0 MHz, which results * in a UART clock of 1.8462 MHz. diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 8e916e76b7b5..babd9470982b 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -37,14 +37,15 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/prom.h> +#include <asm/setup.h> #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif #include <linux/serial_core.h> +#include <linux/sunserialcore.h> -#include "suncore.h" #include "sunzilog.h" /* On 32-bit sparcs we need to delay after register accesses @@ -1397,7 +1398,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) #endif } -static int zilog_irq = -1; +static int zilog_irq; static int __devinit zs_probe(struct platform_device *op) { @@ -1425,7 +1426,7 @@ static int __devinit zs_probe(struct platform_device *op) rp = sunzilog_chip_regs[inst]; - if (zilog_irq == -1) + if (!zilog_irq) zilog_irq = op->archdata.irqs[0]; up = &sunzilog_port_table[inst * 2]; @@ -1580,7 +1581,7 @@ static int __init sunzilog_init(void) if (err) goto out_unregister_uart; - if (zilog_irq != -1) { + if (zilog_irq) { struct uart_sunzilog_port *up = sunzilog_irq_chain; err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, "zs", sunzilog_irq_chain); @@ -1621,7 +1622,7 @@ static void __exit sunzilog_exit(void) { platform_driver_unregister(&zs_driver); - if (zilog_irq != -1) { + if (zilog_irq) { struct uart_sunzilog_port *up = sunzilog_irq_chain; /* Disable Interrupts */ @@ -1637,7 +1638,7 @@ static void __exit sunzilog_exit(void) } free_irq(zilog_irq, sunzilog_irq_chain); - zilog_irq = -1; + zilog_irq = 0; } if (sunzilog_reg.nr) { diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 2ebe606a2db1..f99b0c965f85 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -1360,7 +1360,7 @@ static int ucc_uart_probe(struct platform_device *ofdev) } qe_port->port.irq = irq_of_parse_and_map(np, 0); - if (qe_port->port.irq == NO_IRQ) { + if (qe_port->port.irq == 0) { dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n", qe_port->ucc_num + 1); ret = -EINVAL; diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index 83148e79ca13..cf0d9485ec08 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c @@ -61,7 +61,7 @@ static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { [0 ... SIU_PORTS_MAX-1] = { .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), - .irq = -1, + .irq = 0, }, }; @@ -171,7 +171,7 @@ static inline unsigned int siu_check_type(struct uart_port *port) { if (port->line == 0) return PORT_VR41XX_SIU; - if (port->line == 1 && port->irq != -1) + if (port->line == 1 && port->irq) return PORT_VR41XX_DSIU; return PORT_UNKNOWN; diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 026cb9ea5cd1..2be006fb3da0 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -544,7 +544,7 @@ static struct uart_driver vt8500_uart_driver = { .cons = VT8500_CONSOLE, }; -static int __init vt8500_serial_probe(struct platform_device *pdev) +static int __devinit vt8500_serial_probe(struct platform_device *pdev) { struct vt8500_port *vt8500_port; struct resource *mmres, *irqres; @@ -605,7 +605,7 @@ static int __devexit vt8500_serial_remove(struct platform_device *pdev) static struct platform_driver vt8500_platform_driver = { .probe = vt8500_serial_probe, - .remove = vt8500_serial_remove, + .remove = __devexit_p(vt8500_serial_remove), .driver = { .name = "vt8500_serial", .owner = THIS_MODULE, diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index b7455b526080..4001eee6c08d 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -67,7 +67,6 @@ #include <linux/types.h> #include <linux/atomic.h> -#include <asm/system.h> #include <asm/dec/interrupts.h> #include <asm/dec/ioasic_addrs.h> |