Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* drivers/serial/serial_lh7a40x.c
  2  *
  3  *  Copyright (C) 2004 Coastal Environmental Systems
  4  *
  5  *  This program is free software; you can redistribute it and/or
  6  *  modify it under the terms of the GNU General Public License
  7  *  version 2 as published by the Free Software Foundation.
  8  *
  9  */
 10 
 11 /* Driver for Sharp LH7A40X embedded serial ports
 12  *
 13  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
 14  *  Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd.
 15  *
 16  *  ---
 17  *
 18  * This driver supports the embedded UARTs of the Sharp LH7A40X series
 19  * CPUs.  While similar to the 16550 and other UART chips, there is
 20  * nothing close to register compatibility.  Moreover, some of the
 21  * modem control lines are not available, either in the chip or they
 22  * are lacking in the board-level implementation.
 23  *
 24  * - Use of SIRDIS
 25  *   For simplicity, we disable the IR functions of any UART whenever
 26  *   we enable it.
 27  *
 28  */
 29 
 30 
 31 #if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 32 #define SUPPORT_SYSRQ
 33 #endif
 34 
 35 #include <linux/module.h>
 36 #include <linux/ioport.h>
 37 #include <linux/init.h>
 38 #include <linux/console.h>
 39 #include <linux/sysrq.h>
 40 #include <linux/tty.h>
 41 #include <linux/tty_flip.h>
 42 #include <linux/serial_core.h>
 43 #include <linux/serial.h>
 44 #include <linux/io.h>
 45 
 46 #include <asm/irq.h>
 47 #include <mach/hardware.h>
 48 
 49 #define DEV_MAJOR       204
 50 #define DEV_MINOR       16
 51 #define DEV_NR          3
 52 
 53 #define ISR_LOOP_LIMIT  256
 54 
 55 #define UR(p,o) _UR ((p)->membase, o)
 56 #define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o))))
 57 #define BIT_CLR(p,o,m)  UR(p,o) = UR(p,o) & (~(unsigned int)m)
 58 #define BIT_SET(p,o,m)  UR(p,o) = UR(p,o) | ( (unsigned int)m)
 59 
 60 #define UART_REG_SIZE   32
 61 
 62 #define UART_R_DATA     (0x00)
 63 #define UART_R_FCON     (0x04)
 64 #define UART_R_BRCON    (0x08)
 65 #define UART_R_CON      (0x0c)
 66 #define UART_R_STATUS   (0x10)
 67 #define UART_R_RAWISR   (0x14)
 68 #define UART_R_INTEN    (0x18)
 69 #define UART_R_ISR      (0x1c)
 70 
 71 #define UARTEN          (0x01)          /* UART enable */
 72 #define SIRDIS          (0x02)          /* Serial IR disable (UART1 only) */
 73 
 74 #define RxEmpty         (0x10)
 75 #define TxEmpty         (0x80)
 76 #define TxFull          (0x20)
 77 #define nRxRdy          RxEmpty
 78 #define nTxRdy          TxFull
 79 #define TxBusy          (0x08)
 80 
 81 #define RxBreak         (0x0800)
 82 #define RxOverrunError  (0x0400)
 83 #define RxParityError   (0x0200)
 84 #define RxFramingError  (0x0100)
 85 #define RxError     (RxBreak | RxOverrunError | RxParityError | RxFramingError)
 86 
 87 #define DCD             (0x04)
 88 #define DSR             (0x02)
 89 #define CTS             (0x01)
 90 
 91 #define RxInt           (0x01)
 92 #define TxInt           (0x02)
 93 #define ModemInt        (0x04)
 94 #define RxTimeoutInt    (0x08)
 95 
 96 #define MSEOI           (0x10)
 97 
 98 #define WLEN_8          (0x60)
 99 #define WLEN_7          (0x40)
