static int msm_hsl_loopback_enable_set(void *data, u64 val)
{
	struct msm_hsl_port *msm_hsl_port = data;
	struct uart_port *port = &(msm_hsl_port->uart);
	unsigned int vid;
	unsigned long flags;
	int ret = 0;

	ret = clk_set_rate(msm_hsl_port->clk, 7372800);
	if (!ret)
		clk_en(port, 1);
	else {
		E("%s(): Error: Setting the clock rate\n", __func__);
		return -EINVAL;
	}

	vid = msm_hsl_port->ver_id;
	if (val) {
		spin_lock_irqsave(&port->lock, flags);
		ret = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
		ret |= UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, ret, regmap[vid][UARTDM_MR2]);
		spin_unlock_irqrestore(&port->lock, flags);
		E("%s(): irda loopback enabled for line(%d)\n", __func__, port->line);
	} else {
		spin_lock_irqsave(&port->lock, flags);
		ret = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
		ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, ret, regmap[vid][UARTDM_MR2]);
		spin_unlock_irqrestore(&port->lock, flags);
	}

	clk_en(port, 0);
	return 0;
}
static void msm_hsl_set_mctrl_irda(struct uart_port *port, unsigned int mctrl)
{
	unsigned int vid = UART_TO_MSM(port)->ver_id;
	unsigned int mr;
	unsigned int loop_mode;

	mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);

	if (!(mctrl & TIOCM_RTS)) {
		mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
		msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
		msm_hsl_write(port, RFR_HIGH, regmap[vid][UARTDM_CR]);
	} else {
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
		msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
	}

	loop_mode = TIOCM_LOOP & mctrl;
	if (loop_mode) {
		mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
		mr |= UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);

		/* Reset TX */
		msm_hsl_reset(port);

		/* Turn on Uart Receiver & Transmitter*/
		msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK
		      | UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
	}
}
示例#3
0
static int msm_hsl_loopback_enable_set(void *data, u64 val)
{
	struct msm_hsl_port *msm_hsl_port = data;
	struct uart_port *port = &(msm_hsl_port->uart);
	unsigned long flags;
	int ret = 0;

	ret = clk_set_rate(msm_hsl_port->clk, 7372800);
	if (!ret)
		clk_en(port, 1);
	else {
		pr_err("%s(): Error: Setting the clock rate\n", __func__);
		return -EINVAL;
	}

	if (val) {
		spin_lock_irqsave(&port->lock, flags);
		ret = msm_hsl_read(port, UARTDM_MR2_ADDR);
		ret |= UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, ret, UARTDM_MR2_ADDR);
		spin_unlock_irqrestore(&port->lock, flags);
	} else {
		spin_lock_irqsave(&port->lock, flags);
		ret = msm_hsl_read(port, UARTDM_MR2_ADDR);
		ret &= ~UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, ret, UARTDM_MR2_ADDR);
		spin_unlock_irqrestore(&port->lock, flags);
	}

	clk_en(port, 0);
	return 0;
}
示例#4
0
static void msm_hsl_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
	unsigned int mr;
	unsigned int loop_mode;

	clk_en(port, 1);

	mr = msm_hsl_read(port, UARTDM_MR1_ADDR);

	if (!(mctrl & TIOCM_RTS)) {
		mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
		msm_hsl_write(port, mr, UARTDM_MR1_ADDR);
		msm_hsl_write(port, RFR_HIGH, UARTDM_CR_ADDR);
	} else {
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
		msm_hsl_write(port, mr, UARTDM_MR1_ADDR);
	}

	loop_mode = TIOCM_LOOP & mctrl;
	if (loop_mode) {
		mr = msm_hsl_read(port, UARTDM_MR2_ADDR);
		mr |= UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, mr, UARTDM_MR2_ADDR);

		/* Reset TX */
		msm_hsl_reset(port);

		/* Turn on Uart Receiver & Transmitter*/
		msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK
			      | UARTDM_CR_TX_EN_BMSK, UARTDM_CR_ADDR);
	}

	clk_en(port, 0);
}
示例#5
0
/*
 *  Wait for transmitter & holding register to empty
 *  Derived from wait_for_xmitr in 8250 serial driver by Russell King  */
void wait_for_xmitr(struct uart_port *port, int bits)
{
	if (!(msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_TXEMT_BMSK)) {
		while ((msm_hsl_read(port, UARTDM_ISR_ADDR) & bits) != bits) {
			udelay(1);
			touch_nmi_watchdog();
			cpu_relax();
		}
		msm_hsl_write(port, CLEAR_TX_READY, UARTDM_CR_ADDR);
	}
}
static void msm_hsl_console_putchars(struct uart_port *port,
				     int num, const char *s)
{
	int word;
	int i;

	if (num == 0)
		return;

	wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
	msm_hsl_write(port, num, UARTDM_NCF_TX_ADDR);

	for (i = 0; i < num; i += 4)  {
		word = 0;
		switch (num - i) {
		default:
			word |= s[i + 3] << 24;
			/* deliberate fall-through */
		case 3:
			word |= s[i + 2] << 16;
		case 2:
			word |= s[i + 1] << 8;
		case 1:
			word |= s[i];
		}
		while (!(msm_hsl_read(port, UARTDM_SR_ADDR) &
			UARTDM_SR_TXRDY_BMSK)) {
			udelay(1);
			touch_nmi_watchdog();
		}
		msm_hsl_write(port, word, UARTDM_TF_ADDR);
	}
}
/*
 *  Wait for transmitter & holding register to empty
 *  Derived from wait_for_xmitr in 8250 serial driver by Russell King  */
