Compare commits

...

17 Commits

Author SHA1 Message Date
Tom Rini
5d4d6e331d Merge tag 'xilinx-for-v2026.10-rc1-v2' of https://source.denx.de/u-boot/custodians/u-boot-microblaze into next
AMD/Xilinx/FPGA changes for v2026.10-rc1 v2

zynqmp:
- Clean up USB gadget configuration

mbv:
- Reduce SPL size

versal:
- Add support for A/B capsule update

versal2:
- Add support for A/B capsule update

reset:
- Introduce reset_reset_bulk() generic interface
- zynqmp: Implement reset_reset_bulk() interface

spi:
- cadence: Switch to reset_reset_bulk() interface
2026-06-08 08:36:57 -06:00
Michal Simek
8efa173b38 reset: zynqmp: Implement rst_reset using PM_RESET_ACTION_PULSE
Implement the rst_reset operation in the ZynqMP reset driver to use
PM_RESET_ACTION_PULSE. This allows the reset controller to perform
a reset pulse in a single firmware call instead of separate assert
and deassert calls.

This matches the Linux kernel implementation of zynqmp_reset_reset().

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/be77d6f1b60f591ef626c14229d85c5cab867967.1779709539.git.michal.simek@amd.com
2026-06-08 10:50:06 +02:00
Michal Simek
f59b7a010e spi: cadence: Use reset_reset_bulk() for proper reset cycling
Use the new reset_reset_bulk() API to properly cycle reset signals
during probe instead of just deasserting them. This ensures the
controller is properly reset before initialization.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/92e614075d2c4820d3e4485aa0bdda11efd1f7ca.1779709539.git.michal.simek@amd.com
2026-06-08 10:50:06 +02:00
Michal Simek
4e3f64c7cc reset: sandbox: Cover reset_reset() fallback with second sandbox provider
Add a sandbox reset controller compatible string
"sandbox,reset-ctl-fallback-only" that reuses the existing sandbox assert,
deassert, request, and free helpers but omits rst_reset. That forces
reset_reset() through the core assert / udelay / deassert fallback.

Extend the reset-ctl-test DT node with a fifth reset line named "fallback"
that points at the new provider, and add dm_test_reset_reset_fallback_path
which verifies sandbox_reset_get_count() stays zero (rst_reset is never
invoked) while the line ends deasserted after reset_reset().

This complements the existing rst_reset coverage on sandbox,reset-ctl and
matches the approach of using a separate controller to exercise the
fallback path in unit tests.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/c1d40db6e2332a8b23ba842385b3f8c3d0290109.1779709539.git.michal.simek@amd.com
2026-06-08 10:50:06 +02:00
Michal Simek
724d3cafe3 reset: Add sandbox tests for reset_reset() and reset_reset_bulk()
Add DM test coverage for the new reset_reset() and reset_reset_bulk()
API functions.
The sandbox reset driver implements rst_reset so these tests exercise that
op (not the assert/udelay/deassert fallback in reset_reset()).
reset_reset_bulk() calls reset_reset() on each bulk entry in order, so each
line's rst_reset runs in sequence.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/be5411daf0de8eb64fbddf06e8ad82f50066e811.1779709539.git.michal.simek@amd.com
2026-06-08 10:50:06 +02:00
Michal Simek
19f7def264 reset: Add reset_reset() and reset_reset_bulk() API
Add reset_reset() and reset_reset_bulk() functions to the reset
controller API. These functions assert and then deassert reset signals
in a single call, providing a convenient way to pulse/toggle a reset
line.

This mimics the Linux kernel's reset_control_reset() and
reset_control_bulk_reset() APIs. The new functions are useful for
drivers that need to cycle a reset line during initialization or
error recovery but with also passing delay parameter.

If a driver implements the rst_reset op, it will be called directly
with the delay parameter. Otherwise, the reset core performs
reset_assert(), optional udelay(), and reset_deassert() as fallback.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/55ddd313c9e7b2d4dc79ab36bdd0040f871610f6.1779709539.git.michal.simek@amd.com
2026-06-08 10:50:06 +02:00
Padmarao Begari
4706bd0208 configs: amd: Enable capsule update and DFU support
Enable EFI capsule update configs (EFI_RUNTIME_UPDATE_CAPSULE,
EFI_CAPSULE_ON_DISK, EFI_CAPSULE_ON_DISK_EARLY, and
EFI_CAPSULE_FIRMWARE_RAW) and DFU backend configs (DFU_MMC,
DFU_MTD, DFU_SF) for the Versal Gen 2 virtual platform. Increase
SYS_MALLOC_LEN, SYS_MALLOC_F_LEN and SYS_INIT_SP_BSS_OFFSET to
accommodate capsule update buffer requirements.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514103845.1761891-1-padmarao.begari@amd.com
2026-06-08 10:50:06 +02:00
Padmarao Begari
de6b77c22f configs: xilinx: Enable DFU MTD support
Enable CONFIG_DFU_MTD and CONFIG_DM_MTD to support DFU transfers
over MTD partitions, required for FWU multi-bank update using
NOR flash.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514102601.1759779-7-padmarao.begari@amd.com
2026-06-08 10:50:06 +02:00
Padmarao Begari
edccbc53af 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 <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514102601.1759779-6-padmarao.begari@amd.com
2026-06-08 10:50:05 +02:00
Padmarao Begari
818c06faa1 board: amd: Add capsule and FWU support
Add configure_capsule_updates() supporting MMC, SD and QSPI/OSPI
boot modes for DFU string generation. Add set_dfu_alt_info() for
FWU multi-bank mode to generate DFU alt info from NOR flash MTD
partitions. Add XILINX_BOOT_IMAGE_GUID for the capsule updatable
firmware image.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514102601.1759779-5-padmarao.begari@amd.com
2026-06-08 10:50:05 +02:00
Padmarao Begari
371a6c1744 board: xilinx: Add capsule and FWU support
Guard configure_capsule_updates() so it is skipped when FWU
multi-bank update is enabled. Add set_dfu_alt_info() for FWU
multi-bank mode to generate DFU alt info dynamically from NOR
flash MTD partitions using fwu_gen_alt_info_from_mtd().

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514102601.1759779-4-padmarao.begari@amd.com
2026-06-08 10:50:05 +02:00
Padmarao Begari
f2390069d4 firmware: zynqmp: Add PMC PGGS register read API
Add zynqmp_pm_get_pmc_global_pggs_reg() to read PMC Global PGGS3
and PGGS4 registers via firmware IOCTL. Supports IOCTL_READ_PGGS
as the preferred path and falls back to IOCTL_READ_REG for older
PLM firmware versions that do not support IOCTL_READ_PGGS.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514102601.1759779-3-padmarao.begari@amd.com
2026-06-08 10:50:05 +02:00
Padmarao Begari
7188742e7e arm64: xilinx: Add PMC PGGS3 and PGGS4 registers
Add PMC Global PGGS3 and PGGS4 register defines to Versal and
Versal Gen 2 hardware headers. These registers hold boot index
and boot metadata required for FWU multi-bank update support.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260514102601.1759779-2-padmarao.begari@amd.com
2026-06-08 10:50:05 +02:00
Michal Simek
472ea8b621 xilinx: mbv: Allow compiler to optimize inlining in SPL
Enable CONFIG_SPL_OPTIMIZE_INLINING to let the compiler decide which
functions marked 'inline' to actually inline, rather than forcing all of
them. This reduces SPL code size by allowing the compiler to eliminate
unnecessary code duplication.

   spl/u-boot-spl: all -872 text -872

Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/09f2a62099abf561b91b0d3692714f0f29057d31.1777550623.git.michal.simek@amd.com
2026-06-08 08:02:39 +02:00
Michal Simek
62a49635b0 xilinx: mbv: Disable AVAILABLE_HARTS
The MicroBlaze V platform has only a single hart, so multi-hart
enumeration support is unnecessary. Disable CONFIG_AVAILABLE_HARTS
to reduce code size.

   all -121 data -12 text -109
   spl/u-boot-spl: all -68 data -4 text -64

Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/511c3c05d29479a4d1410a902cc01963113c4e1a.1777550623.git.michal.simek@amd.com
2026-06-08 08:02:39 +02:00
Pranav Sanwal
38831cce70 board: zynqmp: Remove hardcoded USB ethernet initialization
usb_ether_init() called in board_late_init() when CONFIG_USB_ETHER
was enabled without CONFIG_USB_GADGET_DOWNLOAD.
This makes USB ethernet gadget a fixed default, with no way to opt
out at runtime without a rebuild.

Remove the hardcoded call. If USB ethernet gadget functionality is
needed, it can be added via the preboot environment variable.

Signed-off-by: Pranav Sanwal <pranav.sanwal@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260430093427.1852145-3-pranav.sanwal@amd.com
2026-06-08 08:02:39 +02:00
Pranav Sanwal
e81bb069a4 configs: zynqmp: Enable USB gadget download support
USB_GADGET_DOWNLOAD enables the g_dnl composite gadget framework,
allowing other functions to operate over the USB peripheral
interface.

Signed-off-by: Pranav Sanwal <pranav.sanwal@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20260430093427.1852145-2-pranav.sanwal@amd.com
2026-06-08 08:02:39 +02:00
23 changed files with 637 additions and 23 deletions

View File

