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 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
15 #include <linux/module.h>
16 #include <linux/device.h>
17 #include <linux/console.h>
18 #include <linux/serial_core.h>
19 #include <linux/serial.h>
20 #include <linux/clk.h>
22 #include <linux/tty.h>
23 #include <linux/tty_flip.h>
24 #include <linux/ioport.h>
26 #include <linux/platform_device.h>
27 #include <linux/regmap.h>
29 #include <linux/mfd/syscon.h>
30 #include <linux/mfd/syscon/clps711x.h>
32 #include "serial_mctrl_gpio.h"
34 #define UART_CLPS711X_DEVNAME "ttyCL"
35 #define UART_CLPS711X_NR 2
36 #define UART_CLPS711X_MAJOR 204
37 #define UART_CLPS711X_MINOR 40
39 #define UARTDR_OFFSET (0x00)
40 #define UBRLCR_OFFSET (0x40)
42 #define UARTDR_FRMERR (1 << 8)
43 #define UARTDR_PARERR (1 << 9)
44 #define UARTDR_OVERR (1 << 10)
46 #define UBRLCR_BAUD_MASK ((1 << 12) - 1)
47 #define UBRLCR_BREAK (1 << 12)
48 #define UBRLCR_PRTEN (1 << 13)
49 #define UBRLCR_EVENPRT (1 << 14)
50 #define UBRLCR_XSTOP (1 << 15)
51 #define UBRLCR_FIFOEN (1 << 16)
52 #define UBRLCR_WRDLEN5 (0 << 17)
53 #define UBRLCR_WRDLEN6 (1 << 17)
54 #define UBRLCR_WRDLEN7 (2 << 17)
55 #define UBRLCR_WRDLEN8 (3 << 17)
56 #define UBRLCR_WRDLEN_MASK (3 << 17)
58 struct clps711x_port
{
59 struct uart_port port
;
60 unsigned int tx_enabled
;
62 struct regmap
*syscon
;
63 struct mctrl_gpios
*gpios
;
66 static struct uart_driver clps711x_uart
= {
68 .driver_name
= UART_CLPS711X_DEVNAME
,
69 .dev_name
= UART_CLPS711X_DEVNAME
,
70 .major
= UART_CLPS711X_MAJOR
,
71 .minor
= UART_CLPS711X_MINOR
,
72 .nr
= UART_CLPS711X_NR
,
75 static void uart_clps711x_stop_tx(struct uart_port
*port
)
77 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
80 disable_irq(port
->irq
);
85 static void uart_clps711x_start_tx(struct uart_port
*port
)
87 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
91 enable_irq(port
->irq
);
95 static irqreturn_t
uart_clps711x_int_rx(int irq
, void *dev_id
)
97 struct uart_port
*port
= dev_id
;
98 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
99 unsigned int status
, flg
;
105 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
106 if (sysflg
& SYSFLG_URXFE
)
109 ch
= readw(port
->membase
+ UARTDR_OFFSET
);
110 status
= ch
& (UARTDR_FRMERR
| UARTDR_PARERR
| UARTDR_OVERR
);
116 if (unlikely(status
)) {
117 if (status
& UARTDR_PARERR
)
118 port
->icount
.parity
++;
119 else if (status
& UARTDR_FRMERR
)
120 port
->icount
.frame
++;
121 else if (status
& UARTDR_OVERR
)
122 port
->icount
.overrun
++;
124 status
&= port
->read_status_mask
;
126 if (status
& UARTDR_PARERR
)
128 else if (status
& UARTDR_FRMERR
)
130 else if (status
& UARTDR_OVERR
)
134 if (uart_handle_sysrq_char(port
, ch
))
137 if (status
& port
->ignore_status_mask
)
140 uart_insert_char(port
, status
, UARTDR_OVERR
, ch
, flg
);
143 tty_flip_buffer_push(&port
->state
->port
);
148 static irqreturn_t
uart_clps711x_int_tx(int irq
, void *dev_id
)
150 struct uart_port
*port
= dev_id
;
151 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
152 struct circ_buf
*xmit
= &port
->state
->xmit
;
155 writew(port
->x_char
, port
->membase
+ UARTDR_OFFSET
);
161 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
163 disable_irq_nosync(port
->irq
);
169 while (!uart_circ_empty(xmit
)) {
172 writew(xmit
->buf
[xmit
->tail
], port
->membase
+ UARTDR_OFFSET
);
173 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
176 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
177 if (sysflg
& SYSFLG_UTXFF
)
181 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
182 uart_write_wakeup(port
);
187 static unsigned int uart_clps711x_tx_empty(struct uart_port
*port
)
189 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
192 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
194 return (sysflg
& SYSFLG_UBUSY
) ? 0 : TIOCSER_TEMT
;
197 static unsigned int uart_clps711x_get_mctrl(struct uart_port
*port
)
199 unsigned int result
= TIOCM_DSR
| TIOCM_CTS
| TIOCM_CAR
;
200 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
202 return mctrl_gpio_get(s
->gpios
, &result
);
205 static void uart_clps711x_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
207 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
209 mctrl_gpio_set(s
->gpios
, mctrl
);
212 static void uart_clps711x_break_ctl(struct uart_port
*port
, int break_state
)
216 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
218 ubrlcr
|= UBRLCR_BREAK
;
220 ubrlcr
&= ~UBRLCR_BREAK
;
221 writel(ubrlcr
, port
->membase
+ UBRLCR_OFFSET
);
224 static void uart_clps711x_set_ldisc(struct uart_port
*port
,
225 struct ktermios
*termios
)
228 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
230 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON1_SIREN
,
231 (termios
->c_line
== N_IRDA
) ? SYSCON1_SIREN
: 0);
235 static int uart_clps711x_startup(struct uart_port
*port
)
237 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
240 writel(readl(port
->membase
+ UBRLCR_OFFSET
) & ~UBRLCR_BREAK
,
241 port
->membase
+ UBRLCR_OFFSET
);
243 /* Enable the port */
244 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
245 SYSCON_UARTEN
, SYSCON_UARTEN
);
248 static void uart_clps711x_shutdown(struct uart_port
*port
)
250 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
252 /* Disable the port */
253 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
256 static void uart_clps711x_set_termios(struct uart_port
*port
,
257 struct ktermios
*termios
,
258 struct ktermios
*old
)
261 unsigned int baud
, quot
;
263 /* Mask termios capabilities we don't support */
264 termios
->c_cflag
&= ~CMSPAR
;
265 termios
->c_iflag
&= ~(BRKINT
| IGNBRK
);
267 /* Ask the core to calculate the divisor for us */
268 baud
= uart_get_baud_rate(port
, termios
, old
, port
->uartclk
/ 4096,
270 quot
= uart_get_divisor(port
, baud
);
272 switch (termios
->c_cflag
& CSIZE
) {
274 ubrlcr
= UBRLCR_WRDLEN5
;
277 ubrlcr
= UBRLCR_WRDLEN6
;
280 ubrlcr
= UBRLCR_WRDLEN7
;
284 ubrlcr
= UBRLCR_WRDLEN8
;
288 if (termios
->c_cflag
& CSTOPB
)
289 ubrlcr
|= UBRLCR_XSTOP
;
291 if (termios
->c_cflag
& PARENB
) {
292 ubrlcr
|= UBRLCR_PRTEN
;
293 if (!(termios
->c_cflag
& PARODD
))
294 ubrlcr
|= UBRLCR_EVENPRT
;
298 ubrlcr
|= UBRLCR_FIFOEN
;
300 /* Set read status mask */
301 port
->read_status_mask
= UARTDR_OVERR
;
302 if (termios
->c_iflag
& INPCK
)
303 port
->read_status_mask
|= UARTDR_PARERR
| UARTDR_FRMERR
;
305 /* Set status ignore mask */
306 port
->ignore_status_mask
= 0;
307 if (!(termios
->c_cflag
& CREAD
))
308 port
->ignore_status_mask
|= UARTDR_OVERR
| UARTDR_PARERR
|
311 uart_update_timeout(port
, termios
->c_cflag
, baud
);
313 writel(ubrlcr
| (quot
- 1), port
->membase
+ UBRLCR_OFFSET
);
316 static const char *uart_clps711x_type(struct uart_port
*port
)
318 return (port
->type
== PORT_CLPS711X
) ? "CLPS711X" : NULL
;
321 static void uart_clps711x_config_port(struct uart_port
*port
, int flags
)
323 if (flags
& UART_CONFIG_TYPE
)
324 port
->type
= PORT_CLPS711X
;
327 static void uart_clps711x_nop_void(struct uart_port
*port
)
331 static int uart_clps711x_nop_int(struct uart_port
*port
)
336 static const struct uart_ops uart_clps711x_ops
= {
337 .tx_empty
= uart_clps711x_tx_empty
,
338 .set_mctrl
= uart_clps711x_set_mctrl
,
339 .get_mctrl
= uart_clps711x_get_mctrl
,
340 .stop_tx
= uart_clps711x_stop_tx
,
341 .start_tx
= uart_clps711x_start_tx
,
342 .stop_rx
= uart_clps711x_nop_void
,
343 .break_ctl
= uart_clps711x_break_ctl
,
344 .set_ldisc
= uart_clps711x_set_ldisc
,
345 .startup
= uart_clps711x_startup
,
346 .shutdown
= uart_clps711x_shutdown
,
347 .set_termios
= uart_clps711x_set_termios
,
348 .type
= uart_clps711x_type
,
349 .config_port
= uart_clps711x_config_port
,
350 .release_port
= uart_clps711x_nop_void
,
351 .request_port
= uart_clps711x_nop_int
,
354 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
355 static void uart_clps711x_console_putchar(struct uart_port
*port
, int ch
)
357 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
360 /* Wait for FIFO is not full */
362 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
363 } while (sysflg
& SYSFLG_UTXFF
);
365 writew(ch
, port
->membase
+ UARTDR_OFFSET
);
368 static void uart_clps711x_console_write(struct console
*co
, const char *c
,
371 struct uart_port
*port
= clps711x_uart
.state
[co
->index
].uart_port
;
372 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
375 uart_console_write(port
, c
, n
, uart_clps711x_console_putchar
);
377 /* Wait for transmitter to become empty */
379 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
380 } while (sysflg
& SYSFLG_UBUSY
);
383 static int uart_clps711x_console_setup(struct console
*co
, char *options
)
385 int baud
= 38400, bits
= 8, parity
= 'n', flow
= 'n';
386 int ret
, index
= co
->index
;
387 struct clps711x_port
*s
;
388 struct uart_port
*port
;
392 if (index
< 0 || index
>= UART_CLPS711X_NR
)
395 port
= clps711x_uart
.state
[index
].uart_port
;
399 s
= dev_get_drvdata(port
->dev
);
404 regmap_read(s
->syscon
, SYSCON_OFFSET
, &syscon
);
405 if (syscon
& SYSCON_UARTEN
) {
406 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
408 if (ubrlcr
& UBRLCR_PRTEN
) {
409 if (ubrlcr
& UBRLCR_EVENPRT
)
415 if ((ubrlcr
& UBRLCR_WRDLEN_MASK
) == UBRLCR_WRDLEN7
)
418 quot
= ubrlcr
& UBRLCR_BAUD_MASK
;
419 baud
= port
->uartclk
/ (16 * (quot
+ 1));
422 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
424 ret
= uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
428 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
429 SYSCON_UARTEN
, SYSCON_UARTEN
);
432 static struct console clps711x_console
= {
433 .name
= UART_CLPS711X_DEVNAME
,
434 .device
= uart_console_device
,
435 .write
= uart_clps711x_console_write
,
436 .setup
= uart_clps711x_console_setup
,
437 .flags
= CON_PRINTBUFFER
,
442 static int uart_clps711x_probe(struct platform_device
*pdev
)
444 struct device_node
*np
= pdev
->dev
.of_node
;
445 int ret
, index
= np
? of_alias_get_id(np
, "serial") : pdev
->id
;
446 struct clps711x_port
*s
;
447 struct resource
*res
;
448 struct clk
*uart_clk
;
451 if (index
< 0 || index
>= UART_CLPS711X_NR
)
454 s
= devm_kzalloc(&pdev
->dev
, sizeof(*s
), GFP_KERNEL
);
458 uart_clk
= devm_clk_get(&pdev
->dev
, NULL
);
459 if (IS_ERR(uart_clk
))
460 return PTR_ERR(uart_clk
);
462 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
463 s
->port
.membase
= devm_ioremap_resource(&pdev
->dev
, res
);
464 if (IS_ERR(s
->port
.membase
))
465 return PTR_ERR(s
->port
.membase
);
467 irq
= platform_get_irq(pdev
, 0);
472 s
->rx_irq
= platform_get_irq(pdev
, 1);
479 sprintf(syscon_name
, "syscon.%i", index
+ 1);
480 s
->syscon
= syscon_regmap_lookup_by_pdevname(syscon_name
);
481 if (IS_ERR(s
->syscon
))
482 return PTR_ERR(s
->syscon
);
484 s
->syscon
= syscon_regmap_lookup_by_phandle(np
, "syscon");
485 if (IS_ERR(s
->syscon
))
486 return PTR_ERR(s
->syscon
);
489 s
->port
.line
= index
;
490 s
->port
.dev
= &pdev
->dev
;
491 s
->port
.iotype
= UPIO_MEM32
;
492 s
->port
.mapbase
= res
->start
;
493 s
->port
.type
= PORT_CLPS711X
;
494 s
->port
.fifosize
= 16;
495 s
->port
.flags
= UPF_SKIP_TEST
| UPF_FIXED_TYPE
;
496 s
->port
.uartclk
= clk_get_rate(uart_clk
);
497 s
->port
.ops
= &uart_clps711x_ops
;
499 platform_set_drvdata(pdev
, s
);
501 s
->gpios
= mctrl_gpio_init_noauto(&pdev
->dev
, 0);
502 if (IS_ERR(s
->gpios
))
503 return PTR_ERR(s
->gpios
);
505 ret
= uart_add_one_port(&clps711x_uart
, &s
->port
);
510 if (!uart_console(&s
->port
))
511 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
515 ret
= devm_request_irq(&pdev
->dev
, s
->port
.irq
, uart_clps711x_int_tx
, 0,
516 dev_name(&pdev
->dev
), &s
->port
);
518 uart_remove_one_port(&clps711x_uart
, &s
->port
);
522 ret
= devm_request_irq(&pdev
->dev
, s
->rx_irq
, uart_clps711x_int_rx
, 0,
523 dev_name(&pdev
->dev
), &s
->port
);
525 uart_remove_one_port(&clps711x_uart
, &s
->port
);
530 static int uart_clps711x_remove(struct platform_device
*pdev
)
532 struct clps711x_port
*s
= platform_get_drvdata(pdev
);
534 return uart_remove_one_port(&clps711x_uart
, &s
->port
);
537 static const struct of_device_id __maybe_unused clps711x_uart_dt_ids
[] = {
538 { .compatible
= "cirrus,ep7209-uart", },
541 MODULE_DEVICE_TABLE(of
, clps711x_uart_dt_ids
);
543 static struct platform_driver clps711x_uart_platform
= {
545 .name
= "clps711x-uart",
546 .of_match_table
= of_match_ptr(clps711x_uart_dt_ids
),
548 .probe
= uart_clps711x_probe
,
549 .remove
= uart_clps711x_remove
,
552 static int __init
uart_clps711x_init(void)
556 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
557 clps711x_uart
.cons
= &clps711x_console
;
558 clps711x_console
.data
= &clps711x_uart
;
561 ret
= uart_register_driver(&clps711x_uart
);
565 return platform_driver_register(&clps711x_uart_platform
);
567 module_init(uart_clps711x_init
);
569 static void __exit
uart_clps711x_exit(void)
571 platform_driver_unregister(&clps711x_uart_platform
);
572 uart_unregister_driver(&clps711x_uart
);
574 module_exit(uart_clps711x_exit
);
576 MODULE_AUTHOR("Deep Blue Solutions Ltd");
577 MODULE_DESCRIPTION("CLPS711X serial driver");
578 MODULE_LICENSE("GPL");