linux/drivers/tty/serial/serial_ks8695.c
<<
>>
Prefs
   1/*
   2 *  Driver for KS8695 serial ports
   3 *
   4 *  Based on drivers/serial/serial_amba.c, by Kam Lee.
   5 *
   6 *  Copyright 2002-2005 Micrel Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 */
  14#include <linux/module.h>
  15#include <linux/tty.h>
  16#include <linux/tty_flip.h>
  17#include <linux/ioport.h>
  18#include <linux/init.h>
  19#include <linux/serial.h>
  20#include <linux/console.h>
  21#include <linux/sysrq.h>
  22#include <linux/device.h>
  23
  24#include <asm/io.h>
  25#include <asm/irq.h>
  26#include <asm/mach/irq.h>
  27
  28#include <mach/regs-uart.h>
  29#include <mach/regs-irq.h>
  30
  31#if defined(CONFIG_SERIAL_KS8695_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  32#define SUPPORT_SYSRQ
  33#endif
  34
  35#include <linux/serial_core.h>
  36
  37
  38#define SERIAL_KS8695_MAJOR     204
  39#define SERIAL_KS8695_MINOR     16
  40#define SERIAL_KS8695_DEVNAME   "ttyAM"
  41
  42#define SERIAL_KS8695_NR        1
  43
  44/*
  45 * Access macros for the KS8695 UART
  46 */
  47#define UART_GET_CHAR(p)        (__raw_readl((p)->membase + KS8695_URRB) & 0xFF)
  48#define UART_PUT_CHAR(p, c)     __raw_writel((c), (p)->membase + KS8695_URTH)
  49#define UART_GET_FCR(p)         __raw_readl((p)->membase + KS8695_URFC)
  50#define UART_PUT_FCR(p, c)      __raw_writel((c), (p)->membase + KS8695_URFC)
  51#define UART_GET_MSR(p)         __raw_readl((p)->membase + KS8695_URMS)
  52#define UART_GET_LSR(p)         __raw_readl((p)->membase + KS8695_URLS)
  53#define UART_GET_LCR(p)         __raw_readl((p)->membase + KS8695_URLC)
  54#define UART_PUT_LCR(p, c)      __raw_writel((c), (p)->membase + KS8695_URLC)
  55#define UART_GET_MCR(p)         __raw_readl((p)->membase + KS8695_URMC)
  56#define UART_PUT_MCR(p, c)      __raw_writel((c), (p)->membase + KS8695_URMC)
  57#define UART_GET_BRDR(p)        __raw_readl((p)->membase + KS8695_URBD)
  58#define UART_PUT_BRDR(p, c)     __raw_writel((c), (p)->membase + KS8695_URBD)
  59
  60#define KS8695_CLR_TX_INT()     __raw_writel(1 << KS8695_IRQ_UART_TX, KS8695_IRQ_VA + KS8695_INTST)
  61
  62#define UART_DUMMY_LSR_RX       0x100
  63#define UART_PORT_SIZE          (KS8695_USR - KS8695_URRB + 4)
  64
  65static inline int tx_enabled(struct uart_port *port)
  66{
  67        return port->unused[0] & 1;
  68}
  69
  70static inline int rx_enabled(struct uart_port *port)
  71{
  72        return port->unused[0] & 2;
  73}
  74
  75static inline int ms_enabled(struct uart_port *port)
  76{
  77        return port->unused[0] & 4;
  78}
  79
  80static inline void ms_enable(struct uart_port *port, int enabled)
  81{
  82        if(enabled)
  83                port->unused[0] |= 4;
  84        else
  85                port->unused[0] &= ~4;
  86}
  87
  88static inline void rx_enable(struct uart_port *port, int enabled)
  89{
  90        if(enabled)
  91                port->unused[0] |= 2;
  92        else
  93                port->unused[0] &= ~2;
  94}
  95
  96static inline void tx_enable(struct uart_port *port, int enabled)
  97{
  98        if(enabled)
  99                port->unused[0] |= 1;
 100        else
 101                port->unused[0] &= ~1;
 102}
 103
 104
 105#ifdef SUPPORT_SYSRQ
 106static struct console ks8695_console;
 107#endif
 108
 109static void ks8695uart_stop_tx(struct uart_port *port)
 110{
 111        if (tx_enabled(port)) {
 112                /* use disable_irq_nosync() and not disable_irq() to avoid self
 113                 * imposed deadlock by not waiting for irq handler to end,
 114                 * since this ks8695uart_stop_tx() is called from interrupt context.
 115                 */
 116                disable_irq_nosync(KS8695_IRQ_UART_TX);
 117                tx_enable(port, 0);
 118        }
 119}
 120
 121static void ks8695uart_start_tx(struct uart_port *port)
 122{
 123        if (!tx_enabled(port)) {
 124                enable_irq(KS8695_IRQ_UART_TX);
 125                tx_enable(port, 1);
 126        }
 127}
 128
 129static void ks8695uart_stop_rx(struct uart_port *port)
 130{
 131        if (rx_enabled(port)) {
 132                disable_irq(KS8695_IRQ_UART_RX);
 133                rx_enable(port, 0);
 134        }
 135}
 136
 137static void ks8695uart_enable_ms(struct uart_port *port)
 138{
 139        if (!ms_enabled(port)) {
 140                enable_irq(KS8695_IRQ_UART_MODEM_STATUS);
 141                ms_enable(port,1);
 142        }
 143}
 144
 145static void ks8695uart_disable_ms(struct uart_port *port)
 146{
 147        if (ms_enabled(port)) {
 148                disable_irq(KS8695_IRQ_UART_MODEM_STATUS);
 149                ms_enable(port,0);
 150        }
 151}
 152
 153static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id)
 154{
 155        struct uart_port *port = dev_id;
 156        unsigned int status, ch, lsr, flg, max_count = 256;
 157
 158        status = UART_GET_LSR(port);            /* clears pending LSR interrupts */
 159        while ((status & URLS_URDR) && max_count--) {
 160                ch = UART_GET_CHAR(port);
 161                flg = TTY_NORMAL;
 162
 163                port->icount.rx++;
 164
 165                /*
 166                 * Note that the error handling code is
 167                 * out of the main execution path
 168                 */
 169                lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX;
 170                if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) {
 171                        if (lsr & URLS_URBI) {
 172                                lsr &= ~(URLS_URFE | URLS_URPE);
 173                                port->icount.brk++;
 174                                if (uart_handle_break(port))
 175                                        goto ignore_char;
 176                        }
 177                        if (lsr & URLS_URPE)
 178                                port->icount.parity++;
 179                        if (lsr & URLS_URFE)
 180                                port->icount.frame++;
 181                        if (lsr & URLS_URROE)
 182                                port->icount.overrun++;
 183
 184                        lsr &= port->read_status_mask;
 185
 186                        if (lsr & URLS_URBI)
 187                                flg = TTY_BREAK;
 188                        else if (lsr & URLS_URPE)
 189                                flg = TTY_PARITY;
 190                        else if (lsr & URLS_URFE)
 191                                flg = TTY_FRAME;
 192                }
 193
 194                if (uart_handle_sysrq_char(port, ch))
 195                        goto ignore_char;
 196
 197                uart_insert_char(port, lsr, URLS_URROE, ch, flg);
 198
 199ignore_char:
 200                status = UART_GET_LSR(port);
 201        }
 202        tty_flip_buffer_push(&port->state->port);
 203
 204        return IRQ_HANDLED;
 205}
 206
 207
 208static irqreturn_t ks8695uart_tx_chars(int irq, void *dev_id)
 209{
 210        struct uart_port *port = dev_id;
 211        struct circ_buf *xmit = &port->state->xmit;
 212        unsigned int count;
 213
 214        if (port->x_char) {
 215                KS8695_CLR_TX_INT();
 216                UART_PUT_CHAR(port, port->x_char);
 217                port->icount.tx++;
 218                port->x_char = 0;
 219                return IRQ_HANDLED;
 220        }
 221
 222        if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
 223                ks8695uart_stop_tx(port);
 224                return IRQ_HANDLED;
 225        }
 226
 227        count = 16;     /* fifo size */
 228        while (!uart_circ_empty(xmit) && (count-- > 0)) {
 229                KS8695_CLR_TX_INT();
 230                UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
 231
 232                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 233                port->icount.tx++;
 234        }
 235
 236        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 237                uart_write_wakeup(port);
 238
 239        if (uart_circ_empty(xmit))
 240                ks8695uart_stop_tx(port);
 241
 242        return IRQ_HANDLED;
 243}
 244
 245static irqreturn_t ks8695uart_modem_status(int irq, void *dev_id)
 246{
 247        struct uart_port *port = dev_id;
 248        unsigned int status;
 249
 250        /*
 251         * clear modem interrupt by reading MSR
 252         */
 253        status = UART_GET_MSR(port);
 254
 255        if (status & URMS_URDDCD)
 256                uart_handle_dcd_change(port, status & URMS_URDDCD);
 257
 258        if (status & URMS_URDDST)
 259                port->icount.dsr++;
 260
 261        if (status & URMS_URDCTS)
 262                uart_handle_cts_change(port, status & URMS_URDCTS);
 263
 264        if (status & URMS_URTERI)
 265                port->icount.rng++;
 266
 267        wake_up_interruptible(&port->state->port.delta_msr_wait);
 268
 269        return IRQ_HANDLED;
 270}
 271
 272static unsigned int ks8695uart_tx_empty(struct uart_port *port)
 273{
 274        return (UART_GET_LSR(port) & URLS_URTE) ? TIOCSER_TEMT : 0;
 275}
 276
 277static unsigned int ks8695uart_get_mctrl(struct uart_port *port)
 278{
 279        unsigned int result = 0;
 280        unsigned int status;
 281
 282        status = UART_GET_MSR(port);
 283        if (status & URMS_URDCD)
 284                result |= TIOCM_CAR;
 285        if (status & URMS_URDSR)
 286                result |= TIOCM_DSR;
 287        if (status & URMS_URCTS)
 288                result |= TIOCM_CTS;
 289        if (status & URMS_URRI)
 290                result |= TIOCM_RI;
 291
 292        return result;
 293}
 294
 295static void ks8695uart_set_mctrl(struct uart_port *port, u_int mctrl)
 296{
 297        unsigned int mcr;
 298
 299        mcr = UART_GET_MCR(port);
 300        if (mctrl & TIOCM_RTS)
 301                mcr |= URMC_URRTS;
 302        else
 303                mcr &= ~URMC_URRTS;
 304
 305        if (mctrl & TIOCM_DTR)
 306                mcr |= URMC_URDTR;
 307        else
 308                mcr &= ~URMC_URDTR;
 309
 310        UART_PUT_MCR(port, mcr);
 311}
 312
 313static void ks8695uart_break_ctl(struct uart_port *port, int break_state)
 314{
 315        unsigned int lcr;
 316
 317        lcr = UART_GET_LCR(port);
 318
 319        if (break_state == -1)
 320                lcr |= URLC_URSBC;
 321        else
 322                lcr &= ~URLC_URSBC;
 323
 324        UART_PUT_LCR(port, lcr);
 325}
 326
 327static int ks8695uart_startup(struct uart_port *port)
 328{
 329        int retval;
 330
 331        set_irq_flags(KS8695_IRQ_UART_TX, IRQF_VALID | IRQF_NOAUTOEN);
 332        tx_enable(port, 0);
 333        rx_enable(port, 1);
 334        ms_enable(port, 1);
 335
 336        /*
 337         * Allocate the IRQ
 338         */
 339        retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, 0, "UART TX", port);
 340        if (retval)
 341                goto err_tx;
 342
 343        retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, 0, "UART RX", port);
 344        if (retval)
 345                goto err_rx;
 346
 347        retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, 0, "UART LineStatus", port);
 348        if (retval)
 349                goto err_ls;
 350
 351        retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, 0, "UART ModemStatus", port);
 352        if (retval)
 353                goto err_ms;
 354
 355        return 0;
 356
 357err_ms:
 358        free_irq(KS8695_IRQ_UART_LINE_STATUS, port);
 359err_ls:
 360        free_irq(KS8695_IRQ_UART_RX, port);
 361err_rx:
 362        free_irq(KS8695_IRQ_UART_TX, port);
 363err_tx:
 364        return retval;
 365}
 366
 367static void ks8695uart_shutdown(struct uart_port *port)
 368{
 369        /*
 370         * Free the interrupt
 371         */
 372        free_irq(KS8695_IRQ_UART_RX, port);
 373        free_irq(KS8695_IRQ_UART_TX, port);
 374        free_irq(KS8695_IRQ_UART_MODEM_STATUS, port);
 375        free_irq(KS8695_IRQ_UART_LINE_STATUS, port);
 376
 377        /* disable break condition and fifos */
 378        UART_PUT_LCR(port, UART_GET_LCR(port) & ~URLC_URSBC);
 379        UART_PUT_FCR(port, UART_GET_FCR(port) & ~URFC_URFE);
 380}
 381
 382static void ks8695uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
 383{
 384        unsigned int lcr, fcr = 0;
 385        unsigned long flags;
 386        unsigned int baud, quot;
 387
 388        /*
 389         * Ask the core to calculate the divisor for us.
 390         */
 391        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
 392        quot = uart_get_divisor(port, baud);
 393
 394        switch (termios->c_cflag & CSIZE) {
 395        case CS5:
 396                lcr = URCL_5;
 397                break;
 398        case CS6:
 399                lcr = URCL_6;
 400                break;
 401        case CS7:
 402                lcr = URCL_7;
 403                break;
 404        default:
 405                lcr = URCL_8;
 406                break;
 407        }
 408
 409        /* stop bits */
 410        if (termios->c_cflag & CSTOPB)
 411                lcr |= URLC_URSB;
 412
 413        /* parity */
 414        if (termios->c_cflag & PARENB) {
 415                if (termios->c_cflag & CMSPAR) {        /* Mark or Space parity */
 416                        if (termios->c_cflag & PARODD)
 417                                lcr |= URPE_MARK;
 418                        else
 419                                lcr |= URPE_SPACE;
 420                }
 421                else if (termios->c_cflag & PARODD)
 422                        lcr |= URPE_ODD;
 423                else
 424                        lcr |= URPE_EVEN;
 425        }
 426
 427        if (port->fifosize > 1)
 428                fcr = URFC_URFRT_8 | URFC_URTFR | URFC_URRFR | URFC_URFE;
 429
 430        spin_lock_irqsave(&port->lock, flags);
 431
 432        /*
 433         * Update the per-port timeout.
 434         */
 435        uart_update_timeout(port, termios->c_cflag, baud);
 436
 437        port->read_status_mask = URLS_URROE;
 438        if (termios->c_iflag & INPCK)
 439                port->read_status_mask |= (URLS_URFE | URLS_URPE);
 440        if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
 441                port->read_status_mask |= URLS_URBI;
 442
 443        /*
 444         * Characters to ignore
 445         */
 446        port->ignore_status_mask = 0;
 447        if (termios->c_iflag & IGNPAR)
 448                port->ignore_status_mask |= (URLS_URFE | URLS_URPE);
 449        if (termios->c_iflag & IGNBRK) {
 450                port->ignore_status_mask |= URLS_URBI;
 451                /*
 452                 * If we're ignoring parity and break indicators,
 453                 * ignore overruns too (for real raw support).
 454                 */
 455                if (termios->c_iflag & IGNPAR)
 456                        port->ignore_status_mask |= URLS_URROE;
 457        }
 458
 459        /*
 460         * Ignore all characters if CREAD is not set.
 461         */
 462        if ((termios->c_cflag & CREAD) == 0)
 463                port->ignore_status_mask |= UART_DUMMY_LSR_RX;
 464
 465        /* first, disable everything */
 466        if (UART_ENABLE_MS(port, termios->c_cflag))
 467                ks8695uart_enable_ms(port);
 468        else
 469                ks8695uart_disable_ms(port);
 470
 471        /* Set baud rate */
 472        UART_PUT_BRDR(port, quot);
 473
 474        UART_PUT_LCR(port, lcr);
 475        UART_PUT_FCR(port, fcr);
 476
 477        spin_unlock_irqrestore(&port->lock, flags);
 478}
 479
 480static const char *ks8695uart_type(struct uart_port *port)
 481{
 482        return port->type == PORT_KS8695 ? "KS8695" : NULL;
 483}
 484
 485/*
 486 * Release the memory region(s) being used by 'port'
 487 */
 488static void ks8695uart_release_port(struct uart_port *port)
 489{
 490        release_mem_region(port->mapbase, UART_PORT_SIZE);
 491}
 492
 493/*
 494 * Request the memory region(s) being used by 'port'
 495 */
 496static int ks8695uart_request_port(struct uart_port *port)
 497{
 498        return request_mem_region(port->mapbase, UART_PORT_SIZE,
 499                        "serial_ks8695") != NULL ? 0 : -EBUSY;
 500}
 501
 502/*
 503 * Configure/autoconfigure the port.
 504 */
 505static void ks8695uart_config_port(struct uart_port *port, int flags)
 506{
 507        if (flags & UART_CONFIG_TYPE) {
 508                port->type = PORT_KS8695;
 509                ks8695uart_request_port(port);
 510        }
 511}
 512
 513/*
 514 * verify the new serial_struct (for TIOCSSERIAL).
 515 */
 516static int ks8695uart_verify_port(struct uart_port *port, struct serial_struct *ser)
 517{
 518        int ret = 0;
 519
 520        if (ser->type != PORT_UNKNOWN && ser->type != PORT_KS8695)
 521                ret = -EINVAL;
 522        if (ser->irq != port->irq)
 523                ret = -EINVAL;
 524        if (ser->baud_base < 9600)
 525                ret = -EINVAL;
 526        return ret;
 527}
 528
 529static struct uart_ops ks8695uart_pops = {
 530        .tx_empty       = ks8695uart_tx_empty,
 531        .set_mctrl      = ks8695uart_set_mctrl,
 532        .get_mctrl      = ks8695uart_get_mctrl,
 533        .stop_tx        = ks8695uart_stop_tx,
 534        .start_tx       = ks8695uart_start_tx,
 535        .stop_rx        = ks8695uart_stop_rx,
 536        .enable_ms      = ks8695uart_enable_ms,
 537        .break_ctl      = ks8695uart_break_ctl,
 538        .startup        = ks8695uart_startup,
 539        .shutdown       = ks8695uart_shutdown,
 540        .set_termios    = ks8695uart_set_termios,
 541        .type           = ks8695uart_type,
 542        .release_port   = ks8695uart_release_port,
 543        .request_port   = ks8695uart_request_port,
 544        .config_port    = ks8695uart_config_port,
 545        .verify_port    = ks8695uart_verify_port,
 546};
 547
 548static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = {
 549        {
 550                .membase        = KS8695_UART_VA,
 551                .mapbase        = KS8695_UART_PA,
 552                .iotype         = SERIAL_IO_MEM,
 553                .irq            = KS8695_IRQ_UART_TX,
 554                .uartclk        = KS8695_CLOCK_RATE * 16,
 555                .fifosize       = 16,
 556                .ops            = &ks8695uart_pops,
 557                .flags          = ASYNC_BOOT_AUTOCONF,
 558                .line           = 0,
 559        }
 560};
 561
 562#ifdef CONFIG_SERIAL_KS8695_CONSOLE
 563static void ks8695_console_putchar(struct uart_port *port, int ch)
 564{
 565        while (!(UART_GET_LSR(port) & URLS_URTHRE))
 566                barrier();
 567
 568        UART_PUT_CHAR(port, ch);
 569}
 570
 571static void ks8695_console_write(struct console *co, const char *s, u_int count)
 572{
 573        struct uart_port *port = ks8695uart_ports + co->index;
 574
 575        uart_console_write(port, s, count, ks8695_console_putchar);
 576}
 577
 578static void __init ks8695_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
 579{
 580        unsigned int lcr;
 581
 582        lcr = UART_GET_LCR(port);
 583
 584        switch (lcr & URLC_PARITY) {
 585                case URPE_ODD:
 586                        *parity = 'o';
 587                        break;
 588                case URPE_EVEN:
 589                        *parity = 'e';
 590                        break;
 591                default:
 592                        *parity = 'n';
 593        }
 594
 595        switch (lcr & URLC_URCL) {
 596                case URCL_5:
 597                        *bits = 5;
 598                        break;
 599                case URCL_6:
 600                        *bits = 6;
 601                        break;
 602                case URCL_7:
 603                        *bits = 7;
 604                        break;
 605                default:
 606                        *bits = 8;
 607        }
 608
 609        *baud = port->uartclk / (UART_GET_BRDR(port) & 0x0FFF);
 610        *baud /= 16;
 611        *baud &= 0xFFFFFFF0;
 612}
 613
 614static int __init ks8695_console_setup(struct console *co, char *options)
 615{
 616        struct uart_port *port;
 617        int baud = 115200;
 618        int bits = 8;
 619        int parity = 'n';
 620        int flow = 'n';
 621
 622        /*
 623         * Check whether an invalid uart number has been specified, and
 624         * if so, search for the first available port that does have
 625         * console support.
 626         */
 627        port = uart_get_console(ks8695uart_ports, SERIAL_KS8695_NR, co);
 628
 629        if (options)
 630                uart_parse_options(options, &baud, &parity, &bits, &flow);
 631        else
 632                ks8695_console_get_options(port, &baud, &parity, &bits);
 633
 634        return uart_set_options(port, co, baud, parity, bits, flow);
 635}
 636
 637static struct uart_driver ks8695_reg;
 638
 639static struct console ks8695_console = {
 640        .name           = SERIAL_KS8695_DEVNAME,
 641        .write          = ks8695_console_write,
 642        .device         = uart_console_device,
 643        .setup          = ks8695_console_setup,
 644        .flags          = CON_PRINTBUFFER,
 645        .index          = -1,
 646        .data           = &ks8695_reg,
 647};
 648
 649static int __init ks8695_console_init(void)
 650{
 651        add_preferred_console(SERIAL_KS8695_DEVNAME, 0, NULL);
 652        register_console(&ks8695_console);
 653        return 0;
 654}
 655
 656console_initcall(ks8695_console_init);
 657
 658#define KS8695_CONSOLE  &ks8695_console
 659#else
 660#define KS8695_CONSOLE  NULL
 661#endif
 662
 663static struct uart_driver ks8695_reg = {
 664        .owner                  = THIS_MODULE,
 665        .driver_name            = "serial_ks8695",
 666        .dev_name               = SERIAL_KS8695_DEVNAME,
 667        .major                  = SERIAL_KS8695_MAJOR,
 668        .minor                  = SERIAL_KS8695_MINOR,
 669        .nr                     = SERIAL_KS8695_NR,
 670        .cons                   = KS8695_CONSOLE,
 671};
 672
 673static int __init ks8695uart_init(void)
 674{
 675        int i, ret;
 676
 677        printk(KERN_INFO "Serial: Micrel KS8695 UART driver\n");
 678
 679        ret = uart_register_driver(&ks8695_reg);
 680        if (ret)
 681                return ret;
 682
 683        for (i = 0; i < SERIAL_KS8695_NR; i++)
 684                uart_add_one_port(&ks8695_reg, &ks8695uart_ports[0]);
 685
 686        return 0;
 687}
 688
 689static void __exit ks8695uart_exit(void)
 690{
 691        int i;
 692
 693        for (i = 0; i < SERIAL_KS8695_NR; i++)
 694                uart_remove_one_port(&ks8695_reg, &ks8695uart_ports[0]);
 695        uart_unregister_driver(&ks8695_reg);
 696}
 697
 698module_init(ks8695uart_init);
 699module_exit(ks8695uart_exit);
 700
 701MODULE_DESCRIPTION("KS8695 serial port driver");
 702MODULE_AUTHOR("Micrel Inc.");
 703MODULE_LICENSE("GPL");
 704