static void omap8250_restore_regs(struct uart_8250_port *up) { struct omap8250_priv *priv = up->port.private_data; struct uart_8250_dma *dma = up->dma; if (dma && dma->tx_running) { /* * TCSANOW requests the change to occur immediately however if * we have a TX-DMA operation in progress then it has been * observed that it might stall and never complete. Therefore we * delay DMA completes to prevent this hang from happen. */ priv->delayed_restore = 1; return; } serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, UART_MCR_TCRTLR); serial_out(up, UART_FCR, up->fcr); omap8250_update_scr(up, priv); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) | OMAP_UART_TCR_HALT(52)); serial_out(up, UART_TI752_TLR, TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX | TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX); serial_out(up, UART_LCR, 0); /* drop TCR + TLR access, we setup XON/XOFF later */ serial_out(up, UART_MCR, up->mcr); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_dl_write(up, priv->quot); serial_out(up, UART_EFR, priv->efr); /* Configure flow control */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_XON1, priv->xon); serial_out(up, UART_XOFF1, priv->xoff); serial_out(up, UART_LCR, up->lcr); /* need mode A for FCR */ if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS) omap_8250_mdr1_errataset(up, priv); else serial_out(up, UART_OMAP_MDR1, priv->mdr1); up->port.ops->set_mctrl(&up->port, up->port.mctrl); }
static void mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; unsigned int baud, quot; #ifdef CONFIG_SERIAL_8250_DMA if (up->dma) { if (uart_console(port)) { devm_kfree(up->port.dev, up->dma); up->dma = NULL; } else { mtk8250_dma_enable(up); } } #endif serial8250_do_set_termios(port, termios, old); /* * Mediatek UARTs use an extra highspeed register (UART_MTK_HIGHS) * * We need to recalcualte the quot register, as the claculation depends * on the vaule in the highspeed register. * * Some baudrates are not supported by the chip, so we use the next * lower rate supported and update termios c_flag. * * If highspeed register is set to 3, we need to specify sample count * and sample point to increase accuracy. If not, we reset the * registers to their default values. */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / UART_DIV_MAX, port->uartclk); if (baud <= 115200) { serial_port_out(port, UART_MTK_HIGHS, 0x0); quot = uart_get_divisor(port, baud); } else if (baud <= 576000) { serial_port_out(port, UART_MTK_HIGHS, 0x2); /* Set to next lower baudrate supported */ if ((baud == 500000) || (baud == 576000)) baud = 460800; quot = DIV_ROUND_UP(port->uartclk, 4 * baud); } else { serial_port_out(port, UART_MTK_HIGHS, 0x3); quot = DIV_ROUND_UP(port->uartclk, 256 * baud); } /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ spin_lock_irqsave(&port->lock, flags); /* set DLAB we have cval saved in up->lcr from the call to the core */ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); serial_dl_write(up, quot); /* reset DLAB */ serial_port_out(port, UART_LCR, up->lcr); if (baud > 460800) { unsigned int tmp; tmp = DIV_ROUND_CLOSEST(port->uartclk, quot * baud); serial_port_out(port, UART_MTK_SAMPLE_COUNT, tmp - 1); serial_port_out(port, UART_MTK_SAMPLE_POINT, (tmp - 2) >> 1); } else {