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

Configure Feed

Select the types of activity you want to include in your feed.

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