[go: nahoru, domu]

mxs-auart.c revision f4b1f03b826ba22c9835e9e89a1ca03541313e04
1/*
2 * Freescale STMP37XX/STMP378X Application UART driver
3 *
4 * Author: dmitry pervushin <dimka@embeddedalley.com>
5 *
6 * Copyright 2008-2010 Freescale Semiconductor, Inc.
7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8 *
9 * The code contained herein is licensed under the GNU General Public
10 * License. You may obtain a copy of the GNU General Public License
11 * Version 2 or later at the following locations:
12 *
13 * http://www.opensource.org/licenses/gpl-license.html
14 * http://www.gnu.org/copyleft/gpl.html
15 */
16
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/console.h>
21#include <linux/interrupt.h>
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/wait.h>
25#include <linux/tty.h>
26#include <linux/tty_driver.h>
27#include <linux/tty_flip.h>
28#include <linux/serial.h>
29#include <linux/serial_core.h>
30#include <linux/platform_device.h>
31#include <linux/device.h>
32#include <linux/clk.h>
33#include <linux/delay.h>
34#include <linux/io.h>
35#include <linux/pinctrl/consumer.h>
36#include <linux/of_device.h>
37
38#include <asm/cacheflush.h>
39
40#define MXS_AUART_PORTS 5
41
42#define AUART_CTRL0			0x00000000
43#define AUART_CTRL0_SET			0x00000004
44#define AUART_CTRL0_CLR			0x00000008
45#define AUART_CTRL0_TOG			0x0000000c
46#define AUART_CTRL1			0x00000010
47#define AUART_CTRL1_SET			0x00000014
48#define AUART_CTRL1_CLR			0x00000018
49#define AUART_CTRL1_TOG			0x0000001c
50#define AUART_CTRL2			0x00000020
51#define AUART_CTRL2_SET			0x00000024
52#define AUART_CTRL2_CLR			0x00000028
53#define AUART_CTRL2_TOG			0x0000002c
54#define AUART_LINECTRL			0x00000030
55#define AUART_LINECTRL_SET		0x00000034
56#define AUART_LINECTRL_CLR		0x00000038
57#define AUART_LINECTRL_TOG		0x0000003c
58#define AUART_LINECTRL2			0x00000040
59#define AUART_LINECTRL2_SET		0x00000044
60#define AUART_LINECTRL2_CLR		0x00000048
61#define AUART_LINECTRL2_TOG		0x0000004c
62#define AUART_INTR			0x00000050
63#define AUART_INTR_SET			0x00000054
64#define AUART_INTR_CLR			0x00000058
65#define AUART_INTR_TOG			0x0000005c
66#define AUART_DATA			0x00000060
67#define AUART_STAT			0x00000070
68#define AUART_DEBUG			0x00000080
69#define AUART_VERSION			0x00000090
70#define AUART_AUTOBAUD			0x000000a0
71
72#define AUART_CTRL0_SFTRST			(1 << 31)
73#define AUART_CTRL0_CLKGATE			(1 << 30)
74
75#define AUART_CTRL2_CTSEN			(1 << 15)
76#define AUART_CTRL2_RTSEN			(1 << 14)
77#define AUART_CTRL2_RTS				(1 << 11)
78#define AUART_CTRL2_RXE				(1 << 9)
79#define AUART_CTRL2_TXE				(1 << 8)
80#define AUART_CTRL2_UARTEN			(1 << 0)
81
82#define AUART_LINECTRL_BAUD_DIVINT_SHIFT	16
83#define AUART_LINECTRL_BAUD_DIVINT_MASK		0xffff0000
84#define AUART_LINECTRL_BAUD_DIVINT(v)		(((v) & 0xffff) << 16)
85#define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT	8
86#define AUART_LINECTRL_BAUD_DIVFRAC_MASK	0x00003f00
87#define AUART_LINECTRL_BAUD_DIVFRAC(v)		(((v) & 0x3f) << 8)
88#define AUART_LINECTRL_WLEN_MASK		0x00000060
89#define AUART_LINECTRL_WLEN(v)			(((v) & 0x3) << 5)
90#define AUART_LINECTRL_FEN			(1 << 4)
91#define AUART_LINECTRL_STP2			(1 << 3)
92#define AUART_LINECTRL_EPS			(1 << 2)
93#define AUART_LINECTRL_PEN			(1 << 1)
94#define AUART_LINECTRL_BRK			(1 << 0)
95
96#define AUART_INTR_RTIEN			(1 << 22)
97#define AUART_INTR_TXIEN			(1 << 21)
98#define AUART_INTR_RXIEN			(1 << 20)
99#define AUART_INTR_CTSMIEN			(1 << 17)
100#define AUART_INTR_RTIS				(1 << 6)
101#define AUART_INTR_TXIS				(1 << 5)
102#define AUART_INTR_RXIS				(1 << 4)
103#define AUART_INTR_CTSMIS			(1 << 1)
104
105#define AUART_STAT_BUSY				(1 << 29)
106#define AUART_STAT_CTS				(1 << 28)
107#define AUART_STAT_TXFE				(1 << 27)
108#define AUART_STAT_TXFF				(1 << 25)
109#define AUART_STAT_RXFE				(1 << 24)
110#define AUART_STAT_OERR				(1 << 19)
111#define AUART_STAT_BERR				(1 << 18)
112#define AUART_STAT_PERR				(1 << 17)
113#define AUART_STAT_FERR				(1 << 16)
114
115static struct uart_driver auart_driver;
116
117enum mxs_auart_type {
118	IMX23_AUART,
119	IMX28_AUART,
120};
121
122struct mxs_auart_port {
123	struct uart_port port;
124
125	unsigned int flags;
126	unsigned int ctrl;
127	enum mxs_auart_type devtype;
128
129	unsigned int irq;
130
131	struct clk *clk;
132	struct device *dev;
133};
134
135static struct platform_device_id mxs_auart_devtype[] = {
136	{ .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
137	{ .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
138	{ /* sentinel */ }
139};
140MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
141
142static struct of_device_id mxs_auart_dt_ids[] = {
143	{
144		.compatible = "fsl,imx28-auart",
145		.data = &mxs_auart_devtype[IMX28_AUART]
146	}, {
147		.compatible = "fsl,imx23-auart",
148		.data = &mxs_auart_devtype[IMX23_AUART]
149	}, { /* sentinel */ }
150};
151MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
152
153static inline int is_imx28_auart(struct mxs_auart_port *s)
154{
155	return s->devtype == IMX28_AUART;
156}
157
158static void mxs_auart_stop_tx(struct uart_port *u);
159
160#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
161
162static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
163{
164	struct circ_buf *xmit = &s->port.state->xmit;
165
166	while (!(readl(s->port.membase + AUART_STAT) &
167		 AUART_STAT_TXFF)) {
168		if (s->port.x_char) {
169			s->port.icount.tx++;
170			writel(s->port.x_char,
171				     s->port.membase + AUART_DATA);
172			s->port.x_char = 0;
173			continue;
174		}
175		if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
176			s->port.icount.tx++;
177			writel(xmit->buf[xmit->tail],
178				     s->port.membase + AUART_DATA);
179			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
180		} else
181			break;
182	}
183	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
184		uart_write_wakeup(&s->port);
185
186	if (uart_circ_empty(&(s->port.state->xmit)))
187		writel(AUART_INTR_TXIEN,
188			     s->port.membase + AUART_INTR_CLR);
189	else
190		writel(AUART_INTR_TXIEN,
191			     s->port.membase + AUART_INTR_SET);
192
193	if (uart_tx_stopped(&s->port))
194		mxs_auart_stop_tx(&s->port);
195}
196
197static void mxs_auart_rx_char(struct mxs_auart_port *s)
198{
199	int flag;
200	u32 stat;
201	u8 c;
202
203	c = readl(s->port.membase + AUART_DATA);
204	stat = readl(s->port.membase + AUART_STAT);
205
206	flag = TTY_NORMAL;
207	s->port.icount.rx++;
208
209	if (stat & AUART_STAT_BERR) {
210		s->port.icount.brk++;
211		if (uart_handle_break(&s->port))
212			goto out;
213	} else if (stat & AUART_STAT_PERR) {
214		s->port.icount.parity++;
215	} else if (stat & AUART_STAT_FERR) {
216		s->port.icount.frame++;
217	}
218
219	/*
220	 * Mask off conditions which should be ingored.
221	 */
222	stat &= s->port.read_status_mask;
223
224	if (stat & AUART_STAT_BERR) {
225		flag = TTY_BREAK;
226	} else if (stat & AUART_STAT_PERR)
227		flag = TTY_PARITY;
228	else if (stat & AUART_STAT_FERR)
229		flag = TTY_FRAME;
230
231	if (stat & AUART_STAT_OERR)
232		s->port.icount.overrun++;
233
234	if (uart_handle_sysrq_char(&s->port, c))
235		goto out;
236
237	uart_insert_char(&s->port, stat, AUART_STAT_OERR, c, flag);
238out:
239	writel(stat, s->port.membase + AUART_STAT);
240}
241
242static void mxs_auart_rx_chars(struct mxs_auart_port *s)
243{
244	struct tty_struct *tty = s->port.state->port.tty;
245	u32 stat = 0;
246
247	for (;;) {
248		stat = readl(s->port.membase + AUART_STAT);
249		if (stat & AUART_STAT_RXFE)
250			break;
251		mxs_auart_rx_char(s);
252	}
253
254	writel(stat, s->port.membase + AUART_STAT);
255	tty_flip_buffer_push(tty);
256}
257
258static int mxs_auart_request_port(struct uart_port *u)
259{
260	return 0;
261}
262
263static int mxs_auart_verify_port(struct uart_port *u,
264				    struct serial_struct *ser)
265{
266	if (u->type != PORT_UNKNOWN && u->type != PORT_IMX)
267		return -EINVAL;
268	return 0;
269}
270
271static void mxs_auart_config_port(struct uart_port *u, int flags)
272{
273}
274
275static const char *mxs_auart_type(struct uart_port *u)
276{
277	struct mxs_auart_port *s = to_auart_port(u);
278
279	return dev_name(s->dev);
280}
281
282static void mxs_auart_release_port(struct uart_port *u)
283{
284}
285
286static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
287{
288	struct mxs_auart_port *s = to_auart_port(u);
289
290	u32 ctrl = readl(u->membase + AUART_CTRL2);
291
292	ctrl &= ~AUART_CTRL2_RTSEN;
293	if (mctrl & TIOCM_RTS) {
294		if (tty_port_cts_enabled(&u->state->port))
295			ctrl |= AUART_CTRL2_RTSEN;
296	}
297
298	s->ctrl = mctrl;
299	writel(ctrl, u->membase + AUART_CTRL2);
300}
301
302static u32 mxs_auart_get_mctrl(struct uart_port *u)
303{
304	struct mxs_auart_port *s = to_auart_port(u);
305	u32 stat = readl(u->membase + AUART_STAT);
306	int ctrl2 = readl(u->membase + AUART_CTRL2);
307	u32 mctrl = s->ctrl;
308
309	mctrl &= ~TIOCM_CTS;
310	if (stat & AUART_STAT_CTS)
311		mctrl |= TIOCM_CTS;
312
313	if (ctrl2 & AUART_CTRL2_RTS)
314		mctrl |= TIOCM_RTS;
315
316	return mctrl;
317}
318
319static void mxs_auart_settermios(struct uart_port *u,
320				 struct ktermios *termios,
321				 struct ktermios *old)
322{
323	u32 bm, ctrl, ctrl2, div;
324	unsigned int cflag, baud;
325
326	cflag = termios->c_cflag;
327
328	ctrl = AUART_LINECTRL_FEN;
329	ctrl2 = readl(u->membase + AUART_CTRL2);
330
331	/* byte size */
332	switch (cflag & CSIZE) {
333	case CS5:
334		bm = 0;
335		break;
336	case CS6:
337		bm = 1;
338		break;
339	case CS7:
340		bm = 2;
341		break;
342	case CS8:
343		bm = 3;
344		break;
345	default:
346		return;
347	}
348
349	ctrl |= AUART_LINECTRL_WLEN(bm);
350
351	/* parity */
352	if (cflag & PARENB) {
353		ctrl |= AUART_LINECTRL_PEN;
354		if ((cflag & PARODD) == 0)
355			ctrl |= AUART_LINECTRL_EPS;
356	}
357
358	u->read_status_mask = 0;
359
360	if (termios->c_iflag & INPCK)
361		u->read_status_mask |= AUART_STAT_PERR;
362	if (termios->c_iflag & (BRKINT | PARMRK))
363		u->read_status_mask |= AUART_STAT_BERR;
364
365	/*
366	 * Characters to ignore
367	 */
368	u->ignore_status_mask = 0;
369	if (termios->c_iflag & IGNPAR)
370		u->ignore_status_mask |= AUART_STAT_PERR;
371	if (termios->c_iflag & IGNBRK) {
372		u->ignore_status_mask |= AUART_STAT_BERR;
373		/*
374		 * If we're ignoring parity and break indicators,
375		 * ignore overruns too (for real raw support).
376		 */
377		if (termios->c_iflag & IGNPAR)
378			u->ignore_status_mask |= AUART_STAT_OERR;
379	}
380
381	/*
382	 * ignore all characters if CREAD is not set
383	 */
384	if (cflag & CREAD)
385		ctrl2 |= AUART_CTRL2_RXE;
386	else
387		ctrl2 &= ~AUART_CTRL2_RXE;
388
389	/* figure out the stop bits requested */
390	if (cflag & CSTOPB)
391		ctrl |= AUART_LINECTRL_STP2;
392
393	/* figure out the hardware flow control settings */
394	if (cflag & CRTSCTS)
395		ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN;
396	else
397		ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN);
398
399	/* set baud rate */
400	baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
401	div = u->uartclk * 32 / baud;
402	ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
403	ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
404
405	writel(ctrl, u->membase + AUART_LINECTRL);
406	writel(ctrl2, u->membase + AUART_CTRL2);
407
408	uart_update_timeout(u, termios->c_cflag, baud);
409}
410
411static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
412{
413	u32 istatus, istat;
414	struct mxs_auart_port *s = context;
415	u32 stat = readl(s->port.membase + AUART_STAT);
416
417	istatus = istat = readl(s->port.membase + AUART_INTR);
418
419	if (istat & AUART_INTR_CTSMIS) {
420		uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS);
421		writel(AUART_INTR_CTSMIS,
422				s->port.membase + AUART_INTR_CLR);
423		istat &= ~AUART_INTR_CTSMIS;
424	}
425
426	if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) {
427		mxs_auart_rx_chars(s);
428		istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS);
429	}
430
431	if (istat & AUART_INTR_TXIS) {
432		mxs_auart_tx_chars(s);
433		istat &= ~AUART_INTR_TXIS;
434	}
435
436	writel(istatus & (AUART_INTR_RTIS
437		| AUART_INTR_TXIS
438		| AUART_INTR_RXIS
439		| AUART_INTR_CTSMIS),
440			s->port.membase + AUART_INTR_CLR);
441
442	return IRQ_HANDLED;
443}
444
445static void mxs_auart_reset(struct uart_port *u)
446{
447	int i;
448	unsigned int reg;
449
450	writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_CLR);
451
452	for (i = 0; i < 10000; i++) {
453		reg = readl(u->membase + AUART_CTRL0);
454		if (!(reg & AUART_CTRL0_SFTRST))
455			break;
456		udelay(3);
457	}
458	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
459}
460
461static int mxs_auart_startup(struct uart_port *u)
462{
463	struct mxs_auart_port *s = to_auart_port(u);
464
465	clk_prepare_enable(s->clk);
466
467	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
468
469	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
470
471	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
472			u->membase + AUART_INTR);
473
474	/*
475	 * Enable fifo so all four bytes of a DMA word are written to
476	 * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
477	 */
478	writel(AUART_LINECTRL_FEN, u->membase + AUART_LINECTRL_SET);
479
480	return 0;
481}
482
483static void mxs_auart_shutdown(struct uart_port *u)
484{
485	struct mxs_auart_port *s = to_auart_port(u);
486
487	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
488
489	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
490			u->membase + AUART_INTR_CLR);
491
492	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
493
494	clk_disable_unprepare(s->clk);
495}
496
497static unsigned int mxs_auart_tx_empty(struct uart_port *u)
498{
499	if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE)
500		return TIOCSER_TEMT;
501	else
502		return 0;
503}
504
505static void mxs_auart_start_tx(struct uart_port *u)
506{
507	struct mxs_auart_port *s = to_auart_port(u);
508
509	/* enable transmitter */
510	writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_SET);
511
512	mxs_auart_tx_chars(s);
513}
514
515static void mxs_auart_stop_tx(struct uart_port *u)
516{
517	writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_CLR);
518}
519
520static void mxs_auart_stop_rx(struct uart_port *u)
521{
522	writel(AUART_CTRL2_RXE, u->membase + AUART_CTRL2_CLR);
523}
524
525static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
526{
527	if (ctl)
528		writel(AUART_LINECTRL_BRK,
529			     u->membase + AUART_LINECTRL_SET);
530	else
531		writel(AUART_LINECTRL_BRK,
532			     u->membase + AUART_LINECTRL_CLR);
533}
534
535static void mxs_auart_enable_ms(struct uart_port *port)
536{
537	/* just empty */
538}
539
540static struct uart_ops mxs_auart_ops = {
541	.tx_empty       = mxs_auart_tx_empty,
542	.start_tx       = mxs_auart_start_tx,
543	.stop_tx	= mxs_auart_stop_tx,
544	.stop_rx	= mxs_auart_stop_rx,
545	.enable_ms      = mxs_auart_enable_ms,
546	.break_ctl      = mxs_auart_break_ctl,
547	.set_mctrl	= mxs_auart_set_mctrl,
548	.get_mctrl      = mxs_auart_get_mctrl,
549	.startup	= mxs_auart_startup,
550	.shutdown       = mxs_auart_shutdown,
551	.set_termios    = mxs_auart_settermios,
552	.type	   	= mxs_auart_type,
553	.release_port   = mxs_auart_release_port,
554	.request_port   = mxs_auart_request_port,
555	.config_port    = mxs_auart_config_port,
556	.verify_port    = mxs_auart_verify_port,
557};
558
559static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
560
561#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
562static void mxs_auart_console_putchar(struct uart_port *port, int ch)
563{
564	unsigned int to = 1000;
565
566	while (readl(port->membase + AUART_STAT) & AUART_STAT_TXFF) {
567		if (!to--)
568			break;
569		udelay(1);
570	}
571
572	writel(ch, port->membase + AUART_DATA);
573}
574
575static void
576auart_console_write(struct console *co, const char *str, unsigned int count)
577{
578	struct mxs_auart_port *s;
579	struct uart_port *port;
580	unsigned int old_ctrl0, old_ctrl2;
581	unsigned int to = 1000;
582
583	if (co->index >	MXS_AUART_PORTS || co->index < 0)
584		return;
585
586	s = auart_port[co->index];
587	port = &s->port;
588
589	clk_enable(s->clk);
590
591	/* First save the CR then disable the interrupts */
592	old_ctrl2 = readl(port->membase + AUART_CTRL2);
593	old_ctrl0 = readl(port->membase + AUART_CTRL0);
594
595	writel(AUART_CTRL0_CLKGATE,
596		     port->membase + AUART_CTRL0_CLR);
597	writel(AUART_CTRL2_UARTEN | AUART_CTRL2_TXE,
598		     port->membase + AUART_CTRL2_SET);
599
600	uart_console_write(port, str, count, mxs_auart_console_putchar);
601
602	/*
603	 * Finally, wait for transmitter to become empty
604	 * and restore the TCR
605	 */
606	while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) {
607		if (!to--)
608			break;
609		udelay(1);
610	}
611
612	writel(old_ctrl0, port->membase + AUART_CTRL0);
613	writel(old_ctrl2, port->membase + AUART_CTRL2);
614
615	clk_disable(s->clk);
616}
617
618static void __init
619auart_console_get_options(struct uart_port *port, int *baud,
620			  int *parity, int *bits)
621{
622	unsigned int lcr_h, quot;
623
624	if (!(readl(port->membase + AUART_CTRL2) & AUART_CTRL2_UARTEN))
625		return;
626
627	lcr_h = readl(port->membase + AUART_LINECTRL);
628
629	*parity = 'n';
630	if (lcr_h & AUART_LINECTRL_PEN) {
631		if (lcr_h & AUART_LINECTRL_EPS)
632			*parity = 'e';
633		else
634			*parity = 'o';
635	}
636
637	if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(2))
638		*bits = 7;
639	else
640		*bits = 8;
641
642	quot = ((readl(port->membase + AUART_LINECTRL)
643			& AUART_LINECTRL_BAUD_DIVINT_MASK))
644			    >> (AUART_LINECTRL_BAUD_DIVINT_SHIFT - 6);
645	quot |= ((readl(port->membase + AUART_LINECTRL)
646			& AUART_LINECTRL_BAUD_DIVFRAC_MASK))
647				>> AUART_LINECTRL_BAUD_DIVFRAC_SHIFT;
648	if (quot == 0)
649		quot = 1;
650
651	*baud = (port->uartclk << 2) / quot;
652}
653
654static int __init
655auart_console_setup(struct console *co, char *options)
656{
657	struct mxs_auart_port *s;
658	int baud = 9600;
659	int bits = 8;
660	int parity = 'n';
661	int flow = 'n';
662	int ret;
663
664	/*
665	 * Check whether an invalid uart number has been specified, and
666	 * if so, search for the first available port that does have
667	 * console support.
668	 */
669	if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port))
670		co->index = 0;
671	s = auart_port[co->index];
672	if (!s)
673		return -ENODEV;
674
675	clk_prepare_enable(s->clk);
676
677	if (options)
678		uart_parse_options(options, &baud, &parity, &bits, &flow);
679	else
680		auart_console_get_options(&s->port, &baud, &parity, &bits);
681
682	ret = uart_set_options(&s->port, co, baud, parity, bits, flow);
683
684	clk_disable_unprepare(s->clk);
685
686	return ret;
687}
688
689static struct console auart_console = {
690	.name		= "ttyAPP",
691	.write		= auart_console_write,
692	.device		= uart_console_device,
693	.setup		= auart_console_setup,
694	.flags		= CON_PRINTBUFFER,
695	.index		= -1,
696	.data		= &auart_driver,
697};
698#endif
699
700static struct uart_driver auart_driver = {
701	.owner		= THIS_MODULE,
702	.driver_name	= "ttyAPP",
703	.dev_name	= "ttyAPP",
704	.major		= 0,
705	.minor		= 0,
706	.nr		= MXS_AUART_PORTS,
707#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
708	.cons =		&auart_console,
709#endif
710};
711
712/*
713 * This function returns 1 if pdev isn't a device instatiated by dt, 0 if it
714 * could successfully get all information from dt or a negative errno.
715 */
716static int serial_mxs_probe_dt(struct mxs_auart_port *s,
717		struct platform_device *pdev)
718{
719	struct device_node *np = pdev->dev.of_node;
720	int ret;
721
722	if (!np)
723		/* no device tree device */
724		return 1;
725
726	ret = of_alias_get_id(np, "serial");
727	if (ret < 0) {
728		dev_err(&pdev->dev, "failed to get alias id: %d\n", ret);
729		return ret;
730	}
731	s->port.line = ret;
732
733	return 0;
734}
735
736static int __devinit mxs_auart_probe(struct platform_device *pdev)
737{
738	const struct of_device_id *of_id =
739			of_match_device(mxs_auart_dt_ids, &pdev->dev);
740	struct mxs_auart_port *s;
741	u32 version;
742	int ret = 0;
743	struct resource *r;
744	struct pinctrl *pinctrl;
745
746	s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
747	if (!s) {
748		ret = -ENOMEM;
749		goto out;
750	}
751
752	ret = serial_mxs_probe_dt(s, pdev);
753	if (ret > 0)
754		s->port.line = pdev->id < 0 ? 0 : pdev->id;
755	else if (ret < 0)
756		goto out_free;
757
758	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
759	if (IS_ERR(pinctrl)) {
760		ret = PTR_ERR(pinctrl);
761		goto out_free;
762	}
763
764	if (of_id) {
765		pdev->id_entry = of_id->data;
766		s->devtype = pdev->id_entry->driver_data;
767	}
768
769	s->clk = clk_get(&pdev->dev, NULL);
770	if (IS_ERR(s->clk)) {
771		ret = PTR_ERR(s->clk);
772		goto out_free;
773	}
774
775	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
776	if (!r) {
777		ret = -ENXIO;
778		goto out_free_clk;
779	}
780
781	s->port.mapbase = r->start;
782	s->port.membase = ioremap(r->start, resource_size(r));
783	s->port.ops = &mxs_auart_ops;
784	s->port.iotype = UPIO_MEM;
785	s->port.fifosize = 16;
786	s->port.uartclk = clk_get_rate(s->clk);
787	s->port.type = PORT_IMX;
788	s->port.dev = s->dev = get_device(&pdev->dev);
789
790	s->flags = 0;
791	s->ctrl = 0;
792
793	s->irq = platform_get_irq(pdev, 0);
794	s->port.irq = s->irq;
795	ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s);
796	if (ret)
797		goto out_free_clk;
798
799	platform_set_drvdata(pdev, s);
800
801	auart_port[s->port.line] = s;
802
803	mxs_auart_reset(&s->port);
804
805	ret = uart_add_one_port(&auart_driver, &s->port);
806	if (ret)
807		goto out_free_irq;
808
809	version = readl(s->port.membase + AUART_VERSION);
810	dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
811	       (version >> 24) & 0xff,
812	       (version >> 16) & 0xff, version & 0xffff);
813
814	return 0;
815
816out_free_irq:
817	auart_port[pdev->id] = NULL;
818	free_irq(s->irq, s);
819out_free_clk:
820	put_device(s->dev);
821	clk_put(s->clk);
822out_free:
823	kfree(s);
824out:
825	return ret;
826}
827
828static int __devexit mxs_auart_remove(struct platform_device *pdev)
829{
830	struct mxs_auart_port *s = platform_get_drvdata(pdev);
831
832	uart_remove_one_port(&auart_driver, &s->port);
833
834	auart_port[pdev->id] = NULL;
835
836	put_device(s->dev);
837	clk_put(s->clk);
838	free_irq(s->irq, s);
839	kfree(s);
840
841	return 0;
842}
843
844static struct platform_driver mxs_auart_driver = {
845	.probe = mxs_auart_probe,
846	.remove = __devexit_p(mxs_auart_remove),
847	.driver = {
848		.name = "mxs-auart",
849		.owner = THIS_MODULE,
850		.of_match_table = mxs_auart_dt_ids,
851	},
852};
853
854static int __init mxs_auart_init(void)
855{
856	int r;
857
858	r = uart_register_driver(&auart_driver);
859	if (r)
860		goto out;
861
862	r = platform_driver_register(&mxs_auart_driver);
863	if (r)
864		goto out_err;
865
866	return 0;
867out_err:
868	uart_unregister_driver(&auart_driver);
869out:
870	return r;
871}
872
873static void __exit mxs_auart_exit(void)
874{
875	platform_driver_unregister(&mxs_auart_driver);
876	uart_unregister_driver(&auart_driver);
877}
878
879module_init(mxs_auart_init);
880module_exit(mxs_auart_exit);
881MODULE_LICENSE("GPL");
882MODULE_DESCRIPTION("Freescale MXS application uart driver");
883MODULE_ALIAS("platform:mxs-auart");
884