This is for new platform enablement for agilex5.
Add new ddr and iossm mailbox files for new platform.Add

Signed-off-by: Jit Loon Lim <jit.loon....@intel.com>
---
 drivers/ddr/altera/Makefile        |   5 +-
 drivers/ddr/altera/iossm_mailbox.c | 786 +++++++++++++++++++++++++++++
 drivers/ddr/altera/iossm_mailbox.h | 141 ++++++
 drivers/ddr/altera/sdram_agilex5.c | 329 ++++++++++++
 drivers/ddr/altera/sdram_soc64.c   |  78 ++-
 drivers/ddr/altera/sdram_soc64.h   |  17 +-
 6 files changed, 1345 insertions(+), 11 deletions(-)
 create mode 100644 drivers/ddr/altera/iossm_mailbox.c
 create mode 100644 drivers/ddr/altera/iossm_mailbox.h
 create mode 100644 drivers/ddr/altera/sdram_agilex5.c

diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile
index 9fa5d85a27..fa6c880b39 100644
--- a/drivers/ddr/altera/Makefile
+++ b/drivers/ddr/altera/Makefile
@@ -7,9 +7,10 @@
 # Copyright (C) 2014-2021 Altera Corporation <www.altera.com>
 
 ifdef CONFIG_$(SPL_)ALTERA_SDRAM
-obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram_gen5.o sequencer.o
-obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += sdram_arria10.o
+obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram_soc32.o sdram_gen5.o sequencer.o
+obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += sdram_soc32.o sdram_arria10.o
 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
 endif
diff --git a/drivers/ddr/altera/iossm_mailbox.c 
b/drivers/ddr/altera/iossm_mailbox.c
new file mode 100644
index 0000000000..c7ceed7c45
--- /dev/null
+++ b/drivers/ddr/altera/iossm_mailbox.c
@@ -0,0 +1,786 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Intel Corporation <www.intel.com>
+ *
+ */
+
+#define DEBUG
+#include <common.h>
+#include <hang.h>
+#include <asm/io.h>
+#include "iossm_mailbox.h"
+#include <wait_bit.h>
+
+/* supported DDR type list */
+static const char *ddr_type_list[7] = {
+               "DDR4", "DDR5", "DDR5_RDIMM", "LPDDR4", "LPDDR5", "QDRIV", 
"UNKNOWN"
+};
+
+/* Mailbox request function
+ * This function will send the request to IOSSM mailbox and wait for response 
return
+ *
+ * @io96b_csr_addr: CSR address for the target IO96B
+ * @ip_type:       IP type for the specified memory interface
+ * @instance_id:    IP instance ID for the specified memory interface
+ * @usr_cmd_type:   User desire IOSSM mailbox command type
+ * @usr_cmd_opcode: User desire IOSSM mailbox command opcode
+ * @cmd_param_*:    Parameters (if applicable) for the requested IOSSM mailbox 
command
+ * @resp_data_len:  User desire extra response data fields other than
+ *                                     CMD_RESPONSE_DATA_SHORT field on 
CMD_RESPONSE_STATUS
+ * @resp:                      Structure contain responses returned from the 
requested IOSSM
+ *                                     mailbox command
+ */
+int io96b_mb_req(phys_addr_t io96b_csr_addr, u32 ip_type, u32 instance_id
+                                       , u32 usr_cmd_type, u32 usr_cmd_opcode, 
u32 cmd_param_0
+                                       , u32 cmd_param_1, u32 cmd_param_2, u32 
cmd_param_3
+                                       , u32 cmd_param_4, u32 cmd_param_5, u32 
cmd_param_6
+                                       , u32 resp_data_len, struct 
io96b_mb_resp *resp)
+{
+       int i;
+       int ret;
+       u32 cmd_req, cmd_resp;
+
+       /* Initialized zeros for responses*/
+       resp->cmd_resp_status = 0;
+       resp->cmd_resp_data_0 = 0;
+       resp->cmd_resp_data_1 = 0;
+       resp->cmd_resp_data_2 = 0;
+
+       /* Ensure CMD_REQ is cleared before write any command request */
+       ret = wait_for_bit_le32((const void *)(io96b_csr_addr + 
IOSSM_CMD_REQ_OFFSET)
+                               , GENMASK(31, 0), 0, TIMEOUT, false);
+
+       if (ret) {
+               printf("%s: CMD_REQ not ready\n", __func__);
+               return -1;
+       }
+
+       /* Write CMD_PARAM_* */
+       for (i = 0; i < 6 ; i++) {
+               switch (i) {
+               case 0:
+                       if (cmd_param_0)
+                               writel(cmd_param_0, io96b_csr_addr + 
IOSSM_CMD_PARAM_0_OFFSET);
+                       break;
+               case 1:
+                       if (cmd_param_1)
+                               writel(cmd_param_1, io96b_csr_addr + 
IOSSM_CMD_PARAM_1_OFFSET);
+                       break;
+               case 2:
+                       if (cmd_param_2)
+                               writel(cmd_param_2, io96b_csr_addr + 
IOSSM_CMD_PARAM_2_OFFSET);
+                       break;
+               case 3:
+                       if (cmd_param_3)
+                               writel(cmd_param_3, io96b_csr_addr + 
IOSSM_CMD_PARAM_3_OFFSET);
+                       break;
+               case 4:
+                       if (cmd_param_4)
+                               writel(cmd_param_4, io96b_csr_addr + 
IOSSM_CMD_PARAM_4_OFFSET);
+                       break;
+               case 5:
+                       if (cmd_param_5)
+                               writel(cmd_param_5, io96b_csr_addr + 
IOSSM_CMD_PARAM_5_OFFSET);
+                       break;
+               case 6:
+                       if (cmd_param_6)
+                               writel(cmd_param_6, io96b_csr_addr + 
IOSSM_CMD_PARAM_6_OFFSET);
+                       break;
+               default:
+                       printf("%s: Invalid command parameter\n", __func__);
+               }
+       }
+
+       /* Write CMD_REQ (IP_TYPE, IP_INSTANCE_ID, CMD_TYPE and CMD_OPCODE) */
+       cmd_req = (usr_cmd_opcode << 0) | (usr_cmd_type << 16) | (instance_id 
<< 24) |
+                               (ip_type << 29);
+       writel(cmd_req, io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
+       debug("%s: Write 0x%x to IOSSM_CMD_REQ_OFFSET 0x%llx\n", __func__, 
cmd_req
+               , io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
+
+       /* Read CMD_RESPONSE_READY in CMD_RESPONSE_STATUS*/
+       ret = wait_for_bit_le32((const void *)(io96b_csr_addr +
+                       IOSSM_CMD_RESPONSE_STATUS_OFFSET), 
IOSSM_STATUS_COMMAND_RESPONSE_READY, 1,
+                       TIMEOUT, false);
+
+       if (ret) {
+               printf("%s: CMD_RESPONSE ERROR:\n", __func__);
+               cmd_resp = readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+               printf("%s: STATUS_GENERAL_ERROR: 0x%x\n", __func__, (cmd_resp 
>> 1) & 0xF);
+               printf("%s: STATUS_CMD_RESPONSE_ERROR: 0x%x\n", __func__, 
(cmd_resp >> 5) & 0x7);
+       }
+
+       /* read CMD_RESPONSE_STATUS*/
+       resp->cmd_resp_status = readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+       debug("%s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n", __func__, 
io96b_csr_addr +
+               IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+       /* read CMD_RESPONSE_DATA_* */
+       for (i = 0; i < resp_data_len; i++) {
+               switch (i) {
+               case 0:
+                       resp->cmd_resp_data_0 =
+                                       readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_DATA_0_OFFSET);
+                       debug("%s: IOSSM_CMD_RESPONSE_DATA_0_OFFSET 0x%llx: 
0x%x\n", __func__
+                               , io96b_csr_addr + 
IOSSM_CMD_RESPONSE_DATA_0_OFFSET,
+                               resp->cmd_resp_data_0);
+                       break;
+               case 1:
+                       resp->cmd_resp_data_1 =
+                                       readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_DATA_1_OFFSET);
+                       debug("%s: IOSSM_CMD_RESPONSE_DATA_1_OFFSET 0x%llx: 
0x%x\n", __func__
+                               , io96b_csr_addr + 
IOSSM_CMD_RESPONSE_DATA_1_OFFSET,
+                               resp->cmd_resp_data_1);
+                       break;
+               case 2:
+                       resp->cmd_resp_data_2 =
+                                       readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_DATA_2_OFFSET);
+                       debug("%s: IOSSM_CMD_RESPONSE_DATA_2_OFFSET 0x%llx: 
0x%x\n", __func__
+                               , io96b_csr_addr + 
IOSSM_CMD_RESPONSE_DATA_2_OFFSET,
+                               resp->cmd_resp_data_2);
+                       break;
+               default:
+                       printf("%s: Invalid response data\n", __func__);
+               }
+       }
+
+       resp->cmd_resp_status = readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+       debug("%s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n", __func__, 
io96b_csr_addr +
+               IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+       /* write CMD_RESPONSE_READY = 0 */
+       clrbits_le32((u32 *)(uintptr_t)(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_STATUS_OFFSET)
+                                       , IOSSM_STATUS_COMMAND_RESPONSE_READY);
+
+       resp->cmd_resp_status = readl(io96b_csr_addr + 
IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+       debug("%s: CMD_RESPONSE_READY 0x%llx: 0x%x\n", __func__, io96b_csr_addr 
+
+               IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+       return 0;
+}
+
+/*
+ * Initial function to be called to set memory interface IP type and instance 
ID
+ * IP type and instance ID need to be determined before sending mailbox command
+ */
+void io96b_mb_init(struct io96b_info *io96b_ctrl)
+{
+       struct io96b_mb_resp usr_resp;
+       u8 ip_type_ret, instance_id_ret;
+       int i, j, k;
+
+       debug("%s: num_instance %d\n", __func__, io96b_ctrl->num_instance);
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               debug("%s: get memory interface IO96B %d\n", __func__, i);
+               switch (i) {
+               case 0:
+                       /* Get memory interface IP type & instance ID (IP 
identifier) */
+                       io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0
+                                       , CMD_GET_SYS_INFO, GET_MEM_INTF_INFO
+                                       , 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+                       debug("%s: get response from memory interface IO96B 
%d\n", __func__, i);
+                       /* Retrieve number of memory interface(s) */
+                       io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface =
+                               
IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
+
+                       /* Retrieve memory interface IP type and instance ID 
(IP identifier) */
+                       j = 0;
+                       for (k = 0; k < MAX_MEM_INTERFACES_SUPPORTED; k++) {
+                               switch (k) {
+                               case 0:
+                                       ip_type_ret = (usr_resp.cmd_resp_data_0 
>> 29) & 0x7;
+                                       instance_id_ret = 
(usr_resp.cmd_resp_data_0 >> 24) & 0x1F;
+                                       break;
+                               case 1:
+                                       ip_type_ret = (usr_resp.cmd_resp_data_1 
>> 29) & 0x7;
+                                       instance_id_ret = 
(usr_resp.cmd_resp_data_1 >> 24) & 0x1F;
+                                       break;
+                               }
+
+                               if (ip_type_ret) {
+                                       io96b_ctrl->io96b_0.mb_ctrl.ip_type[j] 
= ip_type_ret;
+                                       
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j] =
+                                               instance_id_ret;
+                                       j++;
+                               }
+                       }
+                       break;
+               case 1:
+                       /* Get memory interface IP type and instance ID (IP 
identifier) */
+                       io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0, 
CMD_GET_SYS_INFO
+                                       , GET_MEM_INTF_INFO, 0, 0, 0, 0, 0, 0, 
0, 2, &usr_resp);
+                       debug("%s: get response from memory interface IO96B 
%d\n", __func__, i);
+                       /* Retrieve number of memory interface(s) */
+                       io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface =
+                               
IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
+                       debug("%s: IO96B %d: num_mem_interface: 0x%x\n", 
__func__, i
+                               , 
io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface);
+
+                       /* Retrieve memory interface IP type and instance ID 
(IP identifier) */
+                       j = 0;
+                       for (k = 0; k < MAX_MEM_INTERFACES_SUPPORTED; k++) {
+                               switch (k) {
+                               case 0:
+                                       ip_type_ret = (usr_resp.cmd_resp_data_0 
>> 29) & 0x7;
+                                       instance_id_ret = 
(usr_resp.cmd_resp_data_0 >> 24) & 0x1F;
+                                       break;
+                               case 1:
+                                       ip_type_ret = (usr_resp.cmd_resp_data_1 
>> 29) & 0x7;
+                                       instance_id_ret = 
(usr_resp.cmd_resp_data_1 >> 24) & 0x1F;
+                                       break;
+                               }
+
+                               if (ip_type_ret) {
+                                       io96b_ctrl->io96b_1.mb_ctrl.ip_type[j] 
= ip_type_ret;
+                                       
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j] =
+                                               instance_id_ret;
+                                       j++;
+                               }
+                       }
+                       break;
+               }
+               debug("%s: IO96B %d: ip_type_ret: 0x%x\n", __func__, i, 
ip_type_ret);
+               debug("%s: IO96B %d: instance_id_ret: 0x%x\n", __func__, i, 
instance_id_ret);
+       }
+}
+
+int io96b_cal_status(phys_addr_t addr)
+{
+       int ret;
+       u32 cal_success, cal_fail;
+       phys_addr_t status_addr = addr + IOSSM_STATUS_OFFSET;
+       /* Ensure calibration completed */
+       ret = wait_for_bit_le32((const void *)status_addr, 
IOSSM_STATUS_CAL_BUSY, false
+                                                       , TIMEOUT, false);
+       if (ret) {
+               printf("%s: SDRAM calibration IO96b instance 0x%llx timeout\n", 
__func__
+                       , status_addr);
+               hang();
+       }
+
+       /* Calibration status */
+       cal_success = readl(status_addr) & IOSSM_STATUS_CAL_SUCCESS;
+       cal_fail = readl(status_addr) & IOSSM_STATUS_CAL_FAIL;
+
+       if (cal_success && !cal_fail)
+               return 0;
+       else
+               return -EPERM;
+}
+
+void init_mem_cal(struct io96b_info *io96b_ctrl)
+{
+       int count, i, ret;
+
+       /* Initialize overall calibration status */
+       io96b_ctrl->overall_cal_status = false;
+
+       /* Check initial calibration status for the assigned IO96B*/
+       count = 0;
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               switch (i) {
+               case 0:
+                       ret = 
io96b_cal_status(io96b_ctrl->io96b_0.io96b_csr_addr);
+                       if (ret) {
+                               io96b_ctrl->io96b_0.cal_status = false;
+                               printf("%s: Initial DDR calibration IO96B_0 
failed %d\n", __func__
+                                               , ret);
+                               break;
+                       }
+                       io96b_ctrl->io96b_0.cal_status = true;
+                       printf("%s: Initial DDR calibration IO96B_0 succeed\n", 
__func__);
+                       count++;
+                       break;
+               case 1:
+                       ret = 
io96b_cal_status(io96b_ctrl->io96b_1.io96b_csr_addr);
+                       if (ret) {
+                               io96b_ctrl->io96b_1.cal_status = false;
+                               printf("%s: Initial DDR calibration IO96B_1 
failed %d\n", __func__
+                                               , ret);
+                               break;
+                       }
+                       io96b_ctrl->io96b_1.cal_status = true;
+                       printf("%s: Initial DDR calibration IO96B_1 succeed\n", 
__func__);
+                       count++;
+                       break;
+               }
+       }
+
+       if (count == io96b_ctrl->num_instance)
+               io96b_ctrl->overall_cal_status = true;
+}
+
+/*
+ * Trying 3 times re-calibration if initial calibration failed
+ */
+int trig_mem_cal(struct io96b_info *io96b_ctrl)
+{
+       struct io96b_mb_resp usr_resp;
+       bool recal_success;
+       int i;
+       u8 cal_stat;
+
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               switch (i) {
+               case 0:
+                       if (!(io96b_ctrl->io96b_0.cal_status)) {
+                               /* Get the memory calibration status for first 
memory interface */
+                               
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0
+                                               , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS, 0, 0, 0
+                                               , 0, 0, 0, 0, 2, &usr_resp);
+
+                               recal_success = false;
+
+                               /* Re-calibration first memory interface with 
failed calibration */
+                               for (i = 0; i < 3; i++) {
+                                       cal_stat = usr_resp.cmd_resp_data_0 & 
GENMASK(2, 0);
+                                       if (cal_stat < 0x2) {
+                                               recal_success = true;
+                                               break;
+                                       }
+                                       
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[0]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[0]
+                                               , CMD_TRIG_MEM_CAL_OP, 
TRIG_MEM_CAL, 0, 0, 0, 0, 0
+                                               , 0, 0, 2, &usr_resp);
+
+                                       udelay(1);
+
+                                       
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0
+                                                       , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS
+                                                       , 0, 0, 0, 0, 0, 0, 0, 
2, &usr_resp);
+                               }
+
+                               if (!recal_success) {
+                                       printf("%s: Error as SDRAM calibration 
failed\n", __func__);
+                                       hang();
+                               }
+
+                               /* Get the memory calibration status for second 
memory interface */
+                               
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0
+                                               , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS, 0, 0, 0
+                                               , 0, 0, 0, 0, 2, &usr_resp);
+
+                               recal_success = false;
+
+                               /* Re-calibration second memory interface with 
failed calibration */
+                               for (i = 0; i < 3; i++) {
+                                       cal_stat = usr_resp.cmd_resp_data_1 & 
GENMASK(2, 0);
+                                       if (cal_stat < 0x2) {
+                                               recal_success = true;
+                                               break;
+                                       }
+                                       
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[1]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[1]
+                                               , CMD_TRIG_MEM_CAL_OP, 
TRIG_MEM_CAL, 0, 0, 0, 0, 0
+                                               , 0, 0, 2, &usr_resp);
+
+                                       udelay(1);
+
+                                       
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0
+                                                       , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS
+                                                       , 0, 0, 0, 0, 0, 0, 0, 
2, &usr_resp);
+                               }
+
+                               if (!recal_success) {
+                                       printf("%s: Error as SDRAM calibration 
failed\n", __func__);
+                                       hang();
+                               }
+
+                               io96b_ctrl->io96b_0.cal_status = true;
+                       }
+                       break;
+               case 1:
+                       if (!(io96b_ctrl->io96b_1.cal_status)) {
+                               /* Get the memory calibration status for first 
memory interface */
+                               
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0
+                                               , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS, 0, 0, 0
+                                               , 0, 0, 0, 0, 2, &usr_resp);
+
+                               recal_success = false;
+
+                               /* Re-calibration first memory interface with 
failed calibration */
+                               for (i = 0; i < 3; i++) {
+                                       cal_stat = usr_resp.cmd_resp_data_0 & 
GENMASK(2, 0);
+                                       if (cal_stat < 0x2) {
+                                               recal_success = true;
+                                               break;
+                                       }
+                                       
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[0]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[0]
+                                               , CMD_TRIG_MEM_CAL_OP, 
TRIG_MEM_CAL, 0, 0, 0, 0, 0
+                                               , 0, 0, 2, &usr_resp);
+
+                                       udelay(1);
+
+                                       
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0
+                                                       , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS
+                                                       , 0, 0, 0, 0, 0, 0, 0, 
2, &usr_resp);
+                               }
+
+                               if (!recal_success) {
+                                       printf("%s: Error as SDRAM calibration 
failed\n", __func__);
+                                       hang();
+                               }
+
+                               /* Get the memory calibration status for second 
memory interface */
+                               
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0
+                                               , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS, 0, 0, 0
+                                               , 0, 0, 0, 0, 2, &usr_resp);
+
+                               recal_success = false;
+
+                               /* Re-calibration second memory interface with 
failed calibration */
+                               for (i = 0; i < 3; i++) {
+                                       cal_stat = usr_resp.cmd_resp_data_0 & 
GENMASK(2, 0);
+                                       if (cal_stat < 0x2) {
+                                               recal_success = true;
+                                               break;
+                                       }
+                                       
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[1]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[1]
+                                               , CMD_TRIG_MEM_CAL_OP, 
TRIG_MEM_CAL, 0, 0, 0, 0, 0
+                                               , 0, 0, 2, &usr_resp);
+
+                                       udelay(1);
+
+                                       
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0
+                                                       , CMD_TRIG_MEM_CAL_OP, 
GET_MEM_CAL_STATUS
+                                                       , 0, 0, 0, 0, 0, 0, 0, 
2, &usr_resp);
+                               }
+
+                               if (!recal_success) {
+                                       printf("%s: Error as SDRAM calibration 
failed\n", __func__);
+                                       hang();
+                               }
+
+                               io96b_ctrl->io96b_1.cal_status = true;
+                       }
+                       break;
+               }
+       }
+
+       if (io96b_ctrl->io96b_0.cal_status && io96b_ctrl->io96b_1.cal_status) {
+               debug("%s: Overall SDRAM calibration success\n", __func__);
+               io96b_ctrl->overall_cal_status = true;
+       }
+
+       return 0;
+}
+
+int get_mem_technology(struct io96b_info *io96b_ctrl)
+{
+       struct io96b_mb_resp usr_resp;
+       int i, j;
+       u8 ddr_type_ret;
+
+       /* Initialize ddr type */
+       io96b_ctrl->ddr_type = ddr_type_list[6];
+
+       /* Get and ensure all memory interface(s) same DDR type */
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               switch (i) {
+               case 0:
+                       for (j = 0; j < 
io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+                               io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j]
+                                               , CMD_GET_MEM_INFO, 
GET_MEM_TECHNOLOGY, 0, 0, 0, 0
+                                               , 0, 0, 0, 0, &usr_resp);
+
+                               ddr_type_ret =
+                                       
IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                       & GENMASK(2, 0);
+
+                               if (!strcmp(io96b_ctrl->ddr_type, "UNKNOWN"))
+                                       io96b_ctrl->ddr_type = 
ddr_type_list[ddr_type_ret];
+
+                               if (ddr_type_list[ddr_type_ret] != 
io96b_ctrl->ddr_type) {
+                                       printf("%s: Mismatch DDR type on 
IO96B_0\n", __func__);
+                                       return -ENOEXEC;
+                               }
+                       }
+                       break;
+               case 1:
+                       for (j = 0; j < 
io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+                               io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j]
+                                               , CMD_GET_MEM_INFO, 
GET_MEM_TECHNOLOGY, 0, 0, 0, 0
+                                               , 0, 0, 0, 0, &usr_resp);
+
+                               ddr_type_ret =
+                                       
IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                       & GENMASK(2, 0);
+
+                               if (!strcmp(io96b_ctrl->ddr_type, "UNKNOWN"))
+                                       io96b_ctrl->ddr_type = 
ddr_type_list[ddr_type_ret];
+
+                               if (ddr_type_list[ddr_type_ret] != 
io96b_ctrl->ddr_type) {
+                                       printf("%s: Mismatch DDR type on 
IO96B_1\n", __func__);
+                                       return -ENOEXEC;
+                               }
+                       }
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+int get_mem_width_info(struct io96b_info *io96b_ctrl)
+{
+       struct io96b_mb_resp usr_resp;
+       int i, j;
+       u16 memory_size;
+       u16 total_memory_size = 0;
+
+       /* Get all memory interface(s) total memory size on all instance(s) */
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               switch (i) {
+               case 0:
+                       memory_size = 0;
+                       for (j = 0; j < 
io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+                               io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j]
+                                               , CMD_GET_MEM_INFO, 
GET_MEM_WIDTH_INFO, 0, 0, 0, 0
+                                               , 0, 0, 0, 2, &usr_resp);
+
+                               memory_size = memory_size +
+                                               (usr_resp.cmd_resp_data_1 & 
GENMASK(7, 0));
+                       }
+
+                       if (!memory_size) {
+                               printf("%s: Failed to get valid memory size\n", 
__func__);
+                               return -ENOEXEC;
+                       }
+
+                       io96b_ctrl->io96b_0.size = memory_size;
+
+                       break;
+               case 1:
+                       memory_size = 0;
+                       for (j = 0; j < 
io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+                               io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j]
+                                               , CMD_GET_MEM_INFO, 
GET_MEM_WIDTH_INFO, 0, 0, 0, 0
+                                               , 0, 0, 0, 2, &usr_resp);
+
+                               memory_size = memory_size +
+                                               (usr_resp.cmd_resp_data_1 & 
GENMASK(7, 0));
+                       }
+
+                       if (!memory_size) {
+                               printf("%s: Failed to get valid memory size\n", 
__func__);
+                               return -ENOEXEC;
+                       }
+
+                       io96b_ctrl->io96b_1.size = memory_size;
+
+                       break;
+               }
+
+               total_memory_size = total_memory_size + memory_size;
+       }
+
+       if (!total_memory_size) {
+               printf("%s: Failed to get valid memory size\n", __func__);
+               return -ENOEXEC;
+       }
+
+       io96b_ctrl->overall_size = total_memory_size;
+
+       return 0;
+}
+
+int ecc_enable_status(struct io96b_info *io96b_ctrl)
+{
+       struct io96b_mb_resp usr_resp;
+       int i, j;
+       bool ecc_stat_set = false;
+       bool ecc_stat;
+
+       /* Initialize ECC status */
+       io96b_ctrl->ecc_status = false;
+
+       /* Get and ensure all memory interface(s) same ECC status */
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               switch (i) {
+               case 0:
+                       for (j = 0; j < 
io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+                               debug("%s: ECC_ENABLE_STATUS\n", __func__);
+                               io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j]
+                                               , CMD_TRIG_CONTROLLER_OP, 
ECC_ENABLE_STATUS, 0, 0, 0
+                                               , 0, 0, 0, 0, 0, &usr_resp);
+
+                               ecc_stat = 
((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                               & GENMASK(1, 0)) == 0 ? false : 
true);
+
+                               if (!ecc_stat_set) {
+                                       io96b_ctrl->ecc_status = ecc_stat;
+                                       ecc_stat_set = true;
+                               }
+
+                               if (ecc_stat != io96b_ctrl->ecc_status) {
+                                       printf("%s: Mismatch DDR ECC status on 
IO96B_0\n"
+                                               , __func__);
+                                       return -ENOEXEC;
+                               }
+                       }
+                       break;
+               case 1:
+                       for (j = 0; j < 
io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+                               debug("%s: ECC_ENABLE_STATUS\n", __func__);
+                               io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j]
+                                               , CMD_TRIG_CONTROLLER_OP, 
ECC_ENABLE_STATUS, 0, 0, 0
+                                               , 0, 0, 0, 0, 0, &usr_resp);
+
+                               ecc_stat = 
((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                               & GENMASK(1, 0)) == 0 ? false : 
true);
+
+                               if (!ecc_stat_set) {
+                                       io96b_ctrl->ecc_status = ecc_stat;
+                                       ecc_stat_set = true;
+                               }
+
+                               if (ecc_stat != io96b_ctrl->ecc_status) {
+                                       printf("%s: Mismatch DDR ECC status on 
IO96B_1\n"
+                                               , __func__);
+                                       return -ENOEXEC;
+                               }
+                       }
+                       break;
+               }
+       }
+       return 0;
+}
+
+int bist_mem_init_start(struct io96b_info *io96b_ctrl)
+{
+       struct io96b_mb_resp usr_resp;
+       int i, j;
+       bool bist_start, bist_success;
+       u32 start;
+
+       /* Full memory initialization BIST performed on all memory interface(s) 
*/
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               switch (i) {
+               case 0:
+                       for (j = 0; j < 
io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+                               bist_start = false;
+                               bist_success = false;
+
+                               /* Start memory initialization BIST on full 
memory address */
+                               io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j]
+                                               , CMD_TRIG_CONTROLLER_OP, 
BIST_MEM_INIT_START, 0x40
+                                               , 0, 0, 0, 0, 0, 0, 0, 
&usr_resp);
+
+                               bist_start =
+                                       
(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                       & BIT(0));
+
+                               if (!bist_start) {
+                                       printf("%s: Failed to initialized 
memory on IO96B_0\n"
+                                               , __func__);
+                                       printf("%s: BIST_MEM_INIT_START Error 
code 0x%x\n", __func__
+                                       , 
(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                       & GENMASK(2, 1)) > 0x1);
+                                       return -ENOEXEC;
+                               }
+
+                               /* Polling for the initiated memory 
initialization BIST status */
+                               start = get_timer(0);
+                               while (!bist_success) {
+                                       
io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j]
+                                               , CMD_TRIG_CONTROLLER_OP, 
BIST_MEM_INIT_STATUS, 0
+                                               , 0, 0, 0, 0, 0, 0, 0, 
&usr_resp);
+
+                                       bist_success = 
(IOSSM_CMD_RESPONSE_DATA_SHORT
+                                                       
(usr_resp.cmd_resp_status) & BIT(0));
+
+                                       if (!bist_success && (get_timer(start) 
> TIMEOUT)) {
+                                               printf("%s: Timeout initialize 
memory on IO96B_0\n"
+                                                       , __func__);
+                                               printf("%s: 
BIST_MEM_INIT_STATUS Error code 0x%x\n"
+                                                       , __func__, 
(IOSSM_CMD_RESPONSE_DATA_SHORT
+                                                       
(usr_resp.cmd_resp_status)
+                                                       & GENMASK(2, 1)) > 0x1);
+                                               return -ETIMEDOUT;
+                                       }
+
+                                       udelay(1);
+                               }
+                       }
+
+                       debug("%s: Memory initialized successfully on 
IO96B_0\n", __func__);
+                       break;
+               case 1:
+                       for (j = 0; j < 
io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+                               bist_start = false;
+                               bist_success = false;
+
+                               /* Start memory initialization BIST on full 
memory address */
+                               io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j]
+                                               , CMD_TRIG_CONTROLLER_OP, 
BIST_MEM_INIT_START, 0x40
+                                               , 0, 0, 0, 0, 0, 0, 0, 
&usr_resp);
+
+                               bist_start =
+                                       
(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                       & BIT(0));
+
+                               if (!bist_start) {
+                                       printf("%s: Failed to initialized 
memory on IO96B_1\n"
+                                               , __func__);
+                                       printf("%s: BIST_MEM_INIT_START Error 
code 0x%x\n", __func__
+                                       , 
(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+                                       & GENMASK(2, 1)) > 0x1);
+                                       return -ENOEXEC;
+                               }
+
+                               /* Polling for the initiated memory 
initialization BIST status */
+                               start = get_timer(0);
+                               while (!bist_success) {
+                                       
io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_type[j]
+                                               , 
io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j]
+                                               , CMD_TRIG_CONTROLLER_OP, 
BIST_MEM_INIT_STATUS, 0
+                                               , 0, 0, 0, 0, 0, 0, 0, 
&usr_resp);
+
+                                       bist_success = 
(IOSSM_CMD_RESPONSE_DATA_SHORT
+                                                       
(usr_resp.cmd_resp_status) & BIT(0));
+
+                                       if (!bist_success && (get_timer(start) 
> TIMEOUT)) {
+                                               printf("%s: Timeout initialize 
memory on IO96B_1\n"
+                                                       , __func__);
+                                               printf("%s: 
BIST_MEM_INIT_STATUS Error code 0x%x\n"
+                                                       , __func__, 
(IOSSM_CMD_RESPONSE_DATA_SHORT
+                                                       
(usr_resp.cmd_resp_status)
+                                                       & GENMASK(2, 1)) > 0x1);
+                                               return -ETIMEDOUT;
+                                       }
+
+                                       udelay(1);
+                               }
+                       }
+
+                       debug("%s: Memory initialized successfully on 
IO96B_1\n", __func__);
+                       break;
+               }
+       }
+       return 0;
+}
diff --git a/drivers/ddr/altera/iossm_mailbox.h 
b/drivers/ddr/altera/iossm_mailbox.h
new file mode 100644
index 0000000000..8c57126c3e
--- /dev/null
+++ b/drivers/ddr/altera/iossm_mailbox.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Intel Corporation <www.intel.com>
+ */
+
+#define TIMEOUT_10000MS                        10000
+#define TIMEOUT                                TIMEOUT_10000MS
+#define IOSSM_STATUS_CAL_SUCCESS       BIT(0)
+#define IOSSM_STATUS_CAL_FAIL          BIT(1)
+#define IOSSM_STATUS_CAL_BUSY          BIT(2)
+#define IOSSM_STATUS_COMMAND_RESPONSE_READY    BIT(0)
+#define IOSSM_CMD_RESPONSE_STATUS_OFFSET       0x45C
+#define IOSSM_CMD_RESPONSE_DATA_0_OFFSET       0x458
+#define IOSSM_CMD_RESPONSE_DATA_1_OFFSET       0x454
+#define IOSSM_CMD_RESPONSE_DATA_2_OFFSET       0x450
+#define IOSSM_CMD_REQ_OFFSET                   0x43C
+#define IOSSM_CMD_PARAM_0_OFFSET               0x438
+#define IOSSM_CMD_PARAM_1_OFFSET               0x434
+#define IOSSM_CMD_PARAM_2_OFFSET               0x430
+#define IOSSM_CMD_PARAM_3_OFFSET               0x42C
+#define IOSSM_CMD_PARAM_4_OFFSET               0x428
+#define IOSSM_CMD_PARAM_5_OFFSET               0x424
+#define IOSSM_CMD_PARAM_6_OFFSET               0x420
+#define IOSSM_STATUS_OFFSET                    0x400
+#define IOSSM_CMD_RESPONSE_DATA_SHORT_MASK     GENMASK(31, 16)
+#define IOSSM_CMD_RESPONSE_DATA_SHORT(data) (((data) & 
IOSSM_CMD_RESPONSE_DATA_SHORT_MASK) >> 16)
+#define MAX_IO96B_SUPPORTED            2
+#define MAX_MEM_INTERFACES_SUPPORTED   2
+
+/* supported mailbox command type */
+enum iossm_mailbox_cmd_type  {
+       CMD_NOP,
+       CMD_GET_SYS_INFO,
+       CMD_GET_MEM_INFO,
+       CMD_GET_MEM_CAL_INFO,
+       CMD_TRIG_CONTROLLER_OP,
+       CMD_TRIG_MEM_CAL_OP
+};
+
+/* supported mailbox command opcode */
+enum iossm_mailbox_cmd_opcode  {
+       GET_MEM_INTF_INFO = 0x0001,
+       GET_MEM_TECHNOLOGY,
+       GET_MEMCLK_FREQ_KHZ,
+       GET_MEM_WIDTH_INFO,
+       ECC_ENABLE_SET = 0x0101,
+       ECC_ENABLE_STATUS,
+       ECC_INTERRUPT_STATUS,
+       ECC_INTERRUPT_ACK,
+       ECC_INTERRUPT_MASK,
+       ECC_WRITEBACK_ENABLE,
+       ECC_SCRUB_IN_PROGRESS_STATUS = 0x0201,
+       ECC_SCRUB_MODE_0_START,
+       ECC_SCRUB_MODE_1_START,
+       BIST_STANDARD_MODE_START = 0x0301,
+       BIST_RESULTS_STATUS,
+       BIST_MEM_INIT_START,
+       BIST_MEM_INIT_STATUS,
+       BIST_SET_DATA_PATTERN_UPPER,
+       BIST_SET_DATA_PATTERN_LOWER,
+       TRIG_MEM_CAL = 0x000a,
+       GET_MEM_CAL_STATUS
+};
+
+/*
+ * IOSSM mailbox required information
+ *
+ * @num_mem_interface: Number of memory interfaces instantiated
+ * @ip_type:           IP type implemented on the IO96B
+ * @ip_instance_id:    IP identifier for every IP instance implemented on the 
IO96B
+ */
+struct io96b_mb_ctrl {
+       u32 num_mem_interface;
+       u32 ip_type[2];
+       u32 ip_instance_id[2];
+};
+
+/*
+ * IOSSM mailbox response outputs
+ *
+ * @cmd_resp_status: Command Interface status
+ * @cmd_resp_data_*: More spaces for command response
+ */
+struct io96b_mb_resp {
+       u32 cmd_resp_status;
+       u32 cmd_resp_data_0;
+       u32 cmd_resp_data_1;
+       u32 cmd_resp_data_2;
+};
+
+/*
+ * IO96B instance specific information
+ *
+ * @size:              Memory size
+ * @io96b_csr_addr:    IO96B instance CSR address
+ * @cal_status:                IO96B instance calibration status
+ * @mb_ctrl:           IOSSM mailbox required information
+ */
+struct io96b_instance {
+       u16 size;
+       phys_addr_t io96b_csr_addr;
+       bool cal_status;
+       struct io96b_mb_ctrl mb_ctrl;
+};
+
+/*
+ * Overall IO96B instance(s) information
+ *
+ * @num_instance:      Number of instance(s) assigned to HPS
+ * @overall_cal_status: Overall calibration status for all IO96B instance(s)
+ * @ddr_type:          DDR memory type
+ * @ecc_status:                ECC enable status (false = disabled, true = 
enabled)
+ * @overall_size:      Total DDR memory size
+ * @io96b_0:           IO96B 0 instance specific information
+ * @io96b_1:           IO96B 1 instance specific information
+ */
+struct io96b_info {
+       u8 num_instance;
+       bool overall_cal_status;
+       const char *ddr_type;
+       bool ecc_status;
+       u16 overall_size;
+       struct io96b_instance io96b_0;
+       struct io96b_instance io96b_1;
+};
+
+int io96b_mb_req(phys_addr_t io96b_csr_addr, u32 ip_type, u32 instance_id
+                       , u32 usr_cmd_type, u32 usr_cmd_opcode, u32 cmd_param_0
+                       , u32 cmd_param_1, u32 cmd_param_2, u32 cmd_param_3, 
u32 cmd_param_4
+                       , u32 cmd_param_5, u32 cmd_param_6, u32 resp_data_len
+                       , struct io96b_mb_resp *resp);
+
+/* Supported IOSSM mailbox function */
+void io96b_mb_init(struct io96b_info *io96b_ctrl);
+int io96b_cal_status(phys_addr_t addr);
+void init_mem_cal(struct io96b_info *io96b_ctrl);
+int trig_mem_cal(struct io96b_info *io96b_ctrl);
+int get_mem_technology(struct io96b_info *io96b_ctrl);
+int get_mem_width_info(struct io96b_info *io96b_ctrl);
+int ecc_enable_status(struct io96b_info *io96b_ctrl);
+int bist_mem_init_start(struct io96b_info *io96b_ctrl);
diff --git a/drivers/ddr/altera/sdram_agilex5.c 
b/drivers/ddr/altera/sdram_agilex5.c
new file mode 100644
index 0000000000..e8e3f258b9
--- /dev/null
+++ b/drivers/ddr/altera/sdram_agilex5.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2023 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <div64.h>
+#include <fdtdec.h>
+#include <hang.h>
+#include <log.h>
+#include <ram.h>
+#include <reset.h>
+#include <asm/global_data.h>
+#include "iossm_mailbox.h"
+#include "sdram_soc64.h"
+#include <wait_bit.h>
+#include <asm/arch/firewall.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* 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
+
+/* Reset type */
+enum reset_type {
+       POR_RESET,
+       WARM_RESET,
+       COLD_RESET,
+       NCONFIG,
+       JTAG_CONFIG,
+       RSU_RECONFIG
+};
+
+static enum reset_type get_reset_type(u32 reg)
+{
+       return (reg & ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_MASK) >>
+               ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_SHIFT;
+}
+
+int set_mpfe_config(void)
+{
+       /* Set mpfe_lite_active */
+       setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_MPFE_CONFIG, 
BIT(8));
+
+       debug("%s: mpfe_config: 0x%x\n", __func__,
+             readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_MPFE_CONFIG));
+
+       return 0;
+}
+
+bool is_ddr_init_hang(void)
+{
+       u32 reg = readl(socfpga_get_sysmgr_addr() +
+                       SYSMGR_SOC64_BOOT_SCRATCH_POR0);
+
+       if (reg & ALT_SYSMGR_SCRATCH_REG_POR_0_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_POR0,
+                               ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK);
+       else
+               clrbits_le32(socfpga_get_sysmgr_addr() +
+                               SYSMGR_SOC64_BOOT_SCRATCH_POR0,
+                               ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK);
+}
+
+int populate_ddr_handoff(struct udevice *dev, struct io96b_info *io96b_ctrl)
+{
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+       fdt_addr_t addr;
+       int i;
+       u32 len = SOC64_HANDOFF_SDRAM_LEN;
+       u32 handoff_table[len];
+
+       /* Read handoff for DDR configuration */
+       socfpga_handoff_read((void *)SOC64_HANDOFF_SDRAM, handoff_table, len);
+
+       /* Read handoff - dual port */
+       plat->dualport = handoff_table[0] & BIT(0);
+       debug("%s: dualport from handoff: 0x%x\n", __func__, plat->dualport);
+
+       /* Read handoff - dual EMIF */
+       plat->dualemif = handoff_table[0] & BIT(1);
+       debug("%s: dualemif from handoff: 0x%x\n", __func__, plat->dualemif);
+
+       if (plat->dualemif)
+               io96b_ctrl->num_instance = 2;
+       else
+               io96b_ctrl->num_instance = 1;
+
+       /* Assign IO96B CSR base address if it is valid */
+       for (i = 0; i < io96b_ctrl->num_instance; i++) {
+               addr = dev_read_addr_index(dev, i + 1);
+               if (addr == FDT_ADDR_T_NONE)
+                       return -EINVAL;
+
+               switch (i) {
+               case 0:
+                       io96b_ctrl->io96b_0.io96b_csr_addr = addr;
+                       debug("%s: IO96B 0x%llx CSR enabled\n", __func__
+                                       , io96b_ctrl->io96b_0.io96b_csr_addr);
+                       break;
+               case 1:
+                       io96b_ctrl->io96b_1.io96b_csr_addr = addr;
+                       debug("%s: IO96B 0x%llx CSR enabled\n", __func__
+                                       , io96b_ctrl->io96b_1.io96b_csr_addr);
+                       break;
+               default:
+                       printf("%s: Invalid IO96B CSR\n", __func__);
+               }
+       }
+
+       return 0;
+}
+
+int config_mpfe_sideband_mgr(struct udevice *dev)
+{
+       struct altera_sdram_plat *plat = dev_get_plat(dev);
+
+       /* Dual port setting */
+       if (plat->dualport)
+               setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(4));
+
+       /* Dual EMIF setting */
+       if (plat->dualemif) {
+               set_mpfe_config();
+               setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(5));
+       }
+
+       debug("%s: SIDEBANDMGR_FLAGOUTSTATUS0: 0x%x\n", __func__,
+             readl(SIDEBANDMGR_FLAGOUTSTATUS0_REG));
+
+       return 0;
+}
+
+bool hps_ocram_dbe_status(void)
+{
+       u32 reg = readl(socfpga_get_sysmgr_addr() +
+                       SYSMGR_SOC64_BOOT_SCRATCH_COLD3);
+
+       if (reg & ALT_SYSMGR_SCRATCH_REG_3_OCRAM_DBE_MASK)
+               return true;
+
+       return false;
+}
+
+bool ddr_ecc_dbe_status(void)
+{
+       u32 reg = readl(socfpga_get_sysmgr_addr() +
+                       SYSMGR_SOC64_BOOT_SCRATCH_COLD3);
+
+       if (reg & ALT_SYSMGR_SCRATCH_REG_3_DDR_DBE_MASK)
+               return true;
+
+       return false;
+}
+
+int sdram_mmr_init_full(struct udevice *dev)
+{
+       int ret;
+       phys_size_t hw_size;
+       struct bd_info bd = {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));
+
+       u32 reg = readl(socfpga_get_sysmgr_addr() + 
SYSMGR_SOC64_BOOT_SCRATCH_COLD3);
+       enum reset_type reset_t = get_reset_type(reg);
+       bool full_mem_init = false;
+
+       /* DDR initialization progress status tracking */
+       bool is_ddr_hang_be4_rst = is_ddr_init_hang();
+
+       debug("DDR: SDRAM init in progress ...\n");
+       ddr_init_inprogress(true);
+
+       debug("DDR: Address MPFE 0x%llx\n", plat->mpfe_base_addr);
+
+       /* Populating DDR handoff data */
+       debug("DDR: Checking SDRAM configuration in progress ...\n");
+       ret = populate_ddr_handoff(dev, io96b_ctrl);
+       if (ret) {
+               printf("DDR: Failed to populate DDR handoff\n");
+               free(io96b_ctrl);
+               return ret;
+       }
+
+       /* Configuring MPFE sideband manager registers - dual port & dual emif*/
+       ret = config_mpfe_sideband_mgr(dev);
+       if (ret) {
+               printf("DDR: Failed to configure dual port dual emif\n");
+               free(io96b_ctrl);
+               return ret;
+       }
+
+       /* Ensure calibration status passing */
+       init_mem_cal(io96b_ctrl);
+
+       /* Initiate IOSSM mailbox */
+       io96b_mb_init(io96b_ctrl);
+
+       /* Need to trigger re-calibration for DDR DBE */
+       if (ddr_ecc_dbe_status()) {
+               io96b_ctrl->io96b_0.cal_status = false;
+               io96b_ctrl->io96b_1.cal_status = false;
+               io96b_ctrl->overall_cal_status = io96b_ctrl->io96b_0.cal_status 
||
+                                                io96b_ctrl->io96b_1.cal_status;
+       }
+
+       /* Trigger re-calibration if calibration failed */
+       if (!(io96b_ctrl->overall_cal_status)) {
+               printf("DDR: Re-calibration in progress...\n");
+               trig_mem_cal(io96b_ctrl);
+       }
+
+       printf("DDR: Calibration success\n");
+
+       /* DDR type, DDR size and ECC status) */
+       ret = get_mem_technology(io96b_ctrl);
+       if (ret) {
+               printf("DDR: Failed to get DDR type\n");
+               free(io96b_ctrl);
+               return ret;
+       }
+
+       ret = get_mem_width_info(io96b_ctrl);
+       if (ret) {
+               printf("DDR: Failed to get DDR size\n");
+               free(io96b_ctrl);
+               return ret;
+       }
+
+       hw_size = (phys_size_t)io96b_ctrl->overall_size * SZ_1G / SZ_8;
+
+       /* 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) {
+               puts("DDR: Failed to decode memory node\n");
+               free(io96b_ctrl);
+               return -ENXIO;
+       }
+
+       if (gd->ram_size != hw_size) {
+               printf("DDR: Warning: DRAM size from device tree (%lld MiB)\n",
+                      gd->ram_size >> 20);
+               printf(" mismatch with hardware (%lld MiB).\n",
+                      hw_size >> 20);
+       }
+
+       if (gd->ram_size > hw_size) {
+               printf("DDR: Error: DRAM size from device tree is greater\n");
+               printf(" than hardware size.\n");
+               hang();
+       }
+
+       printf("%s: %lld MiB\n", io96b_ctrl->ddr_type, gd->ram_size >> 20);
+
+       ret = ecc_enable_status(io96b_ctrl);
+       if (ret) {
+               printf("DDR: Failed to get DDR ECC status\n");
+               free(io96b_ctrl);
+               return ret;
+       }
+
+       /* Is HPS cold or warm reset? If yes, Skip full memory initialization 
if ECC
+        *  enabled to preserve memory content
+        */
+       if (io96b_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)) {
+                       ret = bist_mem_init_start(io96b_ctrl);
+                       if (ret) {
+                               printf("DDR: Failed to fully initialize DDR 
memory\n");
+                               free(io96b_ctrl);
+                               return ret;
+                       }
+               }
+
+               printf("SDRAM-ECC: Initialized success\n");
+       }
+
+       sdram_size_check(&bd);
+       printf("DDR: size check success\n");
+
+       sdram_set_firewall(&bd);
+
+       /* Firewall setting for MPFE CSR */
+       /* IO96B0_reg */
+       writel(0x1, 0x18000d00);
+       /* IO96B1_reg */
+       writel(0x1, 0x18000d04);
+       /* noc_csr */
+       writel(0x1, 0x18000d08);
+
+       printf("DDR: firewall init success\n");
+
+       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("DDR: init success\n");
+
+       free(io96b_ctrl);
+
+       return 0;
+}
diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c
index 4716abfc9a..0fee07fcaf 100644
--- a/drivers/ddr/altera/sdram_soc64.c
+++ b/drivers/ddr/altera/sdram_soc64.c
@@ -28,6 +28,7 @@
 
 #define PGTABLE_OFF    0x4000
 
