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