]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/x86/cpu/sc520/sc520_sdram.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
[karo-tx-uboot.git] / arch / x86 / cpu / sc520 / sc520_sdram.c
1 /*
2  * (C) Copyright 2010,2011
3  * Graeme Russ, <graeme.russ@gmail.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <asm/io.h>
26 #include <asm/processor-flags.h>
27 #include <asm/arch/sc520.h>
28
29 DECLARE_GLOBAL_DATA_PTR;
30
31 struct sc520_sdram_info {
32         u8 banks;
33         u8 columns;
34         u8 rows;
35         u8 size;
36 };
37
38 static void sc520_sizemem(void);
39 static void sc520_set_dram_timing(void);
40 static void sc520_set_dram_refresh_rate(void);
41 static void sc520_enable_dram_refresh(void);
42 static void sc520_enable_sdram(void);
43
44 int dram_init_f(void)
45 {
46         sc520_sizemem();
47         sc520_set_dram_timing();
48         sc520_set_dram_refresh_rate();
49         sc520_enable_dram_refresh();
50         sc520_enable_sdram();
51
52         return 0;
53 }
54
55 static inline void sc520_dummy_write(void)
56 {
57         writew(0x0000, CACHELINESZ);
58 }
59 static inline void sc520_issue_sdram_op_mode_select(u8 command)
60 {
61         writeb(command, &sc520_mmcr->drcctl);
62         sc520_dummy_write();
63 }
64
65 static inline int check_long(u32 test_long)
66 {
67         u8 i;
68         u8 tmp_byte = (u8)(test_long & 0x000000ff);
69
70         for (i = 1; i < 4; i++) {
71                 if ((u8)((test_long >> (i * 8)) & 0x000000ff) != tmp_byte)
72                                 return -1;
73         }
74
75         return 0;
76 }
77
78 static inline int write_and_test(u32 data, u32 address)
79 {
80         writel(data, address);
81         if (readl(address) == data)
82                 return 0; /* Good */
83         else
84                 return -1; /* Bad */
85 }
86
87 static void sc520_enable_sdram(void)
88 {
89         u32 par_config;
90
91         /* Enable Writes, Caching and Code Execution to SDRAM */
92         par_config = readl(&sc520_mmcr->par[3]);
93         par_config &= ~(SC520_PAR_EXEC_DIS |
94                         SC520_PAR_CACHE_DIS |
95                         SC520_PAR_WRITE_DIS);
96         writel(par_config, &sc520_mmcr->par[3]);
97
98         par_config = readl(&sc520_mmcr->par[4]);
99         par_config &= ~(SC520_PAR_EXEC_DIS |
100                         SC520_PAR_CACHE_DIS |
101                         SC520_PAR_WRITE_DIS);
102         writel(par_config, &sc520_mmcr->par[4]);
103 }
104
105 static void sc520_set_dram_timing(void)
106 {
107         u8 drctmctl = 0x00;
108
109 #if defined CONFIG_SYS_SDRAM_DRCTMCTL
110         /* just have your hardware designer _GIVE_ you what you need here! */
111         drctmctl = CONFIG_SYS_SDRAM_DRCTMCTL;
112 #else
113         switch (CONFIG_SYS_SDRAM_RAS_CAS_DELAY) {
114         case 2:
115                 break;
116         case 3:
117                 drctmctl |= 0x01;
118                 break;
119         case 4:
120         default:
121                 drctmctl |= 0x02;
122                 break;
123         }
124
125         switch (CONFIG_SYS_SDRAM_PRECHARGE_DELAY) {
126         case 2:
127                 break;
128         case 3:
129                 drctmctl |= 0x04;
130                 break;
131         case 4:
132         default:
133                 drctmctl |= 0x08;
134                 break;
135
136         case 6:
137                 drctmctl |= 0x0c;
138                 break;
139         }
140
141         switch (CONFIG_SYS_SDRAM_CAS_LATENCY) {
142         case 2:
143                 break;
144         case 3:
145         default:
146                 drctmctl |= 0x10;
147                 break;
148         }
149 #endif
150         writeb(drctmctl, &sc520_mmcr->drctmctl);
151
152         /* Issue load mode register command */
153         sc520_issue_sdram_op_mode_select(0x03);
154 }
155
156 static void sc520_set_dram_refresh_rate(void)
157 {
158         u8 drctl;
159
160         drctl = readb(&sc520_mmcr->drcctl);
161         drctl &= 0xcf;
162
163         switch (CONFIG_SYS_SDRAM_REFRESH_RATE) {
164         case 78:
165                 break;
166         case 156:
167         default:
168                 drctl |= 0x10;
169                 break;
170         case 312:
171                 drctl |= 0x20;
172                 break;
173         case 624:
174                 drctl |= 0x30;
175                 break;
176         }
177
178         writeb(drctl, &sc520_mmcr->drcctl);
179 }
180
181 static void sc520_enable_dram_refresh(void)
182 {
183         u8 drctl;
184
185         drctl = readb(&sc520_mmcr->drcctl);
186         drctl &= 0x30; /* keep refresh rate */
187         drctl |= 0x08; /* enable refresh, normal mode */
188
189         writeb(drctl, &sc520_mmcr->drcctl);
190 }
191
192 static void sc520_get_bank_info(int bank, struct sc520_sdram_info *bank_info)
193 {
194         u32 col_data;
195         u32 row_data;
196
197         u32 drcbendadr;
198         u16 drccfg;
199
200         u8 banks = 0x00;
201         u8 columns = 0x00;
202         u8 rows = 0x00;
203
204         bank_info->banks = 0x00;
205         bank_info->columns = 0x00;
206         bank_info->rows = 0x00;
207         bank_info->size = 0x00;
208
209         if ((bank < 0) || (bank > 3)) {
210                 printf("Bad Bank ID\n");
211                 return;
212         }
213
214         /* Save configuration */
215         drcbendadr = readl(&sc520_mmcr->drcbendadr);
216         drccfg = readw(&sc520_mmcr->drccfg);
217
218         /* Setup SDRAM Bank to largest possible size */
219         writew(0x000b << (bank * 4), &sc520_mmcr->drccfg);
220
221         /* Set ending address for this bank */
222         writel(0x000000ff << (bank * 8), &sc520_mmcr->drcbendadr);
223
224         /* write col 11 wrap adr */
225         if (write_and_test(COL11_DATA, COL11_ADR) != 0)
226                 goto restore_and_exit;
227
228         /* write col 10 wrap adr */
229         if (write_and_test(COL10_DATA, COL10_ADR) != 0)
230                 goto restore_and_exit;
231
232         /* write col 9 wrap adr */
233         if (write_and_test(COL09_DATA, COL09_ADR) != 0)
234                 goto restore_and_exit;
235
236         /* write col 8 wrap adr */
237         if (write_and_test(COL08_DATA, COL08_ADR) != 0)
238                 goto restore_and_exit;
239
240         col_data = readl(COL11_ADR);
241
242         /* All four bytes in the read long must be the same */
243         if (check_long(col_data) < 0)
244                 goto restore_and_exit;
245
246         if ((col_data >= COL08_DATA) && (col_data <= COL11_DATA))
247                 columns = (u8)(col_data & 0x000000ff);
248         else
249                 goto restore_and_exit;
250
251         /* write row 14 wrap adr */
252         if (write_and_test(ROW14_DATA, ROW14_ADR) != 0)
253                 goto restore_and_exit;
254
255         /* write row 13 wrap adr */
256         if (write_and_test(ROW13_DATA, ROW13_ADR) != 0)
257                 goto restore_and_exit;
258
259         /* write row 12 wrap adr */
260         if (write_and_test(ROW12_DATA, ROW12_ADR) != 0)
261                 goto restore_and_exit;
262
263         /* write row 11 wrap adr */
264         if (write_and_test(ROW11_DATA, ROW11_ADR) != 0)
265                 goto restore_and_exit;
266
267         if (write_and_test(ROW10_DATA, ROW10_ADR) != 0)
268                 goto restore_and_exit;
269
270         /*
271          * read data @ row 12 wrap adr to determine number of banks,
272          * and read data @ row 14 wrap adr to determine number of rows.
273          * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
274          * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
275          * if data @ row 12 wrap == 11 or 12, we have 4 banks,
276          */
277         row_data = readl(ROW12_ADR);
278
279         /* All four bytes in the read long must be the same */
280         if (check_long(row_data) != 0)
281                 goto restore_and_exit;
282
283         switch (row_data) {
284         case ROW10_DATA:
285                 banks = 2;
286                 break;
287
288         case ROW11_DATA:
289         case ROW12_DATA:
290                 banks = 4;
291                 break;
292
293         default:
294                 goto restore_and_exit;
295         }
296
297         row_data = readl(ROW14_ADR);
298
299         /* All four bytes in the read long must be the same */
300         if (check_long(row_data) != 0)
301                 goto restore_and_exit;
302
303         switch (row_data) {
304         case ROW11_DATA:
305         case ROW12_DATA:
306         case ROW13_DATA:
307         case ROW14_DATA:
308                 rows = (u8)(row_data & 0x000000ff);
309                 break;
310
311         default:
312                 goto restore_and_exit;
313         }
314
315         bank_info->banks = banks;
316         bank_info->columns = columns;
317         bank_info->rows = rows;
318
319         if ((bank_info->banks != 0) &&
320             (bank_info->columns != 0) &&
321             (bank_info->rows != 0)) {
322                 bank_info->size = bank_info->rows;
323                 bank_info->size >>= (11 - bank_info->columns);
324                 bank_info->size++;
325         }
326
327 restore_and_exit:
328         /* Restore configuration */
329         writel(drcbendadr, &sc520_mmcr->drcbendadr);
330         writew(drccfg, &sc520_mmcr->drccfg);
331 }
332
333 static void sc520_setup_sizemem(void)
334 {
335         u8 i;
336
337         /* Disable write buffer */
338         writeb(0x00, &sc520_mmcr->dbctl);
339
340         /* Disable ECC */
341         writeb(0x00, &sc520_mmcr->eccctl);
342
343         /* Set slowest SDRAM timing */
344         writeb(0x1e, &sc520_mmcr->drctmctl);
345
346         /* Issue a NOP to all SDRAM banks */
347         sc520_issue_sdram_op_mode_select(0x01);
348
349         /* Delay for 100 microseconds */
350         udelay(100);
351
352         /* Issue 'All Banks Precharge' command */
353         sc520_issue_sdram_op_mode_select(0x02);
354
355         /* Issue 2 'Auto Refresh Enable' command */
356         sc520_issue_sdram_op_mode_select(0x04);
357         sc520_dummy_write();
358
359         /* Issue 'Load Mode Register' command */
360         sc520_issue_sdram_op_mode_select(0x03);
361
362         /* Issue 8 more 'Auto Refresh Enable' commands */
363         sc520_issue_sdram_op_mode_select(0x04);
364         for (i = 0; i < 7; i++)
365                 sc520_dummy_write();
366
367         /* Set control register to 'Normal Mode' */
368         writeb(0x00, &sc520_mmcr->drcctl);
369 }
370
371 static void sc520_sizemem(void)
372 {
373         struct sc520_sdram_info sdram_info[4];
374         u8 bank_config = 0x00;
375         u8 end_addr = 0x00;
376         u16 drccfg = 0x0000;
377         u32 drcbendadr = 0x00000000;
378         u8 i;
379
380         /* Use PARs to disable caching of maximum allowable 256MB SDRAM */
381         writel(SC520_SDRAM1_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[3]);
382         writel(SC520_SDRAM2_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[4]);
383
384         sc520_setup_sizemem();
385
386         gd->ram_size = 0;
387
388         /* Size each SDRAM bank */
389         for (i = 0; i <= 3; i++) {
390                 sc520_get_bank_info(i, &sdram_info[i]);
391
392                 if (sdram_info[i].banks != 0) {
393                         /* Update Configuration register */
394                         bank_config = sdram_info[i].columns - 8;
395
396                         if (sdram_info[i].banks == 4)
397                                 bank_config |= 0x08;
398
399                         drccfg |= bank_config << (i * 4);
400
401                         /* Update End Address register */
402                         end_addr += sdram_info[i].size;
403                         drcbendadr |= (end_addr | 0x80) << (i * 8);
404
405                         gd->ram_size += sdram_info[i].size << 22;
406                 }
407
408                 /* Issue 'All Banks Precharge' command */
409                 sc520_issue_sdram_op_mode_select(0x02);
410
411                 /* Set control register to 'Normal Mode' */
412                 writeb(0x00, &sc520_mmcr->drcctl);
413         }
414
415         writel(drcbendadr, &sc520_mmcr->drcbendadr);
416         writew(drccfg, &sc520_mmcr->drccfg);
417
418         /* Clear PARs preventing caching of SDRAM */
419         writel(0x00000000, &sc520_mmcr->par[3]);
420         writel(0x00000000, &sc520_mmcr->par[4]);
421 }
422
423 int dram_init(void)
424 {
425         ulong dram_ctrl;
426         ulong dram_present = 0x00000000;
427
428         /*
429          * We read-back the configuration of the dram
430          * controller that the assembly code wrote
431          */
432         dram_ctrl = readl(&sc520_mmcr->drcbendadr);
433
434         gd->bd->bi_dram[0].start = 0;
435         if (dram_ctrl & 0x80) {
436                 /* bank 0 enabled */
437                 gd->bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
438                 dram_present = gd->bd->bi_dram[1].start;
439                 gd->bd->bi_dram[0].size = gd->bd->bi_dram[1].start;
440         } else {
441                 gd->bd->bi_dram[0].size = 0;
442                 gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
443         }
444
445         if (dram_ctrl & 0x8000) {
446                 /* bank 1 enabled */
447                 gd->bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
448                 dram_present = gd->bd->bi_dram[2].start;
449                 gd->bd->bi_dram[1].size = gd->bd->bi_dram[2].start -
450                                 gd->bd->bi_dram[1].start;
451         } else {
452                 gd->bd->bi_dram[1].size = 0;
453                 gd->bd->bi_dram[2].start = gd->bd->bi_dram[1].start;
454         }
455
456         if (dram_ctrl & 0x800000) {
457                 /* bank 2 enabled */
458                 gd->bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
459                 dram_present = gd->bd->bi_dram[3].start;
460                 gd->bd->bi_dram[2].size = gd->bd->bi_dram[3].start -
461                                 gd->bd->bi_dram[2].start;
462         } else {
463                 gd->bd->bi_dram[2].size = 0;
464                 gd->bd->bi_dram[3].start = gd->bd->bi_dram[2].start;
465         }
466
467         if (dram_ctrl & 0x80000000) {
468                 /* bank 3 enabled */
469                 dram_present  = (dram_ctrl & 0x7f000000) >> 2;
470                 gd->bd->bi_dram[3].size = dram_present -
471                                 gd->bd->bi_dram[3].start;
472         } else {
473                 gd->bd->bi_dram[3].size = 0;
474         }
475
476         gd->ram_size = dram_present;
477
478         return 0;
479 }