+#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
 u32 hmc_readl(struct altera_sdram_plat *plat, u32 reg)
 {
        return readl(plat->iomhc + reg);
@@ -99,8 +100,9 @@ int emif_reset(struct altera_sdram_plat *plat)
        debug("DDR: %s triggered successly\n", __func__);
        return 0;
 }
+#endif
 
-#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#if !(IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X) || 
IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5))
 int poll_hmc_clock_status(void)
 {
        return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
@@ -246,13 +248,13 @@ phys_size_t sdram_calculate_size(struct altera_sdram_plat 
*plat)
                         DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) +
                         DRAMADDRW_CFG_COL_ADDR_WIDTH(dramaddrw));
 
-       size *= (2 << (hmc_ecc_readl(plat, DDRIOCTRL) &
+       size *= ((phys_size_t)2 << (hmc_ecc_readl(plat, DDRIOCTRL) &
                        DDR_HMC_DDRIOCTRL_IOSIZE_MSK));
 
        return size;
 }
 
-void sdram_set_firewall(struct bd_info *bd)
+static void sdram_set_firewall_non_f2sdram(struct bd_info *bd)
 {
        u32 i;
        phys_size_t value;
@@ -288,7 +290,7 @@ void sdram_set_firewall(struct bd_info *bd)
                                      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT +
                                      (i * 4 * sizeof(u32)));
 
-               /* Setting non-secure MPU limit and limit extexded */
+               /* Setting non-secure MPU limit and limit extended */
                value = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
 
                lower = lower_32_bits(value);
@@ -301,7 +303,7 @@ void sdram_set_firewall(struct bd_info *bd)
                                      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT +
                                      (i * 4 * sizeof(u32)));
 
