u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
* [v3 00/17] Add Intel N5X SoC support
@ 2021-06-13  8:48 Siew Chin Lim
  2021-06-13  8:48 ` [v3 01/17] arm: socfpga: Move linux_qspi_enable from bootcommand to board_prep_linux function Siew Chin Lim
                   ` (16 more replies)
  0 siblings, 17 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

This is the 3rd version of patchset to add Intel N5X SoC[1] support.

Intel N5X SoC is with a 64-bit quad core ARM Cortex-A53 MPCore
hard processor system (HPS). New IPs in N5X are clock manager
and DDR subsystem, other IPs have minor changes compared to Agilex.

Intel N5X SoC supports legacy boot without ATF for debugging purpose,
ATF boot, and ATF boot with VAB enabled.

[1]: https://www.intel.com/content/www/us/en/products/programmable/asic/easic-devices/diamond-mesa-soc-devices.html


Patch status:
Have changes: Patch 4, 5, 7, 12, 15
Other patches unchanged.

Detail changelog can find in commit message.

v2->v3:
--------
Patch 4:
- Adding helper function for getting endianness type.

Patch 5:
- Use BIT() macro for CLKMGR_INTER_*_MASK macro

Patch 7:
- Use BIT() and GENMASK() macro for all *MASK macro

Patch 12:
- Sorting header
- Used prefix OPM_xxx
- Simplify the code with do...while loop.
- Created common function for processing handoff
- Adding function of calibration data feedback to LPDDR4 controllers

Patch 15:
- Update comment for memory example code
- Move all common dts settings for N5X from
  socfpga_n5x_socdk.dts to socfpga_n5x-u-boot.dtsi
- Remove unused parameter "u-boot,boot0"


History:
--------
[v1] https://patchwork.ozlabs.org/project/uboot/cover/20210331143908.48211-1-elly.siew.chin.lim@intel.com/
[v2] https://patchwork.ozlabs.org/project/uboot/cover/20210430073814.193576-1-elly.siew.chin.lim@intel.com/


Siew Chin Lim (14):
  arm: socfpga: Move linux_qspi_enable from bootcommand to
    board_prep_linux function
  arm: socfpga: Changed base_addr_s10.h to base_addr_soc64.h
  arm: socfpga: Add base address for Intel N5X device
  drivers: clk: Add clock driver for Intel N5X device
  arm: socfpga: Get clock manager base address for Intel N5X device
  drivers: clk: Add memory clock driver for Intel N5X device
  arm: socfpga: Move cm_get_mpu_clk_hz function declaration to
    clock_manager.h
  arm: socfpga: Add clock manager for Intel N5X device
  arm: socfpga: Changed misc_s10.c to misc_soc64.c
  arm: socfpga: Add SPL for Intel N5X device
  board: intel: Add socdk board support for Intel N5X device
  arm: dts: Add base dtsi and devkit dts for Intel N5X device
  include: configs: Add Intel N5X device CONFIGs
  arm: socfpga: Enable Intel N5X device build

Tien Fong Chee (3):
  arm: socfpga: Add handoff data support for Intel N5X device
  ddr: socfpga: Enable memory test on memory size less than 1GB
  ddr: altera: Add SDRAM driver for Intel N5X device

 arch/arm/dts/Makefile                         |    1 +
 arch/arm/dts/socfpga_n5x-u-boot.dtsi          |  175 ++
 arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi    |   67 +
 arch/arm/dts/socfpga_n5x_socdk.dts            |  154 ++
 arch/arm/mach-socfpga/Kconfig                 |   21 +-
 arch/arm/mach-socfpga/Makefile                |   32 +-
 arch/arm/mach-socfpga/board.c                 |   17 +-
 arch/arm/mach-socfpga/clock_manager_n5x.c     |   80 +
 .../{base_addr_s10.h => base_addr_soc64.h}    |   11 +-
 .../mach-socfpga/include/mach/clock_manager.h |    3 +
 .../include/mach/clock_manager_agilex.h       |    2 -
 .../include/mach/clock_manager_arria10.h      |    1 -
 .../include/mach/clock_manager_gen5.h         |    1 -
 .../include/mach/clock_manager_n5x.h          |   12 +
 .../include/mach/clock_manager_s10.h          |    1 -
 arch/arm/mach-socfpga/include/mach/firewall.h |    6 +
 .../mach-socfpga/include/mach/handoff_soc64.h |   38 +-
 .../include/mach/system_manager_soc64.h       |   10 +-
 arch/arm/mach-socfpga/misc.c                  |    3 +
 .../mach-socfpga/{misc_s10.c => misc_soc64.c} |   12 +-
 arch/arm/mach-socfpga/spl_n5x.c               |   94 +
 arch/arm/mach-socfpga/system_manager_soc64.c  |   18 +-
 arch/arm/mach-socfpga/wrap_handoff_soc64.c    |  132 +-
 board/intel/n5x-socdk/MAINTAINERS             |    7 +
 board/intel/n5x-socdk/Makefile                |    7 +
 board/intel/n5x-socdk/socfpga.c               |    7 +
 configs/socfpga_agilex_atf_defconfig          |    2 +-
 ...tf_defconfig => socfpga_n5x_atf_defconfig} |   13 +-
 ...ex_atf_defconfig => socfpga_n5x_defconfig} |   29 +-
 ...tf_defconfig => socfpga_n5x_vab_defconfig} |   14 +-
 configs/socfpga_stratix10_atf_defconfig       |    2 +-
 drivers/clk/altera/Makefile                   |    4 +-
 drivers/clk/altera/clk-mem-n5x.c              |  136 +
 drivers/clk/altera/clk-mem-n5x.h              |   84 +
 drivers/clk/altera/clk-n5x.c                  |  489 ++++
 drivers/clk/altera/clk-n5x.h                  |  217 ++
 drivers/ddr/altera/Makefile                   |    3 +-
 drivers/ddr/altera/sdram_n5x.c                | 2298 +++++++++++++++++
 drivers/ddr/altera/sdram_soc64.c              |   94 +-
 drivers/ddr/altera/sdram_soc64.h              |    1 +
 include/configs/socfpga_n5x_socdk.h           |   45 +
 include/configs/socfpga_soc64_common.h        |    2 +-
 include/dt-bindings/clock/n5x-clock.h         |   71 +
 43 files changed, 4296 insertions(+), 120 deletions(-)
 create mode 100644 arch/arm/dts/socfpga_n5x-u-boot.dtsi
 create mode 100644 arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
 create mode 100644 arch/arm/dts/socfpga_n5x_socdk.dts
 create mode 100644 arch/arm/mach-socfpga/clock_manager_n5x.c
 rename arch/arm/mach-socfpga/include/mach/{base_addr_s10.h => base_addr_soc64.h} (85%)
 create mode 100644 arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h
 rename arch/arm/mach-socfpga/{misc_s10.c => misc_soc64.c} (100%)
 create mode 100644 arch/arm/mach-socfpga/spl_n5x.c
 create mode 100644 board/intel/n5x-socdk/MAINTAINERS
 create mode 100644 board/intel/n5x-socdk/Makefile
 create mode 100644 board/intel/n5x-socdk/socfpga.c
 copy configs/{socfpga_agilex_atf_defconfig => socfpga_n5x_atf_defconfig} (83%)
 copy configs/{socfpga_agilex_atf_defconfig => socfpga_n5x_defconfig} (63%)
 copy configs/{socfpga_agilex_atf_defconfig => socfpga_n5x_vab_defconfig} (82%)
 create mode 100644 drivers/clk/altera/clk-mem-n5x.c
 create mode 100644 drivers/clk/altera/clk-mem-n5x.h
 create mode 100644 drivers/clk/altera/clk-n5x.c
 create mode 100644 drivers/clk/altera/clk-n5x.h
 create mode 100644 drivers/ddr/altera/sdram_n5x.c
 create mode 100644 include/configs/socfpga_n5x_socdk.h
 create mode 100644 include/dt-bindings/clock/n5x-clock.h

-- 
2.19.0


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

* [v3 01/17] arm: socfpga: Move linux_qspi_enable from bootcommand to board_prep_linux function
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 02/17] arm: socfpga: Changed base_addr_s10.h to base_addr_soc64.h Siew Chin Lim
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Move 'linux_qspi_enable' from bootcommand to board_prep_linux function when
OS booted from FIT image for Stratix 10 and Agilex. This flow is common for
all Intel SOC64 devices.

U-Boot will update 'fdt_addr' environment value based on FIT image in
board_prep_linux function, and 'linux_qspi_enable' will refer to 'fdt_addr'
environment value to retrieve the device tree node.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 arch/arm/mach-socfpga/board.c           | 17 +++++++++--------
 configs/socfpga_agilex_atf_defconfig    |  2 +-
 configs/socfpga_stratix10_atf_defconfig |  2 +-
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c
index 650122fcd4..f5a3f2ad62 100644
--- a/arch/arm/mach-socfpga/board.c
+++ b/arch/arm/mach-socfpga/board.c
@@ -115,17 +115,18 @@ void board_fit_image_post_process(void **p_image, size_t *p_size)
 #if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_FIT)
 void board_prep_linux(bootm_headers_t *images)
 {
-	if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH) &&
-	    !IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE)) {
-		/*
-		 * Ensure the OS is always booted from FIT and with
-		 * VAB signed certificate
-		 */
-		if (!images->fit_uname_cfg) {
+	if (!images->fit_uname_cfg) {
+		if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH) &&
+		    !IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE)) {
+			/*
+			 * Ensure the OS is always booted from FIT and with
+			 * VAB signed certificate
+			 */
 			printf("Please use FIT with VAB signed images!\n");
 			hang();
 		}
-
+	} else {
+		/* Update fdt_addr in enviroment variable */
 		env_set_hex("fdt_addr", (ulong)images->ft_addr);
 		debug("images->ft_addr = 0x%08lx\n", (ulong)images->ft_addr);
 	}
diff --git a/configs/socfpga_agilex_atf_defconfig b/configs/socfpga_agilex_atf_defconfig
index 29e3fb865e..a4b9c23919 100644
--- a/configs/socfpga_agilex_atf_defconfig
+++ b/configs/socfpga_agilex_atf_defconfig
@@ -22,7 +22,7 @@ CONFIG_BOOTDELAY=5
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="earlycon"
 CONFIG_USE_BOOTCOMMAND=y
-CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run linux_qspi_enable; run mmcfitboot"
+CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
 CONFIG_SPL_CRC32_SUPPORT=y
 CONFIG_SPL_CACHE=y
 CONFIG_SPL_SPI_LOAD=y
diff --git a/configs/socfpga_stratix10_atf_defconfig b/configs/socfpga_stratix10_atf_defconfig
index 9f2f220c3a..3a05d4f486 100644
--- a/configs/socfpga_stratix10_atf_defconfig
+++ b/configs/socfpga_stratix10_atf_defconfig
@@ -22,7 +22,7 @@ CONFIG_BOOTDELAY=5
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="earlycon"
 CONFIG_USE_BOOTCOMMAND=y
-CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run linux_qspi_enable; run mmcfitboot"
+CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
 CONFIG_SPL_CRC32_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SPL_ATF=y
-- 
2.19.0


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

* [v3 02/17] arm: socfpga: Changed base_addr_s10.h to base_addr_soc64.h
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
  2021-06-13  8:48 ` [v3 01/17] arm: socfpga: Move linux_qspi_enable from bootcommand to board_prep_linux function Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 03/17] arm: socfpga: Add base address for Intel N5X device Siew Chin Lim
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Rename to common file name to used by all SOC64 devices and change
"_S10_" to "_SOC64_" in base_addr_soc64.h.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 .../include/mach/{base_addr_s10.h => base_addr_soc64.h}   | 8 ++++----
 include/configs/socfpga_soc64_common.h                    | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)
 rename arch/arm/mach-socfpga/include/mach/{base_addr_s10.h => base_addr_soc64.h} (89%)

diff --git a/arch/arm/mach-socfpga/include/mach/base_addr_s10.h b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
similarity index 89%
rename from arch/arm/mach-socfpga/include/mach/base_addr_s10.h
rename to arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
index d3eca65e97..f89066d771 100644
--- a/arch/arm/mach-socfpga/include/mach/base_addr_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
@@ -1,10 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  */
 
-#ifndef _SOCFPGA_S10_BASE_HARDWARE_H_
-#define _SOCFPGA_S10_BASE_HARDWARE_H_
+#ifndef _SOCFPGA_SOC64_BASE_HARDWARE_H_
+#define _SOCFPGA_SOC64_BASE_HARDWARE_H_
 
 #define SOCFPGA_CCU_ADDRESS			0xf7000000
 #define SOCFPGA_SDR_SCHEDULER_ADDRESS		0xf8000400
@@ -44,4 +44,4 @@
 #define GICD_BASE				0xfffc1000
 #define GICC_BASE				0xfffc2000
 
-#endif /* _SOCFPGA_S10_BASE_HARDWARE_H_ */
+#endif /* _SOCFPGA_SOC64_BASE_HARDWARE_H_ */
diff --git a/include/configs/socfpga_soc64_common.h b/include/configs/socfpga_soc64_common.h
index 5afdb10454..f0b7884ebc 100644
--- a/include/configs/socfpga_soc64_common.h
+++ b/include/configs/socfpga_soc64_common.h
@@ -7,7 +7,7 @@
 #ifndef __CONFIG_SOCFPGA_SOC64_COMMON_H__
 #define __CONFIG_SOCFPGA_SOC64_COMMON_H__
 
-#include <asm/arch/base_addr_s10.h>
+#include <asm/arch/base_addr_soc64.h>
 #include <asm/arch/handoff_soc64.h>
 #include <linux/stringify.h>
 
-- 
2.19.0


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

* [v3 03/17] arm: socfpga: Add base address for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
  2021-06-13  8:48 ` [v3 01/17] arm: socfpga: Move linux_qspi_enable from bootcommand to board_prep_linux function Siew Chin Lim
  2021-06-13  8:48 ` [v3 02/17] arm: socfpga: Changed base_addr_s10.h to base_addr_soc64.h Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 04/17] arm: socfpga: Add handoff data support " Siew Chin Lim
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Reuse base_addr_soc64.h for Intel N5X device, the address is the
same as Agilex.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 arch/arm/mach-socfpga/include/mach/base_addr_soc64.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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 f89066d771..3f899fcfa3 100644
--- a/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
+++ b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h
@@ -10,7 +10,8 @@
 #define SOCFPGA_SDR_SCHEDULER_ADDRESS		0xf8000400
 #define SOCFPGA_HMC_MMR_IO48_ADDRESS		0xf8010000
 #define SOCFPGA_SDR_ADDRESS			0xf8011000
-#ifdef CONFIG_TARGET_SOCFPGA_AGILEX
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX) || \
+	IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
 #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS		0xf8020200
 #else
 #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS		0xf8020100
-- 
2.19.0


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

* [v3 04/17] arm: socfpga: Add handoff data support for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (2 preceding siblings ...)
  2021-06-13  8:48 ` [v3 03/17] arm: socfpga: Add base address for Intel N5X device Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-07-08 16:15   ` Ley Foon Tan
  2021-06-13  8:48 ` [v3 05/17] drivers: clk: Add clock driver " Siew Chin Lim
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

From: Tien Fong Chee <tien.fong.chee@intel.com>

N5X support both HPS handoff data and DDR handoff data.
Existing HPS handoff functions are restructured to support both existing
devices and N5X device.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>

---
v3
- Adding helper function for getting endianness type.

v2:
- Enabled auto detect the endianness from the magic word
- Merged and simplifying the big and little endian flow
---
 .../mach-socfpga/include/mach/handoff_soc64.h |  38 ++++-
 arch/arm/mach-socfpga/system_manager_soc64.c  |  18 +--
 arch/arm/mach-socfpga/wrap_handoff_soc64.c    | 132 +++++++++++++-----
 3 files changed, 140 insertions(+), 48 deletions(-)

diff --git a/arch/arm/mach-socfpga/include/mach/handoff_soc64.h b/arch/arm/mach-socfpga/include/mach/handoff_soc64.h
index 3750216a9a..902fc6bfb5 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-2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -23,8 +23,36 @@
 #define SOC64_HANDOFF_OFFSET_DATA	0x10
 #define SOC64_HANDOFF_SIZE		4096
 
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_STRATIX10) || \
+	IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX)
 #define SOC64_HANDOFF_BASE		0xFFE3F000
 #define SOC64_HANDOFF_MISC		(SOC64_HANDOFF_BASE + 0x610)
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define SOC64_HANDOFF_BASE		0xFFE5F000
+#define SOC64_HANDOFF_MISC		(SOC64_HANDOFF_BASE + 0x630)
+
+/* DDR handoff */
+#define SOC64_HANDOFF_DDR_BASE			0xFFE5C000
+#define SOC64_HANDOFF_DDR_MAGIC			0x48524444
+#define SOC64_HANDOFF_DDR_UMCTL2_MAGIC		0x4C54434D
+#define SOC64_HANDOFF_DDR_UMCTL2_DDR4_TYPE	0x34524444
+#define SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_0_TYPE	0x3044504C
+#define SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_1_TYPE	0x3144504C
+#define SOC64_HANDOFF_DDR_MEMRESET_BASE		(SOC64_HANDOFF_DDR_BASE + 0xC)
+#define SOC64_HANDOFF_DDR_UMCTL2_SECTION	(SOC64_HANDOFF_DDR_BASE + 0x10)
+#define SOC64_HANDOFF_DDR_PHY_MAGIC		0x43594850
+#define SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC	0x45594850
+#define SOC64_HANDOFF_DDR_PHY_BASE_OFFSET	0x8
+#define SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET	0x8
+#define SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET	0xC
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_1D_SECTION	0xFFE50000
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_1D_SECTION	0xFFE58000
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_2D_SECTION	0xFFE44000
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_2D_SECTION	0xFFE4C000
+#define SOC64_HANDOFF_DDR_TRAIN_IMEM_LENGTH	SZ_32K
+#define SOC64_HANDOFF_DDR_TRAIN_DMEM_LENGTH	SZ_16K
+#endif
+
 #define SOC64_HANDOFF_MUX		(SOC64_HANDOFF_BASE + 0x10)
 #define SOC64_HANDOFF_IOCTL		(SOC64_HANDOFF_BASE + 0x1A0)
 #define SOC64_HANDOFF_FPGA		(SOC64_HANDOFF_BASE + 0x330)
@@ -52,11 +80,11 @@
 #include <asm/types.h>
 enum endianness {
 	LITTLE_ENDIAN = 0,
-	BIG_ENDIAN
+	BIG_ENDIAN,
+	UNKNOWN_ENDIANNESS
 };
 
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian);
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
-			 enum endianness big_endian);
+int socfpga_get_handoff_size(void *handoff_address);
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len);
 #endif
 #endif /* _HANDOFF_SOC64_H_ */
diff --git a/arch/arm/mach-socfpga/system_manager_soc64.c b/arch/arm/mach-socfpga/system_manager_soc64.c
index 3b5e774e2d..958bb5107b 100644
--- a/arch/arm/mach-socfpga/system_manager_soc64.c
+++ b/arch/arm/mach-socfpga/system_manager_soc64.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -66,10 +66,10 @@ void populate_sysmgr_fpgaintf_module(void)
 void populate_sysmgr_pinmux(void)
 {
 	u32 len, i;
-	u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX, BIG_ENDIAN);
-	u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL, BIG_ENDIAN);
-	u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA, BIG_ENDIAN);
-	u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY, BIG_ENDIAN);
+	u32 len_mux = socfpga_get_handoff_size((void *)SOC64_HANDOFF_MUX);
+	u32 len_ioctl = socfpga_get_handoff_size((void *)SOC64_HANDOFF_IOCTL);
+	u32 len_fpga = socfpga_get_handoff_size((void *)SOC64_HANDOFF_FPGA);
+	u32 len_delay = socfpga_get_handoff_size((void *)SOC64_HANDOFF_DELAY);
 
 	len = (len_mux > len_ioctl) ? len_mux : len_ioctl;
 	len = (len > len_fpga) ? len : len_fpga;
@@ -79,7 +79,7 @@ void populate_sysmgr_pinmux(void)
 
 	/* setup the pin sel */
 	len = (len_mux < SOC64_HANDOFF_MUX_LEN) ? len_mux : SOC64_HANDOFF_MUX_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_MUX, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
@@ -89,7 +89,7 @@ void populate_sysmgr_pinmux(void)
 
 	/* setup the pin ctrl */
 	len = (len_ioctl < SOC64_HANDOFF_IOCTL_LEN) ? len_ioctl : SOC64_HANDOFF_IOCTL_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_IOCTL, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
@@ -99,7 +99,7 @@ void populate_sysmgr_pinmux(void)
 
 	/* setup the fpga use */
 	len = (len_fpga < SOC64_HANDOFF_FPGA_LEN) ? len_fpga : SOC64_HANDOFF_FPGA_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_FPGA, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
@@ -109,7 +109,7 @@ void populate_sysmgr_pinmux(void)
 
 	/* setup the IO delay */
 	len = (len_delay < SOC64_HANDOFF_DELAY_LEN) ? len_delay : SOC64_HANDOFF_DELAY_LEN;
-	socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len, BIG_ENDIAN);
+	socfpga_handoff_read((void *)SOC64_HANDOFF_DELAY, handoff_table, len);
 	for (i = 0; i < len; i = i + 2) {
 		writel(handoff_table[i + 1],
 		       handoff_table[i] +
diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
index a7ad7a18ed..e7cb5ea89c 100644
--- a/arch/arm/mach-socfpga/wrap_handoff_soc64.c
+++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -10,12 +10,64 @@
 #include <errno.h>
 #include "log.h"
 
-int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
+static enum endianness check_endianness(u32 handoff)
+{
+	switch (handoff) {
+	case SOC64_HANDOFF_MAGIC_BOOT:
+	case SOC64_HANDOFF_MAGIC_MUX:
+	case SOC64_HANDOFF_MAGIC_IOCTL:
+	case SOC64_HANDOFF_MAGIC_FPGA:
+	case SOC64_HANDOFF_MAGIC_DELAY:
+	case SOC64_HANDOFF_MAGIC_CLOCK:
+	case SOC64_HANDOFF_MAGIC_MISC:
+		return BIG_ENDIAN;
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
+		debug("%s: umctl2 handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+	case SOC64_HANDOFF_DDR_PHY_MAGIC:
+		debug("%s: PHY handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+	case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
+		debug("%s: PHY engine handoff data\n", __func__);
+		return LITTLE_ENDIAN;
+#endif
+	default:
+		debug("%s: Unknown endianness!!\n", __func__);
+		return UNKNOWN_ENDIANNESS;
+	}
+}
+
+static int getting_endianness(void *handoff_address, enum endianness *endian_t)
+{
+	/* Checking handoff data is little endian ? */
+	*endian_t = check_endianness(readl(handoff_address));
+
+	if (*endian_t == UNKNOWN_ENDIANNESS) {
+		/* Trying to check handoff data is big endian? */
+		*endian_t = check_endianness(swab32(readl(handoff_address)));
+		if (*endian_t == UNKNOWN_ENDIANNESS) {
+			debug("%s: Cannot find HANDOFF MAGIC ", __func__);
+			debug("at addr 0x%p\n", (u32 *)handoff_address);
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+int socfpga_get_handoff_size(void *handoff_address)
 {
 	u32 size;
+	int ret;
+	enum endianness endian_t;
+
+	ret = getting_endianness(handoff_address, &endian_t);
+	if (ret)
+		return ret;
 
 	size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
-	if (endian == BIG_ENDIAN)
+	if (endian_t == BIG_ENDIAN)
 		size = swab32(size);
 
 	size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
@@ -26,41 +78,53 @@ int socfpga_get_handoff_size(void *handoff_address, enum endianness endian)
 	return size;
 }
 
-int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len,
-			 enum endianness big_endian)
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
 {
-	u32 temp, i;
+	u32 temp;
 	u32 *table_x32 = table;
+	u32 i = 0;
+	int ret;
+	enum endianness endian_t;
 
-	debug("%s: handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
-
-	if (big_endian) {
-		if (swab32(readl(SOC64_HANDOFF_BASE)) == SOC64_HANDOFF_MAGIC_BOOT) {
-			debug("Handoff table address = 0x%p ", table_x32);
-			debug("table length = 0x%x\n", table_len);
-			debug("%s: handoff data =\n{\n", __func__);
-
-			for (i = 0; i < table_len; i++) {
-				temp = readl(handoff_address +
-					     SOC64_HANDOFF_OFFSET_DATA +
-					     (i * sizeof(u32)));
-				*table_x32 = swab32(temp);
-
-				if (!(i % 2))
-					debug(" No.%d Addr 0x%08x: ", i,
-					      *table_x32);
-				else
-					debug(" 0x%08x\n", *table_x32);
-
-				table_x32++;
-			}
-			debug("\n}\n");
-		} else {
-			debug("%s: Cannot find SOC64_HANDOFF_MAGIC_BOOT ", __func__);
-			debug("at addr  0x%p\n", (u32 *)handoff_address);
-			return -EPERM;
-		}
+	ret = getting_endianness(handoff_address, &endian_t);
+	if (ret)
+		return ret;
+
+	temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
+		    (i * sizeof(u32)));
+
+	if (endian_t == BIG_ENDIAN) {
+		debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
+		debug("Handoff table address = 0x%p ", table_x32);
+		debug("table length = 0x%x\n", table_len);
+		debug("%s: handoff data =\n{\n", __func__);
+		*table_x32 = swab32(temp);
+	} else if (endian_t == LITTLE_ENDIAN) {
+		debug(" {\n");
+		*table_x32 = temp;
+	}
+
+	debug(" No.%d Addr 0x%08x: ", i, *table_x32);
+
+	for (i = 1; i < table_len; i++) {
+		table_x32++;
+
+		temp = readl(handoff_address +
+			     SOC64_HANDOFF_OFFSET_DATA +
+			     (i * sizeof(u32)));
+
+		if (endian_t == BIG_ENDIAN)
+			*table_x32 = swab32(temp);
+		else if (endian_t == LITTLE_ENDIAN)
+			*table_x32 = temp;
+
+		if (!(i % 2))
+			debug(" No.%d Addr 0x%08x: ", i,
+			      *table_x32);
+		else
+			debug(" 0x%08x\n", *table_x32);
 	}
+	debug("\n}\n");
 
 	return 0;
 }
-- 
2.19.0


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

* [v3 05/17] drivers: clk: Add clock driver for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (3 preceding siblings ...)
  2021-06-13  8:48 ` [v3 04/17] arm: socfpga: Add handoff data support " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-07-08 16:17   ` Ley Foon Tan
  2021-06-13  8:48 ` [v3 06/17] arm: socfpga: Get clock manager base address " Siew Chin Lim
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add clock manager driver for N5X. Provides clock initialization
and get_rate functions.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>

---
v3:
- Use BIT() macro for CLKMGR_INTER_*_MASK macro

v2:
- common.h need to be included before clock_manager.h
- Remove unnecessary comment : write 1 to clear
- Remove unnecessary () in the code
---
 drivers/clk/altera/Makefile           |   3 +-
 drivers/clk/altera/clk-n5x.c          | 489 ++++++++++++++++++++++++++
 drivers/clk/altera/clk-n5x.h          | 217 ++++++++++++
 include/dt-bindings/clock/n5x-clock.h |  71 ++++
 4 files changed, 779 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/altera/clk-n5x.c
 create mode 100644 drivers/clk/altera/clk-n5x.h
 create mode 100644 include/dt-bindings/clock/n5x-clock.h

diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile
index 96215ad5c4..38cd730685 100644
--- a/drivers/clk/altera/Makefile
+++ b/drivers/clk/altera/Makefile
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-# Copyright (C) 2018 Marek Vasut <marex@denx.de>
+# Copyright (C) 2018-2021 Marek Vasut <marex@denx.de>
 #
 
 obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += clk-agilex.o
 obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o
+obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-n5x.o
diff --git a/drivers/clk/altera/clk-n5x.c b/drivers/clk/altera/clk-n5x.c
new file mode 100644
index 0000000000..bdcbbaae91
--- /dev/null
+++ b/drivers/clk/altera/clk-n5x.c
@@ -0,0 +1,489 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/util.h>
+#include <dt-bindings/clock/n5x-clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct socfpga_clk_plat {
+	void __iomem *regs;
+};
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+static void clk_write_bypass_mainpll(struct socfpga_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS);
+	cm_wait_for_fsm();
+}
+
+static void clk_write_bypass_perpll(struct socfpga_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS);
+	cm_wait_for_fsm();
+}
+
+/* function to write the ctrl register which requires a poll of the busy bit */
+static void clk_write_ctrl(struct socfpga_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, CLKMGR_CTRL);
+	cm_wait_for_fsm();
+}
+
+/*
+ * Setup clocks while making no assumptions about previous state of the clocks.
+ */
+static void clk_basic_init(struct udevice *dev,
+			   const struct cm_config * const cfg)
+{
+	struct socfpga_clk_plat *plat = dev_get_plat(dev);
+
+	if (!cfg)
+		return;
+
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+	/* Always force clock manager into boot mode before any configuration */
+	clk_write_ctrl(plat,
+		       CM_REG_READL(plat, CLKMGR_CTRL) | CLKMGR_CTRL_BOOTMODE);
+#else
+	/* Skip clock configuration in SSBL if it's not in boot mode */
+	if (!(CM_REG_READL(plat, CLKMGR_CTRL) & CLKMGR_CTRL_BOOTMODE))
+		return;
+#endif
+
+	/* Put both PLLs in bypass */
+	clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL);
+	clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL);
+
+	/* Put both PLLs in Reset */
+	CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+	CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+
+	/* setup main PLL */
+	CM_REG_WRITEL(plat, cfg->main_pll_pllglob, CLKMGR_MAINPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, cfg->main_pll_plldiv, CLKMGR_MAINPLL_PLLDIV);
+	CM_REG_WRITEL(plat, cfg->main_pll_plloutdiv, CLKMGR_MAINPLL_PLLOUTDIV);
+	CM_REG_WRITEL(plat, cfg->main_pll_mpuclk, CLKMGR_MAINPLL_MPUCLK);
+	CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK);
+	CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV);
+
+	/* setup peripheral */
+	CM_REG_WRITEL(plat, cfg->per_pll_pllglob, CLKMGR_PERPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, cfg->per_pll_plldiv, CLKMGR_PERPLL_PLLDIV);
+	CM_REG_WRITEL(plat, cfg->per_pll_plloutdiv, CLKMGR_PERPLL_PLLOUTDIV);
+	CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL);
+	CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV);
+
+	/* Take both PLL out of reset and power up */
+	CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+	CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLCTRL,
+		       CLKMGR_PLLCTRL_BYPASS_MASK);
+
+	cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK);
+
+	CM_REG_WRITEL(plat, cfg->alt_emacactr, CLKMGR_ALTR_EMACACTR);
+	CM_REG_WRITEL(plat, cfg->alt_emacbctr, CLKMGR_ALTR_EMACBCTR);
+	CM_REG_WRITEL(plat, cfg->alt_emacptpctr, CLKMGR_ALTR_EMACPTPCTR);
+	CM_REG_WRITEL(plat, cfg->alt_gpiodbctr, CLKMGR_ALTR_GPIODBCTR);
+	CM_REG_WRITEL(plat, cfg->alt_sdmmcctr, CLKMGR_ALTR_SDMMCCTR);
+	CM_REG_WRITEL(plat, cfg->alt_s2fuser0ctr, CLKMGR_ALTR_S2FUSER0CTR);
+	CM_REG_WRITEL(plat, cfg->alt_s2fuser1ctr, CLKMGR_ALTR_S2FUSER1CTR);
+	CM_REG_WRITEL(plat, cfg->alt_psirefctr, CLKMGR_ALTR_PSIREFCTR);
+
+	/* Configure ping pong counters in altera group */
+	CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK);
+	CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK);
+
+	CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) |
+			CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+			CLKMGR_MAINPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) |
+			CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+			CLKMGR_PERPLL_PLLGLOB);
+
+	/* Take all PLLs out of bypass */
+	clk_write_bypass_mainpll(plat, 0);
+	clk_write_bypass_perpll(plat, 0);
+
+	/* Clear the loss of lock bits */
+	CM_REG_CLRBITS(plat, CLKMGR_INTRCLR,
+		       CLKMGR_INTER_PERPLLLOST_MASK |
+		       CLKMGR_INTER_MAINPLLLOST_MASK);
+
+	/* Take all ping pong counters out of reset */
+	CM_REG_CLRBITS(plat, CLKMGR_ALTR_EXTCNTRST,
+		       CLKMGR_ALT_EXTCNTRST_ALLCNTRST_MASK);
+
+	/* Out of boot mode */
+	clk_write_ctrl(plat,
+		       CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE);
+}
+
+static u32 clk_get_5_1_clk_src(struct socfpga_clk_plat *plat, u32 reg)
+{
+	u32 clksrc = CM_REG_READL(plat, reg);
+
+	return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET;
+}
+
+static u64 clk_get_pll_output_hz(struct socfpga_clk_plat *plat,
+				 u32 pllglob_reg, u32 plldiv_reg)
+{
+	u64 clock = 0;
+	u32 clklsrc, divf, divr, divq, power = 1;
+
+	/* Get input clock frequency */
+	clklsrc = (CM_REG_READL(plat, pllglob_reg) &
+		   CLKMGR_PLLGLOB_VCO_PSRC_MASK) >>
+		   CLKMGR_PLLGLOB_VCO_PSRC_OFFSET;
+
+	switch (clklsrc) {
+	case CLKMGR_VCO_PSRC_EOSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_F2S:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	/* Calculate pll out clock frequency */
+	divf = (CM_REG_READL(plat, plldiv_reg) &
+		CLKMGR_PLLDIV_FDIV_MASK) >>
+		CLKMGR_PLLDIV_FDIV_OFFSET;
+
+	divr = (CM_REG_READL(plat, plldiv_reg) &
+		CLKMGR_PLLDIV_REFCLKDIV_MASK) >>
+		CLKMGR_PLLDIV_REFCLKDIV_OFFSET;
+
+	divq = (CM_REG_READL(plat, plldiv_reg) &
+		CLKMGR_PLLDIV_OUTDIV_QDIV_MASK) >>
+		CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET;
+
+	while (divq) {
+		power *= 2;
+		divq--;
+	}
+
+	return (clock * 2 * (divf + 1)) / ((divr + 1) * power);
+}
+
+static u64 clk_get_clksrc_hz(struct socfpga_clk_plat *plat, u32 clksrc_reg,
+			     u32 main_div, u32 per_div)
+{
+	u64 clock = 0;
+	u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg);
+
+	switch (clklsrc) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_MAINPLL_PLLGLOB,
+					      CLKMGR_MAINPLL_PLLDIV);
+		clock /= 1 + main_div;
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_PERPLL_PLLGLOB,
+					      CLKMGR_PERPLL_PLLDIV);
+		clock /= 1 + per_div;
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	default:
+		return 0;
+	}
+
+	return clock;
+}
+
+static u64 clk_get_mpu_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u32 mainpll_c0cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
+			     CLKMGR_PLLOUTDIV_C0CNT_MASK) >>
+			     CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
+
+	u32 perpll_c0cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
+			    CLKMGR_PLLOUTDIV_C0CNT_MASK) >>
+			    CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
+
+	u64 clock = clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_MPUCLK,
+				      mainpll_c0cnt, perpll_c0cnt);
+
+	clock /= 1 + (CM_REG_READL(plat, CLKMGR_MAINPLL_MPUCLK) &
+		      CLKMGR_CLKCNT_MSK);
+
+	return clock;
+}
+
+static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u32 mainpll_c1cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
+			     CLKMGR_PLLOUTDIV_C1CNT_MASK) >>
+			     CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
+
+	u32 perpll_c1cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
+			    CLKMGR_PLLOUTDIV_C1CNT_MASK) >>
+			    CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
+
+	return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK,
+				 mainpll_c1cnt, perpll_c1cnt);
+}
+
+static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u64 clock = clk_get_l3_main_clk_hz(plat);
+
+	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4MAIN_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u32 mainpll_c3cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
+			     CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+			     CLKMGR_PLLOUTDIV_C3CNT_OFFSET;
+
+	u32 perpll_c3cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
+			    CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+			    CLKMGR_PLLOUTDIV_C3CNT_OFFSET;
+
+	u64 clock = clk_get_clksrc_hz(plat, CLKMGR_ALTR_SDMMCCTR,
+				      mainpll_c3cnt, perpll_c3cnt);
+
+	clock /= 1 + (CM_REG_READL(plat, CLKMGR_ALTR_SDMMCCTR) &
+		      CLKMGR_CLKCNT_MSK);
+
+	return clock / 4;
+}
+
+static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u64 clock = clk_get_l3_main_clk_hz(plat);
+
+	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4SPCLK_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_plat *plat)
+{
+	u64 clock = clk_get_l3_main_clk_hz(plat);
+
+	clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4MPCLK_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_plat *plat)
+{
+	if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE)
+		return clk_get_l3_main_clk_hz(plat) / 2;
+
+	return clk_get_l3_main_clk_hz(plat) / 4;
+}
+
+static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id)
+{
+	bool emacsel_a;
+	u32 ctl;
+	u32 ctr_reg;
+	u32 clock;
+	u32 div;
+	u32 reg;
+
+	/* Get EMAC clock source */
+	ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL);
+	if (emac_id == N5X_EMAC0_CLK)
+		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) &
+		       CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK;
+	else if (emac_id == N5X_EMAC1_CLK)
+		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) &
+		       CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK;
+	else if (emac_id == N5X_EMAC2_CLK)
+		ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) &
+		       CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK;
+	else
+		return 0;
+
+	if (ctl) {
+		/* EMAC B source */
+		emacsel_a = false;
+		ctr_reg = CLKMGR_ALTR_EMACBCTR;
+	} else {
+		/* EMAC A source */
+		emacsel_a = true;
+		ctr_reg = CLKMGR_ALTR_EMACACTR;
+	}
+
+	reg = CM_REG_READL(plat, ctr_reg);
+	clock = (reg & CLKMGR_ALT_EMACCTR_SRC_MASK)
+		 >> CLKMGR_ALT_EMACCTR_SRC_OFFSET;
+	div = (reg & CLKMGR_ALT_EMACCTR_CNT_MASK)
+	       >> CLKMGR_ALT_EMACCTR_CNT_OFFSET;
+
+	switch (clock) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_MAINPLL_PLLGLOB,
+					      CLKMGR_MAINPLL_PLLDIV);
+
+		if (emacsel_a) {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_MAINPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C2CNT_MASK) >>
+				       CLKMGR_PLLOUTDIV_C2CNT_OFFSET);
+		} else {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_MAINPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
+				       CLKMGR_PLLOUTDIV_C3CNT_OFFSET);
+		}
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = clk_get_pll_output_hz(plat,
+					      CLKMGR_PERPLL_PLLGLOB,
+					      CLKMGR_PERPLL_PLLDIV);
+		if (emacsel_a) {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_PERPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C2CNT_MASK) >>
+				       CLKMGR_PLLOUTDIV_C2CNT_OFFSET);
+		} else {
+			clock /= 1 + ((CM_REG_READL(plat,
+				       CLKMGR_PERPLL_PLLOUTDIV) &
+				       CLKMGR_PLLOUTDIV_C3CNT_MASK >>
+				       CLKMGR_PLLOUTDIV_C3CNT_OFFSET));
+		}
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	clock /= 1 + div;
+
+	return clock;
+}
+
+static ulong socfpga_clk_get_rate(struct clk *clk)
+{
+	struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
+
+	switch (clk->id) {
+	case N5X_MPU_CLK:
+		return clk_get_mpu_clk_hz(plat);
+	case N5X_L4_MAIN_CLK:
+		return clk_get_l4_main_clk_hz(plat);
+	case N5X_L4_SYS_FREE_CLK:
+		return clk_get_l4_sys_free_clk_hz(plat);
+	case N5X_L4_MP_CLK:
+		return clk_get_l4_mp_clk_hz(plat);
+	case N5X_L4_SP_CLK:
+		return clk_get_l4_sp_clk_hz(plat);
+	case N5X_SDMMC_CLK:
+		return clk_get_sdmmc_clk_hz(plat);
+	case N5X_EMAC0_CLK:
+	case N5X_EMAC1_CLK:
+	case N5X_EMAC2_CLK:
+		return clk_get_emac_clk_hz(plat, clk->id);
+	case N5X_USB_CLK:
+	case N5X_NAND_X_CLK:
+		return clk_get_l4_mp_clk_hz(plat);
+	case N5X_NAND_CLK:
+		return clk_get_l4_mp_clk_hz(plat) / 4;
+	default:
+		return -ENXIO;
+	}
+}
+
+static int socfpga_clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+static int socfpga_clk_probe(struct udevice *dev)
+{
+	const struct cm_config *cm_default_cfg = cm_get_default_config();
+
+	clk_basic_init(dev, cm_default_cfg);
+
+	return 0;
+}
+
+static int socfpga_clk_of_to_plat(struct udevice *dev)
+{
+	struct socfpga_clk_plat *plat = dev_get_plat(dev);
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	plat->regs = (void __iomem *)addr;
+
+	return 0;
+}
+
+static struct clk_ops socfpga_clk_ops = {
+	.enable		= socfpga_clk_enable,
+	.get_rate	= socfpga_clk_get_rate,
+};
+
+static const struct udevice_id socfpga_clk_match[] = {
+	{ .compatible = "intel,n5x-clkmgr" },
+	{}
+};
+
+U_BOOT_DRIVER(socfpga_n5x_clk) = {
+	.name		= "clk-n5x",
+	.id		= UCLASS_CLK,
+	.of_match	= socfpga_clk_match,
+	.ops		= &socfpga_clk_ops,
+	.probe		= socfpga_clk_probe,
+	.of_to_plat	= socfpga_clk_of_to_plat,
+	.plat_auto	= sizeof(struct socfpga_clk_plat),
+};
diff --git a/drivers/clk/altera/clk-n5x.h b/drivers/clk/altera/clk-n5x.h
new file mode 100644
index 0000000000..8c00e90f89
--- /dev/null
+++ b/drivers/clk/altera/clk-n5x.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#ifndef	_CLK_N5X_
+#define	_CLK_N5X_
+
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+#define CM_REG_READL(plat, reg)				\
+	readl((plat)->regs + (reg))
+
+#define CM_REG_WRITEL(plat, data, reg)			\
+	writel(data, (plat)->regs + (reg))
+
+#define CM_REG_CLRBITS(plat, reg, clear)		\
+	clrbits_le32((plat)->regs + (reg), (clear))
+
+#define CM_REG_SETBITS(plat, reg, set)			\
+	setbits_le32((plat)->regs + (reg), (set))
+
+struct cm_config {
+	/* main group */
+	u32 main_pll_mpuclk;
+	u32 main_pll_nocclk;
+	u32 main_pll_nocdiv;
+	u32 main_pll_pllglob;
+	u32 main_pll_plldiv;
+	u32 main_pll_plloutdiv;
+	u32 spare_1[4];
+
+	/* peripheral group */
+	u32 per_pll_emacctl;
+	u32 per_pll_gpiodiv;
+	u32 per_pll_pllglob;
+	u32 per_pll_plldiv;
+	u32 per_pll_plloutdiv;
+	u32 spare_2[4];
+
+	/* altera group */
+	u32 alt_emacactr;
+	u32 alt_emacbctr;
+	u32 alt_emacptpctr;
+	u32 alt_gpiodbctr;
+	u32 alt_sdmmcctr;
+	u32 alt_s2fuser0ctr;
+	u32 alt_s2fuser1ctr;
+	u32 alt_psirefctr;
+
+	/* incoming clock */
+	u32 hps_osc_clk_hz;
+	u32 fpga_clk_hz;
+	u32 spare_3[3];
+
+	/* memory clock group */
+	u32 mem_memdiv;
+	u32 mem_pllglob;
+	u32 mem_plldiv;
+	u32 mem_plloutdiv;
+	u32 spare_4[4];
+};
+
+/* Clock Manager registers */
+#define CLKMGR_CTRL					0
+#define CLKMGR_STAT					4
+#define CLKMGR_TESTIOCTRL				8
+#define CLKMGR_INTRGEN					0x0c
+#define CLKMGR_INTRMSK					0x10
+#define CLKMGR_INTRCLR					0x14
+#define CLKMGR_INTRSTS					0x18
+#define CLKMGR_INTRSTK					0x1c
+#define CLKMGR_INTRRAW					0x20
+
+/* Clock Manager Main PPL group registers */
+#define CLKMGR_MAINPLL_EN				0x24
+#define CLKMGR_MAINPLL_ENS				0x28
+#define CLKMGR_MAINPLL_ENR				0x2c
+#define CLKMGR_MAINPLL_BYPASS				0x30
+#define CLKMGR_MAINPLL_BYPASSS				0x34
+#define CLKMGR_MAINPLL_BYPASSR				0x38
+#define CLKMGR_MAINPLL_MPUCLK				0x3c
+#define CLKMGR_MAINPLL_NOCCLK				0x40
+#define CLKMGR_MAINPLL_NOCDIV				0x44
+#define CLKMGR_MAINPLL_PLLGLOB				0x48
+#define CLKMGR_MAINPLL_PLLCTRL				0x4c
+#define CLKMGR_MAINPLL_PLLDIV				0x50
+#define CLKMGR_MAINPLL_PLLOUTDIV			0x54
+#define CLKMGR_MAINPLL_LOSTLOCK				0x58
+
+/* Clock Manager Peripheral PPL group registers */
+#define CLKMGR_PERPLL_EN				0x7c
+#define CLKMGR_PERPLL_ENS				0x80
+#define CLKMGR_PERPLL_ENR				0x84
+#define CLKMGR_PERPLL_BYPASS				0x88
+#define CLKMGR_PERPLL_BYPASSS				0x8c
+#define CLKMGR_PERPLL_BYPASSR				0x90
+#define CLKMGR_PERPLL_EMACCTL				0x94
+#define CLKMGR_PERPLL_GPIODIV				0x98
+#define CLKMGR_PERPLL_PLLGLOB				0x9c
+#define CLKMGR_PERPLL_PLLCTRL				0xa0
+#define CLKMGR_PERPLL_PLLDIV				0xa4
+#define CLKMGR_PERPLL_PLLOUTDIV				0xa8
+#define CLKMGR_PERPLL_LOSTLOCK				0xac
+
+/* Clock Manager Altera group registers */
+#define CLKMGR_ALTR_EMACACTR				0xd4
+#define CLKMGR_ALTR_EMACBCTR				0xd8
+#define CLKMGR_ALTR_EMACPTPCTR				0xdc
+#define CLKMGR_ALTR_GPIODBCTR				0xe0
+#define CLKMGR_ALTR_SDMMCCTR				0xe4
+#define CLKMGR_ALTR_S2FUSER0CTR				0xe8
+#define CLKMGR_ALTR_S2FUSER1CTR				0xec
+#define CLKMGR_ALTR_PSIREFCTR				0xf0
+#define CLKMGR_ALTR_EXTCNTRST				0xf4
+
+#define CLKMGR_CTRL_BOOTMODE				BIT(0)
+
+#define CLKMGR_STAT_BUSY				BIT(0)
+#define CLKMGR_STAT_MAINPLL_LOCKED			BIT(8)
+#define CLKMGR_STAT_MAIN_TRANS				BIT(9)
+#define CLKMGR_STAT_PERPLL_LOCKED			BIT(16)
+#define CLKMGR_STAT_PERF_TRANS				BIT(17)
+#define CLKMGR_STAT_BOOTMODE				BIT(24)
+#define CLKMGR_STAT_BOOTCLKSRC				BIT(25)
+
+#define CLKMGR_STAT_ALLPLL_LOCKED_MASK			\
+	(CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED)
+
+#define CLKMGR_INTER_MAINPLLLOCKED_MASK			BIT(0)
+#define CLKMGR_INTER_PERPLLLOCKED_MASK			BIT(1)
+#define CLKMGR_INTER_MAINPLLLOST_MASK			BIT(2)
+#define CLKMGR_INTER_PERPLLLOST_MASK			BIT(3)
+
+#define CLKMGR_CLKSRC_MASK				GENMASK(18, 16)
+#define CLKMGR_CLKSRC_OFFSET				16
+#define CLKMGR_CLKSRC_MAIN				0
+#define CLKMGR_CLKSRC_PER				1
+#define CLKMGR_CLKSRC_OSC1				2
+#define CLKMGR_CLKSRC_INTOSC				3
+#define CLKMGR_CLKSRC_FPGA				4
+#define CLKMGR_CLKCNT_MSK				GENMASK(10, 0)
+
+#define CLKMGR_BYPASS_MAINPLL_ALL			0x7
+#define CLKMGR_BYPASS_PERPLL_ALL			0x7f
+
+#define CLKMGR_NOCDIV_L4MAIN_OFFSET			0
+#define CLKMGR_NOCDIV_L4MPCLK_OFFSET			8
+#define CLKMGR_NOCDIV_L4SPCLK_OFFSET			16
+#define CLKMGR_NOCDIV_CSATCLK_OFFSET			24
+#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET			26
+#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET			28
+#define CLKMGR_NOCDIV_DIVIDER_MASK			0x3
+
+#define CLKMGR_PLLGLOB_VCO_PSRC_MASK			GENMASK(17, 16)
+#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET			16
+#define CLKMGR_PLLGLOB_LOSTLOCK_BYPASS_EN_MASK		BIT(28)
+#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK		BIT(29)
+
+#define CLKMGR_VCO_PSRC_EOSC1				0
+#define CLKMGR_VCO_PSRC_INTOSC				1
+#define CLKMGR_VCO_PSRC_F2S				2
+
+#define CLKMGR_PLLCTRL_BYPASS_MASK			BIT(0)
+#define CLKMGR_PLLCTRL_RST_N_MASK			BIT(1)
+
+#define CLKMGR_PLLDIV_REFCLKDIV_MASK			GENMASK(5, 0)
+#define CLKMGR_PLLDIV_FDIV_MASK				GENMASK(16, 8)
+#define CLKMGR_PLLDIV_OUTDIV_QDIV_MASK			GENMASK(26, 24)
+#define CLKMGR_PLLDIV_RANGE_MASK			GENMASK(30, 28)
+
+#define CLKMGR_PLLDIV_REFCLKDIV_OFFSET			0
+#define CLKMGR_PLLDIV_FDIV_OFFSET			8
+#define CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET		24
+#define CLKMGR_PLLDIV_RANGE_OFFSET			28
+
+#define CLKMGR_PLLOUTDIV_C0CNT_MASK			GENMASK(4, 0)
+#define CLKMGR_PLLOUTDIV_C1CNT_MASK			GENMASK(12, 8)
+#define CLKMGR_PLLOUTDIV_C2CNT_MASK			GENMASK(20, 16)
+#define CLKMGR_PLLOUTDIV_C3CNT_MASK			GENMASK(28, 24)
+
+#define CLKMGR_PLLOUTDIV_C0CNT_OFFSET			0
+#define CLKMGR_PLLOUTDIV_C1CNT_OFFSET			8
+#define CLKMGR_PLLOUTDIV_C2CNT_OFFSET			16
+#define CLKMGR_PLLOUTDIV_C3CNT_OFFSET			24
+
+#define CLKMGR_PLLCX_EN_SET_MSK				BIT(27)
+#define CLKMGR_PLLCX_MUTE_SET_MSK			BIT(28)
+
+#define CLKMGR_VCOCALIB_MSCNT_MASK			GENMASK(23, 16)
+#define CLKMGR_VCOCALIB_MSCNT_OFFSET			16
+#define CLKMGR_VCOCALIB_HSCNT_MASK			GENMASK(9, 0)
+#define CLKMGR_VCOCALIB_MSCNT_CONST			100
+#define CLKMGR_VCOCALIB_HSCNT_CONST			4
+
+#define CLKMGR_PLLM_MDIV_MASK				GENMASK(9, 0)
+
+#define CLKMGR_LOSTLOCK_SET_MASK			BIT(0)
+
+#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK		BIT(5)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET	26
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK		BIT(26)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET	27
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK		BIT(27)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET	28
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK		BIT(28)
+
+#define CLKMGR_ALT_EMACCTR_SRC_OFFSET			16
+#define CLKMGR_ALT_EMACCTR_SRC_MASK			GENMASK(18, 16)
+#define CLKMGR_ALT_EMACCTR_CNT_OFFSET			0
+#define CLKMGR_ALT_EMACCTR_CNT_MASK			GENMASK(10, 0)
+
+#define CLKMGR_ALT_EXTCNTRST_ALLCNTRST_MASK		GENMASK(15, 0)
+
+#endif /* _CLK_N5X_ */
diff --git a/include/dt-bindings/clock/n5x-clock.h b/include/dt-bindings/clock/n5x-clock.h
new file mode 100644
index 0000000000..a56e4dba77
--- /dev/null
+++ b/include/dt-bindings/clock/n5x-clock.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021, Intel Corporation
+ */
+
+#ifndef __N5X_CLOCK_H
+#define __N5X_CLOCK_H
+
+/* fixed rate clocks */
+#define N5X_OSC1					0
+#define N5X_CB_INTOSC_HS_DIV2_CLK		1
+#define N5X_CB_INTOSC_LS_CLK			2
+#define N5X_L4_SYS_FREE_CLK			3
+#define N5X_F2S_FREE_CLK				4
+
+/* PLL clocks */
+#define N5X_MAIN_PLL_CLK				5
+#define N5X_MAIN_PLL_C0_CLK			6
+#define N5X_MAIN_PLL_C1_CLK			7
+#define N5X_MAIN_PLL_C2_CLK			8
+#define N5X_MAIN_PLL_C3_CLK			9
+#define N5X_PERIPH_PLL_CLK			10
+#define N5X_PERIPH_PLL_C0_CLK			11
+#define N5X_PERIPH_PLL_C1_CLK			12
+#define N5X_PERIPH_PLL_C2_CLK			13
+#define N5X_PERIPH_PLL_C3_CLK			14
+#define N5X_MPU_FREE_CLK				15
+#define N5X_MPU_CCU_CLK				16
+#define N5X_BOOT_CLK				17
+
+/* fixed factor clocks */
+#define N5X_L3_MAIN_FREE_CLK			18
+#define N5X_NOC_FREE_CLK				19
+#define N5X_S2F_USR0_CLK				20
+#define N5X_NOC_CLK				21
+#define N5X_EMAC_A_FREE_CLK			22
+#define N5X_EMAC_B_FREE_CLK			23
+#define N5X_EMAC_PTP_FREE_CLK			24
+#define N5X_GPIO_DB_FREE_CLK			25
+#define N5X_SDMMC_FREE_CLK			26
+#define N5X_S2F_USER0_FREE_CLK			27
+#define N5X_S2F_USER1_FREE_CLK			28
+#define N5X_PSI_REF_FREE_CLK			29
+
+/* Gate clocks */
+#define N5X_MPU_CLK				30
+#define N5X_MPU_PERIPH_CLK			31
+#define N5X_L4_MAIN_CLK				32
+#define N5X_L4_MP_CLK				33
+#define N5X_L4_SP_CLK				34
+#define N5X_CS_AT_CLK				35
+#define N5X_CS_TRACE_CLK				36
+#define N5X_CS_PDBG_CLK				37
+#define N5X_CS_TIMER_CLK				38
+#define N5X_S2F_USER0_CLK			39
+#define N5X_EMAC0_CLK				40
+#define N5X_EMAC1_CLK				41
+#define N5X_EMAC2_CLK				42
+#define N5X_EMAC_PTP_CLK				43
+#define N5X_GPIO_DB_CLK				44
+#define N5X_NAND_CLK				45
+#define N5X_PSI_REF_CLK				46
+#define N5X_S2F_USER1_CLK			47
+#define N5X_SDMMC_CLK				48
+#define N5X_SPI_M_CLK				49
+#define N5X_USB_CLK				50
+#define N5X_NAND_X_CLK				51
+#define N5X_NAND_ECC_CLK				52
+#define N5X_NUM_CLKS				53
+
+#endif	/* __N5X_CLOCK_H */
-- 
2.19.0


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

* [v3 06/17] arm: socfpga: Get clock manager base address for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (4 preceding siblings ...)
  2021-06-13  8:48 ` [v3 05/17] drivers: clk: Add clock driver " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 07/17] drivers: clk: Add memory clock driver " Siew Chin Lim
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add N5X clock manager to socfpga_get_managers_addr function.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 arch/arm/mach-socfpga/misc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c
index 64a7c9d652..9305bec38a 100644
--- a/arch/arm/mach-socfpga/misc.c
+++ b/arch/arm/mach-socfpga/misc.c
@@ -254,6 +254,9 @@ void socfpga_get_managers_addr(void)
 #ifdef CONFIG_TARGET_SOCFPGA_AGILEX
 	ret = socfpga_get_base_addr("intel,agilex-clkmgr",
 				    &socfpga_clkmgr_base);
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	ret = socfpga_get_base_addr("intel,n5x-clkmgr",
+				    &socfpga_clkmgr_base);
 #else
 	ret = socfpga_get_base_addr("altr,clk-mgr", &socfpga_clkmgr_base);
 #endif
-- 
2.19.0


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

* [v3 07/17] drivers: clk: Add memory clock driver for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (5 preceding siblings ...)
  2021-06-13  8:48 ` [v3 06/17] arm: socfpga: Get clock manager base address " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-07-08 16:19   ` Ley Foon Tan
  2021-06-13  8:48 ` [v3 08/17] arm: socfpga: Move cm_get_mpu_clk_hz function declaration to clock_manager.h Siew Chin Lim
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add memory clock manager driver for N5X. Provides memory clock
initialization and enable functions.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>

---
v3:
- Use BIT() and GENMASK() macro for all *MASK macro

v2:
- common.h need to be included before clock_manager.h
- For consistency, use small letter fo 0x0c and 0x1c in macros
---
 drivers/clk/altera/Makefile      |   1 +
 drivers/clk/altera/clk-mem-n5x.c | 136 +++++++++++++++++++++++++++++++
 drivers/clk/altera/clk-mem-n5x.h |  84 +++++++++++++++++++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/clk/altera/clk-mem-n5x.c
 create mode 100644 drivers/clk/altera/clk-mem-n5x.h

diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile
index 38cd730685..33db092918 100644
--- a/drivers/clk/altera/Makefile
+++ b/drivers/clk/altera/Makefile
@@ -6,3 +6,4 @@
 obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += clk-agilex.o
 obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o
 obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-n5x.o
+obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-mem-n5x.o
diff --git a/drivers/clk/altera/clk-mem-n5x.c b/drivers/clk/altera/clk-mem-n5x.c
new file mode 100644
index 0000000000..ca44998641
--- /dev/null
+++ b/drivers/clk/altera/clk-mem-n5x.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include "clk-mem-n5x.h"
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/util.h>
+#include <dt-bindings/clock/n5x-clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct socfpga_mem_clk_plat {
+	void __iomem *regs;
+};
+
+void clk_mem_wait_for_lock(struct socfpga_mem_clk_plat *plat, u32 mask)
+{
+	u32 inter_val;
+	u32 retry = 0;
+
+	do {
+		inter_val = CM_REG_READL(plat, MEMCLKMGR_STAT) & mask;
+
+		/* Wait for stable lock */
+		if (inter_val == mask)
+			retry++;
+		else
+			retry = 0;
+
+		if (retry >= 10)
+			return;
+	} while (1);
+}
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+void clk_mem_write_bypass_mempll(struct socfpga_mem_clk_plat *plat, u32 val)
+{
+	CM_REG_WRITEL(plat, val, MEMCLKMGR_MEMPLL_BYPASS);
+}
+
+/*
+ * Setup clocks while making no assumptions about previous state of the clocks.
+ */
+static void clk_mem_basic_init(struct udevice *dev,
+			       const struct cm_config * const cfg)
+{
+	struct socfpga_mem_clk_plat *plat = dev_get_plat(dev);
+
+	if (!cfg)
+		return;
+
+	/* Put PLLs in bypass */
+	clk_mem_write_bypass_mempll(plat, MEMCLKMGR_BYPASS_MEMPLL_ALL);
+
+	/* Put PLLs in Reset */
+	CM_REG_SETBITS(plat, MEMCLKMGR_MEMPLL_PLLCTRL,
+		       MEMCLKMGR_PLLCTRL_BYPASS_MASK);
+
+	/* setup mem PLL */
+	CM_REG_WRITEL(plat, cfg->mem_memdiv, MEMCLKMGR_MEMPLL_MEMDIV);
+	CM_REG_WRITEL(plat, cfg->mem_pllglob, MEMCLKMGR_MEMPLL_PLLGLOB);
+	CM_REG_WRITEL(plat, cfg->mem_plldiv, MEMCLKMGR_MEMPLL_PLLDIV);
+	CM_REG_WRITEL(plat, cfg->mem_plloutdiv, MEMCLKMGR_MEMPLL_PLLOUTDIV);
+
+	/* Take PLL out of reset and power up */
+	CM_REG_CLRBITS(plat, MEMCLKMGR_MEMPLL_PLLCTRL,
+		       MEMCLKMGR_PLLCTRL_BYPASS_MASK);
+}
+
+static int socfpga_mem_clk_enable(struct clk *clk)
+{
+	const struct cm_config *cm_default_cfg = cm_get_default_config();
+	struct socfpga_mem_clk_plat *plat = dev_get_plat(clk->dev);
+
+	clk_mem_basic_init(clk->dev, cm_default_cfg);
+
+	clk_mem_wait_for_lock(plat, MEMCLKMGR_STAT_ALLPLL_LOCKED_MASK);
+
+	CM_REG_WRITEL(plat, CM_REG_READL(plat, MEMCLKMGR_MEMPLL_PLLGLOB) |
+		      MEMCLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+		      MEMCLKMGR_MEMPLL_PLLGLOB);
+
+	/* Take all PLLs out of bypass */
+	clk_mem_write_bypass_mempll(plat, 0);
+
+	/* Clear the loss of lock bits (write 1 to clear) */
+	CM_REG_CLRBITS(plat, MEMCLKMGR_INTRCLR,
+		       MEMCLKMGR_INTER_MEMPLLLOST_MASK);
+
+	/* Take all ping pong counters out of reset */
+	CM_REG_CLRBITS(plat, MEMCLKMGR_MEMPLL_EXTCNTRST,
+		       MEMCLKMGR_EXTCNTRST_ALLCNTRST);
+
+	return 0;
+}
+
+static int socfpga_mem_clk_of_to_plat(struct udevice *dev)
+{
+	struct socfpga_mem_clk_plat *plat = dev_get_plat(dev);
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	plat->regs = (void __iomem *)addr;
+
+	return 0;
+}
+
+static struct clk_ops socfpga_mem_clk_ops = {
+	.enable		= socfpga_mem_clk_enable
+};
+
+static const struct udevice_id socfpga_mem_clk_match[] = {
+	{ .compatible = "intel,n5x-mem-clkmgr" },
+	{}
+};
+
+U_BOOT_DRIVER(socfpga_n5x_mem_clk) = {
+	.name		= "mem-clk-n5x",
+	.id		= UCLASS_CLK,
+	.of_match	= socfpga_mem_clk_match,
+	.ops		= &socfpga_mem_clk_ops,
+	.of_to_plat     = socfpga_mem_clk_of_to_plat,
+	.plat_auto	= sizeof(struct socfpga_mem_clk_plat),
+};
diff --git a/drivers/clk/altera/clk-mem-n5x.h b/drivers/clk/altera/clk-mem-n5x.h
new file mode 100644
index 0000000000..d000ae260c
--- /dev/null
+++ b/drivers/clk/altera/clk-mem-n5x.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#ifndef	_CLK_MEM_N5X_
+#define	_CLK_MEM_N5X_
+
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+/* Clock Manager registers */
+#define MEMCLKMGR_STAT					4
+#define MEMCLKMGR_INTRGEN				8
+#define MEMCLKMGR_INTRMSK				0x0c
+#define MEMCLKMGR_INTRCLR				0x10
+#define MEMCLKMGR_INTRSTS				0x14
+#define MEMCLKMGR_INTRSTK				0x18
+#define MEMCLKMGR_INTRRAW				0x1c
+
+/* Memory Clock Manager PPL group registers */
+#define MEMCLKMGR_MEMPLL_EN				0x20
+#define MEMCLKMGR_MEMPLL_ENS				0x24
+#define MEMCLKMGR_MEMPLL_ENR				0x28
+#define MEMCLKMGR_MEMPLL_BYPASS				0x2c
+#define MEMCLKMGR_MEMPLL_BYPASSS			0x30
+#define MEMCLKMGR_MEMPLL_BYPASSR			0x34
+#define MEMCLKMGR_MEMPLL_MEMDIV				0x38
+#define MEMCLKMGR_MEMPLL_PLLGLOB			0x3c
+#define MEMCLKMGR_MEMPLL_PLLCTRL			0x40
+#define MEMCLKMGR_MEMPLL_PLLDIV				0x44
+#define MEMCLKMGR_MEMPLL_PLLOUTDIV			0x48
+#define MEMCLKMGR_MEMPLL_EXTCNTRST			0x4c
+
+#define MEMCLKMGR_CTRL_BOOTMODE				BIT(0)
+
+#define MEMCLKMGR_STAT_MEMPLL_LOCKED			BIT(8)
+
+#define MEMCLKMGR_STAT_ALLPLL_LOCKED_MASK		\
+	(MEMCLKMGR_STAT_MEMPLL_LOCKED)
+
+#define MEMCLKMGR_INTER_MEMPLLLOCKED_MASK		BIT(0)
+#define MEMCLKMGR_INTER_MEMPLLLOST_MASK			BIT(2)
+
+#define MEMCLKMGR_BYPASS_MEMPLL_ALL			0x1
+
+#define MEMCLKMGR_MEMDIV_MPFEDIV_OFFSET			0
+#define MEMCLKMGR_MEMDIV_APBDIV_OFFSET			4
+#define MEMCLKMGR_MEMDIV_DFICTRLDIV_OFFSET		8
+#define MEMCLKMGR_MEMDIV_DFIDIV_OFFSET			12
+#define MEMCLKMGR_MEMDIV_DFICTRLDIV_MASK		BIT(0)
+#define MEMCLKMGR_MEMDIV_DIVIDER_MASK			GENMASK(1, 0)
+
+#define MEMCLKMGR_PLLGLOB_PSRC_MASK			GENMASK(17, 16)
+#define MEMCLKMGR_PLLGLOB_PSRC_OFFSET			16
+#define MEMCLKMGR_PLLGLOB_LOSTLOCK_BYPASS_EN_MASK	BIT(28)
+#define MEMCLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK	BIT(29)
+
+#define MEMCLKMGR_PSRC_EOSC1				0
+#define MEMCLKMGR_PSRC_INTOSC				1
+#define MEMCLKMGR_PSRC_F2S				2
+
+#define MEMCLKMGR_PLLCTRL_BYPASS_MASK			BIT(0)
+#define MEMCLKMGR_PLLCTRL_RST_N_MASK			BIT(1)
+
+#define MEMCLKMGR_PLLDIV_DIVR_MASK			GENMASK(5, 0)
+#define MEMCLKMGR_PLLDIV_DIVF_MASK			GENMASK(16, 8)
+#define MEMCLKMGR_PLLDIV_DIVQ_MASK			GENMASK(26, 24)
+#define MEMCLKMGR_PLLDIV_RANGE_MASK			GENMASK(30, 28)
+
+#define MEMCLKMGR_PLLDIV_DIVR_OFFSET			0
+#define MEMCLKMGR_PLLDIV_DIVF_OFFSET			8
+#define MEMCLKMGR_PLLDIV_DIVQ_QDIV_OFFSET		24
+#define MEMCLKMGR_PLLDIV_RANGE_OFFSET			28
+
+#define MEMCLKMGR_PLLOUTDIV_C0CNT_MASK			GENMASK(4, 0)
+#define MEMCLKMGR_PLLOUTDIV_C0CNT_OFFSET		0
+
+#define MEMCLKMGR_EXTCNTRST_C0CNTRST			BIT(7)
+#define MEMCLKMGR_EXTCNTRST_ALLCNTRST			\
+	(MEMCLKMGR_EXTCNTRST_C0CNTRST)
+
+#endif /* _CLK_MEM_N5X_ */
-- 
2.19.0


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

* [v3 08/17] arm: socfpga: Move cm_get_mpu_clk_hz function declaration to clock_manager.h
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (6 preceding siblings ...)
  2021-06-13  8:48 ` [v3 07/17] drivers: clk: Add memory clock driver " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 09/17] arm: socfpga: Add clock manager for Intel N5X device Siew Chin Lim
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Move cm_get_mpu_clk_hz function declaration from individual device's
clock manager header file to common clock_manager.h.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 arch/arm/mach-socfpga/include/mach/clock_manager.h         | 1 +
 arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h  | 2 --
 arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h | 1 -
 arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h    | 1 -
 arch/arm/mach-socfpga/include/mach/clock_manager_s10.h     | 1 -
 5 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
index 2f9b471af3..d0b172a30e 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
@@ -12,6 +12,7 @@ phys_addr_t socfpga_get_clkmgr_addr(void);
 void cm_wait_for_lock(u32 mask);
 int cm_wait_for_fsm(void);
 void cm_print_clock_quick_summary(void);
+unsigned long cm_get_mpu_clk_hz(void);
 unsigned int cm_get_qspi_controller_clk_hz(void);
 
 #if defined(CONFIG_TARGET_SOCFPGA_SOC64)
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h b/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
index 386e82a4e3..4feae3dda9 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
@@ -6,8 +6,6 @@
 #ifndef _CLOCK_MANAGER_AGILEX_
 #define _CLOCK_MANAGER_AGILEX_
 
-unsigned long cm_get_mpu_clk_hz(void);
-
 #include <asm/arch/clock_manager_soc64.h>
 #include "../../../../../drivers/clk/altera/clk-agilex.h"
 
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
index 798d3741bd..553ebe660d 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_arria10.h
@@ -68,7 +68,6 @@ int cm_basic_init(const void *blob);
 
 #include <linux/bitops.h>
 unsigned int cm_get_l4_sp_clk_hz(void);
-unsigned long cm_get_mpu_clk_hz(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h b/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
index 4cc1268b4c..d53095a7da 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_gen5.h
@@ -96,7 +96,6 @@ struct cm_config {
 #define CLKMGR_PERPLL_EN			CLKMGR_GEN5_PERPLL_EN
 
 /* Clock speed accessors */
-unsigned long cm_get_mpu_clk_hz(void);
 unsigned long cm_get_sdram_clk_hz(void);
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned int cm_get_mmc_controller_clk_hz(void);
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
index 98c3bf1b03..7f10296dc7 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
@@ -11,7 +11,6 @@
 #include <linux/bitops.h>
 
 /* Clock speed accessors */
-unsigned long cm_get_mpu_clk_hz(void);
 unsigned long cm_get_sdram_clk_hz(void);
 unsigned int cm_get_l4_sp_clk_hz(void);
 unsigned int cm_get_mmc_controller_clk_hz(void);
-- 
2.19.0


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

* [v3 09/17] arm: socfpga: Add clock manager for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (7 preceding siblings ...)
  2021-06-13  8:48 ` [v3 08/17] arm: socfpga: Move cm_get_mpu_clk_hz function declaration to clock_manager.h Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 10/17] arm: socfpga: Changed misc_s10.c to misc_soc64.c Siew Chin Lim
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add clock manager for N5X.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 ...k_manager_agilex.c => clock_manager_n5x.c} | 32 +++++++++----------
 .../mach-socfpga/include/mach/clock_manager.h |  2 ++
 .../include/mach/clock_manager_n5x.h          | 12 +++++++
 3 files changed, 29 insertions(+), 17 deletions(-)
 copy arch/arm/mach-socfpga/{clock_manager_agilex.c => clock_manager_n5x.c} (64%)
 create mode 100644 arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h

diff --git a/arch/arm/mach-socfpga/clock_manager_agilex.c b/arch/arm/mach-socfpga/clock_manager_n5x.c
similarity index 64%
copy from arch/arm/mach-socfpga/clock_manager_agilex.c
copy to arch/arm/mach-socfpga/clock_manager_n5x.c
index e035c09aae..4f098533e7 100644
--- a/arch/arm/mach-socfpga/clock_manager_agilex.c
+++ b/arch/arm/mach-socfpga/clock_manager_n5x.c
@@ -1,19 +1,18 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
  *
  */
 
-#include <clk.h>
 #include <common.h>
-#include <dm.h>
-#include <log.h>
-#include <malloc.h>
 #include <asm/arch/clock_manager.h>
 #include <asm/arch/system_manager.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
-#include <dt-bindings/clock/agilex-clock.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-bindings/clock/n5x-clock.h>
+#include <malloc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -25,7 +24,7 @@ static ulong cm_get_rate_dm(u32 id)
 	int ret;
 
 	ret = uclass_get_device_by_driver(UCLASS_CLK,
-					  DM_DRIVER_GET(socfpga_agilex_clk),
+					  DM_DRIVER_GET(socfpga_n5x_clk),
 					  &dev);
 	if (ret)
 		return 0;
@@ -39,8 +38,7 @@ static ulong cm_get_rate_dm(u32 id)
 
 	clk_free(&clk);
 
-	if ((rate == (unsigned long)-ENOSYS) ||
-	    (rate == (unsigned long)-ENXIO) ||
+	if ((rate == (unsigned long)-ENXIO) ||
 	    (rate == (unsigned long)-EIO)) {
 		debug("%s id %u: clk_get_rate err: %ld\n",
 		      __func__, id, rate);
@@ -57,26 +55,26 @@ static u32 cm_get_rate_dm_khz(u32 id)
 
 unsigned long cm_get_mpu_clk_hz(void)
 {
-	return cm_get_rate_dm(AGILEX_MPU_CLK);
+	return cm_get_rate_dm(N5X_MPU_CLK);
 }
 
 unsigned int cm_get_l4_sys_free_clk_hz(void)
 {
-	return cm_get_rate_dm(AGILEX_L4_SYS_FREE_CLK);
+	return cm_get_rate_dm(N5X_L4_SYS_FREE_CLK);
 }
 
 void cm_print_clock_quick_summary(void)
 {
 	printf("MPU       %10d kHz\n",
-	       cm_get_rate_dm_khz(AGILEX_MPU_CLK));
+	       cm_get_rate_dm_khz(N5X_MPU_CLK));
 	printf("L4 Main	    %8d kHz\n",
-	       cm_get_rate_dm_khz(AGILEX_L4_MAIN_CLK));
+	       cm_get_rate_dm_khz(N5X_L4_MAIN_CLK));
 	printf("L4 sys free %8d kHz\n",
-	       cm_get_rate_dm_khz(AGILEX_L4_SYS_FREE_CLK));
+	       cm_get_rate_dm_khz(N5X_L4_SYS_FREE_CLK));
 	printf("L4 MP       %8d kHz\n",
-	       cm_get_rate_dm_khz(AGILEX_L4_MP_CLK));
+	       cm_get_rate_dm_khz(N5X_L4_MP_CLK));
 	printf("L4 SP       %8d kHz\n",
-	       cm_get_rate_dm_khz(AGILEX_L4_SP_CLK));
+	       cm_get_rate_dm_khz(N5X_L4_SP_CLK));
 	printf("SDMMC       %8d kHz\n",
-	       cm_get_rate_dm_khz(AGILEX_SDMMC_CLK));
+	       cm_get_rate_dm_khz(N5X_SDMMC_CLK));
 }
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
index d0b172a30e..a8cb07a1c4 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
@@ -28,6 +28,8 @@ int cm_set_qspi_controller_clk_hz(u32 clk_hz);
 #include <asm/arch/clock_manager_s10.h>
 #elif defined(CONFIG_TARGET_SOCFPGA_AGILEX)
 #include <asm/arch/clock_manager_agilex.h>
+#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#include <asm/arch/clock_manager_n5x.h>
 #endif
 
 #endif /* _CLOCK_MANAGER_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h b/arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h
new file mode 100644
index 0000000000..54615ae8f7
--- /dev/null
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_n5x.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _CLOCK_MANAGER_N5X_
+#define _CLOCK_MANAGER_N5X_
+
+#include <asm/arch/clock_manager_soc64.h>
+#include "../../../../../drivers/clk/altera/clk-n5x.h"
+
+#endif /* _CLOCK_MANAGER_N5X_ */
-- 
2.19.0


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

* [v3 10/17] arm: socfpga: Changed misc_s10.c to misc_soc64.c
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (8 preceding siblings ...)
  2021-06-13  8:48 ` [v3 09/17] arm: socfpga: Add clock manager for Intel N5X device Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 11/17] ddr: socfpga: Enable memory test on memory size less than 1GB Siew Chin Lim
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Rename to common file name to used by all SOC64 devices.
No functionality change.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 arch/arm/mach-socfpga/Makefile                     |  4 ++--
 arch/arm/mach-socfpga/{misc_s10.c => misc_soc64.c} | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)
 rename arch/arm/mach-socfpga/{misc_s10.c => misc_soc64.c} (100%)

diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 5779c55621..58afde950f 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -32,7 +32,7 @@ ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
 obj-y	+= clock_manager_s10.o
 obj-y	+= lowlevel_init_soc64.o
 obj-y	+= mailbox_s10.o
-obj-y	+= misc_s10.o
+obj-y	+= misc_soc64.o
 obj-y	+= mmu-arm64_s10.o
 obj-y	+= reset_manager_s10.o
 obj-y	+= system_manager_soc64.o
@@ -45,7 +45,7 @@ ifdef CONFIG_TARGET_SOCFPGA_AGILEX
 obj-y	+= clock_manager_agilex.o
 obj-y	+= lowlevel_init_soc64.o
 obj-y	+= mailbox_s10.o
-obj-y	+= misc_s10.o
+obj-y	+= misc_soc64.o
 obj-y	+= mmu-arm64_s10.o
 obj-y	+= reset_manager_s10.o
 obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= secure_vab.o
diff --git a/arch/arm/mach-socfpga/misc_s10.c b/arch/arm/mach-socfpga/misc_soc64.c
similarity index 100%
rename from arch/arm/mach-socfpga/misc_s10.c
rename to arch/arm/mach-socfpga/misc_soc64.c
index 50c7f19ae1..7b973a79e8 100644
--- a/arch/arm/mach-socfpga/misc_s10.c
+++ b/arch/arm/mach-socfpga/misc_soc64.c
@@ -6,16 +6,16 @@
 
 #include <altera.h>
 #include <common.h>
-#include <env.h>
-#include <errno.h>
-#include <init.h>
-#include <log.h>
-#include <asm/global_data.h>
-#include <asm/io.h>
 #include <asm/arch/mailbox_s10.h>
 #include <asm/arch/misc.h>
 #include <asm/arch/reset_manager.h>
 #include <asm/arch/system_manager.h>
+#include <asm/io.h>
+#include <asm/global_data.h>
+#include <env.h>
+#include <errno.h>
+#include <init.h>
+#include <log.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-- 
2.19.0


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

* [v3 11/17] ddr: socfpga: Enable memory test on memory size less than 1GB
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (9 preceding siblings ...)
  2021-06-13  8:48 ` [v3 10/17] arm: socfpga: Changed misc_s10.c to misc_soc64.c Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 12/17] ddr: altera: Add SDRAM driver for Intel N5X device Siew Chin Lim
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan

From: Tien Fong Chee <tien.fong.chee@intel.com>

Minimum 1GB memory size is required in current memory test, so this patch
improves the memory test for processing memory size less than 1GB, and
the size in power of two.

Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
---
 drivers/ddr/altera/sdram_soc64.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c
index a08f0953e5..cc656db97c 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-2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
  *
  */
 
@@ -182,6 +182,7 @@ void sdram_size_check(struct bd_info *bd)
 	phys_size_t total_ram_check = 0;
 	phys_size_t ram_check = 0;
 	phys_addr_t start = 0;
+	phys_size_t size, remaining_size;
 	int bank;
 
 	/* Sanity check ensure correct SDRAM size specified */
@@ -189,10 +190,27 @@ void sdram_size_check(struct bd_info *bd)
 
 	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
 		start = bd->bi_dram[bank].start;
+		remaining_size = bd->bi_dram[bank].size;
 		while (ram_check < bd->bi_dram[bank].size) {
-			ram_check += get_ram_size((void *)(start + ram_check),
-						 (phys_size_t)SZ_1G);
+			size = min((phys_addr_t)SZ_1G,
+				   (phys_addr_t)remaining_size);
+
+			/*
+			 * Ensure the size is power of two, this is requirement
+			 * to run get_ram_size() / memory test
+			 */
+			if (size != 0 && ((size & (size - 1)) == 0)) {
+				ram_check += get_ram_size((void *)
+						(start + ram_check), size);
+				remaining_size = bd->bi_dram[bank].size -
+							ram_check;
+			} else {
+				puts("DDR: Memory test requires SDRAM size ");
+				puts("in power of two!\n");
+				hang();
+			}
 		}
+
 		total_ram_check += ram_check;
 		ram_check = 0;
 	}
-- 
2.19.0


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

* [v3 12/17] ddr: altera: Add SDRAM driver for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (10 preceding siblings ...)
  2021-06-13  8:48 ` [v3 11/17] ddr: socfpga: Enable memory test on memory size less than 1GB Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-07-08 17:06   ` Ley Foon Tan
  2021-06-13  8:48 ` [v3 13/17] arm: socfpga: Add SPL " Siew Chin Lim
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

From: Tien Fong Chee <tien.fong.chee@intel.com>

The DDR subsystem in Diamond Mesa is consisted of controller, PHY,
memory reset manager and memory clock manager.

Configuration settings of controller, PHY and  memory reset manager
is come from DDR handoff data in bitstream, which contain the register
base addresses and user settings from tool.

Configuration settings of memory clock manager is come from the HPS
handoff data in bitstream, however the register base address is defined
in device tree.

The calibration is fully done in HPS, which requires IMEM and DMEM
binaries loading to PHY SRAM for running this calibration, both
IMEM and DMEM binaries are also part of bitstream, this bitstream
would be loaded to OCRAM by SDM, and configured by DDR driver.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>

---
v3:
- Sorting header
- Used prefix OPM_xxx
- Simplify the code with do...while loop.
- Created common function for processing handoff
- Adding function of calibration data feedback to LPDDR4 controllers

v2:
- Move is_ddr_init_skipped and its helper functions to DDR driver and
  converted function to positive checking
- Using GENMASK() macro
- Fixed typo
- Return status of subfunction
- Changed dm to n5x
---
 arch/arm/mach-socfpga/include/mach/firewall.h |    6 +
 .../include/mach/system_manager_soc64.h       |   10 +-
 drivers/ddr/altera/Makefile                   |    3 +-
 drivers/ddr/altera/sdram_n5x.c                | 2298 +++++++++++++++++
 drivers/ddr/altera/sdram_soc64.c              |   70 +
 drivers/ddr/altera/sdram_soc64.h              |    1 +
 6 files changed, 2386 insertions(+), 2 deletions(-)
 create mode 100644 drivers/ddr/altera/sdram_n5x.c

diff --git a/arch/arm/mach-socfpga/include/mach/firewall.h b/arch/arm/mach-socfpga/include/mach/firewall.h
index adab65bc96..5cb7f23f8f 100644
--- a/arch/arm/mach-socfpga/include/mach/firewall.h
+++ b/arch/arm/mach-socfpga/include/mach/firewall.h
@@ -115,10 +115,16 @@ struct socfpga_firwall_l4_sys {
 /* Firewall MPU DDR SCR registers */
 #define FW_MPU_DDR_SCR_EN				0x00
 #define FW_MPU_DDR_SCR_EN_SET				0x04
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE		0x10
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT		0x14
 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT		0x18
 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT		0x1c
+
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE		0x90
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT	0x94
 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT		0x98
 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT	0x9c
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT_FIELD	0xff
 
 #define MPUREGION0_ENABLE				BIT(0)
 #define NONMPUREGION0_ENABLE				BIT(8)
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 fc4e17821b..a8009664fe 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 Intel Corporation <www.intel.com>
+ * Copyright (C) 2019-2021 Intel Corporation <www.intel.com>
  */
 
 #ifndef _SYSTEM_MANAGER_SOC64_H_
@@ -28,8 +28,12 @@ void populate_sysmgr_pinmux(void);
 #define SYSMGR_SOC64_FPGAINTF_EN2		0x6c
 #define SYSMGR_SOC64_FPGAINTF_EN3		0x70
 #define SYSMGR_SOC64_DMA_L3MASTER		0x74
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define SYSMGR_SOC64_DDR_MODE			0xb8
+#else
 #define SYSMGR_SOC64_HMC_CLK			0xb4
 #define SYSMGR_SOC64_IO_PA_CTRL			0xb8
+#endif
 #define SYSMGR_SOC64_NOC_TIMEOUT		0xc0
 #define SYSMGR_SOC64_NOC_IDLEREQ_SET		0xc4
 #define SYSMGR_SOC64_NOC_IDLEREQ_CLR		0xc8
@@ -143,4 +147,8 @@ void populate_sysmgr_pinmux(void);
 
 #define SYSMGR_WDDBG_PAUSE_ALL_CPU	0x0F0F0F0F
 
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+#define	SYSMGR_SOC64_DDR_MODE_MSK	BIT(0)
+#endif
+
 #endif /* _SYSTEM_MANAGER_SOC64_H_ */
diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile
index 39dfee5d5a..9fa5d85a27 100644
--- a/drivers/ddr/altera/Makefile
+++ b/drivers/ddr/altera/Makefile
@@ -4,11 +4,12 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # (C) Copyright 2010, Thomas Chou <thomas@wytron.com.tw>
-# Copyright (C) 2014 Altera Corporation <www.altera.com>
+# Copyright (C) 2014-2021 Altera Corporation <www.altera.com>
 
 ifdef CONFIG_$(SPL_)ALTERA_SDRAM
 obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram_gen5.o sequencer.o
 obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += sdram_arria10.o
 obj-$(CONFIG_TARGET_SOCFPGA_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
 endif
diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c
new file mode 100644
index 0000000000..ac13ac4319
--- /dev/null
+++ b/drivers/ddr/altera/sdram_n5x.c
@@ -0,0 +1,2298 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 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;
+
+/* MPFE NOC registers */
+#define FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0	0xF8024050
+
+/* 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_MSTR_OFFSET		0x0
+#define DDR4_FREQ_RATIO			BIT(22)
+
+#define DDR4_STAT_OFFSET		0x4
+#define DDR4_STAT_SELFREF_TYPE		GENMASK(5, 4)
+#define DDR4_STAT_SELFREF_TYPE_SHIFT	4
+#define DDR4_STAT_OPERATING_MODE	GENMASK(2, 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		GENMASK(5, 4)
+#define DDR4_MRCTRL0_MR_RANK_SHIFT	4
+#define DDR4_MRCTRL0_MR_ADDR		GENMASK(15, 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		GENMASK(6, 4)
+#define DDR4_RFSHCTL3_REFRESH_MODE_SHIFT	4
+
+#define DDR4_ECCCFG0_OFFSET		0x70
+#define DDR4_ECC_MODE			GENMASK(2, 0)
+#define DDR4_DIS_SCRUB			BIT(4)
+#define LPDDR4_ECCCFG0_ECC_REGION_MAP_GRANU_SHIFT	30
+#define LPDDR4_ECCCFG0_ECC_REGION_MAP_SHIFT	8
+
+#define DDR4_ECCCFG1_OFFSET		0x74
+#define LPDDR4_ECCCFG1_ECC_REGIONS_PARITY_LOCK	BIT(4)
+
+#define DDR4_CRCPARCTL0_OFFSET			0xC0
+#define DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR	BIT(1)
+
+#define DDR4_CRCPARCTL1_OFFSET			0xC4
+#define DDR4_CRCPARCTL1_CRC_PARITY_RETRY_ENABLE	BIT(8)
+#define DDR4_CRCPARCTL1_ALERT_WAIT_FOR_SW	BIT(9)
+
+#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_INIT0_OFFSET			0xD0
+#define DDR4_INIT0_SKIP_RAM_INIT		GENMASK(31, 30)
+
+#define DDR4_RANKCTL_OFFSET			0xF4
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP		GENMASK(7, 4)
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP		GENMASK(11, 8)
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP_MSB	BIT(24)
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP_MSB	BIT(26)
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP_SHIFT	4
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP_SHIFT	8
+#define DDR4_RANKCTL_DIFF_RANK_RD_GAP_MSB_SHIFT	24
+#define DDR4_RANKCTL_DIFF_RANK_WR_GAP_MSB_SHIFT	26
+
+#define DDR4_RANKCTL1_OFFSET	0xF8
+#define DDR4_RANKCTL1_WR2RD_DR	GENMASK(5, 0)
+
+#define DDR4_DRAMTMG2_OFFSET	0x108
+#define DDR4_DRAMTMG2_WR2RD	GENMASK(5, 0)
+#define DDR4_DRAMTMG2_RD2WR	GENMASK(13, 8)
+#define DDR4_DRAMTMG2_RD2WR_SHIFT	8
+
+#define DDR4_DRAMTMG9_OFFSET	0x124
+#define DDR4_DRAMTMG9_W2RD_S	GENMASK(5, 0)
+
+#define DDR4_DFITMG1_OFFSET	0x194
+#define DDR4_DFITMG1_DFI_T_WRDATA_DELAY	GENMASK(20, 16)
+#define DDR4_DFITMG1_DFI_T_WRDATA_SHIFT	16
+
+#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 DDR4_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_DBYTE0_TXDQDLYTG0_U0_P0		0x201A0
+
+#define DDR_PHY_DBYTE0_TXDQDLYTG0_U1_P0		0x203A0
+#define DDR_PHY_DBYTE1_TXDQDLYTG0_U0_P0		0x221A0
+#define DDR_PHY_DBYTE1_TXDQDLYTG0_U1_P0		0x223A0
+#define DDR_PHY_TXDQDLYTG0_COARSE_DELAY		GENMASK(9, 6)
+#define DDR_PHY_TXDQDLYTG0_COARSE_DELAY_SHIFT	6
+
+#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_MEMRESETL_OFFSET		0x400C0
+#define DDR_PHY_MEMRESETL_VALUE			BIT(0)
+#define DDR_PHY_PROTECT_MEMRESET		BIT(1)
+
+#define DDR_PHY_CALBUSY_OFFSET			0x4012E
+#define DDR_PHY_CALBUSY				BIT(0)
+
+#define DDR_PHY_TRAIN_IMEM_OFFSET		0xA0000
+#define DDR_PHY_TRAIN_DMEM_OFFSET		0xA8000
+
+#define DMEM_MB_CDD_RR_1_0_OFFSET		0xA802C
+#define DMEM_MB_CDD_RR_0_1_OFFSET		0xA8030
+#define DMEM_MB_CDD_WW_1_0_OFFSET		0xA8038
+#define DMEM_MB_CDD_WW_0_1_OFFSET		0xA803C
+#define DMEM_MB_CDD_RW_1_1_OFFSET		0xA8046
+#define DMEM_MB_CDD_RW_1_0_OFFSET		0xA8048
+#define DMEM_MB_CDD_RW_0_1_OFFSET		0xA804A
+#define DMEM_MB_CDD_RW_0_0_OFFSET		0xA804C
+
+#define DMEM_MB_CDD_CHA_RR_1_0_OFFSET		0xA8026
+#define DMEM_MB_CDD_CHA_RR_0_1_OFFSET		0xA8026
+#define DMEM_MB_CDD_CHB_RR_1_0_OFFSET		0xA8058
+#define DMEM_MB_CDD_CHB_RR_0_1_OFFSET		0xA805A
+#define DMEM_MB_CDD_CHA_WW_1_0_OFFSET		0xA8030
+#define DMEM_MB_CDD_CHA_WW_0_1_OFFSET		0xA8030
+#define DMEM_MB_CDD_CHB_WW_1_0_OFFSET		0xA8062
+#define DMEM_MB_CDD_CHB_WW_0_1_OFFSET		0xA8064
+
+#define DMEM_MB_CDD_CHA_RW_1_1_OFFSET		0xA8028
+#define DMEM_MB_CDD_CHA_RW_1_0_OFFSET		0xA8028
+#define DMEM_MB_CDD_CHA_RW_0_1_OFFSET		0xA802A
+#define DMEM_MB_CDD_CHA_RW_0_0_OFFSET		0xA802A
+
+#define DMEM_MB_CDD_CHB_RW_1_1_OFFSET		0xA805A
+#define DMEM_MB_CDD_CHB_RW_1_0_OFFSET		0xA805C
+#define DMEM_MB_CDD_CHB_RW_0_1_OFFSET		0xA805c
+#define DMEM_MB_CDD_CHB_RW_0_0_OFFSET		0xA805E
+
+#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_UCCLKHCLKENABLES_UCCLKEN	BIT(0)
+#define DDR_PHY_UCCLKHCLKENABLES_HCLKEN		BIT(1)
+
+#define DDR_PHY_UCTWRITEPROT_OFFSET		0x180066
+#define DDR_PHY_UCTWRITEPROT			BIT(0)
+
+#define DDR_PHY_APBONLY0_OFFSET			0x1A0000
+#define DDR_PHY_MICROCONTMUXSEL			BIT(0)
+
+#define DDR_PHY_UCTSHADOWREGS_OFFSET			0x1A0008
+#define DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW	BIT(0)
+
+#define DDR_PHY_DCTWRITEPROT_OFFSET		0x1A0062
+#define DDR_PHY_DCTWRITEPROT			BIT(0)
+
+#define DDR_PHY_UCTWRITEONLYSHADOW_OFFSET	0x1A0064
+#define DDR_PHY_UCTDATWRITEONLYSHADOW_OFFSET	0x1A0068
+
+#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
+
+/* For firmware training */
+#define HW_DBG_TRACE_CONTROL_OFFSET	0x18
+#define FW_TRAINING_COMPLETED_STAT	0x07
+#define FW_TRAINING_FAILED_STAT		0xFF
+#define FW_COMPLETION_MSG_ONLY_MODE	0xFF
+#define FW_STREAMING_MSG_ID		0x08
+#define GET_LOWHW_DATA(x)		((x) & 0xFFFF)
+#define GET_LOWB_DATA(x)		((x) & 0xFF)
+#define GET_HIGHB_DATA(x)		(((x) & 0xFF00) >> 8)
+
+/* Operating mode */
+#define OPM_INIT			0x000
+#define OPM_NORMAL			0x001
+#define OPM_PWR_D0WN			0x010
+#define OPM_SELF_SELFREF		0x011
+#define OPM_DDR4_DEEP_PWR_DOWN		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)
+
+/* Value for ecc_region_map */
+#define ALL_PROTECTED	0x7F
+
+/* Region size for ECCCFG0.ecc_region_map */
+enum region_size {
+	ONE_EIGHT,
+	ONE_SIXTEENTH,
+	ONE_THIRTY_SECOND,
+	ONE_SIXTY_FOURTH
+};
+
+enum ddr_type {
+	DDRTYPE_LPDDR4_0,
+	DDRTYPE_LPDDR4_1,
+	DDRTYPE_DDR4,
+	DDRTYPE_UNKNOWN
+};
+
+/* Reset type */
+enum reset_type {
+	POR_RESET,
+	WARM_RESET,
+	COLD_RESET
+};
+
+/* DDR handoff structure */
+struct ddr_handoff {
+	/* Memory reset manager base */
+	phys_addr_t mem_reset_base;
+
+	/* First controller attributes */
+	phys_addr_t cntlr_handoff_base;
+	phys_addr_t cntlr_base;
+	size_t cntlr_total_length;
+	enum ddr_type cntlr_t;
+	size_t cntlr_handoff_length;
+
+	/* Second controller attributes*/
+	phys_addr_t cntlr2_handoff_base;
+	phys_addr_t cntlr2_base;
+	size_t cntlr2_total_length;
+	enum ddr_type cntlr2_t;
+	size_t cntlr2_handoff_length;
+
+	/* PHY attributes */
+	phys_addr_t phy_handoff_base;
+	phys_addr_t phy_base;
+	size_t phy_total_length;
+	size_t phy_handoff_length;
+
+	/* PHY engine attributes */
+	phys_addr_t phy_engine_handoff_base;
+	size_t phy_engine_total_length;
+	size_t phy_engine_handoff_length;
+
+	/* Calibration attributes */
+	phys_addr_t train_imem_base;
+	phys_addr_t train_dmem_base;
+	size_t train_imem_length;
+	size_t train_dmem_length;
+};
+
+/* Message mode */
+enum message_mode {
+	MAJOR_MESSAGE,
+	STREAMING_MESSAGE
+};
+
+static int clr_ca_parity_error_status(phys_addr_t umctl2_base)
+{
+	int ret;
+
+	debug("%s: Clear C/A parity error status in MR5[4]\n", __func__);
+
+	/* Set mode register MRS */
+	clrbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET, DDR4_MRCTRL0_MPR_EN);
+
+	/* Set mode register to write operation */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET, DDR4_MRCTRL0_MR_TYPE);
+
+	/* Set the address of mode rgister to 0x101(MR5) */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET,
+		     (MR5 << DDR4_MRCTRL0_MR_ADDR_SHIFT) &
+		     DDR4_MRCTRL0_MR_ADDR);
+
+	/* Set MR rank to rank 1 */
+	setbits_le32(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(umctl2_base + DDR4_MRCTRL1_OFFSET, MR5_BIT4);
+
+	/* Trigger mode register read or write operation */
+	setbits_le32(umctl2_base + DDR4_MRCTRL0_OFFSET, DDR4_MRCTRL0_MR_WR);
+
+	/* Wait for retry done */
+	ret = wait_for_bit_le32((const void *)(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 ddr_retry_software_sequence(phys_addr_t umctl2_base)
+{
+	u32 value;
+	int ret;
+
+	/* Check software can perform MRS/MPR/PDA? */
+	value = readl(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+		      DDR4_CRCPARSTAT_DFI_ALERT_ERR_NO_SW;
+
+	if (value) {
+		/* Clear interrupt bit for DFI alert error */
+		setbits_le32(umctl2_base + DDR4_CRCPARCTL0_OFFSET,
+			     DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR);
+	}
+
+	debug("%s: Software can perform MRS/MPR/PDA\n", __func__);
+
+	ret = wait_for_bit_le32((const void *)(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;
+	}
+
+	ret = clr_ca_parity_error_status(umctl2_base);
+	if (ret)
+		return ret;
+
+	if (!value) {
+		/* Clear interrupt bit for DFI alert error */
+		setbits_le32(umctl2_base + DDR4_CRCPARCTL0_OFFSET,
+			     DDR4_CRCPARCTL0_DFI_ALERT_ERR_INIT_CLR);
+	}
+
+	return 0;
+}
+
+static int ensure_retry_procedure_complete(phys_addr_t umctl2_base)
+{
+	u32 value;
+	u32 start = get_timer(0);
+	int ret;
+
+	/* Check parity/crc/error window is emptied ? */
+	value = readl(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(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(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+				      DDR4_CRCPARSTAT_DFI_ALERT_ERR_INT;
+
+			if (value) {
+				ret = ddr_retry_software_sequence(umctl2_base);
+				debug("%s: DFI alert error interrupt ",
+				      __func__);
+				debug("is set\n");
+
+				if (ret)
+					return ret;
+			}
+
+			/*
+			 * Check fatal parity error interrupt is set?
+			 */
+			value = readl(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(umctl2_base + DDR4_CRCPARSTAT_OFFSET) &
+			      DDR4_CRCPARSTAT_CMD_IN_ERR_WINDOW;
+
+		udelay(1);
+		WATCHDOG_RESET();
+	}
+
+	return 0;
+}
+
+static int enable_quasi_dynamic_reg_grp3(phys_addr_t umctl2_base,
+					 enum ddr_type umctl2_type)
+{
+	u32 i, value, backup;
+	int ret = 0;
+
+	/* Disable input traffic per port */
+	clrbits_le32(umctl2_base + DDR4_PCTRL0_OFFSET, DDR4_PCTRL0_PORT_EN);
+
+	/* Polling AXI port until idle */
+	ret = wait_for_bit_le32((const void *)(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(umctl2_base + DDR4_DBG1_OFFSET);
+
+	/* Disable input traffic to the controller */
+	setbits_le32(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 *)(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");
+
+			goto out;
+		}
+	}
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		/* Check DDR4 retry is enabled ? */
+		value = readl(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(umctl2_base);
+			if (ret) {
+				debug("%s: Timeout while waiting for",
+				      __func__);
+				debug(" retry procedure complete\n");
+
+				goto out;
+			}
+		}
+	}
+
+	debug("%s: Quasi-dynamic group 3 registers are enabled\n", __func__);
+
+out:
+	/* Restore user setting */
+	writel(backup, umctl2_base + DDR4_DBG1_OFFSET);
+
+	return ret;
+}
+
+static enum ddr_type get_ddr_type(phys_addr_t ddr_type_location)
+{
+	u32 ddr_type_magic = readl(ddr_type_location);
+
+	if (ddr_type_magic == SOC64_HANDOFF_DDR_UMCTL2_DDR4_TYPE)
+		return DDRTYPE_DDR4;
+
+	if (ddr_type_magic == SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_0_TYPE)
+		return DDRTYPE_LPDDR4_0;
+
+	if (ddr_type_magic == SOC64_HANDOFF_DDR_UMCTL2_LPDDR4_1_TYPE)
+		return DDRTYPE_LPDDR4_1;
+
+	return DDRTYPE_UNKNOWN;
+}
+
+static void use_lpddr4_interleaving(bool set)
+{
+	if (set) {
+		printf("Starting LPDDR4 interleaving configuration ...\n");
+		setbits_le32(FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0,
+			     BIT(5));
+	} else {
+		printf("Starting LPDDR4 non-interleaving configuration ...\n");
+		clrbits_le32(FPGA2SDRAM_MGR_MAIN_SIDEBANDMGR_FLAGOUTSET0,
+			     BIT(5));
+	}
+}
+
+static void use_ddr4(enum ddr_type type)
+{
+	if (type == DDRTYPE_DDR4) {
+		printf("Starting DDR4 configuration ...\n");
+		setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_DDR_MODE,
+			     SYSMGR_SOC64_DDR_MODE_MSK);
+	} else if (type == DDRTYPE_LPDDR4_0)  {
+		printf("Starting LPDDR4 configuration ...\n");
+		clrbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_DDR_MODE,
+			     SYSMGR_SOC64_DDR_MODE_MSK);
+
+		use_lpddr4_interleaving(false);
+	}
+}
+
+static int scrubber_ddr_config(phys_addr_t umctl2_base,
+			       enum ddr_type umctl2_type)
+{
+	u32 backup[9];
+	int ret;
+
+	/* Reset to default value, prevent scrubber stop due to lower power */
+	writel(0, umctl2_base + DDR4_PWRCTL_OFFSET);
+
+	/* Backup user settings */
+	backup[0] = readl(umctl2_base + DDR4_SBRCTL_OFFSET);
+	backup[1] = readl(umctl2_base + DDR4_SBRWDATA0_OFFSET);
+	backup[2] = readl(umctl2_base + DDR4_SBRSTART0_OFFSET);
+	if (umctl2_type == DDRTYPE_DDR4) {
+		backup[3] = readl(umctl2_base + DDR4_SBRWDATA1_OFFSET);
+		backup[4] = readl(umctl2_base + DDR4_SBRSTART1_OFFSET);
+	}
+	backup[5] = readl(umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	backup[6] = readl(umctl2_base + DDR4_SBRRANGE1_OFFSET);
+	backup[7] = readl(umctl2_base + DDR4_ECCCFG0_OFFSET);
+	backup[8] = readl(umctl2_base + DDR4_ECCCFG1_OFFSET);
+
+	if (umctl2_type != DDRTYPE_DDR4) {
+		/* Lock ECC region, ensure this regions is not being accessed */
+		setbits_le32(umctl2_base + DDR4_ECCCFG1_OFFSET,
+			     LPDDR4_ECCCFG1_ECC_REGIONS_PARITY_LOCK);
+	}
+	/* Disable input traffic per port */
+	clrbits_le32(umctl2_base + DDR4_PCTRL0_OFFSET, DDR4_PCTRL0_PORT_EN);
+	/* Disables scrubber */
+	clrbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET, DDR4_SBRCTL_SCRUB_EN);
+	/* Polling all scrub writes data have been sent */
+	ret = wait_for_bit_le32((const void *)(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;
+	}
+
+	/* LPDDR4 supports inline ECC only */
+	if (umctl2_type != DDRTYPE_DDR4) {
+		/*
+		 * Setting all regions for protected, this is required for
+		 * srubber to init whole LPDDR4 expect ECC region
+		 */
+		writel(((ONE_EIGHT <<
+		       LPDDR4_ECCCFG0_ECC_REGION_MAP_GRANU_SHIFT) |
+		       (ALL_PROTECTED << LPDDR4_ECCCFG0_ECC_REGION_MAP_SHIFT)),
+		       umctl2_base + DDR4_ECCCFG0_OFFSET);
+	}
+
+	/* Scrub_burst = 1, scrub_mode = 1(performs writes) */
+	writel(DDR4_SBRCTL_SCRUB_BURST_1 | DDR4_SBRCTL_SCRUB_WRITE,
+	       umctl2_base + DDR4_SBRCTL_OFFSET);
+
+	/* Zeroing whole DDR */
+	writel(0, umctl2_base + DDR4_SBRWDATA0_OFFSET);
+	writel(0, umctl2_base + DDR4_SBRSTART0_OFFSET);
+	if (umctl2_type == DDRTYPE_DDR4) {
+		writel(0, umctl2_base + DDR4_SBRWDATA1_OFFSET);
+		writel(0, umctl2_base + DDR4_SBRSTART1_OFFSET);
+	}
+	writel(0, umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	writel(0, umctl2_base + DDR4_SBRRANGE1_OFFSET);
+
+	/* Enables scrubber */
+	setbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET, DDR4_SBRCTL_SCRUB_EN);
+	/* Polling all scrub writes commands have been sent */
+	ret = wait_for_bit_le32((const void *)(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 *)(umctl2_base +
+				DDR4_SBRSTAT_OFFSET), DDR4_SBRSTAT_SCRUB_BUSY,
+				false, TIMEOUT_5000MS, false);
+	if (ret) {
+		printf("%s: Timeout while waiting for", __func__);
+		printf(" sending all scrub data\n");
+		return ret;
+	}
+
+	/* Disables scrubber */
+	clrbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET, DDR4_SBRCTL_SCRUB_EN);
+
+	/* Restore user settings */
+	writel(backup[0], umctl2_base + DDR4_SBRCTL_OFFSET);
+	writel(backup[1], umctl2_base + DDR4_SBRWDATA0_OFFSET);
+	writel(backup[2], umctl2_base + DDR4_SBRSTART0_OFFSET);
+	if (umctl2_type == DDRTYPE_DDR4) {
+		writel(backup[3], umctl2_base + DDR4_SBRWDATA1_OFFSET);
+		writel(backup[4], umctl2_base + DDR4_SBRSTART1_OFFSET);
+	}
+	writel(backup[5], umctl2_base + DDR4_SBRRANGE0_OFFSET);
+	writel(backup[6], umctl2_base + DDR4_SBRRANGE1_OFFSET);
+	writel(backup[7], umctl2_base + DDR4_ECCCFG0_OFFSET);
+	writel(backup[8], umctl2_base + DDR4_ECCCFG1_OFFSET);
+
+	/* Enables ECC scrub on scrubber */
+	if (!(readl(umctl2_base + DDR4_SBRCTL_OFFSET) &
+	    DDR4_SBRCTL_SCRUB_WRITE)) {
+		/* Enables scrubber */
+		setbits_le32(umctl2_base + DDR4_SBRCTL_OFFSET,
+			     DDR4_SBRCTL_SCRUB_EN);
+	}
+
+	return 0;
+}
+
+static void handoff_process(struct ddr_handoff *ddr_handoff_info,
+			    phys_addr_t handoff_base, size_t length,
+			    phys_addr_t base)
+{
+	u32 handoff_table[length];
+	u32 i, value = 0;
+
+	/* Execute configuration handoff */
+	socfpga_handoff_read((void *)handoff_base, handoff_table, length);
+
+	for (i = 0; i < length; i = i + 2) {
+		debug("%s: wr = 0x%08x ",  __func__, handoff_table[i + 1]);
+		if (ddr_handoff_info && base == ddr_handoff_info->phy_base) {
+			/*
+			 * Convert PHY odd offset to even offset that
+			 * supported by ARM processor.
+			 */
+			value = handoff_table[i] << 1;
+
+			writew(handoff_table[i + 1],
+			       (uintptr_t)(value + base));
+			debug("rd = 0x%08x ",
+			      readw((uintptr_t)(value + base)));
+			debug("PHY offset: 0x%08x ", handoff_table[i + 1]);
+		} else {
+			value = handoff_table[i];
+			writel(handoff_table[i + 1], (uintptr_t)(value +
+			       base));
+			 debug("rd = 0x%08x ",
+			       readl((uintptr_t)(value + base)));
+		}
+
+		debug("Absolute addr: 0x%08llx, APB offset: 0x%08x\n",
+		      value + base, value);
+	}
+}
+
+static int init_umctl2(phys_addr_t umctl2_handoff_base,
+		       phys_addr_t umctl2_base, enum ddr_type umctl2_type,
+		       size_t umctl2_handoff_length,
+		       u32 *user_backup)
+{
+	int ret;
+
+	if (umctl2_type == DDRTYPE_DDR4)
+		printf("Initializing DDR4 controller ...\n");
+	else if (umctl2_type == DDRTYPE_LPDDR4_0)
+		printf("Initializing LPDDR4_0 controller ...\n");
+	else if (umctl2_type == DDRTYPE_LPDDR4_1)
+		printf("Initializing LPDDR4_1 controller ...\n");
+
+	/* Prevent controller from issuing read/write to SDRAM */
+	setbits_le32(umctl2_base + DDR4_DBG1_OFFSET, DDR4_DBG1_DISDQ);
+
+	/* Put SDRAM into self-refresh */
+	setbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET, DDR4_PWRCTL_SELFREF_EN);
+
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Ensure the controller is in initialization mode */
+	ret = wait_for_bit_le32((const void *)(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: UMCTL2 handoff base address = 0x%p table length = 0x%08x\n",
+	      __func__, (u32 *)umctl2_handoff_base,
+	      (u32)umctl2_handoff_length);
+
+	handoff_process(NULL, umctl2_handoff_base, umctl2_handoff_length,
+			umctl2_base);
+
+	/* Backup user settings, restore after DDR up running */
+	*user_backup = readl(umctl2_base + DDR4_PWRCTL_OFFSET);
+
+	/* Disable self resfresh */
+	clrbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET, DDR4_PWRCTL_SELFREF_EN);
+
+	if (umctl2_type == DDRTYPE_LPDDR4_0 ||
+	    umctl2_type == DDRTYPE_LPDDR4_1) {
+		/* Setting selfref_sw to 1, based on lpddr4 requirement */
+		setbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET,
+			     DDR4_PWRCTL_SELFREF_SW);
+
+		/* Backup user settings, restore after DDR up running */
+		user_backup++;
+		*user_backup = readl(umctl2_base + DDR4_INIT0_OFFSET) &
+				     DDR4_INIT0_SKIP_RAM_INIT;
+
+		/*
+		 * Setting INIT0.skip_dram_init to 0x3, based on lpddr4
+		 * requirement
+		 */
+		setbits_le32(umctl2_base + DDR4_INIT0_OFFSET,
+			     DDR4_INIT0_SKIP_RAM_INIT);
+	}
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Enable controller from issuing read/write to SDRAM */
+	clrbits_le32(umctl2_base + DDR4_DBG1_OFFSET, DDR4_DBG1_DISDQ);
+
+	return 0;
+}
+
+static int phy_pre_handoff_config(phys_addr_t umctl2_base,
+				  enum ddr_type umctl2_type)
+{
+	int ret;
+	u32 value;
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		/* Check DDR4 retry is enabled ? */
+		value = readl(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(umctl2_base + DDR4_RFSHCTL3_OFFSET,
+				     DDR4_RFSHCTL3_DIS_AUTO_REFRESH);
+		}
+	}
+
+	/* Disable selfref_en & powerdown_en, nvr disable dfi dram clk */
+	clrbits_le32(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(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Masking dfi init complete */
+	clrbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_COMPLETE_EN);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(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;
+}
+
+static int init_phy(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+
+	printf("Initializing DDR PHY ...\n");
+
+	if (ddr_handoff_info->cntlr_t == DDRTYPE_DDR4 ||
+	    ddr_handoff_info->cntlr_t == DDRTYPE_LPDDR4_0) {
+		ret = phy_pre_handoff_config(ddr_handoff_info->cntlr_base,
+					     ddr_handoff_info->cntlr_t);
+		if (ret)
+			return ret;
+	}
+
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1) {
+		ret = phy_pre_handoff_config
+			(ddr_handoff_info->cntlr2_base,
+			 ddr_handoff_info->cntlr2_t);
+		if (ret)
+			return ret;
+	}
+
+	/* Execute PHY configuration handoff */
+	handoff_process(ddr_handoff_info, ddr_handoff_info->phy_handoff_base,
+			ddr_handoff_info->phy_handoff_length,
+			ddr_handoff_info->phy_base);
+
+	printf("DDR PHY configuration is completed\n");
+
+	return 0;
+}
+
+static void phy_init_engine(struct ddr_handoff *handoff)
+{
+	printf("Load PHY Init Engine ...\n");
+
+	/* Execute PIE production code handoff */
+	handoff_process(handoff, handoff->phy_engine_handoff_base,
+			handoff->phy_engine_handoff_length, handoff->phy_base);
+
+	printf("End of loading PHY Init Engine\n");
+}
+
+int populate_ddr_handoff(struct ddr_handoff *handoff)
+{
+	phys_addr_t next_section_header;
+
+	/* DDR handoff */
+	handoff->mem_reset_base = SOC64_HANDOFF_DDR_MEMRESET_BASE;
+	debug("%s: DDR memory reset base = 0x%x\n", __func__,
+	      (u32)handoff->mem_reset_base);
+	debug("%s: DDR memory reset address = 0x%x\n", __func__,
+	      readl(handoff->mem_reset_base));
+
+	/* Beginning of DDR controller handoff */
+	handoff->cntlr_handoff_base = SOC64_HANDOFF_DDR_UMCTL2_SECTION;
+	debug("%s: cntlr handoff base = 0x%x\n", __func__,
+	      (u32)handoff->cntlr_handoff_base);
+
+	/* Get 1st DDR type */
+	handoff->cntlr_t = get_ddr_type(handoff->cntlr_handoff_base +
+					SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET);
+	if (handoff->cntlr_t == DDRTYPE_LPDDR4_1 ||
+	    handoff->cntlr_t == DDRTYPE_UNKNOWN) {
+		debug("%s: Wrong DDR handoff format, the 1st DDR ", __func__);
+		debug("type must be DDR4 or LPDDR4_0\n");
+		return -ENOEXEC;
+	}
+
+	/* 1st cntlr base physical address */
+	handoff->cntlr_base = readl(handoff->cntlr_handoff_base +
+				    SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET);
+	debug("%s: cntlr base = 0x%x\n", __func__, (u32)handoff->cntlr_base);
+
+	/* Get the total length of DDR cntlr handoff section */
+	handoff->cntlr_total_length = readl(handoff->cntlr_handoff_base +
+					    SOC64_HANDOFF_OFFSET_LENGTH);
+	debug("%s: Umctl2 total length in byte = 0x%x\n", __func__,
+	      (u32)handoff->cntlr_total_length);
+
+	/* Get the length of user setting data in DDR cntlr handoff section */
+	handoff->cntlr_handoff_length = socfpga_get_handoff_size((void *)
+						handoff->cntlr_handoff_base);
+	debug("%s: Umctl2 handoff length in word(32-bit) = 0x%x\n", __func__,
+	      (u32)handoff->cntlr_handoff_length);
+
+	/* Wrong format on user setting data */
+	if (handoff->cntlr_handoff_length < 0) {
+		debug("%s: Wrong format on user setting data\n", __func__);
+		return -ENOEXEC;
+	}
+
+	/* Get the next handoff section address */
+	next_section_header = handoff->cntlr_handoff_base +
+				handoff->cntlr_total_length;
+	debug("%s: Next handoff section header location = 0x%llx\n", __func__,
+	      next_section_header);
+
+	/*
+	 * Checking next section handoff is cntlr or PHY, and changing
+	 * subsequent implementation accordingly
+	 */
+	if (readl(next_section_header) == SOC64_HANDOFF_DDR_UMCTL2_MAGIC) {
+		/* Get the next cntlr handoff section address */
+		handoff->cntlr2_handoff_base = next_section_header;
+		debug("%s: umctl2 2nd handoff base = 0x%x\n", __func__,
+		      (u32)handoff->cntlr2_handoff_base);
+
+		/* Get 2nd DDR type */
+		handoff->cntlr2_t = get_ddr_type(handoff->cntlr2_handoff_base +
+					SOC64_HANDOFF_DDR_UMCTL2_TYPE_OFFSET);
+		if (handoff->cntlr2_t == DDRTYPE_LPDDR4_0 ||
+		    handoff->cntlr2_t == DDRTYPE_UNKNOWN) {
+			debug("%s: Wrong DDR handoff format, the 2nd DDR ",
+			      __func__);
+			debug("type must be LPDDR4_1\n");
+			return -ENOEXEC;
+		}
+
+		/* 2nd umctl2 base physical address */
+		handoff->cntlr2_base =
+			readl(handoff->cntlr2_handoff_base +
+			      SOC64_HANDOFF_DDR_UMCTL2_BASE_ADDR_OFFSET);
+		debug("%s: cntlr2 base = 0x%x\n", __func__,
+		      (u32)handoff->cntlr2_base);
+
+		/* Get the total length of 2nd DDR umctl2 handoff section */
+		handoff->cntlr2_total_length =
+			readl(handoff->cntlr2_handoff_base +
+			      SOC64_HANDOFF_OFFSET_LENGTH);
+		debug("%s: Umctl2_2nd total length in byte = 0x%x\n", __func__,
+		      (u32)handoff->cntlr2_total_length);
+
+		/*
+		 * Get the length of user setting data in DDR umctl2 handoff
+		 * section
+		 */
+		handoff->cntlr2_handoff_length =
+			socfpga_get_handoff_size((void *)
+						 handoff->cntlr2_handoff_base);
+		debug("%s: cntlr2 handoff length in word(32-bit) = 0x%x\n",
+		      __func__,
+		     (u32)handoff->cntlr2_handoff_length);
+
+		/* Wrong format on user setting data */
+		if (handoff->cntlr2_handoff_length < 0) {
+			debug("%s: Wrong format on umctl2 user setting data\n",
+			      __func__);
+			return -ENOEXEC;
+		}
+
+		/* Get the next handoff section address */
+		next_section_header = handoff->cntlr2_handoff_base +
+					handoff->cntlr2_total_length;
+		debug("%s: Next handoff section header location = 0x%llx\n",
+		      __func__, next_section_header);
+	}
+
+	/* Checking next section handoff is PHY ? */
+	if (readl(next_section_header) == SOC64_HANDOFF_DDR_PHY_MAGIC) {
+		/* DDR PHY handoff */
+		handoff->phy_handoff_base = next_section_header;
+		debug("%s: PHY handoff base = 0x%x\n", __func__,
+		      (u32)handoff->phy_handoff_base);
+
+		/* PHY base physical address */
+		handoff->phy_base = readl(handoff->phy_handoff_base +
+					SOC64_HANDOFF_DDR_PHY_BASE_OFFSET);
+		debug("%s: PHY base = 0x%x\n", __func__,
+		      (u32)handoff->phy_base);
+
+		/* Get the total length of PHY handoff section */
+		handoff->phy_total_length = readl(handoff->phy_handoff_base +
+						SOC64_HANDOFF_OFFSET_LENGTH);
+		debug("%s: PHY total length in byte = 0x%x\n", __func__,
+		      (u32)handoff->phy_total_length);
+
+		/*
+		 * Get the length of user setting data in DDR PHY handoff
+		 * section
+		 */
+		handoff->phy_handoff_length = socfpga_get_handoff_size((void *)
+						handoff->phy_handoff_base);
+		debug("%s: PHY handoff length in word(32-bit) = 0x%x\n",
+		      __func__, (u32)handoff->phy_handoff_length);
+
+		/* Wrong format on PHY user setting data */
+		if (handoff->phy_handoff_length < 0) {
+			debug("%s: Wrong format on PHY user setting data\n",
+			      __func__);
+			return -ENOEXEC;
+		}
+
+		/* Get the next handoff section address */
+		next_section_header = handoff->phy_handoff_base +
+					handoff->phy_total_length;
+		debug("%s: Next handoff section header location = 0x%llx\n",
+		      __func__, next_section_header);
+	} else {
+		debug("%s: Wrong format for DDR handoff, expect PHY",
+		      __func__);
+		debug(" handoff section after umctl2 handoff section\n");
+		return -ENOEXEC;
+	}
+
+	/* Checking next section handoff is PHY init Engine ? */
+	if (readl(next_section_header) ==
+		SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC) {
+		/* DDR PHY Engine handoff */
+		handoff->phy_engine_handoff_base = next_section_header;
+		debug("%s: PHY init engine handoff base = 0x%x\n", __func__,
+		      (u32)handoff->phy_engine_handoff_base);
+
+		/* Get the total length of PHY init engine handoff section */
+		handoff->phy_engine_total_length =
+				readl(handoff->phy_engine_handoff_base +
+				      SOC64_HANDOFF_OFFSET_LENGTH);
+		debug("%s: PHY engine total length in byte = 0x%x\n", __func__,
+		      (u32)handoff->phy_engine_total_length);
+
+		/*
+		 * Get the length of user setting data in DDR PHY init engine
+		 * handoff section
+		 */
+		handoff->phy_engine_handoff_length =
+			socfpga_get_handoff_size((void *)
+					handoff->phy_engine_handoff_base);
+		debug("%s: PHY engine handoff length in word(32-bit) = 0x%x\n",
+		      __func__, (u32)handoff->phy_engine_handoff_length);
+
+		/* Wrong format on PHY init engine setting data */
+		if (handoff->phy_engine_handoff_length < 0) {
+			debug("%s: Wrong format on PHY init engine ",
+			      __func__);
+			debug("user setting data\n");
+			return -ENOEXEC;
+		}
+	} else {
+		debug("%s: Wrong format for DDR handoff, expect PHY",
+		      __func__);
+		debug(" init engine handoff section after PHY handoff\n");
+		debug(" section\n");
+		return -ENOEXEC;
+	}
+
+	handoff->train_imem_base = handoff->phy_base +
+						DDR_PHY_TRAIN_IMEM_OFFSET;
+	debug("%s: PHY train IMEM base = 0x%x\n",
+	      __func__, (u32)handoff->train_imem_base);
+
+	handoff->train_dmem_base = handoff->phy_base +
+						DDR_PHY_TRAIN_DMEM_OFFSET;
+	debug("%s: PHY train DMEM base = 0x%x\n",
+	      __func__, (u32)handoff->train_dmem_base);
+
+	handoff->train_imem_length = SOC64_HANDOFF_DDR_TRAIN_IMEM_LENGTH;
+	debug("%s: PHY train IMEM length = 0x%x\n",
+	      __func__, (u32)handoff->train_imem_length);
+
+	handoff->train_dmem_length = SOC64_HANDOFF_DDR_TRAIN_DMEM_LENGTH;
+	debug("%s: PHY train DMEM length = 0x%x\n",
+	      __func__, (u32)handoff->train_dmem_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;
+}
+
+static int ddr_start_dfi_init(phys_addr_t umctl2_base,
+			      enum ddr_type umctl2_type)
+{
+	int ret;
+
+	debug("%s: Start DFI init\n", __func__);
+
+	/* Enable quasi-dynamic programing of controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Start DFI init sequence */
+	setbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_START);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(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;
+}
+
+static int ddr_check_dfi_init_complete(phys_addr_t umctl2_base,
+				       enum ddr_type umctl2_type)
+{
+	int ret;
+
+	/* Polling DFI init complete */
+	ret = wait_for_bit_le32((const void *)(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("%s: DFI init completed.\n", __func__);
+
+	/* Enable quasi-dynamic programing of controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Stop DFI init sequence */
+	clrbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_START);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(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:DDR programming done\n", __func__);
+
+	return ret;
+}
+
+static int ddr_trigger_sdram_init(phys_addr_t umctl2_base,
+				  enum ddr_type umctl2_type)
+{
+	int ret;
+
+	/* Enable quasi-dynamic programing of controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Unmasking dfi init complete */
+	setbits_le32(umctl2_base + DDR4_DFIMISC_OFFSET,
+		     DDR4_DFIMISC_DFI_INIT_COMPLETE_EN);
+
+	/* Software exit from self-refresh */
+	clrbits_le32(umctl2_base + DDR4_PWRCTL_OFFSET, DDR4_PWRCTL_SELFREF_SW);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(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:DDR programming done\n", __func__);
+	return ret;
+}
+
+static int ddr_post_handoff_config(phys_addr_t umctl2_base,
+				   enum ddr_type umctl2_type)
+{
+	int ret = 0;
+	u32 value;
+	u32 start = get_timer(0);
+
+	do {
+		if (get_timer(start) > TIMEOUT_200MS) {
+			debug("%s: Timeout while waiting for",
+			      __func__);
+			debug(" DDR enters normal operating mode\n");
+			return -ETIMEDOUT;
+		}
+
+		udelay(1);
+		WATCHDOG_RESET();
+
+		/* Polling until SDRAM entered normal operating mode */
+		value = readl(umctl2_base + DDR4_STAT_OFFSET) &
+			      DDR4_STAT_OPERATING_MODE;
+	} while (value != OPM_NORMAL);
+
+	printf("DDR entered normal operating mode\n");
+
+	/* Enabling auto refresh */
+	clrbits_le32(umctl2_base + DDR4_RFSHCTL3_OFFSET,
+		     DDR4_RFSHCTL3_DIS_AUTO_REFRESH);
+
+	/* Checking ECC is enabled? */
+	value = readl(umctl2_base + DDR4_ECCCFG0_OFFSET) & DDR4_ECC_MODE;
+	if (value) {
+		printf("ECC is enabled\n");
+		ret = scrubber_ddr_config(umctl2_base, umctl2_type);
+		if (ret)
+			printf("Failed to enable ECC\n");
+	}
+
+	return ret;
+}
+
+static int configure_training_firmware(struct ddr_handoff *ddr_handoff_info,
+				       const void *train_imem,
+				       const void *train_dmem)
+{
+	int ret = 0;
+
+	printf("Configuring training firmware ...\n");
+
+	/* Reset SDRAM */
+	writew(DDR_PHY_PROTECT_MEMRESET,
+	       (uintptr_t)(ddr_handoff_info->phy_base +
+	       DDR_PHY_MEMRESETL_OFFSET));
+
+	/* Enable access to the PHY configuration registers */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	/* Copy train IMEM bin */
+	memcpy((void *)ddr_handoff_info->train_imem_base, train_imem,
+	       ddr_handoff_info->train_imem_length);
+
+	ret = memcmp((void *)ddr_handoff_info->train_imem_base, train_imem,
+		     ddr_handoff_info->train_imem_length);
+	if (ret) {
+		debug("%s: Failed to copy train IMEM binary\n", __func__);
+		/* Isolate the APB access from internal CSRs */
+		setbits_le16(ddr_handoff_info->phy_base +
+			     DDR_PHY_APBONLY0_OFFSET, DDR_PHY_MICROCONTMUXSEL);
+		return ret;
+	}
+
+	memcpy((void *)ddr_handoff_info->train_dmem_base, train_dmem,
+	       ddr_handoff_info->train_dmem_length);
+
+	ret = memcmp((void *)ddr_handoff_info->train_dmem_base, train_dmem,
+		     ddr_handoff_info->train_dmem_length);
+	if (ret)
+		debug("%s: Failed to copy train DMEM binary\n", __func__);
+
+	/* Isolate the APB access from internal CSRs */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	return ret;
+}
+
+static void calibrating_sdram(struct ddr_handoff *ddr_handoff_info)
+{
+	/* Init mailbox protocol - set 1 to DCTWRITEPROT[0] */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	/* Init mailbox protocol - set 1 to UCTWRITEPROT[0] */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_UCTWRITEPROT_OFFSET,
+		     DDR_PHY_UCTWRITEPROT);
+
+	/* Reset and stalling ARC processor */
+	setbits_le16(ddr_handoff_info->phy_base + DDR_PHY_MICRORESET_OFFSET,
+		     DDR_PHY_MICRORESET_RESET | DDR_PHY_MICRORESET_STALL);
+
+	/* Release ARC processor */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_MICRORESET_OFFSET,
+		     DDR_PHY_MICRORESET_RESET);
+
+	/* Starting PHY firmware execution */
+	clrbits_le16(ddr_handoff_info->phy_base + DDR_PHY_MICRORESET_OFFSET,
+		     DDR_PHY_MICRORESET_STALL);
+}
+
+static int get_mail(struct ddr_handoff *handoff, enum message_mode mode,
+		    u32 *message_id)
+{
+	int ret;
+
+	/* Polling major messages from PMU */
+	ret = wait_for_bit_le16((const void *)(handoff->phy_base +
+				DDR_PHY_UCTSHADOWREGS_OFFSET),
+				DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW,
+				false, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for",
+		      __func__);
+		debug(" major messages from PMU\n");
+		return ret;
+	}
+
+	*message_id = readw((uintptr_t)(handoff->phy_base +
+			    DDR_PHY_UCTWRITEONLYSHADOW_OFFSET));
+
+	if (mode == STREAMING_MESSAGE)
+		*message_id |= readw((uintptr_t)((handoff->phy_base +
+				     DDR_PHY_UCTDATWRITEONLYSHADOW_OFFSET))) <<
+				     SZ_16;
+
+	/* Ack the receipt of the major message */
+	clrbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	ret = wait_for_bit_le16((const void *)(handoff->phy_base +
+				DDR_PHY_UCTSHADOWREGS_OFFSET),
+				DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for",
+		      __func__);
+		debug(" ack the receipt of the major message completed\n");
+		return ret;
+	}
+
+	/* Complete protocol */
+	setbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	return ret;
+}
+
+static int get_mail_streaming(struct ddr_handoff *handoff,
+			      enum message_mode mode, u32 *index)
+{
+	int ret;
+
+	*index = readw((uintptr_t)(handoff->phy_base +
+		       DDR_PHY_UCTWRITEONLYSHADOW_OFFSET));
+
+	if (mode == STREAMING_MESSAGE)
+		*index |= readw((uintptr_t)((handoff->phy_base +
+				DDR_PHY_UCTDATWRITEONLYSHADOW_OFFSET))) <<
+				SZ_16;
+
+	/* Ack the receipt of the major message */
+	clrbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	ret = wait_for_bit_le16((const void *)(handoff->phy_base +
+				DDR_PHY_UCTSHADOWREGS_OFFSET),
+				DDR_PHY_UCTSHADOWREGS_UCTWRITEPROTESHADOW,
+				true, TIMEOUT_200MS, false);
+	if (ret) {
+		debug("%s: Timeout while waiting for",
+		      __func__);
+		debug(" ack the receipt of the major message completed\n");
+		return ret;
+	}
+
+	/* Complete protocol */
+	setbits_le16(handoff->phy_base + DDR_PHY_DCTWRITEPROT_OFFSET,
+		     DDR_PHY_DCTWRITEPROT);
+
+	return 0;
+}
+
+static int decode_streaming_message(struct ddr_handoff *ddr_handoff_info,
+				    u32 *streaming_index)
+{
+	int i = 0, ret;
+	u32 temp;
+
+	temp = *streaming_index;
+
+	while (i < GET_LOWHW_DATA(temp)) {
+		ret = get_mail(ddr_handoff_info, STREAMING_MESSAGE,
+			       streaming_index);
+		if (ret)
+			return ret;
+
+		printf("args[%d]: 0x%x ", i, *streaming_index);
+		i++;
+	}
+
+	return 0;
+}
+
+static int poll_for_training_complete(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+	u32 message_id = 0;
+	u32 streaming_index = 0;
+
+	do {
+		ret = get_mail(ddr_handoff_info, MAJOR_MESSAGE, &message_id);
+		if (ret)
+			return ret;
+
+		 printf("Major message id = 0%x\n", message_id);
+
+		if (message_id == FW_STREAMING_MSG_ID) {
+			ret = get_mail_streaming(ddr_handoff_info,
+						 STREAMING_MESSAGE,
+						 &streaming_index);
+			if (ret)
+				return ret;
+
+			printf("streaming index 0%x : ", streaming_index);
+
+			decode_streaming_message(ddr_handoff_info,
+						 &streaming_index);
+
+			printf("\n");
+		}
+	} while ((message_id != FW_TRAINING_COMPLETED_STAT) &&
+	       (message_id != FW_TRAINING_FAILED_STAT));
+
+	if (message_id == FW_TRAINING_COMPLETED_STAT) {
+		printf("DDR firmware training completed\n");
+	} else if (message_id == FW_TRAINING_FAILED_STAT) {
+		printf("DDR firmware training failed\n");
+		hang();
+	}
+
+	return 0;
+}
+
+static void enable_phy_clk_for_csr_access(struct ddr_handoff *handoff,
+					  bool enable)
+{
+	if (enable) {
+		/* Enable PHY clk */
+		setbits_le16((uintptr_t)(handoff->phy_base +
+			     DDR_PHY_UCCLKHCLKENABLES_OFFSET),
+			     DDR_PHY_UCCLKHCLKENABLES_UCCLKEN |
+			     DDR_PHY_UCCLKHCLKENABLES_HCLKEN);
+	} else {
+		/* Disable PHY clk */
+		clrbits_le16((uintptr_t)(handoff->phy_base +
+			     DDR_PHY_UCCLKHCLKENABLES_OFFSET),
+			     DDR_PHY_UCCLKHCLKENABLES_UCCLKEN |
+			     DDR_PHY_UCCLKHCLKENABLES_HCLKEN);
+	}
+}
+
+/* helper function for updating train result to umctl2 RANKCTL register */
+static void set_cal_res_to_rankctrl(u32 reg_addr, u16 update_value,
+				    u32 mask, u32 msb_mask, u32 shift)
+{
+	u32 reg, value;
+
+	reg = readl((uintptr_t)reg_addr);
+
+	debug("max value divided by 2 is 0x%x\n", update_value);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+
+	value = (reg & mask) >> shift;
+
+	value += update_value + 3;
+
+	/* reg value greater than 0xF, set one to diff_rank_wr_gap_msb */
+	if (value > 0xF)
+		setbits_le32((u32 *)(uintptr_t)reg_addr, msb_mask);
+	else
+		clrbits_le32((u32 *)(uintptr_t)reg_addr, msb_mask);
+
+	reg = readl((uintptr_t)reg_addr);
+
+	value = (value << shift) & mask;
+
+	/* update register */
+	writel((reg & (~mask)) | value, (uintptr_t)reg_addr);
+
+	reg = readl((uintptr_t)reg_addr);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+}
+
+/* helper function for updating train result to register */
+static void set_cal_res_to_reg(u32 reg_addr, u16 update_value, u32 mask,
+			       u32 shift)
+{
+	u32 reg, value;
+
+	reg = readl((uintptr_t)reg_addr);
+
+	debug("max value divided by 2 is 0x%x\n", update_value);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+
+	value = (reg & mask) >> shift;
+
+	value = ((value + update_value + 3) << shift) & mask;
+
+	/* update register */
+	writel((reg & (~mask)) | value, (uintptr_t)reg_addr);
+
+	reg = readl((uintptr_t)reg_addr);
+	debug("umclt2 register 0x%x value is 0%x before ", reg_addr, reg);
+	debug("update with train result\n");
+}
+
+static u16 get_max_txdqsdlytg0_ux_p0(struct ddr_handoff *handoff, u32 reg,
+				     u8 numdbyte, u16 upd_val)
+{
+	u32 b_addr;
+	u16 val;
+	u8 byte;
+
+	/* Getting max value from DBYTEx TxDqsDlyTg0_ux_p0 */
+	for (byte = 0; byte < numdbyte; byte++) {
+		b_addr = byte << 13;
+
+		/* TxDqsDlyTg0[9:6] is the coarse delay */
+		val = (readw((uintptr_t)(handoff->phy_base +
+			     reg + b_addr)) &
+			     DDR_PHY_TXDQDLYTG0_COARSE_DELAY) >>
+			     DDR_PHY_TXDQDLYTG0_COARSE_DELAY_SHIFT;
+
+		upd_val = max(val, upd_val);
+	}
+
+	return upd_val;
+}
+
+static int set_cal_res_to_umctl2(struct ddr_handoff *handoff,
+				 phys_addr_t umctl2_base,
+				 enum ddr_type umctl2_type)
+{
+	int ret;
+	u8 numdbyte = 0x8;
+	u16 upd_val, val;
+	u32 dramtmg2_reg_addr, rankctl_reg_addr, reg_addr;
+
+	/* Enable quasi-dynamic programing of the controller registers */
+	clrbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	ret = enable_quasi_dynamic_reg_grp3(umctl2_base, umctl2_type);
+	if (ret)
+		return ret;
+
+	/* Enable access to the PHY configuration registers */
+	clrbits_le16(handoff->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_WW_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_WW_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_0) {
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_WW_1_0_OFFSET)));
+
+		upd_val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+					 DMEM_MB_CDD_CHA_WW_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_1) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_WW_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_CHB_WW_0_1_OFFSET)));
+	}
+
+	upd_val = max(val, upd_val);
+	debug("max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	debug("Update train value to umctl2 RANKCTL.diff_rank_wr_gap\n");
+	rankctl_reg_addr = umctl2_base + DDR4_RANKCTL_OFFSET;
+	/* Update train value to umctl2 RANKCTL.diff_rank_wr_gap */
+	set_cal_res_to_rankctrl(rankctl_reg_addr, upd_val,
+				DDR4_RANKCTL_DIFF_RANK_WR_GAP,
+				DDR4_RANKCTL_DIFF_RANK_WR_GAP_MSB,
+				DDR4_RANKCTL_DIFF_RANK_WR_GAP_SHIFT);
+
+	debug("Update train value to umctl2 DRAMTMG2.W2RD\n");
+	dramtmg2_reg_addr = umctl2_base + DDR4_DRAMTMG2_OFFSET;
+	/* Update train value to umctl2 dramtmg2.wr2rd */
+	set_cal_res_to_reg(dramtmg2_reg_addr, upd_val, DDR4_DRAMTMG2_WR2RD, 0);
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		debug("Update train value to umctl2 DRAMTMG9.W2RD_S\n");
+		reg_addr = umctl2_base + DDR4_DRAMTMG9_OFFSET;
+		/* Update train value to umctl2 dramtmg9.wr2rd_s */
+		set_cal_res_to_reg(reg_addr, upd_val, DDR4_DRAMTMG9_W2RD_S, 0);
+	}
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_RR_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_RR_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_0) {
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_RR_1_0_OFFSET)));
+
+		upd_val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+					 DMEM_MB_CDD_CHA_RR_0_1_OFFSET)));
+	} else if (umctl2_type == DDRTYPE_LPDDR4_1) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_RR_1_0_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_CHB_RR_0_1_OFFSET)));
+	}
+
+	upd_val = max(val, upd_val);
+	debug("max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	debug("Update train value to umctl2 RANKCTL.diff_rank_rd_gap\n");
+	/* Update train value to umctl2 RANKCTL.diff_rank_rd_gap */
+	set_cal_res_to_rankctrl(rankctl_reg_addr, upd_val,
+				DDR4_RANKCTL_DIFF_RANK_RD_GAP,
+				DDR4_RANKCTL_DIFF_RANK_RD_GAP_MSB,
+				DDR4_RANKCTL_DIFF_RANK_RD_GAP_SHIFT);
+
+	if (umctl2_type == DDRTYPE_DDR4) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_RW_1_1_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_RW_1_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_RW_0_1_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_RW_0_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+	} else if (umctl2_type == DDRTYPE_LPDDR4_0) {
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_RW_1_1_OFFSET)));
+
+		upd_val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+					 DMEM_MB_CDD_CHA_RW_1_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHA_RW_0_1_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHA_RW_0_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+	} else if (umctl2_type == DDRTYPE_LPDDR4_1) {
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_RW_1_1_OFFSET)));
+
+		upd_val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+					DMEM_MB_CDD_CHB_RW_1_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_HIGHB_DATA(readw((uintptr_t)(handoff->phy_base +
+				     DMEM_MB_CDD_CHB_RW_0_1_OFFSET)));
+
+		upd_val = max(val, upd_val);
+
+		val = GET_LOWB_DATA(readw((uintptr_t)(handoff->phy_base +
+				    DMEM_MB_CDD_CHB_RW_0_0_OFFSET)));
+
+		upd_val = max(val, upd_val);
+	}
+
+	debug("max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	debug("Update train value to umctl2 dramtmg2.rd2wr\n");
+	/* Update train value to umctl2 dramtmg2.rd2wr */
+	set_cal_res_to_reg(dramtmg2_reg_addr, upd_val, DDR4_DRAMTMG2_RD2WR,
+			   DDR4_DRAMTMG2_RD2WR_SHIFT);
+
+	/* Checking ECC is enabled?, lpddr4 using inline ECC */
+	val = readl(umctl2_base + DDR4_ECCCFG0_OFFSET) & DDR4_ECC_MODE;
+	if (val && umctl2_type == DDRTYPE_DDR4)
+		numdbyte = 0x9;
+
+	upd_val = 0;
+
+	/* Getting max value from DBYTEx TxDqsDlyTg0_u0_p0 */
+	upd_val = get_max_txdqsdlytg0_ux_p0(handoff,
+					    DDR_PHY_DBYTE0_TXDQDLYTG0_U0_P0,
+					    numdbyte, upd_val);
+
+	/* Getting max value from DBYTEx TxDqsDlyTg0_u1_p0 */
+	upd_val = get_max_txdqsdlytg0_ux_p0(handoff,
+					    DDR_PHY_DBYTE0_TXDQDLYTG0_U1_P0,
+					    numdbyte, upd_val);
+
+	debug("TxDqsDlyTg0 max value is 0x%x\n", upd_val);
+
+	/* Divided by two is required when running in freq ratio 1:2 */
+	if (!(readl(umctl2_base + DDR4_MSTR_OFFSET) & DDR4_FREQ_RATIO))
+		upd_val = DIV_ROUND_CLOSEST(upd_val, 2);
+
+	reg_addr = umctl2_base + DDR4_DFITMG1_OFFSET;
+	/* Update train value to umctl2 dfitmg1.dfi_wrdata_delay */
+	set_cal_res_to_reg(reg_addr, upd_val, DDR4_DFITMG1_DFI_T_WRDATA_DELAY,
+			   DDR4_DFITMG1_DFI_T_WRDATA_SHIFT);
+
+	/* Complete quasi-dynamic register programming */
+	setbits_le32(umctl2_base + DDR4_SWCTL_OFFSET, DDR4_SWCTL_SW_DONE);
+
+	/* Polling programming done */
+	ret = wait_for_bit_le32((const void *)(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");
+	}
+
+	/* Isolate the APB access from internal CSRs */
+	setbits_le16(handoff->phy_base + DDR_PHY_APBONLY0_OFFSET,
+		     DDR_PHY_MICROCONTMUXSEL);
+
+	return ret;
+}
+
+static int update_training_result(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret = 0;
+
+	/* Updating training result to first DDR controller */
+	if (ddr_handoff_info->cntlr_t == DDRTYPE_DDR4 ||
+	    ddr_handoff_info->cntlr_t == DDRTYPE_LPDDR4_0) {
+		ret = set_cal_res_to_umctl2(ddr_handoff_info,
+					    ddr_handoff_info->cntlr_base,
+					    ddr_handoff_info->cntlr_t);
+		if (ret) {
+			debug("%s: Failed to update train result to ",
+			      __func__);
+			debug("first DDR controller\n");
+			return ret;
+		}
+	}
+
+	/* Updating training result to 2nd DDR controller */
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1) {
+		ret = set_cal_res_to_umctl2(ddr_handoff_info,
+					    ddr_handoff_info->cntlr2_base,
+					    ddr_handoff_info->cntlr2_t);
+		if (ret) {
+			debug("%s: Failed to update train result to ",
+			      __func__);
+			debug("2nd DDR controller\n");
+		}
+	}
+
+	return ret;
+}
+
+static int start_ddr_calibration(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+
+	/* Implement 1D training firmware */
+	ret = configure_training_firmware(ddr_handoff_info,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_IMEM_1D_SECTION,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_DMEM_1D_SECTION);
+	if (ret) {
+		debug("%s: Failed to configure 1D training firmware\n",
+		      __func__);
+		return ret;
+	}
+
+	calibrating_sdram(ddr_handoff_info);
+
+	ret = poll_for_training_complete(ddr_handoff_info);
+	if (ret) {
+		debug("%s: Failed to get FW training completed\n",
+		      __func__);
+		return ret;
+	}
+
+	/* Updating training result to DDR controller */
+	ret = update_training_result(ddr_handoff_info);
+	if (ret)
+		return ret;
+
+	/* Implement 2D training firmware */
+	ret = configure_training_firmware(ddr_handoff_info,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_IMEM_2D_SECTION,
+		(const void *)SOC64_HANDOFF_DDR_TRAIN_DMEM_2D_SECTION);
+	if (ret) {
+		debug("%s: Failed to update train result to ", __func__);
+		debug("DDR controller\n");
+		return ret;
+	}
+
+	calibrating_sdram(ddr_handoff_info);
+
+	ret = poll_for_training_complete(ddr_handoff_info);
+	if (ret)
+		debug("%s: Failed to get FW training completed\n",
+		      __func__);
+
+	return ret;
+}
+
+static int init_controller(struct ddr_handoff *ddr_handoff_info,
+			   u32 *user_backup, u32 *user_backup_2nd)
+{
+	int ret = 0;
+
+	if (ddr_handoff_info->cntlr_t == DDRTYPE_DDR4  ||
+	    ddr_handoff_info->cntlr_t == DDRTYPE_LPDDR4_0) {
+		/* Initialize 1st DDR controller */
+		ret = init_umctl2(ddr_handoff_info->cntlr_handoff_base,
+				  ddr_handoff_info->cntlr_base,
+				  ddr_handoff_info->cntlr_t,
+				  ddr_handoff_info->cntlr_handoff_length,
+				  user_backup);
+		if (ret) {
+			debug("%s: Failed to inilialize first controller\n",
+			      __func__);
+			return ret;
+		}
+	}
+
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1) {
+		/* Initialize 2nd DDR controller */
+		ret = init_umctl2(ddr_handoff_info->cntlr2_handoff_base,
+				  ddr_handoff_info->cntlr2_base,
+				  ddr_handoff_info->cntlr2_t,
+				  ddr_handoff_info->cntlr2_handoff_length,
+				  user_backup_2nd);
+		if (ret)
+			debug("%s: Failed to inilialize 2nd controller\n",
+			      __func__);
+	}
+
+	return ret;
+}
+
+static int dfi_init(struct ddr_handoff *ddr_handoff_info)
+{
+	int ret;
+
+	ret = ddr_start_dfi_init(ddr_handoff_info->cntlr_base,
+				 ddr_handoff_info->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (ddr_handoff_info->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_start_dfi_init(ddr_handoff_info->cntlr2_base,
+					 ddr_handoff_info->cntlr2_t);
+
+	return ret;
+}
+
+static int check_dfi_init(struct ddr_handoff *handoff)
+{
+	int ret;
+
+	ret = ddr_check_dfi_init_complete(handoff->cntlr_base,
+					  handoff->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (handoff->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_check_dfi_init_complete(handoff->cntlr2_base,
+						  handoff->cntlr2_t);
+
+	return ret;
+}
+
+static int trigger_sdram_init(struct ddr_handoff *handoff)
+{
+	int ret;
+
+	ret = ddr_trigger_sdram_init(handoff->cntlr_base,
+				     handoff->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (handoff->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_trigger_sdram_init(handoff->cntlr2_base,
+					     handoff->cntlr2_t);
+
+	return ret;
+}
+
+static int ddr_post_config(struct ddr_handoff *handoff)
+{
+	int ret;
+
+	ret = ddr_post_handoff_config(handoff->cntlr_base,
+				      handoff->cntlr_t);
+	if (ret)
+		return ret;
+
+	if (handoff->cntlr2_t == DDRTYPE_LPDDR4_1)
+		ret = ddr_post_handoff_config(handoff->cntlr2_base,
+					      handoff->cntlr2_t);
+
+	return ret;
+}
+
+static bool is_ddr_retention_enabled(u32 boot_scratch_cold0_reg)
+{
+	return boot_scratch_cold0_reg &
+	       ALT_SYSMGR_SCRATCH_REG_0_DDR_RETENTION_MASK;
+}
+
+static bool is_ddr_bitstream_sha_matching(u32 boot_scratch_cold0_reg)
+{
+	return boot_scratch_cold0_reg & ALT_SYSMGR_SCRATCH_REG_0_DDR_SHA_MASK;
+}
+
+static enum reset_type get_reset_type(u32 boot_scratch_cold0_reg)
+{
+	return (boot_scratch_cold0_reg &
+		ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_MASK) >>
+		ALT_SYSMGR_SCRATCH_REG_0_DDR_RESET_TYPE_SHIFT;
+}
+
+void reset_type_debug_print(u32 boot_scratch_cold0_reg)
+{
+	switch (get_reset_type(boot_scratch_cold0_reg)) {
+	case POR_RESET:
+		debug("%s: POR is triggered\n", __func__);
+		break;
+	case WARM_RESET:
+		debug("%s: Warm reset is triggered\n", __func__);
+		break;
+	case COLD_RESET:
+		debug("%s: Cold reset is triggered\n", __func__);
+		break;
+	default:
+		debug("%s: Invalid reset type\n", __func__);
+	}
+}
+
+bool is_ddr_init(void)
+{
+	u32 reg = readl(socfpga_get_sysmgr_addr() +
+			SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
+
+	reset_type_debug_print(reg);
+
+	if (get_reset_type(reg) == POR_RESET) {
+		debug("%s: DDR init is required\n", __func__);
+		return true;
+	}
+
+	if (get_reset_type(reg) == WARM_RESET) {
+		debug("%s: DDR init is skipped\n", __func__);
+		return false;
+	}
+
+	if (get_reset_type(reg) == COLD_RESET) {
+		if (is_ddr_retention_enabled(reg) &&
+		    is_ddr_bitstream_sha_matching(reg)) {
+			debug("%s: DDR retention bit is set\n", __func__);
+			debug("%s: Matching in DDR bistream\n", __func__);
+			debug("%s: DDR init is skipped\n", __func__);
+			return false;
+		}
+	}
+
+	debug("%s: DDR init is required\n", __func__);
+	return true;
+}
+
+int sdram_mmr_init_full(struct udevice *dev)
+{
+	u32 user_backup[2], user_backup_2nd[2];
+	int ret;
+	struct bd_info bd;
+	struct ddr_handoff ddr_handoff_info;
+	struct altera_sdram_priv *priv = dev_get_priv(dev);
+
+	printf("Checking SDRAM configuration in progress ...\n");
+	ret = populate_ddr_handoff(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to populate DDR handoff\n",
+			      __func__);
+			return ret;
+		}
+
+	/* Set the MPFE NoC mux to correct DDR controller type */
+	use_ddr4(ddr_handoff_info.cntlr_t);
+
+	if (is_ddr_init()) {
+		printf("SDRAM init in progress ...\n");
+
+		/*
+		 * 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;
+
+		ret = init_controller(&ddr_handoff_info, user_backup,
+				      user_backup_2nd);
+		if (ret) {
+			debug("%s: Failed to inilialize DDR controller\n",
+			      __func__);
+			return ret;
+		}
+
+		/* 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");
+
+		/* Initialize DDR PHY */
+		ret = init_phy(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to inilialize DDR PHY\n", __func__);
+			return ret;
+		}
+
+		enable_phy_clk_for_csr_access(&ddr_handoff_info, true);
+
+		ret = start_ddr_calibration(&ddr_handoff_info);
+		if (ret) {
+			debug("%s: Failed to calibrate DDR\n", __func__);
+			return ret;
+		}
+
+		enable_phy_clk_for_csr_access(&ddr_handoff_info, false);
+
+		/* 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);
+
+		ret = dfi_init(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		ret = check_dfi_init(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		ret = trigger_sdram_init(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		ret = ddr_post_config(&ddr_handoff_info);
+		if (ret)
+			return ret;
+
+		/* Restore user settings */
+		writel(user_backup[0], ddr_handoff_info.cntlr_base +
+		       DDR4_PWRCTL_OFFSET);
+
+		if (ddr_handoff_info.cntlr2_t == DDRTYPE_LPDDR4_0)
+			setbits_le32(ddr_handoff_info.cntlr_base +
+				     DDR4_INIT0_OFFSET, user_backup[1]);
+
+		if (ddr_handoff_info.cntlr2_t == DDRTYPE_LPDDR4_1) {
+			/* Restore user settings */
+			writel(user_backup_2nd[0],
+			       ddr_handoff_info.cntlr2_base +
+			       DDR4_PWRCTL_OFFSET);
+
+			setbits_le32(ddr_handoff_info.cntlr2_base +
+				     DDR4_INIT0_OFFSET, user_backup_2nd[1]);
+		}
+
+		/* Enable input traffic per port */
+		setbits_le32(ddr_handoff_info.cntlr_base + DDR4_PCTRL0_OFFSET,
+			     DDR4_PCTRL0_PORT_EN);
+
+		if (ddr_handoff_info.cntlr2_t == DDRTYPE_LPDDR4_1) {
+			/* Enable input traffic per port */
+			setbits_le32(ddr_handoff_info.cntlr2_base +
+				     DDR4_PCTRL0_OFFSET, DDR4_PCTRL0_PORT_EN);
+		}
+
+		printf("DDR init success\n");
+	}
+
+	/* Get bank configuration from devicetree */
+	ret = fdtdec_decode_ram_size(gd->fdt_blob, NULL, 0, NULL,
+				     (phys_size_t *)&gd->ram_size, &bd);
+	if (ret) {
+		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_size_check(&bd);
+
+	sdram_set_firewall(&bd);
+
+	return 0;
+}
diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c
index cc656db97c..d6baac2410 100644
--- a/drivers/ddr/altera/sdram_soc64.c
+++ b/drivers/ddr/altera/sdram_soc64.c
@@ -100,12 +100,14 @@ int emif_reset(struct altera_sdram_plat *plat)
 	return 0;
 }
 
+#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
 int poll_hmc_clock_status(void)
 {
 	return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
 				 SYSMGR_SOC64_HMC_CLK),
 				 SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
 }
+#endif
 
 void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
 {
@@ -249,11 +251,78 @@ phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat)
 	return size;
 }
 
+void sdram_set_firewall(struct bd_info *bd)
+{
+	u32 i;
+	phys_size_t value;
+	u32 lower, upper;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		if (!bd->bi_dram[i].size)
+			continue;
+
+		value = bd->bi_dram[i].start;
+
+		/* Keep first 1MB of SDRAM memory region as secure region when
+		 * using ATF flow, where the ATF code is located.
+		 */
+		if (IS_ENABLED(CONFIG_SPL_ATF) && i == 0)
+			value += SZ_1M;
+
+		/* Setting non-secure MPU region base and base extended */
+		lower = lower_32_bits(value);
+		upper = upper_32_bits(value);
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT +
+				      (i * 4 * sizeof(u32)));
+
+		/* Setting non-secure Non-MPU region base and base extended */
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT +
+				      (i * 4 * sizeof(u32)));
+
+		/* Setting non-secure MPU limit and limit extexded */
+		value = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
+
+		lower = lower_32_bits(value);
+		upper = upper_32_bits(value);
+
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT +
+				      (i * 4 * sizeof(u32)));
+
+		/* Setting non-secure Non-MPU limit and limit extexded */
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT +
+				      (i * 4 * sizeof(u32)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT +
+				      (i * 4 * sizeof(u32)));
+
+		FW_MPU_DDR_SCR_WRITEL(BIT(i) | BIT(i + 8),
+				      FW_MPU_DDR_SCR_EN_SET);
+	}
+}
+
 static int altera_sdram_of_to_plat(struct udevice *dev)
 {
 	struct altera_sdram_plat *plat = dev_get_plat(dev);
 	fdt_addr_t addr;
 
+	/* These regs info are part of DDR handoff in bitstream */
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
+	return 0;
+#endif
+
 	addr = dev_read_addr_index(dev, 0);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
@@ -314,6 +383,7 @@ static struct ram_ops altera_sdram_ops = {
 static const struct udevice_id altera_sdram_ids[] = {
 	{ .compatible = "altr,sdr-ctl-s10" },
 	{ .compatible = "intel,sdr-ctl-agilex" },
+	{ .compatible = "intel,sdr-ctl-n5x" },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/ddr/altera/sdram_soc64.h b/drivers/ddr/altera/sdram_soc64.h
index 8af0afc410..7460f8c220 100644
--- a/drivers/ddr/altera/sdram_soc64.h
+++ b/drivers/ddr/altera/sdram_soc64.h
@@ -180,6 +180,7 @@ int emif_reset(struct altera_sdram_plat *plat);
 int poll_hmc_clock_status(void);
 void sdram_clear_mem(phys_addr_t addr, phys_size_t size);
 void sdram_init_ecc_bits(struct bd_info *bd);
+void sdram_set_firewall(struct bd_info *bd);
 void sdram_size_check(struct bd_info *bd);
 phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat);
 int sdram_mmr_init_full(struct udevice *dev);
-- 
2.19.0


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

* [v3 13/17] arm: socfpga: Add SPL for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (11 preceding siblings ...)
  2021-06-13  8:48 ` [v3 12/17] ddr: altera: Add SDRAM driver for Intel N5X device Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 14/17] board: intel: Add socdk board support " Siew Chin Lim
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add SPL for N5X.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 .../mach-socfpga/{spl_agilex.c => spl_n5x.c}  | 37 +++++++++++--------
 1 file changed, 22 insertions(+), 15 deletions(-)
 copy arch/arm/mach-socfpga/{spl_agilex.c => spl_n5x.c} (83%)

diff --git a/arch/arm/mach-socfpga/spl_agilex.c b/arch/arm/mach-socfpga/spl_n5x.c
similarity index 83%
copy from arch/arm/mach-socfpga/spl_agilex.c
copy to arch/arm/mach-socfpga/spl_n5x.c
index ee5a9dc1e2..d056871d29 100644
--- a/arch/arm/mach-socfpga/spl_agilex.c
+++ b/arch/arm/mach-socfpga/spl_n5x.c
@@ -1,27 +1,26 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 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 <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/system_manager.h>
-#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/u-boot.h>
+#include <asm/utils.h>
 #include <dm/uclass.h>
+#include <hang.h>
+#include <image.h>
+#include <init.h>
+#include <spl.h>
+#include <watchdog.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -54,27 +53,35 @@ void board_init_f(ulong dummy)
 
 	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
-- 
2.19.0


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

* [v3 14/17] board: intel: Add socdk board support for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (12 preceding siblings ...)
  2021-06-13  8:48 ` [v3 13/17] arm: socfpga: Add SPL " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 15/17] arm: dts: Add base dtsi and devkit dts " Siew Chin Lim
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add N5X SoC devkit board.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 board/intel/n5x-socdk/MAINTAINERS                          | 7 +++++++
 board/{altera/stratix10-socdk => intel/n5x-socdk}/Makefile | 2 +-
 .../{altera/stratix10-socdk => intel/n5x-socdk}/socfpga.c  | 2 +-
 3 files changed, 9 insertions(+), 2 deletions(-)
 create mode 100644 board/intel/n5x-socdk/MAINTAINERS
 copy board/{altera/stratix10-socdk => intel/n5x-socdk}/Makefile (50%)
 copy board/{altera/stratix10-socdk => intel/n5x-socdk}/socfpga.c (52%)

diff --git a/board/intel/n5x-socdk/MAINTAINERS b/board/intel/n5x-socdk/MAINTAINERS
new file mode 100644
index 0000000000..c1059f092c
--- /dev/null
+++ b/board/intel/n5x-socdk/MAINTAINERS
@@ -0,0 +1,7 @@
+SOCFPGA BOARD
+M:	Chee Tien Fong <tien.fong.chee@intel.com>
+M:	Lim Siew Chin <elly.siew.chin.lim@intel.com>
+S:	Maintained
+F:	board/intel/n5x-socdk/
+F:	include/configs/socfpga_n5x_socdk.h
+F:	configs/socfpga_n5x_atf_defconfig
diff --git a/board/altera/stratix10-socdk/Makefile b/board/intel/n5x-socdk/Makefile
similarity index 50%
copy from board/altera/stratix10-socdk/Makefile
copy to board/intel/n5x-socdk/Makefile
index 02a9cadf76..accfdcddcb 100644
--- a/board/altera/stratix10-socdk/Makefile
+++ b/board/intel/n5x-socdk/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
+# Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
 #
 # SPDX-License-Identifier:	GPL-2.0
 #
diff --git a/board/altera/stratix10-socdk/socfpga.c b/board/intel/n5x-socdk/socfpga.c
similarity index 52%
copy from board/altera/stratix10-socdk/socfpga.c
copy to board/intel/n5x-socdk/socfpga.c
index 043fc543f1..985ba190d0 100644
--- a/board/altera/stratix10-socdk/socfpga.c
+++ b/board/intel/n5x-socdk/socfpga.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
  *
  */
 
-- 
2.19.0


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

* [v3 15/17] arm: dts: Add base dtsi and devkit dts for Intel N5X device
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (13 preceding siblings ...)
  2021-06-13  8:48 ` [v3 14/17] board: intel: Add socdk board support " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-07-08 16:32   ` Ley Foon Tan
  2021-06-13  8:48 ` [v3 16/17] include: configs: Add Intel N5X device CONFIGs Siew Chin Lim
  2021-06-13  8:48 ` [v3 17/17] arm: socfpga: Enable Intel N5X device build Siew Chin Lim
  16 siblings, 1 reply; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add device tree for N5X.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>

---
v3:
- Update comment for memory example code
- Move all common dts settings for N5X from
  socfpga_n5x_socdk.dts to socfpga_n5x-u-boot.dtsi
- Remove unused parameter "u-boot,boot0"

v2:
- Remove socfpga_n5x.dtsi
- Reuse socfpga_agilex.dtsi in socfpga_n5x_socdk.dts and update
  n5x data accordingly.
---
 arch/arm/dts/Makefile                         |   1 +
 arch/arm/dts/socfpga_n5x-u-boot.dtsi          | 175 ++++++++++++++++++
 arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi    |  67 +++++++
 ...agilex_socdk.dts => socfpga_n5x_socdk.dts} |  25 ++-
 4 files changed, 262 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/dts/socfpga_n5x-u-boot.dtsi
 create mode 100644 arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
 copy arch/arm/dts/{socfpga_agilex_socdk.dts => socfpga_n5x_socdk.dts} (81%)

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 096068261d..8a513e2a87 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -393,6 +393,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) +=				\
 	socfpga_cyclone5_socrates.dtb			\
 	socfpga_cyclone5_sr1500.dtb			\
 	socfpga_cyclone5_vining_fpga.dtb		\
+	socfpga_n5x_socdk.dtb				\
 	socfpga_stratix10_socdk.dtb
 
 dtb-$(CONFIG_TARGET_DRA7XX_EVM) += dra72-evm.dtb dra7-evm.dtb	\
diff --git a/arch/arm/dts/socfpga_n5x-u-boot.dtsi b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
new file mode 100644
index 0000000000..d144116e71
--- /dev/null
+++ b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include "socfpga_soc64_fit-u-boot.dtsi"
+
+/{
+	memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		u-boot,dm-pre-reloc;
+	};
+
+	soc {
+		u-boot,dm-pre-reloc;
+
+		ccu: cache-controller@f7000000 {
+			compatible = "arteris,ncore-ccu";
+			reg = <0xf7000000 0x100900>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+};
+
+&clkmgr {
+	compatible = "intel,n5x-clkmgr";
+	u-boot,dm-pre-reloc;
+};
+
+
+&gmac1 {
+	altr,sysmgr-syscon = <&sysmgr 0x48 0>;
+	clocks = <&clkmgr N5X_EMAC1_CLK>;
+};
+
+&gmac2 {
+	altr,sysmgr-syscon = <&sysmgr 0x4c 0>;
+	clocks = <&clkmgr N5X_EMAC2_CLK>;
+};
+
+&i2c0 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c1 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c2 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c3 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&i2c4 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	reset-names = "i2c";
+};
+
+&memclkmgr {
+	u-boot,dm-pre-reloc;
+};
+
+
+&mmc {
+	clocks = <&clkmgr N5X_L4_MP_CLK>,
+		 <&clkmgr N5X_SDMMC_CLK>;
+	resets = <&rst SDMMC_RESET>, <&rst SDMMC_OCP_RESET>;
+};
+
+&pdma {
+	clocks = <&clkmgr N5X_L4_MAIN_CLK>;
+};
+
+&spi0 {
+	clocks = <&clkmgr N5X_L4_MAIN_CLK>;
+};
+
+&spi1 {
+	clocks = <&clkmgr N5X_L4_MAIN_CLK>;
+};
+
+&timer0 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&timer1 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&timer2 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&timer3 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&porta {
+	bank-name = "porta";
+};
+
+&portb {
+	bank-name = "portb";
+};
+
+&qspi {
+	u-boot,dm-pre-reloc;
+};
+
+&rst {
+	compatible = "altr,rst-mgr";
+	altr,modrst-offset = <0x20>;
+	u-boot,dm-pre-reloc;
+};
+
+&sdr {
+	compatible = "intel,sdr-ctl-n5x";
+	resets = <&rst DDRSCH_RESET>;
+	clocks = <&memclkmgr>;
+	clock-names = "mem_clk";
+	u-boot,dm-pre-reloc;
+};
+
+&sysmgr {
+	compatible = "altr,sys-mgr", "syscon";
+	u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+	u-boot,dm-pre-reloc;
+};
+
+&uart1 {
+	clocks = <&clkmgr N5X_L4_SP_CLK>;
+};
+
+&usb0 {
+	clocks = <&clkmgr N5X_USB_CLK>;
+	disable-over-current;
+	u-boot,dm-pre-reloc;
+};
+
+&usb1 {
+	clocks = <&clkmgr N5X_USB_CLK>;
+	u-boot,dm-pre-reloc;
+};
+
+&watchdog0 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+	u-boot,dm-pre-reloc;
+};
+
+&watchdog1 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+};
+
+&watchdog2 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+};
+
+&watchdog3 {
+	clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
+};
+
diff --git a/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
new file mode 100644
index 0000000000..612d394019
--- /dev/null
+++ b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ */
+
+#include "socfpga_n5x-u-boot.dtsi"
+
+/{
+	aliases {
+		spi0 = &qspi;
+		i2c0 = &i2c1;
+	};
+
+	memory {
+		/*
+		 * Memory type: DDR4 (interleaving mode)
+		 * 16GB
+		 *     <0 0x00000000 0 0x80000000>,
+		 *     <4 0x80000000 3 0x80000000>;
+		 *
+		 * 8GB
+		 *     <0 0x00000000 0 0x80000000>,
+		 *     <2 0x80000000 1 0x80000000>;
+		 *
+		 * 4GB
+		 *     <0 0x00000000 0 0x80000000>,
+		 *     <1 0x80000000 0 0x80000000>;
+		 *
+		 * Memory type: LPDDR4 (non-interleaving mode)
+		 * Total memory size 3GB, usable = 2.5GB, 0.5GB trade off for secure
+		 * region.
+		 */
+		reg = <0 0x00000000 0 0x60000000>,
+			  <0x10 0x00100000 0 0x40000000>;
+	};
+};
+
+&flash0 {
+	compatible = "jedec,spi-nor";
+	spi-tx-bus-width = <4>;
+	spi-rx-bus-width = <4>;
+	u-boot,dm-pre-reloc;
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&nand {
+	u-boot,dm-pre-reloc;
+};
+
+&mmc {
+	drvsel = <3>;
+	smplsel = <0>;
+	u-boot,dm-pre-reloc;
+};
+
+&qspi {
+	status = "okay";
+};
+
+&watchdog0 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/socfpga_agilex_socdk.dts b/arch/arm/dts/socfpga_n5x_socdk.dts
similarity index 81%
copy from arch/arm/dts/socfpga_agilex_socdk.dts
copy to arch/arm/dts/socfpga_n5x_socdk.dts
index bcdeecc0e0..4cb71b5de3 100644
--- a/arch/arm/dts/socfpga_agilex_socdk.dts
+++ b/arch/arm/dts/socfpga_n5x_socdk.dts
@@ -1,11 +1,12 @@
 // SPDX-License-Identifier:     GPL-2.0
 /*
- * Copyright (C) 2019, Intel Corporation
+ * Copyright (C) 2020-2021, Intel Corporation
  */
 #include "socfpga_agilex.dtsi"
+#include <dt-bindings/clock/n5x-clock.h>
 
 / {
-	model = "SoCFPGA Agilex SoCDK";
+	model = "eASIC N5X SoCDK";
 
 	aliases {
 		serial0 = &uart0;
@@ -47,6 +48,18 @@
 			osc1 {
 				clock-frequency = <25000000>;
 			};
+
+			dram_eosc_clk: dram-eosc-clk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+			};
+		};
+
+		memclkmgr: mem-clock-controller@f8040000 {
+			compatible = "intel,n5x-mem-clkmgr";
+			reg = <0xf8040000 0x1000>;
+			#clock-cells = <0>;
+			clocks = <&dram_eosc_clk>, <&f2s_free_clk>;
 		};
 	};
 };