@@ -100,3 +100,6 @@ struct crp_regs {
#define MIO_PIN_12 0xF1060030
#define BANK0_OUTPUT 0xF1020040
#define BANK0_TRI 0xF1060200
#define PMC_GLOBAL_PGGS3_REG 0xF111005C
#define PMC_GLOBAL_PGGS4_REG 0xF1110060

View File

@@ -105,3 +105,6 @@ enum versal2_platform {
#define PMXC_UFS_CAL_1_OFFSET 0xBE8
#define PMXC_SRAM_CSR 0x4C
#define PMXC_TX_RX_CFG_RDY 0x54
#define PMC_GLOBAL_PGGS3_REG 0xF111005C
#define PMC_GLOBAL_PGGS4_REG 0xF1110060

View File

@@ -1530,10 +1530,16 @@
#reset-cells = <1>;
};
resetc_fb: reset-ctl-fallback {
compatible = "sandbox,reset-ctl-fallback-only";
#reset-cells = <1>;
};
reset-ctl-test {
compatible = "sandbox,reset-ctl-test";
resets = <&resetc 100>, <&resetc 2>, <&resetc 20>, <&resetc 40>;
reset-names = "other", "test", "test2", "test3";
resets = <&resetc 100>, <&resetc 2>, <&resetc 20>, <&resetc 40>,
<&resetc_fb 5>;
reset-names = "other", "test", "test2", "test3", "fallback";
};
rng {

View File

@@ -10,6 +10,7 @@ struct udevice;
int sandbox_reset_query(struct udevice *dev, unsigned long id);
int sandbox_reset_is_requested(struct udevice *dev, unsigned long id);
int sandbox_reset_get_count(struct udevice *dev, unsigned long id);
int sandbox_reset_test_get(struct udevice *dev);
int sandbox_reset_test_get_devm(struct udevice *dev);
@@ -19,6 +20,8 @@ int sandbox_reset_test_assert(struct udevice *dev);
int sandbox_reset_test_assert_bulk(struct udevice *dev);
int sandbox_reset_test_deassert(struct udevice *dev);
int sandbox_reset_test_deassert_bulk(struct udevice *dev);
int sandbox_reset_test_reset(struct udevice *dev);
int sandbox_reset_test_reset_bulk(struct udevice *dev);
int sandbox_reset_test_free(struct udevice *dev);
int sandbox_reset_test_release_bulk(struct udevice *dev);

View File

@@ -1,17 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 - 2022, Xilinx, Inc.
* Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc.
* Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc.
*
* Michal Simek <michal.simek@amd.com>
*/
#include <cpu_func.h>
#include <dfu.h>
#include <env.h>
#include <efi_loader.h>
#include <fdtdec.h>
#include <fwu.h>
#include <init.h>
#include <env_internal.h>
#include <log.h>
#include <malloc.h>
#include <memalign.h>
#include <mmc.h>
#include <mtd.h>
#include <time.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -26,6 +33,7 @@
#include "../../xilinx/common/board.h"
#include <linux/bitfield.h>
#include <linux/sizes.h>
#include <debug_uart.h>
#include <generated/dt.h>
#include <linux/ioport.h>
@@ -348,6 +356,10 @@ int board_late_init(void)
int ret;
u32 multiboot;
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) &&
!IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
configure_capsule_updates();
if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
debug("Saved variables - Skipping\n");
return 0;
@@ -476,3 +488,120 @@ enum env_location env_get_location(enum env_operation op, int prio)
}
}
#endif
#define DFU_ALT_BUF_LEN SZ_1K
#if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && \
!defined(CONFIG_FWU_MULTI_BANK_UPDATE)
static void mtd_found_part(u32 *base, u32 *size)
{
struct mtd_info *part, *mtd;
mtd_probe_devices();
mtd = get_mtd_device_nm("nor0");
if (!IS_ERR_OR_NULL(mtd)) {
list_for_each_entry(part, &mtd->partitions, node) {
debug("0x%012llx-0x%012llx : \"%s\"\n",
part->offset, part->offset + part->size,
part->name);
if (*base >= part->offset &&
*base < part->offset + part->size) {
debug("Found my partition: %d/%s\n",
part->index, part->name);
*base = part->offset;
*size = part->size;
break;
}
}
}
}
void configure_capsule_updates(void)
{
int bootseq = 0, len = 0;
u32 multiboot = versal2_multi_boot();
u32 bootmode = versal2_get_bootmode();
ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
memset(buf, 0, DFU_ALT_BUF_LEN);
multiboot = env_get_hex("multiboot", multiboot);
switch (bootmode) {
case EMMC_MODE:
case SD_MODE:
case SD1_LSHFT_MODE:
case SD_MODE1:
bootseq = mmc_get_env_dev();
len += snprintf(buf + len, DFU_ALT_BUF_LEN, "mmc %d=boot",
bootseq);
if (multiboot)
len += snprintf(buf + len, DFU_ALT_BUF_LEN,
"%04d", multiboot);
len += snprintf(buf + len, DFU_ALT_BUF_LEN, ".bin fat %d 1",
bootseq);
break;
case QSPI_MODE_24BIT:
case QSPI_MODE_32BIT:
case OSPI_MODE:
{
u32 base = multiboot * SZ_32K;
u32 size = 0x1500000;
u32 limit = size;
mtd_found_part(&base, &limit);
len += snprintf(buf + len, DFU_ALT_BUF_LEN,
"sf 0:0=boot.bin raw 0x%x 0x%x",
base, limit);
}
break;
default:
return;
}
update_info.dfu_string = strdup(buf);
debug("Capsule DFU: %s\n", update_info.dfu_string);
}
#endif
#if defined(CONFIG_FWU_MULTI_BANK_UPDATE)
/* Generate dfu_alt_info from partitions */
void set_dfu_alt_info(char *interface, char *devstr)
{
int ret;
struct mtd_info *mtd;
/*
* It is called multiple times for every image
* per bank that's why enough to set it up once.
*/
if (env_get("dfu_alt_info"))
return;
ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
memset(buf, 0, DFU_ALT_BUF_LEN);
mtd_probe_devices();
mtd = get_mtd_device_nm("nor0");
if (IS_ERR_OR_NULL(mtd))
return;
ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd);
if (ret < 0) {
log_err("Error: Failed to generate dfu_alt_info. (%d)\n", ret);
return;
}
log_debug("Make dfu_alt_info: '%s'\n", buf);
env_set("dfu_alt_info", buf);
}
#endif

View File

@@ -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)

View File

@@ -10,6 +10,7 @@
#include <env.h>
#include <efi_loader.h>
#include <fdtdec.h>
#include <fwu.h>
#include <init.h>
#include <env_internal.h>
#include <log.h>
@@ -293,7 +294,8 @@ int board_late_init(void)
{
int ret;
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) &&
!IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
configure_capsule_updates();
if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
@@ -374,6 +376,8 @@ enum env_location env_get_location(enum env_operation op, int prio)
#define DFU_ALT_BUF_LEN SZ_1K
#if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && \
!defined(CONFIG_FWU_MULTI_BANK_UPDATE)
static void mtd_found_part(u32 *base, u32 *size)
{
struct mtd_info *part, *mtd;
@@ -450,3 +454,39 @@ void configure_capsule_updates(void)
update_info.dfu_string = strdup(buf);
debug("Capsule DFU: %s\n", update_info.dfu_string);
}
#endif
#if defined(CONFIG_FWU_MULTI_BANK_UPDATE)
/* Generate dfu_alt_info from partitions */
void set_dfu_alt_info(char *interface, char *devstr)
{
int ret;
struct mtd_info *mtd;
/*
* It is called multiple times for every image
* per bank that's why enough to set it up once.
*/
if (env_get("dfu_alt_info"))
return;
ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
memset(buf, 0, DFU_ALT_BUF_LEN);
mtd_probe_devices();
mtd = get_mtd_device_nm("nor0");
if (IS_ERR_OR_NULL(mtd))
return;
ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd);
if (ret < 0) {
log_err("Error: Failed to generate dfu_alt_info. (%d)\n", ret);
return;
}
log_debug("Make dfu_alt_info: '%s'\n", buf);
env_set("dfu_alt_info", buf);
}
#endif

View File

