[RFC 1/1] arm: mach-k3: Rework spl/get_boot_device()

Wadim Egorov w.egorov at phytec.de
Wed Aug 13 12:29:48 CEST 2025


The current implementation requires every K3 SoC to provide its own
get_boot_device()/get_*_bootmedia() functions which look very identical.
Rework it using table lookups for SoC data and reduce code duplication.

Signed-off-by: Wadim Egorov <w.egorov at phytec.de>
---
 arch/arm/mach-k3/Makefile                     |   2 +-
 arch/arm/mach-k3/am62x/boot.c                 | 129 +++++-------------
 arch/arm/mach-k3/boot-device.c                | 109 +++++++++++++++
 arch/arm/mach-k3/boot-device.h                |  27 ++++
 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..6d458f546a6 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,33 @@ const char *get_reset_reason(void)
 
 	return "UNKNOWN";
 }
+
+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 },
+};
+
+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, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT, 0, BOOT_DEVICE_MMC1 },
+	{ BACKUP_BOOT_DEVICE_MMC, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT, 1, BOOT_DEVICE_MMC2 },
+	{ 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_BOOTMODE_CFG_MASK, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT, 0, BOOT_DEVICE_DFU },
+	{ BACKUP_BOOT_DEVICE_DFU, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK, MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT, 1, BOOT_DEVICE_USB },
+};
+
+unsigned int am62_boot_device_primary_table_count = ARRAY_SIZE(am62_boot_device_primary_table);
+unsigned int am62_boot_device_backup_table_count = ARRAY_SIZE(am62_boot_device_backup_table);
diff --git a/arch/arm/mach-k3/boot-device.c b/arch/arm/mach-k3/boot-device.c
new file mode 100644
index 00000000000..9b4f0ae7aa6
--- /dev/null
+++ b/arch/arm/mach-k3/boot-device.c
@@ -0,0 +1,109 @@
+/* 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>
+
+struct k3_boot_device_info {
+	struct k3_boot_map *boot_device_primary_table;
+	unsigned int *boot_device_primary_count;
+	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;
+};
+
+static const struct k3_boot_device_info k3_boot_device_info[] = {
+#if defined(CONFIG_SOC_K3_AM625)
+	{
+		.boot_device_primary_table = am62_boot_device_primary_table,
+		.boot_device_primary_count = &am62_boot_device_primary_table_count,
+		.boot_device_backup_table = am62_boot_device_backup_table,
+		.boot_device_backup_count = &am62_boot_device_backup_table_count,
+		.main_devstat_reg = (void __iomem *)CTRLMMR_MAIN_DEVSTAT,
+		.wkup_devstat_reg = 0,
+		.bootmode_addr = (void __iomem *)K3_BOOT_PARAM_TABLE_INDEX_OCRAM,
+	},
+#endif
+};
+
+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;
+
+	const struct k3_boot_device_info *info = &k3_boot_device_info[0];
+	unsigned int i;
+
+	for (i = 0; i < *info->boot_device_backup_count; i++) {
+		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(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;
+	const struct k3_boot_device_info *info = &k3_boot_device_info[0];
+	unsigned int i;
+
+	for (i = 0; i < *info->boot_device_primary_count; i++) {
+		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 get_boot_device(void)
+{
+	const struct k3_boot_device_info *info = &k3_boot_device_info[0];
+	u32 bootmode = readl(info->bootmode_addr);
+	u32 main_devstat = readl(info->main_devstat_reg);
+	u32 bootmedia;
+
+	if (!ARRAY_SIZE(k3_boot_device_info)) {
+		pr_err("%s: no boot-device info for this SoC\n", __func__);
+		return BOOT_DEVICE_NOBOOT;
+	}
+
+	if (bootmode == K3_PRIMARY_BOOTMODE)
+		bootmedia = __get_primary_bootmedia(main_devstat);
+	else
+		bootmedia = __get_backup_bootmedia(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..351f710151b
--- /dev/null
+++ b/arch/arm/mach-k3/boot-device.h
@@ -0,0 +1,27 @@
+/* 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>
+
+/* 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 */
+};
+
+extern struct k3_boot_map am62_boot_device_primary_table[];
+extern unsigned int am62_boot_device_primary_table_count;
+
+extern struct k3_boot_map am62_boot_device_backup_table[];
+extern unsigned int am62_boot_device_backup_table_count;
+
+#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>
 #ifndef __ASSEMBLY__
 #include <linux/bitops.h>
 #endif
-- 
2.48.1



More information about the U-Boot mailing list