CAINIAO CNIoT-CORE: U-Boot: Add a method to prioritize booting from USB drive via the power button
Some checks failed
Data: Sync board list / Send dispatch (push) Has been cancelled
Infrastructure: Dispatch to fork / 📢 Run repository dispatch on fork (push) Has been cancelled
Infrastructure: Mirror to Codeberg / codeberg (push) Has been cancelled
Maintenance: Announce merge / announcepush (push) Has been cancelled
Maintenance: Security scan / Scorecards analysis (push) Has been cancelled

This commit is contained in:
retro98boy 2026-03-09 05:20:20 +08:00 committed by Werner
parent 48dad6c987
commit 631abc02c2

View File

@ -11,15 +11,190 @@ index 00000000..236f2468
+ */
+
+#include "meson-g12-common-u-boot.dtsi"
diff --git a/board/amlogic/cniot-core/Makefile b/board/amlogic/cniot-core/Makefile
new file mode 100644
index 00000000..c4135658
--- /dev/null
+++ b/board/amlogic/cniot-core/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Author: retro98boy <retro98boy@qq.com>
+
+obj-y := cniot-core.o
diff --git a/board/amlogic/cniot-core/cniot-core.c b/board/amlogic/cniot-core/cniot-core.c
new file mode 100644
index 00000000..325e39f9
--- /dev/null
+++ b/board/amlogic/cniot-core/cniot-core.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author: retro98boy <retro98boy@qq.com>
+ */
+
+#include <asm-generic/gpio.h>
+#include <linux/delay.h>
+#include <dm.h>
+#include <env_internal.h>
+#include <init.h>
+#include <net.h>
+#include <asm/io.h>
+#include <asm/arch/eth.h>
+#include <stdbool.h>
+
+static struct gpio_desc pwrbtn_gpio[1] = { 0 };
+static bool pwrbtn_valid = false;
+
+static int request_gpios(void)
+{
+ int node = -1;
+ int rc = -1;
+
+ node = fdt_path_offset(gd->fdt_blob, "/gpio-keys-polled/pwr-btn");
+ if (node < 0)
+ return -ENODEV;
+
+ rc = gpio_request_list_by_name_nodev(offset_to_ofnode(node), "gpios",
+ pwrbtn_gpio,
+ ARRAY_SIZE(pwrbtn_gpio),
+ GPIOD_IS_IN);
+ if (rc < 0)
+ return -ENODEV;
+
+ pwrbtn_valid = true;
+
+ return 0;
+}
+
+static void free_gpios(void)
+{
+ if (pwrbtn_valid) {
+ gpio_free_list_nodev(pwrbtn_gpio, ARRAY_SIZE(pwrbtn_gpio));
+ pwrbtn_valid = false;
+ }
+}
+
+static bool is_pwrbtn_really_released(void)
+{
+ const int check_ms = 300;
+ const int step_ms = 50;
+
+ for (int i = 0; i < check_ms / step_ms; i++) {
+ mdelay(step_ms);
+ if (dm_gpio_get_value(&pwrbtn_gpio[0]) == 1)
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * The UART pads on this device are deeply recessed,
+ * and disassembling the hardware is a major hassle.
+ * Once U-Boot and the OS are installed on the eMMC,
+ * rescuing data or recovering the system becomes difficult
+ * if a failure occurs (such as a kernel panic or rootfs corruption),
+ * because U-Boot prioritizes booting from eMMC over USB.
+ * To address this, here is a workaround:
+ * by holding the power button for 5 seconds during boot-up,
+ * U-Boot will be forced to retain only the USB boot target.
+ * This prevents U-Boot from loading a corrupted kernel image from the eMMC
+ * and getting stuck in a boot loop. Additionally,
+ * it is recommended that the OS image flashed to the USB drive
+ * be different from the one on the eMMC to avoid partition UUID conflicts.
+ */
+static void handle_usb_boot_detection(void)
+{
+ const int target_seconds = 5;
+ ulong start_time = get_timer(0);
+ ulong last_print_time = 0;
+
+ printf("Check USB boot: Hold Power Button for %ds\n", target_seconds);
+
+ while (get_timer(start_time) < (target_seconds * 1000)) {
+ if (dm_gpio_get_value(&pwrbtn_gpio[0]) == 0) {
+ if (is_pwrbtn_really_released()) {
+ printf("[Normal Boot] Button released early.\n");
+ return;
+ }
+ }
+
+ ulong current_elapsed = get_timer(start_time) / 1000;
+ if (current_elapsed > last_print_time) {
+ /*
+ * It would be even better if this device had an integrated LED.
+ * We could toggle the LED status here as a visual indicator.
+ */
+ printf("Power button holding... %ld/%ds\r",
+ current_elapsed, target_seconds);
+ last_print_time = current_elapsed;
+ }
+
+ mdelay(10);
+ }
+
+ printf("\n[USB Boot] Trigger matched!\n");
+ env_set("boot_targets", "usb0");
+
+ /*
+ * We must wait for the user to release the power button
+ * before proceeding with the kernel boot.
+ * Otherwise, an extended press (since the user cannot perceive the boot progress)
+ * might trigger a reset once the kernel is running.
+ * A timeout should also be implemented:
+ * if the button is stuck due to hardware damage,
+ * the system shouldn't hang in U-Boot indefinitely.
+ * This is crucial because U-Boot is fixed in eMMC,
+ * whereas the kernel and DTB are easily modifiable on a USB drive,
+ * making it simpler to disable the power button later if needed.
+ */
+ const ulong release_timeout_ms = 30000;
+ ulong release_start = get_timer(0);
+ while (!is_pwrbtn_really_released()) {
+ if (get_timer(release_start) > release_timeout_ms) {
+ printf("\nRelease timeout reached. Continuing boot.\n");
+ break;
+ }
+ printf("Waiting for button release to continue...\r");
+ }
+
+ printf("\nButton released safely. Proceeding...\n");
+}
+
+int misc_init_r(void)
+{
+ meson_generate_serial_ethaddr();
+
+ return 0;
+}
+
+int meson_board_late_init(void)
+{
+#if defined(CONFIG_WATCHDOG)
+ printf("Watchdog set, skip USB boot detection.\n");
+ return 0;
+#else
+ if (request_gpios()) {
+ printf("Failed to request gpios for USB boot detection.\n");
+ return 0;
+ }
+
+ handle_usb_boot_detection();
+ free_gpios();
+
+ return 0;
+#endif
+}
diff --git a/configs/cainiao-cniot-core_defconfig b/configs/cainiao-cniot-core_defconfig
new file mode 100644
index 00000000..0ee30015
index 00000000..27000ab4
--- /dev/null
+++ b/configs/cainiao-cniot-core_defconfig
@@ -0,0 +1,110 @@
+# Reference from khadas-vim3_defconfig
+CONFIG_ARM=y
+CONFIG_SYS_BOARD="w400"
+CONFIG_SYS_BOARD="cniot-core"
+CONFIG_ARCH_MESON=y
+CONFIG_TEXT_BASE=0x01000000
+CONFIG_NR_DRAM_BANKS=1
@ -129,7 +304,7 @@ index 00000000..0ee30015
+CONFIG_ZSTD=y
diff --git a/dts/upstream/src/arm64/amlogic/meson-g12b-a311d-cainiao-cniot-core.dts b/dts/upstream/src/arm64/amlogic/meson-g12b-a311d-cainiao-cniot-core.dts
new file mode 100644
index 00000000..09b1bbac
index 00000000..85ea1c4a
--- /dev/null
+++ b/dts/upstream/src/arm64/amlogic/meson-g12b-a311d-cainiao-cniot-core.dts
@@ -0,0 +1,600 @@