-               /* Setting non-secure Non-MPU limit and limit extexded */
+               /* Setting non-secure Non-MPU limit and limit extended */
                FW_MPU_DDR_SCR_WRITEL(lower,
                                      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT +
                                      (i * 4 * sizeof(u32)));
@@ -314,6 +316,60 @@ void sdram_set_firewall(struct bd_info *bd)
        }
 }
 
+static void sdram_set_firewall_f2sdram(struct bd_info *bd)
+{
+       u32 i;
+       phys_size_t value;
+       u32 lower, upper;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               if (!bd->bi_dram[i].size)
+                       continue;
+
+               value = bd->bi_dram[i].start;
+
+               /* Keep first 1MB of SDRAM memory region as secure region when
+                * using ATF flow, where the ATF code is located.
+                */
+               if (IS_ENABLED(CONFIG_SPL_ATF) && i == 0)
+                       value += SZ_1M;
+
+               /* Setting base and base extended */
+               lower = lower_32_bits(value);
+               upper = upper_32_bits(value);
+               FW_F2SDRAM_DDR_SCR_WRITEL(lower,
+                                         FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE +
+                                         (i * 4 * sizeof(u32)));
+               FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff,
+                                         
FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT +
+                                         (i * 4 * sizeof(u32)));
+
+               /* Setting limit and limit extended */
+               value = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
+
+               lower = lower_32_bits(value);
+               upper = upper_32_bits(value);
+
+               FW_F2SDRAM_DDR_SCR_WRITEL(lower,
+                                         FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT +
+                                         (i * 4 * sizeof(u32)));
+               FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff,
+                                         
FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT +
+                                         (i * 4 * sizeof(u32)));
+
+               FW_F2SDRAM_DDR_SCR_WRITEL(BIT(i), FW_F2SDRAM_DDR_SCR_EN_SET);
+       }
+}
+
+void sdram_set_firewall(struct bd_info *bd)
+{
+       sdram_set_firewall_non_f2sdram(bd);
+
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
+       sdram_set_firewall_f2sdram(bd);
+#endif
+}
+
 static int altera_sdram_of_to_plat(struct udevice *dev)
 {
        struct altera_sdram_plat *plat = dev_get_plat(dev);
@@ -322,7 +378,12 @@ 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;
-#endif
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
+       addr = dev_read_addr_index(dev, 0);
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+       plat->mpfe_base_addr = addr;
+#else
 
        addr = dev_read_addr_index(dev, 0);
        if (addr == FDT_ADDR_T_NONE)
@@ -338,15 +399,15 @@ static int altera_sdram_of_to_plat(struct udevice *dev)
        if (addr == FDT_ADDR_T_NONE)
                return -EINVAL;
        plat->hmc = (void __iomem *)addr;
-
+#endif
        return 0;
 }
 
 static int altera_sdram_probe(struct udevice *dev)
 {
-       int ret;
        struct altera_sdram_priv *priv = dev_get_priv(dev);
 
+       int ret;
        ret = reset_get_bulk(dev, &priv->resets);
        if (ret) {
                dev_err(dev, "Can't get reset: %d\n", ret);
@@ -385,6 +446,7 @@ static const struct udevice_id altera_sdram_ids[] = {
        { .compatible = "altr,sdr-ctl-s10" },
        { .compatible = "intel,sdr-ctl-agilex" },
        { .compatible = "intel,sdr-ctl-n5x" },
+       { .compatible = "intel,sdr-ctl-agilex5" },
        { /* sentinel */ }
 };
 
diff --git a/drivers/ddr/altera/sdram_soc64.h b/drivers/ddr/altera/sdram_soc64.h
index 07a0f9f2ae..c96025f8b1 100644
--- a/drivers/ddr/altera/sdram_soc64.h
+++ b/drivers/ddr/altera/sdram_soc64.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2017-2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2017-2022 Intel Corporation <www.intel.com>
  */
 
 #ifndef        _SDRAM_SOC64_H_
@@ -14,11 +14,20 @@ struct altera_sdram_priv {
        struct reset_ctl_bulk resets;
 };
 
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5)
+struct altera_sdram_plat {
+       fdt_addr_t mpfe_base_addr;
+       bool dualport;
+       bool dualemif;
+};
+#else
+
 struct altera_sdram_plat {
        void __iomem *hmc;
        void __iomem *ddr_sch;
        void __iomem *iomhc;
 };
+#endif
 
 /* ECC HMC registers */
 #define DDRIOCTRL                      0x8
@@ -39,6 +48,8 @@ struct altera_sdram_plat {
 #define RSTHANDSHAKESTAT               0x218
 
 #define DDR_HMC_DDRIOCTRL_IOSIZE_MSK           0x00000003
+#define DDR_HMC_DDRIOCTRL_MPFE_HMCA_DATA_RATE_MSK BIT(2)
+#define DDR_HMC_DDRIOCTRL_MPFE_HMCA_DATA_RATE_SHIFT 2
 #define DDR_HMC_DDRCALSTAT_CAL_MSK             BIT(0)
 #define DDR_HMC_ECCCTL_AWB_CNT_RST_SET_MSK     BIT(16)
 #define DDR_HMC_ECCCTL_CNT_RST_SET_MSK         BIT(8)
@@ -66,6 +77,7 @@ struct altera_sdram_plat {
 #define CTRLCFG0                       0x28
 #define CTRLCFG1                       0x2c
 #define CTRLCFG3                        0x34
+#define CTRLCFG5                        0x3c
 #define DRAMTIMING0                    0x50
 #define CALTIMING0                     0x7c
 #define CALTIMING1                     0x80
@@ -79,6 +91,9 @@ struct altera_sdram_plat {
 #define NIOSRESERVED1                  0x114
 #define NIOSRESERVED2                  0x118
 
+#define CTRLCFG3_CFG_CTRL_CMD_RATE_QUARTER     BIT(2)
+#define CTRLCFG5_CFG_CTRL_RC_EN_MASK           BIT(8)
+
 #define DRAMADDRW_CFG_COL_ADDR_WIDTH(x)                        \
        (((x) >> 0) & 0x1F)
 #define DRAMADDRW_CFG_ROW_ADDR_WIDTH(x)                        \
-- 
2.26.2


Reply via email to