static int serial_m3110_startup(struct uart_port *port)
{
	struct uart_max3110 *max =
		container_of(port, struct uart_max3110, port);
	u16 config = 0;
	int ret = 0;

	if (port->line != 0) {
		pr_err(PR_FMT "uart port startup failed\n");
		return -1;
	}

	/* Disable all IRQ and config it to 115200, 8n1 */
	config = WC_TAG | WC_FIFO_ENABLE
			| WC_1_STOPBITS
			| WC_8BIT_WORD
			| WC_BAUD_DR2;

	/* as we use thread to handle tx/rx, need set low latency */
	port->state->port.tty->low_latency = 1;

	if (max->irq) {
		max->read_thread = NULL;
		ret = request_irq(max->irq, serial_m3110_irq,
				IRQ_TYPE_EDGE_FALLING, "max3110", max);
		if (ret) {
			max->irq = 0;
			pr_err(PR_FMT "unable to allocate IRQ, polling\n");
		}  else {
			/* Enable RX IRQ only */
			config |= WC_RXA_IRQ_ENABLE;
		}
	}

	if (max->irq == 0) {
		/* If IRQ is disabled, start a read thread for input data */
		max->read_thread =
			kthread_run(max3110_read_thread, max, "max3110_read");
		if (IS_ERR(max->read_thread)) {
			ret = PTR_ERR(max->read_thread);
			max->read_thread = NULL;
			pr_err(PR_FMT "Can't create read thread!\n");
			return ret;
		}
	}

	ret = max3110_out(max, config);
	if (ret) {
		if (max->irq)
			free_irq(max->irq, max);
		if (max->read_thread)
			kthread_stop(max->read_thread);
		max->read_thread = NULL;
		return ret;
	}

	max->cur_conf = config;
	max->opened = true;
	return 0;
}
static int serial_m3110_resume(struct spi_device *spi)
{
	struct uart_max3110 *max = spi_get_drvdata(spi);

	max3110_out(max, max->cur_conf);
	uart_resume_port(&serial_m3110_reg, &max->port);
	enable_irq(max->irq);
	return 0;
}
static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
{
	struct uart_max3110 *max = spi_get_drvdata(spi);

	disable_irq(max->irq);
	uart_suspend_port(&serial_m3110_reg, &max->port);
	max3110_out(max, max->cur_conf | WC_SW_SHDI);
	return 0;
}
static int serial_m3110_suspend(struct device *dev)
{
	struct spi_device *spi = to_spi_device(dev);
	struct uart_max3110 *max = spi_get_drvdata(spi);

	if (max->irq > 0)
		disable_irq(max->irq);
	uart_suspend_port(&serial_m3110_reg, &max->port);
	max3110_out(max, max->cur_conf | WC_SW_SHDI);
	return 0;
}
static int serial_m3110_resume(struct device *dev)
{
	struct spi_device *spi = to_spi_device(dev);
	struct uart_max3110 *max = spi_get_drvdata(spi);

	/* Enable IRQ before max3110 write */
	if (max->irq > 0)
		enable_irq(max->irq);
	max3110_out(max, max->cur_conf);
	uart_resume_port(&serial_m3110_reg, &max->port);
	return 0;
}
Beispiel #6
0
static int serial_m3110_startup(struct uart_port *port)
{
	struct uart_max3110 *max =
		container_of(port, struct uart_max3110, port);
	u16 config = 0;
	int ret = 0;

	if (port->line != 0)
		pr_err(PR_FMT "uart port startup failed\n");

	/* firstly disable all IRQ and config it to 115200, 8n1 */
	config = WC_TAG | WC_FIFO_ENABLE
			| WC_1_STOPBITS
			| WC_8BIT_WORD
			| WC_BAUD_DR2;
	ret = max3110_out(max, config);

	/* as we use thread to handle tx/rx, need set low latency */
	port->state->port.tty->low_latency = 1;

#ifdef CONFIG_MRST_MAX3110_IRQ
	ret = request_irq(max->irq, serial_m3110_irq,
				IRQ_TYPE_EDGE_FALLING, "max3110", max);
	if (ret)
		return ret;

	/* enable RX IRQ only */
	config |= WC_RXA_IRQ_ENABLE;
	max3110_out(max, config);
#else
	/* if IRQ is disabled, start a read thread for input data */
	max->read_thread =
		kthread_run(max3110_read_thread, max, "max3110_read");
#endif

	max->cur_conf = config;
	return 0;
}
static void serial_m3110_shutdown(struct uart_port *port)
{
	struct uart_max3110 *max =
		container_of(port, struct uart_max3110, port);
	u16 config;

	if (max->read_thread) {
		kthread_stop(max->read_thread);
		max->read_thread = NULL;
	}

	/* Disable interrupts from this port */
	config = WC_TAG | WC_SW_SHDI;
	max3110_out(max, config);
}
Beispiel #8
0
static void serial_m3110_shutdown(struct uart_port *port)
{
	struct uart_max3110 *max =
		container_of(port, struct uart_max3110, port);
	u16 config;

	if (max->read_thread) {
		kthread_stop(max->read_thread);
		max->read_thread = NULL;
	}

#ifdef CONFIG_MRST_MAX3110_IRQ
	free_irq(max->irq, max);
#endif

	/* Disable interrupts from this port */
	config = WC_TAG | WC_SW_SHDI;
	max3110_out(max, config);
}
Beispiel #9
0
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;
	}
}