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#if defined(CONFIG_M5272)
 216        unsigned int baudfr;
 217#endif
 218        unsigned char mr1, mr2;
 219
 220        baud = uart_get_baud_rate(port, termios, old, 0, 230400);
 221#if defined(CONFIG_M5272)
 222        baudclk = (MCF_BUSCLK / baud) / 32;
 223        baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16;
 224#else
 225        baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
 226#endif
 227
 228        mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
 229        mr2 = 0;
 230
 231        switch (termios->c_cflag & CSIZE) {
 232        case CS5: mr1 |= MCFUART_MR1_CS5; break;
 233        case CS6: mr1 |= MCFUART_MR1_CS6; break;
 234        case CS7: mr1 |= MCFUART_MR1_CS7; break;
 235        case CS8:
 236        default:  mr1 |= MCFUART_MR1_CS8; break;
 237        }
 238
 239        if (termios->c_cflag & PARENB) {
 240                if (termios->c_cflag & CMSPAR) {
 241                        if (termios->c_cflag & PARODD)
 242                                mr1 |= MCFUART_MR1_PARITYMARK;
 243                        else
 244                                mr1 |= MCFUART_MR1_PARITYSPACE;
 245                } else {
 246                        if (termios->c_cflag & PARODD)
 247                                mr1 |= MCFUART_MR1_PARITYODD;
 248                        else
 249                                mr1 |= MCFUART_MR1_PARITYEVEN;
 250                }
 251        } else {
 252                mr1 |= MCFUART_MR1_PARITYNONE;
 253        }
 254
 255        if (termios->c_cflag & CSTOPB)
 256                mr2 |= MCFUART_MR2_STOP2;
 257        else
 258                mr2 |= MCFUART_MR2_STOP1;
 259
 260        if (termios->c_cflag & CRTSCTS) {
 261                mr1 |= MCFUART_MR1_RXRTS;
 262                mr2 |= MCFUART_MR2_TXCTS;
 263        }
 264
 265        spin_lock_irqsave(&port->lock, flags);
 266        writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
 267        writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
 268        writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR);
 269        writeb(mr1, port->membase + MCFUART_UMR);
 270        writeb(mr2, port->membase + MCFUART_UMR);
 271        writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);
 272        writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);
 273#if defined(CONFIG_M5272)
 274        writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD);
 275#endif
 276        writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,
 277                port->membase + MCFUART_UCSR);
 278        writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
 279                port->membase + MCFUART_UCR);
 280        spin_unlock_irqrestore(&port->lock, flags);
 281}
 282
 283/****************************************************************************/
 284
 285static void mcf_rx_chars(struct mcf_uart *pp)
 286{
 287        struct uart_port *port = &pp->port;
 288        unsigned char status, ch, flag;
 289
 290        while ((status = readb(port->membase + MCFUART_USR)) & MCFUART_USR_RXREADY) {
 291                ch = readb(port->membase + MCFUART_URB);
 292                flag = TTY_NORMAL;
 293                port->icount.rx++;
 294
 295                if (status & MCFUART_USR_RXERR) {
 296                        writeb(MCFUART_UCR_CMDRESETERR,
 297                                port->membase + MCFUART_UCR);
 298
 299                        if (status & MCFUART_USR_RXBREAK) {
 300                                port->icount.brk++;
 301                                if (uart_handle_break(port))
 302                                        continue;
 303                        } else if (status & MCFUART_USR_RXPARITY) {
 304                                port->icount.parity++;
 305                        } else if (status & MCFUART_USR_RXOVERRUN) {
 306                                port->icount.overrun++;
 307                        } else if (status & MCFUART_USR_RXFRAMING) {
 308                                port->icount.frame++;
 309                        }
 310
 311                        status &= port->read_status_mask;
 312
 313                        if (status & MCFUART_USR_RXBREAK)
 314                                flag = TTY_BREAK;
 315                        else if (status & MCFUART_USR_RXPARITY)
 316                                flag = TTY_PARITY;
 317                        else if (status & MCFUART_USR_RXFRAMING)
 318                                flag = TTY_FRAME;
 319                }
 320
 321                if (uart_handle_sysrq_char(port, ch))
 322                        continue;
 323                uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
 324        }
 325
 326        tty_flip_buffer_push(port->info->port.tty);
 327}
 328
 329/****************************************************************************/
 330
 331static void mcf_tx_chars(struct mcf_uart *pp)
 332{
 333        struct uart_port *port = &pp->port;
 334        struct circ_buf *xmit = &port->info->xmit;
 335
 336        if (port->x_char) {
 337                /* Send special char - probably flow control */
 338                writeb(port->x_char, port->membase + MCFUART_UTB);
 339                port->x_char = 0;
 340                port->icount.tx++;
 341                return;
 342        }
 343
 344        while (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY) {
 345                if (xmit->head == xmit->tail)
 346                        break;
 347                writeb(xmit->buf[xmit->tail], port->membase + MCFUART_UTB);
 348                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
 349                port->icount.tx++;
 350        }
 351
 352        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 353                uart_write_wakeup(port);
 354
 355        if (xmit->head == xmit->tail) {
 356                pp->imr &= ~MCFUART_UIR_TXREADY;
 357                writeb(pp->imr, port->membase + MCFUART_UIMR);
 358        }
 359}
 360
 361/****************************************************************************/
 362
 363static irqreturn_t mcf_interrupt(int irq, void *data)
 364{
 365        struct uart_port *port = data;
 366        struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
 367        unsigned int isr;
 368
 369        isr = readb(port->membase + MCFUART_UISR) & pp->imr;
 370        if (isr & MCFUART_UIR_RXREADY)
 371                mcf_rx_chars(pp);
 372        if (isr & MCFUART_UIR_TXREADY)
 373                mcf_tx_chars(pp);
 374        return IRQ_HANDLED;
 375}
 376
 377/****************************************************************************/
 378
 379static void mcf_config_port(struct uart_port *port, int flags)
 380{
 381        port->type = PORT_MCF;
 382
 383        /* Clear mask, so no surprise interrupts. */
 384        writeb(0, port->membase + MCFUART_UIMR);
 385
 386        if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port))
 387                printk(KERN_ERR "MCF: unable to attach ColdFire UART %d "
 388                        "interrupt vector=%d\n", port->line, port->irq);
 389}
 390
 391/****************************************************************************/
 392
 393static const char *mcf_type(struct uart_port *port)
 394{
 395        return (port->type == PORT_MCF) ? "ColdFire UART" : NULL;
 396}
 397
 398/****************************************************************************/
 399
 400static int mcf_request_port(struct uart_port *port)
 401{
 402        /* UARTs always present */
 403        return 0;
 404}
 405
 406/****************************************************************************/
 407
 408static void mcf_release_port(struct uart_port *port)
 409{
 410        /* Nothing to release... */
 411}
 412
 413/****************************************************************************/
 414
 415static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser)
 416{
 417        if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_MCF))
 418                return -EINVAL;
 419        return 0;
 420}
 421
 422/****************************************************************************/
 423
 424/*
 425 *      Define the basic serial functions we support.
 426 */
 427static struct uart_ops mcf_uart_ops = {
 428        .tx_empty       = mcf_tx_empty,
 429        .get_mctrl      = mcf_get_mctrl,
 430        .set_mctrl      = mcf_set_mctrl,
 431        .start_tx       = mcf_start_tx,
 432        .stop_tx        = mcf_stop_tx,
 433        .stop_rx        = mcf_stop_rx,
 434        .enable_ms      = mcf_enable_ms,
 435        .break_ctl      = mcf_break_ctl,
 436        .startup        = mcf_startup,
 437        .shutdown       = mcf_shutdown,
 438        .set_termios    = mcf_set_termios,
 439        .type           = mcf_type,
 440        .request_port   = mcf_request_port,
 441        .release_port   = mcf_release_port,
 442        .config_port    = mcf_config_port,
 443        .verify_port    = mcf_verify_port,
 444};
 445
 446static struct mcf_uart mcf_ports[3];
 447
 448#define MCF_MAXPORTS    ARRAY_SIZE(mcf_ports)
 449
 450/****************************************************************************/
 451#if defined(CONFIG_SERIAL_MCF_CONSOLE)
 452/****************************************************************************/
 453
 454int __init early_mcf_setup(struct mcf_platform_uart *platp)
 455{
 456        struct uart_port *port;
 457        int i;
 458
 459        for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
 460                port = &mcf_ports[i].port;
 461
 462                port->line = i;
 463                port->type = PORT_MCF;
 464                port->mapbase = platp[i].mapbase;
 465                port->membase = (platp[i].membase) ? platp[i].membase :
 466                        (unsigned char __iomem *) port->mapbase;
 467                port->iotype = SERIAL_IO_MEM;
 468                port->irq = platp[i].irq;
 469                port->uartclk = MCF_BUSCLK;
 470                port->flags = ASYNC_BOOT_AUTOCONF;
 471                port->ops = &mcf_uart_ops;
 472        }
 473
 474        return 0;
 475}
 476
 477/****************************************************************************/
 478
 479static void mcf_console_putc(struct console *co, const char c)
 480{
 481        struct uart_port *port = &(mcf_ports + co->index)->port;
 482        int i;
 483
 484        for (i = 0; (i < 0x10000); i++) {
 485                if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
 486                        break;
 487        }
 488        writeb(c, port->membase + MCFUART_UTB);
 489        for (i = 0; (i < 0x10000); i++) {
 490                if (readb(port->membase + MCFUART_USR) & MCFUART_USR_TXREADY)
 491                        break;
 492        }
 493}
 494
 495/****************************************************************************/
 496
 497static void mcf_console_write(struct console *co, const char *s, unsigned int count)
 498{
 499        for (; (count); count--, s++) {
 500                mcf_console_putc(co, *s);
 501                if (*s == '\n')
 502                        mcf_console_putc(co, '\r');
 503        }
 504}
 505
 506/****************************************************************************/
 507
 508static int __init mcf_console_setup(struct console *co, char *options)
 509{
 510        struct uart_port *port;
 511        int baud = CONFIG_SERIAL_MCF_BAUDRATE;
 512        int bits = 8;
 513        int parity = 'n';
 514        int flow = 'n';
 515
 516        if ((co->index < 0) || (co->index >= MCF_MAXPORTS))
 517                co->index = 0;
 518        port = &mcf_ports[co->index].port;
 519        if (port->membase == 0)
 520                return -ENODEV;
 521
 522        if (options)
 523                uart_parse_options(options, &baud, &parity, &bits, &flow);
 524
 525        return uart_set_options(port, co, baud, parity, bits, flow);
 526}
 527
 528/****************************************************************************/
 529
 530static struct uart_driver mcf_driver;
 531
 532static struct console mcf_console = {
 533        .name           = "ttyS",
 534        .write          = mcf_console_write,
 535        .device         = uart_console_device,
 536        .setup          = mcf_console_setup,
 537        .flags          = CON_PRINTBUFFER,
 538        .index          = -1,
 539        .data           = &mcf_driver,
 540};
 541
 542static int __init mcf_console_init(void)
 543{
 544        register_console(&mcf_console);
 545        return 0;
 546}
 547
 548console_initcall(mcf_console_init);
 549
 550#define MCF_CONSOLE     &mcf_console
 551
 552/****************************************************************************/
 553#else
 554/****************************************************************************/
 555
 556#define MCF_CONSOLE     NULL
 557
 558/****************************************************************************/
 559#endif /* CONFIG_MCF_CONSOLE */
 560/****************************************************************************/
 561
 562/*
 563 *      Define the mcf UART driver structure.
 564 */
 565static struct uart_driver mcf_driver = {
 566        .owner          = THIS_MODULE,
 567        .driver_name    = "mcf",
 568        .dev_name       = "ttyS",
 569        .major          = TTY_MAJOR,
 570        .minor          = 64,
 571        .nr             = MCF_MAXPORTS,
 572        .cons           = MCF_CONSOLE,
 573};
 574
 575/****************************************************************************/
 576
 577static int __devinit mcf_probe(struct platform_device *pdev)
 578{
 579        struct mcf_platform_uart *platp = pdev->dev.platform_data;
 580        struct uart_port *port;
 581        int i;
 582
 583        for (i = 0; ((i < MCF_MAXPORTS) && (platp[i].mapbase)); i++) {
 584                port = &mcf_ports[i].port;
 585
 586                port->line = i;
 587                port->type = PORT_MCF;
 588                port->mapbase = platp[i].mapbase;
 589                port->membase = (platp[i].membase) ? platp[i].membase :
 590                        (unsigned char __iomem *) platp[i].mapbase;
 591                port->iotype = SERIAL_IO_MEM;
 592                port->irq = platp[i].irq;
 593                port->uartclk = MCF_BUSCLK;
 594                port->ops = &mcf_uart_ops;
 595                port->flags = ASYNC_BOOT_AUTOCONF;
 596
 597                uart_add_one_port(&mcf_driver, port);
 598        }
 599
 600        return 0;
 601}
 602
 603/****************************************************************************/
 604
 605static int mcf_remove(struct platform_device *pdev)
 606{
 607        struct uart_port *port;
 608        int i;
 609
 610        for (i = 0; (i < MCF_MAXPORTS); i++) {
 611                port = &mcf_ports[i].port;
 612                if (port)
 613                        uart_remove_one_port(&mcf_driver, port);
 614        }
 615
 616        return 0;
 617}
 618
 619/****************************************************************************/
 620
 621static struct platform_driver mcf_platform_driver = {
 622        .probe          = mcf_probe,
 623        .remove         = __devexit_p(mcf_remove),
 624        .driver         = {
 625                .name   = "mcfuart",
 626                .owner  = THIS_MODULE,
 627        },
 628};
 629
 630/****************************************************************************/
 631
 632static int __init mcf_init(void)
 633{
 634        int rc;
 635
 636        printk("ColdFire internal UART serial driver\n");
 637
 638        rc = uart_register_driver(&mcf_driver);
 639        if (rc)
 640                return rc;
 641        rc = platform_driver_register(&mcf_platform_driver);
 642        if (rc)
 643                return rc;
 644        return 0;
 645}
 646
 647/****************************************************************************/
 648
 649static void __exit mcf_exit(void)
 650{
 651        platform_driver_unregister(&mcf_platform_driver);
 652        uart_unregister_driver(&mcf_driver);
 653}
 654
 655/****************************************************************************/
 656
 657module_init(mcf_init);
 658module_exit(mcf_exit);
 659
 660MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
 661MODULE_DESCRIPTION("Freescale ColdFire UART driver");
 662MODULE_LICENSE("GPL");
 663MODULE_ALIAS("platform:mcfuart");
 664
 665/****************************************************************************/
 666