blob: a955a5ba6329ca2ab74aa8e5a16b90ed7c8eac1b [file] [log] [blame]
Larry Johnson41bf3642007-12-22 15:15:30 -05001/*
Stefan Roese88fbf932010-04-15 16:07:28 +02002 * arch/powerpc/cpu/ppc4xx/denali_data_eye.c
Larry Johnson41bf3642007-12-22 15:15:30 -05003 * 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 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +020015 * SPDX-License-Identifier: GPL-2.0+
Larry Johnson41bf3642007-12-22 15:15:30 -050016 */
17
18/* define DEBUG for debugging output (obviously ;-)) */
19#if 0
20#define DEBUG
21#endif
22
23#include <common.h>
24#include <asm/processor.h>
25#include <asm/io.h>
Stefan Roese247e9d72010-09-09 19:18:00 +020026#include <asm/ppc4xx.h>
Larry Johnson41bf3642007-12-22 15:15:30 -050027
28#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
29/*-----------------------------------------------------------------------------+
30 * denali_wait_for_dlllock.
31 +----------------------------------------------------------------------------*/
32int denali_wait_for_dlllock(void)
33{
34 u32 val;
35 int wait;
36
37 /* -----------------------------------------------------------+
38 * Wait for the DCC master delay line to finish calibration
39 * ----------------------------------------------------------*/
40 for (wait = 0; wait != 0xffff; ++wait) {
41 mfsdram(DDR0_17, val);
42 if (DDR0_17_DLLLOCKREG_DECODE(val)) {
43 /* dlllockreg bit on */
44 return 0;
45 }
46 }
47 debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val);
48 debug("Waiting for dlllockreg bit to raise\n");
49 return -1;
50}
51
52#if defined(CONFIG_DDR_DATA_EYE)
53#define DDR_DCR_BASE 0x10
54#define ddrcfga (DDR_DCR_BASE+0x0) /* DDR configuration address reg */
55#define ddrcfgd (DDR_DCR_BASE+0x1) /* DDR configuration data reg */
56
57/*-----------------------------------------------------------------------------+
58 * wait_for_dram_init_complete.
59 +----------------------------------------------------------------------------*/
60static int wait_for_dram_init_complete(void)
61{
62 unsigned long val;
63 int wait = 0;
64
65 /* --------------------------------------------------------------+
66 * Wait for 'DRAM initialization complete' bit in status register
67 * -------------------------------------------------------------*/
68 mtdcr(ddrcfga, DDR0_00);
69
70 while (wait != 0xffff) {
71 val = mfdcr(ddrcfgd);
72 if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6)
73 /* 'DRAM initialization complete' bit */
74 return 0;
75 else
76 wait++;
77 }
78 debug("DRAM initialization complete bit in status register did not "
79 "rise\n");
80 return -1;
81}
82
83#define NUM_TRIES 64
84#define NUM_READS 10
85
86/*-----------------------------------------------------------------------------+
87 * denali_core_search_data_eye.
88 +----------------------------------------------------------------------------*/
Larry Johnson41bf3642007-12-22 15:15:30 -050089void denali_core_search_data_eye(void)
Larry Johnson41bf3642007-12-22 15:15:30 -050090{
91 int k, j;
92 u32 val;
93 u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X;
94 u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0;
95 u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0;
96 u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0;
97 volatile u32 *ram_pointer;
98 u32 test[NUM_TRIES] = {
99 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
100 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
101 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
102 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
103 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
104 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
105 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
106 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
107 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
108 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
109 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
110 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
111 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
112 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
113 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
114 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55
115 };
116
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200117 ram_pointer = (volatile u32 *)(CONFIG_SYS_SDRAM_BASE);
Larry Johnson41bf3642007-12-22 15:15:30 -0500118
119 for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) {
120 /* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */
121
122 /* -----------------------------------------------------------+
123 * De-assert 'start' parameter.
124 * ----------------------------------------------------------*/
125 mtdcr(ddrcfga, DDR0_02);
126 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
127 DDR0_02_START_OFF;
128 mtdcr(ddrcfgd, val);
129
130 /* -----------------------------------------------------------+
131 * Set 'wr_dqs_shift'
132 * ----------------------------------------------------------*/
133 mtdcr(ddrcfga, DDR0_09);
134 val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) |
135 DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
136 mtdcr(ddrcfgd, val);
137
138 /* -----------------------------------------------------------+
139 * Set 'dqs_out_shift' = wr_dqs_shift + 32
140 * ----------------------------------------------------------*/
141 dqs_out_shift = wr_dqs_shift + 32;
142 mtdcr(ddrcfga, DDR0_22);
143 val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) |
144 DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
145 mtdcr(ddrcfgd, val);
146
147 passing_cases = 0;
148
149 for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
150 dll_dqs_delay_X++) {
151 /* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128;
152 dll_dqs_delay_X++) { */
153 /* -----------------------------------------------------------+
154 * Set 'dll_dqs_delay_X'.
155 * ----------------------------------------------------------*/
156 /* dll_dqs_delay_0 */
157 mtdcr(ddrcfga, DDR0_17);
158 val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
159 | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
160 mtdcr(ddrcfgd, val);
161 /* dll_dqs_delay_1 to dll_dqs_delay_4 */
162 mtdcr(ddrcfga, DDR0_18);
163 val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
164 | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
165 | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
166 | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
167 | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
168 mtdcr(ddrcfgd, val);
169 /* dll_dqs_delay_5 to dll_dqs_delay_8 */
170 mtdcr(ddrcfga, DDR0_19);
171 val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
172 | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
173 | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
174 | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
175 | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
176 mtdcr(ddrcfgd, val);
177 /* clear any ECC errors */
178 mtdcr(ddrcfga, DDR0_00);
179 mtdcr(ddrcfgd,
180 mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
181
182 sync();
183 eieio();
184
185 /* -----------------------------------------------------------+
186 * Assert 'start' parameter.
187 * ----------------------------------------------------------*/
188 mtdcr(ddrcfga, DDR0_02);
189 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
190 DDR0_02_START_ON;
191 mtdcr(ddrcfgd, val);
192
193 sync();
194 eieio();
195
196 /* -----------------------------------------------------------+
197 * Wait for the DCC master delay line to finish calibration
198 * ----------------------------------------------------------*/
199 if (denali_wait_for_dlllock() != 0) {
200 printf("dll lock did not occur !!!\n");
201 printf("denali_core_search_data_eye!!!\n");
202 printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
203 "%d\n", wr_dqs_shift, dll_dqs_delay_X);
204 hang();
205 }
206 sync();
207 eieio();
208
209 if (wait_for_dram_init_complete() != 0) {
210 printf("dram init complete did not occur!!!\n");
211 printf("denali_core_search_data_eye!!!\n");
212 printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
213 "%d\n", wr_dqs_shift, dll_dqs_delay_X);
214 hang();
215 }
216 udelay(100); /* wait 100us to ensure init is really completed !!! */
217
218 /* write values */
219 for (j = 0; j < NUM_TRIES; j++) {
220 ram_pointer[j] = test[j];
221
222 /* clear any cache at ram location */
223 __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
224 }
225
226 /* read values back */
227 for (j = 0; j < NUM_TRIES; j++) {
228 for (k = 0; k < NUM_READS; k++) {
229 /* clear any cache at ram location */
230 __asm__("dcbf 0,%0": :"r"(&ram_pointer
231 [j]));
232
233 if (ram_pointer[j] != test[j])
234 break;
235 }
236
237 /* read error */
238 if (k != NUM_READS)
239 break;
240 }
241
242 /* See if the dll_dqs_delay_X value passed. */
243 mtdcr(ddrcfga, DDR0_00);
244 if (j < NUM_TRIES
245 || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
246 0x3F)) {
247 /* Failed */
248 passing_cases = 0;
249 /* break; */
250 } else {
251 /* Passed */
252 if (passing_cases == 0)
253 dll_dqs_delay_X_sw_val =
254 dll_dqs_delay_X;
255 passing_cases++;
256 if (passing_cases >= max_passing_cases) {
257 max_passing_cases = passing_cases;
258 wr_dqs_shift_with_max_passing_cases =
259 wr_dqs_shift;
260 dll_dqs_delay_X_start_window =
261 dll_dqs_delay_X_sw_val;
262 dll_dqs_delay_X_end_window =
263 dll_dqs_delay_X;
264 }
265 }
266
267 /* -----------------------------------------------------------+
268 * De-assert 'start' parameter.
269 * ----------------------------------------------------------*/
270 mtdcr(ddrcfga, DDR0_02);
271 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
272 DDR0_02_START_OFF;
273 mtdcr(ddrcfgd, val);
274 } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */
275 } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */
276
277 /* -----------------------------------------------------------+
278 * Largest passing window is now detected.
279 * ----------------------------------------------------------*/
280
281 /* Compute dll_dqs_delay_X value */
282 dll_dqs_delay_X = (dll_dqs_delay_X_end_window +
283 dll_dqs_delay_X_start_window) / 2;
284 wr_dqs_shift = wr_dqs_shift_with_max_passing_cases;
285
286 debug("DQS calibration - Window detected:\n");
287 debug("max_passing_cases = %d\n", max_passing_cases);
288 debug("wr_dqs_shift = %d\n", wr_dqs_shift);
289 debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X);
290 debug("dll_dqs_delay_X window = %d - %d\n",
291 dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window);
292
293 /* -----------------------------------------------------------+
294 * De-assert 'start' parameter.
295 * ----------------------------------------------------------*/
296 mtdcr(ddrcfga, DDR0_02);
297 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
298 mtdcr(ddrcfgd, val);
299
300 /* -----------------------------------------------------------+
301 * Set 'wr_dqs_shift'
302 * ----------------------------------------------------------*/
303 mtdcr(ddrcfga, DDR0_09);
304 val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK)
305 | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
306 mtdcr(ddrcfgd, val);
Marek Vasutc16d0542011-10-21 14:17:06 +0000307 debug("DDR0_09=0x%08x\n", val);
Larry Johnson41bf3642007-12-22 15:15:30 -0500308
309 /* -----------------------------------------------------------+
310 * Set 'dqs_out_shift' = wr_dqs_shift + 32
311 * ----------------------------------------------------------*/
312 dqs_out_shift = wr_dqs_shift + 32;
313 mtdcr(ddrcfga, DDR0_22);
314 val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK)
315 | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
316 mtdcr(ddrcfgd, val);
Marek Vasutc16d0542011-10-21 14:17:06 +0000317 debug("DDR0_22=0x%08x\n", val);
Larry Johnson41bf3642007-12-22 15:15:30 -0500318
319 /* -----------------------------------------------------------+
320 * Set 'dll_dqs_delay_X'.
321 * ----------------------------------------------------------*/
322 /* dll_dqs_delay_0 */
323 mtdcr(ddrcfga, DDR0_17);
324 val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
325 | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
326 mtdcr(ddrcfgd, val);
Marek Vasutc16d0542011-10-21 14:17:06 +0000327 debug("DDR0_17=0x%08x\n", val);
Larry Johnson41bf3642007-12-22 15:15:30 -0500328
329 /* dll_dqs_delay_1 to dll_dqs_delay_4 */
330 mtdcr(ddrcfga, DDR0_18);
331 val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
332 | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
333 | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
334 | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
335 | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
336 mtdcr(ddrcfgd, val);
Marek Vasutc16d0542011-10-21 14:17:06 +0000337 debug("DDR0_18=0x%08x\n", val);
Larry Johnson41bf3642007-12-22 15:15:30 -0500338
339 /* dll_dqs_delay_5 to dll_dqs_delay_8 */
340 mtdcr(ddrcfga, DDR0_19);
341 val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
342 | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
343 | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
344 | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
345 | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
346 mtdcr(ddrcfgd, val);
Marek Vasutc16d0542011-10-21 14:17:06 +0000347 debug("DDR0_19=0x%08x\n", val);
Larry Johnson41bf3642007-12-22 15:15:30 -0500348
349 /* -----------------------------------------------------------+
350 * Assert 'start' parameter.
351 * ----------------------------------------------------------*/
352 mtdcr(ddrcfga, DDR0_02);
353 val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
354 mtdcr(ddrcfgd, val);
355
356 sync();
357 eieio();
358
359 /* -----------------------------------------------------------+
360 * Wait for the DCC master delay line to finish calibration
361 * ----------------------------------------------------------*/
362 if (denali_wait_for_dlllock() != 0) {
363 printf("dll lock did not occur !!!\n");
364 hang();
365 }
366 sync();
367 eieio();
368
369 if (wait_for_dram_init_complete() != 0) {
370 printf("dram init complete did not occur !!!\n");
371 hang();
372 }
373 udelay(100); /* wait 100us to ensure init is really completed !!! */
374}
375#endif /* defined(CONFIG_DDR_DATA_EYE) */
376#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */