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