@@ -59,8 +72,8 @@
 	status = "okay";
 	phy-mode = "rgmii";
 	phy-handle = <&phy0>;
-
 	max-frame-size = <9000>;
+	clocks = <&clkmgr N5X_EMAC0_CLK>;
 
 	mdio0 {
 		#address-cells = <1>;
@@ -98,14 +111,14 @@
 
 &usb0 {
 	status = "okay";
-	disable-over-current;
 };
 
-&watchdog0 {
+&usb1 {
 	status = "okay";
 };
 
 &qspi {
+	status = "okay";
 	flash0: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -116,7 +129,7 @@
 		m25p,fast-read;
 		cdns,page-size = <256>;
 		cdns,block-size = <16>;
-		cdns,read-delay = <1>;
+		cdns,read-delay = <3>;
 		cdns,tshsl-ns = <50>;
 		cdns,tsd2d-ns = <50>;
 		cdns,tchsh-ns = <4>;
-- 
2.19.0


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

* [v3 16/17] include: configs: Add Intel N5X device CONFIGs
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (14 preceding siblings ...)
  2021-06-13  8:48 ` [v3 15/17] arm: dts: Add base dtsi and devkit dts " Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  2021-06-13  8:48 ` [v3 17/17] arm: socfpga: Enable Intel N5X device build Siew Chin Lim
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add CONFIGs for N5X.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 include/configs/socfpga_n5x_socdk.h | 45 +++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 include/configs/socfpga_n5x_socdk.h

diff --git a/include/configs/socfpga_n5x_socdk.h b/include/configs/socfpga_n5x_socdk.h
new file mode 100644
index 0000000000..c295e91e3d
--- /dev/null
+++ b/include/configs/socfpga_n5x_socdk.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef __CONFIG_SOCFGPA_N5X_H__
+#define __CONFIG_SOCFGPA_N5X_H__
+
+#include <configs/socfpga_soc64_common.h>
+
+#undef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \
+	"bootfile=" CONFIG_BOOTFILE "\0" \
+	"fdt_addr=1100000\0" \
+	"fdtimage=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
+	"mmcroot=/dev/mmcblk0p2\0" \
+	"mmcboot=setenv bootargs " CONFIG_BOOTARGS \
+		" root=${mmcroot} rw rootwait;" \
+		"booti ${loadaddr} - ${fdt_addr}\0" \
+	"mmcload=mmc rescan;" \
+		"load mmc 0:1 ${loadaddr} ${bootfile};" \
+		"load mmc 0:1 ${fdt_addr} ${fdtimage}\0" \
+	"mmcfitboot=setenv bootargs " CONFIG_BOOTARGS \
+		" root=${mmcroot} rw rootwait;" \
+		"bootm ${loadaddr}\0" \
+	"mmcfitload=mmc rescan;" \
+		"load mmc 0:1 ${loadaddr} ${bootfile}\0" \
+	"ramboot=setenv bootargs " CONFIG_BOOTARGS";" \
+		"booti ${loadaddr} - ${fdt_addr}\0" \
+	"linux_qspi_enable=if sf probe; then " \
+		"echo Enabling QSPI at Linux DTB...;" \
+		"fdt addr ${fdt_addr}; fdt resize;" \
+		"fdt set /soc/spi@ff8d2000 status okay;" \
+		"if fdt set /soc/clocks/qspi-clk clock-frequency" \
+		" ${qspi_clock}; then" \
+		" else fdt set /soc/clkmgr/clocks/qspi_clk clock-frequency" \
+		" ${qspi_clock}; fi; fi\0" \
+	"scriptaddr=0x02100000\0" \
+	"scriptfile=u-boot.scr\0" \
+	"fatscript=if fatload mmc 0:1 ${scriptaddr} ${scriptfile};" \
+		   "then source ${scriptaddr}; fi\0"
+
+#endif	/* __CONFIG_SOCFGPA_N5X_H__ */
-- 
2.19.0


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

* [v3 17/17] arm: socfpga: Enable Intel N5X device build
  2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
                   ` (15 preceding siblings ...)
  2021-06-13  8:48 ` [v3 16/17] include: configs: Add Intel N5X device CONFIGs Siew Chin Lim
@ 2021-06-13  8:48 ` Siew Chin Lim
  16 siblings, 0 replies; 24+ messages in thread
From: Siew Chin Lim @ 2021-06-13  8:48 UTC (permalink / raw)
  To: u-boot
  Cc: Marek Vasut, Ley Foon Tan, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan, Siew Chin Lim

Add defconfig for N5X to support legacy, ATF and VAB boot flow.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
---
 arch/arm/mach-socfpga/Kconfig                 | 21 +++++++++++++-
 arch/arm/mach-socfpga/Makefile                | 28 +++++++++++++++----
 ...ab_defconfig => socfpga_n5x_atf_defconfig} | 12 ++++----
 ...agilex_defconfig => socfpga_n5x_defconfig} | 14 ++++------
 ...ab_defconfig => socfpga_n5x_vab_defconfig} | 11 ++++----
 5 files changed, 61 insertions(+), 25 deletions(-)
 copy configs/{socfpga_agilex_vab_defconfig => socfpga_n5x_atf_defconfig} (87%)
 copy configs/{socfpga_agilex_defconfig => socfpga_n5x_defconfig} (82%)
 copy configs/{socfpga_agilex_vab_defconfig => socfpga_n5x_vab_defconfig} (87%)

diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 0c35406232..a4d733c756 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -8,7 +8,7 @@ config NR_DRAM_BANKS
 
 config SOCFPGA_SECURE_VAB_AUTH
 	bool "Enable boot image authentication with Secure Device Manager"
-	depends on TARGET_SOCFPGA_AGILEX
+	depends on TARGET_SOCFPGA_AGILEX || TARGET_SOCFPGA_N5X
 	select FIT_IMAGE_POST_PROCESS
 	select SHA384
 	select SHA512_ALGO
@@ -91,6 +91,22 @@ config TARGET_SOCFPGA_GEN5
 	imply SPL_SYS_MALLOC_SIMPLE
 	imply SPL_USE_TINY_PRINTF
 
+config TARGET_SOCFPGA_N5X
+	bool
+	select ARMV8_MULTIENTRY
+	select ARMV8_SET_SMPEN
+	select BINMAN if SPL_ATF
+	select CLK
+	select FPGA_INTEL_SDM_MAILBOX
+	select NCORE_CACHE
+	select SPL_ALTERA_SDRAM
+	select SPL_CLK if SPL
+	select TARGET_SOCFPGA_SOC64
+
+config TARGET_SOCFPGA_N5X_SOCDK
+	bool "Intel eASIC SoCDK (N5X)"
+	select TARGET_SOCFPGA_N5X
+
 config TARGET_SOCFPGA_SOC64
 	bool
 
@@ -183,6 +199,7 @@ config SYS_BOARD
 	default "de0-nano-soc" if TARGET_SOCFPGA_TERASIC_DE0_NANO
 	default "de1-soc" if TARGET_SOCFPGA_TERASIC_DE1_SOC
 	default "de10-nano" if TARGET_SOCFPGA_TERASIC_DE10_NANO
+	default "n5x-socdk" if TARGET_SOCFPGA_N5X_SOCDK
 	default "is1" if TARGET_SOCFPGA_IS1
 	default "mcvevk" if TARGET_SOCFPGA_ARIES_MCVEVK
 	default "secu1" if TARGET_SOCFPGA_ARRIA5_SECU1
@@ -194,6 +211,7 @@ config SYS_BOARD
 
 config SYS_VENDOR
 	default "intel" if TARGET_SOCFPGA_AGILEX_SOCDK
+	default "intel" if TARGET_SOCFPGA_N5X_SOCDK
 	default "altera" if TARGET_SOCFPGA_ARRIA5_SOCDK
 	default "altera" if TARGET_SOCFPGA_ARRIA10_SOCDK
 	default "altera" if TARGET_SOCFPGA_CYCLONE5_SOCDK
@@ -221,6 +239,7 @@ config SYS_CONFIG_NAME
 	default "socfpga_de0_nano_soc" if TARGET_SOCFPGA_TERASIC_DE0_NANO
 	default "socfpga_de1_soc" if TARGET_SOCFPGA_TERASIC_DE1_SOC
 	default "socfpga_de10_nano" if TARGET_SOCFPGA_TERASIC_DE10_NANO
+	default "socfpga_n5x_socdk" if TARGET_SOCFPGA_N5X_SOCDK
 	default "socfpga_is1" if TARGET_SOCFPGA_IS1
 	default "socfpga_mcvevk" if TARGET_SOCFPGA_ARIES_MCVEVK
 	default "socfpga_sockit" if TARGET_SOCFPGA_TERASIC_SOCKIT
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 58afde950f..ec38b64dd4 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -4,7 +4,7 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # Copyright (C) 2012-2017 Altera Corporation <www.altera.com>
-# Copyright (C) 2017-2020 Intel Corporation <www.intel.com>
+# Copyright (C) 2017-2021 Intel Corporation <www.intel.com>
 
 obj-y	+= board.o
 obj-y	+= clock_manager.o
@@ -56,6 +56,21 @@ obj-y	+= wrap_handoff_soc64.o
 obj-y	+= wrap_pll_config_soc64.o
 endif
 
+ifdef CONFIG_TARGET_SOCFPGA_N5X
+obj-y	+= clock_manager_n5x.o
+obj-y	+= lowlevel_init_soc64.o
+obj-y	+= mailbox_s10.o
+obj-y	+= misc_soc64.o
+obj-y	+= mmu-arm64_s10.o
+obj-y	+= reset_manager_s10.o
+obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= secure_vab.o
+obj-y	+= system_manager_soc64.o
+obj-y	+= timer_s10.o
+obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)	+= vab.o
+obj-y	+= wrap_handoff_soc64.o
+obj-y	+= wrap_pll_config_soc64.o
+endif
+
 ifdef CONFIG_SPL_BUILD
 ifdef CONFIG_TARGET_SOCFPGA_GEN5
 obj-y	+= spl_gen5.o
@@ -64,18 +79,21 @@ obj-y	+= wrap_iocsr_config.o
 obj-y	+= wrap_pinmux_config.o
 obj-y	+= wrap_sdram_config.o
 endif
+ifdef CONFIG_TARGET_SOCFPGA_SOC64
+obj-y	+= firewall.o
+obj-y	+= spl_soc64.o
+endif
 ifdef CONFIG_TARGET_SOCFPGA_ARRIA10
 obj-y	+= spl_a10.o
 endif
 ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
-obj-y	+= firewall.o
 obj-y	+= spl_s10.o
-obj-y	+= spl_soc64.o
 endif
 ifdef CONFIG_TARGET_SOCFPGA_AGILEX
-obj-y	+= firewall.o
 obj-y	+= spl_agilex.o
-obj-y	+= spl_soc64.o
+endif
+ifdef CONFIG_TARGET_SOCFPGA_N5X
+obj-y	+= spl_n5x.o
 endif
 else
 obj-$(CONFIG_SPL_ATF) += secure_reg_helper.o
diff --git a/configs/socfpga_agilex_vab_defconfig b/configs/socfpga_n5x_atf_defconfig
similarity index 87%
copy from configs/socfpga_agilex_vab_defconfig
copy to configs/socfpga_n5x_atf_defconfig
index af726bab69..b65ed00006 100644
--- a/configs/socfpga_agilex_vab_defconfig
+++ b/configs/socfpga_n5x_atf_defconfig
@@ -9,11 +9,10 @@ CONFIG_ENV_OFFSET=0x200
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
 CONFIG_DM_GPIO=y
 CONFIG_SPL_TEXT_BASE=0xFFE00000
-CONFIG_SOCFPGA_SECURE_VAB_AUTH=y
-CONFIG_TARGET_SOCFPGA_AGILEX_SOCDK=y
-CONFIG_IDENT_STRING="socfpga_agilex"
+CONFIG_TARGET_SOCFPGA_N5X_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_n5x"
 CONFIG_SPL_FS_FAT=y
-CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk"
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_n5x_socdk"
 CONFIG_FIT=y
 CONFIG_SPL_FIT_SIGNATURE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -21,7 +20,7 @@ CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_BOOTDELAY=5
 CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="earlycon"
+CONFIG_BOOTARGS="earlycon panic=-1 earlyprintk=ttyS0,115200"
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
 CONFIG_SPL_CRC32_SUPPORT=y
@@ -30,7 +29,7 @@ CONFIG_SPL_SPI_LOAD=y
 CONFIG_SPL_ATF=y
 CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="SOCFPGA_AGILEX # "
+CONFIG_SYS_PROMPT="SOCFPGA_N5X # "
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -44,6 +43,7 @@ CONFIG_CMD_CACHE=y
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_WDT=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
diff --git a/configs/socfpga_agilex_defconfig b/configs/socfpga_n5x_defconfig
similarity index 82%
copy from configs/socfpga_agilex_defconfig
copy to configs/socfpga_n5x_defconfig
index 0e5ef062a5..1f6e23e08d 100644
--- a/configs/socfpga_agilex_defconfig
+++ b/configs/socfpga_n5x_defconfig
@@ -3,27 +3,25 @@ CONFIG_ARCH_SOCFPGA=y
 CONFIG_SYS_TEXT_BASE=0x1000
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_NR_DRAM_BANKS=2
-CONFIG_SYS_MEMTEST_START=0x00000000
-CONFIG_SYS_MEMTEST_END=0x3fe00000
 CONFIG_ENV_SIZE=0x1000
 CONFIG_ENV_OFFSET=0x200
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x3c00000
 CONFIG_DM_GPIO=y
 CONFIG_SPL_TEXT_BASE=0xFFE00000
-CONFIG_TARGET_SOCFPGA_AGILEX_SOCDK=y
-CONFIG_IDENT_STRING="socfpga_agilex"
+CONFIG_TARGET_SOCFPGA_N5X_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_n5x"
 CONFIG_SPL_FS_FAT=y
 # CONFIG_PSCI_RESET is not set
-CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk"
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_n5x_socdk"
 CONFIG_BOOTDELAY=5
 CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="earlycon"
+CONFIG_BOOTARGS="earlycon panic=-1 earlyprintk=ttyS0,115200"
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="run fatscript; run mmcload; run linux_qspi_enable; run mmcboot"
 CONFIG_SPL_CACHE=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="SOCFPGA_AGILEX # "
+CONFIG_SYS_PROMPT="SOCFPGA_N5X # "
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -37,10 +35,10 @@ CONFIG_CMD_CACHE=y
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_WDT=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
-CONFIG_SPL_ALTERA_SDRAM=y
 CONFIG_DWAPB_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_DW=y
diff --git a/configs/socfpga_agilex_vab_defconfig b/configs/socfpga_n5x_vab_defconfig
similarity index 87%
copy from configs/socfpga_agilex_vab_defconfig
copy to configs/socfpga_n5x_vab_defconfig
index af726bab69..987d5ce58c 100644
--- a/configs/socfpga_agilex_vab_defconfig
+++ b/configs/socfpga_n5x_vab_defconfig
@@ -10,10 +10,10 @@ CONFIG_SYS_SPI_U_BOOT_OFFS=0x02000000
 CONFIG_DM_GPIO=y
 CONFIG_SPL_TEXT_BASE=0xFFE00000
 CONFIG_SOCFPGA_SECURE_VAB_AUTH=y
-CONFIG_TARGET_SOCFPGA_AGILEX_SOCDK=y
-CONFIG_IDENT_STRING="socfpga_agilex"
+CONFIG_TARGET_SOCFPGA_N5X_SOCDK=y
+CONFIG_IDENT_STRING="socfpga_n5x"
 CONFIG_SPL_FS_FAT=y
-CONFIG_DEFAULT_DEVICE_TREE="socfpga_agilex_socdk"
+CONFIG_DEFAULT_DEVICE_TREE="socfpga_n5x_socdk"
 CONFIG_FIT=y
 CONFIG_SPL_FIT_SIGNATURE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -21,7 +21,7 @@ CONFIG_SPL_LOAD_FIT_ADDRESS=0x02000000
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_BOOTDELAY=5
 CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="earlycon"
+CONFIG_BOOTARGS="earlycon panic=-1 earlyprintk=ttyS0,115200"
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="run fatscript; run mmcfitload; run mmcfitboot"
 CONFIG_SPL_CRC32_SUPPORT=y
@@ -30,7 +30,7 @@ CONFIG_SPL_SPI_LOAD=y
 CONFIG_SPL_ATF=y
 CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PROMPT="SOCFPGA_AGILEX # "
+CONFIG_SYS_PROMPT="SOCFPGA_N5X # "
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
@@ -44,6 +44,7 @@ CONFIG_CMD_CACHE=y
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_WDT=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
-- 
2.19.0


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

* Re: [v3 04/17] arm: socfpga: Add handoff data support for Intel N5X device
  2021-06-13  8:48 ` [v3 04/17] arm: socfpga: Add handoff data support " Siew Chin Lim
@ 2021-07-08 16:15   ` Ley Foon Tan
  0 siblings, 0 replies; 24+ messages in thread
From: Ley Foon Tan @ 2021-07-08 16:15 UTC (permalink / raw)
  To: Siew Chin Lim
  Cc: ZY - u-boot, Marek Vasut, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan

On Sun, Jun 13, 2021 at 4:49 PM Siew Chin Lim
<elly.siew.chin.lim@intel.com> wrote:
>
> From: Tien Fong Chee <tien.fong.chee@intel.com>
>
> N5X support both HPS handoff data and DDR handoff data.
> Existing HPS handoff functions are restructured to support both existing
> devices and N5X device.
>
> Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
> Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
>
> ---
> v3
> - Adding helper function for getting endianness type.
>
> v2:
> - Enabled auto detect the endianness from the magic word
> - Merged and simplifying the big and little endian flow
> ---
>  .../mach-socfpga/include/mach/handoff_soc64.h |  38 ++++-
>  arch/arm/mach-socfpga/system_manager_soc64.c  |  18 +--
>  arch/arm/mach-socfpga/wrap_handoff_soc64.c    | 132 +++++++++++++-----

Reviewed-by: Ley Foon Tan <lftan.linux@gmail.com>

Regards
Ley Foon

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

* Re: [v3 05/17] drivers: clk: Add clock driver for Intel N5X device
  2021-06-13  8:48 ` [v3 05/17] drivers: clk: Add clock driver " Siew Chin Lim
@ 2021-07-08 16:17   ` Ley Foon Tan
  0 siblings, 0 replies; 24+ messages in thread
From: Ley Foon Tan @ 2021-07-08 16:17 UTC (permalink / raw)
  To: Siew Chin Lim
  Cc: ZY - u-boot, Marek Vasut, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan

On Sun, Jun 13, 2021 at 4:49 PM Siew Chin Lim
<elly.siew.chin.lim@intel.com> wrote:
>
> Add clock manager driver for N5X. Provides clock initialization
> and get_rate functions.
>
> Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
>
> ---
> v3:
> - Use BIT() macro for CLKMGR_INTER_*_MASK macro
>
> v2:
> - common.h need to be included before clock_manager.h
> - Remove unnecessary comment : write 1 to clear
> - Remove unnecessary () in the code
> ---
>  drivers/clk/altera/Makefile           |   3 +-
>  drivers/clk/altera/clk-n5x.c          | 489 ++++++++++++++++++++++++++
>  drivers/clk/altera/clk-n5x.h          | 217 ++++++++++++
>  include/dt-bindings/clock/n5x-clock.h |  71 ++++
>  4 files changed, 779 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/altera/clk-n5x.c
>  create mode 100644 drivers/clk/altera/clk-n5x.h
>  create mode 100644 include/dt-bindings/clock/n5x-clock.h

Reviewed-by: Ley Foon Tan <lftan.linux@gmail.com>

Regards
Ley Foon

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

* Re: [v3 07/17] drivers: clk: Add memory clock driver for Intel N5X device
  2021-06-13  8:48 ` [v3 07/17] drivers: clk: Add memory clock driver " Siew Chin Lim
@ 2021-07-08 16:19   ` Ley Foon Tan
  0 siblings, 0 replies; 24+ messages in thread
From: Ley Foon Tan @ 2021-07-08 16:19 UTC (permalink / raw)
  To: Siew Chin Lim
  Cc: ZY - u-boot, Marek Vasut, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan

On Sun, Jun 13, 2021 at 4:49 PM Siew Chin Lim
<elly.siew.chin.lim@intel.com> wrote:
>
> Add memory clock manager driver for N5X. Provides memory clock
> initialization and enable functions.
>
> Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
>
> ---
> v3:
> - Use BIT() and GENMASK() macro for all *MASK macro
>
> v2:
> - common.h need to be included before clock_manager.h
> - For consistency, use small letter fo 0x0c and 0x1c in macros
> ---
>  drivers/clk/altera/Makefile      |   1 +
>  drivers/clk/altera/clk-mem-n5x.c | 136 +++++++++++++++++++++++++++++++
>  drivers/clk/altera/clk-mem-n5x.h |  84 +++++++++++++++++++
>  3 files changed, 221 insertions(+)
>  create mode 100644 drivers/clk/altera/clk-mem-n5x.c
>  create mode 100644 drivers/clk/altera/clk-mem-n5x.h
>

Reviewed-by: Ley Foon Tan <lftan.linux@gmail.com>

Regards
Ley Foon

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

* Re: [v3 15/17] arm: dts: Add base dtsi and devkit dts for Intel N5X device
  2021-06-13  8:48 ` [v3 15/17] arm: dts: Add base dtsi and devkit dts " Siew Chin Lim
@ 2021-07-08 16:32   ` Ley Foon Tan
  2021-07-09  1:10     ` Lim, Elly Siew Chin
  0 siblings, 1 reply; 24+ messages in thread
From: Ley Foon Tan @ 2021-07-08 16:32 UTC (permalink / raw)
  To: Siew Chin Lim
  Cc: ZY - u-boot, Marek Vasut, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan

On Sun, Jun 13, 2021 at 4:49 PM Siew Chin Lim
<elly.siew.chin.lim@intel.com> wrote:
>
> Add device tree for N5X.
>
> Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
> Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
>
> ---
> v3:
> - Update comment for memory example code
> - Move all common dts settings for N5X from
>   socfpga_n5x_socdk.dts to socfpga_n5x-u-boot.dtsi
> - Remove unused parameter "u-boot,boot0"
>
> v2:
> - Remove socfpga_n5x.dtsi
> - Reuse socfpga_agilex.dtsi in socfpga_n5x_socdk.dts and update
>   n5x data accordingly.
> ---
>  arch/arm/dts/Makefile                         |   1 +
>  arch/arm/dts/socfpga_n5x-u-boot.dtsi          | 175 ++++++++++++++++++
>  arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi    |  67 +++++++
>  ...agilex_socdk.dts => socfpga_n5x_socdk.dts} |  25 ++-
>  4 files changed, 262 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm/dts/socfpga_n5x-u-boot.dtsi
>  create mode 100644 arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
>  copy arch/arm/dts/{socfpga_agilex_socdk.dts => socfpga_n5x_socdk.dts} (81%)
>
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index 096068261d..8a513e2a87 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -393,6 +393,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) +=                               \
>         socfpga_cyclone5_socrates.dtb                   \
>         socfpga_cyclone5_sr1500.dtb                     \
>         socfpga_cyclone5_vining_fpga.dtb                \
> +       socfpga_n5x_socdk.dtb                           \
>         socfpga_stratix10_socdk.dtb
>
>  dtb-$(CONFIG_TARGET_DRA7XX_EVM) += dra72-evm.dtb dra7-evm.dtb  \
> diff --git a/arch/arm/dts/socfpga_n5x-u-boot.dtsi b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
> new file mode 100644
> index 0000000000..d144116e71
> --- /dev/null
> +++ b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
> @@ -0,0 +1,175 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * U-Boot additions
> + *
> + * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
> + */
> +
> +#include "socfpga_soc64_fit-u-boot.dtsi"
> +
> +/{
> +       memory {
> +               #address-cells = <2>;
> +               #size-cells = <2>;
> +               u-boot,dm-pre-reloc;
> +       };
> +
> +       soc {
> +               u-boot,dm-pre-reloc;
> +
> +               ccu: cache-controller@f7000000 {
> +                       compatible = "arteris,ncore-ccu";
> +                       reg = <0xf7000000 0x100900>;
> +                       u-boot,dm-pre-reloc;
> +               };
> +       };
> +};
> +
> +&clkmgr {
> +       compatible = "intel,n5x-clkmgr";
> +       u-boot,dm-pre-reloc;
> +};
> +
> +
> +&gmac1 {
> +       altr,sysmgr-syscon = <&sysmgr 0x48 0>;
> +       clocks = <&clkmgr N5X_EMAC1_CLK>;
> +};
> +
> +&gmac2 {
> +       altr,sysmgr-syscon = <&sysmgr 0x4c 0>;
> +       clocks = <&clkmgr N5X_EMAC2_CLK>;
> +};
> +
> +&i2c0 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +       reset-names = "i2c";
> +};
> +
> +&i2c1 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +       reset-names = "i2c";
> +};
> +
> +&i2c2 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +       reset-names = "i2c";
> +};
> +
> +&i2c3 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +       reset-names = "i2c";
> +};
> +
> +&i2c4 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +       reset-names = "i2c";
> +};
> +
> +&memclkmgr {
> +       u-boot,dm-pre-reloc;
> +};
> +
> +
> +&mmc {
> +       clocks = <&clkmgr N5X_L4_MP_CLK>,
> +                <&clkmgr N5X_SDMMC_CLK>;
> +       resets = <&rst SDMMC_RESET>, <&rst SDMMC_OCP_RESET>;
> +};
> +
> +&pdma {
> +       clocks = <&clkmgr N5X_L4_MAIN_CLK>;
> +};
> +
> +&spi0 {
> +       clocks = <&clkmgr N5X_L4_MAIN_CLK>;
> +};
> +
> +&spi1 {
> +       clocks = <&clkmgr N5X_L4_MAIN_CLK>;
> +};
> +
> +&timer0 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +};
> +
> +&timer1 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +};
> +
> +&timer2 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +};
> +
> +&timer3 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +};
> +
> +&porta {
> +       bank-name = "porta";
> +};
> +
> +&portb {
> +       bank-name = "portb";
> +};
> +
> +&qspi {
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&rst {
> +       compatible = "altr,rst-mgr";
> +       altr,modrst-offset = <0x20>;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&sdr {
> +       compatible = "intel,sdr-ctl-n5x";
> +       resets = <&rst DDRSCH_RESET>;
> +       clocks = <&memclkmgr>;
> +       clock-names = "mem_clk";
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&sysmgr {
> +       compatible = "altr,sys-mgr", "syscon";
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&uart0 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&uart1 {
> +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> +};
> +
> +&usb0 {
> +       clocks = <&clkmgr N5X_USB_CLK>;
> +       disable-over-current;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&usb1 {
> +       clocks = <&clkmgr N5X_USB_CLK>;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&watchdog0 {
> +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&watchdog1 {
> +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
> +};
> +
> +&watchdog2 {
> +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
> +};
> +
> +&watchdog3 {
> +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
> +};
> +
> diff --git a/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
> new file mode 100644
> index 0000000000..612d394019
> --- /dev/null
> +++ b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
> @@ -0,0 +1,67 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * U-Boot additions
> + *
> + * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
> + */
> +
> +#include "socfpga_n5x-u-boot.dtsi"
> +
> +/{
> +       aliases {
> +               spi0 = &qspi;
> +               i2c0 = &i2c1;
> +       };
> +
> +       memory {
> +               /*
> +                * Memory type: DDR4 (interleaving mode)
> +                * 16GB
> +                *     <0 0x00000000 0 0x80000000>,
> +                *     <4 0x80000000 3 0x80000000>;
> +                *
> +                * 8GB
> +                *     <0 0x00000000 0 0x80000000>,
> +                *     <2 0x80000000 1 0x80000000>;
> +                *
> +                * 4GB
> +                *     <0 0x00000000 0 0x80000000>,
> +                *     <1 0x80000000 0 0x80000000>;
> +                *
> +                * Memory type: LPDDR4 (non-interleaving mode)
> +                * Total memory size 3GB, usable = 2.5GB, 0.5GB trade off for secure
> +                * region.
> +                */
> +               reg = <0 0x00000000 0 0x60000000>,
> +                         <0x10 0x00100000 0 0x40000000>;
> +       };
> +};
> +
> +&flash0 {
> +       compatible = "jedec,spi-nor";
> +       spi-tx-bus-width = <4>;
> +       spi-rx-bus-width = <4>;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&i2c1 {
> +       status = "okay";
> +};
> +
> +&nand {
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&mmc {
> +       drvsel = <3>;
> +       smplsel = <0>;
> +       u-boot,dm-pre-reloc;
> +};
> +
> +&qspi {
> +       status = "okay";
> +};
> +
> +&watchdog0 {
> +       u-boot,dm-pre-reloc;
> +};
> diff --git a/arch/arm/dts/socfpga_agilex_socdk.dts b/arch/arm/dts/socfpga_n5x_socdk.dts
> similarity index 81%
> copy from arch/arm/dts/socfpga_agilex_socdk.dts
> copy to arch/arm/dts/socfpga_n5x_socdk.dts
> index bcdeecc0e0..4cb71b5de3 100644
> --- a/arch/arm/dts/socfpga_agilex_socdk.dts
> +++ b/arch/arm/dts/socfpga_n5x_socdk.dts
> @@ -1,11 +1,12 @@
>  // SPDX-License-Identifier:     GPL-2.0
>  /*
> - * Copyright (C) 2019, Intel Corporation
> + * Copyright (C) 2020-2021, Intel Corporation
>   */
>  #include "socfpga_agilex.dtsi"
> +#include <dt-bindings/clock/n5x-clock.h>
>
>  / {
> -       model = "SoCFPGA Agilex SoCDK";
> +       model = "eASIC N5X SoCDK";
>
>         aliases {
>                 serial0 = &uart0;
> @@ -47,6 +48,18 @@
>                         osc1 {
>                                 clock-frequency = <25000000>;
>                         };
> +
> +                       dram_eosc_clk: dram-eosc-clk {
> +                               #clock-cells = <0>;
> +                               compatible = "fixed-clock";
> +                       };
> +               };
> +
> +               memclkmgr: mem-clock-controller@f8040000 {
> +                       compatible = "intel,n5x-mem-clkmgr";
> +                       reg = <0xf8040000 0x1000>;
> +                       #clock-cells = <0>;
> +                       clocks = <&dram_eosc_clk>, <&f2s_free_clk>;
>                 };
>         };
>  };
> @@ -59,8 +72,8 @@
>         status = "okay";
>         phy-mode = "rgmii";
>         phy-handle = <&phy0>;
> -
>         max-frame-size = <9000>;
> +       clocks = <&clkmgr N5X_EMAC0_CLK>;
>
>         mdio0 {
>                 #address-cells = <1>;
> @@ -98,14 +111,14 @@
>
>  &usb0 {
>         status = "okay";
> -       disable-over-current;
>  };
>
> -&watchdog0 {
> +&usb1 {
>         status = "okay";
>  };
>
>  &qspi {
> +       status = "okay";
>         flash0: flash@0 {
>                 #address-cells = <1>;
>                 #size-cells = <1>;
> @@ -116,7 +129,7 @@
>                 m25p,fast-read;
>                 cdns,page-size = <256>;
>                 cdns,block-size = <16>;
> -               cdns,read-delay = <1>;
> +               cdns,read-delay = <3>;
>                 cdns,tshsl-ns = <50>;
>                 cdns,tsd2d-ns = <50>;
>                 cdns,tchsh-ns = <4>;
> --
> 2.19.0
>

socfpga_n5x_socdk.dts is not imported from
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts?
Reuse socfpga_n5x_socdk.dts from Linux and add U-boot specifc dts to
u-boot.dtsi.

Regards
Ley Foon

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

* Re: [v3 12/17] ddr: altera: Add SDRAM driver for Intel N5X device
  2021-06-13  8:48 ` [v3 12/17] ddr: altera: Add SDRAM driver for Intel N5X device Siew Chin Lim
@ 2021-07-08 17:06   ` Ley Foon Tan
  0 siblings, 0 replies; 24+ messages in thread
From: Ley Foon Tan @ 2021-07-08 17:06 UTC (permalink / raw)
  To: Siew Chin Lim
  Cc: ZY - u-boot, Marek Vasut, Simon Goldschmidt, Tien Fong Chee,
	Dalon Westergreen, Simon Glass, Yau Wai Gan

On Sun, Jun 13, 2021 at 4:49 PM Siew Chin Lim
<elly.siew.chin.lim@intel.com> wrote:
>
> From: Tien Fong Chee <tien.fong.chee@intel.com>
>
> The DDR subsystem in Diamond Mesa is consisted of controller, PHY,
> memory reset manager and memory clock manager.
>
> Configuration settings of controller, PHY and  memory reset manager
> is come from DDR handoff data in bitstream, which contain the register
> base addresses and user settings from tool.
>
> Configuration settings of memory clock manager is come from the HPS
> handoff data in bitstream, however the register base address is defined
> in device tree.
>
> The calibration is fully done in HPS, which requires IMEM and DMEM
> binaries loading to PHY SRAM for running this calibration, both
> IMEM and DMEM binaries are also part of bitstream, this bitstream
> would be loaded to OCRAM by SDM, and configured by DDR driver.
>
> Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
> Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
>
> ---
> v3:
> - Sorting header
> - Used prefix OPM_xxx
> - Simplify the code with do...while loop.
> - Created common function for processing handoff
> - Adding function of calibration data feedback to LPDDR4 controllers
>
> v2:
> - Move is_ddr_init_skipped and its helper functions to DDR driver and
>   converted function to positive checking
> - Using GENMASK() macro
> - Fixed typo
> - Return status of subfunction
> - Changed dm to n5x
> ---
>  arch/arm/mach-socfpga/include/mach/firewall.h |    6 +
>  .../include/mach/system_manager_soc64.h       |   10 +-
>  drivers/ddr/altera/Makefile                   |    3 +-
>  drivers/ddr/altera/sdram_n5x.c                | 2298 +++++++++++++++++
>  drivers/ddr/altera/sdram_soc64.c              |   70 +
>  drivers/ddr/altera/sdram_soc64.h              |    1 +
>  6 files changed, 2386 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/ddr/altera/sdram_n5x.c
>

Reviewed-by: Ley Foon Tan <lftan.linux@gmail.com>

Regards
Ley Foon

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

* RE: [v3 15/17] arm: dts: Add base dtsi and devkit dts for Intel N5X device
  2021-07-08 16:32   ` Ley Foon Tan
@ 2021-07-09  1:10     ` Lim, Elly Siew Chin
  0 siblings, 0 replies; 24+ messages in thread
From: Lim, Elly Siew Chin @ 2021-07-09  1:10 UTC (permalink / raw)
  To: Ley Foon Tan
  Cc: ZY - u-boot, Marek Vasut, Simon Goldschmidt, Chee, Tien Fong,
	Westergreen, Dalon, Simon Glass, Gan, Yau Wai



> -----Original Message-----
> From: Ley Foon Tan <lftan.linux@gmail.com>
> Sent: Friday, July 9, 2021 12:33 AM
> To: Lim, Elly Siew Chin <elly.siew.chin.lim@intel.com>
> Cc: ZY - u-boot <u-boot@lists.denx.de>; Marek Vasut <marex@denx.de>;
> Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>; Chee, Tien Fong
> <tien.fong.chee@intel.com>; Westergreen, Dalon
> <dalon.westergreen@intel.com>; Simon Glass <sjg@chromium.org>; Gan,
> Yau Wai <yau.wai.gan@intel.com>
> Subject: Re: [v3 15/17] arm: dts: Add base dtsi and devkit dts for Intel N5X
> device
> 
> On Sun, Jun 13, 2021 at 4:49 PM Siew Chin Lim <elly.siew.chin.lim@intel.com>
> wrote:
> >
> > Add device tree for N5X.
> >
> > Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
> > Signed-off-by: Tien Fong Chee <tien.fong.chee@intel.com>
> >
> > ---
> > v3:
> > - Update comment for memory example code
> > - Move all common dts settings for N5X from
> >   socfpga_n5x_socdk.dts to socfpga_n5x-u-boot.dtsi
> > - Remove unused parameter "u-boot,boot0"
> >
> > v2:
> > - Remove socfpga_n5x.dtsi
> > - Reuse socfpga_agilex.dtsi in socfpga_n5x_socdk.dts and update
> >   n5x data accordingly.
> > ---
> >  arch/arm/dts/Makefile                         |   1 +
> >  arch/arm/dts/socfpga_n5x-u-boot.dtsi          | 175 ++++++++++++++++++
> >  arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi    |  67 +++++++
> >  ...agilex_socdk.dts => socfpga_n5x_socdk.dts} |  25 ++-
> >  4 files changed, 262 insertions(+), 6 deletions(-)  create mode
> > 100644 arch/arm/dts/socfpga_n5x-u-boot.dtsi
> >  create mode 100644 arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
> >  copy arch/arm/dts/{socfpga_agilex_socdk.dts => socfpga_n5x_socdk.dts}
> > (81%)
> >
> > diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index
> > 096068261d..8a513e2a87 100644
> > --- a/arch/arm/dts/Makefile
> > +++ b/arch/arm/dts/Makefile
> > @@ -393,6 +393,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) +=
> \
> >         socfpga_cyclone5_socrates.dtb                   \
> >         socfpga_cyclone5_sr1500.dtb                     \
> >         socfpga_cyclone5_vining_fpga.dtb                \
> > +       socfpga_n5x_socdk.dtb                           \
> >         socfpga_stratix10_socdk.dtb
> >
> >  dtb-$(CONFIG_TARGET_DRA7XX_EVM) += dra72-evm.dtb dra7-evm.dtb  \
> diff
> > --git a/arch/arm/dts/socfpga_n5x-u-boot.dtsi
> > b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
> > new file mode 100644
> > index 0000000000..d144116e71
> > --- /dev/null
> > +++ b/arch/arm/dts/socfpga_n5x-u-boot.dtsi
> > @@ -0,0 +1,175 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * U-Boot additions
> > + *
> > + * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>  */
> > +
> > +#include "socfpga_soc64_fit-u-boot.dtsi"
> > +
> > +/{
> > +       memory {
> > +               #address-cells = <2>;
> > +               #size-cells = <2>;
> > +               u-boot,dm-pre-reloc;
> > +       };
> > +
> > +       soc {
> > +               u-boot,dm-pre-reloc;
> > +
> > +               ccu: cache-controller@f7000000 {
> > +                       compatible = "arteris,ncore-ccu";
> > +                       reg = <0xf7000000 0x100900>;
> > +                       u-boot,dm-pre-reloc;
> > +               };
> > +       };
> > +};
> > +
> > +&clkmgr {
> > +       compatible = "intel,n5x-clkmgr";
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +
> > +&gmac1 {
> > +       altr,sysmgr-syscon = <&sysmgr 0x48 0>;
> > +       clocks = <&clkmgr N5X_EMAC1_CLK>; };
> > +
> > +&gmac2 {
> > +       altr,sysmgr-syscon = <&sysmgr 0x4c 0>;
> > +       clocks = <&clkmgr N5X_EMAC2_CLK>; };
> > +
> > +&i2c0 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> > +       reset-names = "i2c";
> > +};
> > +
> > +&i2c1 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> > +       reset-names = "i2c";
> > +};
> > +
> > +&i2c2 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> > +       reset-names = "i2c";
> > +};
> > +
> > +&i2c3 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> > +       reset-names = "i2c";
> > +};
> > +
> > +&i2c4 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> > +       reset-names = "i2c";
> > +};
> > +
> > +&memclkmgr {
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +
> > +&mmc {
> > +       clocks = <&clkmgr N5X_L4_MP_CLK>,
> > +                <&clkmgr N5X_SDMMC_CLK>;
> > +       resets = <&rst SDMMC_RESET>, <&rst SDMMC_OCP_RESET>; };
> > +
> > +&pdma {
> > +       clocks = <&clkmgr N5X_L4_MAIN_CLK>; };
> > +
> > +&spi0 {
> > +       clocks = <&clkmgr N5X_L4_MAIN_CLK>; };
> > +
> > +&spi1 {
> > +       clocks = <&clkmgr N5X_L4_MAIN_CLK>; };
> > +
> > +&timer0 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>; };
> > +
> > +&timer1 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>; };
> > +
> > +&timer2 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>; };
> > +
> > +&timer3 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>; };
> > +
> > +&porta {
> > +       bank-name = "porta";
> > +};
> > +
> > +&portb {
> > +       bank-name = "portb";
> > +};
> > +
> > +&qspi {
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&rst {
> > +       compatible = "altr,rst-mgr";
> > +       altr,modrst-offset = <0x20>;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&sdr {
> > +       compatible = "intel,sdr-ctl-n5x";
> > +       resets = <&rst DDRSCH_RESET>;
> > +       clocks = <&memclkmgr>;
> > +       clock-names = "mem_clk";
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&sysmgr {
> > +       compatible = "altr,sys-mgr", "syscon";
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&uart0 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&uart1 {
> > +       clocks = <&clkmgr N5X_L4_SP_CLK>; };
> > +
> > +&usb0 {
> > +       clocks = <&clkmgr N5X_USB_CLK>;
> > +       disable-over-current;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&usb1 {
> > +       clocks = <&clkmgr N5X_USB_CLK>;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&watchdog0 {
> > +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&watchdog1 {
> > +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>; };
> > +
> > +&watchdog2 {
> > +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>; };
> > +
> > +&watchdog3 {
> > +       clocks = <&clkmgr N5X_L4_SYS_FREE_CLK>; };
> > +
> > diff --git a/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
> > b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
> > new file mode 100644
> > index 0000000000..612d394019
> > --- /dev/null
> > +++ b/arch/arm/dts/socfpga_n5x_socdk-u-boot.dtsi
> > @@ -0,0 +1,67 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * U-Boot additions
> > + *
> > + * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>  */
> > +
> > +#include "socfpga_n5x-u-boot.dtsi"
> > +
> > +/{
> > +       aliases {
> > +               spi0 = &qspi;
> > +               i2c0 = &i2c1;
> > +       };
> > +
> > +       memory {
> > +               /*
> > +                * Memory type: DDR4 (interleaving mode)
> > +                * 16GB
> > +                *     <0 0x00000000 0 0x80000000>,
> > +                *     <4 0x80000000 3 0x80000000>;
> > +                *
> > +                * 8GB
> > +                *     <0 0x00000000 0 0x80000000>,
> > +                *     <2 0x80000000 1 0x80000000>;
> > +                *
> > +                * 4GB
> > +                *     <0 0x00000000 0 0x80000000>,
> > +                *     <1 0x80000000 0 0x80000000>;
> > +                *
> > +                * Memory type: LPDDR4 (non-interleaving mode)
> > +                * Total memory size 3GB, usable = 2.5GB, 0.5GB trade off for
> secure
> > +                * region.
> > +                */
> > +               reg = <0 0x00000000 0 0x60000000>,
> > +                         <0x10 0x00100000 0 0x40000000>;
> > +       };
> > +};
> > +
> > +&flash0 {
> > +       compatible = "jedec,spi-nor";
> > +       spi-tx-bus-width = <4>;
> > +       spi-rx-bus-width = <4>;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&i2c1 {
> > +       status = "okay";
> > +};
> > +
> > +&nand {
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&mmc {
> > +       drvsel = <3>;
> > +       smplsel = <0>;
> > +       u-boot,dm-pre-reloc;
> > +};
> > +
> > +&qspi {
> > +       status = "okay";
> > +};
> > +
> > +&watchdog0 {
> > +       u-boot,dm-pre-reloc;
> > +};
> > diff --git a/arch/arm/dts/socfpga_agilex_socdk.dts
> > b/arch/arm/dts/socfpga_n5x_socdk.dts
> > similarity index 81%
> > copy from arch/arm/dts/socfpga_agilex_socdk.dts
> > copy to arch/arm/dts/socfpga_n5x_socdk.dts
> > index bcdeecc0e0..4cb71b5de3 100644
> > --- a/arch/arm/dts/socfpga_agilex_socdk.dts
> > +++ b/arch/arm/dts/socfpga_n5x_socdk.dts
> > @@ -1,11 +1,12 @@
> >  // SPDX-License-Identifier:     GPL-2.0
> >  /*
> > - * Copyright (C) 2019, Intel Corporation
> > + * Copyright (C) 2020-2021, Intel Corporation
> >   */
> >  #include "socfpga_agilex.dtsi"
> > +#include <dt-bindings/clock/n5x-clock.h>
> >
> >  / {
> > -       model = "SoCFPGA Agilex SoCDK";
> > +       model = "eASIC N5X SoCDK";
> >
> >         aliases {
> >                 serial0 = &uart0;
> > @@ -47,6 +48,18 @@
> >                         osc1 {
> >                                 clock-frequency = <25000000>;
> >                         };
> > +
> > +                       dram_eosc_clk: dram-eosc-clk {
> > +                               #clock-cells = <0>;
> > +                               compatible = "fixed-clock";
> > +                       };
> > +               };
> > +
> > +               memclkmgr: mem-clock-controller@f8040000 {
> > +                       compatible = "intel,n5x-mem-clkmgr";
> > +                       reg = <0xf8040000 0x1000>;
> > +                       #clock-cells = <0>;
> > +                       clocks = <&dram_eosc_clk>, <&f2s_free_clk>;
> >                 };
> >         };
> >  };
> > @@ -59,8 +72,8 @@
> >         status = "okay";
> >         phy-mode = "rgmii";
> >         phy-handle = <&phy0>;
> > -
> >         max-frame-size = <9000>;
> > +       clocks = <&clkmgr N5X_EMAC0_CLK>;
> >
> >         mdio0 {
> >                 #address-cells = <1>;
> > @@ -98,14 +111,14 @@
> >
> >  &usb0 {
> >         status = "okay";
> > -       disable-over-current;
> >  };
> >
> > -&watchdog0 {
> > +&usb1 {
> >         status = "okay";
> >  };
> >
> >  &qspi {
> > +       status = "okay";
> >         flash0: flash@0 {
> >                 #address-cells = <1>;
> >                 #size-cells = <1>;
> > @@ -116,7 +129,7 @@
> >                 m25p,fast-read;
> >                 cdns,page-size = <256>;
> >                 cdns,block-size = <16>;
> > -               cdns,read-delay = <1>;
> > +               cdns,read-delay = <3>;
> >                 cdns,tshsl-ns = <50>;
> >                 cdns,tsd2d-ns = <50>;
> >                 cdns,tchsh-ns = <4>;
> > --
> > 2.19.0
> >
> 
> socfpga_n5x_socdk.dts is not imported from
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/
> arm64/boot/dts/intel/socfpga_n5x_socdk.dts?
> Reuse socfpga_n5x_socdk.dts from Linux and add U-boot specifc dts to u-
> boot.dtsi.
> 
> Regards
> Ley Foon

Noted.

Thanks,
Siew Chin

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

end of thread, other threads:[~2021-07-09  1:10 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-13  8:48 [v3 00/17] Add Intel N5X SoC support Siew Chin Lim
2021-06-13  8:48 ` [v3 01/17] arm: socfpga: Move linux_qspi_enable from bootcommand to board_prep_linux function Siew Chin Lim
2021-06-13  8:48 ` [v3 02/17] arm: socfpga: Changed base_addr_s10.h to base_addr_soc64.h Siew Chin Lim
2021-06-13  8:48 ` [v3 03/17] arm: socfpga: Add base address for Intel N5X device Siew Chin Lim
2021-06-13  8:48 ` [v3 04/17] arm: socfpga: Add handoff data support " Siew Chin Lim
2021-07-08 16:15   ` Ley Foon Tan
2021-06-13  8:48 ` [v3 05/17] drivers: clk: Add clock driver " Siew Chin Lim
2021-07-08 16:17   ` Ley Foon Tan
2021-06-13  8:48 ` [v3 06/17] arm: socfpga: Get clock manager base address " Siew Chin Lim
2021-06-13  8:48 ` [v3 07/17] drivers: clk: Add memory clock driver " Siew Chin Lim
2021-07-08 16:19   ` Ley Foon Tan
2021-06-13  8:48 ` [v3 08/17] arm: socfpga: Move cm_get_mpu_clk_hz function declaration to clock_manager.h Siew Chin Lim
2021-06-13  8:48 ` [v3 09/17] arm: socfpga: Add clock manager for Intel N5X device Siew Chin Lim
2021-06-13  8:48 ` [v3 10/17] arm: socfpga: Changed misc_s10.c to misc_soc64.c Siew Chin Lim
2021-06-13  8:48 ` [v3 11/17] ddr: socfpga: Enable memory test on memory size less than 1GB Siew Chin Lim
2021-06-13  8:48 ` [v3 12/17] ddr: altera: Add SDRAM driver for Intel N5X device Siew Chin Lim
2021-07-08 17:06   ` Ley Foon Tan
2021-06-13  8:48 ` [v3 13/17] arm: socfpga: Add SPL " Siew Chin Lim
2021-06-13  8:48 ` [v3 14/17] board: intel: Add socdk board support " Siew Chin Lim
2021-06-13  8:48 ` [v3 15/17] arm: dts: Add base dtsi and devkit dts " Siew Chin Lim
2021-07-08 16:32   ` Ley Foon Tan
2021-07-09  1:10     ` Lim, Elly Siew Chin
2021-06-13  8:48 ` [v3 16/17] include: configs: Add Intel N5X device CONFIGs Siew Chin Lim
2021-06-13  8:48 ` [v3 17/17] arm: socfpga: Enable Intel N5X device build Siew Chin Lim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).