Merge branch '2023-01-02-platform-updates' into next

- Synquacer updates / fixes, PowerPC keymile platform dts fix, assorted
  TI platform updates, ht1380 RTC driver, serial driver cleanups,
  pg_wcom defconfig updates, s5p4418 DM_SERIAL (and legacy code removal).
diff --git a/MAINTAINERS b/MAINTAINERS
index 3fc4cd0..5f9636f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -436,6 +436,7 @@
 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/arch/arm/cpu/armv7/s5p4418/cpu.c b/arch/arm/cpu/armv7/s5p4418/cpu.c
index 7ba9c0b..fcaafc0 100644
--- a/arch/arm/cpu/armv7/s5p4418/cpu.c
+++ b/arch/arm/cpu/armv7/s5p4418/cpu.c
@@ -13,10 +13,8 @@
 #include <asm/io.h>
 #include <asm/arch/nexell.h>
 #include <asm/arch/clk.h>
-#include <asm/arch/reset.h>
 #include <asm/arch/tieoff.h>
 #include <cpu_func.h>
-#include <linux/delay.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -45,39 +43,12 @@
 	nx_tieoff_set(NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_1, 1);
 }
 
-#ifdef CONFIG_PL011_SERIAL
-static void serial_device_init(void)
-{
-	char dev[10];
-	int id;
-
-	sprintf(dev, "nx-uart.%d", CONFIG_CONS_INDEX);
-	id = RESET_ID_UART0 + CONFIG_CONS_INDEX;
-
-	struct clk *clk = clk_get((const char *)dev);
-
-	/* reset control: Low active ___|---   */
-	nx_rstcon_setrst(id, RSTCON_ASSERT);
-	udelay(10);
-	nx_rstcon_setrst(id, RSTCON_NEGATE);
-	udelay(10);
-
-	/* set clock   */
-	clk_disable(clk);
-	clk_set_rate(clk, CFG_PL011_CLOCK);
-	clk_enable(clk);
-}
-#endif
-
 int arch_cpu_init(void)
 {
 	flush_dcache_all();
 	cpu_soc_init();
 	clk_init();
 
-	if (IS_ENABLED(CONFIG_PL011_SERIAL))
-		serial_device_init();
-
 	return 0;
 }
 
diff --git a/arch/arm/dts/k3-am64-mcu.dtsi b/arch/arm/dts/k3-am64-mcu.dtsi
index 59cc58f..2bb5c9f 100644
--- a/arch/arm/dts/k3-am64-mcu.dtsi
+++ b/arch/arm/dts/k3-am64-mcu.dtsi
@@ -97,4 +97,12 @@
 		clocks = <&k3_clks 79 0>;
 		clock-names = "gpio";
 	};
+
+	mcu_pmx0: pinctrl@4084000 {
+		compatible = "pinctrl-single";
+		reg = <0x00 0x4084000 0x00 0x84>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
 };
diff --git a/arch/arm/dts/s5p4418-nanopi2.dts b/arch/arm/dts/s5p4418-nanopi2.dts
index 4deaf10..42251e0 100644
--- a/arch/arm/dts/s5p4418-nanopi2.dts
+++ b/arch/arm/dts/s5p4418-nanopi2.dts
@@ -25,6 +25,7 @@
 		i2c0 = "/i2c@c00a4000";
 		i2c1 = "/i2c@c00a5000";
 		i2c2 = "/i2c@c00a6000";
+		serial0 = "/uart@c00a1000";
 	};
 
 	mmc0:mmc@c0062000 {
@@ -107,4 +108,9 @@
 			};
 		};
 	};
+
+	uart0:uart@c00a1000 {
+		skip-init;
+		status = "okay";
+	};
 };
diff --git a/arch/arm/dts/s5p4418-pinctrl.dtsi b/arch/arm/dts/s5p4418-pinctrl.dtsi
index a7e1c2c..0768d80 100644
--- a/arch/arm/dts/s5p4418-pinctrl.dtsi
+++ b/arch/arm/dts/s5p4418-pinctrl.dtsi
@@ -132,4 +132,75 @@
 		pin-pull = <2>;
 		pin-strength = <0>;
 	};
+
+	/* UART */
+	uart0_rx:uart0-rx {
+		pins = "gpiod-14";
+		pin-function = <1>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart0_tx:uart0-tx {
+		pins = "gpiod-18";
+		pin-function = <1>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart1_rx:uart1-rx {
+		pins = "gpiod-15";
+		pin-function = <2>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart1_tx:uart1-tx {
+		pins = "gpiod-19";
+		pin-function = <2>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart2_rx:uart2-rx {
+		pins = "gpiod-16";
+		pin-function = <1>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart2_tx:uart2-tx {
+		pins = "gpiod-20";
+		pin-function = <1>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart3_rx:uart3-rx {
+		pins = "gpiod-17";
+		pin-function = <1>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart3_tx:uart3-tx {
+		pins = "gpiod-21";
+		pin-function = <1>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart4_rx:uart4-rx {
+		pins = "gpiob-28";
+		pin-function = <3>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
+
+	uart4_tx:uart4-tx {
+		pins = "gpiob-29";
+		pin-function = <3>;
+		pin-pull = <2>;
+		pin-strength = <0>;
+	};
 };
diff --git a/arch/arm/dts/s5p4418.dtsi b/arch/arm/dts/s5p4418.dtsi
index a4d1a1b..3027cd4 100644
--- a/arch/arm/dts/s5p4418.dtsi
+++ b/arch/arm/dts/s5p4418.dtsi
@@ -167,4 +167,44 @@
 		reg = <0xc0010000 0xf000>;
 		u-boot,dm-pre-reloc;
 	};
+
+	uart0:uart@c00a1000 {
+		compatible = "nexell,s5p4418-pl011", "arm,primecell";
+		reg = <0xc00a1000 0x1000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_rx>, <&uart0_tx>;
+		status = "disabled";
+	};
+
+	uart1:uart@c00a0000 {
+		compatible = "nexell,s5p4418-pl011", "arm,primecell";
+		reg = <0xc00a0000 0x1000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_rx>, <&uart1_tx>;
+		status = "disabled";
+	};
+
+	uart2:uart@c00a2000 {
+		compatible = "nexell,s5p4418-pl011", "arm,primecell";
+		reg = <0xc00a2000 0x1000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2_rx>, <&uart2_tx>;
+		status = "disabled";
+	};
+
+	uart3:uart@c00a3000 {
+		compatible = "nexell,s5p4418-pl011", "arm,primecell";
+		reg = <0xc00a3000 0x1000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart3_rx>, <&uart3_tx>;
+		status = "disabled";
+	};
+
+	uart4:uart@c006d000 {
+		compatible = "nexell,s5p4418-pl011", "arm,primecell";
+		reg = <0xc006d000 0x1000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart4_rx>, <&uart4_tx>;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
index 7a56116..9f9837b 100644
--- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
+++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi
@@ -20,10 +20,8 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "okay";
-		active_clk_edges;
-		chipselect_num = <1>;
 
-		spi-flash@0 {
+		flash@0 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "jedec,spi-nor";
diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox.dts b/arch/arm/dts/synquacer-sc2a11-developerbox.dts
index 42b6cbb..c8087b9 100644
--- a/arch/arm/dts/synquacer-sc2a11-developerbox.dts
+++ b/arch/arm/dts/synquacer-sc2a11-developerbox.dts
@@ -18,7 +18,7 @@
         compatible = "gpio-keys";
         interrupt-parent = <&exiu>;
 
-        power {
+        power-button {
             label = "Power Button";
             linux,code = <KEY_POWER>;
             interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/dts/synquacer-sc2a11.dtsi b/arch/arm/dts/synquacer-sc2a11.dtsi
index 1fe7d21..7ba1cd1 100644
--- a/arch/arm/dts/synquacer-sc2a11.dtsi
+++ b/arch/arm/dts/synquacer-sc2a11.dtsi
@@ -41,168 +41,168 @@
 
         CPU0: cpu@0 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x0>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU1: cpu@1 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x1>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU2: cpu@100 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x100>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU3: cpu@101 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x101>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU4: cpu@200 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x200>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU5: cpu@201 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x201>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU6: cpu@300 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x300>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU7: cpu@301 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x301>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU8: cpu@400 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x400>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU9: cpu@401 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x401>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU10: cpu@500 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x500>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU11: cpu@501 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x501>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU12: cpu@600 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x600>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU13: cpu@601 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x601>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU14: cpu@700 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x700>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU15: cpu@701 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x701>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU16: cpu@800 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x800>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU17: cpu@801 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x801>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU18: cpu@900 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x900>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU19: cpu@901 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0x901>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU20: cpu@a00 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0xa00>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU21: cpu@a01 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0xa01>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU22: cpu@b00 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0xb00>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
         };
         CPU23: cpu@b01 {
             device_type = "cpu";
-            compatible = "arm,cortex-a53","arm,armv8";
+            compatible = "arm,cortex-a53";
             reg = <0xb01>;
             enable-method = "psci";
             cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
@@ -309,7 +309,7 @@
     };
 
     idle-states {
-        entry-method = "arm,psci";
+        entry-method = "psci";
 
         CPU_SLEEP_0: cpu-sleep-0 {
             compatible = "arm,idle-state";
@@ -344,7 +344,7 @@
         interrupt-controller;
         interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
 
-        its: gic-its@30020000 {
+        its: msi-controller@30020000 {
             compatible = "arm,gic-v3-its";
             reg = <0x0 0x30020000 0x0 0x20000>;
             #msi-cells = <1>;
@@ -361,16 +361,16 @@
                      <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;   // HYP
     };
 
-    mmio-timer@2a810000 {
+    timer@2a810000 {
         compatible = "arm,armv7-timer-mem";
         reg = <0x0 0x2a810000 0x0 0x10000>;
-        #address-cells = <2>;
-        #size-cells = <2>;
-        ranges;
-        frame@2a830000 {
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges = <0x0 0x0 0x2a810000 0x30000>;
+        frame@20000 {
             frame-number = <0>;
             interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
-            reg = <0x0 0x2a830000 0x0 0x10000>;
+            reg = <0x20000 0x10000>;
         };
     };
 
@@ -398,7 +398,7 @@
         clock-output-names = "apb_pclk";
     };
 
-    soc_uart0: uart@2a400000 {
+    soc_uart0: serial@2a400000 {
         compatible = "arm,pl011", "arm,primecell";
         reg = <0x0 0x2a400000 0x0 0x1000>;
         interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
@@ -406,7 +406,7 @@
         clock-names = "uartclk", "apb_pclk";
     };
 
-    fuart: uart@51040000 {
+    fuart: serial@51040000 {
         compatible = "snps,dw-apb-uart";
         reg = <0x0 0x51040000 0x0 0x1000>;
         interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
@@ -497,7 +497,6 @@
         gpio-controller;
         #gpio-cells = <2>;
         clocks = <&clk_apb>;
-        base = <0>;
     };
 
     exiu: interrupt-controller@510c0000 {
@@ -523,7 +522,7 @@
         clock-output-names = "sd_sd4clk";
     };
 
-    sdhci: sdhci@52300000 {
+    sdhci: mmc@52300000 {
         compatible = "socionext,synquacer-sdhci", "fujitsu,mb86s70-sdhci-3.0";
         reg = <0 0x52300000 0x0 0x1000>;
         interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm/dts/uniphier-v7-u-boot.dtsi b/arch/arm/dts/uniphier-v7-u-boot.dtsi
index 9459bf0..603b33d 100644
--- a/arch/arm/dts/uniphier-v7-u-boot.dtsi
+++ b/arch/arm/dts/uniphier-v7-u-boot.dtsi
@@ -2,6 +2,10 @@
 	soc {
 		u-boot,dm-pre-reloc;
 
+		timer@60000200 {
+			u-boot,dm-pre-reloc;
+		};
+
 		serial@54006800 {
 			u-boot,dm-pre-reloc;
 		};
diff --git a/arch/arm/mach-nexell/Kconfig b/arch/arm/mach-nexell/Kconfig
index 86a2398..16324e1 100644
--- a/arch/arm/mach-nexell/Kconfig
+++ b/arch/arm/mach-nexell/Kconfig
@@ -6,8 +6,8 @@
 	select OF_CONTROL
 	select OF_SEPARATE
 	select NX_GPIO
-	select PL011_SERIAL
-	select PL011_SERIAL_FLUSH_ON_INIT
+	select DM_SERIAL
+	select PL01X_SERIAL
 	help
 	  Enable support for Nexell S5P4418 SoC.
 
diff --git a/arch/arm/mach-nexell/clock.c b/arch/arm/mach-nexell/clock.c
index 24fa204..59ffa26 100644
--- a/arch/arm/mach-nexell/clock.c
+++ b/arch/arm/mach-nexell/clock.c
@@ -856,7 +856,7 @@
 		}
 
 		/* prevent uart clock disable for low step debug message */
-		#ifndef CONFIG_DEBUG_NX_UART
+		#ifndef CONFIG_DEBUG_UART
 		if (peri->dev_name) {
 			#ifdef CONFIG_BACKLIGHT_PWM
 			if (!strcmp(peri->dev_name, DEV_NAME_PWM))
diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig
index 3a8eee7..c570fb3 100644
--- a/arch/arm/mach-uniphier/Kconfig
+++ b/arch/arm/mach-uniphier/Kconfig
@@ -12,6 +12,7 @@
 	select ARMV7_NONSEC
 	select CPU_V7A
 	select CPU_V7_HAS_NONSEC
+	select ARM_GLOBAL_TIMER if TIMER
 
 config ARCH_UNIPHIER_V8_MULTI
 	bool "UniPhier V8 SoCs"
diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile
index 3cd00b7..b41aba7 100644
--- a/arch/arm/mach-uniphier/arm32/Makefile
+++ b/arch/arm/mach-uniphier/arm32/Makefile
@@ -8,5 +8,3 @@
 obj-y += cache-uniphier.o
 obj-$(CONFIG_ARMV7_PSCI) += psci.o psci_smp.o
 endif
-
-obj-y += timer.o
diff --git a/arch/arm/mach-uniphier/arm32/timer.c b/arch/arm/mach-uniphier/arm32/timer.c
deleted file mode 100644
index 58247c2..0000000
--- a/arch/arm/mach-uniphier/arm32/timer.c
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- */
-
-#include <config.h>
-#include <init.h>
-#include <linux/io.h>
-
-#include "arm-mpcore.h"
-
-#define PERIPHCLK (50 * 1000 * 1000) /* 50 MHz */
-#define PRESCALER ((PERIPHCLK) / (CFG_SYS_TIMER_RATE) - 1)
-
-static void *get_global_timer_base(void)
-{
-	void *val;
-
-	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (val) : : "memory");
-
-	return val + GLOBAL_TIMER_OFFSET;
-}
-
-unsigned long timer_read_counter(void)
-{
-	/*
-	 * ARM 64bit Global Timer is too much for our purpose.
-	 * We use only lower 32 bit of the timer counter.
-	 */
-	return readl(get_global_timer_base() + GTIMER_CNT_L);
-}
-
-int timer_init(void)
-{
-	/* enable timer */
-	writel(PRESCALER << 8 | 1, get_global_timer_base() + GTIMER_CTRL);
-
-	return 0;
-}
diff --git a/arch/powerpc/dts/kmcent2-u-boot.dtsi b/arch/powerpc/dts/kmcent2-u-boot.dtsi
index 53bac55..d027762 100644
--- a/arch/powerpc/dts/kmcent2-u-boot.dtsi
+++ b/arch/powerpc/dts/kmcent2-u-boot.dtsi
@@ -74,24 +74,6 @@
 		compatible = "fsl,pcie-t104x";
 		law_trgt_if = <0>;
 	};
-
-	binman {
-		filename = "u-boot.bin";
-		skip-at-start = <CONFIG_TEXT_BASE>;
-		sort-by-offset;
-		pad-byte = <0xff>;
-		size = <CONFIG_SYS_MONITOR_LEN>;
-
-		u-boot-with-ucode-ptr {
-			offset = <CONFIG_TEXT_BASE>;
-			optional-ucode;
-		};
-
-		u-boot-dtb-with-ucode {
-			align = <256>;
-		};
-		powerpc-mpc85xx-bootpg-resetvec {
-			offset = <(CFG_RESET_VECTOR_ADDRESS - 0xffc)>;
-		};
-	};
 };
+
+#include "u-boot.dtsi"
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c
index c37629f..9a53884 100644
--- a/board/ti/common/board_detect.c
+++ b/board/ti/common/board_detect.c
@@ -87,6 +87,8 @@
 					    u32 header, u32 size, uint8_t *ep)
 {
 	int rc;
+	uint8_t offset_test;
+	bool one_byte_addressing = true;
 
 #if CONFIG_IS_ENABLED(DM_I2C)
 	struct udevice *dev;
@@ -114,8 +116,23 @@
 	 */
 	(void)dm_i2c_read(dev, 0, ep, size);
 
+	if (*((u32 *)ep) != header)
+		one_byte_addressing = false;
+
+	/*
+	 * Handle case of bad 2 byte eeproms that responds to 1 byte addressing
+	 * but gets stuck in const addressing when read requests are performed
+	 * on offsets. We perform an offset test to make sure it is not a 2 byte
+	 * eeprom that works with 1 byte addressing but just without an offset
+	 */
+
+	rc = dm_i2c_read(dev, 0x1, &offset_test, sizeof(offset_test));
+
+	if (*((u32 *)ep) != (header & 0xFF))
+		one_byte_addressing = false;
+
 	/* Corrupted data??? */
-	if (*((u32 *)ep) != header) {
+	if (!one_byte_addressing) {
 		/*
 		 * read the eeprom header using i2c again, but use only a
 		 * 2 byte address (some newer boards need this..)
@@ -151,8 +168,23 @@
 	 */
 	(void)i2c_read(dev_addr, 0x0, byte, ep, size);
 
+	if (*((u32 *)ep) != header)
+		one_byte_addressing = false;
+
+	/*
+	 * Handle case of bad 2 byte eeproms that responds to 1 byte addressing
+	 * but gets stuck in const addressing when read requests are performed
+	 * on offsets. We perform an offset test to make sure it is not a 2 byte
+	 * eeprom that works with 1 byte addressing but just without an offset
+	 */
+
+	rc = i2c_read(dev_addr, 0x1, byte, &offset_test, sizeof(offset_test));
+
+	if (*((u32 *)ep) != (header & 0xFF))
+		one_byte_addressing = false;
+
 	/* Corrupted data??? */
-	if (*((u32 *)ep) != header) {
+	if (!one_byte_addressing) {
 		/*
 		 * read the eeprom header using i2c again, but use only a
 		 * 2 byte address (some newer boards need this..)
@@ -444,16 +476,6 @@
 	if (rc)
 		return rc;
 
-	/*
-	 * Handle case of bad 2 byte eeproms that responds to 1 byte addressing
-	 * but gets stuck in const addressing when read requests are performed
-	 * on offsets. We re-read the board ID to ensure we have sane data back
-	 */
-	rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
-			       sizeof(board_id), (uint8_t *)&board_id);
-	if (rc)
-		return rc;
-
 	if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) {
 		pr_err("%s: Invalid board ID record!\n", __func__);
 		return -EINVAL;
diff --git a/configs/pg_wcom_expu1_defconfig b/configs/pg_wcom_expu1_defconfig
index b7c0b0d..acbef25 100644
--- a/configs/pg_wcom_expu1_defconfig
+++ b/configs/pg_wcom_expu1_defconfig
@@ -17,7 +17,6 @@
 # CONFIG_HAS_ARMV7_SECURE_BASE is not set
 CONFIG_SYS_LOAD_ADDR=0x82000000
 CONFIG_ENV_ADDR=0x60060000
-CONFIG_AHCI=y
 # CONFIG_DEEP_SLEEP is not set
 CONFIG_LAYERSCAPE_NS_ACCESS=y
 CONFIG_KM_COMMON_ETH_INIT=y
@@ -62,6 +61,7 @@
 CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)"
 CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBIFS is not set
 CONFIG_OF_CONTROL=y
 CONFIG_ENV_SOURCE_FILE="pg-wcom-expu1"
 CONFIG_ENV_OVERWRITE=y
@@ -73,6 +73,7 @@
 CONFIG_USE_HOSTNAME=y
 CONFIG_HOSTNAME="EXPU1"
 CONFIG_VERSION_VARIABLE=y
+# CONFIG_SCSI_AHCI is not set
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_SYS_BOOTCOUNT_BE=y
 CONFIG_DDR_CLK_FREQ=50000000
@@ -98,8 +99,9 @@
 CONFIG_MII=y
 CONFIG_TSEC_ENET=y
 CONFIG_SYS_QE_FW_ADDR=0x60020000
-CONFIG_SCSI_AHCI_PLAT=y
+# CONFIG_SCSI is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_POST=y
+CONFIG_LZO=y
diff --git a/configs/pg_wcom_expu1_update_defconfig b/configs/pg_wcom_expu1_update_defconfig
index a5193cb..3d9581a 100644
--- a/configs/pg_wcom_expu1_update_defconfig
+++ b/configs/pg_wcom_expu1_update_defconfig
@@ -16,7 +16,6 @@
 # CONFIG_HAS_ARMV7_SECURE_BASE is not set
 CONFIG_SYS_LOAD_ADDR=0x82000000
 CONFIG_ENV_ADDR=0x60220000
-CONFIG_AHCI=y
 # CONFIG_DEEP_SLEEP is not set
 CONFIG_LAYERSCAPE_NS_ACCESS=y
 CONFIG_KM_COMMON_ETH_INIT=y
@@ -60,6 +59,7 @@
 CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)"
 CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBIFS is not set
 CONFIG_OF_CONTROL=y
 CONFIG_ENV_SOURCE_FILE="pg-wcom-expu1"
 CONFIG_ENV_OVERWRITE=y
@@ -71,6 +71,7 @@
 CONFIG_USE_HOSTNAME=y
 CONFIG_HOSTNAME="EXPU1"
 CONFIG_VERSION_VARIABLE=y
+# CONFIG_SCSI_AHCI is not set
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_SYS_BOOTCOUNT_BE=y
 CONFIG_DDR_CLK_FREQ=50000000
@@ -96,8 +97,9 @@
 CONFIG_MII=y
 CONFIG_TSEC_ENET=y
 CONFIG_SYS_QE_FW_ADDR=0x60020000
-CONFIG_SCSI_AHCI_PLAT=y
+# CONFIG_SCSI is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_POST=y
+CONFIG_LZO=y
diff --git a/configs/pg_wcom_seli8_defconfig b/configs/pg_wcom_seli8_defconfig
index 1b9e0b6..0d7299e 100644
--- a/configs/pg_wcom_seli8_defconfig
+++ b/configs/pg_wcom_seli8_defconfig
@@ -17,7 +17,6 @@
 # CONFIG_HAS_ARMV7_SECURE_BASE is not set
 CONFIG_SYS_LOAD_ADDR=0x82000000
 CONFIG_ENV_ADDR=0x60060000
-CONFIG_AHCI=y
 # CONFIG_DEEP_SLEEP is not set
 CONFIG_LAYERSCAPE_NS_ACCESS=y
 CONFIG_KM_COMMON_ETH_INIT=y
@@ -62,6 +61,7 @@
 CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)"
 CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBIFS is not set
 CONFIG_OF_CONTROL=y
 CONFIG_ENV_SOURCE_FILE="pg-wcom-seli8"
 CONFIG_ENV_OVERWRITE=y
@@ -73,6 +73,7 @@
 CONFIG_USE_HOSTNAME=y
 CONFIG_HOSTNAME="SELI8"
 CONFIG_VERSION_VARIABLE=y
+# CONFIG_SCSI_AHCI is not set
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_SYS_BOOTCOUNT_BE=y
 CONFIG_DDR_CLK_FREQ=50000000
@@ -98,8 +99,9 @@
 CONFIG_MII=y
 CONFIG_TSEC_ENET=y
 CONFIG_SYS_QE_FW_ADDR=0x60020000
-CONFIG_SCSI_AHCI_PLAT=y
+# CONFIG_SCSI is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_POST=y
+CONFIG_LZO=y
diff --git a/configs/pg_wcom_seli8_update_defconfig b/configs/pg_wcom_seli8_update_defconfig
index c193f7b..d677b13 100644
--- a/configs/pg_wcom_seli8_update_defconfig
+++ b/configs/pg_wcom_seli8_update_defconfig
@@ -16,7 +16,6 @@
 # CONFIG_HAS_ARMV7_SECURE_BASE is not set
 CONFIG_SYS_LOAD_ADDR=0x82000000
 CONFIG_ENV_ADDR=0x60220000
-CONFIG_AHCI=y
 # CONFIG_DEEP_SLEEP is not set
 CONFIG_LAYERSCAPE_NS_ACCESS=y
 CONFIG_KM_COMMON_ETH_INIT=y
@@ -60,6 +59,7 @@
 CONFIG_MTDIDS_DEFAULT="nor0=60000000.nor,nand0=68000000.flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=60000000.nor:128k(rcw),128k(qe),128k(envred),128k(env),512k(res),1m(u-boot),128k(redenvred),128k(redenv),1m(redu-boot),-(ubi0);68000000.flash:-(ubi1)"
 CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBIFS is not set
 CONFIG_OF_CONTROL=y
 CONFIG_ENV_SOURCE_FILE="pg-wcom-seli8"
 CONFIG_ENV_OVERWRITE=y
@@ -71,6 +71,7 @@
 CONFIG_USE_HOSTNAME=y
 CONFIG_HOSTNAME="SELI8"
 CONFIG_VERSION_VARIABLE=y
+# CONFIG_SCSI_AHCI is not set
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_SYS_BOOTCOUNT_BE=y
 CONFIG_DDR_CLK_FREQ=50000000
@@ -96,8 +97,9 @@
 CONFIG_MII=y
 CONFIG_TSEC_ENET=y
 CONFIG_SYS_QE_FW_ADDR=0x60020000
-CONFIG_SCSI_AHCI_PLAT=y
+# CONFIG_SCSI is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_POST=y
+CONFIG_LZO=y
diff --git a/configs/s5p4418_nanopi2_defconfig b/configs/s5p4418_nanopi2_defconfig
index 35e7c88..0645b09 100644
--- a/configs/s5p4418_nanopi2_defconfig
+++ b/configs/s5p4418_nanopi2_defconfig
@@ -11,12 +11,15 @@
 CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="s5p4418-nanopi2"
 CONFIG_SYS_PROMPT="nanopi2# "
+CONFIG_DEBUG_UART_BASE=0xC00A1000
+CONFIG_DEBUG_UART_CLOCK=150000000
 CONFIG_TARGET_NANOPI2=y
 CONFIG_S5P4418_ONEWIRE=y
 CONFIG_ROOT_DEV=1
 CONFIG_BOOT_PART=1
 CONFIG_ROOT_PART=2
 CONFIG_SYS_LOAD_ADDR=0x71080000
+CONFIG_DEBUG_UART=y
 CONFIG_SYS_MEMTEST_START=0x71000000
 CONFIG_SYS_MEMTEST_END=0xb0000000
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
@@ -54,7 +57,8 @@
 CONFIG_PINCTRL=y
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
-CONFIG_CONS_INDEX=0
+CONFIG_DEBUG_UART_PL011=y
+CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_VIDEO=y
 CONFIG_VIDEO_LOGO=y
 CONFIG_DISPLAY=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 404e4a3..f9c996b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -334,3 +334,4 @@
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_IPV6=y
+CONFIG_RTC_HT1380=y
diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig
index b361e3f..b11dea5 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -13,6 +13,8 @@
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x84000000
 CONFIG_SYS_MONITOR_LEN=2097152
+CONFIG_TIMER=y
+CONFIG_SPL_TIMER=y
 CONFIG_TIMESTAMP=y
 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_BOOTCOMMAND="run ${bootdev}script; run ${bootdev}boot"
diff --git a/configs/uniphier_v7_defconfig b/configs/uniphier_v7_defconfig
index 765d42a..d626968 100644
--- a/configs/uniphier_v7_defconfig
+++ b/configs/uniphier_v7_defconfig
@@ -13,6 +13,8 @@
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x84000000
 CONFIG_SYS_MONITOR_LEN=2097152
+CONFIG_TIMER=y
+CONFIG_SPL_TIMER=y
 CONFIG_TIMESTAMP=y
 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_BOOTCOMMAND="run ${bootdev}script; run ${bootdev}boot"
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 1e4e5c9..f8b79e5 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -197,6 +197,7 @@
 config NAND_DENALI_DT
 	bool "Support Denali NAND controller as a DT device"
 	select NAND_DENALI
+	select SPL_SYS_NAND_SELF_INIT
 	depends on OF_CONTROL && DM_MTD
 	help
 	  Enable the driver for NAND flash on platforms using a Denali NAND
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 631bb1f..bdca3f2 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -33,6 +33,9 @@
 	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
 	int pins_count = priv->socdata->pins_count;
 
+	if (WARN_ON(!pins_count))
+		return 0; /* no table of pins */
+
 	/*
 	 * We do not list all pins in the pin table to save memory footprint.
 	 * Report the max pin number + 1 to fake the framework.
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c
index 1fc7bdb..8a8f126 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2017 Socionext Inc.
+ * Copyright (C) 2017-2021 Socionext Inc.
  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *   Author: Dai Okamura <dai.okamura@socionext.com>
  */
 
 #include <common.h>
@@ -10,6 +11,21 @@
 
 #include "pinctrl-uniphier.h"
 
+static const struct uniphier_pinctrl_pin uniphier_pxs3_pins[] = {
+	UNIPHIER_PINCTRL_PIN(62, "RGMII0_TXCLK", 28, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(63, "RGMII0_TXD0", 29, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(64, "RGMII0_TXD1", 30, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(65, "RGMII0_TXD2", 31, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(66, "RGMII0_TXD3", 32, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(67, "RGMII0_TXCTL", 33, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(78, "RGMII1_TXCLK", 44, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(79, "RGMII1_TXD0", 45, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(80, "RGMII1_TXD1", 46, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(81, "RGMII1_TXD2", 47, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(82, "RGMII1_TXD3", 48, UNIPHIER_PIN_DRV_2BIT),
+	UNIPHIER_PINCTRL_PIN(83, "RGMII1_TXCTL", 49, UNIPHIER_PIN_DRV_2BIT),
+};
+
 static const unsigned emmc_pins[] = {31, 32, 33, 34, 35, 36, 37, 38};
 static const int emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned emmc_dat8_pins[] = {39, 40, 41, 42};
@@ -121,6 +137,8 @@
 };
 
 static struct uniphier_pinctrl_socdata uniphier_pxs3_pinctrl_socdata = {
+	.pins = uniphier_pxs3_pins,
+	.pins_count = ARRAY_SIZE(uniphier_pxs3_pins),
 	.groups = uniphier_pxs3_groups,
 	.groups_count = ARRAY_SIZE(uniphier_pxs3_groups),
 	.functions = uniphier_pxs3_functions,
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b698722..35b6ed4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -260,4 +260,13 @@
 	  Say "yes" here to support the on chip real time clock
 	  present on Xilinx ZynqMP SoC.
 
+config RTC_HT1380
+	bool "Enable Holtek HT1380/HT1381 RTC driver"
+	depends on DM_RTC && DM_GPIO
+	help
+	  Say "yes" here to get support for Holtek HT1380/HT1381
+	  Serial Timekeeper IC which provides seconds, minutes, hours,
+	  day of the week, date, month and year information. It is to be
+	  connected via 3 GPIO pins which work as reset, clock, and data.
+
 endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 2089086..acfd130 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_RTC_DS3232) += ds3232.o
 obj-$(CONFIG_RTC_EMULATION) += emul_rtc.o
 obj-$(CONFIG_RTC_FTRTC010) += ftrtc010.o
+obj-$(CONFIG_RTC_HT1380) += ht1380.o
 obj-$(CONFIG_SANDBOX) += i2c_rtc_emul.o
 obj-$(CONFIG_RTC_IMXDI) += imxdi.o
 obj-$(CONFIG_RTC_ISL1208) += isl1208.o
diff --git a/drivers/rtc/ht1380.c b/drivers/rtc/ht1380.c
new file mode 100644
index 0000000..85fcee3
--- /dev/null
+++ b/drivers/rtc/ht1380.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Holtek HT1380/HT1381 Serial Timekeeper Chip
+ *
+ * Communication with the chip is vendor-specific.
+ * It is done via 3 GPIO pins: reset, clock, and data.
+ * Describe in .dts this way:
+ *
+ * rtc {
+ *         compatible = "holtek,ht1380";
+ *         rst-gpios = <&gpio 19 GPIO_ACTIVE_LOW>;
+ *         clk-gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
+ *         dat-gpios = <&gpio 21 GPIO_ACTIVE_HIGH>;
+ * };
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <rtc.h>
+#include <bcd.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+
+struct ht1380_priv {
+	struct gpio_desc rst_desc;
+	struct gpio_desc clk_desc;
+	struct gpio_desc dat_desc;
+};
+
+enum registers {
+	SEC,
+	MIN,
+	HOUR,
+	MDAY,
+	MONTH,
+	WDAY,
+	YEAR,
+	WP,
+	N_REGS
+};
+
+enum hour_mode {
+	AMPM_MODE = 0x80, /* RTC is in AM/PM mode */
+	PM_NOW = 0x20,    /* set if PM, clear if AM */
+};
+
+static const int BURST = 0xbe;
+static const int READ = 1;
+
+static void ht1380_half_period_delay(void)
+{
+	/*
+	 * Delay for half a period. 1 us complies with the 500 KHz maximum
+	 * input serial clock limit given by the datasheet.
+	 */
+	udelay(1);
+}
+
+static int ht1380_send_byte(struct ht1380_priv *priv, int byte)
+{
+	int ret;
+
+	for (int bit = 0; bit < 8; bit++) {
+		ret = dm_gpio_set_value(&priv->dat_desc, byte >> bit & 1);
+		if (ret)
+			break;
+		ht1380_half_period_delay();
+
+		ret = dm_gpio_set_value(&priv->clk_desc, 1);
+		if (ret)
+			break;
+		ht1380_half_period_delay();
+
+		ret = dm_gpio_set_value(&priv->clk_desc, 0);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/*
+ * Leave reset state. The transfer operation can then be started.
+ */
+static int ht1380_reset_off(struct ht1380_priv *priv)
+{
+	const unsigned int T_CC = 4; /* us, Reset to Clock Setup */
+	int ret;
+
+	/*
+	 * Leave RESET state.
+	 * Make sure we make the minimal delay required by the datasheet.
+	 */
+	ret = dm_gpio_set_value(&priv->rst_desc, 0);
+	udelay(T_CC);
+
+	return ret;
+}
+
+/*
+ * Enter reset state. Completes the transfer operation.
+ */
+static int ht1380_reset_on(struct ht1380_priv *priv)
+{
+	const unsigned int T_CWH = 4; /* us, Reset Inactive Time */
+	int ret;
+
+	/*
+	 * Enter RESET state.
+	 * Make sure we make the minimal delay required by the datasheet.
+	 */
+	ret = dm_gpio_set_value(&priv->rst_desc, 1);
+	udelay(T_CWH);
+
+	return ret;
+}
+
+static int ht1380_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+	struct ht1380_priv *priv = dev_get_priv(dev);
+	int ret, i, bit, reg[N_REGS];
+
+	ret = dm_gpio_set_value(&priv->clk_desc, 0);
+	if (ret)
+		return ret;
+
+	ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_OUT);
+	if (ret)
+		return ret;
+
+	ret = ht1380_reset_off(priv);
+	if (ret)
+		goto exit;
+
+	ret = ht1380_send_byte(priv, BURST + READ);
+	if (ret)
+		goto exit;
+
+	ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_IN);
+	if (ret)
+		goto exit;
+
+	for (i = 0; i < N_REGS; i++) {
+		reg[i] = 0;
+
+		for (bit = 0; bit < 8; bit++) {
+			ht1380_half_period_delay();
+
+			ret = dm_gpio_set_value(&priv->clk_desc, 1);
+			if (ret)
+				goto exit;
+			ht1380_half_period_delay();
+
+			reg[i] |= dm_gpio_get_value(&priv->dat_desc) << bit;
+			ret = dm_gpio_set_value(&priv->clk_desc, 0);
+			if (ret)
+				goto exit;
+		}
+	}
+
+	ret = -EINVAL;
+
+	/* Correctness check: some bits are always zero */
+	if (reg[MIN] & 0x80 || reg[HOUR] & 0x40 || reg[MDAY] & 0xc0 ||
+	    reg[MONTH] & 0xe0 || reg[WDAY] & 0xf8 || reg[WP] & 0x7f)
+		goto exit;
+
+	/* Correctness check: some registers are always non-zero */
+	if (!reg[MDAY] || !reg[MONTH] || !reg[WDAY])
+		goto exit;
+
+	tm->tm_sec = bcd2bin(reg[SEC]);
+	tm->tm_min = bcd2bin(reg[MIN]);
+	if (reg[HOUR] & AMPM_MODE) {
+		/* AM-PM Mode, range is 01-12 */
+		tm->tm_hour = bcd2bin(reg[HOUR] & 0x1f) % 12;
+		if (reg[HOUR] & PM_NOW) {
+			/* it is PM (otherwise AM) */
+			tm->tm_hour += 12;
+		}
+	} else {
+		/* 24-hour Mode, range is 0-23 */
+		tm->tm_hour = bcd2bin(reg[HOUR]);
+	}
+	tm->tm_mday = bcd2bin(reg[MDAY]);
+	tm->tm_mon = bcd2bin(reg[MONTH]);
+	tm->tm_year = 2000 + bcd2bin(reg[YEAR]);
+	tm->tm_wday = bcd2bin(reg[WDAY]) - 1;
+	tm->tm_yday = 0;
+	tm->tm_isdst = 0;
+
+	ret = 0;
+
+exit:
+	ht1380_reset_on(priv);
+
+	return ret;
+}
+
+static int ht1380_write_protection_off(struct ht1380_priv *priv)
+{
+	int ret;
+	const int PROTECT = 0x8e;
+
+	ret = ht1380_reset_off(priv);
+	if (ret)
+		return ret;
+
+	ret = ht1380_send_byte(priv, PROTECT);
+	if (ret)
+		return ret;
+	ret = ht1380_send_byte(priv, 0); /* WP bit is 0 */
+	if (ret)
+		return ret;
+
+	return ht1380_reset_on(priv);
+}
+
+static int ht1380_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+	struct ht1380_priv *priv = dev_get_priv(dev);
+	int ret, i, reg[N_REGS];
+
+	ret = dm_gpio_set_value(&priv->clk_desc, 0);
+	if (ret)
+		return ret;
+
+	ret = dm_gpio_set_dir_flags(&priv->dat_desc, GPIOD_IS_OUT);
+	if (ret)
+		goto exit;
+
+	ret = ht1380_write_protection_off(priv);
+	if (ret)
+		goto exit;
+
+	reg[SEC] = bin2bcd(tm->tm_sec);
+	reg[MIN] = bin2bcd(tm->tm_min);
+	reg[HOUR] = bin2bcd(tm->tm_hour);
+	reg[MDAY] = bin2bcd(tm->tm_mday);
+	reg[MONTH] = bin2bcd(tm->tm_mon);
+	reg[WDAY] = bin2bcd(tm->tm_wday) + 1;
+	reg[YEAR] = bin2bcd(tm->tm_year - 2000);
+	reg[WP] = 0x80; /* WP bit is 1 */
+
+	ret = ht1380_reset_off(priv);
+	if (ret)
+		goto exit;
+
+	ret = ht1380_send_byte(priv, BURST);
+	for (i = 0; i < N_REGS && ret; i++)
+		ret = ht1380_send_byte(priv, reg[i]);
+
+exit:
+	ht1380_reset_on(priv);
+
+	return ret;
+}
+
+static int ht1380_probe(struct udevice *dev)
+{
+	int ret;
+	struct ht1380_priv *priv;
+
+	priv = dev_get_priv(dev);
+	if (!priv)
+		return -EINVAL;
+
+	ret = gpio_request_by_name(dev, "rst-gpios", 0,
+				   &priv->rst_desc, GPIOD_IS_OUT);
+	if (ret)
+		goto fail_rst;
+
+	ret = gpio_request_by_name(dev, "clk-gpios", 0,
+				   &priv->clk_desc, GPIOD_IS_OUT);
+	if (ret)
+		goto fail_clk;
+
+	ret = gpio_request_by_name(dev, "dat-gpios", 0,
+				   &priv->dat_desc, 0);
+	if (ret)
+		goto fail_dat;
+
+	ret = ht1380_reset_on(priv);
+	if (ret)
+		goto fail;
+
+	return 0;
+
+fail:
+	dm_gpio_free(dev, &priv->dat_desc);
+fail_dat:
+	dm_gpio_free(dev, &priv->clk_desc);
+fail_clk:
+	dm_gpio_free(dev, &priv->rst_desc);
+fail_rst:
+	return ret;
+}
+
+static int ht1380_remove(struct udevice *dev)
+{
+	struct ht1380_priv *priv = dev_get_priv(dev);
+
+	dm_gpio_free(dev, &priv->rst_desc);
+	dm_gpio_free(dev, &priv->clk_desc);
+	dm_gpio_free(dev, &priv->dat_desc);
+
+	return 0;
+}
+
+static const struct rtc_ops ht1380_rtc_ops = {
+	.get = ht1380_rtc_get,
+	.set = ht1380_rtc_set,
+};
+
+static const struct udevice_id ht1380_rtc_ids[] = {
+	{ .compatible = "holtek,ht1380" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_ht1380) = {
+	.name = "rtc-ht1380",
+	.id = UCLASS_RTC,
+	.probe = ht1380_probe,
+	.remove = ht1380_remove,
+	.of_match = ht1380_rtc_ids,
+	.ops = &ht1380_rtc_ops,
+	.priv_auto = sizeof(struct ht1380_priv),
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 14b0feb..bb50832 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -827,6 +827,15 @@
 	help
 	  Select this to enable Samsung S5P UART support.
 
+config S5P4418_PL011_SERIAL
+	bool "Extended PL011 driver for S5P4418"
+	depends on DM_SERIAL && PL01X_SERIAL && ARCH_NEXELL
+	default y
+	help
+	  Select this to enable support of the PL011 UARTs in the S5P4418 SOC.
+	  With this driver the UART-clocks are set to the appropriate rate
+	  (if not 'skip-init').
+
 config SANDBOX_SERIAL
 	bool "Sandbox UART support"
 	depends on SANDBOX
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 37d3f82..01fef3f 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -59,6 +59,7 @@
 obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o
 obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
 obj-$(CONFIG_XEN_SERIAL) += serial_xen.o
+obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c
index b2d95bd..c2fc8a9 100644
--- a/drivers/serial/serial_arc.c
+++ b/drivers/serial/serial_arc.c
@@ -53,8 +53,8 @@
 	struct arc_serial_plat *plat = dev_get_plat(dev);
 	struct arc_serial_regs *const regs = plat->reg;
 
-	while (!(readb(&regs->status) & UART_TXEMPTY))
-		;
+	if (!(readb(&regs->status) & UART_TXEMPTY))
+		return -EAGAIN;
 
 	writeb(c, &regs->data);
 
@@ -83,8 +83,8 @@
 	struct arc_serial_plat *plat = dev_get_plat(dev);
 	struct arc_serial_regs *const regs = plat->reg;
 
-	while (!arc_serial_tstc(regs))
-		;
+	if (!arc_serial_tstc(regs))
+		return -EAGAIN;
 
 	/* Check for overflow errors */
 	if (readb(&regs->status) & UART_OVERFLOW_ERR)
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index ff576da..51e66ab 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -168,23 +168,24 @@
 static int _lpuart_serial_getc(struct lpuart_serial_plat *plat)
 {
 	struct lpuart_fsl *base = plat->reg;
-	while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
-		schedule();
+	if (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
+		return -EAGAIN;
 
 	barrier();
 
 	return __raw_readb(&base->ud);
 }
 
-static void _lpuart_serial_putc(struct lpuart_serial_plat *plat,
+static int _lpuart_serial_putc(struct lpuart_serial_plat *plat,
 				const char c)
 {
 	struct lpuart_fsl *base = plat->reg;
 
-	while (!(__raw_readb(&base->us1) & US1_TDRE))
-		schedule();
+	if (!(__raw_readb(&base->us1) & US1_TDRE))
+		return -EAGAIN;
 
 	__raw_writeb(c, &base->ud);
+	return 0;
 }
 
 /* Test whether a character is in the RX buffer */
@@ -328,10 +329,9 @@
 	u32 stat, val;
 
 	lpuart_read32(plat->flags, &base->stat, &stat);
-	while ((stat & STAT_RDRF) == 0) {
+	if ((stat & STAT_RDRF) == 0) {
 		lpuart_write32(plat->flags, &base->stat, STAT_FLAGS);
-		schedule();
-		lpuart_read32(plat->flags, &base->stat, &stat);
+		return -EAGAIN;
 	}
 
 	lpuart_read32(plat->flags, &base->data, &val);
@@ -343,25 +343,18 @@
 	return val & 0x3ff;
 }
 
-static void _lpuart32_serial_putc(struct lpuart_serial_plat *plat,
+static int _lpuart32_serial_putc(struct lpuart_serial_plat *plat,
 				  const char c)
 {
 	struct lpuart_fsl_reg32 *base = plat->reg;
 	u32 stat;
 
-	if (c == '\n')
-		serial_putc('\r');
-
-	while (true) {
-		lpuart_read32(plat->flags, &base->stat, &stat);
-
-		if ((stat & STAT_TDRE))
-			break;
-
-		schedule();
-	}
+	lpuart_read32(plat->flags, &base->stat, &stat);
+	if (!(stat & STAT_TDRE))
+		return -EAGAIN;
 
 	lpuart_write32(plat->flags, &base->data, c);
+	return 0;
 }
 
 /* Test whether a character is in the RX buffer */
@@ -456,11 +449,9 @@
 	struct lpuart_serial_plat *plat = dev_get_plat(dev);
 
 	if (is_lpuart32(dev))
-		_lpuart32_serial_putc(plat, c);
-	else
-		_lpuart_serial_putc(plat, c);
+		return _lpuart32_serial_putc(plat, c);
 
-	return 0;
+	return _lpuart_serial_putc(plat, c);
 }
 
 static int lpuart_serial_pending(struct udevice *dev, bool input)
diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c
index aeae6ae..b8d6a81 100644
--- a/drivers/serial/serial_mpc8xx.c
+++ b/drivers/serial/serial_mpc8xx.c
@@ -176,19 +176,15 @@
 	cpm8xx_t	__iomem *cpmp = &(im->im_cpm);
 	struct serialbuffer	__iomem *rtx;
 
-	if (c == '\n')
-		serial_mpc8xx_putc(dev, '\r');
-
 	rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
 
-	/* Wait for last character to go. */
+	if (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY)
+		return -EAGAIN;
+
 	out_8(&rtx->txbuf, c);
 	out_be16(&rtx->txbd.cbd_datlen, 1);
 	setbits_be16(&rtx->txbd.cbd_sc, BD_SC_READY);
 
-	while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY)
-		schedule();
-
 	return 0;
 }
 
@@ -202,9 +198,8 @@
 
 	rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
 
-	/* Wait for character to show up. */
-	while (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY)
-		schedule();
+	if (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY)
+		return -EAGAIN;
 
 	/* the characters are read one by one,
 	 * use the rxindex to know the next char to deliver
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c
index 0fcd7e8..b2017c6 100644
--- a/drivers/serial/serial_mvebu_a3700.c
+++ b/drivers/serial/serial_mvebu_a3700.c
@@ -40,8 +40,8 @@
 	struct mvebu_plat *plat = dev_get_plat(dev);
 	void __iomem *base = plat->base;
 
-	while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
-		;
+	if (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+		return -EAGAIN;
 
 	writel(ch, base + UART_TX_REG);
 
@@ -53,8 +53,8 @@
 	struct mvebu_plat *plat = dev_get_plat(dev);
 	void __iomem *base = plat->base;
 
-	while (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY))
-		;
+	if (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY))
+		return -EAGAIN;
 
 	return readl(base + UART_RX_REG) & 0xff;
 }
diff --git a/drivers/serial/serial_s5p4418_pl011.c b/drivers/serial/serial_s5p4418_pl011.c
new file mode 100644
index 0000000..e4492e6
--- /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@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),
+};
diff --git a/include/configs/s5p4418_nanopi2.h b/include/configs/s5p4418_nanopi2.h
index 2fa44e6..fec1bfd 100644
--- a/include/configs/s5p4418_nanopi2.h
+++ b/include/configs/s5p4418_nanopi2.h
@@ -76,11 +76,9 @@
 /*-----------------------------------------------------------------------
  * serial console configuration
  */
-#define CFG_PL011_CLOCK		50000000
-#define CFG_PL01x_PORTS		{(void *)PHY_BASEADDR_UART0, \
-					 (void *)PHY_BASEADDR_UART1, \
-					 (void *)PHY_BASEADDR_UART2, \
-					 (void *)PHY_BASEADDR_UART3}
+
+/* 150MHz is the clock rate set by SPL (uart0) */
+#define CFG_PL011_CLOCK		150000000
 
 /*-----------------------------------------------------------------------
  * BACKLIGHT
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index ecf0d2a..0a14d04 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -36,8 +36,7 @@
 	BOOT_TARGET_DEVICE_USB(func)
 
 #if !defined(CONFIG_ARM64)
-/* Time clock 1MHz */
-#define CFG_SYS_TIMER_RATE			1000000
+#define CFG_SYS_HZ_CLOCK			50000000
 #endif
 
 #define CFG_SYS_NAND_REGS_BASE			0x68100000