Coding style cleanup
[platform/kernel/u-boot.git] / cpu / ppc4xx / sdram.c
1 /*
2  * (C) Copyright 2005-2007
3  * Stefan Roese, DENX Software Engineering, sr@denx.de.
4  *
5  * (C) Copyright 2006
6  * DAVE Srl <www.dave-tech.it>
7  *
8  * (C) Copyright 2002-2004
9  * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
10  *
11  * See file CREDITS for list of people who contributed to this
12  * project.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of
17  * the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27  * MA 02111-1307 USA
28  */
29
30 #include <common.h>
31 #include <ppc4xx.h>
32 #include <asm/processor.h>
33 #include "sdram.h"
34
35 #ifdef CONFIG_SDRAM_BANK0
36
37 #ifndef CONFIG_440
38
39 #ifndef CFG_SDRAM_TABLE
40 sdram_conf_t mb0cf[] = {
41         {(128 << 20), 13, 0x000A4001},      /* (0-128MB) Address Mode 3, 13x10(4) */
42         {(64 << 20),  13, 0x00084001},      /* (0-64MB) Address Mode 3, 13x9(4)   */
43         {(32 << 20),  12, 0x00062001},      /* (0-32MB) Address Mode 2, 12x9(4)   */
44         {(16 << 20),  12, 0x00046001},      /* (0-16MB) Address Mode 4, 12x8(4)   */
45         {(4 << 20),   11, 0x00008001},      /* (0-4MB) Address Mode 5, 11x8(2)    */
46 };
47 #else
48 sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
49 #endif
50
51 #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
52
53 #ifdef CFG_SDRAM_CASL
54 static ulong ns2clks(ulong ns)
55 {
56         ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
57
58         return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
59 }
60 #endif /* CFG_SDRAM_CASL */
61
62 static ulong compute_sdtr1(ulong speed)
63 {
64 #ifdef CFG_SDRAM_CASL
65         ulong tmp;
66         ulong sdtr1 = 0;
67
68         /* CASL */
69         if (CFG_SDRAM_CASL < 2)
70                 sdtr1 |= (1 << SDRAM0_TR_CASL);
71         else
72                 if (CFG_SDRAM_CASL > 4)
73                         sdtr1 |= (3 << SDRAM0_TR_CASL);
74                 else
75                         sdtr1 |= ((CFG_SDRAM_CASL-1) << SDRAM0_TR_CASL);
76
77         /* PTA */
78         tmp = ns2clks(CFG_SDRAM_PTA);
79         if ((tmp >= 2) && (tmp <= 4))
80                 sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
81         else
82                 sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
83
84         /* CTP */
85         tmp = ns2clks(CFG_SDRAM_CTP);
86         if ((tmp >= 2) && (tmp <= 4))
87                 sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
88         else
89                 sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
90
91         /* LDF */
92         tmp = ns2clks(CFG_SDRAM_LDF);
93         if ((tmp >= 2) && (tmp <= 4))
94                 sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
95         else
96                 sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
97
98         /* RFTA */
99         tmp = ns2clks(CFG_SDRAM_RFTA);
100         if ((tmp >= 4) && (tmp <= 10))
101                 sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
102         else
103                 sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
104
105         /* RCD */
106         tmp = ns2clks(CFG_SDRAM_RCD);
107         if ((tmp >= 2) && (tmp <= 4))
108                 sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
109         else
110                 sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
111
112         return sdtr1;
113 #else /* CFG_SDRAM_CASL */
114         /*
115          * If no values are configured in the board config file
116          * use the default values, which seem to be ok for most
117          * boards.
118          *
119          * REMARK:
120          * For new board ports we strongly recommend to define the
121          * correct values for the used SDRAM chips in your board
122          * config file (see PPChameleonEVB.h)
123          */
124         if (speed > 100000000) {
125                 /*
126                  * 133 MHz SDRAM
127                  */
128                 return 0x01074015;
129         } else {
130                 /*
131                  * default: 100 MHz SDRAM
132                  */
133                 return 0x0086400d;
134         }
135 #endif /* CFG_SDRAM_CASL */
136 }
137
138 /* refresh is expressed in ms */
139 static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
140 {
141 #ifdef CFG_SDRAM_CASL
142         ulong tmp;
143
144         tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
145         tmp /= 1000000;
146
147         return ((tmp & 0x00003FF8) << 16);
148 #else /* CFG_SDRAM_CASL */
149         if (speed > 100000000) {
150                 /*
151                  * 133 MHz SDRAM
152                  */
153                 return 0x07f00000;
154         } else {
155                 /*
156                  * default: 100 MHz SDRAM
157                  */
158                 return 0x05f00000;
159         }
160 #endif /* CFG_SDRAM_CASL */
161 }
162
163 /*
164  * Autodetect onboard SDRAM on 405 platforms
165  */
166 void sdram_init(void)
167 {
168         ulong speed;
169         ulong sdtr1;
170         int i;
171
172         /*
173          * Determine SDRAM speed
174          */
175         speed = get_bus_freq(0); /* parameter not used on ppc4xx */
176
177         /*
178          * sdtr1 (register SDRAM0_TR) must take into account timings listed
179          * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
180          * account actual SDRAM size. So we can set up sdtr1 according to what
181          * is specified in board configuration file while rtr dependds on SDRAM
182          * size we are assuming before detection.
183          */
184         sdtr1 = compute_sdtr1(speed);
185
186         for (i=0; i<N_MB0CF; i++) {
187                 /*
188                  * Disable memory controller.
189                  */
190                 mtsdram0(mem_mcopt1, 0x00000000);
191
192                 /*
193                  * Set MB0CF for bank 0.
194                  */
195                 mtsdram0(mem_mb0cf, mb0cf[i].reg);
196                 mtsdram0(mem_sdtr1, sdtr1);
197                 mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
198
199                 udelay(200);
200
201                 /*
202                  * Set memory controller options reg, MCOPT1.
203                  * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
204                  * read/prefetch.
205                  */
206                 mtsdram0(mem_mcopt1, 0x80800000);
207
208                 udelay(10000);
209
210                 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
211                         /*
212                          * OK, size detected -> all done
213                          */
214                         return;
215                 }
216         }
217 }
218
219 #else /* CONFIG_440 */
220
221 /*
222  * Define some default values. Those can be overwritten in the
223  * board config file.
224  */
225
226 #ifndef CFG_SDRAM_TABLE
227 sdram_conf_t mb0cf[] = {
228         {(256 << 20), 13, 0x000C4001},  /* 256MB mode 3, 13x10(4)       */
229         {(64 << 20),  12, 0x00082001}   /* 64MB mode 2, 12x9(4)         */
230 };
231 #else
232 sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
233 #endif
234
235 #ifndef CFG_SDRAM0_TR0
236 #define CFG_SDRAM0_TR0          0x41094012
237 #endif
238
239 #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
240
241 #define NUM_TRIES 64
242 #define NUM_READS 10
243
244 static void sdram_tr1_set(int ram_address, int* tr1_value)
245 {
246         int i;
247         int j, k;
248         volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
249         int first_good = -1, last_bad = 0x1ff;
250
251         unsigned long test[NUM_TRIES] = {
252                 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
253                 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
254                 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
255                 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
256                 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
257                 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
258                 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
259                 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
260                 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
261                 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
262                 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
263                 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
264                 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
265                 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
266                 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
267                 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
268
269         /* go through all possible SDRAM0_TR1[RDCT] values */
270         for (i=0; i<=0x1ff; i++) {
271                 /* set the current value for TR1 */
272                 mtsdram(mem_tr1, (0x80800800 | i));
273
274                 /* write values */
275                 for (j=0; j<NUM_TRIES; j++) {
276                         ram_pointer[j] = test[j];
277
278                         /* clear any cache at ram location */
279                         __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
280                 }
281
282                 /* read values back */
283                 for (j=0; j<NUM_TRIES; j++) {
284                         for (k=0; k<NUM_READS; k++) {
285                                 /* clear any cache at ram location */
286                                 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
287
288                                 if (ram_pointer[j] != test[j])
289                                         break;
290                         }
291
292                         /* read error */
293                         if (k != NUM_READS)
294                                 break;
295                 }
296
297                 /* we have a SDRAM0_TR1[RDCT] that is part of the window */
298                 if (j == NUM_TRIES) {
299                         if (first_good == -1)
300                                 first_good = i;         /* found beginning of window */
301                 } else { /* bad read */
302                         /* if we have not had a good read then don't care */
303                         if (first_good != -1) {
304                                 /* first failure after a good read */
305                                 last_bad = i-1;
306                                 break;
307                         }
308                 }
309         }
310
311         /* return the current value for TR1 */
312         *tr1_value = (first_good + last_bad) / 2;
313 }
314
315 #ifdef CONFIG_SDRAM_ECC
316 static void ecc_init(ulong start, ulong size)
317 {
318         ulong   current_addr;           /* current byte address */
319         ulong   end_addr;               /* end of memory region */
320         ulong   addr_inc;               /* address skip between writes */
321         ulong   cfg0_reg;               /* for restoring ECC state */
322
323         /*
324          * TODO: Enable dcache before running this test (speedup)
325          */
326
327         mfsdram(mem_cfg0, cfg0_reg);
328         mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN);
329
330         /*
331          * look at geometry of SDRAM (data width) to determine whether we
332          * can skip words when writing
333          */
334         if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32)
335                 addr_inc = 4;
336         else
337                 addr_inc = 8;
338
339         current_addr = start;
340         end_addr = start + size;
341
342         while (current_addr < end_addr) {
343                 *((ulong *)current_addr) = 0x00000000;
344                 current_addr += addr_inc;
345         }
346
347         /*
348          * TODO: Flush dcache and disable it again
349          */
350
351         /*
352          * Enable ecc checking and parity errors
353          */
354         mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK);
355 }
356 #endif
357
358 /*
359  * Autodetect onboard DDR SDRAM on 440 platforms
360  *
361  * NOTE: Some of the hardcoded values are hardware dependant,
362  *       so this should be extended for other future boards
363  *       using this routine!
364  */
365 long int initdram(int board_type)
366 {
367         int i;
368         int tr1_bank1;
369
370 #if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
371     defined(CONFIG_440GR) || defined(CONFIG_440SP)
372         /*
373          * Soft-reset SDRAM controller.
374          */
375         mtsdr(sdr_srst, SDR0_SRST_DMC);
376         mtsdr(sdr_srst, 0x00000000);
377 #endif
378
379         for (i=0; i<N_MB0CF; i++) {
380                 /*
381                  * Disable memory controller.
382                  */
383                 mtsdram(mem_cfg0, 0x00000000);
384
385                 /*
386                  * Setup some default
387                  */
388                 mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default)             */
389                 mtsdram(mem_slio, 0x00000000);  /* rdre=0 wrre=0 rarw=0         */
390                 mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal)         */
391                 mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0                */
392                 mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0    */
393
394                 /*
395                  * Following for CAS Latency = 2.5 @ 133 MHz PLB
396                  */
397                 mtsdram(mem_b0cr, mb0cf[i].reg);
398                 mtsdram(mem_tr0, CFG_SDRAM0_TR0);
399                 mtsdram(mem_tr1, 0x80800800);   /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
400                 mtsdram(mem_rtr, 0x04100000);   /* Interval 7.8µs @ 133MHz PLB  */
401                 mtsdram(mem_cfg1, 0x00000000);  /* Self-refresh exit, disable PM*/
402                 udelay(400);                    /* Delay 200 usecs (min)        */
403
404                 /*
405                  * Enable the controller, then wait for DCEN to complete
406                  */
407                 mtsdram(mem_cfg0, 0x82000000);  /* DCEN=1, PMUD=0, 64-bit       */
408                 udelay(10000);
409
410                 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
411                         /*
412                          * Optimize TR1 to current hardware environment
413                          */
414                         sdram_tr1_set(0x00000000, &tr1_bank1);
415                         mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
416
417 #ifdef CONFIG_SDRAM_ECC
418                         ecc_init(0, mb0cf[i].size);
419 #endif
420
421                         /*
422                          * OK, size detected -> all done
423                          */
424                         return mb0cf[i].size;
425                 }
426         }
427
428         return 0;                               /* nothing found !              */
429 }
430
431 #endif /* CONFIG_440 */
432
433 #endif /* CONFIG_SDRAM_BANK0 */