static void altera_uart_tx_chars(struct altera_uart *pp) { struct uart_port *port = &pp->port; struct circ_buf *xmit = &port->state->xmit; if (port->x_char) { /* Send special char - probably flow control */ altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG); port->x_char = 0; port->icount.tx++; return; } while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_TRDY_MSK) { if (xmit->head == xmit->tail) break; altera_uart_writel(port, xmit->buf[xmit->tail], ALTERA_UART_TXDATA_REG); 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 (xmit->head == xmit->tail) { pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); } }
static void altera_uart_config_port(struct uart_port *port, int flags) { port->type = PORT_ALTERA_UART; /* Clear mask, so no surprise interrupts. */ altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG); /* Clear status register */ altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG); }
static void altera_uart_stop_rx(struct uart_port *port) { struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); }
static void altera_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, baudclk; baud = uart_get_baud_rate(port, termios, old, 0, 4000000); baudclk = port->uartclk / baud; if (old) tty_termios_copy_hw(termios, old); tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); spin_unlock_irqrestore(&port->lock, flags); /* * FIXME: port->read_status_mask and port->ignore_status_mask * need to be initialized based on termios settings for * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT */ }
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); }
static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) { struct altera_uart *pp = container_of(port, struct altera_uart, port); pp->sigs = sigs; if (sigs & TIOCM_RTS) pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; else pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); }
static void altera_uart_break_ctl(struct uart_port *port, int break_state) { struct altera_uart *pp = container_of(port, struct altera_uart, port); unsigned long flags; spin_lock_irqsave(&port->lock, flags); if (break_state == -1) pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; else pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); spin_unlock_irqrestore(&port->lock, flags); }
static void altera_uart_rx_chars(struct altera_uart *pp) { struct uart_port *port = &pp->port; unsigned char ch, flag; unsigned short status; while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) & ALTERA_UART_STATUS_RRDY_MSK) { ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG); flag = TTY_NORMAL; port->icount.rx++; if (status & ALTERA_UART_STATUS_E_MSK) { altera_uart_writel(port, status, ALTERA_UART_STATUS_REG); if (status & ALTERA_UART_STATUS_BRK_MSK) { port->icount.brk++; if (uart_handle_break(port)) continue; } else if (status & ALTERA_UART_STATUS_PE_MSK) { port->icount.parity++; } else if (status & ALTERA_UART_STATUS_ROE_MSK) { port->icount.overrun++; } else if (status & ALTERA_UART_STATUS_FE_MSK) { port->icount.frame++; } status &= port->read_status_mask; if (status & ALTERA_UART_STATUS_BRK_MSK) flag = TTY_BREAK; else if (status & ALTERA_UART_STATUS_PE_MSK) flag = TTY_PARITY; else if (status & ALTERA_UART_STATUS_FE_MSK) flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch)) continue; uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch, flag); } spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); spin_lock(&port->lock); }
static void altera_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, baudclk; baud = uart_get_baud_rate(port, termios, old, 0, 4000000); baudclk = port->uartclk / baud; if (old) tty_termios_copy_hw(termios, old); tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); spin_unlock_irqrestore(&port->lock, flags); }