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