brintos

brintos / linux-shallow public Read only

0
0
Text · 21.8 KiB · e972df4 Raw
919 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Freescale LINFlexD UART serial port driver4 *5 * Copyright 2012-2016 Freescale Semiconductor, Inc.6 * Copyright 2017-2019 NXP7 */8 9#include <linux/console.h>10#include <linux/io.h>11#include <linux/irq.h>12#include <linux/module.h>13#include <linux/of.h>14#include <linux/platform_device.h>15#include <linux/serial_core.h>16#include <linux/slab.h>17#include <linux/tty_flip.h>18#include <linux/delay.h>19 20/* All registers are 32-bit width */21 22#define LINCR1	0x0000	/* LIN control register				*/23#define LINIER	0x0004	/* LIN interrupt enable register		*/24#define LINSR	0x0008	/* LIN status register				*/25#define LINESR	0x000C	/* LIN error status register			*/26#define UARTCR	0x0010	/* UART mode control register			*/27#define UARTSR	0x0014	/* UART mode status register			*/28#define LINTCSR	0x0018	/* LIN timeout control status register		*/29#define LINOCR	0x001C	/* LIN output compare register			*/30#define LINTOCR	0x0020	/* LIN timeout control register			*/31#define LINFBRR	0x0024	/* LIN fractional baud rate register		*/32#define LINIBRR	0x0028	/* LIN integer baud rate register		*/33#define LINCFR	0x002C	/* LIN checksum field register			*/34#define LINCR2	0x0030	/* LIN control register 2			*/35#define BIDR	0x0034	/* Buffer identifier register			*/36#define BDRL	0x0038	/* Buffer data register least significant	*/37#define BDRM	0x003C	/* Buffer data register most significant	*/38#define IFER	0x0040	/* Identifier filter enable register		*/39#define IFMI	0x0044	/* Identifier filter match index		*/40#define IFMR	0x0048	/* Identifier filter mode register		*/41#define GCR	0x004C	/* Global control register			*/42#define UARTPTO	0x0050	/* UART preset timeout register			*/43#define UARTCTO	0x0054	/* UART current timeout register		*/44 45/*46 * Register field definitions47 */48 49#define LINFLEXD_LINCR1_INIT		BIT(0)50#define LINFLEXD_LINCR1_MME		BIT(4)51#define LINFLEXD_LINCR1_BF		BIT(7)52 53#define LINFLEXD_LINSR_LINS_INITMODE	BIT(12)54#define LINFLEXD_LINSR_LINS_MASK	(0xF << 12)55 56#define LINFLEXD_LINIER_SZIE		BIT(15)57#define LINFLEXD_LINIER_OCIE		BIT(14)58#define LINFLEXD_LINIER_BEIE		BIT(13)59#define LINFLEXD_LINIER_CEIE		BIT(12)60#define LINFLEXD_LINIER_HEIE		BIT(11)61#define LINFLEXD_LINIER_FEIE		BIT(8)62#define LINFLEXD_LINIER_BOIE		BIT(7)63#define LINFLEXD_LINIER_LSIE		BIT(6)64#define LINFLEXD_LINIER_WUIE		BIT(5)65#define LINFLEXD_LINIER_DBFIE		BIT(4)66#define LINFLEXD_LINIER_DBEIETOIE	BIT(3)67#define LINFLEXD_LINIER_DRIE		BIT(2)68#define LINFLEXD_LINIER_DTIE		BIT(1)69#define LINFLEXD_LINIER_HRIE		BIT(0)70 71#define LINFLEXD_UARTCR_OSR_MASK	(0xF << 24)72#define LINFLEXD_UARTCR_OSR(uartcr)	(((uartcr) \73					& LINFLEXD_UARTCR_OSR_MASK) >> 24)74 75#define LINFLEXD_UARTCR_ROSE		BIT(23)76 77#define LINFLEXD_UARTCR_RFBM		BIT(9)78#define LINFLEXD_UARTCR_TFBM		BIT(8)79#define LINFLEXD_UARTCR_WL1		BIT(7)80#define LINFLEXD_UARTCR_PC1		BIT(6)81 82#define LINFLEXD_UARTCR_RXEN		BIT(5)83#define LINFLEXD_UARTCR_TXEN		BIT(4)84#define LINFLEXD_UARTCR_PC0		BIT(3)85 86#define LINFLEXD_UARTCR_PCE		BIT(2)87#define LINFLEXD_UARTCR_WL0		BIT(1)88#define LINFLEXD_UARTCR_UART		BIT(0)89 90#define LINFLEXD_UARTSR_SZF		BIT(15)91#define LINFLEXD_UARTSR_OCF		BIT(14)92#define LINFLEXD_UARTSR_PE3		BIT(13)93#define LINFLEXD_UARTSR_PE2		BIT(12)94#define LINFLEXD_UARTSR_PE1		BIT(11)95#define LINFLEXD_UARTSR_PE0		BIT(10)96#define LINFLEXD_UARTSR_RMB		BIT(9)97#define LINFLEXD_UARTSR_FEF		BIT(8)98#define LINFLEXD_UARTSR_BOF		BIT(7)99#define LINFLEXD_UARTSR_RPS		BIT(6)100#define LINFLEXD_UARTSR_WUF		BIT(5)101#define LINFLEXD_UARTSR_4		BIT(4)102 103#define LINFLEXD_UARTSR_TO		BIT(3)104 105#define LINFLEXD_UARTSR_DRFRFE		BIT(2)106#define LINFLEXD_UARTSR_DTFTFF		BIT(1)107#define LINFLEXD_UARTSR_NF		BIT(0)108#define LINFLEXD_UARTSR_PE		(LINFLEXD_UARTSR_PE0 |\109					 LINFLEXD_UARTSR_PE1 |\110					 LINFLEXD_UARTSR_PE2 |\111					 LINFLEXD_UARTSR_PE3)112 113#define LINFLEX_LDIV_MULTIPLIER		(16)114 115#define DRIVER_NAME	"fsl-linflexuart"116#define DEV_NAME	"ttyLF"117#define UART_NR		4118 119#define EARLYCON_BUFFER_INITIAL_CAP	8120 121#define PREINIT_DELAY			2000 /* us */122 123static const struct of_device_id linflex_dt_ids[] = {124	{125		.compatible = "fsl,s32v234-linflexuart",126	},127	{ /* sentinel */ }128};129MODULE_DEVICE_TABLE(of, linflex_dt_ids);130 131#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE132static struct uart_port *earlycon_port;133static bool linflex_earlycon_same_instance;134static DEFINE_SPINLOCK(init_lock);135static bool during_init;136 137static struct {138	char *content;139	unsigned int len, cap;140} earlycon_buf;141#endif142 143static void linflex_stop_tx(struct uart_port *port)144{145	unsigned long ier;146 147	ier = readl(port->membase + LINIER);148	ier &= ~(LINFLEXD_LINIER_DTIE);149	writel(ier, port->membase + LINIER);150}151 152static void linflex_stop_rx(struct uart_port *port)153{154	unsigned long ier;155 156	ier = readl(port->membase + LINIER);157	writel(ier & ~LINFLEXD_LINIER_DRIE, port->membase + LINIER);158}159 160static void linflex_put_char(struct uart_port *sport, unsigned char c)161{162	unsigned long status;163 164	writeb(c, sport->membase + BDRL);165 166	/* Waiting for data transmission completed. */167	while (((status = readl(sport->membase + UARTSR)) &168				LINFLEXD_UARTSR_DTFTFF) !=169				LINFLEXD_UARTSR_DTFTFF)170		;171 172	writel(status | LINFLEXD_UARTSR_DTFTFF, sport->membase + UARTSR);173}174 175static inline void linflex_transmit_buffer(struct uart_port *sport)176{177	struct tty_port *tport = &sport->state->port;178	unsigned char c;179 180	while (uart_fifo_get(sport, &c)) {181		linflex_put_char(sport, c);182		sport->icount.tx++;183	}184 185	if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)186		uart_write_wakeup(sport);187 188	if (kfifo_is_empty(&tport->xmit_fifo))189		linflex_stop_tx(sport);190}191 192static void linflex_start_tx(struct uart_port *port)193{194	unsigned long ier;195 196	linflex_transmit_buffer(port);197	ier = readl(port->membase + LINIER);198	writel(ier | LINFLEXD_LINIER_DTIE, port->membase + LINIER);199}200 201static irqreturn_t linflex_txint(int irq, void *dev_id)202{203	struct uart_port *sport = dev_id;204	struct tty_port *tport = &sport->state->port;205	unsigned long flags;206 207	uart_port_lock_irqsave(sport, &flags);208 209	if (sport->x_char) {210		linflex_put_char(sport, sport->x_char);211		goto out;212	}213 214	if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(sport)) {215		linflex_stop_tx(sport);216		goto out;217	}218 219	linflex_transmit_buffer(sport);220out:221	uart_port_unlock_irqrestore(sport, flags);222	return IRQ_HANDLED;223}224 225static irqreturn_t linflex_rxint(int irq, void *dev_id)226{227	struct uart_port *sport = dev_id;228	unsigned int flg;229	struct tty_port *port = &sport->state->port;230	unsigned long flags, status;231	unsigned char rx;232	bool brk;233 234	uart_port_lock_irqsave(sport, &flags);235 236	status = readl(sport->membase + UARTSR);237	while (status & LINFLEXD_UARTSR_RMB) {238		rx = readb(sport->membase + BDRM);239		brk = false;240		flg = TTY_NORMAL;241		sport->icount.rx++;242 243		if (status & (LINFLEXD_UARTSR_BOF | LINFLEXD_UARTSR_FEF |244				LINFLEXD_UARTSR_PE)) {245			if (status & LINFLEXD_UARTSR_BOF)246				sport->icount.overrun++;247			if (status & LINFLEXD_UARTSR_FEF) {248				if (!rx) {249					brk = true;250					sport->icount.brk++;251				} else252					sport->icount.frame++;253			}254			if (status & LINFLEXD_UARTSR_PE)255				sport->icount.parity++;256		}257 258		writel(status, sport->membase + UARTSR);259		status = readl(sport->membase + UARTSR);260 261		if (brk) {262			uart_handle_break(sport);263		} else {264			if (uart_handle_sysrq_char(sport, (unsigned char)rx))265				continue;266			tty_insert_flip_char(port, rx, flg);267		}268	}269 270	uart_port_unlock_irqrestore(sport, flags);271 272	tty_flip_buffer_push(port);273 274	return IRQ_HANDLED;275}276 277static irqreturn_t linflex_int(int irq, void *dev_id)278{279	struct uart_port *sport = dev_id;280	unsigned long status;281 282	status = readl(sport->membase + UARTSR);283 284	if (status & LINFLEXD_UARTSR_DRFRFE)285		linflex_rxint(irq, dev_id);286	if (status & LINFLEXD_UARTSR_DTFTFF)287		linflex_txint(irq, dev_id);288 289	return IRQ_HANDLED;290}291 292/* return TIOCSER_TEMT when transmitter is not busy */293static unsigned int linflex_tx_empty(struct uart_port *port)294{295	unsigned long status;296 297	status = readl(port->membase + UARTSR) & LINFLEXD_UARTSR_DTFTFF;298 299	return status ? TIOCSER_TEMT : 0;300}301 302static unsigned int linflex_get_mctrl(struct uart_port *port)303{304	return 0;305}306 307static void linflex_set_mctrl(struct uart_port *port, unsigned int mctrl)308{309}310 311static void linflex_break_ctl(struct uart_port *port, int break_state)312{313}314 315static void linflex_setup_watermark(struct uart_port *sport)316{317	unsigned long cr, ier, cr1;318 319	/* Disable transmission/reception */320	ier = readl(sport->membase + LINIER);321	ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);322	writel(ier, sport->membase + LINIER);323 324	cr = readl(sport->membase + UARTCR);325	cr &= ~(LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN);326	writel(cr, sport->membase + UARTCR);327 328	/* Enter initialization mode by setting INIT bit */329 330	/* set the Linflex in master mode and activate by-pass filter */331	cr1 = LINFLEXD_LINCR1_BF | LINFLEXD_LINCR1_MME332	      | LINFLEXD_LINCR1_INIT;333	writel(cr1, sport->membase + LINCR1);334 335	/* wait for init mode entry */336	while ((readl(sport->membase + LINSR)337		& LINFLEXD_LINSR_LINS_MASK)338		!= LINFLEXD_LINSR_LINS_INITMODE)339		;340 341	/*342	 *	UART = 0x1;		- Linflex working in UART mode343	 *	TXEN = 0x1;		- Enable transmission of data now344	 *	RXEn = 0x1;		- Receiver enabled345	 *	WL0 = 0x1;		- 8 bit data346	 *	PCE = 0x0;		- No parity347	 */348 349	/* set UART bit to allow writing other bits */350	writel(LINFLEXD_UARTCR_UART, sport->membase + UARTCR);351 352	cr = (LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN |353	      LINFLEXD_UARTCR_WL0 | LINFLEXD_UARTCR_UART);354 355	writel(cr, sport->membase + UARTCR);356 357	cr1 &= ~(LINFLEXD_LINCR1_INIT);358 359	writel(cr1, sport->membase + LINCR1);360 361	ier = readl(sport->membase + LINIER);362	ier |= LINFLEXD_LINIER_DRIE;363	ier |= LINFLEXD_LINIER_DTIE;364 365	writel(ier, sport->membase + LINIER);366}367 368static int linflex_startup(struct uart_port *port)369{370	int ret = 0;371	unsigned long flags;372 373	uart_port_lock_irqsave(port, &flags);374 375	linflex_setup_watermark(port);376 377	uart_port_unlock_irqrestore(port, flags);378 379	ret = devm_request_irq(port->dev, port->irq, linflex_int, 0,380			       DRIVER_NAME, port);381 382	return ret;383}384 385static void linflex_shutdown(struct uart_port *port)386{387	unsigned long ier;388	unsigned long flags;389 390	uart_port_lock_irqsave(port, &flags);391 392	/* disable interrupts */393	ier = readl(port->membase + LINIER);394	ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);395	writel(ier, port->membase + LINIER);396 397	uart_port_unlock_irqrestore(port, flags);398 399	devm_free_irq(port->dev, port->irq, port);400}401 402static void403linflex_set_termios(struct uart_port *port, struct ktermios *termios,404		    const struct ktermios *old)405{406	unsigned long flags;407	unsigned long cr, old_cr, cr1;408	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;409 410	cr = readl(port->membase + UARTCR);411	old_cr = cr;412 413	/* Enter initialization mode by setting INIT bit */414	cr1 = readl(port->membase + LINCR1);415	cr1 |= LINFLEXD_LINCR1_INIT;416	writel(cr1, port->membase + LINCR1);417 418	/* wait for init mode entry */419	while ((readl(port->membase + LINSR)420		& LINFLEXD_LINSR_LINS_MASK)421		!= LINFLEXD_LINSR_LINS_INITMODE)422		;423 424	/*425	 * only support CS8 and CS7, and for CS7 must enable PE.426	 * supported mode:427	 *	- (7,e/o,1)428	 *	- (8,n,1)429	 *	- (8,e/o,1)430	 */431	/* enter the UART into configuration mode */432 433	while ((termios->c_cflag & CSIZE) != CS8 &&434	       (termios->c_cflag & CSIZE) != CS7) {435		termios->c_cflag &= ~CSIZE;436		termios->c_cflag |= old_csize;437		old_csize = CS8;438	}439 440	if ((termios->c_cflag & CSIZE) == CS7) {441		/* Word length: WL1WL0:00 */442		cr = old_cr & ~LINFLEXD_UARTCR_WL1 & ~LINFLEXD_UARTCR_WL0;443	}444 445	if ((termios->c_cflag & CSIZE) == CS8) {446		/* Word length: WL1WL0:01 */447		cr = (old_cr | LINFLEXD_UARTCR_WL0) & ~LINFLEXD_UARTCR_WL1;448	}449 450	if (termios->c_cflag & CMSPAR) {451		if ((termios->c_cflag & CSIZE) != CS8) {452			termios->c_cflag &= ~CSIZE;453			termios->c_cflag |= CS8;454		}455		/* has a space/sticky bit */456		cr |= LINFLEXD_UARTCR_WL0;457	}458 459	if (termios->c_cflag & CSTOPB)460		termios->c_cflag &= ~CSTOPB;461 462	/* parity must be enabled when CS7 to match 8-bits format */463	if ((termios->c_cflag & CSIZE) == CS7)464		termios->c_cflag |= PARENB;465 466	if ((termios->c_cflag & PARENB)) {467		cr |= LINFLEXD_UARTCR_PCE;468		if (termios->c_cflag & PARODD)469			cr = (cr | LINFLEXD_UARTCR_PC0) &470			     (~LINFLEXD_UARTCR_PC1);471		else472			cr = cr & (~LINFLEXD_UARTCR_PC1 &473				   ~LINFLEXD_UARTCR_PC0);474	} else {475		cr &= ~LINFLEXD_UARTCR_PCE;476	}477 478	uart_port_lock_irqsave(port, &flags);479 480	port->read_status_mask = 0;481 482	if (termios->c_iflag & INPCK)483		port->read_status_mask |=	(LINFLEXD_UARTSR_FEF |484						 LINFLEXD_UARTSR_PE0 |485						 LINFLEXD_UARTSR_PE1 |486						 LINFLEXD_UARTSR_PE2 |487						 LINFLEXD_UARTSR_PE3);488	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))489		port->read_status_mask |= LINFLEXD_UARTSR_FEF;490 491	/* characters to ignore */492	port->ignore_status_mask = 0;493	if (termios->c_iflag & IGNPAR)494		port->ignore_status_mask |= LINFLEXD_UARTSR_PE;495	if (termios->c_iflag & IGNBRK) {496		port->ignore_status_mask |= LINFLEXD_UARTSR_PE;497		/*498		 * if we're ignoring parity and break indicators,499		 * ignore overruns too (for real raw support).500		 */501		if (termios->c_iflag & IGNPAR)502			port->ignore_status_mask |= LINFLEXD_UARTSR_BOF;503	}504 505	writel(cr, port->membase + UARTCR);506 507	cr1 &= ~(LINFLEXD_LINCR1_INIT);508 509	writel(cr1, port->membase + LINCR1);510 511	uart_port_unlock_irqrestore(port, flags);512}513 514static const char *linflex_type(struct uart_port *port)515{516	return "FSL_LINFLEX";517}518 519static void linflex_release_port(struct uart_port *port)520{521	/* nothing to do */522}523 524static int linflex_request_port(struct uart_port *port)525{526	return 0;527}528 529/* configure/auto-configure the port */530static void linflex_config_port(struct uart_port *port, int flags)531{532	if (flags & UART_CONFIG_TYPE)533		port->type = PORT_LINFLEXUART;534}535 536static const struct uart_ops linflex_pops = {537	.tx_empty	= linflex_tx_empty,538	.set_mctrl	= linflex_set_mctrl,539	.get_mctrl	= linflex_get_mctrl,540	.stop_tx	= linflex_stop_tx,541	.start_tx	= linflex_start_tx,542	.stop_rx	= linflex_stop_rx,543	.break_ctl	= linflex_break_ctl,544	.startup	= linflex_startup,545	.shutdown	= linflex_shutdown,546	.set_termios	= linflex_set_termios,547	.type		= linflex_type,548	.request_port	= linflex_request_port,549	.release_port	= linflex_release_port,550	.config_port	= linflex_config_port,551};552 553static struct uart_port *linflex_ports[UART_NR];554 555#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE556static void linflex_console_putchar(struct uart_port *port, unsigned char ch)557{558	unsigned long cr;559 560	cr = readl(port->membase + UARTCR);561 562	writeb(ch, port->membase + BDRL);563 564	if (!(cr & LINFLEXD_UARTCR_TFBM))565		while ((readl(port->membase + UARTSR) &566					LINFLEXD_UARTSR_DTFTFF)567				!= LINFLEXD_UARTSR_DTFTFF)568			;569	else570		while (readl(port->membase + UARTSR) &571					LINFLEXD_UARTSR_DTFTFF)572			;573 574	if (!(cr & LINFLEXD_UARTCR_TFBM)) {575		writel((readl(port->membase + UARTSR) |576					LINFLEXD_UARTSR_DTFTFF),577					port->membase + UARTSR);578	}579}580 581static void linflex_earlycon_putchar(struct uart_port *port, unsigned char ch)582{583	unsigned long flags;584	char *ret;585 586	if (!linflex_earlycon_same_instance) {587		linflex_console_putchar(port, ch);588		return;589	}590 591	spin_lock_irqsave(&init_lock, flags);592	if (!during_init)593		goto outside_init;594 595	if (earlycon_buf.len >= 1 << CONFIG_LOG_BUF_SHIFT)596		goto init_release;597 598	if (!earlycon_buf.cap) {599		earlycon_buf.content = kmalloc(EARLYCON_BUFFER_INITIAL_CAP,600					       GFP_ATOMIC);601		earlycon_buf.cap = earlycon_buf.content ?602				   EARLYCON_BUFFER_INITIAL_CAP : 0;603	} else if (earlycon_buf.len == earlycon_buf.cap) {604		ret = krealloc(earlycon_buf.content, earlycon_buf.cap << 1,605			       GFP_ATOMIC);606		if (ret) {607			earlycon_buf.content = ret;608			earlycon_buf.cap <<= 1;609		}610	}611 612	if (earlycon_buf.len < earlycon_buf.cap)613		earlycon_buf.content[earlycon_buf.len++] = ch;614 615	goto init_release;616 617outside_init:618	linflex_console_putchar(port, ch);619init_release:620	spin_unlock_irqrestore(&init_lock, flags);621}622 623static void linflex_string_write(struct uart_port *sport, const char *s,624				 unsigned int count)625{626	unsigned long cr, ier = 0;627 628	ier = readl(sport->membase + LINIER);629	linflex_stop_tx(sport);630 631	cr = readl(sport->membase + UARTCR);632	cr |= (LINFLEXD_UARTCR_TXEN);633	writel(cr, sport->membase + UARTCR);634 635	uart_console_write(sport, s, count, linflex_console_putchar);636 637	writel(ier, sport->membase + LINIER);638}639 640static void641linflex_console_write(struct console *co, const char *s, unsigned int count)642{643	struct uart_port *sport = linflex_ports[co->index];644	unsigned long flags;645	int locked = 1;646 647	if (sport->sysrq)648		locked = 0;649	else if (oops_in_progress)650		locked = uart_port_trylock_irqsave(sport, &flags);651	else652		uart_port_lock_irqsave(sport, &flags);653 654	linflex_string_write(sport, s, count);655 656	if (locked)657		uart_port_unlock_irqrestore(sport, flags);658}659 660/*661 * if the port was already initialised (eg, by a boot loader),662 * try to determine the current setup.663 */664static void __init665linflex_console_get_options(struct uart_port *sport, int *parity, int *bits)666{667	unsigned long cr;668 669	cr = readl(sport->membase + UARTCR);670	cr &= LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN;671 672	if (!cr)673		return;674 675	/* ok, the port was enabled */676 677	*parity = 'n';678	if (cr & LINFLEXD_UARTCR_PCE) {679		if (cr & LINFLEXD_UARTCR_PC0)680			*parity = 'o';681		else682			*parity = 'e';683	}684 685	if ((cr & LINFLEXD_UARTCR_WL0) && ((cr & LINFLEXD_UARTCR_WL1) == 0)) {686		if (cr & LINFLEXD_UARTCR_PCE)687			*bits = 9;688		else689			*bits = 8;690	}691}692 693static int __init linflex_console_setup(struct console *co, char *options)694{695	struct uart_port *sport;696	int baud = 115200;697	int bits = 8;698	int parity = 'n';699	int flow = 'n';700	int ret;701	int i;702	unsigned long flags;703	/*704	 * check whether an invalid uart number has been specified, and705	 * if so, search for the first available port that does have706	 * console support.707	 */708	if (co->index == -1 || co->index >= ARRAY_SIZE(linflex_ports))709		co->index = 0;710 711	sport = linflex_ports[co->index];712	if (!sport)713		return -ENODEV;714 715	if (options)716		uart_parse_options(options, &baud, &parity, &bits, &flow);717	else718		linflex_console_get_options(sport, &parity, &bits);719 720	if (earlycon_port && sport->mapbase == earlycon_port->mapbase) {721		linflex_earlycon_same_instance = true;722 723		spin_lock_irqsave(&init_lock, flags);724		during_init = true;725		spin_unlock_irqrestore(&init_lock, flags);726 727		/* Workaround for character loss or output of many invalid728		 * characters, when INIT mode is entered shortly after a729		 * character has just been printed.730		 */731		udelay(PREINIT_DELAY);732	}733 734	linflex_setup_watermark(sport);735 736	ret = uart_set_options(sport, co, baud, parity, bits, flow);737 738	if (!linflex_earlycon_same_instance)739		goto done;740 741	spin_lock_irqsave(&init_lock, flags);742 743	/* Emptying buffer */744	if (earlycon_buf.len) {745		for (i = 0; i < earlycon_buf.len; i++)746			linflex_console_putchar(earlycon_port,747				earlycon_buf.content[i]);748 749		kfree(earlycon_buf.content);750		earlycon_buf.len = 0;751	}752 753	during_init = false;754	spin_unlock_irqrestore(&init_lock, flags);755 756done:757	return ret;758}759 760static struct uart_driver linflex_reg;761static struct console linflex_console = {762	.name		= DEV_NAME,763	.write		= linflex_console_write,764	.device		= uart_console_device,765	.setup		= linflex_console_setup,766	.flags		= CON_PRINTBUFFER,767	.index		= -1,768	.data		= &linflex_reg,769};770 771static void linflex_earlycon_write(struct console *con, const char *s,772				   unsigned int n)773{774	struct earlycon_device *dev = con->data;775 776	uart_console_write(&dev->port, s, n, linflex_earlycon_putchar);777}778 779static int __init linflex_early_console_setup(struct earlycon_device *device,780					      const char *options)781{782	if (!device->port.membase)783		return -ENODEV;784 785	device->con->write = linflex_earlycon_write;786	earlycon_port = &device->port;787 788	return 0;789}790 791OF_EARLYCON_DECLARE(linflex, "fsl,s32v234-linflexuart",792		    linflex_early_console_setup);793 794#define LINFLEX_CONSOLE	(&linflex_console)795#else796#define LINFLEX_CONSOLE	NULL797#endif798 799static struct uart_driver linflex_reg = {800	.owner		= THIS_MODULE,801	.driver_name	= DRIVER_NAME,802	.dev_name	= DEV_NAME,803	.nr		= ARRAY_SIZE(linflex_ports),804	.cons		= LINFLEX_CONSOLE,805};806 807static int linflex_probe(struct platform_device *pdev)808{809	struct device_node *np = pdev->dev.of_node;810	struct uart_port *sport;811	struct resource *res;812	int ret;813 814	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);815	if (!sport)816		return -ENOMEM;817 818	ret = of_alias_get_id(np, "serial");819	if (ret < 0) {820		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);821		return ret;822	}823	if (ret >= UART_NR) {824		dev_err(&pdev->dev, "driver limited to %d serial ports\n",825			UART_NR);826		return -ENOMEM;827	}828 829	sport->line = ret;830 831	sport->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);832	if (IS_ERR(sport->membase))833		return PTR_ERR(sport->membase);834	sport->mapbase = res->start;835 836	ret = platform_get_irq(pdev, 0);837	if (ret < 0)838		return ret;839 840	sport->dev = &pdev->dev;841	sport->iotype = UPIO_MEM;842	sport->irq = ret;843	sport->ops = &linflex_pops;844	sport->flags = UPF_BOOT_AUTOCONF;845	sport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE);846 847	linflex_ports[sport->line] = sport;848 849	platform_set_drvdata(pdev, sport);850 851	return uart_add_one_port(&linflex_reg, sport);852}853 854static void linflex_remove(struct platform_device *pdev)855{856	struct uart_port *sport = platform_get_drvdata(pdev);857 858	uart_remove_one_port(&linflex_reg, sport);859}860 861#ifdef CONFIG_PM_SLEEP862static int linflex_suspend(struct device *dev)863{864	struct uart_port *sport = dev_get_drvdata(dev);865 866	uart_suspend_port(&linflex_reg, sport);867 868	return 0;869}870 871static int linflex_resume(struct device *dev)872{873	struct uart_port *sport = dev_get_drvdata(dev);874 875	uart_resume_port(&linflex_reg, sport);876 877	return 0;878}879#endif880 881static SIMPLE_DEV_PM_OPS(linflex_pm_ops, linflex_suspend, linflex_resume);882 883static struct platform_driver linflex_driver = {884	.probe		= linflex_probe,885	.remove_new	= linflex_remove,886	.driver		= {887		.name	= DRIVER_NAME,888		.of_match_table	= linflex_dt_ids,889		.pm	= &linflex_pm_ops,890	},891};892 893static int __init linflex_serial_init(void)894{895	int ret;896 897	ret = uart_register_driver(&linflex_reg);898	if (ret)899		return ret;900 901	ret = platform_driver_register(&linflex_driver);902	if (ret)903		uart_unregister_driver(&linflex_reg);904 905	return ret;906}907 908static void __exit linflex_serial_exit(void)909{910	platform_driver_unregister(&linflex_driver);911	uart_unregister_driver(&linflex_reg);912}913 914module_init(linflex_serial_init);915module_exit(linflex_serial_exit);916 917MODULE_DESCRIPTION("Freescale LINFlexD serial port driver");918MODULE_LICENSE("GPL v2");919