int omap_uart_active(int num, u32 timeout) { struct uart_omap_port *up = ui[num]; struct circ_buf *xmit; unsigned int status; /* Though when UART's initialised this can never happen, * but during initialisation, it can happen the "ui" * structure is not initialized and the timer kicks * in. This would result in a NULL value, resulting * in crash. */ if (up == NULL) return 0; /* Check for recent driver activity. If time delta from now * to last activty < "uart idle timeout" second keep clocks on. */ if (((jiffies - up->port_activity) < timeout)) return 1; xmit = &up->port.state->xmit; if (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) return 1; status = serial_in(up, UART_LSR); /* TX hardware not empty */ if (!(status & (UART_LSR_TEMT | UART_LSR_THRE))) return 1; /* Any rx activity? */ if (status & UART_LSR_DR) return 1; /* Check if DMA channels are active */ if (up->use_dma && (up->uart_dma.rx_dma_channel != OMAP_UART_DMA_CH_FREE || up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE)) return 1; return 0; }
/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. */ static void serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { struct uart_pxa_port *up = &serial_pxa_ports[co->index]; unsigned int ier; /* * First save the IER then disable the interrupts */ ier = serial_in(up, UART_IER); serial_out(up, UART_IER, UART_IER_UUE); uart_console_write(&up->port, s, count, serial_pxa_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the IER */ wait_for_xmitr(up); serial_out(up, UART_IER, ier); }
static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr) { unsigned char ch = 0; unsigned int flag; if (!(lsr & UART_LSR_DR)) return; ch = serial_in(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; #ifdef CONFIG_CONSOLE_POLL if (up->port.poll_rx_cb && up->port.poll_rx_cb(ch)) return; #endif if (uart_handle_sysrq_char(&up->port, ch)) return; uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); }
static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = up->port.private_data; u8 lcr; serial8250_do_set_mctrl(port, mctrl); /* * Turn off autoRTS if RTS is lowered and restore autoRTS setting * if RTS is raised */ lcr = serial_in(up, UART_LCR); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) priv->efr |= UART_EFR_RTS; else priv->efr &= ~UART_EFR_RTS; serial_out(up, UART_EFR, priv->efr); serial_out(up, UART_LCR, lcr); }
static void serial_omap_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char efr; dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, 0); /* Enable module level wake up */ serial_out(up, UART_OMAP_WER, (state != 0) ? OMAP_UART_WER_MOD_WKUP : 0); }
static void ip3106_tx_chars(struct ip3106_port *sport) { struct circ_buf *xmit = &sport->port.info->xmit; if (sport->port.x_char) { serial_out(sport, IP3106_FIFO, sport->port.x_char); sport->port.icount.tx++; sport->port.x_char = 0; return; } /* * Check the modem control lines before * transmitting anything. */ ip3106_mctrl_check(sport); if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { ip3106_stop_tx(&sport->port, 0); return; } /* * TX while bytes available */ while (((serial_in(sport, IP3106_FIFO) & IP3106_UART_FIFO_TXFIFO) >> 16) < 16) { serial_out(sport, IP3106_FIFO, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); sport->port.icount.tx++; if (uart_circ_empty(xmit)) break; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&sport->port); if (uart_circ_empty(xmit)) ip3106_stop_tx(&sport->port, 0); }
static unsigned int serial_pxa_tx_empty(struct uart_port *port) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned long flags; unsigned int ret; spin_lock_irqsave(&up->port.lock, flags); if (up->dma_enable) { if (up->ier & UART_IER_DMAE) { if (up->uart_dma.dma_status & TX_DMA_RUNNING) { spin_unlock_irqrestore(&up->port.lock, flags); return 0; } } } ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; spin_unlock_irqrestore(&up->port.lock, flags); return ret; }
static unsigned int serial8250_get_mctrl(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned long flags; unsigned char status; unsigned int ret; spin_lock_irqsave(&up->port.lock, flags); status = serial_in(up, UART_MSR); spin_unlock_irqrestore(&up->port.lock, flags); ret = 0; if (status & UART_MSR_DCD) ret |= TIOCM_CAR; if (status & UART_MSR_RI) ret |= TIOCM_RNG; if (status & UART_MSR_DSR) ret |= TIOCM_DSR; if (status & UART_MSR_CTS) ret |= TIOCM_CTS; return ret; }
static inline void check_modem_status(struct uart_hsu_port *up) { int status; status = serial_in(up, UART_MSR); if ((status & UART_MSR_ANY_DELTA) == 0) return; if (status & UART_MSR_TERI) up->port.icount.rng++; if (status & UART_MSR_DDSR) up->port.icount.dsr++; /* We may only get DDCD when HW init and reset */ if (status & UART_MSR_DDCD) uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); /* Will start/stop_tx accordingly */ if (status & UART_MSR_DCTS) uart_handle_cts_change(&up->port, status & UART_MSR_CTS); wake_up_interruptible(&up->port.state->port.delta_msr_wait); }
/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. */ static void serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { struct uart_pxa_port *up = serial_pxa_ports[co->index]; unsigned int ier; unsigned long flags; int locked = 1; clk_enable(up->clk); local_irq_save(flags); if (up->port.sysrq) locked = 0; else if (oops_in_progress) locked = spin_trylock(&up->port.lock); else spin_lock(&up->port.lock); /* * First save the IER then disable the interrupts */ ier = serial_in(up, UART_IER); serial_out(up, UART_IER, UART_IER_UUE); uart_console_write(&up->port, s, count, serial_pxa_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the IER */ wait_for_xmitr(up); serial_out(up, UART_IER, ier); if (locked) spin_unlock(&up->port.lock); local_irq_restore(flags); clk_disable(up->clk); }
static void serial_hsu_shutdown(struct uart_port *port) { struct uart_hsu_port *up = container_of(port, struct uart_hsu_port, port); unsigned long flags; /* Disable interrupts from this port */ up->ier = 0; serial_out(up, UART_IER, 0); up->running = 0; spin_lock_irqsave(&up->port.lock, flags); up->port.mctrl &= ~TIOCM_OUT2; serial_hsu_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); /* Disable break condition and FIFOs */ serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_out(up, UART_FCR, 0); }
//static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char mcr = 0; dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id); if (mctrl & TIOCM_RTS) mcr |= UART_MCR_RTS; if (mctrl & TIOCM_DTR) mcr |= UART_MCR_DTR; if (mctrl & TIOCM_OUT1) mcr |= UART_MCR_OUT1; if (mctrl & TIOCM_OUT2) mcr |= UART_MCR_OUT2; if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; serial_omap_port_enable(up); up->mcr = serial_in(up, UART_MCR); up->mcr |= mcr; serial_out(up, UART_MCR, up->mcr); serial_omap_port_disable(up); }
static void serial_omap_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { struct uart_omap_port *up = to_uart_omap_port(port); unsigned char efr; dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line); pm_runtime_get_sync(up->dev); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, 0); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); }
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char mcr = 0; dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line); if (mctrl & TIOCM_RTS) mcr |= UART_MCR_RTS; if (mctrl & TIOCM_DTR) mcr |= UART_MCR_DTR; if (mctrl & TIOCM_OUT1) mcr |= UART_MCR_OUT1; if (mctrl & TIOCM_OUT2) mcr |= UART_MCR_OUT2; if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; pm_runtime_get_sync(&up->pdev->dev); up->mcr = serial_in(up, UART_MCR); up->mcr |= mcr; serial_out(up, UART_MCR, up->mcr); pm_runtime_put(&up->pdev->dev); }
/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. */ static void serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; int i; /* * First save the UER then disable the interrupts */ ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); /* * Now, do each character */ for (i = 0; i < count; i++, s++) { wait_for_xmitr(up); /* * Send the character out. * If a LF, also do CR... */ serial_out(up, UART_TX, *s); if (*s == 10) { wait_for_xmitr(up); serial_out(up, UART_TX, 13); } } /* * Finally, wait for transmitter to become empty * and restore the IER */ wait_for_xmitr(up); serial_out(up, UART_IER, ier); }
static void transmit_chars(struct uart_sio_port *up) { struct circ_buf *xmit = &up->port.state->xmit; int count; if (up->port.x_char) { #ifndef CONFIG_SERIAL_M32R_PLDSIO /* XXX */ serial_out(up, UART_TX, up->port.x_char); #endif up->port.icount.tx++; up->port.x_char = 0; return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { m32r_sio_stop_tx(&up->port); return; } count = up->port.fifosize; do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); up->port.icount.tx++; if (uart_circ_empty(xmit)) break; while (!(serial_in(up, UART_LSR) & UART_LSR_THRE)); } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); pr_debug("THRE...\n"); if (uart_circ_empty(xmit)) m32r_sio_stop_tx(&up->port); }
static void serial_omap_set_autorts(struct uart_omap_port *p, int set) { u8 lcr_val = 0, mcr_val = 0, efr_val = 0; u8 lcr_backup = 0, mcr_backup = 0, efr_backup = 0; lcr_val = serial_in(p, UART_LCR); lcr_backup = lcr_val; /* Enter Config mode B */ serial_out(p, UART_LCR, 0xbf); efr_val = serial_in(p, UART_EFR); efr_backup = efr_val; /* * Enhanced functions write enable. * Enables writes to IER[7:4], FCR[5:4], MCR[7:5] */ serial_out(p, UART_EFR, efr_val | 0x10); mcr_val = serial_in(p, UART_MCR); mcr_backup = mcr_val; /* Enable access to TCR_REG and TLR_REG */ serial_out(p, UART_MCR, mcr_val | 0x40); /* Set RX_FIFO_TRIG levels */ serial_out(p, 0x18, 0x0f); efr_val = serial_in(p, UART_EFR); if (set) serial_out(p, UART_EFR, efr_val | (1 << 6)); else serial_out(p, UART_EFR, efr_val & ~(1 << 6)); mcr_val = serial_in(p, UART_MCR); /* Restore original state of TCR_TLR access */ serial_out(p, UART_MCR, (mcr_val & ~0x40) | (mcr_backup & 0x40)); /* Enhanced function write disable. */ serial_out(p, UART_EFR, serial_in(p, UART_EFR) & ~0x10); /* Normal operation */ serial_out(p, UART_LCR, lcr_backup); }
static int pnx8xxx_startup(struct uart_port *port) { struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; int retval; retval = request_irq(sport->port.irq, pnx8xxx_int, 0, "pnx8xxx-uart", sport); if (retval) return retval; serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX | PNX8XXX_UART_INT_ALLTX); serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) | PNX8XXX_UART_INT_ALLRX | PNX8XXX_UART_INT_ALLTX); spin_lock_irq(&sport->port.lock); pnx8xxx_enable_ms(&sport->port); spin_unlock_irq(&sport->port.lock); return 0; }
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_omap_port *up = to_uart_omap_port(port); unsigned char mcr = 0, old_mcr; dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line); if (mctrl & TIOCM_RTS) mcr |= UART_MCR_RTS; if (mctrl & TIOCM_DTR) mcr |= UART_MCR_DTR; if (mctrl & TIOCM_OUT1) mcr |= UART_MCR_OUT1; if (mctrl & TIOCM_OUT2) mcr |= UART_MCR_OUT2; if (mctrl & TIOCM_LOOP) mcr |= UART_MCR_LOOP; pm_runtime_get_sync(up->dev); old_mcr = serial_in(up, UART_MCR); old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 | UART_MCR_DTR | UART_MCR_RTS); up->mcr = old_mcr | mcr; serial_out(up, UART_MCR, up->mcr); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); if (gpio_is_valid(up->DTR_gpio) && !!(mctrl & TIOCM_DTR) != up->DTR_active) { up->DTR_active = !up->DTR_active; if (gpio_cansleep(up->DTR_gpio)) schedule_work(&up->qos_work); else gpio_set_value(up->DTR_gpio, up->DTR_active != up->DTR_inverted); } }
DEBUG_UART_FUNCS #endif #ifdef CONFIG_DM_SERIAL static int ns16550_serial_putc(struct udevice *dev, const char ch) { struct NS16550 *const com_port = dev_get_priv(dev); if (!(serial_in(&com_port->lsr) & UART_LSR_THRE)) return -EAGAIN; serial_out(ch, &com_port->thr); /* * Call watchdog_reset() upon newline. This is done here in putc * since the environment code uses a single puts() to print the complete * environment upon "printenv". So we can't put this watchdog call * in puts(). */ if (ch == '\n') WATCHDOG_RESET(); return 0; }
static unsigned int sw_uart_modem_status(struct sw_uart_port *sw_uport) { unsigned int status = serial_in(&sw_uport->port, SW_UART_MSR); status |= sw_uport->msr_saved_flags; sw_uport->msr_saved_flags = 0; if (status & SW_UART_MSR_ANY_DELTA && sw_uport->ier & SW_UART_IER_MSI && sw_uport->port.state != NULL) { if (status & SW_UART_MSR_TERI) sw_uport->port.icount.rng++; if (status & SW_UART_MSR_DDSR) sw_uport->port.icount.dsr++; if (status & SW_UART_MSR_DDCD) uart_handle_dcd_change(&sw_uport->port, status & SW_UART_MSR_DCD); if (!(sw_uport->mcr & SW_UART_MCR_AFE) && status & SW_UART_MSR_DCTS) uart_handle_cts_change(&sw_uport->port, status & SW_UART_MSR_CTS); wake_up_interruptible(&sw_uport->port.state->port.delta_msr_wait); } SERIAL_DBG("modem status: %x\n", status); return status; }
static void serial_omap_start_rxdma(struct uart_omap_port *up) { #ifdef CONFIG_OMAP3_PM /* Disallow OCP bus idle. UART TX irqs are not seen during * bus idle. Alternative is to set kernel timer at fifo * drain rate. */ unsigned int tmp; tmp = (serial_in(up, UART_OMAP_SYSC) & 0x7) | (1 << 3); serial_out(up, UART_OMAP_SYSC, tmp); /* no-idle */ #endif if (up->uart_dma.rx_dma_channel == 0xFF) omap_request_dma(uart_dma_rx[up->pdev->id-1], "UART Rx DMA", (void *)uart_rx_dma_callback, up, &(up->uart_dma.rx_dma_channel)); omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, UART_BASE(up->pdev->id - 1), 0, 0); omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, up->uart_dma.rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.rx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_rx[up->pdev->id-1], 0); up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; omap_writel(0, OMAP34XX_DMA4_BASE + OMAP_DMA4_CDAC(up->uart_dma.rx_dma_channel)); omap_start_dma(up->uart_dma.rx_dma_channel); mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_timeout)); up->uart_dma.rx_dma_state = 1; }
static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char cval = 0; unsigned char efr = 0; unsigned long flags = 0; unsigned int baud, quot; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); quot = serial_omap_get_divisor(port, baud); up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; if (up->use_dma) up->fcr |= UART_FCR_DMA_SELECT; /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ spin_lock_irqsave(&up->port.lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, cval); /* reset DLAB */ /* FIFOs and DMA Settings */ /* FCR can be changed only when the * baud clock is not running * DLL_REG and DLH_REG set to 0. */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_DLL, 0); serial_out(up, UART_DLM, 0); serial_out(up, UART_LCR, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if (up->use_dma) { serial_out(up, UART_TI752_TLR, 0); serial_out(up, UART_OMAP_SCR, (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8)); } serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr); /* Protocol, Baud Rate, and Interrupt Settings */ serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, cval); if (baud > 230400 && baud != 3000000) serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE); else serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE); /* Hardware Flow Control Configuration */ if (termios->c_cflag & CRTSCTS) { efr |= (UART_EFR_CTS | UART_EFR_RTS); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS); serial_out(up, UART_LCR, cval); } serial_omap_set_mctrl(&up->port, up->port.mctrl); /* Software Flow Control Configuration */ serial_omap_configure_xonxoff(up, termios); spin_unlock_irqrestore(&up->port.lock, flags); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); }
static int serial_omap_startup(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned long flags = 0; int retval; /* * Allocate the IRQ */ retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags, up->name, up); if (retval) return retval; dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id); /* * Clear the FIFO buffers and disable them. * (they will be reenabled in set_termios()) */ serial_omap_clear_fifos(up); /* For Hardware flow control */ serial_out(up, UART_MCR, UART_MCR_RTS); /* * Clear the interrupt registers. */ (void) serial_in(up, UART_LSR); if (serial_in(up, UART_LSR) & UART_LSR_DR) (void) serial_in(up, UART_RX); (void) serial_in(up, UART_IIR); (void) serial_in(up, UART_MSR); /* * Now, initialize the UART */ serial_out(up, UART_LCR, UART_LCR_WLEN8); spin_lock_irqsave(&up->port.lock, flags); /* * Most PC uarts need OUT2 raised to enable interrupts. */ up->port.mctrl |= TIOCM_OUT2; serial_omap_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); up->msr_saved_flags = 0; if (up->use_dma) { free_page((unsigned long)up->port.state->xmit.buf); up->port.state->xmit.buf = dma_alloc_coherent(NULL, UART_XMIT_SIZE, (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys), 0); init_timer(&(up->uart_dma.rx_timer)); up->uart_dma.rx_timer.function = serial_omap_rx_timeout; up->uart_dma.rx_timer.data = up->pdev->id; /* Currently the buffer size is 4KB. Can increase it */ up->uart_dma.rx_buf = dma_alloc_coherent(NULL, up->uart_dma.rx_buf_size, (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0); } /* * Finally, enable interrupts. Note: Modem status interrupts * are set via set_termios(), which will be occurring imminently * anyway, so we don't enable them here. */ up->ier = UART_IER_RLSI | UART_IER_RDI; serial_out(up, UART_IER, up->ier); /* Enable module level wake up */ serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); up->port_activity = jiffies; return 0; }
static inline void serial_omap_configure_xonxoff (struct uart_omap_port *up, struct ktermios *termios) { unsigned char efr = 0; up->lcr = serial_in(up, UART_LCR); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB); serial_out(up, UART_XON1, termios->c_cc[VSTART]); serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); /* clear SW control mode bits */ efr = up->efr; efr &= OMAP_UART_SW_CLR; /* * IXON Flag: * Enable XON/XOFF flow control on output. * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXON) efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: * Enable XON/XOFF flow control on input. * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXOFF) efr |= OMAP_UART_SW_RX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); /* * IXANY Flag: * Enable any character to restart output. * Operation resumes after receiving any * character after recognition of the XOFF character */ if (termios->c_iflag & IXANY) up->mcr |= UART_MCR_XONANY; serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, 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. */ serial_out(up, UART_EFR, efr | UART_EFR_SCD); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR); serial_out(up, UART_LCR, up->lcr); }
static inline void receive_chars(struct uart_omap_port *up, int *status) { struct tty_struct *tty = up->port.state->port.tty; unsigned int flag; unsigned char ch, lsr = *status; int max_count = 256; do { if (likely(lsr & UART_LSR_DR)) ch = serial_in(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { /* * For statistics only */ if (lsr & UART_LSR_BI) { lsr &= ~(UART_LSR_FE | UART_LSR_PE); up->port.icount.brk++; /* * We do the SysRQ and SAK checking * here because otherwise the break * may get masked by ignore_status_mask * or read_status_mask. */ if (uart_handle_break(&up->port)) goto ignore_char; } else if (lsr & UART_LSR_PE) { up->port.icount.parity++; } else if (lsr & UART_LSR_FE) { up->port.icount.frame++; } if (lsr & UART_LSR_OE) up->port.icount.overrun++; /* * Mask off conditions which should be ignored. */ lsr &= up->port.read_status_mask; #ifdef CONFIG_SERIAL_OMAP_CONSOLE if (up->port.line == up->port.cons->index) { /* Recover the break flag from console xmit */ lsr |= up->lsr_break_flag; } #endif if (lsr & UART_LSR_BI) flag = TTY_BREAK; else if (lsr & UART_LSR_PE) flag = TTY_PARITY; else if (lsr & UART_LSR_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); ignore_char: lsr = serial_in(up, UART_LSR); } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); spin_unlock(&up->port.lock); tty_flip_buffer_push(tty); spin_lock(&up->port.lock); }
static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char cval = 0; unsigned char efr = 0; unsigned long flags = 0; unsigned int baud, quot; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); quot = serial_omap_get_divisor(port, baud); up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8); up->latency = up->calc_latency; schedule_work(&up->qos_work); up->dll = quot & 0xff; up->dlh = quot >> 8; up->mdr1 = UART_OMAP_MDR1_DISABLE; up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; if (up->use_dma) up->fcr |= UART_FCR_DMA_SELECT; pm_runtime_get_sync(&up->pdev->dev); spin_lock_irqsave(&up->port.lock, flags); uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, cval); up->lcr = cval; up->scr = OMAP_UART_SCR_TX_EMPTY; serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_DLL, 0); serial_out(up, UART_DLM, 0); serial_out(up, UART_LCR, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; if (up->use_dma) { serial_out(up, UART_TI752_TLR, 0); up->scr |= UART_FCR_TRIGGER_4; } else { up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT); } serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_OMAP_SCR, up->scr); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr); if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) serial_omap_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_DLL, up->dll); serial_out(up, UART_DLM, up->dlh); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, cval); if (baud > 230400 && baud != 3000000) up->mdr1 = UART_OMAP_MDR1_13X_MODE; else up->mdr1 = UART_OMAP_MDR1_16X_MODE; if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) serial_omap_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); if (termios->c_cflag & CRTSCTS) { efr |= (UART_EFR_CTS | UART_EFR_RTS); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); serial_out(up, UART_EFR, efr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS); serial_out(up, UART_LCR, cval); } serial_omap_set_mctrl(&up->port, up->port.mctrl); serial_omap_configure_xonxoff(up, termios); spin_unlock_irqrestore(&up->port.lock, flags); pm_runtime_put(&up->pdev->dev); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); }
int NS16550_tstc(NS16550_t com_port) { return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0; }
/* * What special to do: * 1. chose the 64B fifo mode * 2. make sure not to select half empty mode for A0 stepping * 3. start dma or pio depends on configuration * 4. we only allocate dma memory when needed */ static int serial_hsu_startup(struct uart_port *port) { struct uart_hsu_port *up = container_of(port, struct uart_hsu_port, port); unsigned long flags; /* * Clear the FIFO buffers and disable them. * (they will be reenabled in set_termios()) */ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_out(up, UART_FCR, 0); /* Clear the interrupt registers. */ (void) serial_in(up, UART_LSR); (void) serial_in(up, UART_RX); (void) serial_in(up, UART_IIR); (void) serial_in(up, UART_MSR); /* Now, initialize the UART, default is 8n1 */ serial_out(up, UART_LCR, UART_LCR_WLEN8); spin_lock_irqsave(&up->port.lock, flags); up->port.mctrl |= TIOCM_OUT2; serial_hsu_set_mctrl(&up->port, up->port.mctrl); /* * Finally, enable interrupts. Note: Modem status interrupts * are set via set_termios(), which will be occurring imminently * anyway, so we don't enable them here. */ if (!up->use_dma) up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE; else up->ier = 0; serial_out(up, UART_IER, up->ier); spin_unlock_irqrestore(&up->port.lock, flags); /* DMA init */ if (up->use_dma) { struct hsu_dma_buffer *dbuf; struct circ_buf *xmit = &port->state->xmit; up->dma_tx_on = 0; /* First allocate the RX buffer */ dbuf = &up->rxbuf; dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL); if (!dbuf->buf) { up->use_dma = 0; goto exit; } dbuf->dma_addr = dma_map_single(port->dev, dbuf->buf, HSU_DMA_BUF_SIZE, DMA_FROM_DEVICE); dbuf->dma_size = HSU_DMA_BUF_SIZE; /* Start the RX channel right now */ hsu_dma_start_rx_chan(up->rxc, dbuf); /* Next init the TX DMA */ dbuf = &up->txbuf; dbuf->buf = xmit->buf; dbuf->dma_addr = dma_map_single(port->dev, dbuf->buf, UART_XMIT_SIZE, DMA_TO_DEVICE); dbuf->dma_size = UART_XMIT_SIZE; /* This should not be changed all around */ chan_writel(up->txc, HSU_CH_BSR, 32); chan_writel(up->txc, HSU_CH_MOTSR, 4); dbuf->ofs = 0; } exit: /* And clear the interrupt registers again for luck. */ (void) serial_in(up, UART_LSR); (void) serial_in(up, UART_RX); (void) serial_in(up, UART_IIR); (void) serial_in(up, UART_MSR); up->running = 1; return 0; }
static inline void receive_chars(struct uart_hsu_port *up, int *status) { struct tty_struct *tty = up->port.state->port.tty; unsigned int ch, flag; unsigned int max_count = 256; if (!tty) return; do { ch = serial_in(up, UART_RX); flag = TTY_NORMAL; up->port.icount.rx++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE | UART_LSR_OE))) { dev_warn(up->dev, "We really rush into ERR/BI case" "status = 0x%02x", *status); /* For statistics only */ if (*status & UART_LSR_BI) { *status &= ~(UART_LSR_FE | UART_LSR_PE); up->port.icount.brk++; /* * We do the SysRQ and SAK checking * here because otherwise the break * may get masked by ignore_status_mask * or read_status_mask. */ if (uart_handle_break(&up->port)) goto ignore_char; } else if (*status & UART_LSR_PE) up->port.icount.parity++; else if (*status & UART_LSR_FE) up->port.icount.frame++; if (*status & UART_LSR_OE) up->port.icount.overrun++; /* Mask off conditions which should be ignored. */ *status &= up->port.read_status_mask; #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE if (up->port.cons && up->port.cons->index == up->port.line) { /* Recover the break flag from console xmit */ *status |= up->lsr_break_flag; up->lsr_break_flag = 0; } #endif if (*status & UART_LSR_BI) { flag = TTY_BREAK; } else if (*status & UART_LSR_PE) flag = TTY_PARITY; else if (*status & UART_LSR_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); ignore_char: *status = serial_in(up, UART_LSR); } while ((*status & UART_LSR_DR) && max_count--); tty_flip_buffer_push(tty); }