void wait_for_xmitr(struct uart_port *port, int bits)
{
	unsigned int vid = UART_TO_MSM(port)->ver_id;

	if (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
			UARTDM_SR_TXEMT_BMSK)) {
		while ((msm_hsl_read(port, regmap[vid][UARTDM_ISR]) &
					bits) != bits) {
			udelay(1);
			touch_nmi_watchdog();
			cpu_relax();
		}
		msm_hsl_write(port, CLEAR_TX_READY, regmap[vid][UARTDM_CR]);
	}
	D("%s ():port->line %d, ir\n", __func__, port->line);
}
示例#8
0
static int msm_hsl_startup_cir(struct uart_port *port)
{
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);

	unsigned int data, rfr_level;
	unsigned int vid;
	int ret;
	unsigned long flags;

	snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name),
		 "msm_serial_hsl%d", port->line);
	D("%s () :port->line %d, ir\n", __func__, port->line);
	if (!(is_console(port)) || (!port->cons) ||
		(port->cons && (!(port->cons->flags & CON_ENABLED)))) {

		if (msm_serial_hsl_has_gsbi(port)) {
			D("%s () serial_hsl_has_gsbi:port->line %d, ir\n", __func__, port->line);
			if ((ioread32(msm_hsl_port->mapped_gsbi +
				GSBI_CONTROL_ADDR) & GSBI_PROTOCOL_I2C_UART)
					!= GSBI_PROTOCOL_I2C_UART){
				D("%s () iowrite32i:port->line %d, ir\n", __func__, port->line);
				iowrite32(GSBI_PROTOCOL_I2C_UART,
					msm_hsl_port->mapped_gsbi +
						GSBI_CONTROL_ADDR);
			}
		}
	}
#ifndef CONFIG_PM_RUNTIME
	msm_hsl_init_clock(port);
#endif
	pm_runtime_get_sync(port->dev);

	
	if (likely(port->fifosize > 48))
		rfr_level = port->fifosize - 16;
	else
		rfr_level = port->fifosize;

	rfr_level = (rfr_level / 4);

	spin_lock_irqsave(&port->lock, flags);

	vid = msm_hsl_port->ver_id;
	
	data = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
	data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
	data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
	msm_hsl_write(port, data, regmap[vid][UARTDM_MR1]);
	spin_unlock_irqrestore(&port->lock, flags);

	ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
			  msm_hsl_port->name, port);
	if (unlikely(ret)) {
		printk(KERN_ERR "%s: failed to request_irq\n", __func__);
		return ret;
	}
	return 0;
}
示例#9
0
static irqreturn_t msm_hsl_irq(int irq, void *dev_id)
{
	struct uart_port *port = dev_id;
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
	unsigned int vid;
	unsigned int misr;
	unsigned long flags;

	spin_lock_irqsave(&port->lock, flags);
	vid = msm_hsl_port->ver_id;
	misr = msm_hsl_read(port, regmap[vid][UARTDM_MISR]);
	
	msm_hsl_write(port, 0, regmap[vid][UARTDM_IMR]);

	if (misr & (UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_RXLEV_BMSK)) {
		handle_rx(port, misr);
		if (misr & (UARTDM_ISR_RXSTALE_BMSK))
			msm_hsl_write(port, RESET_STALE_INT,
					regmap[vid][UARTDM_CR]);
		msm_hsl_write(port, 6500, regmap[vid][UARTDM_DMRX]);
		msm_hsl_write(port, STALE_EVENT_ENABLE, regmap[vid][UARTDM_CR]);
	}
	if (misr & UARTDM_ISR_TXLEV_BMSK)
		handle_tx(port);

	if (misr & UARTDM_ISR_DELTA_CTS_BMSK)
		handle_delta_cts(port);

	
	msm_hsl_write(port, msm_hsl_port->imr, regmap[vid][UARTDM_IMR]);
	spin_unlock_irqrestore(&port->lock, flags);

	return IRQ_HANDLED;
}
示例#10
0
static irqreturn_t msm_hsl_irq(int irq, void *dev_id)
{
	struct uart_port *port = dev_id;
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
	unsigned int misr;
	unsigned long flags;

	spin_lock_irqsave(&port->lock, flags);
	clk_en(port, 1);
	misr = msm_hsl_read(port, UARTDM_MISR_ADDR);
	msm_hsl_write(port, 0, UARTDM_IMR_ADDR); /* disable interrupt */

	if (misr & (UARTDM_ISR_RXSTALE_BMSK | UARTDM_ISR_RXLEV_BMSK)) {
		handle_rx(port, misr);
		if (misr & (UARTDM_ISR_RXSTALE_BMSK))
			msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR);
		msm_hsl_write(port, 6500, UARTDM_DMRX_ADDR);
		msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR_ADDR);
	}
	if (misr & UARTDM_ISR_TXLEV_BMSK)
		handle_tx(port);

	if (misr & UARTDM_ISR_DELTA_CTS_BMSK)
		handle_delta_cts(port);

	/* restore interrupt */
	msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR);
	clk_en(port, 0);
	spin_unlock_irqrestore(&port->lock, flags);

	return IRQ_HANDLED;
}
static unsigned int msm_hsl_tx_empty_irda(struct uart_port *port)
{
	unsigned int ret;
	unsigned int vid = UART_TO_MSM(port)->ver_id;

	ret = (msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
	       UARTDM_SR_TXEMT_BMSK) ? TIOCSER_TEMT : 0;
	return ret;
}
示例#12
0
static unsigned int msm_hsl_tx_empty(struct uart_port *port)
{
	unsigned int ret;

	clk_en(port, 1);
	ret = (msm_hsl_read(port, UARTDM_SR_ADDR) &
	       UARTDM_SR_TXEMT_BMSK) ? TIOCSER_TEMT : 0;
	clk_en(port, 0);

	return ret;
}
示例#13
0
static unsigned int msm_hsl_tx_empty_cir(struct uart_port *port)
{
	unsigned int vid = UART_TO_MSM(port)->ver_id;
	unsigned int ret;
	pr_info("%s ():port->line %d, ir\n", __func__, port->line);
	clk_en(port, 1);
	ret = (msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
	       UARTDM_SR_TXEMT_BMSK) ? TIOCSER_TEMT : 0;
	clk_en(port, 0);

	return ret;
}
示例#14
0
static void msm_hsl_console_putchar(struct uart_port *port, int ch)
{
	wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
	msm_hsl_write(port, 1, UARTDM_NCF_TX_ADDR);

	while (!(msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_TXRDY_BMSK)) {
		udelay(1);
		touch_nmi_watchdog();
	}

	msm_hsl_write(port, ch, UARTDM_TF_ADDR);
}
示例#15
0
static void msm_hsl_set_mctrl_cir(struct uart_port *port, unsigned int mctrl)
{
	unsigned int vid = UART_TO_MSM(port)->ver_id;
	unsigned int mr;
	unsigned int loop_mode;

	clk_en(port, 1);

	mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);

	if (!(mctrl & TIOCM_RTS)) {
		pr_info("%s ()mctrl & TIOCM_RTS:port->line %d, ir\n", __func__, port->line);
		mr &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
		msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
		msm_hsl_write(port, RFR_HIGH, regmap[vid][UARTDM_CR]);
	} else {
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
		msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);
		pr_info("%s () TIOCM_RTS:port->line %d, ir\n", __func__, port->line);
	}

	loop_mode = TIOCM_LOOP & mctrl;
	if (loop_mode) {
		pr_info("%s ()loop_mode:port->line %d, ir\n", __func__, port->line);
		mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
		mr |= UARTDM_MR2_LOOP_MODE_BMSK;
		msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);

		
		msm_hsl_reset(port);

		
		msm_hsl_write(port, UARTDM_CR_RX_EN_BMSK
		      | UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
	}

	clk_en(port, 0);
}
static void msm_hsl_console_putchar(struct uart_port *port, int ch)
{
	unsigned int vid = UART_TO_MSM(port)->ver_id;

	wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
	msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
#if 1
	while (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
				UARTDM_SR_TXRDY_BMSK)) {
		udelay(1);
		touch_nmi_watchdog();
	}
