ppc4xx: Add support for AMCC 405EP Taihu board
[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.  Enable second bank if
213                          * defined (assumes same type as bank 0)
214                          */
215 #ifdef CONFIG_SDRAM_BANK1
216                         u32 b1cr = mb0cf[i].size | mb0cf[i].reg;
217
218                         mtsdram0(mem_mcopt1, 0x00000000);
219                         mtsdram0(mem_mb1cf, b1cr); /* SDRAM0_B1CR */
220                         mtsdram0(mem_mcopt1, 0x80800000);
221                         udelay(10000);
222 #endif
223                         return;
224                 }
225         }
226 }
227
228 #else /* CONFIG_440 */
229
230 /*
231  * Define some default values. Those can be overwritten in the
232  * board config file.
233  */
234
235 #ifndef CFG_SDRAM_TABLE
236 sdram_conf_t mb0cf[] = {
237         {(256 << 20), 13, 0x000C4001},  /* 256MB mode 3, 13x10(4)       */
238         {(64 << 20),  12, 0x00082001}   /* 64MB mode 2, 12x9(4)         */
239 };
240 #else
241 sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
242 #endif
243
244 #ifndef CFG_SDRAM0_TR0
245 #define CFG_SDRAM0_TR0          0x41094012
246 #endif
247
248 #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
249
250 #define NUM_TRIES 64
251 #define NUM_READS 10
252
253 static void sdram_tr1_set(int ram_address, int* tr1_value)
254 {
255         int i;
256         int j, k;
257         volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
258         int first_good = -1, last_bad = 0x1ff;
259
260         unsigned long test[NUM_TRIES] = {
261                 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
262                 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
263                 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
264                 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
265                 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
266                 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
267                 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
268                 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
269                 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
270                 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
271                 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
272                 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
273                 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
274                 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
275                 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
276                 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
277
278         /* go through all possible SDRAM0_TR1[RDCT] values */
279         for (i=0; i<=0x1ff; i++) {
280                 /* set the current value for TR1 */
281                 mtsdram(mem_tr1, (0x80800800 | i));
282
283                 /* write values */
284                 for (j=0; j<NUM_TRIES; j++) {
285                         ram_pointer[j] = test[j];
286
287                         /* clear any cache at ram location */
288                         __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
289                 }
290
291                 /* read values back */
292                 for (j=0; j<NUM_TRIES; j++) {
293                         for (k=0; k<NUM_READS; k++) {
294                                 /* clear any cache at ram location */
295                                 __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
296
297                                 if (ram_pointer[j] != test[j])
298                                         break;
299                         }
300
301                         /* read error */
302                         if (k != NUM_READS)
303                                 break;
304                 }
305
306                 /* we have a SDRAM0_TR1[RDCT] that is part of the window */
307                 if (j == NUM_TRIES) {
308                         if (first_good == -1)
309                                 first_good = i;         /* found beginning of window */
310                 } else { /* bad read */
311                         /* if we have not had a good read then don't care */
312                         if (first_good != -1) {
313                                 /* first failure after a good read */
314                                 last_bad = i-1;
315                                 break;
316                         }
317                 }
318         }
319
320         /* return the current value for TR1 */
321         *tr1_value = (first_good + last_bad) / 2;
322 }
323
324 #ifdef CONFIG_SDRAM_ECC
325 static void ecc_init(ulong start, ulong size)
326 {
327         ulong   current_addr;           /* current byte address */
328         ulong   end_addr;               /* end of memory region */
329         ulong   addr_inc;               /* address skip between writes */
330         ulong   cfg0_reg;               /* for restoring ECC state */
331
332         /*
333          * TODO: Enable dcache before running this test (speedup)
334          */
335
336         mfsdram(mem_cfg0, cfg0_reg);
337         mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN);
338
339         /*
340          * look at geometry of SDRAM (data width) to determine whether we
341          * can skip words when writing
342          */
343         if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32)
344                 addr_inc = 4;
345         else
346                 addr_inc = 8;
347
348         current_addr = start;
349         end_addr = start + size;
350
351         while (current_addr < end_addr) {
352                 *((ulong *)current_addr) = 0x00000000;
353                 current_addr += addr_inc;
354         }
355
356         /*
357          * TODO: Flush dcache and disable it again
358          */
359
360         /*
361          * Enable ecc checking and parity errors
362          */
363         mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK);
364 }
365 #endif
366
367 /*
368  * Autodetect onboard DDR SDRAM on 440 platforms
369  *
370  * NOTE: Some of the hardcoded values are hardware dependant,
371  *       so this should be extended for other future boards
372  *       using this routine!
373  */
374 long int initdram(int board_type)
375 {
376         int i;
377         int tr1_bank1;
378
379 #if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
380     defined(CONFIG_440GR) || defined(CONFIG_440SP)
381         /*
382          * Soft-reset SDRAM controller.
383          */
384         mtsdr(sdr_srst, SDR0_SRST_DMC);
385         mtsdr(sdr_srst, 0x00000000);
386 #endif
387
388         for (i=0; i<N_MB0CF; i++) {
389                 /*
390                  * Disable memory controller.
391                  */
392                 mtsdram(mem_cfg0, 0x00000000);
393
394                 /*
395                  * Setup some default
396                  */
397                 mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default)             */
398                 mtsdram(mem_slio, 0x00000000);  /* rdre=0 wrre=0 rarw=0         */
399                 mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal)         */
400                 mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0                */
401                 mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0    */
402
403                 /*
404                  * Following for CAS Latency = 2.5 @ 133 MHz PLB
405                  */
406                 mtsdram(mem_b0cr, mb0cf[i].reg);
407                 mtsdram(mem_tr0, CFG_SDRAM0_TR0);
408                 mtsdram(mem_tr1, 0x80800800);   /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
409                 mtsdram(mem_rtr, 0x04100000);   /* Interval 7.8µs @ 133MHz PLB  */
410                 mtsdram(mem_cfg1, 0x00000000);  /* Self-refresh exit, disable PM*/
411                 udelay(400);                    /* Delay 200 usecs (min)        */
412
413                 /*
414                  * Enable the controller, then wait for DCEN to complete
415                  */
416                 mtsdram(mem_cfg0, 0x82000000);  /* DCEN=1, PMUD=0, 64-bit       */
417                 udelay(10000);
418
419                 if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
420                         /*
421                          * Optimize TR1 to current hardware environment
422                          */
423                         sdram_tr1_set(0x00000000, &tr1_bank1);
424                         mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
425
426 #ifdef CONFIG_SDRAM_ECC
427                         ecc_init(0, mb0cf[i].size);
428 #endif
429
430                         /*
431                          * OK, size detected -> all done
432                          */
433                         return mb0cf[i].size;
434                 }
435         }
436
437         return 0;                               /* nothing found !              */
438 }
439
440 #endif /* CONFIG_440 */
441
442 #endif /* CONFIG_SDRAM_BANK0 */