1 /* 2 * drivers/serial/msm_serial.c - driver for msm7k serial device and console 3 * 4 * Copyright (C) 2007 Google, Inc. 5 * Author: Robert Love <rlove@google.com> 6 * 7 * This software is licensed under the terms of the GNU General Public 8 * License version 2, as published by the Free Software Foundation, and 9 * may be copied, distributed, and modified under those terms. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #if defined(CONFIG_SERIAL_MSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 18 # define SUPPORT_SYSRQ 19 #endif 20 21 #include <linux/hrtimer.h> 22 #include <linux/module.h> 23 #include <linux/io.h> 24 #include <linux/ioport.h> 25 #include <linux/irq.h> 26 #include <linux/init.h> 27 #include <linux/console.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/clk.h> 33 #include <linux/platform_device.h> 34 35 #include "msm_serial.h" 36 37 struct msm_port { 38 struct uart_port uart; 39 char name[16]; 40 struct clk *clk; 41 unsigned int imr; 42 }; 43 44 static void msm_stop_tx(struct uart_port *port) 45 { 46 struct msm_port *msm_port = UART_TO_MSM(port); 47 48 msm_port->imr &= ~UART_IMR_TXLEV; 49 msm_write(port, msm_port->imr, UART_IMR); 50 } 51 52 static void msm_start_tx(struct uart_port *port) 53 { 54 struct msm_port *msm_port = UART_TO_MSM(port); 55 56 msm_port->imr |= UART_IMR_TXLEV; 57 msm_write(port, msm_port->imr, UART_IMR); 58 } 59 60 static void msm_stop_rx(struct uart_port *port) 61 { 62 struct msm_port *msm_port = UART_TO_MSM(port); 63 64 msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); 65 msm_write(port, msm_port->imr, UART_IMR); 66 } 67 68 static void msm_enable_ms(struct uart_port *port) 69 { 70 struct msm_port *msm_port = UART_TO_MSM(port); 71 72 msm_port->imr |= UART_IMR_DELTA_CTS; 73 msm_write(port, msm_port->imr, UART_IMR); 74 } 75 76 static void handle_rx(struct uart_port *port) 77 { 78 struct tty_struct *tty = port->state->port.tty; 79 unsigned int sr; 80 81 /* 82 * Handle overrun. My understanding of the hardware is that overrun 83 * is not tied to the RX buffer, so we handle the case out of band. 84 */ 85 if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { 86 port->icount.overrun++; 87 tty_insert_flip_char(tty, 0, TTY_OVERRUN); 88 msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); 89 } 90 91 /* and now the main RX loop */ 92 while ((sr = msm_read(port, UART_SR)) & UART_SR_RX_READY) { 93 unsigned int c; 94 char flag = TTY_NORMAL; 95 96 c = msm_read(port, UART_RF); 97 98 if (sr & UART_SR_RX_BREAK) { 99 port->icount.brk++; 100 if (uart_handle_break(port)) 101 continue; 102 } else if (sr & UART_SR_PAR_FRAME_ERR) { 103 port->icount.frame++; 104 } else { 105 port->icount.rx++; 106 } 107 108 /* Mask conditions we're ignorning. */ 109 sr &= port->read_status_mask; 110 111 if (sr & UART_SR_RX_BREAK) { 112 flag = TTY_BREAK; 113 } else if (sr & UART_SR_PAR_FRAME_ERR) { 114 flag = TTY_FRAME; 115 } 116 117 if (!uart_handle_sysrq_char(port, c)) 118 tty_insert_flip_char(tty, c, flag); 119 } 120 121 tty_flip_buffer_push(tty); 122 } 123 124 static void handle_tx(struct uart_port *port) 125 { 126 struct circ_buf *xmit = &port->state->xmit; 127 struct msm_port *msm_port = UART_TO_MSM(port); 128 int sent_tx; 129 130 if (port->x_char) { 131 msm_write(port, port->x_char, UART_TF); 132 port->icount.tx++; 133 port->x_char = 0; 134 } 135 136 while (msm_read(port, UART_SR) & UART_SR_TX_READY) { 137 if (uart_circ_empty(xmit)) { 138 /* disable tx interrupts */ 139 msm_port->imr &= ~UART_IMR_TXLEV; 140 msm_write(port, msm_port->imr, UART_IMR); 141 break; 142 } 143 144 msm_write(port, xmit->buf[xmit->tail], UART_TF); 145 146 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); 147 port->icount.tx++; 148 sent_tx = 1; 149 } 150 151 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 152 uart_write_wakeup(port); 153 } 154 155 static void handle_delta_cts(struct uart_port *port) 156 { 157 msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); 158 port->icount.cts++; 159 wake_up_interruptible(&port->state->port.delta_msr_wait); 160 } 161 162 static irqreturn_t msm_irq(int irq, void *dev_id) 163 { 164 struct uart_port *port = dev_id; 165 struct msm_port *msm_port = UART_TO_MSM(port); 166 unsigned int misr; 167 168 spin_lock(&port->lock); 169 misr = msm_read(port, UART_MISR); 170 msm_write(port, 0, UART_IMR); /* disable interrupt */ 171 172 if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) 173 handle_rx(port); 174 if (misr & UART_IMR_TXLEV) 175 handle_tx(port); 176 if (misr & UART_IMR_DELTA_CTS) 177 handle_delta_cts(port); 178 179 msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */ 180 spin_unlock(&port->lock); 181 182 return IRQ_HANDLED; 183 } 184 185 static unsigned int msm_tx_empty(struct uart_port *port) 186 { 187 return (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0; 188 } 189 190 static unsigned int msm_get_mctrl(struct uart_port *port) 191 { 192 return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS; 193 } 194 195 static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) 196 { 197 unsigned int mr; 198 199 mr = msm_read(port, UART_MR1); 200 201 if (!(mctrl & TIOCM_RTS)) { 202 mr &= ~UART_MR1_RX_RDY_CTL; 203 msm_write(port, mr, UART_MR1); 204 msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); 205 } else { 206 mr |= UART_MR1_RX_RDY_CTL; 207 msm_write(port, mr, UART_MR1); 208 } 209 } 210 211 static void msm_break_ctl(struct uart_port *port, int break_ctl) 212 { 213 if (break_ctl) 214 msm_write(port, UART_CR_CMD_START_BREAK, UART_CR); 215 else 216 msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR); 217 } 218 219 static int msm_set_baud_rate(struct uart_port *port, unsigned int baud) 220 { 221 unsigned int baud_code, rxstale, watermark; 222 223 switch (baud) { 224 case 300: 225 baud_code = UART_CSR_300; 226 rxstale = 1; 227 break; 228 case 600: 229 baud_code = UART_CSR_600; 230 rxstale = 1; 231 break; 232 case 1200: 233 baud_code = UART_CSR_1200; 234 rxstale = 1; 235 break; 236 case 2400: 237 baud_code = UART_CSR_2400; 238 rxstale = 1; 239 break; 240 case 4800: 241 baud_code = UART_CSR_4800; 242 rxstale = 1; 243 break; 244 case 9600: 245 baud_code = UART_CSR_9600; 246 rxstale = 2; 247 break; 248 case 14400: 249 baud_code = UART_CSR_14400; 250 rxstale = 3; 251 break; 252 case 19200: 253 baud_code = UART_CSR_19200; 254 rxstale = 4; 255 break; 256 case 28800: 257 baud_code = UART_CSR_28800; 258 rxstale = 6; 259 break; 260 case 38400: 261 baud_code = UART_CSR_38400; 262 rxstale = 8; 263 break; 264 case 57600: 265 baud_code = UART_CSR_57600; 266 rxstale = 16; 267 break; 268 case 115200: 269 default: 270 baud_code = UART_CSR_115200; 271 baud = 115200; 272 rxstale = 31; 273 break; 274 } 275 276 msm_write(port, baud_code, UART_CSR); 277 278 /* RX stale watermark */ 279 watermark = UART_IPR_STALE_LSB & rxstale; 280 watermark |= UART_IPR_RXSTALE_LAST; 281 watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2); 282 msm_write(port, watermark, UART_IPR); 283 284 /* set RX watermark */ 285 watermark = (port->fifosize * 3) / 4; 286 msm_write(port, watermark, UART_RFWR); 287 288 /* set TX watermark */ 289 msm_write(port, 10, UART_TFWR); 290 291 return baud; 292 } 293 294 static void msm_reset(struct uart_port *port) 295 { 296 /* reset everything */ 297 msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); 298 msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); 299 msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); 300 msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); 301 msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); 302 msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); 303 } 304 305 static void msm_init_clock(struct uart_port *port) 306 { 307 struct msm_port *msm_port = UART_TO_MSM(port); 308 309 clk_enable(msm_port->clk); 310 msm_serial_set_mnd_regs(port); 311 } 312 313 static int msm_startup(struct uart_port *port) 314 { 315 struct msm_port *msm_port = UART_TO_MSM(port); 316 unsigned int data, rfr_level; 317 int ret; 318 319 snprintf(msm_port->name, sizeof(msm_port->name), 320 "msm_serial%d", port->line); 321 322 ret = request_irq(port->irq, msm_irq, IRQF_TRIGGER_HIGH, 323 msm_port->name, port); 324 if (unlikely(ret)) 325 return ret; 326 327 msm_init_clock(port); 328 329 if (likely(port->fifosize > 12)) 330 rfr_level = port->fifosize - 12; 331 else 332 rfr_level = port->fifosize; 333 334 /* set automatic RFR level */ 335 data = msm_read(port, UART_MR1); 336 data &= ~UART_MR1_AUTO_RFR_LEVEL1; 337 data &= ~UART_MR1_AUTO_RFR_LEVEL0; 338 data |= UART_MR1_AUTO_RFR_LEVEL1 & (rfr_level << 2); 339 data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level; 340 msm_write(port, data, UART_MR1); 341 342 /* make sure that RXSTALE count is non-zero */ 343 data = msm_read(port, UART_IPR); 344 if (unlikely(!data)) { 345 data |= UART_IPR_RXSTALE_LAST; 346 data |= UART_IPR_STALE_LSB; 347 msm_write(port, data, UART_IPR); 348 } 349 350 msm_reset(port); 351 352 msm_write(port, 0x05, UART_CR); /* enable TX & RX */ 353 354 /* turn on RX and CTS interrupts */ 355 msm_port->imr = UART_IMR_RXLEV | UART_IMR_RXSTALE | 356 UART_IMR_CURRENT_CTS; 357 msm_write(port, msm_port->imr, UART_IMR); 358 359 return 0; 360 } 361 362 static void msm_shutdown(struct uart_port *port) 363 { 364 struct msm_port *msm_port = UART_TO_MSM(port); 365 366 msm_port->imr = 0; 367 msm_write(port, 0, UART_IMR); /* disable interrupts */ 368 369 clk_disable(msm_port->clk); 370 371 free_irq(port->irq, port); 372 } 373 374 static void msm_set_termios(struct uart_port *port, struct ktermios *termios, 375 struct ktermios *old) 376 { 377 unsigned long flags; 378 unsigned int baud, mr; 379 380 spin_lock_irqsave(&port->lock, flags); 381 382 /* calculate and set baud rate */ 383 baud = uart_get_baud_rate(port, termios, old, 300, 115200); 384 baud = msm_set_baud_rate(port, baud); 385 if (tty_termios_baud_rate(termios)) 386 tty_termios_encode_baud_rate(termios, baud, baud); 387 388 /* calculate parity */ 389 mr = msm_read(port, UART_MR2); 390 mr &= ~UART_MR2_PARITY_MODE; 391 if (termios->c_cflag & PARENB) { 392 if (termios->c_cflag & PARODD) 393 mr |= UART_MR2_PARITY_MODE_ODD; 394 else if (termios->c_cflag & CMSPAR) 395 mr |= UART_MR2_PARITY_MODE_SPACE; 396 else 397 mr |= UART_MR2_PARITY_MODE_EVEN; 398 } 399 400 /* calculate bits per char */ 401 mr &= ~UART_MR2_BITS_PER_CHAR; 402 switch (termios->c_cflag & CSIZE) { 403 case CS5: 404 mr |= UART_MR2_BITS_PER_CHAR_5; 405 break; 406 case CS6: 407 mr |= UART_MR2_BITS_PER_CHAR_6; 408 break; 409 case CS7: 410 mr |= UART_MR2_BITS_PER_CHAR_7; 411 break; 412 case CS8: 413 default: 414 mr |= UART_MR2_BITS_PER_CHAR_8; 415 break; 416 } 417 418 /* calculate stop bits */ 419 mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO); 420 if (termios->c_cflag & CSTOPB) 421 mr |= UART_MR2_STOP_BIT_LEN_TWO; 422 else 423 mr |= UART_MR2_STOP_BIT_LEN_ONE; 424 425 /* set parity, bits per char, and stop bit */ 426 msm_write(port, mr, UART_MR2); 427 428 /* calculate and set hardware flow control */ 429 mr = msm_read(port, UART_MR1); 430 mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL); 431 if (termios->c_cflag & CRTSCTS) { 432 mr |= UART_MR1_CTS_CTL; 433 mr |= UART_MR1_RX_RDY_CTL; 434 } 435 msm_write(port, mr, UART_MR1); 436 437 /* Configure status bits to ignore based on termio flags. */ 438 port->read_status_mask = 0; 439 if (termios->c_iflag & INPCK) 440 port->read_status_mask |= UART_SR_PAR_FRAME_ERR; 441 if (termios->c_iflag & (BRKINT | PARMRK)) 442 port->read_status_mask |= UART_SR_RX_BREAK; 443 444 uart_update_timeout(port, termios->c_cflag, baud); 445 446 spin_unlock_irqrestore(&port->lock, flags); 447 } 448 449 static const char *msm_type(struct uart_port *port) 450 { 451 return "MSM"; 452 } 453 454 static void msm_release_port(struct uart_port *port) 455 { 456 struct platform_device *pdev = to_platform_device(port->dev); 457 struct resource *resource; 458 resource_size_t size; 459 460 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 461 if (unlikely(!resource)) 462 return; 463 size = resource->end - resource->start + 1; 464 465 release_mem_region(port->mapbase, size); 466 iounmap(port->membase); 467 port->membase = NULL; 468 } 469 470 static int msm_request_port(struct uart_port *port) 471 { 472 struct platform_device *pdev = to_platform_device(port->dev); 473 struct resource *resource; 474 resource_size_t size; 475 476 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 477 if (unlikely(!resource)) 478 return -ENXIO; 479 size = resource->end - resource->start + 1; 480 481 if (unlikely(!request_mem_region(port->mapbase, size, "msm_serial"))) 482 return -EBUSY; 483 484 port->membase = ioremap(port->mapbase, size); 485 if (!port->membase) { 486 release_mem_region(port->mapbase, size); 487 return -EBUSY; 488 } 489 490 return 0; 491 } 492 493 static void msm_config_port(struct uart_port *port, int flags) 494 { 495 if (flags & UART_CONFIG_TYPE) { 496 port->type = PORT_MSM; 497 msm_request_port(port); 498 } 499 } 500 501 static int msm_verify_port(struct uart_port *port, struct serial_struct *ser) 502 { 503 if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_MSM)) 504 return -EINVAL; 505 if (unlikely(port->irq != ser->irq)) 506 return -EINVAL; 507 return 0; 508 } 509 510 static void msm_power(struct uart_port *port, unsigned int state, 511 unsigned int oldstate) 512 { 513 struct msm_port *msm_port = UART_TO_MSM(port); 514 515 switch (state) { 516 case 0: 517 clk_enable(msm_port->clk); 518 break; 519 case 3: 520 clk_disable(msm_port->clk); 521 break; 522 default: 523 printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state); 524 } 525 } 526 527 static struct uart_ops msm_uart_pops = { 528 .tx_empty = msm_tx_empty, 529 .set_mctrl = msm_set_mctrl, 530 .get_mctrl = msm_get_mctrl, 531 .stop_tx = msm_stop_tx, 532 .start_tx = msm_start_tx, 533 .stop_rx = msm_stop_rx, 534 .enable_ms = msm_enable_ms, 535 .break_ctl = msm_break_ctl, 536 .startup = msm_startup, 537 .shutdown = msm_shutdown, 538 .set_termios = msm_set_termios, 539 .type = msm_type, 540 .release_port = msm_release_port, 541 .request_port = msm_request_port, 542 .config_port = msm_config_port, 543 .verify_port = msm_verify_port, 544 .pm = msm_power, 545 }; 546 547 static struct msm_port msm_uart_ports[] = { 548 { 549 .uart = { 550 .iotype = UPIO_MEM, 551 .ops = &msm_uart_pops, 552 .flags = UPF_BOOT_AUTOCONF, 553 .fifosize = 512, 554 .line = 0, 555 }, 556 }, 557 { 558 .uart = { 559 .iotype = UPIO_MEM, 560 .ops = &msm_uart_pops, 561 .flags = UPF_BOOT_AUTOCONF, 562 .fifosize = 512, 563 .line = 1, 564 }, 565 }, 566 { 567 .uart = { 568 .iotype = UPIO_MEM, 569 .ops = &msm_uart_pops, 570 .flags = UPF_BOOT_AUTOCONF, 571 .fifosize = 64, 572 .line = 2, 573 }, 574 }, 575 }; 576 577 #define UART_NR ARRAY_SIZE(msm_uart_ports) 578 579 static inline struct uart_port *get_port_from_line(unsigned int line) 580 { 581 return &msm_uart_ports[line].uart; 582 } 583 584 #ifdef CONFIG_SERIAL_MSM_CONSOLE 585 586 static void msm_console_putchar(struct uart_port *port, int c) 587 { 588 while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) 589 ; 590 msm_write(port, c, UART_TF); 591 } 592 593 static void msm_console_write(struct console *co, const char *s, 594 unsigned int count) 595 { 596 struct uart_port *port; 597 struct msm_port *msm_port; 598 599 BUG_ON(co->index < 0 || co->index >= UART_NR); 600 601 port = get_port_from_line(co->index); 602 msm_port = UART_TO_MSM(port); 603 604 spin_lock(&port->lock); 605 uart_console_write(port, s, count, msm_console_putchar); 606 spin_unlock(&port->lock); 607 } 608 609 static int __init msm_console_setup(struct console *co, char *options) 610 { 611 struct uart_port *port; 612 int baud, flow, bits, parity; 613 614 if (unlikely(co->index >= UART_NR || co->index < 0)) 615 return -ENXIO; 616 617 port = get_port_from_line(co->index); 618 619 if (unlikely(!port->membase)) 620 return -ENXIO; 621 622 port->cons = co; 623 624 msm_init_clock(port); 625 626 if (options) 627 uart_parse_options(options, &baud, &parity, &bits, &flow); 628 629 bits = 8; 630 parity = 'n'; 631 flow = 'n'; 632 msm_write(port, UART_MR2_BITS_PER_CHAR_8 | UART_MR2_STOP_BIT_LEN_ONE, 633 UART_MR2); /* 8N1 */ 634 635 if (baud < 300 || baud > 115200) 636 baud = 115200; 637 msm_set_baud_rate(port, baud); 638 639 msm_reset(port); 640 641 printk(KERN_INFO "msm_serial: console setup on port #%d\n", port->line); 642 643 return uart_set_options(port, co, baud, parity, bits, flow); 644 } 645 646 static struct uart_driver msm_uart_driver; 647 648 static struct console msm_console = { 649 .name = "ttyMSM", 650 .write = msm_console_write, 651 .device = uart_console_device, 652 .setup = msm_console_setup, 653 .flags = CON_PRINTBUFFER, 654 .index = -1, 655 .data = &msm_uart_driver, 656 }; 657 658 #define MSM_CONSOLE (&msm_console) 659 660 #else 661 #define MSM_CONSOLE NULL 662 #endif 663 664 static struct uart_driver msm_uart_driver = { 665 .owner = THIS_MODULE, 666 .driver_name = "msm_serial", 667 .dev_name = "ttyMSM", 668 .nr = UART_NR, 669 .cons = MSM_CONSOLE, 670 }; 671 672 static int __init msm_serial_probe(struct platform_device *pdev) 673 { 674 struct msm_port *msm_port; 675 struct resource *resource; 676 struct uart_port *port; 677 int irq; 678 679 if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) 680 return -ENXIO; 681 682 printk(KERN_INFO "msm_serial: detected port #%d\n", pdev->id); 683 684 port = get_port_from_line(pdev->id); 685 port->dev = &pdev->dev; 686 msm_port = UART_TO_MSM(port); 687 688 msm_port->clk = clk_get(&pdev->dev, "uart_clk"); 689 if (IS_ERR(msm_port->clk)) 690 return PTR_ERR(msm_port->clk); 691 port->uartclk = clk_get_rate(msm_port->clk); 692 printk(KERN_INFO "uartclk = %d\n", port->uartclk); 693 694 695 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 696 if (unlikely(!resource)) 697 return -ENXIO; 698 port->mapbase = resource->start; 699 700 irq = platform_get_irq(pdev, 0); 701 if (unlikely(irq < 0)) 702 return -ENXIO; 703 port->irq = irq; 704 705 platform_set_drvdata(pdev, port); 706 707 return uart_add_one_port(&msm_uart_driver, port); 708 } 709 710 static int __devexit msm_serial_remove(struct platform_device *pdev) 711 { 712 struct msm_port *msm_port = platform_get_drvdata(pdev); 713 714 clk_put(msm_port->clk); 715 716 return 0; 717 } 718 719 static struct platform_driver msm_platform_driver = { 720 .remove = msm_serial_remove, 721 .driver = { 722 .name = "msm_serial", 723 .owner = THIS_MODULE, 724 }, 725 }; 726 727 static int __init msm_serial_init(void) 728 { 729 int ret; 730 731 ret = uart_register_driver(&msm_uart_driver); 732 if (unlikely(ret)) 733 return ret; 734 735 ret = platform_driver_probe(&msm_platform_driver, msm_serial_probe); 736 if (unlikely(ret)) 737 uart_unregister_driver(&msm_uart_driver); 738 739 printk(KERN_INFO "msm_serial: driver initialized\n"); 740 741 return ret; 742 } 743 744 static void __exit msm_serial_exit(void) 745 { 746 #ifdef CONFIG_SERIAL_MSM_CONSOLE 747 unregister_console(&msm_console); 748 #endif 749 platform_driver_unregister(&msm_platform_driver); 750 uart_unregister_driver(&msm_uart_driver); 751 } 752 753 module_init(msm_serial_init); 754 module_exit(msm_serial_exit); 755 756 MODULE_AUTHOR("Robert Love <rlove@google.com>"); 757 MODULE_DESCRIPTION("Driver for msm7x serial device"); 758 MODULE_LICENSE("GPL"); 759