static void tegra_stop_rx(struct uart_port *u) { struct tegra_uart_port *t; unsigned char ier; t = container_of(u, struct tegra_uart_port, uport); if (t->rts_active) set_rts(t, false); if (t->rx_in_progress) { wait_sym_time(t, 1); /* wait a character interval */ ier = t->ier_shadow; ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD); t->ier_shadow = ier; uart_writeb(t, ier, UART_IER); t->rx_in_progress = 0; if (t->use_rx_dma && t->rx_dma) tegra_dma_dequeue_req(t->rx_dma, &t->rx_dma_req); else do_handle_rx_pio(t); tty_flip_buffer_push(u->state->port.tty); } return; }
static void tegra_start_rx(struct uart_port *u) { struct tegra_uart_port *t; unsigned char ier; t = container_of(u, struct tegra_uart_port, uport); if (t->rts_active) set_rts(t, true); if (!t->rx_in_progress) { wait_sym_time(t, 1); /* wait a character interval */ /* Clear the received Bytes from FIFO */ tegra_fifo_reset(t, UART_FCR_CLEAR_RCVR); uart_readb(t, UART_LSR); ier = 0; ier |= (UART_IER_RLSI | UART_IER_RTOIE); if (t->use_rx_dma) ier |= UART_IER_EORD; else ier |= UART_IER_RDI; t->ier_shadow |= ier; uart_writeb(t, t->ier_shadow, UART_IER); t->rx_in_progress = 1; if (t->use_rx_dma && t->rx_dma) tegra_dma_enqueue_req(t->rx_dma, &t->rx_dma_req); tty_flip_buffer_push(u->state->port.tty); } return; }
/* Flush desired FIFO. */ static void tegra_fifo_reset(struct tegra_uart_port *t, u8 fcr_bits) { unsigned char fcr = t->fcr_shadow; fcr |= fcr_bits & (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); uart_writeb(t, fcr, UART_FCR); uart_readb(t, UART_SCR); /* Dummy read to ensure the write is posted */ wait_sym_time(t, 1); /* Wait for the flush to propagate. */ }
static void tegra_set_baudrate(struct tegra_uart_port *t, unsigned int baud) { unsigned long rate; unsigned int divisor; unsigned char lcr; unsigned int baud_actual; unsigned int baud_delta; unsigned long best_rate; if (t->baud == baud) return; rate = baud * 16; best_rate = find_best_clock_source(t, rate); clk_set_rate(t->clk, best_rate); rate = clk_get_rate(t->clk); divisor = rate; do_div(divisor, 16); divisor += baud/2; do_div(divisor, baud); /* The allowable baudrate error from desired baudrate is 5% */ baud_actual = divisor ? rate / (16 * divisor) : 0; baud_delta = abs(baud_actual - baud); if (WARN_ON(baud_delta * 20 > baud)) { dev_err(t->uport.dev, "requested baud %u, actual %u\n", baud, baud_actual); } lcr = t->lcr_shadow; lcr |= UART_LCR_DLAB; uart_writeb(t, lcr, UART_LCR); uart_writel(t, divisor & 0xFF, UART_TX); uart_writel(t, ((divisor >> 8) & 0xFF), UART_IER); lcr &= ~UART_LCR_DLAB; uart_writeb(t, lcr, UART_LCR); uart_readb(t, UART_SCR); /* Dummy read to ensure the write is posted */ t->baud = baud; wait_sym_time(t, 2); /* wait two character intervals at new rate */ dev_dbg(t->uport.dev, "Baud %u clock freq %lu and divisor of %u\n", baud, rate, divisor); }
/* Flush desired FIFO. */ static void tegra_fifo_reset(struct tegra_uart_port *t, u8 fcr_bits) { unsigned char fcr = t->fcr_shadow; #ifdef CONFIG_ARCH_TEGRA_2x_SOC fcr |= fcr_bits & (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); uart_writeb(t, fcr, UART_FCR); #else /*Hw issue: Resetting tx fifo with non-fifo mode to avoid any extra character to be sent*/ fcr &= ~UART_FCR_ENABLE_FIFO; uart_writeb(t, fcr, UART_FCR); udelay(60); fcr |= fcr_bits & (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); uart_writeb(t, fcr, UART_FCR); fcr |= UART_FCR_ENABLE_FIFO; uart_writeb(t, fcr, UART_FCR); #endif uart_readb(t, UART_SCR); /* Dummy read to ensure the write is posted */ wait_sym_time(t, 1); /* Wait for the flush to propagate. */ }