static void sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) { struct tty_struct *tty = sport->port.info->tty; unsigned int status, ch, flg; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; sport->port.icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) { if (status & UTSR1_TO_SM(UTSR1_PRE)) sport->port.icount.parity++; else if (status & UTSR1_TO_SM(UTSR1_FRE)) sport->port.icount.frame++; if (status & UTSR1_TO_SM(UTSR1_ROR)) sport->port.icount.overrun++; status &= sport->port.read_status_mask; if (status & UTSR1_TO_SM(UTSR1_PRE)) flg = TTY_PARITY; else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; #ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; #endif } if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } tty_flip_buffer_push(tty); }
static void sa1100_rx_chars(struct sa1100_port *sport) { struct tty_struct *tty = sport->port.state->port.tty; unsigned int status, ch, flg; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); sport->port.icount.rx++; flg = TTY_NORMAL; if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) { if (status & UTSR1_TO_SM(UTSR1_PRE)) sport->port.icount.parity++; else if (status & UTSR1_TO_SM(UTSR1_FRE)) sport->port.icount.frame++; if (status & UTSR1_TO_SM(UTSR1_ROR)) sport->port.icount.overrun++; status &= sport->port.read_status_mask; if (status & UTSR1_TO_SM(UTSR1_PRE)) flg = TTY_PARITY; else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; #ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; #endif } if (uart_handle_sysrq_char(&sport->port, ch)) goto ignore_char; uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } tty_flip_buffer_push(tty); }
/* * port locked and interrupts disabled */ static void sa1100_start_tx(struct uart_port *port) { struct sa1100_port *sport = (struct sa1100_port *)port; u32 utcr3; utcr3 = UART_GET_UTCR3(sport); sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); }
/* * interrupts may not be disabled on entry */ static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; u32 utcr3; spin_lock_irqsave(&sport->port.lock, flags); utcr3 = UART_GET_UTCR3(sport); sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); spin_unlock_irqrestore(&sport->port.lock, flags); }
/* * interrupts may not be disabled on entry */ static void sa1100_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty) { if (nonempty) { unsigned long flags; u32 utcr3; local_irq_save(flags); utcr3 = UART_GET_UTCR3(port); port->read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); UART_PUT_UTCR3(port, utcr3 | UTCR3_TIE); local_irq_restore(flags); } }
static void sa1100_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; unsigned int utcr0, old_utcr3, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; /* * We only support CS7 and CS8. */ while ((termios->c_cflag & CSIZE) != CS7 && (termios->c_cflag & CSIZE) != CS8) { termios->c_cflag &= ~CSIZE; termios->c_cflag |= old_csize; old_csize = CS8; } if ((termios->c_cflag & CSIZE) == CS8) utcr0 = UTCR0_DSS; else utcr0 = 0; if (termios->c_cflag & CSTOPB) utcr0 |= UTCR0_SBS; if (termios->c_cflag & PARENB) { utcr0 |= UTCR0_PE; if (!(termios->c_cflag & PARODD)) utcr0 |= UTCR0_OES; } /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); if (termios->c_iflag & INPCK) sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * Characters to ignore */ sport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & IGNBRK) { sport->port.ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR); } del_timer_sync(&sport->timer); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* * disable interrupts and drain transmitter */ old_utcr3 = UART_GET_UTCR3(sport); UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); while (UART_GET_UTSR1(sport) & UTSR1_TBY) barrier(); /* then, disable everything */ UART_PUT_UTCR3(sport, 0); /* set the parity, stop bits and data size */ UART_PUT_UTCR0(sport, utcr0); /* set the baud rate */ quot -= 1; UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8)); UART_PUT_UTCR2(sport, (quot & 0xff)); UART_PUT_UTSR0(sport, -1); UART_PUT_UTCR3(sport, old_utcr3); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) sa1100_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); }
static void ip3106_set_termios(struct uart_port *port, struct termios *termios, struct termios *old) { struct ip3106_port *sport = (struct ip3106_port *)port; unsigned long flags; unsigned int lcr_fcr, old_ien, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; /* * We only support CS7 and CS8. */ while ((termios->c_cflag & CSIZE) != CS7 && (termios->c_cflag & CSIZE) != CS8) { termios->c_cflag &= ~CSIZE; termios->c_cflag |= old_csize; old_csize = CS8; } if ((termios->c_cflag & CSIZE) == CS8) lcr_fcr = IP3106_UART_LCR_8BIT; else lcr_fcr = 0; if (termios->c_cflag & CSTOPB) lcr_fcr |= IP3106_UART_LCR_2STOPB; if (termios->c_cflag & PARENB) { lcr_fcr |= IP3106_UART_LCR_PAREN; if (!(termios->c_cflag & PARODD)) lcr_fcr |= IP3106_UART_LCR_PAREVN; } /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); #if 0 /* REVISIT */ sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); if (termios->c_iflag & INPCK) sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * Characters to ignore */ sport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & IGNBRK) { sport->port.ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR); } #endif del_timer_sync(&sport->timer); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* * disable interrupts and drain transmitter */ old_ien = serial_in(sport, IP3106_IEN); serial_out(sport, IP3106_IEN, old_ien & ~(IP3106_UART_INT_ALLTX | IP3106_UART_INT_ALLRX)); while (serial_in(sport, IP3106_FIFO) & IP3106_UART_FIFO_TXFIFO_STA) barrier(); /* then, disable everything */ serial_out(sport, IP3106_IEN, 0); /* Reset the Rx and Tx FIFOs too */ lcr_fcr |= IP3106_UART_LCR_TX_RST; lcr_fcr |= IP3106_UART_LCR_RX_RST; /* set the parity, stop bits and data size */ serial_out(sport, IP3106_LCR, lcr_fcr); /* set the baud rate */ quot -= 1; serial_out(sport, IP3106_BAUD, quot); serial_out(sport, IP3106_ICLR, -1); serial_out(sport, IP3106_IEN, old_ien); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) ip3106_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); }
static void sa1100_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; unsigned int utcr0, old_utcr3, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; while ((termios->c_cflag & CSIZE) != CS7 && (termios->c_cflag & CSIZE) != CS8) { termios->c_cflag &= ~CSIZE; termios->c_cflag |= old_csize; old_csize = CS8; } if ((termios->c_cflag & CSIZE) == CS8) utcr0 = UTCR0_DSS; else utcr0 = 0; if (termios->c_cflag & CSTOPB) utcr0 |= UTCR0_SBS; if (termios->c_cflag & PARENB) { utcr0 |= UTCR0_PE; if (!(termios->c_cflag & PARODD)) utcr0 |= UTCR0_OES; } baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); if (termios->c_iflag & INPCK) sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); sport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & IGNBRK) { sport->port.ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR); } del_timer_sync(&sport->timer); uart_update_timeout(port, termios->c_cflag, baud); old_utcr3 = UART_GET_UTCR3(sport); UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); while (UART_GET_UTSR1(sport) & UTSR1_TBY) barrier(); UART_PUT_UTCR3(sport, 0); UART_PUT_UTCR0(sport, utcr0); quot -= 1; UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8)); UART_PUT_UTCR2(sport, (quot & 0xff)); UART_PUT_UTSR0(sport, -1); UART_PUT_UTCR3(sport, old_utcr3); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) sa1100_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); }
static void sa1100_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; unsigned int utcr0, old_utcr3; if ((cflag & CSIZE) == CS8) utcr0 = UTCR0_DSS; else utcr0 = 0; if (cflag & CSTOPB) utcr0 |= UTCR0_SBS; if (cflag & PARENB) { utcr0 |= UTCR0_PE; if (!(cflag & PARODD)) utcr0 |= UTCR0_OES; } spin_lock_irqsave(&sport->port.lock, flags); sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); if (iflag & INPCK) sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * Characters to ignore */ sport->port.ignore_status_mask = 0; if (iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (iflag & IGNBRK) { sport->port.ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR); } del_timer_sync(&sport->timer); /* * disable interrupts and drain transmitter */ old_utcr3 = UART_GET_UTCR3(sport); UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); while (UART_GET_UTSR1(sport) & UTSR1_TBY) barrier(); /* then, disable everything */ UART_PUT_UTCR3(sport, 0); /* set the parity, stop bits and data size */ UART_PUT_UTCR0(sport, utcr0); /* set the baud rate */ quot -= 1; UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8)); UART_PUT_UTCR2(sport, (quot & 0xff)); UART_PUT_UTSR0(sport, -1); UART_PUT_UTCR3(sport, old_utcr3); if (UART_ENABLE_MS(&sport->port, cflag)) sa1100_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); }
static void sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) { struct tty_struct *tty = sport->port.info->tty; unsigned int status, ch, flg, ignored = 0; status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); while (status & UTSR1_TO_SM(UTSR1_RNE)) { ch = UART_GET_CHAR(sport); if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; sport->port.icount.rx++; flg = TTY_NORMAL; /* * note that the error handling code is * out of the main execution path */ if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) goto handle_error; if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; error_return: *tty->flip.flag_buf_ptr++ = flg; *tty->flip.char_buf_ptr++ = ch; tty->flip.count++; ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } out: tty_flip_buffer_push(tty); return; handle_error: if (status & UTSR1_TO_SM(UTSR1_PRE)) sport->port.icount.parity++; else if (status & UTSR1_TO_SM(UTSR1_FRE)) sport->port.icount.frame++; if (status & UTSR1_TO_SM(UTSR1_ROR)) sport->port.icount.overrun++; if (status & sport->port.ignore_status_mask) { if (++ignored > 100) goto out; goto ignore_char; } status &= sport->port.read_status_mask; if (status & UTSR1_TO_SM(UTSR1_PRE)) flg = TTY_PARITY; else if (status & UTSR1_TO_SM(UTSR1_FRE)) flg = TTY_FRAME; if (status & UTSR1_TO_SM(UTSR1_ROR)) { /* * overrun does *not* affect the character * we read from the FIFO */ *tty->flip.flag_buf_ptr++ = flg; *tty->flip.char_buf_ptr++ = ch; tty->flip.count++; if (tty->flip.count >= TTY_FLIPBUF_SIZE) goto ignore_char; ch = 0; flg = TTY_OVERRUN; } #ifdef SUPPORT_SYSRQ sport->port.sysrq = 0; #endif goto error_return; }
static void sa1100_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot) { unsigned long flags; u_int utcr0, old_utcr3; /* byte size and parity */ switch (cflag & CSIZE) { case CS7: utcr0 = 0; break; default: utcr0 = UTCR0_DSS; break; } if (cflag & CSTOPB) utcr0 |= UTCR0_SBS; if (cflag & PARENB) { utcr0 |= UTCR0_PE; if (!(cflag & PARODD)) utcr0 |= UTCR0_OES; } port->read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); port->read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); if (iflag & INPCK) port->read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (iflag & (BRKINT | PARMRK)) port->read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * Characters to ignore */ port->ignore_status_mask = 0; if (iflag & IGNPAR) port->ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (iflag & IGNBRK) { port->ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (iflag & IGNPAR) port->ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR); } /* first, disable interrupts and drain transmitter */ local_irq_save(flags); old_utcr3 = UART_GET_UTCR3(port); UART_PUT_UTCR3(port, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); local_irq_restore(flags); while (UART_GET_UTSR1(port) & UTSR1_TBY); /* then, disable everything */ UART_PUT_UTCR3(port, 0); /* set the parity, stop bits and data size */ UART_PUT_UTCR0(port, utcr0); /* set the baud rate */ quot -= 1; UART_PUT_UTCR1(port, ((quot & 0xf00) >> 8)); UART_PUT_UTCR2(port, (quot & 0xff)); UART_PUT_UTSR0(port, -1); UART_PUT_UTCR3(port, old_utcr3); }