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