board: rockchip: Add Radxa ZERO 3W/3E

The Radxa ZERO 3W/3E is an ultra-small, high-performance single board
computer based on the Rockchip RK3566, with a compact form factor and
rich interfaces.

Implement rk_board_late_init() to set correct fdtfile env var and
board_fit_config_name_match() to load correct FIT config based on what
board is detected at runtime so a single board target can be used for
both board models.

Features tested on a ZERO 3W 8GB v1.11:
- SD-card boot
- eMMC boot
- USB gadget
- USB host

Features tested on a ZERO 3E 4GB v1.2:
- SD-card boot
- Ethernet
- USB gadget
- USB host

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Tested-by: FUKAUMI Naoki <naoki@radxa.com>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
diff --git a/board/radxa/zero3-rk3566/Kconfig b/board/radxa/zero3-rk3566/Kconfig
new file mode 100644
index 0000000..7d46efc
--- /dev/null
+++ b/board/radxa/zero3-rk3566/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_RADXA_ZERO_3_RK3566
+
+config SYS_BOARD
+	default "zero3-rk3566"
+
+config SYS_VENDOR
+	default "radxa"
+
+config SYS_CONFIG_NAME
+	default "evb_rk3568"
+
+endif
diff --git a/board/radxa/zero3-rk3566/MAINTAINERS b/board/radxa/zero3-rk3566/MAINTAINERS
new file mode 100644
index 0000000..e5a5d85
--- /dev/null
+++ b/board/radxa/zero3-rk3566/MAINTAINERS
@@ -0,0 +1,6 @@
+RADXA-ZERO-3-RK3566
+M:	Jonas Karlman <jonas@kwiboo.se>
+S:	Maintained
+F:	board/radxa/zero3-rk3566
+F:	configs/radxa-zero-3-rk3566_defconfig
+F:	arch/arm/dts/rk3566-radxa-zero-3*
diff --git a/board/radxa/zero3-rk3566/Makefile b/board/radxa/zero3-rk3566/Makefile
new file mode 100644
index 0000000..b28b58e
--- /dev/null
+++ b/board/radxa/zero3-rk3566/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += zero3-rk3566.o
diff --git a/board/radxa/zero3-rk3566/zero3-rk3566.c b/board/radxa/zero3-rk3566/zero3-rk3566.c
new file mode 100644
index 0000000..cf30c4e
--- /dev/null
+++ b/board/radxa/zero3-rk3566/zero3-rk3566.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <adc.h>
+#include <env.h>
+
+#define HW_ID_CHANNEL	1
+
+struct board_model {
+	unsigned int low;
+	unsigned int high;
+	const char *fdtfile;
+};
+
+static const struct board_model board_models[] = {
+	{ 230, 270, "rockchip/rk3566-radxa-zero-3w.dtb" },
+	{ 400, 450, "rockchip/rk3566-radxa-zero-3e.dtb" },
+};
+
+static const struct board_model *get_board_model(void)
+{
+	unsigned int val;
+	int i, ret;
+
+	ret = adc_channel_single_shot("saradc@fe720000", HW_ID_CHANNEL, &val);
+	if (ret)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(board_models); i++) {
+		unsigned int min = board_models[i].low;
+		unsigned int max = board_models[i].high;
+
+		if (min <= val && val <= max)
+			return &board_models[i];
+	}
+
+	return NULL;
+}
+
+int rk_board_late_init(void)
+{
+	const struct board_model *model = get_board_model();
+
+	if (model)
+		env_set("fdtfile", model->fdtfile);
+
+	return 0;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+	const struct board_model *model = get_board_model();
+
+	if (model && !strcmp(name, model->fdtfile))
+		return 0;
+
+	return -EINVAL;
+}