2 * Based on meson_uart.c, by AMLOGIC, INC.
4 * Copyright (C) 2014 Carlo Caione <carlo@caione.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/clk.h>
18 #include <linux/console.h>
19 #include <linux/delay.h>
20 #include <linux/init.h>
22 #include <linux/module.h>
23 #include <linux/kernel.h>
25 #include <linux/platform_device.h>
26 #include <linux/serial.h>
27 #include <linux/serial_core.h>
28 #include <linux/tty.h>
29 #include <linux/tty_flip.h>
31 /* Register offsets */
32 #define AML_UART_WFIFO 0x00
33 #define AML_UART_RFIFO 0x04
34 #define AML_UART_CONTROL 0x08
35 #define AML_UART_STATUS 0x0c
36 #define AML_UART_MISC 0x10
37 #define AML_UART_REG5 0x14
39 /* AML_UART_CONTROL bits */
40 #define AML_UART_TX_EN BIT(12)
41 #define AML_UART_RX_EN BIT(13)
42 #define AML_UART_TX_RST BIT(22)
43 #define AML_UART_RX_RST BIT(23)
44 #define AML_UART_CLR_ERR BIT(24)
45 #define AML_UART_RX_INT_EN BIT(27)
46 #define AML_UART_TX_INT_EN BIT(28)
47 #define AML_UART_DATA_LEN_MASK (0x03 << 20)
48 #define AML_UART_DATA_LEN_8BIT (0x00 << 20)
49 #define AML_UART_DATA_LEN_7BIT (0x01 << 20)
50 #define AML_UART_DATA_LEN_6BIT (0x02 << 20)
51 #define AML_UART_DATA_LEN_5BIT (0x03 << 20)
53 /* AML_UART_STATUS bits */
54 #define AML_UART_PARITY_ERR BIT(16)
55 #define AML_UART_FRAME_ERR BIT(17)
56 #define AML_UART_TX_FIFO_WERR BIT(18)
57 #define AML_UART_RX_EMPTY BIT(20)
58 #define AML_UART_TX_FULL BIT(21)
59 #define AML_UART_TX_EMPTY BIT(22)
60 #define AML_UART_ERR (AML_UART_PARITY_ERR | \
61 AML_UART_FRAME_ERR | \
62 AML_UART_TX_FIFO_WERR)
64 /* AML_UART_CONTROL bits */
65 #define AML_UART_TWO_WIRE_EN BIT(15)
66 #define AML_UART_PARITY_TYPE BIT(18)
67 #define AML_UART_PARITY_EN BIT(19)
68 #define AML_UART_CLEAR_ERR BIT(24)
69 #define AML_UART_STOP_BIN_LEN_MASK (0x03 << 16)
70 #define AML_UART_STOP_BIN_1SB (0x00 << 16)
71 #define AML_UART_STOP_BIN_2SB (0x01 << 16)
73 /* AML_UART_MISC bits */
74 #define AML_UART_XMIT_IRQ(c) (((c) & 0xff) << 8)
75 #define AML_UART_RECV_IRQ(c) ((c) & 0xff)
77 /* AML_UART_REG5 bits */
78 #define AML_UART_BAUD_MASK 0x7fffff
79 #define AML_UART_BAUD_USE BIT(23)
81 #define AML_UART_PORT_NUM 6
82 #define AML_UART_DEV_NAME "ttyAML"
85 static struct uart_driver meson_uart_driver
;
87 static struct uart_port
*meson_ports
[AML_UART_PORT_NUM
];
89 static void meson_uart_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
93 static unsigned int meson_uart_get_mctrl(struct uart_port
*port
)
98 static unsigned int meson_uart_tx_empty(struct uart_port
*port
)
102 val
= readl(port
->membase
+ AML_UART_STATUS
);
103 return (val
& AML_UART_TX_EMPTY
) ? TIOCSER_TEMT
: 0;
106 static void meson_uart_stop_tx(struct uart_port
*port
)
110 val
= readl(port
->membase
+ AML_UART_CONTROL
);
111 val
&= ~AML_UART_TX_EN
;
112 writel(val
, port
->membase
+ AML_UART_CONTROL
);
115 static void meson_uart_stop_rx(struct uart_port
*port
)
119 val
= readl(port
->membase
+ AML_UART_CONTROL
);
120 val
&= ~AML_UART_RX_EN
;
121 writel(val
, port
->membase
+ AML_UART_CONTROL
);
124 static void meson_uart_shutdown(struct uart_port
*port
)
129 free_irq(port
->irq
, port
);
131 spin_lock_irqsave(&port
->lock
, flags
);
133 val
= readl(port
->membase
+ AML_UART_CONTROL
);
134 val
&= ~(AML_UART_RX_EN
| AML_UART_TX_EN
);
135 val
&= ~(AML_UART_RX_INT_EN
| AML_UART_TX_INT_EN
);
136 writel(val
, port
->membase
+ AML_UART_CONTROL
);
138 spin_unlock_irqrestore(&port
->lock
, flags
);
141 static void meson_uart_start_tx(struct uart_port
*port
)
143 struct circ_buf
*xmit
= &port
->state
->xmit
;
146 if (uart_tx_stopped(port
)) {
147 meson_uart_stop_tx(port
);
151 while (!(readl(port
->membase
+ AML_UART_STATUS
) & AML_UART_TX_FULL
)) {
153 writel(port
->x_char
, port
->membase
+ AML_UART_WFIFO
);
159 if (uart_circ_empty(xmit
))
162 ch
= xmit
->buf
[xmit
->tail
];
163 writel(ch
, port
->membase
+ AML_UART_WFIFO
);
164 xmit
->tail
= (xmit
->tail
+1) & (SERIAL_XMIT_SIZE
- 1);
168 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
169 uart_write_wakeup(port
);
172 static void meson_receive_chars(struct uart_port
*port
)
174 struct tty_port
*tport
= &port
->state
->port
;
176 u32 status
, ch
, mode
;
181 status
= readl(port
->membase
+ AML_UART_STATUS
);
183 if (status
& AML_UART_ERR
) {
184 if (status
& AML_UART_TX_FIFO_WERR
)
185 port
->icount
.overrun
++;
186 else if (status
& AML_UART_FRAME_ERR
)
187 port
->icount
.frame
++;
188 else if (status
& AML_UART_PARITY_ERR
)
189 port
->icount
.frame
++;
191 mode
= readl(port
->membase
+ AML_UART_CONTROL
);
192 mode
|= AML_UART_CLEAR_ERR
;
193 writel(mode
, port
->membase
+ AML_UART_CONTROL
);
195 /* It doesn't clear to 0 automatically */
196 mode
&= ~AML_UART_CLEAR_ERR
;
197 writel(mode
, port
->membase
+ AML_UART_CONTROL
);
199 status
&= port
->read_status_mask
;
200 if (status
& AML_UART_FRAME_ERR
)
202 else if (status
& AML_UART_PARITY_ERR
)
206 ch
= readl(port
->membase
+ AML_UART_RFIFO
);
209 if ((status
& port
->ignore_status_mask
) == 0)
210 tty_insert_flip_char(tport
, ch
, flag
);
212 if (status
& AML_UART_TX_FIFO_WERR
)
213 tty_insert_flip_char(tport
, 0, TTY_OVERRUN
);
215 } while (!(readl(port
->membase
+ AML_UART_STATUS
) & AML_UART_RX_EMPTY
));
217 spin_unlock(&port
->lock
);
218 tty_flip_buffer_push(tport
);
219 spin_lock(&port
->lock
);
222 static irqreturn_t
meson_uart_interrupt(int irq
, void *dev_id
)
224 struct uart_port
*port
= (struct uart_port
*)dev_id
;
226 spin_lock(&port
->lock
);
228 if (!(readl(port
->membase
+ AML_UART_STATUS
) & AML_UART_RX_EMPTY
))
229 meson_receive_chars(port
);
231 if (!(readl(port
->membase
+ AML_UART_STATUS
) & AML_UART_TX_FULL
))
232 meson_uart_start_tx(port
);
234 spin_unlock(&port
->lock
);
239 static const char *meson_uart_type(struct uart_port
*port
)
241 return (port
->type
== PORT_MESON
) ? "meson_uart" : NULL
;
244 static int meson_uart_startup(struct uart_port
*port
)
249 val
= readl(port
->membase
+ AML_UART_CONTROL
);
250 val
|= (AML_UART_RX_RST
| AML_UART_TX_RST
| AML_UART_CLR_ERR
);
251 writel(val
, port
->membase
+ AML_UART_CONTROL
);
253 val
&= ~(AML_UART_RX_RST
| AML_UART_TX_RST
| AML_UART_CLR_ERR
);
254 writel(val
, port
->membase
+ AML_UART_CONTROL
);
256 val
|= (AML_UART_RX_EN
| AML_UART_TX_EN
);
257 writel(val
, port
->membase
+ AML_UART_CONTROL
);
259 val
|= (AML_UART_RX_INT_EN
| AML_UART_TX_INT_EN
);
260 writel(val
, port
->membase
+ AML_UART_CONTROL
);
262 val
= (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port
->fifosize
/ 2));
263 writel(val
, port
->membase
+ AML_UART_MISC
);
265 ret
= request_irq(port
->irq
, meson_uart_interrupt
, 0,
266 meson_uart_type(port
), port
);
271 static void meson_uart_change_speed(struct uart_port
*port
, unsigned long baud
)
275 while (!(readl(port
->membase
+ AML_UART_STATUS
) & AML_UART_TX_EMPTY
))
278 val
= readl(port
->membase
+ AML_UART_REG5
);
279 val
&= ~AML_UART_BAUD_MASK
;
280 val
= ((port
->uartclk
* 10 / (baud
* 4) + 5) / 10) - 1;
281 val
|= AML_UART_BAUD_USE
;
282 writel(val
, port
->membase
+ AML_UART_REG5
);
285 static void meson_uart_set_termios(struct uart_port
*port
,
286 struct ktermios
*termios
,
287 struct ktermios
*old
)
289 unsigned int cflags
, iflags
, baud
;
293 spin_lock_irqsave(&port
->lock
, flags
);
295 cflags
= termios
->c_cflag
;
296 iflags
= termios
->c_iflag
;
298 val
= readl(port
->membase
+ AML_UART_CONTROL
);
300 val
&= ~AML_UART_DATA_LEN_MASK
;
301 switch (cflags
& CSIZE
) {
303 val
|= AML_UART_DATA_LEN_8BIT
;
306 val
|= AML_UART_DATA_LEN_7BIT
;
309 val
|= AML_UART_DATA_LEN_6BIT
;
312 val
|= AML_UART_DATA_LEN_5BIT
;
317 val
|= AML_UART_PARITY_EN
;
319 val
&= ~AML_UART_PARITY_EN
;
322 val
|= AML_UART_PARITY_TYPE
;
324 val
&= ~AML_UART_PARITY_TYPE
;
326 val
&= ~AML_UART_STOP_BIN_LEN_MASK
;
328 val
|= AML_UART_STOP_BIN_2SB
;
330 val
&= ~AML_UART_STOP_BIN_1SB
;
332 if (cflags
& CRTSCTS
)
333 val
&= ~AML_UART_TWO_WIRE_EN
;
335 val
|= AML_UART_TWO_WIRE_EN
;
337 writel(val
, port
->membase
+ AML_UART_CONTROL
);
339 baud
= uart_get_baud_rate(port
, termios
, old
, 9600, 115200);
340 meson_uart_change_speed(port
, baud
);
342 port
->read_status_mask
= AML_UART_TX_FIFO_WERR
;
344 port
->read_status_mask
|= AML_UART_PARITY_ERR
|
347 port
->ignore_status_mask
= 0;
349 port
->ignore_status_mask
|= AML_UART_PARITY_ERR
|
352 uart_update_timeout(port
, termios
->c_cflag
, baud
);
353 spin_unlock_irqrestore(&port
->lock
, flags
);
356 static int meson_uart_verify_port(struct uart_port
*port
,
357 struct serial_struct
*ser
)
361 if (port
->type
!= PORT_MESON
)
363 if (port
->irq
!= ser
->irq
)
365 if (ser
->baud_base
< 9600)
370 static void meson_uart_release_port(struct uart_port
*port
)
372 if (port
->flags
& UPF_IOREMAP
) {
373 iounmap(port
->membase
);
374 port
->membase
= NULL
;
378 static int meson_uart_request_port(struct uart_port
*port
)
380 struct platform_device
*pdev
= to_platform_device(port
->dev
);
381 struct resource
*res
;
384 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
386 dev_err(&pdev
->dev
, "cannot obtain I/O memory region");
389 size
= resource_size(res
);
391 if (!devm_request_mem_region(port
->dev
, port
->mapbase
, size
,
392 dev_name(port
->dev
))) {
393 dev_err(port
->dev
, "Memory region busy\n");
397 if (port
->flags
& UPF_IOREMAP
) {
398 port
->membase
= devm_ioremap_nocache(port
->dev
,
401 if (port
->membase
== NULL
)
408 static void meson_uart_config_port(struct uart_port
*port
, int flags
)
410 if (flags
& UART_CONFIG_TYPE
) {
411 port
->type
= PORT_MESON
;
412 meson_uart_request_port(port
);
416 static struct uart_ops meson_uart_ops
= {
417 .set_mctrl
= meson_uart_set_mctrl
,
418 .get_mctrl
= meson_uart_get_mctrl
,
419 .tx_empty
= meson_uart_tx_empty
,
420 .start_tx
= meson_uart_start_tx
,
421 .stop_tx
= meson_uart_stop_tx
,
422 .stop_rx
= meson_uart_stop_rx
,
423 .startup
= meson_uart_startup
,
424 .shutdown
= meson_uart_shutdown
,
425 .set_termios
= meson_uart_set_termios
,
426 .type
= meson_uart_type
,
427 .config_port
= meson_uart_config_port
,
428 .request_port
= meson_uart_request_port
,
429 .release_port
= meson_uart_release_port
,
430 .verify_port
= meson_uart_verify_port
,
433 #ifdef CONFIG_SERIAL_MESON_CONSOLE
435 static void meson_console_putchar(struct uart_port
*port
, int ch
)
440 while (readl(port
->membase
+ AML_UART_STATUS
) & AML_UART_TX_FULL
)
442 writel(ch
, port
->membase
+ AML_UART_WFIFO
);
445 static void meson_serial_console_write(struct console
*co
, const char *s
,
448 struct uart_port
*port
;
452 port
= meson_ports
[co
->index
];
456 local_irq_save(flags
);
459 } else if (oops_in_progress
) {
460 locked
= spin_trylock(&port
->lock
);
462 spin_lock(&port
->lock
);
466 uart_console_write(port
, s
, count
, meson_console_putchar
);
469 spin_unlock(&port
->lock
);
470 local_irq_restore(flags
);
473 static int meson_serial_console_setup(struct console
*co
, char *options
)
475 struct uart_port
*port
;
481 if (co
->index
< 0 || co
->index
>= AML_UART_PORT_NUM
)
484 port
= meson_ports
[co
->index
];
485 if (!port
|| !port
->membase
)
489 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
491 return uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
494 static struct console meson_serial_console
= {
495 .name
= AML_UART_DEV_NAME
,
496 .write
= meson_serial_console_write
,
497 .device
= uart_console_device
,
498 .setup
= meson_serial_console_setup
,
499 .flags
= CON_PRINTBUFFER
,
501 .data
= &meson_uart_driver
,
504 static int __init
meson_serial_console_init(void)
506 register_console(&meson_serial_console
);
509 console_initcall(meson_serial_console_init
);
511 #define MESON_SERIAL_CONSOLE (&meson_serial_console)
513 #define MESON_SERIAL_CONSOLE NULL
516 static struct uart_driver meson_uart_driver
= {
517 .owner
= THIS_MODULE
,
518 .driver_name
= "meson_uart",
519 .dev_name
= AML_UART_DEV_NAME
,
520 .nr
= AML_UART_PORT_NUM
,
521 .cons
= MESON_SERIAL_CONSOLE
,
524 static int meson_uart_probe(struct platform_device
*pdev
)
526 struct resource
*res_mem
, *res_irq
;
527 struct uart_port
*port
;
531 if (pdev
->dev
.of_node
)
532 pdev
->id
= of_alias_get_id(pdev
->dev
.of_node
, "serial");
534 if (pdev
->id
< 0 || pdev
->id
>= AML_UART_PORT_NUM
)
537 res_mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
541 res_irq
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
545 if (meson_ports
[pdev
->id
]) {
546 dev_err(&pdev
->dev
, "port %d already allocated\n", pdev
->id
);
550 port
= devm_kzalloc(&pdev
->dev
, sizeof(struct uart_port
), GFP_KERNEL
);
554 clk
= clk_get(&pdev
->dev
, NULL
);
558 port
->uartclk
= clk_get_rate(clk
);
559 port
->iotype
= UPIO_MEM
;
560 port
->mapbase
= res_mem
->start
;
561 port
->irq
= res_irq
->start
;
562 port
->flags
= UPF_BOOT_AUTOCONF
| UPF_IOREMAP
| UPF_LOW_LATENCY
;
563 port
->dev
= &pdev
->dev
;
564 port
->line
= pdev
->id
;
565 port
->type
= PORT_MESON
;
567 port
->ops
= &meson_uart_ops
;
570 meson_ports
[pdev
->id
] = port
;
571 platform_set_drvdata(pdev
, port
);
573 ret
= uart_add_one_port(&meson_uart_driver
, port
);
575 meson_ports
[pdev
->id
] = NULL
;
580 static int meson_uart_remove(struct platform_device
*pdev
)
582 struct uart_port
*port
;
584 port
= platform_get_drvdata(pdev
);
585 uart_remove_one_port(&meson_uart_driver
, port
);
586 meson_ports
[pdev
->id
] = NULL
;
592 static const struct of_device_id meson_uart_dt_match
[] = {
593 { .compatible
= "amlogic,meson-uart" },
596 MODULE_DEVICE_TABLE(of
, meson_uart_dt_match
);
598 static struct platform_driver meson_uart_platform_driver
= {
599 .probe
= meson_uart_probe
,
600 .remove
= meson_uart_remove
,
602 .name
= "meson_uart",
603 .of_match_table
= meson_uart_dt_match
,
607 static int __init
meson_uart_init(void)
611 ret
= uart_register_driver(&meson_uart_driver
);
615 ret
= platform_driver_register(&meson_uart_platform_driver
);
617 uart_unregister_driver(&meson_uart_driver
);
622 static void __exit
meson_uart_exit(void)
624 platform_driver_unregister(&meson_uart_platform_driver
);
625 uart_unregister_driver(&meson_uart_driver
);
628 module_init(meson_uart_init
);
629 module_exit(meson_uart_exit
);
631 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
632 MODULE_DESCRIPTION("Amlogic Meson serial port driver");
633 MODULE_LICENSE("GPL v2");