linux/drivers/serial/pnx8xxx_uart.c
<<
>>
Prefs
   1/*
   2 * UART driver for PNX8XXX SoCs
   3 *
   4 * Author: Per Hallsmark per.hallsmark@mvista.com
   5 * Ported to 2.6 kernel by EmbeddedAlley
   6 * Reworked by Vitaly Wool <vitalywool@gmail.com>
   7 *
   8 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
   9 * Copyright (C) 2000 Deep Blue Solutions Ltd.
  10 *
  11 * This file is licensed under the terms of the GNU General Public License
  12 * version 2. This program is licensed "as is" without any warranty of
  13 * any kind, whether express or implied.
  14 *
  15 */
  16
  17#if defined(CONFIG_SERIAL_PNX8XXX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  18#define SUPPORT_SYSRQ
  19#endif
  20
  21#include <linux/module.h>
  22#include <linux/ioport.h>
  23#include <linux/init.h>
  24#include <linux/console.h>
  25#include <linux/sysrq.h>
  26#include <linux/device.h>
  27#include <linux/platform_device.h>
  28#include <linux/tty.h>
  29#include <linux/tty_flip.h>
  30#include <linux/serial_core.h>
  31#include <linux/serial.h>
  32#include <linux/serial_pnx8xxx.h>
  33
  34#include <asm/io.h>
  35#include <asm/irq.h>
  36
  37/* We'll be using StrongARM sa1100 serial port major/minor */
  38#define SERIAL_PNX8XXX_MAJOR    204
  39#define MINOR_START             5
  40
  41#define NR_PORTS                2
  42
  43#define PNX8XXX_ISR_PASS_LIMIT  256
  44
  45/*
  46 * Convert from ignore_status_mask or read_status_mask to FIFO
  47 * and interrupt status bits
  48 */
  49#define SM_TO_FIFO(x)   ((x) >> 10)
  50#define SM_TO_ISTAT(x)  ((x) & 0x000001ff)
  51#define FIFO_TO_SM(x)   ((x) << 10)
  52#define ISTAT_TO_SM(x)  ((x) & 0x000001ff)
  53
  54/*
  55 * This is the size of our serial port register set.
  56 */
  57#define UART_PORT_SIZE  0x1000
  58
  59/*
  60 * This determines how often we check the modem status signals
  61 * for any change.  They generally aren't connected to an IRQ
  62 * so we have to poll them.  We also check immediately before
  63 * filling the TX fifo incase CTS has been dropped.
  64 */
  65#define MCTRL_TIMEOUT   (250*HZ/1000)
  66
  67extern struct pnx8xxx_port pnx8xxx_ports[];
  68
  69static inline int serial_in(struct pnx8xxx_port *sport, int offset)
  70{
  71        return (__raw_readl(sport->port.membase + offset));
  72}
  73
  74static inline void serial_out(struct pnx8xxx_port *sport, int offset, int value)
  75{
  76        __raw_writel(value, sport->port.membase + offset);
  77}
  78
  79/*
  80 * Handle any change of modem status signal since we were last called.
  81 */
  82static void pnx8xxx_mctrl_check(struct pnx8xxx_port *sport)
  83{
  84        unsigned int status, changed;
  85
  86        status = sport->port.ops->get_mctrl(&sport->port);
  87        changed = status ^ sport->old_status;
  88
  89        if (changed == 0)
  90                return;
  91
  92        sport->old_status = status;
  93
  94        if (changed & TIOCM_RI)
  95                sport->port.icount.rng++;
  96        if (changed & TIOCM_DSR)
  97                sport->port.icount.dsr++;
  98        if (changed & TIOCM_CAR)
  99                uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
 100        if (changed & TIOCM_CTS)
 101                uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
 102
 103        wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 104}
 105
 106/*
 107 * This is our per-port timeout handler, for checking the
 108 * modem status signals.
 109 */
 110static void pnx8xxx_timeout(unsigned long data)
 111{
 112        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)data;
 113        unsigned long flags;
 114
 115        if (sport->port.state) {
 116                spin_lock_irqsave(&sport->port.lock, flags);
 117                pnx8xxx_mctrl_check(sport);
 118                spin_unlock_irqrestore(&sport->port.lock, flags);
 119
 120                mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
 121        }
 122}
 123
 124/*
 125 * interrupts disabled on entry
 126 */
 127static void pnx8xxx_stop_tx(struct uart_port *port)
 128{
 129        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 130        u32 ien;
 131
 132        /* Disable TX intr */
 133        ien = serial_in(sport, PNX8XXX_IEN);
 134        serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLTX);
 135
 136        /* Clear all pending TX intr */
 137        serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
 138}
 139
 140/*
 141 * interrupts may not be disabled on entry
 142 */
 143static void pnx8xxx_start_tx(struct uart_port *port)
 144{
 145        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 146        u32 ien;
 147
 148        /* Clear all pending TX intr */
 149        serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLTX);
 150
 151        /* Enable TX intr */
 152        ien = serial_in(sport, PNX8XXX_IEN);
 153        serial_out(sport, PNX8XXX_IEN, ien | PNX8XXX_UART_INT_ALLTX);
 154}
 155
 156/*
 157 * Interrupts enabled
 158 */
 159static void pnx8xxx_stop_rx(struct uart_port *port)
 160{
 161        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 162        u32 ien;
 163
 164        /* Disable RX intr */
 165        ien = serial_in(sport, PNX8XXX_IEN);
 166        serial_out(sport, PNX8XXX_IEN, ien & ~PNX8XXX_UART_INT_ALLRX);
 167
 168        /* Clear all pending RX intr */
 169        serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX);
 170}
 171
 172/*
 173 * Set the modem control timer to fire immediately.
 174 */
 175static void pnx8xxx_enable_ms(struct uart_port *port)
 176{
 177        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 178
 179        mod_timer(&sport->timer, jiffies);
 180}
 181
 182static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
 183{
 184        struct tty_struct *tty = sport->port.state->port.tty;
 185        unsigned int status, ch, flg;
 186
 187        status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
 188                 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
 189        while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
 190                ch = serial_in(sport, PNX8XXX_FIFO) & 0xff;
 191
 192                sport->port.icount.rx++;
 193
 194                flg = TTY_NORMAL;
 195
 196                /*
 197                 * note that the error handling code is
 198                 * out of the main execution path
 199                 */
 200                if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
 201                                        PNX8XXX_UART_FIFO_RXPAR |
 202                                        PNX8XXX_UART_FIFO_RXBRK) |
 203                              ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
 204                        if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) {
 205                                status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
 206                                        FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR));
 207                                sport->port.icount.brk++;
 208                                if (uart_handle_break(&sport->port))
 209                                        goto ignore_char;
 210                        } else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
 211                                sport->port.icount.parity++;
 212                        else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
 213                                sport->port.icount.frame++;
 214                        if (status & ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))
 215                                sport->port.icount.overrun++;
 216
 217                        status &= sport->port.read_status_mask;
 218
 219                        if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
 220                                flg = TTY_PARITY;
 221                        else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
 222                                flg = TTY_FRAME;
 223
 224#ifdef SUPPORT_SYSRQ
 225                        sport->port.sysrq = 0;
 226#endif
 227                }
 228
 229                if (uart_handle_sysrq_char(&sport->port, ch))
 230                        goto ignore_char;
 231
 232                uart_insert_char(&sport->port, status,
 233                                ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN), ch, flg);
 234
 235        ignore_char:
 236                serial_out(sport, PNX8XXX_LCR, serial_in(sport, PNX8XXX_LCR) |
 237                                PNX8XXX_UART_LCR_RX_NEXT);
 238                status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
 239                         ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
 240        }
 241        tty_flip_buffer_push(tty);
 242}
 243
 244static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport)
 245{
 246        struct circ_buf *xmit = &sport->port.state->xmit;
 247
 248        if (sport->port.x_char) {
 249                serial_out(sport, PNX8XXX_FIFO, sport->port.x_char);
 250                sport->port.icount.tx++;
 251                sport->port.x_char = 0;
 252                return;
 253        }
 254
 255        /*
 256         * Check the modem control lines before
 257         * transmitting anything.
 258         */
 259        pnx8xxx_mctrl_check(sport);
 260
 261        if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
 262                pnx8xxx_stop_tx(&sport->port);
 263                return;
 264        }
 265
 266        /*
 267         * TX while bytes available
 268         */
 269        while (((serial_in(sport, PNX8XXX_FIFO) &
 270                                        PNX8XXX_UART_FIFO_TXFIFO) >> 16) < 16) {
 271                serial_out(sport, PNX8XXX_FIFO, xmit->buf[xmit->tail]);
 272                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 273                sport->port.icount.tx++;
 274                if (uart_circ_empty(xmit))
 275                        break;
 276        }
 277
 278        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 279                uart_write_wakeup(&sport->port);
 280
 281        if (uart_circ_empty(xmit))
 282                pnx8xxx_stop_tx(&sport->port);
 283}
 284
 285static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
 286{
 287        struct pnx8xxx_port *sport = dev_id;
 288        unsigned int status;
 289
 290        spin_lock(&sport->port.lock);
 291        /* Get the interrupts */
 292        status  = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
 293
 294        /* Byte or break signal received */
 295        if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK))
 296                pnx8xxx_rx_chars(sport);
 297
 298        /* TX holding register empty - transmit a byte */
 299        if (status & PNX8XXX_UART_INT_TX)
 300                pnx8xxx_tx_chars(sport);
 301
 302        /* Clear the ISTAT register */
 303        serial_out(sport, PNX8XXX_ICLR, status);
 304
 305        spin_unlock(&sport->port.lock);
 306        return IRQ_HANDLED;
 307}
 308
 309/*
 310 * Return TIOCSER_TEMT when transmitter is not busy.
 311 */
 312static unsigned int pnx8xxx_tx_empty(struct uart_port *port)
 313{
 314        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 315
 316        return serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA ? 0 : TIOCSER_TEMT;
 317}
 318
 319static unsigned int pnx8xxx_get_mctrl(struct uart_port *port)
 320{
 321        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 322        unsigned int mctrl = TIOCM_DSR;
 323        unsigned int msr;
 324
 325        /* REVISIT */
 326
 327        msr = serial_in(sport, PNX8XXX_MCR);
 328
 329        mctrl |= msr & PNX8XXX_UART_MCR_CTS ? TIOCM_CTS : 0;
 330        mctrl |= msr & PNX8XXX_UART_MCR_DCD ? TIOCM_CAR : 0;
 331
 332        return mctrl;
 333}
 334
 335static void pnx8xxx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 336{
 337#if     0       /* FIXME */
 338        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 339        unsigned int msr;
 340#endif
 341}
 342
 343/*
 344 * Interrupts always disabled.
 345 */
 346static void pnx8xxx_break_ctl(struct uart_port *port, int break_state)
 347{
 348        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 349        unsigned long flags;
 350        unsigned int lcr;
 351
 352        spin_lock_irqsave(&sport->port.lock, flags);
 353        lcr = serial_in(sport, PNX8XXX_LCR);
 354        if (break_state == -1)
 355                lcr |= PNX8XXX_UART_LCR_TXBREAK;
 356        else
 357                lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
 358        serial_out(sport, PNX8XXX_LCR, lcr);
 359        spin_unlock_irqrestore(&sport->port.lock, flags);
 360}
 361
 362static int pnx8xxx_startup(struct uart_port *port)
 363{
 364        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 365        int retval;
 366
 367        /*
 368         * Allocate the IRQ
 369         */
 370        retval = request_irq(sport->port.irq, pnx8xxx_int, 0,
 371                             "pnx8xxx-uart", sport);
 372        if (retval)
 373                return retval;
 374
 375        /*
 376         * Finally, clear and enable interrupts
 377         */
 378
 379        serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
 380                             PNX8XXX_UART_INT_ALLTX);
 381
 382        serial_out(sport, PNX8XXX_IEN, serial_in(sport, PNX8XXX_IEN) |
 383                            PNX8XXX_UART_INT_ALLRX |
 384                            PNX8XXX_UART_INT_ALLTX);
 385
 386        /*
 387         * Enable modem status interrupts
 388         */
 389        spin_lock_irq(&sport->port.lock);
 390        pnx8xxx_enable_ms(&sport->port);
 391        spin_unlock_irq(&sport->port.lock);
 392
 393        return 0;
 394}
 395
 396static void pnx8xxx_shutdown(struct uart_port *port)
 397{
 398        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 399        int lcr;
 400
 401        /*
 402         * Stop our timer.
 403         */
 404        del_timer_sync(&sport->timer);
 405
 406        /*
 407         * Disable all interrupts
 408         */
 409        serial_out(sport, PNX8XXX_IEN, 0);
 410
 411        /*
 412         * Reset the Tx and Rx FIFOS, disable the break condition
 413         */
 414        lcr = serial_in(sport, PNX8XXX_LCR);
 415        lcr &= ~PNX8XXX_UART_LCR_TXBREAK;
 416        lcr |= PNX8XXX_UART_LCR_TX_RST | PNX8XXX_UART_LCR_RX_RST;
 417        serial_out(sport, PNX8XXX_LCR, lcr);
 418
 419        /*
 420         * Clear all interrupts
 421         */
 422        serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_ALLRX |
 423                             PNX8XXX_UART_INT_ALLTX);
 424
 425        /*
 426         * Free the interrupt
 427         */
 428        free_irq(sport->port.irq, sport);
 429}
 430
 431static void
 432pnx8xxx_set_termios(struct uart_port *port, struct ktermios *termios,
 433                   struct ktermios *old)
 434{
 435        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 436        unsigned long flags;
 437        unsigned int lcr_fcr, old_ien, baud, quot;
 438        unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
 439
 440        /*
 441         * We only support CS7 and CS8.
 442         */
 443        while ((termios->c_cflag & CSIZE) != CS7 &&
 444               (termios->c_cflag & CSIZE) != CS8) {
 445                termios->c_cflag &= ~CSIZE;
 446                termios->c_cflag |= old_csize;
 447                old_csize = CS8;
 448        }
 449
 450        if ((termios->c_cflag & CSIZE) == CS8)
 451                lcr_fcr = PNX8XXX_UART_LCR_8BIT;
 452        else
 453                lcr_fcr = 0;
 454
 455        if (termios->c_cflag & CSTOPB)
 456                lcr_fcr |= PNX8XXX_UART_LCR_2STOPB;
 457        if (termios->c_cflag & PARENB) {
 458                lcr_fcr |= PNX8XXX_UART_LCR_PAREN;
 459                if (!(termios->c_cflag & PARODD))
 460                        lcr_fcr |= PNX8XXX_UART_LCR_PAREVN;
 461        }
 462
 463        /*
 464         * Ask the core to calculate the divisor for us.
 465         */
 466        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
 467        quot = uart_get_divisor(port, baud);
 468
 469        spin_lock_irqsave(&sport->port.lock, flags);
 470
 471        sport->port.read_status_mask = ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN) |
 472                                ISTAT_TO_SM(PNX8XXX_UART_INT_EMPTY) |
 473                                ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
 474        if (termios->c_iflag & INPCK)
 475                sport->port.read_status_mask |=
 476                        FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
 477                        FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
 478        if (termios->c_iflag & (BRKINT | PARMRK))
 479                sport->port.read_status_mask |=
 480                        ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
 481
 482        /*
 483         * Characters to ignore
 484         */
 485        sport->port.ignore_status_mask = 0;
 486        if (termios->c_iflag & IGNPAR)
 487                sport->port.ignore_status_mask |=
 488                        FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
 489                        FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR);
 490        if (termios->c_iflag & IGNBRK) {
 491                sport->port.ignore_status_mask |=
 492                        ISTAT_TO_SM(PNX8XXX_UART_INT_BREAK);
 493                /*
 494                 * If we're ignoring parity and break indicators,
 495                 * ignore overruns too (for real raw support).
 496                 */
 497                if (termios->c_iflag & IGNPAR)
 498                        sport->port.ignore_status_mask |=
 499                                ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN);
 500        }
 501
 502        /*
 503         * ignore all characters if CREAD is not set
 504         */
 505        if ((termios->c_cflag & CREAD) == 0)
 506                sport->port.ignore_status_mask |=
 507                        ISTAT_TO_SM(PNX8XXX_UART_INT_RX);
 508
 509        del_timer_sync(&sport->timer);
 510
 511        /*
 512         * Update the per-port timeout.
 513         */
 514        uart_update_timeout(port, termios->c_cflag, baud);
 515
 516        /*
 517         * disable interrupts and drain transmitter
 518         */
 519        old_ien = serial_in(sport, PNX8XXX_IEN);
 520        serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
 521                                        PNX8XXX_UART_INT_ALLRX));
 522
 523        while (serial_in(sport, PNX8XXX_FIFO) & PNX8XXX_UART_FIFO_TXFIFO_STA)
 524                barrier();
 525
 526        /* then, disable everything */
 527        serial_out(sport, PNX8XXX_IEN, 0);
 528
 529        /* Reset the Rx and Tx FIFOs too */
 530        lcr_fcr |= PNX8XXX_UART_LCR_TX_RST;
 531        lcr_fcr |= PNX8XXX_UART_LCR_RX_RST;
 532
 533        /* set the parity, stop bits and data size */
 534        serial_out(sport, PNX8XXX_LCR, lcr_fcr);
 535
 536        /* set the baud rate */
 537        quot -= 1;
 538        serial_out(sport, PNX8XXX_BAUD, quot);
 539
 540        serial_out(sport, PNX8XXX_ICLR, -1);
 541
 542        serial_out(sport, PNX8XXX_IEN, old_ien);
 543
 544        if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
 545                pnx8xxx_enable_ms(&sport->port);
 546
 547        spin_unlock_irqrestore(&sport->port.lock, flags);
 548}
 549
 550static const char *pnx8xxx_type(struct uart_port *port)
 551{
 552        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 553
 554        return sport->port.type == PORT_PNX8XXX ? "PNX8XXX" : NULL;
 555}
 556
 557/*
 558 * Release the memory region(s) being used by 'port'.
 559 */
 560static void pnx8xxx_release_port(struct uart_port *port)
 561{
 562        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 563
 564        release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
 565}
 566
 567/*
 568 * Request the memory region(s) being used by 'port'.
 569 */
 570static int pnx8xxx_request_port(struct uart_port *port)
 571{
 572        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 573        return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
 574                        "pnx8xxx-uart") != NULL ? 0 : -EBUSY;
 575}
 576
 577/*
 578 * Configure/autoconfigure the port.
 579 */
 580static void pnx8xxx_config_port(struct uart_port *port, int flags)
 581{
 582        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 583
 584        if (flags & UART_CONFIG_TYPE &&
 585            pnx8xxx_request_port(&sport->port) == 0)
 586                sport->port.type = PORT_PNX8XXX;
 587}
 588
 589/*
 590 * Verify the new serial_struct (for TIOCSSERIAL).
 591 * The only change we allow are to the flags and type, and
 592 * even then only between PORT_PNX8XXX and PORT_UNKNOWN
 593 */
 594static int
 595pnx8xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
 596{
 597        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 598        int ret = 0;
 599
 600        if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8XXX)
 601                ret = -EINVAL;
 602        if (sport->port.irq != ser->irq)
 603                ret = -EINVAL;
 604        if (ser->io_type != SERIAL_IO_MEM)
 605                ret = -EINVAL;
 606        if (sport->port.uartclk / 16 != ser->baud_base)
 607                ret = -EINVAL;
 608        if ((void *)sport->port.mapbase != ser->iomem_base)
 609                ret = -EINVAL;
 610        if (sport->port.iobase != ser->port)
 611                ret = -EINVAL;
 612        if (ser->hub6 != 0)
 613                ret = -EINVAL;
 614        return ret;
 615}
 616
 617static struct uart_ops pnx8xxx_pops = {
 618        .tx_empty       = pnx8xxx_tx_empty,
 619        .set_mctrl      = pnx8xxx_set_mctrl,
 620        .get_mctrl      = pnx8xxx_get_mctrl,
 621        .stop_tx        = pnx8xxx_stop_tx,
 622        .start_tx       = pnx8xxx_start_tx,
 623        .stop_rx        = pnx8xxx_stop_rx,
 624        .enable_ms      = pnx8xxx_enable_ms,
 625        .break_ctl      = pnx8xxx_break_ctl,
 626        .startup        = pnx8xxx_startup,
 627        .shutdown       = pnx8xxx_shutdown,
 628        .set_termios    = pnx8xxx_set_termios,
 629        .type           = pnx8xxx_type,
 630        .release_port   = pnx8xxx_release_port,
 631        .request_port   = pnx8xxx_request_port,
 632        .config_port    = pnx8xxx_config_port,
 633        .verify_port    = pnx8xxx_verify_port,
 634};
 635
 636
 637/*
 638 * Setup the PNX8XXX serial ports.
 639 *
 640 * Note also that we support "console=ttySx" where "x" is either 0 or 1.
 641 */
 642static void __init pnx8xxx_init_ports(void)
 643{
 644        static int first = 1;
 645        int i;
 646
 647        if (!first)
 648                return;
 649        first = 0;
 650
 651        for (i = 0; i < NR_PORTS; i++) {
 652                init_timer(&pnx8xxx_ports[i].timer);
 653                pnx8xxx_ports[i].timer.function = pnx8xxx_timeout;
 654                pnx8xxx_ports[i].timer.data     = (unsigned long)&pnx8xxx_ports[i];
 655                pnx8xxx_ports[i].port.ops = &pnx8xxx_pops;
 656        }
 657}
 658
 659#ifdef CONFIG_SERIAL_PNX8XXX_CONSOLE
 660
 661static void pnx8xxx_console_putchar(struct uart_port *port, int ch)
 662{
 663        struct pnx8xxx_port *sport = (struct pnx8xxx_port *)port;
 664        int status;
 665
 666        do {
 667                /* Wait for UART_TX register to empty */
 668                status = serial_in(sport, PNX8XXX_FIFO);
 669        } while (status & PNX8XXX_UART_FIFO_TXFIFO);
 670        serial_out(sport, PNX8XXX_FIFO, ch);
 671}
 672
 673/*
 674 * Interrupts are disabled on entering
 675 */static void
 676pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
 677{
 678        struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index];
 679        unsigned int old_ien, status;
 680
 681        /*
 682         *      First, save IEN and then disable interrupts
 683         */
 684        old_ien = serial_in(sport, PNX8XXX_IEN);
 685        serial_out(sport, PNX8XXX_IEN, old_ien & ~(PNX8XXX_UART_INT_ALLTX |
 686                                        PNX8XXX_UART_INT_ALLRX));
 687
 688        uart_console_write(&sport->port, s, count, pnx8xxx_console_putchar);
 689
 690        /*
 691         *      Finally, wait for transmitter to become empty
 692         *      and restore IEN
 693         */
 694        do {
 695                /* Wait for UART_TX register to empty */
 696                status = serial_in(sport, PNX8XXX_FIFO);
 697        } while (status & PNX8XXX_UART_FIFO_TXFIFO);
 698
 699        /* Clear TX and EMPTY interrupt */
 700        serial_out(sport, PNX8XXX_ICLR, PNX8XXX_UART_INT_TX |
 701                             PNX8XXX_UART_INT_EMPTY);
 702
 703        serial_out(sport, PNX8XXX_IEN, old_ien);
 704}
 705
 706static int __init
 707pnx8xxx_console_setup(struct console *co, char *options)
 708{
 709        struct pnx8xxx_port *sport;
 710        int baud = 38400;
 711        int bits = 8;
 712        int parity = 'n';
 713        int flow = 'n';
 714
 715        /*
 716         * Check whether an invalid uart number has been specified, and
 717         * if so, search for the first available port that does have
 718         * console support.
 719         */
 720        if (co->index == -1 || co->index >= NR_PORTS)
 721                co->index = 0;
 722        sport = &pnx8xxx_ports[co->index];
 723
 724        if (options)
 725                uart_parse_options(options, &baud, &parity, &bits, &flow);
 726
 727        return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 728}
 729
 730static struct uart_driver pnx8xxx_reg;
 731static struct console pnx8xxx_console = {
 732        .name           = "ttyS",
 733        .write          = pnx8xxx_console_write,
 734        .device         = uart_console_device,
 735        .setup          = pnx8xxx_console_setup,
 736        .flags          = CON_PRINTBUFFER,
 737        .index          = -1,
 738        .data           = &pnx8xxx_reg,
 739};
 740
 741static int __init pnx8xxx_rs_console_init(void)
 742{
 743        pnx8xxx_init_ports();
 744        register_console(&pnx8xxx_console);
 745        return 0;
 746}
 747console_initcall(pnx8xxx_rs_console_init);
 748
 749#define PNX8XXX_CONSOLE &pnx8xxx_console
 750#else
 751#define PNX8XXX_CONSOLE NULL
 752#endif
 753
 754static struct uart_driver pnx8xxx_reg = {
 755        .owner                  = THIS_MODULE,
 756        .driver_name            = "ttyS",
 757        .dev_name               = "ttyS",
 758        .major                  = SERIAL_PNX8XXX_MAJOR,
 759        .minor                  = MINOR_START,
 760        .nr                     = NR_PORTS,
 761        .cons                   = PNX8XXX_CONSOLE,
 762};
 763
 764static int pnx8xxx_serial_suspend(struct platform_device *pdev, pm_message_t state)
 765{
 766        struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
 767
 768        return uart_suspend_port(&pnx8xxx_reg, &sport->port);
 769}
 770
 771static int pnx8xxx_serial_resume(struct platform_device *pdev)
 772{
 773        struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
 774
 775        return uart_resume_port(&pnx8xxx_reg, &sport->port);
 776}
 777
 778static int pnx8xxx_serial_probe(struct platform_device *pdev)
 779{
 780        struct resource *res = pdev->resource;
 781        int i;
 782
 783        for (i = 0; i < pdev->num_resources; i++, res++) {
 784                if (!(res->flags & IORESOURCE_MEM))
 785                        continue;
 786
 787                for (i = 0; i < NR_PORTS; i++) {
 788                        if (pnx8xxx_ports[i].port.mapbase != res->start)
 789                                continue;
 790
 791                        pnx8xxx_ports[i].port.dev = &pdev->dev;
 792                        uart_add_one_port(&pnx8xxx_reg, &pnx8xxx_ports[i].port);
 793                        platform_set_drvdata(pdev, &pnx8xxx_ports[i]);
 794                        break;
 795                }
 796        }
 797
 798        return 0;
 799}
 800
 801static int pnx8xxx_serial_remove(struct platform_device *pdev)
 802{
 803        struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
 804
 805        platform_set_drvdata(pdev, NULL);
 806
 807        if (sport)
 808                uart_remove_one_port(&pnx8xxx_reg, &sport->port);
 809
 810        return 0;
 811}
 812
 813static struct platform_driver pnx8xxx_serial_driver = {
 814        .driver         = {
 815                .name   = "pnx8xxx-uart",
 816                .owner  = THIS_MODULE,
 817        },
 818        .probe          = pnx8xxx_serial_probe,
 819        .remove         = pnx8xxx_serial_remove,
 820        .suspend        = pnx8xxx_serial_suspend,
 821        .resume         = pnx8xxx_serial_resume,
 822};
 823
 824static int __init pnx8xxx_serial_init(void)
 825{
 826        int ret;
 827
 828        printk(KERN_INFO "Serial: PNX8XXX driver\n");
 829
 830        pnx8xxx_init_ports();
 831
 832        ret = uart_register_driver(&pnx8xxx_reg);
 833        if (ret == 0) {
 834                ret = platform_driver_register(&pnx8xxx_serial_driver);
 835                if (ret)
 836                        uart_unregister_driver(&pnx8xxx_reg);
 837        }
 838        return ret;
 839}
 840
 841static void __exit pnx8xxx_serial_exit(void)
 842{
 843        platform_driver_unregister(&pnx8xxx_serial_driver);
 844        uart_unregister_driver(&pnx8xxx_reg);
 845}
 846
 847module_init(pnx8xxx_serial_init);
 848module_exit(pnx8xxx_serial_exit);
 849
 850MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
 851MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver");
 852MODULE_LICENSE("GPL");
 853MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR);
 854MODULE_ALIAS("platform:pnx8xxx-uart");
 855