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