xref: /linux/drivers/tty/serial/tegra-utc.c (revision 378ec25aec5a8444879f8696d580c94950a1f1df)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 // NVIDIA Tegra UTC (UART Trace Controller) driver.
4 
5 #include <linux/bits.h>
6 #include <linux/console.h>
7 #include <linux/container_of.h>
8 #include <linux/device.h>
9 #include <linux/err.h>
10 #include <linux/iopoll.h>
11 #include <linux/kfifo.h>
12 #include <linux/module.h>
13 #include <linux/mod_devicetable.h>
14 #include <linux/property.h>
15 #include <linux/platform_device.h>
16 #include <linux/serial.h>
17 #include <linux/serial_core.h>
18 #include <linux/slab.h>
19 #include <linux/tty.h>
20 #include <linux/tty_flip.h>
21 #include <linux/types.h>
22 
23 #define TEGRA_UTC_ENABLE			0x000
24 #define TEGRA_UTC_ENABLE_CLIENT_ENABLE		BIT(0)
25 
26 #define TEGRA_UTC_FIFO_THRESHOLD		0x008
27 
28 #define TEGRA_UTC_COMMAND			0x00c
29 #define TEGRA_UTC_COMMAND_RESET			BIT(0)
30 #define TEGRA_UTC_COMMAND_FLUSH			BIT(1)
31 
32 #define TEGRA_UTC_DATA				0x020
33 
34 #define TEGRA_UTC_FIFO_STATUS			0x100
35 #define TEGRA_UTC_FIFO_EMPTY			BIT(0)
36 #define TEGRA_UTC_FIFO_FULL			BIT(1)
37 #define TEGRA_UTC_FIFO_REQ			BIT(2)
38 #define TEGRA_UTC_FIFO_OVERFLOW			BIT(3)
39 #define TEGRA_UTC_FIFO_TIMEOUT			BIT(4)
40 
41 #define TEGRA_UTC_FIFO_OCCUPANCY		0x104
42 
43 #define TEGRA_UTC_INTR_STATUS			0x108
44 #define TEGRA_UTC_INTR_SET			0x10c
45 #define TEGRA_UTC_INTR_MASK			0x110
46 #define TEGRA_UTC_INTR_CLEAR			0x114
47 #define TEGRA_UTC_INTR_EMPTY			BIT(0)
48 #define TEGRA_UTC_INTR_FULL			BIT(1)
49 #define TEGRA_UTC_INTR_REQ			BIT(2)
50 #define TEGRA_UTC_INTR_OVERFLOW			BIT(3)
51 #define TEGRA_UTC_INTR_TIMEOUT			BIT(4)
52 
53 #define TEGRA_UTC_UART_NR			16
54 
55 #define TEGRA_UTC_INTR_COMMON	(TEGRA_UTC_INTR_REQ | TEGRA_UTC_INTR_FULL | TEGRA_UTC_INTR_EMPTY)
56 
57 struct tegra_utc_port {
58 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE)
59 	struct console console;
60 #endif
61 	struct uart_port port;
62 
63 	void __iomem *rx_base;
64 	void __iomem *tx_base;
65 
66 	u32 tx_irqmask;
67 	u32 rx_irqmask;
68 
69 	unsigned int fifosize;
70 	u32 tx_threshold;
71 	u32 rx_threshold;
72 };
73 
tegra_utc_rx_readl(struct tegra_utc_port * tup,unsigned int offset)74 static u32 tegra_utc_rx_readl(struct tegra_utc_port *tup, unsigned int offset)
75 {
76 	void __iomem *addr = tup->rx_base + offset;
77 
78 	return readl_relaxed(addr);
79 }
80 
tegra_utc_rx_writel(struct tegra_utc_port * tup,u32 val,unsigned int offset)81 static void tegra_utc_rx_writel(struct tegra_utc_port *tup, u32 val, unsigned int offset)
82 {
83 	void __iomem *addr = tup->rx_base + offset;
84 
85 	writel_relaxed(val, addr);
86 }
87 
tegra_utc_tx_readl(struct tegra_utc_port * tup,unsigned int offset)88 static u32 tegra_utc_tx_readl(struct tegra_utc_port *tup, unsigned int offset)
89 {
90 	void __iomem *addr = tup->tx_base + offset;
91 
92 	return readl_relaxed(addr);
93 }
94 
tegra_utc_tx_writel(struct tegra_utc_port * tup,u32 val,unsigned int offset)95 static void tegra_utc_tx_writel(struct tegra_utc_port *tup, u32 val, unsigned int offset)
96 {
97 	void __iomem *addr = tup->tx_base + offset;
98 
99 	writel_relaxed(val, addr);
100 }
101 
tegra_utc_enable_tx_irq(struct tegra_utc_port * tup)102 static void tegra_utc_enable_tx_irq(struct tegra_utc_port *tup)
103 {
104 	tup->tx_irqmask = TEGRA_UTC_INTR_REQ;
105 
106 	tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_MASK);
107 	tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_SET);
108 }
109 
tegra_utc_disable_tx_irq(struct tegra_utc_port * tup)110 static void tegra_utc_disable_tx_irq(struct tegra_utc_port *tup)
111 {
112 	tup->tx_irqmask = 0x0;
113 
114 	tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_MASK);
115 	tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_SET);
116 }
117 
tegra_utc_stop_tx(struct uart_port * port)118 static void tegra_utc_stop_tx(struct uart_port *port)
119 {
120 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
121 
122 	tegra_utc_disable_tx_irq(tup);
123 }
124 
tegra_utc_init_tx(struct tegra_utc_port * tup)125 static void tegra_utc_init_tx(struct tegra_utc_port *tup)
126 {
127 	/* Disable TX. */
128 	tegra_utc_tx_writel(tup, 0x0, TEGRA_UTC_ENABLE);
129 
130 	/* Update the FIFO Threshold. */
131 	tegra_utc_tx_writel(tup, tup->tx_threshold, TEGRA_UTC_FIFO_THRESHOLD);
132 
133 	/* Clear and mask all the interrupts. */
134 	tegra_utc_tx_writel(tup, TEGRA_UTC_INTR_COMMON, TEGRA_UTC_INTR_CLEAR);
135 	tegra_utc_disable_tx_irq(tup);
136 
137 	/* Enable TX. */
138 	tegra_utc_tx_writel(tup, TEGRA_UTC_ENABLE_CLIENT_ENABLE, TEGRA_UTC_ENABLE);
139 }
140 
tegra_utc_init_rx(struct tegra_utc_port * tup)141 static void tegra_utc_init_rx(struct tegra_utc_port *tup)
142 {
143 	tup->rx_irqmask = TEGRA_UTC_INTR_REQ | TEGRA_UTC_INTR_TIMEOUT;
144 
145 	tegra_utc_rx_writel(tup, TEGRA_UTC_COMMAND_RESET, TEGRA_UTC_COMMAND);
146 	tegra_utc_rx_writel(tup, tup->rx_threshold, TEGRA_UTC_FIFO_THRESHOLD);
147 
148 	/* Clear all the pending interrupts. */
149 	tegra_utc_rx_writel(tup, TEGRA_UTC_INTR_TIMEOUT | TEGRA_UTC_INTR_OVERFLOW |
150 			    TEGRA_UTC_INTR_COMMON, TEGRA_UTC_INTR_CLEAR);
151 	tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_MASK);
152 	tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_SET);
153 
154 	/* Enable RX. */
155 	tegra_utc_rx_writel(tup, TEGRA_UTC_ENABLE_CLIENT_ENABLE, TEGRA_UTC_ENABLE);
156 }
157 
tegra_utc_tx_chars(struct tegra_utc_port * tup)158 static bool tegra_utc_tx_chars(struct tegra_utc_port *tup)
159 {
160 	struct uart_port *port = &tup->port;
161 	unsigned int pending;
162 	u8 c;
163 
164 	pending = uart_port_tx(port, c,
165 		     !(tegra_utc_tx_readl(tup, TEGRA_UTC_FIFO_STATUS) & TEGRA_UTC_FIFO_FULL),
166 		     tegra_utc_tx_writel(tup, c, TEGRA_UTC_DATA));
167 
168 	return pending;
169 }
170 
tegra_utc_rx_chars(struct tegra_utc_port * tup)171 static void tegra_utc_rx_chars(struct tegra_utc_port *tup)
172 {
173 	struct tty_port *port = &tup->port.state->port;
174 	unsigned int max_chars = 256;
175 	u32 status;
176 	int sysrq;
177 	u32 ch;
178 
179 	while (max_chars--) {
180 		status = tegra_utc_rx_readl(tup, TEGRA_UTC_FIFO_STATUS);
181 		if (status & TEGRA_UTC_FIFO_EMPTY)
182 			break;
183 
184 		ch = tegra_utc_rx_readl(tup, TEGRA_UTC_DATA);
185 		tup->port.icount.rx++;
186 
187 		if (status & TEGRA_UTC_FIFO_OVERFLOW)
188 			tup->port.icount.overrun++;
189 
190 		uart_port_unlock(&tup->port);
191 		sysrq = uart_handle_sysrq_char(&tup->port, ch);
192 		uart_port_lock(&tup->port);
193 
194 		if (!sysrq)
195 			tty_insert_flip_char(port, ch, TTY_NORMAL);
196 	}
197 
198 	tty_flip_buffer_push(port);
199 }
200 
tegra_utc_isr(int irq,void * dev_id)201 static irqreturn_t tegra_utc_isr(int irq, void *dev_id)
202 {
203 	struct tegra_utc_port *tup = dev_id;
204 	unsigned int handled = 0;
205 	u32 status;
206 
207 	uart_port_lock(&tup->port);
208 
209 	/* Process RX_REQ and RX_TIMEOUT interrupts. */
210 	do {
211 		status = tegra_utc_rx_readl(tup, TEGRA_UTC_INTR_STATUS) & tup->rx_irqmask;
212 		if (status) {
213 			tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_CLEAR);
214 			tegra_utc_rx_chars(tup);
215 			handled = 1;
216 		}
217 	} while (status);
218 
219 	/* Process TX_REQ interrupt. */
220 	do {
221 		status = tegra_utc_tx_readl(tup, TEGRA_UTC_INTR_STATUS) & tup->tx_irqmask;
222 		if (status) {
223 			tegra_utc_tx_writel(tup, tup->tx_irqmask, TEGRA_UTC_INTR_CLEAR);
224 			tegra_utc_tx_chars(tup);
225 			handled = 1;
226 		}
227 	} while (status);
228 
229 	uart_port_unlock(&tup->port);
230 
231 	return IRQ_RETVAL(handled);
232 }
233 
tegra_utc_tx_empty(struct uart_port * port)234 static unsigned int tegra_utc_tx_empty(struct uart_port *port)
235 {
236 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
237 
238 	return tegra_utc_tx_readl(tup, TEGRA_UTC_FIFO_OCCUPANCY) ? 0 : TIOCSER_TEMT;
239 }
240 
tegra_utc_set_mctrl(struct uart_port * port,unsigned int mctrl)241 static void tegra_utc_set_mctrl(struct uart_port *port, unsigned int mctrl)
242 {
243 }
244 
tegra_utc_get_mctrl(struct uart_port * port)245 static unsigned int tegra_utc_get_mctrl(struct uart_port *port)
246 {
247 	return 0;
248 }
249 
tegra_utc_start_tx(struct uart_port * port)250 static void tegra_utc_start_tx(struct uart_port *port)
251 {
252 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
253 
254 	if (tegra_utc_tx_chars(tup))
255 		tegra_utc_enable_tx_irq(tup);
256 }
257 
tegra_utc_stop_rx(struct uart_port * port)258 static void tegra_utc_stop_rx(struct uart_port *port)
259 {
260 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
261 
262 	tup->rx_irqmask = 0x0;
263 	tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_MASK);
264 	tegra_utc_rx_writel(tup, tup->rx_irqmask, TEGRA_UTC_INTR_SET);
265 }
266 
tegra_utc_hw_init(struct tegra_utc_port * tup)267 static void tegra_utc_hw_init(struct tegra_utc_port *tup)
268 {
269 	tegra_utc_init_tx(tup);
270 	tegra_utc_init_rx(tup);
271 }
272 
tegra_utc_startup(struct uart_port * port)273 static int tegra_utc_startup(struct uart_port *port)
274 {
275 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
276 	int ret;
277 
278 	tegra_utc_hw_init(tup);
279 
280 	/* Interrupt is dedicated to this UTC client. */
281 	ret = request_irq(port->irq, tegra_utc_isr, 0, dev_name(port->dev), tup);
282 	if (ret < 0)
283 		dev_err(port->dev, "failed to register interrupt handler\n");
284 
285 	return ret;
286 }
287 
tegra_utc_shutdown(struct uart_port * port)288 static void tegra_utc_shutdown(struct uart_port *port)
289 {
290 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
291 
292 	tegra_utc_rx_writel(tup, 0x0, TEGRA_UTC_ENABLE);
293 	free_irq(port->irq, tup);
294 }
295 
tegra_utc_set_termios(struct uart_port * port,struct ktermios * termios,const struct ktermios * old)296 static void tegra_utc_set_termios(struct uart_port *port, struct ktermios *termios,
297 				  const struct ktermios *old)
298 {
299 	/* The Tegra UTC clients supports only 8-N-1 configuration without HW flow control */
300 	termios->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
301 	termios->c_cflag &= ~(CMSPAR | CRTSCTS);
302 	termios->c_cflag |= CS8 | CLOCAL;
303 }
304 
305 #ifdef CONFIG_CONSOLE_POLL
306 
tegra_utc_poll_init(struct uart_port * port)307 static int tegra_utc_poll_init(struct uart_port *port)
308 {
309 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
310 
311 	tegra_utc_hw_init(tup);
312 	return 0;
313 }
314 
tegra_utc_get_poll_char(struct uart_port * port)315 static int tegra_utc_get_poll_char(struct uart_port *port)
316 {
317 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
318 
319 	if (tegra_utc_rx_readl(tup, TEGRA_UTC_FIFO_STATUS) & TEGRA_UTC_FIFO_EMPTY)
320 		return NO_POLL_CHAR;
321 
322 	return tegra_utc_rx_readl(tup, TEGRA_UTC_DATA);
323 }
324 
tegra_utc_put_poll_char(struct uart_port * port,unsigned char ch)325 static void tegra_utc_put_poll_char(struct uart_port *port, unsigned char ch)
326 {
327 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
328 	u32 val;
329 
330 	read_poll_timeout_atomic(tegra_utc_tx_readl, val, !(val & TEGRA_UTC_FIFO_FULL),
331 				 0, USEC_PER_SEC, false, tup, TEGRA_UTC_FIFO_STATUS);
332 
333 	tegra_utc_tx_writel(tup, ch, TEGRA_UTC_DATA);
334 }
335 
336 #endif
337 
338 static const struct uart_ops tegra_utc_uart_ops = {
339 	.tx_empty = tegra_utc_tx_empty,
340 	.set_mctrl = tegra_utc_set_mctrl,
341 	.get_mctrl = tegra_utc_get_mctrl,
342 	.stop_tx = tegra_utc_stop_tx,
343 	.start_tx = tegra_utc_start_tx,
344 	.stop_rx = tegra_utc_stop_rx,
345 	.startup = tegra_utc_startup,
346 	.shutdown = tegra_utc_shutdown,
347 	.set_termios = tegra_utc_set_termios,
348 #ifdef CONFIG_CONSOLE_POLL
349 	.poll_init = tegra_utc_poll_init,
350 	.poll_get_char = tegra_utc_get_poll_char,
351 	.poll_put_char = tegra_utc_put_poll_char,
352 #endif
353 };
354 
355 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE)
356 #define TEGRA_UTC_DEFAULT_FIFO_THRESHOLD	4
357 #define TEGRA_UTC_EARLYCON_MAX_BURST_SIZE	128
358 
tegra_utc_putc(struct uart_port * port,unsigned char c)359 static void tegra_utc_putc(struct uart_port *port, unsigned char c)
360 {
361 	writel(c, port->membase + TEGRA_UTC_DATA);
362 }
363 
tegra_utc_early_write(struct console * con,const char * s,unsigned int n)364 static void tegra_utc_early_write(struct console *con, const char *s, unsigned int n)
365 {
366 	struct earlycon_device *dev = con->data;
367 
368 	while (n) {
369 		u32 burst_size = TEGRA_UTC_EARLYCON_MAX_BURST_SIZE;
370 
371 		burst_size -= readl(dev->port.membase + TEGRA_UTC_FIFO_OCCUPANCY);
372 		if (n < burst_size)
373 			burst_size = n;
374 
375 		uart_console_write(&dev->port, s, burst_size, tegra_utc_putc);
376 
377 		n -= burst_size;
378 		s += burst_size;
379 	}
380 }
381 
tegra_utc_early_console_setup(struct earlycon_device * device,const char * opt)382 static int __init tegra_utc_early_console_setup(struct earlycon_device *device, const char *opt)
383 {
384 	if (!device->port.membase)
385 		return -ENODEV;
386 
387 	/* Configure TX */
388 	writel(TEGRA_UTC_COMMAND_FLUSH | TEGRA_UTC_COMMAND_RESET,
389 		device->port.membase + TEGRA_UTC_COMMAND);
390 	writel(TEGRA_UTC_DEFAULT_FIFO_THRESHOLD, device->port.membase + TEGRA_UTC_FIFO_THRESHOLD);
391 
392 	/* Clear and mask all the interrupts. */
393 	writel(TEGRA_UTC_INTR_COMMON, device->port.membase + TEGRA_UTC_INTR_CLEAR);
394 
395 	writel(0x0, device->port.membase + TEGRA_UTC_INTR_MASK);
396 	writel(0x0, device->port.membase + TEGRA_UTC_INTR_SET);
397 
398 	/* Enable TX. */
399 	writel(TEGRA_UTC_ENABLE_CLIENT_ENABLE, device->port.membase + TEGRA_UTC_ENABLE);
400 
401 	device->con->write = tegra_utc_early_write;
402 
403 	return 0;
404 }
405 OF_EARLYCON_DECLARE(tegra_utc, "nvidia,tegra264-utc", tegra_utc_early_console_setup);
406 
tegra_utc_console_putchar(struct uart_port * port,unsigned char ch)407 static void tegra_utc_console_putchar(struct uart_port *port, unsigned char ch)
408 {
409 	struct tegra_utc_port *tup = container_of(port, struct tegra_utc_port, port);
410 
411 	tegra_utc_tx_writel(tup, ch, TEGRA_UTC_DATA);
412 }
413 
tegra_utc_console_write_atomic(struct console * cons,struct nbcon_write_context * wctxt)414 static void tegra_utc_console_write_atomic(struct console *cons, struct nbcon_write_context *wctxt)
415 {
416 	struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console);
417 	unsigned int len;
418 	char *outbuf;
419 
420 	if (!nbcon_enter_unsafe(wctxt))
421 		return;
422 
423 	outbuf = wctxt->outbuf;
424 	len = wctxt->len;
425 
426 	while (len) {
427 		u32 burst_size = tup->fifosize;
428 
429 		burst_size -= tegra_utc_tx_readl(tup, TEGRA_UTC_FIFO_OCCUPANCY);
430 		if (len < burst_size)
431 			burst_size = len;
432 
433 		uart_console_write(&tup->port, outbuf, burst_size, tegra_utc_console_putchar);
434 
435 		outbuf += burst_size;
436 		len -= burst_size;
437 	}
438 
439 	nbcon_exit_unsafe(wctxt);
440 }
441 
tegra_utc_console_write_thread(struct console * cons,struct nbcon_write_context * wctxt)442 static void tegra_utc_console_write_thread(struct console *cons, struct nbcon_write_context *wctxt)
443 {
444 	struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console);
445 	unsigned int len = READ_ONCE(wctxt->len);
446 	unsigned int i;
447 	u32 val;
448 
449 	for (i = 0; i < len; i++) {
450 		if (!nbcon_enter_unsafe(wctxt))
451 			break;
452 
453 		read_poll_timeout_atomic(tegra_utc_tx_readl, val, !(val & TEGRA_UTC_FIFO_FULL),
454 					 0, USEC_PER_SEC, false, tup, TEGRA_UTC_FIFO_STATUS);
455 		uart_console_write(&tup->port, wctxt->outbuf + i, 1, tegra_utc_console_putchar);
456 
457 		if (!nbcon_exit_unsafe(wctxt))
458 			break;
459 	}
460 }
461 
tegra_utc_console_device_lock(struct console * cons,unsigned long * flags)462 static void tegra_utc_console_device_lock(struct console *cons, unsigned long *flags)
463 {
464 	struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console);
465 	struct uart_port *port = &tup->port;
466 
467 	__uart_port_lock_irqsave(port, flags);
468 }
469 
tegra_utc_console_device_unlock(struct console * cons,unsigned long flags)470 static void tegra_utc_console_device_unlock(struct console *cons, unsigned long flags)
471 {
472 	struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console);
473 	struct uart_port *port = &tup->port;
474 
475 	__uart_port_unlock_irqrestore(port, flags);
476 }
477 
tegra_utc_console_setup(struct console * cons,char * options)478 static int tegra_utc_console_setup(struct console *cons, char *options)
479 {
480 	struct tegra_utc_port *tup = container_of(cons, struct tegra_utc_port, console);
481 
482 	tegra_utc_init_tx(tup);
483 
484 	return 0;
485 }
486 #endif
487 
488 static struct uart_driver tegra_utc_driver = {
489 	.driver_name	= "tegra-utc",
490 	.dev_name	= "ttyUTC",
491 	.nr		= TEGRA_UTC_UART_NR,
492 };
493 
tegra_utc_setup_port(struct device * dev,struct tegra_utc_port * tup)494 static int tegra_utc_setup_port(struct device *dev, struct tegra_utc_port *tup)
495 {
496 	tup->port.dev			= dev;
497 	tup->port.fifosize		= tup->fifosize;
498 	tup->port.flags			= UPF_BOOT_AUTOCONF;
499 	tup->port.iotype		= UPIO_MEM;
500 	tup->port.ops			= &tegra_utc_uart_ops;
501 	tup->port.type			= PORT_TEGRA_TCU;
502 	tup->port.private_data		= tup;
503 
504 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE)
505 	strscpy(tup->console.name, "ttyUTC", sizeof(tup->console.name));
506 	tup->console.write_atomic	= tegra_utc_console_write_atomic;
507 	tup->console.write_thread	= tegra_utc_console_write_thread;
508 	tup->console.device_lock	= tegra_utc_console_device_lock;
509 	tup->console.device_unlock	= tegra_utc_console_device_unlock;
510 	tup->console.device		= uart_console_device;
511 	tup->console.setup		= tegra_utc_console_setup;
512 	tup->console.flags		= CON_PRINTBUFFER | CON_NBCON;
513 	tup->console.data		= &tegra_utc_driver;
514 #endif
515 
516 	return uart_read_port_properties(&tup->port);
517 }
518 
tegra_utc_register_port(struct tegra_utc_port * tup)519 static int tegra_utc_register_port(struct tegra_utc_port *tup)
520 {
521 	int ret;
522 
523 	ret = uart_add_one_port(&tegra_utc_driver, &tup->port);
524 	if (ret)
525 		return ret;
526 
527 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE)
528 	register_console(&tup->console);
529 #endif
530 
531 	return 0;
532 }
533 
tegra_utc_probe(struct platform_device * pdev)534 static int tegra_utc_probe(struct platform_device *pdev)
535 {
536 	const unsigned int *soc_fifosize;
537 	struct device *dev = &pdev->dev;
538 	struct tegra_utc_port *tup;
539 	int ret;
540 
541 	tup = devm_kzalloc(dev, sizeof(*tup), GFP_KERNEL);
542 	if (!tup)
543 		return -ENOMEM;
544 
545 	ret = device_property_read_u32(dev, "tx-threshold", &tup->tx_threshold);
546 	if (ret)
547 		return dev_err_probe(dev, ret, "missing %s property\n", "tx-threshold");
548 
549 	ret = device_property_read_u32(dev, "rx-threshold", &tup->rx_threshold);
550 	if (ret)
551 		return dev_err_probe(dev, ret, "missing %s property\n", "rx-threshold");
552 
553 	soc_fifosize = device_get_match_data(dev);
554 	tup->fifosize = *soc_fifosize;
555 
556 	tup->tx_base = devm_platform_ioremap_resource_byname(pdev, "tx");
557 	if (IS_ERR(tup->tx_base))
558 		return PTR_ERR(tup->tx_base);
559 
560 	tup->rx_base = devm_platform_ioremap_resource_byname(pdev, "rx");
561 	if (IS_ERR(tup->rx_base))
562 		return PTR_ERR(tup->rx_base);
563 
564 	ret = tegra_utc_setup_port(dev, tup);
565 	if (ret)
566 		dev_err_probe(dev, ret, "failed to setup uart port\n");
567 
568 	platform_set_drvdata(pdev, tup);
569 
570 	return tegra_utc_register_port(tup);
571 }
572 
tegra_utc_remove(struct platform_device * pdev)573 static void tegra_utc_remove(struct platform_device *pdev)
574 {
575 	struct tegra_utc_port *tup = platform_get_drvdata(pdev);
576 
577 #if IS_ENABLED(CONFIG_SERIAL_TEGRA_UTC_CONSOLE)
578 	unregister_console(&tup->console);
579 #endif
580 	uart_remove_one_port(&tegra_utc_driver, &tup->port);
581 }
582 
583 static const unsigned int tegra264_utc_soc = 128;
584 
585 static const struct of_device_id tegra_utc_of_match[] = {
586 	{ .compatible = "nvidia,tegra264-utc", .data = &tegra264_utc_soc },
587 	{}
588 };
589 MODULE_DEVICE_TABLE(of, tegra_utc_of_match);
590 
591 static struct platform_driver tegra_utc_platform_driver = {
592 	.probe = tegra_utc_probe,
593 	.remove = tegra_utc_remove,
594 	.driver = {
595 		.name = "tegra-utc",
596 		.of_match_table = tegra_utc_of_match,
597 	},
598 };
599 
tegra_utc_init(void)600 static int __init tegra_utc_init(void)
601 {
602 	int ret;
603 
604 	ret = uart_register_driver(&tegra_utc_driver);
605 	if (ret)
606 		return ret;
607 
608 	ret = platform_driver_register(&tegra_utc_platform_driver);
609 	if (ret)
610 		uart_unregister_driver(&tegra_utc_driver);
611 
612 	return ret;
613 }
614 module_init(tegra_utc_init);
615 
tegra_utc_exit(void)616 static void __exit tegra_utc_exit(void)
617 {
618 	platform_driver_unregister(&tegra_utc_platform_driver);
619 	uart_unregister_driver(&tegra_utc_driver);
620 }
621 module_exit(tegra_utc_exit);
622 
623 MODULE_AUTHOR("Kartik Rajput <kkartik@nvidia.com>");
624 MODULE_DESCRIPTION("Tegra UART Trace Controller");
625 MODULE_LICENSE("GPL");
626