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