1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
6 #include <linux/console.h>
7 #include <linux/mailbox_client.h>
8 #include <linux/module.h>
10 #include <linux/of_device.h>
11 #include <linux/platform_device.h>
12 #include <linux/serial.h>
13 #include <linux/serial_core.h>
14 #include <linux/slab.h>
15 #include <linux/tty.h>
16 #include <linux/tty_flip.h>
18 #define TCU_MBOX_BYTE(i, x) ((x) << (i * 8))
19 #define TCU_MBOX_BYTE_V(x, i) (((x) >> (i * 8)) & 0xff)
20 #define TCU_MBOX_NUM_BYTES(x) ((x) << 24)
21 #define TCU_MBOX_NUM_BYTES_V(x) (((x) >> 24) & 0x3)
24 struct uart_driver driver
;
25 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
26 struct console console
;
28 struct uart_port port
;
30 struct mbox_client tx_client
, rx_client
;
31 struct mbox_chan
*tx
, *rx
;
34 static unsigned int tegra_tcu_uart_tx_empty(struct uart_port
*port
)
39 static void tegra_tcu_uart_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
43 static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port
*port
)
48 static void tegra_tcu_uart_stop_tx(struct uart_port
*port
)
52 static void tegra_tcu_write_one(struct tegra_tcu
*tcu
, u32 value
,
57 value
|= TCU_MBOX_NUM_BYTES(count
);
58 msg
= (void *)(unsigned long)value
;
59 mbox_send_message(tcu
->tx
, msg
);
60 mbox_flush(tcu
->tx
, 1000);
63 static void tegra_tcu_write(struct tegra_tcu
*tcu
, const char *s
,
66 unsigned int written
= 0, i
= 0;
67 bool insert_nl
= false;
72 value
|= TCU_MBOX_BYTE(written
++, '\n');
75 } else if (s
[i
] == '\n') {
76 value
|= TCU_MBOX_BYTE(written
++, '\r');
79 value
|= TCU_MBOX_BYTE(written
++, s
[i
++]);
83 tegra_tcu_write_one(tcu
, value
, 3);
89 tegra_tcu_write_one(tcu
, value
, written
);
92 static void tegra_tcu_uart_start_tx(struct uart_port
*port
)
94 struct tegra_tcu
*tcu
= port
->private_data
;
95 struct circ_buf
*xmit
= &port
->state
->xmit
;
99 count
= CIRC_CNT_TO_END(xmit
->head
, xmit
->tail
, UART_XMIT_SIZE
);
103 tegra_tcu_write(tcu
, &xmit
->buf
[xmit
->tail
], count
);
104 xmit
->tail
= (xmit
->tail
+ count
) & (UART_XMIT_SIZE
- 1);
107 uart_write_wakeup(port
);
110 static void tegra_tcu_uart_stop_rx(struct uart_port
*port
)
114 static void tegra_tcu_uart_break_ctl(struct uart_port
*port
, int ctl
)
118 static int tegra_tcu_uart_startup(struct uart_port
*port
)
123 static void tegra_tcu_uart_shutdown(struct uart_port
*port
)
127 static void tegra_tcu_uart_set_termios(struct uart_port
*port
,
128 struct ktermios
*new,
129 struct ktermios
*old
)
133 static const struct uart_ops tegra_tcu_uart_ops
= {
134 .tx_empty
= tegra_tcu_uart_tx_empty
,
135 .set_mctrl
= tegra_tcu_uart_set_mctrl
,
136 .get_mctrl
= tegra_tcu_uart_get_mctrl
,
137 .stop_tx
= tegra_tcu_uart_stop_tx
,
138 .start_tx
= tegra_tcu_uart_start_tx
,
139 .stop_rx
= tegra_tcu_uart_stop_rx
,
140 .break_ctl
= tegra_tcu_uart_break_ctl
,
141 .startup
= tegra_tcu_uart_startup
,
142 .shutdown
= tegra_tcu_uart_shutdown
,
143 .set_termios
= tegra_tcu_uart_set_termios
,
146 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
147 static void tegra_tcu_console_write(struct console
*cons
, const char *s
,
150 struct tegra_tcu
*tcu
= container_of(cons
, struct tegra_tcu
, console
);
152 tegra_tcu_write(tcu
, s
, count
);
155 static int tegra_tcu_console_setup(struct console
*cons
, char *options
)
161 static void tegra_tcu_receive(struct mbox_client
*cl
, void *msg
)
163 struct tegra_tcu
*tcu
= container_of(cl
, struct tegra_tcu
, rx_client
);
164 struct tty_port
*port
= &tcu
->port
.state
->port
;
165 u32 value
= (u32
)(unsigned long)msg
;
166 unsigned int num_bytes
, i
;
168 num_bytes
= TCU_MBOX_NUM_BYTES_V(value
);
170 for (i
= 0; i
< num_bytes
; i
++)
171 tty_insert_flip_char(port
, TCU_MBOX_BYTE_V(value
, i
),
174 tty_flip_buffer_push(port
);
177 static int tegra_tcu_probe(struct platform_device
*pdev
)
179 struct uart_port
*port
;
180 struct tegra_tcu
*tcu
;
183 tcu
= devm_kzalloc(&pdev
->dev
, sizeof(*tcu
), GFP_KERNEL
);
187 tcu
->tx_client
.dev
= &pdev
->dev
;
188 tcu
->rx_client
.dev
= &pdev
->dev
;
189 tcu
->rx_client
.rx_callback
= tegra_tcu_receive
;
191 tcu
->tx
= mbox_request_channel_byname(&tcu
->tx_client
, "tx");
192 if (IS_ERR(tcu
->tx
)) {
193 err
= PTR_ERR(tcu
->tx
);
194 dev_err(&pdev
->dev
, "failed to get tx mailbox: %d\n", err
);
198 tcu
->rx
= mbox_request_channel_byname(&tcu
->rx_client
, "rx");
199 if (IS_ERR(tcu
->rx
)) {
200 err
= PTR_ERR(tcu
->rx
);
201 dev_err(&pdev
->dev
, "failed to get rx mailbox: %d\n", err
);
205 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
206 /* setup the console */
207 strcpy(tcu
->console
.name
, "ttyTCU");
208 tcu
->console
.device
= uart_console_device
;
209 tcu
->console
.flags
= CON_PRINTBUFFER
| CON_ANYTIME
;
210 tcu
->console
.index
= -1;
211 tcu
->console
.write
= tegra_tcu_console_write
;
212 tcu
->console
.setup
= tegra_tcu_console_setup
;
213 tcu
->console
.data
= &tcu
->driver
;
216 /* setup the driver */
217 tcu
->driver
.owner
= THIS_MODULE
;
218 tcu
->driver
.driver_name
= "tegra-tcu";
219 tcu
->driver
.dev_name
= "ttyTCU";
220 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
221 tcu
->driver
.cons
= &tcu
->console
;
225 err
= uart_register_driver(&tcu
->driver
);
227 dev_err(&pdev
->dev
, "failed to register UART driver: %d\n",
234 spin_lock_init(&port
->lock
);
235 port
->dev
= &pdev
->dev
;
236 port
->type
= PORT_TEGRA_TCU
;
237 port
->ops
= &tegra_tcu_uart_ops
;
239 port
->iotype
= UPIO_MEM
;
240 port
->flags
= UPF_BOOT_AUTOCONF
;
241 port
->private_data
= tcu
;
243 err
= uart_add_one_port(&tcu
->driver
, port
);
245 dev_err(&pdev
->dev
, "failed to add UART port: %d\n", err
);
246 goto unregister_uart
;
249 platform_set_drvdata(pdev
, tcu
);
250 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
251 register_console(&tcu
->console
);
257 uart_unregister_driver(&tcu
->driver
);
259 mbox_free_channel(tcu
->rx
);
261 mbox_free_channel(tcu
->tx
);
266 static int tegra_tcu_remove(struct platform_device
*pdev
)
268 struct tegra_tcu
*tcu
= platform_get_drvdata(pdev
);
270 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
271 unregister_console(&tcu
->console
);
273 uart_remove_one_port(&tcu
->driver
, &tcu
->port
);
274 uart_unregister_driver(&tcu
->driver
);
275 mbox_free_channel(tcu
->rx
);
276 mbox_free_channel(tcu
->tx
);
281 static const struct of_device_id tegra_tcu_match
[] = {
282 { .compatible
= "nvidia,tegra194-tcu" },
286 static struct platform_driver tegra_tcu_driver
= {
289 .of_match_table
= tegra_tcu_match
,
291 .probe
= tegra_tcu_probe
,
292 .remove
= tegra_tcu_remove
,
294 module_platform_driver(tegra_tcu_driver
);
296 MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
297 MODULE_LICENSE("GPL v2");
298 MODULE_DESCRIPTION("NVIDIA Tegra Combined UART driver");