forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-02-19 1c055e55a242a33e574e48be530e06770a210dcd
kernel/drivers/tty/serial/meson_uart.c
....@@ -5,15 +5,12 @@
55 * Copyright (C) 2014 Carlo Caione <carlo@caione.org>
66 */
77
8
-#if defined(CONFIG_SERIAL_MESON_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
9
-#define SUPPORT_SYSRQ
10
-#endif
11
-
128 #include <linux/clk.h>
139 #include <linux/console.h>
1410 #include <linux/delay.h>
1511 #include <linux/init.h>
1612 #include <linux/io.h>
13
+#include <linux/iopoll.h>
1714 #include <linux/module.h>
1815 #include <linux/kernel.h>
1916 #include <linux/of.h>
....@@ -72,9 +69,12 @@
7269 #define AML_UART_BAUD_USE BIT(23)
7370 #define AML_UART_BAUD_XTAL BIT(24)
7471
75
-#define AML_UART_PORT_NUM 6
72
+#define AML_UART_PORT_NUM 12
73
+#define AML_UART_PORT_OFFSET 6
7674 #define AML_UART_DEV_NAME "ttyAML"
7775
76
+#define AML_UART_POLL_USEC 5
77
+#define AML_UART_TIMEOUT_USEC 10000
7878
7979 static struct uart_driver meson_uart_driver;
8080
....@@ -255,6 +255,14 @@
255255 return (port->type == PORT_MESON) ? "meson_uart" : NULL;
256256 }
257257
258
+/*
259
+ * This function is called only from probe() using a temporary io mapping
260
+ * in order to perform a reset before setting up the device. Since the
261
+ * temporarily mapped region was successfully requested, there can be no
262
+ * console on this port at this time. Hence it is not necessary for this
263
+ * function to acquire the port->lock. (Since there is no console on this
264
+ * port at this time, the port->lock is not initialized yet.)
265
+ */
258266 static void meson_uart_reset(struct uart_port *port)
259267 {
260268 u32 val;
....@@ -269,8 +277,11 @@
269277
270278 static int meson_uart_startup(struct uart_port *port)
271279 {
280
+ unsigned long flags;
272281 u32 val;
273282 int ret = 0;
283
+
284
+ spin_lock_irqsave(&port->lock, flags);
274285
275286 val = readl(port->membase + AML_UART_CONTROL);
276287 val |= AML_UART_CLEAR_ERR;
....@@ -286,6 +297,8 @@
286297
287298 val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
288299 writel(val, port->membase + AML_UART_MISC);
300
+
301
+ spin_unlock_irqrestore(&port->lock, flags);
289302
290303 ret = request_irq(port->irq, meson_uart_interrupt, 0,
291304 port->name, port);
....@@ -410,7 +423,7 @@
410423 return -EBUSY;
411424 }
412425
413
- port->membase = devm_ioremap_nocache(port->dev, port->mapbase,
426
+ port->membase = devm_ioremap(port->dev, port->mapbase,
414427 port->mapsize);
415428 if (!port->membase)
416429 return -ENOMEM;
....@@ -425,6 +438,64 @@
425438 meson_uart_request_port(port);
426439 }
427440 }
441
+
442
+#ifdef CONFIG_CONSOLE_POLL
443
+/*
444
+ * Console polling routines for writing and reading from the uart while
445
+ * in an interrupt or debug context (i.e. kgdb).
446
+ */
447
+
448
+static int meson_uart_poll_get_char(struct uart_port *port)
449
+{
450
+ u32 c;
451
+ unsigned long flags;
452
+
453
+ spin_lock_irqsave(&port->lock, flags);
454
+
455
+ if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)
456
+ c = NO_POLL_CHAR;
457
+ else
458
+ c = readl(port->membase + AML_UART_RFIFO);
459
+
460
+ spin_unlock_irqrestore(&port->lock, flags);
461
+
462
+ return c;
463
+}
464
+
465
+static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c)
466
+{
467
+ unsigned long flags;
468
+ u32 reg;
469
+ int ret;
470
+
471
+ spin_lock_irqsave(&port->lock, flags);
472
+
473
+ /* Wait until FIFO is empty or timeout */
474
+ ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
475
+ reg & AML_UART_TX_EMPTY,
476
+ AML_UART_POLL_USEC,
477
+ AML_UART_TIMEOUT_USEC);
478
+ if (ret == -ETIMEDOUT) {
479
+ dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
480
+ goto out;
481
+ }
482
+
483
+ /* Write the character */
484
+ writel(c, port->membase + AML_UART_WFIFO);
485
+
486
+ /* Wait until FIFO is empty or timeout */
487
+ ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
488
+ reg & AML_UART_TX_EMPTY,
489
+ AML_UART_POLL_USEC,
490
+ AML_UART_TIMEOUT_USEC);
491
+ if (ret == -ETIMEDOUT)
492
+ dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
493
+
494
+out:
495
+ spin_unlock_irqrestore(&port->lock, flags);
496
+}
497
+
498
+#endif /* CONFIG_CONSOLE_POLL */
428499
429500 static const struct uart_ops meson_uart_ops = {
430501 .set_mctrl = meson_uart_set_mctrl,
....@@ -441,6 +512,10 @@
441512 .request_port = meson_uart_request_port,
442513 .release_port = meson_uart_release_port,
443514 .verify_port = meson_uart_verify_port,
515
+#ifdef CONFIG_CONSOLE_POLL
516
+ .poll_get_char = meson_uart_poll_get_char,
517
+ .poll_put_char = meson_uart_poll_put_char,
518
+#endif
444519 };
445520
446521 #ifdef CONFIG_SERIAL_MESON_CONSOLE
....@@ -542,7 +617,6 @@
542617 register_console(&meson_serial_console);
543618 return 0;
544619 }
545
-console_initcall(meson_serial_console_init);
546620
547621 static void meson_serial_early_console_write(struct console *co,
548622 const char *s,
....@@ -572,6 +646,9 @@
572646
573647 #define MESON_SERIAL_CONSOLE (&meson_serial_console)
574648 #else
649
+static int __init meson_serial_console_init(void) {
650
+ return 0;
651
+}
575652 #define MESON_SERIAL_CONSOLE NULL
576653 #endif
577654
....@@ -654,9 +731,19 @@
654731 struct resource *res_mem, *res_irq;
655732 struct uart_port *port;
656733 int ret = 0;
734
+ int id = -1;
657735
658736 if (pdev->dev.of_node)
659737 pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
738
+
739
+ if (pdev->id < 0) {
740
+ for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) {
741
+ if (!meson_ports[id]) {
742
+ pdev->id = id;
743
+ break;
744
+ }
745
+ }
746
+ }
660747
661748 if (pdev->id < 0 || pdev->id >= AML_UART_PORT_NUM)
662749 return -EINVAL;
....@@ -692,6 +779,7 @@
692779 port->mapsize = resource_size(res_mem);
693780 port->irq = res_irq->start;
694781 port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
782
+ port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE);
695783 port->dev = &pdev->dev;
696784 port->line = pdev->id;
697785 port->type = PORT_MESON;
....@@ -751,6 +839,10 @@
751839 {
752840 int ret;
753841
842
+ ret = meson_serial_console_init();
843
+ if (ret)
844
+ return ret;
845
+
754846 ret = uart_register_driver(&meson_uart_driver);
755847 if (ret)
756848 return ret;