a few tweaks etc.
[coreboot.git] / src / northbridge / via / vt8601 / raminit.c
1 #include <cpu/p6/mtrr.h>
2 #include "raminit.h"
3 #if 0
4 /*
5 This software and ancillary information (herein called SOFTWARE )
6 called LinuxBIOS          is made available under the terms described
7 here.  The SOFTWARE has been approved for release with associated
8 LA-CC Number 00-34   .  Unless otherwise indicated, this SOFTWARE has
9 been authored by an employee or employees of the University of
10 California, operator of the Los Alamos National Laboratory under
11 Contract No. W-7405-ENG-36 with the U.S. Department of Energy.  The
12 U.S. Government has rights to use, reproduce, and distribute this
13 SOFTWARE.  The public may copy, distribute, prepare derivative works
14 and publicly display this SOFTWARE without charge, provided that this
15 Notice and any statement of authorship are reproduced on all copies.
16 Neither the Government nor the University makes any warranty, express 
17 or implied, or assumes any liability or responsibility for the use of
18 this SOFTWARE.  If SOFTWARE is modified to produce derivative works,
19 such modified SOFTWARE should be clearly marked, so as not to confuse
20 it with the version available from LANL.
21  */
22 /* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
23  * rminnich@lanl.gov
24  */
25 /*
26  * 11/26/02 - kevinh@ispiri.com - The existing comments implied that
27  * this didn't work yet.  Therefore, I've updated it so that it works
28  * correctly - at least on my VIA epia motherboard.  64MB DIMM in slot 0.
29  */
30
31 /* Added automatic detection of first equipped bank and its MA mapping type.
32  * (Rest of configuration is done in C)
33  * 5/19/03 by SONE Takeshi <ts1@tsn.or.jp>
34  */
35
36
37 /* Stable ~1 usec delay by hitting unused ISA port. */
38 #define UDELAY(x) movl $x,%ecx; 9: outb %al,$0x81; loop 9b
39
40 #define DIMMS_READ(x) \
41         movl 0x00000000+x, %eax; \
42         movl 0x10000000+x, %eax; \
43         movl 0x20000000+x, %eax; \
44         movl 0x30000000+x, %eax; \
45         movl 0x40000000+x, %eax; \
46         movl 0x50000000+x, %eax
47
48 #define DIMMS_WRITE(x) \
49         movl %eax, 0x00000000+x; \
50         movl %eax, 0x10000000+x; \
51         movl %eax, 0x20000000+x; \
52         movl %eax, 0x30000000+x; \
53         movl %eax, 0x40000000+x; \
54         movl %eax, 0x50000000+x
55
56 raminit:
57         intel_chip_post_macro(0x35)
58
59         // memory clk enable. We are not using ECC
60         CS_WRITE($0x78, $0x01)
61         // dram control, see the book. 
62 #if DIMM_PC133
63         CS_WRITE($0x68, $0x52)
64 #else
65         CS_WRITE($0x68, $0x42)
66 #endif
67         // dram control, see the book. 
68         CS_WRITE($0x6B, $0x0c)
69         // Initial setting, 256MB in each bank, will be rewritten later.
70         CS_WRITE($0x5A, $0x20)
71         CS_WRITE($0x5B, $0x40)
72         CS_WRITE($0x5C, $0x60)
73         CS_WRITE($0x5D, $0x80)
74         CS_WRITE($0x5E, $0xA0)
75         CS_WRITE($0x5F, $0xC0)
76         // It seems we have to take care of these 2 registers as if 
77         // they are bank 6 and 7.
78         CS_WRITE($0x56, $0xC0)
79         CS_WRITE($0x57, $0xC0)
80
81         // SDRAM in all banks
82         CS_WRITE($0x60, $0x3F)
83         // DRAM timing. I'm suspicious of this
84         // This is for all banks, 64 is 0,1.  65 is 2,3. 66 is 4,5.
85         // ras precharge 4T, RAS pulse 5T
86         // cas2 is 0xd6, cas3 is 0xe6
87         // we're also backing off write pulse width to 2T, so result is 0xee
88 #if DIMM_CL2
89         CS_WRITE($0x64, $0xd4)
90         CS_WRITE($0x65, $0xd4)
91         CS_WRITE($0x66, $0xd4)
92 #else // CL=3
93         CS_WRITE($0x64, $0xe4)
94         CS_WRITE($0x65, $0xe4)
95         CS_WRITE($0x66, $0xe4)
96 #endif
97
98         // dram frequency select.
99         // enable 4K pages for 64M dram. 
100 #if DIMM_PC133
101         CS_WRITE($0x69, $0x3c)
102 #else
103         CS_WRITE($0x69, $0xac)
104 #endif
105         // refresh counter, disabled.
106         CS_WRITE($0x6A, $0x00)
107         // clkenable configuration. kevinh FIXME - add precharge
108         CS_WRITE($0x6C, $0x00)
109         // dram read latch delay of 1 ns, MD drive 8 mA,
110         // high drive strength on MA[2: 13], we#, cas#, ras#
111         // As per Cindy Lee, set to 0x37, not 0x57
112         CS_WRITE($0x6D, $0x7f)
113
114         /* Initialize all banks at once */
115
116 /* begin to initialize*/
117         // I forget why we need this, but we do
118         mov $0xa55a5aa5, %eax
119         DIMMS_WRITE(0)
120         
121 /* set NOP*/
122         CS_WRITE($0x6C, $0x01)
123
124 /* wait 200us*/
125         // You need to do the memory reference. That causes the nop cycle. 
126         DIMMS_READ(0)
127         UDELAY(400)
128
129 /* set precharge */
130         CS_WRITE($0x6C, $0x02)
131
132 /* dummy reads*/
133         DIMMS_READ(0)
134         UDELAY(200)
135
136 /* set CBR*/
137         CS_WRITE($0x6C, $0x04)
138         
139 /* do 8 reads and wait >100us between each - from via*/
140         DIMMS_READ(0)
141         UDELAY(200)
142         DIMMS_READ(0)
143         UDELAY(200)
144         DIMMS_READ(0)
145         UDELAY(200)
146         DIMMS_READ(0)
147         UDELAY(200)
148         DIMMS_READ(0)
149         UDELAY(200)
150         DIMMS_READ(0)
151         UDELAY(200)
152         DIMMS_READ(0)
153         UDELAY(200)
154         DIMMS_READ(0)
155         UDELAY(200)
156
157 /* set MRS*/
158         CS_WRITE($0x6c, $0x03)
159 #if DIMM_CL2
160         DIMMS_READ(0x150)
161 #else // CL=3
162         DIMMS_READ(0x1d0)
163 #endif
164         UDELAY(200)
165
166 /* set to normal mode */
167         CS_WRITE($0x6C, $0x08)
168         movl $0x55aa55aa, %eax
169         DIMMS_WRITE(0)
170         DIMMS_READ(0)
171         UDELAY(200)
172
173         // Set the refresh rate. 
174 #if DIMM_PC133
175         CS_WRITE($0x6A, $0x86)
176 #else
177         CS_WRITE($0x6A, $0x65)
178 #endif
179         // enable multi-page open
180         CS_WRITE($0x6B, $0x0d)
181
182         /* Begin auto-detection
183          * Find the first bank with DIMM equipped. */
184
185         /* Maximum possible memory in bank 0, none in other banks.
186          * Starting from bank 0, we's fill 0 in these registers
187          * until memory is found. */
188         CS_WRITE($0x5A, $0xff)
189         CS_WRITE($0x5B, $0xff)
190         CS_WRITE($0x5C, $0xff)
191         CS_WRITE($0x5D, $0xff)
192         CS_WRITE($0x5E, $0xff)
193         CS_WRITE($0x5F, $0xff)
194         CS_WRITE($0x56, $0xff)
195         CS_WRITE($0x57, $0xff)
196
197         movl $0x5A, %ebx // first bank
198 1:
199         /* Write different values to 0 and 8, then read from 0.
200          * If values of address 0 match, we have something there. */
201         movl $0x12345678, %eax
202         movl %eax, 0
203         movl $0x87654321, %edx
204         movl %edx, 8
205         movl 0, %edx
206         cmpl %eax, %edx
207         je 2f
208         /* No memory in this bank. Tell it to the bridge. */
209         movl %ebx, %eax
210         xorl %edx, %edx
211         PCI_WRITE_CONFIG_BYTE
212         incl %ebx
213         cmpl $0x60, %ebx
214         jne 1b
215         /* No memory at all! */
216         CONSOLE_EMERG_TX_STRING($msg_nomem)
217 1:
218         hlt
219         jmp 1b
220 2:
221
222         /* Detect MA mapping type of the first bank. */
223
224         jmp raminit_ma
225 raminit_ma_reg_table:
226         /* Values for MA type register to try */
227         .word 0x0000, 0x8088, 0xe0ee
228         .word 0xffff // end mark
229
230 raminit_ma:
231         xorl %esi, %esi // highest address
232         movl $raminit_ma_reg_table, %ebx
233 1:
234         movw (%ebx), %cx
235         cmpw $0xffff, %cx
236         je raminit_ma_done
237         movl $0x58, %eax
238         PCI_WRITE_CONFIG_WORD
239
240         xorl %eax, %eax
241         movl %eax, (%eax)
242
243         // Write to addresses with only one address bit on,
244         // from 0x80000000 to 0x00000008 (lower 3 bits are ignored, assuming 
245         // 64-bit bus).
246         // Then what is read at address 0 is the value written to the lowest
247         // address where it gets wrap-around. That address is either the size
248         // of the bank, or a missing bit due to incorrect MA mapping.
249         movl $0x80000000, %eax
250 2:
251         movl %eax, (%eax)
252         shrl $1, %eax
253         cmpl $4, %eax
254         jne 2b
255
256         movl 0, %eax
257         cmpl %eax, %esi
258         jnc 3f
259
260         // This is the current best MA mapping.
261         // Save the address and its MA mapping value.
262         movl %eax, %esi
263         movl %ecx, %edi
264 3:
265         incl %ebx
266         incl %ebx
267         jmp 1b
268
269
270 raminit_ma_done:
271         // Set the best (hopefully correct) MA mapping type.
272         movl $0x58, %eax
273         movl %edi, %ecx
274         PCI_WRITE_CONFIG_WORD
275
276         CONSOLE_DEBUG_TX_STRING($msg_enabled)
277         CONSOLE_DEBUG_TX_HEX32(%esi)
278         CONSOLE_DEBUG_TX_STRING($msg_bytes)
279
280         /*
281          * We have the size of first bank in %esi, but throwing it away.
282          * Sizing will again be done in C, because we'll configure the rest
283          * of banks in there anyway.
284          */
285
286         //CALLSP(dumpnorth)
287
288         intel_chip_post_macro(0x36)
289
290
291         .section ".rom.data"
292 msg_nomem:
293         .asciz "No memory\r\n"
294 msg_enabled:
295         .asciz "Enabled first bank of RAM: 0x"
296 msg_bytes:
297         .asciz " bytes\r\n"
298         .previous
299 #endif
300
301         /* this is an early hack. We're going to just try to get memory
302          * working as it was before. I need help for SPD! RGM
303          */
304 // Set to 1 if your DIMMs are PC133
305 // Note that I'm assuming CPU's FSB frequency is 133MHz. If your CPU runs
306 // at another bus speed, you might need to change some of register values.
307 #ifndef DIMM_PC133
308 #define DIMM_PC133 0
309 #endif
310
311 // Set to 1 if your DIMMs are CL=2
312 #ifndef DIMM_CL2
313 #define DIMM_CL2 0
314 #endif
315
316           void dimms_read(unsigned long x) {
317           uint8_t c;
318           unsigned long eax; 
319           volatile unsigned long y;
320           eax =  x;
321           for(c = 0; c < 6; c++) {
322             
323             print_err("dimms_read: ");
324             print_err_hex32(eax);
325             print_err("\r\n");
326             y = * (volatile unsigned long *) eax;
327             eax += 0x10000000;
328           }
329 }
330
331 void dimms_write(int x) {
332   uint8_t c;
333   unsigned long eax = x;
334   for(c = 0; c < 6; c++) {
335     print_err("dimms_write: ");
336     print_err_hex32(eax);
337     print_err("\r\n");
338     *(volatile unsigned long *) eax = 0;
339     eax += 0x10000000;
340   }
341 }
342
343 #define setnorthb pci_write_config8
344 #if 0
345 void setnorthb(device_t north, uint8_t reg, uint8_t val) {
346   print_err("setnorth: reg ");
347     print_err_hex8(reg);
348   print_err(" to ");
349   print_err_hex8(val);
350   print_err("\r\n");
351   pci_write_config8(north, reg, val);
352 }
353 #endif
354
355 void
356 dumpnorth(device_t north) {
357   uint8_t r, c;
358   for(r = 0; r < 256; r += 16) {
359     print_err_hex8(r);
360     print_err(":");
361     for(c = 0; c < 16; c++) {
362       print_err_hex8(pci_read_config8(north, r+c));
363       print_err(" ");
364     }
365     print_err("\r\n");
366   }
367 }
368 static void sdram_set_registers(const struct mem_controller *ctrl) {
369   static const uint16_t raminit_ma_reg_table[] = {
370     /* Values for MA type register to try */
371     0x0000, 0x8088, 0xe0ee,
372     0xffff // end mark
373   };
374   static cont uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
375                                         0x56, 0x57};
376
377   device_t north = 0;
378   uint8_t c, r;
379
380   print_err("vt8601 init starting\n");
381   north = pci_locate_device(PCI_ID(0x1106, 0x8601), 0);
382   north = 0;
383   print_err_hex32(north);
384   print_err(" is the north\n");
385   print_err_hex16(pci_read_config16(north, 0));
386   print_err(" ");
387   print_err_hex16(pci_read_config16(north, 2));
388   print_err("\r\n");
389         
390   // memory clk enable. We are not using ECC
391   pci_write_config8(north,0x78, 0x01);
392   print_err_hex8(pci_read_config8(north, 0x78));
393   // dram control, see the book. 
394 #if DIMM_PC133
395   pci_write_config8(north,0x68, 0x52);
396 #else
397   pci_write_config8(north,0x68, 0x42);
398 #endif
399   // dram control, see the book. 
400   pci_write_config8(north,0x6B, 0x0c);
401   // Initial setting, 256MB in each bank, will be rewritten later.
402   pci_write_config8(north,0x5A, 0x20);
403   print_err_hex8(pci_read_config8(north, 0x5a));
404   pci_write_config8(north,0x5B, 0x40);
405   pci_write_config8(north,0x5C, 0x60);
406   pci_write_config8(north,0x5D, 0x80);
407   pci_write_config8(north,0x5E, 0xA0);
408   pci_write_config8(north,0x5F, 0xC0);
409   // It seems we have to take care of these 2 registers as if 
410   // they are bank 6 and 7.
411   pci_write_config8(north,0x56, 0xC0);
412   pci_write_config8(north,0x57, 0xC0);
413
414   // SDRAM in all banks
415   pci_write_config8(north,0x60, 0x3F);
416   // DRAM timing. I'm suspicious of this
417   // This is for all banks, 64 is 0,1.  65 is 2,3. 66 is 4,5.
418   // ras precharge 4T, RAS pulse 5T
419   // cas2 is 0xd6, cas3 is 0xe6
420   // we're also backing off write pulse width to 2T, so result is 0xee
421 #if DIMM_CL2
422   pci_write_config8(north,0x64, 0xd4);
423   pci_write_config8(north,0x65, 0xd4);
424   pci_write_config8(north,0x66, 0xd4);
425 #else // CL=3
426   pci_write_config8(north,0x64, 0xe4);
427   pci_write_config8(north,0x65, 0xe4);
428   pci_write_config8(north,0x66, 0xe4);
429 #endif
430
431   // dram frequency select.
432   // enable 4K pages for 64M dram. 
433 #if DIMM_PC133
434   pci_write_config8(north,0x69, 0x3c);
435 #else
436   pci_write_config8(north,0x69, 0xac);
437 #endif
438   // refresh counter, disabled.
439   pci_write_config8(north,0x6A, 0x00);
440   // clkenable configuration. kevinh FIXME - add precharge
441   pci_write_config8(north,0x6C, 0x00);
442   // dram read latch delay of 1 ns, MD drive 8 mA,
443   // high drive strength on MA[2:       13], we#, cas#, ras#
444   // As per Cindy Lee, set to 0x37, not 0x57
445   pci_write_config8(north,0x6D, 0x7f);
446
447   /* Initialize all banks at once */
448
449   /* begin to initialize*/
450   // I forget why we need this, but we do
451   dimms_write(0xa55a5aa5);
452
453   /* set NOP*/
454   pci_write_config8(north,0x6C, 0x01);
455   print_err("NOP\r\n");
456   /* wait 200us*/
457   // You need to do the memory reference. That causes the nop cycle. 
458   dimms_read(0);
459   udelay(400);
460   print_err("PRECHARGE\r\n");
461   /* set precharge */
462   pci_write_config8(north,0x6C, 0x02);
463   print_err("DUMMY READS\r\n");
464   /* dummy reads*/
465   dimms_read(0);
466   udelay(200);
467   print_err("CBR\r\n");
468   /* set CBR*/
469   pci_write_config8(north,0x6C, 0x04);
470         
471   /* do 8 reads and wait >100us between each - from via*/
472   dimms_read(0);
473   udelay(200);
474   dimms_read(0);
475   udelay(200);
476   dimms_read(0);
477   udelay(200);
478   dimms_read(0);
479   udelay(200);
480   dimms_read(0);
481   udelay(200);
482   dimms_read(0);
483   udelay(200);
484   dimms_read(0);
485   udelay(200);
486   dimms_read(0);
487   udelay(200);
488   print_err("MRS\r\n");
489   /* set MRS*/
490   pci_write_config8(north,0x6c, 0x03);
491 #if DIMM_CL2
492   dimms_read(0x150);
493 #else // CL=3
494   dimms_read(0x1d0);
495 #endif
496   udelay(200);
497   print_err("NORMAL\r\n");
498   /* set to normal mode */
499   pci_write_config8(north,0x6C, 0x08);
500
501   dimms_write(0x55aa55aa);
502   dimms_read(0);
503   udelay(200);
504   print_err("set ref. rate\r\n");
505   // Set the refresh rate. 
506 #if DIMM_PC133
507   pci_write_config8(north,0x6A, 0x86);
508 #else
509   pci_write_config8(north,0x6A, 0x65);
510 #endif
511   print_err("enable multi-page open\r\n");
512   // enable multi-page open
513   pci_write_config8(north,0x6B, 0x0d);
514
515   /* Begin auto-detection
516    * Find the first bank with DIMM equipped. */
517
518   /* Maximum possible memory in bank 0, none in other banks.
519    * Starting from bank 0, we fill 0 in these registers
520    * until memory is found. */
521   pci_write_config8(north,0x5A, 0xff);
522   pci_write_config8(north,0x5B, 0xff);
523   pci_write_config8(north,0x5C, 0xff);
524   pci_write_config8(north,0x5D, 0xff);
525   pci_write_config8(north,0x5E, 0xff);
526   pci_write_config8(north,0x5F, 0xff);
527   pci_write_config8(north,0x56, 0xff);
528   pci_write_config8(north,0x57, 0xff);
529   dumpnorth(north);
530   print_err("MA\r\n");
531   for(c = 0; c < 8; c++) {
532     /* Write different values to 0 and 8, then read from 0.
533      * If values of address 0 match, we have something there. */
534     print_err("write to 0\r\n");
535     *(volatile unsigned long *) 0 = 0x12345678;
536
537     /* LEAVE THIS HERE. IT IS ESSENTIAL. OTHERWISE BUFFERING
538      * WILL FOOL YOU!
539      */
540     print_err("write to 8\r\n");
541     *(volatile unsigned long *) 8 = 0x87654321;
542
543     if (*(volatile unsigned long *) 0 != 0x12345678) {
544       print_err("no memory in this bank\r\n");
545       /* No memory in this bank. Tell it to the bridge. */
546       pci_write_config8(north,ramregs[c], 0);
547     } else {
548       uint8_t best = 0;
549
550       /* Detect MA mapping type of the bank. */
551
552       for(r = 0; r < 3; r++) {
553         volatile unsigned long esi = 0;
554         volatile unsigned long eax = 0;
555         pci_write_config8(north,0x58, raminit_ma_reg_table[r]);
556
557         * (volatile unsigned long *) eax = 0;
558         print_err(" done write to eax\r\n");
559         // Write to addresses with only one address bit
560         // on, from 0x80000000 to 0x00000008 (lower 3 bits
561         // are ignored, assuming 64-bit bus).  Then what
562         // is read at address 0 is the value written to
563         // the lowest address where it gets
564         // wrap-around. That address is either the size of
565         // the bank, or a missing bit due to incorrect MA
566         // mapping.
567         eax = 0x80000000;
568         while (eax !=  4) {
569           * (volatile unsigned long *) eax = eax;
570           //print_err_hex32(eax);
571           outb(eax&0xff, 0x80);
572           eax >>= 1;
573         }
574         print_err(" done read to eax\r\n");
575         eax = * (unsigned long *)0;
576         /* oh boy ... what is this. 
577            movl 0, %eax
578            cmpl %eax, %esi
579            jnc 3f
580         */
581         print_err("eax and esi: ");
582         print_err_hex32(eax); print_err(" ");
583         print_err_hex32(esi); print_err("\r\n");
584
585         if (eax < esi) { /* ??*/
586                       
587           // This is the current best MA mapping.
588           // Save the address and its MA mapping value.
589           best = r;
590           esi = eax;
591         }
592       }
593                   
594       pci_write_config8(north,0x58, raminit_ma_reg_table[best]);
595       print_err("enabled first bank of ram ... ma is ");
596       print_err_hex8(pci_read_config8(north, 0x58));
597       print_err("\r\n");
598     }
599   }
600   print_err("vt8601 done\n");
601   dumpnorth(north);
602   udelay(1000);
603 }
604
605 static void sdram_set_spd_registers(const struct mem_controller *ctrl) {
606 }
607
608 static void sdram_enable(int controllers, const struct mem_controller *ctrl) {
609 }