root/drivers/tty/serial/pnx8xxx_uart.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. serial_in
  2. serial_out
  3. pnx8xxx_mctrl_check
  4. pnx8xxx_timeout
  5. pnx8xxx_stop_tx
  6. pnx8xxx_start_tx
  7. pnx8xxx_stop_rx
  8. pnx8xxx_enable_ms
  9. pnx8xxx_rx_chars
  10. pnx8xxx_tx_chars
  11. pnx8xxx_int
  12. pnx8xxx_tx_empty
  13. pnx8xxx_get_mctrl
  14. pnx8xxx_set_mctrl
  15. pnx8xxx_break_ctl
  16. pnx8xxx_startup
  17. pnx8xxx_shutdown
  18. pnx8xxx_set_termios
  19. pnx8xxx_type
  20. pnx8xxx_release_port
  21. pnx8xxx_request_port
  22. pnx8xxx_config_port
  23. pnx8xxx_verify_port
  24. pnx8xxx_init_ports
  25. pnx8xxx_console_putchar
  26. pnx8xxx_console_write
  27. pnx8xxx_console_setup
  28. pnx8xxx_rs_console_init
  29. pnx8xxx_serial_suspend
  30. pnx8xxx_serial_resume
  31. pnx8xxx_serial_probe
  32. pnx8xxx_serial_remove
  33. pnx8xxx_serial_init
  34. pnx8xxx_serial_exit

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

/* [<][>][^][v][top][bottom][index][help] */