2 * arch/powerpc/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>
39 #include <asm/ppc4xx.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 +----------------------------------------------------------------------------*/
102 void denali_core_search_data_eye(void)
106 u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X;
107 u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0;
108 u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0;
109 u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0;
110 volatile u32 *ram_pointer;
111 u32 test[NUM_TRIES] = {
112 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
113 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
114 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
115 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
116 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
117 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
118 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
119 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
120 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
121 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
122 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
123 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
124 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
125 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
126 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
127 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55
130 ram_pointer = (volatile u32 *)(CONFIG_SYS_SDRAM_BASE);
132 for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) {
133 /* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */
135 /* -----------------------------------------------------------+
136 * De-assert 'start' parameter.
137 * ----------------------------------------------------------*/
138 mtdcr(ddrcfga, DDR0_02);
139 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
143 /* -----------------------------------------------------------+
145 * ----------------------------------------------------------*/
146 mtdcr(ddrcfga, DDR0_09);
147 val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) |
148 DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
151 /* -----------------------------------------------------------+
152 * Set 'dqs_out_shift' = wr_dqs_shift + 32
153 * ----------------------------------------------------------*/
154 dqs_out_shift = wr_dqs_shift + 32;
155 mtdcr(ddrcfga, DDR0_22);
156 val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) |
157 DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
162 for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
164 /* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128;
165 dll_dqs_delay_X++) { */
166 /* -----------------------------------------------------------+
167 * Set 'dll_dqs_delay_X'.
168 * ----------------------------------------------------------*/
169 /* dll_dqs_delay_0 */
170 mtdcr(ddrcfga, DDR0_17);
171 val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
172 | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
174 /* dll_dqs_delay_1 to dll_dqs_delay_4 */
175 mtdcr(ddrcfga, DDR0_18);
176 val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
177 | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
178 | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
179 | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
180 | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
182 /* dll_dqs_delay_5 to dll_dqs_delay_8 */
183 mtdcr(ddrcfga, DDR0_19);
184 val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
185 | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
186 | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
187 | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
188 | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
190 /* clear any ECC errors */
191 mtdcr(ddrcfga, DDR0_00);
193 mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
198 /* -----------------------------------------------------------+
199 * Assert 'start' parameter.
200 * ----------------------------------------------------------*/
201 mtdcr(ddrcfga, DDR0_02);
202 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
209 /* -----------------------------------------------------------+
210 * Wait for the DCC master delay line to finish calibration
211 * ----------------------------------------------------------*/
212 if (denali_wait_for_dlllock() != 0) {
213 printf("dll lock did not occur !!!\n");
214 printf("denali_core_search_data_eye!!!\n");
215 printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
216 "%d\n", wr_dqs_shift, dll_dqs_delay_X);
222 if (wait_for_dram_init_complete() != 0) {
223 printf("dram init complete did not occur!!!\n");
224 printf("denali_core_search_data_eye!!!\n");
225 printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
226 "%d\n", wr_dqs_shift, dll_dqs_delay_X);
229 udelay(100); /* wait 100us to ensure init is really completed !!! */
232 for (j = 0; j < NUM_TRIES; j++) {
233 ram_pointer[j] = test[j];
235 /* clear any cache at ram location */
236 __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
239 /* read values back */
240 for (j = 0; j < NUM_TRIES; j++) {
241 for (k = 0; k < NUM_READS; k++) {
242 /* clear any cache at ram location */
243 __asm__("dcbf 0,%0": :"r"(&ram_pointer
246 if (ram_pointer[j] != test[j])
255 /* See if the dll_dqs_delay_X value passed. */
256 mtdcr(ddrcfga, DDR0_00);
258 || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
265 if (passing_cases == 0)
266 dll_dqs_delay_X_sw_val =
269 if (passing_cases >= max_passing_cases) {
270 max_passing_cases = passing_cases;
271 wr_dqs_shift_with_max_passing_cases =
273 dll_dqs_delay_X_start_window =
274 dll_dqs_delay_X_sw_val;
275 dll_dqs_delay_X_end_window =
280 /* -----------------------------------------------------------+
281 * De-assert 'start' parameter.
282 * ----------------------------------------------------------*/
283 mtdcr(ddrcfga, DDR0_02);
284 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
287 } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */
288 } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */
290 /* -----------------------------------------------------------+
291 * Largest passing window is now detected.
292 * ----------------------------------------------------------*/
294 /* Compute dll_dqs_delay_X value */
295 dll_dqs_delay_X = (dll_dqs_delay_X_end_window +
296 dll_dqs_delay_X_start_window) / 2;
297 wr_dqs_shift = wr_dqs_shift_with_max_passing_cases;
299 debug("DQS calibration - Window detected:\n");
300 debug("max_passing_cases = %d\n", max_passing_cases);
301 debug("wr_dqs_shift = %d\n", wr_dqs_shift);
302 debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X);
303 debug("dll_dqs_delay_X window = %d - %d\n",
304 dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window);
306 /* -----------------------------------------------------------+
307 * De-assert 'start' parameter.
308 * ----------------------------------------------------------*/
309 mtdcr(ddrcfga, DDR0_02);
310 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
313 /* -----------------------------------------------------------+
315 * ----------------------------------------------------------*/
316 mtdcr(ddrcfga, DDR0_09);
317 val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK)
318 | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
320 debug("DDR0_09=0x%08x\n", val);
322 /* -----------------------------------------------------------+
323 * Set 'dqs_out_shift' = wr_dqs_shift + 32
324 * ----------------------------------------------------------*/
325 dqs_out_shift = wr_dqs_shift + 32;
326 mtdcr(ddrcfga, DDR0_22);
327 val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK)
328 | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
330 debug("DDR0_22=0x%08x\n", val);
332 /* -----------------------------------------------------------+
333 * Set 'dll_dqs_delay_X'.
334 * ----------------------------------------------------------*/
335 /* dll_dqs_delay_0 */
336 mtdcr(ddrcfga, DDR0_17);
337 val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
338 | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
340 debug("DDR0_17=0x%08x\n", val);
342 /* dll_dqs_delay_1 to dll_dqs_delay_4 */
343 mtdcr(ddrcfga, DDR0_18);
344 val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
345 | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
346 | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
347 | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
348 | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
350 debug("DDR0_18=0x%08x\n", val);
352 /* dll_dqs_delay_5 to dll_dqs_delay_8 */
353 mtdcr(ddrcfga, DDR0_19);
354 val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
355 | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
356 | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
357 | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
358 | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
360 debug("DDR0_19=0x%08x\n", val);
362 /* -----------------------------------------------------------+
363 * Assert 'start' parameter.
364 * ----------------------------------------------------------*/
365 mtdcr(ddrcfga, DDR0_02);
366 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
372 /* -----------------------------------------------------------+
373 * Wait for the DCC master delay line to finish calibration
374 * ----------------------------------------------------------*/
375 if (denali_wait_for_dlllock() != 0) {
376 printf("dll lock did not occur !!!\n");
382 if (wait_for_dram_init_complete() != 0) {
383 printf("dram init complete did not occur !!!\n");
386 udelay(100); /* wait 100us to ensure init is really completed !!! */
388 #endif /* defined(CONFIG_DDR_DATA_EYE) */
389 #endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */