2 * Driver for CLPS711x serial ports
4 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
6 * Copyright 1999 ARM Limited
7 * Copyright (C) 2000 Deep Blue Solutions Ltd.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
15 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
19 #include <linux/module.h>
20 #include <linux/device.h>
21 #include <linux/console.h>
22 #include <linux/serial_core.h>
23 #include <linux/serial.h>
24 #include <linux/clk.h>
26 #include <linux/tty.h>
27 #include <linux/tty_flip.h>
28 #include <linux/ioport.h>
30 #include <linux/platform_device.h>
31 #include <linux/regmap.h>
33 #include <linux/mfd/syscon.h>
34 #include <linux/mfd/syscon/clps711x.h>
36 #define UART_CLPS711X_DEVNAME "ttyCL"
37 #define UART_CLPS711X_NR 2
38 #define UART_CLPS711X_MAJOR 204
39 #define UART_CLPS711X_MINOR 40
41 #define UARTDR_OFFSET (0x00)
42 #define UBRLCR_OFFSET (0x40)
44 #define UARTDR_FRMERR (1 << 8)
45 #define UARTDR_PARERR (1 << 9)
46 #define UARTDR_OVERR (1 << 10)
48 #define UBRLCR_BAUD_MASK ((1 << 12) - 1)
49 #define UBRLCR_BREAK (1 << 12)
50 #define UBRLCR_PRTEN (1 << 13)
51 #define UBRLCR_EVENPRT (1 << 14)
52 #define UBRLCR_XSTOP (1 << 15)
53 #define UBRLCR_FIFOEN (1 << 16)
54 #define UBRLCR_WRDLEN5 (0 << 17)
55 #define UBRLCR_WRDLEN6 (1 << 17)
56 #define UBRLCR_WRDLEN7 (2 << 17)
57 #define UBRLCR_WRDLEN8 (3 << 17)
58 #define UBRLCR_WRDLEN_MASK (3 << 17)
60 struct clps711x_port
{
61 struct uart_port port
;
62 unsigned int tx_enabled
;
64 struct regmap
*syscon
;
68 static struct uart_driver clps711x_uart
= {
70 .driver_name
= UART_CLPS711X_DEVNAME
,
71 .dev_name
= UART_CLPS711X_DEVNAME
,
72 .major
= UART_CLPS711X_MAJOR
,
73 .minor
= UART_CLPS711X_MINOR
,
74 .nr
= UART_CLPS711X_NR
,
77 static void uart_clps711x_stop_tx(struct uart_port
*port
)
79 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
82 disable_irq(port
->irq
);
87 static void uart_clps711x_start_tx(struct uart_port
*port
)
89 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
93 enable_irq(port
->irq
);
97 static irqreturn_t
uart_clps711x_int_rx(int irq
, void *dev_id
)
99 struct uart_port
*port
= dev_id
;
100 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
101 unsigned int status
, flg
;
107 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
108 if (sysflg
& SYSFLG_URXFE
)
111 ch
= readw(port
->membase
+ UARTDR_OFFSET
);
112 status
= ch
& (UARTDR_FRMERR
| UARTDR_PARERR
| UARTDR_OVERR
);
118 if (unlikely(status
)) {
119 if (status
& UARTDR_PARERR
)
120 port
->icount
.parity
++;
121 else if (status
& UARTDR_FRMERR
)
122 port
->icount
.frame
++;
123 else if (status
& UARTDR_OVERR
)
124 port
->icount
.overrun
++;
126 status
&= port
->read_status_mask
;
128 if (status
& UARTDR_PARERR
)
130 else if (status
& UARTDR_FRMERR
)
132 else if (status
& UARTDR_OVERR
)
136 if (uart_handle_sysrq_char(port
, ch
))
139 if (status
& port
->ignore_status_mask
)
142 uart_insert_char(port
, status
, UARTDR_OVERR
, ch
, flg
);
145 tty_flip_buffer_push(&port
->state
->port
);
150 static irqreturn_t
uart_clps711x_int_tx(int irq
, void *dev_id
)
152 struct uart_port
*port
= dev_id
;
153 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
154 struct circ_buf
*xmit
= &port
->state
->xmit
;
157 writew(port
->x_char
, port
->membase
+ UARTDR_OFFSET
);
163 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
165 disable_irq_nosync(port
->irq
);
171 while (!uart_circ_empty(xmit
)) {
174 writew(xmit
->buf
[xmit
->tail
], port
->membase
+ UARTDR_OFFSET
);
175 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
178 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
179 if (sysflg
& SYSFLG_UTXFF
)
183 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
184 uart_write_wakeup(port
);
189 static unsigned int uart_clps711x_tx_empty(struct uart_port
*port
)
191 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
194 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
196 return (sysflg
& SYSFLG_UBUSY
) ? 0 : TIOCSER_TEMT
;
199 static unsigned int uart_clps711x_get_mctrl(struct uart_port
*port
)
201 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
202 unsigned int result
= 0;
207 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
208 if (sysflg
& SYSFLG1_DCD
)
210 if (sysflg
& SYSFLG1_DSR
)
212 if (sysflg
& SYSFLG1_CTS
)
215 result
= TIOCM_DSR
| TIOCM_CTS
| TIOCM_CAR
;
220 static void uart_clps711x_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
225 static void uart_clps711x_break_ctl(struct uart_port
*port
, int break_state
)
229 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
231 ubrlcr
|= UBRLCR_BREAK
;
233 ubrlcr
&= ~UBRLCR_BREAK
;
234 writel(ubrlcr
, port
->membase
+ UBRLCR_OFFSET
);
237 static void uart_clps711x_set_ldisc(struct uart_port
*port
, int ld
)
240 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
242 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON1_SIREN
,
243 (ld
== N_IRDA
) ? SYSCON1_SIREN
: 0);
247 static int uart_clps711x_startup(struct uart_port
*port
)
249 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
252 writel(readl(port
->membase
+ UBRLCR_OFFSET
) & ~UBRLCR_BREAK
,
253 port
->membase
+ UBRLCR_OFFSET
);
255 /* Enable the port */
256 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
257 SYSCON_UARTEN
, SYSCON_UARTEN
);
260 static void uart_clps711x_shutdown(struct uart_port
*port
)
262 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
264 /* Disable the port */
265 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
268 static void uart_clps711x_set_termios(struct uart_port
*port
,
269 struct ktermios
*termios
,
270 struct ktermios
*old
)
273 unsigned int baud
, quot
;
275 /* Mask termios capabilities we don't support */
276 termios
->c_cflag
&= ~CMSPAR
;
277 termios
->c_iflag
&= ~(BRKINT
| IGNBRK
);
279 /* Ask the core to calculate the divisor for us */
280 baud
= uart_get_baud_rate(port
, termios
, old
, port
->uartclk
/ 4096,
282 quot
= uart_get_divisor(port
, baud
);
284 switch (termios
->c_cflag
& CSIZE
) {
286 ubrlcr
= UBRLCR_WRDLEN5
;
289 ubrlcr
= UBRLCR_WRDLEN6
;
292 ubrlcr
= UBRLCR_WRDLEN7
;
296 ubrlcr
= UBRLCR_WRDLEN8
;
300 if (termios
->c_cflag
& CSTOPB
)
301 ubrlcr
|= UBRLCR_XSTOP
;
303 if (termios
->c_cflag
& PARENB
) {
304 ubrlcr
|= UBRLCR_PRTEN
;
305 if (!(termios
->c_cflag
& PARODD
))
306 ubrlcr
|= UBRLCR_EVENPRT
;
310 ubrlcr
|= UBRLCR_FIFOEN
;
312 /* Set read status mask */
313 port
->read_status_mask
= UARTDR_OVERR
;
314 if (termios
->c_iflag
& INPCK
)
315 port
->read_status_mask
|= UARTDR_PARERR
| UARTDR_FRMERR
;
317 /* Set status ignore mask */
318 port
->ignore_status_mask
= 0;
319 if (!(termios
->c_cflag
& CREAD
))
320 port
->ignore_status_mask
|= UARTDR_OVERR
| UARTDR_PARERR
|
323 uart_update_timeout(port
, termios
->c_cflag
, baud
);
325 writel(ubrlcr
| (quot
- 1), port
->membase
+ UBRLCR_OFFSET
);
328 static const char *uart_clps711x_type(struct uart_port
*port
)
330 return (port
->type
== PORT_CLPS711X
) ? "CLPS711X" : NULL
;
333 static void uart_clps711x_config_port(struct uart_port
*port
, int flags
)
335 if (flags
& UART_CONFIG_TYPE
)
336 port
->type
= PORT_CLPS711X
;
339 static void uart_clps711x_nop_void(struct uart_port
*port
)
343 static int uart_clps711x_nop_int(struct uart_port
*port
)
348 static const struct uart_ops uart_clps711x_ops
= {
349 .tx_empty
= uart_clps711x_tx_empty
,
350 .set_mctrl
= uart_clps711x_set_mctrl
,
351 .get_mctrl
= uart_clps711x_get_mctrl
,
352 .stop_tx
= uart_clps711x_stop_tx
,
353 .start_tx
= uart_clps711x_start_tx
,
354 .stop_rx
= uart_clps711x_nop_void
,
355 .enable_ms
= uart_clps711x_nop_void
,
356 .break_ctl
= uart_clps711x_break_ctl
,
357 .set_ldisc
= uart_clps711x_set_ldisc
,
358 .startup
= uart_clps711x_startup
,
359 .shutdown
= uart_clps711x_shutdown
,
360 .set_termios
= uart_clps711x_set_termios
,
361 .type
= uart_clps711x_type
,
362 .config_port
= uart_clps711x_config_port
,
363 .release_port
= uart_clps711x_nop_void
,
364 .request_port
= uart_clps711x_nop_int
,
367 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
368 static void uart_clps711x_console_putchar(struct uart_port
*port
, int ch
)
370 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
374 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
375 } while (sysflg
& SYSFLG_UTXFF
);
377 writew(ch
, port
->membase
+ UARTDR_OFFSET
);
380 static void uart_clps711x_console_write(struct console
*co
, const char *c
,
383 struct uart_port
*port
= clps711x_uart
.state
[co
->index
].uart_port
;
384 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
387 uart_console_write(port
, c
, n
, uart_clps711x_console_putchar
);
389 /* Wait for transmitter to become empty */
391 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
392 } while (sysflg
& SYSFLG_UBUSY
);
395 static int uart_clps711x_console_setup(struct console
*co
, char *options
)
397 int baud
= 38400, bits
= 8, parity
= 'n', flow
= 'n';
398 int ret
, index
= co
->index
;
399 struct clps711x_port
*s
;
400 struct uart_port
*port
;
404 if (index
< 0 || index
>= UART_CLPS711X_NR
)
407 port
= clps711x_uart
.state
[index
].uart_port
;
411 s
= dev_get_drvdata(port
->dev
);
416 regmap_read(s
->syscon
, SYSCON_OFFSET
, &syscon
);
417 if (syscon
& SYSCON_UARTEN
) {
418 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
420 if (ubrlcr
& UBRLCR_PRTEN
) {
421 if (ubrlcr
& UBRLCR_EVENPRT
)
427 if ((ubrlcr
& UBRLCR_WRDLEN_MASK
) == UBRLCR_WRDLEN7
)
430 quot
= ubrlcr
& UBRLCR_BAUD_MASK
;
431 baud
= port
->uartclk
/ (16 * (quot
+ 1));
434 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
436 ret
= uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
440 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
441 SYSCON_UARTEN
, SYSCON_UARTEN
);
444 static struct console clps711x_console
= {
445 .name
= UART_CLPS711X_DEVNAME
,
446 .device
= uart_console_device
,
447 .write
= uart_clps711x_console_write
,
448 .setup
= uart_clps711x_console_setup
,
449 .flags
= CON_PRINTBUFFER
,
454 static int uart_clps711x_probe(struct platform_device
*pdev
)
456 struct device_node
*np
= pdev
->dev
.of_node
;
457 int ret
, index
= np
? of_alias_get_id(np
, "serial") : pdev
->id
;
458 struct clps711x_port
*s
;
459 struct resource
*res
;
460 struct clk
*uart_clk
;
462 if (index
< 0 || index
>= UART_CLPS711X_NR
)
465 s
= devm_kzalloc(&pdev
->dev
, sizeof(*s
), GFP_KERNEL
);
469 uart_clk
= devm_clk_get(&pdev
->dev
, NULL
);
470 if (IS_ERR(uart_clk
))
471 return PTR_ERR(uart_clk
);
473 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
474 s
->port
.membase
= devm_ioremap_resource(&pdev
->dev
, res
);
475 if (IS_ERR(s
->port
.membase
))
476 return PTR_ERR(s
->port
.membase
);
478 s
->port
.irq
= platform_get_irq(pdev
, 0);
479 if (IS_ERR_VALUE(s
->port
.irq
))
482 s
->rx_irq
= platform_get_irq(pdev
, 1);
483 if (IS_ERR_VALUE(s
->rx_irq
))
489 sprintf(syscon_name
, "syscon.%i", index
+ 1);
490 s
->syscon
= syscon_regmap_lookup_by_pdevname(syscon_name
);
491 if (IS_ERR(s
->syscon
))
492 return PTR_ERR(s
->syscon
);
496 s
->syscon
= syscon_regmap_lookup_by_phandle(np
, "syscon");
497 if (IS_ERR(s
->syscon
))
498 return PTR_ERR(s
->syscon
);
501 s
->use_ms
= of_property_read_bool(np
, "uart-use-ms");
504 s
->port
.line
= index
;
505 s
->port
.dev
= &pdev
->dev
;
506 s
->port
.iotype
= UPIO_MEM32
;
507 s
->port
.mapbase
= res
->start
;
508 s
->port
.type
= PORT_CLPS711X
;
509 s
->port
.fifosize
= 16;
510 s
->port
.flags
= UPF_SKIP_TEST
| UPF_FIXED_TYPE
;
511 s
->port
.uartclk
= clk_get_rate(uart_clk
);
512 s
->port
.ops
= &uart_clps711x_ops
;
514 platform_set_drvdata(pdev
, s
);
516 ret
= uart_add_one_port(&clps711x_uart
, &s
->port
);
521 if (!uart_console(&s
->port
))
522 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
526 ret
= devm_request_irq(&pdev
->dev
, s
->port
.irq
, uart_clps711x_int_tx
, 0,
527 dev_name(&pdev
->dev
), &s
->port
);
529 uart_remove_one_port(&clps711x_uart
, &s
->port
);
533 ret
= devm_request_irq(&pdev
->dev
, s
->rx_irq
, uart_clps711x_int_rx
, 0,
534 dev_name(&pdev
->dev
), &s
->port
);
536 uart_remove_one_port(&clps711x_uart
, &s
->port
);
541 static int uart_clps711x_remove(struct platform_device
*pdev
)
543 struct clps711x_port
*s
= platform_get_drvdata(pdev
);
545 return uart_remove_one_port(&clps711x_uart
, &s
->port
);
548 static const struct of_device_id __maybe_unused clps711x_uart_dt_ids
[] = {
549 { .compatible
= "cirrus,clps711x-uart", },
552 MODULE_DEVICE_TABLE(of
, clps711x_uart_dt_ids
);
554 static struct platform_driver clps711x_uart_platform
= {
556 .name
= "clps711x-uart",
557 .owner
= THIS_MODULE
,
558 .of_match_table
= of_match_ptr(clps711x_uart_dt_ids
),
560 .probe
= uart_clps711x_probe
,
561 .remove
= uart_clps711x_remove
,
564 static int __init
uart_clps711x_init(void)
568 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
569 clps711x_uart
.cons
= &clps711x_console
;
570 clps711x_console
.data
= &clps711x_uart
;
573 ret
= uart_register_driver(&clps711x_uart
);
577 return platform_driver_register(&clps711x_uart_platform
);
579 module_init(uart_clps711x_init
);
581 static void __exit
uart_clps711x_exit(void)
583 platform_driver_unregister(&clps711x_uart_platform
);
584 uart_unregister_driver(&clps711x_uart
);
586 module_exit(uart_clps711x_exit
);
588 MODULE_AUTHOR("Deep Blue Solutions Ltd");
589 MODULE_DESCRIPTION("CLPS711X serial driver");
590 MODULE_LICENSE("GPL");