blob: 967e61bd415684fb0036dab673f09cc7bbe7dbf6 [file] [log] [blame]
Larry Johnson41bf3642007-12-22 15:15:30 -05001/*
2 * cpu/ppc4xx/denali_data_eye.c
3 * Extracted from board/amcc/sequoia/sdram.c by Larry Johnson <lrj@acm.org>.
4 *
5 * (C) Copyright 2006
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
11 *
12 * (C) Copyright 2006-2007
13 * Stefan Roese, DENX Software Engineering, sr@denx.de.
14 *
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.
19 *
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.
24 *
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,
28 * MA 02111-1307 USA
29 */
30
31/* define DEBUG for debugging output (obviously ;-)) */
32#if 0
33#define DEBUG
34#endif
35
36#include <common.h>
37#include <asm/processor.h>
38#include <asm/io.h>
39#include <ppc4xx.h>
40
41#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
42/*-----------------------------------------------------------------------------+
43 * denali_wait_for_dlllock.
44 +----------------------------------------------------------------------------*/
45int denali_wait_for_dlllock(void)
46{
47 u32 val;
48 int wait;
49
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 */
57 return 0;
58 }
59 }
60 debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val);
61 debug("Waiting for dlllockreg bit to raise\n");
62 return -1;
63}
64
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 */
69
70/*-----------------------------------------------------------------------------+
71 * wait_for_dram_init_complete.
72 +----------------------------------------------------------------------------*/
73static int wait_for_dram_init_complete(void)
74{
75 unsigned long val;
76 int wait = 0;
77
78 /* --------------------------------------------------------------+
79 * Wait for 'DRAM initialization complete' bit in status register
80 * -------------------------------------------------------------*/
81 mtdcr(ddrcfga, DDR0_00);
82
83 while (wait != 0xffff) {
84 val = mfdcr(ddrcfgd);
85 if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6)
86 /* 'DRAM initialization complete' bit */
87 return 0;
88 else
89 wait++;
90 }
91 debug("DRAM initialization complete bit in status register did not "
92 "rise\n");
93 return -1;
94}
95
96#define NUM_TRIES 64
97#define NUM_READS 10
98
99/*-----------------------------------------------------------------------------+
100 * denali_core_search_data_eye.
101 +----------------------------------------------------------------------------*/
Larry Johnson41bf3642007-12-22 15:15:30 -0500102void denali_core_search_data_eye(void)
Larry Johnson41bf3642007-12-22 15:15:30 -0500103{
104 int k, j;
105 u32 val;
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
128 };
129
130 ram_pointer = (volatile u32 *)(CFG_SDRAM_BASE);
131
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++) { */
134
135 /* -----------------------------------------------------------+
136 * De-assert 'start' parameter.
137 * ----------------------------------------------------------*/
138 mtdcr(ddrcfga, DDR0_02);
139 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
140 DDR0_02_START_OFF;
141 mtdcr(ddrcfgd, val);
142
143 /* -----------------------------------------------------------+
144 * Set 'wr_dqs_shift'
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);
149 mtdcr(ddrcfgd, val);
150
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);
158 mtdcr(ddrcfgd, val);
159
160 passing_cases = 0;
161
162 for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
163 dll_dqs_delay_X++) {
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);
173 mtdcr(ddrcfgd, val);
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);
181 mtdcr(ddrcfgd, val);
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);
189 mtdcr(ddrcfgd, val);
190 /* clear any ECC errors */
191 mtdcr(ddrcfga, DDR0_00);
192 mtdcr(ddrcfgd,
193 mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
194
195 sync();
196 eieio();
197
198 /* -----------------------------------------------------------+
199 * Assert 'start' parameter.
200 * ----------------------------------------------------------*/
201 mtdcr(ddrcfga, DDR0_02);
202 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
203 DDR0_02_START_ON;
204 mtdcr(ddrcfgd, val);
205
206 sync();
207 eieio();
208
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);
217 hang();
218 }
219 sync();
220 eieio();
221
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);
227 hang();
228 }
229 udelay(100); /* wait 100us to ensure init is really completed !!! */
230
231 /* write values */
232 for (j = 0; j < NUM_TRIES; j++) {
233 ram_pointer[j] = test[j];
234
235 /* clear any cache at ram location */
236 __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
237 }
238
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
244 [j]));
245
246 if (ram_pointer[j] != test[j])
247 break;
248 }
249
250 /* read error */
251 if (k != NUM_READS)
252 break;
253 }
254
255 /* See if the dll_dqs_delay_X value passed. */
256 mtdcr(ddrcfga, DDR0_00);
257 if (j < NUM_TRIES
258 || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
259 0x3F)) {
260 /* Failed */
261 passing_cases = 0;
262 /* break; */
263 } else {
264 /* Passed */
265 if (passing_cases == 0)
266 dll_dqs_delay_X_sw_val =
267 dll_dqs_delay_X;
268 passing_cases++;
269 if (passing_cases >= max_passing_cases) {
270 max_passing_cases = passing_cases;
271 wr_dqs_shift_with_max_passing_cases =
272 wr_dqs_shift;
273 dll_dqs_delay_X_start_window =
274 dll_dqs_delay_X_sw_val;
275 dll_dqs_delay_X_end_window =
276 dll_dqs_delay_X;
277 }
278 }
279
280 /* -----------------------------------------------------------+
281 * De-assert 'start' parameter.
282 * ----------------------------------------------------------*/
283 mtdcr(ddrcfga, DDR0_02);
284 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
285 DDR0_02_START_OFF;
286 mtdcr(ddrcfgd, val);
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++) */
289
290 /* -----------------------------------------------------------+
291 * Largest passing window is now detected.
292 * ----------------------------------------------------------*/
293
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;
298
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);
305
306 /* -----------------------------------------------------------+
307 * De-assert 'start' parameter.
308 * ----------------------------------------------------------*/
309 mtdcr(ddrcfga, DDR0_02);
310 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
311 mtdcr(ddrcfgd, val);
312
313 /* -----------------------------------------------------------+
314 * Set 'wr_dqs_shift'
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);
319 mtdcr(ddrcfgd, val);
320 debug("DDR0_09=0x%08lx\n", val);
321
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);
329 mtdcr(ddrcfgd, val);
330 debug("DDR0_22=0x%08lx\n", val);
331
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);
339 mtdcr(ddrcfgd, val);
340 debug("DDR0_17=0x%08lx\n", val);
341
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);
349 mtdcr(ddrcfgd, val);
350 debug("DDR0_18=0x%08lx\n", val);
351
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);
359 mtdcr(ddrcfgd, val);
360 debug("DDR0_19=0x%08lx\n", val);
361
362 /* -----------------------------------------------------------+
363 * Assert 'start' parameter.
364 * ----------------------------------------------------------*/
365 mtdcr(ddrcfga, DDR0_02);
366 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
367 mtdcr(ddrcfgd, val);
368
369 sync();
370 eieio();
371
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");
377 hang();
378 }
379 sync();
380 eieio();
381
382 if (wait_for_dram_init_complete() != 0) {
383 printf("dram init complete did not occur !!!\n");
384 hang();
385 }
386 udelay(100); /* wait 100us to ensure init is really completed !!! */
387}
388#endif /* defined(CONFIG_DDR_DATA_EYE) */
389#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */