static void altera_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, baudclk; baud = uart_get_baud_rate(port, termios, old, 0, 4000000); baudclk = port->uartclk / baud; if (old) tty_termios_copy_hw(termios, old); tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); spin_unlock_irqrestore(&port->lock, flags); /* * FIXME: port->read_status_mask and port->ignore_status_mask * need to be initialized based on termios settings for * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT */ }
static void timbuart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud; short bindex; unsigned long flags; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); bindex = get_bindex(baud); dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex); if (bindex < 0) bindex = 0; baud = baudrates[bindex]; /* The serial layer calls into this once with old = NULL when setting up initially */ if (old) tty_termios_copy_hw(termios, old); tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&port->lock, flags); iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE); uart_update_timeout(port, termios->c_cflag, baud); spin_unlock_irqrestore(&port->lock, flags); }
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed) { struct tty_struct *tty = hu->tty; struct ktermios ktermios; ktermios = tty->termios; ktermios.c_cflag &= ~CBAUD; tty_termios_encode_baud_rate(&ktermios, speed, speed); /* tty_set_termios() return not checked as it is always 0 */ tty_set_termios(tty, &ktermios); BT_DBG("%s: New tty speeds: %d/%d", hu->hdev->name, tty->termios.c_ispeed, tty->termios.c_ospeed); }
static void altera_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, baudclk; baud = uart_get_baud_rate(port, termios, old, 0, 4000000); baudclk = port->uartclk / baud; if (old) tty_termios_copy_hw(termios, old); tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&port->lock, flags); writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG); spin_unlock_irqrestore(&port->lock, flags); }
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); }
void nci_uart_set_config(struct nci_uart *nu, int baudrate, int flow_ctrl) { struct ktermios new_termios; if (!nu->tty) return; down_read(&nu->tty->termios_rwsem); new_termios = nu->tty->termios; up_read(&nu->tty->termios_rwsem); tty_termios_encode_baud_rate(&new_termios, baudrate, baudrate); if (flow_ctrl) new_termios.c_cflag |= CRTSCTS; else new_termios.c_cflag &= ~CRTSCTS; tty_set_termios(nu->tty, &new_termios); }
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed) { struct tty_struct *tty = hu->tty; struct ktermios ktermios; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) ktermios = tty->termios; #else ktermios = *tty->termios; #endif ktermios.c_cflag &= ~CBAUD; tty_termios_encode_baud_rate(&ktermios, speed, speed); /* tty_set_termios() return not checked as it is always 0 */ tty_set_termios(tty, &ktermios); BT_DBG("%s: New tty speeds: %d/%d", hu->hdev->name, ktermios.c_ispeed, ktermios.c_ospeed); }
int kgdb_register_nmi_console(void) { int ret; if (!arch_kgdb_ops.enable_nmi) return 0; kgdb_nmi_tty_driver = alloc_tty_driver(1); if (!kgdb_nmi_tty_driver) { pr_err("%s: cannot allocate tty\n", __func__); return -ENOMEM; } kgdb_nmi_tty_driver->driver_name = "ttyNMI"; kgdb_nmi_tty_driver->name = "ttyNMI"; kgdb_nmi_tty_driver->num = 1; kgdb_nmi_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; kgdb_nmi_tty_driver->subtype = SERIAL_TYPE_NORMAL; kgdb_nmi_tty_driver->flags = TTY_DRIVER_REAL_RAW; kgdb_nmi_tty_driver->init_termios = tty_std_termios; tty_termios_encode_baud_rate(&kgdb_nmi_tty_driver->init_termios, KGDB_NMI_BAUD, KGDB_NMI_BAUD); tty_set_operations(kgdb_nmi_tty_driver, &kgdb_nmi_tty_ops); ret = tty_register_driver(kgdb_nmi_tty_driver); if (ret) { pr_err("%s: can't register tty driver: %d\n", __func__, ret); goto err_drv_reg; } register_console(&kgdb_nmi_console); arch_kgdb_ops.enable_nmi(1); return 0; err_drv_reg: put_tty_driver(kgdb_nmi_tty_driver); return ret; }
static void serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_max3110 *max = container_of(port, struct uart_max3110, port); unsigned char cval; unsigned int baud, parity = 0; int clk_div = -1; u16 new_conf = max->cur_conf; switch (termios->c_cflag & CSIZE) { case CS7: cval = UART_LCR_WLEN7; new_conf |= WC_7BIT_WORD; break; default: case CS8: cval = UART_LCR_WLEN8; new_conf |= WC_8BIT_WORD; break; } baud = uart_get_baud_rate(port, termios, old, 0, 230400); /* first calc the div for 1.8MHZ clock case */ switch (baud) { case 300: clk_div = WC_BAUD_DR384; break; case 600: clk_div = WC_BAUD_DR192; break; case 1200: clk_div = WC_BAUD_DR96; break; case 2400: clk_div = WC_BAUD_DR48; break; case 4800: clk_div = WC_BAUD_DR24; break; case 9600: clk_div = WC_BAUD_DR12; break; case 19200: clk_div = WC_BAUD_DR6; break; case 38400: clk_div = WC_BAUD_DR3; break; case 57600: clk_div = WC_BAUD_DR2; break; case 115200: clk_div = WC_BAUD_DR1; break; case 230400: if (max->clock & MAX3110_HIGH_CLK) break; default: /* pick the previous baud rate */ baud = max->baud; clk_div = max->cur_conf & WC_BAUD_DIV_MASK; tty_termios_encode_baud_rate(termios, baud, baud); } if (max->clock & MAX3110_HIGH_CLK) { clk_div += 1; /* high clk version max3110 doesn't support B300 */ if (baud == 300) baud = 600; if (baud == 230400) clk_div = WC_BAUD_DR1; tty_termios_encode_baud_rate(termios, baud, baud); } new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div; if (termios->c_cflag & CSTOPB) new_conf |= WC_2_STOPBITS; else new_conf &= ~WC_2_STOPBITS; if (termios->c_cflag & PARENB) { new_conf |= WC_PARITY_ENABLE; parity |= UART_LCR_PARITY; } else new_conf &= ~WC_PARITY_ENABLE; if (!(termios->c_cflag & PARODD)) parity |= UART_LCR_EPAR; max->parity = parity; uart_update_timeout(port, termios->c_cflag, baud); new_conf |= WC_TAG; if (new_conf != max->cur_conf) { max3110_out(max, new_conf); max->cur_conf = new_conf; max->baud = baud; } }
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 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 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 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); }
/** * 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 ipoctal_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { unsigned int cflag; unsigned char mr1 = 0; unsigned char mr2 = 0; unsigned char csr = 0; struct ipoctal_channel *channel = tty->driver_data; speed_t baud; cflag = tty->termios.c_cflag; /* Disable and reset everything before change the setup */ iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); /* Set Bits per chars */ switch (cflag & CSIZE) { case CS6: mr1 |= MR1_CHRL_6_BITS; break; case CS7: mr1 |= MR1_CHRL_7_BITS; break; case CS8: default: mr1 |= MR1_CHRL_8_BITS; /* By default, select CS8 */ tty->termios.c_cflag = (cflag & ~CSIZE) | CS8; break; } /* Set Parity */ if (cflag & PARENB) if (cflag & PARODD) mr1 |= MR1_PARITY_ON | MR1_PARITY_ODD; else mr1 |= MR1_PARITY_ON | MR1_PARITY_EVEN; else mr1 |= MR1_PARITY_OFF; /* Mark or space parity is not supported */ tty->termios.c_cflag &= ~CMSPAR; /* Set stop bits */ if (cflag & CSTOPB) mr2 |= MR2_STOP_BITS_LENGTH_2; else mr2 |= MR2_STOP_BITS_LENGTH_1; /* Set the flow control */ switch (channel->board_id) { case IPACK1_DEVICE_ID_SBS_OCTAL_232: if (cflag & CRTSCTS) { mr1 |= MR1_RxRTS_CONTROL_ON; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON; } else { mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; } break; case IPACK1_DEVICE_ID_SBS_OCTAL_422: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; break; case IPACK1_DEVICE_ID_SBS_OCTAL_485: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF; break; default: return; break; } baud = tty_get_baud_rate(tty); tty_termios_encode_baud_rate(&tty->termios, baud, baud); /* Set baud rate */ switch (baud) { case 75: csr |= TX_CLK_75 | RX_CLK_75; break; case 110: csr |= TX_CLK_110 | RX_CLK_110; break; case 150: csr |= TX_CLK_150 | RX_CLK_150; break; case 300: csr |= TX_CLK_300 | RX_CLK_300; break; case 600: csr |= TX_CLK_600 | RX_CLK_600; break; case 1200: csr |= TX_CLK_1200 | RX_CLK_1200; break; case 1800: csr |= TX_CLK_1800 | RX_CLK_1800; break; case 2000: csr |= TX_CLK_2000 | RX_CLK_2000; break; case 2400: csr |= TX_CLK_2400 | RX_CLK_2400; break; case 4800: csr |= TX_CLK_4800 | RX_CLK_4800; break; case 9600: csr |= TX_CLK_9600 | RX_CLK_9600; break; case 19200: csr |= TX_CLK_19200 | RX_CLK_19200; break; case 38400: default: csr |= TX_CLK_38400 | RX_CLK_38400; /* In case of default, we establish 38400 bps */ tty_termios_encode_baud_rate(&tty->termios, 38400, 38400); break; } mr1 |= MR1_ERROR_CHAR; mr1 |= MR1_RxINT_RxRDY; /* Write the control registers */ iowrite8(mr1, &channel->regs->w.mr); iowrite8(mr2, &channel->regs->w.mr); iowrite8(csr, &channel->regs->w.csr); /* Enable again the RX, if it was before */ if (channel->rx_enable) iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); }
/* * The parsing of the command line works exactly like the * serial.c code, except that the specifier is "ttyUSB" instead * of "ttyS". */ static int usb_console_setup(struct console *co, char *options) { struct usbcons_info *info = &usbcons_info; int baud = 9600; int bits = 8; int parity = 'n'; int doflow = 0; int cflag = CREAD | HUPCL | CLOCAL; char *s; struct usb_serial *serial; struct usb_serial_port *port; int retval = 0; struct tty_struct *tty = NULL; struct ktermios *termios = NULL, dummy; dbg("%s", __func__); if (options) { baud = simple_strtoul(options, NULL, 10); s = options; while (*s >= '0' && *s <= '9') s++; if (*s) parity = *s++; if (*s) bits = *s++ - '0'; if (*s) doflow = (*s++ == 'r'); } /* Sane default */ if (baud == 0) baud = 9600; switch (bits) { case 7: cflag |= CS7; break; default: case 8: cflag |= CS8; break; } switch (parity) { case 'o': case 'O': cflag |= PARODD; break; case 'e': case 'E': cflag |= PARENB; break; } co->cflag = cflag; /* * no need to check the index here: if the index is wrong, console * code won't call us */ serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ err("No USB device connected to ttyUSB%i", co->index); return -ENODEV; } port = serial->port[0]; port->port.tty = NULL; info->port = port; ++port->port.count; if (port->port.count == 1) { if (serial->type->set_termios) { /* * allocate a fake tty so the driver can initialize * the termios structure, then later call set_termios to * configure according to command line arguments */ tty = kzalloc(sizeof(*tty), GFP_KERNEL); if (!tty) { retval = -ENOMEM; err("no more memory"); goto reset_open_count; } termios = kzalloc(sizeof(*termios), GFP_KERNEL); if (!termios) { retval = -ENOMEM; err("no more memory"); goto free_tty; } memset(&dummy, 0, sizeof(struct ktermios)); tty->termios = termios; port->port.tty = tty; } /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) retval = serial->type->open(NULL, port, NULL); else retval = usb_serial_generic_open(NULL, port, NULL); if (retval) { err("could not open USB console port"); goto free_termios; } if (serial->type->set_termios) { termios->c_cflag = cflag; tty_termios_encode_baud_rate(termios, baud, baud); serial->type->set_termios(tty, port, &dummy); port->port.tty = NULL; kfree(termios); kfree(tty); } } port->console = 1; retval = 0; out: return retval; free_termios: kfree(termios); port->port.tty = NULL; free_tty: kfree(tty); reset_open_count: port->port.count = 0; goto out; }
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 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); }
/* * 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); }
static void imx_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; unsigned int div, ufcr; unsigned long num, denom; uint64_t tdiv64; /* * If we don't support modem control lines, don't allow * these to be set. */ if (0) { termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR); termios->c_cflag |= CLOCAL; } /* * We only support CS7 and CS8. */ while ((termios->c_cflag & CSIZE) != CS7 && (termios->c_cflag & CSIZE) != CS8) { termios->c_cflag &= ~CSIZE; termios->c_cflag |= old_csize; old_csize = CS8; } if ((termios->c_cflag & CSIZE) == CS8) ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS; else ucr2 = UCR2_SRST | UCR2_IRTS; if (termios->c_cflag & CRTSCTS) { if( sport->have_rtscts ) { ucr2 &= ~UCR2_IRTS; ucr2 |= UCR2_CTSC; } else { termios->c_cflag &= ~CRTSCTS; } } if (termios->c_cflag & CSTOPB) ucr2 |= UCR2_STPB; if (termios->c_cflag & PARENB) { ucr2 |= UCR2_PREN; if (termios->c_cflag & PARODD) ucr2 |= UCR2_PROE; } /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); sport->port.read_status_mask = 0; if (termios->c_iflag & INPCK) sport->port.read_status_mask |= (URXD_FRMERR | URXD_PRERR); if (termios->c_iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= URXD_BRK; /* * Characters to ignore */ sport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= URXD_PRERR; if (termios->c_iflag & IGNBRK) { sport->port.ignore_status_mask |= URXD_BRK; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= URXD_OVRRUN; } del_timer_sync(&sport->timer); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* * disable interrupts and drain transmitter */ old_ucr1 = readl(sport->port.membase + UCR1); writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), sport->port.membase + UCR1); while ( !(readl(sport->port.membase + USR2) & USR2_TXDC)) barrier(); /* then, disable everything */ old_txrxen = readl(sport->port.membase + UCR2); writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN), sport->port.membase + UCR2); old_txrxen &= (UCR2_TXEN | UCR2_RXEN); if (USE_IRDA(sport)) { /* * use maximum available submodule frequency to * avoid missing short pulses due to low sampling rate */ div = 1; } else { div = sport->port.uartclk / (baud * 16); if (div > 7) div = 7; if (!div) div = 1; } rational_best_approximation(16 * div * baud, sport->port.uartclk, 1 << 16, 1 << 16, &num, &denom); tdiv64 = sport->port.uartclk; tdiv64 *= num; do_div(tdiv64, denom * 16 * div); tty_termios_encode_baud_rate(termios, (speed_t)tdiv64, (speed_t)tdiv64); num -= 1; denom -= 1; ufcr = readl(sport->port.membase + UFCR); ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); writel(ufcr, sport->port.membase + UFCR); writel(num, sport->port.membase + UBIR); writel(denom, sport->port.membase + UBMR); if (!cpu_is_mx1()) writel(sport->port.uartclk / div / 1000, sport->port.membase + MX2_ONEMS); writel(old_ucr1, sport->port.membase + UCR1); /* set the parity, stop bits and data size */ writel(ucr2 | old_txrxen, sport->port.membase + UCR2); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->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); }
/* * The parsing of the command line works exactly like the * serial.c code, except that the specifier is "ttyUSB" instead * of "ttyS". */ static int usb_console_setup(struct console *co, char *options) { struct usbcons_info *info = &usbcons_info; int baud = 9600; int bits = 8; int parity = 'n'; int doflow = 0; int cflag = CREAD | HUPCL | CLOCAL; char *s; struct usb_serial *serial; struct usb_serial_port *port; int retval; struct tty_struct *tty = NULL; struct ktermios dummy; dbg("%s", __func__); if (options) { baud = simple_strtoul(options, NULL, 10); s = options; while (*s >= '0' && *s <= '9') s++; if (*s) parity = *s++; if (*s) bits = *s++ - '0'; if (*s) doflow = (*s++ == 'r'); } /* Sane default */ if (baud == 0) baud = 9600; switch (bits) { case 7: cflag |= CS7; break; default: case 8: cflag |= CS8; break; } switch (parity) { case 'o': case 'O': cflag |= PARODD; break; case 'e': case 'E': cflag |= PARENB; break; } co->cflag = cflag; /* * no need to check the index here: if the index is wrong, console * code won't call us */ serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ err("No USB device connected to ttyUSB%i", co->index); return -ENODEV; } retval = usb_autopm_get_interface(serial->interface); if (retval) goto error_get_interface; port = serial->port[co->index - serial->minor]; tty_port_tty_set(&port->port, NULL); info->port = port; ++port->port.count; if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { if (serial->type->set_termios) { /* * allocate a fake tty so the driver can initialize * the termios structure, then later call set_termios to * configure according to command line arguments */ tty = kzalloc(sizeof(*tty), GFP_KERNEL); if (!tty) { retval = -ENOMEM; err("no more memory"); goto reset_open_count; } kref_init(&tty->kref); tty_port_tty_set(&port->port, tty); tty->driver = usb_serial_tty_driver; tty->index = co->index; if (tty_init_termios(tty)) { retval = -ENOMEM; err("no more memory"); goto free_tty; } } /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) retval = serial->type->open(NULL, port); else retval = usb_serial_generic_open(NULL, port); if (retval) { err("could not open USB console port"); goto fail; } if (serial->type->set_termios) { tty->termios->c_cflag = cflag; tty_termios_encode_baud_rate(tty->termios, baud, baud); memset(&dummy, 0, sizeof(struct ktermios)); serial->type->set_termios(tty, port, &dummy); tty_port_tty_set(&port->port, NULL); kfree(tty); } set_bit(ASYNCB_INITIALIZED, &port->port.flags); } /* Now that any required fake tty operations are completed restore * the tty port count */ --port->port.count; /* The console is special in terms of closing the device so * indicate this port is now acting as a system console. */ port->port.console = 1; mutex_unlock(&serial->disc_mutex); return retval; fail: tty_port_tty_set(&port->port, NULL); free_tty: kfree(tty); reset_open_count: port->port.count = 0; usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); mutex_unlock(&serial->disc_mutex); return retval; }
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); }