Various i.MX-based boards can be booted in a USB-serial download mode, where the bootrom pauses and waits for an upload from the host.
The documented and expected behaviour is that a separate host computer then uploads a U-Boot binary which then boots into fastboot mode, allowing for storage devices to be flashed, usually by the 'uuu' tool. This is implemented inconsistently over different boards, for example within the i.MX9 family: - i.MX93 FRDM: fastboot mode only activates if "bootflow scan" fails to boot an OS from an available storage device. - phyCORE i.MX91/93: fastboot is prepended to the default bootcmd, and the board boots normally once the host ends the session. - Kontron OSM-S i.MX93: bootcmd is replaced with "fastboot 0" and bootdelay set to 0, so U-Boot stops at the prompt afterwards. - Variscite i.MX93 VAR-SOM, Toradex Aquila, SMARC and Verdin i.MX95: USB fastboot is enabled, but nothing starts it, so the normal boot command runs. Implement a common i.MX handler for this, offering consistent behaviour: on a USB boot, prepend "fastboot usb <FASTBOOT_USB_DEV>" to bootcmd from the last-stage init event. This handler takes effect on i.MX8, i.MX8M, i.MX8ULP and i.MX9 families when USB fastboot is enabled, and only when the bootcmd has not been customised by the user or by the board code. Signed-off-by: Daniel Drake <[email protected]> --- arch/arm/mach-imx/Makefile | 6 ++++++ arch/arm/mach-imx/usb_boot.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 43febc10460..f3d1f7aac62 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -300,6 +300,12 @@ obj-$(CONFIG_ARCH_IMX8) += imx8/ obj-$(CONFIG_ARCH_IMX9) += imx9/ obj-$(CONFIG_ARCH_IMXRT) += imxrt/ +ifeq ($(SOC),$(filter $(SOC),imx8 imx8m imx8ulp imx9)) +ifneq ($(CONFIG_XPL_BUILD),y) +obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += usb_boot.o +endif +endif + obj-$(CONFIG_SPL_BOOTROM_SUPPORT) += spl_imx_romapi.o obj-$(CONFIG_IMX8_ROMAPI) += romapi.o diff --git a/arch/arm/mach-imx/usb_boot.c b/arch/arm/mach-imx/usb_boot.c new file mode 100644 index 00000000000..93640362fcc --- /dev/null +++ b/arch/arm/mach-imx/usb_boot.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2026 BayLibre SAS + */ + +#include <env.h> +#include <event.h> +#include <malloc.h> +#include <stdio.h> +#include <vsprintf.h> +#include <asm/mach-imx/boot_mode.h> +#include <asm/mach-imx/sys_proto.h> +#include <linux/string.h> + +/* + * When the boot ROM loaded U-Boot in serial download mode, the host (uuu) + * is waiting for fastboot. Run it ahead of the default boot command. + */ +static int imx_usb_boot_fastboot(void) +{ + enum boot_device dev = get_boot_device(); + const char *bootcmd; + char *buf; + + if (!IS_ENABLED(CONFIG_CMD_FASTBOOT) || dev != USB_BOOT) + return 0; + + /* Allow override by the board or by the user */ + bootcmd = env_get("bootcmd") ?: ""; + buf = malloc(CONFIG_ENV_SIZE); + if (!buf) + return 0; + if (env_get_default_into("bootcmd", buf, CONFIG_ENV_SIZE) < 0) + *buf = '\0'; + if (!strcmp(bootcmd, buf)) { + printf("USB boot detected, entering fastboot\n"); + snprintf(buf, CONFIG_ENV_SIZE, "fastboot usb %d; %s", + CONFIG_FASTBOOT_USB_DEV, bootcmd); + env_set("bootcmd", buf); + } + free(buf); + + return 0; +} +EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, imx_usb_boot_fastboot); -- 2.56.0
