IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
[safe/jmp/linux-2.6] / drivers / serial / amba-pl010.c
1 /*
2  *  linux/drivers/char/amba.c
3  *
4  *  Driver for AMBA serial ports
5  *
6  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
7  *
8  *  Copyright 1999 ARM Limited
9  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
10  *
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.
15  *
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.
20  *
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
24  *
25  *  $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $
26  *
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.
33  */
34
35 #if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
36 #define SUPPORT_SYSRQ
37 #endif
38
39 #include <linux/module.h>
40 #include <linux/ioport.h>
41 #include <linux/init.h>
42 #include <linux/console.h>
43 #include <linux/sysrq.h>
44 #include <linux/device.h>
45 #include <linux/tty.h>
46 #include <linux/tty_flip.h>
47 #include <linux/serial_core.h>
48 #include <linux/serial.h>
49 #include <linux/amba/bus.h>
50 #include <linux/amba/serial.h>
51
52 #include <asm/io.h>
53
54 #define UART_NR         8
55
56 #define SERIAL_AMBA_MAJOR       204
57 #define SERIAL_AMBA_MINOR       16
58 #define SERIAL_AMBA_NR          UART_NR
59
60 #define AMBA_ISR_PASS_LIMIT     256
61
62 #define UART_RX_DATA(s)         (((s) & UART01x_FR_RXFE) == 0)
63 #define UART_TX_READY(s)        (((s) & UART01x_FR_TXFF) == 0)
64
65 #define UART_DUMMY_RSR_RX       256
66 #define UART_PORT_SIZE          64
67
68 /*
69  * We wrap our port structure around the generic uart_port.
70  */
71 struct uart_amba_port {
72         struct uart_port        port;
73         struct amba_device      *dev;
74         struct amba_pl010_data  *data;
75         unsigned int            old_status;
76 };
77
78 static void pl010_stop_tx(struct uart_port *port)
79 {
80         unsigned int cr;
81
82         cr = readb(port->membase + UART010_CR);
83         cr &= ~UART010_CR_TIE;
84         writel(cr, port->membase + UART010_CR);
85 }
86
87 static void pl010_start_tx(struct uart_port *port)
88 {
89         unsigned int cr;
90
91         cr = readb(port->membase + UART010_CR);
92         cr |= UART010_CR_TIE;
93         writel(cr, port->membase + UART010_CR);
94 }
95
96 static void pl010_stop_rx(struct uart_port *port)
97 {
98         unsigned int cr;
99
100         cr = readb(port->membase + UART010_CR);
101         cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
102         writel(cr, port->membase + UART010_CR);
103 }
104
105 static void pl010_enable_ms(struct uart_port *port)
106 {
107         unsigned int cr;
108
109         cr = readb(port->membase + UART010_CR);
110         cr |= UART010_CR_MSIE;
111         writel(cr, port->membase + UART010_CR);
112 }
113
114 static void pl010_rx_chars(struct uart_port *port)
115 {
116         struct tty_struct *tty = port->info->tty;
117         unsigned int status, ch, flag, rsr, max_count = 256;
118
119         status = readb(port->membase + UART01x_FR);
120         while (UART_RX_DATA(status) && max_count--) {
121                 ch = readb(port->membase + UART01x_DR);
122                 flag = TTY_NORMAL;
123
124                 port->icount.rx++;
125
126                 /*
127                  * Note that the error handling code is
128                  * out of the main execution path
129                  */
130                 rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
131                 if (unlikely(rsr & UART01x_RSR_ANY)) {
132                         if (rsr & UART01x_RSR_BE) {
133                                 rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
134                                 port->icount.brk++;
135                                 if (uart_handle_break(port))
136                                         goto ignore_char;
137                         } else if (rsr & UART01x_RSR_PE)
138                                 port->icount.parity++;
139                         else if (rsr & UART01x_RSR_FE)
140                                 port->icount.frame++;
141                         if (rsr & UART01x_RSR_OE)
142                                 port->icount.overrun++;
143
144                         rsr &= port->read_status_mask;
145
146                         if (rsr & UART01x_RSR_BE)
147                                 flag = TTY_BREAK;
148                         else if (rsr & UART01x_RSR_PE)
149                                 flag = TTY_PARITY;
150                         else if (rsr & UART01x_RSR_FE)
151                                 flag = TTY_FRAME;
152                 }
153
154                 if (uart_handle_sysrq_char(port, ch))
155                         goto ignore_char;
156
157                 uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
158
159         ignore_char:
160                 status = readb(port->membase + UART01x_FR);
161         }
162         tty_flip_buffer_push(tty);
163         return;
164 }
165
166 static void pl010_tx_chars(struct uart_port *port)
167 {
168         struct circ_buf *xmit = &port->info->xmit;
169         int count;
170
171         if (port->x_char) {
172                 writel(port->x_char, port->membase + UART01x_DR);
173                 port->icount.tx++;
174                 port->x_char = 0;
175                 return;
176         }
177         if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
178                 pl010_stop_tx(port);
179                 return;
180         }
181
182         count = port->fifosize >> 1;
183         do {
184                 writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
185                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
186                 port->icount.tx++;
187                 if (uart_circ_empty(xmit))
188                         break;
189         } while (--count > 0);
190
191         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
192                 uart_write_wakeup(port);
193
194         if (uart_circ_empty(xmit))
195                 pl010_stop_tx(port);
196 }
197
198 static void pl010_modem_status(struct uart_port *port)
199 {
200         struct uart_amba_port *uap = (struct uart_amba_port *)port;
201         unsigned int status, delta;
202
203         writel(0, uap->port.membase + UART010_ICR);
204
205         status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
206
207         delta = status ^ uap->old_status;
208         uap->old_status = status;
209
210         if (!delta)
211                 return;
212
213         if (delta & UART01x_FR_DCD)
214                 uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
215
216         if (delta & UART01x_FR_DSR)
217                 uap->port.icount.dsr++;
218
219         if (delta & UART01x_FR_CTS)
220                 uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
221
222         wake_up_interruptible(&uap->port.info->delta_msr_wait);
223 }
224
225 static irqreturn_t pl010_int(int irq, void *dev_id)
226 {
227         struct uart_port *port = dev_id;
228         unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
229         int handled = 0;
230
231         spin_lock(&port->lock);
232
233         status = readb(port->membase + UART010_IIR);
234         if (status) {
235                 do {
236                         if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
237                                 pl010_rx_chars(port);
238                         if (status & UART010_IIR_MIS)
239                                 pl010_modem_status(port);
240                         if (status & UART010_IIR_TIS)
241                                 pl010_tx_chars(port);
242
243                         if (pass_counter-- == 0)
244                                 break;
245
246                         status = readb(port->membase + UART010_IIR);
247                 } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
248                                    UART010_IIR_TIS));
249                 handled = 1;
250         }
251
252         spin_unlock(&port->lock);
253
254         return IRQ_RETVAL(handled);
255 }
256
257 static unsigned int pl010_tx_empty(struct uart_port *port)
258 {
259         return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
260 }
261
262 static unsigned int pl010_get_mctrl(struct uart_port *port)
263 {
264         unsigned int result = 0;
265         unsigned int status;
266
267         status = readb(port->membase + UART01x_FR);
268         if (status & UART01x_FR_DCD)
269                 result |= TIOCM_CAR;
270         if (status & UART01x_FR_DSR)
271                 result |= TIOCM_DSR;
272         if (status & UART01x_FR_CTS)
273                 result |= TIOCM_CTS;
274
275         return result;
276 }
277
278 static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
279 {
280         struct uart_amba_port *uap = (struct uart_amba_port *)port;
281
282         if (uap->data)
283                 uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
284 }
285
286 static void pl010_break_ctl(struct uart_port *port, int break_state)
287 {
288         unsigned long flags;
289         unsigned int lcr_h;
290
291         spin_lock_irqsave(&port->lock, flags);
292         lcr_h = readb(port->membase + UART010_LCRH);
293         if (break_state == -1)
294                 lcr_h |= UART01x_LCRH_BRK;
295         else
296                 lcr_h &= ~UART01x_LCRH_BRK;
297         writel(lcr_h, port->membase + UART010_LCRH);
298         spin_unlock_irqrestore(&port->lock, flags);
299 }
300
301 static int pl010_startup(struct uart_port *port)
302 {
303         struct uart_amba_port *uap = (struct uart_amba_port *)port;
304         int retval;
305
306         /*
307          * Allocate the IRQ
308          */
309         retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", port);
310         if (retval)
311                 return retval;
312
313         /*
314          * initialise the old status of the modem signals
315          */
316         uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
317
318         /*
319          * Finally, enable interrupts
320          */
321         writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
322                port->membase + UART010_CR);
323
324         return 0;
325 }
326
327 static void pl010_shutdown(struct uart_port *port)
328 {
329         /*
330          * Free the interrupt
331          */
332         free_irq(port->irq, port);
333
334         /*
335          * disable all interrupts, disable the port
336          */
337         writel(0, port->membase + UART010_CR);
338
339         /* disable break condition and fifos */
340         writel(readb(port->membase + UART010_LCRH) &
341                 ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
342                port->membase + UART010_LCRH);
343 }
344
345 static void
346 pl010_set_termios(struct uart_port *port, struct termios *termios,
347                      struct termios *old)
348 {
349         unsigned int lcr_h, old_cr;
350         unsigned long flags;
351         unsigned int baud, quot;
352
353         /*
354          * Ask the core to calculate the divisor for us.
355          */
356         baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
357         quot = uart_get_divisor(port, baud);
358
359         switch (termios->c_cflag & CSIZE) {
360         case CS5:
361                 lcr_h = UART01x_LCRH_WLEN_5;
362                 break;
363         case CS6:
364                 lcr_h = UART01x_LCRH_WLEN_6;
365                 break;
366         case CS7:
367                 lcr_h = UART01x_LCRH_WLEN_7;
368                 break;
369         default: // CS8
370                 lcr_h = UART01x_LCRH_WLEN_8;
371                 break;
372         }
373         if (termios->c_cflag & CSTOPB)
374                 lcr_h |= UART01x_LCRH_STP2;
375         if (termios->c_cflag & PARENB) {
376                 lcr_h |= UART01x_LCRH_PEN;
377                 if (!(termios->c_cflag & PARODD))
378                         lcr_h |= UART01x_LCRH_EPS;
379         }
380         if (port->fifosize > 1)
381                 lcr_h |= UART01x_LCRH_FEN;
382
383         spin_lock_irqsave(&port->lock, flags);
384
385         /*
386          * Update the per-port timeout.
387          */
388         uart_update_timeout(port, termios->c_cflag, baud);
389
390         port->read_status_mask = UART01x_RSR_OE;
391         if (termios->c_iflag & INPCK)
392                 port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
393         if (termios->c_iflag & (BRKINT | PARMRK))
394                 port->read_status_mask |= UART01x_RSR_BE;
395
396         /*
397          * Characters to ignore
398          */
399         port->ignore_status_mask = 0;
400         if (termios->c_iflag & IGNPAR)
401                 port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
402         if (termios->c_iflag & IGNBRK) {
403                 port->ignore_status_mask |= UART01x_RSR_BE;
404                 /*
405                  * If we're ignoring parity and break indicators,
406                  * ignore overruns too (for real raw support).
407                  */
408                 if (termios->c_iflag & IGNPAR)
409                         port->ignore_status_mask |= UART01x_RSR_OE;
410         }
411
412         /*
413          * Ignore all characters if CREAD is not set.
414          */
415         if ((termios->c_cflag & CREAD) == 0)
416                 port->ignore_status_mask |= UART_DUMMY_RSR_RX;
417
418         /* first, disable everything */
419         old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE;
420
421         if (UART_ENABLE_MS(port, termios->c_cflag))
422                 old_cr |= UART010_CR_MSIE;
423
424         writel(0, port->membase + UART010_CR);
425
426         /* Set baud rate */
427         quot -= 1;
428         writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM);
429         writel(quot & 0xff, port->membase + UART010_LCRL);
430
431         /*
432          * ----------v----------v----------v----------v-----
433          * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
434          * ----------^----------^----------^----------^-----
435          */
436         writel(lcr_h, port->membase + UART010_LCRH);
437         writel(old_cr, port->membase + UART010_CR);
438
439         spin_unlock_irqrestore(&port->lock, flags);
440 }
441
442 static const char *pl010_type(struct uart_port *port)
443 {
444         return port->type == PORT_AMBA ? "AMBA" : NULL;
445 }
446
447 /*
448  * Release the memory region(s) being used by 'port'
449  */
450 static void pl010_release_port(struct uart_port *port)
451 {
452         release_mem_region(port->mapbase, UART_PORT_SIZE);
453 }
454
455 /*
456  * Request the memory region(s) being used by 'port'
457  */
458 static int pl010_request_port(struct uart_port *port)
459 {
460         return request_mem_region(port->mapbase, UART_PORT_SIZE, "uart-pl010")
461                         != NULL ? 0 : -EBUSY;
462 }
463
464 /*
465  * Configure/autoconfigure the port.
466  */
467 static void pl010_config_port(struct uart_port *port, int flags)
468 {
469         if (flags & UART_CONFIG_TYPE) {
470                 port->type = PORT_AMBA;
471                 pl010_request_port(port);
472         }
473 }
474
475 /*
476  * verify the new serial_struct (for TIOCSSERIAL).
477  */
478 static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
479 {
480         int ret = 0;
481         if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
482                 ret = -EINVAL;
483         if (ser->irq < 0 || ser->irq >= NR_IRQS)
484                 ret = -EINVAL;
485         if (ser->baud_base < 9600)
486                 ret = -EINVAL;
487         return ret;
488 }
489
490 static struct uart_ops amba_pl010_pops = {
491         .tx_empty       = pl010_tx_empty,
492         .set_mctrl      = pl010_set_mctrl,
493         .get_mctrl      = pl010_get_mctrl,
494         .stop_tx        = pl010_stop_tx,
495         .start_tx       = pl010_start_tx,
496         .stop_rx        = pl010_stop_rx,
497         .enable_ms      = pl010_enable_ms,
498         .break_ctl      = pl010_break_ctl,
499         .startup        = pl010_startup,
500         .shutdown       = pl010_shutdown,
501         .set_termios    = pl010_set_termios,
502         .type           = pl010_type,
503         .release_port   = pl010_release_port,
504         .request_port   = pl010_request_port,
505         .config_port    = pl010_config_port,
506         .verify_port    = pl010_verify_port,
507 };
508
509 static struct uart_amba_port *amba_ports[UART_NR];
510
511 #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
512
513 static void pl010_console_putchar(struct uart_port *port, int ch)
514 {
515         unsigned int status;
516
517         do {
518                 status = readb(port->membase + UART01x_FR);
519                 barrier();
520         } while (!UART_TX_READY(status));
521         writel(ch, port->membase + UART01x_DR);
522 }
523
524 static void
525 pl010_console_write(struct console *co, const char *s, unsigned int count)
526 {
527         struct uart_port *port = &amba_ports[co->index]->port;
528         unsigned int status, old_cr;
529
530         /*
531          *      First save the CR then disable the interrupts
532          */
533         old_cr = readb(port->membase + UART010_CR);
534         writel(UART01x_CR_UARTEN, port->membase + UART010_CR);
535
536         uart_console_write(port, s, count, pl010_console_putchar);
537
538         /*
539          *      Finally, wait for transmitter to become empty
540          *      and restore the TCR
541          */
542         do {
543                 status = readb(port->membase + UART01x_FR);
544                 barrier();
545         } while (status & UART01x_FR_BUSY);
546         writel(old_cr, port->membase + UART010_CR);
547 }
548
549 static void __init
550 pl010_console_get_options(struct uart_port *port, int *baud,
551                              int *parity, int *bits)
552 {
553         if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) {
554                 unsigned int lcr_h, quot;
555                 lcr_h = readb(port->membase + UART010_LCRH);
556
557                 *parity = 'n';
558                 if (lcr_h & UART01x_LCRH_PEN) {
559                         if (lcr_h & UART01x_LCRH_EPS)
560                                 *parity = 'e';
561                         else
562                                 *parity = 'o';
563                 }
564
565                 if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
566                         *bits = 7;
567                 else
568                         *bits = 8;
569
570                 quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8;
571                 *baud = port->uartclk / (16 * (quot + 1));
572         }
573 }
574
575 static int __init pl010_console_setup(struct console *co, char *options)
576 {
577         struct uart_port *port;
578         int baud = 38400;
579         int bits = 8;
580         int parity = 'n';
581         int flow = 'n';
582
583         /*
584          * Check whether an invalid uart number has been specified, and
585          * if so, search for the first available port that does have
586          * console support.
587          */
588         if (co->index >= UART_NR)
589                 co->index = 0;
590         port = &amba_ports[co->index]->port;
591
592         if (options)
593                 uart_parse_options(options, &baud, &parity, &bits, &flow);
594         else
595                 pl010_console_get_options(port, &baud, &parity, &bits);
596
597         return uart_set_options(port, co, baud, parity, bits, flow);
598 }
599
600 static struct uart_driver amba_reg;
601 static struct console amba_console = {
602         .name           = "ttyAM",
603         .write          = pl010_console_write,
604         .device         = uart_console_device,
605         .setup          = pl010_console_setup,
606         .flags          = CON_PRINTBUFFER,
607         .index          = -1,
608         .data           = &amba_reg,
609 };
610
611 #define AMBA_CONSOLE    &amba_console
612 #else
613 #define AMBA_CONSOLE    NULL
614 #endif
615
616 static struct uart_driver amba_reg = {
617         .owner                  = THIS_MODULE,
618         .driver_name            = "ttyAM",
619         .dev_name               = "ttyAM",
620         .major                  = SERIAL_AMBA_MAJOR,
621         .minor                  = SERIAL_AMBA_MINOR,
622         .nr                     = UART_NR,
623         .cons                   = AMBA_CONSOLE,
624 };
625
626 static int pl010_probe(struct amba_device *dev, void *id)
627 {
628         struct uart_amba_port *port;
629         void __iomem *base;
630         int i, ret;
631
632         for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
633                 if (amba_ports[i] == NULL)
634                         break;
635
636         if (i == ARRAY_SIZE(amba_ports)) {
637                 ret = -EBUSY;
638                 goto out;
639         }
640
641         port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
642         if (!port) {
643                 ret = -ENOMEM;
644                 goto out;
645         }
646
647         base = ioremap(dev->res.start, PAGE_SIZE);
648         if (!base) {
649                 ret = -ENOMEM;
650                 goto free;
651         }
652
653         port->port.dev = &dev->dev;
654         port->port.mapbase = dev->res.start;
655         port->port.membase = base;
656         port->port.iotype = UPIO_MEM;
657         port->port.irq = dev->irq[0];
658         port->port.uartclk = 14745600;
659         port->port.fifosize = 16;
660         port->port.ops = &amba_pl010_pops;
661         port->port.flags = UPF_BOOT_AUTOCONF;
662         port->port.line = i;
663         port->dev = dev;
664         port->data = dev->dev.platform_data;
665
666         amba_ports[i] = port;
667
668         amba_set_drvdata(dev, port);
669         ret = uart_add_one_port(&amba_reg, &port->port);
670         if (ret) {
671                 amba_set_drvdata(dev, NULL);
672                 amba_ports[i] = NULL;
673                 iounmap(base);
674  free:
675                 kfree(port);
676         }
677
678  out:
679         return ret;
680 }
681
682 static int pl010_remove(struct amba_device *dev)
683 {
684         struct uart_amba_port *port = amba_get_drvdata(dev);
685         int i;
686
687         amba_set_drvdata(dev, NULL);
688
689         uart_remove_one_port(&amba_reg, &port->port);
690
691         for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
692                 if (amba_ports[i] == port)
693                         amba_ports[i] = NULL;
694
695         iounmap(port->port.membase);
696         kfree(port);
697
698         return 0;
699 }
700
701 static int pl010_suspend(struct amba_device *dev, pm_message_t state)
702 {
703         struct uart_amba_port *uap = amba_get_drvdata(dev);
704
705         if (uap)
706                 uart_suspend_port(&amba_reg, &uap->port);
707
708         return 0;
709 }
710
711 static int pl010_resume(struct amba_device *dev)
712 {
713         struct uart_amba_port *uap = amba_get_drvdata(dev);
714
715         if (uap)
716                 uart_resume_port(&amba_reg, &uap->port);
717
718         return 0;
719 }
720
721 static struct amba_id pl010_ids[] __initdata = {
722         {
723                 .id     = 0x00041010,
724                 .mask   = 0x000fffff,
725         },
726         { 0, 0 },
727 };
728
729 static struct amba_driver pl010_driver = {
730         .drv = {
731                 .name   = "uart-pl010",
732         },
733         .id_table       = pl010_ids,
734         .probe          = pl010_probe,
735         .remove         = pl010_remove,
736         .suspend        = pl010_suspend,
737         .resume         = pl010_resume,
738 };
739
740 static int __init pl010_init(void)
741 {
742         int ret;
743
744         printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n");
745
746         ret = uart_register_driver(&amba_reg);
747         if (ret == 0) {
748                 ret = amba_driver_register(&pl010_driver);
749                 if (ret)
750                         uart_unregister_driver(&amba_reg);
751         }
752         return ret;
753 }
754
755 static void __exit pl010_exit(void)
756 {
757         amba_driver_unregister(&pl010_driver);
758         uart_unregister_driver(&amba_reg);
759 }
760
761 module_init(pl010_init);
762 module_exit(pl010_exit);
763
764 MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
765 MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $");
766 MODULE_LICENSE("GPL");