Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / northbridge / amd / gx1 / raminit.c
1 #include <cpu/amd/gx1def.h>
2
3 /*
4 This software and ancillary information (herein called SOFTWARE )
5 called LinuxBIOS          is made available under the terms described
6 here.  The SOFTWARE has been approved for release with associated
7 LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
8 been authored by an employee or employees of the University of
9 California, operator of the Los Alamos National Laboratory under
10 Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
11 U.S. Government has rights to use, reproduce, and distribute this
12 SOFTWARE.  The public may copy, distribute, prepare derivative works
13 and publicly display this SOFTWARE without charge, provided that this
14 Notice and any statement of authorship are reproduced on all copies.
15 Neither the Government nor the University makes any warranty, express
16 or implied, or assumes any liability or responsibility for the use of
17 this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
18 such modified SOFTWARE should be clearly marked, so as not to confuse
19 it with the version available from LANL.
20  */
21 /* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
22  * rminnich@lanl.gov
23  */
24
25 /*      SDRAM initialization for GX1 - translated from Christer Weinigel's
26         assembler version into C.
27
28         Hamish Guthrie 10/4/2005 hamish@prodigi.ch
29 */
30
31 #define NUM_REFRESH 8
32 #define TEST_DATA1 0x05A5A5A5A
33 #define TEST_DATA2 0x0DEADBEEF
34
35 void setGX1Mem(unsigned int addr, unsigned int data)
36 {
37         write32(addr, data);
38 }
39
40 unsigned int getGX1Mem(unsigned int addr)
41 {
42         return (unsigned int)read32(addr);
43 }
44
45 void do_refresh(void)
46 {
47 unsigned int tval, i;
48
49         outb(0x71, 0x80);
50         tval = getGX1Mem(GX_BASE + MC_MEM_CNTRL1);
51         tval |= RFSHTST;
52         for(i=0; i>NUM_REFRESH; i++)
53                 setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
54         outb(0x72, 0x80);
55 }
56
57
58 void enable_dimm(void)
59 {
60 unsigned int tval, i;
61
62         outb(0x73, 0x80);
63
64         /* start SDCLCK's */
65         tval = getGX1Mem(GX_BASE + MC_MEM_CNTRL1);
66         tval &= ~SDCLKSTRT;
67         setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
68         tval |= SDCLKSTRT;
69         setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
70
71         /* Unmask SDCLK's */
72         tval = getGX1Mem(GX_BASE + MC_MEM_CNTRL2);
73         tval &= ~(SDCLK_MASK | SDCLKOUT_MASK);
74         setGX1Mem(GX_BASE + MC_MEM_CNTRL2, tval);
75         tval = getGX1Mem(GX_BASE + MC_MEM_CNTRL2);
76
77         /* Wait for clocks to unmask */
78         for(i=0; i<5000; i++)
79                 outb(0, 0xed);
80
81         /* Refresh memory */
82         tval = getGX1Mem(GX_BASE + MC_MEM_CNTRL1);
83         tval |= RFSHTST;
84         for(i=0; i<NUM_REFRESH; i++)
85                 setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
86         tval &= ~RFSHTST;
87
88         /* Start the SDCLK's */
89         tval &= ~PROGRAM_SDRAM;
90         setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
91         tval |= PROGRAM_SDRAM | 0x00002000;   /* Set refresh timing */
92         setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
93         tval &= ~PROGRAM_SDRAM;
94         setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
95
96         /* Refresh memory again */
97         tval = getGX1Mem(GX_BASE + MC_MEM_CNTRL1);
98         tval |= RFSHTST;
99         for(i=0; i>NUM_REFRESH; i++)
100                 setGX1Mem(GX_BASE + MC_MEM_CNTRL1, tval);
101
102         for(i=0; i<2000; i++)
103                 outb(0, 0xed);
104         outb(0x74, 0x80);
105 }
106
107 static unsigned int size_dimm(int dimm_shift)
108 {
109 int bank_cfg = 0x700;           /* MC_BANK_CFG for 512M */
110 unsigned int offset = 0x10000000;       /* Offset 256M */
111 int failed_flag = 1;
112
113         do {
114                 setGX1Mem(0, TEST_DATA1);
115                 setGX1Mem(offset, TEST_DATA2);
116                 setGX1Mem(0x100, 0);            /* Clear the bus */
117                 if (getGX1Mem(0) != TEST_DATA1) {
118                         setGX1Mem(GX_BASE + MC_BANK_CFG,
119                                 getGX1Mem(GX_BASE + MC_BANK_CFG) & ~(DIMM_SZ << dimm_shift));
120                         bank_cfg -= 0x100;
121                         setGX1Mem(GX_BASE + MC_BANK_CFG,
122                                 getGX1Mem(GX_BASE + MC_BANK_CFG) | (bank_cfg << dimm_shift));
123                         do_refresh();
124                         offset >>= 1;
125                 } else {
126                         failed_flag = 0;
127                         break;
128                 }
129         } while (bank_cfg >= 0);
130
131         if (failed_flag)
132                 return (0x0070 << dimm_shift);
133         else
134                 return(getGX1Mem(GX_BASE + MC_BANK_CFG) & (DIMM_SZ << dimm_shift));
135
136 }
137
138 static unsigned int module_banks(int dimm_shift)
139 {
140 int page_size = 0x800;                  /* Smallest page = 1K * 2 banks */
141 int comp_banks;
142
143 #if 0
144         print_debug("MC_BANK_CFG = ");
145         print_debug_hex32(getGX1Mem(GX_BASE + MC_BANK_CFG));
146         print_debug("\n");
147 #endif
148
149         /* retrieve the page size from the MC register */
150         page_size <<= (((getGX1Mem(GX_BASE + MC_BANK_CFG) & (DIMM_PG_SZ << dimm_shift)) >> dimm_shift) >> 4);
151
152 #if 0
153         print_debug("    page_size = ");
154         print_debug_hex32(page_size);
155         print_debug("\n");
156 #endif
157
158         comp_banks = (((getGX1Mem(GX_BASE + MC_BANK_CFG) & (DIMM_COMP_BNK << dimm_shift)) >> dimm_shift) >> 12);
159         page_size <<= comp_banks;
160
161         setGX1Mem(0, TEST_DATA1);
162         setGX1Mem(page_size, TEST_DATA2);
163         setGX1Mem(0x100, 0);            /* Clear the bus */
164         if (getGX1Mem(page_size) != TEST_DATA2) {
165                 setGX1Mem(GX_BASE + MC_BANK_CFG,
166                           getGX1Mem(GX_BASE + MC_BANK_CFG) & ~(DIMM_MOD_BNK << dimm_shift));
167                 do_refresh();
168         }
169 #if 0
170         print_debug("MC_BANK_CFG = ");
171         print_debug_hex32(getGX1Mem(GX_BASE + MC_BANK_CFG));
172         print_debug("\n");
173 #endif
174         return(getGX1Mem(GX_BASE + MC_BANK_CFG) & (DIMM_MOD_BNK << dimm_shift));
175 }
176
177 static unsigned int component_banks(int dimm_shift)
178 {
179 int page_size = 0x800;                  /* Smallest page = 1K * 2 banks */
180
181 #if 0
182         print_debug("MC_BANK_CFG = ");
183         print_debug_hex32(getGX1Mem(GX_BASE + MC_BANK_CFG));
184         print_debug("\n");
185 #endif
186
187         page_size = page_size << (((getGX1Mem(GX_BASE + MC_BANK_CFG) & (DIMM_PG_SZ << dimm_shift)) >> dimm_shift) >> 4);
188
189 #if 0
190         print_debug("    page_size = ");
191         print_debug_hex32(page_size);
192         print_debug("\n");
193 #endif
194
195         setGX1Mem(0, TEST_DATA1);
196         setGX1Mem(page_size, TEST_DATA2);
197         setGX1Mem(0x100, 0);            /* Clear the bus */
198         if (getGX1Mem(0) != TEST_DATA1) {
199                 setGX1Mem(GX_BASE + MC_BANK_CFG,
200                           getGX1Mem(GX_BASE + MC_BANK_CFG) & ~(DIMM_COMP_BNK << dimm_shift));
201                 do_refresh();
202         }
203 #if 0
204         print_debug("MC_BANK_CFG = ");
205         print_debug_hex32(getGX1Mem(GX_BASE + MC_BANK_CFG));
206         print_debug("\n");
207 #endif
208         return(getGX1Mem(GX_BASE + MC_BANK_CFG) & (DIMM_COMP_BNK << dimm_shift));
209 }
210
211 static unsigned int page_size(int dimm_shift)
212 {
213 unsigned int page_test_offset = 0x2000;
214 unsigned int temp;
215 int page_size_config = 0x40;
216 unsigned int probe_config;
217
218         do {
219                 setGX1Mem(0, TEST_DATA1);
220                 setGX1Mem(page_test_offset, TEST_DATA2);
221                 setGX1Mem(0x100, 0);
222                 temp = getGX1Mem(0);
223                 setGX1Mem(0, 0);
224                 if(temp == TEST_DATA1) {
225 #if 0
226                         print_debug("    Page size Config = ");
227                         print_debug_hex32(page_size_config << dimm_shift);
228                         print_debug("\n");
229 #endif
230                         return(page_size_config << dimm_shift);
231                         }
232
233                 temp = ~(DIMM_PG_SZ << dimm_shift);
234
235                 probe_config = getGX1Mem(GX_BASE + MC_BANK_CFG);
236                 probe_config &= temp;
237
238                 page_size_config -= 0x10;
239                 page_size_config <<= dimm_shift;
240
241                 probe_config |= page_size_config;
242
243                 page_size_config >>= dimm_shift;
244
245                 page_test_offset >>= 1;
246
247                 setGX1Mem(GX_BASE + MC_BANK_CFG, probe_config);
248                 do_refresh();
249         } while (page_size_config >= 0);
250
251         return 0x70;
252 }
253
254 static int dimm_detect(int dimm_shift)
255 {
256 unsigned int test;
257
258         print_debug("Probing for DIMM");
259         print_debug_char((dimm_shift >> 4) + 0x30);
260         print_debug("\n");
261
262         setGX1Mem(0, TEST_DATA1);
263         setGX1Mem(0x100, 0);
264         test = getGX1Mem(0);
265         setGX1Mem(0, 0);
266
267         if (test != TEST_DATA1)
268                 return 0;
269
270         print_debug("    Found DIMM");
271         print_debug_char((dimm_shift >> 4) + 0x30);
272         print_debug("\n");
273
274         return 1;
275 }
276
277 static int size_memory(int dimm_shift, unsigned int mem_config)
278 {
279
280         if (!dimm_detect(dimm_shift))
281                 return (mem_config);
282
283         mem_config &= (~(DIMM_PG_SZ << dimm_shift));
284         mem_config |= (page_size(dimm_shift));
285
286         print_debug("    Page Size:       ");
287         print_debug_hex32(0x400 << ((mem_config & (DIMM_PG_SZ << dimm_shift)) >> (dimm_shift + 4)));
288         print_debug("\n");
289
290         /* Now do component banks detection */
291
292         mem_config &= (~(DIMM_COMP_BNK << dimm_shift));
293         mem_config |= (component_banks(dimm_shift));
294
295         print_debug("    Component Banks: ");
296         print_debug_char((((mem_config & (DIMM_COMP_BNK << dimm_shift)) >> (dimm_shift + 12)) ? 4 : 2) + 0x30);
297         print_debug("\n");
298
299         /* Now do module banks */
300
301         mem_config &= (~(DIMM_MOD_BNK << dimm_shift));
302         mem_config |= (module_banks(dimm_shift));
303
304         print_debug("    Module Banks:    ");
305         print_debug_char((((mem_config & (DIMM_MOD_BNK << dimm_shift)) >> (dimm_shift + 14)) ? 2 : 1) + 0x30);
306         print_debug("\n");
307
308         mem_config &= (~(DIMM_SZ << dimm_shift));
309         mem_config |= (size_dimm(dimm_shift));
310
311         print_debug("    DIMM size:       ");
312         print_debug_hex32(1 <<
313                 ((mem_config & (DIMM_SZ << dimm_shift)) >> (dimm_shift + 8)) + 22);
314         print_debug("\n");
315
316         return (mem_config);
317 }
318
319 static void sdram_init(void)
320 {
321 unsigned int mem_config = 0x00700070;
322
323         print_debug("Setting up default parameters for memory\n");
324         outb(0x70, 0x80);
325
326         setGX1Mem(GX_BASE + MC_MEM_CNTRL2, 0x000007d8); /* Disable all CLKS, Shift = 3 */
327         setGX1Mem(GX_BASE + MC_MEM_CNTRL1, 0x92140000); /* MD_DS=2, MA_DS=2, CNTL_DS=2 SDCLKRATE=4 */
328         setGX1Mem(GX_BASE + MC_BANK_CFG,   0x00700070); /* No DIMMS installed */
329         setGX1Mem(GX_BASE + MC_SYNC_TIM1,  0x3a733225); /* LTMODE=3, RC=10, RAS=7, RP=3, RCD=3, RRD=2, DPL=2 */
330         setGX1Mem(GX_BASE + MC_BANK_CFG,   0x57405740); /* Largest DIMM size
331                                                 0x4000 -- 2 module banks
332                                                 0x1000 -- 4 component banks
333                                                 0x0700 -- DIMM size 512MB
334                                                 0x0040 -- Page Size 16kB */
335
336         enable_dimm();
337
338         print_debug("Sizing memory\n");
339
340         setGX1Mem(GX_BASE + MC_BANK_CFG, 0x00705740);
341         do_refresh();
342         mem_config = size_memory(0, mem_config);
343         setGX1Mem(GX_BASE + MC_BANK_CFG, 0x57400070);
344         do_refresh();
345         mem_config = size_memory(16, mem_config);
346
347         print_debug("MC_BANK_CFG = ");
348         print_debug_hex32(mem_config);
349         print_debug("\n");
350
351         setGX1Mem(GX_BASE + MC_BANK_CFG, mem_config);
352         enable_dimm();
353         outb(0x7e, 0x80);
354 }