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); }
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; }
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); }
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); }
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; }
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(); } }
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; }
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(); } }
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; } }
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; } }
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); }
static void ulite_start_tx(struct uart_port *port) { ulite_transmit(port, uart_in32(ULITE_STATUS, port)); }