summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/dts/socfpga_agilex5-u-boot.dtsi6
-rw-r--r--arch/arm/dts/socfpga_agilex5.dtsi2
-rw-r--r--arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi2
-rw-r--r--arch/arm/mach-socfpga/Kconfig1
-rw-r--r--arch/arm/mach-socfpga/board.c2
-rw-r--r--arch/arm/mach-socfpga/include/mach/handoff_soc64.h1
-rw-r--r--arch/arm/mach-socfpga/include/mach/secure_vab.h4
-rw-r--r--arch/arm/mach-socfpga/misc_soc64.c32
-rw-r--r--arch/arm/mach-socfpga/secure_vab.c9
-rw-r--r--arch/arm/mach-socfpga/spl_agilex5.c6
-rw-r--r--configs/socfpga_agilex5_defconfig6
-rw-r--r--doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml39
-rw-r--r--drivers/clk/altera/clk-n5x.c4
-rw-r--r--drivers/ddr/altera/sdram_n5x.c8
-rw-r--r--drivers/fpga/socfpga_gen5.c25
-rw-r--r--drivers/misc/socfpga_dtreg.c5
-rw-r--r--drivers/power/domain/Kconfig8
-rw-r--r--drivers/power/domain/Makefile1
-rw-r--r--drivers/power/domain/altr-pmgr-agilex5.c112
-rw-r--r--include/configs/socfpga_soc64_common.h24
21 files changed, 258 insertions, 40 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index c4eaba58a90..795ff2328dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -156,6 +156,7 @@ M: Tingting Meng <tingting.meng@altera.com>
S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git
F: drivers/ddr/altera/
+F: drivers/power/domain/altr-pmgr-agilex5.c
F: arch/arm/mach-socfpga/
F: configs/socfpga_agilex5_vab_defconfig
F: drivers/sysreset/sysreset_socfpga*
diff --git a/arch/arm/dts/socfpga_agilex5-u-boot.dtsi b/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
index 874e71b5ca4..402f0bec173 100644
--- a/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_agilex5-u-boot.dtsi
@@ -668,6 +668,12 @@
bootph-all;
};
};
+
+ pwrmgr: pwrmgr@10d14000 {
+ compatible = "altr,pmgr-agilex5";
+ reg = <0x10d14000 0x100>;
+ bootph-all;
+ };
};
};
diff --git a/arch/arm/dts/socfpga_agilex5.dtsi b/arch/arm/dts/socfpga_agilex5.dtsi
index 86322d7b0ce..9bc3864022b 100644
--- a/arch/arm/dts/socfpga_agilex5.dtsi
+++ b/arch/arm/dts/socfpga_agilex5.dtsi
@@ -388,6 +388,7 @@
reg-io-width = <4>;
num-cs = <4>;
clocks = <&clkmgr AGILEX5_L4_MAIN_CLK>;
+ spi-max-frequency = <50000000>;
status = "disabled";
};
@@ -402,6 +403,7 @@
reg-io-width = <4>;
num-cs = <4>;
clocks = <&clkmgr AGILEX5_L4_MAIN_CLK>;
+ spi-max-frequency = <50000000>;
status = "disabled";
};
diff --git a/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
index 8d7dc0945ab..938ddb04c04 100644
--- a/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
@@ -67,7 +67,7 @@
chosen {
stdout-path = "serial0:115200n8";
- u-boot,spl-boot-order = &mmc,&flash0,"/memory";
+ u-boot,spl-boot-order = &mmc,&flash0,&nand,"/memory";
};
};
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index a76a9fb2a39..156cfbbcf3b 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -120,7 +120,6 @@ config TARGET_SOCFPGA_N5X
select BINMAN if SPL_ATF
select CLK
select GICV2
- select FPGA_INTEL_SDM_MAILBOX
select NCORE_CACHE
select SPL_ALTERA_SDRAM
select SPL_CLK if SPL
diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c
index bda12324803..28554b7a109 100644
--- a/arch/arm/mach-socfpga/board.c
+++ b/arch/arm/mach-socfpga/board.c
@@ -134,7 +134,7 @@ u8 socfpga_get_board_id(void)
if (jtag_usercode == DEFAULT_JTAG_USERCODE) {
debug("JTAG Usercode is not set. Default Board ID to 0\n");
- } else if (jtag_usercode >= 0 && jtag_usercode <= 255) {
+ } else if (jtag_usercode <= 255) {
board_id = jtag_usercode;
debug("Valid JTAG Usercode. Set Board ID to %u\n", board_id);
} else {
diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
index 763b077d8c1..04203cceb8a 100644
--- a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
@@ -68,6 +68,7 @@
#define SOC64_HANDOFF_CLOCK (SOC64_HANDOFF_BASE + 0x580)
#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
#define SOC64_HANDOFF_PERI (SOC64_HANDOFF_BASE + 0x620)
+#define SOC64_HANDOFF_PERI_LEN 1
#define SOC64_HANDOFF_SDRAM (SOC64_HANDOFF_BASE + 0x634)
#define SOC64_HANDOFF_SDRAM_LEN 5
#endif
diff --git a/arch/arm/mach-socfpga/include/mach/secure_vab.h b/arch/arm/mach-socfpga/include/mach/secure_vab.h
index 42588588e87..1be0cb61e7a 100644
--- a/arch/arm/mach-socfpga/include/mach/secure_vab.h
+++ b/arch/arm/mach-socfpga/include/mach/secure_vab.h
@@ -1,7 +1,7 @@
-/* SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
*
* Copyright (C) 2020 Intel Corporation <www.intel.com>
- *
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
*/
#ifndef _SECURE_VAB_H_
diff --git a/arch/arm/mach-socfpga/misc_soc64.c b/arch/arm/mach-socfpga/misc_soc64.c
index 4f080f4f0b3..5222b384434 100644
--- a/arch/arm/mach-socfpga/misc_soc64.c
+++ b/arch/arm/mach-socfpga/misc_soc64.c
@@ -22,6 +22,22 @@
DECLARE_GLOBAL_DATA_PTR;
+/* Agilex5 Sub Device Jtag ID List */
+#define A3690_JTAG_ID 0x036090DD
+#define A3694_JTAG_ID 0x436090DD
+#define A36C0_JTAG_ID 0x0360C0DD
+#define A36C4_JTAG_ID 0x4360C0DD
+#define A36D0_JTAG_ID 0x0360D0DD
+#define A36D4_JTAG_ID 0x4360D0DD
+#define A36F0_JTAG_ID 0x0360F0DD
+#define A36F4_JTAG_ID 0x4360F0DD
+#define A3610_JTAG_ID 0x036010DD
+#define A3614_JTAG_ID 0x436010DD
+#define A3630_JTAG_ID 0x036030DD
+#define A3634_JTAG_ID 0x436030DD
+
+#define JTAG_ID_MASK 0xCFF0FFFF
+
/*
* FPGA programming support for SoC FPGA Stratix 10
*/
@@ -42,6 +58,22 @@ static Altera_desc altera_fpga[] = {
},
};
+u32 socfpga_get_jtag_id(void)
+{
+ u32 jtag_id;
+
+ jtag_id = readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD4);
+
+ if (!jtag_id) {
+ debug("Failed to read JTAG ID. Default JTAG ID to A36F4_JTAG_ID.\n");
+ jtag_id = A36F4_JTAG_ID;
+ }
+
+ debug("%s: jtag_id: 0x%x\n", __func__, jtag_id);
+
+ return jtag_id;
+}
+
/*
* The Agilex5 platform has enabled the bloblist feature, and the bloblist
* address and size are initialized based on the defconfig settings.
diff --git a/arch/arm/mach-socfpga/secure_vab.c b/arch/arm/mach-socfpga/secure_vab.c
index e931f1043b3..d5ff47a142c 100644
--- a/arch/arm/mach-socfpga/secure_vab.c
+++ b/arch/arm/mach-socfpga/secure_vab.c
@@ -1,17 +1,18 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2020 Intel Corporation <www.intel.com>
- *
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
*/
+#include <log.h>
+#include <malloc.h>
#include <asm/arch/mailbox_s10.h>
#include <asm/arch/secure_vab.h>
#include <asm/arch/smc_api.h>
#include <asm/unaligned.h>
-#include <exports.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/intel-smc.h>
-#include <log.h>
#define CHUNKSZ_PER_WD_RESET (256 * SZ_1K)
diff --git a/arch/arm/mach-socfpga/spl_agilex5.c b/arch/arm/mach-socfpga/spl_agilex5.c
index a9aad5350d2..2a13301802d 100644
--- a/arch/arm/mach-socfpga/spl_agilex5.c
+++ b/arch/arm/mach-socfpga/spl_agilex5.c
@@ -96,6 +96,12 @@ void board_init_f(ulong dummy)
hang();
}
+ ret = uclass_get_device(UCLASS_POWER_DOMAIN, 0, &dev);
+ if (ret) {
+ debug("PSS SRAM power-off failed: %d\n", ret);
+ hang();
+ }
+
if (IS_ENABLED(CONFIG_SPL_ALTERA_SDRAM)) {
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
diff --git a/configs/socfpga_agilex5_defconfig b/configs/socfpga_agilex5_defconfig
index 33a6221979a..cc812c7008c 100644
--- a/configs/socfpga_agilex5_defconfig
+++ b/configs/socfpga_agilex5_defconfig
@@ -12,7 +12,7 @@ CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex5_socdk"
CONFIG_DM_RESET=y
CONFIG_SPL_STACK=0x7d000
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
-CONFIG_SPL_BSS_START_ADDR=0xbff00000
+CONFIG_SPL_BSS_START_ADDR=0x9ff00000
CONFIG_SPL_BSS_MAX_SIZE=0x100000
CONFIG_SYS_LOAD_ADDR=0x82000000
CONFIG_TARGET_SOCFPGA_AGILEX5_SOCDK=y
@@ -42,7 +42,7 @@ CONFIG_HANDOFF=y
CONFIG_SPL_HAVE_INIT_STACK=y
CONFIG_SPL_SYS_MALLOC=y
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
-CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xbfa00000
+CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x9fa00000
CONFIG_SPL_SYS_MALLOC_SIZE=0x500000
CONFIG_SPL_CACHE=y
CONFIG_SPL_MTD=y
@@ -103,3 +103,5 @@ CONFIG_DESIGNWARE_WATCHDOG=y
CONFIG_WDT=y
# CONFIG_SPL_USE_TINY_PRINTF is not set
CONFIG_PANIC_HANG=y
+CONFIG_SPL_POWER_DOMAIN=y
+CONFIG_AGILEX5_PMGR_POWER_DOMAIN=y
diff --git a/doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml b/doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml
new file mode 100644
index 00000000000..af7aeaa922c
--- /dev/null
+++ b/doc/device-tree-bindings/power/altr,pmgr-agilex5.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/power/altr,pmgr-agilex5.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Altera Agilex5 Power Manager
+
+maintainers:
+ - name: Alif Zakuan Yuslaimi
+ email: alif.zakuan.yuslaimi@altera.com
+
+description: |
+ This controller will read the peripheral handoff data obtained from the
+ bitstream and will power gate the specified peripheral's SRAM from the
+ handoff data values to reduce power consumption.
+
+properties:
+ compatible:
+ const: "altr,pmgr-agilex5"
+
+ reg:
+ maxItems: 1
+
+ bootph-all: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pwrmgr: pwrmgr@10d14000 {
+ compatible = "altr,pmgr-agilex5";
+ reg = <0x10d14000 0x100>;
+ bootph-all;
+ };
diff --git a/drivers/clk/altera/clk-n5x.c b/drivers/clk/altera/clk-n5x.c
index 09db250ab6d..9e4e7a1d908 100644
--- a/drivers/clk/altera/clk-n5x.c
+++ b/drivers/clk/altera/clk-n5x.c
@@ -386,8 +386,8 @@ static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id)
} else {
clock /= 1 + ((CM_REG_READL(plat,
CLKMGR_PERPLL_PLLOUTDIV) &
- CLKMGR_PLLOUTDIV_C3CNT_MASK >>
- CLKMGR_PLLOUTDIV_C3CNT_OFFSET));
+ CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+ CLKMGR_PLLOUTDIV_C3CNT_OFFSET);
}
break;
diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c
index d1fc93b6bdd..17ec6afa82b 100644
--- a/drivers/ddr/altera/sdram_n5x.c
+++ b/drivers/ddr/altera/sdram_n5x.c
@@ -346,25 +346,25 @@ struct ddr_handoff {
phys_addr_t cntlr_base;
size_t cntlr_total_length;
enum ddr_type cntlr_t;
- size_t cntlr_handoff_length;
+ int cntlr_handoff_length;
/* Second controller attributes*/
phys_addr_t cntlr2_handoff_base;
phys_addr_t cntlr2_base;
size_t cntlr2_total_length;
enum ddr_type cntlr2_t;
- size_t cntlr2_handoff_length;
+ int cntlr2_handoff_length;
/* PHY attributes */
phys_addr_t phy_handoff_base;
phys_addr_t phy_base;
size_t phy_total_length;
- size_t phy_handoff_length;
+ int phy_handoff_length;
/* PHY engine attributes */
phys_addr_t phy_engine_handoff_base;
size_t phy_engine_total_length;
- size_t phy_engine_handoff_length;
+ int phy_engine_handoff_length;
/* Calibration attributes */
phys_addr_t train_imem_base;
diff --git a/drivers/fpga/socfpga_gen5.c b/drivers/fpga/socfpga_gen5.c
index 9473f057328..964a5cc8789 100644
--- a/drivers/fpga/socfpga_gen5.c
+++ b/drivers/fpga/socfpga_gen5.c
@@ -119,27 +119,14 @@ static int fpgamgr_program_poll_cd(void)
{
const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK |
FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK;
- unsigned long reg, i;
+ unsigned long reg;
- /* (3) wait until full config done */
- for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
- reg = readl(&fpgamgr_regs->gpio_ext_porta);
-
- /* Config error */
- if (!(reg & mask)) {
- printf("FPGA: Configuration error.\n");
- return -3;
- }
-
- /* Config done without error */
- if (reg & mask)
- break;
- }
+ reg = readl(&fpgamgr_regs->gpio_ext_porta);
- /* Timeout happened, return error */
- if (i == FPGA_TIMEOUT_CNT) {
- printf("FPGA: Timeout waiting for program.\n");
- return -4;
+ /* Config error */
+ if (!(reg & mask)) {
+ printf("FPGA: Configuration error.\n");
+ return -3;
}
/* Disable AXI configuration */
diff --git a/drivers/misc/socfpga_dtreg.c b/drivers/misc/socfpga_dtreg.c
index ea5d0bcdf51..dd6809433e3 100644
--- a/drivers/misc/socfpga_dtreg.c
+++ b/drivers/misc/socfpga_dtreg.c
@@ -76,16 +76,15 @@ static int socfpga_dtreg_probe(struct udevice *dev)
return -EINVAL;
}
+ reg = base + offset;
+
if (mask != 0) {
if (mask == 0xffffffff) {
- reg = base + offset;
writel(val, (uintptr_t)reg);
} else {
/* Mask the value with the masking bits */
set_mask = val & mask;
- reg = base + offset;
-
/* Clears and sets specific bits in the register */
clrsetbits_le32((uintptr_t)reg, mask, set_mask);
}
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 5f5218bd8b5..ebf5d828cb0 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -18,6 +18,14 @@ config APPLE_PMGR_POWER_DOMAIN
This driver is needed to power on parts of the SoC that have
not been powered on by previous boot stages.
+config AGILEX5_PMGR_POWER_DOMAIN
+ bool "Enable the Agilex5 PMGR power domain driver"
+ depends on SPL_POWER_DOMAIN
+ help
+ Enable support for power gating peripherals' SRAM specified in
+ the handoff data values obtained from the bitstream to reduce
+ power consumption.
+
config BCM6328_POWER_DOMAIN
bool "Enable the BCM6328 power domain driver"
depends on POWER_DOMAIN && ARCH_BMIPS
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index 4d20c97d26c..8e03f620437 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_$(PHASE_)POWER_DOMAIN) += power-domain-uclass.o
obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
+obj-$(CONFIG_AGILEX5_PMGR_POWER_DOMAIN) += altr-pmgr-agilex5.o
obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
diff --git a/drivers/power/domain/altr-pmgr-agilex5.c b/drivers/power/domain/altr-pmgr-agilex5.c
new file mode 100644
index 00000000000..257e8b234fd
--- /dev/null
+++ b/drivers/power/domain/altr-pmgr-agilex5.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
+ */
+
+#include <dm.h>
+#include <power-domain-uclass.h>
+#include <asm/io.h>
+#include <asm/arch/handoff_soc64.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <time.h>
+
+#define PSS_FWENCTL 0x44
+#define PSS_PGENCTL 0x48
+#define PSS_PGSTAT 0x4c
+
+#define DATA_MASK GENMASK(7, 0)
+#define TIMEOUT_MS 1000
+
+static int wait_verify_fsm(u16 timeout_ms, uintptr_t base_addr, u32 peripheral_handoff)
+{
+ u32 data = 0;
+ u32 pgstat = 0;
+ ulong start = get_timer(0);
+
+ /* Wait FSM ready */
+ do {
+ data = FIELD_GET(DATA_MASK, readl(base_addr + PSS_PGSTAT));
+ if (data != 0)
+ break;
+ } while (get_timer(start) < timeout_ms);
+
+ if (get_timer(start) >= timeout_ms)
+ return -ETIMEDOUT;
+
+ /* Verify PSS SRAM power gated */
+ pgstat = FIELD_GET(DATA_MASK, readl(base_addr + PSS_PGSTAT));
+ if (pgstat != FIELD_GET(DATA_MASK, peripheral_handoff))
+ return -EPERM;
+
+ return 0;
+}
+
+static int pss_sram_power_off(uintptr_t base_addr, u32 *handoff_table)
+{
+ u32 peripheral_handoff;
+
+ /* Get PSS SRAM handoff data */
+ peripheral_handoff = handoff_table[0];
+
+ /* Enable firewall for PSS SRAM */
+ setbits_le32(base_addr + PSS_FWENCTL, peripheral_handoff);
+
+ /* Wait */
+ udelay(1);
+
+ /* Power gating PSS SRAM */
+ setbits_le32(base_addr + PSS_PGENCTL, peripheral_handoff);
+
+ return wait_verify_fsm(TIMEOUT_MS, base_addr, peripheral_handoff);
+}
+
+static int altera_pmgr_off(struct power_domain *power_domain)
+{
+ fdt_addr_t base_addr = dev_read_addr(power_domain->dev);
+ u32 handoff_table[SOC64_HANDOFF_PERI_LEN];
+ int ret;
+
+ /* Read handoff data for peripherals configuration */
+ ret = socfpga_handoff_read((void *)SOC64_HANDOFF_PERI, handoff_table,
+ SOC64_HANDOFF_PERI_LEN);
+ if (ret) {
+ debug("%s: handoff data read failed. ret: %d\n", __func__, ret);
+ return ret;
+ }
+
+ pss_sram_power_off(base_addr, handoff_table);
+
+ return 0;
+}
+
+static int altera_pmgr_probe(struct udevice *dev)
+{
+ struct power_domain *power_domain = dev_get_priv(dev);
+
+ if (!power_domain)
+ return -EINVAL;
+
+ power_domain->dev = dev;
+
+ return altera_pmgr_off(power_domain);
+}
+
+static const struct udevice_id altera_pmgr_ids[] = {
+ { .compatible = "altr,pmgr-agilex5" },
+ { /* sentinel */ }
+};
+
+static struct power_domain_ops altera_pmgr_ops = {
+ .off = altera_pmgr_off,
+};
+
+U_BOOT_DRIVER(altr_pmgr) = {
+ .name = "altr_pmgr",
+ .id = UCLASS_POWER_DOMAIN,
+ .of_match = altera_pmgr_ids,
+ .ops = &altera_pmgr_ops,
+ .probe = altera_pmgr_probe,
+ .priv_auto = sizeof(struct power_domain),
+};
diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h
index 5ed17671f79..83b600c7fcc 100644
--- a/include/configs/socfpga_soc64_common.h
+++ b/include/configs/socfpga_soc64_common.h
@@ -73,9 +73,31 @@
#define BOOTENV_DEV_NAME_QSPI(devtypeu, devtypel, instance) \
"qspi "
+#if IS_ENABLED(CONFIG_CMD_NAND)
+#define BOOT_TARGET_DEVICES_NAND(func) func(NAND, nand, na)
+#else
+#define BOOT_TARGET_DEVICES_NAND(func)
+#endif
+
+#define BOOTENV_DEV_NAND(devtypeu, devtypel, instance) \
+ "bootcmd_nand=ubi detach && " \
+ "setenv mtdids 'nor0=nor0,nand0=nand.0' && " \
+ "setenv mtdparts 'mtdparts=nor0:66m(qspi_uboot),190m(qspi_root);" \
+ "nand.0:2m(u-boot),500m(root)' && " \
+ "env select UBI; saveenv && " \
+ "ubi part root && " \
+ "ubi readvol ${scriptaddr} script && " \
+ "echo NAND: Trying to boot script at ${scriptaddr} && " \
+ "source ${scriptaddr}; " \
+ "echo NAND: SCRIPT FAILED: continuing...; ubi detach;\0"
+
+#define BOOTENV_DEV_NAME_NAND(devtypeu, devtypel, instance) \
+ "nand "
+
#define BOOT_TARGET_DEVICES(func) \
BOOT_TARGET_DEVICES_MMC(func) \
- BOOT_TARGET_DEVICES_QSPI(func)
+ BOOT_TARGET_DEVICES_QSPI(func) \
+ BOOT_TARGET_DEVICES_NAND(func)
#include <config_distro_bootcmd.h>