Commit 4516ff816084605990115d127df97950c23e389c

Authored by York Sun
1 parent 6b95be2280

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>

Showing 2 changed files with 76 additions and 0 deletions Side-by-side Diff

... ... @@ -4884,6 +4884,9 @@
4884 4884 - CONFIG_FSL_DDR_SYNC_REFRESH
4885 4885 Enable sync of refresh for multiple controllers.
4886 4886  
  4887 +- CONFIG_FSL_DDR_BIST
  4888 + Enable built-in memory test for Freescale DDR controllers.
  4889 +
4887 4890 - CONFIG_SYS_83XX_DDR_USES_CS0
4888 4891 Only for 83xx systems. If specified, then DDR should
4889 4892 be configured using CS0 and CS1 instead of CS2 and CS3.
drivers/ddr/fsl/fsl_ddr_gen4.c
... ... @@ -36,6 +36,13 @@
36 36 defined(CONFIG_SYS_FSL_ERRATUM_A008514)
37 37 u32 *eddrtqcr1;
38 38 #endif
  39 +#ifdef CONFIG_FSL_DDR_BIST
  40 + u32 mtcr, err_detect, err_sbe;
  41 + u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config;
  42 +#endif
  43 +#ifdef CONFIG_FSL_DDR_BIST
  44 + char buffer[CONFIG_SYS_CBSIZE];
  45 +#endif
39 46  
40 47 switch (ctrl_num) {
41 48 case 0:
... ... @@ -307,6 +314,72 @@
307 314 temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
308 315 temp_sdram_cfg &= ~SDRAM_CFG2_FRC_SR;
309 316 ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
  317 + }
  318 +#endif
  319 +
  320 +#ifdef CONFIG_FSL_DDR_BIST
  321 +#define BIST_PATTERN1 0xFFFFFFFF
  322 +#define BIST_PATTERN2 0x0
  323 +#define BIST_CR 0x80010000
  324 +#define BIST_CR_EN 0x80000000
  325 +#define BIST_CR_STAT 0x00000001
  326 +#define CTLR_INTLV_MASK 0x20000000
  327 + /* Perform build-in test on memory. Three-way interleaving is not yet
  328 + * supported by this code. */
  329 + if (getenv_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) {
  330 + puts("Running BIST test. This will take a while...");
  331 + cs0_config = ddr_in32(&ddr->cs0_config);
  332 + if (cs0_config & CTLR_INTLV_MASK) {
  333 + cs0_bnds = ddr_in32(&cs0_bnds);
  334 + cs1_bnds = ddr_in32(&cs1_bnds);
  335 + cs2_bnds = ddr_in32(&cs2_bnds);
  336 + cs3_bnds = ddr_in32(&cs3_bnds);
  337 + /* set bnds to non-interleaving */
  338 + ddr_out32(&cs0_bnds, (cs0_bnds & 0xfffefffe) >> 1);
  339 + ddr_out32(&cs1_bnds, (cs1_bnds & 0xfffefffe) >> 1);
  340 + ddr_out32(&cs2_bnds, (cs2_bnds & 0xfffefffe) >> 1);
  341 + ddr_out32(&cs3_bnds, (cs3_bnds & 0xfffefffe) >> 1);
  342 + }
  343 + ddr_out32(&ddr->mtp1, BIST_PATTERN1);
  344 + ddr_out32(&ddr->mtp2, BIST_PATTERN1);
  345 + ddr_out32(&ddr->mtp3, BIST_PATTERN2);
  346 + ddr_out32(&ddr->mtp4, BIST_PATTERN2);
  347 + ddr_out32(&ddr->mtp5, BIST_PATTERN1);
  348 + ddr_out32(&ddr->mtp6, BIST_PATTERN1);
  349 + ddr_out32(&ddr->mtp7, BIST_PATTERN2);
  350 + ddr_out32(&ddr->mtp8, BIST_PATTERN2);
  351 + ddr_out32(&ddr->mtp9, BIST_PATTERN1);
  352 + ddr_out32(&ddr->mtp10, BIST_PATTERN2);
  353 + mtcr = BIST_CR;
  354 + ddr_out32(&ddr->mtcr, mtcr);
  355 + timeout = 100;
  356 + while (timeout > 0 && (mtcr & BIST_CR_EN)) {
  357 + mdelay(1000);
  358 + timeout--;
  359 + mtcr = ddr_in32(&ddr->mtcr);
  360 + }
  361 + if (timeout <= 0)
  362 + puts("Timeout\n");
  363 + else
  364 + puts("Done\n");
  365 + err_detect = ddr_in32(&ddr->err_detect);
  366 + err_sbe = ddr_in32(&ddr->err_sbe);
  367 + if (mtcr & BIST_CR_STAT) {
  368 + printf("BIST test failed on controller %d.\n",
  369 + ctrl_num);
  370 + }
  371 + if (err_detect || (err_sbe & 0xffff)) {
  372 + printf("ECC error detected on controller %d.\n",
  373 + ctrl_num);
  374 + }
  375 +
  376 + if (cs0_config & CTLR_INTLV_MASK) {
  377 + /* restore bnds registers */
  378 + ddr_out32(&cs0_bnds, cs0_bnds);
  379 + ddr_out32(&cs1_bnds, cs1_bnds);
  380 + ddr_out32(&cs2_bnds, cs2_bnds);
  381 + ddr_out32(&cs3_bnds, cs3_bnds);
  382 + }
310 383 }
311 384 #endif
312 385 }