1/* 2 * UART driver for PNX8XXX SoCs 3 * 4 * Author: Per Hallsmark per.hallsmark@mvista.com 5 * Ported to 2.6 kernel by EmbeddedAlley 6 * Reworked by Vitaly Wool <vitalywool@gmail.com> 7 * 8 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 9 * Copyright (C) 2000 Deep Blue Solutions Ltd. 10 * 11 * This file is licensed under the terms of the GNU General Public License 12 * version 2. This program is licensed "as is" without any warranty of 13 * any kind, whether express or implied. 14 * 15 */ 16 17#if defined(CONFIG_SERIAL_PNX8XXX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 18#define SUPPORT_SYSRQ 19#endif 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/device.h> 27#include <linux/platform_device.h> 28#include <linux/tty.h> 29#include <linux/tty_flip.h> 30#include <linux/serial_core.h> 31#include <linux/serial.h> 32#include <linux/serial_pnx8xxx.h> 33 34#include <asm/io.h> 35#include <asm/irq.h> 36 37/* We'll be using StrongARM sa1100 serial port major/minor */ 38#define SERIAL_PNX8XXX_MAJOR 204 39#define MINOR_START 5 40 41#define NR_PORTS 2 42 43#define PNX8XXX_ISR_PASS_LIMIT 256 44 45/* 46 * Convert from ignore_status_mask or read_status_mask to FIFO 47 * and interrupt status bits 48 */ 49#define SM_TO_FIFO(x) ((x) >> 10) 50#define SM_TO_ISTAT(x) ((x) & 0x000001ff) 51#define FIFO_TO_SM(x) ((x) << 10) 52#define ISTAT_TO_SM(x) ((x) & 0x000001ff) 53 54/* 55 * This is the size of our serial port register set. 56 */ 57#define UART_PORT_SIZE 0x1000 58 59/* 60 * This determines how often we check the modem status signals 61 * for any change. They generally aren't connected to an IRQ 62 * so we have to poll them. We also check immediately before 63 * filling the TX fifo incase CTS has been dropped. 64 */ 65#define MCTRL_TIMEOUT (250*HZ/1000) 66 67extern struct pnx8xxx_port pnx8xxx_ports[]; 68 69static inline int serial_in(struct pnx8xxx_port *sport, int offset) 70{ 71 return (__raw_readl(sport->port.membase + offset)); 72} 73 74static inline void serial_out(struct pnx8xxx_port *sport, int offset, int value) 75{ 76 __raw_writel(value, sport->port.membase + offset); 77} 78 79/* 80 * Handle any change of modem status signal since we were last called. 81 */ 82static void pnx8xxx_mctrl_check(struct pnx8xxx_port *sport) 83{ 84 unsigned int status, changed; 85 86 status = sport->port.ops->get_mctrl(&sport->port); 87 changed = status ^ sport->old_status; 88 89 if (changed == 0) 90 return; 91 92 sport->old_status = status; 93 94 if (changed & TIOCM_RI) 95 sport->port.icount.rng++; 96 if (changed & TIOCM_DSR) 97 sport->port.icount.dsr++; 98 if (changed & TIOCM_CAR) 99 uart_handle_dcd_change(&sport->port, status & TIOCM_CAR); 100 if (changed & TIOCM_CTS) 101 uart_handle_cts_change(&sport->port, status & TIOCM_CTS); 102 103 wake_up_interruptible(&sport->port.info->delta_msr_wait); 104} 105 106/* 107 * This is our per-port timeout handler, for checking the 108 * modem status signals. 109 */ 110static void pnx8xxx_timeout(unsigned long data) 111{ 112 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)data; 113 unsigned long flags; 114 115 if (sport->port.info) { 116 spin_lock_irqsave(&sport->port.lock, flags); 117 pnx8xxx_mctrl_check(sport); 118 spin_unlock_irqrestore(&sport->port.lock, flags); 119 120 mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); 121 } 122} 123 124/* 125 * interrupts disabled on entry 126 */ 127static void pnx8xxx_stop_tx(struct uart_port *port) 128{ 129 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 130 u32 ien; 131 132 /* Disable TX intr */ 133 ien = serial_in(sport, PNX8XXX_IEN); 134 serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLTX); 135 136 /* Clear all pending TX intr */ 137 serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX); 138} 139 140/* 141 * interrupts may not be disabled on entry 142 */ 143static void pnx8xxx_start_tx(struct uart_port *port) 144{ 145 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 146 u32 ien; 147 148 /* Clear all pending TX intr */ 149 serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX); 150 151 /* Enable TX intr */ 152 ien = serial_in(sport, PNX8XXX_IEN); 153 serial_out(sport, PNX8XXX_IEN, ien | PNX8XXX_UART_INT_ALLTX); 154} 155 156/* 157 * Interrupts enabled 158 */ 159static void pnx8xxx_stop_rx(struct uart_port *port) 160{ 161 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 162 u32 ien; 163 164 /* Disable RX intr */ 165 ien = serial_in(sport, PNX8XXX_IEN); 166 serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLRX); 167 168 /* Clear all pending RX intr */ 169 serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX); 170} 171 172/* 173 * Set the modem control timer to fire immediately. 174 */ 175static void pnx8xxx_enable_ms(struct uart_port *port) 176{ 177 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 178 179 mod_timer(&sport->timer, jiffies); 180} 181 182static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport) 183{ 184 struct tty_struct *tty = sport->port.info->tty; 185 unsigned int status, ch, flg; 186 187 status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) | 188 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT)); 189 while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) { 190 ch = serial_in(sport, PNX8XXX_FIFO); 191 192 sport->port.icount.rx++; 193 194 flg = TTY_NORMAL; 195 196 /* 197 * note that the error handling code is 198 * out of the main execution path 199 */ 200 if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE | 201 PNX8XXX_UART_FIFO_RXPAR) | 202 ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) { 203 if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)) 204 sport->port.icount.parity++; 205 else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE)) 206 sport->port.icount.frame++; 207 if (status & ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN)) 208 sport->port.icount.overrun++; 209 210 status &= sport->port.read_status_mask; 211 212 if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)) 213 flg = TTY_PARITY; 214 else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE)) 215 flg = TTY_FRAME; 216 217#ifdef SUPPORT_SYSRQ 218 sport->port.sysrq = 0; 219#endif 220 } 221 222 if (uart_handle_sysrq_char(&sport->port, ch)) 223 goto ignore_char; 224 225 uart_insert_char(&sport->port, status, 226 ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN), ch, flg); 227 228 ignore_char: 229 serial_out(sport, PNX8XXX_LCR, serial_in(sport, PNX8XXX_LCR) | 230 PNX8XXX_UART_LCR_RX_NEXT); 231 status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) | 232 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT)); 233 } 234 tty_flip_buffer_push(tty); 235} 236 237static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport) 238{ 239 struct circ_buf *xmit = &sport->port.info->xmit; 240 241 if (sport->port.x_char) { 242 serial_out(sport, PNX8XXX_FIFO, sport->port.x_char); 243 sport->port.icount.tx++; 244 sport->port.x_char = 0; 245 return; 246 } 247 248 /* 249 * Check the modem control lines before 250 * transmitting anything. 251 */ 252 pnx8xxx_mctrl_check(sport); 253 254 if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { 255 pnx8xxx_stop_tx(&sport->port); 256 return; 257 } 258 259 /* 260 * TX while bytes available 261 */ 262 while (((serial_in(sport, PNX8XXX_FIFO) & 263 PNX8XXX_UART_FIFO_TXFIFO) >> 16) < 16) { 264 serial_out(sport, PNX8XXX_FIFO, xmit->buf[xmit->tail]); 265 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 266 sport->port.icount.tx++; 267 if (uart_circ_empty(xmit)) 268 break; 269 } 270 271 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 272 uart_write_wakeup(&sport->port); 273 274 if (uart_circ_empty(xmit)) 275 pnx8xxx_stop_tx(&sport->port); 276} 277 278static irqreturn_t pnx8xxx_int(int irq, void *dev_id) 279{ 280 struct pnx8xxx_port *sport = dev_id; 281 unsigned int status; 282 283 spin_lock(&sport->port.lock); 284 /* Get the interrupts */ 285 status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN); 286 287 /* Break signal received */ 288 if (status & PNX8XXX_UART_INT_BREAK) { 289 sport->port.icount.brk++; 290 uart_handle_break(&sport->port); 291 } 292 293 /* Byte received */ 294 if (status & PNX8XXX_UART_INT_RX) 295 pnx8xxx_rx_chars(sport); 296 297 /* TX holding register empty - transmit a byte */ 298 if (status & PNX8XXX_UART_INT_TX) 299 pnx8xxx_tx_chars(sport); 300 301 /* Clear the ISTAT register */ 302 serial_out(sport, PNX8XXX_ICLR, status); 303 304 spin_unlock(&sport->port.lock); 305 return IRQ_HANDLED; 306} 307 308/* 309 * Return TIOCSER_TEMT when transmitter is not busy. 310 */ 311static unsigned int pnx8xxx_tx_empty(struct uart_port *port) 312{ 313 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 314 315 return serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA ? 0 : TIOCSER_TEMT; 316} 317 318static unsigned int pnx8xxx_get_mctrl(struct uart_port *port) 319{ 320 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 321 unsigned int mctrl = TIOCM_DSR; 322 unsigned int msr; 323 324 /* REVISIT */ 325 326 msr = serial_in(sport, PNX8XXX_MCR); 327 328 mctrl |= msr & PNX8XXX_UART_MCR_CTS ? TIOCM_CTS : 0; 329 mctrl |= msr & PNX8XXX_UART_MCR_DCD ? TIOCM_CAR : 0; 330 331 return mctrl; 332} 333 334static void pnx8xxx_set_mctrl(struct uart_port *port, unsigned int mctrl) 335{ 336} 337 338/* 339 * Interrupts always disabled. 340 */ 341static void pnx8xxx_break_ctl(struct uart_port *port, int break_state) 342{ 343 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 344 unsigned long flags; 345 unsigned int lcr; 346 347 spin_lock_irqsave(&sport->port.lock, flags); 348 lcr = serial_in(sport, PNX8XXX_LCR); 349 if (break_state == -1) 350 lcr |= PNX8XXX_UART_LCR_TXBREAK; 351 else 352 lcr &= ~PNX8XXX_UART_LCR_TXBREAK; 353 serial_out(sport, PNX8XXX_LCR, lcr); 354 spin_unlock_irqrestore(&sport->port.lock, flags); 355} 356 357static int pnx8xxx_startup(struct uart_port *port) 358{ 359 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 360 int retval; 361 362 /* 363 * Allocate the IRQ 364 */ 365 retval = request_irq(sport->port.irq, pnx8xxx_int, 0, 366 "pnx8xxx-uart", sport); 367 if (retval) 368 return retval; 369 370 /* 371 * Finally, clear and enable interrupts 372 */ 373 374 serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX | 375 PNX8XXX_UART_INT_ALLTX); 376 377 serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) | 378 PNX8XXX_UART_INT_ALLRX | 379 PNX8XXX_UART_INT_ALLTX); 380 381 /* 382 * Enable modem status interrupts 383 */ 384 spin_lock_irq(&sport->port.lock); 385 pnx8xxx_enable_ms(&sport->port); 386 spin_unlock_irq(&sport->port.lock); 387 388 return 0; 389} 390 391static void pnx8xxx_shutdown(struct uart_port *port) 392{ 393 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 394 int lcr; 395 396 /* 397 * Stop our timer. 398 */ 399 del_timer_sync(&sport->timer); 400 401 /* 402 * Disable all interrupts 403 */ 404 serial_out(sport, PNX8XXX_IEN, 0); 405 406 /* 407 * Reset the Tx and Rx FIFOS, disable the break condition 408 */ 409 lcr = serial_in(sport, PNX8XXX_LCR); 410 lcr &= ~PNX8XXX_UART_LCR_TXBREAK; 411 lcr |= PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST; 412 serial_out(sport, PNX8XXX_LCR, lcr); 413 414 /* 415 * Clear all interrupts 416 */ 417 serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX | 418 PNX8XXX_UART_INT_ALLTX); 419 420 /* 421 * Free the interrupt 422 */ 423 free_irq(sport->port.irq, sport); 424} 425 426static void 427pnx8xxx_set_termios(struct uart_port *port, struct ktermios *termios, 428 struct ktermios *old) 429{ 430 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 431 unsigned long flags; 432 unsigned int lcr_fcr, old_ien, baud, quot; 433 unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; 434 435 /* 436 * We only support CS7 and CS8. 437 */ 438 while ((termios->c_cflag & CSIZE) != CS7 && 439 (termios->c_cflag & CSIZE) != CS8) { 440 termios->c_cflag &= ~CSIZE; 441 termios->c_cflag |= old_csize; 442 old_csize = CS8; 443 } 444 445 if ((termios->c_cflag & CSIZE) == CS8) 446 lcr_fcr = PNX8XXX_UART_LCR_8BIT; 447 else 448 lcr_fcr = 0; 449 450 if (termios->c_cflag & CSTOPB) 451 lcr_fcr |= PNX8XXX_UART_LCR_2STOPB; 452 if (termios->c_cflag & PARENB) { 453 lcr_fcr |= PNX8XXX_UART_LCR_PAREN; 454 if (!(termios->c_cflag & PARODD)) 455 lcr_fcr |= PNX8XXX_UART_LCR_PAREVN; 456 } 457 458 /* 459 * Ask the core to calculate the divisor for us. 460 */ 461 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 462 quot = uart_get_divisor(port, baud); 463 464 spin_lock_irqsave(&sport->port.lock, flags); 465 466 sport->port.read_status_mask = ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN) | 467 ISTAT_TO_SM(PNX8XXX_UART_INT_EMPTY) | 468 ISTAT_TO_SM(PNX8XXX_UART_INT_RX); 469 if (termios->c_iflag & INPCK) 470 sport->port.read_status_mask |= 471 FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) | 472 FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR); 473 if (termios->c_iflag & (BRKINT | PARMRK)) 474 sport->port.read_status_mask |= 475 ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK); 476 477 /* 478 * Characters to ignore 479 */ 480 sport->port.ignore_status_mask = 0; 481 if (termios->c_iflag & IGNPAR) 482 sport->port.ignore_status_mask |= 483 FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) | 484 FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR); 485 if (termios->c_iflag & IGNBRK) { 486 sport->port.ignore_status_mask |= 487 ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK); 488 /* 489 * If we're ignoring parity and break indicators, 490 * ignore overruns too (for real raw support). 491 */ 492 if (termios->c_iflag & IGNPAR) 493 sport->port.ignore_status_mask |= 494 ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN); 495 } 496 497 /* 498 * ignore all characters if CREAD is not set 499 */ 500 if ((termios->c_cflag & CREAD) == 0) 501 sport->port.ignore_status_mask |= 502 ISTAT_TO_SM(PNX8XXX_UART_INT_RX); 503 504 del_timer_sync(&sport->timer); 505 506 /* 507 * Update the per-port timeout. 508 */ 509 uart_update_timeout(port, termios->c_cflag, baud); 510 511 /* 512 * disable interrupts and drain transmitter 513 */ 514 old_ien = serial_in(sport, PNX8XXX_IEN); 515 serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX | 516 PNX8XXX_UART_INT_ALLRX)); 517 518 while (serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA) 519 barrier(); 520 521 /* then, disable everything */ 522 serial_out(sport, PNX8XXX_IEN, 0); 523 524 /* Reset the Rx and Tx FIFOs too */ 525 lcr_fcr |= PNX8XXX_UART_LCR_TX_RST; 526 lcr_fcr |= PNX8XXX_UART_LCR_RX_RST; 527 528 /* set the parity, stop bits and data size */ 529 serial_out(sport, PNX8XXX_LCR, lcr_fcr); 530 531 /* set the baud rate */ 532 quot -= 1; 533 serial_out(sport, PNX8XXX_BAUD, quot); 534 535 serial_out(sport, PNX8XXX_ICLR, -1); 536 537 serial_out(sport, PNX8XXX_IEN, old_ien); 538 539 if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) 540 pnx8xxx_enable_ms(&sport->port); 541 542 spin_unlock_irqrestore(&sport->port.lock, flags); 543} 544 545static const char *pnx8xxx_type(struct uart_port *port) 546{ 547 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 548 549 return sport->port.type == PORT_PNX8XXX ? "PNX8XXX" : NULL; 550} 551 552/* 553 * Release the memory region(s) being used by 'port'. 554 */ 555static void pnx8xxx_release_port(struct uart_port *port) 556{ 557 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 558 559 release_mem_region(sport->port.mapbase, UART_PORT_SIZE); 560} 561 562/* 563 * Request the memory region(s) being used by 'port'. 564 */ 565static int pnx8xxx_request_port(struct uart_port *port) 566{ 567 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 568 return request_mem_region(sport->port.mapbase, UART_PORT_SIZE, 569 "pnx8xxx-uart") != NULL ? 0 : -EBUSY; 570} 571 572/* 573 * Configure/autoconfigure the port. 574 */ 575static void pnx8xxx_config_port(struct uart_port *port, int flags) 576{ 577 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 578 579 if (flags & UART_CONFIG_TYPE && 580 pnx8xxx_request_port(&sport->port) == 0) 581 sport->port.type = PORT_PNX8XXX; 582} 583 584/* 585 * Verify the new serial_struct (for TIOCSSERIAL). 586 * The only change we allow are to the flags and type, and 587 * even then only between PORT_PNX8XXX and PORT_UNKNOWN 588 */ 589static int 590pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser) 591{ 592 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 593 int ret = 0; 594 595 if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8XXX) 596 ret = -EINVAL; 597 if (sport->port.irq != ser->irq) 598 ret = -EINVAL; 599 if (ser->io_type != SERIAL_IO_MEM) 600 ret = -EINVAL; 601 if (sport->port.uartclk / 16 != ser->baud_base) 602 ret = -EINVAL; 603 if ((void *)sport->port.mapbase != ser->iomem_base) 604 ret = -EINVAL; 605 if (sport->port.iobase != ser->port) 606 ret = -EINVAL; 607 if (ser->hub6 != 0) 608 ret = -EINVAL; 609 return ret; 610} 611 612static struct uart_ops pnx8xxx_pops = { 613 .tx_empty = pnx8xxx_tx_empty, 614 .set_mctrl = pnx8xxx_set_mctrl, 615 .get_mctrl = pnx8xxx_get_mctrl, 616 .stop_tx = pnx8xxx_stop_tx, 617 .start_tx = pnx8xxx_start_tx, 618 .stop_rx = pnx8xxx_stop_rx, 619 .enable_ms = pnx8xxx_enable_ms, 620 .break_ctl = pnx8xxx_break_ctl, 621 .startup = pnx8xxx_startup, 622 .shutdown = pnx8xxx_shutdown, 623 .set_termios = pnx8xxx_set_termios, 624 .type = pnx8xxx_type, 625 .release_port = pnx8xxx_release_port, 626 .request_port = pnx8xxx_request_port, 627 .config_port = pnx8xxx_config_port, 628 .verify_port = pnx8xxx_verify_port, 629}; 630 631 632/* 633 * Setup the PNX8XXX serial ports. 634 * 635 * Note also that we support "console=ttySx" where "x" is either 0 or 1. 636 */ 637static void __init pnx8xxx_init_ports(void) 638{ 639 static int first = 1; 640 int i; 641 642 if (!first) 643 return; 644 first = 0; 645 646 for (i = 0; i < NR_PORTS; i++) { 647 init_timer(&pnx8xxx_ports[i].timer); 648 pnx8xxx_ports[i].timer.function = pnx8xxx_timeout; 649 pnx8xxx_ports[i].timer.data = (unsigned long)&pnx8xxx_ports[i]; 650 pnx8xxx_ports[i].port.ops = &pnx8xxx_pops; 651 } 652} 653 654#ifdef CONFIG_SERIAL_PNX8XXX_CONSOLE 655 656static void pnx8xxx_console_putchar(struct uart_port *port, int ch) 657{ 658 struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port; 659 int status; 660 661 do { 662 /* Wait for UART_TX register to empty */ 663 status = serial_in(sport, PNX8XXX_FIFO); 664 } while (status & PNX8XXX_UART_FIFO_TXFIFO); 665 serial_out(sport, PNX8XXX_FIFO, ch); 666} 667 668/* 669 * Interrupts are disabled on entering 670 */static void 671pnx8xxx_console_write(struct console *co, const char *s, unsigned int count) 672{ 673 struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index]; 674 unsigned int old_ien, status; 675 676 /* 677 * First, save IEN and then disable interrupts 678 */ 679 old_ien = serial_in(sport, PNX8XXX_IEN); 680 serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX | 681 PNX8XXX_UART_INT_ALLRX)); 682 683 uart_console_write(&sport->port, s, count, pnx8xxx_console_putchar); 684 685 /* 686 * Finally, wait for transmitter to become empty 687 * and restore IEN 688 */ 689 do { 690 /* Wait for UART_TX register to empty */ 691 status = serial_in(sport, PNX8XXX_FIFO); 692 } while (status & PNX8XXX_UART_FIFO_TXFIFO); 693 694 /* Clear TX and EMPTY interrupt */ 695 serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX | 696 PNX8XXX_UART_INT_EMPTY); 697 698 serial_out(sport, PNX8XXX_IEN, old_ien); 699} 700 701static int __init 702pnx8xxx_console_setup(struct console *co, char *options) 703{ 704 struct pnx8xxx_port *sport; 705 int baud = 38400; 706 int bits = 8; 707 int parity = 'n'; 708 int flow = 'n'; 709 710 /* 711 * Check whether an invalid uart number has been specified, and 712 * if so, search for the first available port that does have 713 * console support. 714 */ 715 if (co->index == -1 || co->index >= NR_PORTS) 716 co->index = 0; 717 sport = &pnx8xxx_ports[co->index]; 718 719 if (options) 720 uart_parse_options(options, &baud, &parity, &bits, &flow); 721 722 return uart_set_options(&sport->port, co, baud, parity, bits, flow); 723} 724 725static struct uart_driver pnx8xxx_reg; 726static struct console pnx8xxx_console = { 727 .name = "ttyS", 728 .write = pnx8xxx_console_write, 729 .device = uart_console_device, 730 .setup = pnx8xxx_console_setup, 731 .flags = CON_PRINTBUFFER, 732 .index = -1, 733 .data = &pnx8xxx_reg, 734}; 735 736static int __init pnx8xxx_rs_console_init(void) 737{ 738 pnx8xxx_init_ports(); 739 register_console(&pnx8xxx_console); 740 return 0; 741} 742console_initcall(pnx8xxx_rs_console_init); 743 744#define PNX8XXX_CONSOLE &pnx8xxx_console 745#else 746#define PNX8XXX_CONSOLE NULL 747#endif 748 749static struct uart_driver pnx8xxx_reg = { 750 .owner = THIS_MODULE, 751 .driver_name = "ttyS", 752 .dev_name = "ttyS", 753 .major = SERIAL_PNX8XXX_MAJOR, 754 .minor = MINOR_START, 755 .nr = NR_PORTS, 756 .cons = PNX8XXX_CONSOLE, 757}; 758 759static int pnx8xxx_serial_suspend(struct platform_device *pdev, pm_message_t state) 760{ 761 struct pnx8xxx_port *sport = platform_get_drvdata(pdev); 762 763 return uart_suspend_port(&pnx8xxx_reg, &sport->port); 764} 765 766static int pnx8xxx_serial_resume(struct platform_device *pdev) 767{ 768 struct pnx8xxx_port *sport = platform_get_drvdata(pdev); 769 770 return uart_resume_port(&pnx8xxx_reg, &sport->port); 771} 772 773static int pnx8xxx_serial_probe(struct platform_device *pdev) 774{ 775 struct resource *res = pdev->resource; 776 int i; 777 778 for (i = 0; i < pdev->num_resources; i++, res++) { 779 if (!(res->flags & IORESOURCE_MEM)) 780 continue; 781 782 for (i = 0; i < NR_PORTS; i++) { 783 if (pnx8xxx_ports[i].port.mapbase != res->start) 784 continue; 785 786 pnx8xxx_ports[i].port.dev = &pdev->dev; 787 uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port); 788 platform_set_drvdata(pdev, &pnx8xxx_ports[i]); 789 break; 790 } 791 } 792 793 return 0; 794} 795 796static int pnx8xxx_serial_remove(struct platform_device *pdev) 797{ 798 struct pnx8xxx_port *sport = platform_get_drvdata(pdev); 799 800 platform_set_drvdata(pdev, NULL); 801 802 if (sport) 803 uart_remove_one_port(&pnx8xxx_reg, &sport->port); 804 805 return 0; 806} 807 808static struct platform_driver pnx8xxx_serial_driver = { 809 .driver = { 810 .name = "pnx8xxx-uart", 811 .owner = THIS_MODULE, 812 }, 813 .probe = pnx8xxx_serial_probe, 814 .remove = pnx8xxx_serial_remove, 815 .suspend = pnx8xxx_serial_suspend, 816 .resume = pnx8xxx_serial_resume, 817}; 818 819static int __init pnx8xxx_serial_init(void) 820{ 821 int ret; 822 823 printk(KERN_INFO "Serial: PNX8XXX driver $Revision: 1.1.1.1 $\n"); 824 825 pnx8xxx_init_ports(); 826 827 ret = uart_register_driver(&pnx8xxx_reg); 828 if (ret == 0) { 829 ret = platform_driver_register(&pnx8xxx_serial_driver); 830 if (ret) 831 uart_unregister_driver(&pnx8xxx_reg); 832 } 833 return ret; 834} 835 836static void __exit pnx8xxx_serial_exit(void) 837{ 838 platform_driver_unregister(&pnx8xxx_serial_driver); 839 uart_unregister_driver(&pnx8xxx_reg); 840} 841 842module_init(pnx8xxx_serial_init); 843module_exit(pnx8xxx_serial_exit); 844 845MODULE_AUTHOR("Embedded Alley Solutions, Inc."); 846MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver"); 847MODULE_LICENSE("GPL"); 848MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR); 849