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 #include <asm/mach-adm5120/adm5120_defs.h>
28 #include <asm/mach-adm5120/adm5120_irq.h>
30 #define ADM5120_UART_REG(base, reg) \
31 (*(volatile u32 *)KSEG1ADDR((base)+(reg)))
33 #define ADM5120_UARTCLK_FREQ 62500000
34 #define ADM5120_UART_BAUDDIV(rate) ((unsigned long)(ADM5120_UARTCLK_FREQ/(16*(rate)) - 1))
36 #define ADM5120_UART_BAUD115200 ADM5120_UART_BAUDDIV(115200)
38 #define ADM5120_UART_DATA 0x00
39 #define ADM5120_UART_RS 0x04
40 #define ADM5120_UART_LCR_H 0x08
41 #define ADM5120_UART_LCR_M 0x0c
42 #define ADM5120_UART_LCR_L 0x10
43 #define ADM5120_UART_CR 0x14
44 #define ADM5120_UART_FR 0x18
45 #define ADM5120_UART_IR 0x1c
47 #define ADM5120_UART_FE 0x01
48 #define ADM5120_UART_PE 0x02
49 #define ADM5120_UART_BE 0x04
50 #define ADM5120_UART_OE 0x08
51 #define ADM5120_UART_ERR 0x0f
52 #define ADM5120_UART_FIFO_EN 0x10
53 #define ADM5120_UART_EN 0x01
54 #define ADM5120_UART_TIE 0x20
55 #define ADM5120_UART_RIE 0x50
56 #define ADM5120_UART_IE 0x78
57 #define ADM5120_UART_CTS 0x01
58 #define ADM5120_UART_DSR 0x02
59 #define ADM5120_UART_DCD 0x04
60 #define ADM5120_UART_TXFF 0x20
61 #define ADM5120_UART_TXFE 0x80
62 #define ADM5120_UART_RXFE 0x10
63 #define ADM5120_UART_BRK 0x01
64 #define ADM5120_UART_PEN 0x02
65 #define ADM5120_UART_EPS 0x04
66 #define ADM5120_UART_STP2 0x08
67 #define ADM5120_UART_W5 0x00
68 #define ADM5120_UART_W6 0x20
69 #define ADM5120_UART_W7 0x40
70 #define ADM5120_UART_W8 0x60
71 #define ADM5120_UART_MIS 0x01
72 #define ADM5120_UART_RIS 0x02
73 #define ADM5120_UART_TIS 0x04
74 #define ADM5120_UART_RTIS 0x08
76 static void adm5120ser_stop_tx(struct uart_port
*port
)
78 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) &= ~ADM5120_UART_TIE
;
81 static void adm5120ser_irq_rx(struct uart_port
*port
)
83 struct tty_struct
*tty
= port
->info
->tty
;
84 unsigned int status
, ch
, rds
, flg
, ignored
= 0;
86 status
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
87 while (!(status
& ADM5120_UART_RXFE
)) {
89 * We need to read rds before reading the
90 * character from the fifo
92 rds
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_RS
);
93 ch
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_DATA
);
97 tty_flip_buffer_push(tty
);
102 * Note that the error handling code is
103 * out of the main execution path
105 if (rds
& ADM5120_UART_ERR
)
107 if (uart_handle_sysrq_char(port
, ch
))
111 tty_insert_flip_char(tty
, ch
, flg
);
114 status
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
117 tty_flip_buffer_push(tty
);
121 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_RS
) = 0xff;
122 if (rds
& ADM5120_UART_BE
) {
124 if (uart_handle_break(port
))
126 } else if (rds
& ADM5120_UART_PE
)
127 port
->icount
.parity
++;
128 else if (rds
& ADM5120_UART_FE
)
129 port
->icount
.frame
++;
130 if (rds
& ADM5120_UART_OE
)
131 port
->icount
.overrun
++;
133 if (rds
& port
->ignore_status_mask
) {
138 rds
&= port
->read_status_mask
;
140 if (rds
& ADM5120_UART_BE
)
142 else if (rds
& ADM5120_UART_PE
)
144 else if (rds
& ADM5120_UART_FE
)
147 if (rds
& ADM5120_UART_OE
) {
149 * CHECK: does overrun affect the current character?
150 * ASSUMPTION: it does not.
152 tty_insert_flip_char(tty
, ch
, flg
);
156 #ifdef CONFIG_MAGIC_SYSRQ
162 static void adm5120ser_irq_tx(struct uart_port
*port
)
164 struct circ_buf
*xmit
= &port
->info
->xmit
;
168 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_DATA
) =
174 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
175 adm5120ser_stop_tx(port
);
179 count
= port
->fifosize
>> 1;
181 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_DATA
) =
182 xmit
->buf
[xmit
->tail
];
183 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
185 if (uart_circ_empty(xmit
))
187 } while (--count
> 0);
189 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
190 uart_write_wakeup(port
);
192 if (uart_circ_empty(xmit
))
193 adm5120ser_stop_tx(port
);
196 static void adm5120ser_irq_modem(struct uart_port
*port
)
200 status
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
202 if (status
& ADM5120_UART_DCD
)
203 uart_handle_dcd_change(port
, status
& ADM5120_UART_DCD
);
205 if (status
& ADM5120_UART_DSR
)
208 if (status
& ADM5120_UART_CTS
)
209 uart_handle_cts_change(port
, status
& ADM5120_UART_CTS
);
211 wake_up_interruptible(&port
->info
->delta_msr_wait
);
214 static irqreturn_t
adm5120ser_irq(int irq
, void *dev_id
)
216 struct uart_port
*port
= dev_id
;
217 unsigned long ir
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_IR
);
219 if (ir
& (ADM5120_UART_RIS
| ADM5120_UART_RTIS
))
220 adm5120ser_irq_rx(port
);
221 if (ir
& ADM5120_UART_TIS
)
222 adm5120ser_irq_tx(port
);
223 if (ir
& ADM5120_UART_MIS
) {
224 adm5120ser_irq_modem(port
);
225 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_IR
) = 0xff;
231 static unsigned int adm5120ser_tx_empty(struct uart_port
*port
)
233 unsigned int fr
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
234 return (fr
& ADM5120_UART_TXFE
) ? TIOCSER_TEMT
: 0;
237 static void adm5120ser_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
241 static unsigned int adm5120ser_get_mctrl(struct uart_port
*port
)
243 unsigned int result
= 0;
244 unsigned int fr
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_FR
);
246 if (fr
& ADM5120_UART_CTS
)
248 if (fr
& ADM5120_UART_DSR
)
250 if (fr
& ADM5120_UART_DCD
)
255 static void adm5120ser_start_tx(struct uart_port
*port
)
257 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) |= ADM5120_UART_TIE
;
260 static void adm5120ser_stop_rx(struct uart_port
*port
)
262 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) &= ~ADM5120_UART_RIE
;
265 static void adm5120ser_enable_ms(struct uart_port
*port
)
269 static void adm5120ser_break_ctl(struct uart_port
*port
, int break_state
)
274 spin_lock_irqsave(&port
->lock
, flags
);
275 lcrh
= ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
);
276 if (break_state
== -1)
277 lcrh
|= ADM5120_UART_BRK
;
279 lcrh
&= ~ADM5120_UART_BRK
;
280 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
) = lcrh
;
281 spin_unlock_irqrestore(&port
->lock
, flags
);
284 static int adm5120ser_startup(struct uart_port
*port
)
288 ret
= request_irq(port
->irq
, adm5120ser_irq
, 0, "ADM5120 UART", port
);
290 printk(KERN_ERR
"Couldn't get irq %d\n", port
->irq
);
293 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
) |=
294 ADM5120_UART_FIFO_EN
;
295 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) |=
296 ADM5120_UART_EN
| ADM5120_UART_IE
;
300 static void adm5120ser_shutdown(struct uart_port
*port
)
302 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_CR
) &= ~ADM5120_UART_IE
;
303 free_irq(port
->irq
, port
);
306 static void adm5120ser_set_termios(struct uart_port
*port
,
307 struct ktermios
*termios
, struct ktermios
*old
)
309 unsigned int baud
, quot
, lcrh
;
312 termios
->c_cflag
|= CREAD
;
314 baud
= uart_get_baud_rate(port
, termios
, old
, 0, port
->uartclk
/16);
315 quot
= uart_get_divisor(port
, baud
);
317 lcrh
= ADM5120_UART_FIFO_EN
;
318 switch (termios
->c_cflag
& CSIZE
) {
320 lcrh
|= ADM5120_UART_W5
;
323 lcrh
|= ADM5120_UART_W6
;
326 lcrh
|= ADM5120_UART_W7
;
329 lcrh
|= ADM5120_UART_W8
;
332 if (termios
->c_cflag
& CSTOPB
)
333 lcrh
|= ADM5120_UART_STP2
;
334 if (termios
->c_cflag
& PARENB
) {
335 lcrh
|= ADM5120_UART_PEN
;
336 if (!(termios
->c_cflag
& PARODD
))
337 lcrh
|= ADM5120_UART_EPS
;
340 spin_lock_irqsave(port
->lock
, flags
);
342 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_H
) = lcrh
;
345 * Update the per-port timeout.
347 uart_update_timeout(port
, termios
->c_cflag
, baud
);
349 port
->read_status_mask
= ADM5120_UART_OE
;
350 if (termios
->c_iflag
& INPCK
)
351 port
->read_status_mask
|= ADM5120_UART_FE
| ADM5120_UART_PE
;
352 if (termios
->c_iflag
& (BRKINT
| PARMRK
))
353 port
->read_status_mask
|= ADM5120_UART_BE
;
356 * Characters to ignore
358 port
->ignore_status_mask
= 0;
359 if (termios
->c_iflag
& IGNPAR
)
360 port
->ignore_status_mask
|= ADM5120_UART_FE
| ADM5120_UART_PE
;
361 if (termios
->c_iflag
& IGNBRK
) {
362 port
->ignore_status_mask
|= ADM5120_UART_BE
;
364 * If we're ignoring parity and break indicators,
365 * ignore overruns to (for real raw support).
367 if (termios
->c_iflag
& IGNPAR
)
368 port
->ignore_status_mask
|= ADM5120_UART_OE
;
371 quot
= ADM5120_UART_BAUD115200
;
372 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_L
) = quot
& 0xff;
373 ADM5120_UART_REG(port
->iobase
, ADM5120_UART_LCR_M
) = quot
>> 8;
375 spin_unlock_irqrestore(&port
->lock
, flags
);
378 static const char *adm5120ser_type(struct uart_port
*port
)
380 return port
->type
== PORT_ADM5120
? "ADM5120" : NULL
;
383 static void adm5120ser_config_port(struct uart_port
*port
, int flags
)
385 if (flags
& UART_CONFIG_TYPE
)
386 port
->type
= PORT_ADM5120
;
389 static void adm5120ser_release_port(struct uart_port
*port
)
391 release_mem_region(port
->iobase
, ADM5120_UART_SIZE
);
394 static int adm5120ser_request_port(struct uart_port
*port
)
396 return request_mem_region(port
->iobase
, ADM5120_UART_SIZE
,
397 "adm5120-uart") != NULL
? 0 : -EBUSY
;
400 static struct uart_ops adm5120ser_ops
= {
401 .tx_empty
= adm5120ser_tx_empty
,
402 .set_mctrl
= adm5120ser_set_mctrl
,
403 .get_mctrl
= adm5120ser_get_mctrl
,
404 .stop_tx
= adm5120ser_stop_tx
,
405 .start_tx
= adm5120ser_start_tx
,
406 .stop_rx
= adm5120ser_stop_rx
,
407 .enable_ms
= adm5120ser_enable_ms
,
408 .break_ctl
= adm5120ser_break_ctl
,
409 .startup
= adm5120ser_startup
,
410 .shutdown
= adm5120ser_shutdown
,
411 .set_termios
= adm5120ser_set_termios
,
412 .type
= adm5120ser_type
,
413 .config_port
= adm5120ser_config_port
,
414 .release_port
= adm5120ser_release_port
,
415 .request_port
= adm5120ser_request_port
,
418 static void adm5120console_put(const char c
)
420 while ((ADM5120_UART_REG(ADM5120_UART0_BASE
, ADM5120_UART_FR
) &
421 ADM5120_UART_TXFF
) != 0);
422 ADM5120_UART_REG(ADM5120_UART0_BASE
, ADM5120_UART_DATA
) = c
;
425 static void adm5120console_write(struct console
*con
, const char *s
,
430 adm5120console_put('\r');
431 adm5120console_put(*s
);
436 static int __init
adm5120console_setup(struct console
*con
, char *options
)
438 /* Set to 115200 baud, 8N1 and enable FIFO */
439 ADM5120_UART_REG(ADM5120_UART0_BASE
, ADM5120_UART_LCR_L
) =
440 ADM5120_UART_BAUD115200
& 0xff;
441 ADM5120_UART_REG(ADM5120_UART0_BASE
, ADM5120_UART_LCR_M
) =
442 ADM5120_UART_BAUD115200
>> 8;
443 ADM5120_UART_REG(ADM5120_UART0_BASE
, ADM5120_UART_LCR_H
) =
444 ADM5120_UART_W8
| ADM5120_UART_FIFO_EN
;
446 ADM5120_UART_REG(ADM5120_UART0_BASE
, ADM5120_UART_CR
) =
452 static struct uart_driver adm5120ser_reg
;
454 static struct console adm5120_serconsole
= {
456 .write
= adm5120console_write
,
457 .device
= uart_console_device
,
458 .setup
= adm5120console_setup
,
459 .flags
= CON_PRINTBUFFER
,
460 .cflag
= B115200
| CS8
| CREAD
,
462 .data
= &adm5120ser_reg
,
465 static int __init
adm5120console_init(void)
467 register_console(&adm5120_serconsole
);
471 console_initcall(adm5120console_init
);
474 static struct uart_port adm5120ser_ports
[] = {
476 .iobase
= ADM5120_UART0_BASE
,
477 .irq
= ADM5120_IRQ_UART0
,
478 .uartclk
= ADM5120_UARTCLK_FREQ
,
480 .ops
= &adm5120ser_ops
,
482 .flags
= ASYNC_BOOT_AUTOCONF
,
484 #if (CONFIG_ADM5120_NR_UARTS > 1)
486 .iobase
= ADM5120_UART1_BASE
,
487 .irq
= ADM5120_IRQ_UART1
,
488 .uartclk
= ADM5120_UARTCLK_FREQ
,
490 .ops
= &adm5120ser_ops
,
492 .flags
= ASYNC_BOOT_AUTOCONF
,
497 static struct uart_driver adm5120ser_reg
= {
498 .owner
= THIS_MODULE
,
499 .driver_name
= "ttyS",
503 .nr
= CONFIG_ADM5120_NR_UARTS
,
504 .cons
= &adm5120_serconsole
,
507 static int __init
adm5120ser_init(void)
511 ret
= uart_register_driver(&adm5120ser_reg
);
513 for (i
= 0; i
< CONFIG_ADM5120_NR_UARTS
; i
++)
514 uart_add_one_port(&adm5120ser_reg
, &adm5120ser_ports
[i
]);
520 __initcall(adm5120ser_init
);