Version:  2.0.40 2.2.26 2.4.37 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2

Linux/drivers/tty/serial/pnx8xxx_uart.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us