static void keyspan_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { int baud_rate, device_port; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; unsigned int cflag; p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; cflag = tty->termios->c_cflag; device_port = port->number - port->serial->minor; /* Baud rate calculation takes baud rate as an integer so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(tty); /* If no match or invalid, don't change */ if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { /* FIXME - more to do here to ensure rate changes cleanly */ /* FIXME - calcuate exact rate from divisor ? */ p_priv->baud = baud_rate; } else baud_rate = tty_termios_baud_rate(old_termios); tty_encode_baud_rate(tty, baud_rate, baud_rate); /* set CTS/RTS handshake etc. */ p_priv->cflag = cflag; p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; /* Mark/Space not supported */ tty->termios->c_cflag &= ~CMSPAR; keyspan_send_setup(port, 0); }
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { unsigned int baud = tty_termios_baud_rate(termios); struct dw8250_data *d = p->private_data; unsigned int rate; int ret; if (IS_ERR(d->clk) || !old) goto out; /* Not requesting clock rates below 1.8432Mhz */ if (baud < 115200) baud = 115200; clk_disable_unprepare(d->clk); rate = clk_round_rate(d->clk, baud * 16); ret = clk_set_rate(d->clk, rate); clk_prepare_enable(d->clk); if (!ret) p->uartclk = rate; p->status &= ~UPSTAT_AUTOCTS; if (termios->c_cflag & CRTSCTS) p->status |= UPSTAT_AUTOCTS; out: serial8250_do_set_termios(p, termios, old); }
static void tty_reset_termios(struct tty_struct *tty) { mutex_lock(&tty->termios_mutex); *tty->termios = tty->driver->init_termios; tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); mutex_unlock(&tty->termios_mutex); }
static void tty_reset_termios(struct tty_struct *tty) { down_write(&tty->termios_rwsem); tty->termios = tty->driver->init_termios; tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); up_write(&tty->termios_rwsem); }
static void milkymist_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud; unsigned int quot; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); iowrite32be(quot, port->membase + UART_DIV); spin_unlock_irqrestore(&port->lock, flags); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); }
static void am_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud; struct am_uart_port * info = &am_ports[port->line]; #ifdef PRINT_DEBUG if(info->line == DEBUG_PORT_ID) printk("%s\n", __FUNCTION__); #endif baud = tty_termios_baud_rate(termios); change_speed(info, baud); uart_update_timeout(port, termios->c_cflag, baud); return; }
static void vt8500_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct vt8500_port *vt8500_port = container_of(port, struct vt8500_port, uart); unsigned long flags; unsigned int baud, lcr; unsigned int loops = 1000; spin_lock_irqsave(&port->lock, flags); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 900, 921600); baud = vt8500_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* calculate parity */ lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR); lcr &= ~((1 << 5) | (1 << 4)); if (termios->c_cflag & PARENB) { lcr |= (1 << 4); termios->c_cflag &= ~CMSPAR; if (termios->c_cflag & PARODD) lcr |= (1 << 5); } /* calculate bits per char */ lcr &= ~(1 << 2); switch (termios->c_cflag & CSIZE) { case CS7: break; case CS8: default: lcr |= (1 << 2); termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* calculate stop bits */ lcr &= ~(1 << 3); if (termios->c_cflag & CSTOPB) lcr |= (1 << 3); /* set parity, bits per char, and stop bit */ vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & IGNPAR) port->read_status_mask = FER | PER; uart_update_timeout(port, termios->c_cflag, baud); /* Reset FIFOs */ vt8500_write(&vt8500_port->uart, 0x88c, VT8500_URFCR); while ((vt8500_read(&vt8500_port->uart, VT8500_URFCR) & 0xc) && --loops) cpu_relax(); /* Every possible FIFO-related interrupt */ vt8500_port->ier = RX_FIFO_INTS | TX_FIFO_INTS; /* * CTS flow control */ if (UART_ENABLE_MS(&vt8500_port->uart, termios->c_cflag)) vt8500_port->ier |= TCTS; vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR); vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER); spin_unlock_irqrestore(&port->lock, flags); }
static void tegra_uart_set_termios(struct uart_port *u, struct ktermios *termios, struct ktermios *oldtermios) { struct tegra_uart_port *tup = to_tegra_uport(u); unsigned int baud; unsigned long flags; unsigned int lcr; int symb_bit = 1; struct clk *parent_clk = clk_get_parent(tup->uart_clk); unsigned long parent_clk_rate = clk_get_rate(parent_clk); int max_divider = (tup->cdata->support_clk_src_div) ? 0x7FFF : 0xFFFF; max_divider *= 16; spin_lock_irqsave(&u->lock, flags); /* Changing configuration, it is safe to stop any rx now */ if (tup->rts_active) set_rts(tup, false); /* Clear all interrupts as configuration is going to be change */ tegra_uart_write(tup, tup->ier_shadow | UART_IER_RDI, UART_IER); tegra_uart_read(tup, UART_IER); tegra_uart_write(tup, 0, UART_IER); tegra_uart_read(tup, UART_IER); /* Parity */ lcr = tup->lcr_shadow; lcr &= ~UART_LCR_PARITY; /* CMSPAR isn't supported by this driver */ termios->c_cflag &= ~CMSPAR; if ((termios->c_cflag & PARENB) == PARENB) { symb_bit++; if (termios->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 (termios->c_cflag & CSIZE) { case CS5: lcr |= UART_LCR_WLEN5; symb_bit += 5; break; case CS6: lcr |= UART_LCR_WLEN6; symb_bit += 6; break; case CS7: lcr |= UART_LCR_WLEN7; symb_bit += 7; break; default: lcr |= UART_LCR_WLEN8; symb_bit += 8; break; } /* Stop bits */ if (termios->c_cflag & CSTOPB) { lcr |= UART_LCR_STOP; symb_bit += 2; } else { lcr &= ~UART_LCR_STOP; symb_bit++; } tegra_uart_write(tup, lcr, UART_LCR); tup->lcr_shadow = lcr; tup->symb_bit = symb_bit; /* Baud rate. */ baud = uart_get_baud_rate(u, termios, oldtermios, parent_clk_rate/max_divider, parent_clk_rate/16); spin_unlock_irqrestore(&u->lock, flags); tegra_set_baudrate(tup, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&u->lock, flags); /* Flow control */ if (termios->c_cflag & CRTSCTS) { tup->mcr_shadow |= TEGRA_UART_MCR_CTS_EN; tup->mcr_shadow &= ~TEGRA_UART_MCR_RTS_EN; tegra_uart_write(tup, tup->mcr_shadow, UART_MCR); /* if top layer has asked to set rts active then do so here */ if (tup->rts_active) set_rts(tup, true); } else { tup->mcr_shadow &= ~TEGRA_UART_MCR_CTS_EN; tup->mcr_shadow &= ~TEGRA_UART_MCR_RTS_EN; tegra_uart_write(tup, tup->mcr_shadow, UART_MCR); } /* update the port timeout based on new settings */ uart_update_timeout(u, termios->c_cflag, baud); /* Make sure all write has completed */ tegra_uart_read(tup, UART_IER); /* Reenable interrupt */ tegra_uart_write(tup, tup->ier_shadow, UART_IER); tegra_uart_read(tup, UART_IER); spin_unlock_irqrestore(&u->lock, flags); }
/** * cdns_uart_set_termios - termios operations, handling data length, parity, * stop bits, flow control, baud rate * @port: Handle to the uart port structure * @termios: Handle to the input termios structure * @old: Values of the previously saved termios structure */ static void cdns_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cval = 0; unsigned int baud, minbaud, maxbaud; unsigned long flags; unsigned int ctrl_reg, mode_reg; spin_lock_irqsave(&port->lock, flags); /* Empty the receive FIFO 1st before making changes */ while ((cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY) != CDNS_UART_SR_RXEMPTY) { cdns_uart_readl(CDNS_UART_FIFO_OFFSET); } /* Disable the TX and RX to set baud rate */ ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET); ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET); /* * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk * min and max baud should be calculated here based on port->uartclk. * this way we get a valid baud and can safely call set_baud() */ minbaud = port->uartclk / ((CDNS_UART_BDIV_MAX + 1) * CDNS_UART_CD_MAX * 8); maxbaud = port->uartclk / (CDNS_UART_BDIV_MIN + 1); baud = uart_get_baud_rate(port, termios, old, minbaud, maxbaud); baud = cdns_uart_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* Set TX/RX Reset */ ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET); /* * Clear the RX disable and TX disable bits and then set the TX enable * bit and RX enable bit to enable the transmitter and receiver. */ ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET); cdns_uart_writel(rx_timeout, CDNS_UART_RXTOUT_OFFSET); port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; port->ignore_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN; /* ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT | CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN; mode_reg = cdns_uart_readl(CDNS_UART_MR_OFFSET); /* Handling Data Size */ switch (termios->c_cflag & CSIZE) { case CS6: cval |= CDNS_UART_MR_CHARLEN_6_BIT; break; case CS7: cval |= CDNS_UART_MR_CHARLEN_7_BIT; break; default: case CS8: cval |= CDNS_UART_MR_CHARLEN_8_BIT; termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* Handling Parity and Stop Bits length */ if (termios->c_cflag & CSTOPB) cval |= CDNS_UART_MR_STOPMODE_2_BIT; /* 2 STOP bits */ else cval |= CDNS_UART_MR_STOPMODE_1_BIT; /* 1 STOP bit */ if (termios->c_cflag & PARENB) { /* Mark or Space parity */ if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) cval |= CDNS_UART_MR_PARITY_MARK; else cval |= CDNS_UART_MR_PARITY_SPACE; } else { if (termios->c_cflag & PARODD) cval |= CDNS_UART_MR_PARITY_ODD; else cval |= CDNS_UART_MR_PARITY_EVEN; } } else { cval |= CDNS_UART_MR_PARITY_NONE; } cval |= mode_reg & 1; cdns_uart_writel(cval, CDNS_UART_MR_OFFSET); spin_unlock_irqrestore(&port->lock, flags); }
static void msm_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, mr; spin_lock_irqsave(&port->lock, flags); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 300, 115200); baud = msm_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* calculate parity */ mr = msm_read(port, UART_MR2); mr &= ~UART_MR2_PARITY_MODE; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) mr |= UART_MR2_PARITY_MODE_ODD; else if (termios->c_cflag & CMSPAR) mr |= UART_MR2_PARITY_MODE_SPACE; else mr |= UART_MR2_PARITY_MODE_EVEN; } /* calculate bits per char */ mr &= ~UART_MR2_BITS_PER_CHAR; switch (termios->c_cflag & CSIZE) { case CS5: mr |= UART_MR2_BITS_PER_CHAR_5; break; case CS6: mr |= UART_MR2_BITS_PER_CHAR_6; break; case CS7: mr |= UART_MR2_BITS_PER_CHAR_7; break; case CS8: default: mr |= UART_MR2_BITS_PER_CHAR_8; break; } /* calculate stop bits */ mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO); if (termios->c_cflag & CSTOPB) mr |= UART_MR2_STOP_BIT_LEN_TWO; else mr |= UART_MR2_STOP_BIT_LEN_ONE; /* set parity, bits per char, and stop bit */ msm_write(port, mr, UART_MR2); /* calculate and set hardware flow control */ mr = msm_read(port, UART_MR1); mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL); if (termios->c_cflag & CRTSCTS) { mr |= UART_MR1_CTS_CTL; mr |= UART_MR1_RX_RDY_CTL; } msm_write(port, mr, UART_MR1); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= UART_SR_PAR_FRAME_ERR; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= UART_SR_RX_BREAK; uart_update_timeout(port, termios->c_cflag, baud); spin_unlock_irqrestore(&port->lock, flags); }
static void sirfsoc_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); unsigned long config_reg = 0; unsigned long baud_rate; unsigned long setted_baud; unsigned long flags; unsigned long ic; unsigned int clk_div_reg = 0; unsigned long temp_reg_val; unsigned long rx_time_out; int threshold_div; int temp; switch (termios->c_cflag & CSIZE) { default: case CS8: config_reg |= SIRFUART_DATA_BIT_LEN_8; break; case CS7: config_reg |= SIRFUART_DATA_BIT_LEN_7; break; case CS6: config_reg |= SIRFUART_DATA_BIT_LEN_6; break; case CS5: config_reg |= SIRFUART_DATA_BIT_LEN_5; break; } if (termios->c_cflag & CSTOPB) config_reg |= SIRFUART_STOP_BIT_LEN_2; baud_rate = uart_get_baud_rate(port, termios, old, 0, 4000000); spin_lock_irqsave(&port->lock, flags); port->read_status_mask = SIRFUART_RX_OFLOW_INT; port->ignore_status_mask = 0; /* read flags */ if (termios->c_iflag & INPCK) port->read_status_mask |= SIRFUART_FRM_ERR_INT | SIRFUART_PARITY_ERR_INT; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= SIRFUART_RXD_BREAK_INT; /* ignore flags */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SIRFUART_FRM_ERR_INT | SIRFUART_PARITY_ERR_INT; if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= SIRFUART_DUMMY_READ; /* enable parity if PARENB is set*/ if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) config_reg |= SIRFUART_STICK_BIT_MARK; else config_reg |= SIRFUART_STICK_BIT_SPACE; } else if (termios->c_cflag & PARODD) { config_reg |= SIRFUART_STICK_BIT_ODD; } else { config_reg |= SIRFUART_STICK_BIT_EVEN; } } /* Hardware Flow Control Settings */ if (UART_ENABLE_MS(port, termios->c_cflag)) { if (!sirfport->ms_enabled) sirfsoc_uart_enable_ms(port); } else { if (sirfport->ms_enabled) sirfsoc_uart_disable_ms(port); } if (port->uartclk == 150000000) { /* common rate: fast calculation */ for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) if (baud_rate == baudrate_to_regv[ic].baud_rate) clk_div_reg = baudrate_to_regv[ic].reg_val; } setted_baud = baud_rate; /* arbitary rate setting */ if (unlikely(clk_div_reg == 0)) clk_div_reg = sirfsoc_calc_sample_div(baud_rate, port->uartclk, &setted_baud); wr_regl(port, SIRFUART_DIVISOR, clk_div_reg); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, setted_baud, setted_baud); /* set receive timeout */ rx_time_out = SIRFSOC_UART_RX_TIMEOUT(baud_rate, 20000); rx_time_out = (rx_time_out > 0xFFFF) ? 0xFFFF : rx_time_out; config_reg |= SIRFUART_RECV_TIMEOUT(rx_time_out); temp_reg_val = rd_regl(port, SIRFUART_TX_FIFO_OP); wr_regl(port, SIRFUART_RX_FIFO_OP, 0); wr_regl(port, SIRFUART_TX_FIFO_OP, temp_reg_val & ~SIRFUART_TX_FIFO_START); wr_regl(port, SIRFUART_TX_DMA_IO_CTRL, SIRFUART_TX_MODE_IO); wr_regl(port, SIRFUART_RX_DMA_IO_CTRL, SIRFUART_RX_MODE_IO); wr_regl(port, SIRFUART_LINE_CTRL, config_reg); /* Reset Rx/Tx FIFO Threshold level for proper baudrate */ if (baud_rate < 1000000) threshold_div = 1; else threshold_div = 2; temp = port->line == 1 ? 16 : 64; wr_regl(port, SIRFUART_TX_FIFO_CTRL, temp / threshold_div); wr_regl(port, SIRFUART_RX_FIFO_CTRL, temp / threshold_div); temp_reg_val |= SIRFUART_TX_FIFO_START; wr_regl(port, SIRFUART_TX_FIFO_OP, temp_reg_val); uart_update_timeout(port, termios->c_cflag, baud_rate); sirfsoc_uart_start_rx(port); wr_regl(port, SIRFUART_TX_RX_EN, SIRFUART_TX_EN | SIRFUART_RX_EN); spin_unlock_irqrestore(&port->lock, flags); }
static void cp2101_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; unsigned int baud = 0, bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); if (!tty) return; tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; baud = tty_get_baud_rate(tty); /* If the baud rate is to be updated*/ if (baud != tty_termios_baud_rate(old_termios)) { switch (baud) { case 0: case 600: case 1200: case 1800: case 2400: case 4800: case 7200: case 9600: case 14400: case 19200: case 28800: case 38400: case 55854: case 57600: case 115200: case 127117: case 230400: case 460800: case 921600: case 3686400: break; default: baud = 9600; break; } if (baud) { dbg("%s - Setting baud rate to %d baud", __func__, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, (BAUD_RATE_GEN_FREQ / baud))) { dev_err(&port->dev, "Baud rate requested not " "supported by device\n"); baud = tty_termios_baud_rate(old_termios); } } } /* Report back the resulting baud rate */ tty_encode_baud_rate(tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_DATA_MASK; switch (cflag & CSIZE) { case CS5: bits |= BITS_DATA_5; dbg("%s - data bits = 5", __func__); break; case CS6: bits |= BITS_DATA_6; dbg("%s - data bits = 6", __func__); break; case CS7: bits |= BITS_DATA_7; dbg("%s - data bits = 7", __func__); break; case CS8: bits |= BITS_DATA_8; dbg("%s - data bits = 8", __func__); break; /*case CS9: bits |= BITS_DATA_9; dbg("%s - data bits = 9", __func__); break;*/ default: dev_err(&port->dev, "cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) dev_err(&port->dev, "Number of data bits requested " "not supported by device\n"); } if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_PARITY_MASK; if (cflag & PARENB) { if (cflag & PARODD) { bits |= BITS_PARITY_ODD; dbg("%s - parity = ODD", __func__); } else { bits |= BITS_PARITY_EVEN; dbg("%s - parity = EVEN", __func__); } } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) dev_err(&port->dev, "Parity mode not supported " "by device\n"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { cp2101_get_config(port, CP2101_BITS, &bits, 2); bits &= ~BITS_STOP_MASK; if (cflag & CSTOPB) { bits |= BITS_STOP_2; dbg("%s - stop bits = 2", __func__); } else { bits |= BITS_STOP_1; dbg("%s - stop bits = 1", __func__); } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) dev_err(&port->dev, "Number of stop bits requested " "not supported by device\n"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); if (cflag & CRTSCTS) { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x09; modem_ctl[1] = 0x80; dbg("%s - flow control = CRTSCTS", __func__); } else { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x01; modem_ctl[1] |= 0x40; dbg("%s - flow control = NONE", __func__); } dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); } }
static void am_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud; struct meson_uart_port * mup = &am_ports[port->line]; am_uart_t *uart = mup->uart; unsigned tmp; tmp = readl(&uart->mode); switch (termios->c_cflag & CSIZE) { case CS8: printk(KERN_DEBUG "config %s: Character length 8bits/char\n", mup->name); tmp &= ~(0x3 << 20); break; case CS7: printk(KERN_DEBUG "config %s: Character length 7bits/char\n", mup->name); tmp &= ~(0x1 << 21); tmp |= (0x1 << 20); break; case CS6: printk(KERN_DEBUG "config %s: Character length 6bits/char\n", mup->name); tmp |= 0x1 << 21; tmp &= ~(0x1 << 20); break; case CS5: printk(KERN_DEBUG "config %s: Character length 5bits/char\n", mup->name); tmp |= 0x3 << 20; break; default: printk(KERN_DEBUG "default config %s: Character length 8bits/char\n", mup->name); tmp &= ~(0x3 << 20); break; } if(PARENB & termios->c_cflag) { tmp |= 0x1 << 19; if(PARODD & termios->c_cflag) { tmp |= 0x1<<18; } else { tmp &=~(0x1 << 18); } } else { tmp &=~(0x1 << 19); } if(termios->c_cflag & CSTOPB) { tmp |= 0x1 << 16 ; tmp &=~(0x1 << 17); } else { tmp &=~(0x3 << 16); } if(termios->c_cflag & CRTSCTS) { tmp &= ~(0x1 << 15); } else { tmp |= (0x1 << 15); } writel(tmp, &uart->mode); baud = tty_termios_baud_rate(termios); if(baud){ meson_uart_change_speed(mup, baud); uart_update_timeout(port, termios->c_cflag, baud); } return; }
/** * xuartps_set_termios - termios operations, handling data length, parity, * stop bits, flow control, baud rate * @port: Handle to the uart port structure * @termios: Handle to the input termios structure * @old: Values of the previously saved termios structure * **/ static void xuartps_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cval = 0; unsigned int baud; unsigned long flags; unsigned int ctrl_reg, mode_reg; spin_lock_irqsave(&port->lock, flags); /* Empty the receive FIFO 1st before making changes */ while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { xuartps_readl(XUARTPS_FIFO_OFFSET); } /* Disable the TX and RX to set baud rate */ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), XUARTPS_CR_OFFSET); /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ baud = uart_get_baud_rate(port, termios, old, 0, 10000000); baud = xuartps_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* Set TX/RX Reset */ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), XUARTPS_CR_OFFSET); ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); /* Clear the RX disable and TX disable bits and then set the TX enable * bit and RX enable bit to enable the transmitter and receiver. */ xuartps_writel( (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), XUARTPS_CR_OFFSET); xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; port->ignore_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; /* ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; mode_reg = xuartps_readl(XUARTPS_MR_OFFSET); /* Handling Data Size */ switch (termios->c_cflag & CSIZE) { case CS6: cval |= XUARTPS_MR_CHARLEN_6_BIT; break; case CS7: cval |= XUARTPS_MR_CHARLEN_7_BIT; break; default: case CS8: cval |= XUARTPS_MR_CHARLEN_8_BIT; termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* Handling Parity and Stop Bits length */ if (termios->c_cflag & CSTOPB) cval |= XUARTPS_MR_STOPMODE_2_BIT; /* 2 STOP bits */ else cval |= XUARTPS_MR_STOPMODE_1_BIT; /* 1 STOP bit */ if (termios->c_cflag & PARENB) { /* Mark or Space parity */ if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) cval |= XUARTPS_MR_PARITY_MARK; else cval |= XUARTPS_MR_PARITY_SPACE; } else if (termios->c_cflag & PARODD) cval |= XUARTPS_MR_PARITY_ODD; else cval |= XUARTPS_MR_PARITY_EVEN; } else cval |= XUARTPS_MR_PARITY_NONE; xuartps_writel(cval , XUARTPS_MR_OFFSET); spin_unlock_irqrestore(&port->lock, flags); }
static void sprd_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud, quot; unsigned int lcr = 0, fc; unsigned long flags; /* ask the core to calculate the divisor for us */ baud = uart_get_baud_rate(port, termios, old, 0, SPRD_BAUD_IO_LIMIT); quot = (unsigned int)((port->uartclk + baud / 2) / baud); /* set data length */ switch (termios->c_cflag & CSIZE) { case CS5: lcr |= SPRD_LCR_DATA_LEN5; break; case CS6: lcr |= SPRD_LCR_DATA_LEN6; break; case CS7: lcr |= SPRD_LCR_DATA_LEN7; break; case CS8: default: lcr |= SPRD_LCR_DATA_LEN8; break; } /* calculate stop bits */ lcr &= ~(SPRD_LCR_STOP_1BIT | SPRD_LCR_STOP_2BIT); if (termios->c_cflag & CSTOPB) lcr |= SPRD_LCR_STOP_2BIT; else lcr |= SPRD_LCR_STOP_1BIT; /* calculate parity */ lcr &= ~SPRD_LCR_PARITY; termios->c_cflag &= ~CMSPAR; /* no support mark/space */ if (termios->c_cflag & PARENB) { lcr |= SPRD_LCR_PARITY_EN; if (termios->c_cflag & PARODD) lcr |= SPRD_LCR_ODD_PAR; else lcr |= SPRD_LCR_EVEN_PAR; } spin_lock_irqsave(&port->lock, flags); /* update the per-port timeout */ uart_update_timeout(port, termios->c_cflag, baud); port->read_status_mask = SPRD_LSR_OE; if (termios->c_iflag & INPCK) port->read_status_mask |= SPRD_LSR_FE | SPRD_LSR_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) port->read_status_mask |= SPRD_LSR_BI; /* characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SPRD_LSR_PE | SPRD_LSR_FE; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= SPRD_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SPRD_LSR_OE; } /* flow control */ fc = serial_in(port, SPRD_CTL1); fc &= ~(RX_HW_FLOW_CTL_THLD | RX_HW_FLOW_CTL_EN | TX_HW_FLOW_CTL_EN); if (termios->c_cflag & CRTSCTS) { fc |= RX_HW_FLOW_CTL_THLD; fc |= RX_HW_FLOW_CTL_EN; fc |= TX_HW_FLOW_CTL_EN; } /* clock divider bit0~bit15 */ serial_out(port, SPRD_CLKD0, quot & 0xffff); /* clock divider bit16~bit20 */ serial_out(port, SPRD_CLKD1, (quot & 0x1f0000) >> 16); serial_out(port, SPRD_LCR, lcr); fc |= RX_TOUT_THLD_DEF | RX_HFC_THLD_DEF; serial_out(port, SPRD_CTL1, fc); spin_unlock_irqrestore(&port->lock, flags); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); }
unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, struct ktermios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; int hung_up = 0; upf_t flags = port->flags & UPF_SPD_MASK; if (flags == UPF_SPD_HI) altbaud = 57600; else if (flags == UPF_SPD_VHI) altbaud = 115200; else if (flags == UPF_SPD_SHI) altbaud = 230400; else if (flags == UPF_SPD_WARP) altbaud = 460800; for (try = 0; try < 2; try++) { baud = tty_termios_baud_rate(termios); if (baud == 38400) baud = altbaud; if (baud == 0) { hung_up = 1; baud = 9600; } if (baud >= min && baud <= max) return baud; termios->c_cflag &= ~CBAUD; if (old) { baud = tty_termios_baud_rate(old); if (!hung_up) tty_termios_encode_baud_rate(termios, baud, baud); old = NULL; continue; } if (!hung_up) { if (baud <= min) tty_termios_encode_baud_rate(termios, min + 1, min + 1); else tty_termios_encode_baud_rate(termios, max - 1, max - 1); } } WARN_ON(1); return 0; } EXPORT_SYMBOL(uart_get_baud_rate); unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud) { unsigned int quot; if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) quot = port->custom_divisor; else quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); return quot; }
static void sirfsoc_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; unsigned long config_reg = 0; unsigned long baud_rate; unsigned long set_baud; unsigned long flags; unsigned long ic; unsigned int clk_div_reg = 0; unsigned long txfifo_op_reg, ioclk_rate; unsigned long rx_time_out; int threshold_div; u32 data_bit_len, stop_bit_len, len_val; unsigned long sample_div_reg = 0xf; ioclk_rate = port->uartclk; switch (termios->c_cflag & CSIZE) { default: case CS8: data_bit_len = 8; config_reg |= SIRFUART_DATA_BIT_LEN_8; break; case CS7: data_bit_len = 7; config_reg |= SIRFUART_DATA_BIT_LEN_7; break; case CS6: data_bit_len = 6; config_reg |= SIRFUART_DATA_BIT_LEN_6; break; case CS5: data_bit_len = 5; config_reg |= SIRFUART_DATA_BIT_LEN_5; break; } if (termios->c_cflag & CSTOPB) { config_reg |= SIRFUART_STOP_BIT_LEN_2; stop_bit_len = 2; } else stop_bit_len = 1; spin_lock_irqsave(&port->lock, flags); port->read_status_mask = uint_en->sirfsoc_rx_oflow_en; port->ignore_status_mask = 0; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (termios->c_iflag & INPCK) port->read_status_mask |= uint_en->sirfsoc_frm_err_en | uint_en->sirfsoc_parity_err_en; } else { if (termios->c_iflag & INPCK) port->read_status_mask |= uint_en->sirfsoc_frm_err_en; } if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) port->read_status_mask |= uint_en->sirfsoc_rxd_brk_en; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= uint_en->sirfsoc_frm_err_en | uint_en->sirfsoc_parity_err_en; if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) config_reg |= SIRFUART_STICK_BIT_MARK; else config_reg |= SIRFUART_STICK_BIT_SPACE; } else if (termios->c_cflag & PARODD) { config_reg |= SIRFUART_STICK_BIT_ODD; } else { config_reg |= SIRFUART_STICK_BIT_EVEN; } } } else { if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= uint_en->sirfsoc_frm_err_en; if (termios->c_cflag & PARENB) dev_warn(port->dev, "USP-UART not support parity err\n"); } if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= uint_en->sirfsoc_rxd_brk_en; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= uint_en->sirfsoc_rx_oflow_en; } if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= SIRFUART_DUMMY_READ; /* Hardware Flow Control Settings */ if (UART_ENABLE_MS(port, termios->c_cflag)) { if (!sirfport->ms_enabled) sirfsoc_uart_enable_ms(port); } else { if (sirfport->ms_enabled) sirfsoc_uart_disable_ms(port); } baud_rate = uart_get_baud_rate(port, termios, old, 0, 4000000); if (ioclk_rate == 150000000) { for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) if (baud_rate == baudrate_to_regv[ic].baud_rate) clk_div_reg = baudrate_to_regv[ic].reg_val; } set_baud = baud_rate; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (unlikely(clk_div_reg == 0)) clk_div_reg = sirfsoc_uart_calc_sample_div(baud_rate, ioclk_rate, &set_baud); wr_regl(port, ureg->sirfsoc_divisor, clk_div_reg); } else { clk_div_reg = sirfsoc_usp_calc_sample_div(baud_rate, ioclk_rate, &sample_div_reg); sample_div_reg--; set_baud = ((ioclk_rate / (clk_div_reg+1) - 1) / (sample_div_reg + 1)); /* setting usp mode 2 */ len_val = ((1 << SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET) | (1 << SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET)); len_val |= ((clk_div_reg & SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK) << SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET); wr_regl(port, ureg->sirfsoc_mode2, len_val); } if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, set_baud, set_baud); /* set receive timeout && data bits len */ rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000); rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out); txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op); wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_STOP); wr_regl(port, ureg->sirfsoc_tx_fifo_op, (txfifo_op_reg & ~SIRFUART_FIFO_START)); if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { config_reg |= SIRFUART_RECV_TIMEOUT(port, rx_time_out); wr_regl(port, ureg->sirfsoc_line_ctrl, config_reg); } else { /*tx frame ctrl*/ len_val = (data_bit_len - 1) << SIRFSOC_USP_TX_DATA_LEN_OFFSET; len_val |= (data_bit_len + 1 + stop_bit_len - 1) << SIRFSOC_USP_TX_FRAME_LEN_OFFSET; len_val |= ((data_bit_len - 1) << SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET); len_val |= (((clk_div_reg & 0xc00) >> 10) << SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET); wr_regl(port, ureg->sirfsoc_tx_frame_ctrl, len_val); /*rx frame ctrl*/ len_val = (data_bit_len - 1) << SIRFSOC_USP_RX_DATA_LEN_OFFSET; len_val |= (data_bit_len + 1 + stop_bit_len - 1) << SIRFSOC_USP_RX_FRAME_LEN_OFFSET; len_val |= (data_bit_len - 1) << SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET; len_val |= (((clk_div_reg & 0xf000) >> 12) << SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET); wr_regl(port, ureg->sirfsoc_rx_frame_ctrl, len_val); /*async param*/ wr_regl(port, ureg->sirfsoc_async_param_reg, (SIRFUART_RECV_TIMEOUT(port, rx_time_out)) | (sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) << SIRFSOC_USP_ASYNC_DIV2_OFFSET); } if (sirfport->tx_dma_chan) wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE); else wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE); if (sirfport->rx_dma_chan) wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE); else wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE); /* Reset Rx/Tx FIFO Threshold level for proper baudrate */ if (set_baud < 1000000) threshold_div = 1; else threshold_div = 2; wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port) / threshold_div); wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port) / threshold_div); txfifo_op_reg |= SIRFUART_FIFO_START; wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg); uart_update_timeout(port, termios->c_cflag, set_baud); sirfsoc_uart_start_rx(port); wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN); spin_unlock_irqrestore(&port->lock, flags); }
static void sw_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sw_uart_port *sw_uport = UART_TO_SPORT(port); unsigned long flags; unsigned int baud, quot, lcr = 0, dll, dlh; unsigned int lcr_fail = 0; SERIAL_DBG("set termios ...\n"); switch (termios->c_cflag & CSIZE) { case CS5: lcr |= SW_UART_LCR_WLEN5; break; case CS6: lcr |= SW_UART_LCR_WLEN6; break; case CS7: lcr |= SW_UART_LCR_WLEN7; break; case CS8: default: lcr |= SW_UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) lcr |= SW_UART_LCR_STOP; if (termios->c_cflag & PARENB) lcr |= SW_UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) lcr |= SW_UART_LCR_EPAR; /* set buadrate */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / 0xffff, port->uartclk / 16); sw_uart_check_baudset(port, baud); quot = uart_get_divisor(port, baud); dll = quot & 0xff; dlh = quot >> 8; SERIAL_DBG("set baudrate %d, quot %d\n", baud, quot); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); /* Update the per-port timeout. */ port->read_status_mask = SW_UART_LSR_OE | SW_UART_LSR_THRE | SW_UART_LSR_DR; if (termios->c_iflag & INPCK) port->read_status_mask |= SW_UART_LSR_FE | SW_UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= SW_UART_LSR_BI; /* Characteres to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SW_UART_LSR_PE | SW_UART_LSR_FE; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= SW_UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= SW_UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= SW_UART_LSR_DR; /* * if lcr & baud are changed, reset controller to disable transfer */ if (lcr != sw_uport->lcr || dll != sw_uport->dll || dlh != sw_uport->dlh) { // SERIAL_DBG("LCR & BAUD changed, reset controller...\n"); sw_uart_reset(sw_uport); } sw_uport->dll = dll; sw_uport->dlh = dlh; /* flow control */ sw_uport->mcr &= ~SW_UART_MCR_AFE; if (termios->c_cflag & CRTSCTS) sw_uport->mcr |= SW_UART_MCR_AFE; serial_out(port, sw_uport->mcr, SW_UART_MCR); /* * CTS flow control flag and modem status interrupts */ sw_uport->ier &= ~SW_UART_IER_MSI; if (UART_ENABLE_MS(port, termios->c_cflag)) sw_uport->ier |= SW_UART_IER_MSI; serial_out(port, sw_uport->ier, SW_UART_IER); sw_uport->fcr = SW_UART_FCR_RXTRG_1_2 | SW_UART_FCR_TXTRG_1_2 | SW_UART_FCR_FIFO_EN; serial_out(port, sw_uport->fcr, SW_UART_FCR); sw_uport->lcr = lcr; serial_out(port, sw_uport->lcr|SW_UART_LCR_DLAB, SW_UART_LCR); if (serial_in(port, SW_UART_LCR) != (sw_uport->lcr|SW_UART_LCR_DLAB)) { lcr_fail = 1; } else { sw_uport->lcr = lcr; serial_out(port, sw_uport->dll, SW_UART_DLL); serial_out(port, sw_uport->dlh, SW_UART_DLH); serial_out(port, sw_uport->lcr, SW_UART_LCR); if (serial_in(port, SW_UART_LCR) != sw_uport->lcr) { lcr_fail = 2; } } #ifdef CONFIG_SW_UART_FORCE_LCR if (lcr_fail) { sw_uart_force_lcr(sw_uport, 50); serial_in(port, SW_UART_USR); } #endif /* clear rxfifo after set lcr & baud to discard redundant data */ serial_out(port, sw_uport->fcr|SW_UART_FCR_RXFIFO_RST, SW_UART_FCR); port->ops->set_mctrl(port, port->mctrl); /* Must save the current config for the resume of console(no tty user). */ if (sw_is_console_port(port)) port->cons->cflag = termios->c_cflag; spin_unlock_irqrestore(&port->lock, flags); /* lately output force lcr information */ if (lcr_fail == 1) { SERIAL_MSG("uart%d write LCR(pre-dlab) failed, lcr %x reg %x\n", sw_uport->id, sw_uport->lcr|(u32)SW_UART_LCR_DLAB, serial_in(port, SW_UART_LCR)); } else if (lcr_fail == 2) { SERIAL_MSG("uart%d write LCR(post-dlab) failed, lcr %x reg %x\n", sw_uport->id, sw_uport->lcr, serial_in(port, SW_UART_LCR)); } /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); SERIAL_DBG("termios lcr 0x%x fcr 0x%x mcr 0x%x dll 0x%x dlh 0x%x\n", sw_uport->lcr, sw_uport->fcr, sw_uport->mcr, sw_uport->dll, sw_uport->dlh); }
static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; unsigned int baud = 0, bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); if (!tty) return; tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); /* If the baud rate is to be updated*/ if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { dbg("%s - Setting baud rate to %d baud", __func__, baud); if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { dbg("Baud rate requested not supported by device"); baud = tty_termios_baud_rate(old_termios); } } /* Report back the resulting baud rate */ tty_encode_baud_rate(tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); bits &= ~BITS_DATA_MASK; switch (cflag & CSIZE) { case CS5: bits |= BITS_DATA_5; dbg("%s - data bits = 5", __func__); break; case CS6: bits |= BITS_DATA_6; dbg("%s - data bits = 6", __func__); break; case CS7: bits |= BITS_DATA_7; dbg("%s - data bits = 7", __func__); break; case CS8: bits |= BITS_DATA_8; dbg("%s - data bits = 8", __func__); break; /*case CS9: bits |= BITS_DATA_9; dbg("%s - data bits = 9", __func__); break;*/ default: dbg("cp210x driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of data bits requested " "not supported by device\n"); } if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); bits &= ~BITS_PARITY_MASK; if (cflag & PARENB) { if (cflag & PARODD) { bits |= BITS_PARITY_ODD; dbg("%s - parity = ODD", __func__); } else { bits |= BITS_PARITY_EVEN; dbg("%s - parity = EVEN", __func__); } } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Parity mode not supported " "by device\n"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); bits &= ~BITS_STOP_MASK; if (cflag & CSTOPB) { bits |= BITS_STOP_2; dbg("%s - stop bits = 2", __func__); } else { bits |= BITS_STOP_1; dbg("%s - stop bits = 1", __func__); } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of stop bits requested " "not supported by device\n"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16); dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); if (cflag & CRTSCTS) { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x09; modem_ctl[1] = 0x80; dbg("%s - flow control = CRTSCTS", __func__); } else { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x01; modem_ctl[1] |= 0x40; dbg("%s - flow control = NONE", __func__); } dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", __func__, modem_ctl[0], modem_ctl[1], modem_ctl[2], modem_ctl[3]); cp210x_set_config(port, CP210X_SET_FLOW, modem_ctl, 16); } }
/* * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have * some differences in how we want to handle flow control. */ static void omap_8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); struct omap8250_priv *priv = up->port.private_data; unsigned char cval = 0; unsigned int baud; 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; if (termios->c_cflag & CMSPAR) cval |= UART_LCR_SPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / 0xffff, port->uartclk / 13); omap_8250_get_divisor(port, baud, priv); /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ pm_runtime_get_sync(port->dev); spin_lock_irq(&port->lock); /* * 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 & (IGNBRK | 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; up->lcr = cval; /* Up to here it was mostly serial8250_do_set_termios() */ /* * We enable TRIG_GRANU for RX and TX and additionaly we set * SCR_TX_EMPTY bit. The result is the following: * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt. * - less than RX_TRIGGER number of bytes will also cause an interrupt * once the UART decides that there no new bytes arriving. * - Once THRE is enabled, the interrupt will be fired once the FIFO is * empty - the trigger level is ignored here. * * Once DMA is enabled: * - UART will assert the TX DMA line once there is room for TX_TRIGGER * bytes in the TX FIFO. On each assert the DMA engine will move * TX_TRIGGER bytes into the FIFO. * - UART will assert the RX DMA line once there are RX_TRIGGER bytes in * the FIFO and move RX_TRIGGER bytes. * This is because threshold and trigger values are the same. */ up->fcr = UART_FCR_ENABLE_FIFO; up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG; up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG; priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY | OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; if (up->dma) priv->scr |= OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL; priv->xon = termios->c_cc[VSTART]; priv->xoff = termios->c_cc[VSTOP]; priv->efr = 0; up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY); if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { /* Enable AUTORTS and AUTOCTS */ priv->efr |= UART_EFR_CTS | UART_EFR_RTS; /* Ensure MCR RTS is asserted */ up->mcr |= UART_MCR_RTS; } else if (up->port.flags & UPF_SOFT_FLOW) { /* * IXON Flag: * Enable XON/XOFF flow control on input. * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXON) priv->efr |= OMAP_UART_SW_RX; /* * IXOFF Flag: * Enable XON/XOFF flow control on output. * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXOFF) priv->efr |= OMAP_UART_SW_TX; /* * 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; } omap8250_restore_regs(up); spin_unlock_irq(&up->port.lock); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); /* calculate wakeup latency constraint */ priv->calc_latency = USEC_PER_SEC * 64 * 8 / baud; priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); }