0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/ioport.h>
0014 #include <linux/init.h>
0015 #include <linux/console.h>
0016 #include <linux/sysrq.h>
0017 #include <linux/tty.h>
0018 #include <linux/tty_flip.h>
0019 #include <linux/serial_core.h>
0020 #include <linux/serial.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/delay.h>
0023 #include <linux/nmi.h>
0024 #include <linux/io.h>
0025 #include <linux/irq.h>
0026 #include <linux/of.h>
0027 #include <linux/sizes.h>
0028 #include <linux/soc/nxp/lpc32xx-misc.h>
0029
0030
0031
0032
0033 #define LPC32XX_HSUART_FIFO(x) ((x) + 0x00)
0034 #define LPC32XX_HSUART_LEVEL(x) ((x) + 0x04)
0035 #define LPC32XX_HSUART_IIR(x) ((x) + 0x08)
0036 #define LPC32XX_HSUART_CTRL(x) ((x) + 0x0C)
0037 #define LPC32XX_HSUART_RATE(x) ((x) + 0x10)
0038
0039 #define LPC32XX_HSU_BREAK_DATA (1 << 10)
0040 #define LPC32XX_HSU_ERROR_DATA (1 << 9)
0041 #define LPC32XX_HSU_RX_EMPTY (1 << 8)
0042
0043 #define LPC32XX_HSU_TX_LEV(n) (((n) >> 8) & 0xFF)
0044 #define LPC32XX_HSU_RX_LEV(n) ((n) & 0xFF)
0045
0046 #define LPC32XX_HSU_TX_INT_SET (1 << 6)
0047 #define LPC32XX_HSU_RX_OE_INT (1 << 5)
0048 #define LPC32XX_HSU_BRK_INT (1 << 4)
0049 #define LPC32XX_HSU_FE_INT (1 << 3)
0050 #define LPC32XX_HSU_RX_TIMEOUT_INT (1 << 2)
0051 #define LPC32XX_HSU_RX_TRIG_INT (1 << 1)
0052 #define LPC32XX_HSU_TX_INT (1 << 0)
0053
0054 #define LPC32XX_HSU_HRTS_INV (1 << 21)
0055 #define LPC32XX_HSU_HRTS_TRIG_8B (0x0 << 19)
0056 #define LPC32XX_HSU_HRTS_TRIG_16B (0x1 << 19)
0057 #define LPC32XX_HSU_HRTS_TRIG_32B (0x2 << 19)
0058 #define LPC32XX_HSU_HRTS_TRIG_48B (0x3 << 19)
0059 #define LPC32XX_HSU_HRTS_EN (1 << 18)
0060 #define LPC32XX_HSU_TMO_DISABLED (0x0 << 16)
0061 #define LPC32XX_HSU_TMO_INACT_4B (0x1 << 16)
0062 #define LPC32XX_HSU_TMO_INACT_8B (0x2 << 16)
0063 #define LPC32XX_HSU_TMO_INACT_16B (0x3 << 16)
0064 #define LPC32XX_HSU_HCTS_INV (1 << 15)
0065 #define LPC32XX_HSU_HCTS_EN (1 << 14)
0066 #define LPC32XX_HSU_OFFSET(n) ((n) << 9)
0067 #define LPC32XX_HSU_BREAK (1 << 8)
0068 #define LPC32XX_HSU_ERR_INT_EN (1 << 7)
0069 #define LPC32XX_HSU_RX_INT_EN (1 << 6)
0070 #define LPC32XX_HSU_TX_INT_EN (1 << 5)
0071 #define LPC32XX_HSU_RX_TL1B (0x0 << 2)
0072 #define LPC32XX_HSU_RX_TL4B (0x1 << 2)
0073 #define LPC32XX_HSU_RX_TL8B (0x2 << 2)
0074 #define LPC32XX_HSU_RX_TL16B (0x3 << 2)
0075 #define LPC32XX_HSU_RX_TL32B (0x4 << 2)
0076 #define LPC32XX_HSU_RX_TL48B (0x5 << 2)
0077 #define LPC32XX_HSU_TX_TLEMPTY (0x0 << 0)
0078 #define LPC32XX_HSU_TX_TL0B (0x0 << 0)
0079 #define LPC32XX_HSU_TX_TL4B (0x1 << 0)
0080 #define LPC32XX_HSU_TX_TL8B (0x2 << 0)
0081 #define LPC32XX_HSU_TX_TL16B (0x3 << 0)
0082
0083 #define LPC32XX_MAIN_OSC_FREQ 13000000
0084
0085 #define MODNAME "lpc32xx_hsuart"
0086
0087 struct lpc32xx_hsuart_port {
0088 struct uart_port port;
0089 };
0090
0091 #define FIFO_READ_LIMIT 128
0092 #define MAX_PORTS 3
0093 #define LPC32XX_TTY_NAME "ttyTX"
0094 static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS];
0095
0096 #ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE
0097 static void wait_for_xmit_empty(struct uart_port *port)
0098 {
0099 unsigned int timeout = 10000;
0100
0101 do {
0102 if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
0103 port->membase))) == 0)
0104 break;
0105 if (--timeout == 0)
0106 break;
0107 udelay(1);
0108 } while (1);
0109 }
0110
0111 static void wait_for_xmit_ready(struct uart_port *port)
0112 {
0113 unsigned int timeout = 10000;
0114
0115 while (1) {
0116 if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(
0117 port->membase))) < 32)
0118 break;
0119 if (--timeout == 0)
0120 break;
0121 udelay(1);
0122 }
0123 }
0124
0125 static void lpc32xx_hsuart_console_putchar(struct uart_port *port, unsigned char ch)
0126 {
0127 wait_for_xmit_ready(port);
0128 writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase));
0129 }
0130
0131 static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
0132 unsigned int count)
0133 {
0134 struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index];
0135 unsigned long flags;
0136 int locked = 1;
0137
0138 touch_nmi_watchdog();
0139 local_irq_save(flags);
0140 if (up->port.sysrq)
0141 locked = 0;
0142 else if (oops_in_progress)
0143 locked = spin_trylock(&up->port.lock);
0144 else
0145 spin_lock(&up->port.lock);
0146
0147 uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
0148 wait_for_xmit_empty(&up->port);
0149
0150 if (locked)
0151 spin_unlock(&up->port.lock);
0152 local_irq_restore(flags);
0153 }
0154
0155 static int __init lpc32xx_hsuart_console_setup(struct console *co,
0156 char *options)
0157 {
0158 struct uart_port *port;
0159 int baud = 115200;
0160 int bits = 8;
0161 int parity = 'n';
0162 int flow = 'n';
0163
0164 if (co->index >= MAX_PORTS)
0165 co->index = 0;
0166
0167 port = &lpc32xx_hs_ports[co->index].port;
0168 if (!port->membase)
0169 return -ENODEV;
0170
0171 if (options)
0172 uart_parse_options(options, &baud, &parity, &bits, &flow);
0173
0174 lpc32xx_loopback_set(port->mapbase, 0);
0175
0176 return uart_set_options(port, co, baud, parity, bits, flow);
0177 }
0178
0179 static struct uart_driver lpc32xx_hsuart_reg;
0180 static struct console lpc32xx_hsuart_console = {
0181 .name = LPC32XX_TTY_NAME,
0182 .write = lpc32xx_hsuart_console_write,
0183 .device = uart_console_device,
0184 .setup = lpc32xx_hsuart_console_setup,
0185 .flags = CON_PRINTBUFFER,
0186 .index = -1,
0187 .data = &lpc32xx_hsuart_reg,
0188 };
0189
0190 static int __init lpc32xx_hsuart_console_init(void)
0191 {
0192 register_console(&lpc32xx_hsuart_console);
0193 return 0;
0194 }
0195 console_initcall(lpc32xx_hsuart_console_init);
0196
0197 #define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console)
0198 #else
0199 #define LPC32XX_HSUART_CONSOLE NULL
0200 #endif
0201
0202 static struct uart_driver lpc32xx_hs_reg = {
0203 .owner = THIS_MODULE,
0204 .driver_name = MODNAME,
0205 .dev_name = LPC32XX_TTY_NAME,
0206 .nr = MAX_PORTS,
0207 .cons = LPC32XX_HSUART_CONSOLE,
0208 };
0209 static int uarts_registered;
0210
0211 static unsigned int __serial_get_clock_div(unsigned long uartclk,
0212 unsigned long rate)
0213 {
0214 u32 div, goodrate, hsu_rate, l_hsu_rate, comprate;
0215 u32 rate_diff;
0216
0217
0218 div = uartclk / rate;
0219 goodrate = hsu_rate = (div / 14) - 1;
0220 if (hsu_rate != 0)
0221 hsu_rate--;
0222
0223
0224 l_hsu_rate = hsu_rate + 3;
0225 rate_diff = 0xFFFFFFFF;
0226
0227 while (hsu_rate < l_hsu_rate) {
0228 comprate = uartclk / ((hsu_rate + 1) * 14);
0229 if (abs(comprate - rate) < rate_diff) {
0230 goodrate = hsu_rate;
0231 rate_diff = abs(comprate - rate);
0232 }
0233
0234 hsu_rate++;
0235 }
0236 if (hsu_rate > 0xFF)
0237 hsu_rate = 0xFF;
0238
0239 return goodrate;
0240 }
0241
0242 static void __serial_uart_flush(struct uart_port *port)
0243 {
0244 int cnt = 0;
0245
0246 while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) &&
0247 (cnt++ < FIFO_READ_LIMIT))
0248 readl(LPC32XX_HSUART_FIFO(port->membase));
0249 }
0250
0251 static void __serial_lpc32xx_rx(struct uart_port *port)
0252 {
0253 struct tty_port *tport = &port->state->port;
0254 unsigned int tmp, flag;
0255
0256
0257 tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
0258 while (!(tmp & LPC32XX_HSU_RX_EMPTY)) {
0259 flag = TTY_NORMAL;
0260 port->icount.rx++;
0261
0262 if (tmp & LPC32XX_HSU_ERROR_DATA) {
0263
0264 writel(LPC32XX_HSU_FE_INT,
0265 LPC32XX_HSUART_IIR(port->membase));
0266 port->icount.frame++;
0267 flag = TTY_FRAME;
0268 tty_insert_flip_char(tport, 0, TTY_FRAME);
0269 }
0270
0271 tty_insert_flip_char(tport, (tmp & 0xFF), flag);
0272
0273 tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
0274 }
0275
0276 tty_flip_buffer_push(tport);
0277 }
0278
0279 static void serial_lpc32xx_stop_tx(struct uart_port *port);
0280
0281 static void __serial_lpc32xx_tx(struct uart_port *port)
0282 {
0283 struct circ_buf *xmit = &port->state->xmit;
0284
0285 if (port->x_char) {
0286 writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase));
0287 port->icount.tx++;
0288 port->x_char = 0;
0289 return;
0290 }
0291
0292 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
0293 goto exit_tx;
0294
0295
0296 while (LPC32XX_HSU_TX_LEV(readl(
0297 LPC32XX_HSUART_LEVEL(port->membase))) < 64) {
0298 writel((u32) xmit->buf[xmit->tail],
0299 LPC32XX_HSUART_FIFO(port->membase));
0300 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
0301 port->icount.tx++;
0302 if (uart_circ_empty(xmit))
0303 break;
0304 }
0305
0306 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
0307 uart_write_wakeup(port);
0308
0309 exit_tx:
0310 if (uart_circ_empty(xmit))
0311 serial_lpc32xx_stop_tx(port);
0312 }
0313
0314 static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
0315 {
0316 struct uart_port *port = dev_id;
0317 struct tty_port *tport = &port->state->port;
0318 u32 status;
0319
0320 spin_lock(&port->lock);
0321
0322
0323 status = readl(LPC32XX_HSUART_IIR(port->membase));
0324
0325 if (status & LPC32XX_HSU_BRK_INT) {
0326
0327 writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase));
0328 port->icount.brk++;
0329 uart_handle_break(port);
0330 }
0331
0332
0333 if (status & LPC32XX_HSU_FE_INT)
0334 writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase));
0335
0336 if (status & LPC32XX_HSU_RX_OE_INT) {
0337
0338 writel(LPC32XX_HSU_RX_OE_INT,
0339 LPC32XX_HSUART_IIR(port->membase));
0340 port->icount.overrun++;
0341 tty_insert_flip_char(tport, 0, TTY_OVERRUN);
0342 tty_flip_buffer_push(tport);
0343 }
0344
0345
0346 if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT))
0347 __serial_lpc32xx_rx(port);
0348
0349
0350 if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {
0351 writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase));
0352 __serial_lpc32xx_tx(port);
0353 }
0354
0355 spin_unlock(&port->lock);
0356
0357 return IRQ_HANDLED;
0358 }
0359
0360
0361 static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port)
0362 {
0363 unsigned int ret = 0;
0364
0365 if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0)
0366 ret = TIOCSER_TEMT;
0367
0368 return ret;
0369 }
0370
0371
0372 static void serial_lpc32xx_set_mctrl(struct uart_port *port,
0373 unsigned int mctrl)
0374 {
0375
0376 }
0377
0378
0379 static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port)
0380 {
0381
0382 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
0383 }
0384
0385
0386 static void serial_lpc32xx_stop_tx(struct uart_port *port)
0387 {
0388 u32 tmp;
0389
0390 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
0391 tmp &= ~LPC32XX_HSU_TX_INT_EN;
0392 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0393 }
0394
0395
0396 static void serial_lpc32xx_start_tx(struct uart_port *port)
0397 {
0398 u32 tmp;
0399
0400 __serial_lpc32xx_tx(port);
0401 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
0402 tmp |= LPC32XX_HSU_TX_INT_EN;
0403 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0404 }
0405
0406
0407 static void serial_lpc32xx_stop_rx(struct uart_port *port)
0408 {
0409 u32 tmp;
0410
0411 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
0412 tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
0413 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0414
0415 writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT |
0416 LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
0417 }
0418
0419
0420 static void serial_lpc32xx_break_ctl(struct uart_port *port,
0421 int break_state)
0422 {
0423 unsigned long flags;
0424 u32 tmp;
0425
0426 spin_lock_irqsave(&port->lock, flags);
0427 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
0428 if (break_state != 0)
0429 tmp |= LPC32XX_HSU_BREAK;
0430 else
0431 tmp &= ~LPC32XX_HSU_BREAK;
0432 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0433 spin_unlock_irqrestore(&port->lock, flags);
0434 }
0435
0436
0437 static int serial_lpc32xx_startup(struct uart_port *port)
0438 {
0439 int retval;
0440 unsigned long flags;
0441 u32 tmp;
0442
0443 spin_lock_irqsave(&port->lock, flags);
0444
0445 __serial_uart_flush(port);
0446
0447 writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
0448 LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
0449 LPC32XX_HSUART_IIR(port->membase));
0450
0451 writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
0452
0453
0454
0455
0456
0457 tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
0458 LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
0459 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0460
0461 lpc32xx_loopback_set(port->mapbase, 0);
0462
0463 spin_unlock_irqrestore(&port->lock, flags);
0464
0465 retval = request_irq(port->irq, serial_lpc32xx_interrupt,
0466 0, MODNAME, port);
0467 if (!retval)
0468 writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN),
0469 LPC32XX_HSUART_CTRL(port->membase));
0470
0471 return retval;
0472 }
0473
0474
0475 static void serial_lpc32xx_shutdown(struct uart_port *port)
0476 {
0477 u32 tmp;
0478 unsigned long flags;
0479
0480 spin_lock_irqsave(&port->lock, flags);
0481
0482 tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
0483 LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
0484 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0485
0486 lpc32xx_loopback_set(port->mapbase, 1);
0487
0488 spin_unlock_irqrestore(&port->lock, flags);
0489
0490 free_irq(port->irq, port);
0491 }
0492
0493
0494 static void serial_lpc32xx_set_termios(struct uart_port *port,
0495 struct ktermios *termios,
0496 struct ktermios *old)
0497 {
0498 unsigned long flags;
0499 unsigned int baud, quot;
0500 u32 tmp;
0501
0502
0503 termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
0504 termios->c_cflag |= CS8;
0505
0506 termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS);
0507
0508 baud = uart_get_baud_rate(port, termios, old, 0,
0509 port->uartclk / 14);
0510
0511 quot = __serial_get_clock_div(port->uartclk, baud);
0512
0513 spin_lock_irqsave(&port->lock, flags);
0514
0515
0516 tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
0517 if ((termios->c_cflag & CREAD) == 0)
0518 tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN);
0519 else
0520 tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN;
0521 writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
0522
0523 writel(quot, LPC32XX_HSUART_RATE(port->membase));
0524
0525 uart_update_timeout(port, termios->c_cflag, baud);
0526
0527 spin_unlock_irqrestore(&port->lock, flags);
0528
0529
0530 if (tty_termios_baud_rate(termios))
0531 tty_termios_encode_baud_rate(termios, baud, baud);
0532 }
0533
0534 static const char *serial_lpc32xx_type(struct uart_port *port)
0535 {
0536 return MODNAME;
0537 }
0538
0539 static void serial_lpc32xx_release_port(struct uart_port *port)
0540 {
0541 if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
0542 if (port->flags & UPF_IOREMAP) {
0543 iounmap(port->membase);
0544 port->membase = NULL;
0545 }
0546
0547 release_mem_region(port->mapbase, SZ_4K);
0548 }
0549 }
0550
0551 static int serial_lpc32xx_request_port(struct uart_port *port)
0552 {
0553 int ret = -ENODEV;
0554
0555 if ((port->iotype == UPIO_MEM32) && (port->mapbase)) {
0556 ret = 0;
0557
0558 if (!request_mem_region(port->mapbase, SZ_4K, MODNAME))
0559 ret = -EBUSY;
0560 else if (port->flags & UPF_IOREMAP) {
0561 port->membase = ioremap(port->mapbase, SZ_4K);
0562 if (!port->membase) {
0563 release_mem_region(port->mapbase, SZ_4K);
0564 ret = -ENOMEM;
0565 }
0566 }
0567 }
0568
0569 return ret;
0570 }
0571
0572 static void serial_lpc32xx_config_port(struct uart_port *port, int uflags)
0573 {
0574 int ret;
0575
0576 ret = serial_lpc32xx_request_port(port);
0577 if (ret < 0)
0578 return;
0579 port->type = PORT_UART00;
0580 port->fifosize = 64;
0581
0582 __serial_uart_flush(port);
0583
0584 writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT |
0585 LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT),
0586 LPC32XX_HSUART_IIR(port->membase));
0587
0588 writel(0xFF, LPC32XX_HSUART_RATE(port->membase));
0589
0590
0591
0592 writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
0593 LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B,
0594 LPC32XX_HSUART_CTRL(port->membase));
0595 }
0596
0597 static int serial_lpc32xx_verify_port(struct uart_port *port,
0598 struct serial_struct *ser)
0599 {
0600 int ret = 0;
0601
0602 if (ser->type != PORT_UART00)
0603 ret = -EINVAL;
0604
0605 return ret;
0606 }
0607
0608 static const struct uart_ops serial_lpc32xx_pops = {
0609 .tx_empty = serial_lpc32xx_tx_empty,
0610 .set_mctrl = serial_lpc32xx_set_mctrl,
0611 .get_mctrl = serial_lpc32xx_get_mctrl,
0612 .stop_tx = serial_lpc32xx_stop_tx,
0613 .start_tx = serial_lpc32xx_start_tx,
0614 .stop_rx = serial_lpc32xx_stop_rx,
0615 .break_ctl = serial_lpc32xx_break_ctl,
0616 .startup = serial_lpc32xx_startup,
0617 .shutdown = serial_lpc32xx_shutdown,
0618 .set_termios = serial_lpc32xx_set_termios,
0619 .type = serial_lpc32xx_type,
0620 .release_port = serial_lpc32xx_release_port,
0621 .request_port = serial_lpc32xx_request_port,
0622 .config_port = serial_lpc32xx_config_port,
0623 .verify_port = serial_lpc32xx_verify_port,
0624 };
0625
0626
0627
0628
0629 static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
0630 {
0631 struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
0632 int ret = 0;
0633 struct resource *res;
0634
0635 if (uarts_registered >= MAX_PORTS) {
0636 dev_err(&pdev->dev,
0637 "Error: Number of possible ports exceeded (%d)!\n",
0638 uarts_registered + 1);
0639 return -ENXIO;
0640 }
0641
0642 memset(p, 0, sizeof(*p));
0643
0644 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0645 if (!res) {
0646 dev_err(&pdev->dev,
0647 "Error getting mem resource for HS UART port %d\n",
0648 uarts_registered);
0649 return -ENXIO;
0650 }
0651 p->port.mapbase = res->start;
0652 p->port.membase = NULL;
0653
0654 ret = platform_get_irq(pdev, 0);
0655 if (ret < 0)
0656 return ret;
0657 p->port.irq = ret;
0658
0659 p->port.iotype = UPIO_MEM32;
0660 p->port.uartclk = LPC32XX_MAIN_OSC_FREQ;
0661 p->port.regshift = 2;
0662 p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
0663 p->port.dev = &pdev->dev;
0664 p->port.ops = &serial_lpc32xx_pops;
0665 p->port.line = uarts_registered++;
0666 spin_lock_init(&p->port.lock);
0667
0668
0669 lpc32xx_loopback_set(p->port.mapbase, 1);
0670
0671 ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port);
0672
0673 platform_set_drvdata(pdev, p);
0674
0675 return ret;
0676 }
0677
0678
0679
0680
0681 static int serial_hs_lpc32xx_remove(struct platform_device *pdev)
0682 {
0683 struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
0684
0685 uart_remove_one_port(&lpc32xx_hs_reg, &p->port);
0686
0687 return 0;
0688 }
0689
0690
0691 #ifdef CONFIG_PM
0692 static int serial_hs_lpc32xx_suspend(struct platform_device *pdev,
0693 pm_message_t state)
0694 {
0695 struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
0696
0697 uart_suspend_port(&lpc32xx_hs_reg, &p->port);
0698
0699 return 0;
0700 }
0701
0702 static int serial_hs_lpc32xx_resume(struct platform_device *pdev)
0703 {
0704 struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
0705
0706 uart_resume_port(&lpc32xx_hs_reg, &p->port);
0707
0708 return 0;
0709 }
0710 #else
0711 #define serial_hs_lpc32xx_suspend NULL
0712 #define serial_hs_lpc32xx_resume NULL
0713 #endif
0714
0715 static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = {
0716 { .compatible = "nxp,lpc3220-hsuart" },
0717 { }
0718 };
0719
0720 MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
0721
0722 static struct platform_driver serial_hs_lpc32xx_driver = {
0723 .probe = serial_hs_lpc32xx_probe,
0724 .remove = serial_hs_lpc32xx_remove,
0725 .suspend = serial_hs_lpc32xx_suspend,
0726 .resume = serial_hs_lpc32xx_resume,
0727 .driver = {
0728 .name = MODNAME,
0729 .of_match_table = serial_hs_lpc32xx_dt_ids,
0730 },
0731 };
0732
0733 static int __init lpc32xx_hsuart_init(void)
0734 {
0735 int ret;
0736
0737 ret = uart_register_driver(&lpc32xx_hs_reg);
0738 if (ret)
0739 return ret;
0740
0741 ret = platform_driver_register(&serial_hs_lpc32xx_driver);
0742 if (ret)
0743 uart_unregister_driver(&lpc32xx_hs_reg);
0744
0745 return ret;
0746 }
0747
0748 static void __exit lpc32xx_hsuart_exit(void)
0749 {
0750 platform_driver_unregister(&serial_hs_lpc32xx_driver);
0751 uart_unregister_driver(&lpc32xx_hs_reg);
0752 }
0753
0754 module_init(lpc32xx_hsuart_init);
0755 module_exit(lpc32xx_hsuart_exit);
0756
0757 MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
0758 MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
0759 MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver");
0760 MODULE_LICENSE("GPL");