linux/drivers/tty/serial/mcf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/****************************************************************************/
   3
   4/*
   5 *      mcf.c -- Freescale ColdFire UART driver
   6 *
   7 *      (C) Copyright 2003-2007, Greg Ungerer <gerg@uclinux.org>
   8 */
   9
  10/****************************************************************************/
  11
  12#include <linux/kernel.h>
  13#include <linux/init.h>
  14#include <linux/interrupt.h>
  15#include <linux/module.h>
  16#include <linux/console.h>
  17#include <linux/tty.h>
  18#include <linux/tty_flip.h>
  19#include <linux/serial.h>
  20#include <linux/serial_core.h>
  21#include <linux/io.h>
  22#include <linux/uaccess.h>
  23#include <linux/platform_device.h>
  24#include <asm/coldfire.h>
  25#include <asm/mcfsim.h>
  26#include <asm/mcfuart.h>
  27#include <asm/nettel.h>
  28
  29/****************************************************************************/
  30
  31/*
  32 *      Some boards implement the DTR/DCD lines using GPIO lines, most
  33 *      don't. Dummy out the access macros for those that don't. Those
  34 *      that do should define these macros somewhere in there board
  35 *      specific inlude files.
  36 */
  37#if !defined(mcf_getppdcd)
  38#define mcf_getppdcd(p)         (1)
  39#endif
  40#if !defined(mcf_getppdtr)
  41#define mcf_getppdtr(p)         (1)
  42#endif
  43#if !defined(mcf_setppdtr)
  44#define mcf_setppdtr(p, v)      do { } while (0)
  45#endif
  46
  47/****************************************************************************/
  48
  49/*
  50 *      Local per-uart structure.
  51 */
  52struct mcf_uart {
  53        struct uart_port        port;
  54        unsigned int            sigs;           /* Local copy of line sigs */
  55        unsigned char           imr;            /* Local IMR mirror */
  56};
  57
  58/****************************************************************************/
  59
  60static unsigned int mcf_tx_empty(struct uart_port *port)
  61{
  62        return (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXEMPTY) ?
  63                TIOCSER_TEMT : 0;
  64}
  65
  66/****************************************************************************/
  67
  68static unsigned int mcf_get_mctrl(struct uart_port *port)
  69{
  70        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
  71        unsigned int sigs;
  72
  73        sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ?
  74                0 : TIOCM_CTS;
  75        sigs |= (pp->sigs & TIOCM_RTS);
  76        sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0);
  77        sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0);
  78
  79        return sigs;
  80}
  81
  82/****************************************************************************/
  83
  84static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs)
  85{
  86        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
  87
  88        pp->sigs = sigs;
  89        mcf_setppdtr(port->line, (sigs & TIOCM_DTR));
  90        if (sigs & TIOCM_RTS)
  91                writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
  92        else
  93                writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0);
  94}
  95
  96/****************************************************************************/
  97
  98static void mcf_start_tx(struct uart_port *port)
  99{
 100        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 101
 102        if (port->rs485.flags & SER_RS485_ENABLED) {
 103                /* Enable Transmitter */
 104                writeb(MCFUART_UCR_TXENABLE, port->membase + MCFUART_UCR);
 105                /* Manually assert RTS */
 106                writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1);
 107        }
 108        pp->imr |= MCFUART_UIR_TXREADY;
 109        writeb(pp->imr, port->membase + MCFUART_UIMR);
 110}
 111
 112/****************************************************************************/
 113
 114static void mcf_stop_tx(struct uart_port *port)
 115{
 116        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 117
 118        pp->imr &= ~MCFUART_UIR_TXREADY;
 119        writeb(pp->imr, port->membase + MCFUART_UIMR);
 120}
 121
 122/****************************************************************************/
 123
 124static void mcf_stop_rx(struct uart_port *port)
 125{
 126        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 127
 128        pp->imr &= ~MCFUART_UIR_RXREADY;
 129        writeb(pp->imr, port->membase + MCFUART_UIMR);
 130}
 131
 132/****************************************************************************/
 133
 134static void mcf_break_ctl(struct uart_port *port, int break_state)
 135{
 136        unsigned long flags;
 137
 138        spin_lock_irqsave(&port->lock, flags);
 139        if (break_state == -1)
 140                writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);
 141        else
 142                writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);
 143        spin_unlock_irqrestore(&port->lock, flags);
 144}
 145
 146/****************************************************************************/
 147
 148static int mcf_startup(struct uart_port *port)
 149{
 150        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 151        unsigned long flags;
 152
 153        spin_lock_irqsave(&port->lock, flags);
 154
 155        /* Reset UART, get it into known state... */
 156        writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
 157        writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
 158
 159        /* Enable the UART transmitter and receiver */
 160        writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
 161                port->membase + MCFUART_UCR);
 162
 163        /* Enable RX interrupts now */
 164        pp->imr = MCFUART_UIR_RXREADY;
 165        writeb(pp->imr, port->membase + MCFUART_UIMR);
 166
 167        spin_unlock_irqrestore(&port->lock, flags);
 168
 169        return 0;
 170}
 171
 172/****************************************************************************/
 173
 174static void mcf_shutdown(struct uart_port *port)
 175{
 176        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 177        unsigned long flags;
 178
 179        spin_lock_irqsave(&port->lock, flags);
 180
 181        /* Disable all interrupts now */
 182        pp->imr = 0;
 183        writeb(pp->imr, port->membase + MCFUART_UIMR);
 184
 185        /* Disable UART transmitter and receiver */
 186        writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
 187        writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
 188
 189        spin_unlock_irqrestore(&port->lock, flags);
 190}
 191
 192/****************************************************************************/
 193
 194static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
 195        struct ktermios *old)
 196{
 197        unsigned long flags;
 198        unsigned int baud, baudclk;
 199#if defined(CONFIG_M5272)
 200        unsigned int baudfr;
 201#endif
 202        unsigned char mr1, mr2;
 203
 204        baud = uart_get_baud_rate(port, termios, old, 0, 230400);
 205#if defined(CONFIG_M5272)
 206        baudclk = (MCF_BUSCLK / baud) / 32;
 207        baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16;
 208#else
 209        baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
 210#endif
 211
 212        mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
 213        mr2 = 0;
 214
 215        switch (termios->c_cflag & CSIZE) {
 216        case CS5: mr1 |= MCFUART_MR1_CS5; break;
 217        case CS6: mr1 |= MCFUART_MR1_CS6; break;
 218        case CS7: mr1 |= MCFUART_MR1_CS7; break;
 219        case CS8:
 220        default:  mr1 |= MCFUART_MR1_CS8; break;
 221        }
 222
 223        if (termios->c_cflag & PARENB) {
 224                if (termios->c_cflag & CMSPAR) {
 225                        if (termios->c_cflag & PARODD)
 226                                mr1 |= MCFUART_MR1_PARITYMARK;
 227                        else
 228                                mr1 |= MCFUART_MR1_PARITYSPACE;
 229                } else {
 230                        if (termios->c_cflag & PARODD)
 231                                mr1 |= MCFUART_MR1_PARITYODD;
 232                        else
 233                                mr1 |= MCFUART_MR1_PARITYEVEN;
 234                }
 235        } else {
 236                mr1 |= MCFUART_MR1_PARITYNONE;
 237        }
 238
 239        /*
 240         * FIXME: port->read_status_mask and port->ignore_status_mask
 241         * need to be initialized based on termios settings for
 242         * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT
 243         */
 244
 245        if (termios->c_cflag & CSTOPB)
 246                mr2 |= MCFUART_MR2_STOP2;
 247        else
 248                mr2 |= MCFUART_MR2_STOP1;
 249
 250        if (termios->c_cflag & CRTSCTS) {
 251                mr1 |= MCFUART_MR1_RXRTS;
 252                mr2 |= MCFUART_MR2_TXCTS;
 253        }
 254
 255        spin_lock_irqsave(&port->lock, flags);
 256        if (port->rs485.flags & SER_RS485_ENABLED) {
 257                dev_dbg(port->dev, "Setting UART to RS485\n");
 258                mr2 |= MCFUART_MR2_TXRTS;
 259        }
 260
 261        uart_update_timeout(port, termios->c_cflag, baud);
 262        writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
 263        writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
 264        writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR);
 265        writeb(mr1, port->membase + MCFUART_UMR);
 266        writeb(mr2, port->membase + MCFUART_UMR);
 267        writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);
 268        writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);
 269#if defined(CONFIG_M5272)
 270        writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD);
 271#endif
 272        writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,
 273                port->membase + MCFUART_UCSR);
 274        writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
 275                port->membase + MCFUART_UCR);
 276        spin_unlock_irqrestore(&port->lock, flags);
 277}
 278
 279/****************************************************************************/
 280
 281static void mcf_rx_chars(struct mcf_uart *pp)
 282{
 283        struct uart_port *port = &pp->port;
 284        unsigned char status, ch, flag;
 285
 286        while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) {
 287                ch = readb(port->membase + MCFUART_URB);
 288                flag = TTY_NORMAL;
 289                port->icount.rx++;
 290
 291                if (status & MCFUART_USR_RXERR) {
 292                        writeb(MCFUART_UCR_CMDRESETERR,
 293                                port->membase + MCFUART_UCR);
 294
 295                        if (status & MCFUART_USR_RXBREAK) {
 296                                port->icount.brk++;
 297                                if (uart_handle_break(port))
 298                                        continue;
 299                        } else if (status & MCFUART_USR_RXPARITY) {
 300                                port->icount.parity++;
 301                        } else if (status & MCFUART_USR_RXOVERRUN) {
 302                                port->icount.overrun++;
 303                        } else if (status & MCFUART_USR_RXFRAMING) {
 304                                port->icount.frame++;
 305                        }
 306
 307                        status &= port->read_status_mask;
 308
 309                        if (status & MCFUART_USR_RXBREAK)
 310                                flag = TTY_BREAK;
 311                        else if (status & MCFUART_USR_RXPARITY)
 312                                flag = TTY_PARITY;
 313                        else if (status & MCFUART_USR_RXFRAMING)
 314                                flag = TTY_FRAME;
 315                }
 316
 317                if (uart_handle_sysrq_char(port, ch))
 318                        continue;
 319                uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
 320        }
 321
 322        spin_unlock(&port->lock);
 323        tty_flip_buffer_push(&port->state->port);
 324        spin_lock(&port->lock);
 325}
 326
 327/****************************************************************************/
 328
 329static void mcf_tx_chars(struct mcf_uart *pp)
 330{
 331        struct uart_port *port = &pp->port;
 332        struct circ_buf *xmit = &port->state->xmit;
 333
 334        if (port->x_char) {
 335                /* Send special char - probably flow control */
 336                writeb(port->x_char, port->membase + MCFUART_UTB);
 337                port->x_char = 0;
 338                port->icount.tx++;
 339                return;
 340        }
 341
 342        while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
 343                if (xmit->head == xmit->tail)
 344                        break;
 345                writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
 346                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
 347                port->icount.tx++;
 348        }
 349
 350        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 351                uart_write_wakeup(port);
 352
 353        if (xmit->head == xmit->tail) {
 354                pp->imr &= ~MCFUART_UIR_TXREADY;
 355                writeb(pp->imr, port->membase + MCFUART_UIMR);
 356                /* Disable TX to negate RTS automatically */
 357                if (port->rs485.flags & SER_RS485_ENABLED)
 358                        writeb(MCFUART_UCR_TXDISABLE,
 359                                port->membase + MCFUART_UCR);
 360        }
 361}
 362
 363/****************************************************************************/
 364
 365static irqreturn_t mcf_interrupt(int irq, void *data)
 366{
 367        struct uart_port *port = data;
 368        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 369        unsigned int isr;
 370        irqreturn_t ret = IRQ_NONE;
 371
 372        isr = readb(port->membase + MCFUART_UISR) & pp->imr;
 373
 374        spin_lock(&port->lock);
 375        if (isr & MCFUART_UIR_RXREADY) {
 376                mcf_rx_chars(pp);
 377                ret = IRQ_HANDLED;
 378        }
 379        if (isr & MCFUART_UIR_TXREADY) {
 380                mcf_tx_chars(pp);
 381                ret = IRQ_HANDLED;
 382        }
 383        spin_unlock(&port->lock);
 384
 385        return ret;
 386}
 387
 388/****************************************************************************/
 389
 390static void mcf_config_port(struct uart_port *port, int flags)
 391{
 392        port->type = PORT_MCF;
 393        port->fifosize = MCFUART_TXFIFOSIZE;
 394
 395        /* Clear mask, so no surprise interrupts. */
 396        writeb(0, port->membase + MCFUART_UIMR);
 397
 398        if (request_irq(port->irq, mcf_interrupt, 0, "UART", port))
 399                printk(KERN_ERR "MCF: unable to attach ColdFire UART %d "
 400                        "interrupt vector=%d\n", port->line, port->irq);
 401}
 402
 403/****************************************************************************/
 404
 405static const char *mcf_type(struct uart_port *port)
 406{
 407        return (port->type == PORT_MCF) ? "ColdFire UART" : NULL;
 408}
 409
 410/****************************************************************************/
 411
 412static int mcf_request_port(struct uart_port *port)
 413{
 414        /* UARTs always present */
 415        return 0;
 416}
 417
 418/****************************************************************************/
 419
 420static void mcf_release_port(struct uart_port *port)
 421{
 422        /* Nothing to release... */
 423}
 424
 425/****************************************************************************/
 426
 427static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
 428{
 429        if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF))
 430                return -EINVAL;
 431        return 0;
 432}
 433
 434/****************************************************************************/
 435
 436/* Enable or disable the RS485 support */
 437static int mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
 438{
 439        unsigned char mr1, mr2;
 440
 441        /* Get mode registers */
 442        mr1 = readb(port->membase + MCFUART_UMR);
 443        mr2 = readb(port->membase + MCFUART_UMR);
 444        if (rs485->flags & SER_RS485_ENABLED) {
 445                dev_dbg(port->dev, "Setting UART to RS485\n");
 446                /* Automatically negate RTS after TX completes */
 447                mr2 |= MCFUART_MR2_TXRTS;
 448        } else {
 449                dev_dbg(port->dev, "Setting UART to RS232\n");
 450                mr2 &= ~MCFUART_MR2_TXRTS;
 451        }
 452        writeb(mr1, port->membase + MCFUART_UMR);
 453        writeb(mr2, port->membase + MCFUART_UMR);
 454        port->rs485 = *rs485;
 455
 456        return 0;
 457}
 458
 459/****************************************************************************/
 460
 461/*
 462 *      Define the basic serial functions we support.
 463 */
 464static const struct uart_ops mcf_uart_ops = {
 465        .tx_empty       = mcf_tx_empty,
 466        .get_mctrl      = mcf_get_mctrl,
 467        .set_mctrl      = mcf_set_mctrl,
 468        .start_tx       = mcf_start_tx,
 469        .stop_tx        = mcf_stop_tx,
 470        .stop_rx        = mcf_stop_rx,
 471        .break_ctl      = mcf_break_ctl,
 472        .startup        = mcf_startup,
 473        .shutdown       = mcf_shutdown,
 474        .set_termios    = mcf_set_termios,
 475        .type           = mcf_type,
 476        .request_port   = mcf_request_port,
 477        .release_port   = mcf_release_port,
 478        .config_port    = mcf_config_port,
 479        .verify_port    = mcf_verify_port,
 480};
 481
 482static struct mcf_uart mcf_ports[4];
 483
 484#define MCF_MAXPORTS    ARRAY_SIZE(mcf_ports)
 485
 486/****************************************************************************/
 487#if defined(CONFIG_SERIAL_MCF_CONSOLE)
 488/****************************************************************************/
 489
 490int __init early_mcf_setup(struct mcf_platform_uart *platp)
 491{
 492        struct uart_port *port;
 493        int i;
 494
 495        for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
 496                port = &mcf_ports[i].port;
 497
 498                port->line = i;
 499                port->type = PORT_MCF;
 500                port->mapbase = platp[i].mapbase;
 501                port->membase = (platp[i].membase) ? platp[i].membase :
 502                        (unsigned char __iomem *) port->mapbase;
 503                port->iotype = SERIAL_IO_MEM;
 504                port->irq = platp[i].irq;
 505                port->uartclk = MCF_BUSCLK;
 506                port->flags = UPF_BOOT_AUTOCONF;
 507                port->rs485_config = mcf_config_rs485;
 508                port->ops = &mcf_uart_ops;
 509        }
 510
 511        return 0;
 512}
 513
 514/****************************************************************************/
 515
 516static void mcf_console_putc(struct console *co, const char c)
 517{
 518        struct uart_port *port = &(mcf_ports + co->index)->port;
 519        int i;
 520
 521        for (i = 0; (i < 0x10000); i++) {
 522                if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
 523                        break;
 524        }
 525        writeb(c, port->membase + MCFUART_UTB);
 526        for (i = 0; (i < 0x10000); i++) {
 527                if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
 528                        break;
 529        }
 530}
 531
 532/****************************************************************************/
 533
 534static void mcf_console_write(struct console *co, const char *s, unsigned int count)
 535{
 536        for (; (count); count--, s++) {
 537                mcf_console_putc(co, *s);
 538                if (*s == '\n')
 539                        mcf_console_putc(co, '\r');
 540        }
 541}
 542
 543/****************************************************************************/
 544
 545static int __init mcf_console_setup(struct console *co, char *options)
 546{
 547        struct uart_port *port;
 548        int baud = CONFIG_SERIAL_MCF_BAUDRATE;
 549        int bits = 8;
 550        int parity = 'n';
 551        int flow = 'n';
 552
 553        if ((co->index < 0) || (co->index >= MCF_MAXPORTS))
 554                co->index = 0;
 555        port = &mcf_ports[co->index].port;
 556        if (port->membase == 0)
 557                return -ENODEV;
 558
 559        if (options)
 560                uart_parse_options(options, &baud, &parity, &bits, &flow);
 561
 562        return uart_set_options(port, co, baud, parity, bits, flow);
 563}
 564
 565/****************************************************************************/
 566
 567static struct uart_driver mcf_driver;
 568
 569static struct console mcf_console = {
 570        .name           = "ttyS",
 571        .write          = mcf_console_write,
 572        .device         = uart_console_device,
 573        .setup          = mcf_console_setup,
 574        .flags          = CON_PRINTBUFFER,
 575        .index          = -1,
 576        .data           = &mcf_driver,
 577};
 578
 579static int __init mcf_console_init(void)
 580{
 581        register_console(&mcf_console);
 582        return 0;
 583}
 584
 585console_initcall(mcf_console_init);
 586
 587#define MCF_CONSOLE     &mcf_console
 588
 589/****************************************************************************/
 590#else
 591/****************************************************************************/
 592
 593#define MCF_CONSOLE     NULL
 594
 595/****************************************************************************/
 596#endif /* CONFIG_SERIAL_MCF_CONSOLE */
 597/****************************************************************************/
 598
 599/*
 600 *      Define the mcf UART driver structure.
 601 */
 602static struct uart_driver mcf_driver = {
 603        .owner          = THIS_MODULE,
 604        .driver_name    = "mcf",
 605        .dev_name       = "ttyS",
 606        .major          = TTY_MAJOR,
 607        .minor          = 64,
 608        .nr             = MCF_MAXPORTS,
 609        .cons           = MCF_CONSOLE,
 610};
 611
 612/****************************************************************************/
 613
 614static int mcf_probe(struct platform_device *pdev)
 615{
 616        struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev);
 617        struct uart_port *port;
 618        int i;
 619
 620        for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
 621                port = &mcf_ports[i].port;
 622
 623                port->line = i;
 624                port->type = PORT_MCF;
 625                port->mapbase = platp[i].mapbase;
 626                port->membase = (platp[i].membase) ? platp[i].membase :
 627                        (unsigned char __iomem *) platp[i].mapbase;
 628                port->dev = &pdev->dev;
 629                port->iotype = SERIAL_IO_MEM;
 630                port->irq = platp[i].irq;
 631                port->uartclk = MCF_BUSCLK;
 632                port->ops = &mcf_uart_ops;
 633                port->flags = UPF_BOOT_AUTOCONF;
 634                port->rs485_config = mcf_config_rs485;
 635
 636                uart_add_one_port(&mcf_driver, port);
 637        }
 638
 639        return 0;
 640}
 641
 642/****************************************************************************/
 643
 644static int mcf_remove(struct platform_device *pdev)
 645{
 646        struct uart_port *port;
 647        int i;
 648
 649        for (i = 0; (i < MCF_MAXPORTS); i++) {
 650                port = &mcf_ports[i].port;
 651                if (port)
 652                        uart_remove_one_port(&mcf_driver, port);
 653        }
 654
 655        return 0;
 656}
 657
 658/****************************************************************************/
 659
 660static struct platform_driver mcf_platform_driver = {
 661        .probe          = mcf_probe,
 662        .remove         = mcf_remove,
 663        .driver         = {
 664                .name   = "mcfuart",
 665        },
 666};
 667
 668/****************************************************************************/
 669
 670static int __init mcf_init(void)
 671{
 672        int rc;
 673
 674        printk("ColdFire internal UART serial driver\n");
 675
 676        rc = uart_register_driver(&mcf_driver);
 677        if (rc)
 678                return rc;
 679        rc = platform_driver_register(&mcf_platform_driver);
 680        if (rc) {
 681                uart_unregister_driver(&mcf_driver);
 682                return rc;
 683        }
 684        return 0;
 685}
 686
 687/****************************************************************************/
 688
 689static void __exit mcf_exit(void)
 690{
 691        platform_driver_unregister(&mcf_platform_driver);
 692        uart_unregister_driver(&mcf_driver);
 693}
 694
 695/****************************************************************************/
 696
 697module_init(mcf_init);
 698module_exit(mcf_exit);
 699
 700MODULE_AUTHOR("Greg Ungerer <gerg@uclinux.org>");
 701MODULE_DESCRIPTION("Freescale ColdFire UART driver");
 702MODULE_LICENSE("GPL");
 703MODULE_ALIAS("platform:mcfuart");
 704
 705/****************************************************************************/
 706