static vmm_irq_return_t omap_uart_irq_handler(int irq_no, void *dev) { u16 iir, lsr; struct omap_uart_port *port = (struct omap_uart_port *)dev; iir = omap_serial_in(port, UART_IIR); if (iir & UART_IIR_NO_INT) return VMM_IRQ_NONE; lsr = omap_serial_in(port, UART_LSR); /* Handle RX FIFO not empty */ if (iir & (UART_IIR_RLSI | UART_IIR_RTO | UART_IIR_RDI)) { if (lsr & UART_LSR_DR) { /* Mask RX interrupts till RX FIFO is empty */ port->ier &= ~(UART_IER_RDI | UART_IER_RLSI); /* Signal work completion to sleeping thread */ vmm_completion_complete(&port->read_possible); } else if (lsr & (UART_LSR_OE | UART_LSR_PE | UART_LSR_BI | UART_LSR_FE) ) { while(1); } } /* Handle TX FIFO not full */ if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI)) { /* Mask TX interrupts till TX FIFO is full */ port->ier &= ~UART_IER_THRI; /* Signal work completion to sleeping thread */ vmm_completion_complete(&port->write_possible); } omap_serial_out(port, UART_IER, port->ier); return VMM_IRQ_HANDLED; }
static vmm_irq_return_t omap_uart_irq_handler(int irq_no, void *dev) { u16 iir, lsr; struct omap_uart_port *port = (struct omap_uart_port *)dev; iir = omap_serial_in(port, UART_IIR); if (iir & UART_IIR_NO_INT) return VMM_IRQ_NONE; lsr = omap_serial_in(port, UART_LSR); /* Handle RX FIFO not empty */ if (iir & (UART_IIR_RLSI | UART_IIR_RTO | UART_IIR_RDI)) { if (lsr & UART_LSR_DR) { do { u8 ch = omap_serial_in(port, UART_RBR); serial_rx(port->p, &ch, 1); } while (omap_serial_in(port, UART_LSR) & (UART_LSR_DR | UART_LSR_OE)); } else if (lsr & (UART_LSR_OE | \ UART_LSR_PE | \ UART_LSR_BI | UART_LSR_FE) ) { while (1); } } omap_serial_out(port, UART_IER, port->ier); return VMM_IRQ_HANDLED; }
void uart_configure_xonxoff(struct omap_uart_port *port) { u16 efr; port->lcr = omap_serial_in(port, UART_LCR); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); port->efr = omap_serial_in(port, UART_EFR); omap_serial_out(port, UART_EFR, port->efr & ~UART_EFR_ECB); omap_serial_out(port, UART_XON1, 0x11); omap_serial_out(port, UART_XOFF1, 0x13); /* clear SW control mode bits */ efr = port->efr; efr &= OMAP_UART_SW_CLR; #if 0 /* Enable if required */ /* * IXON Flag: * Enable XON/XOFF flow control on output. * Transmit XON1, XOFF1 */ efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: * Enable XON/XOFF flow control on input. * Receiver compares XON1, XOFF1. */ efr |= OMAP_UART_SW_RX; #endif omap_serial_out(port, UART_EFR, port->efr | UART_EFR_ECB); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A); port->mcr = omap_serial_in(port, UART_MCR); omap_serial_out(port, UART_MCR, port->mcr | UART_MCR_TCRTLR); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); omap_serial_out(port, UART_TI752_TCR, OMAP_UART_TCR_TRIG); /* Enable special char function UARTi.EFR_REG[5] and * load the new software flow control mode IXON or IXOFF * and restore the UARTi.EFR_REG[4] ENHANCED_EN value. */ omap_serial_out(port, UART_EFR, efr | UART_EFR_SCD); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A); omap_serial_out(port, UART_MCR, port->mcr & ~UART_MCR_TCRTLR); omap_serial_out(port, UART_LCR, port->lcr); }
static u8 omap_uart_getc_sleepable(struct omap_uart_port *port) { /* Wait until there is data in the FIFO */ if (!(omap_serial_in(port, UART_LSR) & UART_LSR_DR)) { /* Enable the RX interrupt */ port->ier |= (UART_IER_RDI | UART_IER_RLSI); omap_serial_out(port, UART_IER, port->ier); /* Wait for completion */ vmm_completion_wait(&port->read_possible); } /* Read data to destination */ return (omap_serial_in(port, UART_RBR)); }
bool omap_uart_lowlevel_can_putc(virtual_addr_t base, u32 reg_align) { if ((omap_serial_in(UART_LSR) & BOTH_EMPTY) == BOTH_EMPTY) { return TRUE; } return FALSE; }
bool omap_uart_lowlevel_can_getc(virtual_addr_t base, u32 reg_align) { if (omap_serial_in(UART_LSR) & UART_LSR_DR) { return TRUE; } return FALSE; }
/* * Internal UARTs need to be initialized for the 8250 autoconfig to work * properly. Note that the TX watermark initialization may not be needed * once the 8250.c watermark handling code is merged. */ static void __init omap_serial_reset(struct plat_serial8250_port *p) { omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */ omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */ omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */ if (!cpu_is_omap1510()) { omap_serial_outp(p, UART_OMAP_SYSC, 0x01); while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01)); } }
static void __init omap_serial_reset(struct plat_serial8250_port *p) { omap_serial_outp(p, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); omap_serial_outp(p, UART_OMAP_SCR, 0x08); omap_serial_outp(p, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); if (!cpu_is_omap15xx()) { omap_serial_outp(p, UART_OMAP_SYSC, 0x01); while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01)); } }
u8 omap_uart_lowlevel_getc(virtual_addr_t base, u32 reg_align) { while (!omap_uart_lowlevel_can_getc(base, reg_align)); return (omap_serial_in(UART_RBR)); }
static int omap_uart_startup_configure(struct omap_uart_port *port) { u16 bdiv, cval; bdiv = udiv32(port->input_clock, (16 * port->baudrate)); /* * Clear the FIFO buffers and disable them. */ omap_serial_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); omap_serial_out(port, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); omap_serial_out(port, UART_FCR, 0); /* * Clear the interrupt registers. */ (void) omap_serial_in(port, UART_LSR); if (omap_serial_in(port, UART_LSR) & UART_LSR_DR) (void) omap_serial_in(port, UART_RBR); (void) omap_serial_in(port, UART_IIR); (void) omap_serial_in(port, UART_MSR); cval = UART_LCR_WLEN8; /* * Now, initialize the UART */ omap_serial_out(port, UART_LCR, cval); /* * Finally, enable interrupts */ port->ier = UART_IER_RLSI | UART_IER_RDI; omap_serial_out(port, UART_IER, port->ier); /* Enable module level wake port */ omap_serial_out(port, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); port->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; port->ier &= ~UART_IER_MSI; omap_serial_out(port, UART_IER, port->ier); omap_serial_out(port, UART_LCR, cval); /* reset DLAB */ /* FCR can be changed only when the * baud clock is not running * DLL_REG and DLH_REG set to 0. */ omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A); omap_serial_out(port, UART_DLL, 0); omap_serial_out(port, UART_DLM, 0); omap_serial_out(port, UART_LCR, 0); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); port->efr = omap_serial_in(port, UART_EFR); omap_serial_out(port, UART_EFR, port->efr | UART_EFR_ECB); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A); port->mcr = omap_serial_in(port, UART_MCR); omap_serial_out(port, UART_MCR, port->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ omap_serial_out(port, UART_FCR, port->fcr); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); omap_serial_out(port, UART_EFR, port->efr); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_A); omap_serial_out(port, UART_MCR, port->mcr); /* Protocol, Baud Rate, and Interrupt Settings */ omap_serial_out(port, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); port->efr = omap_serial_in(port, UART_EFR); omap_serial_out(port, UART_EFR, port->efr | UART_EFR_ECB); omap_serial_out(port, UART_LCR, 0); omap_serial_out(port, UART_IER, 0); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); omap_serial_out(port, UART_DLL, bdiv & 0xff); /* LS of divisor */ omap_serial_out(port, UART_DLM, bdiv >> 8); /* MS of divisor */ omap_serial_out(port, UART_LCR, 0); omap_serial_out(port, UART_IER, port->ier); omap_serial_out(port, UART_LCR, UART_LCR_CONF_MODE_B); omap_serial_out(port, UART_EFR, port->efr); omap_serial_out(port, UART_LCR, cval); omap_serial_out(port, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); omap_serial_out(port, UART_MCR, port->mcr); uart_configure_xonxoff(port); return VMM_OK; }