blob: 6c949a0fe15cc8ba08fa5cebdbca9e45da8ba5a5 [file] [log] [blame]
Larry Johnson8a24a692007-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 +----------------------------------------------------------------------------*/
102/*
103 * Avoid conflict with implementations of denali_core_search_data_eye in board-
104 * specific code.
105 */
106void denali_core_search_data_eye(void)
107 __attribute__ ((weak, alias("__denali_core_search_data_eye")));
108
109void __denali_core_search_data_eye(void)
110{
111 int k, j;
112 u32 val;
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
135 };
136
137 ram_pointer = (volatile u32 *)(CFG_SDRAM_BASE);
138
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++) { */
141
142 /* -----------------------------------------------------------+
143 * De-assert 'start' parameter.
144 * ----------------------------------------------------------*/
145 mtdcr(ddrcfga, DDR0_02);
146 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
147 DDR0_02_START_OFF;
148 mtdcr(ddrcfgd, val);
149
150 /* -----------------------------------------------------------+
151 * Set 'wr_dqs_shift'
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);
156 mtdcr(ddrcfgd, val);
157
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);
165 mtdcr(ddrcfgd, val);
166
167 passing_cases = 0;
168
169 for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
170 dll_dqs_delay_X++) {
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);
180 mtdcr(ddrcfgd, val);
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);
188 mtdcr(ddrcfgd, val);
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);
196 mtdcr(ddrcfgd, val);
197 /* clear any ECC errors */
198 mtdcr(ddrcfga, DDR0_00);
199 mtdcr(ddrcfgd,
200 mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
201
202 sync();
203 eieio();
204
205 /* -----------------------------------------------------------+
206 * Assert 'start' parameter.
207 * ----------------------------------------------------------*/
208 mtdcr(ddrcfga, DDR0_02);
209 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
210 DDR0_02_START_ON;
211 mtdcr(ddrcfgd, val);
212
213 sync();
214 eieio();
215
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);
224 hang();
225 }
226 sync();
227 eieio();
228
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);
234 hang();
235 }
236 udelay(100); /* wait 100us to ensure init is really completed !!! */
237
238 /* write values */
239 for (j = 0; j < NUM_TRIES; j++) {
240 ram_pointer[j] = test[j];
241
242 /* clear any cache at ram location */
243 __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
244 }
245
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
251 [j]));
252
253 if (ram_pointer[j] != test[j])
254 break;
255 }
256
257 /* read error */
258 if (k != NUM_READS)
259 break;
260 }
261
262 /* See if the dll_dqs_delay_X value passed. */
263 mtdcr(ddrcfga, DDR0_00);
264 if (j < NUM_TRIES
265 || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
266 0x3F)) {
267 /* Failed */
268 passing_cases = 0;
269 /* break; */
270 } else {
271 /* Passed */
272 if (passing_cases == 0)
273 dll_dqs_delay_X_sw_val =
274 dll_dqs_delay_X;
275 passing_cases++;
276 if (passing_cases >= max_passing_cases) {
277 max_passing_cases = passing_cases;
278 wr_dqs_shift_with_max_passing_cases =
279 wr_dqs_shift;
280 dll_dqs_delay_X_start_window =
281 dll_dqs_delay_X_sw_val;
282 dll_dqs_delay_X_end_window =
283 dll_dqs_delay_X;
284 }
285 }
286
287 /* -----------------------------------------------------------+
288 * De-assert 'start' parameter.
289 * ----------------------------------------------------------*/
290 mtdcr(ddrcfga, DDR0_02);
291 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
292 DDR0_02_START_OFF;
293 mtdcr(ddrcfgd, val);
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++) */
296
297 /* -----------------------------------------------------------+
298 * Largest passing window is now detected.
299 * ----------------------------------------------------------*/
300
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;
305
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);
312
313 /* -----------------------------------------------------------+
314 * De-assert 'start' parameter.
315 * ----------------------------------------------------------*/
316 mtdcr(ddrcfga, DDR0_02);
317 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
318 mtdcr(ddrcfgd, val);
319
320 /* -----------------------------------------------------------+
321 * Set 'wr_dqs_shift'
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);
326 mtdcr(ddrcfgd, val);
327 debug("DDR0_09=0x%08lx\n", val);
328
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);
336 mtdcr(ddrcfgd, val);
337 debug("DDR0_22=0x%08lx\n", val);
338
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);
346 mtdcr(ddrcfgd, val);
347 debug("DDR0_17=0x%08lx\n", val);
348
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);
356 mtdcr(ddrcfgd, val);
357 debug("DDR0_18=0x%08lx\n", val);
358
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);
366 mtdcr(ddrcfgd, val);
367 debug("DDR0_19=0x%08lx\n", val);
368
369 /* -----------------------------------------------------------+
370 * Assert 'start' parameter.
371 * ----------------------------------------------------------*/
372 mtdcr(ddrcfga, DDR0_02);
373 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
374 mtdcr(ddrcfgd, val);
375
376 sync();
377 eieio();
378
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");
384 hang();
385 }
386 sync();
387 eieio();
388
389 if (wait_for_dram_init_complete() != 0) {
390 printf("dram init complete did not occur !!!\n");
391 hang();
392 }
393 udelay(100); /* wait 100us to ensure init is really completed !!! */
394}
395#endif /* defined(CONFIG_DDR_DATA_EYE) */
396#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */