All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] arm: socfpga: soc64: Move spl_board_prepare_for_boot()
@ 2022-09-18 15:12 Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 2/5] arm: socfpga: soc64: Change to use spl_perform_fixups() Jit Loon Lim
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jit Loon Lim @ 2022-09-18 15:12 UTC (permalink / raw)
  To: u-boot
  Cc: Jagan Teki, Vignesh R, Marek, Simon, Tien Fong, Kok Kiang,
	Siew Chin, Sin Hui, Raaj, Dinesh, Boon Khai, Alif, Teik Heng,
	Hazim, Jit Loon Lim, Sieu Mun Tang, Ley Foon Tan

From: Ley Foon Tan <ley.foon.tan@intel.com>

Move spl_board_prepare_for_boot() to spl_soc64.c.

spl_board_prepare_for_boot() will use for all SoC64 platforms.

Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
---
 arch/arm/mach-socfpga/spl_soc64.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/mach-socfpga/spl_soc64.c b/arch/arm/mach-socfpga/spl_soc64.c
index ba6efc1d86..f3fa1ae361 100644
--- a/arch/arm/mach-socfpga/spl_soc64.c
+++ b/arch/arm/mach-socfpga/spl_soc64.c
@@ -23,3 +23,9 @@ u32 spl_boot_mode(const u32 boot_device)
 		return MMCSD_MODE_RAW;
 }
 #endif
+
+/* board specific function prior loading SSBL / U-Boot */
+void spl_board_prepare_for_boot(void)
+{
+	mbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/5] arm: socfpga: soc64: Change to use spl_perform_fixups()
  2022-09-18 15:12 [PATCH 1/5] arm: socfpga: soc64: Move spl_board_prepare_for_boot() Jit Loon Lim
@ 2022-09-18 15:12 ` Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 3/5] arm: socfpga: soc64: Move socfpga_init_smmu() to before boot SSBL Jit Loon Lim
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jit Loon Lim @ 2022-09-18 15:12 UTC (permalink / raw)
  To: u-boot
  Cc: Jagan Teki, Vignesh R, Marek, Simon, Tien Fong, Kok Kiang,
	Siew Chin, Sin Hui, Raaj, Dinesh, Boon Khai, Alif, Teik Heng,
	Hazim, Jit Loon Lim, Sieu Mun Tang, Ley Foon Tan

From: Ley Foon Tan <ley.foon.tan@intel.com>

spl_board_prepare_for_boot() function is only called in U-boot flow, not
for ATF flow.

Change to use spl_perform_fixups() to support U-boot and ATF flow.

Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
---
 arch/arm/mach-socfpga/spl_soc64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-socfpga/spl_soc64.c b/arch/arm/mach-socfpga/spl_soc64.c
index f3fa1ae361..2204703853 100644
--- a/arch/arm/mach-socfpga/spl_soc64.c
+++ b/arch/arm/mach-socfpga/spl_soc64.c
@@ -25,7 +25,7 @@ u32 spl_boot_mode(const u32 boot_device)
 #endif
 
 /* board specific function prior loading SSBL / U-Boot */
-void spl_board_prepare_for_boot(void)
+void spl_perform_fixups(struct spl_image_info *spl_image)
 {
 	mbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/5] arm: socfpga: soc64: Move socfpga_init_smmu() to before boot SSBL
  2022-09-18 15:12 [PATCH 1/5] arm: socfpga: soc64: Move spl_board_prepare_for_boot() Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 2/5] arm: socfpga: soc64: Change to use spl_perform_fixups() Jit Loon Lim
@ 2022-09-18 15:12 ` Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 4/5] ddr: altera: soc64: Add secure region support for ATF flow Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 5/5] doc: socfpga: Add secure region change Jit Loon Lim
  3 siblings, 0 replies; 5+ messages in thread
From: Jit Loon Lim @ 2022-09-18 15:12 UTC (permalink / raw)
  To: u-boot
  Cc: Jagan Teki, Vignesh R, Marek, Simon, Tien Fong, Kok Kiang,
	Siew Chin, Sin Hui, Raaj, Dinesh, Boon Khai, Alif, Teik Heng,
	Hazim, Jit Loon Lim, Sieu Mun Tang, Ley Foon Tan

From: Ley Foon Tan <ley.foon.tan@intel.com>

socfpga_init_smmu() change the L3 masters (eg: SDMMC, NAND and etc) to
non-secure , this cause the failure when L3 masters loading SSBL image to
secure region in DDR.

Move socfpga_init_smmu() to spl_perform_fixups(), so, it is called prior
running SSBL.

Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
---
 arch/arm/mach-socfpga/spl_agilex.c            |  1 +
 .../mach-socfpga/{spl_agilex.c => spl_dm.c}   | 38 +++++++------------
 arch/arm/mach-socfpga/spl_soc64.c             |  3 ++
 3 files changed, 18 insertions(+), 24 deletions(-)
 copy arch/arm/mach-socfpga/{spl_agilex.c => spl_dm.c} (82%)

diff --git a/arch/arm/mach-socfpga/spl_agilex.c b/arch/arm/mach-socfpga/spl_agilex.c
index ee5a9dc1e2..f137b71e99 100644
--- a/arch/arm/mach-socfpga/spl_agilex.c
+++ b/arch/arm/mach-socfpga/spl_agilex.c
@@ -65,6 +65,7 @@ void board_init_f(ulong dummy)
 	cm_print_clock_quick_summary();
 
 	firewall_setup();
+
 	ret = uclass_get_device(UCLASS_CACHE, 0, &dev);
 	if (ret) {
 		debug("CCU init failed: %d\n", ret);
diff --git a/arch/arm/mach-socfpga/spl_agilex.c b/arch/arm/mach-socfpga/spl_dm.c
similarity index 82%
copy from arch/arm/mach-socfpga/spl_agilex.c
copy to arch/arm/mach-socfpga/spl_dm.c
index ee5a9dc1e2..17b3cb28dc 100644
--- a/arch/arm/mach-socfpga/spl_agilex.c
+++ b/arch/arm/mach-socfpga/spl_dm.c
@@ -1,87 +1,77 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
  *
  */
-
-#include <init.h>
-#include <log.h>
-#include <asm/global_data.h>
 #include <asm/io.h>
 #include <asm/u-boot.h>
 #include <asm/utils.h>
 #include <common.h>
 #include <hang.h>
 #include <image.h>
+#include <init.h>
 #include <spl.h>
 #include <asm/arch/clock_manager.h>
 #include <asm/arch/firewall.h>
 #include <asm/arch/mailbox_s10.h>
 #include <asm/arch/misc.h>
 #include <asm/arch/reset_manager.h>
+#include <asm/arch/smmu_s10.h>
 #include <asm/arch/system_manager.h>
 #include <watchdog.h>
 #include <dm/uclass.h>
-
 DECLARE_GLOBAL_DATA_PTR;
-
 void board_init_f(ulong dummy)
 {
 	int ret;
 	struct udevice *dev;
-
 	ret = spl_early_init();
 	if (ret)
 		hang();
-
 	socfpga_get_managers_addr();
-
 	/* Ensure watchdog is paused when debugging is happening */
 	writel(SYSMGR_WDDBG_PAUSE_ALL_CPU,
 	       socfpga_get_sysmgr_addr() + SYSMGR_SOC64_WDDBG);
-
 #ifdef CONFIG_HW_WATCHDOG
 	/* Enable watchdog before initializing the HW */
 	socfpga_per_reset(SOCFPGA_RESET(L4WD0), 1);
 	socfpga_per_reset(SOCFPGA_RESET(L4WD0), 0);
 	hw_watchdog_init();
 #endif
-
 	/* ensure all processors are not released prior Linux boot */
 	writeq(0, CPU_RELEASE_ADDR);
-
 	timer_init();
-
 	sysmgr_pinmux_init();
-
+	preloader_console_init();
 	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
 	if (ret) {
-		debug("Clock init failed: %d\n", ret);
+		printf("Clock init failed: %d\n", ret);
+		hang();
+	}
+	ret = uclass_get_device(UCLASS_CLK, 1, &dev);
+	if (ret) {
+		printf("Memory clock init failed: %d\n", ret);
 		hang();
 	}
-
-	preloader_console_init();
 	print_reset_info();
 	cm_print_clock_quick_summary();
 
 	firewall_setup();
+
 	ret = uclass_get_device(UCLASS_CACHE, 0, &dev);
 	if (ret) {
-		debug("CCU init failed: %d\n", ret);
+		printf("CCU init failed: %d\n", ret);
 		hang();
 	}
-
 #if CONFIG_IS_ENABLED(ALTERA_SDRAM)
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
-		debug("DRAM init failed: %d\n", ret);
+		printf("DRAM init failed: %d\n", ret);
 		hang();
 	}
 #endif
-
 	mbox_init();
-
 #ifdef CONFIG_CADENCE_QSPI
 	mbox_qspi_open();
 #endif
-}
+}
\ No newline at end of file
diff --git a/arch/arm/mach-socfpga/spl_soc64.c b/arch/arm/mach-socfpga/spl_soc64.c
index 2204703853..2f0ad65c18 100644
--- a/arch/arm/mach-socfpga/spl_soc64.c
+++ b/arch/arm/mach-socfpga/spl_soc64.c
@@ -27,5 +27,8 @@ u32 spl_boot_mode(const u32 boot_device)
 /* board specific function prior loading SSBL / U-Boot */
 void spl_perform_fixups(struct spl_image_info *spl_image)
 {
+	/* Setup and Initialize SMMU */
+	socfpga_init_smmu();
+
 	mbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/5] ddr: altera: soc64: Add secure region support for ATF flow
  2022-09-18 15:12 [PATCH 1/5] arm: socfpga: soc64: Move spl_board_prepare_for_boot() Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 2/5] arm: socfpga: soc64: Change to use spl_perform_fixups() Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 3/5] arm: socfpga: soc64: Move socfpga_init_smmu() to before boot SSBL Jit Loon Lim
@ 2022-09-18 15:12 ` Jit Loon Lim
  2022-09-18 15:12 ` [PATCH 5/5] doc: socfpga: Add secure region change Jit Loon Lim
  3 siblings, 0 replies; 5+ messages in thread
