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

SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.

Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: alan@lxorguk.ukuu.org.uk
Cc: linux-mips@linux-mips.org
Cc: linux-serial@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/2269/
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

John Crispin and committed by
Ralf Baechle
2f0fc415 935c500c

+765
+8
drivers/tty/serial/Kconfig
··· 1391 1391 help 1392 1392 Support for Console on the NWP serial ports. 1393 1393 1394 + config SERIAL_LANTIQ 1395 + bool "Lantiq serial driver" 1396 + depends on LANTIQ 1397 + select SERIAL_CORE 1398 + select SERIAL_CORE_CONSOLE 1399 + help 1400 + Support for console and UART on Lantiq SoCs. 1401 + 1394 1402 config SERIAL_QE 1395 1403 tristate "Freescale QUICC Engine serial port support" 1396 1404 depends on QUICC_ENGINE
+1
drivers/tty/serial/Makefile
··· 94 94 obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o 95 95 obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o 96 96 obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o 97 + obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
+756
drivers/tty/serial/lantiq.c
··· 1 + /* 2 + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published 6 + * by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program; if not, write to the Free Software 15 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 + * 17 + * Copyright (C) 2004 Infineon IFAP DC COM CPE 18 + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> 19 + * Copyright (C) 2007 John Crispin <blogic@openwrt.org> 20 + * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com> 21 + */ 22 + 23 + #include <linux/slab.h> 24 + #include <linux/module.h> 25 + #include <linux/ioport.h> 26 + #include <linux/init.h> 27 + #include <linux/console.h> 28 + #include <linux/sysrq.h> 29 + #include <linux/device.h> 30 + #include <linux/tty.h> 31 + #include <linux/tty_flip.h> 32 + #include <linux/serial_core.h> 33 + #include <linux/serial.h> 34 + #include <linux/platform_device.h> 35 + #include <linux/io.h> 36 + #include <linux/clk.h> 37 + 38 + #include <lantiq_soc.h> 39 + 40 + #define PORT_LTQ_ASC 111 41 + #define MAXPORTS 2 42 + #define UART_DUMMY_UER_RX 1 43 + #define DRVNAME "ltq_asc" 44 + #ifdef __BIG_ENDIAN 45 + #define LTQ_ASC_TBUF (0x0020 + 3) 46 + #define LTQ_ASC_RBUF (0x0024 + 3) 47 + #else 48 + #define LTQ_ASC_TBUF 0x0020 49 + #define LTQ_ASC_RBUF 0x0024 50 + #endif 51 + #define LTQ_ASC_FSTAT 0x0048 52 + #define LTQ_ASC_WHBSTATE 0x0018 53 + #define LTQ_ASC_STATE 0x0014 54 + #define LTQ_ASC_IRNCR 0x00F8 55 + #define LTQ_ASC_CLC 0x0000 56 + #define LTQ_ASC_ID 0x0008 57 + #define LTQ_ASC_PISEL 0x0004 58 + #define LTQ_ASC_TXFCON 0x0044 59 + #define LTQ_ASC_RXFCON 0x0040 60 + #define LTQ_ASC_CON 0x0010 61 + #define LTQ_ASC_BG 0x0050 62 + #define LTQ_ASC_IRNREN 0x00F4 63 + 64 + #define ASC_IRNREN_TX 0x1 65 + #define ASC_IRNREN_RX 0x2 66 + #define ASC_IRNREN_ERR 0x4 67 + #define ASC_IRNREN_TX_BUF 0x8 68 + #define ASC_IRNCR_TIR 0x1 69 + #define ASC_IRNCR_RIR 0x2 70 + #define ASC_IRNCR_EIR 0x4 71 + 72 + #define ASCOPT_CSIZE 0x3 73 + #define TXFIFO_FL 1 74 + #define RXFIFO_FL 1 75 + #define ASCCLC_DISS 0x2 76 + #define ASCCLC_RMCMASK 0x0000FF00 77 + #define ASCCLC_RMCOFFSET 8 78 + #define ASCCON_M_8ASYNC 0x0 79 + #define ASCCON_M_7ASYNC 0x2 80 + #define ASCCON_ODD 0x00000020 81 + #define ASCCON_STP 0x00000080 82 + #define ASCCON_BRS 0x00000100 83 + #define ASCCON_FDE 0x00000200 84 + #define ASCCON_R 0x00008000 85 + #define ASCCON_FEN 0x00020000 86 + #define ASCCON_ROEN 0x00080000 87 + #define ASCCON_TOEN 0x00100000 88 + #define ASCSTATE_PE 0x00010000 89 + #define ASCSTATE_FE 0x00020000 90 + #define ASCSTATE_ROE 0x00080000 91 + #define ASCSTATE_ANY (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE) 92 + #define ASCWHBSTATE_CLRREN 0x00000001 93 + #define ASCWHBSTATE_SETREN 0x00000002 94 + #define ASCWHBSTATE_CLRPE 0x00000004 95 + #define ASCWHBSTATE_CLRFE 0x00000008 96 + #define ASCWHBSTATE_CLRROE 0x00000020 97 + #define ASCTXFCON_TXFEN 0x0001 98 + #define ASCTXFCON_TXFFLU 0x0002 99 + #define ASCTXFCON_TXFITLMASK 0x3F00 100 + #define ASCTXFCON_TXFITLOFF 8 101 + #define ASCRXFCON_RXFEN 0x0001 102 + #define ASCRXFCON_RXFFLU 0x0002 103 + #define ASCRXFCON_RXFITLMASK 0x3F00 104 + #define ASCRXFCON_RXFITLOFF 8 105 + #define ASCFSTAT_RXFFLMASK 0x003F 106 + #define ASCFSTAT_TXFFLMASK 0x3F00 107 + #define ASCFSTAT_TXFREEMASK 0x3F000000 108 + #define ASCFSTAT_TXFREEOFF 24 109 + 110 + static void lqasc_tx_chars(struct uart_port *port); 111 + static struct ltq_uart_port *lqasc_port[MAXPORTS]; 112 + static struct uart_driver lqasc_reg; 113 + static DEFINE_SPINLOCK(ltq_asc_lock); 114 + 115 + struct ltq_uart_port { 116 + struct uart_port port; 117 + struct clk *clk; 118 + unsigned int tx_irq; 119 + unsigned int rx_irq; 120 + unsigned int err_irq; 121 + }; 122 + 123 + static inline struct 124 + ltq_uart_port *to_ltq_uart_port(struct uart_port *port) 125 + { 126 + return container_of(port, struct ltq_uart_port, port); 127 + } 128 + 129 + static void 130 + lqasc_stop_tx(struct uart_port *port) 131 + { 132 + return; 133 + } 134 + 135 + static void 136 + lqasc_start_tx(struct uart_port *port) 137 + { 138 + unsigned long flags; 139 + spin_lock_irqsave(&ltq_asc_lock, flags); 140 + lqasc_tx_chars(port); 141 + spin_unlock_irqrestore(&ltq_asc_lock, flags); 142 + return; 143 + } 144 + 145 + static void 146 + lqasc_stop_rx(struct uart_port *port) 147 + { 148 + ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); 149 + } 150 + 151 + static void 152 + lqasc_enable_ms(struct uart_port *port) 153 + { 154 + } 155 + 156 + static int 157 + lqasc_rx_chars(struct uart_port *port) 158 + { 159 + struct tty_struct *tty = tty_port_tty_get(&port->state->port); 160 + unsigned int ch = 0, rsr = 0, fifocnt; 161 + 162 + if (!tty) { 163 + dev_dbg(port->dev, "%s:tty is busy now", __func__); 164 + return -EBUSY; 165 + } 166 + fifocnt = 167 + ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; 168 + while (fifocnt--) { 169 + u8 flag = TTY_NORMAL; 170 + ch = ltq_r8(port->membase + LTQ_ASC_RBUF); 171 + rsr = (ltq_r32(port->membase + LTQ_ASC_STATE) 172 + & ASCSTATE_ANY) | UART_DUMMY_UER_RX; 173 + tty_flip_buffer_push(tty); 174 + port->icount.rx++; 175 + 176 + /* 177 + * Note that the error handling code is 178 + * out of the main execution path 179 + */ 180 + if (rsr & ASCSTATE_ANY) { 181 + if (rsr & ASCSTATE_PE) { 182 + port->icount.parity++; 183 + ltq_w32_mask(0, ASCWHBSTATE_CLRPE, 184 + port->membase + LTQ_ASC_WHBSTATE); 185 + } else if (rsr & ASCSTATE_FE) { 186 + port->icount.frame++; 187 + ltq_w32_mask(0, ASCWHBSTATE_CLRFE, 188 + port->membase + LTQ_ASC_WHBSTATE); 189 + } 190 + if (rsr & ASCSTATE_ROE) { 191 + port->icount.overrun++; 192 + ltq_w32_mask(0, ASCWHBSTATE_CLRROE, 193 + port->membase + LTQ_ASC_WHBSTATE); 194 + } 195 + 196 + rsr &= port->read_status_mask; 197 + 198 + if (rsr & ASCSTATE_PE) 199 + flag = TTY_PARITY; 200 + else if (rsr & ASCSTATE_FE) 201 + flag = TTY_FRAME; 202 + } 203 + 204 + if ((rsr & port->ignore_status_mask) == 0) 205 + tty_insert_flip_char(tty, ch, flag); 206 + 207 + if (rsr & ASCSTATE_ROE) 208 + /* 209 + * Overrun is special, since it's reported 210 + * immediately, and doesn't affect the current 211 + * character 212 + */ 213 + tty_insert_flip_char(tty, 0, TTY_OVERRUN); 214 + } 215 + if (ch != 0) 216 + tty_flip_buffer_push(tty); 217 + tty_kref_put(tty); 218 + return 0; 219 + } 220 + 221 + static void 222 + lqasc_tx_chars(struct uart_port *port) 223 + { 224 + struct circ_buf *xmit = &port->state->xmit; 225 + if (uart_tx_stopped(port)) { 226 + lqasc_stop_tx(port); 227 + return; 228 + } 229 + 230 + while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) & 231 + ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) { 232 + if (port->x_char) { 233 + ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF); 234 + port->icount.tx++; 235 + port->x_char = 0; 236 + continue; 237 + } 238 + 239 + if (uart_circ_empty(xmit)) 240 + break; 241 + 242 + ltq_w8(port->state->xmit.buf[port->state->xmit.tail], 243 + port->membase + LTQ_ASC_TBUF); 244 + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 245 + port->icount.tx++; 246 + } 247 + 248 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 249 + uart_write_wakeup(port); 250 + } 251 + 252 + static irqreturn_t 253 + lqasc_tx_int(int irq, void *_port) 254 + { 255 + unsigned long flags; 256 + struct uart_port *port = (struct uart_port *)_port; 257 + spin_lock_irqsave(&ltq_asc_lock, flags); 258 + ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); 259 + spin_unlock_irqrestore(&ltq_asc_lock, flags); 260 + lqasc_start_tx(port); 261 + return IRQ_HANDLED; 262 + } 263 + 264 + static irqreturn_t 265 + lqasc_err_int(int irq, void *_port) 266 + { 267 + unsigned long flags; 268 + struct uart_port *port = (struct uart_port *)_port; 269 + spin_lock_irqsave(&ltq_asc_lock, flags); 270 + /* clear any pending interrupts */ 271 + ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE | 272 + ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE); 273 + spin_unlock_irqrestore(&ltq_asc_lock, flags); 274 + return IRQ_HANDLED; 275 + } 276 + 277 + static irqreturn_t 278 + lqasc_rx_int(int irq, void *_port) 279 + { 280 + unsigned long flags; 281 + struct uart_port *port = (struct uart_port *)_port; 282 + spin_lock_irqsave(&ltq_asc_lock, flags); 283 + ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); 284 + lqasc_rx_chars(port); 285 + spin_unlock_irqrestore(&ltq_asc_lock, flags); 286 + return IRQ_HANDLED; 287 + } 288 + 289 + static unsigned int 290 + lqasc_tx_empty(struct uart_port *port) 291 + { 292 + int status; 293 + status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; 294 + return status ? 0 : TIOCSER_TEMT; 295 + } 296 + 297 + static unsigned int 298 + lqasc_get_mctrl(struct uart_port *port) 299 + { 300 + return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR; 301 + } 302 + 303 + static void 304 + lqasc_set_mctrl(struct uart_port *port, u_int mctrl) 305 + { 306 + } 307 + 308 + static void 309 + lqasc_break_ctl(struct uart_port *port, int break_state) 310 + { 311 + } 312 + 313 + static int 314 + lqasc_startup(struct uart_port *port) 315 + { 316 + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); 317 + int retval; 318 + 319 + port->uartclk = clk_get_rate(ltq_port->clk); 320 + 321 + ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), 322 + port->membase + LTQ_ASC_CLC); 323 + 324 + ltq_w32(0, port->membase + LTQ_ASC_PISEL); 325 + ltq_w32( 326 + ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | 327 + ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, 328 + port->membase + LTQ_ASC_TXFCON); 329 + ltq_w32( 330 + ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) 331 + | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, 332 + port->membase + LTQ_ASC_RXFCON); 333 + /* make sure other settings are written to hardware before 334 + * setting enable bits 335 + */ 336 + wmb(); 337 + ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | 338 + ASCCON_ROEN, port->membase + LTQ_ASC_CON); 339 + 340 + retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, 341 + IRQF_DISABLED, "asc_tx", port); 342 + if (retval) { 343 + pr_err("failed to request lqasc_tx_int\n"); 344 + return retval; 345 + } 346 + 347 + retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, 348 + IRQF_DISABLED, "asc_rx", port); 349 + if (retval) { 350 + pr_err("failed to request lqasc_rx_int\n"); 351 + goto err1; 352 + } 353 + 354 + retval = request_irq(ltq_port->err_irq, lqasc_err_int, 355 + IRQF_DISABLED, "asc_err", port); 356 + if (retval) { 357 + pr_err("failed to request lqasc_err_int\n"); 358 + goto err2; 359 + } 360 + 361 + ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, 362 + port->membase + LTQ_ASC_IRNREN); 363 + return 0; 364 + 365 + err2: 366 + free_irq(ltq_port->rx_irq, port); 367 + err1: 368 + free_irq(ltq_port->tx_irq, port); 369 + return retval; 370 + } 371 + 372 + static void 373 + lqasc_shutdown(struct uart_port *port) 374 + { 375 + struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); 376 + free_irq(ltq_port->tx_irq, port); 377 + free_irq(ltq_port->rx_irq, port); 378 + free_irq(ltq_port->err_irq, port); 379 + 380 + ltq_w32(0, port->membase + LTQ_ASC_CON); 381 + ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU, 382 + port->membase + LTQ_ASC_RXFCON); 383 + ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, 384 + port->membase + LTQ_ASC_TXFCON); 385 + } 386 + 387 + static void 388 + lqasc_set_termios(struct uart_port *port, 389 + struct ktermios *new, struct ktermios *old) 390 + { 391 + unsigned int cflag; 392 + unsigned int iflag; 393 + unsigned int divisor; 394 + unsigned int baud; 395 + unsigned int con = 0; 396 + unsigned long flags; 397 + 398 + cflag = new->c_cflag; 399 + iflag = new->c_iflag; 400 + 401 + switch (cflag & CSIZE) { 402 + case CS7: 403 + con = ASCCON_M_7ASYNC; 404 + break; 405 + 406 + case CS5: 407 + case CS6: 408 + default: 409 + new->c_cflag &= ~ CSIZE; 410 + new->c_cflag |= CS8; 411 + con = ASCCON_M_8ASYNC; 412 + break; 413 + } 414 + 415 + cflag &= ~CMSPAR; /* Mark/Space parity is not supported */ 416 + 417 + if (cflag & CSTOPB) 418 + con |= ASCCON_STP; 419 + 420 + if (cflag & PARENB) { 421 + if (!(cflag & PARODD)) 422 + con &= ~ASCCON_ODD; 423 + else 424 + con |= ASCCON_ODD; 425 + } 426 + 427 + port->read_status_mask = ASCSTATE_ROE; 428 + if (iflag & INPCK) 429 + port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE; 430 + 431 + port->ignore_status_mask = 0; 432 + if (iflag & IGNPAR) 433 + port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE; 434 + 435 + if (iflag & IGNBRK) { 436 + /* 437 + * If we're ignoring parity and break indicators, 438 + * ignore overruns too (for real raw support). 439 + */ 440 + if (iflag & IGNPAR) 441 + port->ignore_status_mask |= ASCSTATE_ROE; 442 + } 443 + 444 + if ((cflag & CREAD) == 0) 445 + port->ignore_status_mask |= UART_DUMMY_UER_RX; 446 + 447 + /* set error signals - framing, parity and overrun, enable receiver */ 448 + con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN; 449 + 450 + spin_lock_irqsave(&ltq_asc_lock, flags); 451 + 452 + /* set up CON */ 453 + ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON); 454 + 455 + /* Set baud rate - take a divider of 2 into account */ 456 + baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); 457 + divisor = uart_get_divisor(port, baud); 458 + divisor = divisor / 2 - 1; 459 + 460 + /* disable the baudrate generator */ 461 + ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON); 462 + 463 + /* make sure the fractional divider is off */ 464 + ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON); 465 + 466 + /* set up to use divisor of 2 */ 467 + ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON); 468 + 469 + /* now we can write the new baudrate into the register */ 470 + ltq_w32(divisor, port->membase + LTQ_ASC_BG); 471 + 472 + /* turn the baudrate generator back on */ 473 + ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON); 474 + 475 + /* enable rx */ 476 + ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); 477 + 478 + spin_unlock_irqrestore(&ltq_asc_lock, flags); 479 + 480 + /* Don't rewrite B0 */ 481 + if (tty_termios_baud_rate(new)) 482 + tty_termios_encode_baud_rate(new, baud, baud); 483 + } 484 + 485 + static const char* 486 + lqasc_type(struct uart_port *port) 487 + { 488 + if (port->type == PORT_LTQ_ASC) 489 + return DRVNAME; 490 + else 491 + return NULL; 492 + } 493 + 494 + static void 495 + lqasc_release_port(struct uart_port *port) 496 + { 497 + if (port->flags & UPF_IOREMAP) { 498 + iounmap(port->membase); 499 + port->membase = NULL; 500 + } 501 + } 502 + 503 + static int 504 + lqasc_request_port(struct uart_port *port) 505 + { 506 + struct platform_device *pdev = to_platform_device(port->dev); 507 + struct resource *res; 508 + int size; 509 + 510 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 511 + if (!res) { 512 + dev_err(&pdev->dev, "cannot obtain I/O memory region"); 513 + return -ENODEV; 514 + } 515 + size = resource_size(res); 516 + 517 + res = devm_request_mem_region(&pdev->dev, res->start, 518 + size, dev_name(&pdev->dev)); 519 + if (!res) { 520 + dev_err(&pdev->dev, "cannot request I/O memory region"); 521 + return -EBUSY; 522 + } 523 + 524 + if (port->flags & UPF_IOREMAP) { 525 + port->membase = devm_ioremap_nocache(&pdev->dev, 526 + port->mapbase, size); 527 + if (port->membase == NULL) 528 + return -ENOMEM; 529 + } 530 + return 0; 531 + } 532 + 533 + static void 534 + lqasc_config_port(struct uart_port *port, int flags) 535 + { 536 + if (flags & UART_CONFIG_TYPE) { 537 + port->type = PORT_LTQ_ASC; 538 + lqasc_request_port(port); 539 + } 540 + } 541 + 542 + static int 543 + lqasc_verify_port(struct uart_port *port, 544 + struct serial_struct *ser) 545 + { 546 + int ret = 0; 547 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC) 548 + ret = -EINVAL; 549 + if (ser->irq < 0 || ser->irq >= NR_IRQS) 550 + ret = -EINVAL; 551 + if (ser->baud_base < 9600) 552 + ret = -EINVAL; 553 + return ret; 554 + } 555 + 556 + static struct uart_ops lqasc_pops = { 557 + .tx_empty = lqasc_tx_empty, 558 + .set_mctrl = lqasc_set_mctrl, 559 + .get_mctrl = lqasc_get_mctrl, 560 + .stop_tx = lqasc_stop_tx, 561 + .start_tx = lqasc_start_tx, 562 + .stop_rx = lqasc_stop_rx, 563 + .enable_ms = lqasc_enable_ms, 564 + .break_ctl = lqasc_break_ctl, 565 + .startup = lqasc_startup, 566 + .shutdown = lqasc_shutdown, 567 + .set_termios = lqasc_set_termios, 568 + .type = lqasc_type, 569 + .release_port = lqasc_release_port, 570 + .request_port = lqasc_request_port, 571 + .config_port = lqasc_config_port, 572 + .verify_port = lqasc_verify_port, 573 + }; 574 + 575 + static void 576 + lqasc_console_putchar(struct uart_port *port, int ch) 577 + { 578 + int fifofree; 579 + 580 + if (!port->membase) 581 + return; 582 + 583 + do { 584 + fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT) 585 + & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF; 586 + } while (fifofree == 0); 587 + ltq_w8(ch, port->membase + LTQ_ASC_TBUF); 588 + } 589 + 590 + 591 + static void 592 + lqasc_console_write(struct console *co, const char *s, u_int count) 593 + { 594 + struct ltq_uart_port *ltq_port; 595 + struct uart_port *port; 596 + unsigned long flags; 597 + 598 + if (co->index >= MAXPORTS) 599 + return; 600 + 601 + ltq_port = lqasc_port[co->index]; 602 + if (!ltq_port) 603 + return; 604 + 605 + port = &ltq_port->port; 606 + 607 + spin_lock_irqsave(&ltq_asc_lock, flags); 608 + uart_console_write(port, s, count, lqasc_console_putchar); 609 + spin_unlock_irqrestore(&ltq_asc_lock, flags); 610 + } 611 + 612 + static int __init 613 + lqasc_console_setup(struct console *co, char *options) 614 + { 615 + struct ltq_uart_port *ltq_port; 616 + struct uart_port *port; 617 + int baud = 115200; 618 + int bits = 8; 619 + int parity = 'n'; 620 + int flow = 'n'; 621 + 622 + if (co->index >= MAXPORTS) 623 + return -ENODEV; 624 + 625 + ltq_port = lqasc_port[co->index]; 626 + if (!ltq_port) 627 + return -ENODEV; 628 + 629 + port = &ltq_port->port; 630 + 631 + port->uartclk = clk_get_rate(ltq_port->clk); 632 + 633 + if (options) 634 + uart_parse_options(options, &baud, &parity, &bits, &flow); 635 + return uart_set_options(port, co, baud, parity, bits, flow); 636 + } 637 + 638 + static struct console lqasc_console = { 639 + .name = "ttyLTQ", 640 + .write = lqasc_console_write, 641 + .device = uart_console_device, 642 + .setup = lqasc_console_setup, 643 + .flags = CON_PRINTBUFFER, 644 + .index = -1, 645 + .data = &lqasc_reg, 646 + }; 647 + 648 + static int __init 649 + lqasc_console_init(void) 650 + { 651 + register_console(&lqasc_console); 652 + return 0; 653 + } 654 + console_initcall(lqasc_console_init); 655 + 656 + static struct uart_driver lqasc_reg = { 657 + .owner = THIS_MODULE, 658 + .driver_name = DRVNAME, 659 + .dev_name = "ttyLTQ", 660 + .major = 0, 661 + .minor = 0, 662 + .nr = MAXPORTS, 663 + .cons = &lqasc_console, 664 + }; 665 + 666 + static int __init 667 + lqasc_probe(struct platform_device *pdev) 668 + { 669 + struct ltq_uart_port *ltq_port; 670 + struct uart_port *port; 671 + struct resource *mmres, *irqres; 672 + int tx_irq, rx_irq, err_irq; 673 + struct clk *clk; 674 + int ret; 675 + 676 + mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); 677 + irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 678 + if (!mmres || !irqres) 679 + return -ENODEV; 680 + 681 + if (pdev->id >= MAXPORTS) 682 + return -EBUSY; 683 + 684 + if (lqasc_port[pdev->id] != NULL) 685 + return -EBUSY; 686 + 687 + clk = clk_get(&pdev->dev, "fpi"); 688 + if (IS_ERR(clk)) { 689 + pr_err("failed to get fpi clk\n"); 690 + return -ENOENT; 691 + } 692 + 693 + tx_irq = platform_get_irq_byname(pdev, "tx"); 694 + rx_irq = platform_get_irq_byname(pdev, "rx"); 695 + err_irq = platform_get_irq_byname(pdev, "err"); 696 + if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0)) 697 + return -ENODEV; 698 + 699 + ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL); 700 + if (!ltq_port) 701 + return -ENOMEM; 702 + 703 + port = &ltq_port->port; 704 + 705 + port->iotype = SERIAL_IO_MEM; 706 + port->flags = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP; 707 + port->ops = &lqasc_pops; 708 + port->fifosize = 16; 709 + port->type = PORT_LTQ_ASC, 710 + port->line = pdev->id; 711 + port->dev = &pdev->dev; 712 + 713 + port->irq = tx_irq; /* unused, just to be backward-compatibe */ 714 + port->mapbase = mmres->start; 715 + 716 + ltq_port->clk = clk; 717 + 718 + ltq_port->tx_irq = tx_irq; 719 + ltq_port->rx_irq = rx_irq; 720 + ltq_port->err_irq = err_irq; 721 + 722 + lqasc_port[pdev->id] = ltq_port; 723 + platform_set_drvdata(pdev, ltq_port); 724 + 725 + ret = uart_add_one_port(&lqasc_reg, port); 726 + 727 + return ret; 728 + } 729 + 730 + static struct platform_driver lqasc_driver = { 731 + .driver = { 732 + .name = DRVNAME, 733 + .owner = THIS_MODULE, 734 + }, 735 + }; 736 + 737 + int __init 738 + init_lqasc(void) 739 + { 740 + int ret; 741 + 742 + ret = uart_register_driver(&lqasc_reg); 743 + if (ret != 0) 744 + return ret; 745 + 746 + ret = platform_driver_probe(&lqasc_driver, lqasc_probe); 747 + if (ret != 0) 748 + uart_unregister_driver(&lqasc_reg); 749 + 750 + return ret; 751 + } 752 + 753 + module_init(init_lqasc); 754 + 755 + MODULE_DESCRIPTION("Lantiq serial port driver"); 756 + MODULE_LICENSE("GPL");