#else
	/*
	 * Dummy read to add 1 AHB clock delay to fix UART hardware bug.
	 * Bug: Delay required on TX-transfer-init. after writing to
	 * NO_CHARS_FOR_TX register.
	 */
	msm_hsl_read(port, regmap[vid][UARTDM_SR]);
#endif
	msm_hsl_write(port, ch, regmap[vid][UARTDM_TF]);
	D("%s ():port->line %d, ir\n", __func__, port->line);
}
示例#17
0
static void msm_hsl_console_putchar(struct uart_port *port, int ch)
{
	unsigned int vid = UART_TO_MSM(port)->ver_id;

	wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
	msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);

	while (!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
				UARTDM_SR_TXRDY_BMSK)) {
		udelay(1);
		touch_nmi_watchdog();
	}

	msm_hsl_write(port, ch, regmap[vid][UARTDM_TF]);
	D("%s ():port->line %d, ir\n", __func__, port->line);
}
示例#18
0
static int msm_hsl_loopback_enable_get(void *data, u64 *val)
{
	struct msm_hsl_port *msm_hsl_port = data;
	struct uart_port *port = &(msm_hsl_port->uart);
	unsigned long flags;
	int ret = 0;

	ret = clk_set_rate(msm_hsl_port->clk, 7372800);
	if (!ret)
		clk_en(port, 1);
	else {
		pr_err("%s(): Error setting clk rate\n", __func__);
		return -EINVAL;
	}

	spin_lock_irqsave(&port->lock, flags);
	ret = msm_hsl_read(port, UARTDM_MR2_ADDR);
	spin_unlock_irqrestore(&port->lock, flags);
	clk_en(port, 0);

	*val = (ret & UARTDM_MR2_LOOP_MODE_BMSK) ? 1 : 0;
	return 0;
}
示例#19
0
static int msm_hsl_startup(struct uart_port *port)
{
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
	struct platform_device *pdev = to_platform_device(port->dev);
	struct msm_serial_hslite_platform_data *pdata = pdev->dev.platform_data;
	unsigned int data, rfr_level;
	int ret;
	unsigned long flags;

	snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name),
		 "msm_serial_hsl%d", port->line);

	if (!(is_console(port)) || (!port->cons) ||
		(port->cons && (!(port->cons->flags & CON_ENABLED)))) {
		if (msm_serial_hsl_has_gsbi())
			if ((ioread32(msm_hsl_port->mapped_gsbi +
				GSBI_CONTROL_ADDR) & GSBI_PROTOCOL_I2C_UART)
					!= GSBI_PROTOCOL_I2C_UART)
				iowrite32(GSBI_PROTOCOL_I2C_UART,
					msm_hsl_port->mapped_gsbi +
						GSBI_CONTROL_ADDR);

		if (pdata && pdata->config_gpio) {
			ret = gpio_request(pdata->uart_tx_gpio,
							"UART_TX_GPIO");
			if (unlikely(ret)) {
				pr_err("%s: gpio request failed for:%d\n",
						 __func__, pdata->uart_tx_gpio);
				return ret;
			}

			ret = gpio_request(pdata->uart_rx_gpio, "UART_RX_GPIO");
			if (unlikely(ret)) {
				pr_err("%s: gpio request failed for:%d\n",
						__func__, pdata->uart_rx_gpio);
				gpio_free(pdata->uart_tx_gpio);
				return ret;
			}
		}
	}
#ifndef CONFIG_PM_RUNTIME
	msm_hsl_init_clock(port);
