📄 4xx_ibm_ddr2_autocalib.c
字号:
curr_win_min = curr_win_max = 0; best_win_min = best_win_max = 0; for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { mfsdram(SDRAM_RQDC, rqdc_reg); rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); pass = 1; for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); /* Banks enabled */ if (bxcf & SDRAM_BXCF_M_BE_MASK) { /* Bank is enabled */ membase = get_membase(bxcr_num); pass &= short_mem_test(membase); } /* if bank enabled */ } /* for bxcf_num */ /* If this value passed */ if (pass && !in_window) { in_window = 1; curr_win_min = curr_win_max = rqfd; } else if (!pass && in_window) { in_window = 0; } else if (pass && in_window) { curr_win_max = rqfd; } if (in_window) { if ((curr_win_max - curr_win_min) > (best_win_max - best_win_min)) { best_win_min = curr_win_min; best_win_max = curr_win_max; } passed = 1; } } /* for rqfd */ if ((best_win_min == 0) && (best_win_max == 0)) passed = 0; debug("RQFD Min: 0x%x\n", best_win_min); debug("RQFD Max: 0x%x\n", best_win_max); rqfd_average = ((best_win_min + best_win_max) / 2); if (rqfd_average < 0) rqfd_average = 0; if (rqfd_average > SDRAM_RQDC_RQFD_MAX) rqfd_average = SDRAM_RQDC_RQFD_MAX; mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); mfsdram(SDRAM_RQDC, rqdc_reg); mfsdram(SDRAM_RFDC, rfdc_reg); /* * Need to program RQDC before RFDC. The value is read above. * That is the reason why auto cal not work. * See, comments below. */ mtsdram(SDRAM_RQDC, rqdc_reg); mtsdram(SDRAM_RFDC, rfdc_reg); debug("RQDC: 0x%08X\n", rqdc_reg); debug("RFDC: 0x%08X\n", rfdc_reg); /* if something passed, then return the size of the largest window */ if (passed != 0) { passed = size; cal->rqfd = rqfd_average; cal->rffd = rffd_average; } return (uint)passed;}#endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) *//* * Default table for DDR auto-calibration of all * possible WRDTR and CLKTR values. * Table format is: * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} * * Table is terminated with {-1, -1} value pair. * * Board vendors can specify their own board specific subset of * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value * pairs via a board defined ddr_scan_option() function. */struct sdram_timing full_scan_options[] = { {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {2, 0}, {2, 1}, {2, 2}, {2, 3}, {3, 0}, {3, 1}, {3, 2}, {3, 3}, {4, 0}, {4, 1}, {4, 2}, {4, 3}, {5, 0}, {5, 1}, {5, 2}, {5, 3}, {6, 0}, {6, 1}, {6, 2}, {6, 3}, {-1, -1}};/*---------------------------------------------------------------------------+| DQS_calibration.+----------------------------------------------------------------------------*/u32 DQS_autocalibration(void){ u32 wdtr; u32 clkp; u32 result = 0; u32 best_result = 0; u32 best_rdcc; struct ddrautocal ddrcal; struct autocal_clks tcal; ulong rfdc_reg; ulong rqdc_reg; u32 val; int verbose_lvl = 0; char *str; char slash[] = "\\|/-\\|/-"; int loopi = 0; struct sdram_timing *scan_list;#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION) int i; char tmp[64]; /* long enough for environment variables */#endif memset(&tcal, 0, sizeof(tcal)); ddr_scan_option((ulong)full_scan_options); scan_list = (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options); mfsdram(SDRAM_MCOPT1, val); if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP) str = "ECC Auto calibration -"; else str = "Auto calibration -"; puts(str);#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION) i = getenv_r("autocalib", tmp, sizeof(tmp)); if (i < 0) strcpy(tmp, CONFIG_AUTOCALIB); if (strcmp(tmp, "final") == 0) { /* display the final autocalibration results only */ verbose_lvl = 1; } else if (strcmp(tmp, "loop") == 0) { /* display summary autocalibration info per iteration */ verbose_lvl = 2; } else if (strcmp(tmp, "display") == 0) { /* display full debug autocalibration window info. */ verbose_lvl = 3; }#endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */ best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30); while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) { wdtr = scan_list->wrdtr; clkp = scan_list->clktr; mfsdram(SDRAM_WRDTR, val); val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK); mtsdram(SDRAM_WRDTR, (val | ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25)))); mtsdram(SDRAM_CLKTR, clkp << 30); relock_memory_DLL(); putc('\b'); putc(slash[loopi++ % 8]);#ifdef DEBUG debug("\n"); debug("*** --------------\n"); mfsdram(SDRAM_WRDTR, val); debug("*** SDRAM_WRDTR set to 0x%08x\n", val); mfsdram(SDRAM_CLKTR, val); debug("*** SDRAM_CLKTR set to 0x%08x\n", val);#endif debug("\n"); if (verbose_lvl > 2) { printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr); printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp); } memset(&ddrcal, 0, sizeof(ddrcal)); /* * DQS calibration. */ /* * program_DQS_calibration_method[A|B]() returns 0 if no * passing RFDC.[RFFD] window is found or returns the size * of the best passing window; in the case of a found passing * window, the ddrcal will contain the values of the best * window RQDC.[RQFD] and RFDC.[RFFD]. */ /* * Call PPC4xx SDRAM DDR autocalibration methodA or methodB. * Default is methodB. * Defined the autocalibration method in the board specific * header file. * Please see include/configs/kilauea.h for an example for * a board specific implementation. */#if defined(CONFIG_PPC4xx_DDR_METHOD_A) result = program_DQS_calibration_methodA(&ddrcal);#else result = program_DQS_calibration_methodB(&ddrcal);#endif sync(); /* * Clear potential errors resulting from auto-calibration. * If not done, then we could get an interrupt later on when * exceptions are enabled. */ set_mcsr(get_mcsr()); val = ddrcal.rdcc; /* RDCC from the best passing window */ udelay(100); if (verbose_lvl > 1) { char *tstr; switch ((val >> 30)) { case 0: if (result != 0) tstr = "T1"; else tstr = "N/A"; break; case 1: tstr = "T2"; break; case 2: tstr = "T3"; break; case 3: tstr = "T4"; break; default: tstr = "unknown"; break; } printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), " "max-min(0x%04x)(0x%04x), RDCC: %s\n", wdtr, clkp, result, best_result, ddrcal.rffd_min, ddrcal.rffd_max, tstr); } /* * The DQS calibration "result" is either "0" * if no passing window was found, or is the * size of the RFFD passing window. */ if (result != 0) { tcal.autocal.flags = 1; debug("*** (%d)(%d) result passed window size: 0x%08x, " "rqfd = 0x%08x, rffd = 0x%08x, rdcc = 0x%08x\n", wdtr, clkp, result, ddrcal.rqfd, ddrcal.rffd, ddrcal.rdcc); /* * Save the SDRAM_WRDTR and SDRAM_CLKTR * settings for the largest returned * RFFD passing window size. */ if (result > best_result) { /* * want the lowest Read Sample Cycle Select */ val = (val & SDRAM_RDCC_RDSS_MASK) >> 30; debug("*** (%d) (%d) current_rdcc, best_rdcc\n", val, best_rdcc); if (val <= best_rdcc) { best_rdcc = val; tcal.clocks.wrdtr = wdtr; tcal.clocks.clktr = clkp; tcal.clocks.rdcc = (val << 30); tcal.autocal.rqfd = ddrcal.rqfd; tcal.autocal.rffd = ddrcal.rffd; best_result = result; if (verbose_lvl > 2) { printf("** (%d)(%d) " "best result: 0x%04x\n", wdtr, clkp, best_result); printf("** (%d)(%d) " "best WRDTR: 0x%04x\n", wdtr, clkp, tcal.clocks.wrdtr); printf("** (%d)(%d) " "best CLKTR: 0x%04x\n", wdtr, clkp, tcal.clocks.clktr); printf("** (%d)(%d) " "best RQDC: 0x%04x\n", wdtr, clkp, tcal.autocal.rqfd); printf("** (%d)(%d) " "best RFDC: 0x%04x\n", wdtr, clkp, tcal.autocal.rffd); printf("** (%d)(%d) " "best RDCC: 0x%08x\n", wdtr, clkp, (u32)tcal.clocks.rdcc); mfsdram(SDRAM_RTSR, val); printf("** (%d)(%d) best " "loop RTSR: 0x%08x\n", wdtr, clkp, val); mfsdram(SDRAM_FCSR, val); printf("** (%d)(%d) best " "loop FCSR: 0x%08x\n", wdtr, clkp, val); } } /* if (val <= best_rdcc) */ } /* if (result >= best_result) */ } /* if (result != 0) */ scan_list++; } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */ if (tcal.autocal.flags == 1) { if (verbose_lvl > 0) { printf("*** --------------\n"); printf("*** best_result window size: %d\n", best_result); printf("*** best_result WRDTR: 0x%04x\n", tcal.clocks.wrdtr); printf("*** best_result CLKTR: 0x%04x\n", tcal.clocks.clktr); printf("*** best_result RQFD: 0x%04x\n", tcal.autocal.rqfd); printf("*** best_result RFFD: 0x%04x\n", tcal.autocal.rffd); printf("*** best_result RDCC: 0x%04x\n", tcal.clocks.rdcc); printf("*** --------------\n"); printf("\n"); } /* * if got best passing result window, then lock in the * best CLKTR, WRDTR, RQFD, and RFFD values */ mfsdram(SDRAM_WRDTR, val); mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) | ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (tcal.clocks.wrdtr << 25))); mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30); relock_memory_DLL(); mfsdram(SDRAM_RQDC, rqdc_reg); rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd)); mfsdram(SDRAM_RQDC, rqdc_reg); debug("*** best_result: read value SDRAM_RQDC 0x%08x\n", rqdc_reg); mfsdram(SDRAM_RFDC, rfdc_reg); rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd)); mfsdram(SDRAM_RFDC, rfdc_reg); debug("*** best_result: read value SDRAM_RFDC 0x%08x\n", rfdc_reg); mfsdram(SDRAM_RDCC, val); debug("*** SDRAM_RDCC 0x%08x\n", val); } else { /* * no valid windows were found */ printf("DQS memory calibration window can not be determined, " "terminating u-boot.\n"); ppc4xx_ibm_ddr2_register_dump(); spd_ddr_init_hang(); } blank_string(strlen(str)); return 0;}#else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */u32 DQS_autocalibration(void){ return 0;}#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */#endif /* defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -