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