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