From: Jit Loon Lim @ 2022-09-18 15:12 UTC (permalink / raw)
  To: u-boot
  Cc: Jagan Teki, Vignesh R, Marek, Simon, Tien Fong, Kok Kiang,
	Siew Chin, Sin Hui, Raaj, Dinesh, Boon Khai, Alif, Teik Heng,
	Hazim, Jit Loon Lim, Sieu Mun Tang, Ley Foon Tan

From: Ley Foon Tan <ley.foon.tan@intel.com>

Setting up firewall regions based on SDRAM memory banks configuration
(up to CONFIG_NR_DRAM_BANKS banks) instead of using whole address space.

First 1 MiB (0 to 0xfffff) of SDRAM is configured as secure region,
other address spaces are non-secure regions. The ARM Trusted Firmware (ATF)
image is located in this first 1 MiB memory region. So, this can prevent
software executing at non-secure state EL0-EL2 and non-secure masters
access to secure region.

Add common function for firewall setup and reuse for all SoC64 devices.

Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
---
 drivers/ddr/altera/sdram_agilex.c |  16 +-
 drivers/ddr/altera/sdram_dm.c     | 998 ++++++++++++++++++++++++++++++
 drivers/ddr/altera/sdram_s10.c    |  16 +-
 3 files changed, 1002 insertions(+), 28 deletions(-)
 create mode 100644 drivers/ddr/altera/sdram_dm.c

diff --git a/drivers/ddr/altera/sdram_agilex.c b/drivers/ddr/altera/sdram_agilex.c
index 65ecdd022c..9f96b4619a 100644
--- a/drivers/ddr/altera/sdram_agilex.c
+++ b/drivers/ddr/altera/sdram_agilex.c
@@ -115,20 +115,6 @@ int sdram_mmr_init_full(struct udevice *dev)
 
 	printf("DDR: %lld MiB\n", gd->ram_size >> 20);
 
-	/* This enables nonsecure access to DDR */
-	/* mpuregion0addr_limit */
-	FW_MPU_DDR_SCR_WRITEL(gd->ram_size - 1,
-			      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT);
-	FW_MPU_DDR_SCR_WRITEL(0x1F, FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT);
-
-	/* nonmpuregion0addr_limit */
-	FW_MPU_DDR_SCR_WRITEL(gd->ram_size - 1,
-			      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT);
-
-	/* Enable mpuregion0enable and nonmpuregion0enable */
-	FW_MPU_DDR_SCR_WRITEL(MPUREGION0_ENABLE | NONMPUREGION0_ENABLE,
-			      FW_MPU_DDR_SCR_EN_SET);
-
 	u32 ctrlcfg1 = hmc_readl(plat, CTRLCFG1);
 
 	/* Enable or disable the DDR ECC */
@@ -163,6 +149,8 @@ int sdram_mmr_init_full(struct udevice *dev)
 
 	sdram_size_check(&bd);
 
+	sdram_set_firewall(&bd);
+
 	priv->info.base = bd.bi_dram[0].start;
 	priv->info.size = gd->ram_size;
 