#endif
	pm_runtime_get_sync(port->dev);

	if (likely(port->fifosize > 12))
		rfr_level = port->fifosize - 12;
	else
		rfr_level = port->fifosize;

	spin_lock_irqsave(&port->lock, flags);

	/* set automatic RFR level */
	data = msm_hsl_read(port, UARTDM_MR1_ADDR);
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
	data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
	data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
	msm_hsl_write(port, data, UARTDM_MR1_ADDR);


	/* Make sure IPR is not 0 to start with*/
	msm_hsl_write(port, UARTDM_IPR_STALE_LSB_BMSK, UARTDM_IPR_ADDR);
	data = 0;

	if (!(is_console(port)) || (!port->cons) ||
		(port->cons && (!(port->cons->flags & CON_ENABLED)))) {
		msm_hsl_write(port, CR_PROTECTION_EN, UARTDM_CR_ADDR);
		msm_hsl_write(port, UARTDM_MR2_BITS_PER_CHAR_8 | STOP_BIT_ONE,
			      UARTDM_MR2_ADDR);	/* 8N1 */
		msm_hsl_reset(port);
		data = UARTDM_CR_TX_EN_BMSK;
	}

	data |= UARTDM_CR_RX_EN_BMSK;

	msm_hsl_write(port, data, UARTDM_CR_ADDR);	/* enable TX & RX */

	/* turn on RX and CTS interrupts */
	msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK
		| UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK;

	spin_unlock_irqrestore(&port->lock, flags);

	ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
			  msm_hsl_port->name, port);
	if (unlikely(ret)) {
		printk(KERN_ERR "%s: failed to request_irq\n", __func__);
		return ret;
	}

	spin_lock_irqsave(&port->lock, flags);
	msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR);
	msm_hsl_write(port, 6500, UARTDM_DMRX_ADDR);
	msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR_ADDR);
	msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR);
	spin_unlock_irqrestore(&port->lock, flags);

	return 0;
}
示例#20
0
static void handle_rx(struct uart_port *port, unsigned int misr)
{
	struct tty_struct *tty = port->state->port.tty;
	unsigned int vid;
	unsigned int sr;
	int count = 0;
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);

	vid = msm_hsl_port->ver_id;
	if ((msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
				UARTDM_SR_OVERRUN_BMSK)) {
		port->icount.overrun++;
		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		msm_hsl_write(port, RESET_ERROR_STATUS,
			regmap[vid][UARTDM_CR]);
	}

	if (misr & UARTDM_ISR_RXSTALE_BMSK) {
		count = msm_hsl_read(port,
			regmap[vid][UARTDM_RX_TOTAL_SNAP]) -
			msm_hsl_port->old_snap_state;
		msm_hsl_port->old_snap_state = 0;
	} else {
		count = 4 * (msm_hsl_read(port, regmap[vid][UARTDM_RFWR]));
		msm_hsl_port->old_snap_state += count;
	}

	
	while (count > 0) {
		unsigned int c;
		char flag = TTY_NORMAL;

		sr = msm_hsl_read(port, regmap[vid][UARTDM_SR]);
		if ((sr & UARTDM_SR_RXRDY_BMSK) == 0) {
			msm_hsl_port->old_snap_state -= count;
			break;
		}
		c = msm_hsl_read(port, regmap[vid][UARTDM_RF]);
		if (sr & UARTDM_SR_RX_BREAK_BMSK) {
			port->icount.brk++;
			if (uart_handle_break(port))
				continue;
		} else if (sr & UARTDM_SR_PAR_FRAME_BMSK) {
			port->icount.frame++;
		} else {
			port->icount.rx++;
		}

		
		sr &= port->read_status_mask;
		if (sr & UARTDM_SR_RX_BREAK_BMSK)
			flag = TTY_BREAK;
		else if (sr & UARTDM_SR_PAR_FRAME_BMSK)
			flag = TTY_FRAME;

		
		
		tty_insert_flip_string(tty, (char *) &c,
				       (count > 4) ? 4 : count);
		count -= 4;
	}

	tty_flip_buffer_push(tty);
}
示例#21
0
static void handle_tx(struct uart_port *port)
{
	struct circ_buf *xmit = &port->state->xmit;
	int sent_tx;
	int tx_count;
	int x;
	unsigned int tf_pointer = 0;

	tx_count = uart_circ_chars_pending(xmit);

	if (tx_count > (UART_XMIT_SIZE - xmit->tail))
		tx_count = UART_XMIT_SIZE - xmit->tail;
	if (tx_count >= port->fifosize)
		tx_count = port->fifosize;

	/* Handle x_char */
	if (port->x_char) {
		wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
		msm_hsl_write(port, tx_count + 1, UARTDM_NCF_TX_ADDR);
		msm_hsl_write(port, port->x_char, UARTDM_TF_ADDR);
		port->icount.tx++;
		port->x_char = 0;
	} else if (tx_count) {
		wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
		msm_hsl_write(port, tx_count, UARTDM_NCF_TX_ADDR);
	}
	if (!tx_count) {
		msm_hsl_stop_tx(port);
		return;
	}

#ifdef FELICA_DEBUG
    if (port->line == 3) pr_info("%s: count=%d\n", __func__, tx_count);
#endif
	while (tf_pointer < tx_count)  {
		if (unlikely(!(msm_hsl_read(port, UARTDM_SR_ADDR) &
			       UARTDM_SR_TXRDY_BMSK)))
			continue;
		switch (tx_count - tf_pointer) {
		case 1: {
			x = xmit->buf[xmit->tail];
			port->icount.tx++;
			break;
		}
		case 2: {
			x = xmit->buf[xmit->tail]
				| xmit->buf[xmit->tail+1] << 8;
			port->icount.tx += 2;
			break;
		}
		case 3: {
			x = xmit->buf[xmit->tail]
				| xmit->buf[xmit->tail+1] << 8
				| xmit->buf[xmit->tail + 2] << 16;
			port->icount.tx += 3;
			break;
		}
		default: {
			x = *((int *)&(xmit->buf[xmit->tail]));
			port->icount.tx += 4;
			break;
		}
		}
#ifdef FELICA_DEBUG
        if (port->line == 3) pr_info("%s: 0x%08X\n", __func__, x);
#endif
		msm_hsl_write(port, x, UARTDM_TF_ADDR);
		xmit->tail = ((tx_count - tf_pointer < 4) ?
			      (tx_count - tf_pointer + xmit->tail) :
			      (xmit->tail + 4)) & (UART_XMIT_SIZE - 1);
		tf_pointer += 4;
		sent_tx = 1;
	}

	if (uart_circ_empty(xmit))
		msm_hsl_stop_tx(port);

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

}
示例#22
0
static void handle_rx(struct uart_port *port, unsigned int misr)
{
	struct tty_struct *tty = port->state->port.tty;
	unsigned int sr;
	int count = 0;
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);

#ifdef FELICA_DEBUG 
    if (port->line == 3) pr_info(">>> %s\n", __func__);
