[PATCH v2 1/3] arm: mach-k3: Rework spl/get_boot_device()
Andrew Davis
afd at ti.com
Tue Nov 4 17:41:16 CET 2025
On 11/4/25 9:24 AM, Wadim Egorov wrote:
> Introduce a shared boot-device helper that translates DEVSTAT boot
> modes via SoC-specific lookup tables. This replaces the per SoC
> get_boot_device()/get_*_bootmedia() implementations and centralizes
> the logic in boot-device.c while keeping the mapping data SoC-owned.
>
> Start with am62x as a reference implementation.
>
> Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
> Acked-by: Anshul Dalal <anshuld at ti.com>
> ---
> arch/arm/mach-k3/Makefile | 2 +-
> arch/arm/mach-k3/am62x/boot.c | 141 ++++++++++-----------------------
> arch/arm/mach-k3/boot-device.c | 90 +++++++++++++++++++++
> arch/arm/mach-k3/boot-device.h | 41 ++++++++++
> 4 files changed, 175 insertions(+), 99 deletions(-)
> create mode 100644 arch/arm/mach-k3/boot-device.c
> create mode 100644 arch/arm/mach-k3/boot-device.h
>
> diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile
> index b2fd5810b67..7dc77328e5c 100644
> --- a/arch/arm/mach-k3/Makefile
> +++ b/arch/arm/mach-k3/Makefile
> @@ -6,7 +6,7 @@
> obj-$(CONFIG_ARM64) += arm64/
> obj-$(CONFIG_CPU_V7R) += r5/
> obj-$(CONFIG_OF_LIBFDT) += common_fdt.o
> -obj-y += common.o security.o k3-ddr.o
> +obj-y += common.o security.o k3-ddr.o boot-device.o
> obj-$(CONFIG_SOC_K3_AM62A7) += am62ax/
> obj-$(CONFIG_SOC_K3_AM62P5) += am62px/
> obj-$(CONFIG_SOC_K3_AM625) += am62x/
> diff --git a/arch/arm/mach-k3/am62x/boot.c b/arch/arm/mach-k3/am62x/boot.c
> index a3a6cda6bdb..06bd04da99f 100644
> --- a/arch/arm/mach-k3/am62x/boot.c
> +++ b/arch/arm/mach-k3/am62x/boot.c
> @@ -3,104 +3,7 @@
> #include <asm/arch/hardware.h>
> #include <asm/arch/am62_spl.h>
>
> -static u32 __get_backup_bootmedia(u32 devstat)
> -{
> - u32 bkup_bootmode = (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_MASK) >>
> - MAIN_DEVSTAT_BACKUP_BOOTMODE_SHIFT;
> - u32 bkup_bootmode_cfg =
> - (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK) >>
> - MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT;
> -
> - switch (bkup_bootmode) {
> - case BACKUP_BOOT_DEVICE_UART:
> - return BOOT_DEVICE_UART;
> -
> - case BACKUP_BOOT_DEVICE_USB:
> - return BOOT_DEVICE_USB;
> -
> - case BACKUP_BOOT_DEVICE_ETHERNET:
> - return BOOT_DEVICE_ETHERNET;
> -
> - case BACKUP_BOOT_DEVICE_MMC:
> - if (bkup_bootmode_cfg)
> - return BOOT_DEVICE_MMC2;
> - return BOOT_DEVICE_MMC1;
> -
> - case BACKUP_BOOT_DEVICE_SPI:
> - return BOOT_DEVICE_SPI;
> -
> - case BACKUP_BOOT_DEVICE_I2C:
> - return BOOT_DEVICE_I2C;
> -
> - case BACKUP_BOOT_DEVICE_DFU:
> - if (bkup_bootmode_cfg & MAIN_DEVSTAT_BACKUP_USB_MODE_MASK)
> - return BOOT_DEVICE_USB;
> - return BOOT_DEVICE_DFU;
> - };
> -
> - return BOOT_DEVICE_RAM;
> -}
> -
> -static u32 __get_primary_bootmedia(u32 devstat)
> -{
> - u32 bootmode = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_MASK) >>
> - MAIN_DEVSTAT_PRIMARY_BOOTMODE_SHIFT;
> - u32 bootmode_cfg = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_MASK) >>
> - MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_SHIFT;
> -
> - switch (bootmode) {
> - case BOOT_DEVICE_OSPI:
> - fallthrough;
> - case BOOT_DEVICE_QSPI:
> - fallthrough;
> - case BOOT_DEVICE_XSPI:
> - fallthrough;
> - case BOOT_DEVICE_SPI:
> - return BOOT_DEVICE_SPI;
> -
> - case BOOT_DEVICE_ETHERNET_RGMII:
> - fallthrough;
> - case BOOT_DEVICE_ETHERNET_RMII:
> - return BOOT_DEVICE_ETHERNET;
> -
> - case BOOT_DEVICE_EMMC:
> - return BOOT_DEVICE_MMC1;
> -
> - case BOOT_DEVICE_MMC:
> - if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_MMC_PORT_MASK) >>
> - MAIN_DEVSTAT_PRIMARY_MMC_PORT_SHIFT)
> - return BOOT_DEVICE_MMC2;
> - return BOOT_DEVICE_MMC1;
> -
> - case BOOT_DEVICE_DFU:
> - if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_USB_MODE_MASK) >>
> - MAIN_DEVSTAT_PRIMARY_USB_MODE_SHIFT)
> - return BOOT_DEVICE_USB;
> - return BOOT_DEVICE_DFU;
> -
> - case BOOT_DEVICE_NOBOOT:
> - return BOOT_DEVICE_RAM;
> - }
> -
> - return bootmode;
> -}
> -
> -u32 get_boot_device(void)
> -{
> - u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
> - u32 bootmode = *(u32 *)(K3_BOOT_PARAM_TABLE_INDEX_OCRAM);
> - u32 bootmedia;
> -
> - if (bootmode == K3_PRIMARY_BOOTMODE)
> - bootmedia = __get_primary_bootmedia(devstat);
> - else
> - bootmedia = __get_backup_bootmedia(devstat);
> -
> - debug("%s: devstat = 0x%x bootmedia = 0x%x bootmode = %d\n",
> - __func__, devstat, bootmedia, bootmode);
> -
> - return bootmedia;
> -}
> +#include "../boot-device.h"
>
> const char *get_reset_reason(void)
> {
> @@ -141,3 +44,45 @@ const char *get_reset_reason(void)
>
> return "UNKNOWN";
> }
> +
> +static const struct k3_boot_map am62_boot_device_primary_table[] = {
> + { BOOT_DEVICE_OSPI, 0, 0, 0, BOOT_DEVICE_SPI },
> + { BOOT_DEVICE_QSPI, 0, 0, 0, BOOT_DEVICE_SPI },
> + { BOOT_DEVICE_XSPI, 0, 0, 0, BOOT_DEVICE_SPI },
> + { BOOT_DEVICE_SPI, 0, 0, 0, BOOT_DEVICE_SPI },
> + { BOOT_DEVICE_ETHERNET_RGMII, 0, 0, 0, BOOT_DEVICE_ETHERNET },
> + { BOOT_DEVICE_ETHERNET_RMII, 0, 0, 0, BOOT_DEVICE_ETHERNET },
> + { BOOT_DEVICE_EMMC, 0, 0, 0, BOOT_DEVICE_MMC1 },
> + { BOOT_DEVICE_MMC, MAIN_DEVSTAT_PRIMARY_MMC_PORT_MASK, MAIN_DEVSTAT_PRIMARY_MMC_PORT_SHIFT, 1, BOOT_DEVICE_MMC2 },
> + { BOOT_DEVICE_MMC, MAIN_DEVSTAT_PRIMARY_MMC_PORT_MASK, MAIN_DEVSTAT_PRIMARY_MMC_PORT_SHIFT, 0, BOOT_DEVICE_MMC1 },
> + { BOOT_DEVICE_DFU, MAIN_DEVSTAT_PRIMARY_USB_MODE_MASK, MAIN_DEVSTAT_PRIMARY_USB_MODE_SHIFT, 1, BOOT_DEVICE_USB },
> + { BOOT_DEVICE_DFU, MAIN_DEVSTAT_PRIMARY_USB_MODE_MASK, MAIN_DEVSTAT_PRIMARY_USB_MODE_SHIFT, 0, BOOT_DEVICE_DFU },
> + { BOOT_DEVICE_NOBOOT, 0, 0, 0, BOOT_DEVICE_RAM },
> +};
> +
> +static const struct k3_boot_map am62_boot_device_backup_table[] = {
> + { BACKUP_BOOT_DEVICE_UART, 0, 0, 0, BOOT_DEVICE_UART },
> + { BACKUP_BOOT_DEVICE_USB, 0, 0, 0, BOOT_DEVICE_USB },
> + { BACKUP_BOOT_DEVICE_ETHERNET, 0, 0, 0, BOOT_DEVICE_ETHERNET },
> + { BACKUP_BOOT_DEVICE_MMC, 1, 0, 1, BOOT_DEVICE_MMC2 },
> + { BACKUP_BOOT_DEVICE_MMC, 1, 0, 0, BOOT_DEVICE_MMC1 },
> + { BACKUP_BOOT_DEVICE_SPI, 0, 0, 0, BOOT_DEVICE_SPI },
> + { BACKUP_BOOT_DEVICE_I2C, 0, 0, 0, BOOT_DEVICE_I2C },
> + { BACKUP_BOOT_DEVICE_DFU, MAIN_DEVSTAT_BACKUP_USB_MODE_MASK, 0, 0, BOOT_DEVICE_DFU },
> + { BACKUP_BOOT_DEVICE_DFU, MAIN_DEVSTAT_BACKUP_USB_MODE_MASK, 0, 1, BOOT_DEVICE_USB },
> +};
> +
> +static const struct k3_boot_device_info am62_boot_device_info = {
> + .boot_device_primary_table = am62_boot_device_primary_table,
> + .boot_device_primary_count = ARRAY_SIZE(am62_boot_device_primary_table),
> + .boot_device_backup_table = am62_boot_device_backup_table,
> + .boot_device_backup_count = ARRAY_SIZE(am62_boot_device_backup_table),
> + .main_devstat_reg = (void __iomem *)CTRLMMR_MAIN_DEVSTAT,
> + .wkup_devstat_reg = NULL,
> + .bootmode_addr = (void __iomem *)K3_BOOT_PARAM_TABLE_INDEX_OCRAM,
> +};
> +
> +const struct k3_boot_device_info *k3_get_boot_device_info(void)
> +{
> + return &am62_boot_device_info;
> +}
> diff --git a/arch/arm/mach-k3/boot-device.c b/arch/arm/mach-k3/boot-device.c
> new file mode 100644
> index 00000000000..4c3f2da3269
> --- /dev/null
> +++ b/arch/arm/mach-k3/boot-device.c
> @@ -0,0 +1,90 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2025 PHYTEC Messtechnik GmbH
> + * Author: Wadim Egorov <w.egorov at phytec.de>
> + */
> +
> +#include "boot-device.h"
> +
> +#include <asm/io.h>
> +#include <asm/arch/hardware.h>
> +#include <spl.h>
> +
> +__weak const struct k3_boot_device_info *k3_get_boot_device_info(void)
> +{
> + return NULL;
> +}
> +
> +static u32 __get_backup_bootmedia(const struct k3_boot_device_info *info, u32 devstat)
> +{
> + u32 bkup_bootmode = (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_MASK) >>
> + MAIN_DEVSTAT_BACKUP_BOOTMODE_SHIFT;
> + u32 bkup_bootmode_cfg = (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK) >>
> + MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT;
> + unsigned int i;
> +
> + for (i = 0; i < info->boot_device_backup_count; i++) {
> + const struct k3_boot_map *m = &info->boot_device_backup_table[i];
> +
> + if (bkup_bootmode != m->mode)
> + continue;
> +
> + if (m->cfg_mask == 0)
> + return m->result;
> +
> + if (((bkup_bootmode_cfg & m->cfg_mask) >> m->cfg_shift) == m->cfg_value)
> + return m->result;
> + }
> +
> + return BOOT_DEVICE_RAM;
> +}
> +
> +static u32 __get_primary_bootmedia(const struct k3_boot_device_info *info, u32 devstat)
> +{
> + u32 bootmode = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_MASK) >>
> + MAIN_DEVSTAT_PRIMARY_BOOTMODE_SHIFT;
So this won't work for J7x devices as they have the primary bootmode in the
wakeup devstat (WKUP_DEVSTAT_*).
Since you already have a k3_boot_device_info table, instead of storing
"main_devstat_reg" and "wkup_devstat_reg" store whichever reg contains the
primary and backup boot modes. No need to label them "main" or "wkup" as
you don't actually care what domain they are in, you care about what
each contains (bootmode). That plus the shift needed to extract that
value would make a table that would work across all mach-k3 platforms.
Andrew
> + u32 bootmode_cfg = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_MASK) >>
> + MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_SHIFT;
> + unsigned int i;
> +
> + for (i = 0; i < info->boot_device_primary_count; i++) {
> + const struct k3_boot_map *m = &info->boot_device_primary_table[i];
> +
> + if (bootmode != m->mode)
> + continue;
> +
> + if (m->cfg_mask == 0)
> + return m->result;
> +
> + if (((bootmode_cfg & m->cfg_mask) >> m->cfg_shift) == m->cfg_value)
> + return m->result;
> + }
> +
> + return bootmode;
> +}
> +
> +u32 __weak get_boot_device(void)
> +{
> + const struct k3_boot_device_info *info = k3_get_boot_device_info();
> + u32 bootmode;
> + u32 main_devstat;
> + u32 bootmedia;
> +
> + if (!info) {
> + pr_err("%s: no boot-device info for this SoC\n", __func__);
> + return BOOT_DEVICE_NOBOOT;
> + }
> +
> + bootmode = readl(info->bootmode_addr);
> + main_devstat = readl(info->main_devstat_reg);
> +
> + if (bootmode == K3_PRIMARY_BOOTMODE)
> + bootmedia = __get_primary_bootmedia(info, main_devstat);
> + else
> + bootmedia = __get_backup_bootmedia(info, main_devstat);
> +
> + debug("%s: devstat = 0x%x bootmedia = 0x%x bootmode = %d\n",
> + __func__, main_devstat, bootmedia, bootmode);
> +
> + return bootmedia;
> +}
> diff --git a/arch/arm/mach-k3/boot-device.h b/arch/arm/mach-k3/boot-device.h
> new file mode 100644
> index 00000000000..04951deafb3
> --- /dev/null
> +++ b/arch/arm/mach-k3/boot-device.h
> @@ -0,0 +1,41 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2025 PHYTEC Messtechnik GmbH
> + * Author: Wadim Egorov <w.egorov at phytec.de>
> + */
> +
> +#ifndef _K3_BOOT_DEVICE_H
> +#define _K3_BOOT_DEVICE_H
> +
> +#include <linux/types.h>
> +#include <asm/io.h>
> +
> +/**
> + * struct k3_boot_map - Descriptor to map a raw boot mode to normalized device
> + * @mode: Raw PRIMARY_BOOTMODE value
> + * @cfg_mask: Bits in devstat-cfg to test (0 if none)
> + * @cfg_shift: Shift right before comparing
> + * @cfg_value: Desired value after mask+shift
> + * @result: Normalized device to return
> + */
> +struct k3_boot_map {
> + u32 mode;
> + u32 cfg_mask;
> + u32 cfg_shift;
> + u32 cfg_value;
> + u32 result;
> +};
> +
> +struct k3_boot_device_info {
> + const struct k3_boot_map *boot_device_primary_table;
> + unsigned int boot_device_primary_count;
> + const struct k3_boot_map *boot_device_backup_table;
> + unsigned int boot_device_backup_count;
> + void __iomem *main_devstat_reg;
> + void __iomem *wkup_devstat_reg;
> + void __iomem *bootmode_addr;
> +};
> +
> +const struct k3_boot_device_info *k3_get_boot_device_info(void);
> +
> +#endif /* _K3_BOOT_DEVICE_H */
More information about the U-Boot
mailing list