Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: Add driver for LPC32xx High Speed UARTs

This patch adds a driver for the 3 High Speed UARTs of the LPC32xx SoC that
support up to 921600bps. These UARTs are different from the 4 "Standard" UARTs
of the LPC32xx.

Signed-off-by: Roland Stigge <stigge@antcom.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Roland Stigge and committed by
Greg Kroah-Hartman
596f93f5 e4305f0c

+857
+14
Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
··· 1 + * NXP LPC32xx SoC High Speed UART 2 + 3 + Required properties: 4 + - compatible: Should be "nxp,lpc3220-hsuart" 5 + - reg: Should contain registers location and length 6 + - interrupts: Should contain interrupt 7 + 8 + Example: 9 + 10 + uart1: serial@40014000 { 11 + compatible = "nxp,lpc3220-hsuart"; 12 + reg = <0x40014000 0x1000>; 13 + interrupts = <26 0>; 14 + };
+19
drivers/tty/serial/Kconfig
··· 704 704 If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330 705 705 and you want to use serial console, say Y. Otherwise, say N. 706 706 707 + config SERIAL_HS_LPC32XX 708 + tristate "LPC32XX high speed serial port support" 709 + depends on ARCH_LPC32XX && OF 710 + select SERIAL_CORE 711 + help 712 + Support for the LPC32XX high speed serial ports (up to 900kbps). 713 + Those are UARTs completely different from the Standard UARTs on the 714 + LPC32XX SoC. 715 + Choose M or Y here to build this driver. 716 + 717 + config SERIAL_HS_LPC32XX_CONSOLE 718 + bool "Enable LPC32XX high speed UART serial console" 719 + depends on SERIAL_HS_LPC32XX 720 + select SERIAL_CORE_CONSOLE 721 + help 722 + If you would like to be able to use one of the high speed serial 723 + ports on the LPC32XX as the console, you can do so by answering 724 + Y to this option. 725 + 707 726 config SERIAL_CORE 708 727 tristate 709 728
+1
drivers/tty/serial/Makefile
··· 34 34 obj-$(CONFIG_SERIAL_68328) += 68328serial.o 35 35 obj-$(CONFIG_SERIAL_MCF) += mcf.o 36 36 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o 37 + obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o 37 38 obj-$(CONFIG_SERIAL_DZ) += dz.o 38 39 obj-$(CONFIG_SERIAL_ZS) += zs.o 39 40 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
+823
drivers/tty/serial/lpc32xx_hs.c
··· 1 + /* 2 + * High Speed Serial Ports on NXP LPC32xx SoC 3 + * 4 + * Authors: Kevin Wells <kevin.wells@nxp.com> 5 + * Roland Stigge <stigge@antcom.de> 6 + * 7 + * Copyright (C) 2010 NXP Semiconductors 8 + * Copyright (C) 2012 Roland Stigge 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + */ 20 + 21 + #include <linux/module.h> 22 + #include <linux/ioport.h> 23 + #include <linux/init.h> 24 + #include <linux/console.h> 25 + #include <linux/sysrq.h> 26 + #include <linux/tty.h> 27 + #include <linux/tty_flip.h> 28 + #include <linux/serial_core.h> 29 + #include <linux/serial.h> 30 + #include <linux/platform_device.h> 31 + #include <linux/delay.h> 32 + #include <linux/nmi.h> 33 + #include <linux/io.h> 34 + #include <linux/irq.h> 35 + #include <linux/gpio.h> 36 + #include <linux/of.h> 37 + #include <mach/platform.h> 38 + #include <mach/hardware.h> 39 + 40 + /* 41 + * High Speed UART register offsets 42 + */ 43 + #define LPC32XX_HSUART_FIFO(x) ((x) + 0x00) 44 + #define LPC32XX_HSUART_LEVEL(x) ((x) + 0x04) 45 + #define LPC32XX_HSUART_IIR(x) ((x) + 0x08) 46 + #define LPC32XX_HSUART_CTRL(x) ((x) + 0x0C) 47 + #define LPC32XX_HSUART_RATE(x) ((x) + 0x10) 48 + 49 + #define LPC32XX_HSU_BREAK_DATA (1 << 10) 50 + #define LPC32XX_HSU_ERROR_DATA (1 << 9) 51 + #define LPC32XX_HSU_RX_EMPTY (1 << 8) 52 + 53 + #define LPC32XX_HSU_TX_LEV(n) (((n) >> 8) & 0xFF) 54 + #define LPC32XX_HSU_RX_LEV(n) ((n) & 0xFF) 55 + 56 + #define LPC32XX_HSU_TX_INT_SET (1 << 6) 57 + #define LPC32XX_HSU_RX_OE_INT (1 << 5) 58 + #define LPC32XX_HSU_BRK_INT (1 << 4) 59 + #define LPC32XX_HSU_FE_INT (1 << 3) 60 + #define LPC32XX_HSU_RX_TIMEOUT_INT (1 << 2) 61 + #define LPC32XX_HSU_RX_TRIG_INT (1 << 1) 62 + #define LPC32XX_HSU_TX_INT (1 << 0) 63 + 64 + #define LPC32XX_HSU_HRTS_INV (1 << 21) 65 + #define LPC32XX_HSU_HRTS_TRIG_8B (0x0 << 19) 66 + #define LPC32XX_HSU_HRTS_TRIG_16B (0x1 << 19) 67 + #define LPC32XX_HSU_HRTS_TRIG_32B (0x2 << 19) 68 + #define LPC32XX_HSU_HRTS_TRIG_48B (0x3 << 19) 69 + #define LPC32XX_HSU_HRTS_EN (1 << 18) 70 + #define LPC32XX_HSU_TMO_DISABLED (0x0 << 16) 71 + #define LPC32XX_HSU_TMO_INACT_4B (0x1 << 16) 72 + #define LPC32XX_HSU_TMO_INACT_8B (0x2 << 16) 73 + #define LPC32XX_HSU_TMO_INACT_16B (0x3 << 16) 74 + #define LPC32XX_HSU_HCTS_INV (1 << 15) 75 + #define LPC32XX_HSU_HCTS_EN (1 << 14) 76 + #define LPC32XX_HSU_OFFSET(n) ((n) << 9) 77 + #define LPC32XX_HSU_BREAK (1 << 8) 78 + #define LPC32XX_HSU_ERR_INT_EN (1 << 7) 79 + #define LPC32XX_HSU_RX_INT_EN (1 << 6) 80 + #define LPC32XX_HSU_TX_INT_EN (1 << 5) 81 + #define LPC32XX_HSU_RX_TL1B (0x0 << 2) 82 + #define LPC32XX_HSU_RX_TL4B (0x1 << 2) 83 + #define LPC32XX_HSU_RX_TL8B (0x2 << 2) 84 + #define LPC32XX_HSU_RX_TL16B (0x3 << 2) 85 + #define LPC32XX_HSU_RX_TL32B (0x4 << 2) 86 + #define LPC32XX_HSU_RX_TL48B (0x5 << 2) 87 + #define LPC32XX_HSU_TX_TLEMPTY (0x0 << 0) 88 + #define LPC32XX_HSU_TX_TL0B (0x0 << 0) 89 + #define LPC32XX_HSU_TX_TL4B (0x1 << 0) 90 + #define LPC32XX_HSU_TX_TL8B (0x2 << 0) 91 + #define LPC32XX_HSU_TX_TL16B (0x3 << 0) 92 + 93 + #define MODNAME "lpc32xx_hsuart" 94 + 95 + struct lpc32xx_hsuart_port { 96 + struct uart_port port; 97 + }; 98 + 99 + #define FIFO_READ_LIMIT 128 100 + #define MAX_PORTS 3 101 + #define LPC32XX_TTY_NAME "ttyTX" 102 + static struct lpc32xx_hsuart_port lpc32xx_hs_ports[MAX_PORTS]; 103 + 104 + #ifdef CONFIG_SERIAL_HS_LPC32XX_CONSOLE 105 + static void wait_for_xmit_empty(struct uart_port *port) 106 + { 107 + unsigned int timeout = 10000; 108 + 109 + do { 110 + if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL( 111 + port->membase))) == 0) 112 + break; 113 + if (--timeout == 0) 114 + break; 115 + udelay(1); 116 + } while (1); 117 + } 118 + 119 + static void wait_for_xmit_ready(struct uart_port *port) 120 + { 121 + unsigned int timeout = 10000; 122 + 123 + while (1) { 124 + if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL( 125 + port->membase))) < 32) 126 + break; 127 + if (--timeout == 0) 128 + break; 129 + udelay(1); 130 + } 131 + } 132 + 133 + static void lpc32xx_hsuart_console_putchar(struct uart_port *port, int ch) 134 + { 135 + wait_for_xmit_ready(port); 136 + writel((u32)ch, LPC32XX_HSUART_FIFO(port->membase)); 137 + } 138 + 139 + static void lpc32xx_hsuart_console_write(struct console *co, const char *s, 140 + unsigned int count) 141 + { 142 + struct lpc32xx_hsuart_port *up = &lpc32xx_hs_ports[co->index]; 143 + unsigned long flags; 144 + int locked = 1; 145 + 146 + touch_nmi_watchdog(); 147 + local_irq_save(flags); 148 + if (up->port.sysrq) 149 + locked = 0; 150 + else if (oops_in_progress) 151 + locked = spin_trylock(&up->port.lock); 152 + else 153 + spin_lock(&up->port.lock); 154 + 155 + uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); 156 + wait_for_xmit_empty(&up->port); 157 + 158 + if (locked) 159 + spin_unlock(&up->port.lock); 160 + local_irq_restore(flags); 161 + } 162 + 163 + static int __init lpc32xx_hsuart_console_setup(struct console *co, 164 + char *options) 165 + { 166 + struct uart_port *port; 167 + int baud = 115200; 168 + int bits = 8; 169 + int parity = 'n'; 170 + int flow = 'n'; 171 + 172 + if (co->index >= MAX_PORTS) 173 + co->index = 0; 174 + 175 + port = &lpc32xx_hs_ports[co->index].port; 176 + if (!port->membase) 177 + return -ENODEV; 178 + 179 + if (options) 180 + uart_parse_options(options, &baud, &parity, &bits, &flow); 181 + 182 + return uart_set_options(port, co, baud, parity, bits, flow); 183 + } 184 + 185 + static struct uart_driver lpc32xx_hsuart_reg; 186 + static struct console lpc32xx_hsuart_console = { 187 + .name = LPC32XX_TTY_NAME, 188 + .write = lpc32xx_hsuart_console_write, 189 + .device = uart_console_device, 190 + .setup = lpc32xx_hsuart_console_setup, 191 + .flags = CON_PRINTBUFFER, 192 + .index = -1, 193 + .data = &lpc32xx_hsuart_reg, 194 + }; 195 + 196 + static int __init lpc32xx_hsuart_console_init(void) 197 + { 198 + register_console(&lpc32xx_hsuart_console); 199 + return 0; 200 + } 201 + console_initcall(lpc32xx_hsuart_console_init); 202 + 203 + #define LPC32XX_HSUART_CONSOLE (&lpc32xx_hsuart_console) 204 + #else 205 + #define LPC32XX_HSUART_CONSOLE NULL 206 + #endif 207 + 208 + static struct uart_driver lpc32xx_hs_reg = { 209 + .owner = THIS_MODULE, 210 + .driver_name = MODNAME, 211 + .dev_name = LPC32XX_TTY_NAME, 212 + .nr = MAX_PORTS, 213 + .cons = LPC32XX_HSUART_CONSOLE, 214 + }; 215 + static int uarts_registered; 216 + 217 + static unsigned int __serial_get_clock_div(unsigned long uartclk, 218 + unsigned long rate) 219 + { 220 + u32 div, goodrate, hsu_rate, l_hsu_rate, comprate; 221 + u32 rate_diff; 222 + 223 + /* Find the closest divider to get the desired clock rate */ 224 + div = uartclk / rate; 225 + goodrate = hsu_rate = (div / 14) - 1; 226 + if (hsu_rate != 0) 227 + hsu_rate--; 228 + 229 + /* Tweak divider */ 230 + l_hsu_rate = hsu_rate + 3; 231 + rate_diff = 0xFFFFFFFF; 232 + 233 + while (hsu_rate < l_hsu_rate) { 234 + comprate = uartclk / ((hsu_rate + 1) * 14); 235 + if (abs(comprate - rate) < rate_diff) { 236 + goodrate = hsu_rate; 237 + rate_diff = abs(comprate - rate); 238 + } 239 + 240 + hsu_rate++; 241 + } 242 + if (hsu_rate > 0xFF) 243 + hsu_rate = 0xFF; 244 + 245 + return goodrate; 246 + } 247 + 248 + static void __serial_uart_flush(struct uart_port *port) 249 + { 250 + u32 tmp; 251 + int cnt = 0; 252 + 253 + while ((readl(LPC32XX_HSUART_LEVEL(port->membase)) > 0) && 254 + (cnt++ < FIFO_READ_LIMIT)) 255 + tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); 256 + } 257 + 258 + static void __serial_lpc32xx_rx(struct uart_port *port) 259 + { 260 + unsigned int tmp, flag; 261 + struct tty_struct *tty = tty_port_tty_get(&port->state->port); 262 + 263 + if (!tty) { 264 + /* Discard data: no tty available */ 265 + while (!(readl(LPC32XX_HSUART_FIFO(port->membase)) & 266 + LPC32XX_HSU_RX_EMPTY)) 267 + ; 268 + 269 + return; 270 + } 271 + 272 + /* Read data from FIFO and push into terminal */ 273 + tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); 274 + while (!(tmp & LPC32XX_HSU_RX_EMPTY)) { 275 + flag = TTY_NORMAL; 276 + port->icount.rx++; 277 + 278 + if (tmp & LPC32XX_HSU_ERROR_DATA) { 279 + /* Framing error */ 280 + writel(LPC32XX_HSU_FE_INT, 281 + LPC32XX_HSUART_IIR(port->membase)); 282 + port->icount.frame++; 283 + flag = TTY_FRAME; 284 + tty_insert_flip_char(tty, 0, TTY_FRAME); 285 + } 286 + 287 + tty_insert_flip_char(tty, (tmp & 0xFF), flag); 288 + 289 + tmp = readl(LPC32XX_HSUART_FIFO(port->membase)); 290 + } 291 + tty_flip_buffer_push(tty); 292 + tty_kref_put(tty); 293 + } 294 + 295 + static void __serial_lpc32xx_tx(struct uart_port *port) 296 + { 297 + struct circ_buf *xmit = &port->state->xmit; 298 + unsigned int tmp; 299 + 300 + if (port->x_char) { 301 + writel((u32)port->x_char, LPC32XX_HSUART_FIFO(port->membase)); 302 + port->icount.tx++; 303 + port->x_char = 0; 304 + return; 305 + } 306 + 307 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) 308 + goto exit_tx; 309 + 310 + /* Transfer data */ 311 + while (LPC32XX_HSU_TX_LEV(readl( 312 + LPC32XX_HSUART_LEVEL(port->membase))) < 64) { 313 + writel((u32) xmit->buf[xmit->tail], 314 + LPC32XX_HSUART_FIFO(port->membase)); 315 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 316 + port->icount.tx++; 317 + if (uart_circ_empty(xmit)) 318 + break; 319 + } 320 + 321 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 322 + uart_write_wakeup(port); 323 + 324 + exit_tx: 325 + if (uart_circ_empty(xmit)) { 326 + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); 327 + tmp &= ~LPC32XX_HSU_TX_INT_EN; 328 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 329 + } 330 + } 331 + 332 + static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) 333 + { 334 + struct uart_port *port = dev_id; 335 + struct tty_struct *tty = tty_port_tty_get(&port->state->port); 336 + u32 status; 337 + 338 + spin_lock(&port->lock); 339 + 340 + /* Read UART status and clear latched interrupts */ 341 + status = readl(LPC32XX_HSUART_IIR(port->membase)); 342 + 343 + if (status & LPC32XX_HSU_BRK_INT) { 344 + /* Break received */ 345 + writel(LPC32XX_HSU_BRK_INT, LPC32XX_HSUART_IIR(port->membase)); 346 + port->icount.brk++; 347 + uart_handle_break(port); 348 + } 349 + 350 + /* Framing error */ 351 + if (status & LPC32XX_HSU_FE_INT) 352 + writel(LPC32XX_HSU_FE_INT, LPC32XX_HSUART_IIR(port->membase)); 353 + 354 + if (status & LPC32XX_HSU_RX_OE_INT) { 355 + /* Receive FIFO overrun */ 356 + writel(LPC32XX_HSU_RX_OE_INT, 357 + LPC32XX_HSUART_IIR(port->membase)); 358 + port->icount.overrun++; 359 + if (tty) { 360 + tty_insert_flip_char(tty, 0, TTY_OVERRUN); 361 + tty_schedule_flip(tty); 362 + } 363 + } 364 + 365 + /* Data received? */ 366 + if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) { 367 + __serial_lpc32xx_rx(port); 368 + if (tty) 369 + tty_flip_buffer_push(tty); 370 + } 371 + 372 + /* Transmit data request? */ 373 + if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) { 374 + writel(LPC32XX_HSU_TX_INT, LPC32XX_HSUART_IIR(port->membase)); 375 + __serial_lpc32xx_tx(port); 376 + } 377 + 378 + spin_unlock(&port->lock); 379 + tty_kref_put(tty); 380 + 381 + return IRQ_HANDLED; 382 + } 383 + 384 + /* port->lock is not held. */ 385 + static unsigned int serial_lpc32xx_tx_empty(struct uart_port *port) 386 + { 387 + unsigned int ret = 0; 388 + 389 + if (LPC32XX_HSU_TX_LEV(readl(LPC32XX_HSUART_LEVEL(port->membase))) == 0) 390 + ret = TIOCSER_TEMT; 391 + 392 + return ret; 393 + } 394 + 395 + /* port->lock held by caller. */ 396 + static void serial_lpc32xx_set_mctrl(struct uart_port *port, 397 + unsigned int mctrl) 398 + { 399 + /* No signals are supported on HS UARTs */ 400 + } 401 + 402 + /* port->lock is held by caller and interrupts are disabled. */ 403 + static unsigned int serial_lpc32xx_get_mctrl(struct uart_port *port) 404 + { 405 + /* No signals are supported on HS UARTs */ 406 + return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; 407 + } 408 + 409 + /* port->lock held by caller. */ 410 + static void serial_lpc32xx_stop_tx(struct uart_port *port) 411 + { 412 + u32 tmp; 413 + 414 + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); 415 + tmp &= ~LPC32XX_HSU_TX_INT_EN; 416 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 417 + } 418 + 419 + /* port->lock held by caller. */ 420 + static void serial_lpc32xx_start_tx(struct uart_port *port) 421 + { 422 + u32 tmp; 423 + 424 + __serial_lpc32xx_tx(port); 425 + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); 426 + tmp |= LPC32XX_HSU_TX_INT_EN; 427 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 428 + } 429 + 430 + /* port->lock held by caller. */ 431 + static void serial_lpc32xx_stop_rx(struct uart_port *port) 432 + { 433 + u32 tmp; 434 + 435 + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); 436 + tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN); 437 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 438 + 439 + writel((LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT | 440 + LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase)); 441 + } 442 + 443 + /* port->lock held by caller. */ 444 + static void serial_lpc32xx_enable_ms(struct uart_port *port) 445 + { 446 + /* Modem status is not supported */ 447 + } 448 + 449 + /* port->lock is not held. */ 450 + static void serial_lpc32xx_break_ctl(struct uart_port *port, 451 + int break_state) 452 + { 453 + unsigned long flags; 454 + u32 tmp; 455 + 456 + spin_lock_irqsave(&port->lock, flags); 457 + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); 458 + if (break_state != 0) 459 + tmp |= LPC32XX_HSU_BREAK; 460 + else 461 + tmp &= ~LPC32XX_HSU_BREAK; 462 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 463 + spin_unlock_irqrestore(&port->lock, flags); 464 + } 465 + 466 + /* LPC3250 Errata HSUART.1: Hang workaround via loopback mode on inactivity */ 467 + static void lpc32xx_loopback_set(resource_size_t mapbase, int state) 468 + { 469 + int bit; 470 + u32 tmp; 471 + 472 + switch (mapbase) { 473 + case LPC32XX_HS_UART1_BASE: 474 + bit = 0; 475 + break; 476 + case LPC32XX_HS_UART2_BASE: 477 + bit = 1; 478 + break; 479 + case LPC32XX_HS_UART7_BASE: 480 + bit = 6; 481 + break; 482 + default: 483 + WARN(1, "lpc32xx_hs: Warning: Unknown port at %08x\n", mapbase); 484 + return; 485 + } 486 + 487 + tmp = readl(LPC32XX_UARTCTL_CLOOP); 488 + if (state) 489 + tmp |= (1 << bit); 490 + else 491 + tmp &= ~(1 << bit); 492 + writel(tmp, LPC32XX_UARTCTL_CLOOP); 493 + } 494 + 495 + /* port->lock is not held. */ 496 + static int serial_lpc32xx_startup(struct uart_port *port) 497 + { 498 + int retval; 499 + unsigned long flags; 500 + u32 tmp; 501 + 502 + spin_lock_irqsave(&port->lock, flags); 503 + 504 + __serial_uart_flush(port); 505 + 506 + writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT | 507 + LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT), 508 + LPC32XX_HSUART_IIR(port->membase)); 509 + 510 + writel(0xFF, LPC32XX_HSUART_RATE(port->membase)); 511 + 512 + /* 513 + * Set receiver timeout, HSU offset of 20, no break, no interrupts, 514 + * and default FIFO trigger levels 515 + */ 516 + tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | 517 + LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; 518 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 519 + 520 + lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */ 521 + 522 + spin_unlock_irqrestore(&port->lock, flags); 523 + 524 + retval = request_irq(port->irq, serial_lpc32xx_interrupt, 525 + 0, MODNAME, port); 526 + if (!retval) 527 + writel((tmp | LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN), 528 + LPC32XX_HSUART_CTRL(port->membase)); 529 + 530 + return retval; 531 + } 532 + 533 + /* port->lock is not held. */ 534 + static void serial_lpc32xx_shutdown(struct uart_port *port) 535 + { 536 + u32 tmp; 537 + unsigned long flags; 538 + 539 + spin_lock_irqsave(&port->lock, flags); 540 + 541 + tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | 542 + LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; 543 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 544 + 545 + lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */ 546 + 547 + spin_unlock_irqrestore(&port->lock, flags); 548 + 549 + free_irq(port->irq, port); 550 + } 551 + 552 + /* port->lock is not held. */ 553 + static void serial_lpc32xx_set_termios(struct uart_port *port, 554 + struct ktermios *termios, 555 + struct ktermios *old) 556 + { 557 + unsigned long flags; 558 + unsigned int baud, quot; 559 + u32 tmp; 560 + 561 + /* Always 8-bit, no parity, 1 stop bit */ 562 + termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD); 563 + termios->c_cflag |= CS8; 564 + 565 + termios->c_cflag &= ~(HUPCL | CMSPAR | CLOCAL | CRTSCTS); 566 + 567 + baud = uart_get_baud_rate(port, termios, old, 0, 568 + port->uartclk / 14); 569 + 570 + quot = __serial_get_clock_div(port->uartclk, baud); 571 + 572 + spin_lock_irqsave(&port->lock, flags); 573 + 574 + /* Ignore characters? */ 575 + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); 576 + if ((termios->c_cflag & CREAD) == 0) 577 + tmp &= ~(LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN); 578 + else 579 + tmp |= LPC32XX_HSU_RX_INT_EN | LPC32XX_HSU_ERR_INT_EN; 580 + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); 581 + 582 + writel(quot, LPC32XX_HSUART_RATE(port->membase)); 583 + 584 + uart_update_timeout(port, termios->c_cflag, baud); 585 + 586 + spin_unlock_irqrestore(&port->lock, flags); 587 + 588 + /* Don't rewrite B0 */ 589 + if (tty_termios_baud_rate(termios)) 590 + tty_termios_encode_baud_rate(termios, baud, baud); 591 + } 592 + 593 + static const char *serial_lpc32xx_type(struct uart_port *port) 594 + { 595 + return MODNAME; 596 + } 597 + 598 + static void serial_lpc32xx_release_port(struct uart_port *port) 599 + { 600 + if ((port->iotype == UPIO_MEM32) && (port->mapbase)) { 601 + if (port->flags & UPF_IOREMAP) { 602 + iounmap(port->membase); 603 + port->membase = NULL; 604 + } 605 + 606 + release_mem_region(port->mapbase, SZ_4K); 607 + } 608 + } 609 + 610 + static int serial_lpc32xx_request_port(struct uart_port *port) 611 + { 612 + int ret = -ENODEV; 613 + 614 + if ((port->iotype == UPIO_MEM32) && (port->mapbase)) { 615 + ret = 0; 616 + 617 + if (!request_mem_region(port->mapbase, SZ_4K, MODNAME)) 618 + ret = -EBUSY; 619 + else if (port->flags & UPF_IOREMAP) { 620 + port->membase = ioremap(port->mapbase, SZ_4K); 621 + if (!port->membase) { 622 + release_mem_region(port->mapbase, SZ_4K); 623 + ret = -ENOMEM; 624 + } 625 + } 626 + } 627 + 628 + return ret; 629 + } 630 + 631 + static void serial_lpc32xx_config_port(struct uart_port *port, int uflags) 632 + { 633 + int ret; 634 + 635 + ret = serial_lpc32xx_request_port(port); 636 + if (ret < 0) 637 + return; 638 + port->type = PORT_UART00; 639 + port->fifosize = 64; 640 + 641 + __serial_uart_flush(port); 642 + 643 + writel((LPC32XX_HSU_TX_INT | LPC32XX_HSU_FE_INT | 644 + LPC32XX_HSU_BRK_INT | LPC32XX_HSU_RX_OE_INT), 645 + LPC32XX_HSUART_IIR(port->membase)); 646 + 647 + writel(0xFF, LPC32XX_HSUART_RATE(port->membase)); 648 + 649 + /* Set receiver timeout, HSU offset of 20, no break, no interrupts, 650 + and default FIFO trigger levels */ 651 + writel(LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | 652 + LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B, 653 + LPC32XX_HSUART_CTRL(port->membase)); 654 + } 655 + 656 + static int serial_lpc32xx_verify_port(struct uart_port *port, 657 + struct serial_struct *ser) 658 + { 659 + int ret = 0; 660 + 661 + if (ser->type != PORT_UART00) 662 + ret = -EINVAL; 663 + 664 + return ret; 665 + } 666 + 667 + static struct uart_ops serial_lpc32xx_pops = { 668 + .tx_empty = serial_lpc32xx_tx_empty, 669 + .set_mctrl = serial_lpc32xx_set_mctrl, 670 + .get_mctrl = serial_lpc32xx_get_mctrl, 671 + .stop_tx = serial_lpc32xx_stop_tx, 672 + .start_tx = serial_lpc32xx_start_tx, 673 + .stop_rx = serial_lpc32xx_stop_rx, 674 + .enable_ms = serial_lpc32xx_enable_ms, 675 + .break_ctl = serial_lpc32xx_break_ctl, 676 + .startup = serial_lpc32xx_startup, 677 + .shutdown = serial_lpc32xx_shutdown, 678 + .set_termios = serial_lpc32xx_set_termios, 679 + .type = serial_lpc32xx_type, 680 + .release_port = serial_lpc32xx_release_port, 681 + .request_port = serial_lpc32xx_request_port, 682 + .config_port = serial_lpc32xx_config_port, 683 + .verify_port = serial_lpc32xx_verify_port, 684 + }; 685 + 686 + /* 687 + * Register a set of serial devices attached to a platform device 688 + */ 689 + static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev) 690 + { 691 + struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered]; 692 + int ret = 0; 693 + struct resource *res; 694 + 695 + if (uarts_registered >= MAX_PORTS) { 696 + dev_err(&pdev->dev, 697 + "Error: Number of possible ports exceeded (%d)!\n", 698 + uarts_registered + 1); 699 + return -ENXIO; 700 + } 701 + 702 + memset(p, 0, sizeof(*p)); 703 + 704 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 705 + if (!res) { 706 + dev_err(&pdev->dev, 707 + "Error getting mem resource for HS UART port %d\n", 708 + uarts_registered); 709 + return -ENXIO; 710 + } 711 + p->port.mapbase = res->start; 712 + p->port.membase = NULL; 713 + 714 + p->port.irq = platform_get_irq(pdev, 0); 715 + if (p->port.irq < 0) { 716 + dev_err(&pdev->dev, "Error getting irq for HS UART port %d\n", 717 + uarts_registered); 718 + return p->port.irq; 719 + } 720 + 721 + p->port.iotype = UPIO_MEM32; 722 + p->port.uartclk = LPC32XX_MAIN_OSC_FREQ; 723 + p->port.regshift = 2; 724 + p->port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; 725 + p->port.dev = &pdev->dev; 726 + p->port.ops = &serial_lpc32xx_pops; 727 + p->port.line = uarts_registered++; 728 + spin_lock_init(&p->port.lock); 729 + 730 + /* send port to loopback mode by default */ 731 + lpc32xx_loopback_set(p->port.mapbase, 1); 732 + 733 + ret = uart_add_one_port(&lpc32xx_hs_reg, &p->port); 734 + 735 + platform_set_drvdata(pdev, p); 736 + 737 + return ret; 738 + } 739 + 740 + /* 741 + * Remove serial ports registered against a platform device. 742 + */ 743 + static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev) 744 + { 745 + struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); 746 + 747 + uart_remove_one_port(&lpc32xx_hs_reg, &p->port); 748 + 749 + return 0; 750 + } 751 + 752 + 753 + #ifdef CONFIG_PM 754 + static int serial_hs_lpc32xx_suspend(struct platform_device *pdev, 755 + pm_message_t state) 756 + { 757 + struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); 758 + 759 + uart_suspend_port(&lpc32xx_hs_reg, &p->port); 760 + 761 + return 0; 762 + } 763 + 764 + static int serial_hs_lpc32xx_resume(struct platform_device *pdev) 765 + { 766 + struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev); 767 + 768 + uart_resume_port(&lpc32xx_hs_reg, &p->port); 769 + 770 + return 0; 771 + } 772 + #else 773 + #define serial_hs_lpc32xx_suspend NULL 774 + #define serial_hs_lpc32xx_resume NULL 775 + #endif 776 + 777 + static const struct of_device_id serial_hs_lpc32xx_dt_ids[] = { 778 + { .compatible = "nxp,lpc3220-hsuart" }, 779 + { /* sentinel */ } 780 + }; 781 + 782 + MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids); 783 + 784 + static struct platform_driver serial_hs_lpc32xx_driver = { 785 + .probe = serial_hs_lpc32xx_probe, 786 + .remove = __devexit_p(serial_hs_lpc32xx_remove), 787 + .suspend = serial_hs_lpc32xx_suspend, 788 + .resume = serial_hs_lpc32xx_resume, 789 + .driver = { 790 + .name = MODNAME, 791 + .owner = THIS_MODULE, 792 + .of_match_table = serial_hs_lpc32xx_dt_ids, 793 + }, 794 + }; 795 + 796 + static int __init lpc32xx_hsuart_init(void) 797 + { 798 + int ret; 799 + 800 + ret = uart_register_driver(&lpc32xx_hs_reg); 801 + if (ret) 802 + return ret; 803 + 804 + ret = platform_driver_register(&serial_hs_lpc32xx_driver); 805 + if (ret) 806 + uart_unregister_driver(&lpc32xx_hs_reg); 807 + 808 + return ret; 809 + } 810 + 811 + static void __exit lpc32xx_hsuart_exit(void) 812 + { 813 + platform_driver_unregister(&serial_hs_lpc32xx_driver); 814 + uart_unregister_driver(&lpc32xx_hs_reg); 815 + } 816 + 817 + module_init(lpc32xx_hsuart_init); 818 + module_exit(lpc32xx_hsuart_exit); 819 + 820 + MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); 821 + MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); 822 + MODULE_DESCRIPTION("NXP LPC32XX High Speed UART driver"); 823 + MODULE_LICENSE("GPL");