@@ -541,10 +541,6 @@ int board_late_init(void)
{
int ret, multiboot;
#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD)
usb_ether_init();
#endif
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
configure_capsule_updates();

View File

@@ -1,10 +1,11 @@
CONFIG_ARM=y
CONFIG_COUNTER_FREQUENCY=100000000
CONFIG_POSITION_INDEPENDENT=y
CONFIG_SYS_INIT_SP_BSS_OFFSET=0x180000
CONFIG_SYS_INIT_SP_BSS_OFFSET=0x200000
CONFIG_ARCH_VERSAL2=y
CONFIG_TEXT_BASE=0x40000000
CONFIG_SYS_MALLOC_F_LEN=0x100000
CONFIG_SYS_MALLOC_LEN=0x4000000
CONFIG_SYS_MALLOC_F_LEN=0x180000
CONFIG_NR_DRAM_BANKS=36
CONFIG_DEFAULT_DEVICE_TREE="amd-versal2-virt"
CONFIG_OF_LIBFDT_OVERLAY=y
@@ -17,6 +18,10 @@ CONFIG_PCI=y
CONFIG_SYS_MEMTEST_START=0x00000000
CONFIG_SYS_MEMTEST_END=0x00001000
CONFIG_REMAKE_ELF=y
CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
CONFIG_EFI_CAPSULE_ON_DISK=y
CONFIG_EFI_CAPSULE_ON_DISK_EARLY=y
CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_EFI_HTTP_BOOT=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
@@ -81,7 +86,12 @@ CONFIG_SIMPLE_PM_BUS=y
CONFIG_CLK_CCF=y
CONFIG_CLK_SCMI=y
CONFIG_CLK_VERSAL=y
CONFIG_DFU_TIMEOUT=y
CONFIG_DFU_MMC=y
CONFIG_DFU_MTD=y
CONFIG_DFU_RAM=y
CONFIG_DFU_SF=y
CONFIG_SYS_DFU_DATA_BUF_SIZE=0x1800000
CONFIG_ARM_FFA_TRANSPORT=y
CONFIG_SCMI_FIRMWARE=y
CONFIG_FPGA_XILINX=y
@@ -106,6 +116,7 @@ CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ZYNQ=y
CONFIG_ZYNQ_SDHCI_MIN_FREQ=100000
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_SPI_FLASH_ISSI=y

View File

@@ -18,6 +18,8 @@ CONFIG_BOOT_SCRIPT_OFFSET=0x0
CONFIG_TARGET_XILINX_MBV=y
# CONFIG_RISCV_ISA_F is not set
# CONFIG_SPL_SMP is not set
# CONFIG_AVAILABLE_HARTS is not set
CONFIG_SPL_OPTIMIZE_INLINING=y
CONFIG_REMAKE_ELF=y
# CONFIG_EFI_LOADER is not set
CONFIG_FIT=y

View File

@@ -80,6 +80,7 @@ CONFIG_SIMPLE_PM_BUS=y
CONFIG_CLK_VERSAL=y
CONFIG_DFU_TIMEOUT=y
CONFIG_DFU_MMC=y
CONFIG_DFU_MTD=y
CONFIG_DFU_RAM=y
CONFIG_DFU_SF=y
CONFIG_SYS_DFU_DATA_BUF_SIZE=0x1800000
@@ -106,6 +107,7 @@ CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ZYNQ=y
CONFIG_ZYNQ_SDHCI_MIN_FREQ=100000
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_SOFT_RESET=y
CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y

View File

@@ -222,6 +222,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_ETHER=y
CONFIG_USB_ETH_CDC=y
CONFIG_VIDEO=y

View File

@@ -3,7 +3,7 @@
* Xilinx Zynq MPSoC Firmware driver
*
* Copyright (C) 2018-2019 Xilinx, Inc.
* Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc.
* Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc.
*/
#include <asm/arch/hardware.h>
@@ -197,6 +197,58 @@ int zynqmp_pm_ufs_cal_reg(u32 *value)
*value = readl(PMXC_EFUSE_CACHE_BASE_ADDRESS + PMXC_UFS_CAL_1_OFFSET);
return 0;
}
#endif /* CONFIG_ARCH_VERSAL2 */
#if defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL2)
u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr)
{
int ret;
u32 value = 0;
u32 ret_payload[PAYLOAD_ARG_CNT];
if (reg_addr == PMC_GLOBAL_PGGS3_REG) {
value = 0;
} else if (reg_addr == PMC_GLOBAL_PGGS4_REG) {
value = 1;
} else {
printf("%s: not supported pggs register 0x%x\n",
__func__, reg_addr);
return 0;
}
ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_PGGS);
if (ret) {
ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_READ_REG);
if (ret) {
printf("%s: IOCTL_READ_REG is not supported : %d\n"
, __func__, ret);
return 0;
}
/* find node ID from the pggs3 offset */
value = PM_REG_PGGS3 + value;
ret = xilinx_pm_request(PM_IOCTL, value,
IOCTL_READ_REG, 0, 0, 0, 0,
ret_payload);
if (ret) {
printf("%s: node 0x%x get pggs register failed\n",
__func__, value);
return 0;
}
} else {
ret = xilinx_pm_request(PM_IOCTL, PMC_GLOBAL_PGGS3_REG_NODE,
IOCTL_READ_PGGS, value, 0, 0, 0,
ret_payload);
if (ret) {
printf("%s: node 0x%x get pggs register failed\n",
__func__, PMC_GLOBAL_PGGS3_REG_NODE);
return 0;
}
}
return ret_payload[1];
}
#endif
int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value)

View File

@@ -13,6 +13,7 @@
#include <reset-uclass.h>
#include <dm/devres.h>
#include <dm/lists.h>
#include <linux/delay.h>
static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
{
@@ -225,6 +226,39 @@ int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
return 0;
}
int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
{
struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
int ret;
debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl,
delay_us);
if (ops->rst_reset)
return ops->rst_reset(reset_ctl, delay_us);
ret = reset_assert(reset_ctl);
if (ret < 0)
return ret;
udelay(delay_us);
return reset_deassert(reset_ctl);
}
int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us)
{
int i, ret;
for (i = 0; i < bulk->count; i++) {
ret = reset_reset(&bulk->resets[i], delay_us);
if (ret < 0)
return ret;
}
return 0;
}
int reset_status(struct reset_ctl *reset_ctl)
{
struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);

View File

