1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for CLPS711x serial ports
5 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
7 * Copyright 1999 ARM Limited
8 * Copyright (C) 2000 Deep Blue Solutions Ltd.
11 #include <linux/module.h>
12 #include <linux/device.h>
13 #include <linux/console.h>
14 #include <linux/serial_core.h>
15 #include <linux/serial.h>
16 #include <linux/clk.h>
18 #include <linux/tty.h>
19 #include <linux/tty_flip.h>
20 #include <linux/ioport.h>
22 #include <linux/platform_device.h>
23 #include <linux/regmap.h>
25 #include <linux/mfd/syscon.h>
26 #include <linux/mfd/syscon/clps711x.h>
28 #include "serial_mctrl_gpio.h"
30 #define UART_CLPS711X_DEVNAME "ttyCL"
31 #define UART_CLPS711X_NR 2
32 #define UART_CLPS711X_MAJOR 204
33 #define UART_CLPS711X_MINOR 40
35 #define UARTDR_OFFSET (0x00)
36 #define UBRLCR_OFFSET (0x40)
38 #define UARTDR_FRMERR (1 << 8)
39 #define UARTDR_PARERR (1 << 9)
40 #define UARTDR_OVERR (1 << 10)
42 #define UBRLCR_BAUD_MASK ((1 << 12) - 1)
43 #define UBRLCR_BREAK (1 << 12)
44 #define UBRLCR_PRTEN (1 << 13)
45 #define UBRLCR_EVENPRT (1 << 14)
46 #define UBRLCR_XSTOP (1 << 15)
47 #define UBRLCR_FIFOEN (1 << 16)
48 #define UBRLCR_WRDLEN5 (0 << 17)
49 #define UBRLCR_WRDLEN6 (1 << 17)
50 #define UBRLCR_WRDLEN7 (2 << 17)
51 #define UBRLCR_WRDLEN8 (3 << 17)
52 #define UBRLCR_WRDLEN_MASK (3 << 17)
54 struct clps711x_port
{
55 struct uart_port port
;
56 unsigned int tx_enabled
;
58 struct regmap
*syscon
;
59 struct mctrl_gpios
*gpios
;
62 static struct uart_driver clps711x_uart
= {
64 .driver_name
= UART_CLPS711X_DEVNAME
,
65 .dev_name
= UART_CLPS711X_DEVNAME
,
66 .major
= UART_CLPS711X_MAJOR
,
67 .minor
= UART_CLPS711X_MINOR
,
68 .nr
= UART_CLPS711X_NR
,
71 static void uart_clps711x_stop_tx(struct uart_port
*port
)
73 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
76 disable_irq(port
->irq
);
81 static void uart_clps711x_start_tx(struct uart_port
*port
)
83 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
87 enable_irq(port
->irq
);
91 static irqreturn_t
uart_clps711x_int_rx(int irq
, void *dev_id
)
93 struct uart_port
*port
= dev_id
;
94 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
102 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
103 if (sysflg
& SYSFLG_URXFE
)
106 ch
= readw(port
->membase
+ UARTDR_OFFSET
);
107 status
= ch
& (UARTDR_FRMERR
| UARTDR_PARERR
| UARTDR_OVERR
);
113 if (unlikely(status
)) {
114 if (status
& UARTDR_PARERR
)
115 port
->icount
.parity
++;
116 else if (status
& UARTDR_FRMERR
)
117 port
->icount
.frame
++;
118 else if (status
& UARTDR_OVERR
)
119 port
->icount
.overrun
++;
121 status
&= port
->read_status_mask
;
123 if (status
& UARTDR_PARERR
)
125 else if (status
& UARTDR_FRMERR
)
127 else if (status
& UARTDR_OVERR
)
131 if (uart_handle_sysrq_char(port
, ch
))
134 if (status
& port
->ignore_status_mask
)
137 uart_insert_char(port
, status
, UARTDR_OVERR
, ch
, flg
);
140 tty_flip_buffer_push(&port
->state
->port
);
145 static irqreturn_t
uart_clps711x_int_tx(int irq
, void *dev_id
)
147 struct uart_port
*port
= dev_id
;
148 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
149 struct tty_port
*tport
= &port
->state
->port
;
153 writew(port
->x_char
, port
->membase
+ UARTDR_OFFSET
);
159 if (kfifo_is_empty(&tport
->xmit_fifo
) || uart_tx_stopped(port
)) {
161 disable_irq_nosync(port
->irq
);
167 while (uart_fifo_get(port
, &c
)) {
170 writew(c
, port
->membase
+ UARTDR_OFFSET
);
172 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
173 if (sysflg
& SYSFLG_UTXFF
)
177 if (kfifo_len(&tport
->xmit_fifo
) < WAKEUP_CHARS
)
178 uart_write_wakeup(port
);
183 static unsigned int uart_clps711x_tx_empty(struct uart_port
*port
)
185 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
188 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
190 return (sysflg
& SYSFLG_UBUSY
) ? 0 : TIOCSER_TEMT
;
193 static unsigned int uart_clps711x_get_mctrl(struct uart_port
*port
)
195 unsigned int result
= TIOCM_DSR
| TIOCM_CTS
| TIOCM_CAR
;
196 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
198 return mctrl_gpio_get(s
->gpios
, &result
);
201 static void uart_clps711x_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
203 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
205 mctrl_gpio_set(s
->gpios
, mctrl
);
208 static void uart_clps711x_break_ctl(struct uart_port
*port
, int break_state
)
212 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
214 ubrlcr
|= UBRLCR_BREAK
;
216 ubrlcr
&= ~UBRLCR_BREAK
;
217 writel(ubrlcr
, port
->membase
+ UBRLCR_OFFSET
);
220 static void uart_clps711x_set_ldisc(struct uart_port
*port
,
221 struct ktermios
*termios
)
224 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
226 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON1_SIREN
,
227 (termios
->c_line
== N_IRDA
) ? SYSCON1_SIREN
: 0);
231 static int uart_clps711x_startup(struct uart_port
*port
)
233 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
236 writel(readl(port
->membase
+ UBRLCR_OFFSET
) & ~UBRLCR_BREAK
,
237 port
->membase
+ UBRLCR_OFFSET
);
239 /* Enable the port */
240 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
241 SYSCON_UARTEN
, SYSCON_UARTEN
);
244 static void uart_clps711x_shutdown(struct uart_port
*port
)
246 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
248 /* Disable the port */
249 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
252 static void uart_clps711x_set_termios(struct uart_port
*port
,
253 struct ktermios
*termios
,
254 const struct ktermios
*old
)
257 unsigned int baud
, quot
;
259 /* Mask termios capabilities we don't support */
260 termios
->c_cflag
&= ~CMSPAR
;
261 termios
->c_iflag
&= ~(BRKINT
| IGNBRK
);
263 /* Ask the core to calculate the divisor for us */
264 baud
= uart_get_baud_rate(port
, termios
, old
, port
->uartclk
/ 4096,
266 quot
= uart_get_divisor(port
, baud
);
268 switch (termios
->c_cflag
& CSIZE
) {
270 ubrlcr
= UBRLCR_WRDLEN5
;
273 ubrlcr
= UBRLCR_WRDLEN6
;
276 ubrlcr
= UBRLCR_WRDLEN7
;
280 ubrlcr
= UBRLCR_WRDLEN8
;
284 if (termios
->c_cflag
& CSTOPB
)
285 ubrlcr
|= UBRLCR_XSTOP
;
287 if (termios
->c_cflag
& PARENB
) {
288 ubrlcr
|= UBRLCR_PRTEN
;
289 if (!(termios
->c_cflag
& PARODD
))
290 ubrlcr
|= UBRLCR_EVENPRT
;
294 ubrlcr
|= UBRLCR_FIFOEN
;
296 /* Set read status mask */
297 port
->read_status_mask
= UARTDR_OVERR
;
298 if (termios
->c_iflag
& INPCK
)
299 port
->read_status_mask
|= UARTDR_PARERR
| UARTDR_FRMERR
;
301 /* Set status ignore mask */
302 port
->ignore_status_mask
= 0;
303 if (!(termios
->c_cflag
& CREAD
))
304 port
->ignore_status_mask
|= UARTDR_OVERR
| UARTDR_PARERR
|
307 uart_update_timeout(port
, termios
->c_cflag
, baud
);
309 writel(ubrlcr
| (quot
- 1), port
->membase
+ UBRLCR_OFFSET
);
312 static const char *uart_clps711x_type(struct uart_port
*port
)
314 return (port
->type
== PORT_CLPS711X
) ? "CLPS711X" : NULL
;
317 static void uart_clps711x_config_port(struct uart_port
*port
, int flags
)
319 if (flags
& UART_CONFIG_TYPE
)
320 port
->type
= PORT_CLPS711X
;
323 static void uart_clps711x_nop_void(struct uart_port
*port
)
327 static int uart_clps711x_nop_int(struct uart_port
*port
)
332 static const struct uart_ops uart_clps711x_ops
= {
333 .tx_empty
= uart_clps711x_tx_empty
,
334 .set_mctrl
= uart_clps711x_set_mctrl
,
335 .get_mctrl
= uart_clps711x_get_mctrl
,
336 .stop_tx
= uart_clps711x_stop_tx
,
337 .start_tx
= uart_clps711x_start_tx
,
338 .stop_rx
= uart_clps711x_nop_void
,
339 .break_ctl
= uart_clps711x_break_ctl
,
340 .set_ldisc
= uart_clps711x_set_ldisc
,
341 .startup
= uart_clps711x_startup
,
342 .shutdown
= uart_clps711x_shutdown
,
343 .set_termios
= uart_clps711x_set_termios
,
344 .type
= uart_clps711x_type
,
345 .config_port
= uart_clps711x_config_port
,
346 .release_port
= uart_clps711x_nop_void
,
347 .request_port
= uart_clps711x_nop_int
,
350 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
351 static void uart_clps711x_console_putchar(struct uart_port
*port
, unsigned char ch
)
353 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
356 /* Wait for FIFO is not full */
358 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
359 } while (sysflg
& SYSFLG_UTXFF
);
361 writew(ch
, port
->membase
+ UARTDR_OFFSET
);
364 static void uart_clps711x_console_write(struct console
*co
, const char *c
,
367 struct uart_port
*port
= clps711x_uart
.state
[co
->index
].uart_port
;
368 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
371 uart_console_write(port
, c
, n
, uart_clps711x_console_putchar
);
373 /* Wait for transmitter to become empty */
375 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
376 } while (sysflg
& SYSFLG_UBUSY
);
379 static int uart_clps711x_console_setup(struct console
*co
, char *options
)
381 int baud
= 38400, bits
= 8, parity
= 'n', flow
= 'n';
382 int ret
, index
= co
->index
;
383 struct clps711x_port
*s
;
384 struct uart_port
*port
;
388 if (index
< 0 || index
>= UART_CLPS711X_NR
)
391 port
= clps711x_uart
.state
[index
].uart_port
;
395 s
= dev_get_drvdata(port
->dev
);
400 regmap_read(s
->syscon
, SYSCON_OFFSET
, &syscon
);
401 if (syscon
& SYSCON_UARTEN
) {
402 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
404 if (ubrlcr
& UBRLCR_PRTEN
) {
405 if (ubrlcr
& UBRLCR_EVENPRT
)
411 if ((ubrlcr
& UBRLCR_WRDLEN_MASK
) == UBRLCR_WRDLEN7
)
414 quot
= ubrlcr
& UBRLCR_BAUD_MASK
;
415 baud
= port
->uartclk
/ (16 * (quot
+ 1));
418 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
420 ret
= uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
424 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
425 SYSCON_UARTEN
, SYSCON_UARTEN
);
428 static struct console clps711x_console
= {
429 .name
= UART_CLPS711X_DEVNAME
,
430 .device
= uart_console_device
,
431 .write
= uart_clps711x_console_write
,
432 .setup
= uart_clps711x_console_setup
,
433 .flags
= CON_PRINTBUFFER
,
438 static int uart_clps711x_probe(struct platform_device
*pdev
)
440 struct device_node
*np
= pdev
->dev
.of_node
;
441 struct clps711x_port
*s
;
442 struct resource
*res
;
443 struct clk
*uart_clk
;
446 s
= devm_kzalloc(&pdev
->dev
, sizeof(*s
), GFP_KERNEL
);
450 uart_clk
= devm_clk_get(&pdev
->dev
, NULL
);
451 if (IS_ERR(uart_clk
))
452 return PTR_ERR(uart_clk
);
454 s
->port
.membase
= devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
455 if (IS_ERR(s
->port
.membase
))
456 return PTR_ERR(s
->port
.membase
);
458 irq
= platform_get_irq(pdev
, 0);
463 s
->rx_irq
= platform_get_irq(pdev
, 1);
467 s
->syscon
= syscon_regmap_lookup_by_phandle(np
, "syscon");
468 if (IS_ERR(s
->syscon
))
469 return PTR_ERR(s
->syscon
);
471 s
->port
.line
= of_alias_get_id(np
, "serial");
472 s
->port
.dev
= &pdev
->dev
;
473 s
->port
.iotype
= UPIO_MEM32
;
474 s
->port
.mapbase
= res
->start
;
475 s
->port
.type
= PORT_CLPS711X
;
476 s
->port
.fifosize
= 16;
477 s
->port
.has_sysrq
= IS_ENABLED(CONFIG_SERIAL_CLPS711X_CONSOLE
);
478 s
->port
.flags
= UPF_SKIP_TEST
| UPF_FIXED_TYPE
;
479 s
->port
.uartclk
= clk_get_rate(uart_clk
);
480 s
->port
.ops
= &uart_clps711x_ops
;
482 platform_set_drvdata(pdev
, s
);
484 s
->gpios
= mctrl_gpio_init_noauto(&pdev
->dev
, 0);
485 if (IS_ERR(s
->gpios
))
486 return PTR_ERR(s
->gpios
);
488 ret
= uart_add_one_port(&clps711x_uart
, &s
->port
);
493 if (!uart_console(&s
->port
))
494 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
498 ret
= devm_request_irq(&pdev
->dev
, s
->port
.irq
, uart_clps711x_int_tx
, 0,
499 dev_name(&pdev
->dev
), &s
->port
);
501 uart_remove_one_port(&clps711x_uart
, &s
->port
);
505 ret
= devm_request_irq(&pdev
->dev
, s
->rx_irq
, uart_clps711x_int_rx
, 0,
506 dev_name(&pdev
->dev
), &s
->port
);
508 uart_remove_one_port(&clps711x_uart
, &s
->port
);
513 static void uart_clps711x_remove(struct platform_device
*pdev
)
515 struct clps711x_port
*s
= platform_get_drvdata(pdev
);
517 uart_remove_one_port(&clps711x_uart
, &s
->port
);
520 static const struct of_device_id __maybe_unused clps711x_uart_dt_ids
[] = {
521 { .compatible
= "cirrus,ep7209-uart", },
524 MODULE_DEVICE_TABLE(of
, clps711x_uart_dt_ids
);
526 static struct platform_driver clps711x_uart_platform
= {
528 .name
= "clps711x-uart",
529 .of_match_table
= of_match_ptr(clps711x_uart_dt_ids
),
531 .probe
= uart_clps711x_probe
,
532 .remove
= uart_clps711x_remove
,
535 static int __init
uart_clps711x_init(void)
539 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
540 clps711x_uart
.cons
= &clps711x_console
;
541 clps711x_console
.data
= &clps711x_uart
;
544 ret
= uart_register_driver(&clps711x_uart
);
548 return platform_driver_register(&clps711x_uart_platform
);
550 module_init(uart_clps711x_init
);
552 static void __exit
uart_clps711x_exit(void)
554 platform_driver_unregister(&clps711x_uart_platform
);
555 uart_unregister_driver(&clps711x_uart
);
557 module_exit(uart_clps711x_exit
);
559 MODULE_AUTHOR("Deep Blue Solutions Ltd");
560 MODULE_DESCRIPTION("CLPS711X serial driver");
561 MODULE_LICENSE("GPL");