new file mode 100644
@@ -0,0 +1,219 @@
+From 5d13f425bd0dea29912bf253a7be83a7cdca591d Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Nov 2021 14:00:07 +0200
+Subject: [PATCH] plat/nxp: lx2160a auto boot
+
+This patch adds support to patch RCW that already has SD/eMMC/SPI boot
+support embedded with conditional load and jump.
+The idea is to look for SD/eMMC/SPI boot, and modify src/dst/size
+address with the correct values; rather than adding blockread at the end
+of RCW code.
+
+With this patch images are unified and can be used to boot from SD /
+eMMC and SPI.
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ .../plat_make_helper/plat_common_def.mk | 5 ++
+ plat/nxp/soc-lx2160a/lx2160ardb/platform.mk | 3 +-
+ plat/nxp/soc-lx2160a/soc.mk | 5 ++
+ tools/nxp/create_pbl/create_pbl.c | 74 ++++++++++++++++---
+ 4 files changed, 76 insertions(+), 11 deletions(-)
+
+diff --git a/plat/nxp/common/plat_make_helper/plat_common_def.mk b/plat/nxp/common/plat_make_helper/plat_common_def.mk
+index 86dacf83d..a1038a073 100644
+--- a/plat/nxp/common/plat_make_helper/plat_common_def.mk
++++ b/plat/nxp/common/plat_make_helper/plat_common_def.mk
+@@ -91,6 +91,11 @@ define add_boot_mode_define
+ else ifeq ($(1),flexspi_nor)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2))
+ $$(eval $$(call add_define,FLEXSPI_NOR_BOOT))
++ else ifeq ($(1),auto)
++ $$(eval $$(call SET_FLAG,SD_MMC_NEEDED,BL2))
++ $$(eval $$(call add_define,EMMC_BOOT))
++ $$(eval $$(call SET_FLAG,XSPI_NEEDED,BL2))
++ $$(eval $$(call add_define,FLEXSPI_NOR_BOOT))
+ else
+ $$(error $(PLAT) Cannot Support Boot Mode: $(BOOT_MODE))
+ endif
+diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk b/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk
+index ffb5fadee..09c552c72 100644
+--- a/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk
++++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk
+@@ -42,7 +42,8 @@ BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+
+ SUPPORTED_BOOT_MODE := flexspi_nor \
+ sd \
+- emmc
++ emmc \
++ auto
+
+ # Adding platform board build info
+ include plat/nxp/common/plat_make_helper/plat_common_def.mk
+diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
+index 239442c20..a72b4113d 100644
+--- a/plat/nxp/soc-lx2160a/soc.mk
++++ b/plat/nxp/soc-lx2160a/soc.mk
+@@ -82,6 +82,11 @@ else
+ ifeq (${BOOT_MODE}, emmc)
+ $(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2))
+ $(eval $(call add_define,EMMC_BOOT))
++else ifeq (${BOOT_MODE}, auto)
++$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2))
++$(eval $(call add_define,EMMC_BOOT))
++$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2))
++$(eval $(call add_define,FLEXSPI_NOR_BOOT))
+ else
+ $(error Un-supported Boot Mode = ${BOOT_MODE})
+ endif
+diff --git a/tools/nxp/create_pbl/create_pbl.c b/tools/nxp/create_pbl/create_pbl.c
+index 792747f0e..35cd39b61 100644
+--- a/tools/nxp/create_pbl/create_pbl.c
++++ b/tools/nxp/create_pbl/create_pbl.c
+@@ -66,6 +66,7 @@ typedef enum {
+ FLXSPI_NOR_BOOT,
+ FLXSPI_NAND_BOOT,
+ FLXSPI_NAND4K_BOOT,
++ AUTO_BOOT,
+ MAX_BOOT /* must be last item in list */
+ } boot_src_t;
+
+@@ -140,6 +141,7 @@ char *boot_src_string[] = {
+ "FLXSPI_NOR_BOOT",
+ "FLXSPI_NAND_BOOT",
+ "FLXSPI_NAND4K_BOOT",
++ "AUTO_BOOT",
+ };
+
+ enum stop_command {
+@@ -193,7 +195,7 @@ struct pbl_image {
+ #define SOC_LS2088 2088
+ #define SOC_LX2160 2160
+
+-static uint32_t pbl_size;
++static uint32_t pbl_size = 0;
+ bool sb_flag;
+
+ /***************************************************************************
+@@ -703,6 +705,8 @@ int main(int argc, char **argv)
+ int ret = FAILURE;
+ bool bootptr_flag = false;
+ enum stop_command flag_stop_cmd = CRC_STOP_COMMAND;
++ int skip = 0;
++ uint32_t saved_src;
+
+ /* Initializing the global structure to zero. */
+ memset(&pblimg, 0x0, sizeof(struct pbl_image));
+@@ -802,6 +806,8 @@ int main(int argc, char **argv)
+ pblimg.boot_src = FLXSPI_NAND_BOOT;
+ } else if (strcmp(optarg, "flexspi_nand2k") == 0) {
+ pblimg.boot_src = FLXSPI_NAND4K_BOOT;
++ } else if (strcmp(optarg, "auto") == 0) {
++ pblimg.boot_src = AUTO_BOOT;
+ } else {
+ printf("CMD Error: Invalid boot source.\n");
+ goto exit_main;
+@@ -909,13 +915,14 @@ int main(int argc, char **argv)
+ printf("%s: Error reading PBI Cmd.\n", __func__);
+ goto exit_main;
+ }
++ saved_src = pblimg.src_addr;
+ while (word != 0x808f0000 && word != 0x80ff0000) {
+ pbl_size++;
+ /* 11th words in RCW has PBL length. Update it
+ * with new length. 2 comamnds get added
+ * Block copy + CCSR Write/CSF header write
+ */
+- if (pbl_size == 11) {
++ if ((pbl_size == 11) && (pblimg.boot_src != AUTO_BOOT)) {
+ word_1 = (word & PBI_LEN_MASK)
+ + (PBI_LEN_ADD << 20);
+ word = word & ~PBI_LEN_MASK;
+@@ -933,8 +940,50 @@ int main(int argc, char **argv)
+ goto exit_main;
+ }
+ }
+- if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK,
+- fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
++ if (pblimg.boot_src == AUTO_BOOT) {
++ if (word == 0x80000008) {
++ printf ("Found SD boot at %d\n",pbl_size);
++ pblimg.boot_src = SD_BOOT;
++ add_blk_cpy_cmd(fp_rcw_pbi_op, args);
++ skip = 4; // skip original blockcopy
++ pblimg.boot_src = AUTO_BOOT;
++ pblimg.src_addr = saved_src;
++ if (bootptr_flag == true) {
++ add_boot_ptr_cmd(fp_rcw_pbi_op);
++ skip += 2; // skip original bootlocptr write (low byte only)
++ printf("added bootptr\n");
++ }
++ }
++ if (word == 0x80000009) {
++ printf ("Found eMMC boot at %d\n",pbl_size);
++ pblimg.boot_src = EMMC_BOOT;
++ add_blk_cpy_cmd(fp_rcw_pbi_op, args);
++ skip = 4; // skip original blockcopy
++ pblimg.boot_src = AUTO_BOOT;
++ pblimg.src_addr = saved_src;
++ if (bootptr_flag == true) {
++ add_boot_ptr_cmd(fp_rcw_pbi_op);
++ skip += 2; // skip original bootlocptr write (low byte only)
++ printf("added bootptr\n");
++ }
++ }
++ if (word == 0x8000000f) {
++ printf ("Found SPI boot at %d\n",pbl_size);
++ pblimg.boot_src = FLXSPI_NOR_BOOT;
++ add_blk_cpy_cmd(fp_rcw_pbi_op, args);
++ skip = 4; // skip original blockcopy
++ pblimg.boot_src = AUTO_BOOT;
++ pblimg.src_addr = saved_src;
++ if (bootptr_flag == true) {
++ add_boot_ptr_cmd(fp_rcw_pbi_op);
++ skip += 2; // skip original bootlocptr write (low byte only)
++ printf("added bootptr\n");
++ }
++ }
++ }
++ if (!skip &&
++ (fwrite(&word, sizeof(word), NUM_MEM_BLOCK,
++ fp_rcw_pbi_op) != NUM_MEM_BLOCK)) {
+ printf("%s: [CH3] Error in Writing PBI Words\n",
+ __func__);
+ goto exit_main;
+@@ -951,8 +1000,11 @@ int main(int argc, char **argv)
+ } else if (word == STOP_CMD_ARM_CH3) {
+ flag_stop_cmd = STOP_COMMAND;
+ }
++
++ if (skip)
++ skip--;
+ }
+- if (bootptr_flag == true) {
++ if ((pblimg.boot_src != AUTO_BOOT) && (bootptr_flag == true)) {
+ /* Add command to set boot_loc ptr */
+ ret = add_boot_ptr_cmd(fp_rcw_pbi_op);
+ if (ret != SUCCESS) {
+@@ -963,11 +1015,13 @@ int main(int argc, char **argv)
+ }
+
+ /* Write acs write commands to output file */
+- ret = add_blk_cpy_cmd(fp_rcw_pbi_op, args);
+- if (ret != SUCCESS) {
+- printf("%s: Function add_blk_cpy_cmd return failure.\n",
+- __func__);
+- goto exit_main;
++ if (pblimg.boot_src != AUTO_BOOT) {
++ ret = add_blk_cpy_cmd(fp_rcw_pbi_op, args);
++ if (ret != SUCCESS) {
++ printf("%s: Function add_blk_cpy_cmd return failure.\n",
++ __func__);
++ goto exit_main;
++ }
+ }
+
+ /* Add stop command after adding pbi commands */
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,85 @@
+From f750b41bf323d04791b4b25962f693c1fb43bade Mon Sep 17 00:00:00 2001
+From: Jon Nettleton <jon@solid-run.com>
+Date: Tue, 8 Oct 2024 04:56:45 +0200
+Subject: [PATCH] dcfg: Take into account MEM_PLL_CFG_SHIFT for ddr frequency
+
+The base ddr clock frequency is 1/4 the speed of the final
+ddr clock frequency. By default the RCW config is setting
+the CFG_SHIFT to be a 1/4 divider of the memory speed,
+i.e. 3200 / 4 (800MHz). The parent DDRCLK is 100MHz so PLL_RAT
+needs to be rounded to 100MHz. However using a divider of / 3 for
+a lower speed always us to match industry standard ddr4 speeds
+2666 and 2933 (2000 / 3 * 4 = 2666.67)
+
+This patch takes into account the PLL_CFG_SHIFT divider so these
+speeds can be configured in the RCW and then updates the helper
+function that reports ddr_clk_freq to properly multiply the
+clock fed into the DDRC * 4 to properly reflect the actual MTs
+that the memory is being configured for.
+
+Signed-off-by: Jon Nettleton <jon@solid-run.com>
+---
+ drivers/nxp/dcfg/dcfg.c | 6 ++++++
+ drivers/nxp/ddr/nxp-ddr/utility.c | 6 +++---
+ include/drivers/nxp/dcfg/dcfg_lsch3.h | 4 ++++
+ 3 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nxp/dcfg/dcfg.c b/drivers/nxp/dcfg/dcfg.c
+index e5c4db437..4a5820a64 100644
+--- a/drivers/nxp/dcfg/dcfg.c
++++ b/drivers/nxp/dcfg/dcfg.c
+@@ -104,9 +104,15 @@ int get_clocks(struct sysinfo *sys)
+ sys->freq_ddr_pll0 *= (gur_in32(rcwsr0) >>
+ RCWSR0_MEM_PLL_RAT_SHIFT) &
+ RCWSR0_MEM_PLL_RAT_MASK;
++ sys->freq_ddr_pll0 /= ((gur_in32(rcwsr0) >>
++ RCWSR0_MEM_PLL_CFG_SHIFT) &
++ RCWSR0_MEM_PLL_CFG_MASK) + 1;
+ sys->freq_ddr_pll1 *= (gur_in32(rcwsr0) >>
+ RCWSR0_MEM2_PLL_RAT_SHIFT) &
+ RCWSR0_MEM2_PLL_RAT_MASK;
++ sys->freq_ddr_pll1 /= ((gur_in32(rcwsr0) >>
++ RCWSR0_MEM2_PLL_CFG_SHIFT) &
++ RCWSR0_MEM2_PLL_CFG_MASK) + 1;
+ if (sys->freq_platform == 0) {
+ return 1;
+ } else {
+diff --git a/drivers/nxp/ddr/nxp-ddr/utility.c b/drivers/nxp/ddr/nxp-ddr/utility.c
+index b6dffc872..3920b4488 100644
+--- a/drivers/nxp/ddr/nxp-ddr/utility.c
++++ b/drivers/nxp/ddr/nxp-ddr/utility.c
+@@ -47,11 +47,11 @@ unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num)
+
+ switch (ctrl_num) {
+ case 0:
+- return sys->freq_ddr_pll0;
++ return sys->freq_ddr_pll0 * 4;
+ case 1:
+- return sys->freq_ddr_pll0;
++ return sys->freq_ddr_pll0 * 4;
+ case 2:
+- return sys->freq_ddr_pll1;
++ return sys->freq_ddr_pll1 * 4;
+ }
+
+ return 0;
+diff --git a/include/drivers/nxp/dcfg/dcfg_lsch3.h b/include/drivers/nxp/dcfg/dcfg_lsch3.h
+index cde86fe19..f9409d1a7 100644
+--- a/include/drivers/nxp/dcfg/dcfg_lsch3.h
++++ b/include/drivers/nxp/dcfg/dcfg_lsch3.h
+@@ -53,8 +53,12 @@
+ #define RCWSR0_OFFSET 0x100
+ #define RCWSR0_SYS_PLL_RAT_SHIFT 2
+ #define RCWSR0_SYS_PLL_RAT_MASK 0x1f
++#define RCWSR0_MEM_PLL_CFG_SHIFT 8
++#define RCWSR0_MEM_PLL_CFG_MASK 0x3
+ #define RCWSR0_MEM_PLL_RAT_SHIFT 10
+ #define RCWSR0_MEM_PLL_RAT_MASK 0x3f
++#define RCWSR0_MEM2_PLL_CFG_SHIFT 16
++#define RCWSR0_MEM2_PLL_CFG_MASK 0x3
+ #define RCWSR0_MEM2_PLL_RAT_SHIFT 18
+ #define RCWSR0_MEM2_PLL_RAT_MASK 0x3f
+
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,29 @@
+From 72557b712198e3292776fbe8697322c68583acf4 Mon Sep 17 00:00:00 2001
+From: Rabeeh Khoury <rabeeh@solid-run.com>
+Date: Sun, 28 Nov 2021 13:33:10 +0200
+Subject: [PATCH] lx2160acex7: assert SUS_S5# GPIO to poweroff the COM
+
+Signed-off-by: Rabeeh Khoury <rabeeh@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/aarch64/lx2160a.S | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+index cc679f2ba..01b3c7ecd 100644
+--- a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
++++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+@@ -563,6 +563,11 @@ endfunc _soc_sys_reset
+ */
+ func _soc_sys_off
+
++ /* assert GPIO3[7] (IRQ07 - CEX-7 SUS_S5) */
++ mov x3, #NXP_GPIO3_ADDR
++ mov w1, #0x01000000
++ str w1, [x3]
++
+ /* disable sec, QBman, spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,29 @@
+From 6bc7cf0b6de6427b230d47ae7ee273175ffe95dd Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Mon, 14 Oct 2024 11:55:03 +0200
+Subject: [PATCH] lx2160acex6: assert IRQ0 GPIO to poweroff the EVB
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/aarch64/lx2160a.S | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+index 01b3c7ecd..8035b145e 100644
+--- a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
++++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+@@ -563,9 +563,9 @@ endfunc _soc_sys_reset
+ */
+ func _soc_sys_off
+
+- /* assert GPIO3[7] (IRQ07 - CEX-7 SUS_S5) */
++ /* assert GPIO3[7] (IRQ07 - CEX-7 SUS_S5), GPIO3[0] (IRQ00 - CEX-6 EVB IRQ0) */
+ mov x3, #NXP_GPIO3_ADDR
+- mov w1, #0x01000000
++ mov w1, #0x81000000
+ str w1, [x3]
+
+ /* disable sec, QBman, spi and qspi */
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,63 @@
+From 13496d248f11fe09d5a634fe15dd6b507a520a87 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 18 Oct 2024 21:09:04 +0200
+Subject: [PATCH 5/6] lx2160a: assert optional S5 gpio from Makefile constant
+
+GPIO address and number for S5 are specific per board and should not be
+set globally across lx2160.
+
+Add support for setting gpio address and number form platform.mk, into
+soc.mk:
+
+- LX2160A_S5_GPIO_ADDR: gpio value register address
+- LX2160A_S5_GPIO: gpio number
+
+This feature can be enabled for individual boards by setting a non-zero
+address in platform.mk file, before including soc.mk.
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/aarch64/lx2160a.S | 9 ++++++---
+ plat/nxp/soc-lx2160a/soc.mk | 8 ++++++++
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+index 8035b145e..67ade7b66 100644
+--- a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
++++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+@@ -563,10 +563,13 @@ endfunc _soc_sys_reset
+ */
+ func _soc_sys_off
+
+- /* assert GPIO3[7] (IRQ07 - CEX-7 SUS_S5), GPIO3[0] (IRQ00 - CEX-6 EVB IRQ0) */
+- mov x3, #NXP_GPIO3_ADDR
+- mov w1, #0x81000000
++#if defined(CONFIG_LX2160A_S5_GPIO_ADDR) && defined(CONFIG_LX2160A_S5_GPIO)
++ /* assert s5 gpio */
++ mov x3, # CONFIG_LX2160A_S5_GPIO_ADDR
++ ldr w1, [x3]
++ orr w1, w1, # 1 << (31 - CONFIG_LX2160A_S5_GPIO)
+ str w1, [x3]
++#endif
+
+ /* disable sec, QBman, spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
+index a72b4113d..20e64753c 100644
+--- a/plat/nxp/soc-lx2160a/soc.mk
++++ b/plat/nxp/soc-lx2160a/soc.mk
+@@ -177,3 +177,11 @@ include ${PLAT_PATH}/common/setup/common.mk
+
+ # Adding source files to generate separate DDR FIP image
+ include ${PLAT_SOC_PATH}/ddr_fip.mk
++
++# S5 GPIO (optional)
++LX2160A_S5_GPIO_ADDR ?= 0
++LX2160A_S5_GPIO ?= 0
++ifneq (${LX2160A_S5_GPIO_ADDR},0)
++$(eval $(call add_define_val,CONFIG_LX2160A_S5_GPIO_ADDR,$(LX2160A_S5_GPIO_ADDR)))
++$(eval $(call add_define_val,CONFIG_LX2160A_S5_GPIO,$(LX2160A_S5_GPIO)))
++endif
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,418 @@
+From 1fc354074e5fe98e185633b8d7f62836d5b2b710 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 18 Oct 2024 15:11:53 +0200
+Subject: [PATCH 6/6] add separate platform for solidrun cex7 module
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2160acex7/ddr_init.c | 116 ++++++++++++++++++
+ plat/nxp/soc-lx2160a/lx2160acex7/plat_def.h | 105 ++++++++++++++++
+ plat/nxp/soc-lx2160a/lx2160acex7/platform.c | 29 +++++
+ plat/nxp/soc-lx2160a/lx2160acex7/platform.mk | 56 +++++++++
+ .../soc-lx2160a/lx2160acex7/platform_def.h | 14 +++
+ plat/nxp/soc-lx2160a/lx2160acex7/policy.h | 38 ++++++
+ 6 files changed, 358 insertions(+)
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex7/ddr_init.c
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex7/plat_def.h
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex7/platform.c
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex7/platform.mk
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex7/platform_def.h
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex7/policy.h
+
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160acex7/ddr_init.c
+new file mode 100644
+index 000000000..2bd014a7e
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/ddr_init.c
+@@ -0,0 +1,116 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <common/debug.h>
++#include <ddr.h>
++#include <lib/utils.h>
++#include <load_img.h>
++
++#include "plat_common.h"
++#include <platform_def.h>
++
++#if defined(CONFIG_STATIC_DDR) || defined(CONFIG_DDR_NODIMM)
++#error not implemented
++#endif /* defined(CONFIG_STATIC_DDR) || defined(CONFIG_DDR_NODIMM) */
++
++int ddr_board_options(struct ddr_info *priv)
++{
++ struct memctl_opt *popts = &priv->opt;
++ const struct ddr_conf *conf = &priv->conf;
++
++ popts->vref_dimm = U(0x24); /* range 1, 83.4% */
++ popts->rtt_override = 0;
++ popts->rtt_park = U(240);
++ popts->otf_burst_chop_en = 0;
++ popts->burst_length = U(DDR_BL8);
++ popts->trwt_override = U(1);
++ popts->bstopre = U(0); /* auto precharge */
++ popts->addr_hash = 1;
++
++ /* Set ODT impedance on PHY side */
++ switch (conf->cs_on_dimm[1]) {
++ case 0xc: /* Two slots dual rank */
++ case 0x4: /* Two slots single rank, not valid for interleaving */
++ popts->trwt = U(0xf);
++ popts->twrt = U(0x7);
++ popts->trrt = U(0x7);
++ popts->twwt = U(0x7);
++ popts->vref_phy = U(0x6B); /* 83.6% */
++ popts->odt = U(60);
++ popts->phy_tx_impedance = U(28);
++ break;
++ case 0: /* One slot used */
++ default:
++ popts->trwt = U(0x3);
++ popts->twrt = U(0x3);
++ popts->trrt = U(0x3);
++ popts->twwt = U(0x3);
++ popts->vref_phy = U(0x60); /* 75% */
++ popts->odt = U(48);
++ popts->phy_tx_impedance = U(28);
++ break;
++ }
++
++ return 0;
++}
++
++long long init_ddr(void)
++{
++ int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 };
++ struct ddr_info info;
++ struct sysinfo sys;
++ long long dram_size;
++
++ zeromem(&sys, sizeof(sys));
++ if (get_clocks(&sys) != 0) {
++ ERROR("System clocks are not set\n");
++ panic();
++ }
++ debug("platform clock %lu\n", sys.freq_platform);
++ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
++ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
++
++ zeromem(&info, sizeof(info));
++
++ /* Set two DDRC. Unused DDRC will be removed automatically. */
++ info.num_ctlrs = NUM_OF_DDRC;
++ info.spd_addr = spd_addr;
++ info.ddr[0] = (void *)NXP_DDR_ADDR;
++ info.ddr[1] = (void *)NXP_DDR2_ADDR;
++ info.phy[0] = (void *)NXP_DDR_PHY1_ADDR;
++ info.phy[1] = (void *)NXP_DDR_PHY2_ADDR;
++ info.clk = get_ddr_freq(&sys, 0);
++ info.img_loadr = load_img;
++ info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER;
++ if (info.clk == 0) {
++ info.clk = get_ddr_freq(&sys, 1);
++ }
++ info.dimm_on_ctlr = DDRC_NUM_DIMM;
++
++ info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED;
++
++ dram_size = dram_init(&info
++#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
++ , NXP_CCN_HN_F_0_ADDR
++#endif
++ );
++
++
++ if (dram_size < 0) {
++ ERROR("DDR init failed.\n");
++ }
++
++ return dram_size;
++}
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/plat_def.h b/plat/nxp/soc-lx2160a/lx2160acex7/plat_def.h
+new file mode 100644
+index 000000000..02f51e74d
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/plat_def.h
+@@ -0,0 +1,105 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef PLAT_DEF_H
++#define PLAT_DEF_H
++
++#include <arch.h>
++#include <cortex_a72.h>
++/* Required without TBBR.
++ * To include the defines for DDR PHY
++ * Images.
++ */
++#include <tbbr_img_def.h>
++
++#include <policy.h>
++#include <soc.h>
++
++#if defined(IMAGE_BL31)
++#define LS_SYS_TIMCTL_BASE 0x2890000
++#define PLAT_LS_NSTIMER_FRAME_ID 0
++#define LS_CONFIG_CNTACR 1
++#endif
++
++#define NXP_SYSCLK_FREQ 100000000
++#define NXP_DDRCLK_FREQ 100000000
++
++/* UART related definition */
++#define NXP_CONSOLE_ADDR NXP_UART_ADDR
++#define NXP_CONSOLE_BAUDRATE 115200
++
++/* Size of cacheable stacks */
++#if defined(IMAGE_BL2)
++#if defined(TRUSTED_BOARD_BOOT)
++#define PLATFORM_STACK_SIZE 0x2000
++#else
++#define PLATFORM_STACK_SIZE 0x1000
++#endif
++#elif defined(IMAGE_BL31)
++#define PLATFORM_STACK_SIZE 0x1000
++#endif
++
++/* SD block buffer */
++#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
++#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
++ - NXP_SD_BLOCK_BUF_SIZE)
++
++#ifdef SD_BOOT
++#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
++ - NXP_SD_BLOCK_BUF_SIZE)
++#else
++#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
++#endif
++
++/* IO defines as needed by IO driver framework */
++#define MAX_IO_DEVICES 4
++#define MAX_IO_BLOCK_DEVICES 1
++#define MAX_IO_HANDLES 4
++
++#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ)
++
++/*
++ * FIP image defines - Offset at which FIP Image would be present
++ * Image would include Bl31 , Bl33 and Bl32 (optional)
++ */
++#ifdef POLICY_FUSE_PROVISION
++#define MAX_FIP_DEVICES 3
++#endif
++
++#ifndef MAX_FIP_DEVICES
++#define MAX_FIP_DEVICES 2
++#endif
++
++/*
++ * ID of the secure physical generic timer interrupt used by the BL32.
++ */
++#define BL32_IRQ_SEC_PHY_TIMER 29
++
++#define BL31_WDOG_SEC 89
++
++#define BL31_NS_WDOG_WS1 108
++
++/*
++ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
++ * terminology. On a GICv2 system or mode, the lists will be merged and treated
++ * as Group 0 interrupts.
++ */
++#define PLAT_LS_G1S_IRQ_PROPS(grp) \
++ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE)
++
++/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
++#define NXP_IRQ_SEC_SGI_7 15
++
++#define PLAT_LS_G0_IRQ_PROPS(grp) \
++ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE), \
++ INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE), \
++ INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_LEVEL)
++#endif
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/platform.c b/plat/nxp/soc-lx2160a/lx2160acex7/platform.c
+new file mode 100644
+index 000000000..b00adb51d
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/platform.c
+@@ -0,0 +1,29 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include <plat_common.h>
++
++#pragma weak board_enable_povdd
++#pragma weak board_disable_povdd
++
++bool board_enable_povdd(void)
++{
++#ifdef CONFIG_POVDD_ENABLE
++ return true;
++#else
++ return false;
++#endif
++}
++
++bool board_disable_povdd(void)
++{
++#ifdef CONFIG_POVDD_ENABLE
++ return true;
++#else
++ return false;
++#endif
++}
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk b/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk
+new file mode 100644
+index 000000000..37598c2d7
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk
+@@ -0,0 +1,56 @@
++#
++# Copyright 2021 NXP
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++
++# board-specific build parameters
++
++BOOT_MODE ?= flexspi_nor
++BOARD ?= lx2160acex7
++POVDD_ENABLE := no
++NXP_COINED_BB := no
++
++ # DDR Compilation Configs
++NUM_OF_DDRC := 2
++DDRC_NUM_DIMM := 2
++DDRC_NUM_CS := 4
++DDR_ECC_EN := yes
++ #enable address decoding feature
++DDR_ADDR_DEC := yes
++APPLY_MAX_CDD := yes
++
++# S5 GPIO
++LX2160A_S5_GPIO_ADDR := NXP_GPIO3_ADDR
++LX2160A_S5_GPIO := 7
++
++# DDR Errata
++ERRATA_DDR_A011396 := 1
++ERRATA_DDR_A050450 := 1
++
++ # On-Board Flash Details
++FLASH_TYPE := MT35XU512A
++XSPI_FLASH_SZ := 0x10000000
++NXP_XSPI_NOR_UNIT_SIZE := 0x20000
++BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000
++# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This
++# config is enabled for future use cases.
++FSPI_ERASE_4K := 0
++
++ # Platform specific features.
++WARM_BOOT := no
++
++ # Adding Platform files build files
++BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
++ ${BOARD_PATH}/platform.c
++
++SUPPORTED_BOOT_MODE := flexspi_nor \
++ sd \
++ emmc \
++ auto
++
++# Adding platform board build info
++include plat/nxp/common/plat_make_helper/plat_common_def.mk
++
++ # Adding SoC build info
++include plat/nxp/soc-lx2160a/soc.mk
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/platform_def.h b/plat/nxp/soc-lx2160a/lx2160acex7/platform_def.h
+new file mode 100644
+index 000000000..666099800
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/platform_def.h
+@@ -0,0 +1,14 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef PLATFORM_DEF_H
++#define PLATFORM_DEF_H
++
++#include "plat_def.h"
++#include "plat_default_def.h"
++
++#endif
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/policy.h b/plat/nxp/soc-lx2160a/lx2160acex7/policy.h
+new file mode 100644
+index 000000000..19ad6dbec
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/policy.h
+@@ -0,0 +1,38 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef POLICY_H
++#define POLICY_H
++
++/* Following defines affect the PLATFORM SECURITY POLICY */
++
++/* set this to 0x0 if the platform is not using/responding to ECC errors
++ * set this to 0x1 if ECC is being used (we have to do some init)
++ */
++#define POLICY_USING_ECC 0x0
++
++/* Set this to 0x0 to leave the default SMMU page size in sACR
++ * Set this to 0x1 to change the SMMU page size to 64K
++ */
++#define POLICY_SMMU_PAGESZ_64K 0x1
++
++/*
++ * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I
++ * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7
++ * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23
++ */
++#define POLICY_PERF_WRIOP 0
++
++/*
++ * set this to '1' if the debug clocks need to remain enabled during
++ * system entry to low-power (LPM20) - this should only be necessary
++ * for testing and NEVER set for normal production
++ */
++#define POLICY_DEBUG_ENABLE 0
++
++
++#endif /* POLICY_H */
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,33 @@
+From 92d0a6fab056eb43fa5561fb1888c8c393ebee29 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 18 Oct 2024 21:17:12 +0200
+Subject: [PATCH 7/8] lx2160a: support flexible value for CONFIG_DDR_NODIMM
+
+Add support for values other than 0 and 1 for CONFIG_DDR_NODIMM.
+This macro can be used for both enabling, and selecting a specific
+memory configuration at compile-time.
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/common/plat_make_helper/plat_common_def.mk | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/plat/nxp/common/plat_make_helper/plat_common_def.mk b/plat/nxp/common/plat_make_helper/plat_common_def.mk
+index a1038a073..ed6e0bdac 100644
+--- a/plat/nxp/common/plat_make_helper/plat_common_def.mk
++++ b/plat/nxp/common/plat_make_helper/plat_common_def.mk
+@@ -39,8 +39,9 @@ ifneq (${NUM_OF_DDRC},)
+ $(eval $(call add_define_val,NUM_OF_DDRC,${NUM_OF_DDRC}))
+ endif
+
+-ifeq (${CONFIG_DDR_NODIMM},1)
+-$(eval $(call add_define,CONFIG_DDR_NODIMM))
++CONFIG_DDR_NODIMM ?= 0
++ifneq (${CONFIG_DDR_NODIMM},0)
++$(eval $(call add_define_val,CONFIG_DDR_NODIMM,${CONFIG_DDR_NODIMM}))
+ DDRC_NUM_DIMM := 1
+ endif
+
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,544 @@
+From 067c11cd6a6de8c7480b1f8c1002f29a9bc85787 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 18 Oct 2024 15:05:13 +0200
+Subject: [PATCH 8/8] add separate platform for solidrun internal cex6
+ evaluation board
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c | 236 ++++++++++++++++++
+ plat/nxp/soc-lx2160a/lx2160acex6/plat_def.h | 105 ++++++++
+ plat/nxp/soc-lx2160a/lx2160acex6/platform.c | 29 +++
+ plat/nxp/soc-lx2160a/lx2160acex6/platform.mk | 61 +++++
+ .../soc-lx2160a/lx2160acex6/platform_def.h | 14 ++
+ plat/nxp/soc-lx2160a/lx2160acex6/policy.h | 38 +++
+ 6 files changed, 483 insertions(+)
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex6/plat_def.h
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex6/platform.c
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex6/platform_def.h
+ create mode 100644 plat/nxp/soc-lx2160a/lx2160acex6/policy.h
+
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+new file mode 100644
+index 000000000..0b978e298
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+@@ -0,0 +1,236 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <common/debug.h>
++#include <ddr.h>
++#include <lib/utils.h>
++#include <load_img.h>
++
++#include "plat_common.h"
++#include <platform_def.h>
++
++#ifdef CONFIG_STATIC_DDR
++#error not implemented
++#elif defined(CONFIG_DDR_NODIMM)
++#if CONFIG_DDR_NODIMM == 1
++/*
++ * PCB Revision 1.0: 9 x K4A8G085WC-BCWE TODO
++ */
++#error Not implemented.
++#endif /* CONFIG_DDR_NODIMM == 1 */
++
++#if CONFIG_DDR_NODIMM == 2
++/*
++ * PCB Revision 1.1: 2 x 5 x K4A8G165WB-BCRC
++ *
++ * ECC disabled because of training failures.
++ */
++#define CONFIG_DDR_NODIMM_CH2
++static const struct dimm_params static_dimm = {
++ .mpart = "Fixed DDR Config 2",
++ .n_ranks = 1,
++ .die_density = 0x6, // encoded per spd byte 4, 0b110 = 16Gbit
++ .rank_density = 0x200000000, // 16GB
++ .capacity = 0x200000000, // 16GB
++ .primary_sdram_width = 64,
++ .ec_sdram_width = 0, // no ecc extension
++ .rdimm = 0,
++ .package_3ds = 0,
++ .device_width = 16, // 16 bit per sdram
++ .rc = 0,
++
++ .n_row_addr = 17,
++ .n_col_addr = 10,
++ .edc_config = 0, // disable ecc
++ .bank_addr_bits = 0, // 4 banks
++ .bank_group_bits = 1, // 2 bank groups
++ .burst_lengths_bitmask = 0xc, // enable 4 & 8-bit burst (DDR4 spec)
++
++ .mirrored_dimm = 0,
++
++ // timings based on K4A8G085WC-BCTD (DDR4-2666), missing values for 3200
++ .mtb_ps = 125, // MTB per SPD spec
++ .ftb_10th_ps = 10, // default value, unused by nxp ddr driver
++ .taa_ps = 13750, // min. 13.75ns
++ .tfaw_ps = 30000, // min: max(30ns or 28CK) (this 16Gbit sdram has 2KB pages)
++
++ .tckmin_x_ps = 625, // 3200 (CK=1600)
++ .tckmax_ps = 1250, // 1600 (CK=800)
++
++ .caslat_x = 0b00000001010101010101010000000000, // CL = [10,12,14,16,18,20,22,24] (1 << CL)
++
++ .trcd_ps = 13750, // 13.75ns - CL22-22-22
++ .trp_ps = 13750, // 13.75ns - CL22-22-22
++ .tras_ps = 32000, // 32ns
++
++ .trfc1_ps = 350000, // 350ns,
++ .trfc2_ps = 260000, // 260ns
++ .trfc4_ps = 160000, // 160ns
++ .trrds_ps = 5300, // min: max(4CK or 5.3ns)
++ .trrdl_ps = 6400, // min: max(4CK or 6.4ns)
++ .tccdl_ps = 5000, // min: max(4CK or 5ns)
++ .trfc_slr_ps = 0,
++
++ .trc_ps = 45750, // tras + trp 45.75ns
++ .twr_ps = 15000, // 15ns
++
++ .refresh_rate_ps = 7800000, // 1x mode 7.8us for standard temperature range (TODO: pick correct range based on temperature?!)
++ // .extended_op_srt = 0,
++
++ // .rcw = {}, // only for registered dimm
++ .dq_mapping = {
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x00,
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x20,
++ 0x00,
++ 0x20,
++ },
++ .dq_mapping_ors = 1,
++};
++#endif /* CONFIG_DDR_NODIMM == 2 */
++
++int ddr_get_ddr_params(struct dimm_params *pdimm,
++ struct ddr_conf *conf)
++{
++ // channel 1
++ conf->dimm_in_use[0] = 1;
++ memcpy(&pdimm[0], &static_dimm, sizeof(struct dimm_params));
++
++#if defined(CONFIG_DDR_NODIMM_CH2)
++ // channel 2
++ conf->dimm_in_use[1] = 1; // enable (module on) channel 2
++ memcpy(&pdimm[1], &static_dimm, sizeof(struct dimm_params));
++
++ /* 2 modules */
++ return 0x3;
++#else
++ /* 1 module */
++ return 0x1;
++#endif /* defined(CONFIG_DDR_NODIMM_CH2) */
++}
++#endif /* defined(CONFIG_DDR_NODIMM) */
++
++int ddr_board_options(struct ddr_info *priv)
++{
++ struct memctl_opt *popts = &priv->opt;
++ const struct ddr_conf *conf = &priv->conf;
++
++ popts->vref_dimm = U(0x24); /* range 1, 83.4% */
++ popts->rtt_override = 0;
++ popts->rtt_park = U(240);
++ popts->otf_burst_chop_en = 0;
++ popts->burst_length = U(DDR_BL8);
++ popts->trwt_override = U(0);
++ popts->bstopre = U(0); /* auto precharge */
++ popts->addr_hash = 1;
++ popts->caslat_override = 0; // TODO: why is this set by default?!
++ popts->caslat_override_value = 0; // TODO: why is this set by default?!
++ popts->auto_self_refresh_en = 1;
++ popts->output_driver_impedance = 0; // 34 Ohm
++ popts->twot_en = 0;
++ popts->threet_en = 0;
++ popts->addt_lat_override = 0; // TODO: why is this set by default?!
++ popts->addt_lat_override_value = 0; // TODO: why is this set by default?!
++ popts->phy_atx_impedance = 30;
++ popts->skip2d = 0;
++
++ /* Set ODT impedance on PHY side */
++ switch (conf->cs_on_dimm[1]) {
++ case 0xc: /* Two slots dual rank */
++ case 0x4: /* Two slots single rank, not valid for interleaving */
++ popts->trwt = U(0xf);
++ popts->twrt = U(0x7);
++ popts->trrt = U(0x7);
++ popts->twwt = U(0x7);
++ popts->vref_phy = U(0x6B); /* 83.6% */
++ popts->odt = U(60);
++ popts->phy_tx_impedance = U(28);
++ break;
++ case 0: /* One slot used */
++ default:
++ popts->trwt = U(0x3);
++ popts->twrt = U(0x3);
++ popts->trrt = U(0x3);
++ popts->twwt = U(0x3);
++ popts->vref_phy = U(0x60); /* 75% */
++ popts->odt = U(48);
++ popts->phy_tx_impedance = U(28);
++ break;
++ }
++
++ return 0;
++}
++
++long long init_ddr(void)
++{
++ int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 };
++ struct ddr_info info;
++ struct sysinfo sys;
++ long long dram_size;
++
++ zeromem(&sys, sizeof(sys));
++ if (get_clocks(&sys) != 0) {
++ ERROR("System clocks are not set\n");
++ panic();
++ }
++ debug("platform clock %lu\n", sys.freq_platform);
++ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
++ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
++
++ zeromem(&info, sizeof(info));
++
++ /* Set two DDRC. Unused DDRC will be removed automatically. */
++ info.num_ctlrs = NUM_OF_DDRC;
++ info.spd_addr = spd_addr;
++ info.ddr[0] = (void *)NXP_DDR_ADDR;
++ info.ddr[1] = (void *)NXP_DDR2_ADDR;
++ info.phy[0] = (void *)NXP_DDR_PHY1_ADDR;
++ info.phy[1] = (void *)NXP_DDR_PHY2_ADDR;
++ info.clk = get_ddr_freq(&sys, 0);
++ info.img_loadr = load_img;
++ info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER;
++ if (info.clk == 0) {
++ info.clk = get_ddr_freq(&sys, 1);
++ }
++ info.dimm_on_ctlr = DDRC_NUM_DIMM;
++
++ info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED;
++
++ dram_size = dram_init(&info
++#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
++ , NXP_CCN_HN_F_0_ADDR
++#endif
++ );
++
++
++ if (dram_size < 0) {
++ ERROR("DDR init failed.\n");
++ }
++
++ return dram_size;
++}
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/plat_def.h b/plat/nxp/soc-lx2160a/lx2160acex6/plat_def.h
+new file mode 100644
+index 000000000..02f51e74d
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/plat_def.h
+@@ -0,0 +1,105 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef PLAT_DEF_H
++#define PLAT_DEF_H
++
++#include <arch.h>
++#include <cortex_a72.h>
++/* Required without TBBR.
++ * To include the defines for DDR PHY
++ * Images.
++ */
++#include <tbbr_img_def.h>
++
++#include <policy.h>
++#include <soc.h>
++
++#if defined(IMAGE_BL31)
++#define LS_SYS_TIMCTL_BASE 0x2890000
++#define PLAT_LS_NSTIMER_FRAME_ID 0
++#define LS_CONFIG_CNTACR 1
++#endif
++
++#define NXP_SYSCLK_FREQ 100000000
++#define NXP_DDRCLK_FREQ 100000000
++
++/* UART related definition */
++#define NXP_CONSOLE_ADDR NXP_UART_ADDR
++#define NXP_CONSOLE_BAUDRATE 115200
++
++/* Size of cacheable stacks */
++#if defined(IMAGE_BL2)
++#if defined(TRUSTED_BOARD_BOOT)
++#define PLATFORM_STACK_SIZE 0x2000
++#else
++#define PLATFORM_STACK_SIZE 0x1000
++#endif
++#elif defined(IMAGE_BL31)
++#define PLATFORM_STACK_SIZE 0x1000
++#endif
++
++/* SD block buffer */
++#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
++#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
++ - NXP_SD_BLOCK_BUF_SIZE)
++
++#ifdef SD_BOOT
++#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
++ - NXP_SD_BLOCK_BUF_SIZE)
++#else
++#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
++#endif
++
++/* IO defines as needed by IO driver framework */
++#define MAX_IO_DEVICES 4
++#define MAX_IO_BLOCK_DEVICES 1
++#define MAX_IO_HANDLES 4
++
++#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ)
++
++/*
++ * FIP image defines - Offset at which FIP Image would be present
++ * Image would include Bl31 , Bl33 and Bl32 (optional)
++ */
++#ifdef POLICY_FUSE_PROVISION
++#define MAX_FIP_DEVICES 3
++#endif
++
++#ifndef MAX_FIP_DEVICES
++#define MAX_FIP_DEVICES 2
++#endif
++
++/*
++ * ID of the secure physical generic timer interrupt used by the BL32.
++ */
++#define BL32_IRQ_SEC_PHY_TIMER 29
++
++#define BL31_WDOG_SEC 89
++
++#define BL31_NS_WDOG_WS1 108
++
++/*
++ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
++ * terminology. On a GICv2 system or mode, the lists will be merged and treated
++ * as Group 0 interrupts.
++ */
++#define PLAT_LS_G1S_IRQ_PROPS(grp) \
++ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE)
++
++/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
++#define NXP_IRQ_SEC_SGI_7 15
++
++#define PLAT_LS_G0_IRQ_PROPS(grp) \
++ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE), \
++ INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE), \
++ INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_LEVEL)
++#endif
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/platform.c b/plat/nxp/soc-lx2160a/lx2160acex6/platform.c
+new file mode 100644
+index 000000000..b00adb51d
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/platform.c
+@@ -0,0 +1,29 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include <plat_common.h>
++
++#pragma weak board_enable_povdd
++#pragma weak board_disable_povdd
++
++bool board_enable_povdd(void)
++{
++#ifdef CONFIG_POVDD_ENABLE
++ return true;
++#else
++ return false;
++#endif
++}
++
++bool board_disable_povdd(void)
++{
++#ifdef CONFIG_POVDD_ENABLE
++ return true;
++#else
++ return false;
++#endif
++}
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk b/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+new file mode 100644
+index 000000000..1165cfa09
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+@@ -0,0 +1,61 @@
++#
++# Copyright 2021 NXP
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++
++# board-specific build parameters
++
++BOOT_MODE ?= flexspi_nor
++BOARD ?= lx2160acex6
++POVDD_ENABLE := no
++NXP_COINED_BB := no
++
++ # DDR Compilation Configs
++NUM_OF_DDRC := 2
++DDRC_NUM_DIMM := 2
++DDRC_NUM_CS := 4
++DDR_ECC_EN := yes
++ #enable address decoding feature
++DDR_ADDR_DEC := yes
++APPLY_MAX_CDD := yes
++
++# Mock SPD:
++# - 0: disable mock spd
++# - 2: 2 x 5 x K4A8G165WB-BCRC PCB v1.1
++CONFIG_DDR_NODIMM := 0
++
++# S5 GPIO
++LX2160A_S5_GPIO_ADDR := NXP_GPIO3_ADDR
++LX2160A_S5_GPIO := 0
++
++# DDR Errata
++ERRATA_DDR_A011396 := 1
++ERRATA_DDR_A050450 := 1
++
++ # On-Board Flash Details
++FLASH_TYPE := MT35XU512A
++XSPI_FLASH_SZ := 0x10000000
++NXP_XSPI_NOR_UNIT_SIZE := 0x20000
++BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000
++# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This
++# config is enabled for future use cases.
++FSPI_ERASE_4K := 0
++
++ # Platform specific features.
++WARM_BOOT := no
++
++ # Adding Platform files build files
++BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
++ ${BOARD_PATH}/platform.c
++
++SUPPORTED_BOOT_MODE := flexspi_nor \
++ sd \
++ emmc \
++ auto
++
++# Adding platform board build info
++include plat/nxp/common/plat_make_helper/plat_common_def.mk
++
++ # Adding SoC build info
++include plat/nxp/soc-lx2160a/soc.mk
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/platform_def.h b/plat/nxp/soc-lx2160a/lx2160acex6/platform_def.h
+new file mode 100644
+index 000000000..666099800
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/platform_def.h
+@@ -0,0 +1,14 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef PLATFORM_DEF_H
++#define PLATFORM_DEF_H
++
++#include "plat_def.h"
++#include "plat_default_def.h"
++
++#endif
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/policy.h b/plat/nxp/soc-lx2160a/lx2160acex6/policy.h
+new file mode 100644
+index 000000000..19ad6dbec
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/policy.h
+@@ -0,0 +1,38 @@
++/*
++ * Copyright 2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef POLICY_H
++#define POLICY_H
++
++/* Following defines affect the PLATFORM SECURITY POLICY */
++
++/* set this to 0x0 if the platform is not using/responding to ECC errors
++ * set this to 0x1 if ECC is being used (we have to do some init)
++ */
++#define POLICY_USING_ECC 0x0
++
++/* Set this to 0x0 to leave the default SMMU page size in sACR
++ * Set this to 0x1 to change the SMMU page size to 64K
++ */
++#define POLICY_SMMU_PAGESZ_64K 0x1
++
++/*
++ * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I
++ * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7
++ * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23
++ */
++#define POLICY_PERF_WRIOP 0
++
++/*
++ * set this to '1' if the debug clocks need to remain enabled during
++ * system entry to low-power (LPM20) - this should only be necessary
++ * for testing and NEVER set for normal production
++ */
++#define POLICY_DEBUG_ENABLE 0
++
++
++#endif /* POLICY_H */
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,365 @@
+From efa6cca1a194050caa37a16ddccbf5d6e568b42f Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 25 Oct 2024 15:36:57 +0200
+Subject: [PATCH 09/11] lx2160a: support flushing i2c bus before ddr init
+
+The i2c bus can get locked by a slave device holding sda low, when the
+cpu is reset during a transaction.
+Implement workaround according to LX2160A Chip Errata 07/2020 A-010650.
+
+The workaround is inactive by default and must be explicitly enabled
+through a board platform.mk file defining buses and muxes to flush:
+
+LX2160_FLUSH_IIC: 1D array, takes comma separate uint8 indicating
+human-readable i2c bus number,
+e.g: IIC1 & IIC2 = "1, 2".
+
+LX2160_FLUSH_IIC_MUX: 2D array, takes comma-separated 1D array
+initializer expressions with i2c bus number, mux address on the bus and
+a bitmask for channels to flush,
+e.g. IIC1 mux @ 77, channels 1&2 = "{1, 0x77, 0x03}".
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/common/setup/common.mk | 1 +
+ plat/nxp/common/setup/include/plat_common.h | 2 +
+ plat/nxp/common/setup/ls_bl2_el3_setup.c | 1 +
+ plat/nxp/common/setup/ls_i2c_init.c | 274 ++++++++++++++++++++
+ plat/nxp/soc-lx2160a/soc.mk | 6 +
+ 5 files changed, 284 insertions(+)
+ create mode 100644 plat/nxp/common/setup/ls_i2c_init.c
+
+diff --git a/plat/nxp/common/setup/common.mk b/plat/nxp/common/setup/common.mk
+index 1fcf1d093..6333ec515 100644
+--- a/plat/nxp/common/setup/common.mk
++++ b/plat/nxp/common/setup/common.mk
+@@ -80,6 +80,7 @@ BL2_SOURCES += drivers/io/io_fip.c \
+ plat/nxp/common/setup/ls_image_load.c \
+ plat/nxp/common/setup/ls_io_storage.c \
+ plat/nxp/common/setup/ls_bl2_el3_setup.c \
++ plat/nxp/common/setup/ls_i2c_init.c \
+ plat/nxp/common/setup/${ARCH}/ls_bl2_mem_params_desc.c
+
+ BL31_SOURCES += plat/nxp/common/setup/ls_bl31_setup.c \
+diff --git a/plat/nxp/common/setup/include/plat_common.h b/plat/nxp/common/setup/include/plat_common.h
+index 45832fa68..1c850ebe2 100644
+--- a/plat/nxp/common/setup/include/plat_common.h
++++ b/plat/nxp/common/setup/include/plat_common.h
+@@ -77,6 +77,8 @@ int open_backend(const uintptr_t spec);
+ void ls_bl2_plat_arch_setup(void);
+ void ls_bl2_el3_plat_arch_setup(void);
+
++void bl2_i2c_init(void);
++
+ enum boot_device {
+ BOOT_DEVICE_IFC_NOR,
+ BOOT_DEVICE_IFC_NAND,
+diff --git a/plat/nxp/common/setup/ls_bl2_el3_setup.c b/plat/nxp/common/setup/ls_bl2_el3_setup.c
+index a4cbaef45..63e3460d7 100644
+--- a/plat/nxp/common/setup/ls_bl2_el3_setup.c
++++ b/plat/nxp/common/setup/ls_bl2_el3_setup.c
+@@ -276,6 +276,7 @@ void bl2_el3_plat_prepare_exit(void)
+ */
+ void bl2_plat_preload_setup(void)
+ {
++ bl2_i2c_init();
+
+ soc_preload_setup();
+
+diff --git a/plat/nxp/common/setup/ls_i2c_init.c b/plat/nxp/common/setup/ls_i2c_init.c
+new file mode 100644
+index 000000000..5392b160d
+--- /dev/null
++++ b/plat/nxp/common/setup/ls_i2c_init.c
+@@ -0,0 +1,274 @@
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <common/debug.h>
++#include <drivers/delay_timer.h>
++#include <i2c.h>
++#include <soc.h>
++
++#define NXP_IIC1_ADDR 0x02000000
++#define NXP_IIC2_ADDR 0x02010000
++#define NXP_IIC3_ADDR 0x02020000
++#define NXP_IIC4_ADDR 0x02030000
++#define NXP_IIC5_ADDR 0x02040000
++#define NXP_IIC6_ADDR 0x02050000
++#define NXP_IIC7_ADDR 0x02060000
++#define NXP_IIC8_ADDR 0x02070000
++
++#define RCWSR12 0x01e0012c
++#define RCWSR12_IIC2_PMUX_MASK 0x00000007 /* [0..2] */
++#define RCWSR12_IIC2_PMUX_IIC2 0x00000000
++#define RCWSR12_IIC2_PMUX_GPIO 0x00000001
++#define RCWSR12_IIC3_PMUX_MASK 0x00000038 /* [3..5] */
++#define RCWSR12_IIC3_PMUX_IIC3 0x00000000
++#define RCWSR12_IIC3_PMUX_GPIO 0x00000008
++#define RCWSR12_IIC4_PMUX_MASK 0x000001c0 /* [6..8] */
++#define RCWSR12_IIC4_PMUX_IIC4 0x00000000
++#define RCWSR12_IIC4_PMUX_GPIO 0x00000040
++#define RCWSR12_IIC5_PMUX_MASK 0x00000e00 /* [9..11] */
++#define RCWSR12_IIC5_PMUX_IIC5 0x00000000
++#define RCWSR12_IIC5_PMUX_GPIO 0x00000200
++#define RCWSR12_IIC6_PMUX_MASK 0x00007000 /* [12..14] */
++#define RCWSR12_IIC6_PMUX_IIC6 0x00000000
++#define RCWSR12_IIC6_PMUX_GPIO 0x00001000
++#define RCWSR13 0x01e00130
++#define RCWSR12_SDHC2_DAT74_PMUX_MASK 0x00000003
++#define RCWSR12_SDHC2_DAT74_PMUX_SDHC2 0x00000000
++#define RCWSR12_SDHC2_DAT74_PMUX_IIC78 0x00000001
++#define RCWSR14 0x01e00134
++#define RCWSR14_IIC1_PMUX_MASK 0x00000400 /* [10] */
++#define RCWSR14_IIC1_PMUX_IIC1 0x00000000
++#define RCWSR14_IIC1_PMUX_GPIO 0x00000400
++
++static void ls_i2c_flush_pca9547(uint8_t busno, const char *busname, uint8_t address, uint8_t channels);
++static void ls_i2c_flush(uint8_t busno, const char *busname);
++
++/**
++ * Flush i2c buses to make slave devices release sda,
++ * in case the system was reset during a transaction.
++ */
++void bl2_i2c_init() {
++ const uint8_t bus_flush_list[] = {CONFIG_LX2160_FLUSH_IIC};
++ /*
++ * List of muxes and channels to flush. Takes 2D array:
++ * {<bus number>, <mux chip address>, <channel bitmask>},
++ */
++ const uint8_t mux_flush_list[][3] = {CONFIG_LX2160_FLUSH_IIC_MUX};
++ const uintptr_t iic_base_addr[] = {
++ NXP_IIC1_ADDR,
++ NXP_IIC2_ADDR,
++ NXP_IIC3_ADDR,
++ NXP_IIC4_ADDR,
++ NXP_IIC5_ADDR,
++ NXP_IIC6_ADDR,
++ };
++ const char *iic_name[] = {
++ "IIC1",
++ "IIC2",
++ "IIC3",
++ "IIC4",
++ "IIC5",
++ "IIC6",
++ };
++ int i;
++ uint8_t busno;
++ uint8_t address;
++ uint8_t channels;
++
++ /* flush i2c buses */
++ for (i = 0; i < ARRAY_SIZE(bus_flush_list); i++) {
++ busno = bus_flush_list[i] - 1;
++ i2c_init(iic_base_addr[busno]);
++ ls_i2c_flush(busno, iic_name[busno]);
++ }
++
++ /* flush muxes channels */
++ for (i = 0; i < ARRAY_SIZE(mux_flush_list); i++) {
++ busno = mux_flush_list[i][0] - 1;
++ address = mux_flush_list[i][1];
++ channels = mux_flush_list[i][2];
++ i2c_init(iic_base_addr[busno]);
++ ls_i2c_flush_pca9547(busno, iic_name[busno], address, channels);
++ }
++}
++
++static void ls_i2c_flush_pca9547(uint8_t busno, const char *busname, uint8_t chip, uint8_t channels) {
++ uint8_t channel, creg = 0;
++ char buffer[64];
++ int ret;
++
++ /* try read configuration register */
++ ret = i2c_read(chip, 0x00, 1, &creg, 1);
++ if(ret != 0) {
++ /* no device responding at address, skip */
++ return;
++ }
++
++ /* after reset configuration register reads 0x08 */
++ if(creg != 0x08) {
++ /* probably not a pca9547, skip */
++ return;
++ }
++
++ /* flush selected channels */
++ for(uint8_t i = 8; i > 0; i--) {
++ if (!(channels & (1 << (i-1))))
++ continue;
++
++ /* select channel i */
++ channel = 0x08 | (i-1);
++ i2c_write(chip, 0x00, 1, &channel, 1);
++
++ /* flush channel */
++ snprintf(buffer, sizeof(buffer), "%s mux@%02x channel %u", busname, chip, i-1);
++ ls_i2c_flush(busno, buffer);
++ }
++}
++
++static struct i2c_bus_info {
++ uintptr_t pinmux_addr;
++ uint32_t pinmux_mask;
++ uint32_t pinmux_sel;
++ uintptr_t gpio_addr;
++ uint8_t gpio_scl;
++ uint8_t gpio_sda;
++} ls_i2c_bus_info[] = {
++ {
++ .pinmux_addr = RCWSR14,
++ .pinmux_mask = RCWSR14_IIC1_PMUX_MASK,
++ .pinmux_sel = RCWSR14_IIC1_PMUX_GPIO,
++ .gpio_addr = NXP_GPIO1_ADDR,
++ .gpio_scl = 3, /* GPIO1_DAT03 */
++ .gpio_sda = 2, /* GPIO1_DAT02 */
++ },
++ {
++ .pinmux_addr = RCWSR12,
++ .pinmux_mask = RCWSR12_IIC2_PMUX_MASK,
++ .pinmux_sel = RCWSR12_IIC2_PMUX_GPIO,
++ .gpio_addr = NXP_GPIO1_ADDR,
++ .gpio_scl = 31, /* GPIO1_DAT31 */
++ .gpio_sda = 30, /* GPIO1_DAT30 */
++ },
++ {
++ .pinmux_addr = RCWSR12,
++ .pinmux_mask = RCWSR12_IIC3_PMUX_MASK,
++ .pinmux_sel = RCWSR12_IIC3_PMUX_GPIO,
++ .gpio_addr = NXP_GPIO1_ADDR,
++ .gpio_scl = 29, /* GPIO1_DAT29 */
++ .gpio_sda = 28, /* GPIO1_DAT28 */
++ },
++ {
++ .pinmux_addr = RCWSR12,
++ .pinmux_mask = RCWSR12_IIC4_PMUX_MASK,
++ .pinmux_sel = RCWSR12_IIC4_PMUX_GPIO,
++ .gpio_addr = NXP_GPIO1_ADDR,
++ .gpio_scl = 27, /* GPIO1_DAT27 */
++ .gpio_sda = 26, /* GPIO1_DAT26 */
++ },
++ {
++ .pinmux_addr = RCWSR12,
++ .pinmux_mask = RCWSR12_IIC5_PMUX_MASK,
++ .pinmux_sel = RCWSR12_IIC5_PMUX_GPIO,
++ .gpio_addr = NXP_GPIO1_ADDR,
++ .gpio_scl = 25, /* GPIO1_DAT25 */
++ .gpio_sda = 24, /* GPIO1_DAT24 */
++ },
++ {
++ .pinmux_addr = RCWSR12,
++ .pinmux_mask = RCWSR12_IIC6_PMUX_MASK,
++ .pinmux_sel = RCWSR12_IIC6_PMUX_GPIO,
++ .gpio_addr = NXP_GPIO1_ADDR,
++ .gpio_scl = 23, /* GPIO1_DAT23 */
++ .gpio_sda = 22, /* GPIO1_DAT22 */
++ },
++ {
++ .pinmux_addr = RCWSR13,
++ .pinmux_mask = RCWSR12_SDHC2_DAT74_PMUX_MASK,
++ .pinmux_sel = RCWSR12_SDHC2_DAT74_PMUX_IIC78,
++ .gpio_addr = NXP_GPIO2_ADDR,
++ .gpio_scl = 16, /* GPIO2_DAT16 */
++ .gpio_sda = 15, /* GPIO2_DAT15 */
++ },
++ {
++ .pinmux_addr = RCWSR13,
++ .pinmux_mask = RCWSR12_SDHC2_DAT74_PMUX_MASK,
++ .pinmux_sel = RCWSR12_SDHC2_DAT74_PMUX_IIC78,
++ .gpio_addr = NXP_GPIO2_ADDR,
++ .gpio_scl = 18, /* GPIO2_DAT18 */
++ .gpio_sda = 17, /* GPIO2_DAT17 */
++ },
++};
++
++/*
++ * Flush the i2c bus through any muxes with 9 clock cycles
++ * to ensure all slave devices release their locks on SDA.
++ * This is a work-around for i2c slave devices locking SDA,
++ * when the system has been reset during a transaction.
++ *
++ * The implementation is inspired by LX2160A Chip Errata 07/2020 A-010650.
++ */
++static void ls_i2c_flush(uint8_t busno, const char *busname) {
++ struct i2c_bus_info *info;
++ uintptr_t gpdir_addr, gpodr_addr, gpdat_addr;
++ uint32_t pinmux, gpdir, gpodr, gpdat;
++ struct {
++ uint32_t pinmux, gpdir, gpodr, gpdat;
++ } backup;
++ uint32_t scl_mask, sda_mask;
++
++ if(busno >= 8) {
++ ERROR("failed to flush i2c bus %u %s: invalid bus number!\n", busno, busname);
++ return;
++ }
++ /* load i2c bus specific information */
++ info = &ls_i2c_bus_info[busno];
++ gpdir_addr = info->gpio_addr + 0x0;
++ gpodr_addr = info->gpio_addr + 0x4;
++ gpdat_addr = info->gpio_addr + 0x8;
++ scl_mask = 0x80000000 >> info->gpio_scl;
++ sda_mask = 0x80000000 >> info->gpio_sda;
++
++ /* backup configuration registers */
++ pinmux = backup.pinmux = mmio_read_32(info->pinmux_addr);
++ gpdir = backup.gpdir = mmio_read_32(gpdir_addr);
++ gpodr = backup.gpodr = mmio_read_32(gpodr_addr);
++ gpdat = backup.gpdat = mmio_read_32(gpdat_addr);
++
++ /* configure SCL+SDA as GPIOs */
++ pinmux = (pinmux & ~info->pinmux_mask) | info->pinmux_sel;
++ mmio_write_32(info->pinmux_addr, pinmux);
++
++ /* configure SCL+SDA as output open drain */
++ gpdir |= scl_mask | sda_mask;
++ gpodr |= scl_mask | sda_mask;
++ gpdat |= scl_mask | sda_mask;
++ mmio_write_32(gpdir_addr, gpdir);
++ mmio_write_32(gpodr_addr, gpodr);
++ mmio_write_32(gpdat_addr, gpdat);
++
++ /*
++ * reliable detection of blocked bus is hard
++ * because sda depends on the last sent bit.
++ * Flush unconditionally instead.
++ */
++
++ VERBOSE("flushing i2c bus %u (%s)\n", busno, busname);
++
++ /* toggle clock 9 times */
++ for(uint8_t i = 0; i < 9; i++) {
++ mmio_write_32(gpdat_addr, gpdat & ~scl_mask);
++ udelay(10);
++ mmio_write_32(gpdat_addr, gpdat | scl_mask);
++ udelay(10);
++ }
++
++ /* restore configuration registers */
++ mmio_write_32(gpdat_addr, backup.gpdat);
++ mmio_write_32(gpodr_addr, backup.gpodr);
++ mmio_write_32(gpdir_addr, backup.gpdir);
++ mmio_write_32(info->pinmux_addr, backup.pinmux);
++
++ return;
++}
+diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
+index 20e64753c..fa8c63251 100644
+--- a/plat/nxp/soc-lx2160a/soc.mk
++++ b/plat/nxp/soc-lx2160a/soc.mk
+@@ -185,3 +185,9 @@ ifneq (${LX2160A_S5_GPIO_ADDR},0)
+ $(eval $(call add_define_val,CONFIG_LX2160A_S5_GPIO_ADDR,$(LX2160A_S5_GPIO_ADDR)))
+ $(eval $(call add_define_val,CONFIG_LX2160A_S5_GPIO,$(LX2160A_S5_GPIO)))
+ endif
++
++# I2C Bus Flushing (optional)
++LX2160_FLUSH_IIC ?= ""
++LX2160_FLUSH_IIC_MUX ?= ""
++$(eval $(call add_define_val,CONFIG_LX2160_FLUSH_IIC,"$(LX2160_FLUSH_IIC)"))
++$(eval $(call add_define_val,CONFIG_LX2160_FLUSH_IIC_MUX,"$(LX2160_FLUSH_IIC_MUX)"))
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,30 @@
+From 668924da1e8df2036dc05022616eb7d15a8c8727 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 25 Oct 2024 16:43:59 +0200
+Subject: [PATCH 10/11] lx2160acex6: flush i2c bus with spd eeprom before ddr
+ init
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2160acex6/platform.mk | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk b/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+index 1165cfa09..950207878 100644
+--- a/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+@@ -29,6 +29,11 @@ CONFIG_DDR_NODIMM := 0
+ LX2160A_S5_GPIO_ADDR := NXP_GPIO3_ADDR
+ LX2160A_S5_GPIO := 0
+
++# I2C Bus Flushing: IIC1
++LX2160_FLUSH_IIC := 1,
++# I2C Mux Flushing: IIC1: PCA9547@77: Channel 0 (SPD EEPROM)
++LX2160_FLUSH_IIC_MUX := { 1, 0x77, 0x01 },
++
+ # DDR Errata
+ ERRATA_DDR_A011396 := 1
+ ERRATA_DDR_A050450 := 1
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,30 @@
+From 722e93b7d159dfb9435e642cb0b38c2255a10391 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Fri, 25 Oct 2024 18:11:56 +0200
+Subject: [PATCH 11/11] lx2160acex7: flush i2c bus with spd eeprom before ddr
+ init
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2160acex7/platform.mk | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk b/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk
+index 37598c2d7..0b064bbbf 100644
+--- a/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk
++++ b/plat/nxp/soc-lx2160a/lx2160acex7/platform.mk
+@@ -24,6 +24,11 @@ APPLY_MAX_CDD := yes
+ LX2160A_S5_GPIO_ADDR := NXP_GPIO3_ADDR
+ LX2160A_S5_GPIO := 7
+
++# I2C Bus Flushing: IIC1
++LX2160_FLUSH_IIC := 1,
++# I2C Mux Flushing: IIC1: PCA9547@77: Channel 0 (SPD EEPROM)
++LX2160_FLUSH_IIC_MUX := { 1, 0x77, 0x01 },
++
+ # DDR Errata
+ ERRATA_DDR_A011396 := 1
+ ERRATA_DDR_A050450 := 1
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,49 @@
+From 94bdc4e055d10b89c7683c7966791612a7aed455 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Tue, 30 Jul 2024 17:45:33 +0300
+Subject: [PATCH 12/13] plat: lx2160a: fix building without
+ NXP_NV_SW_MAINT_LAST_EXEC_DATA
+
+Fix compiler errors encountered when disabling non-volatile storage of
+execution state (NXP_NV_SW_MAINT_LAST_EXEC_DATA := no) while keeping
+watchdog restart enabled (NXP_WDOG_RESTART := yes).
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ drivers/nxp/ddr/phy-gen2/phy.h | 2 +-
+ plat/nxp/soc-lx2160a/soc.c | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nxp/ddr/phy-gen2/phy.h b/drivers/nxp/ddr/phy-gen2/phy.h
+index 5e80f3638..7ddc7c7c6 100644
+--- a/drivers/nxp/ddr/phy-gen2/phy.h
++++ b/drivers/nxp/ddr/phy-gen2/phy.h
+@@ -6,7 +6,7 @@
+ #if !defined(PHY_H) && defined(NXP_WARM_BOOT)
+ #define PHY_H
+
+-#include <flash_info.h>
++#include <drivers/nxp/flexspi/flash_info.h>
+
+ /* To store sector size to be erase on flash*/
+ #define PHY_ERASE_SIZE F_SECTOR_ERASE_SZ
+diff --git a/plat/nxp/soc-lx2160a/soc.c b/plat/nxp/soc-lx2160a/soc.c
+index 137c24ef8..4aebb1393 100644
+--- a/plat/nxp/soc-lx2160a/soc.c
++++ b/plat/nxp/soc-lx2160a/soc.c
+@@ -521,10 +521,12 @@ void soc_init(void)
+ static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+ {
++#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA
+ uint8_t data = WDOG_RESET_FLAG;
+
+ wr_nv_app_data(WDT_RESET_FLAG_OFFSET,
+ (uint8_t *)&data, sizeof(data));
++#endif
+
+ mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT);
+
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,33 @@
+From cbe4212aaa1b934135c8400f16265849d12689c0 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Tue, 30 Jul 2024 17:45:38 +0300
+Subject: [PATCH 13/13] plat: lx2160a: fix boot without spi flash / disable
+ non-volatile storage
+
+Watchdog restart function does not require book-keeping on non-volatile
+storage.
+Remove explicit enabling of NXP_NV_SW_MAINT_LAST_EXEC_DATA.
+
+This fixed hang during boot where atf gets stuck trying to erase a
+sector of spi flash.
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/soc.mk | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
+index fa8c63251..4e864e164 100644
+--- a/plat/nxp/soc-lx2160a/soc.mk
++++ b/plat/nxp/soc-lx2160a/soc.mk
+@@ -28,7 +28,6 @@ NXP_WDOG_RESTART := yes
+
+ # for features enabled above.
+ ifeq (${NXP_WDOG_RESTART}, yes)
+-NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes
+ LS_EL3_INTERRUPT_HANDLER := yes
+ $(eval $(call add_define, NXP_WDOG_RESTART))
+ endif
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,597 @@
+From 956be9ce8f365e7f9ac7d7d1f896f1c2a27f6287 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Sun, 27 Oct 2024 18:00:11 +0100
+Subject: [PATCH] add separate platform for solidrun lx2162a som
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2162asom/ddr_init.c | 290 ++++++++++++++++++
+ plat/nxp/soc-lx2160a/lx2162asom/plat_def.h | 105 +++++++
+ plat/nxp/soc-lx2160a/lx2162asom/platform.c | 29 ++
+ plat/nxp/soc-lx2160a/lx2162asom/platform.mk | 61 ++++
+ .../nxp/soc-lx2160a/lx2162asom/platform_def.h | 14 +
+ plat/nxp/soc-lx2160a/lx2162asom/policy.h | 38 +++
+ 6 files changed, 537 insertions(+)
+ create mode 100644 plat/nxp/soc-lx2160a/lx2162asom/ddr_init.c
+ create mode 100644 plat/nxp/soc-lx2160a/lx2162asom/plat_def.h
+ create mode 100644 plat/nxp/soc-lx2160a/lx2162asom/platform.c
+ create mode 100644 plat/nxp/soc-lx2160a/lx2162asom/platform.mk
+ create mode 100644 plat/nxp/soc-lx2160a/lx2162asom/platform_def.h
+ create mode 100644 plat/nxp/soc-lx2160a/lx2162asom/policy.h
+
+diff --git a/plat/nxp/soc-lx2160a/lx2162asom/ddr_init.c b/plat/nxp/soc-lx2160a/lx2162asom/ddr_init.c
+new file mode 100644
+index 000000000..2cadab7ba
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2162asom/ddr_init.c
+@@ -0,0 +1,290 @@
++/*
++ * Copyright 2018-2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <common/debug.h>
++#include <ddr.h>
++#include <lib/utils.h>
++#include <load_img.h>
++
++#include "plat_common.h"
++#include <platform_def.h>
++
++#ifdef CONFIG_STATIC_DDR
++#error not implemented
++#elif defined(CONFIG_DDR_NODIMM)
++#if CONFIG_DDR_NODIMM == 1
++/*
++ * SoM Revision 1.1: 9 x K4A8G085WC-BCWE (SDP, 8GB w/ ECC)
++ *
++ * Use in production for units with empty SPD,
++ * and development.
++ */
++static const struct dimm_params static_dimm = {
++ .mpart = "Fixed DDR Config 1",
++ .n_ranks = 1,
++ .die_density = 0x5, // encoded per spd byte 4, 0b101 = 8Gbit
++ .rank_density = 0x200000000, // 8GB
++ .capacity = 0x200000000, // 8GB
++ .primary_sdram_width = 64,
++ .ec_sdram_width = 8, // 8 bit ecc extension
++ .rdimm = 0,
++ .package_3ds = 0,
++ .device_width = 8, // 8 bit per sdram
++ .rc = 0,
++
++ .n_row_addr = 16,
++ .n_col_addr = 10,
++ .edc_config = 2, // enable ecc
++ .bank_addr_bits = 0, // 4 banks
++ .bank_group_bits = 2, // 4 bank groups
++ .burst_lengths_bitmask = 0xc, // enable 4 & 8-bit burst (DDR4 spec)
++
++ .mirrored_dimm = 0,
++
++ // timings based on K4A8G085WC-BCTD (DDR4-2666), missing values for 3200
++ .mtb_ps = 125, // MTB per SPD spec
++ .ftb_10th_ps = 10, // default value, unused by nxp ddr driver
++ .taa_ps = 13750, // min. 13.75ns
++ .tfaw_ps = 21000, // min: max(21ns or 20CK) (this 8Gbit sdram has 1KB pages)
++
++ .tckmin_x_ps = 625, // 3200 (CK=1600)
++ .tckmax_ps = 1250, // 1600 (CK=800)
++
++ .caslat_x = 0b00000001011111111111110000000000, // CL = [10-22,24] (1 << CL)
++
++ .trcd_ps = 13750, // 13.75ns - CL22-22-22
++ .trp_ps = 13750, // 13.75ns - CL22-22-22
++ .tras_ps = 32000, // 32ns
++
++ .trfc1_ps = 350000, // 350ns
++ .trfc2_ps = 260000, // 260ns
++ .trfc4_ps = 160000, // 160ns
++ .trrds_ps = 3300, // min: max(4CK or 3.3ns)
++ .trrdl_ps = 4900, // min: max(4CK or 6.4ns)
++ .tccdl_ps = 5000, // min: max(5CK or 5ns)
++ .trfc_slr_ps = 0,
++
++ .trc_ps = 45750, // tras + trp 45.75ns
++ .twr_ps = 15000, // 15ns
++
++ .refresh_rate_ps = 7800000, // 1x mode 7.8us for standard temperature range (TODO: pick correct range based on temperature?!)
++ // .extended_op_srt = 0,
++
++ // .rcw = {}, // only for registered dimm
++ .dq_mapping = {
++ 0x16, // DQ[0:3]: lower nibble, bit order 3120
++ 0x22, // DQ[4:7]: upper nibble, bit order 4576
++ 0x0e, // DQ[8:11]: lower nibble, bit order 2031
++ 0x30, // DQ[12:15]: upper nibble, bit order 6574
++ 0x14, // DQ[16:19]: lower nibble, bit order 3021
++ 0x36, // DQ[20:23]: upper nibble, bit order 7564
++ 0x11, // DQ[24:27]: lower nibble, bit order 2301
++ 0x2f, // DQ[28:31]: upper nibble, bit order 6547
++ 0x03, // ECC[0:3]: lower nibble, bit order 0213
++ 0x22, // ECC[4:7]: upper nibble, bit order 4576
++ 0x10, // DQ[32:35]: lower nibble, bit order 2130
++ 0x30, // DQ[36:39]: upper nibble, bit order 6574
++ 0x0e, // DQ[40:43]: lower nibble, bit order 2031
++ 0x34, // DQ[44:47]: upper nibble, bit order 7465
++ 0x14, // DQ[48:51]: lower nibble, bit order 3021
++ 0x36, // DQ[52:55]: upper nibble, bit order 7564
++ 0x10, // DQ[56:59]: lower nibble, bit order 2130
++ 0x2b, // DQ[60:63]: upper nibble, bit order 5746
++ },
++ .dq_mapping_ors = 1,
++};
++#endif /* CONFIG_DDR_NODIMM == 1 */
++
++#if CONFIG_DDR_NODIMM == 2
++/*
++ * SoM Revision 1.1: 9 x K4AAG085WA-BCWE (DDP, 16GB w/ ECC)
++ *
++ * Use in production for units with empty SPD,
++ * and development.
++ */
++static const struct dimm_params static_dimm = {
++ .mpart = "Fixed DDR Config 2",
++ .n_ranks = 1,
++ .die_density = 0x6, // encoded per spd byte 4, 0b110 = 16Gbit
++ // TODO: for DDP memory should have 2 ranks per DIMM + correct density per die?
++ .rank_density = 0x400000000, // 16GB
++ .capacity = 0x400000000, // 16GB
++ .primary_sdram_width = 64,
++ .ec_sdram_width = 8, // 8 bit ecc extension
++ .rdimm = 0,
++ .package_3ds = 0,
++ .device_width = 8, // 8 bit per sdram
++ .rc = 0,
++
++ .n_row_addr = 17,
++ .n_col_addr = 10,
++ .edc_config = 2, // enable ecc
++ .bank_addr_bits = 0, // 4 banks
++ .bank_group_bits = 2, // 4 bank groups
++ .burst_lengths_bitmask = 0xc, // enable 4 & 8-bit burst (DDR4 spec)
++
++ .mirrored_dimm = 0,
++
++ .mtb_ps = 125, // MTB per SPD spec
++ .ftb_10th_ps = 10, // default value, unused by nxp ddr driver
++ .taa_ps = 13750, // min. 13.75ns
++ .tfaw_ps = 30000, // min: max(30ns or 28CK) (this 16Gbit sdram has 2KB pages)
++
++ .tckmin_x_ps = 625, // 3200 (CK=1600)
++ .tckmax_ps = 1250, // 1600 (CK=800)
++
++ .caslat_x = 0b00000001011111111111110000000000, // CL = [10-22,24] (1 << CL)
++
++ .trcd_ps = 13750, // 13.75ns
++ .trp_ps = 13750, // 13.75ns
++ .tras_ps = 32000, // 32ns
++
++ .trfc1_ps = 350000, // 350ns, assumed same as 8Gbit SDP module
++ .trfc2_ps = 260000, // 260ns, assumed same as 8Gbit SDP module
++ .trfc4_ps = 160000, // 160ns, assumed same as 8Gbit SDP module
++ .trrds_ps = 5300, // min: max(4CK or 5.3ns)
++ .trrdl_ps = 6400, // min: max(4CK or 6.4ns)
++ .tccdl_ps = 5000, // min: max(5CK or 5ns)
++ .trfc_slr_ps = 0,
++
++ .trc_ps = 45750, // tras + trp 45.75ns
++ .twr_ps = 15000, // 15ns
++
++ .refresh_rate_ps = 7800000, // 1x mode 7.8us for standard temperature range (TODO: pick correct range based on temperature?!)
++ // .extended_op_srt = 0,
++
++ // .rcw = {}, // only for registered dimm
++ .dq_mapping = {
++ 0x16, // DQ[0:3]: lower nibble, bit order 3120
++ 0x22, // DQ[4:7]: upper nibble, bit order 4576
++ 0x0e, // DQ[8:11]: lower nibble, bit order 2031
++ 0x30, // DQ[12:15]: upper nibble, bit order 6574
++ 0x14, // DQ[16:19]: lower nibble, bit order 3021
++ 0x36, // DQ[20:23]: upper nibble, bit order 7564
++ 0x11, // DQ[24:27]: lower nibble, bit order 2301
++ 0x2f, // DQ[28:31]: upper nibble, bit order 6547
++ 0x03, // ECC[0:3]: lower nibble, bit order 0213
++ 0x22, // ECC[4:7]: upper nibble, bit order 4576
++ 0x10, // DQ[32:35]: lower nibble, bit order 2130
++ 0x30, // DQ[36:39]: upper nibble, bit order 6574
++ 0x0e, // DQ[40:43]: lower nibble, bit order 2031
++ 0x34, // DQ[44:47]: upper nibble, bit order 7465
++ 0x14, // DQ[48:51]: lower nibble, bit order 3021
++ 0x36, // DQ[52:55]: upper nibble, bit order 7564
++ 0x10, // DQ[56:59]: lower nibble, bit order 2130
++ 0x2b, // DQ[60:63]: upper nibble, bit order 5746
++ },
++ .dq_mapping_ors = 1,
++};
++#endif /* CONFIG_DDR_NODIMM == 2 */
++
++int ddr_get_ddr_params(struct dimm_params *pdimm,
++ struct ddr_conf *conf)
++{
++ // channel 1
++ conf->dimm_in_use[0] = 1;
++ memcpy(&pdimm[0], &static_dimm, sizeof(struct dimm_params));
++
++ /* 1 module */
++ return 0x1;
++}
++#endif /* defined(CONFIG_DDR_NODIMM) */
++
++int ddr_board_options(struct ddr_info *priv)
++{
++ struct memctl_opt *popts = &priv->opt;
++
++ popts->caslat_override = 0;
++ popts->caslat_override_value = 0;
++ popts->auto_self_refresh_en = 1;
++ popts->output_driver_impedance = 0; // 34 Ohm
++ popts->twot_en = 0;
++ popts->threet_en = 0;
++ popts->addt_lat_override = 0;
++ popts->addt_lat_override_value = 0;
++ popts->phy_atx_impedance = 30;
++ popts->skip2d = 0;
++ popts->vref_dimm = U(0x19); /* range 1, 83.4% */
++
++ popts->rtt_override = 0;
++ popts->rtt_park = 120U;
++ popts->otf_burst_chop_en = 0;
++ popts->burst_length = DDR_BL8;
++ popts->trwt_override = 1;
++ popts->bstopre = 0; /* auto precharge */
++ popts->addr_hash = 1;
++ popts->trwt = 0x3;
++ popts->twrt = 0x3;
++ popts->trrt = 0x3;
++ popts->twwt = 0x3;
++ popts->vref_phy = U(0x5D); /* 72% */
++ popts->odt = 60U;
++ popts->phy_tx_impedance = 28U;
++
++ return 0;
++}
++
++#ifdef NXP_WARM_BOOT
++long long init_ddr(uint32_t wrm_bt_flg)
++#else
++long long init_ddr(void)
++#endif
++{
++ int spd_addr[] = { 0x51 };
++ struct ddr_info info;
++ struct sysinfo sys;
++ long long dram_size;
++
++ zeromem(&sys, sizeof(sys));
++ if (get_clocks(&sys) != 0) {
++ ERROR("System clocks are not set\n");
++ panic();
++ }
++ debug("platform clock %lu\n", sys.freq_platform);
++ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
++ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
++
++ zeromem(&info, sizeof(info));
++
++ /* Set two DDRC. Unused DDRC will be removed automatically. */
++ info.num_ctlrs = NUM_OF_DDRC;
++ info.spd_addr = spd_addr;
++ info.ddr[0] = (void *)NXP_DDR_ADDR;
++ info.ddr[1] = (void *)NXP_DDR2_ADDR;
++ info.phy[0] = (void *)NXP_DDR_PHY1_ADDR;
++ info.phy[1] = (void *)NXP_DDR_PHY2_ADDR;
++ info.clk = get_ddr_freq(&sys, 0);
++ info.img_loadr = load_img;
++ info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER;
++ if (info.clk == 0) {
++ info.clk = get_ddr_freq(&sys, 1);
++ }
++ info.dimm_on_ctlr = DDRC_NUM_DIMM;
++
++ info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED;
++
++ dram_size = dram_init(&info
++#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
++ , NXP_CCN_HN_F_0_ADDR
++#endif
++ );
++
++
++ if (dram_size < 0) {
++ ERROR("DDR init failed.\n");
++ }
++
++ return dram_size;
++}
+diff --git a/plat/nxp/soc-lx2160a/lx2162asom/plat_def.h b/plat/nxp/soc-lx2160a/lx2162asom/plat_def.h
+new file mode 100644
+index 000000000..de2d2444a
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2162asom/plat_def.h
+@@ -0,0 +1,105 @@
++/*
++ * Copyright 2018-2021 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef PLAT_DEF_H
++#define PLAT_DEF_H
++
++#include <arch.h>
++#include <cortex_a72.h>
++/* Required without TBBR.
++ * To include the defines for DDR PHY
++ * Images.
++ */
++#include <tbbr_img_def.h>
++
++#include <policy.h>
++#include <soc.h>
++
++#if defined(IMAGE_BL31)
++#define LS_SYS_TIMCTL_BASE 0x2890000
++#define PLAT_LS_NSTIMER_FRAME_ID 0
++#define LS_CONFIG_CNTACR 1
++#endif
++
++#define NXP_SYSCLK_FREQ 100000000
++#define NXP_DDRCLK_FREQ 100000000
++
++/* UART related definition */
++#define NXP_CONSOLE_ADDR NXP_UART_ADDR
++#define NXP_CONSOLE_BAUDRATE 115200
++
++/* Size of cacheable stacks */
++#if defined(IMAGE_BL2)
++#if defined(TRUSTED_BOARD_BOOT)
++#define PLATFORM_STACK_SIZE 0x2000
++#else
++#define PLATFORM_STACK_SIZE 0x1000
++#endif
++#elif defined(IMAGE_BL31)
++#define PLATFORM_STACK_SIZE 0x1000
++#endif
++
++/* SD block buffer */
++#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
++#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
++ - NXP_SD_BLOCK_BUF_SIZE)
++
++#ifdef SD_BOOT
++#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
++ - NXP_SD_BLOCK_BUF_SIZE)
++#else
++#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
++#endif
++
++/* IO defines as needed by IO driver framework */
++#define MAX_IO_DEVICES 4
++#define MAX_IO_BLOCK_DEVICES 1
++#define MAX_IO_HANDLES 4
++
++#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ)
++
++/*
++ * FIP image defines - Offset at which FIP Image would be present
++ * Image would include Bl31 , Bl33 and Bl32 (optional)
++ */
++#ifdef POLICY_FUSE_PROVISION
++#define MAX_FIP_DEVICES 3
++#endif
++
++#ifndef MAX_FIP_DEVICES
++#define MAX_FIP_DEVICES 2
++#endif
++
++/*
++ * ID of the secure physical generic timer interrupt used by the BL32.
++ */
++#define BL32_IRQ_SEC_PHY_TIMER 29
++
++#define BL31_WDOG_SEC 89
++
++#define BL31_NS_WDOG_WS1 108
++
++/*
++ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
++ * terminology. On a GICv2 system or mode, the lists will be merged and treated
++ * as Group 0 interrupts.
++ */
++#define PLAT_LS_G1S_IRQ_PROPS(grp) \
++ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE)
++
++/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
++#define NXP_IRQ_SEC_SGI_7 15
++
++#define PLAT_LS_G0_IRQ_PROPS(grp) \
++ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE), \
++ INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_EDGE), \
++ INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
++ GIC_INTR_CFG_LEVEL)
++#endif
+diff --git a/plat/nxp/soc-lx2160a/lx2162asom/platform.c b/plat/nxp/soc-lx2160a/lx2162asom/platform.c
+new file mode 100644
+index 000000000..7622cf09a
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2162asom/platform.c
+@@ -0,0 +1,29 @@
++/*
++ * Copyright 2020 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include <plat_common.h>
++
++#pragma weak board_enable_povdd
++#pragma weak board_disable_povdd
++
++bool board_enable_povdd(void)
++{
++#ifdef CONFIG_POVDD_ENABLE
++ return true;
++#else
++ return false;
++#endif
++}
++
++bool board_disable_povdd(void)
++{
++#ifdef CONFIG_POVDD_ENABLE
++ return true;
++#else
++ return false;
++#endif
++}
+diff --git a/plat/nxp/soc-lx2160a/lx2162asom/platform.mk b/plat/nxp/soc-lx2160a/lx2162asom/platform.mk
+new file mode 100644
+index 000000000..c1ba077e9
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2162asom/platform.mk
+@@ -0,0 +1,61 @@
++#
++# Copyright 2018-2020 NXP
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++
++# board-specific build parameters
++
++BOOT_MODE ?= flexspi_nor
++BOARD ?= lx2162asom
++POVDD_ENABLE := no
++NXP_COINED_BB := no
++
++ # DDR Compilation Configs
++NUM_OF_DDRC := 1
++DDRC_NUM_DIMM := 1
++DDRC_NUM_CS := 2
++DDR_ECC_EN := yes
++ #enable address decoding feature
++DDR_ADDR_DEC := yes
++APPLY_MAX_CDD := yes
++
++# Mock SPD:
++# - 0: disable mock spd
++# - 1: 9 x K4A8G085WC-BCWE SoM v1.1 8GB w/ ECC
++# - 2: 9 x K4AAG085WA-BCWE SoM v1.1 16GB w/ ECC
++CONFIG_DDR_NODIMM := 0
++
++# I2C Bus Flushing: IIC1 (SPD EEPROM)
++LX2160_FLUSH_IIC := 1,
++
++# DDR Errata
++ERRATA_DDR_A011396 := 1
++ERRATA_DDR_A050450 := 1
++
++# On-Board Flash Details
++FLASH_TYPE := MT35XU512A
++XSPI_FLASH_SZ := 0x10000000
++NXP_XSPI_NOR_UNIT_SIZE := 0x20000
++BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000
++# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This
++# config is enabled for future use cases.
++FSPI_ERASE_4K := 0
++
++# Platform specific features.
++WARM_BOOT := no
++
++# Adding Platform files build files
++BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
++ ${BOARD_PATH}/platform.c
++
++SUPPORTED_BOOT_MODE := flexspi_nor \
++ sd \
++ emmc \
++ auto
++
++# Adding platform board build info
++include plat/nxp/common/plat_make_helper/plat_common_def.mk
++
++# Adding SoC build info
++include plat/nxp/soc-lx2160a/soc.mk
+diff --git a/plat/nxp/soc-lx2160a/lx2162asom/platform_def.h b/plat/nxp/soc-lx2160a/lx2162asom/platform_def.h
+new file mode 100644
+index 000000000..5fa774e90
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2162asom/platform_def.h
+@@ -0,0 +1,14 @@
++/*
++ * Copyright 2018-2020 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef PLATFORM_DEF_H
++#define PLATFORM_DEF_H
++
++#include "plat_def.h"
++#include "plat_default_def.h"
++
++#endif
+diff --git a/plat/nxp/soc-lx2160a/lx2162asom/policy.h b/plat/nxp/soc-lx2160a/lx2162asom/policy.h
+new file mode 100644
+index 000000000..1095f3840
+--- /dev/null
++++ b/plat/nxp/soc-lx2160a/lx2162asom/policy.h
+@@ -0,0 +1,38 @@
++/*
++ * Copyright 2018-2020 NXP
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef POLICY_H
++#define POLICY_H
++
++/* Following defines affect the PLATFORM SECURITY POLICY */
++
++/* set this to 0x0 if the platform is not using/responding to ECC errors
++ * set this to 0x1 if ECC is being used (we have to do some init)
++ */
++#define POLICY_USING_ECC 0x0
++
++/* Set this to 0x0 to leave the default SMMU page size in sACR
++ * Set this to 0x1 to change the SMMU page size to 64K
++ */
++#define POLICY_SMMU_PAGESZ_64K 0x1
++
++/*
++ * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I
++ * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7
++ * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23
++ */
++#define POLICY_PERF_WRIOP 0
++
++/*
++ * set this to '1' if the debug clocks need to remain enabled during
++ * system entry to low-power (LPM20) - this should only be necessary
++ * for testing and NEVER set for normal production
++ */
++#define POLICY_DEBUG_ENABLE 0
++
++
++#endif /* POLICY_H */
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,127 @@
+From 319f6d2f0cbbb54ac56926683c5e0dfefe984e64 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Sun, 24 Nov 2024 12:38:17 +0100
+Subject: [PATCH] lx2160acex6: add ddr configuration for pcb v1.2 with ecc
+
+Tune DDR Configuration for v1.1 PCB with MIcron memory, and v1.2 PCB
+resolving ECC issues.
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c | 42 +++++++++++++-------
+ plat/nxp/soc-lx2160a/lx2160acex6/platform.mk | 3 +-
+ 2 files changed, 29 insertions(+), 16 deletions(-)
+
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+index 0b978e298..61acfd7ac 100644
+--- a/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+@@ -31,21 +31,29 @@
+ #error Not implemented.
+ #endif /* CONFIG_DDR_NODIMM == 1 */
+
+-#if CONFIG_DDR_NODIMM == 2
++#if CONFIG_DDR_NODIMM == 2 || CONFIG_DDR_NODIMM == 3
+ /*
+- * PCB Revision 1.1: 2 x 5 x K4A8G165WB-BCRC
+- *
+- * ECC disabled because of training failures.
++ * PCB Revision 1.1/1.2: 2 x 5 x MT40A1G16TB-062E IT:F
+ */
+ #define CONFIG_DDR_NODIMM_CH2
++
++#if CONFIG_DDR_NODIMM == 3
++/* PCB Revision 1.2 supports ECC */
++#define CONFIG_DDR_NODIMM_ECC
++#endif /* CONFIG_DDR_NODIMM == 3 */
++
+ static const struct dimm_params static_dimm = {
+- .mpart = "Fixed DDR Config 2",
++ .mpart = "Fixed DDR Config " __XSTRING(CONFIG_DDR_NODIMM),
+ .n_ranks = 1,
+ .die_density = 0x6, // encoded per spd byte 4, 0b110 = 16Gbit
+- .rank_density = 0x200000000, // 16GB
+- .capacity = 0x200000000, // 16GB
++ .rank_density = 0x200000000, // 16Gbit
++ .capacity = 0x200000000, // 16Gbit
+ .primary_sdram_width = 64,
++#ifdef CONFIG_DDR_NODIMM_ECC
++ .ec_sdram_width = 8, // 8 bit ecc extension
++#else
+ .ec_sdram_width = 0, // no ecc extension
++#endif
+ .rdimm = 0,
+ .package_3ds = 0,
+ .device_width = 16, // 16 bit per sdram
+@@ -53,26 +61,30 @@ static const struct dimm_params static_dimm = {
+
+ .n_row_addr = 17,
+ .n_col_addr = 10,
++#ifdef CONFIG_DDR_NODIMM_ECC
++ .edc_config = 2, // enable ecc
++#else
+ .edc_config = 0, // disable ecc
++#endif
+ .bank_addr_bits = 0, // 4 banks
+ .bank_group_bits = 1, // 2 bank groups
+ .burst_lengths_bitmask = 0xc, // enable 4 & 8-bit burst (DDR4 spec)
+
+ .mirrored_dimm = 0,
+
+- // timings based on K4A8G085WC-BCTD (DDR4-2666), missing values for 3200
++ // timings based on MT40A4G4 / MT40A2G8 / MT40A1G16 datasheet (DDR4-3200 22-22-22)
+ .mtb_ps = 125, // MTB per SPD spec
+ .ftb_10th_ps = 10, // default value, unused by nxp ddr driver
+ .taa_ps = 13750, // min. 13.75ns
+- .tfaw_ps = 30000, // min: max(30ns or 28CK) (this 16Gbit sdram has 2KB pages)
++ .tfaw_ps = 30000, // min: max(30ns or 28CK) (this 8Gbit sdram has 2KB pages)
+
+- .tckmin_x_ps = 625, // 3200 (CK=1600)
++ .tckmin_x_ps = 625, // 2400 (CK=1600)
+ .tckmax_ps = 1250, // 1600 (CK=800)
+
+- .caslat_x = 0b00000001010101010101010000000000, // CL = [10,12,14,16,18,20,22,24] (1 << CL)
++ .caslat_x = 0b00000001011111111111110000000000, // CL = [10-22,24] (1 << CL)
+
+- .trcd_ps = 13750, // 13.75ns - CL22-22-22
+- .trp_ps = 13750, // 13.75ns - CL22-22-22
++ .trcd_ps = 13750, // 13.75ns
++ .trp_ps = 13750, // 13.75ns
+ .tras_ps = 32000, // 32ns
+
+ .trfc1_ps = 350000, // 350ns,
+@@ -100,7 +112,7 @@ static const struct dimm_params static_dimm = {
+ 0x00,
+ 0x20,
+ 0x00,
+- 0x00,
++ 0x02,
+ 0x00,
+ 0x20,
+ 0x00,
+@@ -112,7 +124,7 @@ static const struct dimm_params static_dimm = {
+ },
+ .dq_mapping_ors = 1,
+ };
+-#endif /* CONFIG_DDR_NODIMM == 2 */
++#endif /* CONFIG_DDR_NODIMM == 2 || CONFIG_DDR_NODIMM == 3 */
+
+ int ddr_get_ddr_params(struct dimm_params *pdimm,
+ struct ddr_conf *conf)
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk b/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+index 950207878..d01a41ea6 100644
+--- a/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/platform.mk
+@@ -22,7 +22,8 @@ APPLY_MAX_CDD := yes
+
+ # Mock SPD:
+ # - 0: disable mock spd
+-# - 2: 2 x 5 x K4A8G165WB-BCRC PCB v1.1
++# - 2: 2 x 5 x MT40A1G16TB-062E IT:F PCB v1.1
++# - 3: 2 x 5 x MT40A1G16TB-062E IT:F PCB v1.2 (with ECC)
+ CONFIG_DDR_NODIMM := 0
+
+ # S5 GPIO
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,83 @@
+From 0591394c1257b79d9d49016476325533c1c2a14a Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Thu, 26 Sep 2024 16:35:40 +0200
+Subject: [PATCH 16/17] nxp: ddr: add debug output for dimm parameters parsed
+ from spd or static
+
+Add debug prints for all members of struct dimm_params, after either
+parsing of SPD - or from static (no-dimm) configuration.
+
+This enables comparison of parameters derived from SPD with static
+configuration.
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ drivers/nxp/ddr/nxp-ddr/ddr.c | 52 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/drivers/nxp/ddr/nxp-ddr/ddr.c b/drivers/nxp/ddr/nxp-ddr/ddr.c
+index c051b3b25..91a6ef5dc 100644
+--- a/drivers/nxp/ddr/nxp-ddr/ddr.c
++++ b/drivers/nxp/ddr/nxp-ddr/ddr.c
+@@ -616,6 +616,58 @@ static int parse_spd(struct ddr_info *priv)
+ /* now we have valid and identical DIMMs on controllers */
+ #endif /* CONFIG_DDR_NODIMM */
+
++ debug("DIMM: n_ranks = %u\n", dimm->n_ranks);
++ debug("DIMM: die_density = %u\n", dimm->die_density);
++ debug("DIMM: rank_density = %llu\n", dimm->rank_density);
++ debug("DIMM: capacity = %llu\n", dimm->capacity);
++ debug("DIMM: primary_sdram_width = %u\n", dimm->primary_sdram_width);
++ debug("DIMM: ec_sdram_width = %u\n", dimm->ec_sdram_width);
++ debug("DIMM: rdimm = %u\n", dimm->rdimm);
++ debug("DIMM: package_3ds = %u\n", dimm->package_3ds);
++ debug("DIMM: device_width = %u\n", dimm->device_width);
++ debug("DIMM: rc = %u\n", dimm->rc);
++
++ debug("DIMM: n_row_addr = %u\n", dimm->n_row_addr);
++ debug("DIMM: n_col_addr = %u\n", dimm->n_col_addr);
++ debug("DIMM: edc_config = %u\n", dimm->edc_config);
++ debug("DIMM: bank_addr_bits = %u\n", dimm->bank_addr_bits);
++ debug("DIMM: bank_group_bits = %u\n", dimm->bank_group_bits);
++ debug("DIMM: burst_lengths_bitmask = %u\n", dimm->burst_lengths_bitmask);
++
++ debug("DIMM: mirrored_dimm = %u\n", dimm->mirrored_dimm);
++
++ debug("DIMM: mtb_ps = %d\n", dimm->mtb_ps);
++ debug("DIMM: ftb_10th_ps = %d\n", dimm->ftb_10th_ps);
++ debug("DIMM: taa_ps = %d\n", dimm->taa_ps);
++ debug("DIMM: tfaw_ps = %d\n", dimm->tfaw_ps);
++
++ debug("DIMM: tckmin_x_ps = %d\n", dimm->tckmin_x_ps);
++ debug("DIMM: tckmax_ps = %d\n", dimm->tckmax_ps);
++
++ debug("DIMM: caslat_x = %u\n", dimm->caslat_x);
++
++ debug("DIMM: trcd_ps = %d\n", dimm->trcd_ps);
++ debug("DIMM: trp_ps = %d\n", dimm->trp_ps);
++ debug("DIMM: tras_ps = %d\n", dimm->tras_ps);
++
++ debug("DIMM: trfc1_ps = %d\n", dimm->trfc1_ps);
++ debug("DIMM: trfc2_ps = %d\n", dimm->trfc2_ps);
++ debug("DIMM: trfc4_ps = %d\n", dimm->trfc4_ps);
++ debug("DIMM: trrds_ps = %d\n", dimm->trrds_ps);
++ debug("DIMM: trrdl_ps = %d\n", dimm->trrdl_ps);
++ debug("DIMM: tccdl_ps = %d\n", dimm->tccdl_ps);
++ debug("DIMM: trfc_slr_ps = %d\n", dimm->trfc_slr_ps);
++
++ debug("DIMM: trc_ps = %d\n", dimm->trc_ps);
++ debug("DIMM: twr_ps = %d\n", dimm->twr_ps);
++
++ debug("DIMM: refresh_rate_ps = %u\n", dimm->refresh_rate_ps);
++ debug("DIMM: extended_op_srt = %u\n", dimm->extended_op_srt);
++
++ debug("DIMM: rcw = [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u]\n", (unsigned int)dimm->rcw[0], (unsigned int)dimm->rcw[1], (unsigned int)dimm->rcw[2], (unsigned int)dimm->rcw[3], (unsigned int)dimm->rcw[4], (unsigned int)dimm->rcw[5], (unsigned int)dimm->rcw[6], (unsigned int)dimm->rcw[7], (unsigned int)dimm->rcw[8], (unsigned int)dimm->rcw[9], (unsigned int)dimm->rcw[10], (unsigned int)dimm->rcw[11], (unsigned int)dimm->rcw[12], (unsigned int)dimm->rcw[13], (unsigned int)dimm->rcw[14], (unsigned int)dimm->rcw[15]);
++ debug("DIMM: dq_mapping = [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u]\n", dimm->dq_mapping[0], dimm->dq_mapping[1], dimm->dq_mapping[2], dimm->dq_mapping[3], dimm->dq_mapping[4], dimm->dq_mapping[5], dimm->dq_mapping[6], dimm->dq_mapping[7], dimm->dq_mapping[8], dimm->dq_mapping[9], dimm->dq_mapping[10], dimm->dq_mapping[11], dimm->dq_mapping[12], dimm->dq_mapping[13], dimm->dq_mapping[14], dimm->dq_mapping[15], dimm->dq_mapping[16], dimm->dq_mapping[17]);
++ debug("DIMM: dq_mapping_ors = %u\n", dimm->dq_mapping_ors);
++
+ debug("cal cs\n");
+ conf->cs_in_use = 0;
+ for (j = 0; j < DDRC_NUM_DIMM; j++) {
+--
+2.43.0
+
new file mode 100644
@@ -0,0 +1,36 @@
+From 65eaf1b55184950c67cb07156477418e93fa9351 Mon Sep 17 00:00:00 2001
+From: Josua Mayer <josua@solid-run.com>
+Date: Tue, 26 Nov 2024 14:37:27 +0100
+Subject: [PATCH 17/17] lx2160acex6: fix dq mapping and remove invalid spd
+ eeprom addresses
+
+Signed-off-by: Josua Mayer <josua@solid-run.com>
+---
+ plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+index 61acfd7ac..95c0a13cf 100644
+--- a/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
++++ b/plat/nxp/soc-lx2160a/lx2160acex6/ddr_init.c
+@@ -112,7 +112,7 @@ static const struct dimm_params static_dimm = {
+ 0x00,
+ 0x20,
+ 0x00,
+- 0x02,
++ 0x20,
+ 0x00,
+ 0x20,
+ 0x00,
+@@ -200,7 +200,7 @@ int ddr_board_options(struct ddr_info *priv)
+
+ long long init_ddr(void)
+ {
+- int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 };
++ int spd_addr[] = { 0x51, 0x00, 0x53, 0x00 };
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+--
+2.43.0
+
new file mode 120000
@@ -0,0 +1 @@
+../../../../freescale/common/patches/arm-trusted-firmware/0001-feat-build-add-support-for-new-binutils-versions.patch
\ No newline at end of file
These come straight from https://github.com/SolidRun/lx2160a_build/, commit 497e9ebf0e2a ("atf: update sdram configuration for internal cex6 evb revision 1.2"), and are unmodified. I've also symlinked the extra patch at board/freescale/common/patches/arm-trusted-firmware/0001-feat-build-add-support-for-new-binutils-versions.patch to avoid this warning treated as error: $(HOSTDIR)/bin/aarch64-buildroot-linux-gnu-ld: warning: $(BUILDDIR)/arm-trusted-firmware-custom/build/lx2160acex7/release/bl2/bl2.elf has a LOAD segment with RWX permissions make[2]: *** [Makefile:1240: $(BUILDDIR)/arm-trusted-firmware-custom/build/lx2160acex7/release/bl2/bl2.elf] Error 1 make[2]: *** Waiting for unfinished jobs.... Since commit 7cbc240ac2c3 ("configs/ls1028ardb: update to Linux 6.6"), Layerscape platforms no longer use board/freescale/common/patches, and neither do we, here. But we use an older arm-trusted-firmware tag of lf-5.15.71-2.2.0, so we need to selectively include that one patch. Signed-off-by: Vladimir Oltean <olteanv@gmail.com> --- v1->v2: - split out from previous [PATCH 6/7] board/lx2160acex7: new platform - update to latest lx2160a_build HEAD .../0001-plat-nxp-lx2160a-auto-boot.patch | 219 +++++++ ...ccount-MEM_PLL_CFG_SHIFT-for-ddr-fre.patch | 85 +++ ...sert-SUS_S5-GPIO-to-poweroff-the-COM.patch | 29 + ...assert-IRQ0-GPIO-to-poweroff-the-EVB.patch | 29 + ...ptional-S5-gpio-from-Makefile-consta.patch | 63 ++ ...te-platform-for-solidrun-cex7-module.patch | 418 ++++++++++++ ...flexible-value-for-CONFIG_DDR_NODIMM.patch | 33 + ...tform-for-solidrun-internal-cex6-eva.patch | 544 ++++++++++++++++ ...ort-flushing-i2c-bus-before-ddr-init.patch | 365 +++++++++++ ...h-i2c-bus-with-spd-eeprom-before-ddr.patch | 30 + ...h-i2c-bus-with-spd-eeprom-before-ddr.patch | 30 + ...-building-without-NXP_NV_SW_MAINT_LA.patch | 49 ++ ...-boot-without-spi-flash-disable-non-.patch | 33 + ...te-platform-for-solidrun-lx2162a-som.patch | 597 ++++++++++++++++++ ...ddr-configuration-for-pcb-v1.2-with-.patch | 127 ++++ ...g-output-for-dimm-parameters-parsed-.patch | 83 +++ ...dq-mapping-and-remove-invalid-spd-ee.patch | 36 ++ ...dd-support-for-new-binutils-versions.patch | 1 + 18 files changed, 2771 insertions(+) create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0001-plat-nxp-lx2160a-auto-boot.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0002-dcfg-Take-into-account-MEM_PLL_CFG_SHIFT-for-ddr-fre.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0003-lx2160acex7-assert-SUS_S5-GPIO-to-poweroff-the-COM.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0004-lx2160acex6-assert-IRQ0-GPIO-to-poweroff-the-EVB.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0005-lx2160a-assert-optional-S5-gpio-from-Makefile-consta.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0006-add-separate-platform-for-solidrun-cex7-module.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0007-lx2160a-support-flexible-value-for-CONFIG_DDR_NODIMM.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0008-add-separate-platform-for-solidrun-internal-cex6-eva.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0009-lx2160a-support-flushing-i2c-bus-before-ddr-init.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0010-lx2160acex6-flush-i2c-bus-with-spd-eeprom-before-ddr.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0011-lx2160acex7-flush-i2c-bus-with-spd-eeprom-before-ddr.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0012-plat-lx2160a-fix-building-without-NXP_NV_SW_MAINT_LA.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0013-plat-lx2160a-fix-boot-without-spi-flash-disable-non-.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0014-add-separate-platform-for-solidrun-lx2162a-som.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0015-lx2160acex6-add-ddr-configuration-for-pcb-v1.2-with-.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0016-nxp-ddr-add-debug-output-for-dimm-parameters-parsed-.patch create mode 100644 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0017-lx2160acex6-fix-dq-mapping-and-remove-invalid-spd-ee.patch create mode 120000 board/solidrun/lx2160acex7/patches/arm-trusted-firmware/0018-feat-build-add-support-for-new-binutils-versions.patch