static void baud_protocol_setup(struct omap_uart *uart) { u32 dll, dlh, efr; unsigned int divisor; divisor = uart->clock_hz / (uart->baud << 4); dll = divisor & 0xff; dlh = divisor >> 8; /* * Switch to register configuration mode B to access the UART_OMAP_EFR * register. */ omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B); /* * Enable access to the UART_IER[7:4] bit field. */ efr = omap_read(uart, UART_OMAP_EFR); omap_write(uart, UART_OMAP_EFR, efr|UART_OMAP_EFR_ECB); /* * Switch to register operation mode to access the UART_IER register. */ omap_write(uart, UART_LCR, 0); /* * Clear the UART_IER register (set the UART_IER[4] SLEEP_MODE bit * to 0 to change the UART_DLL and UART_DLM register). Set the * UART_IER register value to 0x0000. */ omap_write(uart, UART_IER, 0); /* * Switch to register configuartion mode B to access the UART_DLL and * UART_DLM registers. */ omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B); /* * Load divisor value. */ omap_write(uart, UART_DLL, dll); omap_write(uart, UART_DLM, dlh); /* * Restore the UART_OMAP_EFR */ omap_write(uart, UART_OMAP_EFR, efr); /* * Load the new protocol formatting (parity, stop-bit, character length) * and switch to register operational mode. */ omap_write(uart, UART_LCR, (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity); }
static void __init omap_uart_init_preirq(struct serial_port *port) { struct omap_uart *uart = port->uart; /* * Clear the FIFO buffers. */ omap_write(uart, UART_FCR, UART_FCR_ENABLE); omap_write(uart, UART_FCR, UART_FCR_ENABLE|UART_FCR_CLRX|UART_FCR_CLTX); omap_write(uart, UART_FCR, 0); /* * The TRM says the mode should be disabled while UART_DLL and UART_DHL * are being changed so we disable before setup, then enable. */ omap_write(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); /* Baud rate & protocol format setup */ baud_protocol_setup(uart); /* FIFO setup */ fifo_setup(uart); /* No flow control */ omap_write(uart, UART_MCR, UART_MCR_DTR|UART_MCR_RTS); omap_write(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); /* setup idle mode */ omap_write(uart, UART_OMAP_SYSC, UART_OMAP_SYSC_DEF_CONF); }
static int omap_uart_tx_ready(struct serial_port *port) { struct omap_uart *uart = port->uart; uint32_t reg; reg = omap_read(uart, UART_IER); omap_write(uart, UART_IER, reg | UART_IER_ETHREI); return omap_read(uart, UART_LSR) & UART_LSR_THRE ? uart->fifo_size : 0; }
static void __init omap_uart_init_postirq(struct serial_port *port) { struct omap_uart *uart = port->uart; uart->irqaction.handler = omap_uart_interrupt; uart->irqaction.name = "omap_uart"; uart->irqaction.dev_id = port; if ( setup_irq(uart->irq, 0, &uart->irqaction) != 0 ) { dprintk(XENLOG_ERR, "Failed to allocated omap_uart IRQ %d\n", uart->irq); return; } /* Enable interrupts */ omap_write(uart, UART_IER, UART_IER_ERDAI|UART_IER_ETHREI|UART_IER_ELSI); }
static int omap_uart_tx_ready(struct serial_port *port) { struct omap_uart *uart = port->uart; uint32_t reg; uint8_t cnt; reg = omap_read(uart, UART_IER); omap_write(uart, UART_IER, reg | UART_IER_ETHREI); /* Check for empty space in TX FIFO */ if ( omap_read(uart, UART_OMAP_SSR) & UART_OMAP_SSR_TX_FIFO_FULL_MASK ) return 0; /* Check number of data bytes stored in TX FIFO */ cnt = omap_read(uart, UART_OMAP_TXFIFO_LVL); ASSERT( cnt >= 0 && cnt <= uart->fifo_size ); return (uart->fifo_size - cnt); }
static void omap_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs) { struct serial_port *port = data; struct omap_uart *uart = port->uart; u32 lsr; uint32_t reg; while ( !(omap_read(uart, UART_IIR) & UART_IIR_NOINT) ) { lsr = omap_read(uart, UART_LSR) & 0xff; if ( lsr & UART_LSR_THRE ) serial_tx_interrupt(port, regs); if ( lsr & UART_LSR_DR ) serial_rx_interrupt(port, regs); if ( port->txbufc == port->txbufp ) { reg = omap_read(uart, UART_IER); omap_write(uart, UART_IER, reg & (~UART_IER_ETHREI)); } }; }
static void omap_uart_putc(struct serial_port *port, char c) { struct omap_uart *uart = port->uart; omap_write(uart, UART_THR, (uint32_t)(unsigned char)c); }
static void fifo_setup(struct omap_uart *uart) { u32 lcr, efr, mcr; /* * Switch to register configuration mode B to access the UART_OMAP_EFR * register. */ lcr = omap_read(uart, UART_LCR); omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B); /* * Enable register submode TCR_TLR to access the UART_OMAP_TLR register. */ efr = omap_read(uart, UART_OMAP_EFR); omap_write(uart, UART_OMAP_EFR, efr|UART_OMAP_EFR_ECB); /* * Switch to register configuration mode A to access the UART_MCR * register. */ omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_A); /* * Enable register submode TCR_TLR to access the UART_OMAP_TLR register */ mcr = omap_read(uart, UART_MCR); omap_write(uart, UART_MCR, mcr|UART_MCR_TCRTLR); /* * Enable the FIFO; load the new FIFO trigger and the new DMA mode. */ omap_write(uart, UART_FCR, UART_FCR_R_TRIG_01| UART_FCR_T_TRIG_10|UART_FCR_ENABLE); /* * Switch to register configuration mode B to access the UART_EFR * register. */ omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B); /* * Load the new FIFO triggers and the new DMA mode bit. */ omap_write(uart, UART_OMAP_SCR, UART_OMAP_SCR_RX_TRIG_GRANU1_MASK); /* * Restore the UART_OMAP_EFR[4] value. */ omap_write(uart, UART_OMAP_EFR, efr); /* * Switch to register configuration mode A to access the UART_MCR * register. */ omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_A); /* * Restore UART_MCR[6] value. */ omap_write(uart, UART_MCR, mcr); /* * Restore UART_LCR value. */ omap_write(uart, UART_LCR, lcr); uart->fifo_size = 64; }