MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / serial / p2001_uart.c
blobc410b0c87d0a124f84c13541e498720b6064fe57
1 /*
2 * linux/drivers/char/p2001_uart.c
4 * Driver for P2001 uart port
6 * Copyright (C) 2004 Tobias Lorenz
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Version 1.0: First working version
25 * Version 1.1: Removed all READ_REG/WRITE_REG
26 * Version 1.2: Break handling
27 * Version 1.3: Hardware handshake
28 * Device naming, major/minor nr for setserial
29 * ISR cleanups
30 * Version 1.4: cpu frequency scaling
33 #include <linux/module.h>
34 #include <linux/tty.h>
35 #include <linux/ioport.h>
36 #include <linux/init.h>
37 #include <linux/serial.h>
38 #include <linux/console.h>
39 #include <linux/sysrq.h>
40 #include <linux/device.h>
41 #include <linux/serial_core.h>
43 #ifdef CONFIG_CPU_FREQ
44 #include <linux/notifier.h>
45 #include <linux/cpufreq.h>
46 #endif
48 #include <asm/io.h>
49 #include <asm/irq.h>
50 #include <asm/hardware.h>
52 #if defined(CONFIG_SERIAL_P2001_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
53 #define SUPPORT_SYSRQ
54 #endif
57 /**************************************************************************
58 * Definitions
59 **************************************************************************/
60 static const char *version =
61 "p2001_uart.c:v1.4 12/29/2004 Tobias Lorenz (tobias.lorenz@gmx.net)\n";
63 static const char p2001_uart_name[] = "P2001 uart";
65 #define TX_MIN_BUF 10
67 #define tx_enabled(port) ((port)->unused[0])
68 #define rx_enabled(port) ((port)->unused[1])
70 extern struct uart_driver p2001_uart_driver; /* UART Driver */
71 extern struct uart_port p2001_uart_port; /* UART Port */
72 extern struct uart_ops p2001_uart_ops; /* UART Operations */
73 extern struct console p2001_console; /* Console */
75 #define DEFAULT_BAUD 57600
76 static unsigned int baud; /* Current baudrate */
80 /**************************************************************************
81 * UART Driver
82 **************************************************************************/
84 static struct uart_driver p2001_uart_driver = {
85 .owner = THIS_MODULE,
86 .driver_name = "serial", /* name of tty/console device */
87 .dev_name = "ttyS", /* name of tty/console device */
88 #ifdef CONFIG_DEVFS_FS
89 .devfs_name = "tts/", /* name of tty/console device */
90 #endif
91 .major = 4, /* major number for the driver */
92 .minor = 64, /* starting minor number */
93 .nr = 1, /* maximum number of serial ports this driver supports */
94 #ifdef CONFIG_SERIAL_P2001_UART_CONSOLE
95 .cons = &p2001_console,
96 #endif
101 /**************************************************************************
102 * UART Port
103 **************************************************************************/
105 static struct uart_port p2001_uart_port = {
106 .membase = (void*)P2001_UART, /* read/write[bwl] */
107 .mapbase = (unsigned int)P2001_UART, /* for ioremap */
108 .iotype = UPIO_MEM, /* io access style */
109 .irq = IRQ_UART, /* irq number */
110 .uartclk = CONFIG_SYSCLK/8, /* base uart clock */
111 .fifosize = 32, /* tx fifo size */
112 .ops = &p2001_uart_ops,
113 .flags = UPF_BOOT_AUTOCONF,
114 .line = 0, /* port index */
119 /**************************************************************************
120 * UART interrupt routine
121 **************************************************************************/
123 /* uart interrupt send routine */
124 static void p2001_uart_tx_chars(struct uart_port *port)
126 struct circ_buf *xmit = &port->info->xmit;
127 int count;
129 if (port->x_char) {
130 while ((P2001_UART->r.STATUS & 0x3f) > TX_MIN_BUF)
131 barrier();
132 P2001_UART->w.TX[0] = port->x_char;
133 port->icount.tx++;
134 port->x_char = 0;
135 return;
137 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
138 tx_enabled(port) = 0;
139 return;
142 count = port->fifosize >> 1;
143 do {
144 while ((P2001_UART->r.STATUS & 0x3f) > TX_MIN_BUF)
145 barrier();
146 P2001_UART->w.TX[0] = xmit->buf[xmit->tail];
147 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
148 port->icount.tx++;
149 if (uart_circ_empty(xmit))
150 break;
151 } while (--count > 0);
153 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
154 uart_write_wakeup(port);
156 if (uart_circ_empty(xmit))
157 tx_enabled(port) = 0;
159 P2001_UART->w.IRQ_Status |= (1<<0);
162 /* uart interrupt receive routine */
163 static void p2001_uart_rx_chars(struct uart_port *port, struct pt_regs *regs)
165 struct tty_struct *tty = port->info->tty;
166 unsigned int status;
167 unsigned int rxddelta;
168 unsigned int rx;
169 unsigned int max_count = 256;
171 status = P2001_UART->r.IRQ_Status;
172 rxddelta = (P2001_UART->r.STATUS >> 6) & 0x3f;
173 while (rxddelta && max_count--) {
174 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
175 tty->flip.work.func((void *)tty);
176 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
177 printk(KERN_WARNING "TTY_DONT_FLIP set\n");
178 return;
182 rx = P2001_UART->r.RX[0];
184 *tty->flip.char_buf_ptr = rx & 0xff;
185 *tty->flip.flag_buf_ptr = TTY_NORMAL;
186 port->icount.rx++;
189 * Note that the error handling code is
190 * out of the main execution path
192 if (status & ((1<<7)|(1<<6)|(1<<9))) {
193 if (status & (1<<7)) { /* RxD_BRK */
194 port->icount.brk++;
195 if (uart_handle_break(port))
196 goto ignore_chars;
197 } else if (status & (1<<6)) /* RxD_FIFO_PAR_ERR */
198 port->icount.parity++;
199 if (status & (1<<9)) /* RxD_LOST */
200 port->icount.overrun++;
202 status &= port->read_status_mask;
204 if (status & (1<<7)) /* RxD_BRK */
205 *tty->flip.flag_buf_ptr = TTY_BREAK;
206 else if (status & (1<<6)) /* RxD_FIFO_PAR_ERR */
207 *tty->flip.flag_buf_ptr = TTY_PARITY;
211 if (uart_handle_sysrq_char(port, ch, regs))
212 goto ignore_chars;
214 if (rx && port->ignore_status_mask == 0) {
215 tty->flip.flag_buf_ptr++;
216 tty->flip.char_buf_ptr++;
217 tty->flip.count++;
219 if ((status & (1<<9)) && /* RxD_LOST */
220 tty->flip.count < TTY_FLIPBUF_SIZE) {
222 * Overrun is special, since it's reported
223 * immediately, and doesn't affect the current
224 * character
226 *tty->flip.char_buf_ptr++ = 0;
227 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
228 tty->flip.count++;
230 ignore_chars:
231 rxddelta = (P2001_UART->r.STATUS >> 6) & 0x3f;
233 tty_flip_buffer_push(tty);
235 P2001_UART->w.IRQ_Status |= (1<<3) | (1<<6) | (1<<7) | (1<<9);
238 /* uart interrupt routine */
239 static irqreturn_t p2001_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
241 struct uart_port *port = dev_id;
242 unsigned int status;
244 spin_lock(&port->lock);
246 status = P2001_UART->r.IRQ_Status;
247 // TXD_SEND | TXD_LAST_DATA
248 if (status & (1<<0)) // (1<<2)
249 p2001_uart_tx_chars(port);
250 // RXD_DATA | RxD_FIFO_PAR_ERR | RxD_BRK | RxD_LOST
251 if (status & ((1<<3) | (1<<6) | (1<<7) | (1<<9)))
252 p2001_uart_rx_chars(port, regs);
254 //status &= ~((1<<0) | (1<<2) | (1<<3));
255 //if (status & 0x3ff)
256 // printk(KERN_INFO "p2001_uart_interrupt: status=0x%8.8x\n", status);
258 P2001_UART->w.IRQ_Status &= ~0x3ff;
260 spin_unlock(&port->lock);
262 return IRQ_HANDLED;
267 /**************************************************************************
268 * UART Operations
269 **************************************************************************/
271 /* returns if the port transmitter is empty or not. */
272 static unsigned int p2001_uart_ops_tx_empty(struct uart_port *port)
274 unsigned int txddelta = P2001_UART->r.STATUS & 0x3f;
275 return (txddelta > 0) ? 0 : TIOCSER_TEMT;
278 /* sets a new value for the MCR UART register. */
279 static void p2001_uart_ops_set_mctrl(struct uart_port *port, unsigned int mctrl)
281 /* no modem control lines */
284 /* gets the current MCR UART register value. */
285 static unsigned int p2001_uart_ops_get_mctrl(struct uart_port *port)
287 /* no modem control lines */
288 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
291 /* stops the port from sending data. */
292 static void p2001_uart_ops_stop_tx(struct uart_port *port)
294 if (tx_enabled(port)) {
295 P2001_UART->w.IRQ_Status &= ~((1<<20) | (1<<22)); // TXD_SEND | TXD_LAST_DATA
296 tx_enabled(port) = 0;
300 /* starts the port sending data. */
301 static void p2001_uart_ops_start_tx(struct uart_port *port)
303 if (!tx_enabled(port)) {
304 P2001_UART->w.IRQ_Status |= (1<<20) | (1<<22); // TXD_SEND | TXD_LAST_DATA
305 tx_enabled(port) = 1;
307 p2001_uart_tx_chars(port);
310 /* tells the port to send the XOFF character to the host. */
311 #if 0
312 static void p2001_uart_ops_send_xchar(struct uart_port *port, char ch)
314 #warning "p2001_uart_ops_send_xchar is not implemented."
316 #endif
318 /* stops receiving data. */
319 static void p2001_uart_ops_stop_rx(struct uart_port *port)
321 if (rx_enabled(port)) {
322 P2001_UART->w.IRQ_Status &= ~(1<<23); // RXD_DATA
323 rx_enabled(port) = 0;
327 /* enables the modem status interrupts. */
328 static void p2001_uart_ops_enable_ms(struct uart_port *port)
330 /* empty */
333 /* sends the BREAK value over the port. */
334 static void p2001_uart_ops_break_ctl(struct uart_port *port, int ctl)
336 /* no break signal */
339 /* called once each time the open call happens */
340 static int p2001_uart_ops_startup(struct uart_port *port)
342 int ret;
344 tx_enabled(port) = 1;
345 rx_enabled(port) = 1;
347 ret = request_irq(port->irq, p2001_uart_interrupt, 0, p2001_uart_name, port);
349 P2001_UART->w.Clear = 0;
350 // TXD_SEND | TXD_LAST_DATA
351 P2001_UART->w.IRQ_Status |= (1<<20) | (1<<22);
352 // RXD_DATA | RxD_FIFO_PAR_ERR | RxD_BRK | RxD_LOST
353 P2001_UART->w.IRQ_Status |= (1<<23) | (1<<26) | (1<<27) | (1<<29);
355 return ret;
358 /* called when the port is closed */
359 static void p2001_uart_ops_shutdown(struct uart_port *port)
361 free_irq(port->irq, port);
364 /* called whenever the port line settings need to be modified */
365 static void p2001_uart_ops_set_termios(struct uart_port *port, struct termios *new, struct termios *old)
367 unsigned int config;
368 unsigned long flags;
369 unsigned int prod, quot;
372 * Ask the core to calculate the divisor for us.
374 baud = uart_get_baud_rate(port, new, old, 0, port->uartclk); // min:0/max:port->uartclk
375 prod = 3;
376 quot = (port->uartclk * prod)/baud;
378 /* interrupt level */
379 config = (12 << 11) | (12 << 17); /* RXDHIGHWATER = 12, TXDLOWWATER = 12 */
381 /* data bits */
382 switch (new->c_cflag & CSIZE) {
383 case CS5:
384 config |= (5 << 5); /* WORDLENGTH = 5 */
385 break;
386 case CS6:
387 config |= (6 << 5); /* WORDLENGTH = 6 */
388 break;
389 case CS7:
390 config |= (7 << 5); /* WORDLENGTH = 7 */
391 break;
392 default: /* CS8 */
393 config |= (8 << 5); /* WORDLENGTH = 8 */
394 break;
397 /* parity */
398 if (new->c_cflag & PARENB) {
399 if (!(new->c_cflag & PARODD))
400 config |= (1 << 2); /* PARITYMODE = 1 (Even Parity) */
401 else
402 config |= (2 << 2); /* PARITYMODE = 2 (Odd Parity) */
405 /* stop bits */
406 if (new->c_cflag & CSTOPB)
407 config |= (1 << 0); /* STOPBITAW = 1 (1 Stopbit) */
409 /* hardware flow control */
410 if (new->c_cflag & CRTSCTS) {
411 config |= (1 << 10); /* USECTS = 1 */
412 P2001_GPIO->PIN_MUX |= (1<<5);
413 } else {
414 P2001_GPIO->PIN_MUX &= ~(1<<5);
417 spin_lock_irqsave(&port->lock, flags);
420 * Update the per-port timeout.
422 uart_update_timeout(port, new->c_cflag, baud);
424 port->read_status_mask = (1<<9); /* RXD_DATA_LOST */
425 if (new->c_iflag & INPCK)
426 port->read_status_mask |= (1<<6); /* RxD_FIFO_PAR_ERR */
427 if (new->c_iflag & (BRKINT | PARMRK))
428 port->read_status_mask |= (1<<7); /* RxD_BRK */
431 * Characters to ignore
433 port->ignore_status_mask = 0;
434 if (new->c_iflag & IGNPAR)
435 port->ignore_status_mask |= (1<<6); /* RxD_FIFO_PAR_ERR */
436 if (new->c_iflag & IGNBRK) {
437 port->ignore_status_mask |= (1<<7); /* RxD_BRK */
439 * If we're ignoring parity and break indicators,
440 * ignore overruns too (for real raw support).
442 if (new->c_iflag & IGNPAR)
443 port->ignore_status_mask |= (1<<9); /* RxD_LOST */
447 * Ignore all characters if CREAD is not set.
449 if ((new->c_cflag & CREAD) == 0)
450 port->ignore_status_mask |= (1<<3); /* RXD_DATA */
452 /* Set baud rate */
453 P2001_UART->w.Baudrate = (quot<<16)+prod;
454 P2001_UART->w.Config = config;
456 spin_unlock_irqrestore(&port->lock, flags);
459 /* power management: power the hardware down */
460 #ifdef CONFIG_PM
461 static void p2001_uart_ops_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
463 #warning "p2001_uart_ops_pm is not implemented."
465 #endif
467 /* power management: power the hardware up */
468 #ifdef CONFIG_PM
469 static int p2001_uart_ops_set_wake(struct uart_port *port, unsigned int state)
471 #warning "p2001_uart_ops_set_wake is not implemented."
473 #endif
476 * Return a string describing the port type
478 static const char *p2001_uart_ops_type(struct uart_port *port)
480 return port->type == PORT_P2001 ? "P2001" : NULL;
484 * Release IO and memory resources used by
485 * the port. This includes iounmap if necessary.
487 static void p2001_uart_ops_release_port(struct uart_port *port)
489 release_mem_region(port->mapbase, 0x30);
493 * Request IO and memory resources used by the
494 * port. This includes iomapping the port if
495 * necessary.
497 static int p2001_uart_ops_request_port(struct uart_port *port)
499 return request_mem_region(port->mapbase, 0x30, p2001_uart_name)
500 != NULL ? 0 : -EBUSY;
504 * Configure/autoconfigure the port.
506 static void p2001_uart_ops_config_port(struct uart_port *port, int flags)
508 if (flags & UART_CONFIG_TYPE && p2001_uart_ops_request_port(port) == 0)
509 port->type = PORT_P2001;
513 * Verify the new serial_struct (for TIOCSSERIAL).
515 static int p2001_uart_ops_verify_port(struct uart_port *port, struct serial_struct *ser)
517 int ret = 0;
518 if (ser->type != PORT_UNKNOWN && ser->type != PORT_P2001)
519 ret = -EINVAL;
520 if (ser->irq != NO_IRQ)
521 ret = -EINVAL;
522 return ret;
525 /* device specific ioctl calls */
526 #if 0
527 static int p2001_uart_ops_ioctl(struct uart_port *port, unsigned int, unsigned long)
529 #warning "p2001_uart_ops_ioctl is not implemented."
531 #endif
534 static struct uart_ops p2001_uart_ops = {
535 .tx_empty = p2001_uart_ops_tx_empty, /* returns if the port transmitter is empty or not. */
536 .set_mctrl = p2001_uart_ops_set_mctrl, /* sets a new value for the MCR UART register. */
537 .get_mctrl = p2001_uart_ops_get_mctrl, /* gets the current MCR UART register value. */
538 .stop_tx = p2001_uart_ops_stop_tx, /* stops the port from sending data. */
539 .start_tx = p2001_uart_ops_start_tx, /* starts the port sending data. */
540 // .send_xchar = p2001_uart_ops_send_xchar, /* tells the port to send the XOFF character to the host. */
541 .stop_rx = p2001_uart_ops_stop_rx, /* stops receiving data. */
542 .enable_ms = p2001_uart_ops_enable_ms, /* enables the modem status interrupts. */
543 .break_ctl = p2001_uart_ops_break_ctl, /* sends the BREAK value over the port. */
544 .startup = p2001_uart_ops_startup, /* called once each time the open call happens */
545 .shutdown = p2001_uart_ops_shutdown, /* called when the port is closed */
546 .set_termios = p2001_uart_ops_set_termios, /* called whenever the port line settings need to be modified */
547 #ifdef CONFIG_PM
548 .pm = p2001_uart_ops_pm, /* power management: power the hardware down */
549 .set_wake = p2001_uart_ops_set_wake, /* power management: power the hardware up */
550 #endif
551 .type = p2001_uart_ops_type, /* Return a string describing the port type */
552 .release_port = p2001_uart_ops_release_port, /* Release the region(s) being used by 'port' */
553 .request_port = p2001_uart_ops_request_port, /* Request the region(s) being used by 'port' */
554 .config_port = p2001_uart_ops_config_port, /* Configure/autoconfigure the port. */
555 .verify_port = p2001_uart_ops_verify_port, /* Verify the new serial_struct (for TIOCSSERIAL). */
556 // .ioctl = p2001_uart_ops_ioctl, /* device specific ioctl calls */
561 /**************************************************************************
562 * CPU frequency scaling
563 **************************************************************************/
565 #ifdef CONFIG_CPU_FREQ
568 * Starts receiving data.
570 static void p2001_uart_ops_start_rx(struct uart_port *port)
572 if (!rx_enabled(port)) {
573 P2001_UART->w.IRQ_Status |= (1<<23); // RXD_DATA
574 rx_enabled(port) = 1;
579 * Here we define a transistion notifier so that we can update all of our
580 * ports' baud rate when the peripheral clock changes.
582 static int p2001_uart_notifier(struct notifier_block *self, unsigned long phase, void *data)
584 struct cpufreq_freqs *cf = data;
585 unsigned int prod, quot;
586 struct uart_port *port = &p2001_uart_port;
588 if (phase == CPUFREQ_PRECHANGE) {
589 /* Stop transceiver */
590 p2001_uart_ops_stop_rx(&p2001_uart_port);
591 p2001_uart_ops_stop_tx(&p2001_uart_port);
593 while (!p2001_uart_ops_tx_empty(port))
594 barrier();
597 if ((phase == CPUFREQ_POSTCHANGE) ||
598 (phase == CPUFREQ_RESUMECHANGE)){
599 /* Set new baud rate */
600 port->uartclk = 1000 * cf->new / 8; // in MHz
601 prod = 3;
602 quot = (port->uartclk * prod)/baud;
603 P2001_UART->w.Baudrate = (quot<<16)+prod;
605 /* Start transceiver */
606 p2001_uart_ops_start_rx(&p2001_uart_port);
607 p2001_uart_ops_start_tx(&p2001_uart_port);
610 return NOTIFY_OK;
613 static struct notifier_block p2001_uart_nb = { &p2001_uart_notifier, NULL, 0 };
615 #endif /* CONFIG_CPU_FREQ */
619 /**************************************************************************
620 * Console
621 **************************************************************************/
623 #ifdef CONFIG_SERIAL_P2001_UART_CONSOLE
625 /* the function used to print kernel messages */
626 static void p2001_console_write(struct console *co, const char *s, unsigned int count)
628 int i;
630 for (i = 0; i < count; i++) {
631 while ((P2001_UART->r.STATUS & 0x3f) > TX_MIN_BUF)
632 barrier();
633 P2001_UART->w.TX[0] = s[i];
634 if (s[i] == '\n') {
635 while ((P2001_UART->r.STATUS & 0x3f) > TX_MIN_BUF)
636 barrier();
637 P2001_UART->w.TX[0] = '\r';
642 /* the function is called when the console= command-line argument matches the name for this console structure. */
643 static int __init p2001_console_setup(struct console *co, char *options)
645 struct uart_port *port = &p2001_uart_port;
646 int parity = 'n';
647 int bits = 8;
648 int flow = 'n';
650 baud = DEFAULT_BAUD;
651 if (options)
652 uart_parse_options(options, &baud, &parity, &bits, &flow);
654 return uart_set_options(port, co, baud, parity, bits, flow);
658 static struct console p2001_console = {
659 .name = "ttyS", /* the name of the console device is used to parse the console= command line option. */
660 .write = p2001_console_write, /* the function used to print kernel messages */
661 // .read = p2001_console_read, /* ??? */
662 .device = uart_console_device, /* a function that returns the device number for the underlying tty device that is currently acting as a console */
663 // .unblank = p2001_console_unblank, /* the function, if defined, is used to unblank the screen. */
664 .setup = p2001_console_setup, /* the function is called when the console= command-line argument matches the name for this console structure. */
665 .flags = CON_PRINTBUFFER, /* various console flags */
666 .index = -1, /* the number of the device acting as a console in an array of devices. */
667 // .cflag = 0,
668 .data = &p2001_uart_driver,
671 static int __init p2001_console_init(void)
673 register_console(&p2001_console);
674 return 0;
676 console_initcall(p2001_console_init);
677 #endif
681 /**************************************************************************
682 * Module functions
683 **************************************************************************/
685 static int __init p2001_uart_module_init(void)
687 int ret;
689 printk(version);
691 ret = uart_register_driver(&p2001_uart_driver);
692 if (ret != 0) return ret;
694 ret = uart_add_one_port(&p2001_uart_driver, &p2001_uart_port);
695 if (ret != 0) return ret;
697 #ifdef CONFIG_CPU_FREQ
698 ret = cpufreq_register_notifier(&p2001_uart_nb, CPUFREQ_TRANSITION_NOTIFIER);
699 printk("p2001_uart: CPU frequency notifier registered\n");
700 #endif
702 return ret;
705 static void __exit p2001_uart_module_exit(void)
707 #ifdef CONFIG_CPU_FREQ
708 cpufreq_unregister_notifier(&p2001_uart_nb, CPUFREQ_TRANSITION_NOTIFIER);
709 printk("p2001_uart: CPU frequency notifier unregistered\n");
710 #endif
711 uart_remove_one_port(&p2001_uart_driver, &p2001_uart_port);
712 uart_unregister_driver(&p2001_uart_driver);
715 module_init(p2001_uart_module_init);
716 module_exit(p2001_uart_module_exit);
718 MODULE_AUTHOR("Tobias Lorenz");
719 MODULE_DESCRIPTION("P2001 uart driver");
720 MODULE_LICENSE("GPL");