100 #define WLEN_6          (0x20)
101 #define WLEN_5          (0x00)
102 #define WLEN            (0x60)  /* Mask for all word-length bits */
103 #define STP2            (0x08)
104 #define PEN             (0x02)  /* Parity Enable */
105 #define EPS             (0x04)  /* Even Parity Set */
106 #define FEN             (0x10)  /* FIFO Enable */
107 #define BRK             (0x01)  /* Send Break */
108 
109 
110 struct uart_port_lh7a40x {
111         struct uart_port port;
112         unsigned int statusPrev; /* Most recently read modem status */
113 };
114 
115 static void lh7a40xuart_stop_tx (struct uart_port* port)
116 {
117         BIT_CLR (port, UART_R_INTEN, TxInt);
118 }
119 
120 static void lh7a40xuart_start_tx (struct uart_port* port)
121 {
122         BIT_SET (port, UART_R_INTEN, TxInt);
123 
124         /* *** FIXME: do I need to check for startup of the
125                       transmitter?  The old driver did, but AMBA
126                       doesn't . */
127 }
128 
129 static void lh7a40xuart_stop_rx (struct uart_port* port)
130 {
131         BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
132 }
133 
134 static void lh7a40xuart_enable_ms (struct uart_port* port)
135 {
136         BIT_SET (port, UART_R_INTEN, ModemInt);
137 }
138 
139 static void lh7a40xuart_rx_chars (struct uart_port* port)
140 {
141         struct tty_struct* tty = port->info->port.tty;
142         int cbRxMax = 256;      /* (Gross) limit on receive */
143         unsigned int data;      /* Received data and status */
144         unsigned int flag;
145 
146         while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
147                 data = UR (port, UART_R_DATA);
148                 flag = TTY_NORMAL;
149                 ++port->icount.rx;
150 
151                 if (unlikely(data & RxError)) {
152                         if (data & RxBreak) {
153                                 data &= ~(RxFramingError | RxParityError);
154                                 ++port->icount.brk;
155                                 if (uart_handle_break (port))
156                                         continue;
157                         }
158                         else if (data & RxParityError)
159                                 ++port->icount.parity;
160                         else if (data & RxFramingError)
161                                 ++port->icount.frame;
162                         if (data & RxOverrunError)
163                                 ++port->icount.overrun;
164 
165                                 /* Mask by termios, leave Rx'd byte */
166                         data &= port->read_status_mask | 0xff;
167 
168                         if (data & RxBreak)
169                                 flag = TTY_BREAK;
170                         else if (data & RxParityError)
171                                 flag = TTY_PARITY;
172                         else if (data & RxFramingError)
173                                 flag = TTY_FRAME;
174                 }
175 
176                 if (uart_handle_sysrq_char (port, (unsigned char) data))
177                         continue;
178 
179                 uart_insert_char(port, data, RxOverrunError, data, flag);
180         }
181         tty_flip_buffer_push (tty);
182         return;
183 }
184 
185 static void lh7a40xuart_tx_chars (struct uart_port* port)
186 {
187         struct circ_buf* xmit = &port->info->xmit;
188         int cbTxMax = port->fifosize;
189 
190         if (port->x_char) {
191                 UR (port, UART_R_DATA) = port->x_char;
192                 ++port->icount.tx;
193                 port->x_char = 0;
194                 return;
195         }
196         if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
197                 lh7a40xuart_stop_tx (port);
198                 return;
199         }
200 
201         /* Unlike the AMBA UART, the lh7a40x UART does not guarantee
202            that at least half of the FIFO is empty.  Instead, we check
203            status for every character.  Using the AMBA method causes
204            the transmitter to drop characters. */
205 
206         do {
207                 UR (port, UART_R_DATA) = xmit->buf[xmit->tail];
208                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
209                 ++port->icount.tx;
210                 if (uart_circ_empty(xmit))
211                         break;
212         } while (!(UR (port, UART_R_STATUS) & nTxRdy)
213                  && cbTxMax--);
214 
215         if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
216                 uart_write_wakeup (port);
217 
218         if (uart_circ_empty (xmit))
219                 lh7a40xuart_stop_tx (port);
220 }
221 
222 static void lh7a40xuart_modem_status (struct uart_port* port)
223 {
224         unsigned int status = UR (port, UART_R_STATUS);
225         unsigned int delta
226                 = status ^ ((struct uart_port_lh7a40x*) port)->statusPrev;
227 
228         BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */
229 
230         if (!delta)             /* Only happens if we missed 2 transitions */
231                 return;
232 
233         ((struct uart_port_lh7a40x*) port)->statusPrev = status;
234 
235         if (delta & DCD)
236                 uart_handle_dcd_change (port, status & DCD);
237 
238         if (delta & DSR)
239                 ++port->icount.dsr;
240 
241         if (delta & CTS)
242                 uart_handle_cts_change (port, status & CTS);
243 
244         wake_up_interruptible (&port->info->delta_msr_wait);
245 }
246 
247 static irqreturn_t lh7a40xuart_int (int irq, void* dev_id)
248 {
249         struct uart_port* port = dev_id;
250         unsigned int cLoopLimit = ISR_LOOP_LIMIT;
251         unsigned int isr = UR (port, UART_R_ISR);
252 
253 
254         do {
255                 if (isr & (RxInt | RxTimeoutInt))
256                         lh7a40xuart_rx_chars(port);
257                 if (isr & ModemInt)
258                         lh7a40xuart_modem_status (port);
259                 if (isr & TxInt)
260                         lh7a40xuart_tx_chars (port);
261 
262                 if (--cLoopLimit == 0)
263                         break;
264 
265                 isr = UR (port, UART_R_ISR);
266         } while (isr & (RxInt | TxInt | RxTimeoutInt));
267 
268         return IRQ_HANDLED;
269 }
270 
271 static unsigned int lh7a40xuart_tx_empty (struct uart_port* port)
272 {
273         return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0;
274 }
275 
276 static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port)
277 {
278         unsigned int result = 0;
279         unsigned int status = UR (port, UART_R_STATUS);
280 
281         if (status & DCD)
282                 result |= TIOCM_CAR;
283         if (status & DSR)
284                 result |= TIOCM_DSR;
285         if (status & CTS)
286                 result |= TIOCM_CTS;
287 
288         return result;
289 }
290 
291 static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
292 {
293         /* None of the ports supports DTR. UART1 supports RTS through GPIO. */
294         /* Note, kernel appears to be setting DTR and RTS on console. */
295 
296         /* *** FIXME: this deserves more work.  There's some work in
297                tracing all of the IO pins. */
298 #if 0
299         if( port->mapbase == UART1_PHYS) {
300                 gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
301 
302                 if (mctrl & TIOCM_RTS)
303                         gpio->pbdr &= ~GPIOB_UART1_RTS;
304                 else
305                         gpio->pbdr |= GPIOB_UART1_RTS;
306         }
307 #endif
308 }
309 
310 static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state)
311 {
312         unsigned long flags;
313 
314         spin_lock_irqsave(&port->lock, flags);
315         if (break_state == -1)
316                 BIT_SET (port, UART_R_FCON, BRK); /* Assert break */
317         else
318                 BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */
319         spin_unlock_irqrestore(&port->lock, flags);
320 }
321 
322 static int lh7a40xuart_startup (struct uart_port* port)
323 {
324         int retval;
325 
326         retval = request_irq (port->irq, lh7a40xuart_int, 0,
327                               "serial_lh7a40x", port);
328         if (retval)
329                 return retval;
330 
331                                 /* Initial modem control-line settings */
332         ((struct uart_port_lh7a40x*) port)->statusPrev
333                 = UR (port, UART_R_STATUS);
334 
335         /* There is presently no configuration option to enable IR.
336            Thus, we always disable it. */
337 
338         BIT_SET (port, UART_R_CON, UARTEN | SIRDIS);
339         BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
340 
341         return 0;
342 }
343 
344 static void lh7a40xuart_shutdown (struct uart_port* port)
345 {
346         free_irq (port->irq, port);
347         BIT_CLR (port, UART_R_FCON, BRK | FEN);
348         BIT_CLR (port, UART_R_CON, UARTEN);
349 }
350 
351 static void lh7a40xuart_set_termios (struct uart_port* port,
352                                      struct ktermios* termios,
353                                      struct ktermios* old)
354 {
355         unsigned int con;
356         unsigned int inten;
357         unsigned int fcon;
358         unsigned long flags;
359         unsigned int baud;
360         unsigned int quot;
361 
362         baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16);
363         quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */
364 
365         switch (termios->c_cflag & CSIZE) {
366         case CS5:
367                 fcon = WLEN_5;
368                 break;
369         case CS6:
370                 fcon = WLEN_6;
371                 break;
372         case CS7:
373                 fcon = WLEN_7;
374                 break;
375         case CS8:
376         default:
377                 fcon = WLEN_8;
378                 break;
379         }
380         if (termios->c_cflag & CSTOPB)
381                 fcon |= STP2;
382         if (termios->c_cflag & PARENB) {
383                 fcon |= PEN;
384                 if (!(termios->c_cflag & PARODD))
385                         fcon |= EPS;
386         }
387         if (port->fifosize > 1)
388                 fcon |= FEN;
389 
390         spin_lock_irqsave (&port->lock, flags);
391 
392         uart_update_timeout (port, termios->c_cflag, baud);
393 
394         port->read_status_mask = RxOverrunError;
395         if (termios->c_iflag & INPCK)
396                 port->read_status_mask |= RxFramingError | RxParityError;
397         if (termios->c_iflag & (BRKINT | PARMRK))
398                 port->read_status_mask |= RxBreak;
399 
400                 /* Figure mask for status we ignore */
401         port->ignore_status_mask = 0;
402         if (termios->c_iflag & IGNPAR)
403                 port->ignore_status_mask |= RxFramingError | RxParityError;
404         if (termios->c_iflag & IGNBRK) {
405                 port->ignore_status_mask |= RxBreak;
406                 /* Ignore overrun when ignorning parity */
407                 /* *** FIXME: is this in the right place? */
408                 if (termios->c_iflag & IGNPAR)
409                         port->ignore_status_mask |= RxOverrunError;
410         }
411 
412                 /* Ignore all receive errors when receive disabled */
413         if ((termios->c_cflag & CREAD) == 0)
414                 port->ignore_status_mask |= RxError;
415 
416         con   = UR (port, UART_R_CON);
417         inten = (UR (port, UART_R_INTEN) & ~ModemInt);
418 
419         if (UART_ENABLE_MS (port, termios->c_cflag))
420                 inten |= ModemInt;
421 
422         BIT_CLR (port, UART_R_CON, UARTEN);     /* Disable UART */
423         UR (port, UART_R_INTEN) = 0;            /* Disable interrupts */
424         UR (port, UART_R_BRCON) = quot - 1;     /* Set baud rate divisor */
425         UR (port, UART_R_FCON)  = fcon;         /* Set FIFO and frame ctrl */
426         UR (port, UART_R_INTEN) = inten;        /* Enable interrupts */
427         UR (port, UART_R_CON)   = con;          /* Restore UART mode */
428 
429         spin_unlock_irqrestore(&port->lock, flags);
430 }
431 
432 static const char* lh7a40xuart_type (struct uart_port* port)
433 {
434         return port->type == PORT_LH7A40X ? "LH7A40X" : NULL;
435 }
436 
437 static void lh7a40xuart_release_port (struct uart_port* port)
438 {
439         release_mem_region (port->mapbase, UART_REG_SIZE);
440 }
441 
442 static int lh7a40xuart_request_port (struct uart_port* port)
443 {
444         return request_mem_region (port->mapbase, UART_REG_SIZE,
445                                    "serial_lh7a40x") != NULL
446                 ? 0 : -EBUSY;
447 }
448 
449 static void lh7a40xuart_config_port (struct uart_port* port, int flags)
450 {
451         if (flags & UART_CONFIG_TYPE) {
452                 port->type = PORT_LH7A40X;
453                 lh7a40xuart_request_port (port);
454         }
455 }
456 
457 static int lh7a40xuart_verify_port (struct uart_port* port,
458                                     struct serial_struct* ser)
459 {
460         int ret = 0;
461 
462         if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
463                 ret = -EINVAL;
464         if (ser->irq < 0 || ser->irq >= nr_irqs)
465                 ret = -EINVAL;
466         if (ser->baud_base < 9600) /* *** FIXME: is this true? */
467                 ret = -EINVAL;
468         return ret;
469 }
470 
471 static struct uart_ops lh7a40x_uart_ops = {
472         .tx_empty       = lh7a40xuart_tx_empty,
473         .set_mctrl      = lh7a40xuart_set_mctrl,
474         .get_mctrl      = lh7a40xuart_get_mctrl,
475         .stop_tx        = lh7a40xuart_stop_tx,
476         .start_tx       = lh7a40xuart_start_tx,
477         .stop_rx        = lh7a40xuart_stop_rx,
478         .enable_ms      = lh7a40xuart_enable_ms,
479         .break_ctl      = lh7a40xuart_break_ctl,
480         .startup        = lh7a40xuart_startup,
481         .shutdown       = lh7a40xuart_shutdown,
482         .set_termios    = lh7a40xuart_set_termios,
483         .type           = lh7a40xuart_type,
484         .release_port   = lh7a40xuart_release_port,
485         .request_port   = lh7a40xuart_request_port,
486         .config_port    = lh7a40xuart_config_port,
487         .verify_port    = lh7a40xuart_verify_port,
488 };
489 
490 static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
491         {
492                 .port = {
493                         .membase        = (void*) io_p2v (UART1_PHYS),
494                         .mapbase        = UART1_PHYS,
495                         .iotype         = UPIO_MEM,
496                         .irq            = IRQ_UART1INTR,
497                         .uartclk        = 14745600/2,
498                         .fifosize       = 16,
499                         .ops            = &lh7a40x_uart_ops,
500                         .flags          = UPF_BOOT_AUTOCONF,
501                         .line           = 0,
502                 },
503         },
504         {
505                 .port = {
506                         .membase        = (void*) io_p2v (UART2_PHYS),
507                         .mapbase        = UART2_PHYS,
508                         .iotype         = UPIO_MEM,
509                         .irq            = IRQ_UART2INTR,
510                         .uartclk        = 14745600/2,
511                         .fifosize       = 16,
512                         .ops            = &lh7a40x_uart_ops,
513                         .flags          = UPF_BOOT_AUTOCONF,
514                         .line           = 1,
515                 },
516         },
517         {
518                 .port = {
519                         .membase        = (void*) io_p2v (UART3_PHYS),
520                         .mapbase        = UART3_PHYS,
521                         .iotype         = UPIO_MEM,
522                         .irq            = IRQ_UART3INTR,
523                         .uartclk        = 14745600/2,
524                         .fifosize       = 16,
525                         .ops            = &lh7a40x_uart_ops,
526                         .flags          = UPF_BOOT_AUTOCONF,
527                         .line           = 2,
528                 },
529         },
530 };
531 
532 #ifndef CONFIG_SERIAL_LH7A40X_CONSOLE
533 # define LH7A40X_CONSOLE NULL
534 #else
535 # define LH7A40X_CONSOLE &lh7a40x_console
536 
537 static void lh7a40xuart_console_putchar(struct uart_port *port, int ch)
538 {
539         while (UR(port, UART_R_STATUS) & nTxRdy)
540                 ;
541         UR(port, UART_R_DATA) = ch;
542 }
543 
544 static void lh7a40xuart_console_write (struct console* co,
545                                        const char* s,
546                                        unsigned int count)
547 {
548         struct uart_port* port = &lh7a40x_ports[co->index].port;
549         unsigned int con = UR (port, UART_R_CON);
550         unsigned int inten = UR (port, UART_R_INTEN);
551 
552 
553         UR (port, UART_R_INTEN) = 0;            /* Disable all interrupts */
554         BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
555 
556         uart_console_write(port, s, count, lh7a40xuart_console_putchar);
557 
558                                 /* Wait until all characters are sent */
559         while (UR (port, UART_R_STATUS) & TxBusy)
560                 ;
561 
562                                 /* Restore control and interrupt mask */
563         UR (port, UART_R_CON) = con;
564         UR (port, UART_R_INTEN) = inten;
565 }
566 
567 static void __init lh7a40xuart_console_get_options (struct uart_port* port,
568                                                     int* baud,
569                                                     int* parity,
570                                                     int* bits)
571 {
572         if (UR (port, UART_R_CON) & UARTEN) {
573                 unsigned int fcon = UR (port, UART_R_FCON);
574                 unsigned int quot = UR (port, UART_R_BRCON) + 1;
575 
576                 switch (fcon & (PEN | EPS)) {
577                 default:        *parity = 'n'; break;
578                 case PEN:       *parity = 'o'; break;
579                 case PEN | EPS: *parity = 'e'; break;
580                 }
581 
582                 switch (fcon & WLEN) {
583                 default:
584                 case WLEN_8: *bits = 8; break;
585                 case WLEN_7: *bits = 7; break;
586                 case WLEN_6: *bits = 6; break;
587                 case WLEN_5: *bits = 5; break;
588                 }
589 
590                 *baud = port->uartclk/(16*quot);
591         }
592 }
593 
594 static int __init lh7a40xuart_console_setup (struct console* co, char* options)
595 {
596         struct uart_port* port;
597         int baud = 38400;
598         int bits = 8;
599         int parity = 'n';
600         int flow = 'n';
601 
602         if (co->index >= DEV_NR) /* Bounds check on device number */
603                 co->index = 0;
604         port = &lh7a40x_ports[co->index].port;
605 
606         if (options)
607                 uart_parse_options (options, &baud, &parity, &bits, &flow);
608         else
609                 lh7a40xuart_console_get_options (port, &baud, &parity, &bits);
610 
611         return uart_set_options (port, co, baud, parity, bits, flow);
612 }
613 
614 static struct uart_driver lh7a40x_reg;
615 static struct console lh7a40x_console = {
616         .name           = "ttyAM",
617         .write          = lh7a40xuart_console_write,
618         .device         = uart_console_device,
619         .setup          = lh7a40xuart_console_setup,
620         .flags          = CON_PRINTBUFFER,
621         .index          = -1,
622         .data           = &lh7a40x_reg,
623 };
624 
625 static int __init lh7a40xuart_console_init(void)
626 {
627         register_console (&lh7a40x_console);
628         return 0;
629 }
630 
631 console_initcall (lh7a40xuart_console_init);
632 
633 #endif
634 
635 static struct uart_driver lh7a40x_reg = {
636         .owner                  = THIS_MODULE,
637         .driver_name            = "ttyAM",
638         .dev_name               = "ttyAM",
639         .major                  = DEV_MAJOR,
640         .minor                  = DEV_MINOR,
641         .nr                     = DEV_NR,
642         .cons                   = LH7A40X_CONSOLE,
643 };
644 
645 static int __init lh7a40xuart_init(void)
646 {
647         int ret;
648 
649         printk (KERN_INFO "serial: LH7A40X serial driver\n");
650 
651         ret = uart_register_driver (&lh7a40x_reg);
652 
653         if (ret == 0) {
654                 int i;
655 
656                 for (i = 0; i < DEV_NR; i++) {
657                         /* UART3, when used, requires GPIO pin reallocation */
658                         if (lh7a40x_ports[i].port.mapbase == UART3_PHYS)
659                                 GPIO_PINMUX |= 1<<3;
660                         uart_add_one_port (&lh7a40x_reg,
661                                            &lh7a40x_ports[i].port);
662                 }
663         }
664         return ret;
665 }
666 
667 static void __exit lh7a40xuart_exit(void)
668 {
669         int i;
670 
671         for (i = 0; i < DEV_NR; i++)
672                 uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port);
673 
674         uart_unregister_driver (&lh7a40x_reg);
675 }
676 
677 module_init (lh7a40xuart_init);
678 module_exit (lh7a40xuart_exit);
679 
680 MODULE_AUTHOR ("Marc Singer");
681 MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver");
682 MODULE_LICENSE ("GPL");
683 
  This page was automatically generated by the LXR engine.