]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/denali_data_eye.c
Merge branch 'katmai-ddr-gda'
[karo-tx-uboot.git] / cpu / ppc4xx / denali_data_eye.c
1 /*
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  +----------------------------------------------------------------------------*/
45 int 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  +----------------------------------------------------------------------------*/
73 static 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  */
106 void denali_core_search_data_eye(void)
107     __attribute__ ((weak, alias("__denali_core_search_data_eye")));
108
109 void __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) */