driver/ddr/fsl: Add built-in memory test for DDR4 driver
Add built-in memory test to catch errors after DDR is initialized, before any other transactions. To enable this test, define CONFIG_FSL_DDR_BIST. An environmental variable "ddr_bist" is checked before starting test. It takes a while (several seconds) depending on system memory size. Signed-off-by: York Sun <yorksun@freescale.com>
This commit is contained in:
parent
6b95be2280
commit
4516ff8160
3
README
3
README
@ -4884,6 +4884,9 @@ Low Level (hardware related) configuration options:
|
||||
- CONFIG_FSL_DDR_SYNC_REFRESH
|
||||
Enable sync of refresh for multiple controllers.
|
||||
|
||||
- CONFIG_FSL_DDR_BIST
|
||||
Enable built-in memory test for Freescale DDR controllers.
|
||||
|
||||
- CONFIG_SYS_83XX_DDR_USES_CS0
|
||||
Only for 83xx systems. If specified, then DDR should
|
||||
be configured using CS0 and CS1 instead of CS2 and CS3.
|
||||
|
@ -36,6 +36,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
|
||||
defined(CONFIG_SYS_FSL_ERRATUM_A008514)
|
||||
u32 *eddrtqcr1;
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_DDR_BIST
|
||||
u32 mtcr, err_detect, err_sbe;
|
||||
u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config;
|
||||
#endif
|
||||
#ifdef CONFIG_FSL_DDR_BIST
|
||||
char buffer[CONFIG_SYS_CBSIZE];
|
||||
#endif
|
||||
|
||||
switch (ctrl_num) {
|
||||
case 0:
|
||||
@ -309,4 +316,70 @@ step2:
|
||||
ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_DDR_BIST
|
||||
#define BIST_PATTERN1 0xFFFFFFFF
|
||||
#define BIST_PATTERN2 0x0
|
||||
#define BIST_CR 0x80010000
|
||||
#define BIST_CR_EN 0x80000000
|
||||
#define BIST_CR_STAT 0x00000001
|
||||
#define CTLR_INTLV_MASK 0x20000000
|
||||
/* Perform build-in test on memory. Three-way interleaving is not yet
|
||||
* supported by this code. */
|
||||
if (getenv_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) {
|
||||
puts("Running BIST test. This will take a while...");
|
||||
cs0_config = ddr_in32(&ddr->cs0_config);
|
||||
if (cs0_config & CTLR_INTLV_MASK) {
|
||||
cs0_bnds = ddr_in32(&cs0_bnds);
|
||||
cs1_bnds = ddr_in32(&cs1_bnds);
|
||||
cs2_bnds = ddr_in32(&cs2_bnds);
|
||||
cs3_bnds = ddr_in32(&cs3_bnds);
|
||||
/* set bnds to non-interleaving */
|
||||
ddr_out32(&cs0_bnds, (cs0_bnds & 0xfffefffe) >> 1);
|
||||
ddr_out32(&cs1_bnds, (cs1_bnds & 0xfffefffe) >> 1);
|
||||
ddr_out32(&cs2_bnds, (cs2_bnds & 0xfffefffe) >> 1);
|
||||
ddr_out32(&cs3_bnds, (cs3_bnds & 0xfffefffe) >> 1);
|
||||
}
|
||||
ddr_out32(&ddr->mtp1, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp2, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp3, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp4, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp5, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp6, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp7, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp8, BIST_PATTERN2);
|
||||
ddr_out32(&ddr->mtp9, BIST_PATTERN1);
|
||||
ddr_out32(&ddr->mtp10, BIST_PATTERN2);
|
||||
mtcr = BIST_CR;
|
||||
ddr_out32(&ddr->mtcr, mtcr);
|
||||
timeout = 100;
|
||||
while (timeout > 0 && (mtcr & BIST_CR_EN)) {
|
||||
mdelay(1000);
|
||||
timeout--;
|
||||
mtcr = ddr_in32(&ddr->mtcr);
|
||||
}
|
||||
if (timeout <= 0)
|
||||
puts("Timeout\n");
|
||||
else
|
||||
puts("Done\n");
|
||||
err_detect = ddr_in32(&ddr->err_detect);
|
||||
err_sbe = ddr_in32(&ddr->err_sbe);
|
||||
if (mtcr & BIST_CR_STAT) {
|
||||
printf("BIST test failed on controller %d.\n",
|
||||
ctrl_num);
|
||||
}
|
||||
if (err_detect || (err_sbe & 0xffff)) {
|
||||
printf("ECC error detected on controller %d.\n",
|
||||
ctrl_num);
|
||||
}
|
||||
|
||||
if (cs0_config & CTLR_INTLV_MASK) {
|
||||
/* restore bnds registers */
|
||||
ddr_out32(&cs0_bnds, cs0_bnds);
|
||||
ddr_out32(&cs1_bnds, cs1_bnds);
|
||||
ddr_out32(&cs2_bnds, cs2_bnds);
|
||||
ddr_out32(&cs3_bnds, cs3_bnds);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user