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