]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
ddr: altera: Add DDR driver for Agilex7 M-series
authorTingting Meng <tingting.meng@altera.com>
Mon, 4 Aug 2025 01:24:56 +0000 (18:24 -0700)
committerTien Fong Chee <tien.fong.chee@intel.com>
Fri, 8 Aug 2025 14:20:54 +0000 (22:20 +0800)
This is for new platform enablement for Agilex7 M-series.
Add DDR driver for Agilex7 M-series. This driver is designed to support
DDR and HBM memory. The official HBM handoff is not ready yet, therefore
hardcoded handoff is used for HBM driver validation on mUDV board.

Signed-off-by: Tingting Meng <tingting.meng@altera.com>
Signed-off-by: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi@altera.com>
Reviewed-by: Tien Fong Chee <tien.fong.chee@altera.com>
arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
arch/arm/mach-socfpga/include/mach/system_manager_soc64.h
drivers/ddr/altera/Makefile
drivers/ddr/altera/sdram_agilex7m.c [new file with mode: 0644]
drivers/ddr/altera/sdram_soc64.c
drivers/ddr/altera/sdram_soc64.h

index 5ac868a281b95d577163730d97e17edb83beb001..074b9691af84ea207a52ef82739d5d965a34b412 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2016-2024 Intel Corporation <www.intel.com>
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
  */
 
 #ifndef _SOCFPGA_SOC64_BASE_HARDWARE_H_
 #define SOCFPGA_SDR_SCHEDULER_ADDRESS          0xf8000400
 #define SOCFPGA_HMC_MMR_IO48_ADDRESS           0xf8010000
 #define SOCFPGA_SDR_ADDRESS                    0xf8011000
+#define SOCFPGA_FW_MPFE_SCR_ADDRESS            0xf8020000
 #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX) || \
-       IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+       IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X) || \
+       IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7M)
 #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS         0xf8020200
 #else
 #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS         0xf8020100
@@ -75,6 +78,7 @@
 #define SOCFPGA_FIREWALL_SOC2FPGA              0xffd21200
 #define SOCFPGA_FIREWALL_LWSOC2FPGA            0xffd21300
 #define SOCFPGA_FIREWALL_TCU                   0xffd21400
+#define SOCFPGA_FIREWALL_PRIV_MEMORYMAP_PRIV   0xffd24800
 #define SOCFPGA_DMANONSECURE_ADDRESS           0xffda0000
 #define SOCFPGA_DMASECURE_ADDRESS              0xffda1000
 #define SOCFPGA_OCRAM_ADDRESS                  0xffe00000
index 713fa2c517b73d77160e14c35bd0fd9f45f26b13..054a28d845da82ec60c5d7f2bf0ccde78f654b5b 100644 (file)
@@ -146,6 +146,7 @@ void populate_sysmgr_pinmux(void);
  * Bit[31] reserved for FSBL to check DBE is triggered (set by SDM to "1") ?
  *
  * Bit[30] reserved for FSBL to update the DDR init progress
+
  * 1 - means in progress, 0 - haven't started / DDR is up running.
  *
  * Bit[19] store ATF CPU0 ON OFF value.
@@ -156,6 +157,8 @@ void populate_sysmgr_pinmux(void);
  */
 #define ALT_SYSMGR_SCRATCH_REG_8_DDR_DBE_MASK  BIT(31)
 #define ALT_SYSMGR_SCRATCH_REG_8_DDR_PROGRESS_MASK     BIT(30)
+#define ALT_SYSMGR_SCRATCH_REG_8_OCRAM_DBE_MASK                BIT(29)
+#define ALT_SYSMGR_SCRATCH_REG_8_IO96B_HPS_MASK                GENMASK(28, 27)
 #define SYSMGR_SCRATCH_REG_8_ACF_DDR_RATE_MASK BIT(18)
 #define SYSMGR_SCRATCH_REG_8_ACF_DDR_RATE_SHIFT 18
 
index c627f16711e7d8af7124d1580cfa0f1fa95f18fc..7ed43965be5bc7493a95137d14a2af5e1a2a38f9 100644 (file)
@@ -13,4 +13,5 @@ obj-$(CONFIG_TARGET_SOCFPGA_STRATIX10) += sdram_soc64.o sdram_s10.o
 obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += sdram_soc64.o sdram_agilex.o
 obj-$(CONFIG_TARGET_SOCFPGA_N5X) += sdram_soc64.o sdram_n5x.o
 obj-$(CONFIG_TARGET_SOCFPGA_AGILEX5) += sdram_soc64.o sdram_agilex5.o iossm_mailbox.o
+obj-$(CONFIG_TARGET_SOCFPGA_AGILEX7M) += sdram_soc64.o sdram_agilex7m.o iossm_mailbox.o uibssm_mailbox.o
 endif
diff --git a/drivers/ddr/altera/sdram_agilex7m.c b/drivers/ddr/altera/sdram_agilex7m.c
new file mode 100644 (file)
index 0000000..9b3cc5c
--- /dev/null
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
+ */
+
+#include <dm.h>
+#include <hang.h>
+#include <log.h>
+#include <ram.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <wdt.h>
+#include <asm/arch/system_manager.h>
+#include <linux/bitfield.h>
+#include "iossm_mailbox.h"
+#include "sdram_soc64.h"
+#include "uibssm_mailbox.h"
+
+/* NOCPLL register */
+#define SYSMGR_HMC_CLK         0xB4
+#define SYSMGR_HMC_CLK_NOCPLL  BIT(8)
+
+/* MPFE NOC registers */
+#define F2SDRAM_SIDEBAND_FLAGOUTSET0   0x50
+#define F2SDRAM_SIDEBAND_FLAGOUTSTATUS0        0x58
+#define SIDEBANDMGR_FLAGOUTSET0_REG    SOCFPGA_F2SDRAM_MGR_ADDRESS +\
+                                       F2SDRAM_SIDEBAND_FLAGOUTSET0
+#define SIDEBANDMGR_FLAGOUTSTATUS0_REG SOCFPGA_F2SDRAM_MGR_ADDRESS +\
+                                       F2SDRAM_SIDEBAND_FLAGOUTSTATUS0
+
+#define SIDEBANDMGR_FLAGOUTSET0_REG_MULTICHANNEL       BIT(4)
+#define SIDEBANDMGR_FLAGOUTSET0_REG_INTERLEAVING       BIT(5)
+
+/* Reset type */
+enum reset_type {
+       POR_RESET,
+       WARM_RESET,
+       COLD_RESET,
+       NCONFIG,
+       JTAG_CONFIG,
+       RSU_RECONFIG
+};
+
+phys_addr_t io96b_csr_reg_addr[] = {
+       0xf8400000, /* IO96B_0 CSR registers address */
+       0xf8800000  /* IO96B_1 CSR registers address */
+};
+
+phys_addr_t uib_csr_reg_addr[] = {
+       0xf8400000, /* UIB_0 CSR registers address */
+       0xf8410000, /* UIB_1 CSR registers address */
+       0xf8420000, /* UIB_2 CSR registers address */
+       0xf8430000, /* UIB_3 CSR registers address */
+       0xf8440000, /* UIB_4 CSR registers address */
+       0xf8450000, /* UIB_5 CSR registers address */
+       0xf8460000, /* UIB_6 CSR registers address */
+       0xf8470000  /* UIB_7 CSR registers address */
+};
+
+static enum reset_type get_reset_type(u32 reg)
+{
+       return FIELD_GET(ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_MASK, reg);
+}
+
+bool is_ddr_init_hang(void)
+{
+       u32 reg = readl(socfpga_get_sysmgr_addr() +
+                       SYSMGR_SOC64_BOOT_SCRATCH_COLD8);
+
+       debug("%s: 0x%x\n", __func__, reg);
+
+       if (reg & ALT_SYSMGR_SCRATCH_REG_8_DDR_PROGRESS_MASK)
+               return true;
+
+       return false;
+}
+
+void ddr_init_inprogress(bool start)
+{
+       if (start)
+               setbits_le32(socfpga_get_sysmgr_addr() +
+                            SYSMGR_SOC64_BOOT_SCRATCH_COLD8,
+                            ALT_SYSMGR_SCRATCH_REG_8_DDR_PROGRESS_MASK);
+       else
+               clrbits_le32(socfpga_get_sysmgr_addr() +
+                            SYSMGR_SOC64_BOOT_SCRATCH_COLD8,
+                            ALT_SYSMGR_SCRATCH_REG_8_DDR_PROGRESS_MASK);
+}
+
+static const char *memory_type_in_use(struct udevice *dev)
+{
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+
+       return (plat->mem_type == DDR_MEMORY ? "DDR" : "HBM");
+}
+
+static bool is_ddr_in_use(struct udevice *dev)
+{
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+
+       return (plat->mem_type == DDR_MEMORY ? true : false);
+}
+
+int populate_ddr_handoff(struct udevice *dev, struct io96b_info *io96b_ctrl,
+                        struct uib_info *uib_ctrl)
+{
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+       int i;
+       u8 count = 0;
+       u32 len = SOC64_HANDOFF_DDR_LEN;
+       u32 handoff_table[len];
+
+       /* Read handoff for DDR configuration */
+       socfpga_handoff_read((void *)SOC64_HANDOFF_DDR_BASE, handoff_table, len);
+
+       /* Interleaving Mode */
+       if (handoff_table[0] & SOC64_HANDOFF_DDR_INTERLEAVING_MODE_MASK)
+               plat->multichannel_interleaving = true;
+       else
+               plat->multichannel_interleaving = false;
+
+       debug("%s: MPFE-EMIF is in %s mode\n", __func__,
+             plat->multichannel_interleaving ? "interleaving" : "multichannel");
+
+       /* Memory type */
+       if (handoff_table[2] & SOC64_HANDOFF_DDR_MEMORY_TYPE_MASK)
+               plat->mem_type = HBM_MEMORY;
+       else
+               plat->mem_type = DDR_MEMORY;
+
+       debug("%s: Memory type is %s\n", __func__
+                       , plat->mem_type ? "HBM" : "DDR");
+
+       if (plat->mem_type == HBM_MEMORY) {
+               /* Assign UIB CSR base address if it is valid */
+               for (i = 0; i < MAX_UIB_SUPPORTED; i++) {
+                       if (handoff_table[3] & BIT(i)) {
+                               uib_ctrl->uib[count].uib_csr_addr = uib_csr_reg_addr[i];
+                               debug("%s: UIB 0x%llx CSR enabled\n", __func__
+                                       , uib_ctrl->uib[count].uib_csr_addr);
+                               count++;
+                       }
+               }
+
+               uib_ctrl->num_instance = count;
+               debug("%s: returned num_instance 0x%x\n", __func__, uib_ctrl->num_instance);
+
+               /*
+                * HBM memory size
+                * 1 UIB channel has 2 pseudo channels
+                * 1 pseudo channel is 1GB, hence 1 UIB channel is 2GB
+                */
+               uib_ctrl->overall_size = (phys_size_t)uib_ctrl->num_instance * SZ_2G;
+
+               /* UIB ECC status */
+               uib_ctrl->ecc_status = handoff_table[4];
+
+               debug("%s: ECC status 0x%x\n", __func__, uib_ctrl->ecc_status);
+       } else {
+               /* Assign IO96B CSR base address if it is valid */
+               for (i = 0; i < MAX_IO96B_SUPPORTED; i++) {
+                       if (handoff_table[1] & BIT(i)) {
+                               io96b_ctrl->io96b[i].io96b_csr_addr = io96b_csr_reg_addr[i];
+
+                               debug("%s: IO96B 0x%llx CSR enabled\n", __func__,
+                                     io96b_ctrl->io96b[i].io96b_csr_addr);
+
+                               count++;
+                       }
+               }
+
+               io96b_ctrl->num_instance = count;
+               debug("%s: returned num_instance 0x%x\n", __func__, io96b_ctrl->num_instance);
+       }
+
+       return 0;
+}
+
+int config_mpfe_sideband_mgr(struct udevice *dev)
+{
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+       u32 reg, mask;
+       int ret = 0;
+
+       if (plat->multichannel_interleaving) {
+               mask = SIDEBANDMGR_FLAGOUTSET0_REG_INTERLEAVING;
+               setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, mask);
+       } else {
+               mask = SIDEBANDMGR_FLAGOUTSET0_REG_MULTICHANNEL;
+               setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, mask);
+       }
+
+       reg = readl(SIDEBANDMGR_FLAGOUTSTATUS0_REG);
+
+       debug("%s: F2SDRAM_SIDEBAND_FLAGOUTSTATUS0: 0x%x\n", __func__, reg);
+
+       if ((reg & mask) == SIDEBANDMGR_FLAGOUTSET0_REG_INTERLEAVING)
+               debug("%s: Interleaving bit is set\n", __func__);
+       else if ((reg & mask) == SIDEBANDMGR_FLAGOUTSET0_REG_MULTICHANNEL)
+               debug("%s: Multichannel bit is set\n", __func__);
+       else
+               ret = -EINVAL;
+
+       return ret;
+}
+
+bool hps_ocram_dbe_status(void)
+{
+       u32 reg = readl(socfpga_get_sysmgr_addr() +
+                       SYSMGR_SOC64_BOOT_SCRATCH_COLD8);
+
+       if (reg & ALT_SYSMGR_SCRATCH_REG_8_OCRAM_DBE_MASK)
+               return true;
+
+       return false;
+}
+
+bool ddr_ecc_dbe_status(void)
+{
+       u32 reg = readl(socfpga_get_sysmgr_addr() +
+                       SYSMGR_SOC64_BOOT_SCRATCH_COLD8);
+
+       if (reg & ALT_SYSMGR_SCRATCH_REG_8_DDR_DBE_MASK)
+               return true;
+
+       return false;
+}
+
+int sdram_mmr_init_full(struct udevice *dev)
+{
+       int i, ret = 0;
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+       struct altera_sdram_priv *priv = dev_get_priv(dev);
+       struct io96b_info *io96b_ctrl = malloc(sizeof(*io96b_ctrl));
+       struct uib_info *uib_ctrl = malloc(sizeof(*uib_ctrl));
+       struct bd_info bd = {0};
+       bool full_mem_init = false, is_ddr_hang_be4_rst = false;
+       phys_size_t hw_size;
+       u32 reg = readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
+       enum reset_type reset_t = get_reset_type(reg);
+
+       /* Populating DDR handoff data */
+       debug("DDR: Populating DDR handoff\n");
+
+       ret = populate_ddr_handoff(dev, io96b_ctrl, uib_ctrl);
+       if (ret) {
+               printf("DDR: Failed to populate DDR handoff\n");
+
+               goto err;
+       }
+
+       debug("%s: Address MPFE 0x%llx\n", memory_type_in_use(dev), plat->mpfe_base_addr);
+
+       /* DDR initialization progress status tracking */
+       is_ddr_hang_be4_rst = is_ddr_init_hang();
+
+       printf("%s: SDRAM init in progress ...\n", memory_type_in_use(dev));
+
+       ddr_init_inprogress(true);
+
+       /* Configuring MPFE sideband manager registers - multichannel or interleaving*/
+       debug("%s: MPFE configuration in progress ...\n", memory_type_in_use(dev));
+
+       ret = config_mpfe_sideband_mgr(dev);
+       if (ret) {
+               printf("%s: Failed to configure multichannel/interleaving mode\n",
+                      memory_type_in_use(dev));
+
+               goto err;
+       }
+
+       debug("%s: MPFE configuration completed\n", memory_type_in_use(dev));
+
+       debug("%s: Waiting for NOCPLL locked ...\n", memory_type_in_use(dev));
+
+       /* Ensure NOCPLL locked */
+       ret = wait_for_bit_le32((const void *)socfpga_get_sysmgr_addr() + SYSMGR_HMC_CLK
+                               , SYSMGR_HMC_CLK_NOCPLL, true, TIMEOUT, false);
+       if (ret) {
+               printf("%s: NOCPLL is not locked\n", memory_type_in_use(dev));
+
+               goto err;
+       }
+
+       debug("%s: NOCPLL locked\n", memory_type_in_use(dev));
+
+       debug("%s: Checking calibration...\n", memory_type_in_use(dev));
+
+       if (is_ddr_in_use(dev)) {
+               /* Configure if polling is needed for IO96B GEN PLL locked */
+               io96b_ctrl->ckgen_lock = false;
+
+               /* Ensure calibration status passing */
+               init_mem_cal(io96b_ctrl);
+
+               printf("DDR: Calibration success\n");
+
+               /* Initiate IOSSM mailbox */
+               io96b_mb_init(io96b_ctrl);
+
+               /* DDR type */
+               ret = get_mem_technology(io96b_ctrl);
+               if (ret) {
+                       printf("DDR: Failed to get DDR type\n");
+
+                       goto err;
+               }
+
+               /* DDR size */
+               ret = get_mem_width_info(io96b_ctrl);
+               if (ret) {
+                       printf("DDR: Failed to get DDR size\n");
+
+                       goto err;
+               }
+       } else {
+               /* Ensure calibration status passing */
+               uib_init_mem_cal(uib_ctrl);
+
+               /* Need to trigger re-calibration for HBM DBE */
+               if (ddr_ecc_dbe_status()) {
+                       for (i = 0; i < uib_ctrl->num_instance; i++)
+                               uib_ctrl->uib[i].cal_status = false;
+
+                       uib_ctrl->overall_cal_status = false;
+               }
+
+               /* Trigger re-calibration if calibration failed */
+               if (!(uib_ctrl->overall_cal_status)) {
+                       printf("HBM: Re-calibration in progress...\n");
+
+                       uib_trig_mem_cal(uib_ctrl);
+               }
+
+               if (!(uib_ctrl->overall_cal_status)) {
+                       printf("HBM: Retry calibration failed & not able to re-calibrate\n");
+
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               debug("HBM: Setting Error Mask Register\n");
+
+               /* Responder Error Mask Register */
+               for (i = 0; i < uib_ctrl->num_instance; i++) {
+                       clrsetbits_le32(uib_ctrl->uib[i].uib_csr_addr +
+                                       UIB_R_ERRMSK_PSEUDO_CH0_OFFSET,
+                                       UIB_DRAM_SBE_MSK | UIB_INTERNAL_CORR_ERR_MSK,
+                                       UIB_DRAM_SBE(0x1) | UIB_INTERNAL_CORR_ERR(0x1));
+
+                       debug("HBM: Error Mask Pseudo CH0 addr: 0x%llx\n",
+                             uib_ctrl->uib[i].uib_csr_addr +
+                             UIB_R_ERRMSK_PSEUDO_CH0_OFFSET);
+
+                       debug("HBM: Error Mask Pseudo CH0 value: 0x%x\n",
+                             readl(uib_ctrl->uib[i].uib_csr_addr +
+                             UIB_R_ERRMSK_PSEUDO_CH0_OFFSET));
+
+                       clrsetbits_le32(uib_ctrl->uib[i].uib_csr_addr +
+                                       UIB_R_ERRMSK_PSEUDO_CH1_OFFSET,
+                                       UIB_DRAM_SBE_MSK | UIB_INTERNAL_CORR_ERR_MSK,
+                                       UIB_DRAM_SBE(0x1) | UIB_INTERNAL_CORR_ERR(0x1));
+
+                       debug("HBM: Error Mask Pseudo CH1 addr: 0x%llx\n",
+                             uib_ctrl->uib[i].uib_csr_addr +
+                             UIB_R_ERRMSK_PSEUDO_CH1_OFFSET);
+
+                       debug("HBM: Error Mask Pseudo CH1 value: 0x%x\n\n",
+                             readl(uib_ctrl->uib[i].uib_csr_addr +
+                             UIB_R_ERRMSK_PSEUDO_CH1_OFFSET));
+               }
+
+               printf("HBM: Calibration success\n");
+       }
+
+       /* Get bank configuration from devicetree */
+       ret = fdtdec_decode_ram_size(gd->fdt_blob, NULL, 0, NULL,
+                                    (phys_size_t *)&gd->ram_size, &bd);
+       if (ret) {
+               printf("%s: Failed to decode memory node\n", memory_type_in_use(dev));
+
+               goto err;
+       }
+
+       if (!is_ddr_in_use(dev)) {
+               hw_size = uib_ctrl->overall_size;
+       } else {
+               /* ECC status */
+               ret = ecc_enable_status(io96b_ctrl);
+               if (ret) {
+                       printf("DDR: Failed to get DDR ECC status\n");
+
+                       goto err;
+               }
+
+               hw_size = io96b_ctrl->overall_size;
+
+               if (io96b_ctrl->inline_ecc)
+                       hw_size = CALC_INLINE_ECC_HW_SIZE(hw_size);
+       }
+
+       if (gd->ram_size != hw_size) {
+               printf("%s: Warning: DRAM size from device tree (%lld MiB)\n",
+                      memory_type_in_use(dev), gd->ram_size >> 20);
+               printf(" mismatch with hardware (%lld MiB).\n",
+                      hw_size >> 20);
+       }
+
+       if (gd->ram_size > hw_size) {
+               printf("%s: Error: DRAM size from device tree is greater\n",
+                      memory_type_in_use(dev));
+               printf(" than hardware size.\n");
+
+               hang();
+       }
+
+       printf("%s: %lld MiB\n", (is_ddr_in_use(dev) ? io96b_ctrl->ddr_type : "HBM"),
+              gd->ram_size >> 20);
+
+       if (is_ddr_in_use(dev)) {
+               /*
+                * Is HPS cold or warm reset? If yes, Skip full memory initialization if ECC
+                * enabled to preserve memory content
+                */
+               if (io96b_ctrl->ecc_status) {
+                       if (ecc_interrupt_status(io96b_ctrl)) {
+                               if (CONFIG_IS_ENABLED(WDT)) {
+                                       struct udevice *wdt;
+
+                                       printf("DDR: ECC error recover start now\n");
+                                       ret = uclass_first_device_err(UCLASS_WDT, &wdt);
+                                       if (ret) {
+                                               printf("DDR: Failed to trigger watchdog reset\n");
+                                               hang();
+                                       }
+
+                                       wdt_expire_now(wdt, 0);
+                               }
+                               hang();
+                       }
+
+                       full_mem_init = hps_ocram_dbe_status() | is_ddr_hang_be4_rst;
+                       if (full_mem_init || !(reset_t == WARM_RESET || reset_t == COLD_RESET)) {
+                               debug("%s: Needed to fully initialize DDR memory\n",
+                                     io96b_ctrl->ddr_type);
+
+                               ret = bist_mem_init_start(io96b_ctrl);
+                               if (ret) {
+                                       printf("%s: Failed to fully initialize DDR memory\n",
+                                              io96b_ctrl->ddr_type);
+
+                                       goto err;
+                               }
+                       }
+               }
+       } else {
+               debug("HBM: ECC enable status: %d\n", uib_ctrl->ecc_status);
+
+               /*
+                * Is HPS cold or warm reset? If yes, Skip full memory initialization if ECC
+                * enabled to preserve memory content
+                */
+               if (uib_ctrl->ecc_status) {
+                       full_mem_init = hps_ocram_dbe_status() | ddr_ecc_dbe_status() |
+                                       is_ddr_hang_be4_rst;
+                       if (full_mem_init || !(reset_t == WARM_RESET || reset_t == COLD_RESET)) {
+                               debug("HBM: Needed to fully initialize HBM memory\n");
+
+                               ret = uib_bist_mem_init_start(uib_ctrl);
+                               if (ret) {
+                                       printf("HBM: Failed to fully initialize HBM memory\n");
+
+                                       goto err;
+                               }
+                       }
+               }
+       }
+
+       /* Ensure sanity memory test passing */
+       sdram_size_check(&bd);
+       printf("%s: size check success\n", (is_ddr_in_use(dev) ? io96b_ctrl->ddr_type : "HBM"));
+
+       sdram_set_firewall(&bd);
+
+       printf("%s: firewall init success\n", (is_ddr_in_use(dev) ? io96b_ctrl->ddr_type : "HBM"));
+
+       priv->info.base = bd.bi_dram[0].start;
+       priv->info.size = gd->ram_size;
+
+       /* Ending DDR driver initialization success tracking */
+       ddr_init_inprogress(false);
+
+       printf("%s init success\n", (is_ddr_in_use(dev) ? io96b_ctrl->ddr_type : "HBM"));
+
+err:
+       free(io96b_ctrl);
+       free(uib_ctrl);
+
+       return ret;
+}
index 27fbe80ed41a8a963685cd9504b2d98bc0ca06c2..81cb79f35a9ae5f1ed3d808ad6e34b3112be51a3 100644 (file)
@@ -29,7 +29,7 @@
 
 #define PGTABLE_OFF    0x4000
 
-#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
+#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) && !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7M)
 u32 hmc_readl(struct altera_sdram_plat *plat, u32 reg)
 {
        return readl(plat->iomhc + reg);
@@ -398,7 +398,7 @@ static int altera_sdram_of_to_plat(struct udevice *dev)
        /* These regs info are part of DDR handoff in bitstream */
 #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
        return 0;
-#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) || IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7M)
        addr = dev_read_addr_index(dev, 0);
        if (addr == FDT_ADDR_T_NONE)
                return -EINVAL;
@@ -467,6 +467,7 @@ static const struct udevice_id altera_sdram_ids[] = {
        { .compatible = "intel,sdr-ctl-agilex" },
        { .compatible = "intel,sdr-ctl-n5x" },
        { .compatible = "intel,sdr-ctl-agilex5" },
+       { .compatible = "intel,sdr-ctl-agilex7m" },
        { /* sentinel */ }
 };
 
index 4c1205b63b6796cec2ba04bd8303493c7efe8b40..6783deadc26453c2f6adfcd2f0451c375f5854db 100644 (file)
@@ -21,6 +21,17 @@ struct altera_sdram_plat {
        bool dualport;
        bool dualemif;
 };
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7M)
+enum memory_type {
+       DDR_MEMORY = 0,
+       HBM_MEMORY
+};
+
+struct altera_sdram_plat {
+       fdt_addr_t mpfe_base_addr;
+       bool multichannel_interleaving;
+       enum memory_type mem_type;
+};
 #else
 struct altera_sdram_plat {
        void __iomem *hmc;