735 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * High Speed Serial Ports on NXP LPC32xx SoC4 *5 * Authors: Kevin Wells <kevin.wells@nxp.com>6 * Roland Stigge <stigge@antcom.de>7 *8 * Copyright (C) 2010 NXP Semiconductors9 * Copyright (C) 2012 Roland Stigge10 */11 12#include <linux/module.h>13#include <linux/ioport.h>14#include <linux/init.h>15#include <linux/console.h>16#include <linux/sysrq.h>17#include <linux/tty.h>18#include <linux/tty_flip.h>19#include <linux/serial_core.h>20#include <linux/serial.h>21#include <linux/platform_device.h>22#include <linux/delay.h>23#include <linux/nmi.h>24#include <linux/io.h>25#include <linux/irq.h>26#include <linux/of.h>27#include <linux/sizes.h>28#include <linux/soc/nxp/lpc32xx-misc.h>29 30/*31 * High Speed UART register offsets32 */33#define LPC32XX_HSUART_FIFO(x) ((x) + 0x00)34#define LPC32XX_HSUART_LEVEL(x) ((x) + 0x04)35#define LPC32XX_HSUART_IIR(x) ((x) + 0x08)36#define LPC32XX_HSUART_CTRL(x) ((x) + 0x0C)37#define LPC32XX_HSUART_RATE(x) ((x) + 0x10)38 39#define LPC32XX_HSU_BREAK_DATA (1 << 10)40#define LPC32XX_HSU_ERROR_DATA (1 << 9)41#define LPC32XX_HSU_RX_EMPTY (1 << 8)42 43#define LPC32XX_HSU_TX_LEV(n) (((n) >> 8) & 0xFF)44#define LPC32XX_HSU_RX_LEV(n) ((n) & 0xFF)45 46#define LPC32XX_HSU_TX_INT_SET (1 << 6)47#define LPC32XX_HSU_RX_OE_INT (1 << 5)48#define LPC32XX_HSU_BRK_INT (1 << 4)49#define LPC32XX_HSU_FE_INT (1 << 3)50#define LPC32XX_HSU_RX_TIMEOUT_INT (1 << 2)51#define LPC32XX_HSU_RX_TRIG_INT (1 << 1)52#define LPC32XX_HSU_TX_INT (1 << 0)53 54#define LPC32XX_HSU_HRTS_INV (1 << 21)55#define LPC32XX_HSU_HRTS_TRIG_8B (0x0 << 19)56#define LPC32XX_HSU_HRTS_TRIG_16B (0x1 << 19)57#define LPC32XX_HSU_HRTS_TRIG_32B (0x2 << 19)58#define LPC32XX_HSU_HRTS_TRIG_48B (0x3 << 19)59#define LPC32XX_HSU_HRTS_EN (1 << 18)60#define LPC32XX_HSU_TMO_DISABLED (0x0 << 16)61#define LPC32XX_HSU_TMO_INACT_4B (0x1 << 16)62#define LPC32XX_HSU_TMO_INACT_8B (0x2 << 16)63#define LPC32XX_HSU_TMO_INACT_16B (0x3 << 16)64#define LPC32XX_HSU_HCTS_INV (1 << 15)65#define LPC32XX_HSU_HCTS_EN (1 << 14)66#define LPC32XX_HSU_OFFSET(n) ((n) << 9)67#define LPC32XX_HSU_BREAK (1 << 8)68#define LPC32XX_HSU_ERR_INT_EN (1 << 7)69#define LPC32XX_HSU_RX_INT_EN (1 << 6)70#define LPC32XX_HSU_TX_INT_EN (1 << 5)71#define LPC32XX_HSU_RX_TL1B (0x0 << 2)72#define LPC32XX_HSU_RX_TL4B (0x1 << 2)73#define LPC32XX_HSU_RX_TL8B (0x2 << 2)74#define LPC32XX_HSU_RX_TL16B (0x3 << 2)75#define LPC32XX_HSU_RX_TL32B (0x4 << 2)76#define LPC32XX_HSU_RX_TL48B (0x5 << 2)77#define LPC32XX_HSU_TX_TLEMPTY (0x0 << 0)78#define LPC32XX_HSU_TX_TL0B (0x0 << 0)79#define LPC32XX_HSU_TX_TL4B (0x1 << 0)80#define LPC32XX_HSU_TX_TL8B (0x2 << 0)81#define LPC32XX_HSU_TX_TL16B (0x3 << 0)82 83#define LPC32XX_MAIN_OSC_FREQ 1300000084 85#define MODNAME "lpc32xx_hsuart"86 87struct lpc32xx_hsuart_port {88 struct uart_port port;89};90 91#define FIFO_READ_LIMIT 12892#define MAX_PORTS 393#define LPC32XX_TTY_NAME "ttyTX"94static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS];95 96#ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE97static void wait_for_xmit_empty(struct uart_port *port)98{99 unsigned int timeout = 10000;100 101 do {102 if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(103 port->membase))) == 0)104 break;105 if (--timeout == 0)106 break;107 udelay(1);108 } while (1);109}110 111static void wait_for_xmit_ready(struct uart_port *port)112{113 unsigned int timeout = 10000;114 115 while (1) {116 if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(117 port->membase))) < 32)118 break;119 if (--timeout == 0)120 break;121 udelay(1);122 }123}124 125static void lpc32xx_hsuart_console_putchar(struct uart_port *port, unsigned char ch)126{127 wait_for_xmit_ready(port);128 writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase));129}130 131static void lpc32xx_hsuart_console_write(struct console *co, const char *s,132 unsigned int count)133{134 struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index];135 unsigned long flags;136 int locked = 1;137 138 touch_nmi_watchdog();139 if (oops_in_progress)140 locked = uart_port_trylock_irqsave(&up->port, &flags);141 else142 uart_port_lock_irqsave(&up->port, &flags);143 144 uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);145 wait_for_xmit_empty(&up->port);146 147 if (locked)148 uart_port_unlock_irqrestore(&up->port, flags);149}150 151static int __init lpc32xx_hsuart_console_setup(struct console *co,152 char *options)153{154 struct uart_port *port;155 int baud = 115200;156 int bits = 8;157 int parity = 'n';158 int flow = 'n';159 160 if (co->index >= MAX_PORTS)161 co->index = 0;162 163 port = &lpc32xx_hs_ports[co->index].port;164 if (!port->membase)165 return -ENODEV;166 167 if (options)168 uart_parse_options(options, &baud, &parity, &bits, &flow);169 170 lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */171 172 return uart_set_options(port, co, baud, parity, bits, flow);173}174 175static struct uart_driver lpc32xx_hsuart_reg;176static struct console lpc32xx_hsuart_console = {177 .name = LPC32XX_TTY_NAME,178 .write = lpc32xx_hsuart_console_write,179 .device = uart_console_device,180 .setup = lpc32xx_hsuart_console_setup,181 .flags = CON_PRINTBUFFER,182 .index = -1,183 .data = &lpc32xx_hsuart_reg,184};185 186static int __init lpc32xx_hsuart_console_init(void)187{188 register_console(&lpc32xx_hsuart_console);189 return 0;190}191console_initcall(lpc32xx_hsuart_console_init);192 193#define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console)194#else195#define LPC32XX_HSUART_CONSOLE NULL196#endif197 198static struct uart_driver lpc32xx_hs_reg = {199 .owner = THIS_MODULE,200 .driver_name = MODNAME,201 .dev_name = LPC32XX_TTY_NAME,202 .nr = MAX_PORTS,203 .cons = LPC32XX_HSUART_CONSOLE,204};205static int uarts_registered;206 207static unsigned int __serial_get_clock_div(unsigned long uartclk,208 unsigned long rate)209{210 u32 div, goodrate, hsu_rate, l_hsu_rate, comprate;211 u32 rate_diff;212 213 /* Find the closest divider to get the desired clock rate */214 div = uartclk / rate;215 goodrate = hsu_rate = (div / 14) - 1;216 if (hsu_rate != 0)217 hsu_rate--;218 219 /* Tweak divider */220 l_hsu_rate = hsu_rate + 3;221 rate_diff = 0xFFFFFFFF;222 223 while (hsu_rate < l_hsu_rate) {224 comprate = uartclk / ((hsu_rate + 1) * 14);225 if (abs(comprate - rate) < rate_diff) {226 goodrate = hsu_rate;227 rate_diff = abs(comprate - rate);228 }229 230 hsu_rate++;231 }232 233 return goodrate;234}235 236static void __serial_uart_flush(struct uart_port *port)237{238 int cnt = 0;239 240 while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) &&241 (cnt++ < FIFO_READ_LIMIT))242 readl(LPC32XX_HSUART_FIFO(port->membase));243}244 245static void __serial_lpc32xx_rx(struct uart_port *port)246{247 struct tty_port *tport = &port->state->port;248 unsigned int tmp, flag;249 250 /* Read data from FIFO and push into terminal */251 tmp = readl(LPC32XX_HSUART_FIFO(port->membase));252 while (!(tmp & LPC32XX_HSU_RX_EMPTY)) {253 flag = TTY_NORMAL;254 port->icount.rx++;255 256 if (tmp & LPC32XX_HSU_ERROR_DATA) {257 /* Framing error */258 writel(LPC32XX_HSU_FE_INT,259 LPC32XX_HSUART_IIR(port->membase));260 port->icount.frame++;261 flag = TTY_FRAME;262 tty_insert_flip_char(tport, 0, TTY_FRAME);263 }264 265 if (!uart_prepare_sysrq_char(port, tmp & 0xff))266 tty_insert_flip_char(tport, (tmp & 0xFF), flag);267 268 tmp = readl(LPC32XX_HSUART_FIFO(port->membase));269 }270 271 tty_flip_buffer_push(tport);272}273 274static bool serial_lpc32xx_tx_ready(struct uart_port *port)275{276 u32 level = readl(LPC32XX_HSUART_LEVEL(port->membase));277 278 return LPC32XX_HSU_TX_LEV(level) < 64;279}280 281static void __serial_lpc32xx_tx(struct uart_port *port)282{283 u8 ch;284 285 uart_port_tx(port, ch,286 serial_lpc32xx_tx_ready(port),287 writel(ch, LPC32XX_HSUART_FIFO(port->membase)));288}289 290static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)291{292 struct uart_port *port = dev_id;293 struct tty_port *tport = &port->state->port;294 u32 status;295 296 uart_port_lock(port);297 298 /* Read UART status and clear latched interrupts */299 status = readl(LPC32XX_HSUART_IIR(port->membase));300 301 if (status & LPC32XX_HSU_BRK_INT) {302 /* Break received */303 writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase));304 port->icount.brk++;305 uart_handle_break(port);306 }307 308 /* Framing error */309 if (status & LPC32XX_HSU_FE_INT)310 writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase));311 312 if (status & LPC32XX_HSU_RX_OE_INT) {313 /* Receive FIFO overrun */314 writel(LPC32XX_HSU_RX_OE_INT,315 LPC32XX_HSUART_IIR(port->membase));316 port->icount.overrun++;317 tty_insert_flip_char(tport, 0, TTY_OVERRUN);318 tty_flip_buffer_push(tport);319 }320 321 /* Data received? */322 if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT))323 __serial_lpc32xx_rx(port);324 325 /* Transmit data request? */326 if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {327 writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase));328 __serial_lpc32xx_tx(port);329 }330 331 uart_unlock_and_check_sysrq(port);332 333 return IRQ_HANDLED;334}335 336/* port->lock is not held. */337static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port)338{339 unsigned int ret = 0;340 341 if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0)342 ret = TIOCSER_TEMT;343 344 return ret;345}346 347/* port->lock held by caller. */348static void serial_lpc32xx_set_mctrl(struct uart_port *port,349 unsigned int mctrl)350{351 /* No signals are supported on HS UARTs */352}353 354/* port->lock is held by caller and interrupts are disabled. */355static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port)356{357 /* No signals are supported on HS UARTs */358 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;359}360 361/* port->lock held by caller. */362static void serial_lpc32xx_stop_tx(struct uart_port *port)363{364 u32 tmp;365 366 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));367 tmp &= ~LPC32XX_HSU_TX_INT_EN;368 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));369}370 371/* port->lock held by caller. */372static void serial_lpc32xx_start_tx(struct uart_port *port)373{374 u32 tmp;375 376 __serial_lpc32xx_tx(port);377 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));378 tmp |= LPC32XX_HSU_TX_INT_EN;379 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));380}381 382/* port->lock held by caller. */383static void serial_lpc32xx_stop_rx(struct uart_port *port)384{385 u32 tmp;386 387 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));388 tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);389 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));390 391 writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT |392 LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));393}394 395/* port->lock is not held. */396static void serial_lpc32xx_break_ctl(struct uart_port *port,397 int break_state)398{399 unsigned long flags;400 u32 tmp;401 402 uart_port_lock_irqsave(port, &flags);403 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));404 if (break_state != 0)405 tmp |= LPC32XX_HSU_BREAK;406 else407 tmp &= ~LPC32XX_HSU_BREAK;408 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));409 uart_port_unlock_irqrestore(port, flags);410}411 412/* port->lock is not held. */413static int serial_lpc32xx_startup(struct uart_port *port)414{415 int retval;416 unsigned long flags;417 u32 tmp;418 419 uart_port_lock_irqsave(port, &flags);420 421 __serial_uart_flush(port);422 423 writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |424 LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),425 LPC32XX_HSUART_IIR(port->membase));426 427 writel(0xFF, LPC32XX_HSUART_RATE(port->membase));428 429 /*430 * Set receiver timeout, HSU offset of 20, no break, no interrupts,431 * and default FIFO trigger levels432 */433 tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |434 LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;435 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));436 437 lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */438 439 uart_port_unlock_irqrestore(port, flags);440 441 retval = request_irq(port->irq, serial_lpc32xx_interrupt,442 0, MODNAME, port);443 if (!retval)444 writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN),445 LPC32XX_HSUART_CTRL(port->membase));446 447 return retval;448}449 450/* port->lock is not held. */451static void serial_lpc32xx_shutdown(struct uart_port *port)452{453 u32 tmp;454 unsigned long flags;455 456 uart_port_lock_irqsave(port, &flags);457 458 tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |459 LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;460 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));461 462 lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */463 464 uart_port_unlock_irqrestore(port, flags);465 466 free_irq(port->irq, port);467}468 469/* port->lock is not held. */470static void serial_lpc32xx_set_termios(struct uart_port *port,471 struct ktermios *termios,472 const struct ktermios *old)473{474 unsigned long flags;475 unsigned int baud, quot;476 u32 tmp;477 478 /* Always 8-bit, no parity, 1 stop bit */479 termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);480 termios->c_cflag |= CS8;481 482 termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS);483 484 baud = uart_get_baud_rate(port, termios, old, 0,485 port->uartclk / 14);486 487 quot = __serial_get_clock_div(port->uartclk, baud);488 489 uart_port_lock_irqsave(port, &flags);490 491 /* Ignore characters? */492 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));493 if ((termios->c_cflag & CREAD) == 0)494 tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);495 else496 tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN;497 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));498 499 writel(quot, LPC32XX_HSUART_RATE(port->membase));500 501 uart_update_timeout(port, termios->c_cflag, baud);502 503 uart_port_unlock_irqrestore(port, flags);504 505 /* Don't rewrite B0 */506 if (tty_termios_baud_rate(termios))507 tty_termios_encode_baud_rate(termios, baud, baud);508}509 510static const char *serial_lpc32xx_type(struct uart_port *port)511{512 return MODNAME;513}514 515static void serial_lpc32xx_release_port(struct uart_port *port)516{517 if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {518 if (port->flags & UPF_IOREMAP) {519 iounmap(port->membase);520 port->membase = NULL;521 }522 523 release_mem_region(port->mapbase, SZ_4K);524 }525}526 527static int serial_lpc32xx_request_port(struct uart_port *port)528{529 int ret = -ENODEV;530 531 if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {532 ret = 0;533 534 if (!request_mem_region(port->mapbase, SZ_4K, MODNAME))535 ret = -EBUSY;536 else if (port->flags & UPF_IOREMAP) {537 port->membase = ioremap(port->mapbase, SZ_4K);538 if (!port->membase) {539 release_mem_region(port->mapbase, SZ_4K);540 ret = -ENOMEM;541 }542 }543 }544 545 return ret;546}547 548static void serial_lpc32xx_config_port(struct uart_port *port, int uflags)549{550 int ret;551 552 ret = serial_lpc32xx_request_port(port);553 if (ret < 0)554 return;555 port->type = PORT_UART00;556 port->fifosize = 64;557 558 __serial_uart_flush(port);559 560 writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |561 LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),562 LPC32XX_HSUART_IIR(port->membase));563 564 writel(0xFF, LPC32XX_HSUART_RATE(port->membase));565 566 /* Set receiver timeout, HSU offset of 20, no break, no interrupts,567 and default FIFO trigger levels */568 writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |569 LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B,570 LPC32XX_HSUART_CTRL(port->membase));571}572 573static int serial_lpc32xx_verify_port(struct uart_port *port,574 struct serial_struct *ser)575{576 int ret = 0;577 578 if (ser->type != PORT_UART00)579 ret = -EINVAL;580 581 return ret;582}583 584static const struct uart_ops serial_lpc32xx_pops = {585 .tx_empty = serial_lpc32xx_tx_empty,586 .set_mctrl = serial_lpc32xx_set_mctrl,587 .get_mctrl = serial_lpc32xx_get_mctrl,588 .stop_tx = serial_lpc32xx_stop_tx,589 .start_tx = serial_lpc32xx_start_tx,590 .stop_rx = serial_lpc32xx_stop_rx,591 .break_ctl = serial_lpc32xx_break_ctl,592 .startup = serial_lpc32xx_startup,593 .shutdown = serial_lpc32xx_shutdown,594 .set_termios = serial_lpc32xx_set_termios,595 .type = serial_lpc32xx_type,596 .release_port = serial_lpc32xx_release_port,597 .request_port = serial_lpc32xx_request_port,598 .config_port = serial_lpc32xx_config_port,599 .verify_port = serial_lpc32xx_verify_port,600};601 602/*603 * Register a set of serial devices attached to a platform device604 */605static int serial_hs_lpc32xx_probe(struct platform_device *pdev)606{607 struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];608 int ret = 0;609 struct resource *res;610 611 if (uarts_registered >= MAX_PORTS) {612 dev_err(&pdev->dev,613 "Error: Number of possible ports exceeded (%d)!\n",614 uarts_registered + 1);615 return -ENXIO;616 }617 618 memset(p, 0, sizeof(*p));619 620 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);621 if (!res) {622 dev_err(&pdev->dev,623 "Error getting mem resource for HS UART port %d\n",624 uarts_registered);625 return -ENXIO;626 }627 p->port.mapbase = res->start;628 p->port.membase = NULL;629 630 ret = platform_get_irq(pdev, 0);631 if (ret < 0)632 return ret;633 p->port.irq = ret;634 635 p->port.iotype = UPIO_MEM32;636 p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;637 p->port.regshift = 2;638 p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;639 p->port.dev = &pdev->dev;640 p->port.ops = &serial_lpc32xx_pops;641 p->port.line = uarts_registered++;642 spin_lock_init(&p->port.lock);643 644 /* send port to loopback mode by default */645 lpc32xx_loopback_set(p->port.mapbase, 1);646 647 ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port);648 649 platform_set_drvdata(pdev, p);650 651 return ret;652}653 654/*655 * Remove serial ports registered against a platform device.656 */657static void serial_hs_lpc32xx_remove(struct platform_device *pdev)658{659 struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);660 661 uart_remove_one_port(&lpc32xx_hs_reg, &p->port);662}663 664 665#ifdef CONFIG_PM666static int serial_hs_lpc32xx_suspend(struct platform_device *pdev,667 pm_message_t state)668{669 struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);670 671 uart_suspend_port(&lpc32xx_hs_reg, &p->port);672 673 return 0;674}675 676static int serial_hs_lpc32xx_resume(struct platform_device *pdev)677{678 struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);679 680 uart_resume_port(&lpc32xx_hs_reg, &p->port);681 682 return 0;683}684#else685#define serial_hs_lpc32xx_suspend NULL686#define serial_hs_lpc32xx_resume NULL687#endif688 689static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = {690 { .compatible = "nxp,lpc3220-hsuart" },691 { /* sentinel */ }692};693 694MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);695 696static struct platform_driver serial_hs_lpc32xx_driver = {697 .probe = serial_hs_lpc32xx_probe,698 .remove_new = serial_hs_lpc32xx_remove,699 .suspend = serial_hs_lpc32xx_suspend,700 .resume = serial_hs_lpc32xx_resume,701 .driver = {702 .name = MODNAME,703 .of_match_table = serial_hs_lpc32xx_dt_ids,704 },705};706 707static int __init lpc32xx_hsuart_init(void)708{709 int ret;710 711 ret = uart_register_driver(&lpc32xx_hs_reg);712 if (ret)713 return ret;714 715 ret = platform_driver_register(&serial_hs_lpc32xx_driver);716 if (ret)717 uart_unregister_driver(&lpc32xx_hs_reg);718 719 return ret;720}721 722static void __exit lpc32xx_hsuart_exit(void)723{724 platform_driver_unregister(&serial_hs_lpc32xx_driver);725 uart_unregister_driver(&lpc32xx_hs_reg);726}727 728module_init(lpc32xx_hsuart_init);729module_exit(lpc32xx_hsuart_exit);730 731MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");732MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");733MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver");734MODULE_LICENSE("GPL");735