@@ -45,6 +45,16 @@ static int zynqmp_reset_deassert(struct reset_ctl *rst)
PM_RESET_ACTION_RELEASE);
}
static int zynqmp_reset_reset(struct reset_ctl *rst, ulong delay_us)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
PM_RESET_ACTION_PULSE);
}
static int zynqmp_reset_request(struct reset_ctl *rst)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
@@ -74,6 +84,7 @@ const struct reset_ops zynqmp_reset_ops = {
.request = zynqmp_reset_request,
.rst_assert = zynqmp_reset_assert,
.rst_deassert = zynqmp_reset_deassert,
.rst_reset = zynqmp_reset_reset,
};
static const struct udevice_id zynqmp_reset_ids[] = {

View File

@@ -96,6 +96,20 @@ int sandbox_reset_test_deassert_bulk(struct udevice *dev)
return reset_deassert_bulk(sbrt->bulkp);
}
int sandbox_reset_test_reset(struct udevice *dev)
{
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
return reset_reset(sbrt->ctlp, 0);
}
int sandbox_reset_test_reset_bulk(struct udevice *dev)
{
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
return reset_reset_bulk(sbrt->bulkp, 0);
}
int sandbox_reset_test_free(struct udevice *dev)
{
struct sandbox_reset_test *sbrt = dev_get_priv(dev);

View File

@@ -9,12 +9,14 @@
#include <reset-uclass.h>
#include <asm/io.h>
#include <asm/reset.h>
#include <linux/delay.h>
#define SANDBOX_RESET_SIGNALS 101
struct sandbox_reset_signal {
bool asserted;
bool requested;
int reset_count;
};
struct sandbox_reset {
@@ -31,6 +33,7 @@ static int sandbox_reset_request(struct reset_ctl *reset_ctl)
return -EINVAL;
sbr->signals[reset_ctl->id].requested = true;
sbr->signals[reset_ctl->id].reset_count = 0;
return 0;
}
@@ -66,6 +69,21 @@ static int sandbox_reset_deassert(struct reset_ctl *reset_ctl)
return 0;
}
static int sandbox_reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
{
struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl,
delay_us);
sbr->signals[reset_ctl->id].asserted = true;
udelay(delay_us);
sbr->signals[reset_ctl->id].asserted = false;
sbr->signals[reset_ctl->id].reset_count++;
return 0;
}
static int sandbox_reset_bind(struct udevice *dev)
{
debug("%s(dev=%p)\n", __func__, dev);
@@ -90,6 +108,7 @@ static const struct reset_ops sandbox_reset_reset_ops = {
.rfree = sandbox_reset_free,
.rst_assert = sandbox_reset_assert,
.rst_deassert = sandbox_reset_deassert,
.rst_reset = sandbox_reset_reset,
};
U_BOOT_DRIVER(sandbox_reset) = {
@@ -102,6 +121,33 @@ U_BOOT_DRIVER(sandbox_reset) = {
.ops = &sandbox_reset_reset_ops,
};
/*
* Second sandbox reset controller for tests: same assert/deassert
* behaviour as sandbox_reset, but no rst_reset so reset_reset() uses
* the core assert / udelay / deassert fallback (reset_count never bumps).
*/
static const struct udevice_id sandbox_reset_fallback_ids[] = {
{ .compatible = "sandbox,reset-ctl-fallback-only" },
{ }
};
static const struct reset_ops sandbox_reset_fallback_reset_ops = {
.request = sandbox_reset_request,
.rfree = sandbox_reset_free,
.rst_assert = sandbox_reset_assert,
.rst_deassert = sandbox_reset_deassert,
};
U_BOOT_DRIVER(sandbox_reset_fallback) = {
.name = "sandbox_reset_fallback",
.id = UCLASS_RESET,
.of_match = sandbox_reset_fallback_ids,
.bind = sandbox_reset_bind,
.probe = sandbox_reset_probe,
.priv_auto = sizeof(struct sandbox_reset),
.ops = &sandbox_reset_fallback_reset_ops,
};
int sandbox_reset_query(struct udevice *dev, unsigned long id)
{
struct sandbox_reset *sbr = dev_get_priv(dev);
@@ -125,3 +171,15 @@ int sandbox_reset_is_requested(struct udevice *dev, unsigned long id)
return sbr->signals[id].requested;
}
int sandbox_reset_get_count(struct udevice *dev, unsigned long id)
{
struct sandbox_reset *sbr = dev_get_priv(dev);
debug("%s(dev=%p, id=%ld)\n", __func__, dev, id);
if (id >= SANDBOX_RESET_SIGNALS)
return -EINVAL;
return sbr->signals[id].reset_count;
}

View File

@@ -31,6 +31,8 @@
#define CQSPI_DISABLE_STIG_MODE BIT(0)
#define CQSPI_DMA_MODE BIT(1)
#define CQSPI_RESET_DELAY_US 10
__weak int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
const struct spi_mem_op *op)
{
@@ -256,19 +258,9 @@ static int cadence_spi_probe(struct udevice *bus)
priv->resets = devm_reset_bulk_get_optional(bus);
if (priv->resets) {
/* Assert all OSPI reset lines */
ret = reset_assert_bulk(priv->resets);
ret = reset_reset_bulk(priv->resets, CQSPI_RESET_DELAY_US);
if (ret) {
dev_err(bus, "Failed to assert OSPI reset: %d\n", ret);
return ret;
}
udelay(10);
/* Deassert all OSPI reset lines */
ret = reset_deassert_bulk(priv->resets);
if (ret) {
dev_err(bus, "Failed to deassert OSPI reset: %d\n", ret);
dev_err(bus, "Failed to reset OSPI: %d\n", ret);
return ret;
}
}

View File

@@ -23,6 +23,11 @@
#define CFG_SYS_BAUDRATE_TABLE \
{ 4800, 9600, 19200, 38400, 57600, 115200 }
/* GUID for capsule updatable firmware image */
#define XILINX_BOOT_IMAGE_GUID \
EFI_GUID(0xed9e7fcf, 0x47b3, 0x40cd, 0xb6, 0xe3, \
0x56, 0x5f, 0x14, 0x67, 0x6d, 0x82)
#if defined(CONFIG_CMD_DFU)
#define DFU_DEFAULT_POLL_TIMEOUT 300
#define DFU_ALT_INFO_RAM \

View File

@@ -76,6 +76,25 @@ struct reset_ops {
* @return 0 if OK, or a negative error code.
*/
int (*rst_deassert)(struct reset_ctl *reset_ctl);
/**
* rst_reset - Reset a HW module.
*
* This optional function triggers a reset pulse on the reset line.
* If not implemented, reset_reset() falls back to rst_assert(),
* udelay(@delay_us), then rst_deassert(); that delay is therefore
* observed only on the fallback path.
*
* When rst_reset is provided, @delay_us is controller-specific: the
* implementation should honour it if the hardware needs a minimum
* assertion time before release. It may ignore @delay_us when the
* pulse shape is fixed elsewhere (for example a firmware pulse).
*
* @reset_ctl: The reset signal to pulse.
* @delay_us: Minimum delay in microseconds between assert and
* deassert where applicable; see above.
* @return 0 if OK, or a negative error code.
*/
int (*rst_reset)(struct reset_ctl *reset_ctl, ulong delay_us);
/**
* rst_status - Check reset signal status.
*

View File

@@ -320,6 +320,45 @@ int reset_deassert(struct reset_ctl *reset_ctl);
*/
int reset_deassert_bulk(struct reset_ctl_bulk *bulk);
/**
* reset_reset - Reset a HW module by asserting and deasserting a reset signal.
*
* This function will assert and then deassert the specified reset signal,
* thus resetting the affected HW module. This is a convenience function
* that combines reset_assert() and reset_deassert().
*
* If the controller implements struct reset_ops.rst_reset, that callback
* is used and @delay_us is interpreted as documented there. Otherwise the
* core performs reset_assert(), udelay(@delay_us), then reset_deassert().
*
* @reset_ctl: A reset control struct that was previously successfully
* requested by reset_get_by_*().
* @delay_us: Delay in microseconds between assert and deassert on the
* fallback path; meaning is driver-specific when rst_reset is used.
* Use 0 for no delay on the fallback path.
* Return: 0 if OK, or a negative error code.
*/
int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us);
/**
* reset_reset_bulk - Reset all HW modules in a reset control bulk struct.
*
* This calls reset_reset() on each entry in order. Each line therefore
* completes its own assert/delay/deassert (or controller rst_reset) before
* the next entry starts. That matches Linux reset_control_bulk_reset().
*
* When several lines must stay asserted together for @delay_us (typical
* multi-reset controllers), use reset_assert_bulk(), udelay(@delay_us),
* and reset_deassert_bulk() instead.
*
* @bulk: A reset control bulk struct that was previously successfully
* requested by reset_get_bulk().
* @delay_us: Delay in microseconds passed to each reset_reset(); see
* reset_reset() and struct reset_ops.rst_reset.
* Return: 0 if OK, or a negative error code.
*/
int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us);
/**
* rst_status - Check reset signal status.
*
@@ -443,6 +482,16 @@ static inline int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
return 0;
}
static inline int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us)
{
return -ENOSYS;
}
static inline int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us)
{
return -ENOSYS;
}
static inline int reset_status(struct reset_ctl *reset_ctl)
{
return -ENOTSUPP;

View File

@@ -470,6 +470,7 @@ int zynqmp_pm_ufs_sram_csr_read(u32 *value);
int zynqmp_pm_ufs_sram_csr_write(u32 *value);
int zynqmp_pm_ufs_cal_reg(u32 *value);
u32 zynqmp_pm_get_pmc_multi_boot_reg(void);
u32 zynqmp_pm_get_pmc_global_pggs_reg(u32 reg_addr);
/* Type of Config Object */
#define PM_CONFIG_OBJECT_TYPE_BASE 0x1U
@@ -534,4 +535,7 @@ extern smc_call_handler_t __data smc_call_handler;
#define PM_DEV_OSPI (0x1822402aU)
#define PM_REG_PGGS3 0x30004003
#define PMC_GLOBAL_PGGS3_REG_NODE 0x1824C005
#endif /* _ZYNQMP_FIRMWARE_H_ */

View File

@@ -19,6 +19,9 @@
/* This is the other reset phandle specifier handled by bulk */
#define OTHER_RESET_ID 2
/* Line on reset-ctl-fallback (sandbox,reset-ctl-fallback-only); see test.dts */
#define FALLBACK_RESET_ID 5
/* Base test of the reset uclass */
static int dm_test_reset_base(struct unit_test_state *uts)
{
@@ -120,6 +123,110 @@ static int dm_test_reset_devm(struct unit_test_state *uts)
}
DM_TEST(dm_test_reset_devm, UTF_SCAN_FDT);
static int dm_test_reset_reset(struct unit_test_state *uts)
{
struct udevice *dev_reset;
struct udevice *dev_test;
ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl",
&dev_reset));
ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
&dev_test));
ut_assertok(sandbox_reset_test_get(dev_test));
/* Verify reset_count starts at 0 */
ut_asserteq(0, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
ut_assertok(sandbox_reset_test_assert(dev_test));
ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID));
ut_assertok(sandbox_reset_test_reset(dev_test));
/* Verify reset was pulsed (count incremented) */
ut_asserteq(1, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
ut_assertok(sandbox_reset_test_free(dev_test));
return 0;
}
DM_TEST(dm_test_reset_reset, UTF_SCAN_FDT);
/*
* reset_reset() fallback path: controller has no rst_reset op, so the
* core does assert -> udelay -> deassert. rst_reset-only accounting
* (reset_count) stays zero. Leave the line asserted before reset_reset()
* so we verify the fallback actually pulses it back to deasserted.
*/
static int dm_test_reset_reset_fallback_path(struct unit_test_state *uts)
{
struct udevice *dev_reset_fb;
struct udevice *dev_test;
struct reset_ctl ctl;
ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl-fallback",
&dev_reset_fb));
ut_asserteq(0, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
&dev_test));
ut_assertok(reset_get_by_name(dev_test, "fallback", &ctl));
ut_asserteq_ptr(ctl.dev, dev_reset_fb);
ut_asserteq(FALLBACK_RESET_ID, ctl.id);
ut_assertok(reset_assert(&ctl));
ut_asserteq(1, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
ut_assertok(reset_reset(&ctl, 1));
ut_asserteq(0, sandbox_reset_get_count(dev_reset_fb, FALLBACK_RESET_ID));
ut_asserteq(0, sandbox_reset_query(dev_reset_fb, FALLBACK_RESET_ID));
ut_assertok(reset_free(&ctl));
return 0;
}
DM_TEST(dm_test_reset_reset_fallback_path, UTF_SCAN_FDT);
static int dm_test_reset_reset_bulk(struct unit_test_state *uts)
{
struct udevice *dev_reset;
struct udevice *dev_test;
ut_assertok(uclass_get_device_by_name(UCLASS_RESET, "reset-ctl",
&dev_reset));
ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID));
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "reset-ctl-test",
&dev_test));
ut_assertok(sandbox_reset_test_get_bulk(dev_test));
/* Verify reset_count starts at 0 */
ut_asserteq(0, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
ut_asserteq(0, sandbox_reset_get_count(dev_reset, OTHER_RESET_ID));
ut_assertok(sandbox_reset_test_assert_bulk(dev_test));
ut_asserteq(1, sandbox_reset_query(dev_reset, TEST_RESET_ID));
ut_asserteq(1, sandbox_reset_query(dev_reset, OTHER_RESET_ID));
ut_assertok(sandbox_reset_test_reset_bulk(dev_test));
/* Verify resets were pulsed (counts incremented) */
ut_asserteq(1, sandbox_reset_get_count(dev_reset, TEST_RESET_ID));
ut_asserteq(1, sandbox_reset_get_count(dev_reset, OTHER_RESET_ID));
ut_asserteq(0, sandbox_reset_query(dev_reset, TEST_RESET_ID));
ut_asserteq(0, sandbox_reset_query(dev_reset, OTHER_RESET_ID));
ut_assertok(sandbox_reset_test_release_bulk(dev_test));
return 0;
}
DM_TEST(dm_test_reset_reset_bulk, UTF_SCAN_FDT);
static int dm_test_reset_bulk(struct unit_test_state *uts)
{
struct udevice *dev_reset;