示例#1
0
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);
}
示例#2
0
文件: 8250_dw.c 项目: DenisLug/mptcp
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);
}
示例#3
0
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);
}
示例#5
0
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);
}
示例#6
0
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;
}
示例#7
0
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);
}
示例#8
0
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);
}
示例#9
0
/**
 * 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);
}
示例#10
0
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);
}
示例#11
0
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);
}
示例#12
0
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);
	}

}
示例#13
0
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;
}
示例#14
0
/**
 * 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);
}
示例#15
0
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);
}
示例#16
0
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;
}
示例#17
0
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);
}
示例#18
0
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);
	}

}
示例#20
0
/*
 * 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);
}