From patchwork Sun Apr 23 18:11:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sin.hui.kho@intel.com X-Patchwork-Id: 1772485 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=QLJ50k4F; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Q4GYw1vVJz23s0 for ; Mon, 24 Apr 2023 04:12:04 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A0DAE8602A; Sun, 23 Apr 2023 20:11:45 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="QLJ50k4F"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 57C4485D95; Sun, 23 Apr 2023 20:11:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7816A85D95 for ; Sun, 23 Apr 2023 20:11:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sin.hui.kho@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1682273498; x=1713809498; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=i6sLVbu97WC1+HD3w2k4X10H9c4ov9s41skKNjIg0a4=; b=QLJ50k4FvhD+vTHaaYChGNQI/rMm67R9CIpBv/8ji0g6BQwA0KxeE9TY OxRZpXp2gg8MkgBBdHfbQdyuGB2ekXWkCDim20q1/7zGtvKTgCEYWj6Wv fTjqsMXd2eWUXd+N1Akb4NKby1c/z70p1qbniJNvlLQltxVM9GDkhU2Ni 6n+WFbw4Xjbw7p7I86dXVrcTnc452sjAkJWWecMjtNqugcOoWMJSSGG5m DcwoVloudjMfK7E5lGORSJLZ/T9ccspLJZthm7oAvzpOCEKWFCNwZnhpY GFraadYwhP9EodB2uLwTqjpCYNHBm8eZMXwAVJ0OoMUo95JeNsr42uN6X A==; X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="374248719" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="374248719" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2023 11:11:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="695507787" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="695507787" Received: from pglc00257.png.intel.com ([10.221.233.180]) by fmsmga007.fm.intel.com with ESMTP; 23 Apr 2023 11:11:35 -0700 From: sin.hui.kho@intel.com To: u-boot@lists.denx.de Cc: Marek Vasut , Simon Goldschmidt , Tien Fong Chee , Sin Hui Kho , Simon Glass , Stefan Roese , Dinesh Maniyam , Jit Loon Lim , Teik Heng , Kok Kiang Subject: [PATCH v1 1/5] ddr: altera: agilex7: Add SDRAM driver for AGILEX7 Date: Mon, 24 Apr 2023 02:11:20 +0800 Message-Id: <20230423181124.28077-2-sin.hui.kho@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230423181124.28077-1-sin.hui.kho@intel.com> References: <20230423181124.28077-1-sin.hui.kho@intel.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sin Hui Kho Add SDRAM driver for AGILEX7 SoC. Signed-off-by: Sin Hui Kho --- drivers/ddr/altera/Makefile | 1 + drivers/ddr/altera/sdram_agilex7.c | 331 +++++++++++++++++++++++++++++ drivers/ddr/altera/sdram_soc64.c | 15 +- drivers/ddr/altera/sdram_soc64.h | 9 +- 4 files changed, 351 insertions(+), 5 deletions(-) create mode 100644 drivers/ddr/altera/sdram_agilex7.c diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile index 9fa5d85a27..555357d669 100644 --- a/drivers/ddr/altera/Makefile +++ b/drivers/ddr/altera/Makefile @@ -12,4 +12,5 @@ obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += 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_AGILEX7) += sdram_soc64.o sdram_agilex7.o endif diff --git a/drivers/ddr/altera/sdram_agilex7.c b/drivers/ddr/altera/sdram_agilex7.c new file mode 100644 index 0000000000..d50e0899cc --- /dev/null +++ b/drivers/ddr/altera/sdram_agilex7.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Intel Corporation + * + */ + +#include +#include +#include +#include +#include +#include "iossm_mailbox.h" +#include "sdram_soc64.h" +#include +#include + +/* 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 + +/* 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_0_DDR_RESET_TYPE_MASK) >> + ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_SHIFT; +} + +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); +} + +void update_io96b_assigned_to_hps(u8 num_io96b_instance) +{ + u32 reg = readl(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_BOOT_SCRATCH_COLD8); + + writel(reg | ((num_io96b_instance << ALT_SYSMGR_SCRATCH_REG_8_IO96B_HPS_SHIFT) + & ALT_SYSMGR_SCRATCH_REG_8_IO96B_HPS_MASK), socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_BOOT_SCRATCH_COLD8); +} + +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; + 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-IO96B is in %s mode\n", __func__ + , plat->multichannel_interleaving ? "interleaving" : "multichannel"); + + /* Assign IO96B CSR base address if it is valid */ + for (i = 0; i < MAX_IO96B_SUPPORTED; i++) { + addr = dev_read_addr_index(dev, i + 1); + + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + switch (i) { + case 0: + if (handoff_table[1] & BIT(i)) { + io96b_ctrl->io96b_0.io96b_csr_addr = addr; + debug("%s: IO96B 0x%llx CSR enabled\n", __func__ + , io96b_ctrl->io96b_0.io96b_csr_addr); + count++; + } + break; + case 1: + if (handoff_table[1] & BIT(i)) { + io96b_ctrl->io96b_1.io96b_csr_addr = addr; + debug("%s: IO96B 0x%llx CSR enabled\n", __func__ + , io96b_ctrl->io96b_1.io96b_csr_addr); + count++; + } + break; + default: + printf("%s: Invalid IO96B CSR\n", __func__); + } + } + + io96b_ctrl->num_instance = count; + update_io96b_assigned_to_hps(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; + + if (plat->multichannel_interleaving) { + debug("%s: Set interleaving bit\n", __func__); + setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(5)); + } else { + debug("%s: Set multichannel bit\n", __func__); + setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(4)); + } + + reg = readl(SIDEBANDMGR_FLAGOUTSTATUS0_REG); + debug("%s: F2SDRAM_SIDEBAND_FLAGOUTSTATUS0: 0x%x\n", __func__, reg); + + if ((reg & BIT(1)) == plat->multichannel_interleaving) + return 0; + + return -1; +} + +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) +{ + 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 bd_info bd = {0}; + bool full_mem_init = false; + phys_size_t hw_size; + int ret; + u32 reg = readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_BOOT_SCRATCH_COLD0); + enum reset_type reset_t = get_reset_type(reg); + + debug("DDR: Address MPFE 0x%llx\n", plat->mpfe_base_addr); + + /* DDR initialization progress status tracking */ + bool is_ddr_hang_be4_rst = is_ddr_init_hang(); + + printf("DDR: IO96B SDRAM init in progress ...\n"); + ddr_init_inprogress(true); + + /* Populating DDR handoff data */ + debug("DDR: MPFE configuration in progress ...\n"); + ret = populate_ddr_handoff(dev, io96b_ctrl); + if (ret) { + printf("DDR: Failed to populate DDR handoff\n"); + return ret; + } + + /* Configuring MPFE sideband manager registers - multichannel or interleaving*/ + ret = config_mpfe_sideband_mgr(dev); + if (ret) { + printf("DDR: Failed to configure multichannel/interleaving mode\n"); + return ret; + } + + debug("DDR: MPFE configuration completed\n"); + + printf("DDR: Waiting for NOCPLL locked ...\n"); + /* Ensure NOCPLL locked */ + ret = wait_for_bit_le32((const void *)socfpga_get_sysmgr_addr() + SYSMGR_HMC_CLK + , SYSMGR_HMC_CLK_NOCPLL, true, TIMEOUT_10000MS, false); + if (ret) { + printf("DDR: NOCPLL is not locked\n"); + return ret; + } + + printf("DDR: NOCPLL locked\n"); + + printf("DDR: Checking calibration...\n"); + + /* 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"); + init_mem_cal(io96b_ctrl); + } + + if (!(io96b_ctrl->overall_cal_status)) { + printf("DDR: Retry calibration failed & not able to re-calibrate\n"); + return -1; + } + + 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"); + return ret; + } + + ret = get_mem_width_info(io96b_ctrl); + if (ret) { + printf("DDR: Failed to get DDR size\n"); + return ret; + } + + /* 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("DDR: Failed to decode memory node\n"); + return -ENXIO; + } + + hw_size = (phys_size_t)io96b_ctrl->overall_size * SZ_1G / SZ_8; + + 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"); + 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)) { + 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); + return ret; + } + } + } + + sdram_size_check(&bd); + printf("%s: size check success\n", io96b_ctrl->ddr_type); + + sdram_set_firewall(&bd); + printf("%s: firewall init success\n", io96b_ctrl->ddr_type); + + 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: IO96B SDRAM init success\n", io96b_ctrl->ddr_type); + + return 0; +} diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c index 4716abfc9a..86561bcbd4 100644 --- a/drivers/ddr/altera/sdram_soc64.c +++ b/drivers/ddr/altera/sdram_soc64.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016-2022 Intel Corporation + * Copyright (C) 2016-2023 Intel Corporation * */ @@ -28,6 +28,7 @@ #define PGTABLE_OFF 0x4000 +#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7) u32 hmc_readl(struct altera_sdram_plat *plat, u32 reg) { return readl(plat->iomhc + reg); @@ -99,6 +100,7 @@ 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) int poll_hmc_clock_status(void) @@ -322,8 +324,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_AGILEX7) + 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) return -EINVAL; @@ -338,7 +344,7 @@ 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; } @@ -385,6 +391,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-agilex7" }, { /* sentinel */ } }; diff --git a/drivers/ddr/altera/sdram_soc64.h b/drivers/ddr/altera/sdram_soc64.h index 07a0f9f2ae..1e802f1bdb 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 + * Copyright (C) 2017-2023 Intel Corporation */ #ifndef _SDRAM_SOC64_H_ @@ -14,11 +14,18 @@ struct altera_sdram_priv { struct reset_ctl_bulk resets; }; +#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7) +struct altera_sdram_plat { + fdt_addr_t mpfe_base_addr; + bool multichannel_interleaving; +}; +#else struct altera_sdram_plat { void __iomem *hmc; void __iomem *ddr_sch; void __iomem *iomhc; }; +#endif /* ECC HMC registers */ #define DDRIOCTRL 0x8 From patchwork Sun Apr 23 18:11:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sin.hui.kho@intel.com X-Patchwork-Id: 1772486 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=brfzZRgV; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Q4GZ91pQQz23s0 for ; Mon, 24 Apr 2023 04:12:17 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3D84C8609B; Sun, 23 Apr 2023 20:11:50 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="brfzZRgV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 38F2285D95; Sun, 23 Apr 2023 20:11:45 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 55EAF8575B for ; Sun, 23 Apr 2023 20:11:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sin.hui.kho@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1682273501; x=1713809501; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/Zc9QamfkMdczcLiK27/PnnZv5BIcCFsqSH47TDEfF8=; b=brfzZRgVZCv1UnknU9/u2FxsNeDdgcslO2cp8c8NjeVvPOhz3rHm501L lMgme+VTprcESyLG1L+UEUppzeJDKGi7tQaJn6ZUmyilgpZRjPSzg+NXA rpsdUjT6mM3+riZrqQy9LCjzZquVenqn/pPWZr56id6zfc8dgpms8Dl+r VpymVAL6LipMZ8jzwv1L9hOMrccPHvf22ETPtI0azySgdx2QE9S+WeZxe 3LJ5TAJCiamOn967r+TeCpPJjIgbG+SnQl4I+/ZXZhrwybuIZGymkDX45 NC/2Wilx2uQupj8K8XX6KnoALHcKv6KSt8Kl/rrPQhe4tEh8mycApc4kr w==; X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="374248728" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="374248728" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2023 11:11:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="695507804" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="695507804" Received: from pglc00257.png.intel.com ([10.221.233.180]) by fmsmga007.fm.intel.com with ESMTP; 23 Apr 2023 11:11:38 -0700 From: sin.hui.kho@intel.com To: u-boot@lists.denx.de Cc: Marek Vasut , Simon Goldschmidt , Tien Fong Chee , Sin Hui Kho , Simon Glass , Stefan Roese , Dinesh Maniyam , Jit Loon Lim , Teik Heng , Kok Kiang Subject: [PATCH v1 2/5] arm: socfpga: agilex7: Add boot scratch register used for DDR driver Date: Mon, 24 Apr 2023 02:11:21 +0800 Message-Id: <20230423181124.28077-3-sin.hui.kho@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230423181124.28077-1-sin.hui.kho@intel.com> References: <20230423181124.28077-1-sin.hui.kho@intel.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sin Hui Kho Add boot scratch register 8 in system manager used for AGILEX7 DDR driver. Signed-off-by: Sin Hui Kho --- .../include/mach/system_manager_soc64.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h b/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h index a8009664fe..fe85c0742d 100644 --- a/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h +++ b/arch/arm/mach-socfpga/include/mach/system_manager_soc64.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2019-2021 Intel Corporation + * Copyright (C) 2019-2023 Intel Corporation */ #ifndef _SYSTEM_MANAGER_SOC64_H_ @@ -102,6 +102,23 @@ void populate_sysmgr_pinmux(void); #define ALT_SYSMGR_SCRATCH_REG_0_DDR_SHA_MASK BIT(30) #define ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_MASK (BIT(29) | BIT(28)) #define ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_SHIFT 28 +/* + * Bits for SYSMGR_SOC64_BOOT_SCRATCH_COLD8 + * Bit[31] reserved for FSBL to check DDR 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[29] reserved for FSBL to check OCRAM DBE is triggered (set by SDM to "1") + * + * Bit[17:1] - Setting by Linux EDAC. + * Bit[1](ECC_OCRAM), Bit[16](ECC_DDR0), Bit[17](ECC_DDR1) + */ +#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 ALT_SYSMGR_SCRATCH_REG_8_IO96B_HPS_SHIFT 27 #define SYSMGR_SDMMC SYSMGR_SOC64_SDMMC From patchwork Sun Apr 23 18:11:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sin.hui.kho@intel.com X-Patchwork-Id: 1772487 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=LyQOK8SS; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Q4GZQ4Ypgz23s0 for ; Mon, 24 Apr 2023 04:12:30 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4B809860A8; Sun, 23 Apr 2023 20:11:53 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="LyQOK8SS"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 77AB58606A; Sun, 23 Apr 2023 20:11:47 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 387A48606A for ; Sun, 23 Apr 2023 20:11:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sin.hui.kho@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1682273504; x=1713809504; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VgGDfJWcwJFPOa1X9LJEviiihcrmGUxoPv5mprGac/w=; b=LyQOK8SS4PMUGK/mi1OYYJNqU+6jG57RFhKy2wuVCK4GiYFWsgnCXW0M 7VGEtfsIl027dVeIsBZvjslSyNyQU3jk2Ecwz63PBP/4rhs9kEkQSL3sq Pgx/Xc9myCONDLqkcZVjjC6xDDe/8OTj6xS4Zr3THQcSl9DY4349j1Aic pTccuqUJXG78Mn6nOdcAgat+9lkoYmbHRpJoY4H3GCwOLgEpnTIBJV+XM 8NusWT+yB416Hy8R6qE0HNly1lCM/zQSb1qOHaHQqMGyNdHSen+xkGxrX FPNsFhDh+hLCOyCMMSvxQh9+XpVXnezfzYLi4b9dIJdxW+PQFQIAqSVew Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="374248734" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="374248734" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2023 11:11:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="695507821" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="695507821" Received: from pglc00257.png.intel.com ([10.221.233.180]) by fmsmga007.fm.intel.com with ESMTP; 23 Apr 2023 11:11:40 -0700 From: sin.hui.kho@intel.com To: u-boot@lists.denx.de Cc: Marek Vasut , Simon Goldschmidt , Tien Fong Chee , Sin Hui Kho , Simon Glass , Stefan Roese , Dinesh Maniyam , Jit Loon Lim , Teik Heng , Kok Kiang Subject: [PATCH v1 3/5] arm: socfpga: soc64: Add F2SDRAM sideband manager base address for SOC64 Date: Mon, 24 Apr 2023 02:11:22 +0800 Message-Id: <20230423181124.28077-4-sin.hui.kho@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230423181124.28077-1-sin.hui.kho@intel.com> References: <20230423181124.28077-1-sin.hui.kho@intel.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sin Hui Kho F2SDRAM sideband manager in MPFE is used in DDR driver to configure the data traffic path. Signed-off-by: Sin Hui Kho --- arch/arm/mach-socfpga/include/mach/base_addr_soc64.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h index eecbb037f5..cee7d482c8 100644 --- a/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h +++ b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h @@ -17,6 +17,7 @@ #else #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS 0xf8020100 #endif +#define SOCFPGA_F2SDRAM_MGR_ADDRESS 0xf8024000 #define SOCFPGA_SMMU_ADDRESS 0xfa000000 #define SOCFPGA_MAILBOX_ADDRESS 0xffa30000 #define SOCFPGA_UART0_ADDRESS 0xffc02000 From patchwork Sun Apr 23 18:11:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sin.hui.kho@intel.com X-Patchwork-Id: 1772488 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=WJraRxhK; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Q4GZj2GDjz23s0 for ; Mon, 24 Apr 2023 04:12:45 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id ACEB1860D1; Sun, 23 Apr 2023 20:11:57 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="WJraRxhK"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DF1348609F; Sun, 23 Apr 2023 20:11:50 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 258B885D95 for ; Sun, 23 Apr 2023 20:11:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sin.hui.kho@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1682273507; x=1713809507; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=05RAf1AUNy+r5NWx6vyGiWUbHWHc69fzVCMfCIRxStc=; b=WJraRxhKq32mHMXiJei3Rh1H5rrnicP0raJp7j1xmLkO7au0jxigzn32 ULGGRVVnfHUg4runUdPzuM5i9lOq7SAvPfEoqeAt6vzdygTQiUPiF/9LA LJ5DRpT1XoAGVUVcIPviF+ohupuzqDlm7vRP4TKCchn+fgp6hUOozAE7p dfgRboMDFxpMtRsB/UjuiWeNvgJ2i0BgaFmlZVZrfxb8x8/ZR2U47Dl64 zGdQhyHi6/yrTTecy0N/AMS3cfqVLuOGmw25P3XfBYQVCGojafiqv0c10 cA/vI+ZQfeIz9DzT6Ptx3hzBYBMSGgTLFoa/K9VpZOMIRy61UnLPHOmYG g==; X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="374248744" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="374248744" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2023 11:11:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="695507834" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="695507834" Received: from pglc00257.png.intel.com ([10.221.233.180]) by fmsmga007.fm.intel.com with ESMTP; 23 Apr 2023 11:11:43 -0700 From: sin.hui.kho@intel.com To: u-boot@lists.denx.de Cc: Marek Vasut , Simon Goldschmidt , Tien Fong Chee , Sin Hui Kho , Simon Glass , Stefan Roese , Dinesh Maniyam , Jit Loon Lim , Teik Heng , Kok Kiang Subject: [PATCH v1 4/5] arm: socfpga: agilex7: Add DDR handoff data support for AGILEX7 Date: Mon, 24 Apr 2023 02:11:23 +0800 Message-Id: <20230423181124.28077-5-sin.hui.kho@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230423181124.28077-1-sin.hui.kho@intel.com> References: <20230423181124.28077-1-sin.hui.kho@intel.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sin Hui Kho Add AGILEX7 supported DDR handoff data Signed-off-by: Sin Hui Kho --- arch/arm/mach-socfpga/include/mach/handoff_soc64.h | 11 ++++++++++- arch/arm/mach-socfpga/wrap_handoff_soc64.c | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h index b0134dd9bd..bfda3c42bb 100644 --- a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h +++ b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 * - * Copyright (C) 2016-2021 Intel Corporation + * Copyright (C) 2016-2023 Intel Corporation * */ @@ -27,7 +27,16 @@ IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX) || \ IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7) #define SOC64_HANDOFF_BASE 0xFFE3F000 +#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7) +#define SOC64_HANDOFF_MISC (SOC64_HANDOFF_BASE + 0x628) +/* DDR handoff */ +#define SOC64_HANDOFF_MAGIC_DDR 0x5344524D +#define SOC64_HANDOFF_DDR_BASE (SOC64_HANDOFF_BASE + 0x610) +#define SOC64_HANDOFF_DDR_LEN 2 +#define SOC64_HANDOFF_DDR_INTERLEAVING_MODE_MASK BIT(0) +#else #define SOC64_HANDOFF_MISC (SOC64_HANDOFF_BASE + 0x610) +#endif #elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X) #define SOC64_HANDOFF_BASE 0xFFE5F000 #define SOC64_HANDOFF_MISC (SOC64_HANDOFF_BASE + 0x630) diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c index e7cb5ea89c..1abbe5a0d0 100644 --- a/arch/arm/mach-socfpga/wrap_handoff_soc64.c +++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c @@ -31,6 +31,10 @@ static enum endianness check_endianness(u32 handoff) case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC: debug("%s: PHY engine handoff data\n", __func__); return LITTLE_ENDIAN; +#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX7) + case SOC64_HANDOFF_MAGIC_DDR: + debug("%s: SOC64_HANDOFF_MAGIC_DDR\n", __func__); + return BIG_ENDIAN; #endif default: debug("%s: Unknown endianness!!\n", __func__); From patchwork Sun Apr 23 18:11:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sin.hui.kho@intel.com X-Patchwork-Id: 1772489 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=YDfiM7mD; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Q4GZx665Lz23s0 for ; Mon, 24 Apr 2023 04:12:57 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6F39A860A4; Sun, 23 Apr 2023 20:12:03 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="YDfiM7mD"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4DCE085AA1; Sun, 23 Apr 2023 20:11:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 85B718575B for ; Sun, 23 Apr 2023 20:11:50 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sin.hui.kho@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1682273510; x=1713809510; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1xQMHtA979HbQnbK1j2hySfd8WTVwJJ5xfTeK1IcARQ=; b=YDfiM7mDqubrEJNyI9FPp4p0LsuJVtky00qx78Auz48sfZXDx3r/ZasX ovtSSpgKtjLGi8/frDXeE7PPsl9F5DplEL+ai3rFdJQKneU0BhG1wer7K TRBKj/0sqy1Jg0whXKYo+QAwZ17Ke7H2kUIrts15I1W8MlrRceDN5oeGS 6AGQ6KSDvRsv1/uyoSJ+/Bn5EBg1V2GFHXx9Wo3g96Y5pxRoKTmwYIFSs Q769fMY90xuASKP1mZIVF/2r7E0Ris9tyAR2UVI1UZ1RsOnUeDZJZWgXI I9Iy3D0LbXuVtwPw6TGEqpi5I8a8hYNwF47szbn5AAwxSO6ymOAwHqAmO g==; X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="374248749" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="374248749" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2023 11:11:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10689"; a="695507848" X-IronPort-AV: E=Sophos;i="5.99,220,1677571200"; d="scan'208";a="695507848" Received: from pglc00257.png.intel.com ([10.221.233.180]) by fmsmga007.fm.intel.com with ESMTP; 23 Apr 2023 11:11:46 -0700 From: sin.hui.kho@intel.com To: u-boot@lists.denx.de Cc: Marek Vasut , Simon Goldschmidt , Tien Fong Chee , Sin Hui Kho , Simon Glass , Stefan Roese , Dinesh Maniyam , Jit Loon Lim , Teik Heng , Kok Kiang Subject: [PATCH v1 5/5] ddr: altera: Add IOSSM mailbox support for DDR driver Date: Mon, 24 Apr 2023 02:11:24 +0800 Message-Id: <20230423181124.28077-6-sin.hui.kho@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230423181124.28077-1-sin.hui.kho@intel.com> References: <20230423181124.28077-1-sin.hui.kho@intel.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sin Hui Kho Add IOSSM mailbox support for DDR driver to access memory interface implemented on an IO96B instance. Signed-off-by: Sin Hui Kho --- drivers/ddr/altera/Makefile | 2 +- drivers/ddr/altera/iossm_mailbox.c | 847 +++++++++++++++++++++++++++++ drivers/ddr/altera/iossm_mailbox.h | 142 +++++ 3 files changed, 990 insertions(+), 1 deletion(-) create mode 100644 drivers/ddr/altera/iossm_mailbox.c create mode 100644 drivers/ddr/altera/iossm_mailbox.h diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile index 555357d669..59938168b5 100644 --- a/drivers/ddr/altera/Makefile +++ b/drivers/ddr/altera/Makefile @@ -12,5 +12,5 @@ obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += 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_AGILEX7) += sdram_soc64.o sdram_agilex7.o +obj-$(CONFIG_TARGET_SOCFPGA_AGILEX7) += sdram_soc64.o sdram_agilex7.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..80aa2fa533 --- /dev/null +++ b/drivers/ddr/altera/iossm_mailbox.c @@ -0,0 +1,847 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Intel Corporation + * + */ + +#include +#include +#include +#include "iossm_mailbox.h" +#include + +/* 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__); + } + } + + /* 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_STATUS 0x%llx: 0x%x (cleared)\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++; + } + + debug("%s: IO96B %d [%d]: ip_type: 0x%x\n", __func__, i, k + , ip_type_ret); + debug("%s: IO96B %d [%d]: instance_id: 0x%x\n", __func__, i, k + , instance_id_ret); + } +; + 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++; + } + + debug("%s: IO96B %d [%d]: ip_type: 0x%x\n", __func__, i, k + , ip_type_ret); + debug("%s: IO96B %d [%d]: instance_id: 0x%x\n", __func__, i, k + , instance_id_ret); + } + break; + } + } +} + +int io96b_cal_status(phys_addr_t addr) +{ + int ret; + 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 + , 1000000000, false); + + debug("%s: Cal_stat 0x%llx: 0x%x\n", __func__, status_addr, readl(status_addr)); + + if (ret) { + printf("%s: SDRAM calibration IO96b instance 0x%llx timeout\n", __func__ + , status_addr); + hang(); + } + + /* Calibration status */ + if (readl(status_addr) == 0x1) + 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; + debug("%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; + debug("%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_done; + int i, j; + u8 cal_stat; + u32 reg; + + /* Initialize overall calibration status */ + io96b_ctrl->overall_cal_status = false; + + for (i = 0; i < io96b_ctrl->num_instance; i++) { + switch (i) { + case 0: + if (!(io96b_ctrl->io96b_0.cal_status)) { + recal_done = false; + + /* Re-calibration first memory interface with failed calibration */ + for (j = 0; j < 3; j++) { + /* Get the memory calibration status for first memory interface */ + io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr + , io96b_ctrl->io96b_0.mb_ctrl.ip_type[0], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0 + , 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_0.io96b_csr_addr + + usr_resp.cmd_resp_data_0); + cal_stat = reg & GENMASK(2, 0); + + /* Calibration was successful or INTF_0 unused*/ + if (cal_stat < 0x2) { + recal_done = true; + break; + } + + /* Calibration failed - recalibration */ + if (cal_stat == 0x2) { + 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); + } + + /* Calibration ongoing */ + while (cal_stat == 0x4) { + udelay(1000); + + io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr + , io96b_ctrl->io96b_0.mb_ctrl.ip_type[0], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS + , 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_0.io96b_csr_addr + + usr_resp.cmd_resp_data_0); + cal_stat = reg & GENMASK(2, 0); + } + } + + if (!recal_done) { + printf("%s: Error as SDRAM calibration failed\n", __func__); + hang(); + } + + recal_done = false; + + /* Re-calibration second memory interface with failed calibration */ + for (j = 0; j < 3; j++) { + /* Get the memory calibration status for second memory interface */ + io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr + , io96b_ctrl->io96b_0.mb_ctrl.ip_type[1], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0 + , 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_0.io96b_csr_addr + + usr_resp.cmd_resp_data_1); + cal_stat = reg & GENMASK(2, 0); + + /* Calibration was successful or INTF_0 unused*/ + if (cal_stat < 0x2) { + recal_done = true; + break; + } + + /* Calibration failed - recalibration */ + if (cal_stat == 0x2) { + 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[0] + , CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0, 0 + , 0, 0, 2, &usr_resp); + } + + /* Calibration ongoing */ + while (cal_stat == 0x4) { + udelay(1000); + + io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr + , io96b_ctrl->io96b_0.mb_ctrl.ip_type[1], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS + , 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_0.io96b_csr_addr + + usr_resp.cmd_resp_data_1); + cal_stat = reg & GENMASK(2, 0); + } + } + + if (!recal_done) { + 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)) { + recal_done = false; + + /* Re-calibration first memory interface with failed calibration */ + for (j = 0; j < 3; j++) { + /* Get the memory calibration status for first memory interface */ + io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr + , io96b_ctrl->io96b_1.mb_ctrl.ip_type[0], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0 + , 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_1.io96b_csr_addr + + usr_resp.cmd_resp_data_0); + cal_stat = reg & GENMASK(2, 0); + + /* Calibration was successful or INTF_0 unused*/ + if (cal_stat < 0x2) { + recal_done = true; + break; + } + + /* Calibration failed - recalibration */ + if (cal_stat == 0x2) { + 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); + } + + /* Calibration ongoing */ + while (cal_stat == 0x4) { + udelay(1000); + + io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr + , io96b_ctrl->io96b_1.mb_ctrl.ip_type[0], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS + , 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_1.io96b_csr_addr + + usr_resp.cmd_resp_data_0); + cal_stat = reg & GENMASK(2, 0); + } + } + + if (!recal_done) { + printf("%s: Error as SDRAM calibration failed\n", __func__); + hang(); + } + + recal_done = false; + + /* Re-calibration second memory interface with failed calibration */ + for (j = 0; j < 3; j++) { + /* Get the memory calibration status for second memory interface */ + io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr + , io96b_ctrl->io96b_1.mb_ctrl.ip_type[1], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0 + , 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_1.io96b_csr_addr + + usr_resp.cmd_resp_data_1); + cal_stat = reg & GENMASK(2, 0); + + /* Calibration was successful or INTF_0 unused*/ + if (cal_stat < 0x2) { + recal_done = true; + break; + } + + /* Calibration failed - recalibration */ + if (cal_stat == 0x2) { + 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[0] + , CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0, 0 + , 0, 0, 2, &usr_resp); + } + + /* Calibration ongoing */ + while (cal_stat == 0x4) { + udelay(1000); + + io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr + , io96b_ctrl->io96b_1.mb_ctrl.ip_type[1], 0 + , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS + , 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp); + reg = readl(io96b_ctrl->io96b_1.io96b_csr_addr + + usr_resp.cmd_resp_data_1); + cal_stat = reg & GENMASK(2, 0); + } + } + + if (!recal_done) { + 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; + } + } + + debug("%s: ECC: %s\n", __func__, io96b_ctrl->ecc_status ? "Enabled" : "Disabled"); + + 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; + int count; + + /* 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, 0x9 + , 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); + count = 1; + while (!bist_success) { + debug(" io96b_0: BIST delay count: %d\n", count); + 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)); + + mdelay(5000); + count++; + } + } + + debug("%s: Memory initialized successfully on IO96B_0\n", __func__); + debug("%s: Initialized success with %d ms\n", __func__ + , (unsigned int)get_timer(start)); + + 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); + count = 1; + while (!bist_success) { + debug(" io96b_1: BIST delay count: %d\n", count); + 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)); + + mdelay(5000); + count++; + } + } + debug("%s: Memory initialized successfully on IO96B_1\n", __func__); + debug("%s: Initialized success with %d ms\n", __func__ + , (unsigned int)get_timer(start)); + 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..e66b240120 --- /dev/null +++ b/drivers/ddr/altera/iossm_mailbox.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Intel Corporation + */ + +#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); +void trig_mem_cal_must(struct io96b_info *io96b_ctrl);