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