linux/drivers/tty/serial/amba-pl010.c
<<
>>
Prefs
   1/*
   2 *  Driver for AMBA serial ports
   3 *
   4 *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
   5 *
   6 *  Copyright 1999 ARM Limited
   7 *  Copyright (C) 2000 Deep Blue Solutions Ltd.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22 *
  23 * This is a generic driver for ARM AMBA-type serial ports.  They
  24 * have a lot of 16550-like features, but are not register compatible.
  25 * Note that although they do have CTS, DCD and DSR inputs, they do
  26 * not have an RI input, nor do they have DTR or RTS outputs.  If
  27 * required, these have to be supplied via some other means (eg, GPIO)
  28 * and hooked into this driver.
  29 */
  30
  31#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  32#define SUPPORT_SYSRQ
  33#endif
  34
  35#include <linux/module.h>
  36#include <linux/ioport.h>
  37#include <linux/init.h>
  38#include <linux/console.h>
  39#include <linux/sysrq.h>
  40#include <linux/device.h>
  41#include <linux/tty.h>
  42#include <linux/tty_flip.h>
  43#include <linux/serial_core.h>
  44#include <linux/serial.h>
  45#include <linux/amba/bus.h>
  46#include <linux/amba/serial.h>
  47#include <linux/clk.h>
  48#include <linux/slab.h>
  49#include <linux/io.h>
  50
  51#define UART_NR         8
  52
  53#define SERIAL_AMBA_MAJOR       204
  54#define SERIAL_AMBA_MINOR       16
  55#define SERIAL_AMBA_NR          UART_NR
  56
  57#define AMBA_ISR_PASS_LIMIT     256
  58
  59#define UART_RX_DATA(s)         (((s) & UART01x_FR_RXFE) == 0)
  60#define UART_TX_READY(s)        (((s) & UART01x_FR_TXFF) == 0)
  61
  62#define UART_DUMMY_RSR_RX       256
  63#define UART_PORT_SIZE          64
  64
  65/*
  66 * We wrap our port structure around the generic uart_port.
  67 */
  68struct uart_amba_port {
  69        struct uart_port        port;
  70        struct clk              *clk;
  71        struct amba_device      *dev;
  72        struct amba_pl010_data  *data;
  73        unsigned int            old_status;
  74};
  75
  76static void pl010_stop_tx(struct uart_port *port)
  77{
  78        struct uart_amba_port *uap =
  79                container_of(port, struct uart_amba_port, port);
  80        unsigned int cr;
  81
  82        cr = readb(uap->port.membase + UART010_CR);
  83        cr &= ~UART010_CR_TIE;
  84        writel(cr, uap->port.membase + UART010_CR);
  85}
  86
  87static void pl010_start_tx(struct uart_port *port)
  88{
  89        struct uart_amba_port *uap =
  90                container_of(port, struct uart_amba_port, port);
  91        unsigned int cr;
  92
  93        cr = readb(uap->port.membase + UART010_CR);
  94        cr |= UART010_CR_TIE;
  95        writel(cr, uap->port.membase + UART010_CR);
  96}
  97
  98static void pl010_stop_rx(struct uart_port *port)
  99{
 100        struct uart_amba_port *uap =
 101                container_of(port, struct uart_amba_port, port);
 102        unsigned int cr;
 103
 104        cr = readb(uap->port.membase + UART010_CR);
 105        cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
 106        writel(cr, uap->port.membase + UART010_CR);
 107}
 108
 109static void pl010_disable_ms(struct uart_port *port)
 110{
 111        struct uart_amba_port *uap = (struct uart_amba_port *)port;
 112        unsigned int cr;
 113
 114        cr = readb(uap->port.membase + UART010_CR);
 115        cr &= ~UART010_CR_MSIE;
 116        writel(cr, uap->port.membase + UART010_CR);
 117}
 118
 119static void pl010_enable_ms(struct uart_port *port)
 120{
 121        struct uart_amba_port *uap =
 122                container_of(port, struct uart_amba_port, port);
 123        unsigned int cr;
 124
 125        cr = readb(uap->port.membase + UART010_CR);
 126        cr |= UART010_CR_MSIE;
 127        writel(cr, uap->port.membase + UART010_CR);
 128}
 129
 130static void pl010_rx_chars(struct uart_amba_port *uap)
 131{
 132        unsigned int status, ch, flag, rsr, max_count = 256;
 133
 134        status = readb(uap->port.membase + UART01x_FR);
 135        while (UART_RX_DATA(status) && max_count--) {
 136                ch = readb(uap->port.membase + UART01x_DR);
 137                flag = TTY_NORMAL;
 138
 139                uap->port.icount.rx++;
 140
 141                /*
 142                 * Note that the error handling code is
 143                 * out of the main execution path
 144                 */
 145                rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
 146                if (unlikely(rsr & UART01x_RSR_ANY)) {
 147                        writel(0, uap->port.membase + UART01x_ECR);
 148
 149                        if (rsr & UART01x_RSR_BE) {
 150                                rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
 151                                uap->port.icount.brk++;
 152                                if (uart_handle_break(&uap->port))
 153                                        goto ignore_char;
 154                        } else if (rsr & UART01x_RSR_PE)
 155                                uap->port.icount.parity++;
 156                        else if (rsr & UART01x_RSR_FE)
 157                                uap->port.icount.frame++;
 158                        if (rsr & UART01x_RSR_OE)
 159                                uap->port.icount.overrun++;
 160
 161                        rsr &= uap->port.read_status_mask;
 162
 163                        if (rsr & UART01x_RSR_BE)
 164                                flag = TTY_BREAK;
 165                        else if (rsr & UART01x_RSR_PE)
 166                                flag = TTY_PARITY;
 167                        else if (rsr & UART01x_RSR_FE)
 168                                flag = TTY_FRAME;
 169                }
 170
 171                if (uart_handle_sysrq_char(&uap->port, ch))
 172                        goto ignore_char;
 173
 174                uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
 175
 176        ignore_char:
 177                status = readb(uap->port.membase + UART01x_FR);
 178        }
 179        spin_unlock(&uap->port.lock);
 180        tty_flip_buffer_push(&uap->port.state->port);
 181        spin_lock(&uap->port.lock);
 182}
 183
 184static void pl010_tx_chars(struct uart_amba_port *uap)
 185{
 186        struct circ_buf *xmit = &uap->port.state->xmit;
 187        int count;
 188
 189        if (uap->port.x_char) {
 190                writel(uap->port.x_char, uap->port.membase + UART01x_DR);
 191                uap->port.icount.tx++;
 192                uap->port.x_char = 0;
 193                return;
 194        }
 195        if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
 196                pl010_stop_tx(&uap->port);
 197                return;
 198        }
 199
 200        count = uap->port.fifosize >> 1;
 201        do {
 202                writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
 203                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 204                uap->port.icount.tx++;
 205                if (uart_circ_empty(xmit))
 206                        break;
 207        } while (--count > 0);
 208
 209        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 210                uart_write_wakeup(&uap->port);
 211
 212        if (uart_circ_empty(xmit))
 213                pl010_stop_tx(&uap->port);
 214}
 215
 216static void pl010_modem_status(struct uart_amba_port *uap)
 217{
 218        unsigned int status, delta;
 219
 220        writel(0, uap->port.membase + UART010_ICR);
 221
 222        status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
 223
 224        delta = status ^ uap->old_status;
 225        uap->old_status = status;
 226
 227        if (!delta)
 228                return;
 229
 230        if (delta & UART01x_FR_DCD)
 231                uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
 232
 233        if (delta & UART01x_FR_DSR)
 234                uap->port.icount.dsr++;
 235
 236        if (delta & UART01x_FR_CTS)
 237                uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
 238
 239        wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 240}
 241
 242static irqreturn_t pl010_int(int irq, void *dev_id)
 243{
 244        struct uart_amba_port *uap = dev_id;
 245        unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
 246        int handled = 0;
 247
 248        spin_lock(&uap->port.lock);
 249
 250        status = readb(uap->port.membase + UART010_IIR);
 251        if (status) {
 252                do {
 253                        if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
 254                                pl010_rx_chars(uap);
 255                        if (status & UART010_IIR_MIS)
 256                                pl010_modem_status(uap);
 257                        if (status & UART010_IIR_TIS)
 258                                pl010_tx_chars(uap);
 259
 260                        if (pass_counter-- == 0)
 261                                break;
 262
 263                        status = readb(uap->port.membase + UART010_IIR);
 264                } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
 265                                   UART010_IIR_TIS));
 266                handled = 1;
 267        }
 268
 269        spin_unlock(&uap->port.lock);
 270
 271        return IRQ_RETVAL(handled);
 272}
 273
 274static unsigned int pl010_tx_empty(struct uart_port *port)
 275{
 276        struct uart_amba_port *uap =
 277                container_of(port, struct uart_amba_port, port);
 278        unsigned int status = readb(uap->port.membase + UART01x_FR);
 279        return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
 280}
 281
 282static unsigned int pl010_get_mctrl(struct uart_port *port)
 283{
 284        struct uart_amba_port *uap =
 285                container_of(port, struct uart_amba_port, port);
 286        unsigned int result = 0;
 287        unsigned int status;
 288
 289        status = readb(uap->port.membase + UART01x_FR);
 290        if (status & UART01x_FR_DCD)
 291                result |= TIOCM_CAR;
 292        if (status & UART01x_FR_DSR)
 293                result |= TIOCM_DSR;
 294        if (status & UART01x_FR_CTS)
 295                result |= TIOCM_CTS;
 296
 297        return result;
 298}
 299
 300static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
 301{
 302        struct uart_amba_port *uap =
 303                container_of(port, struct uart_amba_port, port);
 304
 305        if (uap->data)
 306                uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
 307}
 308
 309static void pl010_break_ctl(struct uart_port *port, int break_state)
 310{
 311        struct uart_amba_port *uap =
 312                container_of(port, struct uart_amba_port, port);
 313        unsigned long flags;
 314        unsigned int lcr_h;
 315
 316        spin_lock_irqsave(&uap->port.lock, flags);
 317        lcr_h = readb(uap->port.membase + UART010_LCRH);
 318        if (break_state == -1)
 319                lcr_h |= UART01x_LCRH_BRK;
 320        else
 321                lcr_h &= ~UART01x_LCRH_BRK;
 322        writel(lcr_h, uap->port.membase + UART010_LCRH);
 323        spin_unlock_irqrestore(&uap->port.lock, flags);
 324}
 325
 326static int pl010_startup(struct uart_port *port)
 327{
 328        struct uart_amba_port *uap =
 329                container_of(port, struct uart_amba_port, port);
 330        int retval;
 331
 332        /*
 333         * Try to enable the clock producer.
 334         */
 335        retval = clk_prepare_enable(uap->clk);
 336        if (retval)
 337                goto out;
 338
 339        uap->port.uartclk = clk_get_rate(uap->clk);
 340
 341        /*
 342         * Allocate the IRQ
 343         */
 344        retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
 345        if (retval)
 346                goto clk_dis;
 347
 348        /*
 349         * initialise the old status of the modem signals
 350         */
 351        uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
 352
 353        /*
 354         * Finally, enable interrupts
 355         */
 356        writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
 357               uap->port.membase + UART010_CR);
 358
 359        return 0;
 360
 361 clk_dis:
 362        clk_disable_unprepare(uap->clk);
 363 out:
 364        return retval;
 365}
 366
 367static void pl010_shutdown(struct uart_port *port)
 368{
 369        struct uart_amba_port *uap =
 370                container_of(port, struct uart_amba_port, port);
 371
 372        /*
 373         * Free the interrupt
 374         */
 375        free_irq(uap->port.irq, uap);
 376
 377        /*
 378         * disable all interrupts, disable the port
 379         */
 380        writel(0, uap->port.membase + UART010_CR);
 381
 382        /* disable break condition and fifos */
 383        writel(readb(uap->port.membase + UART010_LCRH) &
 384                ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
 385               uap->port.membase + UART010_LCRH);
 386
 387        /*
 388         * Shut down the clock producer
 389         */
 390        clk_disable_unprepare(uap->clk);
 391}
 392
 393static void
 394pl010_set_termios(struct uart_port *port, struct ktermios *termios,
 395                     struct ktermios *old)
 396{
 397        struct uart_amba_port *uap =
 398                container_of(port, struct uart_amba_port, port);
 399        unsigned int lcr_h, old_cr;
 400        unsigned long flags;
 401        unsigned int baud, quot;
 402
 403        /*
 404         * Ask the core to calculate the divisor for us.
 405         */
 406        baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); 
 407        quot = uart_get_divisor(port, baud);
 408
 409        switch (termios->c_cflag & CSIZE) {
 410        case CS5:
 411                lcr_h = UART01x_LCRH_WLEN_5;
 412                break;
 413        case CS6:
 414                lcr_h = UART01x_LCRH_WLEN_6;
 415                break;
 416        case CS7:
 417                lcr_h = UART01x_LCRH_WLEN_7;
 418                break;
 419        default: // CS8
 420                lcr_h = UART01x_LCRH_WLEN_8;
 421                break;
 422        }
 423        if (termios->c_cflag & CSTOPB)
 424                lcr_h |= UART01x_LCRH_STP2;
 425        if (termios->c_cflag & PARENB) {
 426                lcr_h |= UART01x_LCRH_PEN;
 427                if (!(termios->c_cflag & PARODD))
 428                        lcr_h |= UART01x_LCRH_EPS;
 429        }
 430        if (uap->port.fifosize > 1)
 431                lcr_h |= UART01x_LCRH_FEN;
 432
 433        spin_lock_irqsave(&uap->port.lock, flags);
 434
 435        /*
 436         * Update the per-port timeout.
 437         */
 438        uart_update_timeout(port, termios->c_cflag, baud);
 439
 440        uap->port.read_status_mask = UART01x_RSR_OE;
 441        if (termios->c_iflag & INPCK)
 442                uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
 443        if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
 444                uap->port.read_status_mask |= UART01x_RSR_BE;
 445
 446        /*
 447         * Characters to ignore
 448         */
 449        uap->port.ignore_status_mask = 0;
 450        if (termios->c_iflag & IGNPAR)
 451                uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
 452        if (termios->c_iflag & IGNBRK) {
 453                uap->port.ignore_status_mask |= UART01x_RSR_BE;
 454                /*
 455                 * If we're ignoring parity and break indicators,
 456                 * ignore overruns too (for real raw support).
 457                 */
 458                if (termios->c_iflag & IGNPAR)
 459                        uap->port.ignore_status_mask |= UART01x_RSR_OE;
 460        }
 461
 462        /*
 463         * Ignore all characters if CREAD is not set.
 464         */
 465        if ((termios->c_cflag & CREAD) == 0)
 466                uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
 467
 468        /* first, disable everything */
 469        old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
 470
 471        if (UART_ENABLE_MS(port, termios->c_cflag))
 472                old_cr |= UART010_CR_MSIE;
 473
 474        writel(0, uap->port.membase + UART010_CR);
 475
 476        /* Set baud rate */
 477        quot -= 1;
 478        writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
 479        writel(quot & 0xff, uap->port.membase + UART010_LCRL);
 480
 481        /*
 482         * ----------v----------v----------v----------v-----
 483         * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
 484         * ----------^----------^----------^----------^-----
 485         */
 486        writel(lcr_h, uap->port.membase + UART010_LCRH);
 487        writel(old_cr, uap->port.membase + UART010_CR);
 488
 489        spin_unlock_irqrestore(&uap->port.lock, flags);
 490}
 491
 492static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios)
 493{
 494        if (termios->c_line == N_PPS) {
 495                port->flags |= UPF_HARDPPS_CD;
 496                spin_lock_irq(&port->lock);
 497                pl010_enable_ms(port);
 498                spin_unlock_irq(&port->lock);
 499        } else {
 500                port->flags &= ~UPF_HARDPPS_CD;
 501                if (!UART_ENABLE_MS(port, termios->c_cflag)) {
 502                        spin_lock_irq(&port->lock);
 503                        pl010_disable_ms(port);
 504                        spin_unlock_irq(&port->lock);
 505                }
 506        }
 507}
 508
 509static const char *pl010_type(struct uart_port *port)
 510{
 511        return port->type == PORT_AMBA ? "AMBA" : NULL;
 512}
 513
 514/*
 515 * Release the memory region(s) being used by 'port'
 516 */
 517static void pl010_release_port(struct uart_port *port)
 518{
 519        release_mem_region(port->mapbase, UART_PORT_SIZE);
 520}
 521
 522/*
 523 * Request the memory region(s) being used by 'port'
 524 */
 525static int pl010_request_port(struct uart_port *port)
 526{
 527        return request_mem_region(port->mapbase, UART_PORT_SIZE, "uart-pl010")
 528                        != NULL ? 0 : -EBUSY;
 529}
 530
 531/*
 532 * Configure/autoconfigure the port.
 533 */
 534static void pl010_config_port(struct uart_port *port, int flags)
 535{
 536        if (flags & UART_CONFIG_TYPE) {
 537                port->type = PORT_AMBA;
 538                pl010_request_port(port);
 539        }
 540}
 541
 542/*
 543 * verify the new serial_struct (for TIOCSSERIAL).
 544 */
 545static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
 546{
 547        int ret = 0;
 548        if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
 549                ret = -EINVAL;
 550        if (ser->irq < 0 || ser->irq >= nr_irqs)
 551                ret = -EINVAL;
 552        if (ser->baud_base < 9600)
 553                ret = -EINVAL;
 554        return ret;
 555}
 556
 557static struct uart_ops amba_pl010_pops = {
 558        .tx_empty       = pl010_tx_empty,
 559        .set_mctrl      = pl010_set_mctrl,
 560        .get_mctrl      = pl010_get_mctrl,
 561        .stop_tx        = pl010_stop_tx,
 562        .start_tx       = pl010_start_tx,
 563        .stop_rx        = pl010_stop_rx,
 564        .enable_ms      = pl010_enable_ms,
 565        .break_ctl      = pl010_break_ctl,
 566        .startup        = pl010_startup,
 567        .shutdown       = pl010_shutdown,
 568        .set_termios    = pl010_set_termios,
 569        .set_ldisc      = pl010_set_ldisc,
 570        .type           = pl010_type,
 571        .release_port   = pl010_release_port,
 572        .request_port   = pl010_request_port,
 573        .config_port    = pl010_config_port,
 574        .verify_port    = pl010_verify_port,
 575};
 576
 577static struct uart_amba_port *amba_ports[UART_NR];
 578
 579#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
 580
 581static void pl010_console_putchar(struct uart_port *port, int ch)
 582{
 583        struct uart_amba_port *uap =
 584                container_of(port, struct uart_amba_port, port);
 585        unsigned int status;
 586
 587        do {
 588                status = readb(uap->port.membase + UART01x_FR);
 589                barrier();
 590        } while (!UART_TX_READY(status));
 591        writel(ch, uap->port.membase + UART01x_DR);
 592}
 593
 594static void
 595pl010_console_write(struct console *co, const char *s, unsigned int count)
 596{
 597        struct uart_amba_port *uap = amba_ports[co->index];
 598        unsigned int status, old_cr;
 599
 600        clk_enable(uap->clk);
 601
 602        /*
 603         *      First save the CR then disable the interrupts
 604         */
 605        old_cr = readb(uap->port.membase + UART010_CR);
 606        writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
 607
 608        uart_console_write(&uap->port, s, count, pl010_console_putchar);
 609
 610        /*
 611         *      Finally, wait for transmitter to become empty
 612         *      and restore the TCR
 613         */
 614        do {
 615                status = readb(uap->port.membase + UART01x_FR);
 616                barrier();
 617        } while (status & UART01x_FR_BUSY);
 618        writel(old_cr, uap->port.membase + UART010_CR);
 619
 620        clk_disable(uap->clk);
 621}
 622
 623static void __init
 624pl010_console_get_options(struct uart_amba_port *uap, int *baud,
 625                             int *parity, int *bits)
 626{
 627        if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
 628                unsigned int lcr_h, quot;
 629                lcr_h = readb(uap->port.membase + UART010_LCRH);
 630
 631                *parity = 'n';
 632                if (lcr_h & UART01x_LCRH_PEN) {
 633                        if (lcr_h & UART01x_LCRH_EPS)
 634                                *parity = 'e';
 635                        else
 636                                *parity = 'o';
 637                }
 638
 639                if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
 640                        *bits = 7;
 641                else
 642                        *bits = 8;
 643
 644                quot = readb(uap->port.membase + UART010_LCRL) |
 645                       readb(uap->port.membase + UART010_LCRM) << 8;
 646                *baud = uap->port.uartclk / (16 * (quot + 1));
 647        }
 648}
 649
 650static int __init pl010_console_setup(struct console *co, char *options)
 651{
 652        struct uart_amba_port *uap;
 653        int baud = 38400;
 654        int bits = 8;
 655        int parity = 'n';
 656        int flow = 'n';
 657        int ret;
 658
 659        /*
 660         * Check whether an invalid uart number has been specified, and
 661         * if so, search for the first available port that does have
 662         * console support.
 663         */
 664        if (co->index >= UART_NR)
 665                co->index = 0;
 666        uap = amba_ports[co->index];
 667        if (!uap)
 668                return -ENODEV;
 669
 670        ret = clk_prepare(uap->clk);
 671        if (ret)
 672                return ret;
 673
 674        uap->port.uartclk = clk_get_rate(uap->clk);
 675
 676        if (options)
 677                uart_parse_options(options, &baud, &parity, &bits, &flow);
 678        else
 679                pl010_console_get_options(uap, &baud, &parity, &bits);
 680
 681        return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 682}
 683
 684static struct uart_driver amba_reg;
 685static struct console amba_console = {
 686        .name           = "ttyAM",
 687        .write          = pl010_console_write,
 688        .device         = uart_console_device,
 689        .setup          = pl010_console_setup,
 690        .flags          = CON_PRINTBUFFER,
 691        .index          = -1,
 692        .data           = &amba_reg,
 693};
 694
 695#define AMBA_CONSOLE    &amba_console
 696#else
 697#define AMBA_CONSOLE    NULL
 698#endif
 699
 700static struct uart_driver amba_reg = {
 701        .owner                  = THIS_MODULE,
 702        .driver_name            = "ttyAM",
 703        .dev_name               = "ttyAM",
 704        .major                  = SERIAL_AMBA_MAJOR,
 705        .minor                  = SERIAL_AMBA_MINOR,
 706        .nr                     = UART_NR,
 707        .cons                   = AMBA_CONSOLE,
 708};
 709
 710static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
 711{
 712        struct uart_amba_port *uap;
 713        void __iomem *base;
 714        int i, ret;
 715
 716        for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
 717                if (amba_ports[i] == NULL)
 718                        break;
 719
 720        if (i == ARRAY_SIZE(amba_ports))
 721                return -EBUSY;
 722
 723        uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
 724                           GFP_KERNEL);
 725        if (!uap)
 726                return -ENOMEM;
 727
 728        base = devm_ioremap(&dev->dev, dev->res.start,
 729                            resource_size(&dev->res));
 730        if (!base)
 731                return -ENOMEM;
 732
 733        uap->clk = devm_clk_get(&dev->dev, NULL);
 734        if (IS_ERR(uap->clk))
 735                return PTR_ERR(uap->clk);
 736
 737        uap->port.dev = &dev->dev;
 738        uap->port.mapbase = dev->res.start;
 739        uap->port.membase = base;
 740        uap->port.iotype = UPIO_MEM;
 741        uap->port.irq = dev->irq[0];
 742        uap->port.fifosize = 16;
 743        uap->port.ops = &amba_pl010_pops;
 744        uap->port.flags = UPF_BOOT_AUTOCONF;
 745        uap->port.line = i;
 746        uap->dev = dev;
 747        uap->data = dev_get_platdata(&dev->dev);
 748
 749        amba_ports[i] = uap;
 750
 751        amba_set_drvdata(dev, uap);
 752        ret = uart_add_one_port(&amba_reg, &uap->port);
 753        if (ret)
 754                amba_ports[i] = NULL;
 755
 756        return ret;
 757}
 758
 759static int pl010_remove(struct amba_device *dev)
 760{
 761        struct uart_amba_port *uap = amba_get_drvdata(dev);
 762        int i;
 763
 764        uart_remove_one_port(&amba_reg, &uap->port);
 765
 766        for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
 767                if (amba_ports[i] == uap)
 768                        amba_ports[i] = NULL;
 769
 770        return 0;
 771}
 772
 773#ifdef CONFIG_PM_SLEEP
 774static int pl010_suspend(struct device *dev)
 775{
 776        struct uart_amba_port *uap = dev_get_drvdata(dev);
 777
 778        if (uap)
 779                uart_suspend_port(&amba_reg, &uap->port);
 780
 781        return 0;
 782}
 783
 784static int pl010_resume(struct device *dev)
 785{
 786        struct uart_amba_port *uap = dev_get_drvdata(dev);
 787
 788        if (uap)
 789                uart_resume_port(&amba_reg, &uap->port);
 790
 791        return 0;
 792}
 793#endif
 794
 795static SIMPLE_DEV_PM_OPS(pl010_dev_pm_ops, pl010_suspend, pl010_resume);
 796
 797static struct amba_id pl010_ids[] = {
 798        {
 799                .id     = 0x00041010,
 800                .mask   = 0x000fffff,
 801        },
 802        { 0, 0 },
 803};
 804
 805MODULE_DEVICE_TABLE(amba, pl010_ids);
 806
 807static struct amba_driver pl010_driver = {
 808        .drv = {
 809                .name   = "uart-pl010",
 810                .pm     = &pl010_dev_pm_ops,
 811        },
 812        .id_table       = pl010_ids,
 813        .probe          = pl010_probe,
 814        .remove         = pl010_remove,
 815};
 816
 817static int __init pl010_init(void)
 818{
 819        int ret;
 820
 821        printk(KERN_INFO "Serial: AMBA driver\n");
 822
 823        ret = uart_register_driver(&amba_reg);
 824        if (ret == 0) {
 825                ret = amba_driver_register(&pl010_driver);
 826                if (ret)
 827                        uart_unregister_driver(&amba_reg);
 828        }
 829        return ret;
 830}
 831
 832static void __exit pl010_exit(void)
 833{
 834        amba_driver_unregister(&pl010_driver);
 835        uart_unregister_driver(&amba_reg);
 836}
 837
 838module_init(pl010_init);
 839module_exit(pl010_exit);
 840
 841MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
 842MODULE_DESCRIPTION("ARM AMBA serial port driver");
 843MODULE_LICENSE("GPL");
 844