[PATCH v1 1/4] arm: s5p4418: dm_serial: add driver source code

Stefan Bosch stefan_b at posteo.net
Sun Dec 18 13:20:49 CET 2022


Add dm_serial driver source code for S5P4418 SOC. Extend the "arm,pl011"
driver by init of UART-clock and UART-reset.

Signed-off-by: Stefan Bosch <stefan_b at posteo.net>
---

 MAINTAINERS                           |  1 +
 drivers/serial/serial_s5p4418_pl011.c | 94 +++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 drivers/serial/serial_s5p4418_pl011.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cb4d44584d..3473f765fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -411,6 +411,7 @@ F:	drivers/gpio/nx_gpio.c
 F:	drivers/i2c/nx_i2c.c
 F:	drivers/mmc/nexell_dw_mmc_dm.c
 F:	drivers/pinctrl/nexell/
+F:	drivers/serial/serial_s5p4418_pl011.c
 F:	drivers/video/nexell/
 F:	drivers/video/nexell_display.c
 F:	include/configs/s5p4418_nanopi2.h
diff --git a/drivers/serial/serial_s5p4418_pl011.c b/drivers/serial/serial_s5p4418_pl011.c
new file mode 100644
index 0000000000..e4492e662e
--- /dev/null
+++ b/drivers/serial/serial_s5p4418_pl011.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022  Stefan Bosch <stefan_b at posteo.net>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/reset.h>
+#include <linux/delay.h>
+
+#include <dm/platform_data/serial_pl01x.h>
+#include <serial.h>
+#include "serial_pl01x_internal.h"
+
+int s5p4418_pl011_serial_probe(struct udevice *dev)
+{
+	struct pl01x_serial_plat *plat = dev_get_plat(dev);
+	struct clk *nx_clk;
+	ulong rate_act;
+	char uart_clk_name[10];
+	int uart_num = -1;
+	int rst_id, ret;
+
+	if (!plat->skip_init) {
+		uart_num = dev->seq_;
+		rst_id = RESET_ID_UART0 + uart_num;
+
+		if (uart_num < 0 || rst_id > RESET_ID_UART5) {
+			/* invalid UART-number */
+			debug("%s: sequence/uart number %d is invalid!\n", __func__, uart_num);
+			return -ENODEV;
+		}
+
+		sprintf(uart_clk_name, "nx-uart.%d", uart_num);
+		nx_clk = clk_get(uart_clk_name);
+		if (!nx_clk) {
+			debug("%s: clk_get('%s') failed!\n", __func__, uart_clk_name);
+			return -ENODEV;
+		}
+
+		/* wait to make sure all pending characters have been sent */
+		mdelay(100);
+	}
+
+	/*
+	 * Note: Unless !plat->skip_init, the UART is disabled here, so printf()
+	 * or debug() must not be used until pl01x_serial_setbrg() has been called
+	 * (enables the UART). Otherwise u-boot is hanging!
+	 */
+	ret = pl01x_serial_probe(dev);
+	if (ret)
+		return ret;
+
+	if (!plat->skip_init) {
+		/* do reset UART */
+		nx_rstcon_setrst(rst_id, RSTCON_ASSERT);
+		udelay(10);
+		nx_rstcon_setrst(rst_id, RSTCON_NEGATE);
+		udelay(10);
+		clk_disable(nx_clk);
+
+		rate_act = clk_set_rate(nx_clk, plat->clock);
+		clk_enable(nx_clk);
+
+		plat->clock = rate_act;
+	}
+
+	return 0;
+}
+
+static const struct dm_serial_ops s5p4418_pl011_serial_ops = {
+	.putc = pl01x_serial_putc,
+	.pending = pl01x_serial_pending,
+	.getc = pl01x_serial_getc,
+	.setbrg = pl01x_serial_setbrg,
+};
+
+static const struct udevice_id s5p4418_pl011_serial_id[] = {
+	{.compatible = "nexell,s5p4418-pl011", .data = TYPE_PL011},
+	{}
+};
+
+U_BOOT_DRIVER(s5p4418_pl011_uart) = {
+	.name	= "s5p4418_pl011",
+	.id	= UCLASS_SERIAL,
+	.of_match = of_match_ptr(s5p4418_pl011_serial_id),
+	.of_to_plat = of_match_ptr(pl01x_serial_of_to_plat),
+	.plat_auto	= sizeof(struct pl01x_serial_plat),
+	.probe = s5p4418_pl011_serial_probe,
+	.ops	= &s5p4418_pl011_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+	.priv_auto	= sizeof(struct pl01x_priv),
+};
-- 
2.17.1



More information about the U-Boot mailing list