]>
Commit | Line | Data |
---|---|---|
08f2b9b8 GKH |
1 | From f597fbce38d230af95384f4a04e0a13a1d0ad45d Mon Sep 17 00:00:00 2001 |
2 | From: Joel Stanley <joel@jms.id.au> | |
3 | Date: Mon, 5 Mar 2018 22:17:38 +1030 | |
4 | Subject: serial: 8250: Add Nuvoton NPCM UART | |
5 | ||
6 | From: Joel Stanley <joel@jms.id.au> | |
7 | ||
8 | commit f597fbce38d230af95384f4a04e0a13a1d0ad45d upstream. | |
9 | ||
10 | The Nuvoton UART is almost compatible with the 8250 driver when probed | |
11 | via the 8250_of driver, however it requires some extra configuration | |
12 | at startup. | |
13 | ||
14 | Reviewed-by: Rob Herring <robh@kernel.org> | |
15 | Signed-off-by: Joel Stanley <joel@jms.id.au> | |
16 | Cc: stable <stable@vger.kernel.org> | |
17 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
18 | ||
19 | --- | |
20 | Documentation/devicetree/bindings/serial/8250.txt | 1 | |
21 | drivers/tty/serial/8250/8250_of.c | 1 | |
22 | drivers/tty/serial/8250/8250_port.c | 33 ++++++++++++++++++++++ | |
23 | include/uapi/linux/serial_core.h | 3 ++ | |
24 | 4 files changed, 38 insertions(+) | |
25 | ||
26 | --- a/Documentation/devicetree/bindings/serial/8250.txt | |
27 | +++ b/Documentation/devicetree/bindings/serial/8250.txt | |
28 | @@ -24,6 +24,7 @@ Required properties: | |
29 | - "ti,da830-uart" | |
30 | - "aspeed,ast2400-vuart" | |
31 | - "aspeed,ast2500-vuart" | |
32 | + - "nuvoton,npcm750-uart" | |
33 | - "serial" if the port type is unknown. | |
34 | - reg : offset and length of the register set for the device. | |
35 | - interrupts : should contain uart interrupt. | |
36 | --- a/drivers/tty/serial/8250/8250_of.c | |
37 | +++ b/drivers/tty/serial/8250/8250_of.c | |
38 | @@ -321,6 +321,7 @@ static const struct of_device_id of_plat | |
39 | { .compatible = "mrvl,mmp-uart", | |
40 | .data = (void *)PORT_XSCALE, }, | |
41 | { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, | |
42 | + { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, | |
43 | { /* end of list */ }, | |
44 | }; | |
45 | MODULE_DEVICE_TABLE(of, of_platform_serial_table); | |
46 | --- a/drivers/tty/serial/8250/8250_port.c | |
47 | +++ b/drivers/tty/serial/8250/8250_port.c | |
48 | @@ -51,6 +51,10 @@ | |
49 | #define UART_EXAR_SLEEP 0x8b /* Sleep mode */ | |
50 | #define UART_EXAR_DVID 0x8d /* Device identification */ | |
51 | ||
52 | +/* Nuvoton NPCM timeout register */ | |
53 | +#define UART_NPCM_TOR 7 | |
54 | +#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */ | |
55 | + | |
56 | /* | |
57 | * Debugging. | |
58 | */ | |
59 | @@ -297,6 +301,15 @@ static const struct serial8250_config ua | |
60 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, | |
61 | .flags = UART_CAP_FIFO, | |
62 | }, | |
63 | + [PORT_NPCM] = { | |
64 | + .name = "Nuvoton 16550", | |
65 | + .fifo_size = 16, | |
66 | + .tx_loadsz = 16, | |
67 | + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | | |
68 | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, | |
69 | + .rxtrig_bytes = {1, 4, 8, 14}, | |
70 | + .flags = UART_CAP_FIFO, | |
71 | + }, | |
72 | }; | |
73 | ||
74 | /* Uart divisor latch read */ | |
75 | @@ -2168,6 +2181,15 @@ int serial8250_do_startup(struct uart_po | |
76 | UART_DA830_PWREMU_MGMT_FREE); | |
77 | } | |
78 | ||
79 | + if (port->type == PORT_NPCM) { | |
80 | + /* | |
81 | + * Nuvoton calls the scratch register 'UART_TOR' (timeout | |
82 | + * register). Enable it, and set TIOC (timeout interrupt | |
83 | + * comparator) to be 0x20 for correct operation. | |
84 | + */ | |
85 | + serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20); | |
86 | + } | |
87 | + | |
88 | #ifdef CONFIG_SERIAL_8250_RSA | |
89 | /* | |
90 | * If this is an RSA port, see if we can kick it up to the | |
91 | @@ -2490,6 +2512,15 @@ static unsigned int xr17v35x_get_divisor | |
92 | return quot_16 >> 4; | |
93 | } | |
94 | ||
95 | +/* Nuvoton NPCM UARTs have a custom divisor calculation */ | |
96 | +static unsigned int npcm_get_divisor(struct uart_8250_port *up, | |
97 | + unsigned int baud) | |
98 | +{ | |
99 | + struct uart_port *port = &up->port; | |
100 | + | |
101 | + return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2; | |
102 | +} | |
103 | + | |
104 | static unsigned int serial8250_get_divisor(struct uart_8250_port *up, | |
105 | unsigned int baud, | |
106 | unsigned int *frac) | |
107 | @@ -2510,6 +2541,8 @@ static unsigned int serial8250_get_divis | |
108 | quot = 0x8002; | |
109 | else if (up->port.type == PORT_XR17V35X) | |
110 | quot = xr17v35x_get_divisor(up, baud, frac); | |
111 | + else if (up->port.type == PORT_NPCM) | |
112 | + quot = npcm_get_divisor(up, baud); | |
113 | else | |
114 | quot = uart_get_divisor(port, baud); | |
115 | ||
116 | --- a/include/uapi/linux/serial_core.h | |
117 | +++ b/include/uapi/linux/serial_core.h | |
118 | @@ -76,6 +76,9 @@ | |
119 | #define PORT_SUNZILOG 38 | |
120 | #define PORT_SUNSAB 39 | |
121 | ||
122 | +/* Nuvoton UART */ | |
123 | +#define PORT_NPCM 40 | |
124 | + | |
125 | /* Intel EG20 */ | |
126 | #define PORT_PCH_8LINE 44 | |
127 | #define PORT_PCH_2LINE 45 |