#endif
	/*
	 * Handle overrun. My understanding of the hardware is that overrun
	 * is not tied to the RX buffer, so we handle the case out of band.
	 */
	if ((msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_OVERRUN_BMSK)) {
#ifdef FELICA_DEBUG 
        if (port->line == 3) pr_info("%s: UARTDM_SR_OVERRUN_BMSK\n", __func__);
#endif
		port->icount.overrun++;
		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR_ADDR);
	}

	if (misr & UARTDM_ISR_RXSTALE_BMSK) {
#ifdef FELICA_DEBUG 
        if (port->line == 3) {
            pr_info("%s: UARTDM_ISR_RXSTALE_BMSK\n", __func__);
            pr_info("%s: rx_total_snap = %u\n", __func__, msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP_ADDR));
            pr_info("%s: old_snap_state = %u\n", __func__, msm_hsl_port->old_snap_state);
        }
#endif
		count = msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP_ADDR) -
			msm_hsl_port->old_snap_state;
		msm_hsl_port->old_snap_state = 0;
	} else {
#ifdef FELICA_DEBUG 
        if (port->line == 3) {
            pr_info("%s: else...\n", __func__);
            pr_info("%s: rfwr = %u\n", __func__, msm_hsl_read(port, UARTDM_RFWR_ADDR));
            pr_info("%s: old_snap_state = %u\n", __func__, msm_hsl_port->old_snap_state);
        }
#endif
		count = 4 * (msm_hsl_read(port, UARTDM_RFWR_ADDR));
		msm_hsl_port->old_snap_state += count;
#ifdef FELICA_DEBUG 
        if (port->line == 3) {
            pr_info("%s: old_snap_state = %u\n", __func__, msm_hsl_port->old_snap_state);
        }
#endif
	}

#ifdef FELICA_DEBUG 
    if (port->line == 3) pr_info("%s: count=%d\n", __func__, count);
#endif
	/* and now the main RX loop */
	while (count > 0) {
		unsigned int c;
		char flag = TTY_NORMAL;

		sr = msm_hsl_read(port, UARTDM_SR_ADDR);
		if ((sr &
		     UARTDM_SR_RXRDY_BMSK) == 0) {
#ifdef FELICA_DEBUG 
            if (port->line == 3) {
                pr_info("%s: UARTDM_SR_RXRDY_BMSK\n", __func__);
                pr_info("%s: old_snap_state = %u, count = %d\n", __func__,
                        msm_hsl_port->old_snap_state, count);
            }
#endif

#ifdef CONFIG_LGE_FELICA
			if (msm_hsl_port->old_snap_state < count)
                msm_hsl_port->old_snap_state = 0;
            else
#endif
			msm_hsl_port->old_snap_state -= count;
			break;
		}
		c = msm_hsl_read(port, UARTDM_RF_ADDR);
#ifdef FELICA_DEBUG 
        if (port->line == 3) pr_info("%s: [%d] 0x%08X\n", __func__, (count > 4) ? 4 : count, c);
#endif
		if (sr & UARTDM_SR_RX_BREAK_BMSK) {
#ifdef FELICA_DEBUG 
            if (port->line == 3) pr_info("%s: UARTDM_SR_RX_BREAK_BMSK\n", __func__);
#endif
			port->icount.brk++;
			if (uart_handle_break(port))
            {
#ifdef FELICA_DEBUG
            if (port->line == 3) pr_info("%s: uart_handle_break\n", __func__);
#endif
				continue;
            }
		} else if (sr & UARTDM_SR_PAR_FRAME_BMSK) {
#ifdef FELICA_DEBUG
            if (port->line == 3) pr_info("%s: UARTDM_SR_PAR_FRAME_BMSK\n", __func__);
#endif
			port->icount.frame++;
		} else {
#ifdef FELICA_DEBUG
        if (port->line == 3) pr_info("%s: RX\n", __func__);
#endif
			port->icount.rx++;
		}

		/* Mask conditions we're ignorning. */
		sr &= port->read_status_mask;
		if (sr & UARTDM_SR_RX_BREAK_BMSK)
			flag = TTY_BREAK;
		else if (sr & UARTDM_SR_PAR_FRAME_BMSK)
			flag = TTY_FRAME;

		/* TODO: handle sysrq */
		/* if (!uart_handle_sysrq_char(port, c)) */
		tty_insert_flip_string(tty, (char *) &c,
				       (count > 4) ? 4 : count);
		count -= 4;
	}

	tty_flip_buffer_push(tty);
#ifdef FELICA_DEBUG
        if (port->line == 3) pr_info("<<< %s\n", __func__);
#endif
}
示例#23
0
static void msm_hsl_set_termios_cir(struct uart_port *port,
				struct ktermios *termios,
				struct ktermios *old)
{
	unsigned long flags;
	unsigned int baud, mr;
	unsigned int vid;

	spin_lock_irqsave(&port->lock, flags);

	
	baud = uart_get_baud_rate(port, termios, old, 300, 460800);

	msm_hsl_set_baud_rate(port, baud);

	vid = UART_TO_MSM(port)->ver_id;
	
	mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
	mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
	if (termios->c_cflag & PARENB) {
		if (termios->c_cflag & PARODD)
			mr |= ODD_PARITY;
		else if (termios->c_cflag & CMSPAR)
			mr |= SPACE_PARITY;
		else
			mr |= EVEN_PARITY;
	}

	
	mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		mr |= FIVE_BPC;
		break;
	case CS6:
		mr |= SIX_BPC;
		break;
	case CS7:
		mr |= SEVEN_BPC;
		break;
	case CS8:
	default:
		mr |= EIGHT_BPC;
		break;
	}

	
	mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
	if (termios->c_cflag & CSTOPB)
		mr |= STOP_BIT_TWO;
	else
		mr |= STOP_BIT_ONE;

	
	msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);

	
	mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
	mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
	if (termios->c_cflag & CRTSCTS) {
		mr |= UARTDM_MR1_CTS_CTL_BMSK;
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
	}
	msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);

	
	port->read_status_mask = 0;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;

	uart_update_timeout(port, termios->c_cflag, baud);

	spin_unlock_irqrestore(&port->lock, flags);

	D("%s: cir MR is 0x%x\n", __func__, mr);
	D("%s: cir baud is %d\n", __func__, baud);
}
static void handle_tx(struct uart_port *port)
{
	struct circ_buf *xmit = &port->state->xmit;
	int sent_tx;
	int tx_count;
	int x;
	unsigned int tf_pointer = 0;
	unsigned int vid;

	vid = UART_TO_MSM(port)->ver_id;
	tx_count = uart_circ_chars_pending(xmit);

	if (tx_count > (UART_XMIT_SIZE - xmit->tail))
		tx_count = UART_XMIT_SIZE - xmit->tail;
	if (tx_count >= port->fifosize)
		tx_count = port->fifosize;

	/* Handle x_char */
	if (port->x_char) {
		wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
		msm_hsl_write(port, tx_count + 1,
			regmap[vid][UARTDM_NCF_TX]);
		msm_hsl_write(port, port->x_char, regmap[vid][UARTDM_TF]);
		port->icount.tx++;
		port->x_char = 0;
	} else if (tx_count) {
		wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK);
		msm_hsl_write(port, tx_count, regmap[vid][UARTDM_NCF_TX]);
	}
	if (!tx_count) {
		msm_hsl_stop_tx_irda(port);
		return;
	}

	while (tf_pointer < tx_count)  {
		if (unlikely(!(msm_hsl_read(port, regmap[vid][UARTDM_SR]) &
			       UARTDM_SR_TXRDY_BMSK)))
			continue;
		switch (tx_count - tf_pointer) {
		case 1: {
			x = xmit->buf[xmit->tail];
			port->icount.tx++;
			break;
		}
		case 2: {
			x = xmit->buf[xmit->tail]
				| xmit->buf[xmit->tail+1] << 8;
			port->icount.tx += 2;
			break;
		}
		case 3: {
			x = xmit->buf[xmit->tail]
				| xmit->buf[xmit->tail+1] << 8
				| xmit->buf[xmit->tail + 2] << 16;
			port->icount.tx += 3;
			break;
		}
		default: {
			x = *((int *)&(xmit->buf[xmit->tail]));
			port->icount.tx += 4;
			break;
		}
		}
		msm_hsl_write(port, x, regmap[vid][UARTDM_TF]);
		xmit->tail = ((tx_count - tf_pointer < 4) ?
			      (tx_count - tf_pointer + xmit->tail) :
			      (xmit->tail + 4)) & (UART_XMIT_SIZE - 1);
		tf_pointer += 4;
		sent_tx = 1;
	}

	if (uart_circ_empty(xmit))
		msm_hsl_stop_tx_irda(port);

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

}
static void msm_hsl_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);
	clk_en(port, 1);

	/* calculate and set baud rate */
	baud = uart_get_baud_rate(port, termios, old, 300, 115200);

	/* Workaround required for UART download feature.
	   set_termios is getting called while opening port and while
	   setting required baud rate using Ioctl. Adding delay allows
	   this feature to work. Reason is still unknown.
	*/
	udelay(1000);

	msm_hsl_set_baud_rate(port, baud);

	/* calculate parity */
	mr = msm_hsl_read(port, UARTDM_MR2_ADDR);
	mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
	if (termios->c_cflag & PARENB) {
		if (termios->c_cflag & PARODD)
			mr |= ODD_PARITY;
		else if (termios->c_cflag & CMSPAR)
			mr |= SPACE_PARITY;
		else
			mr |= EVEN_PARITY;
	}

	/* calculate bits per char */
	mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		mr |= FIVE_BPC;
		break;
	case CS6:
		mr |= SIX_BPC;
		break;
	case CS7:
		mr |= SEVEN_BPC;
		break;
	case CS8:
	default:
		mr |= EIGHT_BPC;
		break;
	}

	/* calculate stop bits */
	mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
	if (termios->c_cflag & CSTOPB)
		mr |= STOP_BIT_TWO;
	else
		mr |= STOP_BIT_ONE;

	/* set parity, bits per char, and stop bit */
	msm_hsl_write(port, mr, UARTDM_MR2_ADDR);

	/* calculate and set hardware flow control */
	mr = msm_hsl_read(port, UARTDM_MR1_ADDR);
	mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
	if (termios->c_cflag & CRTSCTS) {
		mr |= UARTDM_MR1_CTS_CTL_BMSK;
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
	}
	msm_hsl_write(port, mr, UARTDM_MR1_ADDR);

	/* Configure status bits to ignore based on termio flags. */
	port->read_status_mask = 0;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;

	uart_update_timeout(port, termios->c_cflag, baud);

	clk_en(port, 0);
	spin_unlock_irqrestore(&port->lock, flags);
}
static int msm_hsl_startup(struct uart_port *port)
{
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
	unsigned int data, rfr_level;
	int ret;
	unsigned long flags;

	snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name),
		 "msm_serial_hsl%d", port->line);

#ifndef CONFIG_PM_RUNTIME
	msm_hsl_init_clock(port);
