static void ssauart_rx_chars (struct uart_port *port) #endif { #if 1 struct tty_struct *tty = port->info->tty; while (1) { if ((UART_GET_LSR(port) & (1 << 0)) == 0) /* no more chars available */ break; *tty->flip.char_buf_ptr++ = UART_GET_CHAR(port); *tty->flip.flag_buf_ptr++ = TTY_NORMAL; /* Fixme: we should check for overrun, parity, framing errors etc */ port->icount.rx++; tty->flip.count++; if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; } tty_flip_buffer_push (tty); #else struct tty_struct *tty = port->info->tty; unsigned int ch; unsigned int status; unsigned int max_count = 256; while (1) { status = UART_GET_LSR(port); if (((status & (1 << 0)) == 0) || (--max_count == 0)) break; if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine ((void *) tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk (KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } *tty->flip.char_buf_ptr++ = UART_GET_CHAR(port); *tty->flip.flag_buf_ptr++ = TTY_NORMAL; /* Fixme: we should check for overrun, parity, framing errors etc */ tty->flip.count++; port->icount.rx++; } tty_flip_buffer_push (tty); #endif }
static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id) { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->port.tty; unsigned int status, ch, lsr, flg, max_count = 256; status = UART_GET_LSR(port); /* clears pending LSR interrupts */ while ((status & URLS_URDR) && max_count--) { ch = UART_GET_CHAR(port); flg = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX; if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) { if (lsr & URLS_URBI) { lsr &= ~(URLS_URFE | URLS_URPE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } if (lsr & URLS_URPE) port->icount.parity++; if (lsr & URLS_URFE) port->icount.frame++; if (lsr & URLS_URROE) port->icount.overrun++; lsr &= port->read_status_mask; if (lsr & URLS_URBI) flg = TTY_BREAK; else if (lsr & URLS_URPE) flg = TTY_PARITY; else if (lsr & URLS_URFE) flg = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) goto ignore_char; uart_insert_char(port, lsr, URLS_URROE, ch, flg); ignore_char: status = UART_GET_LSR(port); } tty_flip_buffer_push(tty); return IRQ_HANDLED; }
static u_int ambauart_tx_empty(struct uart_port *port) { unsigned int status; status = UART_GET_LSR(port); return UART_TX_READY(status) ? TIOCSER_TEMT : 0; }
static void ks8695_console_putchar(struct uart_port *port, int ch) { while (!(UART_GET_LSR(port) & URLS_URTHRE)) barrier(); UART_PUT_CHAR(port, ch); }
static void bfin_serial_console_putchar(struct uart_port *port, int ch) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; while (!(UART_GET_LSR(uart) & THRE)) barrier(); UART_PUT_CHAR(uart, ch); }
static __init void early_serial_putc(struct uart_port *port, int ch) { unsigned timeout = 0xffff; struct bfin_serial_port *uart = (struct bfin_serial_port *)port; while ((!(UART_GET_LSR(uart) & THRE)) && --timeout) cpu_relax(); UART_PUT_CHAR(uart, ch); }
static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; while (!(UART_GET_LSR(uart) & THRE)) cpu_relax(); UART_CLEAR_DLAB(uart); UART_PUT_CHAR(uart, (unsigned char)chr); }
/* * Return TIOCSER_TEMT when transmitter is not busy. */ static unsigned int bfin_serial_tx_empty(struct uart_port *port) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; unsigned short lsr; lsr = UART_GET_LSR(uart); if (lsr & TEMT) return TIOCSER_TEMT; else return 0; }
static void bfin_sir_stop_tx(struct bfin_sir_port *port) { #ifdef CONFIG_SIR_BFIN_DMA disable_dma(port->tx_dma_channel); #endif while (!(UART_GET_LSR(port) & THRE)) { cpu_relax(); continue; } UART_CLEAR_IER(port, ETBEI); }
static irqreturn_t bfin_sir_tx_int(int irq, void *dev_id) { struct net_device *dev = dev_id; struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; spin_lock(&self->lock); if (UART_GET_LSR(port) & THRE) bfin_sir_tx_chars(dev); spin_unlock(&self->lock); return IRQ_HANDLED; }
static int bfin_serial_poll_get_char(struct uart_port *port) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; unsigned char chr; while (!(UART_GET_LSR(uart) & DR)) cpu_relax(); UART_CLEAR_DLAB(uart); chr = UART_GET_CHAR(uart); return chr; }
/* Called with interrupts off only from start_tx() */ static void ssauart_tx_one_char (struct uart_port *port) { struct circ_buf *xmit = &port->info->xmit; /* The Fifo may already contain data in which case, our work is * done since when it drains it will trigger an interrupt. */ if ((UART_GET_LSR(port) & (1 << 6)) == 0) return; if (port->x_char) { UART_PUT_CHAR(port, port->x_char); port->x_char = 0; port->icount.tx++; return; } if (uart_circ_empty (xmit) || uart_tx_stopped (port)) return; UART_PUT_CHAR(port, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; /* If the number of bytes remaining in the SW Tx circular buffer is less than WAKEUP_CHARS, wake up tasks trying to write to the UART device. */ if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) { uart_write_wakeup (port); /* If there are no more bytes to transmit, disable Tx interrupts. (We don't need to refill the UART Tx fifo when it next becomes empty). */ if (uart_circ_empty (xmit)) ssauart_stop_tx (port, 0); } }
/* * interrupts are disabled on entry */ static void bfin_serial_stop_tx(struct uart_port *port) { struct bfin_serial_port *uart = (struct bfin_serial_port *)port; #ifdef CONFIG_SERIAL_BFIN_DMA struct circ_buf *xmit = &uart->port.info->xmit; #endif while (!(UART_GET_LSR(uart) & TEMT)) cpu_relax(); #ifdef CONFIG_SERIAL_BFIN_DMA disable_dma(uart->tx_dma_channel); xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); uart->port.icount.tx += uart->tx_count; uart->tx_count = 0; uart->tx_done = 1; #else #ifdef CONFIG_BF54x /* Clear TFI bit */ UART_PUT_LSR(uart, TFI); #endif UART_CLEAR_IER(uart, ETBEI); #endif }
static unsigned int ks8695uart_tx_empty(struct uart_port *port) { return (UART_GET_LSR(port) & URLS_URTE) ? TIOCSER_TEMT : 0; }
static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) { int ret = -EINVAL; unsigned int quot; unsigned short val, lsr, lcr; static int utime; int count = 10; lcr = WLS(8); switch (speed) { case 9600: case 19200: case 38400: case 57600: case 115200: /* * IRDA is not affected by anomaly 05000230, so there is no * need to tweak the divisor like he UART driver (which will * slightly speed up the baud rate on us). */ quot = (port->clk + (8 * speed)) / (16 * speed); do { udelay(utime); lsr = UART_GET_LSR(port); } while (!(lsr & TEMT) && count--); /* The useconds for 1 bits to transmit */ utime = 1000000 / speed + 1; /* Clear UCEN bit to reset the UART state machine * and control registers */ val = UART_GET_GCTL(port); val &= ~UCEN; UART_PUT_GCTL(port, val); /* Set DLAB in LCR to Access THR RBR IER */ UART_SET_DLAB(port); SSYNC(); UART_PUT_DLL(port, quot & 0xFF); UART_PUT_DLH(port, (quot >> 8) & 0xFF); SSYNC(); /* Clear DLAB in LCR */ UART_CLEAR_DLAB(port); SSYNC(); UART_PUT_LCR(port, lcr); val = UART_GET_GCTL(port); val |= UCEN; UART_PUT_GCTL(port, val); ret = 0; break; default: printk(KERN_WARNING "bfin_sir: Invalid speed %d\n", speed); break; } val = UART_GET_GCTL(port); /* If not add the 'RPOLC', we can't catch the receive interrupt. * It's related with the HW layout and the IR transiver. */ val |= IREN | RPOLC; UART_PUT_GCTL(port, val); return ret; }
static u_int ssauart_tx_empty (struct uart_port *port) { return UART_GET_LSR(port) & (1 << 6) ? TIOCSER_TEMT : 0; }
static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = NULL; unsigned int status, ch, flg; static struct timeval anomaly_start = { .tv_sec = 0 }; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); ch = UART_GET_CHAR(uart); uart->port.icount.rx++; #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) if (kgdb_connected && kgdboc_port_line == uart->port.line) if (ch == 0x3) {/* Ctrl + C */ kgdb_breakpoint(); return; } if (!uart->port.info || !uart->port.info->tty) return; #endif tty = uart->port.info->tty; if (ANOMALY_05000363) { /* The BF533 (and BF561) family of processors have a nice anomaly * where they continuously generate characters for a "single" break. * We have to basically ignore this flood until the "next" valid * character comes across. Due to the nature of the flood, it is * not possible to reliably catch bytes that are sent too quickly * after this break. So application code talking to the Blackfin * which sends a break signal must allow at least 1.5 character * times after the end of the break for things to stabilize. This * timeout was picked as it must absolutely be larger than 1 * character time +/- some percent. So 1.5 sounds good. All other * Blackfin families operate properly. Woo. */ if (anomaly_start.tv_sec) { struct timeval curr; suseconds_t usecs; if ((~ch & (~ch + 1)) & 0xff) goto known_good_char; do_gettimeofday(&curr); if (curr.tv_sec - anomaly_start.tv_sec > 1) goto known_good_char; usecs = 0; if (curr.tv_sec != anomaly_start.tv_sec) usecs += USEC_PER_SEC; usecs += curr.tv_usec - anomaly_start.tv_usec; if (usecs > UART_GET_ANOMALY_THRESHOLD(uart)) goto known_good_char; if (ch) anomaly_start.tv_sec = 0; else anomaly_start = curr; return; known_good_char: status &= ~BI; anomaly_start.tv_sec = 0; } } if (status & BI) { if (ANOMALY_05000363) if (bfin_revid() < 5) do_gettimeofday(&anomaly_start); uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; if (uart_handle_sysrq_char(&uart->port, ch)) goto ignore_char; uart_insert_char(&uart->port, status, OE, ch, flg); ignore_char: tty_flip_buffer_push(tty); } static void bfin_serial_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.info->xmit; /* * Check the modem control lines before * transmitting anything. */ bfin_serial_mctrl_check(uart); if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { #ifdef CONFIG_BF54x /* Clear TFI bit */ UART_PUT_LSR(uart, TFI); #endif UART_CLEAR_IER(uart, ETBEI); return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); uart->port.icount.tx++; SSYNC(); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&uart->port); } static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; spin_lock(&uart->port.lock); while (UART_GET_LSR(uart) & DR) bfin_serial_rx_chars(uart); spin_unlock(&uart->port.lock); return IRQ_HANDLED; } static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; spin_lock(&uart->port.lock); if (UART_GET_LSR(uart) & THRE) bfin_serial_tx_chars(uart); spin_unlock(&uart->port.lock); return IRQ_HANDLED; } #endif #ifdef CONFIG_SERIAL_BFIN_DMA static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.info->xmit; uart->tx_done = 0; /* * Check the modem control lines before * transmitting anything. */ bfin_serial_mctrl_check(uart); if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { uart->tx_count = 0; uart->tx_done = 1; return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) uart->tx_count = UART_XMIT_SIZE - xmit->tail; blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail), (unsigned long)(xmit->buf+xmit->tail+uart->tx_count)); set_dma_config(uart->tx_dma_channel, set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, DMA_SYNC_RESTART)); set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); set_dma_x_count(uart->tx_dma_channel, uart->tx_count); set_dma_x_modify(uart->tx_dma_channel, 1); enable_dma(uart->tx_dma_channel); UART_SET_IER(uart, ETBEI); } static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = uart->port.info->port.tty; int i, flg, status; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE); if (status & BI) { uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto dma_ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; for (i = uart->rx_dma_buf.tail; i != uart->rx_dma_buf.head; i++) { if (i >= UART_XMIT_SIZE) i = 0; if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg); } dma_ignore_char: tty_flip_buffer_push(tty); } void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) { int x_pos, pos, flags; spin_lock_irqsave(&uart->port.lock, flags); uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); x_pos = get_dma_curr_xcount(uart->rx_dma_channel); uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; if (uart->rx_dma_nrows == DMA_RX_YCOUNT) uart->rx_dma_nrows = 0; x_pos = DMA_RX_XCOUNT - x_pos; if (x_pos == DMA_RX_XCOUNT) x_pos = 0; pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; if (pos != uart->rx_dma_buf.tail) { uart->rx_dma_buf.head = pos; bfin_serial_dma_rx_chars(uart); uart->rx_dma_buf.tail = uart->rx_dma_buf.head; } spin_unlock_irqrestore(&uart->port.lock, flags); mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); }
static void bfin_serial_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = NULL; unsigned int status, ch, flg; static struct timeval anomaly_start = { .tv_sec = 0 }; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); ch = UART_GET_CHAR(uart); uart->port.icount.rx++; #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) if (kgdb_connected && kgdboc_port_line == uart->port.line && kgdboc_break_enabled) if (ch == 0x3) {/* Ctrl + C */ kgdb_breakpoint(); return; } if (!uart->port.state || !uart->port.state->port.tty) return; #endif tty = uart->port.state->port.tty; if (ANOMALY_05000363) { /* The BF533 (and BF561) family of processors have a nice anomaly * where they continuously generate characters for a "single" break. * We have to basically ignore this flood until the "next" valid * character comes across. Due to the nature of the flood, it is * not possible to reliably catch bytes that are sent too quickly * after this break. So application code talking to the Blackfin * which sends a break signal must allow at least 1.5 character * times after the end of the break for things to stabilize. This * timeout was picked as it must absolutely be larger than 1 * character time +/- some percent. So 1.5 sounds good. All other * Blackfin families operate properly. Woo. */ if (anomaly_start.tv_sec) { struct timeval curr; suseconds_t usecs; if ((~ch & (~ch + 1)) & 0xff) goto known_good_char; do_gettimeofday(&curr); if (curr.tv_sec - anomaly_start.tv_sec > 1) goto known_good_char; usecs = 0; if (curr.tv_sec != anomaly_start.tv_sec) usecs += USEC_PER_SEC; usecs += curr.tv_usec - anomaly_start.tv_usec; if (usecs > UART_GET_ANOMALY_THRESHOLD(uart)) goto known_good_char; if (ch) anomaly_start.tv_sec = 0; else anomaly_start = curr; return; known_good_char: status &= ~BI; anomaly_start.tv_sec = 0; } } if (status & BI) { if (ANOMALY_05000363) if (bfin_revid() < 5) do_gettimeofday(&anomaly_start); uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; if (uart_handle_sysrq_char(&uart->port, ch)) goto ignore_char; uart_insert_char(&uart->port, status, OE, ch, flg); ignore_char: tty_flip_buffer_push(tty); } static void bfin_serial_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.state->xmit; if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { #ifdef CONFIG_BF54x /* Clear TFI bit */ UART_PUT_LSR(uart, TFI); #endif /* Anomaly notes: * 05000215 - we always clear ETBEI within last UART TX * interrupt to end a string. It is always set * when start a new tx. */ UART_CLEAR_IER(uart, ETBEI); return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); uart->port.icount.tx++; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&uart->port); } static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; while (UART_GET_LSR(uart) & DR) bfin_serial_rx_chars(uart); return IRQ_HANDLED; } static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) { struct bfin_serial_port *uart = dev_id; #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) { uart->scts = 0; uart_handle_cts_change(&uart->port, uart->scts); } #endif spin_lock(&uart->port.lock); if (UART_GET_LSR(uart) & THRE) bfin_serial_tx_chars(uart); spin_unlock(&uart->port.lock); return IRQ_HANDLED; } #endif #ifdef CONFIG_SERIAL_BFIN_DMA static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) { struct circ_buf *xmit = &uart->port.state->xmit; uart->tx_done = 0; if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { uart->tx_count = 0; uart->tx_done = 1; return; } if (uart->port.x_char) { UART_PUT_CHAR(uart, uart->port.x_char); uart->port.icount.tx++; uart->port.x_char = 0; } uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) uart->tx_count = UART_XMIT_SIZE - xmit->tail; blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail), (unsigned long)(xmit->buf+xmit->tail+uart->tx_count)); set_dma_config(uart->tx_dma_channel, set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, DMA_SYNC_RESTART)); set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); set_dma_x_count(uart->tx_dma_channel, uart->tx_count); set_dma_x_modify(uart->tx_dma_channel, 1); SSYNC(); enable_dma(uart->tx_dma_channel); UART_SET_IER(uart, ETBEI); } static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) { struct tty_struct *tty = uart->port.state->port.tty; int i, flg, status; status = UART_GET_LSR(uart); UART_CLEAR_LSR(uart); uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE); if (status & BI) { uart->port.icount.brk++; if (uart_handle_break(&uart->port)) goto dma_ignore_char; status &= ~(PE | FE); } if (status & PE) uart->port.icount.parity++; if (status & OE) uart->port.icount.overrun++; if (status & FE) uart->port.icount.frame++; status &= uart->port.read_status_mask; if (status & BI) flg = TTY_BREAK; else if (status & PE) flg = TTY_PARITY; else if (status & FE) flg = TTY_FRAME; else flg = TTY_NORMAL; for (i = uart->rx_dma_buf.tail; ; i++) { if (i >= UART_XMIT_SIZE) i = 0; if (i == uart->rx_dma_buf.head) break; if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg); } dma_ignore_char: tty_flip_buffer_push(tty); } void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) { int x_pos, pos; dma_disable_irq_nosync(uart->rx_dma_channel); spin_lock_bh(&uart->rx_lock); /* 2D DMA RX buffer ring is used. Because curr_y_count and * curr_x_count can't be read as an atomic operation, * curr_y_count should be read before curr_x_count. When * curr_x_count is read, curr_y_count may already indicate * next buffer line. But, the position calculated here is * still indicate the old line. The wrong position data may * be smaller than current buffer tail, which cause garbages * are received if it is not prohibit. */ uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); x_pos = get_dma_curr_xcount(uart->rx_dma_channel); uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) uart->rx_dma_nrows = 0; x_pos = DMA_RX_XCOUNT - x_pos; if (x_pos == DMA_RX_XCOUNT) x_pos = 0; pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; /* Ignore receiving data if new position is in the same line of * current buffer tail and small. */ if (pos > uart->rx_dma_buf.tail || uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) { uart->rx_dma_buf.head = pos; bfin_serial_dma_rx_chars(uart); uart->rx_dma_buf.tail = uart->rx_dma_buf.head; } spin_unlock_bh(&uart->rx_lock); dma_enable_irq(uart->rx_dma_channel); mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); }
static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; struct uart_info *info = port->info; unsigned int status, ier, old_ier, count, lsr; old_ier = UART_GET_IER(port); UART_PUT_IER(port, (old_ier & 0xFFFFF0FF)); status = UART_GET_INT_STATUS(port); lsr = UART_GET_LSR(port); /* KS8695_INTMASK_UART_RX is not set during breakpoint as it should (looks * like a HW bug), so we specifically check for a breakpoint condition in * the UART line status register. * Some bits from the UART line status register are cleared only when they * are read by CPU. That is why we cannot read the line status register * twice, and should pass the first read as argument to ambauart_rx_chars. * Refer to CENTAUR KS8695PX's Register Description document: * KS8695PX_REG_DESCP_v1.0.pdf, page 58: "UART Line Status Register". */ if (status & KS8695_INTMASK_UART_RX || lsr & KS8695_UART_LINES_BE) { #ifdef SUPPORT_SYSRQ ambauart_rx_chars(port, regs, lsr); #else ambauart_rx_chars(port, lsr); #endif } if (status & KS8695_INTMASK_UART_TX) { if (port->x_char) { UART_CLR_INT_STATUS(port, KS8695_INTMASK_UART_TX); UART_PUT_CHAR(port, (u_int) port->x_char); port->icount.tx++; port->x_char = 0; ier = UART_GET_IER(port); ier &= 0xFFFFFEFF; UART_PUT_IER(port, ier); printk("XOn/Off sent\n"); return; } for ( count = 0; count < 16; count++) { if (info->xmit.head == info->xmit.tail) { /*ier = UART_GET_IER(port); ier &= 0xFFFFFEFF; UART_PUT_IER(port, ier);*/ break; } UART_CLR_INT_STATUS(port, KS8695_INTMASK_UART_TX); UART_PUT_CHAR(port, (u_int) (info->xmit.buf[info->xmit.tail])); info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; }; if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) < WAKEUP_CHARS) uart_write_wakeup(port); if (info->xmit.head == info->xmit.tail) { ier = UART_GET_IER(port); ier &= 0xFFFFFEFF; UART_PUT_IER(port, ier); } } if (status & KS8695_INTMASK_UART_MODEMS) { ambauart_modem_status(port); } if (status & KS8695_INTMASK_UART_MODEMS) { ambauart_modem_status(port); } if ( status & KS8695_INTMASK_UART_LINE_ERR) { UART_GET_LSR(port); } if (info->xmit.head == info->xmit.tail) UART_PUT_IER(port, (old_ier & 0xFFFFFEFF)); else UART_PUT_IER(port, old_ier | KS8695_INTMASK_UART_TX); }
ambauart_rx_chars(struct uart_port *port, unsigned short status) #endif { struct tty_struct *tty = port->info->tty; unsigned short ch, lsr, max_count = 256; while (UART_RX_DATA(status) && max_count--) { lsr = status; if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n"); return; } } ch = UART_GET_CHAR(port); *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ lsr |= UART_DUMMY_LSR_RX; if (lsr & KS8695_UART_LINES_ANY) { if (lsr & KS8695_UART_LINES_BE) { lsr &= ~(KS8695_UART_LINES_FE | KS8695_UART_LINES_PE); port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } else if (lsr & KS8695_UART_LINES_PE) port->icount.parity++; else if (lsr & KS8695_UART_LINES_FE) port->icount.frame++; if (lsr & KS8695_UART_LINES_OE) port->icount.overrun++; lsr &= port->read_status_mask; if (lsr & KS8695_UART_LINES_BE) *tty->flip.flag_buf_ptr = TTY_BREAK; else if (lsr & KS8695_UART_LINES_PE) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (lsr & KS8695_UART_LINES_FE) *tty->flip.flag_buf_ptr = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; if ((lsr & port->ignore_status_mask) == 0) { tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } if ((lsr & KS8695_UART_LINES_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character */ *tty->flip.char_buf_ptr++ = 0; *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; tty->flip.count++; } ignore_char: status = UART_GET_LSR(port); } tty_flip_buffer_push(tty); return; }