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