2 * cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
3 * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
4 * DDR2 controller (non Denali Core). Those currently are:
7 * 440/460: 440SP/440SPe/460EX/460GT/460SX
9 * (C) Copyright 2008 Applied Micro Circuits Corporation
10 * Adam Graham <agraham@amcc.com>
12 * (C) Copyright 2007-2008
13 * Stefan Roese, DENX Software Engineering, sr@denx.de.
15 * COPYRIGHT AMCC CORPORATION 2004
17 * See file CREDITS for list of people who contributed to this
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License as
22 * published by the Free Software Foundation; either version 2 of
23 * the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
37 /* define DEBUG for debugging output (obviously ;-)) */
43 #include <asm/processor.h>
45 #if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
48 * Only compile the DDR auto-calibration code for NOR boot and
49 * not for NAND boot (NAND SPL and NAND U-Boot - NUB)
51 #if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
54 #define SDRAM_RXBAS_SHIFT_1M 20
56 #if defined(CFG_DECREMENT_PATTERNS)
57 #define NUMMEMTESTS 24
60 #endif /* CFG_DECREMENT_PATTERNS */
61 #define NUMLOOPS 1 /* configure as you deem approporiate */
62 #define NUMMEMWORDS 16
64 /* Private Structure Definitions */
82 struct sdram_timing_clks {
90 struct sdram_timing_clks clocks;
91 struct ddrautocal autocal;
94 /*--------------------------------------------------------------------------+
96 *--------------------------------------------------------------------------*/
97 #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
98 static u32 DQS_calibration_methodA(struct ddrautocal *);
99 static u32 program_DQS_calibration_methodA(struct ddrautocal *);
101 static u32 DQS_calibration_methodB(struct ddrautocal *);
102 static u32 program_DQS_calibration_methodB(struct ddrautocal *);
104 static int short_mem_test(u32 *);
107 * To provide an interface for board specific config values in this common
108 * DDR setup code, we implement he "weak" default functions here. They return
109 * the default value back to the caller.
111 * Please see include/configs/yucca.h for an example fora board specific
115 #if !defined(CONFIG_SPD_EEPROM)
116 u32 __ddr_wrdtr(u32 default_val)
120 u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
122 u32 __ddr_clktr(u32 default_val)
126 u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
129 * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
131 void __spd_ddr_init_hang(void)
136 spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
137 #endif /* defined(CONFIG_SPD_EEPROM) */
139 ulong __ddr_scan_option(ulong default_val)
143 ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option")));
145 static u32 *get_membase(int bxcr_num)
150 #if defined(SDRAM_R0BAS)
151 /* BAS from Memory Queue rank reg. */
153 (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
154 bxcf = 0; /* just to satisfy the compiler */
156 /* BAS from SDRAM_MBxCF mem rank reg. */
157 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
158 membase = (u32 *)((bxcf & 0xfff80000) << 3);
164 static inline void ecc_clear_status_reg(void)
166 mtsdram(SDRAM_ECCCR, 0xffffffff);
167 #if defined(SDRAM_R0BAS)
168 mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
172 static int ecc_check_status_reg(void)
177 * Compare suceeded, now check
178 * if got ecc error. If got an
179 * ecc error, then don't count
180 * this as a passing value
182 mfsdram(SDRAM_ECCCR, ecc_status);
183 if (ecc_status != 0x00000000) {
185 ecc_clear_status_reg();
186 /* ecc check failure */
189 ecc_clear_status_reg();
195 /* return 1 if passes, 0 if fail */
196 static int short_mem_test(u32 *base_address)
201 ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
202 /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
203 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
204 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
205 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
206 /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
207 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
208 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
209 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
210 /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
211 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
212 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
213 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
214 /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
215 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
216 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
217 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
218 /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
219 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
220 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
221 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
222 /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
223 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
224 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
225 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
226 /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
227 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
228 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
229 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
230 /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
231 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
232 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
233 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
235 #if defined(CFG_DECREMENT_PATTERNS)
236 /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
237 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
238 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
239 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
240 /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
241 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
242 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
243 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
244 /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
245 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
246 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
247 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
248 /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
249 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
250 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
251 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
252 /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
253 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
254 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
255 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
256 /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
257 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
258 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
259 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
260 /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
261 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
262 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
263 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
264 /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
265 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
266 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
267 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
268 /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
269 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
270 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
271 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
272 /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
273 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
274 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
275 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
276 /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
277 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
278 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
279 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
280 /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
281 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
282 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
283 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
284 /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
285 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
286 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
287 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
288 /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
289 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
290 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
291 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
292 /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
293 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
294 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
295 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
296 /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
297 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
298 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
299 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
300 #endif /* CFG_DECREMENT_PATTERNS */
303 mfsdram(SDRAM_MCOPT1, ecc_mode);
304 if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
305 SDRAM_MCOPT1_MCHK_CHK_REP) {
306 ecc_clear_status_reg();
314 * Run the short memory test.
316 for (i = 0; i < NUMMEMTESTS; i++) {
317 for (j = 0; j < NUMMEMWORDS; j++) {
318 base_address[j] = test[i][j];
319 ppcDcbf((ulong)&(base_address[j]));
322 for (l = 0; l < NUMLOOPS; l++) {
323 for (j = 0; j < NUMMEMWORDS; j++) {
324 if (base_address[j] != test[i][j]) {
325 ppcDcbf((u32)&(base_address[j]));
329 if (!ecc_check_status_reg())
333 ppcDcbf((u32)&(base_address[j]));
334 } /* for (j = 0; j < NUMMEMWORDS; j++) */
336 } /* for (l=0; l<NUMLOOPS; l++) */
342 #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
343 /*-----------------------------------------------------------------------------+
344 | program_DQS_calibration_methodA.
345 +-----------------------------------------------------------------------------*/
346 static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
353 mfsdram(SDRAM_RDCC, temp);
354 debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
357 pass_result = DQS_calibration_methodA(ddrcal);
363 * DQS_calibration_methodA()
365 * Autocalibration Method A
367 * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
368 * ARRAY [Entire FDBK Range] FDBK_Valid_Window; initialized to all zeros
369 * MEMWRITE(addr, expected_data);
370 * for (i = 0; i < Entire DQS Range; i++) { RQDC.RQFD
371 * for (j = 0; j < Entire FDBK Range; j++) { RFDC.RFFD
372 * MEMREAD(addr, actual_data);
373 * if (actual_data == expected_data) {
374 * DQS_Valid_Window[i] = 1; RQDC.RQFD
375 * FDBK_Valid_Window[i][j] = 1; RFDC.RFFD
380 static u32 DQS_calibration_methodA(struct ddrautocal *cal)
397 struct autocal_regs curr_win_min;
398 struct autocal_regs curr_win_max;
399 struct autocal_regs best_win_min;
400 struct autocal_regs best_win_max;
401 struct autocal_regs loop_win_min;
402 struct autocal_regs loop_win_max;
409 char slash[] = "\\|/-\\|/-";
415 memset(&curr_win_min, 0, sizeof(curr_win_min));
416 memset(&curr_win_max, 0, sizeof(curr_win_max));
417 memset(&best_win_min, 0, sizeof(best_win_min));
418 memset(&best_win_max, 0, sizeof(best_win_max));
419 memset(&loop_win_min, 0, sizeof(loop_win_min));
420 memset(&loop_win_max, 0, sizeof(loop_win_max));
425 * Program RDCC register
426 * Read sample cycle auto-update enable
428 mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE);
431 mfsdram(SDRAM_RDCC, temp);
432 debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
433 mfsdram(SDRAM_RTSR, temp);
434 debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
435 mfsdram(SDRAM_FCSR, temp);
436 debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
440 * Program RQDC register
441 * Internal DQS delay mechanism enable
444 SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
447 mfsdram(SDRAM_RQDC, temp);
448 debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
452 * Program RFDC register
453 * Set Feedback Fractional Oversample
454 * Auto-detect read sample cycle enable
456 mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
457 SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
460 mfsdram(SDRAM_RFDC, temp);
461 debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
465 for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
467 mfsdram(SDRAM_RQDC, rqdc_reg);
468 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
469 mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
472 putc(slash[loopi++ % 8]);
474 curr_win_min.rffd = 0;
475 curr_win_max.rffd = 0;
478 for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
479 mfsdram(SDRAM_RFDC, rfdc_reg);
480 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
482 rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
484 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
485 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
488 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
489 /* Bank is enabled */
490 membase = get_membase(bxcr_num);
491 pass = short_mem_test(membase);
492 } /* if bank enabled */
495 /* If this value passed update RFFD windows */
496 if (pass && !in_window) { /* at the start of window */
498 curr_win_min.rffd = curr_win_max.rffd = rffd;
499 curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
500 mfsdram(SDRAM_RDCC, rdcc); /*record this value*/
501 } else if (!pass && in_window) { /* at end of window */
503 } else if (pass && in_window) { /* within the window */
504 curr_win_max.rffd = rffd;
505 curr_win_max.rqfd = rqfd;
507 /* else if (!pass && !in_window)
508 skip - no pass, not currently in a window */
511 if ((curr_win_max.rffd - curr_win_min.rffd) >
512 (best_win_max.rffd - best_win_min.rffd)) {
513 best_win_min.rffd = curr_win_min.rffd;
514 best_win_max.rffd = curr_win_max.rffd;
516 best_win_min.rqfd = curr_win_min.rqfd;
517 best_win_max.rqfd = curr_win_max.rqfd;
525 * save-off the best window results of the RFDC.RFFD
526 * for this RQDC.RQFD setting
529 * if (just ended RFDC.RFDC loop pass window) >
530 * (prior RFDC.RFFD loop pass window)
532 if ((best_win_max.rffd - best_win_min.rffd) >
533 (loop_win_max.rffd - loop_win_min.rffd)) {
534 loop_win_min.rffd = best_win_min.rffd;
535 loop_win_max.rffd = best_win_max.rffd;
536 loop_win_min.rqfd = rqfd;
537 loop_win_max.rqfd = rqfd;
538 debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
539 "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
540 loop_win_min.rqfd, loop_win_max.rqfd,
541 loop_win_min.rffd, loop_win_max.rffd);
549 if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
550 (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
551 (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
556 * Need to program RQDC before RFDC.
558 debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
559 debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
560 rqfd_average = loop_win_max.rqfd;
562 if (rqfd_average < 0)
565 if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
566 rqfd_average = SDRAM_RQDC_RQFD_MAX;
568 debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
569 mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
570 SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
572 debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
573 debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
574 rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
576 if (rffd_average < 0)
579 if (rffd_average > SDRAM_RFDC_RFFD_MAX)
580 rffd_average = SDRAM_RFDC_RFFD_MAX;
582 debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
583 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
585 /* if something passed, then return the size of the largest window */
587 passed = loop_win_max.rffd - loop_win_min.rffd;
588 cal->rqfd = rqfd_average;
589 cal->rffd = rffd_average;
590 cal->rffd_min = loop_win_min.rffd;
591 cal->rffd_max = loop_win_max.rffd;
597 #else /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */
599 /*-----------------------------------------------------------------------------+
600 | program_DQS_calibration_methodB.
601 +-----------------------------------------------------------------------------*/
602 static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
611 * Program RDCC register
612 * Read sample cycle auto-update enable
614 mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE);
617 mfsdram(SDRAM_RDCC, temp);
618 debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
622 * Program RQDC register
623 * Internal DQS delay mechanism enable
626 #if defined(CONFIG_DDR_RQDC_START_VAL)
627 SDRAM_RQDC_RQDE_ENABLE |
628 SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
630 SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
634 mfsdram(SDRAM_RQDC, temp);
635 debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
639 * Program RFDC register
640 * Set Feedback Fractional Oversample
641 * Auto-detect read sample cycle enable
643 mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
644 SDRAM_RFDC_RFOS_ENCODE(0) |
645 SDRAM_RFDC_RFFD_ENCODE(0));
648 mfsdram(SDRAM_RFDC, temp);
649 debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
652 pass_result = DQS_calibration_methodB(ddrcal);
658 * DQS_calibration_methodB()
660 * Autocalibration Method B
662 * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
663 * ARRAY [Entire Feedback Range] FDBK_Valid_Window; initialized to all zeros
664 * MEMWRITE(addr, expected_data);
665 * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38).
667 * for (j = 0; j < Entire Feedback Range; j++) {
668 * MEMREAD(addr, actual_data);
669 * if (actual_data == expected_data) {
670 * FDBK_Valid_Window[j] = 1;
674 * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window.
676 * for (i = 0; i < Entire DQS Range; i++) {
677 * MEMREAD(addr, actual_data);
678 * if (actual_data == expected_data) {
679 * DQS_Valid_Window[i] = 1;
683 * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window.
685 /*-----------------------------------------------------------------------------+
686 | DQS_calibration_methodB.
687 +-----------------------------------------------------------------------------*/
688 static u32 DQS_calibration_methodB(struct ddrautocal *cal)
707 u32 curr_win_min, curr_win_max;
708 u32 best_win_min, best_win_max;
711 /*------------------------------------------------------------------
712 | Test to determine the best read clock delay tuning bits.
714 | Before the DDR controller can be used, the read clock delay needs to
715 | be set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
716 | This value cannot be hardcoded into the program because it changes
717 | depending on the board's setup and environment.
718 | To do this, all delay values are tested to see if they
719 | work or not. By doing this, you get groups of fails with groups of
720 | passing values. The idea is to find the start and end of a passing
721 | window and take the center of it to use as the read clock delay.
723 | A failure has to be seen first so that when we hit a pass, we know
724 | that it is truely the start of the window. If we get passing values
725 | to start off with, we don't know if we are at the start of the window
727 | The code assumes that a failure will always be found.
728 | If a failure is not found, there is no easy way to get the middle
729 | of the passing window. I guess we can pretty much pick any value
730 | but some values will be better than others. Since the lowest speed
731 | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
732 | from experimentation it is safe to say you will always have a failure
733 +-----------------------------------------------------------------*/
740 curr_win_min = curr_win_max = 0;
741 best_win_min = best_win_max = 0;
742 for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
743 mfsdram(SDRAM_RFDC, rfdc_reg);
744 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
745 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
748 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
749 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
752 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
753 /* Bank is enabled */
754 membase = get_membase(bxcr_num);
755 pass &= short_mem_test(membase);
756 } /* if bank enabled */
759 /* If this value passed */
760 if (pass && !in_window) { /* start of passing window */
762 curr_win_min = curr_win_max = rffd;
763 mfsdram(SDRAM_RDCC, rdcc); /* record this value */
764 } else if (!pass && in_window) { /* end passing window */
766 } else if (pass && in_window) { /* within the passing window */
771 if ((curr_win_max - curr_win_min) >
772 (best_win_max - best_win_min)) {
773 best_win_min = curr_win_min;
774 best_win_max = curr_win_max;
781 if ((best_win_min == 0) && (best_win_max == 0))
784 size = best_win_max - best_win_min;
786 debug("RFFD Min: 0x%x\n", best_win_min);
787 debug("RFFD Max: 0x%x\n", best_win_max);
788 rffd_average = ((best_win_min + best_win_max) / 2);
790 cal->rffd_min = best_win_min;
791 cal->rffd_max = best_win_max;
793 if (rffd_average < 0)
796 if (rffd_average > SDRAM_RFDC_RFFD_MAX)
797 rffd_average = SDRAM_RFDC_RFFD_MAX;
799 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
804 curr_win_min = curr_win_max = 0;
805 best_win_min = best_win_max = 0;
806 for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
807 mfsdram(SDRAM_RQDC, rqdc_reg);
808 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
809 mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
812 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
814 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
817 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
818 /* Bank is enabled */
819 membase = get_membase(bxcr_num);
820 pass &= short_mem_test(membase);
821 } /* if bank enabled */
824 /* If this value passed */
825 if (pass && !in_window) {
827 curr_win_min = curr_win_max = rqfd;
828 } else if (!pass && in_window) {
830 } else if (pass && in_window) {
835 if ((curr_win_max - curr_win_min) >
836 (best_win_max - best_win_min)) {
837 best_win_min = curr_win_min;
838 best_win_max = curr_win_max;
844 if ((best_win_min == 0) && (best_win_max == 0))
847 debug("RQFD Min: 0x%x\n", best_win_min);
848 debug("RQFD Max: 0x%x\n", best_win_max);
849 rqfd_average = ((best_win_min + best_win_max) / 2);
851 if (rqfd_average < 0)
854 if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
855 rqfd_average = SDRAM_RQDC_RQFD_MAX;
857 mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
858 SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
860 mfsdram(SDRAM_RQDC, rqdc_reg);
861 mfsdram(SDRAM_RFDC, rfdc_reg);
864 * Need to program RQDC before RFDC. The value is read above.
865 * That is the reason why auto cal not work.
866 * See, comments below.
868 mtsdram(SDRAM_RQDC, rqdc_reg);
869 mtsdram(SDRAM_RFDC, rfdc_reg);
871 debug("RQDC: 0x%08X\n", rqdc_reg);
872 debug("RFDC: 0x%08X\n", rfdc_reg);
874 /* if something passed, then return the size of the largest window */
877 cal->rqfd = rqfd_average;
878 cal->rffd = rffd_average;
883 #endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */
886 * Default table for DDR auto-calibration of all
887 * possible WRDTR and CLKTR values.
889 * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]}
891 * Table is terminated with {-1, -1} value pair.
893 * Board vendors can specify their own board specific subset of
894 * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value
895 * pairs via a board defined ddr_scan_option() function.
897 struct sdram_timing full_scan_options[] = {
898 {0, 0}, {0, 1}, {0, 2}, {0, 3},
899 {1, 0}, {1, 1}, {1, 2}, {1, 3},
900 {2, 0}, {2, 1}, {2, 2}, {2, 3},
901 {3, 0}, {3, 1}, {3, 2}, {3, 3},
902 {4, 0}, {4, 1}, {4, 2}, {4, 3},
903 {5, 0}, {5, 1}, {5, 2}, {5, 3},
904 {6, 0}, {6, 1}, {6, 2}, {6, 3},
908 /*---------------------------------------------------------------------------+
910 +----------------------------------------------------------------------------*/
911 u32 DQS_autocalibration(void)
918 struct ddrautocal ddrcal;
919 struct autocal_clks tcal;
925 char slash[] = "\\|/-\\|/-";
927 struct sdram_timing *scan_list;
929 #if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
931 char tmp[64]; /* long enough for environment variables */
934 memset(&tcal, 0, sizeof(tcal));
936 ddr_scan_option((ulong)full_scan_options);
939 (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options);
941 mfsdram(SDRAM_MCOPT1, val);
942 if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
943 str = "ECC Auto calibration -";
945 str = "Auto calibration -";
949 #if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
950 i = getenv_r("autocalib", tmp, sizeof(tmp));
952 strcpy(tmp, CONFIG_AUTOCALIB);
954 if (strcmp(tmp, "final") == 0) {
955 /* display the final autocalibration results only */
957 } else if (strcmp(tmp, "loop") == 0) {
958 /* display summary autocalibration info per iteration */
960 } else if (strcmp(tmp, "display") == 0) {
961 /* display full debug autocalibration window info. */
964 #endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */
966 best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
968 while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
969 wdtr = scan_list->wrdtr;
970 clkp = scan_list->clktr;
972 mfsdram(SDRAM_WRDTR, val);
973 val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
974 mtsdram(SDRAM_WRDTR, (val |
975 ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
977 mtsdram(SDRAM_CLKTR, clkp << 30);
980 putc(slash[loopi++ % 8]);
984 debug("*** --------------\n");
985 mfsdram(SDRAM_WRDTR, val);
986 debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
987 mfsdram(SDRAM_CLKTR, val);
988 debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
992 if (verbose_lvl > 2) {
993 printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
994 printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
997 memset(&ddrcal, 0, sizeof(ddrcal));
1003 * program_DQS_calibration_method[A|B]() returns 0 if no
1004 * passing RFDC.[RFFD] window is found or returns the size
1005 * of the best passing window; in the case of a found passing
1006 * window, the ddrcal will contain the values of the best
1007 * window RQDC.[RQFD] and RFDC.[RFFD].
1011 * Call PPC4xx SDRAM DDR autocalibration methodA or methodB.
1012 * Default is methodB.
1013 * Defined the autocalibration method in the board specific
1015 * Please see include/configs/kilauea.h for an example for
1016 * a board specific implementation.
1018 #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
1019 result = program_DQS_calibration_methodA(&ddrcal);
1021 result = program_DQS_calibration_methodB(&ddrcal);
1027 * Clear potential errors resulting from auto-calibration.
1028 * If not done, then we could get an interrupt later on when
1029 * exceptions are enabled.
1031 set_mcsr(get_mcsr());
1033 val = ddrcal.rdcc; /* RDCC from the best passing window */
1037 if (verbose_lvl > 1) {
1039 switch ((val >> 30)) {
1059 printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
1060 "max-min(0x%04x)(0x%04x), RDCC: %s\n",
1061 wdtr, clkp, result, best_result,
1062 ddrcal.rffd_min, ddrcal.rffd_max, tstr);
1066 * The DQS calibration "result" is either "0"
1067 * if no passing window was found, or is the
1068 * size of the RFFD passing window.
1071 tcal.autocal.flags = 1;
1072 debug("*** (%d)(%d) result passed window size: 0x%08x, "
1073 "rqfd = 0x%08x, rffd = 0x%08x, rdcc = 0x%08x\n",
1074 wdtr, clkp, result, ddrcal.rqfd,
1075 ddrcal.rffd, ddrcal.rdcc);
1077 * Save the SDRAM_WRDTR and SDRAM_CLKTR
1078 * settings for the largest returned
1079 * RFFD passing window size.
1081 if (result > best_result) {
1083 * want the lowest Read Sample Cycle Select
1085 val = (val & SDRAM_RDCC_RDSS_MASK) >> 30;
1086 debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
1088 if (val <= best_rdcc) {
1090 tcal.clocks.wrdtr = wdtr;
1091 tcal.clocks.clktr = clkp;
1092 tcal.clocks.rdcc = (val << 30);
1093 tcal.autocal.rqfd = ddrcal.rqfd;
1094 tcal.autocal.rffd = ddrcal.rffd;
1095 best_result = result;
1097 if (verbose_lvl > 2) {
1098 printf("** (%d)(%d) "
1099 "best result: 0x%04x\n",
1102 printf("** (%d)(%d) "
1103 "best WRDTR: 0x%04x\n",
1106 printf("** (%d)(%d) "
1107 "best CLKTR: 0x%04x\n",
1110 printf("** (%d)(%d) "
1111 "best RQDC: 0x%04x\n",
1114 printf("** (%d)(%d) "
1115 "best RFDC: 0x%04x\n",
1118 printf("** (%d)(%d) "
1119 "best RDCC: 0x%08x\n",
1121 (u32)tcal.clocks.rdcc);
1122 mfsdram(SDRAM_RTSR, val);
1123 printf("** (%d)(%d) best "
1124 "loop RTSR: 0x%08x\n",
1126 mfsdram(SDRAM_FCSR, val);
1127 printf("** (%d)(%d) best "
1128 "loop FCSR: 0x%08x\n",
1131 } /* if (val <= best_rdcc) */
1132 } /* if (result >= best_result) */
1133 } /* if (result != 0) */
1135 } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */
1137 if (tcal.autocal.flags == 1) {
1138 if (verbose_lvl > 0) {
1139 printf("*** --------------\n");
1140 printf("*** best_result window size: %d\n",
1142 printf("*** best_result WRDTR: 0x%04x\n",
1144 printf("*** best_result CLKTR: 0x%04x\n",
1146 printf("*** best_result RQFD: 0x%04x\n",
1148 printf("*** best_result RFFD: 0x%04x\n",
1150 printf("*** best_result RDCC: 0x%04x\n",
1152 printf("*** --------------\n");
1157 * if got best passing result window, then lock in the
1158 * best CLKTR, WRDTR, RQFD, and RFFD values
1160 mfsdram(SDRAM_WRDTR, val);
1161 mtsdram(SDRAM_WRDTR, (val &
1162 ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
1163 ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
1164 (tcal.clocks.wrdtr << 25)));
1166 mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
1168 mfsdram(SDRAM_RQDC, rqdc_reg);
1169 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
1170 mtsdram(SDRAM_RQDC, rqdc_reg |
1171 SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
1173 mfsdram(SDRAM_RQDC, rqdc_reg);
1174 debug("*** best_result: read value SDRAM_RQDC 0x%08x\n",
1177 mfsdram(SDRAM_RFDC, rfdc_reg);
1178 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
1179 mtsdram(SDRAM_RFDC, rfdc_reg |
1180 SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
1182 mfsdram(SDRAM_RFDC, rfdc_reg);
1183 debug("*** best_result: read value SDRAM_RFDC 0x%08x\n",
1185 mfsdram(SDRAM_RDCC, val);
1186 debug("*** SDRAM_RDCC 0x%08x\n", val);
1189 * no valid windows were found
1191 printf("DQS memory calibration window can not be determined, "
1192 "terminating u-boot.\n");
1193 ppc4xx_ibm_ddr2_register_dump();
1194 spd_ddr_init_hang();
1197 blank_string(strlen(str));
1201 #else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
1202 u32 DQS_autocalibration(void)
1206 #endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
1207 #endif /* defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */