More meth updates.
[linux-2.6/linux-mips.git] / drivers / serial / amba.c
blob34ae5a57b1bf7ce305f425e1efbd3829efe4b095
1 /*
2 * linux/drivers/char/amba.c
4 * Driver for AMBA serial ports
6 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
8 * Copyright 1999 ARM Limited
9 * Copyright (C) 2000 Deep Blue Solutions Ltd.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $
27 * This is a generic driver for ARM AMBA-type serial ports. They
28 * have a lot of 16550-like features, but are not register compatible.
29 * Note that although they do have CTS, DCD and DSR inputs, they do
30 * not have an RI input, nor do they have DTR or RTS outputs. If
31 * required, these have to be supplied via some other means (eg, GPIO)
32 * and hooked into this driver.
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/tty.h>
37 #include <linux/ioport.h>
38 #include <linux/init.h>
39 #include <linux/serial.h>
40 #include <linux/console.h>
41 #include <linux/sysrq.h>
43 #include <asm/io.h>
44 #include <asm/irq.h>
46 #if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
47 #define SUPPORT_SYSRQ
48 #endif
50 #include <linux/serial_core.h>
52 #include <asm/hardware/serial_amba.h>
54 #define UART_NR 2
56 #define SERIAL_AMBA_MAJOR 204
57 #define SERIAL_AMBA_MINOR 16
58 #define SERIAL_AMBA_NR UART_NR
60 #define AMBA_ISR_PASS_LIMIT 256
63 * Access macros for the AMBA UARTs
65 #define UART_GET_INT_STATUS(p) readb((p)->membase + AMBA_UARTIIR)
66 #define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR)
67 #define UART_GET_FR(p) readb((p)->membase + AMBA_UARTFR)
68 #define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR)
69 #define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR)
70 #define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR)
71 #define UART_GET_CR(p) readb((p)->membase + AMBA_UARTCR)
72 #define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR)
73 #define UART_GET_LCRL(p) readb((p)->membase + AMBA_UARTLCR_L)
74 #define UART_PUT_LCRL(p,c) writel((c), (p)->membase + AMBA_UARTLCR_L)
75 #define UART_GET_LCRM(p) readb((p)->membase + AMBA_UARTLCR_M)
76 #define UART_PUT_LCRM(p,c) writel((c), (p)->membase + AMBA_UARTLCR_M)
77 #define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H)
78 #define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H)
79 #define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
80 #define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
81 #define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
83 #define UART_DUMMY_RSR_RX 256
84 #define UART_PORT_SIZE 64
87 * On the Integrator platform, the port RTS and DTR are provided by
88 * bits in the following SC_CTRLS register bits:
89 * RTS DTR
90 * UART0 7 6
91 * UART1 5 4
93 #define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
94 #define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
97 * We wrap our port structure around the generic uart_port.
99 struct uart_amba_port {
100 struct uart_port port;
101 unsigned int dtr_mask;
102 unsigned int rts_mask;
103 unsigned int old_status;
106 static void ambauart_stop_tx(struct uart_port *port, unsigned int tty_stop)
108 unsigned int cr;
110 cr = UART_GET_CR(port);
111 cr &= ~AMBA_UARTCR_TIE;
112 UART_PUT_CR(port, cr);
115 static void ambauart_start_tx(struct uart_port *port, unsigned int tty_start)
117 unsigned int cr;
119 cr = UART_GET_CR(port);
120 cr |= AMBA_UARTCR_TIE;
121 UART_PUT_CR(port, cr);
124 static void ambauart_stop_rx(struct uart_port *port)
126 unsigned int cr;
128 cr = UART_GET_CR(port);
129 cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
130 UART_PUT_CR(port, cr);
133 static void ambauart_enable_ms(struct uart_port *port)
135 unsigned int cr;
137 cr = UART_GET_CR(port);
138 cr |= AMBA_UARTCR_MSIE;
139 UART_PUT_CR(port, cr);
142 static void
143 #ifdef SUPPORT_SYSRQ
144 ambauart_rx_chars(struct uart_port *port, struct pt_regs *regs)
145 #else
146 ambauart_rx_chars(struct uart_port *port)
147 #endif
149 struct tty_struct *tty = port->info->tty;
150 unsigned int status, ch, rsr, max_count = 256;
152 status = UART_GET_FR(port);
153 while (UART_RX_DATA(status) && max_count--) {
154 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
155 tty->flip.work.func((void *)tty);
156 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
157 printk(KERN_WARNING "TTY_DONT_FLIP set\n");
158 return;
162 ch = UART_GET_CHAR(port);
164 *tty->flip.char_buf_ptr = ch;
165 *tty->flip.flag_buf_ptr = TTY_NORMAL;
166 port->icount.rx++;
169 * Note that the error handling code is
170 * out of the main execution path
172 rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
173 if (rsr & AMBA_UARTRSR_ANY) {
174 if (rsr & AMBA_UARTRSR_BE) {
175 rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
176 port->icount.brk++;
177 if (uart_handle_break(port))
178 goto ignore_char;
179 } else if (rsr & AMBA_UARTRSR_PE)
180 port->icount.parity++;
181 else if (rsr & AMBA_UARTRSR_FE)
182 port->icount.frame++;
183 if (rsr & AMBA_UARTRSR_OE)
184 port->icount.overrun++;
186 rsr &= port->read_status_mask;
188 if (rsr & AMBA_UARTRSR_BE)
189 *tty->flip.flag_buf_ptr = TTY_BREAK;
190 else if (rsr & AMBA_UARTRSR_PE)
191 *tty->flip.flag_buf_ptr = TTY_PARITY;
192 else if (rsr & AMBA_UARTRSR_FE)
193 *tty->flip.flag_buf_ptr = TTY_FRAME;
196 if (uart_handle_sysrq_char(port, ch, regs))
197 goto ignore_char;
199 if ((rsr & port->ignore_status_mask) == 0) {
200 tty->flip.flag_buf_ptr++;
201 tty->flip.char_buf_ptr++;
202 tty->flip.count++;
204 if ((rsr & AMBA_UARTRSR_OE) &&
205 tty->flip.count < TTY_FLIPBUF_SIZE) {
207 * Overrun is special, since it's reported
208 * immediately, and doesn't affect the current
209 * character
211 *tty->flip.char_buf_ptr++ = 0;
212 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
213 tty->flip.count++;
215 ignore_char:
216 status = UART_GET_FR(port);
218 tty_flip_buffer_push(tty);
219 return;
222 static void ambauart_tx_chars(struct uart_port *port)
224 struct circ_buf *xmit = &port->info->xmit;
225 int count;
227 if (port->x_char) {
228 UART_PUT_CHAR(port, port->x_char);
229 port->icount.tx++;
230 port->x_char = 0;
231 return;
233 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
234 ambauart_stop_tx(port, 0);
235 return;
238 count = port->fifosize >> 1;
239 do {
240 UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
241 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
242 port->icount.tx++;
243 if (uart_circ_empty(xmit))
244 break;
245 } while (--count > 0);
247 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
248 uart_write_wakeup(port);
250 if (uart_circ_empty(xmit))
251 ambauart_stop_tx(port, 0);
254 static void ambauart_modem_status(struct uart_port *port)
256 struct uart_amba_port *uap = (struct uart_amba_port *)port;
257 unsigned int status, delta;
259 UART_PUT_ICR(&uap->port, 0);
261 status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY;
263 delta = status ^ uap->old_status;
264 uap->old_status = status;
266 if (!delta)
267 return;
269 if (delta & AMBA_UARTFR_DCD)
270 uart_handle_dcd_change(&uap->port, status & AMBA_UARTFR_DCD);
272 if (delta & AMBA_UARTFR_DSR)
273 uap->port.icount.dsr++;
275 if (delta & AMBA_UARTFR_CTS)
276 uart_handle_cts_change(&uap->port, status & AMBA_UARTFR_CTS);
278 wake_up_interruptible(&uap->port.info->delta_msr_wait);
281 static irqreturn_t ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
283 struct uart_port *port = dev_id;
284 unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
286 status = UART_GET_INT_STATUS(port);
287 do {
288 if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
289 #ifdef SUPPORT_SYSRQ
290 ambauart_rx_chars(port, regs);
291 #else
292 ambauart_rx_chars(port);
293 #endif
294 if (status & AMBA_UARTIIR_MIS)
295 ambauart_modem_status(port);
296 if (status & AMBA_UARTIIR_TIS)
297 ambauart_tx_chars(port);
299 if (pass_counter-- == 0)
300 break;
302 status = UART_GET_INT_STATUS(port);
303 } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
304 AMBA_UARTIIR_TIS));
306 return IRQ_HANDLED;
309 static unsigned int ambauart_tx_empty(struct uart_port *port)
311 return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT;
314 static unsigned int ambauart_get_mctrl(struct uart_port *port)
316 unsigned int result = 0;
317 unsigned int status;
319 status = UART_GET_FR(port);
320 if (status & AMBA_UARTFR_DCD)
321 result |= TIOCM_CAR;
322 if (status & AMBA_UARTFR_DSR)
323 result |= TIOCM_DSR;
324 if (status & AMBA_UARTFR_CTS)
325 result |= TIOCM_CTS;
327 return result;
330 static void ambauart_set_mctrl(struct uart_port *port, unsigned int mctrl)
332 struct uart_amba_port *uap = (struct uart_amba_port *)port;
333 unsigned int ctrls = 0, ctrlc = 0;
335 if (mctrl & TIOCM_RTS)
336 ctrlc |= uap->rts_mask;
337 else
338 ctrls |= uap->rts_mask;
340 if (mctrl & TIOCM_DTR)
341 ctrlc |= uap->dtr_mask;
342 else
343 ctrls |= uap->dtr_mask;
345 __raw_writel(ctrls, SC_CTRLS);
346 __raw_writel(ctrlc, SC_CTRLC);
349 static void ambauart_break_ctl(struct uart_port *port, int break_state)
351 unsigned long flags;
352 unsigned int lcr_h;
354 spin_lock_irqsave(&port->lock, flags);
355 lcr_h = UART_GET_LCRH(port);
356 if (break_state == -1)
357 lcr_h |= AMBA_UARTLCR_H_BRK;
358 else
359 lcr_h &= ~AMBA_UARTLCR_H_BRK;
360 UART_PUT_LCRH(port, lcr_h);
361 spin_unlock_irqrestore(&port->lock, flags);
364 static int ambauart_startup(struct uart_port *port)
366 struct uart_amba_port *uap = (struct uart_amba_port *)port;
367 int retval;
370 * Allocate the IRQ
372 retval = request_irq(port->irq, ambauart_int, 0, "amba", port);
373 if (retval)
374 return retval;
377 * initialise the old status of the modem signals
379 uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
382 * Finally, enable interrupts
384 UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE |
385 AMBA_UARTCR_RTIE);
387 return 0;
390 static void ambauart_shutdown(struct uart_port *port)
393 * Free the interrupt
395 free_irq(port->irq, port);
398 * disable all interrupts, disable the port
400 UART_PUT_CR(port, 0);
402 /* disable break condition and fifos */
403 UART_PUT_LCRH(port, UART_GET_LCRH(port) &
404 ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
407 static void
408 ambauart_set_termios(struct uart_port *port, struct termios *termios,
409 struct termios *old)
411 unsigned int lcr_h, old_cr;
412 unsigned long flags;
413 unsigned int baud, quot;
416 * Ask the core to calculate the divisor for us.
418 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
419 quot = uart_get_divisor(port, baud);
421 switch (termios->c_cflag & CSIZE) {
422 case CS5:
423 lcr_h = AMBA_UARTLCR_H_WLEN_5;
424 break;
425 case CS6:
426 lcr_h = AMBA_UARTLCR_H_WLEN_6;
427 break;
428 case CS7:
429 lcr_h = AMBA_UARTLCR_H_WLEN_7;
430 break;
431 default: // CS8
432 lcr_h = AMBA_UARTLCR_H_WLEN_8;
433 break;
435 if (termios->c_cflag & CSTOPB)
436 lcr_h |= AMBA_UARTLCR_H_STP2;
437 if (termios->c_cflag & PARENB) {
438 lcr_h |= AMBA_UARTLCR_H_PEN;
439 if (!(termios->c_cflag & PARODD))
440 lcr_h |= AMBA_UARTLCR_H_EPS;
442 if (port->fifosize > 1)
443 lcr_h |= AMBA_UARTLCR_H_FEN;
445 spin_lock_irqsave(&port->lock, flags);
448 * Update the per-port timeout.
450 uart_update_timeout(port, termios->c_cflag, baud);
452 port->read_status_mask = AMBA_UARTRSR_OE;
453 if (termios->c_iflag & INPCK)
454 port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
455 if (termios->c_iflag & (BRKINT | PARMRK))
456 port->read_status_mask |= AMBA_UARTRSR_BE;
459 * Characters to ignore
461 port->ignore_status_mask = 0;
462 if (termios->c_iflag & IGNPAR)
463 port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
464 if (termios->c_iflag & IGNBRK) {
465 port->ignore_status_mask |= AMBA_UARTRSR_BE;
467 * If we're ignoring parity and break indicators,
468 * ignore overruns too (for real raw support).
470 if (termios->c_iflag & IGNPAR)
471 port->ignore_status_mask |= AMBA_UARTRSR_OE;
475 * Ignore all characters if CREAD is not set.
477 if ((termios->c_cflag & CREAD) == 0)
478 port->ignore_status_mask |= UART_DUMMY_RSR_RX;
480 /* first, disable everything */
481 old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE;
483 if (UART_ENABLE_MS(port, termios->c_cflag))
484 old_cr |= AMBA_UARTCR_MSIE;
486 UART_PUT_CR(port, 0);
488 /* Set baud rate */
489 quot -= 1;
490 UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
491 UART_PUT_LCRL(port, (quot & 0xff));
494 * ----------v----------v----------v----------v-----
495 * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
496 * ----------^----------^----------^----------^-----
498 UART_PUT_LCRH(port, lcr_h);
499 UART_PUT_CR(port, old_cr);
501 spin_unlock_irqrestore(&port->lock, flags);
504 static const char *ambauart_type(struct uart_port *port)
506 return port->type == PORT_AMBA ? "AMBA" : NULL;
510 * Release the memory region(s) being used by 'port'
512 static void ambauart_release_port(struct uart_port *port)
514 release_mem_region(port->mapbase, UART_PORT_SIZE);
518 * Request the memory region(s) being used by 'port'
520 static int ambauart_request_port(struct uart_port *port)
522 return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba")
523 != NULL ? 0 : -EBUSY;
527 * Configure/autoconfigure the port.
529 static void ambauart_config_port(struct uart_port *port, int flags)
531 if (flags & UART_CONFIG_TYPE) {
532 port->type = PORT_AMBA;
533 ambauart_request_port(port);
538 * verify the new serial_struct (for TIOCSSERIAL).
540 static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser)
542 int ret = 0;
543 if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
544 ret = -EINVAL;
545 if (ser->irq < 0 || ser->irq >= NR_IRQS)
546 ret = -EINVAL;
547 if (ser->baud_base < 9600)
548 ret = -EINVAL;
549 return ret;
552 static struct uart_ops amba_pops = {
553 .tx_empty = ambauart_tx_empty,
554 .set_mctrl = ambauart_set_mctrl,
555 .get_mctrl = ambauart_get_mctrl,
556 .stop_tx = ambauart_stop_tx,
557 .start_tx = ambauart_start_tx,
558 .stop_rx = ambauart_stop_rx,
559 .enable_ms = ambauart_enable_ms,
560 .break_ctl = ambauart_break_ctl,
561 .startup = ambauart_startup,
562 .shutdown = ambauart_shutdown,
563 .set_termios = ambauart_set_termios,
564 .type = ambauart_type,
565 .release_port = ambauart_release_port,
566 .request_port = ambauart_request_port,
567 .config_port = ambauart_config_port,
568 .verify_port = ambauart_verify_port,
571 static struct uart_amba_port amba_ports[UART_NR] = {
573 .port = {
574 .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
575 .mapbase = INTEGRATOR_UART0_BASE,
576 .iotype = SERIAL_IO_MEM,
577 .irq = IRQ_UARTINT0,
578 .uartclk = 14745600,
579 .fifosize = 16,
580 .ops = &amba_pops,
581 .flags = ASYNC_BOOT_AUTOCONF,
582 .line = 0,
584 .dtr_mask = 1 << 5,
585 .rts_mask = 1 << 4,
588 .port = {
589 .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
590 .mapbase = INTEGRATOR_UART1_BASE,
591 .iotype = SERIAL_IO_MEM,
592 .irq = IRQ_UARTINT1,
593 .uartclk = 14745600,
594 .fifosize = 16,
595 .ops = &amba_pops,
596 .flags = ASYNC_BOOT_AUTOCONF,
597 .line = 1,
599 .dtr_mask = 1 << 7,
600 .rts_mask = 1 << 6,
604 #ifdef CONFIG_SERIAL_AMBA_CONSOLE
606 static void
607 ambauart_console_write(struct console *co, const char *s, unsigned int count)
609 struct uart_port *port = &amba_ports[co->index].port;
610 unsigned int status, old_cr;
611 int i;
614 * First save the CR then disable the interrupts
616 old_cr = UART_GET_CR(port);
617 UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
620 * Now, do each character
622 for (i = 0; i < count; i++) {
623 do {
624 status = UART_GET_FR(port);
625 } while (!UART_TX_READY(status));
626 UART_PUT_CHAR(port, s[i]);
627 if (s[i] == '\n') {
628 do {
629 status = UART_GET_FR(port);
630 } while (!UART_TX_READY(status));
631 UART_PUT_CHAR(port, '\r');
636 * Finally, wait for transmitter to become empty
637 * and restore the TCR
639 do {
640 status = UART_GET_FR(port);
641 } while (status & AMBA_UARTFR_BUSY);
642 UART_PUT_CR(port, old_cr);
645 static void __init
646 ambauart_console_get_options(struct uart_port *port, int *baud,
647 int *parity, int *bits)
649 if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) {
650 unsigned int lcr_h, quot;
651 lcr_h = UART_GET_LCRH(port);
653 *parity = 'n';
654 if (lcr_h & AMBA_UARTLCR_H_PEN) {
655 if (lcr_h & AMBA_UARTLCR_H_EPS)
656 *parity = 'e';
657 else
658 *parity = 'o';
661 if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7)
662 *bits = 7;
663 else
664 *bits = 8;
666 quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
667 *baud = port->uartclk / (16 * (quot + 1));
671 static int __init ambauart_console_setup(struct console *co, char *options)
673 struct uart_port *port;
674 int baud = 38400;
675 int bits = 8;
676 int parity = 'n';
677 int flow = 'n';
680 * Check whether an invalid uart number has been specified, and
681 * if so, search for the first available port that does have
682 * console support.
684 if (co->index >= UART_NR)
685 co->index = 0;
686 port = &amba_ports[co->index].port;
688 if (options)
689 uart_parse_options(options, &baud, &parity, &bits, &flow);
690 else
691 ambauart_console_get_options(port, &baud, &parity, &bits);
693 return uart_set_options(port, co, baud, parity, bits, flow);
696 extern struct uart_driver amba_reg;
697 static struct console amba_console = {
698 .name = "ttyAM",
699 .write = ambauart_console_write,
700 .device = uart_console_device,
701 .setup = ambauart_console_setup,
702 .flags = CON_PRINTBUFFER,
703 .index = -1,
704 .data = &amba_reg,
707 static int __init ambauart_console_init(void)
709 register_console(&amba_console);
710 return 0;
712 console_initcall(ambauart_console_init);
714 #define AMBA_CONSOLE &amba_console
715 #else
716 #define AMBA_CONSOLE NULL
717 #endif
719 static struct uart_driver amba_reg = {
720 .owner = THIS_MODULE,
721 .driver_name = "ttyAM",
722 .dev_name = "ttyAM",
723 .major = SERIAL_AMBA_MAJOR,
724 .minor = SERIAL_AMBA_MINOR,
725 .nr = UART_NR,
726 .cons = AMBA_CONSOLE,
729 static int __init ambauart_init(void)
731 int ret;
733 printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n");
735 ret = uart_register_driver(&amba_reg);
736 if (ret == 0) {
737 int i;
739 for (i = 0; i < UART_NR; i++)
740 uart_add_one_port(&amba_reg, &amba_ports[i].port);
742 return ret;
745 static void __exit ambauart_exit(void)
747 int i;
749 for (i = 0; i < UART_NR; i++)
750 uart_remove_one_port(&amba_reg, &amba_ports[i].port);
752 uart_unregister_driver(&amba_reg);
755 module_init(ambauart_init);
756 module_exit(ambauart_exit);
758 MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
759 MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $");
760 MODULE_LICENSE("GPL");