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);
}
示例#4
0
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);
}
示例#8
0
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);
}