#endif
	pm_runtime_get_sync(port->dev);

	if (likely(port->fifosize > 12))
		rfr_level = port->fifosize - 12;
	else
		rfr_level = port->fifosize;

	spin_lock_irqsave(&port->lock, flags);

	/* set automatic RFR level */
	data = msm_hsl_read(port, UARTDM_MR1_ADDR);
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
	data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
	data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
	msm_hsl_write(port, data, UARTDM_MR1_ADDR);


	/* Make sure IPR is not 0 to start with*/
	msm_hsl_write(port, UARTDM_IPR_STALE_LSB_BMSK, UARTDM_IPR_ADDR);
	data = 0;

	if (!(is_console(port)) || (!port->cons) ||
		(port->cons && (!(port->cons->flags & CON_ENABLED)))) {
		msm_hsl_write(port, CR_PROTECTION_EN, UARTDM_CR_ADDR);
		msm_hsl_write(port, UARTDM_MR2_BITS_PER_CHAR_8 | STOP_BIT_ONE,
			      UARTDM_MR2_ADDR);	/* 8N1 */
		msm_hsl_reset(port);
		data = UARTDM_CR_TX_EN_BMSK;
	}

	if(b_terminal_onoff == 0 && console_uart_port && (port == console_uart_port)){
		msm_hsl_write(port, data, UARTDM_CR_ADDR);	/* enable TX */
	}else{
		data |= UARTDM_CR_RX_EN_BMSK;
		msm_hsl_write(port, data, UARTDM_CR_ADDR);	/* enable TX & RX */
	}

	/* turn on RX and CTS interrupts */
	msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK
		| UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK;

	spin_unlock_irqrestore(&port->lock, flags);

	ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
			  msm_hsl_port->name, port);
	if (unlikely(ret)) {
		printk(KERN_ERR "%s: failed to request_irq\n", __func__);
		return ret;
	}

	spin_lock_irqsave(&port->lock, flags);
	msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR);
	msm_hsl_write(port, 6500, UARTDM_DMRX_ADDR);
	msm_hsl_write(port, STALE_EVENT_ENABLE, UARTDM_CR_ADDR);
	msm_hsl_write(port, msm_hsl_port->imr, UARTDM_IMR_ADDR);
	spin_unlock_irqrestore(&port->lock, flags);

	return 0;
}
示例#27
0
static int msm_hsl_startup(struct uart_port *port)
{
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
	struct platform_device *pdev = to_platform_device(port->dev);
	const struct msm_serial_hslite_platform_data *pdata =
					pdev->dev.platform_data;
	unsigned int data, rfr_level;
	int ret;
	unsigned long flags;

	snprintf(msm_hsl_port->name, sizeof(msm_hsl_port->name),
		 "msm_serial_hsl%d", port->line);

	if (!(is_console(port)) || (!port->cons) ||
		(port->cons && (!(port->cons->flags & CON_ENABLED)))) {
		if (msm_serial_hsl_has_gsbi())
			if ((ioread32(msm_hsl_port->mapped_gsbi +
				GSBI_CONTROL_ADDR) & GSBI_PROTOCOL_I2C_UART)
					!= GSBI_PROTOCOL_I2C_UART)
				iowrite32(GSBI_PROTOCOL_I2C_UART,
					msm_hsl_port->mapped_gsbi +
						GSBI_CONTROL_ADDR);

		if (pdata && pdata->config_gpio) {
			ret = gpio_request(pdata->uart_tx_gpio,
							"UART_TX_GPIO");
			if (unlikely(ret)) {
				pr_err("%s: gpio request failed for:%d\n",
						 __func__, pdata->uart_tx_gpio);
				return ret;
			}

			ret = gpio_request(pdata->uart_rx_gpio, "UART_RX_GPIO");
			if (unlikely(ret)) {
				pr_err("%s: gpio request failed for:%d\n",
						__func__, pdata->uart_rx_gpio);
				gpio_free(pdata->uart_tx_gpio);
				return ret;
			}
		}
	}
#ifndef CONFIG_PM_RUNTIME
	msm_hsl_init_clock(port);
#endif
	pm_runtime_get_sync(port->dev);

	if (likely(port->fifosize > 12))
		rfr_level = port->fifosize - 12;
	else
		rfr_level = port->fifosize;

	spin_lock_irqsave(&port->lock, flags);

	/* set automatic RFR level */
	data = msm_hsl_read(port, UARTDM_MR1_ADDR);
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
	data |= UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2);
	data |= UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level;
	msm_hsl_write(port, data, UARTDM_MR1_ADDR);
	spin_unlock_irqrestore(&port->lock, flags);

	ret = request_irq(port->irq, msm_hsl_irq, IRQF_TRIGGER_HIGH,
			  msm_hsl_port->name, port);
	if (unlikely(ret)) {
		printk(KERN_ERR "%s: failed to request_irq\n", __func__);
		return ret;
	}
	return 0;
}
static void msm_hsl_set_termios_irda(struct uart_port *port,
				struct ktermios *termios,
				struct ktermios *old)
{
	unsigned long flags;
	unsigned int baud, mr;
	unsigned int vid;

	spin_lock_irqsave(&port->lock, flags);

	/* calculate and set baud rate */
	baud = uart_get_baud_rate(port, termios, old, 300, 460800);

	msm_hsl_set_baud_rate(port, baud);

	vid = UART_TO_MSM(port)->ver_id;
	/* calculate parity */
	mr = msm_hsl_read(port, regmap[vid][UARTDM_MR2]);
	mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
	if (termios->c_cflag & PARENB) {
		if (termios->c_cflag & PARODD)
			mr |= ODD_PARITY;
		else if (termios->c_cflag & CMSPAR)
			mr |= SPACE_PARITY;
		else
			mr |= EVEN_PARITY;
	}

	/* calculate bits per char */
	mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		mr |= FIVE_BPC;
		break;
	case CS6:
		mr |= SIX_BPC;
		break;
	case CS7:
		mr |= SEVEN_BPC;
		break;
	case CS8:
	default:
		mr |= EIGHT_BPC;
		break;
	}

	/* calculate stop bits */
	mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
	if (termios->c_cflag & CSTOPB)
		mr |= STOP_BIT_TWO;
	else
		mr |= STOP_BIT_ONE;

	/* set parity, bits per char, and stop bit */
	msm_hsl_write(port, mr, regmap[vid][UARTDM_MR2]);

	/* calculate and set hardware flow control */
	mr = msm_hsl_read(port, regmap[vid][UARTDM_MR1]);
	mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
	if (termios->c_cflag & CRTSCTS) {
		mr |= UARTDM_MR1_CTS_CTL_BMSK;
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
	}
	msm_hsl_write(port, mr, regmap[vid][UARTDM_MR1]);

	/* Configure status bits to ignore based on termio flags. */
	port->read_status_mask = 0;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;

	uart_update_timeout(port, termios->c_cflag, baud);

	spin_unlock_irqrestore(&port->lock, flags);

	D("%s: irda MR is 0x%x\n", __func__, mr);
	D("%s: irda baud is %d\n", __func__, baud);