diff --git a/drivers/ddr/altera/sdram_dm.c b/drivers/ddr/altera/sdram_dm.c
new file mode 100644
index 0000000000..5e3951d5c6
--- /dev/null
+++ b/drivers/ddr/altera/sdram_dm.c
@@ -0,0 +1,998 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+#include <common.h>
+#include <clk.h>
+#include <div64.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <hang.h>
+#include <ram.h>
+#include <reset.h>
+#include "sdram_soc64.h"
+#include <wait_bit.h>
+#include <asm/arch/firewall.h>
+#include <asm/arch/handoff_soc64.h>
+#include <asm/arch/misc.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+#include <asm/io.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+DECLARE_GLOBAL_DATA_PTR;
+/* Memory reset manager */
+#define MEM_RST_MGR_STATUS	0x8
+/* Register and bit in memory reset manager */
+#define MEM_RST_MGR_STATUS_RESET_COMPLETE	BIT(0)
+#define MEM_RST_MGR_STATUS_PWROKIN_STATUS	BIT(1)
+#define MEM_RST_MGR_STATUS_CONTROLLER_RST	BIT(2)
+#define MEM_RST_MGR_STATUS_AXI_RST		BIT(3)
+#define TIMEOUT_200MS     200
+#define TIMEOUT_5000MS    5000
+/* DDR4 umctl2 */
+#define DDR4_STAT_OFFSET		0x4
+#define DDR4_STAT_SELFREF_TYPE		(BIT(5) | BIT(4))
+#define DDR4_STAT_SELFREF_TYPE_SHIFT	4
+#define DDR4_STAT_OPERATING_MODE	(BIT(2) | BIT(1) | BIT(0))
+#define DDR4_MRCTRL0_OFFSET		0x10
+#define DDR4_MRCTRL0_MR_TYPE		BIT(0)
+#define DDR4_MRCTRL0_MPR_EN		BIT(1)
+#define DDR4_MRCTRL0_MR_RANK		(BIT(5) | BIT(4))
+#define DDR4_MRCTRL0_MR_RANK_SHIFT	4
+#define DDR4_MRCTRL0_MR_ADDR		(BIT(15) | BIT(14) | BIT(13) | BIT(12))
+#define DDR4_MRCTRL0_MR_ADDR_SHIFT	12
+#define DDR4_MRCTRL0_MR_WR		BIT(31)
+#define DDR4_MRCTRL1_OFFSET		0x14
+#define DDR4_MRCTRL1_MR_DATA		0x3FFFF
+#define DDR4_MRSTAT_OFFSET		0x18
+#define DDR4_MRSTAT_MR_WR_BUSY		BIT(0)
+#define DDR4_MRCTRL2_OFFSET		0x1C
+#define DDR4_PWRCTL_OFFSET			0x30
+#define DDR4_PWRCTL_SELFREF_EN			BIT(0)
+#define DDR4_PWRCTL_POWERDOWN_EN		BIT(1)
+#define DDR4_PWRCTL_EN_DFI_DRAM_CLK_DISABLE	BIT(3)
+#define DDR4_PWRCTL_SELFREF_SW			BIT(5)
+#define DDR4_PWRTMG_OFFSET		0x34
+#define DDR4_HWLPCTL_OFFSET		0x38
+#define DDR4_RFSHCTL0_OFFSET		0x50
+#define DDR4_RFSHCTL1_OFFSET		0x54
+#define DDR4_RFSHCTL3_OFFSET			0x60
+#define DDR4_RFSHCTL3_DIS_AUTO_REFRESH		BIT(0)
+#define DDR4_RFSHCTL3_REFRESH_MODE		(BIT(6) | BIT(5) | BIT(4))
+#define DDR4_RFSHCTL3_REFRESH_MODE_SHIFT	4
+#define DDR4_ECCCFG0_OFFSET		0x70
+#define DDR4_ECC_MODE			(BIT(2) | BIT(1) | BIT(0))
+#define DDR4_DIS_SCRUB			BIT(4)
+#define DDR4_CRCPARCTL1_OFFSET			0x04
+#define DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE	BIT(8)
+#define DDR4_CRCPARCTL1_ALERT_WAIT_FOR_SW	BIT(9)
+#define DDR4_CRCPARCTL0_OFFSET			0xC0
+#define DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR	BIT(1)
+#define DDR4_CRCPARSTAT_OFFSET			0xCC
+#define DDR4_CRCPARSTAT_DFI_ALERT_ERR_INT	BIT(16)
+#define DDR4_CRCPARSTAT_DFI_ALERT_ERR_FATL_INT	BIT(17)
+#define DDR4_CRCPARSTAT_DFI_ALERT_ERR_NO_SW	BIT(19)
+#define DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW	BIT(29)
+#define DDR4_DFIMISC_OFFSET			0x1B0
+#define DDR4_DFIMISC_DFI_INIT_COMPLETE_EN	BIT(0)
+#define DDR4_DFIMISC_DFI_INIT_START		BIT(5)
+#define DDR4_DFISTAT_OFFSET		0x1BC
+#define DDR4_DFI_INIT_COMPLETE		BIT(0)
+#define DDR4_DBG0_OFFSET		0x300
+#define DDR4_DBG1_OFFSET		0x304
+#define DDR4_DBG1_DISDQ			BIT(0)
+#define DDR4_DBG1_DIS_HIF		BIT(1)
+#define DDR4_DBGCAM_OFFSET			0x308
+#define DDR4_DBGCAM_DBG_RD_Q_EMPTY		BIT(25)
+#define DDR4_DBGCAM_DBG_WR_Q_EMPTY		BIT(26)
+#define DDR4_DBGCAM_RD_DATA_PIPELINE_EMPTY	BIT(28)
+#define DDR4_DBGCAM_WR_DATA_PIPELINE_EMPTY	BIT(29)
+#define DDR4_SWCTL_OFFSET		0x320
+#define DDR4_SWCTL_SW_DONE		BIT(0)
+#define DDR4_SWSTAT_OFFSET		0x324
+#define DDR4_SWSTAT_SW_DONE_ACK		BIT(0)
+#define DDR4_PSTAT_OFFSET		0x3FC
+#define DDR4_PSTAT_RD_PORT_BUSY_0	BIT(0)
+#define DDR4_PSTAT_WR_PORT_BUSY_0	BIT(16)
+#define DDR4_PCTRL0_OFFSET		0x490
+#define DDR4_PCTRL0_PORT_EN		BIT(0)
+#define DDR4_SBRCTL_OFFSET		0xF24
+#define DDR4_SBRCTL_SCRUB_INTERVAL	0x1FFF00
+#define DDR4_SBRCTL_SCRUB_EN		BIT(0)
+#define DDR4_SBRCTL_SCRUB_WRITE		BIT(2)
+#define DDR_SBRCTL_SCRUB_BURST_1	BIT(4)
+#define DDR4_SBRSTAT_OFFSET		0xF28
+#define DDR4_SBRSTAT_SCRUB_BUSY BIT(0)
+#define DDR4_SBRSTAT_SCRUB_DONE BIT(1)
+#define DDR4_SBRWDATA0_OFFSET		0xF2C
+#define DDR4_SBRWDATA1_OFFSET		0xF30
+#define DDR4_SBRSTART0_OFFSET		0xF38
+#define DDR4_SBRSTART1_OFFSET		0xF3C
+#define DDR4_SBRRANGE0_OFFSET		0xF40
+#define DDR4_SBRRANGE1_OFFSET		0xF44
+/* DDR PHY */
+#define DDR_PHY_TXODTDRVSTREN_B0_P0		0x2009A
+#define DDR_PHY_RXPBDLYTG0_R0			0x200D0
+#define DDR_PHY_CALRATE_OFFSET			0x40110
+#define DDR_PHY_CALZAP_OFFSET			0x40112
+#define DDR_PHY_SEQ0BDLY0_P0_OFFSET		0x40016
+#define DDR_PHY_SEQ0BDLY1_P0_OFFSET		0x40018
+#define DDR_PHY_SEQ0BDLY2_P0_OFFSET		0x4001A
+#define DDR_PHY_SEQ0BDLY3_P0_OFFSET		0x4001C
+#define DDR_PHY_SEQ0DISABLEFLAG0_OFFSET		0x120018
+#define DDR_PHY_SEQ0DISABLEFLAG1_OFFSET		0x12001A
+#define DDR_PHY_SEQ0DISABLEFLAG2_OFFSET		0x12001C
+#define DDR_PHY_SEQ0DISABLEFLAG3_OFFSET		0x12001E
+#define DDR_PHY_SEQ0DISABLEFLAG4_OFFSET		0x120020
+#define DDR_PHY_SEQ0DISABLEFLAG5_OFFSET		0x120022
+#define DDR_PHY_SEQ0DISABLEFLAG6_OFFSET		0x120024
+#define DDR_PHY_SEQ0DISABLEFLAG7_OFFSET		0x120026
+#define DDR_PHY_UCCLKHCLKENABLES_OFFSET		0x180100
+#define DDR_PHY_APBONLY0_OFFSET			0x1A0000
+#define DDR_PHY_MICROCONTMUXSEL			BIT(0)
+#define DDR_PHY_MICRORESET_OFFSET		0x1A0132
+#define DDR_PHY_MICRORESET_STALL		BIT(0)
+#define DDR_PHY_MICRORESET_RESET		BIT(3)
+#define DDR_PHY_TXODTDRVSTREN_B0_P1		0x22009A
+/* Operating mode */
+#define INIT_OPM			0x000
+#define NORMAL_OPM			0x001
+#define PWR_D0WN_OPM			0x010
+#define SELF_SELFREF_OPM		0x011
+#define DDR4_DEEP_PWR_DOWN_OPM		0x100
+/* Refresh mode */
+#define FIXED_1X		0
+#define FIXED_2X		BIT(0)
+#define FIXED_4X		BIT(4)
+/* Address of mode register */
+#define MR0	0x0000
+#define MR1	0x0001
+#define MR2	0x0010
+#define MR3	0x0011
+#define MR4	0x0100
+#define MR5	0x0101
+#define MR6	0x0110
+#define MR7	0x0111
+/* MR rank */
+#define RANK0		0x1
+#define RANK1		0x2
+#define ALL_RANK	0x3
+#define MR5_BIT4	BIT(4)
+#ifdef CONFIG_TARGET_SOCFPGA_DM
+#define PSI_LL_SLAVE_APS_PER_OFST	0x00000000
+#define alt_write_hword(addr, val)	(writew(val, addr))
+#define SDM_HPS_PERI_ADDR_TRANSLATION(_HPS_OFFSET_) \
+	(PSI_LL_SLAVE_APS_PER_OFST + (_HPS_OFFSET_))
+#define DDR_PHY_BASE	0xF8800000
+#define SNPS_PHY_TRANSLATION(_PHY_OFFSET_) \
+	(PSI_LL_SLAVE_APS_PER_OFST + ((DDR_PHY_BASE + ((_PHY_OFFSET_) << 1))))
+#define dwc_ddrphy_apb_wr(dest, data) \
+	alt_write_hword(SNPS_PHY_TRANSLATION(dest), data)
+#define b_max 1
+#define timing_group_max 4
+#endif
+/* DDR handoff structure */
+struct ddr_handoff {
+	phys_addr_t mem_reset_base;
+	phys_addr_t umctl2_handoff_base;
+	phys_addr_t umctl2_base;
+	size_t umctl2_total_length;
+	size_t umctl2_handoff_length;
+	phys_addr_t phy_handoff_base;
+	phys_addr_t phy_base;
+	size_t phy_total_length;
+	size_t phy_handoff_length;
+	phys_addr_t phy_engine_handoff_base;
+	size_t phy_engine_total_length;
+	size_t phy_engine_handoff_length;
+};
+static int clr_ca_parity_error_status(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+	debug("%s: Clear C/A parity error status in MR5[4]\n", __func__);
+	/* Set mode register MRS */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     DDR4_MRCTRL0_MPR_EN);
+	/* Set mode register to write operation */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     DDR4_MRCTRL0_MR_TYPE);
+	/* Set the address of mode rgister to 0x101(MR5) */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     (MR5 << DDR4_MRCTRL0_MR_ADDR_SHIFT) &
+		     DDR4_MRCTRL0_MR_ADDR);
+	/* Set MR rank to rank 1 */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     (RANK1 << DDR4_MRCTRL0_MR_RANK_SHIFT) &
+		     DDR4_MRCTRL0_MR_RANK);
+	/* Clear C/A parity error status in MR5[4] */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_MRCTRL1_OFFSET,
+		     MR5_BIT4);
+	/* Trigger mode register read or write operation */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     DDR4_MRCTRL0_MR_WR);
+	/* Wait for retry done */
+	ret = wait_for_bit_le32((const void *)(ddr_handoff_info->umctl2_base +
+				DDR4_MRSTAT_OFFSET), DDR4_MRSTAT_MR_WR_BUSY,
+				false, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" no outstanding MR transaction\n");
+		return ret;
+	}
+	return 0;
+}
+static int ddr4_retry_software_sequence(struct ddr_handoff *ddr_handoff_info)
+{
+	u32 value;
+	int ret;
+	/* Check software can perform MRS/MPR/PDA? */
+	value = readl(ddr_handoff_info->umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+		      DDR4_CRCPARSTAT_DFI_ALERT_ERR_NO_SW;
+	if (value) {
+		debug("%s: Software can't perform MRS/MPR/PDA\n", __func__);
+		/* Clear interrupt bit for DFI alert error */
+		setbits_le32(ddr_handoff_info->umctl2_base +
+			     DDR4_CRCPARCTL0_OFFSET,
+			     DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR);
+		/* Wait for retry done */
+		ret = wait_for_bit_le32((const void *)
+					(ddr_handoff_info->umctl2_base +
+					DDR4_MRSTAT_OFFSET),
+					DDR4_MRSTAT_MR_WR_BUSY,
+					false, TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" no outstanding MR transaction\n");
+			return ret;
+		}
+		if (clr_ca_parity_error_status(ddr_handoff_info))
+			return ret;
+	} else {
+		debug("%s: Software can perform MRS/MPR/PDA\n", __func__);
+		ret = wait_for_bit_le32((const void *)
+					(ddr_handoff_info->umctl2_base +
+					DDR4_MRSTAT_OFFSET),
+					DDR4_MRSTAT_MR_WR_BUSY,
+					false, TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" no outstanding MR transaction\n");
+			return ret;
+		}
+		if (clr_ca_parity_error_status(ddr_handoff_info))
+			return ret;
+		/* Clear interrupt bit for DFI alert error */
+		setbits_le32(ddr_handoff_info->umctl2_base +
+			     DDR4_CRCPARCTL0_OFFSET,
+			     DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR);
+	}
+	return 0;
+}
+static int ensure_retry_procedure_complete(struct ddr_handoff *ddr_handoff_info)
+{
+	u32 value;
+	u32 start = get_timer(0);
+	int ret;
+	/* Check parity/crc/error window is emptied ? */
+	value = readl(ddr_handoff_info->umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+		      DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW;
+	/* Polling until parity/crc/error window is emptied */
+	while (value) {
+		if (get_timer(start) > TIMEOUT_200MS) {
+			debug("%s: Timeout while waiting for",
+			      __func__);
+			debug(" parity/crc/error window empty\n");
+			return -ETIMEDOUT;
+		}
+		/* Check software intervention is enabled? */
+		value = readl(ddr_handoff_info->umctl2_base +
+			      DDR4_CRCPARCTL1_OFFSET) &
+			      DDR4_CRCPARCTL1_ALERT_WAIT_FOR_SW;
+		if (value) {
+			debug("%s: Software intervention is enabled\n",
+			      __func__);
+			/* Check dfi alert error interrupt is set? */
+			value = readl(ddr_handoff_info->umctl2_base +
+				      DDR4_CRCPARSTAT_OFFSET) &
+				      DDR4_CRCPARSTAT_DFI_ALERT_ERR_INT;
+			if (value) {
+				ret =
+				ddr4_retry_software_sequence(ddr_handoff_info);
+				debug("%s: DFI alert error interrupt ",
+				      __func__);
+				debug("is set\n");
+				if (ret)
+					return ret;
+			}
+			/*
+			 * Check fatal parity error interrupt is set?
+			 */
+			value = readl(ddr_handoff_info->umctl2_base +
+				      DDR4_CRCPARSTAT_OFFSET) &
+				      DDR4_CRCPARSTAT_DFI_ALERT_ERR_FATL_INT;
+			if (value) {
+				printf("%s: Fatal parity error  ",
+				       __func__);
+				printf("interrupt is set, Hang it!!\n");
+				hang();
+			}
+		}
+		value = readl(ddr_handoff_info->umctl2_base +
+			      DDR4_CRCPARSTAT_OFFSET) &
+			      DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW;
+		udelay(1);
+		WATCHDOG_RESET();
+	}
+	return 0;
+}
+static int enable_quasi_dynamic_reg_grp3(struct ddr_handoff *ddr_handoff_info)
+{
+	u32 i, value, backup;
+	int ret;
+	/* Disable input traffic per port */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_PCTRL0_OFFSET,
+		     DDR4_PCTRL0_PORT_EN);
+	/* Polling AXI port until idle */
+	ret = wait_for_bit_le32((const void *)(ddr_handoff_info->umctl2_base +
+				DDR4_PSTAT_OFFSET), DDR4_PSTAT_WR_PORT_BUSY_0 |
+				DDR4_PSTAT_RD_PORT_BUSY_0, false,
+				TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" controller idle\n");
+		return ret;
+	}
+	/* Backup user setting */
+	backup = readl(ddr_handoff_info->umctl2_base + DDR4_DBG1_OFFSET);
+	/* Disable input traffic to the controller */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_DBG1_OFFSET,
+		     DDR4_DBG1_DIS_HIF);
+	/*
+	 * Ensure CAM/data pipelines are empty.
+	 * Poll until CAM/data pipelines are set at least twice,
+	 * timeout at 200ms
+	 */
+	for (i = 0; i < 2; i++) {
+		ret = wait_for_bit_le32((const void *)
+					(ddr_handoff_info->umctl2_base +
+					DDR4_DBGCAM_OFFSET),
+					DDR4_DBGCAM_WR_DATA_PIPELINE_EMPTY |
+					DDR4_DBGCAM_RD_DATA_PIPELINE_EMPTY |
+					DDR4_DBGCAM_DBG_WR_Q_EMPTY |
+					DDR4_DBGCAM_DBG_RD_Q_EMPTY, true,
+					TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: loop(%u): Timeout while waiting for",
+			      __func__, i + 1);
+			debug(" CAM/data pipelines are empty\n");
+			/* Restore user setting */
+			writel(backup, ddr_handoff_info->umctl2_base +
+			       DDR4_DBG1_OFFSET);
+			return ret;
+		}
+	}
+	/* Check DDR4 retry is enabled ? */
+	value = readl(ddr_handoff_info->umctl2_base + DDR4_CRCPARCTL1_OFFSET) &
+		      DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE;
+	if (value) {
+		debug("%s: DDR4 retry is enabled\n", __func__);
+		ret = ensure_retry_procedure_complete(ddr_handoff_info);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" retry procedure complete\n");
+			/* Restore user setting */
+			writel(backup, ddr_handoff_info->umctl2_base +
+			       DDR4_DBG1_OFFSET);
+			return ret;
+		}
+	}
+	/* Restore user setting */
+	writel(backup, ddr_handoff_info->umctl2_base + DDR4_DBG1_OFFSET);
+	debug("%s: Quasi-dynamic group 3 registers are enabled\n", __func__);
+	return 0;
+}
+static int scrubbing_ddr_config(struct ddr_handoff *ddr_handoff_info)
+{
+	u32 backup[7];
+	int ret;
+	/* Reset to default value, prevent scrubber stop due to lower power */
+	writel(0, ddr_handoff_info->umctl2_base + DDR4_PWRCTL_OFFSET);
+	/* Disable input traffic per port */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_PCTRL0_OFFSET,
+		     DDR4_PCTRL0_PORT_EN);
+	/* Backup user settings */
+	backup[0] = readl(ddr_handoff_info->umctl2_base + DDR4_SBRCTL_OFFSET);
+	backup[1] = readl(ddr_handoff_info->umctl2_base +
+			  DDR4_SBRWDATA0_OFFSET);
+	backup[2] = readl(ddr_handoff_info->umctl2_base +
+			  DDR4_SBRWDATA1_OFFSET);
+	backup[3] = readl(ddr_handoff_info->umctl2_base +
+			  DDR4_SBRSTART0_OFFSET);
+	backup[4] = readl(ddr_handoff_info->umctl2_base +
+			  DDR4_SBRSTART1_OFFSET);
+	backup[5] = readl(ddr_handoff_info->umctl2_base +
+			  DDR4_SBRRANGE0_OFFSET);
+	backup[6] = readl(ddr_handoff_info->umctl2_base +
+			  DDR4_SBRRANGE1_OFFSET);
+	/* Scrub_burst = 1, scrub_mode = 1(performs writes) */
+	writel(DDR_SBRCTL_SCRUB_BURST_1 | DDR4_SBRCTL_SCRUB_WRITE,
+	       ddr_handoff_info->umctl2_base + DDR4_SBRCTL_OFFSET);
+	/* Zeroing whole DDR */
+	writel(0, ddr_handoff_info->umctl2_base +
+	       DDR4_SBRWDATA0_OFFSET);
+	writel(0, ddr_handoff_info->umctl2_base +
+	       DDR4_SBRWDATA1_OFFSET);
+	writel(0, ddr_handoff_info->umctl2_base + DDR4_SBRSTART0_OFFSET);
+	writel(0, ddr_handoff_info->umctl2_base + DDR4_SBRSTART1_OFFSET);
+	writel(0, ddr_handoff_info->umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	writel(0, ddr_handoff_info->umctl2_base + DDR4_SBRRANGE1_OFFSET);
+#ifdef CONFIG_TARGET_SOCFPGA_DM
+	writel(0x0FFFFFFF, ddr_handoff_info->umctl2_base +
+	       DDR4_SBRRANGE0_OFFSET);
+#endif
+	/* Enables scrubber */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_SBRCTL_OFFSET,
+		     DDR4_SBRCTL_SCRUB_EN);
+	/* Polling all scrub writes commands have been sent */
+	ret = wait_for_bit_le32((const void *)(ddr_handoff_info->umctl2_base +
+				DDR4_SBRSTAT_OFFSET), DDR4_SBRSTAT_SCRUB_DONE,
+				true, TIMEOUT_5000MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" sending all scrub commands\n");
+		return ret;
+	}
+	/* Polling all scrub writes data have been sent */
+	ret = wait_for_bit_le32((const void *)(ddr_handoff_info->umctl2_base +
+				DDR4_SBRSTAT_OFFSET), DDR4_SBRSTAT_SCRUB_BUSY,
+				false, TIMEOUT_5000MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" sending all scrub data\n");
+		return ret;
+	}
+	/* Disables scrubber */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_SBRCTL_OFFSET,
+		     DDR4_SBRCTL_SCRUB_EN);
+	/* Restore user settings */
+	writel(backup[0], ddr_handoff_info->umctl2_base + DDR4_SBRCTL_OFFSET);
+	writel(backup[1], ddr_handoff_info->umctl2_base +
+	       DDR4_SBRWDATA0_OFFSET);
+	writel(backup[2], ddr_handoff_info->umctl2_base +
+	       DDR4_SBRWDATA1_OFFSET);
+	writel(backup[3], ddr_handoff_info->umctl2_base +
+	       DDR4_SBRSTART0_OFFSET);
+	writel(backup[4], ddr_handoff_info->umctl2_base +
+	       DDR4_SBRSTART1_OFFSET);
+	writel(backup[5], ddr_handoff_info->umctl2_base +
+	       DDR4_SBRRANGE0_OFFSET);
+	writel(backup[6], ddr_handoff_info->umctl2_base +
+	       DDR4_SBRRANGE1_OFFSET);
+	return 0;
+}
+static int init_umctl2(struct ddr_handoff *ddr_handoff_info, u32 *user_backup)
+{
+	u32 handoff_table[ddr_handoff_info->umctl2_handoff_length];
+	u32 i, value, expected_value;
+	u32 start = get_timer(0);
+	int ret;
+	printf("Initializing DDR controller ...\n");
+	/* Prevent controller from issuing read/write to SDRAM */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_DBG1_OFFSET,
+		     DDR4_DBG1_DISDQ);
+	/* Put SDRAM into self-refresh */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_PWRCTL_OFFSET,
+		     DDR4_PWRCTL_SELFREF_EN);
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_SWCTL_OFFSET,
+		     DDR4_SWCTL_SW_DONE);
+	/* Ensure the controller is in initialization mode */
+	ret = wait_for_bit_le32((const void *)(ddr_handoff_info->umctl2_base +
+				DDR4_STAT_OFFSET), DDR4_STAT_OPERATING_MODE,
+				false, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" init operating mode\n");
+		return ret;
+	}
+	debug("%s: Handoff table address = 0x%p table length = 0x%08x\n",
+	      __func__, (u32 *)handoff_table,
+	      (u32)ddr_handoff_info->umctl2_handoff_length);
+	handoff_read((void *)ddr_handoff_info->umctl2_handoff_base,
+		     handoff_table, ddr_handoff_info->umctl2_handoff_length,
+		     little_endian);
+	for (i = 0; i < ddr_handoff_info->umctl2_handoff_length; i = i + 2) {
+		debug("%s: Absolute addr: 0x%08llx APB offset: 0x%08x",
+		      __func__, handoff_table[i] +
+		      ddr_handoff_info->umctl2_base, handoff_table[i]);
+		debug(" wr = 0x%08x ", handoff_table[i + 1]);
+		writel(handoff_table[i + 1], (uintptr_t)(handoff_table[i] +
+		       ddr_handoff_info->umctl2_base));
+		debug("rd = 0x%08x\n", readl((uintptr_t)(handoff_table[i] +
+		      ddr_handoff_info->umctl2_base)));
+	}
+	/* Backup user settings, restore after DDR up running */
+	*user_backup = readl(ddr_handoff_info->umctl2_base +
+			     DDR4_PWRCTL_OFFSET);
+	/* Polling granularity of refresh mode change to fixed 2x (DDR4) */
+	value = readl(ddr_handoff_info->umctl2_base + DDR4_RFSHCTL3_OFFSET) &
+		      DDR4_RFSHCTL3_REFRESH_MODE;
+	expected_value = FIXED_2X << DDR4_RFSHCTL3_REFRESH_MODE_SHIFT;
+	while (value != expected_value) {
+		if (get_timer(start) > TIMEOUT_200MS) {
+			debug("%s: loop(%u): Timeout while waiting for",
+			      __func__, i + 1);
+			debug(" fine granularity refresh mode change to ");
+			debug("fixed 2x\n");
+			debug("%s: expected_value = 0x%x value= 0x%x\n",
+			      __func__, expected_value, value);
+			return -ETIMEDOUT;
+		}
+		value = readl(ddr_handoff_info->umctl2_base +
+			      DDR4_RFSHCTL3_OFFSET) &
+			      DDR4_RFSHCTL3_REFRESH_MODE;
+	}
+	/* Disable self resfresh */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_PWRCTL_OFFSET,
+		     DDR4_PWRCTL_SELFREF_EN);
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_SWCTL_OFFSET,
+		     DDR4_SWCTL_SW_DONE);
+	/* Enable controller from issuing read/write to SDRAM */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_DBG1_OFFSET,
+		     DDR4_DBG1_DISDQ);
+	/* Release the controller from reset */
+	setbits_le32((uintptr_t)(readl(ddr_handoff_info->mem_reset_base) +
+		     MEM_RST_MGR_STATUS), MEM_RST_MGR_STATUS_AXI_RST |
+		     MEM_RST_MGR_STATUS_CONTROLLER_RST |
+		     MEM_RST_MGR_STATUS_RESET_COMPLETE);
+	printf("DDR controller configuration is completed\n");
+	return 0;
+}
+static int init_phy(struct ddr_handoff *ddr_handoff_info)
+{
+	u32 handoff_table[ddr_handoff_info->phy_handoff_length];
+	u32 i, value;
+	int ret;
+	printf("Initializing DDR PHY ...\n");
+	/* Check DDR4 retry is enabled ? */
+	value = readl(ddr_handoff_info->umctl2_base + DDR4_CRCPARCTL1_OFFSET) &
+		      DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE;
+	if (value) {
+		debug("%s: DDR4 retry is enabled\n", __func__);
+		debug("%s: Disable auto refresh is not supported\n", __func__);
+	} else {
+		/* Disable auto refresh */
+		setbits_le32(ddr_handoff_info->umctl2_base +
+			     DDR4_RFSHCTL3_OFFSET,
+			     DDR4_RFSHCTL3_DIS_AUTO_REFRESH);
+	}
+	/* Disable selfref_en & powerdown_en, nvr disable dfi dram clk */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_PWRCTL_OFFSET,
+		     DDR4_PWRCTL_EN_DFI_DRAM_CLK_DISABLE |
+		     DDR4_PWRCTL_POWERDOWN_EN | DDR4_PWRCTL_SELFREF_EN);
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_SWCTL_OFFSET,
+		     DDR4_SWCTL_SW_DONE);
+	ret = enable_quasi_dynamic_reg_grp3(ddr_handoff_info);
+	if (ret)
+		return ret;
+	/* Masking dfi init complete */
+	clrbits_le32(ddr_handoff_info->umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_COMPLETE_EN);
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(ddr_handoff_info->umctl2_base + DDR4_SWCTL_OFFSET,
+		     DDR4_SWCTL_SW_DONE);
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(ddr_handoff_info->umctl2_base +
+				DDR4_SWSTAT_OFFSET), DDR4_SWSTAT_SW_DONE_ACK,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for", __func__);
+		debug(" programming done\n");
+		return ret;
+	}
+	debug("%s: Handoff table address = 0x%p table length = 0x%08x\n",
+	      __func__, (u32 *)handoff_table,
+	      (u32)ddr_handoff_info->umctl2_handoff_length);
+	/* Execute PHY configuration handoff */
+	handoff_read((void *)ddr_handoff_info->phy_handoff_base, handoff_table,
+		     (u32)ddr_handoff_info->phy_handoff_length, little_endian);
+	for (i = 0; i < ddr_handoff_info->phy_handoff_length; i = i + 2) {
+		/*
+		 * Convert PHY odd offset to even offset that supported by
+		 * ARM processor.
+		 */
+		value = handoff_table[i] << 1;
+		debug("%s: Absolute addr: 0x%08llx, APB offset: 0x%08x ",
+		      __func__, value + ddr_handoff_info->phy_base, value);
+		debug("PHY offset: 0x%08x", handoff_table[i]);
+		debug(" wr = 0x%08x ", handoff_table[i + 1]);
+		writew(handoff_table[i + 1], (uintptr_t)(value +
+		       ddr_handoff_info->phy_base));
+		debug("rd = 0x%08x\n", readw((uintptr_t)(value +
+		      ddr_handoff_info->phy_base)));
+	}
+#ifdef CONFIG_TARGET_SOCFPGA_DM
+	u8 numdbyte = 0x0009;
+	u8 byte, lane;
+	u32 b_addr, c_addr;
+	/* Program TxOdtDrvStren bx_p0 */
+	for (byte = 0; byte < numdbyte; byte++) {
+		c_addr = byte << 13;
+		for (lane = 0; lane <= b_max ; lane++) {
+			b_addr = lane << 9;
+			writew(0x00, (uintptr_t)
+			       (ddr_handoff_info->phy_base +
+			       DDR_PHY_TXODTDRVSTREN_B0_P0 + c_addr +
+			       b_addr));
+		}
+	}
+	/* Program TxOdtDrvStren bx_p1 */
+	for (byte = 0; byte < numdbyte; byte++) {
+		c_addr = byte << 13;
+		for (lane = 0; lane <= b_max ; lane++) {
+			b_addr = lane << 9;
+			writew(0x00, (uintptr_t)
+			       (ddr_handoff_info->phy_base +
+			       DDR_PHY_TXODTDRVSTREN_B0_P1 + c_addr +
+			       b_addr));
+		}
+	}
+	/*
+	 * [phyinit_C_initPhyConfig] Pstate=0, Memclk=1600MHz,
+	 * Programming ARdPtrInitVal to 0x2
+	 * DWC_DDRPHYA_MASTER0_ARdPtrInitVal_p0
+	 */
+	dwc_ddrphy_apb_wr(0x2002e, 0x3);
+	/* [phyinit_C_initPhyConfig] Pstate=1,
+	 * Memclk=1067MHz, Programming ARdPtrInitVal to 0x2
+	 * DWC_DDRPHYA_MASTER0_ARdPtrInitVal_p1
+	 */
+	dwc_ddrphy_apb_wr(0x12002e, 0x3);
+	/* DWC_DDRPHYA_MASTER0_DfiFreqXlat0 */
+	dwc_ddrphy_apb_wr(0x200f0, 0x6666);
+	/* DWC_DDRPHYA_DBYTE0_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x10020, 0x4);
+	/* DWC_DDRPHYA_DBYTE1_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x11020, 0x4);
+	/* DWC_DDRPHYA_DBYTE2_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x12020, 0x4);
+	/* DWC_DDRPHYA_DBYTE3_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x13020, 0x4); //
+	/*  DWC_DDRPHYA_DBYTE4_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x14020, 0x4);
+	/* DWC_DDRPHYA_DBYTE5_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x15020, 0x4);
+	/* DWC_DDRPHYA_DBYTE6_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x16020, 0x4);
+	/* DWC_DDRPHYA_DBYTE7_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x17020, 0x4);
+	/* DWC_DDRPHYA_DBYTE8_DFIMRL_p0 */
+	dwc_ddrphy_apb_wr(0x18020, 0x4);
+	/* DWC_DDRPHYA_MASTER0_HwtMRL_p0 */
+	dwc_ddrphy_apb_wr(0x20020, 0x4);
+#endif
+	printf("DDR PHY configuration is completed\n");
+	return 0;
+}
+static void phy_init_engine(struct ddr_handoff *ddr_handoff_info)
+{
+	u32 i, value;
+	u32 handoff_table[ddr_handoff_info->phy_engine_handoff_length];
+	printf("Load PHY Init Engine ...\n");
+	/* Execute PIE production code handoff */
+	handoff_read((void *)ddr_handoff_info->phy_engine_handoff_base,
+		     handoff_table,
+		     (u32)ddr_handoff_info->phy_engine_handoff_length,
+		     little_endian);
+	for (i = 0; i < ddr_handoff_info->phy_engine_handoff_length;
+	    i = i + 2) {
+		debug("Handoff addr: 0x%8llx ", handoff_table[i] +
+		      ddr_handoff_info->phy_base);
+		/*
+		 * Convert PHY odd offset to even offset that supported by
+		 * ARM processor.
+		 */
+		value = handoff_table[i] << 1;
+		debug("%s: Absolute addr: 0x%08llx, APB offset: 0x%08x ",
+		      __func__, value + ddr_handoff_info->phy_base, value);
+		debug("PHY offset: 0x%08x", handoff_table[i]);
+		debug(" wr = 0x%08x ", handoff_table[i + 1]);
+		writew(handoff_table[i + 1], (uintptr_t)(value +
+		       ddr_handoff_info->phy_base));
+		debug("rd = 0x%08x\n", readw((uintptr_t)(value +
+		      ddr_handoff_info->phy_base)));
+	}
+#ifdef CONFIG_TARGET_SOCFPGA_DM
+	u8 numdbyte = 0x0009;
+	u8 byte, timing_group;
+	u32 b_addr, c_addr;
+	/* Enable access to the PHY configuration registers */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+	/* Program RXPBDLYTG0 bx_p0 */
+	for (byte = 0; byte < numdbyte; byte++) {
+		c_addr = byte << 9;
+		for (timing_group = 0; timing_group <= timing_group_max;
+			timing_group++) {
+			b_addr = timing_group << 1;
+			writew(0x00, (uintptr_t)
+			       (ddr_handoff_info->phy_base +
+			       DDR_PHY_RXPBDLYTG0_R0 + c_addr +
+			       b_addr));
+		}
+	}
+	/* Isolate the APB access from internal CSRs */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+#endif
+	printf("End of loading PHY Init Engine\n");
+}
+int populate_ddr_handoff(struct ddr_handoff *ddr_handoff_info)
+{
+	/* DDR handoff */
+	ddr_handoff_info->mem_reset_base = SOC64_HANDOFF_DDR_MEMRESET_BASE;
+	debug("%s: DDR memory reset base = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->mem_reset_base);
+	debug("%s: DDR memory reset address = 0x%x\n", __func__,
+	      readl(ddr_handoff_info->mem_reset_base));
+	/* DDR controller handoff */
+	ddr_handoff_info->umctl2_handoff_base =
+		SOC64_HANDOFF_DDR_UMCTL2_SECTION;
+	debug("%s: umctl2 handoff base = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->umctl2_handoff_base);
+	ddr_handoff_info->umctl2_base = readl(SOC64_HANDOFF_DDR_UMCTL2_BASE);
+	debug("%s: umctl2 base = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->umctl2_base);
+	ddr_handoff_info->umctl2_total_length =
+			readl(ddr_handoff_info->umctl2_handoff_base +
+			      SOC64_HANDOFF_OFFSET_LENGTH);
+	debug("%s: Umctl2 total length in byte = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->umctl2_total_length);
+	ddr_handoff_info->umctl2_handoff_length =
+		get_handoff_size((void *)ddr_handoff_info->umctl2_handoff_base,
+				 little_endian);
+	debug("%s: Umctl2 handoff length in word(32-bit) = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->umctl2_handoff_length);
+	if (ddr_handoff_info->umctl2_handoff_length < 0)
+		return ddr_handoff_info->umctl2_handoff_length;
+	/* DDR PHY handoff */
+	ddr_handoff_info->phy_handoff_base =
+		ddr_handoff_info->umctl2_handoff_base +
+			ddr_handoff_info->umctl2_total_length;
+	debug("%s: PHY handoff base = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->phy_handoff_base);
+	ddr_handoff_info->phy_base =
+		readl(ddr_handoff_info->phy_handoff_base +
+		      SOC64_HANDOFF_DDR_PHY_BASE_OFFSET);
+	debug("%s: PHY base = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->phy_base);
+	ddr_handoff_info->phy_total_length =
+			readl(ddr_handoff_info->phy_handoff_base +
+			      SOC64_HANDOFF_OFFSET_LENGTH);
+	debug("%s: PHY total length in byte = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->phy_total_length);
+	ddr_handoff_info->phy_handoff_length =
+		get_handoff_size((void *)ddr_handoff_info->phy_handoff_base,
+				 little_endian);
+	debug("%s: PHY handoff length in word(32-bit) = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->phy_handoff_length);
+	if (ddr_handoff_info->phy_handoff_length < 0)
+		return ddr_handoff_info->phy_handoff_length;
+	/* DDR PHY Engine handoff */
+	ddr_handoff_info->phy_engine_handoff_base =
+				ddr_handoff_info->phy_handoff_base +
+					ddr_handoff_info->phy_total_length;
+	debug("%s: PHY base = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->phy_engine_handoff_base);
+	ddr_handoff_info->phy_engine_total_length =
+			readl(ddr_handoff_info->phy_engine_handoff_base +
+			      SOC64_HANDOFF_OFFSET_LENGTH);
+	debug("%s: PHY engine total length in byte = 0x%x\n", __func__,
+	      (u32)ddr_handoff_info->phy_engine_total_length);
+	ddr_handoff_info->phy_engine_handoff_length =
+	get_handoff_size((void *)ddr_handoff_info->phy_engine_handoff_base,
+			 little_endian);
+	debug("%s: PHY engine handoff length in word(32-bit) = 0x%x\n",
+	      __func__, (u32)ddr_handoff_info->phy_engine_handoff_length);
+	if (ddr_handoff_info->phy_engine_handoff_length < 0)
+		return ddr_handoff_info->phy_engine_handoff_length;
+	return 0;
+}
+int enable_ddr_clock(struct udevice *dev)
+{
+	struct clk *ddr_clk;
+	int ret;
+	/* Enable clock before init DDR */
+	ddr_clk = devm_clk_get(dev, "mem_clk");
+	if (!IS_ERR(ddr_clk)) {
+		ret = clk_enable(ddr_clk);
+		if (ret) {
+			printf("%s: Failed to enable DDR clock\n", __func__);
+			return ret;
+		}
+	} else {
+		ret = PTR_ERR(ddr_clk);
+		debug("%s: Failed to get DDR clock from dts\n", __func__);
+		return ret;
+	}
+	printf("%s: DDR clock is enabled\n", __func__);
+	return 0;
+}
+int sdram_mmr_init_full(struct udevice *dev)
+{
+	u32 value, user_backup;
+	u32 start = get_timer(0);
+	int ret;
+	struct bd_info bd;
+	struct ddr_handoff ddr_handoff_info;
+	struct altera_sdram_priv *priv = dev_get_priv(dev);
+	if (!is_ddr_init_skipped()) {
+		printf("%s: SDRAM init in progress ...\n", __func__);
+		ret = populate_ddr_handoff(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to populate DDR handoff\n", __func__);
+			return ret;
+		}
+		/*
+		 * Polling reset complete, must be high to ensure DDR subsystem
+		 * in complete reset state before init DDR clock and DDR
+		 * controller
+		 */
+		ret = wait_for_bit_le32((const void *)((uintptr_t)(readl
+					(ddr_handoff_info.mem_reset_base) +
+					MEM_RST_MGR_STATUS)),
+					MEM_RST_MGR_STATUS_RESET_COMPLETE, true,
+					TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" reset complete done\n");
+			return ret;
+		}
+		ret = enable_ddr_clock(dev);
+		if (ret)
+			return ret;
+		/* Initialize DDR controller */
+		ret = init_umctl2(&ddr_handoff_info, &user_backup);
+		if (ret) {
+			debug("%s: Failed to inilialize DDR controller\n",
+			      __func__);
+			return ret;
+		}
+		/* Initialize DDR PHY */
+		ret = init_phy(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to inilialize DDR PHY\n", __func__);
+			return ret;
+		}
+		/* Reset ARC processor when no using for security purpose */
+		setbits_le16(ddr_handoff_info.phy_base +
+			     DDR_PHY_MICRORESET_OFFSET,
+			     DDR_PHY_MICRORESET_RESET);
+		/* DDR freq set to support DDR4-3200 */
+		phy_init_engine(&ddr_handoff_info);
+		/* Trigger memory controller to init SDRAM */
+		/* Enable quasi-dynamic programing of controller registers */
+		clrbits_le32(ddr_handoff_info.umctl2_base + DDR4_SWCTL_OFFSET,
+			     DDR4_SWCTL_SW_DONE);
+		ret = enable_quasi_dynamic_reg_grp3(&ddr_handoff_info);
+		if (ret)
+			return ret;
+		/* Start DFI init sequence */
+		setbits_le32(ddr_handoff_info.umctl2_base + DDR4_DFIMISC_OFFSET,
+			     DDR4_DFIMISC_DFI_INIT_START);
+		/* Complete quasi-dynamic register programming */
+		setbits_le32(ddr_handoff_info.umctl2_base + DDR4_SWCTL_OFFSET,
+			     DDR4_SWCTL_SW_DONE);
+		/* Polling programming done */
+		ret = wait_for_bit_le32((const void *)
+					(ddr_handoff_info.umctl2_base +
+					DDR4_SWSTAT_OFFSET),
+					DDR4_SWSTAT_SW_DONE_ACK, true,
+					TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" programming done\n");
+			return ret;
+		}
+		/* Polling DFI init complete */
+		ret = wait_for_bit_le32((const void *)
+					(ddr_handoff_info.umctl2_base +
+					DDR4_DFISTAT_OFFSET),
+					DDR4_DFI_INIT_COMPLETE, true,
+					TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" DFI init done\n");
+			return ret;
+		}
+		debug("DFI init completed.\n");
+		/* Enable quasi-dynamic programing of controller registers */
+		clrbits_le32(ddr_handoff_info.umctl2_base + DDR4_SWCTL_OFFSET,
+			     DDR4_SWCTL_SW_DONE);
+		ret = enable_quasi_dynamic_reg_grp3(&ddr_handoff_info);
+		if (ret)
+			return ret;
+		/* Stop DFI init sequence */
+		clrbits_le32(ddr_handoff_info.umctl2_base + DDR4_DFIMISC_OFFSET,
+			     DDR4_DFIMISC_DFI_INIT_START);
+		/* Unmasking dfi init complete */
+		setbits_le32(ddr_handoff_info.umctl2_base + DDR4_DFIMISC_OFFSET,
+			     DDR4_DFIMISC_DFI_INIT_COMPLETE_EN);
+		/* Software exit from self-refresh */
+		clrbits_le32(ddr_handoff_info.umctl2_base + DDR4_PWRCTL_OFFSET,
+			     DDR4_PWRCTL_SELFREF_SW);
+		/* Complete quasi-dynamic register programming */
+		setbits_le32(ddr_handoff_info.umctl2_base + DDR4_SWCTL_OFFSET,
+			     DDR4_SWCTL_SW_DONE);
+		/* Polling programming done */
+		ret = wait_for_bit_le32((const void *)
+					(ddr_handoff_info.umctl2_base +
+					DDR4_SWSTAT_OFFSET),
+					DDR4_SWSTAT_SW_DONE_ACK, true,
+					TIMEOUT_200MS, false);
+		if (ret) {
+			debug("%s: Timeout while waiting for", __func__);
+			debug(" programming done\n");
+			return ret;
+		}
+		debug("DDR programming done\n");
+		/* Polling until SDRAM entered normal operating mode */
+		value = readl(ddr_handoff_info.umctl2_base + DDR4_STAT_OFFSET) &
+			      DDR4_STAT_OPERATING_MODE;
+		while (value != NORMAL_OPM) {
+			if (get_timer(start) > TIMEOUT_200MS) {
+				debug("%s: Timeout while waiting for",
+				      __func__);
+				debug(" DDR enters normal operating mode\n");
+				return -ETIMEDOUT;
+			}
+			value = readl(ddr_handoff_info.umctl2_base +
+				      DDR4_STAT_OFFSET) &
+				      DDR4_STAT_OPERATING_MODE;
+			udelay(1);
+			WATCHDOG_RESET();
+		}
+		debug("DDR entered normal operating mode\n");
+		/* Enabling auto refresh */
+		clrbits_le32(ddr_handoff_info.umctl2_base +
+			     DDR4_RFSHCTL3_OFFSET,
+			     DDR4_RFSHCTL3_DIS_AUTO_REFRESH);
+		/* Checking ECC is enabled? */
+		value = readl(ddr_handoff_info.umctl2_base +
+			      DDR4_ECCCFG0_OFFSET) & DDR4_ECC_MODE;
+		if (value) {
+			printf("%s: ECC is enabled\n", __func__);
+			ret = scrubbing_ddr_config(&ddr_handoff_info);
+			if (ret) {
+				debug("%s: Failed to enable ECC\n", __func__);
+				return ret;
+			}
+		}
+		/* Restore user settings */
+		writel(user_backup, ddr_handoff_info.umctl2_base +
+		       DDR4_PWRCTL_OFFSET);
+		/* Enable input traffic per port */
+		setbits_le32(ddr_handoff_info.umctl2_base + DDR4_PCTRL0_OFFSET,
+			     DDR4_PCTRL0_PORT_EN);
+		printf("%s: DDR init success\n", __func__);
+	}
+	/* 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) {
+		debug("%s: Failed to decode memory node\n",  __func__);
+		return -1;
+	}
+	printf("DDR: %lld MiB\n", gd->ram_size >> 20);
+	priv->info.base = bd.bi_dram[0].start;
+	priv->info.size = gd->ram_size;
+
+	sdram_set_firewall(&bd);
+
+	return 0;
+}
\ No newline at end of file
diff --git a/drivers/ddr/altera/sdram_s10.c b/drivers/ddr/altera/sdram_s10.c
index 4d36fb4533..6b663bbbb8 100644
--- a/drivers/ddr/altera/sdram_s10.c
+++ b/drivers/ddr/altera/sdram_s10.c
@@ -123,20 +123,6 @@ int sdram_mmr_init_full(struct udevice *dev)
 	clrbits_le32(CCU_REG_ADDR(CCU_TCU_MPRT_ADBASE_MEMSPACE1E),
 		     CCU_ADBASE_DI_MASK);
 
-	/* this enables nonsecure access to DDR */
-	/* mpuregion0addr_limit */
-	FW_MPU_DDR_SCR_WRITEL(0xFFFF0000, FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT);
-	FW_MPU_DDR_SCR_WRITEL(0x1F, FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT);
-
-	/* nonmpuregion0addr_limit */
-	FW_MPU_DDR_SCR_WRITEL(0xFFFF0000,
-			      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT);
-	FW_MPU_DDR_SCR_WRITEL(0x1F, FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT);
-
-	/* Enable mpuregion0enable and nonmpuregion0enable */
-	FW_MPU_DDR_SCR_WRITEL(MPUREGION0_ENABLE | NONMPUREGION0_ENABLE,
-			      FW_MPU_DDR_SCR_EN_SET);
-
 	/* Ensure HMC clock is running */
 	if (poll_hmc_clock_status()) {
 		puts("DDR: Error as HMC clock not running\n");
@@ -329,6 +315,8 @@ int sdram_mmr_init_full(struct udevice *dev)
 
 	sdram_size_check(&bd);
 
+	sdram_set_firewall(&bd);
+
 	priv->info.base = bd.bi_dram[0].start;
 	priv->info.size = gd->ram_size;
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 5/5] doc: socfpga: Add secure region change
  2022-09-18 15:12 [PATCH 1/5] arm: socfpga: soc64: Move spl_board_prepare_for_boot() Jit Loon Lim
                   ` (2 preceding siblings ...)
  2022-09-18 15:12 ` [PATCH 4/5] ddr: altera: soc64: Add secure region support for ATF flow Jit Loon Lim
@ 2022-09-18 15:12 ` Jit Loon Lim
  3 siblings, 0 replies; 5+ messages in thread
From: Jit Loon Lim @ 2022-09-18 15:12 UTC (permalink / raw)
  To: u-boot
  Cc: Jagan Teki, Vignesh R, Marek, Simon, Tien Fong, Kok Kiang,
	Siew Chin, Sin Hui, Raaj, Dinesh, Boon Khai, Alif, Teik Heng,
	Hazim, Jit Loon Lim, Sieu Mun Tang, Ley Foon Tan

From: Ley Foon Tan <ley.foon.tan@intel.com>

Add section 3.2 for SDRAM secure region update.

Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@intel.com>
---
 doc/README.socfpga | 327 ++++++++++++++++++++++++---------------------
 1 file changed, 174 insertions(+), 153 deletions(-)

diff --git a/doc/README.socfpga b/doc/README.socfpga
index 4d73398eb9..0518974c1d 100644
--- a/doc/README.socfpga
+++ b/doc/README.socfpga
@@ -1,178 +1,199 @@
-----------------------------------------
-SOCFPGA Documentation for U-Boot and SPL
-----------------------------------------
-
-This README is about U-Boot and SPL support for Altera's ARM Cortex-A9MPCore
-based SOCFPGA. To know more about the hardware itself, please refer to
-www.altera.com.
-
-
-socfpga_dw_mmc
---------------
-
-Here are macro and detailed configuration required to enable DesignWare SDMMC
-controller support within SOCFPGA
-
-#define CONFIG_SYS_MMC_MAX_BLK_COUNT	256
--> Using smaller max blk cnt to avoid flooding the limited stack in OCRAM
-
 ---------------------------------------------------------------------
-Cyclone 5 / Arria 5 generating the handoff header files for U-Boot SPL
+SOCFPGA Documentation for U-Boot and SPL
 ---------------------------------------------------------------------
 
-This text is assuming quartus 16.1, but newer versions will probably work just fine too;
-verified with DE1_SOC_Linux_FB demo project (https://github.com/VCTLabs/DE1_SOC_Linux_FB).
-Updated/working projects should build using either process below.
-
-Note: it *should* work from Quartus 14.0.200 onwards, however, the current vendor demo
-projects must have the IP cores updated as shown below.
-
-Rebuilding your Quartus project
--------------------------------
-
-Choose one of the follwing methods, either command line or GUI.
-
-Using the command line
-~~~~~~~~~~~~~~~~~~~~~~
-
-First run the embedded command shell, using your path to the Quartus install:
-
-  $ /path/to/intelFPGA/16.1/embedded/embedded_command_shell.sh
-
-Then (if necessary) update the IP cores in the project, generate HDL code, and
-build the project:
-
-  $ cd path/to/project/dir
-  $ qsys-generate soc_system.qsys --upgrade-ip-cores
-  $ qsys-generate soc_system.qsys --synthesis=[VERILOG|VHDL]
-  $ quartus_sh --flow compile <project name>
-
-Convert the resulting .sof file (SRAM object file) to .rbf file (Raw bit file):
+This README is about U-Boot and SPL support for Intel SOCFPGA.
+To know more about the hardware itself, please refer to
+https://www.intel.com/content/www/us/en/products/programmable/soc.html
 
-  $ quartus_cpf -c <project_name>.sof soc_system.rbf
 
-
-Generate BSP handoff files
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can run the bsp editor GUI below, or run the following command from the
-project directory:
-
-  $ /path/to/bsb/tools/bsp-create-settings --type spl --bsp-dir build \
-      --preloader-settings-dir hps_isw_handoff/soc_system_hps_0/ \
-      --settings build/settings.bsp
-
-You should use the bsp "build" directory above (ie, where the settings.bsp file is)
-in the following u-boot command to update the board headers.  Once these headers
-are updated for a given project build, u-boot should be configured for the
-project board (eg, de0-nano-sockit) and then build the normal spl build.
-
-Now you can skip the GUI section.
-
-
-Using the Qsys GUI
-~~~~~~~~~~~~~~~~~~
-
-1. Navigate to your project directory
-2. Run Quartus II
-3. Open Project (Ctrl+J), select <project_name>.qpf
-4. Run QSys [Tools->QSys]
-  4.1 In the Open dialog, select '<project_name>.qsys'
-  4.2 In the Open System dialog, wait until completion and press 'Close'
-  4.3 In the Qsys window, click on 'Generate HDL...' in bottom right corner
-     4.3.1 In the 'Generation' window, click 'Generate'
-     4.3.2 In the 'Generate' dialog, wait until completion and click 'Close'
-  4.4 In the QSys window, click 'Finish'
-     4.4.1 In the 'Quartus II' pop up window, click 'OK'
-5. Back in Quartus II main window, do the following
-  5.1 Use Processing -> Start -> Start Analysis & Synthesis (Ctrl+K)
-  5.2 Use Processing -> Start Compilation (Ctrl+L)
-
-    ... this may take some time, have patience ...
-
-6. Start the embedded command shell as shown in the previous section
-  6.1 Change directory to 'software/spl_bsp'
-  6.2 Prepare BSP by launching the BSP editor from ECS
-       => bsp-editor
-  6.3 In BSP editor
-      6.3.1 Use File -> Open
-      6.3.2 Select 'settings.bsp' file
-      6.3.3 Click Generate
-      6.3.4 Click Exit
+Table of Contents
+---------------------------------------------------------------------
+	1. Device Family Support vs Tested Intel Quartus
+	2. Feature Support
+	3. Major Changes and Known Issues
+	4. Cyclone V / Arria V generating the handoff header files for U-Boot SPL
+	5. Arria10 generating the handoff header files for U-Boot SPL
 
 
-Post handoff generation
-~~~~~~~~~~~~~~~~~~~~~~~
+1. Device Family Support vs Tested Intel Quartus
+---------------------------------------------------------------------
 
-Now that the handoff files are generated, U-Boot can be used to process
-the handoff files generated by the bsp-editor. For this, please use the
-following script from the u-boot source tree:
+	Processor			SOCFPGA Device Family		Intel Quartus Prime Pro Edition		Intel Quartus Prime Standard Edition
+	--------------------------------------------------------------------------------------------------------------------------------------------
+	Dual-core ARM Cortex-A9		Cyclone V			N/A					20.1
+					Arria V			N/A					20.1
+					Arria 10			20.1, 20.3					20.1
 
-  $ ./arch/arm/mach-socfpga/qts-filter.sh \
-        <soc_type> \
-        <input_qts_dir> \
-        <input_bsp_dir> \
-        <output_dir>
+	Quad-core ARM Cortex-A53	Stratix 10			20.1, 20.2, 20.3					N/A
+					Agilex				20.1, 20.2, 20.3					N/A
+					Diamond Mesa			Early access					N/A
 
-Process QTS-generated files into U-Boot compatible ones.
 
-    soc_type      - Type of SoC, either 'cyclone5' or 'arria5'.
-    input_qts_dir - Directory with compiled Quartus project
-                    and containing the Quartus project file (QPF).
-    input_bsp_dir - Directory with generated bsp containing
-                    the settings.bsp file.
-    output_dir    - Directory to store the U-Boot compatible
-                    headers.
+2. Feature Support
+---------------------------------------------------------------------
 
-This will generate (or update) the following 4 files:
+	Hardware Feature			Cyclone V	Arria 10	Stratix 10	Agilex		Diamond Mesa
+						Arria V
+	--------------------------------------------------------------------------------------------------------------------
+	SDRAM					Yes		Yes		Yes		Yes		Yes
+	HPS bridge (LWH2F, H2F, F2S)		Yes		Yes		Yes		Yes		Yes
+	HPS cold/warm reset			Yes		Yes		Yes		Yes		Yes
+	FPGA configuration			Yes		Yes		Yes		Yes		No
+	Partial reconfiguration			No		No		Yes		No		No
+	Ethernet (Synopsys EMAC controller)	Yes		Yes		Yes		Yes		Yes
+	Synopsys GPIO controller		Yes		Yes		Yes		Yes		Yes
+	Synopsys UART controller		Yes		Yes		Yes		Yes		Yes
+	Synopsys USB controller			Yes		Yes		Yes		Yes		Yes
+	Synopsys Watchdog timer			Yes		Yes		Yes		Yes		Yes
+	Synopsys I2C master controller		Yes		No		Yes		Yes		Yes
+	Synopsys SDMMC controller		Yes		Yes		Yes		Yes		Yes
+	Cadence QSPI controller			Yes		Yes		Yes		Yes		Yes
+	Denali NAND controller			No		Yes		Yes		Yes		Yes
+	---------------------------------------------------------------------------------------------------------------------
+
+	Software Feature			Cyclone V	Arria 10	Stratix 10	Agilex		Diamond Mesa
+						Arria V
+	---------------------------------------------------------------------------------------------------------------------
+	Remote System Update (RSU) [1]		No		No		Yes		Yes		No
+	ARM Trusted Firmware (ATF) [2]		No		No		Yes		Yes		Yes
+	Vendor Authorized Boot (VAB)		No		No		No		No		Yes
+	---------------------------------------------------------------------------------------------------------------------
+
+3. Major Changes and Known Issues
+---------------------------------------------------------------------
 
-  iocsr_config.h
-  pinmux_config.h
-  pll_config.h
-  sdram_config.h
+	3.1 Support 'vab' command to perform vendor authentication.
 
-These files should be copied into "qts" directory in the board directory
-(see output argument of qts-filter.sh command above).
+		Command format: vab addr len
+		Authorize 'len' bytes starting at 'addr' via vendor public key
 
-Here is an example for the DE-0 Nano SoC after the above rebuild process:
+	3.2 Support SDRAM secure region in U-boot-ATF flow
 
-  $ ll board/terasic/de0-nano-soc/qts/
-  total 36
-  -rw-r--r-- 1 sarnold sarnold 8826 Mar 21 18:11 iocsr_config.h
-  -rw-r--r-- 1 sarnold sarnold 4398 Mar 21 18:11 pinmux_config.h
-  -rw-r--r-- 1 sarnold sarnold 3190 Mar 21 18:11 pll_config.h
-  -rw-r--r-- 1 sarnold sarnold 9022 Mar 21 18:11 sdram_config.h
+		First 1 MiB of SDRAM is configured as secure region, other
+		address spaces are non-secure regions. Only software executing
+		at secure state EL3 (eg: U-boot SPL) and secure masters are
+		allowed access to secure region.
 
-Note: file sizes will differ slightly depending on the selected board.
 
-Now your board is ready for full mainline support including U-Boot SPL.
-The Preloader will not be needed any more.
+4. Cyclone5 / Arria 5 generating the handoff header files for U-Boot SPL
+---------------------------------------------------------------------
+	Rebuilding your Quartus project
+	-------------------------------
+	Choose one of the follwing methods, either command line or GUI.
+	Using the command line
+	~~~~~~~~~~~~~~~~~~~~~~
+	First run the embedded command shell, using your path to the Quartus install:
+	  $ /path/to/intelFPGA/16.1/embedded/embedded_command_shell.sh
+	Then (if necessary) update the IP cores in the project, generate HDL code, and
+	build the project:
+	  $ cd path/to/project/dir
+	  $ qsys-generate soc_system.qsys --upgrade-ip-cores
+	  $ qsys-generate soc_system.qsys --synthesis=[VERILOG|VHDL]
+	  $ quartus_sh --flow compile <project name>
+	Convert the resulting .sof file (SRAM object file) to .rbf file (Raw bit file):
+	  $ quartus_cpf -c <project_name>.sof soc_system.rbf
+	Generate BSP handoff files
+	~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	You can run the bsp editor GUI below, or run the following command from the
+	project directory:
+
+	  $ /path/to/bsb/tools/bsp-create-settings --type spl --bsp-dir build \
+	      --preloader-settings-dir hps_isw_handoff/soc_system_hps_0/ \
+	      --settings build/settings.bsp
+
+	You should use the bsp "build" directory above (ie, where the settings.bsp file is)
+	in the following u-boot command to update the board headers.  Once these headers
+	are updated for a given project build, u-boot should be configured for the
+	project board (eg, de0-nano-sockit) and then build the normal spl build.
+
+	Now you can skip the GUI section.
+
+	Using the Qsys GUI
+	~~~~~~~~~~~~~~~~~~
+	1. Navigate to your project directory
+	2. Run Quartus II
+	3. Open Project (Ctrl+J), select <project_name>.qpf
+	4. Run QSys [Tools->QSys]
+	  4.1 In the Open dialog, select '<project_name>.qsys'
+	  4.2 In the Open System dialog, wait until completion and press 'Close'
+	  4.3 In the Qsys window, click on 'Generate HDL...' in bottom right corner
+	     4.3.1 In the 'Generation' window, click 'Generate'
+	     4.3.2 In the 'Generate' dialog, wait until completion and click 'Close'
+	  4.4 In the QSys window, click 'Finish'
+	     4.4.1 In the 'Quartus II' pop up window, click 'OK'
+	5. Back in Quartus II main window, do the following
+	  5.1 Use Processing -> Start -> Start Analysis & Synthesis (Ctrl+K)
+	  5.2 Use Processing -> Start Compilation (Ctrl+L)
+	    ... this may take some time, have patience ...
+
+	6. Start the embedded command shell as shown in the previous section
+	  $ /path/to/bsb/tools/bsp-create-settings --type spl --bsp-dir build \
+	      --preloader-settings-dir hps_isw_handoff/soc_system_hps_0/ \
+	      --settings build/settings.bsp
+
+	Post handoff generation
+	~~~~~~~~~~~~~~~~~~~~~~~
+	Now that the handoff files are generated, U-Boot can be used to process
+	the handoff files generated by the bsp-editor. For this, please use the
+	following script from the u-boot source tree:
+	  $ ./arch/arm/mach-socfpga/qts-filter.sh \
+		<soc_type> \
+		<input_qts_dir> \
+		<input_bsp_dir> \
+		<output_dir>
+	Process QTS-generated files into U-Boot compatible ones.
+	    soc_type      - Type of SoC, either 'cyclone5' or 'arria5'.
+	    input_qts_dir - Directory with compiled Quartus project
+			    and containing the Quartus project file (QPF).
+	    input_bsp_dir - Directory with generated bsp containing
+			    the settings.bsp file.
+	    output_dir    - Directory to store the U-Boot compatible
+			    headers.
+	This will generate (or update) the following 4 files:
+	  iocsr_config.h
+	  pinmux_config.h
+	  pll_config.h
+	  sdram_config.h
+	These files should be copied into "qts" directory in the board directory
+	(see output argument of qts-filter.sh command above).
+	Here is an example for the DE-0 Nano SoC after the above rebuild process:
+	  $ ll board/terasic/de0-nano-soc/qts/
+	  total 36
+	  -rw-r--r-- 1 sarnold sarnold 8826 Mar 21 18:11 iocsr_config.h
+	  -rw-r--r-- 1 sarnold sarnold 4398 Mar 21 18:11 pinmux_config.h
+	  -rw-r--r-- 1 sarnold sarnold 3190 Mar 21 18:11 pll_config.h
+	  -rw-r--r-- 1 sarnold sarnold 9022 Mar 21 18:11 sdram_config.h
+	Note: file sizes will differ slightly depending on the selected board.
+	      For SoC devkit please refer to https://rocketboards.org/foswiki/Documentation/BuildingBootloader#Cyclone_V_SoC_45_Boot_from_SD_Card
+	Now your board is ready for full mainline support including U-Boot SPL.
+	The Preloader will not be needed any more.
+
+
+5. Arria10 generating the handoff header files for U-Boot SPL
+---------------------------------------------------------------------
 
-----------------------------------------------------------
-Arria 10 generating the handoff header files for U-Boot SPL
-----------------------------------------------------------
+	A header file for inclusion in a devicetree for Arria10 can be generated
+	by the qts-filter-a10.sh script directly from the hps_isw_handoff/hps.xml
+	file generated during the FPGA project compilation.  The header contains
+	all PLL, clock, pinmux, and bridge configurations required.
 
-A header file for inclusion in a devicetree for Arria10 can be generated
-by the qts-filter-a10.sh script directly from the hps_isw_handoff/hps.xml
-file generated during the FPGA project compilation.  The header contains
-all PLL, clock, pinmux, and bridge configurations required.
+	Please look at the socfpga_arria10_socdk_sdmmc-u-boot.dtsi for an example
+	that includes use of the generated handoff header.
 
-Please look at the socfpga_arria10_socdk_sdmmc-u-boot.dtsi for an example
-that includes use of the generated handoff header.
+	Devicetree header generation
+	~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Devicetree header generation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+	The qts-filter-a10.sh script can process the compile time genetated hps.xml
+	to create the appropriate devicetree header.
 
-The qts-filter-a10.sh script can process the compile time genetated hps.xml
-to create the appropriate devicetree header.
+	  $ ./arch/arm/mach-socfpga/qts-filter-a10.sh \
+		<hps_xml> \
+		<output_file>
 
+	    hps_xml      - hps_isw_handoff/hps.xml from Quartus project
+	    output_file  - Output filename and location for header file
 
-  $ ./arch/arm/mach-socfpga/qts-filter-a10.sh \
-        <hps_xml> \
-        <output_file>
-
-    hps_xml      - hps_isw_handoff/hps.xml from Quartus project
-    output_file  - Output filename and location for header file
-
-The script generates a single header file names <output_file> that should
-be placed in arch/arm/dts.
+	The script generates a single header file names <output_file> that should
+	be placed in arch/arm/dts.
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-09-18 15:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-18 15:12 [PATCH 1/5] arm: socfpga: soc64: Move spl_board_prepare_for_boot() Jit Loon Lim
2022-09-18 15:12 ` [PATCH 2/5] arm: socfpga: soc64: Change to use spl_perform_fixups() Jit Loon Lim
2022-09-18 15:12 ` [PATCH 3/5] arm: socfpga: soc64: Move socfpga_init_smmu() to before boot SSBL Jit Loon Lim
2022-09-18 15:12 ` [PATCH 4/5] ddr: altera: soc64: Add secure region support for ATF flow Jit Loon Lim
2022-09-18 15:12 ` [PATCH 5/5] doc: socfpga: Add secure region change Jit Loon Lim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.