I'm performing experiments with LS1046ARDB board. I built ATF & UBoot from scratch from NXP Git code, everything was working OK.
Then I decided to change the DDR4 memory module from original to MTA8ATF1G64AZ-3G2R1(8G,non-ecc,PC4-3200AA-UA2-11).
To make sure I'm doing everything correctly, here's my sequence of actions when trying to run the LS1046 ARDB with a different memory module:
1) Select "SD card" as a RCW source on the ls1046ardb
2) Build the required RCW from the NXP GIT repository (boot from SD, memory speed 2100 MT/S).
3) Write the resulting RCW to the SD card at the correct offset.
4) Run the board.
5) Run QCVS, create a DDR Calibration Project, and select SPD reading.
6) After successfully reading the SPD, run memory validation.
7) After successful validation, I obtain the source files with the DDR controller initialization code for different use scenarios:
- pbi_commands_1.txt - for initialization in PBL
- uboot_ddr1.c - for initialization in uboot
- InitDdrRegisters.c - initialization in a bare-metal application (???)
- ddr_init.c - initialization in ATF (BL2-BL31)
ddr1.h
platform_def1.h
I'm interested in initialization within ATF(at BL2 stage), so I'm using ONLY ddr_init.c, ddr1.h, and platform_def1.h.
Since I'm using a DDR module with SPD reading, I DO NOT define CONFIG_STATIC_DDR. (so const struct ddr_cfg_regs static_2100 is NOT used)
As I understand, from ddr_init.c I only need the following:
static const struct rc_timing rcz[] = { ..... };
static const struct board_timing ram[] = { .... };
int ddr_board_options(struct ddr_info *priv)
{
int ret;
struct memctl_opt *popts = &priv->opt;
if (popts->rdimm) {
debug("RDIMM parameters not set.\n");
return -EINVAL;
}
ret = cal_board_params(priv, ram, ARRAY_SIZE(ram));
if (ret != 0) {
return ret;
}
popts->wrlvl_override = U(1);
popts->wrlvl_sample = U(0x0); /* 32 clocks */
popts->cpo_sample = U(0x61);
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
DDR_CDR2_VREF_TRAIN_EN |
DDR_CDR2_VREF_RANGE_2;
popts->bstopre = U(0);
return 0;
}
long long init_ddr(void) { ... skipped ... }
I transfer this data to ddr_init.c for the ls1046 ardb ATF project(taken from the NXP GIT), change memory type to non-ecc,
then build the ATF.
I upload the resulting bootloader image to the SD card and boot the board with the new bootloader.
9) During boot, the following steps should run: PBL->BL2->BL31->BL33(Uboot).
I expect the successful boot, but in fact I get the following:
NOTICE: BL2: v2.12.0(debug):lf-6.12.34-2.1.0-dirty
NOTICE: BL2: Built : 17:59:52, Feb 13 2026
INFO: Configuring TrustZone Controller
VERBOSE: TrustZone : Configuring region 0 (TZC Interface Base=0x1500000 sec_attr=0x0, ns_devs=0x0)
VERBOSE: TrustZone : Configuring region (TZC Interface Base: 0x1500000, region_no = 1)...
VERBOSE: TrustZone : ... base = fbe00000, top = ffdfffff,
VERBOSE: TrustZone : ... sec_attr = 0x3, ns_devs = 0x0)
VERBOSE: TrustZone : Configuring region (TZC Interface Base: 0x1500000, region_no = 2)...
VERBOSE: TrustZone : ... base = ffe00000, top = ffffffff,
VERBOSE: TrustZone : ... sec_attr = 0x3, ns_devs = 0xffffffff)
VERBOSE: TrustZone : Configuring region (TZC Interface Base: 0x1500000, region_no = 3)...
VERBOSE: TrustZone : ... base = 80000000, top = fbdfffff,
VERBOSE: TrustZone : ... sec_attr = 0x3, ns_devs = 0xffffffff)
VERBOSE: TrustZone : Configuring region (TZC Interface Base: 0x1500000, region_no = 4)...
VERBOSE: TrustZone : ... base = 880000000, top = bffffffff,
VERBOSE: TrustZone : ... sec_attr = 0x3, ns_devs = 0xffffffff)
INFO: BL2: Doing platform setup
INFO: BL2: Loading image id 3
VERBOSE: FIP header looks OK.
VERBOSE: Using FIP
INFO: Loading image id=3 at address 0xfbe00000
I repeat all the steps with original ardb memory module and finally get a successful boot, everything works just fine.
So what can be the problem? Why does the board only work with the original module and not with a non-original one, even if calibration with the non-original module was successful?