]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/sdram.c
Some code cleanup
[karo-tx-uboot.git] / cpu / ppc4xx / sdram.c
1 /*
2  * (C) Copyright 2005-2006
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
36 #ifdef CONFIG_SDRAM_BANK0
37
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
54 #ifndef CONFIG_440
55
56 #ifdef CFG_SDRAM_CASL
57 static ulong ns2clks(ulong ns)
58 {
59         ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
60
61         return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
62 }
63 #endif /* CFG_SDRAM_CASL */
64
65 static ulong compute_sdtr1(ulong speed)
66 {
67 #ifdef CFG_SDRAM_CASL
68         ulong tmp;
69         ulong sdtr1 = 0;
70
71         /* CASL */
72         if (CFG_SDRAM_CASL < 2)
73                 sdtr1 |= (1 << SDRAM0_TR_CASL);
74         else
75                 if (CFG_SDRAM_CASL > 4)
76                         sdtr1 |= (3 << SDRAM0_TR_CASL);
77                 else
78                         sdtr1 |= ((CFG_SDRAM_CASL-1) << SDRAM0_TR_CASL);
79
80         /* PTA */
81         tmp = ns2clks(CFG_SDRAM_PTA);
82         if ((tmp >= 2) && (tmp <= 4))
83                 sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
84         else
85                 sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
86
87         /* CTP */
88         tmp = ns2clks(CFG_SDRAM_CTP);
89         if ((tmp >= 2) && (tmp <= 4))
90                 sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
91         else
92                 sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
93
94         /* LDF */
95         tmp = ns2clks(CFG_SDRAM_LDF);
96         if ((tmp >= 2) && (tmp <= 4))
97                 sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
98         else
99                 sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
100
101         /* RFTA */
102         tmp = ns2clks(CFG_SDRAM_RFTA);
103         if ((tmp >= 4) && (tmp <= 10))
104                 sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
105         else
106                 sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
107
108         /* RCD */
109         tmp = ns2clks(CFG_SDRAM_RCD);
110         if ((tmp >= 2) && (tmp <= 4))
111                 sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
112         else
113                 sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
114
115         return sdtr1;
116 #else /* CFG_SDRAM_CASL */
117         /*
118          * If no values are configured in the board config file
119          * use the default values, which seem to be ok for most
120          * boards.
121          *
122          * REMARK:
123          * For new board ports we strongly recommend to define the
124          * correct values for the used SDRAM chips in your board
125          * config file (see PPChameleonEVB.h)
126          */
127         if (speed > 100000000) {
128                 /*
129                  * 133 MHz SDRAM
130                  */
131                 return 0x01074015;
132         } else {
133                 /*
134                  * default: 100 MHz SDRAM
135                  */
136                 return 0x0086400d;
137         }
138 #endif /* CFG_SDRAM_CASL */
139 }
140
141 /* refresh is expressed in ms */
142 static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
143 {
144 #ifdef CFG_SDRAM_CASL
145         ulong tmp;
146
147         tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
148         tmp /= 1000000;
149
150         return ((tmp & 0x00003FF8) << 16);
151 #else /* CFG_SDRAM_CASL */
152         if (speed > 100000000) {
153                 /*
154                  * 133 MHz SDRAM
155                  */
156                 return 0x07f00000;
157         } else {
158                 /*
159                  * default: 100 MHz SDRAM
160                  */
161                 return 0x05f00000;
162         }
163 #endif /* CFG_SDRAM_CASL */
164 }
165
166 /*
167  * Autodetect onboard SDRAM on 405 platforms
168  */
169 void sdram_init(void)
170 {
171         ulong speed;
172         ulong sdtr1;
173         int i;
174
175         /*
176          * Determine SDRAM speed
177          */
178         speed = get_bus_freq(0); /* parameter not used on ppc4xx */
179
180         /*
181          * sdtr1 (register SDRAM0_TR) must take into account timings listed
182          * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
183          * account actual SDRAM size. So we can set up sdtr1 according to what
184          * is specified in board configuration file while rtr dependds on SDRAM
185          * size we are assuming before detection.
186          */
187         sdtr1 = compute_sdtr1(speed);
188
189         for (i=0; i<N_MB0CF; i++) {
190                 /*
191                  * Disable memory controller.
192                  */
193                 mtsdram0(mem_mcopt1, 0x00000000);
194
195                 /*
196                  * Set MB0CF for bank 0.
197                  */
198                 mtsdram0(mem_mb0cf, mb0cf[i].reg);
199                 mtsdram0(mem_sdtr1, sdtr1);
200                 mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
201
202                 udelay(200);
203
204                 /*
205                  * Set memory controller options reg, MCOPT1.
206                  * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
207                  * read/prefetch.
208                  */
209                 mtsdram0(mem_mcopt1, 0x80800000);
210
211                 udelay(10000);
212
213                 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
214                         /*
215                          * OK, size detected -> all done
216                          */
217                         return;
218                 }
219         }
220 }
221
222 #else /* CONFIG_440 */
223
224 #define NUM_TRIES 64
225 #define NUM_READS 10
226
227 static void sdram_tr1_set(int ram_address, int* tr1_value)
228 {
229         int i;
230         int j, k;
231         volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
232         int first_good = -1, last_bad = 0x1ff;
233
234         unsigned long test[NUM_TRIES] = {
235                 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
236                 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
237                 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
238                 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
239                 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
240                 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
241                 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
242                 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
243                 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
244                 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
245                 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
246                 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
247                 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
248                 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
249                 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
250                 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
251
252         /* go through all possible SDRAM0_TR1[RDCT] values */
253         for (i=0; i<=0x1ff; i++) {
254                 /* set the current value for TR1 */
255                 mtsdram(mem_tr1, (0x80800800 | i));
256
257                 /* write values */
258                 for (j=0; j<NUM_TRIES; j++) {
259                         ram_pointer[j] = test[j];
260
261                         /* clear any cache at ram location */
262                         __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
263                 }
264
265                 /* read values back */
266                 for (j=0; j<NUM_TRIES; j++) {
267                         for (k=0; k<NUM_READS; k++) {
268                                 /* clear any cache at ram location */
269                                 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
270
271                                 if (ram_pointer[j] != test[j])
272                                         break;
273                         }
274
275                         /* read error */
276                         if (k != NUM_READS)
277                                 break;
278                 }
279
280                 /* we have a SDRAM0_TR1[RDCT] that is part of the window */
281                 if (j == NUM_TRIES) {
282                         if (first_good == -1)
283                                 first_good = i;         /* found beginning of window */
284                 } else { /* bad read */
285                         /* if we have not had a good read then don't care */
286                         if (first_good != -1) {
287                                 /* first failure after a good read */
288                                 last_bad = i-1;
289                                 break;
290                         }
291                 }
292         }
293
294         /* return the current value for TR1 */
295         *tr1_value = (first_good + last_bad) / 2;
296 }
297
298
299 #ifdef CONFIG_SDRAM_ECC
300 static void ecc_init(ulong start, ulong size)
301 {
302         ulong   current_addr;           /* current byte address */
303         ulong   end_addr;               /* end of memory region */
304         ulong   addr_inc;               /* address skip between writes */
305         ulong   cfg0_reg;               /* for restoring ECC state */
306
307         /*
308          * TODO: Enable dcache before running this test (speedup)
309          */
310
311         mfsdram(mem_cfg0, cfg0_reg);
312         mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN);
313
314         /*
315          * look at geometry of SDRAM (data width) to determine whether we
316          * can skip words when writing
317          */
318         if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32)
319                 addr_inc = 4;
320         else
321                 addr_inc = 8;
322
323         current_addr = start;
324         end_addr = start + size;
325
326         while (current_addr < end_addr) {
327                 *((ulong *)current_addr) = 0x00000000;
328                 current_addr += addr_inc;
329         }
330
331         /*
332          * TODO: Flush dcache and disable it again
333          */
334
335         /*
336          * Enable ecc checking and parity errors
337          */
338         mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK);
339 }
340 #endif
341
342 /*
343  * Autodetect onboard DDR SDRAM on 440 platforms
344  *
345  * NOTE: Some of the hardcoded values are hardware dependant,
346  *       so this should be extended for other future boards
347  *       using this routine!
348  */
349 long int initdram(int board_type)
350 {
351         int i;
352         int tr1_bank1;
353
354         for (i=0; i<N_MB0CF; i++) {
355                 /*
356                  * Disable memory controller.
357                  */
358                 mtsdram(mem_cfg0, 0x00000000);
359
360                 /*
361                  * Setup some default
362                  */
363                 mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default)             */
364                 mtsdram(mem_slio, 0x00000000);  /* rdre=0 wrre=0 rarw=0         */
365                 mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal)         */
366                 mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0                */
367                 mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0    */
368
369                 /*
370                  * Following for CAS Latency = 2.5 @ 133 MHz PLB
371                  */
372                 mtsdram(mem_b0cr, mb0cf[i].reg);
373                 mtsdram(mem_tr0, 0x41094012);
374                 mtsdram(mem_tr1, 0x80800800);   /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
375                 mtsdram(mem_rtr, 0x7e000000);   /* Interval 15.20µs @ 133MHz PLB*/
376                 mtsdram(mem_cfg1, 0x00000000);  /* Self-refresh exit, disable PM*/
377                 udelay(400);                    /* Delay 200 usecs (min)        */
378
379                 /*
380                  * Enable the controller, then wait for DCEN to complete
381                  */
382                 mtsdram(mem_cfg0, 0x86000000);  /* DCEN=1, PMUD=1, 64-bit       */
383                 udelay(10000);
384
385                 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
386                         /*
387                          * Optimize TR1 to current hardware environment
388                          */
389                         sdram_tr1_set(0x00000000, &tr1_bank1);
390                         mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
391
392 #ifdef CONFIG_SDRAM_ECC
393                         ecc_init(0, mb0cf[i].size);
394 #endif
395
396                         /*
397                          * OK, size detected -> all done
398                          */
399                         return mb0cf[i].size;
400                 }
401         }
402
403         return 0;                               /* nothing found !              */
404 }
405
406 #endif /* CONFIG_440 */
407
408 #endif /* CONFIG_SDRAM_BANK0 */