static void tegra_start_pio_tx(struct tegra_uart_port *t, unsigned int bytes) { if (bytes > TEGRA_UART_FIFO_SIZE) bytes = TEGRA_UART_FIFO_SIZE; t->fcr_shadow &= ~UART_FCR_T_TRIG_11; t->fcr_shadow |= TEGRA_UART_TX_TRIG_8B; uart_writeb(t, t->fcr_shadow, UART_FCR); t->tx_in_progress = TEGRA_TX_PIO; t->tx_bytes = bytes; t->ier_shadow |= UART_IER_THRI; uart_writeb(t, t->ier_shadow, UART_IER); }
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; }
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; 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. */ }
/* 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. */ }
static void tegra_uart_hw_deinit(struct tegra_uart_port *t) { unsigned long flags; unsigned long char_time = DIV_ROUND_UP(10000000, t->baud); unsigned long fifo_empty_time = t->uport.fifosize * char_time; unsigned long wait_time; unsigned char lsr; unsigned char msr; unsigned char mcr; /* Disable interrupts */ uart_writeb(t, 0, UART_IER); lsr = uart_readb(t, UART_LSR); if ((lsr & UART_LSR_TEMT) != UART_LSR_TEMT) { msr = uart_readb(t, UART_MSR); mcr = uart_readb(t, UART_MCR); if ((mcr & UART_MCR_CTS_EN) && (msr & UART_MSR_CTS)) dev_err(t->uport.dev, "%s: Tx fifo not empty and " "slave disabled CTS, Waiting for slave to" " be ready\n", __func__); /* Wait for Tx fifo to be empty */ while ((lsr & UART_LSR_TEMT) != UART_LSR_TEMT) { wait_time = min(fifo_empty_time, 100lu); udelay(wait_time); fifo_empty_time -= wait_time; if (!fifo_empty_time) { msr = uart_readb(t, UART_MSR); mcr = uart_readb(t, UART_MCR); if ((mcr & UART_MCR_CTS_EN) && (msr & UART_MSR_CTS)) dev_err(t->uport.dev, "%s: Slave is " "still not ready!\n", __func__); break; } lsr = uart_readb(t, UART_LSR); } } spin_lock_irqsave(&t->uport.lock, flags); /* Reset the Rx and Tx FIFOs */ tegra_fifo_reset(t, UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); t->baud = 0; t->uart_state = TEGRA_UART_CLOSED; spin_unlock_irqrestore(&t->uport.lock, flags); clk_disable_unprepare(t->clk); pm_runtime_put_sync((&t->uport)->dev); }
static void fill_tx_fifo(struct tegra_uart_port *t, int max_bytes) { int i; struct circ_buf *xmit = &t->uport.state->xmit; for (i = 0; i < max_bytes; i++) { BUG_ON(uart_circ_empty(xmit)); uart_writeb(t, xmit->buf[xmit->tail], UART_TX); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); t->uport.icount.tx++; } }
static void tegra_break_ctl(struct uart_port *u, int break_ctl) { struct tegra_uart_port *t; unsigned char lcr; t = container_of(u, struct tegra_uart_port, uport); lcr = t->lcr_shadow; if (break_ctl) lcr |= UART_LCR_SBC; else lcr &= ~UART_LCR_SBC; uart_writeb(t, lcr, UART_LCR); t->lcr_shadow = lcr; }
static void set_dtr(struct tegra_uart_port *t, bool active) { unsigned char mcr; mcr = t->mcr_shadow; if (active) mcr |= UART_MCR_DTR; else mcr &= ~UART_MCR_DTR; if (mcr != t->mcr_shadow) { uart_writeb(t, mcr, UART_MCR); t->mcr_shadow = mcr; } return; }
static void tegra_start_dma_tx(struct tegra_uart_port *t, unsigned long bytes) { struct circ_buf *xmit; xmit = &t->uport.state->xmit; dma_sync_single_for_device(t->uport.dev, t->xmit_dma_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); t->fcr_shadow &= ~UART_FCR_T_TRIG_11; t->fcr_shadow |= TEGRA_UART_TX_TRIG_4B; uart_writeb(t, t->fcr_shadow, UART_FCR); t->tx_bytes = bytes & ~(sizeof(u32)-1); t->tx_dma_req.source_addr = t->xmit_dma_addr + xmit->tail; t->tx_dma_req.size = t->tx_bytes; t->tx_in_progress = TEGRA_TX_DMA; tegra_dma_enqueue_req(t->tx_dma, &t->tx_dma_req); }
static void fill_tx_fifo(struct tegra_uart_port *t, int max_bytes) { int i; struct circ_buf *xmit = &t->uport.state->xmit; #ifndef CONFIG_ARCH_TEGRA_2x_SOC unsigned long lsr; #endif for (i = 0; i < max_bytes; i++) { BUG_ON(uart_circ_empty(xmit)); #ifndef CONFIG_ARCH_TEGRA_2x_SOC lsr = uart_readl(t, UART_LSR); if ((lsr & UART_LSR_TXFIFO_FULL)) break; #endif uart_writeb(t, xmit->buf[xmit->tail], UART_TX); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); t->uport.icount.tx++; } }
static void tegra_uart_hw_deinit(struct tegra_uart_port *t) { unsigned long flags; /* Disable interrupts */ uart_writeb(t, 0, UART_IER); while ((uart_readb(t, UART_LSR) & UART_LSR_TEMT) != UART_LSR_TEMT); udelay(200); spin_lock_irqsave(&t->uport.lock, flags); /* Reset the Rx and Tx FIFOs */ tegra_fifo_reset(t, UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); clk_disable(t->clk); t->baud = 0; t->uart_state = TEGRA_UART_CLOSED; spin_unlock_irqrestore(&t->uport.lock, flags); }
static int tegra_uart_hw_init(struct tegra_uart_port *t) { unsigned char ier; unsigned char sir; dev_vdbg(t->uport.dev, "+tegra_uart_hw_init\n"); t->fcr_shadow = 0; t->mcr_shadow = 0; t->lcr_shadow = 0; t->ier_shadow = 0; t->baud = 0; pm_runtime_get_sync((&t->uport)->dev); clk_prepare_enable(t->clk); /* Reset the UART controller to clear all previous status.*/ tegra_periph_reset_assert(t->clk); udelay(100); tegra_periph_reset_deassert(t->clk); udelay(100); t->rx_in_progress = 0; /* * Set the trigger level * * For PIO mode: * * For receive, this will interrupt the CPU after that many number of * bytes are received, for the remaining bytes the receive timeout * interrupt is received. * * Rx high watermark is set to 4. * * For transmit, if the trasnmit interrupt is enabled, this will * interrupt the CPU when the number of entries in the FIFO reaches the * low watermark. * * Tx low watermark is set to 8. * * For DMA mode: * * Set the Tx trigger to 4. This should match the DMA burst size that * programmed in the DMA registers. */ t->fcr_shadow = UART_FCR_ENABLE_FIFO; t->fcr_shadow |= UART_FCR_R_TRIG_01; t->fcr_shadow |= TEGRA_UART_TX_TRIG_8B; uart_writeb(t, t->fcr_shadow, UART_FCR); if (t->use_rx_dma) { /* * Initialize the UART for a simple default configuration * so that the receive DMA buffer may be enqueued */ t->lcr_shadow = 3; /* no parity, stop, 8 data bits */ tegra_set_baudrate(t, 115200); t->fcr_shadow |= UART_FCR_DMA_SELECT; uart_writeb(t, t->fcr_shadow, UART_FCR); if (tegra_start_dma_rx(t)) { dev_err(t->uport.dev, "Rx DMA enqueue failed\n"); tegra_uart_free_rx_dma(t); t->fcr_shadow &= ~UART_FCR_DMA_SELECT; uart_writeb(t, t->fcr_shadow, UART_FCR); } } else { uart_writeb(t, t->fcr_shadow, UART_FCR); } t->rx_in_progress = 1; /* * Enable IE_RXS for the receive status interrupts like line errros. * Enable IE_RX_TIMEOUT to get the bytes which cannot be DMA'd. * * If using DMA mode, enable EORD instead of receive interrupt which * will interrupt after the UART is done with the receive instead of * the interrupt when the FIFO "threshold" is reached. * * EORD is different interrupt than RX_TIMEOUT - RX_TIMEOUT occurs when * the DATA is sitting in the FIFO and couldn't be transferred to the * DMA as the DMA size alignment(4 bytes) is not met. EORD will be * triggered when there is a pause of the incomming data stream for 4 * characters long. * * For pauses in the data which is not aligned to 4 bytes, we get * both the EORD as well as RX_TIMEOUT - SW sees RX_TIMEOUT first * then the EORD. * * Don't get confused, believe in the magic of nvidia hw...:-) */ 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, ier, UART_IER); /* * Tegra UART controller also support SIR PHY * Enabled IRDA will transmit each zero bit as a short IR pulse. */ if (t->is_irda) { dev_vdbg(t->uport.dev, "SIR enabled\n"); sir = TEGRA_UART_SIR_ENABLED; uart_writeb(t, sir, TEGRA_UART_IRDA_CSR); } t->uart_state = TEGRA_UART_OPENED; dev_vdbg(t->uport.dev, "-tegra_uart_hw_init\n"); return 0; }
static irqreturn_t tegra_uart_isr(int irq, void *data) { struct tegra_uart_port *t = data; struct uart_port *u = &t->uport; unsigned char iir; unsigned char ier; bool is_rx_int = false; unsigned long flags; spin_lock_irqsave(&u->lock, flags); t = container_of(u, struct tegra_uart_port, uport); while (1) { iir = uart_readb(t, UART_IIR); if (iir & UART_IIR_NO_INT) { if (likely(t->use_rx_dma) && is_rx_int) { do_handle_rx_dma(t); if (t->rx_in_progress) { ier = t->ier_shadow; ier |= (UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD); t->ier_shadow = ier; uart_writeb(t, ier, UART_IER); } } spin_unlock_irqrestore(&u->lock, flags); return IRQ_HANDLED; } dev_dbg(u->dev, "tegra_uart_isr iir = 0x%x (%d)\n", iir, (iir >> 1) & 0x7); switch ((iir >> 1) & 0x7) { case 0: /* Modem signal change interrupt */ do_handle_modem_signal(u); break; case 1: /* Transmit interrupt only triggered when using PIO */ t->ier_shadow &= ~UART_IER_THRI; uart_writeb(t, t->ier_shadow, UART_IER); do_handle_tx_pio(t); break; case 4: /* End of data */ case 6: /* Rx timeout */ case 2: /* Receive */ if (likely(t->use_rx_dma)) { if (!is_rx_int) { is_rx_int = true; /* Disable interrups */ ier = t->ier_shadow; ier |= UART_IER_RDI; uart_writeb(t, ier, UART_IER); ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD); t->ier_shadow = ier; uart_writeb(t, ier, UART_IER); } } else { do_handle_rx_pio(t); spin_unlock_irqrestore(&u->lock, flags); tty_flip_buffer_push(u->state->port.tty); spin_lock_irqsave(&u->lock, flags); } break; case 3: /* Receive error */ /* FIXME how to handle this? Why do we get here */ do_decode_rx_error(t, uart_readb(t, UART_LSR)); break; case 5: /* break nothing to handle */ case 7: /* break nothing to handle */ break; } } }
static void tegra_set_termios(struct uart_port *u, struct ktermios *termios, struct ktermios *oldtermios) { struct tegra_uart_port *t; unsigned int baud; unsigned long flags; unsigned int lcr; unsigned int c_cflag = termios->c_cflag; unsigned char mcr; t = container_of(u, struct tegra_uart_port, uport); dev_vdbg(t->uport.dev, "+tegra_set_termios\n"); spin_lock_irqsave(&u->lock, flags); /* Changing configuration, it is safe to stop any rx now */ if (t->rts_active) set_rts(t, false); /* Clear all interrupts as configuration is going to be change */ uart_writeb(t, t->ier_shadow | UART_IER_RDI, UART_IER); uart_readb(t, UART_IER); uart_writeb(t, 0, UART_IER); uart_readb(t, UART_IER); /* Parity */ lcr = t->lcr_shadow; lcr &= ~UART_LCR_PARITY; if (PARENB == (c_cflag & PARENB)) { if (CMSPAR == (c_cflag & CMSPAR)) { /* FIXME What is space parity? */ /* data |= SPACE_PARITY; */ } else if (c_cflag & PARODD) { lcr |= UART_LCR_PARITY; lcr &= ~UART_LCR_EPAR; lcr &= ~UART_LCR_SPAR; } else { lcr |= UART_LCR_PARITY; lcr |= UART_LCR_EPAR; lcr &= ~UART_LCR_SPAR; } } lcr &= ~UART_LCR_WLEN8; switch (c_cflag & CSIZE) { case CS5: lcr |= UART_LCR_WLEN5; break; case CS6: lcr |= UART_LCR_WLEN6; break; case CS7: lcr |= UART_LCR_WLEN7; break; default: lcr |= UART_LCR_WLEN8; break; } /* Stop bits */ if (termios->c_cflag & CSTOPB) lcr |= UART_LCR_STOP; else lcr &= ~UART_LCR_STOP; uart_writeb(t, lcr, UART_LCR); t->lcr_shadow = lcr; /* Baud rate. */ baud = uart_get_baud_rate(u, termios, oldtermios, 200, 4000000); spin_unlock_irqrestore(&u->lock, flags); tegra_set_baudrate(t, baud); spin_lock_irqsave(&u->lock, flags); /* Flow control */ if (termios->c_cflag & CRTSCTS) { mcr = t->mcr_shadow; mcr |= UART_MCR_CTS_EN; mcr &= ~UART_MCR_RTS_EN; t->mcr_shadow = mcr; uart_writeb(t, mcr, UART_MCR); t->use_cts_control = true; /* if top layer has asked to set rts active then do so here */ if (t->rts_active) set_rts(t, true); } else { mcr = t->mcr_shadow; mcr &= ~UART_MCR_CTS_EN; mcr &= ~UART_MCR_RTS_EN; t->mcr_shadow = mcr; uart_writeb(t, mcr, UART_MCR); t->use_cts_control = false; } /* update the port timeout based on new settings */ uart_update_timeout(u, termios->c_cflag, baud); /* Make sure all write has completed */ uart_readb(t, UART_IER); /* Reenable interrupt */ uart_writeb(t, t->ier_shadow, UART_IER); uart_readb(t, UART_IER); spin_unlock_irqrestore(&u->lock, flags); dev_vdbg(t->uport.dev, "-tegra_set_termios\n"); return; }