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/platform_device.h>
11 #include <linux/serial.h>
12 #include <linux/serial_core.h>
13 #include <linux/slab.h>
14 #include <linux/tty.h>
15 #include <linux/tty_flip.h>
17 #define TCU_MBOX_BYTE(i, x) ((x) << (i * 8))
18 #define TCU_MBOX_BYTE_V(x, i) (((x) >> (i * 8)) & 0xff)
19 #define TCU_MBOX_NUM_BYTES(x) ((x) << 24)
20 #define TCU_MBOX_NUM_BYTES_V(x) (((x) >> 24) & 0x3)
23 struct uart_driver driver
;
24 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
25 struct console console
;
27 struct uart_port port
;
29 struct mbox_client tx_client
, rx_client
;
30 struct mbox_chan
*tx
, *rx
;
33 static unsigned int tegra_tcu_uart_tx_empty(struct uart_port
*port
)
38 static void tegra_tcu_uart_set_mctrl(struct uart_port
*port
, unsigned int mctrl
)
42 static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port
*port
)
47 static void tegra_tcu_uart_stop_tx(struct uart_port
*port
)
51 static void tegra_tcu_write_one(struct tegra_tcu
*tcu
, u32 value
,
56 value
|= TCU_MBOX_NUM_BYTES(count
);
57 msg
= (void *)(unsigned long)value
;
58 mbox_send_message(tcu
->tx
, msg
);
59 mbox_flush(tcu
->tx
, 1000);
62 static void tegra_tcu_write(struct tegra_tcu
*tcu
, const char *s
,
65 unsigned int written
= 0, i
= 0;
66 bool insert_nl
= false;
71 value
|= TCU_MBOX_BYTE(written
++, '\n');
74 } else if (s
[i
] == '\n') {
75 value
|= TCU_MBOX_BYTE(written
++, '\r');
78 value
|= TCU_MBOX_BYTE(written
++, s
[i
++]);
82 tegra_tcu_write_one(tcu
, value
, 3);
88 tegra_tcu_write_one(tcu
, value
, written
);
91 static void tegra_tcu_uart_start_tx(struct uart_port
*port
)
93 struct tegra_tcu
*tcu
= port
->private_data
;
94 struct tty_port
*tport
= &port
->state
->port
;
99 count
= kfifo_out_linear_ptr(&tport
->xmit_fifo
, &tail
,
104 tegra_tcu_write(tcu
, tail
, count
);
105 uart_xmit_advance(port
, count
);
108 uart_write_wakeup(port
);
111 static void tegra_tcu_uart_stop_rx(struct uart_port
*port
)
115 static void tegra_tcu_uart_break_ctl(struct uart_port
*port
, int ctl
)
119 static int tegra_tcu_uart_startup(struct uart_port
*port
)
124 static void tegra_tcu_uart_shutdown(struct uart_port
*port
)
128 static void tegra_tcu_uart_set_termios(struct uart_port
*port
,
129 struct ktermios
*new,
130 const struct ktermios
*old
)
134 static const struct uart_ops tegra_tcu_uart_ops
= {
135 .tx_empty
= tegra_tcu_uart_tx_empty
,
136 .set_mctrl
= tegra_tcu_uart_set_mctrl
,
137 .get_mctrl
= tegra_tcu_uart_get_mctrl
,
138 .stop_tx
= tegra_tcu_uart_stop_tx
,
139 .start_tx
= tegra_tcu_uart_start_tx
,
140 .stop_rx
= tegra_tcu_uart_stop_rx
,
141 .break_ctl
= tegra_tcu_uart_break_ctl
,
142 .startup
= tegra_tcu_uart_startup
,
143 .shutdown
= tegra_tcu_uart_shutdown
,
144 .set_termios
= tegra_tcu_uart_set_termios
,
147 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
148 static void tegra_tcu_console_write(struct console
*cons
, const char *s
,
151 struct tegra_tcu
*tcu
= container_of(cons
, struct tegra_tcu
, console
);
153 tegra_tcu_write(tcu
, s
, count
);
156 static int tegra_tcu_console_setup(struct console
*cons
, char *options
)
162 static void tegra_tcu_receive(struct mbox_client
*cl
, void *msg
)
164 struct tegra_tcu
*tcu
= container_of(cl
, struct tegra_tcu
, rx_client
);
165 struct tty_port
*port
= &tcu
->port
.state
->port
;
166 u32 value
= (u32
)(unsigned long)msg
;
167 unsigned int num_bytes
, i
;
169 num_bytes
= TCU_MBOX_NUM_BYTES_V(value
);
171 for (i
= 0; i
< num_bytes
; i
++)
172 tty_insert_flip_char(port
, TCU_MBOX_BYTE_V(value
, i
),
175 tty_flip_buffer_push(port
);
178 static int tegra_tcu_probe(struct platform_device
*pdev
)
180 struct uart_port
*port
;
181 struct tegra_tcu
*tcu
;
184 tcu
= devm_kzalloc(&pdev
->dev
, sizeof(*tcu
), GFP_KERNEL
);
188 tcu
->tx_client
.dev
= &pdev
->dev
;
189 tcu
->rx_client
.dev
= &pdev
->dev
;
190 tcu
->rx_client
.rx_callback
= tegra_tcu_receive
;
192 tcu
->tx
= mbox_request_channel_byname(&tcu
->tx_client
, "tx");
193 if (IS_ERR(tcu
->tx
)) {
194 err
= PTR_ERR(tcu
->tx
);
195 dev_err(&pdev
->dev
, "failed to get tx mailbox: %d\n", err
);
199 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
200 /* setup the console */
201 strcpy(tcu
->console
.name
, "ttyTCU");
202 tcu
->console
.device
= uart_console_device
;
203 tcu
->console
.flags
= CON_PRINTBUFFER
| CON_ANYTIME
;
204 tcu
->console
.index
= -1;
205 tcu
->console
.write
= tegra_tcu_console_write
;
206 tcu
->console
.setup
= tegra_tcu_console_setup
;
207 tcu
->console
.data
= &tcu
->driver
;
210 /* setup the driver */
211 tcu
->driver
.owner
= THIS_MODULE
;
212 tcu
->driver
.driver_name
= "tegra-tcu";
213 tcu
->driver
.dev_name
= "ttyTCU";
214 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
215 tcu
->driver
.cons
= &tcu
->console
;
219 err
= uart_register_driver(&tcu
->driver
);
221 dev_err(&pdev
->dev
, "failed to register UART driver: %d\n",
228 spin_lock_init(&port
->lock
);
229 port
->dev
= &pdev
->dev
;
230 port
->type
= PORT_TEGRA_TCU
;
231 port
->ops
= &tegra_tcu_uart_ops
;
233 port
->iotype
= UPIO_MEM
;
234 port
->flags
= UPF_BOOT_AUTOCONF
;
235 port
->private_data
= tcu
;
237 err
= uart_add_one_port(&tcu
->driver
, port
);
239 dev_err(&pdev
->dev
, "failed to add UART port: %d\n", err
);
240 goto unregister_uart
;
244 * Request RX channel after creating port to ensure tcu->port
245 * is ready for any immediate incoming bytes.
247 tcu
->rx
= mbox_request_channel_byname(&tcu
->rx_client
, "rx");
248 if (IS_ERR(tcu
->rx
)) {
249 err
= PTR_ERR(tcu
->rx
);
250 dev_err(&pdev
->dev
, "failed to get rx mailbox: %d\n", err
);
251 goto remove_uart_port
;
254 platform_set_drvdata(pdev
, tcu
);
255 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
256 register_console(&tcu
->console
);
262 uart_remove_one_port(&tcu
->driver
, &tcu
->port
);
264 uart_unregister_driver(&tcu
->driver
);
266 mbox_free_channel(tcu
->tx
);
271 static void tegra_tcu_remove(struct platform_device
*pdev
)
273 struct tegra_tcu
*tcu
= platform_get_drvdata(pdev
);
275 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE)
276 unregister_console(&tcu
->console
);
278 mbox_free_channel(tcu
->rx
);
279 uart_remove_one_port(&tcu
->driver
, &tcu
->port
);
280 uart_unregister_driver(&tcu
->driver
);
281 mbox_free_channel(tcu
->tx
);
284 static const struct of_device_id tegra_tcu_match
[] = {
285 { .compatible
= "nvidia,tegra194-tcu" },
288 MODULE_DEVICE_TABLE(of
, tegra_tcu_match
);
290 static struct platform_driver tegra_tcu_driver
= {
293 .of_match_table
= tegra_tcu_match
,
295 .probe
= tegra_tcu_probe
,
296 .remove
= tegra_tcu_remove
,
298 module_platform_driver(tegra_tcu_driver
);
300 MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
301 MODULE_LICENSE("GPL v2");
302 MODULE_DESCRIPTION("NVIDIA Tegra Combined UART driver");