2 * Serial driver for ADM5120 SoC
4 * Derived from drivers/serial/uart00.c
5 * Copyright 2001 Altera Corporation
7 * Some pieces are derived from the ADMtek 2.4 serial driver.
8 * Copyright (C) ADMtek Incorporated, 2003
9 * daniell@admtek.com.tw
10 * Which again was derived from drivers/char/serial.c
11 * Copyright (C) Linus Torvalds et al.
13 * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005
16 #include <linux/autoconf.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/ioport.h>
21 #include <linux/serial.h>
22 #include <linux/serial_core.h>
23 #include <linux/tty.h>
24 #include <linux/tty_flip.h>
25 #include <linux/console.h>
27 #define ADM5120_UART_BASE0 0x12600000
28 #define ADM5120_UART_BASE1 0x12800000
29 #define ADM5120_UART_SIZE 0x20
31 #define ADM5120_UART_IRQ0 1
32 #define ADM5120_UART_IRQ1 2
34 #define ADM5120_UART_REG(base, reg) \
35 (*(volatile u32 *)KSEG1ADDR((base)+(reg)))
37 #define ADM5120_UARTCLK_FREQ 62500000
38 #define ADM5120_UART_BAUDDIV(rate) ((unsigned long)(ADM5120_UARTCLK_FREQ/(16*(rate)) - 1))
40 #define ADM5120_UART_BAUD115200 ADM5120_UART_BAUDDIV(115200)
42 #define ADM5120_UART_DATA 0x00
43 #define ADM5120_UART_RS 0x04
44 #define ADM5120_UART_LCR_H 0x08
45 #define ADM5120_UART_LCR_M 0x0c
46 #define ADM5120_UART_LCR_L 0x10
47 #define ADM5120_UART_CR 0x14
48 #define ADM5120_UART_FR 0x18
49 #define ADM5120_UART_IR 0x1c
51 #define ADM5120_UART_FE 0x01
52 #define ADM5120_UART_PE 0x02
53 #define ADM5120_UART_BE 0x04
54 #define ADM5120_UART_OE 0x08
55 #define ADM5120_UART_ERR 0x0f
56 #define ADM5120_UART_FIFO_EN 0x10
57 #define ADM5120_UART_EN 0x01
58 #define ADM5120_UART_TIE 0x20
59 #define ADM5120_UART_RIE 0x50
60 #define ADM5120_UART_IE 0x78
61 #define ADM5120_UART_CTS 0x01
62 #define ADM5120_UART_DSR 0x02
63 #define ADM5120_UART_DCD 0x04
64 #define ADM5120_UART_TXFF 0x20
65 #define ADM5120_UART_TXFE 0x80
66 #define ADM5120_UART_RXFE 0x10
67 #define ADM5120_UART_BRK 0x01
68 #define ADM5120_UART_PEN 0x02
69 #define ADM5120_UART_EPS 0x04
70 #define ADM5120_UART_STP2 0x08
71 #define ADM5120_UART_W5 0x00
72 #define ADM5120_UART_W6 0x20
73 #define ADM5120_UART_W7 0x40
74 #define ADM5120_UART_W8 0x60
75 #define ADM5120_UART_MIS 0x01
76 #define ADM5120_UART_RIS 0x02
77 #define ADM5120_UART_TIS 0x04
78 #define ADM5120_UART_RTIS 0x08
80 static void adm5120ser_stop_tx(struct uart_port
*port
)
82 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) &= ~ADM5120_UART_TIE
;
85 static void adm5120ser_irq_rx(struct uart_port
*port
)
87 struct tty_struct
*tty
= port
->info
->tty
;
88 unsigned int status
, ch
, rds
, flg
, ignored
= 0;
90 status
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
91 while (!(status
& ADM5120_UART_RXFE
)) {
93 * We need to read rds before reading the
94 * character from the fifo
96 rds
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_RS
);
97 ch
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_DATA
);
100 if (tty
->low_latency
)
101 tty_flip_buffer_push(tty
);
106 * Note that the error handling code is
107 * out of the main execution path
109 if (rds
& ADM5120_UART_ERR
)
111 if (uart_handle_sysrq_char(port
, ch
))
115 tty_insert_flip_char(tty
, ch
, flg
);
118 status
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
121 tty_flip_buffer_push(tty
);
125 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_RS
) = 0xff;
126 if (rds
& ADM5120_UART_BE
) {
128 if (uart_handle_break(port
))
130 } else if (rds
& ADM5120_UART_PE
)
131 port
->icount
.parity
++;
132 else if (rds
& ADM5120_UART_FE
)
133 port
->icount
.frame
++;
134 if (rds
& ADM5120_UART_OE
)
135 port
->icount
.overrun
++;
137 if (rds
& port
->ignore_status_mask
) {
142 rds
&= port
->read_status_mask
;
144 if (rds
& ADM5120_UART_BE
)
146 else if (rds
& ADM5120_UART_PE
)
148 else if (rds
& ADM5120_UART_FE
)
151 if (rds
& ADM5120_UART_OE
) {
153 * CHECK: does overrun affect the current character?
154 * ASSUMPTION: it does not.
156 tty_insert_flip_char(tty
, ch
, flg
);
160 #ifdef CONFIG_MAGIC_SYSRQ
166 static void adm5120ser_irq_tx(struct uart_port
*port
)
168 struct circ_buf
*xmit
= &port
->info
->xmit
;
172 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_DATA
) =
178 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
179 adm5120ser_stop_tx(port
);
183 count
= port
->fifosize
>> 1;
185 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_DATA
) =
186 xmit
->buf
[xmit
->tail
];
187 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
189 if (uart_circ_empty(xmit
))
191 } while (--count
> 0);
193 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
194 uart_write_wakeup(port
);
196 if (uart_circ_empty(xmit
))
197 adm5120ser_stop_tx(port
);
200 static void adm5120ser_irq_modem(struct uart_port
*port
)
204 status
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
206 if (status
& ADM5120_UART_DCD
)
207 uart_handle_dcd_change(port
, status
& ADM5120_UART_DCD
);
209 if (status
& ADM5120_UART_DSR
)
212 if (status
& ADM5120_UART_CTS
)
213 uart_handle_cts_change(port
, status
& ADM5120_UART_CTS
);
215 wake_up_interruptible(&port
->info
->delta_msr_wait
);
218 static irqreturn_t
adm5120ser_irq(int irq
, void *dev_id
)
220 struct uart_port
*port
= dev_id
;
221 unsigned long ir
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_IR
);
223 if (ir
& (ADM5120_UART_RIS
| ADM5120_UART_RTIS
))
224 adm5120ser_irq_rx(port
);
225 if (ir
& ADM5120_UART_TIS
)
226 adm5120ser_irq_tx(port
);
227 if (ir
& ADM5120_UART_MIS
) {
228 adm5120ser_irq_modem(port
);
229 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_IR
) = 0xff;
235 static unsigned int adm5120ser_tx_empty(struct uart_port
*port
)
237 unsigned int fr
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
238 return (fr
& ADM5120_UART_TXFE
) ? TIOCSER_TEMT
: 0;
241 static void adm5120ser_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
245 static unsigned int adm5120ser_get_mctrl(struct uart_port
*port
)
247 unsigned int result
= 0;
248 unsigned int fr
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
250 if (fr
& ADM5120_UART_CTS
)
252 if (fr
& ADM5120_UART_DSR
)
254 if (fr
& ADM5120_UART_DCD
)
259 static void adm5120ser_start_tx(struct uart_port
*port
)
261 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) |= ADM5120_UART_TIE
;
264 static void adm5120ser_stop_rx(struct uart_port
*port
)
266 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) &= ~ADM5120_UART_RIE
;
269 static void adm5120ser_enable_ms(struct uart_port
*port
)
273 static void adm5120ser_break_ctl(struct uart_port
*port
, int break_state
)
278 spin_lock_irqsave(&port
->lock
, flags
);
279 lcrh
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
);
280 if (break_state
== -1)
281 lcrh
|= ADM5120_UART_BRK
;
283 lcrh
&= ~ADM5120_UART_BRK
;
284 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
) = lcrh
;
285 spin_unlock_irqrestore(&port
->lock
, flags
);
288 static int adm5120ser_startup(struct uart_port
*port
)
292 ret
= request_irq(port
->irq
, adm5120ser_irq
, 0, "ADM5120 UART", port
);
294 printk(KERN_ERR
"Couldn't get irq %d\n", port
->irq
);
297 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
) |=
298 ADM5120_UART_FIFO_EN
;
299 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) |=
300 ADM5120_UART_EN
| ADM5120_UART_IE
;
304 static void adm5120ser_shutdown(struct uart_port
*port
)
306 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) &= ~ADM5120_UART_IE
;
307 free_irq(port
->irq
, port
);
310 static void adm5120ser_set_termios(struct uart_port
*port
,
311 struct ktermios
*termios
, struct ktermios
*old
)
313 unsigned int baud
, quot
, lcrh
;
316 termios
->c_cflag
|= CREAD
;
318 baud
= uart_get_baud_rate(port
, termios
, old
, 0, port
->uartclk
/16);
319 quot
= uart_get_divisor(port
, baud
);
321 lcrh
= ADM5120_UART_FIFO_EN
;
322 switch (termios
->c_cflag
& CSIZE
) {
324 lcrh
|= ADM5120_UART_W5
;
327 lcrh
|= ADM5120_UART_W6
;
330 lcrh
|= ADM5120_UART_W7
;
333 lcrh
|= ADM5120_UART_W8
;
336 if (termios
->c_cflag
& CSTOPB
)
337 lcrh
|= ADM5120_UART_STP2
;
338 if (termios
->c_cflag
& PARENB
) {
339 lcrh
|= ADM5120_UART_PEN
;
340 if (!(termios
->c_cflag
& PARODD
))
341 lcrh
|= ADM5120_UART_EPS
;
344 spin_lock_irqsave(port
->lock
, flags
);
346 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
) = lcrh
;
349 * Update the per-port timeout.
351 uart_update_timeout(port
, termios
->c_cflag
, baud
);
353 port
->read_status_mask
= ADM5120_UART_OE
;
354 if (termios
->c_iflag
& INPCK
)
355 port
->read_status_mask
|= ADM5120_UART_FE
| ADM5120_UART_PE
;
356 if (termios
->c_iflag
& (BRKINT
| PARMRK
))
357 port
->read_status_mask
|= ADM5120_UART_BE
;
360 * Characters to ignore
362 port
->ignore_status_mask
= 0;
363 if (termios
->c_iflag
& IGNPAR
)
364 port
->ignore_status_mask
|= ADM5120_UART_FE
| ADM5120_UART_PE
;
365 if (termios
->c_iflag
& IGNBRK
) {
366 port
->ignore_status_mask
|= ADM5120_UART_BE
;
368 * If we're ignoring parity and break indicators,
369 * ignore overruns to (for real raw support).
371 if (termios
->c_iflag
& IGNPAR
)
372 port
->ignore_status_mask
|= ADM5120_UART_OE
;
375 quot
= ADM5120_UART_BAUD115200
;
376 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_L
) = quot
& 0xff;
377 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_M
) = quot
>> 8;
379 spin_unlock_irqrestore(&port
->lock
, flags
);
382 static const char *adm5120ser_type(struct uart_port
*port
)
384 return port
->type
== PORT_ADM5120
? "ADM5120" : NULL
;
387 static void adm5120ser_config_port(struct uart_port
*port
, int flags
)
389 if (flags
& UART_CONFIG_TYPE
)
390 port
->type
= PORT_ADM5120
;
393 static void adm5120ser_release_port(struct uart_port
*port
)
395 release_mem_region(port
->iobase
, ADM5120_UART_SIZE
);
398 static int adm5120ser_request_port(struct uart_port
*port
)
400 return request_mem_region(port
->iobase
, ADM5120_UART_SIZE
,
401 "adm5120-uart") != NULL
? 0 : -EBUSY
;
404 static struct uart_ops adm5120ser_ops
= {
405 .tx_empty
= adm5120ser_tx_empty
,
406 .set_mctrl
= adm5120ser_set_mctrl
,
407 .get_mctrl
= adm5120ser_get_mctrl
,
408 .stop_tx
= adm5120ser_stop_tx
,
409 .start_tx
= adm5120ser_start_tx
,
410 .stop_rx
= adm5120ser_stop_rx
,
411 .enable_ms
= adm5120ser_enable_ms
,
412 .break_ctl
= adm5120ser_break_ctl
,
413 .startup
= adm5120ser_startup
,
414 .shutdown
= adm5120ser_shutdown
,
415 .set_termios
= adm5120ser_set_termios
,
416 .type
= adm5120ser_type
,
417 .config_port
= adm5120ser_config_port
,
418 .release_port
= adm5120ser_release_port
,
419 .request_port
= adm5120ser_request_port
,
422 static void adm5120console_put(const char c
)
424 while ((ADM5120_UART_REG(ADM5120_UART_BASE0
, ADM5120_UART_FR
) &
425 ADM5120_UART_TXFF
) != 0);
426 ADM5120_UART_REG(ADM5120_UART_BASE0
, ADM5120_UART_DATA
) = c
;
429 static void adm5120console_write(struct console
*con
, const char *s
,
434 adm5120console_put('\r');
435 adm5120console_put(*s
);
440 static int __init
adm5120console_setup(struct console
*con
, char *options
)
442 /* Set to 115200 baud, 8N1 and enable FIFO */
443 ADM5120_UART_REG(ADM5120_UART_BASE0
, ADM5120_UART_LCR_L
) =
444 ADM5120_UART_BAUD115200
& 0xff;
445 ADM5120_UART_REG(ADM5120_UART_BASE0
, ADM5120_UART_LCR_M
) =
446 ADM5120_UART_BAUD115200
>> 8;
447 ADM5120_UART_REG(ADM5120_UART_BASE0
, ADM5120_UART_LCR_H
) =
448 ADM5120_UART_W8
| ADM5120_UART_FIFO_EN
;
450 ADM5120_UART_REG(ADM5120_UART_BASE0
, ADM5120_UART_CR
) =
456 static struct uart_driver adm5120ser_reg
;
458 static struct console adm5120_serconsole
= {
460 .write
= adm5120console_write
,
461 .device
= uart_console_device
,
462 .setup
= adm5120console_setup
,
463 .flags
= CON_PRINTBUFFER
,
464 .cflag
= B115200
| CS8
| CREAD
,
466 .data
= &adm5120ser_reg
,
469 static int __init
adm5120console_init(void)
471 register_console(&adm5120_serconsole
);
475 console_initcall(adm5120console_init
);
478 static struct uart_port adm5120ser_ports
[] = {
480 .iobase
= ADM5120_UART_BASE0
,
481 .irq
= ADM5120_UART_IRQ0
,
482 .uartclk
= ADM5120_UARTCLK_FREQ
,
484 .ops
= &adm5120ser_ops
,
486 .flags
= ASYNC_BOOT_AUTOCONF
,
488 #if (CONFIG_ADM5120_NR_UARTS > 1)
490 .iobase
= ADM5120_UART_BASE1
,
491 .irq
= ADM5120_UART_IRQ1
,
492 .uartclk
= ADM5120_UARTCLK_FREQ
,
494 .ops
= &adm5120ser_ops
,
496 .flags
= ASYNC_BOOT_AUTOCONF
,
501 static struct uart_driver adm5120ser_reg
= {
502 .owner
= THIS_MODULE
,
503 .driver_name
= "ttyS",
507 .nr
= CONFIG_ADM5120_NR_UARTS
,
508 .cons
= &adm5120_serconsole
,
511 static int __init
adm5120ser_init(void)
515 ret
= uart_register_driver(&adm5120ser_reg
);
517 for (i
= 0; i
< CONFIG_ADM5120_NR_UARTS
; i
++)
518 uart_add_one_port(&adm5120ser_reg
, &adm5120ser_ports
[i
]);
524 __initcall(adm5120ser_init
);