summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPadmarao Begari <[email protected]>2026-05-14 15:52:22 +0530
committerMichal Simek <[email protected]>2026-06-08 10:50:05 +0200
commitedccbc53afb67f6cbf1b594ba87da5b2fd807797 (patch)
tree2c659116aae3a4df1bfe3253cb571b1a7a09c2cb
parent818c06faa119f3101c9df24c0ef1b815c2abd929 (diff)
board: xilinx: Add FWU boot index support
Add fwu_plat_get_alt_num() and fwu_plat_get_bootidx() platform callbacks required for FWU multi-bank update on Versal and Versal Gen 2. The boot index is read from the PMC Global PGGS4 register which is populated by PLM with a magic number and boot partition index. Uses firmware IOCTL when CONFIG_ZYNQMP_FIRMWARE is enabled, otherwise falls back to direct MMIO read. Signed-off-by: Padmarao Begari <[email protected]> Signed-off-by: Michal Simek <[email protected]> Link: https://lore.kernel.org/r/[email protected]
-rw-r--r--board/xilinx/common/board.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 89562ef77fc..52a2e8767d8 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -14,8 +14,12 @@
#include <init.h>
#include <jffs2/load_kernel.h>
#include <log.h>
+#include <asm/io.h>
#include <asm/global_data.h>
#include <asm/sections.h>
+#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2)
+#include <asm/arch/hardware.h>
+#endif
#include <dm/uclass.h>
#include <i2c.h>
#include <linux/sizes.h>
@@ -30,6 +34,8 @@
#include <rng.h>
#include <slre.h>
#include <soc.h>
+#include <zynqmp_firmware.h>
+#include <linux/bitfield.h>
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <u-boot/uuid.h>
@@ -718,7 +724,74 @@ phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
return reg + size;
}
+#endif
+
+#if defined(CONFIG_FWU_MULTI_BANK_UPDATE)
+
+#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2)
+/*
+ * The Versal and Versal Gen 2 PMC Global pggs4 register contains below
+ * information in each byte as:
+ *
+ * Byte[3]: Magic number
+ * Byte[2]: Boot counter value
+ * Byte[1]: Boot partition value - boot index
+ * Byte[0]: Rollback counter value
+ */
+
+#define MAGIC_NUM 0x1D
+#define MAGIC_MASK GENMASK(31, 24)
+#define BOOTINDEX_MASK GENMASK(15, 8)
+
+static int plat_get_boot_index(void)
+{
+ u32 val;
+
+ if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
+ val = zynqmp_pm_get_pmc_global_pggs_reg(PMC_GLOBAL_PGGS4_REG);
+ else
+ val = readl(PMC_GLOBAL_PGGS4_REG);
+
+ if (FIELD_GET(MAGIC_MASK, val) != MAGIC_NUM) {
+ log_err("FWU requires PMC magic number 0x%x\n", MAGIC_NUM);
+ return -EINVAL;
+ }
+
+ return FIELD_GET(BOOTINDEX_MASK, val);
+}
+#endif
+
+int fwu_plat_get_alt_num(struct udevice __always_unused *dev,
+ efi_guid_t *image_id, u8 *alt_num)
+{
+ int ret;
+
+ ret = fwu_mtd_get_alt_num(image_id, alt_num, "nor0");
+ debug("%s: return %d\n", __func__, ret);
+
+ return ret;
+}
+void fwu_plat_get_bootidx(uint *boot_idx)
+{
+ int ret;
+ u32 active_idx;
+
+ ret = fwu_get_active_index(&active_idx);
+ if (ret < 0)
+ printf("%s: failed to read active index\n", __func__);
+
+ ret = plat_get_boot_index();
+ if (ret < 0) {
+ *boot_idx = 0;
+ printf("%s: failed and setup boot index to 0\n", __func__);
+ } else {
+ *boot_idx = ret;
+ }
+
+ debug("%s: boot_idx: %d, active_idx: %d\n",
+ __func__, *boot_idx, active_idx);
+}
#endif
#if IS_ENABLED(CONFIG_BOARD_RNG_SEED)