diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/21285.c | 14 | ||||
-rw-r--r-- | drivers/serial/8250.c | 32 | ||||
-rw-r--r-- | drivers/serial/amba-pl010.c | 14 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 14 | ||||
-rw-r--r-- | drivers/serial/clps711x.c | 5 | ||||
-rw-r--r-- | drivers/serial/pxa.c | 16 | ||||
-rw-r--r-- | drivers/serial/s3c2410.c | 15 | ||||
-rw-r--r-- | drivers/serial/sa1100.c | 5 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 4 | ||||
-rw-r--r-- | drivers/serial/serial_lh7a40x.c | 13 | ||||
-rw-r--r-- | drivers/serial/serial_txx9.c | 15 | ||||
-rw-r--r-- | drivers/serial/sunsab.c | 109 | ||||
-rw-r--r-- | drivers/serial/sunsab.h | 1 | ||||
-rw-r--r-- | drivers/serial/vr41xx_siu.c | 6 |
14 files changed, 108 insertions, 155 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 33fbda79f35..0b10169961e 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -126,18 +126,8 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r flag = TTY_FRAME; } - if ((rxs & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((rxs & RXSTAT_OVERRUN) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag); + status = *CSR_UARTFLG; } tty_flip_buffer_push(tty); diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 0d9358608fd..30e8beb7143 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -682,8 +682,6 @@ static void autoconfig_16550a(struct uart_8250_port *up) * from EXCR1. Switch back to bank 0, change it in MCR. Then * 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 - * On PowerPC we don't want to change baud_base, as we have - * a number of different divisors. -- Tom Rini */ serial_outp(up, UART_LCR, 0); status1 = serial_in(up, UART_MCR); @@ -699,16 +697,25 @@ static void autoconfig_16550a(struct uart_8250_port *up) serial_outp(up, UART_MCR, status1); if ((status2 ^ status1) & UART_MCR_LOOP) { -#ifndef CONFIG_PPC + unsigned short quot; + serial_outp(up, UART_LCR, 0xE0); + + quot = serial_inp(up, UART_DLM) << 8; + quot += serial_inp(up, UART_DLL); + quot <<= 3; + status1 = serial_in(up, 0x04); /* EXCR1 */ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ serial_outp(up, 0x04, status1); + + serial_outp(up, UART_DLL, quot & 0xff); + serial_outp(up, UART_DLM, quot >> 8); + serial_outp(up, UART_LCR, 0); - up->port.uartclk = 921600*16; -#endif + up->port.uartclk = 921600*16; up->port.type = PORT_NS16550A; up->capabilities |= UART_NATSEMI; return; @@ -1122,18 +1129,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((lsr & up->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((lsr & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + + uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); + ignore_char: lsr = serial_inp(up, UART_LSR); } while ((lsr & UART_LSR_DR) && (max_count-- > 0)); diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index f2a5e2933c4..2884b310e54 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -198,18 +198,8 @@ pl010_rx_chars(struct uart_port *port) if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - if ((rsr & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((rsr & UART01x_RSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); + ignore_char: status = UART_GET_FR(port); } diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index d5cbef3fe8b..7db88ee18f7 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -163,18 +163,8 @@ pl011_rx_chars(struct uart_amba_port *uap) if (uart_handle_sysrq_char(&uap->port, ch, regs)) goto ignore_char; - if ((rsr & uap->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((rsr & UART01x_RSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); + ignore_char: status = readw(uap->port.membase + UART01x_FR); } diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 6242f3090a9..e92522b33c4 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -143,10 +143,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re * CHECK: does overrun affect the current character? * ASSUMPTION: it does not. */ - if ((ch & port->ignore_status_mask & ~RXSTAT_OVERRUN) == 0) - tty_insert_flip_char(tty, ch, flg); - if ((ch & ~port->ignore_status_mask & RXSTAT_OVERRUN) == 0) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + uart_insert_char(port, ch, UARTDR_OVERR, ch, flg); ignore_char: status = clps_readl(SYSFLG(port)); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 51d8a49f447..9dc151d8fa6 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -161,20 +161,12 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) else if (*status & UART_LSR_FE) flag = TTY_FRAME; } + if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((*status & up->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((*status & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + + uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); + ignore_char: *status = serial_in(up, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 435750d40a4..2a9f7ade2c9 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -394,20 +394,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - if ((uerstat & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - - if ((uerstat & S3C2410_UERSTAT_OVERRUN) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag); ignore_char: continue; diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 157218bc6c6..22565a67a57 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -237,10 +237,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; - if ((status & port->ignore_status_mask & ~UTSR1_TO_SM(UTSR1_ROR)) == 0) - tty_insert_flip_char(tty, ch, flg); - if (status & ~port->ignore_status_mask & UTSR1_TO_SM(UTSR1_ROR)) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 6eeb48f6a48..0d7b65f93e8 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -661,10 +661,10 @@ void serial_config(dev_link_t * link) /* Is this a multiport card? */ tuple->DesiredTuple = CISTPL_MANFID; if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { - info->manfid = le16_to_cpu(buf[0]); + info->manfid = parse->manfid.manf; for (i = 0; i < MULTI_COUNT; i++) if ((info->manfid == multi_id[i].manfid) && - (le16_to_cpu(buf[1]) == multi_id[i].prodid)) + (parse->manfid.card == multi_id[i].prodid)) break; if (i < MULTI_COUNT) info->multi = multi_id[i].multi; diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 85cfa08d3ba..56f269b6bfb 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -190,18 +190,7 @@ lh7a40xuart_rx_chars (struct uart_port* port) if (uart_handle_sysrq_char (port, (unsigned char) data, regs)) continue; - if ((data & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, data, flag); - } - if ((data & RxOverrunError) - && tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, data, RxOverrunError, data, flag); } tty_flip_buffer_push (tty); return; diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 37b2ef297cb..3f1051a4a13 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -350,18 +350,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((disr & up->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((disr & TXX9_SIDISR_UOER) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + + uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag); + ignore_char: disr = sio_in(up, TXX9_SIDISR); } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 39b788d95e3..10e2990a40d 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -61,6 +61,16 @@ struct uart_sunsab_port { unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */ unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */ int type; /* SAB82532 version */ + + /* Setting configuration bits while the transmitter is active + * can cause garbage characters to get emitted by the chip. + * Therefore, we cache such writes here and do the real register + * write the next time the transmitter becomes idle. + */ + unsigned int cached_ebrg; + unsigned char cached_mode; + unsigned char cached_pvr; + unsigned char cached_dafo; }; /* @@ -236,6 +246,7 @@ receive_chars(struct uart_sunsab_port *up, } static void sunsab_stop_tx(struct uart_port *, unsigned int); +static void sunsab_tx_idle(struct uart_sunsab_port *); static void transmit_chars(struct uart_sunsab_port *up, union sab82532_irq_status *stat) @@ -258,6 +269,7 @@ static void transmit_chars(struct uart_sunsab_port *up, return; set_bit(SAB82532_XPR, &up->irqflags); + sunsab_tx_idle(up); if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { up->interrupt_mask1 |= SAB82532_IMR1_XPR; @@ -397,21 +409,21 @@ static void sunsab_set_mctrl(struct uart_port *port, unsigned int mctrl) struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; if (mctrl & TIOCM_RTS) { - writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); + up->cached_mode &= ~SAB82532_MODE_FRTS; + up->cached_mode |= SAB82532_MODE_RTS; } else { - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); + up->cached_mode |= (SAB82532_MODE_FRTS | + SAB82532_MODE_RTS); } if (mctrl & TIOCM_DTR) { - writeb(readb(&up->regs->rw.pvr) & ~(up->pvr_dtr_bit), &up->regs->rw.pvr); + up->cached_pvr &= ~(up->pvr_dtr_bit); } else { - writeb(readb(&up->regs->rw.pvr) | up->pvr_dtr_bit, &up->regs->rw.pvr); + up->cached_pvr |= up->pvr_dtr_bit; } + + set_bit(SAB82532_REGS_PENDING, &up->irqflags); + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); } /* port->lock is not held. */ @@ -450,6 +462,25 @@ static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop) } /* port->lock held by caller. */ +static void sunsab_tx_idle(struct uart_sunsab_port *up) +{ + if (test_bit(SAB82532_REGS_PENDING, &up->irqflags)) { + u8 tmp; + + clear_bit(SAB82532_REGS_PENDING, &up->irqflags); + writeb(up->cached_mode, &up->regs->rw.mode); + writeb(up->cached_pvr, &up->regs->rw.pvr); + writeb(up->cached_dafo, &up->regs->w.dafo); + + writeb(up->cached_ebrg & 0xff, &up->regs->w.bgr); + tmp = readb(&up->regs->rw.ccr2); + tmp &= ~0xc0; + tmp |= (up->cached_ebrg >> 2) & 0xc0; + writeb(tmp, &up->regs->rw.ccr2); + } +} + +/* port->lock held by caller. */ static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; @@ -517,12 +548,16 @@ static void sunsab_break_ctl(struct uart_port *port, int break_state) spin_lock_irqsave(&up->port.lock, flags); - val = readb(&up->regs->rw.dafo); + val = up->cached_dafo; if (break_state) val |= SAB82532_DAFO_XBRK; else val &= ~SAB82532_DAFO_XBRK; - writeb(val, &up->regs->rw.dafo); + up->cached_dafo = val; + + set_bit(SAB82532_REGS_PENDING, &up->irqflags); + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -566,8 +601,9 @@ static int sunsab_startup(struct uart_port *port) SAB82532_CCR2_TOE, &up->regs->w.ccr2); writeb(0, &up->regs->w.ccr3); writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4); - writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS | - SAB82532_MODE_RAC, &up->regs->w.mode); + up->cached_mode = (SAB82532_MODE_RTS | SAB82532_MODE_FCTS | + SAB82532_MODE_RAC); + writeb(up->cached_mode, &up->regs->w.mode); writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc); tmp = readb(&up->regs->rw.ccr0); @@ -598,7 +634,6 @@ static void sunsab_shutdown(struct uart_port *port) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; - unsigned char tmp; spin_lock_irqsave(&up->port.lock, flags); @@ -609,14 +644,13 @@ static void sunsab_shutdown(struct uart_port *port) writeb(up->interrupt_mask1, &up->regs->w.imr1); /* Disable break condition */ - tmp = readb(&up->regs->rw.dafo); - tmp &= ~SAB82532_DAFO_XBRK; - writeb(tmp, &up->regs->rw.dafo); + up->cached_dafo = readb(&up->regs->rw.dafo); + up->cached_dafo &= ~SAB82532_DAFO_XBRK; + writeb(up->cached_dafo, &up->regs->rw.dafo); /* Disable Receiver */ - tmp = readb(&up->regs->rw.mode); - tmp &= ~SAB82532_MODE_RAC; - writeb(tmp, &up->regs->rw.mode); + up->cached_mode &= ~SAB82532_MODE_RAC; + writeb(up->cached_mode, &up->regs->rw.mode); /* * XXX FIXME @@ -685,7 +719,6 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla unsigned int iflag, unsigned int baud, unsigned int quot) { - unsigned int ebrg; unsigned char dafo; int bits, n, m; @@ -714,10 +747,11 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla } else { dafo |= SAB82532_DAFO_PAR_EVEN; } + up->cached_dafo = dafo; calc_ebrg(baud, &n, &m); - ebrg = n | (m << 6); + up->cached_ebrg = n | (m << 6); up->tec_timeout = (10 * 1000000) / baud; up->cec_timeout = up->tec_timeout >> 2; @@ -770,16 +804,13 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla uart_update_timeout(&up->port, cflag, (up->port.uartclk / (16 * quot))); - /* Now bang the new settings into the chip. */ - sunsab_cec_wait(up); - sunsab_tec_wait(up); - writeb(dafo, &up->regs->w.dafo); - writeb(ebrg & 0xff, &up->regs->w.bgr); - writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0), - &up->regs->rw.ccr2); - - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode); - + /* Now schedule a register update when the chip's + * transmitter is idle. + */ + up->cached_mode |= SAB82532_MODE_RAC; + set_bit(SAB82532_REGS_PENDING, &up->irqflags); + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); } /* port->lock is not held. */ @@ -1084,11 +1115,13 @@ static void __init sunsab_init_hw(void) up->pvr_dsr_bit = (1 << 3); up->pvr_dtr_bit = (1 << 2); } - writeb((1 << 1) | (1 << 2) | (1 << 4), &up->regs->w.pvr); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); + up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4); + writeb(up->cached_pvr, &up->regs->w.pvr); + up->cached_mode = readb(&up->regs->rw.mode); + up->cached_mode |= SAB82532_MODE_FRTS; + writeb(up->cached_mode, &up->regs->rw.mode); + up->cached_mode |= SAB82532_MODE_RTS; + writeb(up->cached_mode, &up->regs->rw.mode); up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT; up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT; diff --git a/drivers/serial/sunsab.h b/drivers/serial/sunsab.h index 686086fcbbf..b78e1f7b805 100644 --- a/drivers/serial/sunsab.h +++ b/drivers/serial/sunsab.h @@ -126,6 +126,7 @@ union sab82532_irq_status { /* irqflags bits */ #define SAB82532_ALLS 0x00000001 #define SAB82532_XPR 0x00000002 +#define SAB82532_REGS_PENDING 0x00000004 /* RFIFO Status Byte */ #define SAB82532_RSTAT_PE 0x80 diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 307886199f2..5d2ceb623e6 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -412,10 +412,8 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status, if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - if ((lsr & port->ignore_status_mask) == 0) - tty_insert_flip_char(tty, ch, flag); - if ((lsr & UART_LSR_OE) && (tty->flip.count < TTY_FLIPBUF_SIZE)) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); ignore_char: lsr = siu_read(port, UART_LSR); |