/*
	D("%s: irda parity is %d \n", __func__, (termios->c_cflag & PARENB)!=0?1:0);
	D("%s: irda csize is %d \n", __func__,
					(termios->c_cflag & CSIZE)==CS5 ? 5:
					(termios->c_cflag & CSIZE)==CS6 ? 6:
					(termios->c_cflag & CSIZE)==CS7 ? 7:
					(termios->c_cflag & CSIZE)==CS8 ? 8:(-1));
	D("%s: irda stop is %d \n", __func__, (termios->c_cflag & CSTOPB)!=0?1:0);
	D("%s: irda hw-flow is %d \n", __func__, (termios->c_cflag & CRTSCTS)!=0?1:0);
	D("%s: irda INPCK is %d , BRKINT is %d , PARMRK is %d \n", __func__, (termios->c_iflag & INPCK)!=0?1:0,
										(termios->c_iflag & BRKINT)!=0?1:0,
										(termios->c_iflag & PARMRK)!=0?1:0);
	D("%s: irda xon is %d \n", __func__, (termios->c_iflag & IXON)!=0?1:0);
	D("%s: irda xoff is %d \n", __func__, (termios->c_iflag & IXOFF)!=0?1:0);*/
}
示例#29
0
static void msm_hsl_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);
	clk_en(port, 1);

	/* calculate and set baud rate */
    /* [FELICA_S] [email protected] 20110419 */
    /* change default baudrate for felica */
#ifdef CONFIG_LGE_FELICA
    if (port->line == 3)
    {
        termios->c_cflag |= B460800;

        baud = uart_get_baud_rate(port, termios, old, 300, 460800);
        msm_hsl_set_baud_rate(port, baud);
    }
    else
    {
        baud = uart_get_baud_rate(port, termios, old, 300, 115200);
        msm_hsl_set_baud_rate(port, baud);
    }
#else
	baud = uart_get_baud_rate(port, termios, old, 300, 460800);

	msm_hsl_set_baud_rate(port, baud);
#endif
    /* [FELICA_E] [email protected] 20110419 */

	/* calculate parity */
	mr = msm_hsl_read(port, UARTDM_MR2_ADDR);
	mr &= ~UARTDM_MR2_PARITY_MODE_BMSK;
	if (termios->c_cflag & PARENB) {
		if (termios->c_cflag & PARODD)
			mr |= ODD_PARITY;
		else if (termios->c_cflag & CMSPAR)
			mr |= SPACE_PARITY;
		else
			mr |= EVEN_PARITY;
	}

	/* calculate bits per char */
	mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
	switch (termios->c_cflag & CSIZE) {
	case CS5:
		mr |= FIVE_BPC;
		break;
	case CS6:
		mr |= SIX_BPC;
		break;
	case CS7:
		mr |= SEVEN_BPC;
		break;
	case CS8:
	default:
		mr |= EIGHT_BPC;
		break;
	}

	/* calculate stop bits */
	mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO);
	if (termios->c_cflag & CSTOPB)
		mr |= STOP_BIT_TWO;
	else
		mr |= STOP_BIT_ONE;

	/* set parity, bits per char, and stop bit */
	msm_hsl_write(port, mr, UARTDM_MR2_ADDR);

	/* calculate and set hardware flow control */
	mr = msm_hsl_read(port, UARTDM_MR1_ADDR);
	mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
	if (termios->c_cflag & CRTSCTS) {
		mr |= UARTDM_MR1_CTS_CTL_BMSK;
		mr |= UARTDM_MR1_RX_RDY_CTL_BMSK;
	}
	msm_hsl_write(port, mr, UARTDM_MR1_ADDR);

	/* Configure status bits to ignore based on termio flags. */
	port->read_status_mask = 0;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK;
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK;

	uart_update_timeout(port, termios->c_cflag, baud);

	clk_en(port, 0);
	spin_unlock_irqrestore(&port->lock, flags);
}
static void handle_rx(struct uart_port *port, unsigned int misr)
{
	struct tty_struct *tty = port->state->port.tty;
	unsigned int sr;
	int count = 0;
	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);

	/*
	 * Handle overrun. My understanding of the hardware is that overrun
	 * is not tied to the RX buffer, so we handle the case out of band.
	 */
	if ((msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_OVERRUN_BMSK)) {
		port->icount.overrun++;
		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		msm_hsl_write(port, RESET_ERROR_STATUS, UARTDM_CR_ADDR);
	}

	if (misr & UARTDM_ISR_RXSTALE_BMSK) {
		count = msm_hsl_read(port, UARTDM_RX_TOTAL_SNAP_ADDR) -
			msm_hsl_port->old_snap_state;
		msm_hsl_port->old_snap_state = 0;
	} else {
		count = 4 * (msm_hsl_read(port, UARTDM_RFWR_ADDR));
		msm_hsl_port->old_snap_state += count;
	}

	/* and now the main RX loop */
	while (count > 0) {
		unsigned int c;
		char flag = TTY_NORMAL;

		sr = msm_hsl_read(port, UARTDM_SR_ADDR);
		if ((sr &
		     UARTDM_SR_RXRDY_BMSK) == 0) {
			msm_hsl_port->old_snap_state -= count;
			break;
		}
		c = msm_hsl_read(port, UARTDM_RF_ADDR);
		if (sr & UARTDM_SR_RX_BREAK_BMSK) {
			port->icount.brk++;
			if (uart_handle_break(port))
				continue;
		} else if (sr & UARTDM_SR_PAR_FRAME_BMSK) {
			port->icount.frame++;
		} else {
			port->icount.rx++;
		}

		/* Mask conditions we're ignorning. */
		sr &= port->read_status_mask;
		if (sr & UARTDM_SR_RX_BREAK_BMSK)
			flag = TTY_BREAK;
		else if (sr & UARTDM_SR_PAR_FRAME_BMSK)
			flag = TTY_FRAME;

		/* TODO: handle sysrq */
		/* if (!uart_handle_sysrq_char(port, c)) */
		tty_insert_flip_string(tty, (char *) &c,
				       (count > 4) ? 4 : count);
		count -= 4;
	}

	tty_flip_buffer_push(tty);
}