From 5ec6cbcc7fb9604fd70587215123b77fdc326032 Mon Sep 17 00:00:00 2001 From: Stefan Bosch Date: Sun, 18 Dec 2022 12:20:49 +0000 Subject: [PATCH] arm: s5p4418: dm_serial: add driver source code 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 --- 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 3fc4cd0f12..5f9636f4e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -436,6 +436,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 + */ + +#include +#include +#include +#include +#include + +#include +#include +#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.39.5