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 v2.6.14-rc2 830 lines 19 kB view raw
1/* 2 * linux/drivers/char/amba.c 3 * 4 * Driver for AMBA serial ports 5 * 6 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 7 * 8 * Copyright 1999 ARM Limited 9 * Copyright (C) 2000 Deep Blue Solutions Ltd. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 * $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $ 26 * 27 * This is a generic driver for ARM AMBA-type serial ports. They 28 * have a lot of 16550-like features, but are not register compatible. 29 * Note that although they do have CTS, DCD and DSR inputs, they do 30 * not have an RI input, nor do they have DTR or RTS outputs. If 31 * required, these have to be supplied via some other means (eg, GPIO) 32 * and hooked into this driver. 33 */ 34#include <linux/config.h> 35 36#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 37#define SUPPORT_SYSRQ 38#endif 39 40#include <linux/module.h> 41#include <linux/ioport.h> 42#include <linux/init.h> 43#include <linux/console.h> 44#include <linux/sysrq.h> 45#include <linux/device.h> 46#include <linux/tty.h> 47#include <linux/tty_flip.h> 48#include <linux/serial_core.h> 49#include <linux/serial.h> 50 51#include <asm/io.h> 52#include <asm/irq.h> 53#include <asm/hardware/amba.h> 54#include <asm/hardware/amba_serial.h> 55 56#define UART_NR 2 57 58#define SERIAL_AMBA_MAJOR 204 59#define SERIAL_AMBA_MINOR 16 60#define SERIAL_AMBA_NR UART_NR 61 62#define AMBA_ISR_PASS_LIMIT 256 63 64/* 65 * Access macros for the AMBA UARTs 66 */ 67#define UART_GET_INT_STATUS(p) readb((p)->membase + UART010_IIR) 68#define UART_PUT_ICR(p, c) writel((c), (p)->membase + UART010_ICR) 69#define UART_GET_FR(p) readb((p)->membase + UART01x_FR) 70#define UART_GET_CHAR(p) readb((p)->membase + UART01x_DR) 71#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + UART01x_DR) 72#define UART_GET_RSR(p) readb((p)->membase + UART01x_RSR) 73#define UART_GET_CR(p) readb((p)->membase + UART010_CR) 74#define UART_PUT_CR(p,c) writel((c), (p)->membase + UART010_CR) 75#define UART_GET_LCRL(p) readb((p)->membase + UART010_LCRL) 76#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + UART010_LCRL) 77#define UART_GET_LCRM(p) readb((p)->membase + UART010_LCRM) 78#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + UART010_LCRM) 79#define UART_GET_LCRH(p) readb((p)->membase + UART010_LCRH) 80#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + UART010_LCRH) 81#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) 82#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) 83#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0) 84 85#define UART_DUMMY_RSR_RX /*256*/0 86#define UART_PORT_SIZE 64 87 88/* 89 * On the Integrator platform, the port RTS and DTR are provided by 90 * bits in the following SC_CTRLS register bits: 91 * RTS DTR 92 * UART0 7 6 93 * UART1 5 4 94 */ 95#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) 96#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) 97 98/* 99 * We wrap our port structure around the generic uart_port. 100 */ 101struct uart_amba_port { 102 struct uart_port port; 103 unsigned int dtr_mask; 104 unsigned int rts_mask; 105 unsigned int old_status; 106}; 107 108static void pl010_stop_tx(struct uart_port *port) 109{ 110 unsigned int cr; 111 112 cr = UART_GET_CR(port); 113 cr &= ~UART010_CR_TIE; 114 UART_PUT_CR(port, cr); 115} 116 117static void pl010_start_tx(struct uart_port *port) 118{ 119 unsigned int cr; 120 121 cr = UART_GET_CR(port); 122 cr |= UART010_CR_TIE; 123 UART_PUT_CR(port, cr); 124} 125 126static void pl010_stop_rx(struct uart_port *port) 127{ 128 unsigned int cr; 129 130 cr = UART_GET_CR(port); 131 cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); 132 UART_PUT_CR(port, cr); 133} 134 135static void pl010_enable_ms(struct uart_port *port) 136{ 137 unsigned int cr; 138 139 cr = UART_GET_CR(port); 140 cr |= UART010_CR_MSIE; 141 UART_PUT_CR(port, cr); 142} 143 144static void 145#ifdef SUPPORT_SYSRQ 146pl010_rx_chars(struct uart_port *port, struct pt_regs *regs) 147#else 148pl010_rx_chars(struct uart_port *port) 149#endif 150{ 151 struct tty_struct *tty = port->info->tty; 152 unsigned int status, ch, flag, rsr, max_count = 256; 153 154 status = UART_GET_FR(port); 155 while (UART_RX_DATA(status) && max_count--) { 156 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 157 if (tty->low_latency) 158 tty_flip_buffer_push(tty); 159 /* 160 * If this failed then we will throw away the 161 * bytes but must do so to clear interrupts. 162 */ 163 } 164 165 ch = UART_GET_CHAR(port); 166 flag = TTY_NORMAL; 167 168 port->icount.rx++; 169 170 /* 171 * Note that the error handling code is 172 * out of the main execution path 173 */ 174 rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; 175 if (unlikely(rsr & UART01x_RSR_ANY)) { 176 if (rsr & UART01x_RSR_BE) { 177 rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); 178 port->icount.brk++; 179 if (uart_handle_break(port)) 180 goto ignore_char; 181 } else if (rsr & UART01x_RSR_PE) 182 port->icount.parity++; 183 else if (rsr & UART01x_RSR_FE) 184 port->icount.frame++; 185 if (rsr & UART01x_RSR_OE) 186 port->icount.overrun++; 187 188 rsr &= port->read_status_mask; 189 190 if (rsr & UART01x_RSR_BE) 191 flag = TTY_BREAK; 192 else if (rsr & UART01x_RSR_PE) 193 flag = TTY_PARITY; 194 else if (rsr & UART01x_RSR_FE) 195 flag = TTY_FRAME; 196 } 197 198 if (uart_handle_sysrq_char(port, ch, regs)) 199 goto ignore_char; 200 201 uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); 202 203 ignore_char: 204 status = UART_GET_FR(port); 205 } 206 tty_flip_buffer_push(tty); 207 return; 208} 209 210static void pl010_tx_chars(struct uart_port *port) 211{ 212 struct circ_buf *xmit = &port->info->xmit; 213 int count; 214 215 if (port->x_char) { 216 UART_PUT_CHAR(port, port->x_char); 217 port->icount.tx++; 218 port->x_char = 0; 219 return; 220 } 221 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { 222 pl010_stop_tx(port); 223 return; 224 } 225 226 count = port->fifosize >> 1; 227 do { 228 UART_PUT_CHAR(port, xmit->buf[xmit->tail]); 229 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 230 port->icount.tx++; 231 if (uart_circ_empty(xmit)) 232 break; 233 } while (--count > 0); 234 235 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 236 uart_write_wakeup(port); 237 238 if (uart_circ_empty(xmit)) 239 pl010_stop_tx(port); 240} 241 242static void pl010_modem_status(struct uart_port *port) 243{ 244 struct uart_amba_port *uap = (struct uart_amba_port *)port; 245 unsigned int status, delta; 246 247 UART_PUT_ICR(&uap->port, 0); 248 249 status = UART_GET_FR(&uap->port) & UART01x_FR_MODEM_ANY; 250 251 delta = status ^ uap->old_status; 252 uap->old_status = status; 253 254 if (!delta) 255 return; 256 257 if (delta & UART01x_FR_DCD) 258 uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD); 259 260 if (delta & UART01x_FR_DSR) 261 uap->port.icount.dsr++; 262 263 if (delta & UART01x_FR_CTS) 264 uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS); 265 266 wake_up_interruptible(&uap->port.info->delta_msr_wait); 267} 268 269static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs) 270{ 271 struct uart_port *port = dev_id; 272 unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; 273 int handled = 0; 274 275 spin_lock(&port->lock); 276 277 status = UART_GET_INT_STATUS(port); 278 if (status) { 279 do { 280 if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) 281#ifdef SUPPORT_SYSRQ 282 pl010_rx_chars(port, regs); 283#else 284 pl010_rx_chars(port); 285#endif 286 if (status & UART010_IIR_MIS) 287 pl010_modem_status(port); 288 if (status & UART010_IIR_TIS) 289 pl010_tx_chars(port); 290 291 if (pass_counter-- == 0) 292 break; 293 294 status = UART_GET_INT_STATUS(port); 295 } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | 296 UART010_IIR_TIS)); 297 handled = 1; 298 } 299 300 spin_unlock(&port->lock); 301 302 return IRQ_RETVAL(handled); 303} 304 305static unsigned int pl010_tx_empty(struct uart_port *port) 306{ 307 return UART_GET_FR(port) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; 308} 309 310static unsigned int pl010_get_mctrl(struct uart_port *port) 311{ 312 unsigned int result = 0; 313 unsigned int status; 314 315 status = UART_GET_FR(port); 316 if (status & UART01x_FR_DCD) 317 result |= TIOCM_CAR; 318 if (status & UART01x_FR_DSR) 319 result |= TIOCM_DSR; 320 if (status & UART01x_FR_CTS) 321 result |= TIOCM_CTS; 322 323 return result; 324} 325 326static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) 327{ 328 struct uart_amba_port *uap = (struct uart_amba_port *)port; 329 unsigned int ctrls = 0, ctrlc = 0; 330 331 if (mctrl & TIOCM_RTS) 332 ctrlc |= uap->rts_mask; 333 else 334 ctrls |= uap->rts_mask; 335 336 if (mctrl & TIOCM_DTR) 337 ctrlc |= uap->dtr_mask; 338 else 339 ctrls |= uap->dtr_mask; 340 341 __raw_writel(ctrls, SC_CTRLS); 342 __raw_writel(ctrlc, SC_CTRLC); 343} 344 345static void pl010_break_ctl(struct uart_port *port, int break_state) 346{ 347 unsigned long flags; 348 unsigned int lcr_h; 349 350 spin_lock_irqsave(&port->lock, flags); 351 lcr_h = UART_GET_LCRH(port); 352 if (break_state == -1) 353 lcr_h |= UART01x_LCRH_BRK; 354 else 355 lcr_h &= ~UART01x_LCRH_BRK; 356 UART_PUT_LCRH(port, lcr_h); 357 spin_unlock_irqrestore(&port->lock, flags); 358} 359 360static int pl010_startup(struct uart_port *port) 361{ 362 struct uart_amba_port *uap = (struct uart_amba_port *)port; 363 int retval; 364 365 /* 366 * Allocate the IRQ 367 */ 368 retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", port); 369 if (retval) 370 return retval; 371 372 /* 373 * initialise the old status of the modem signals 374 */ 375 uap->old_status = UART_GET_FR(port) & UART01x_FR_MODEM_ANY; 376 377 /* 378 * Finally, enable interrupts 379 */ 380 UART_PUT_CR(port, UART01x_CR_UARTEN | UART010_CR_RIE | 381 UART010_CR_RTIE); 382 383 return 0; 384} 385 386static void pl010_shutdown(struct uart_port *port) 387{ 388 /* 389 * Free the interrupt 390 */ 391 free_irq(port->irq, port); 392 393 /* 394 * disable all interrupts, disable the port 395 */ 396 UART_PUT_CR(port, 0); 397 398 /* disable break condition and fifos */ 399 UART_PUT_LCRH(port, UART_GET_LCRH(port) & 400 ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN)); 401} 402 403static void 404pl010_set_termios(struct uart_port *port, struct termios *termios, 405 struct termios *old) 406{ 407 unsigned int lcr_h, old_cr; 408 unsigned long flags; 409 unsigned int baud, quot; 410 411 /* 412 * Ask the core to calculate the divisor for us. 413 */ 414 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 415 quot = uart_get_divisor(port, baud); 416 417 switch (termios->c_cflag & CSIZE) { 418 case CS5: 419 lcr_h = UART01x_LCRH_WLEN_5; 420 break; 421 case CS6: 422 lcr_h = UART01x_LCRH_WLEN_6; 423 break; 424 case CS7: 425 lcr_h = UART01x_LCRH_WLEN_7; 426 break; 427 default: // CS8 428 lcr_h = UART01x_LCRH_WLEN_8; 429 break; 430 } 431 if (termios->c_cflag & CSTOPB) 432 lcr_h |= UART01x_LCRH_STP2; 433 if (termios->c_cflag & PARENB) { 434 lcr_h |= UART01x_LCRH_PEN; 435 if (!(termios->c_cflag & PARODD)) 436 lcr_h |= UART01x_LCRH_EPS; 437 } 438 if (port->fifosize > 1) 439 lcr_h |= UART01x_LCRH_FEN; 440 441 spin_lock_irqsave(&port->lock, flags); 442 443 /* 444 * Update the per-port timeout. 445 */ 446 uart_update_timeout(port, termios->c_cflag, baud); 447 448 port->read_status_mask = UART01x_RSR_OE; 449 if (termios->c_iflag & INPCK) 450 port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; 451 if (termios->c_iflag & (BRKINT | PARMRK)) 452 port->read_status_mask |= UART01x_RSR_BE; 453 454 /* 455 * Characters to ignore 456 */ 457 port->ignore_status_mask = 0; 458 if (termios->c_iflag & IGNPAR) 459 port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; 460 if (termios->c_iflag & IGNBRK) { 461 port->ignore_status_mask |= UART01x_RSR_BE; 462 /* 463 * If we're ignoring parity and break indicators, 464 * ignore overruns too (for real raw support). 465 */ 466 if (termios->c_iflag & IGNPAR) 467 port->ignore_status_mask |= UART01x_RSR_OE; 468 } 469 470 /* 471 * Ignore all characters if CREAD is not set. 472 */ 473 if ((termios->c_cflag & CREAD) == 0) 474 port->ignore_status_mask |= UART_DUMMY_RSR_RX; 475 476 /* first, disable everything */ 477 old_cr = UART_GET_CR(port) & ~UART010_CR_MSIE; 478 479 if (UART_ENABLE_MS(port, termios->c_cflag)) 480 old_cr |= UART010_CR_MSIE; 481 482 UART_PUT_CR(port, 0); 483 484 /* Set baud rate */ 485 quot -= 1; 486 UART_PUT_LCRM(port, ((quot & 0xf00) >> 8)); 487 UART_PUT_LCRL(port, (quot & 0xff)); 488 489 /* 490 * ----------v----------v----------v----------v----- 491 * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L 492 * ----------^----------^----------^----------^----- 493 */ 494 UART_PUT_LCRH(port, lcr_h); 495 UART_PUT_CR(port, old_cr); 496 497 spin_unlock_irqrestore(&port->lock, flags); 498} 499 500static const char *pl010_type(struct uart_port *port) 501{ 502 return port->type == PORT_AMBA ? "AMBA" : NULL; 503} 504 505/* 506 * Release the memory region(s) being used by 'port' 507 */ 508static void pl010_release_port(struct uart_port *port) 509{ 510 release_mem_region(port->mapbase, UART_PORT_SIZE); 511} 512 513/* 514 * Request the memory region(s) being used by 'port' 515 */ 516static int pl010_request_port(struct uart_port *port) 517{ 518 return request_mem_region(port->mapbase, UART_PORT_SIZE, "uart-pl010") 519 != NULL ? 0 : -EBUSY; 520} 521 522/* 523 * Configure/autoconfigure the port. 524 */ 525static void pl010_config_port(struct uart_port *port, int flags) 526{ 527 if (flags & UART_CONFIG_TYPE) { 528 port->type = PORT_AMBA; 529 pl010_request_port(port); 530 } 531} 532 533/* 534 * verify the new serial_struct (for TIOCSSERIAL). 535 */ 536static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser) 537{ 538 int ret = 0; 539 if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) 540 ret = -EINVAL; 541 if (ser->irq < 0 || ser->irq >= NR_IRQS) 542 ret = -EINVAL; 543 if (ser->baud_base < 9600) 544 ret = -EINVAL; 545 return ret; 546} 547 548static struct uart_ops amba_pl010_pops = { 549 .tx_empty = pl010_tx_empty, 550 .set_mctrl = pl010_set_mctrl, 551 .get_mctrl = pl010_get_mctrl, 552 .stop_tx = pl010_stop_tx, 553 .start_tx = pl010_start_tx, 554 .stop_rx = pl010_stop_rx, 555 .enable_ms = pl010_enable_ms, 556 .break_ctl = pl010_break_ctl, 557 .startup = pl010_startup, 558 .shutdown = pl010_shutdown, 559 .set_termios = pl010_set_termios, 560 .type = pl010_type, 561 .release_port = pl010_release_port, 562 .request_port = pl010_request_port, 563 .config_port = pl010_config_port, 564 .verify_port = pl010_verify_port, 565}; 566 567static struct uart_amba_port amba_ports[UART_NR] = { 568 { 569 .port = { 570 .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), 571 .mapbase = INTEGRATOR_UART0_BASE, 572 .iotype = SERIAL_IO_MEM, 573 .irq = IRQ_UARTINT0, 574 .uartclk = 14745600, 575 .fifosize = 16, 576 .ops = &amba_pl010_pops, 577 .flags = ASYNC_BOOT_AUTOCONF, 578 .line = 0, 579 }, 580 .dtr_mask = 1 << 5, 581 .rts_mask = 1 << 4, 582 }, 583 { 584 .port = { 585 .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), 586 .mapbase = INTEGRATOR_UART1_BASE, 587 .iotype = SERIAL_IO_MEM, 588 .irq = IRQ_UARTINT1, 589 .uartclk = 14745600, 590 .fifosize = 16, 591 .ops = &amba_pl010_pops, 592 .flags = ASYNC_BOOT_AUTOCONF, 593 .line = 1, 594 }, 595 .dtr_mask = 1 << 7, 596 .rts_mask = 1 << 6, 597 } 598}; 599 600#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE 601 602static void 603pl010_console_write(struct console *co, const char *s, unsigned int count) 604{ 605 struct uart_port *port = &amba_ports[co->index].port; 606 unsigned int status, old_cr; 607 int i; 608 609 /* 610 * First save the CR then disable the interrupts 611 */ 612 old_cr = UART_GET_CR(port); 613 UART_PUT_CR(port, UART01x_CR_UARTEN); 614 615 /* 616 * Now, do each character 617 */ 618 for (i = 0; i < count; i++) { 619 do { 620 status = UART_GET_FR(port); 621 } while (!UART_TX_READY(status)); 622 UART_PUT_CHAR(port, s[i]); 623 if (s[i] == '\n') { 624 do { 625 status = UART_GET_FR(port); 626 } while (!UART_TX_READY(status)); 627 UART_PUT_CHAR(port, '\r'); 628 } 629 } 630 631 /* 632 * Finally, wait for transmitter to become empty 633 * and restore the TCR 634 */ 635 do { 636 status = UART_GET_FR(port); 637 } while (status & UART01x_FR_BUSY); 638 UART_PUT_CR(port, old_cr); 639} 640 641static void __init 642pl010_console_get_options(struct uart_port *port, int *baud, 643 int *parity, int *bits) 644{ 645 if (UART_GET_CR(port) & UART01x_CR_UARTEN) { 646 unsigned int lcr_h, quot; 647 lcr_h = UART_GET_LCRH(port); 648 649 *parity = 'n'; 650 if (lcr_h & UART01x_LCRH_PEN) { 651 if (lcr_h & UART01x_LCRH_EPS) 652 *parity = 'e'; 653 else 654 *parity = 'o'; 655 } 656 657 if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7) 658 *bits = 7; 659 else 660 *bits = 8; 661 662 quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8; 663 *baud = port->uartclk / (16 * (quot + 1)); 664 } 665} 666 667static int __init pl010_console_setup(struct console *co, char *options) 668{ 669 struct uart_port *port; 670 int baud = 38400; 671 int bits = 8; 672 int parity = 'n'; 673 int flow = 'n'; 674 675 /* 676 * Check whether an invalid uart number has been specified, and 677 * if so, search for the first available port that does have 678 * console support. 679 */ 680 if (co->index >= UART_NR) 681 co->index = 0; 682 port = &amba_ports[co->index].port; 683 684 if (options) 685 uart_parse_options(options, &baud, &parity, &bits, &flow); 686 else 687 pl010_console_get_options(port, &baud, &parity, &bits); 688 689 return uart_set_options(port, co, baud, parity, bits, flow); 690} 691 692static struct uart_driver amba_reg; 693static struct console amba_console = { 694 .name = "ttyAM", 695 .write = pl010_console_write, 696 .device = uart_console_device, 697 .setup = pl010_console_setup, 698 .flags = CON_PRINTBUFFER, 699 .index = -1, 700 .data = &amba_reg, 701}; 702 703static int __init amba_console_init(void) 704{ 705 /* 706 * All port initializations are done statically 707 */ 708 register_console(&amba_console); 709 return 0; 710} 711console_initcall(amba_console_init); 712 713static int __init amba_late_console_init(void) 714{ 715 if (!(amba_console.flags & CON_ENABLED)) 716 register_console(&amba_console); 717 return 0; 718} 719late_initcall(amba_late_console_init); 720 721#define AMBA_CONSOLE &amba_console 722#else 723#define AMBA_CONSOLE NULL 724#endif 725 726static struct uart_driver amba_reg = { 727 .owner = THIS_MODULE, 728 .driver_name = "ttyAM", 729 .dev_name = "ttyAM", 730 .major = SERIAL_AMBA_MAJOR, 731 .minor = SERIAL_AMBA_MINOR, 732 .nr = UART_NR, 733 .cons = AMBA_CONSOLE, 734}; 735 736static int pl010_probe(struct amba_device *dev, void *id) 737{ 738 int i; 739 740 for (i = 0; i < UART_NR; i++) { 741 if (amba_ports[i].port.mapbase != dev->res.start) 742 continue; 743 744 amba_ports[i].port.dev = &dev->dev; 745 uart_add_one_port(&amba_reg, &amba_ports[i].port); 746 amba_set_drvdata(dev, &amba_ports[i]); 747 break; 748 } 749 750 return 0; 751} 752 753static int pl010_remove(struct amba_device *dev) 754{ 755 struct uart_amba_port *uap = amba_get_drvdata(dev); 756 757 if (uap) 758 uart_remove_one_port(&amba_reg, &uap->port); 759 760 amba_set_drvdata(dev, NULL); 761 762 return 0; 763} 764 765static int pl010_suspend(struct amba_device *dev, pm_message_t state) 766{ 767 struct uart_amba_port *uap = amba_get_drvdata(dev); 768 769 if (uap) 770 uart_suspend_port(&amba_reg, &uap->port); 771 772 return 0; 773} 774 775static int pl010_resume(struct amba_device *dev) 776{ 777 struct uart_amba_port *uap = amba_get_drvdata(dev); 778 779 if (uap) 780 uart_resume_port(&amba_reg, &uap->port); 781 782 return 0; 783} 784 785static struct amba_id pl010_ids[] __initdata = { 786 { 787 .id = 0x00041010, 788 .mask = 0x000fffff, 789 }, 790 { 0, 0 }, 791}; 792 793static struct amba_driver pl010_driver = { 794 .drv = { 795 .name = "uart-pl010", 796 }, 797 .id_table = pl010_ids, 798 .probe = pl010_probe, 799 .remove = pl010_remove, 800 .suspend = pl010_suspend, 801 .resume = pl010_resume, 802}; 803 804static int __init pl010_init(void) 805{ 806 int ret; 807 808 printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n"); 809 810 ret = uart_register_driver(&amba_reg); 811 if (ret == 0) { 812 ret = amba_driver_register(&pl010_driver); 813 if (ret) 814 uart_unregister_driver(&amba_reg); 815 } 816 return ret; 817} 818 819static void __exit pl010_exit(void) 820{ 821 amba_driver_unregister(&pl010_driver); 822 uart_unregister_driver(&amba_reg); 823} 824 825module_init(pl010_init); 826module_exit(pl010_exit); 827 828MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); 829MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $"); 830MODULE_LICENSE("GPL");