static int vt8500_get_poll_char(struct uart_port *port) { unsigned int status = vt8500_read(port, VT8500_URFIDX); if (!(status & 0x1f00)) return NO_POLL_CHAR; return vt8500_read(port, VT8500_RXFIFO) & 0xff; }
static void handle_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; if (port->x_char) { writeb(port->x_char, port->membase + VT8500_TXFIFO); port->icount.tx++; port->x_char = 0; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { vt8500_stop_tx(port); return; } while ((vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16) { if (uart_circ_empty(xmit)) break; writeb(xmit->buf[xmit->tail], port->membase + VT8500_TXFIFO); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit)) vt8500_stop_tx(port); }
static void vt8500_break_ctl(struct uart_port *port, int break_ctl) { if (break_ctl) vt8500_write(port, vt8500_read(port, VT8500_URLCR) | VT8500_BREAK, VT8500_URLCR); }
static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud) { unsigned long div; unsigned int loops = 1000; div = vt8500_read(port, VT8500_URDIV) & ~(0x3ff); if (unlikely((baud < 900) || (baud > 921600))) div |= 7; else div |= (921600 / baud) - 1; while ((vt8500_read(port, VT8500_URUSR) & (1 << 5)) && --loops) cpu_relax(); vt8500_write(port, div, VT8500_URDIV); return baud; }
static unsigned int vt8500_get_mctrl(struct uart_port *port) { unsigned int usr; usr = vt8500_read(port, VT8500_URUSR); if (usr & (1 << 4)) return TIOCM_CTS; else return 0; }
static void vt8500_set_mctrl(struct uart_port *port, unsigned int mctrl) { unsigned int lcr = vt8500_read(port, VT8500_URLCR); if (mctrl & TIOCM_RTS) lcr |= VT8500_RTS; else lcr &= ~VT8500_RTS; vt8500_write(port, lcr, VT8500_URLCR); }
static void handle_rx(struct uart_port *port) { struct tty_struct *tty = tty_port_tty_get(&port->state->port); if (!tty) { /* Discard data: no tty available */ int count = (vt8500_read(port, VT8500_URFIDX) & 0x1f00) >> 8; u16 ch; while (count--) ch = readw(port->membase + VT8500_RXFIFO); return; }
static inline void wait_for_xmitr(struct uart_port *port) { unsigned int status, tmout = 10000; /* Wait up to 10ms for the character(s) to be sent. */ do { status = vt8500_read(port, VT8500_URFIDX); if (--tmout == 0) break; udelay(1); } while (status & 0x10); }
static void handle_rx(struct uart_port *port) { struct tty_port *tport = &port->state->port; /* * Handle overrun */ if ((vt8500_read(port, VT8500_URISR) & RXOVER)) { port->icount.overrun++; tty_insert_flip_char(tport, 0, TTY_OVERRUN); } /* and now the main RX loop */ while (vt8500_read(port, VT8500_URFIDX) & 0x1f00) { unsigned int c; char flag = TTY_NORMAL; c = readw(port->membase + VT8500_RXFIFO) & 0x3ff; /* Mask conditions we're ignorning. */ c &= ~port->read_status_mask; if (c & FER) { port->icount.frame++; flag = TTY_FRAME; } else if (c & PER) { port->icount.parity++; flag = TTY_PARITY; } port->icount.rx++; if (!uart_handle_sysrq_char(port, c)) tty_insert_flip_char(tport, c, flag); } spin_unlock(&port->lock); tty_flip_buffer_push(tport); spin_lock(&port->lock); }
static void vt8500_put_poll_char(struct uart_port *port, unsigned char c) { unsigned int status, tmout = 10000; do { status = vt8500_read(port, VT8500_URFIDX); if (--tmout == 0) break; udelay(1); } while (status & 0x10); vt8500_write(port, c, VT8500_TXFIFO); }
static void vt8500_console_write(struct console *co, const char *s, unsigned int count) { struct vt8500_port *vt8500_port = vt8500_uart_ports[co->index]; unsigned long ier; BUG_ON(co->index < 0 || co->index >= vt8500_uart_driver.nr); ier = vt8500_read(&vt8500_port->uart, VT8500_URIER); vt8500_write(&vt8500_port->uart, VT8500_URIER, 0); uart_console_write(&vt8500_port->uart, s, count, vt8500_console_putchar); /* * Finally, wait for transmitter to become empty * and switch back to FIFO */ wait_for_xmitr(&vt8500_port->uart); vt8500_write(&vt8500_port->uart, VT8500_URIER, ier); }
static irqreturn_t vt8500_irq(int irq, void *dev_id) { struct uart_port *port = dev_id; unsigned long isr; spin_lock(&port->lock); isr = vt8500_read(port, VT8500_URISR); /* Acknowledge active status bits */ vt8500_write(port, isr, VT8500_URISR); if (isr & RX_FIFO_INTS) handle_rx(port); if (isr & TX_FIFO_INTS) handle_tx(port); if (isr & TCTS) handle_delta_cts(port); spin_unlock(&port->lock); return IRQ_HANDLED; }
static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud) { struct vt8500_port *vt8500_port = container_of(port, struct vt8500_port, uart); unsigned long div; unsigned int loops = 1000; div = ((vt8500_port->clk_predivisor - 1) & 0xf) << 16; div |= (uart_get_divisor(port, baud) - 1) & 0x3ff; /* Effective baud rate */ baud = port->uartclk / 16 / ((div & 0x3ff) + 1); while ((vt8500_read(port, VT8500_URUSR) & (1 << 5)) && --loops) cpu_relax(); vt8500_write(port, div, VT8500_URDIV); /* Break signal timing depends on baud rate, update accordingly */ vt8500_write(port, mult_frac(baud, 4096, 1000000), VT8500_URBKR); return baud; }
static void vt8500_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct vt8500_port *vt8500_port = container_of(port, struct vt8500_port, uart); unsigned long flags; unsigned int baud, lcr; unsigned int loops = 1000; spin_lock_irqsave(&port->lock, flags); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 900, 921600); baud = vt8500_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* calculate parity */ lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR); lcr &= ~((1 << 5) | (1 << 4)); if (termios->c_cflag & PARENB) { lcr |= (1 << 4); termios->c_cflag &= ~CMSPAR; if (termios->c_cflag & PARODD) lcr |= (1 << 5); } /* calculate bits per char */ lcr &= ~(1 << 2); switch (termios->c_cflag & CSIZE) { case CS7: break; case CS8: default: lcr |= (1 << 2); termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* calculate stop bits */ lcr &= ~(1 << 3); if (termios->c_cflag & CSTOPB) lcr |= (1 << 3); /* set parity, bits per char, and stop bit */ vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & IGNPAR) port->read_status_mask = FER | PER; uart_update_timeout(port, termios->c_cflag, baud); /* Reset FIFOs */ vt8500_write(&vt8500_port->uart, 0x88c, VT8500_URFCR); while ((vt8500_read(&vt8500_port->uart, VT8500_URFCR) & 0xc) && --loops) cpu_relax(); /* Every possible FIFO-related interrupt */ vt8500_port->ier = RX_FIFO_INTS | TX_FIFO_INTS; /* * CTS flow control */ if (UART_ENABLE_MS(&vt8500_port->uart, termios->c_cflag)) vt8500_port->ier |= TCTS; vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR); vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER); spin_unlock_irqrestore(&port->lock, flags); }
static unsigned int vt8500_tx_empty(struct uart_port *port) { return (vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16 ? TIOCSER_TEMT : 0; }