2 * cpu/ppc4xx/denali_data_eye.c
3 * Extracted from board/amcc/sequoia/sdram.c by Larry Johnson <lrj@acm.org>.
6 * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com
7 * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
8 * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com
9 * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com
10 * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com
12 * (C) Copyright 2006-2007
13 * Stefan Roese, DENX Software Engineering, sr@denx.de.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
31 /* define DEBUG for debugging output (obviously ;-)) */
37 #include <asm/processor.h>
41 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
42 /*-----------------------------------------------------------------------------+
43 * denali_wait_for_dlllock.
44 +----------------------------------------------------------------------------*/
45 int denali_wait_for_dlllock(void)
50 /* -----------------------------------------------------------+
51 * Wait for the DCC master delay line to finish calibration
52 * ----------------------------------------------------------*/
53 for (wait = 0; wait != 0xffff; ++wait) {
54 mfsdram(DDR0_17, val);
55 if (DDR0_17_DLLLOCKREG_DECODE(val)) {
56 /* dlllockreg bit on */
60 debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val);
61 debug("Waiting for dlllockreg bit to raise\n");
65 #if defined(CONFIG_DDR_DATA_EYE)
66 #define DDR_DCR_BASE 0x10
67 #define ddrcfga (DDR_DCR_BASE+0x0) /* DDR configuration address reg */
68 #define ddrcfgd (DDR_DCR_BASE+0x1) /* DDR configuration data reg */
70 /*-----------------------------------------------------------------------------+
71 * wait_for_dram_init_complete.
72 +----------------------------------------------------------------------------*/
73 static int wait_for_dram_init_complete(void)
78 /* --------------------------------------------------------------+
79 * Wait for 'DRAM initialization complete' bit in status register
80 * -------------------------------------------------------------*/
81 mtdcr(ddrcfga, DDR0_00);
83 while (wait != 0xffff) {
85 if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6)
86 /* 'DRAM initialization complete' bit */
91 debug("DRAM initialization complete bit in status register did not "
99 /*-----------------------------------------------------------------------------+
100 * denali_core_search_data_eye.
101 +----------------------------------------------------------------------------*/
103 * Avoid conflict with implementations of denali_core_search_data_eye in board-
106 void denali_core_search_data_eye(void)
107 __attribute__ ((weak, alias("__denali_core_search_data_eye")));
109 void __denali_core_search_data_eye(void)
113 u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X;
114 u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0;
115 u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0;
116 u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0;
117 volatile u32 *ram_pointer;
118 u32 test[NUM_TRIES] = {
119 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
120 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
121 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
122 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
123 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
124 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
125 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
126 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
127 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
128 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
129 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
130 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
131 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
132 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
133 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
134 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55
137 ram_pointer = (volatile u32 *)(CFG_SDRAM_BASE);
139 for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) {
140 /* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */
142 /* -----------------------------------------------------------+
143 * De-assert 'start' parameter.
144 * ----------------------------------------------------------*/
145 mtdcr(ddrcfga, DDR0_02);
146 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
150 /* -----------------------------------------------------------+
152 * ----------------------------------------------------------*/
153 mtdcr(ddrcfga, DDR0_09);
154 val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) |
155 DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
158 /* -----------------------------------------------------------+
159 * Set 'dqs_out_shift' = wr_dqs_shift + 32
160 * ----------------------------------------------------------*/
161 dqs_out_shift = wr_dqs_shift + 32;
162 mtdcr(ddrcfga, DDR0_22);
163 val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) |
164 DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
169 for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
171 /* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128;
172 dll_dqs_delay_X++) { */
173 /* -----------------------------------------------------------+
174 * Set 'dll_dqs_delay_X'.
175 * ----------------------------------------------------------*/
176 /* dll_dqs_delay_0 */
177 mtdcr(ddrcfga, DDR0_17);
178 val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
179 | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
181 /* dll_dqs_delay_1 to dll_dqs_delay_4 */
182 mtdcr(ddrcfga, DDR0_18);
183 val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
184 | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
185 | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
186 | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
187 | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
189 /* dll_dqs_delay_5 to dll_dqs_delay_8 */
190 mtdcr(ddrcfga, DDR0_19);
191 val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
192 | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
193 | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
194 | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
195 | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
197 /* clear any ECC errors */
198 mtdcr(ddrcfga, DDR0_00);
200 mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
205 /* -----------------------------------------------------------+
206 * Assert 'start' parameter.
207 * ----------------------------------------------------------*/
208 mtdcr(ddrcfga, DDR0_02);
209 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
216 /* -----------------------------------------------------------+
217 * Wait for the DCC master delay line to finish calibration
218 * ----------------------------------------------------------*/
219 if (denali_wait_for_dlllock() != 0) {
220 printf("dll lock did not occur !!!\n");
221 printf("denali_core_search_data_eye!!!\n");
222 printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
223 "%d\n", wr_dqs_shift, dll_dqs_delay_X);
229 if (wait_for_dram_init_complete() != 0) {
230 printf("dram init complete did not occur!!!\n");
231 printf("denali_core_search_data_eye!!!\n");
232 printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
233 "%d\n", wr_dqs_shift, dll_dqs_delay_X);
236 udelay(100); /* wait 100us to ensure init is really completed !!! */
239 for (j = 0; j < NUM_TRIES; j++) {
240 ram_pointer[j] = test[j];
242 /* clear any cache at ram location */
243 __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
246 /* read values back */
247 for (j = 0; j < NUM_TRIES; j++) {
248 for (k = 0; k < NUM_READS; k++) {
249 /* clear any cache at ram location */
250 __asm__("dcbf 0,%0": :"r"(&ram_pointer
253 if (ram_pointer[j] != test[j])
262 /* See if the dll_dqs_delay_X value passed. */
263 mtdcr(ddrcfga, DDR0_00);
265 || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
272 if (passing_cases == 0)
273 dll_dqs_delay_X_sw_val =
276 if (passing_cases >= max_passing_cases) {
277 max_passing_cases = passing_cases;
278 wr_dqs_shift_with_max_passing_cases =
280 dll_dqs_delay_X_start_window =
281 dll_dqs_delay_X_sw_val;
282 dll_dqs_delay_X_end_window =
287 /* -----------------------------------------------------------+
288 * De-assert 'start' parameter.
289 * ----------------------------------------------------------*/
290 mtdcr(ddrcfga, DDR0_02);
291 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
294 } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */
295 } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */
297 /* -----------------------------------------------------------+
298 * Largest passing window is now detected.
299 * ----------------------------------------------------------*/
301 /* Compute dll_dqs_delay_X value */
302 dll_dqs_delay_X = (dll_dqs_delay_X_end_window +
303 dll_dqs_delay_X_start_window) / 2;
304 wr_dqs_shift = wr_dqs_shift_with_max_passing_cases;
306 debug("DQS calibration - Window detected:\n");
307 debug("max_passing_cases = %d\n", max_passing_cases);
308 debug("wr_dqs_shift = %d\n", wr_dqs_shift);
309 debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X);
310 debug("dll_dqs_delay_X window = %d - %d\n",
311 dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window);
313 /* -----------------------------------------------------------+
314 * De-assert 'start' parameter.
315 * ----------------------------------------------------------*/
316 mtdcr(ddrcfga, DDR0_02);
317 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
320 /* -----------------------------------------------------------+
322 * ----------------------------------------------------------*/
323 mtdcr(ddrcfga, DDR0_09);
324 val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK)
325 | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
327 debug("DDR0_09=0x%08lx\n", val);
329 /* -----------------------------------------------------------+
330 * Set 'dqs_out_shift' = wr_dqs_shift + 32
331 * ----------------------------------------------------------*/
332 dqs_out_shift = wr_dqs_shift + 32;
333 mtdcr(ddrcfga, DDR0_22);
334 val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK)
335 | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
337 debug("DDR0_22=0x%08lx\n", val);
339 /* -----------------------------------------------------------+
340 * Set 'dll_dqs_delay_X'.
341 * ----------------------------------------------------------*/
342 /* dll_dqs_delay_0 */
343 mtdcr(ddrcfga, DDR0_17);
344 val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
345 | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
347 debug("DDR0_17=0x%08lx\n", val);
349 /* dll_dqs_delay_1 to dll_dqs_delay_4 */
350 mtdcr(ddrcfga, DDR0_18);
351 val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
352 | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
353 | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
354 | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
355 | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
357 debug("DDR0_18=0x%08lx\n", val);
359 /* dll_dqs_delay_5 to dll_dqs_delay_8 */
360 mtdcr(ddrcfga, DDR0_19);
361 val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
362 | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
363 | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
364 | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
365 | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
367 debug("DDR0_19=0x%08lx\n", val);
369 /* -----------------------------------------------------------+
370 * Assert 'start' parameter.
371 * ----------------------------------------------------------*/
372 mtdcr(ddrcfga, DDR0_02);
373 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
379 /* -----------------------------------------------------------+
380 * Wait for the DCC master delay line to finish calibration
381 * ----------------------------------------------------------*/
382 if (denali_wait_for_dlllock() != 0) {
383 printf("dll lock did not occur !!!\n");
389 if (wait_for_dram_init_complete() != 0) {
390 printf("dram init complete did not occur !!!\n");
393 udelay(100); /* wait 100us to ensure init is really completed !!! */
395 #endif /* defined(CONFIG_DDR_DATA_EYE) */
396 #endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */