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 #include "serial_mctrl_gpio.h"
38 #define UART_CLPS711X_DEVNAME "ttyCL"
39 #define UART_CLPS711X_NR 2
40 #define UART_CLPS711X_MAJOR 204
41 #define UART_CLPS711X_MINOR 40
43 #define UARTDR_OFFSET (0x00)
44 #define UBRLCR_OFFSET (0x40)
46 #define UARTDR_FRMERR (1 << 8)
47 #define UARTDR_PARERR (1 << 9)
48 #define UARTDR_OVERR (1 << 10)
50 #define UBRLCR_BAUD_MASK ((1 << 12) - 1)
51 #define UBRLCR_BREAK (1 << 12)
52 #define UBRLCR_PRTEN (1 << 13)
53 #define UBRLCR_EVENPRT (1 << 14)
54 #define UBRLCR_XSTOP (1 << 15)
55 #define UBRLCR_FIFOEN (1 << 16)
56 #define UBRLCR_WRDLEN5 (0 << 17)
57 #define UBRLCR_WRDLEN6 (1 << 17)
58 #define UBRLCR_WRDLEN7 (2 << 17)
59 #define UBRLCR_WRDLEN8 (3 << 17)
60 #define UBRLCR_WRDLEN_MASK (3 << 17)
62 struct clps711x_port
{
63 struct uart_port port
;
64 unsigned int tx_enabled
;
66 struct regmap
*syscon
;
67 struct mctrl_gpios
*gpios
;
70 static struct uart_driver clps711x_uart
= {
72 .driver_name
= UART_CLPS711X_DEVNAME
,
73 .dev_name
= UART_CLPS711X_DEVNAME
,
74 .major
= UART_CLPS711X_MAJOR
,
75 .minor
= UART_CLPS711X_MINOR
,
76 .nr
= UART_CLPS711X_NR
,
79 static void uart_clps711x_stop_tx(struct uart_port
*port
)
81 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
84 disable_irq(port
->irq
);
89 static void uart_clps711x_start_tx(struct uart_port
*port
)
91 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
95 enable_irq(port
->irq
);
99 static irqreturn_t
uart_clps711x_int_rx(int irq
, void *dev_id
)
101 struct uart_port
*port
= dev_id
;
102 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
103 unsigned int status
, flg
;
109 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
110 if (sysflg
& SYSFLG_URXFE
)
113 ch
= readw(port
->membase
+ UARTDR_OFFSET
);
114 status
= ch
& (UARTDR_FRMERR
| UARTDR_PARERR
| UARTDR_OVERR
);
120 if (unlikely(status
)) {
121 if (status
& UARTDR_PARERR
)
122 port
->icount
.parity
++;
123 else if (status
& UARTDR_FRMERR
)
124 port
->icount
.frame
++;
125 else if (status
& UARTDR_OVERR
)
126 port
->icount
.overrun
++;
128 status
&= port
->read_status_mask
;
130 if (status
& UARTDR_PARERR
)
132 else if (status
& UARTDR_FRMERR
)
134 else if (status
& UARTDR_OVERR
)
138 if (uart_handle_sysrq_char(port
, ch
))
141 if (status
& port
->ignore_status_mask
)
144 uart_insert_char(port
, status
, UARTDR_OVERR
, ch
, flg
);
147 tty_flip_buffer_push(&port
->state
->port
);
152 static irqreturn_t
uart_clps711x_int_tx(int irq
, void *dev_id
)
154 struct uart_port
*port
= dev_id
;
155 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
156 struct circ_buf
*xmit
= &port
->state
->xmit
;
159 writew(port
->x_char
, port
->membase
+ UARTDR_OFFSET
);
165 if (uart_circ_empty(xmit
) || uart_tx_stopped(port
)) {
167 disable_irq_nosync(port
->irq
);
173 while (!uart_circ_empty(xmit
)) {
176 writew(xmit
->buf
[xmit
->tail
], port
->membase
+ UARTDR_OFFSET
);
177 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
180 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
181 if (sysflg
& SYSFLG_UTXFF
)
185 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
186 uart_write_wakeup(port
);
191 static unsigned int uart_clps711x_tx_empty(struct uart_port
*port
)
193 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
196 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
198 return (sysflg
& SYSFLG_UBUSY
) ? 0 : TIOCSER_TEMT
;
201 static unsigned int uart_clps711x_get_mctrl(struct uart_port
*port
)
203 unsigned int result
= TIOCM_DSR
| TIOCM_CTS
| TIOCM_CAR
;
204 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
206 return mctrl_gpio_get(s
->gpios
, &result
);
209 static void uart_clps711x_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
211 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
213 mctrl_gpio_set(s
->gpios
, mctrl
);
216 static void uart_clps711x_break_ctl(struct uart_port
*port
, int break_state
)
220 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
222 ubrlcr
|= UBRLCR_BREAK
;
224 ubrlcr
&= ~UBRLCR_BREAK
;
225 writel(ubrlcr
, port
->membase
+ UBRLCR_OFFSET
);
228 static void uart_clps711x_set_ldisc(struct uart_port
*port
,
229 struct ktermios
*termios
)
232 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
234 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON1_SIREN
,
235 (termios
->c_line
== N_IRDA
) ? SYSCON1_SIREN
: 0);
239 static int uart_clps711x_startup(struct uart_port
*port
)
241 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
244 writel(readl(port
->membase
+ UBRLCR_OFFSET
) & ~UBRLCR_BREAK
,
245 port
->membase
+ UBRLCR_OFFSET
);
247 /* Enable the port */
248 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
249 SYSCON_UARTEN
, SYSCON_UARTEN
);
252 static void uart_clps711x_shutdown(struct uart_port
*port
)
254 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
256 /* Disable the port */
257 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
260 static void uart_clps711x_set_termios(struct uart_port
*port
,
261 struct ktermios
*termios
,
262 struct ktermios
*old
)
265 unsigned int baud
, quot
;
267 /* Mask termios capabilities we don't support */
268 termios
->c_cflag
&= ~CMSPAR
;
269 termios
->c_iflag
&= ~(BRKINT
| IGNBRK
);
271 /* Ask the core to calculate the divisor for us */
272 baud
= uart_get_baud_rate(port
, termios
, old
, port
->uartclk
/ 4096,
274 quot
= uart_get_divisor(port
, baud
);
276 switch (termios
->c_cflag
& CSIZE
) {
278 ubrlcr
= UBRLCR_WRDLEN5
;
281 ubrlcr
= UBRLCR_WRDLEN6
;
284 ubrlcr
= UBRLCR_WRDLEN7
;
288 ubrlcr
= UBRLCR_WRDLEN8
;
292 if (termios
->c_cflag
& CSTOPB
)
293 ubrlcr
|= UBRLCR_XSTOP
;
295 if (termios
->c_cflag
& PARENB
) {
296 ubrlcr
|= UBRLCR_PRTEN
;
297 if (!(termios
->c_cflag
& PARODD
))
298 ubrlcr
|= UBRLCR_EVENPRT
;
302 ubrlcr
|= UBRLCR_FIFOEN
;
304 /* Set read status mask */
305 port
->read_status_mask
= UARTDR_OVERR
;
306 if (termios
->c_iflag
& INPCK
)
307 port
->read_status_mask
|= UARTDR_PARERR
| UARTDR_FRMERR
;
309 /* Set status ignore mask */
310 port
->ignore_status_mask
= 0;
311 if (!(termios
->c_cflag
& CREAD
))
312 port
->ignore_status_mask
|= UARTDR_OVERR
| UARTDR_PARERR
|
315 uart_update_timeout(port
, termios
->c_cflag
, baud
);
317 writel(ubrlcr
| (quot
- 1), port
->membase
+ UBRLCR_OFFSET
);
320 static const char *uart_clps711x_type(struct uart_port
*port
)
322 return (port
->type
== PORT_CLPS711X
) ? "CLPS711X" : NULL
;
325 static void uart_clps711x_config_port(struct uart_port
*port
, int flags
)
327 if (flags
& UART_CONFIG_TYPE
)
328 port
->type
= PORT_CLPS711X
;
331 static void uart_clps711x_nop_void(struct uart_port
*port
)
335 static int uart_clps711x_nop_int(struct uart_port
*port
)
340 static const struct uart_ops uart_clps711x_ops
= {
341 .tx_empty
= uart_clps711x_tx_empty
,
342 .set_mctrl
= uart_clps711x_set_mctrl
,
343 .get_mctrl
= uart_clps711x_get_mctrl
,
344 .stop_tx
= uart_clps711x_stop_tx
,
345 .start_tx
= uart_clps711x_start_tx
,
346 .stop_rx
= uart_clps711x_nop_void
,
347 .break_ctl
= uart_clps711x_break_ctl
,
348 .set_ldisc
= uart_clps711x_set_ldisc
,
349 .startup
= uart_clps711x_startup
,
350 .shutdown
= uart_clps711x_shutdown
,
351 .set_termios
= uart_clps711x_set_termios
,
352 .type
= uart_clps711x_type
,
353 .config_port
= uart_clps711x_config_port
,
354 .release_port
= uart_clps711x_nop_void
,
355 .request_port
= uart_clps711x_nop_int
,
358 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
359 static void uart_clps711x_console_putchar(struct uart_port
*port
, int ch
)
361 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
364 /* Wait for FIFO is not full */
366 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
367 } while (sysflg
& SYSFLG_UTXFF
);
369 writew(ch
, port
->membase
+ UARTDR_OFFSET
);
372 static void uart_clps711x_console_write(struct console
*co
, const char *c
,
375 struct uart_port
*port
= clps711x_uart
.state
[co
->index
].uart_port
;
376 struct clps711x_port
*s
= dev_get_drvdata(port
->dev
);
379 uart_console_write(port
, c
, n
, uart_clps711x_console_putchar
);
381 /* Wait for transmitter to become empty */
383 regmap_read(s
->syscon
, SYSFLG_OFFSET
, &sysflg
);
384 } while (sysflg
& SYSFLG_UBUSY
);
387 static int uart_clps711x_console_setup(struct console
*co
, char *options
)
389 int baud
= 38400, bits
= 8, parity
= 'n', flow
= 'n';
390 int ret
, index
= co
->index
;
391 struct clps711x_port
*s
;
392 struct uart_port
*port
;
396 if (index
< 0 || index
>= UART_CLPS711X_NR
)
399 port
= clps711x_uart
.state
[index
].uart_port
;
403 s
= dev_get_drvdata(port
->dev
);
408 regmap_read(s
->syscon
, SYSCON_OFFSET
, &syscon
);
409 if (syscon
& SYSCON_UARTEN
) {
410 ubrlcr
= readl(port
->membase
+ UBRLCR_OFFSET
);
412 if (ubrlcr
& UBRLCR_PRTEN
) {
413 if (ubrlcr
& UBRLCR_EVENPRT
)
419 if ((ubrlcr
& UBRLCR_WRDLEN_MASK
) == UBRLCR_WRDLEN7
)
422 quot
= ubrlcr
& UBRLCR_BAUD_MASK
;
423 baud
= port
->uartclk
/ (16 * (quot
+ 1));
426 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
428 ret
= uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
432 return regmap_update_bits(s
->syscon
, SYSCON_OFFSET
,
433 SYSCON_UARTEN
, SYSCON_UARTEN
);
436 static struct console clps711x_console
= {
437 .name
= UART_CLPS711X_DEVNAME
,
438 .device
= uart_console_device
,
439 .write
= uart_clps711x_console_write
,
440 .setup
= uart_clps711x_console_setup
,
441 .flags
= CON_PRINTBUFFER
,
446 static int uart_clps711x_probe(struct platform_device
*pdev
)
448 struct device_node
*np
= pdev
->dev
.of_node
;
449 int ret
, index
= np
? of_alias_get_id(np
, "serial") : pdev
->id
;
450 struct clps711x_port
*s
;
451 struct resource
*res
;
452 struct clk
*uart_clk
;
454 if (index
< 0 || index
>= UART_CLPS711X_NR
)
457 s
= devm_kzalloc(&pdev
->dev
, sizeof(*s
), GFP_KERNEL
);
461 uart_clk
= devm_clk_get(&pdev
->dev
, NULL
);
462 if (IS_ERR(uart_clk
))
463 return PTR_ERR(uart_clk
);
465 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
466 s
->port
.membase
= devm_ioremap_resource(&pdev
->dev
, res
);
467 if (IS_ERR(s
->port
.membase
))
468 return PTR_ERR(s
->port
.membase
);
470 s
->port
.irq
= platform_get_irq(pdev
, 0);
471 if (IS_ERR_VALUE(s
->port
.irq
))
474 s
->rx_irq
= platform_get_irq(pdev
, 1);
475 if (IS_ERR_VALUE(s
->rx_irq
))
481 sprintf(syscon_name
, "syscon.%i", index
+ 1);
482 s
->syscon
= syscon_regmap_lookup_by_pdevname(syscon_name
);
483 if (IS_ERR(s
->syscon
))
484 return PTR_ERR(s
->syscon
);
486 s
->syscon
= syscon_regmap_lookup_by_phandle(np
, "syscon");
487 if (IS_ERR(s
->syscon
))
488 return PTR_ERR(s
->syscon
);
491 s
->port
.line
= index
;
492 s
->port
.dev
= &pdev
->dev
;
493 s
->port
.iotype
= UPIO_MEM32
;
494 s
->port
.mapbase
= res
->start
;
495 s
->port
.type
= PORT_CLPS711X
;
496 s
->port
.fifosize
= 16;
497 s
->port
.flags
= UPF_SKIP_TEST
| UPF_FIXED_TYPE
;
498 s
->port
.uartclk
= clk_get_rate(uart_clk
);
499 s
->port
.ops
= &uart_clps711x_ops
;
501 platform_set_drvdata(pdev
, s
);
503 s
->gpios
= mctrl_gpio_init(&pdev
->dev
, 0);
504 if (IS_ERR(s
->gpios
))
505 return PTR_ERR(s
->gpios
);
507 ret
= uart_add_one_port(&clps711x_uart
, &s
->port
);
512 if (!uart_console(&s
->port
))
513 regmap_update_bits(s
->syscon
, SYSCON_OFFSET
, SYSCON_UARTEN
, 0);
517 ret
= devm_request_irq(&pdev
->dev
, s
->port
.irq
, uart_clps711x_int_tx
, 0,
518 dev_name(&pdev
->dev
), &s
->port
);
520 uart_remove_one_port(&clps711x_uart
, &s
->port
);
524 ret
= devm_request_irq(&pdev
->dev
, s
->rx_irq
, uart_clps711x_int_rx
, 0,
525 dev_name(&pdev
->dev
), &s
->port
);
527 uart_remove_one_port(&clps711x_uart
, &s
->port
);
532 static int uart_clps711x_remove(struct platform_device
*pdev
)
534 struct clps711x_port
*s
= platform_get_drvdata(pdev
);
536 return uart_remove_one_port(&clps711x_uart
, &s
->port
);
539 static const struct of_device_id __maybe_unused clps711x_uart_dt_ids
[] = {
540 { .compatible
= "cirrus,clps711x-uart", },
543 MODULE_DEVICE_TABLE(of
, clps711x_uart_dt_ids
);
545 static struct platform_driver clps711x_uart_platform
= {
547 .name
= "clps711x-uart",
548 .of_match_table
= of_match_ptr(clps711x_uart_dt_ids
),
550 .probe
= uart_clps711x_probe
,
551 .remove
= uart_clps711x_remove
,
554 static int __init
uart_clps711x_init(void)
558 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
559 clps711x_uart
.cons
= &clps711x_console
;
560 clps711x_console
.data
= &clps711x_uart
;
563 ret
= uart_register_driver(&clps711x_uart
);
567 return platform_driver_register(&clps711x_uart_platform
);
569 module_init(uart_clps711x_init
);
571 static void __exit
uart_clps711x_exit(void)
573 platform_driver_unregister(&clps711x_uart_platform
);
574 uart_unregister_driver(&clps711x_uart
);
576 module_exit(uart_clps711x_exit
);
578 MODULE_AUTHOR("Deep Blue Solutions Ltd");
579 MODULE_DESCRIPTION("CLPS711X serial driver");
580 MODULE_LICENSE("GPL");