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