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