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