1
0
Fork 0

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>
utp
York Sun 2015-03-19 09:30:28 -07:00
parent 6b95be2280
commit 4516ff8160
2 changed files with 76 additions and 0 deletions

3
README
View File

@ -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.

View File

@ -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
}