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>
46 #if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
50 #include <linux/serial_core.h>
52 #include <asm/hardware/serial_amba.h>
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:
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
)
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
)
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
)
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
)
137 cr
= UART_GET_CR(port
);
138 cr
|= AMBA_UARTCR_MSIE
;
139 UART_PUT_CR(port
, cr
);
144 ambauart_rx_chars(struct uart_port
*port
, struct pt_regs
*regs
)
146 ambauart_rx_chars(struct uart_port
*port
)
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");
162 ch
= UART_GET_CHAR(port
);
164 *tty
->flip
.char_buf_ptr
= ch
;
165 *tty
->flip
.flag_buf_ptr
= TTY_NORMAL
;
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
);
177 if (uart_handle_break(port
))
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
))
199 if ((rsr
& port
->ignore_status_mask
) == 0) {
200 tty
->flip
.flag_buf_ptr
++;
201 tty
->flip
.char_buf_ptr
++;
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
211 *tty
->flip
.char_buf_ptr
++ = 0;
212 *tty
->flip
.flag_buf_ptr
++ = TTY_OVERRUN
;
216 status
= UART_GET_FR(port
);
218 tty_flip_buffer_push(tty
);
222 static void ambauart_tx_chars(struct uart_port
*port
)
224 struct circ_buf
*xmit
= &port
->info
->xmit
;
228 UART_PUT_CHAR(port
, port
->x_char
);
233 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
234 ambauart_stop_tx(port
, 0);
238 count
= port
->fifosize
>> 1;
240 UART_PUT_CHAR(port
, xmit
->buf
[xmit
->tail
]);
241 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
243 if (uart_circ_empty(xmit
))
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
;
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
);
288 if (status
& (AMBA_UARTIIR_RTIS
| AMBA_UARTIIR_RIS
))
290 ambauart_rx_chars(port
, regs
);
292 ambauart_rx_chars(port
);
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)
302 status
= UART_GET_INT_STATUS(port
);
303 } while (status
& (AMBA_UARTIIR_RTIS
| AMBA_UARTIIR_RIS
|
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;
319 status
= UART_GET_FR(port
);
320 if (status
& AMBA_UARTFR_DCD
)
322 if (status
& AMBA_UARTFR_DSR
)
324 if (status
& AMBA_UARTFR_CTS
)
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
;
338 ctrls
|= uap
->rts_mask
;
340 if (mctrl
& TIOCM_DTR
)
341 ctrlc
|= uap
->dtr_mask
;
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
)
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
;
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
;
372 retval
= request_irq(port
->irq
, ambauart_int
, 0, "amba", port
);
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
|
390 static void ambauart_shutdown(struct uart_port
*port
)
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
));
408 ambauart_set_termios(struct uart_port
*port
, struct termios
*termios
,
411 unsigned int lcr_h
, old_cr
;
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
) {
423 lcr_h
= AMBA_UARTLCR_H_WLEN_5
;
426 lcr_h
= AMBA_UARTLCR_H_WLEN_6
;
429 lcr_h
= AMBA_UARTLCR_H_WLEN_7
;
432 lcr_h
= AMBA_UARTLCR_H_WLEN_8
;
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);
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
)
543 if (ser
->type
!= PORT_UNKNOWN
&& ser
->type
!= PORT_AMBA
)
545 if (ser
->irq
< 0 || ser
->irq
>= NR_IRQS
)
547 if (ser
->baud_base
< 9600)
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
] = {
574 .membase
= (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE
),
575 .mapbase
= INTEGRATOR_UART0_BASE
,
576 .iotype
= SERIAL_IO_MEM
,
581 .flags
= ASYNC_BOOT_AUTOCONF
,
589 .membase
= (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE
),
590 .mapbase
= INTEGRATOR_UART1_BASE
,
591 .iotype
= SERIAL_IO_MEM
,
596 .flags
= ASYNC_BOOT_AUTOCONF
,
604 #ifdef CONFIG_SERIAL_AMBA_CONSOLE
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
;
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
++) {
624 status
= UART_GET_FR(port
);
625 } while (!UART_TX_READY(status
));
626 UART_PUT_CHAR(port
, s
[i
]);
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
640 status
= UART_GET_FR(port
);
641 } while (status
& AMBA_UARTFR_BUSY
);
642 UART_PUT_CR(port
, old_cr
);
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
);
654 if (lcr_h
& AMBA_UARTLCR_H_PEN
) {
655 if (lcr_h
& AMBA_UARTLCR_H_EPS
)
661 if ((lcr_h
& 0x60) == AMBA_UARTLCR_H_WLEN_7
)
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
;
680 * Check whether an invalid uart number has been specified, and
681 * if so, search for the first available port that does have
684 if (co
->index
>= UART_NR
)
686 port
= &amba_ports
[co
->index
].port
;
689 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
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
= {
699 .write
= ambauart_console_write
,
700 .device
= uart_console_device
,
701 .setup
= ambauart_console_setup
,
702 .flags
= CON_PRINTBUFFER
,
707 static int __init
ambauart_console_init(void)
709 register_console(&amba_console
);
712 console_initcall(ambauart_console_init
);
714 #define AMBA_CONSOLE &amba_console
716 #define AMBA_CONSOLE NULL
719 static struct uart_driver amba_reg
= {
720 .owner
= THIS_MODULE
,
721 .driver_name
= "ttyAM",
723 .major
= SERIAL_AMBA_MAJOR
,
724 .minor
= SERIAL_AMBA_MINOR
,
726 .cons
= AMBA_CONSOLE
,
729 static int __init
ambauart_init(void)
733 printk(KERN_INFO
"Serial: AMBA driver $Revision: 1.41 $\n");
735 ret
= uart_register_driver(&amba_reg
);
739 for (i
= 0; i
< UART_NR
; i
++)
740 uart_add_one_port(&amba_reg
, &amba_ports
[i
].port
);
745 static void __exit
ambauart_exit(void)
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");