예제 #1
0
파일: uartlite.c 프로젝트: vucan/linux
static int ulite_get_poll_char(struct uart_port *port)
{
    if (!(uart_in32(ULITE_STATUS, port) & ULITE_STATUS_RXVALID))
        return NO_POLL_CHAR;

    return uart_in32(ULITE_RX, port);
}
예제 #2
0
파일: uartlite.c 프로젝트: vucan/linux
static int ulite_request_port(struct uart_port *port)
{
    int ret;

    pr_debug("ulite console: port=%p; port->mapbase=%llx\n",
             port, (unsigned long long) port->mapbase);

    if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
        dev_err(port->dev, "Memory region busy\n");
        return -EBUSY;
    }

    port->membase = ioremap(port->mapbase, ULITE_REGION);
    if (!port->membase) {
        dev_err(port->dev, "Unable to map registers\n");
        release_mem_region(port->mapbase, ULITE_REGION);
        return -EBUSY;
    }

    port->private_data = &uartlite_be;
    ret = uart_in32(ULITE_CONTROL, port);
    uart_out32(ULITE_CONTROL_RST_TX, ULITE_CONTROL, port);
    ret = uart_in32(ULITE_STATUS, port);
    /* Endianess detection */
    if ((ret & ULITE_STATUS_TXEMPTY) != ULITE_STATUS_TXEMPTY)
        port->private_data = &uartlite_le;

    return 0;
}
예제 #3
0
파일: uartlite.c 프로젝트: vucan/linux
static void ulite_console_write(struct console *co, const char *s,
                                unsigned int count)
{
    struct uart_port *port = &ulite_ports[co->index];
    unsigned long flags;
    unsigned int ier;
    int locked = 1;

    if (oops_in_progress) {
        locked = spin_trylock_irqsave(&port->lock, flags);
    } else
        spin_lock_irqsave(&port->lock, flags);

    /* save and disable interrupt */
    ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE;
    uart_out32(0, ULITE_CONTROL, port);

    uart_console_write(port, s, count, ulite_console_putchar);

    ulite_console_wait_tx(port);

    /* restore interrupt state */
    if (ier)
        uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port);

    if (locked)
        spin_unlock_irqrestore(&port->lock, flags);
}
예제 #4
0
파일: uartlite.c 프로젝트: vucan/linux
static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
{
    while (uart_in32(ULITE_STATUS, port) & ULITE_STATUS_TXFULL)
        cpu_relax();

    /* write char to device */
    uart_out32(ch, ULITE_TX, port);
}
예제 #5
0
파일: uartlite.c 프로젝트: vucan/linux
static unsigned int ulite_tx_empty(struct uart_port *port)
{
    unsigned long flags;
    unsigned int ret;

    spin_lock_irqsave(&port->lock, flags);
    ret = uart_in32(ULITE_STATUS, port);
    spin_unlock_irqrestore(&port->lock, flags);

    return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
}
예제 #6
0
static void ulite_console_wait_tx(struct uart_port *port)
{
	int i;
	u8 val;

	/* Spin waiting for TX fifo to have space available */
	for (i = 0; i < 10000000; i++) {
		val = uart_in32(ULITE_STATUS, port);
		if ((val & ULITE_STATUS_TXFULL) == 0)
			break;
		cpu_relax();
	}
}
예제 #7
0
파일: uartlite.c 프로젝트: vucan/linux
static int ulite_receive(struct uart_port *port, int stat)
{
    struct tty_port *tport = &port->state->port;
    unsigned char ch = 0;
    char flag = TTY_NORMAL;

    if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
                 | ULITE_STATUS_FRAME)) == 0)
        return 0;

    /* stats */
    if (stat & ULITE_STATUS_RXVALID) {
        port->icount.rx++;
        ch = uart_in32(ULITE_RX, port);

        if (stat & ULITE_STATUS_PARITY)
            port->icount.parity++;
    }

    if (stat & ULITE_STATUS_OVERRUN)
        port->icount.overrun++;

    if (stat & ULITE_STATUS_FRAME)
        port->icount.frame++;


    /* drop byte with parity error if IGNPAR specificed */
    if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
        stat &= ~ULITE_STATUS_RXVALID;

    stat &= port->read_status_mask;

    if (stat & ULITE_STATUS_PARITY)
        flag = TTY_PARITY;


    stat &= ~port->ignore_status_mask;

    if (stat & ULITE_STATUS_RXVALID)
        tty_insert_flip_char(tport, ch, flag);

    if (stat & ULITE_STATUS_FRAME)
        tty_insert_flip_char(tport, 0, TTY_FRAME);

    if (stat & ULITE_STATUS_OVERRUN)
        tty_insert_flip_char(tport, 0, TTY_OVERRUN);

    return 1;
}
예제 #8
0
static void ulite_console_wait_tx(struct uart_port *port)
{
	u8 val;
	unsigned long timeout;

	/* Spin waiting for TX fifo to have space available */
	timeout = jiffies + msecs_to_jiffies(1000);
	while (1) {
		val = uart_in32(ULITE_STATUS, port);
		if ((val & ULITE_STATUS_TXFULL) == 0)
			break;
		if (time_after(jiffies, timeout)) {
			dev_warn(port->dev,
				 "timeout waiting for TX buffer empty\n");
			break;
		}
		cpu_relax();
	}
}
예제 #9
0
static irqreturn_t ulite_isr(int irq, void *dev_id)
{
	struct uart_port *port = dev_id;
	int busy, n = 0;

	do {
		int stat = uart_in32(ULITE_STATUS, port);
		busy  = ulite_receive(port, stat);
		busy |= ulite_transmit(port, stat);
		n++;
	} while (busy);

	/* work done? */
	if (n > 1) {
		tty_flip_buffer_push(port->state->port.tty);
		return IRQ_HANDLED;
	} else {
		return IRQ_NONE;
	}
}
예제 #10
0
파일: uartlite.c 프로젝트: vucan/linux
static irqreturn_t ulite_isr(int irq, void *dev_id)
{
    struct uart_port *port = dev_id;
    int stat, busy, n = 0;
    unsigned long flags;

    do {
        spin_lock_irqsave(&port->lock, flags);
        stat = uart_in32(ULITE_STATUS, port);
        busy  = ulite_receive(port, stat);
        busy |= ulite_transmit(port, stat);
        spin_unlock_irqrestore(&port->lock, flags);
        n++;
    } while (busy);

    /* work done? */
    if (n > 1) {
        tty_flip_buffer_push(&port->state->port);
        return IRQ_HANDLED;
    } else {
        return IRQ_NONE;
    }
}
예제 #11
0
파일: uartlite.c 프로젝트: vucan/linux
static void ulite_shutdown(struct uart_port *port)
{
    uart_out32(0, ULITE_CONTROL, port);
    uart_in32(ULITE_CONTROL, port); /* dummy */
    free_irq(port->irq, port);
}
예제 #12
0
파일: uartlite.c 프로젝트: vucan/linux
static void ulite_start_tx(struct uart_port *port)
{
    ulite_transmit(port, uart_in32(ULITE_STATUS, port));
}