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