[PATCH 1/3] arm: mach-k3: Rework spl/get_boot_device()
    Anshul Dalal 
    anshuld at ti.com
       
    Tue Oct  7 12:32:51 CEST 2025
    
    
  
Hi Wadim, I have noted a few comments below but overall the patch set
looks good to me.
On Thu Oct 2, 2025 at 6:34 PM IST, 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>
> ---
>  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                |  34 +++++
>  arch/arm/mach-k3/include/mach/am62_hardware.h |   1 +
>  5 files changed, 169 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..9431dae71fa
> --- /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 <asm/arch/am62_spl.h>
> +
We shouldn't be including an am62x specific header in a mach-k3 file
meant for multiple SoCs. Please refactor the macros used below so it's
no longer required.
One idea could be to let the SoC's boot.c handle parsing the devstat and
bootmode (primary or not). With get_boot_device in boot-device.c only
receiving the final bootmode and bootmode_cfg as part of the
k3_boot_device_info struct.
This would also allow Jacinto platforms to easily make use of this
refactor since the handling of wkup and main devstat would be handled as
part of the SoC's boot.c.
> +__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;
> +	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)
> +{
Having a k3 specific get_boot_device called by U-Boot's generic
spl_boot_device from SoC's init file is convoluted.
We should probably just replace get_boot_device with spl_boot_device in
a later patch after this series.
> +	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..965a4570710
> --- /dev/null
> +++ b/arch/arm/mach-k3/boot-device.h
> @@ -0,0 +1,34 @@
> +// 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>
> +
> +/* Descriptor for mode + optional cfg test -> normalized device */
> +struct k3_boot_map {
> +	u32 mode;	/* Raw PRIMARY_BOOTMODE value */
> +	u32 cfg_mask;	/* Bits in devstat-cfg to test (0 if none) */
> +	u32 cfg_shift;	/* Shift right before comparing */
> +	u32 cfg_value;	/* Desired value after mask+shift */
> +	u32 result;	/* Normalized device to return */
> +};
> +
Nit: This could be better documented following the standard '@' in a
comment above the struct.
> +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 */
> diff --git a/arch/arm/mach-k3/include/mach/am62_hardware.h b/arch/arm/mach-k3/include/mach/am62_hardware.h
> index 2f5655bf24a..084f16bf2d2 100644
> --- a/arch/arm/mach-k3/include/mach/am62_hardware.h
> +++ b/arch/arm/mach-k3/include/mach/am62_hardware.h
> @@ -10,6 +10,7 @@
>  #define __ASM_ARCH_AM62_HARDWARE_H
>  
>  #include <config.h>
> +#include <asm/io.h>
Why do we need this header here?
>  #ifndef __ASSEMBLY__
>  #include <linux/bitops.h>
>  #endif
Acked-by: Anshul Dalal <anshuld at ti.com>
Regards,
Anshul
    
    
More information about the U-Boot
mailing list