- Checking latest version of romcc
[coreboot.git] / util / romcc / tests / raminit_test2.c
1 #define HAVE_STRING_SUPPORT          0
2 #define HAVE_CAST_SUPPORT            0
3 #define HAVE_STATIC_ARRAY_SUPPORT    0
4 #define HAVE_POINTER_SUPPORT         0
5
6 void outb(unsigned char value, unsigned short port)
7 {
8         __builtin_outb(value, port);
9 }
10
11 void outw(unsigned short value, unsigned short port)
12 {
13         __builtin_outw(value, port);
14 }
15
16 void outl(unsigned int value, unsigned short port)
17 {
18         __builtin_outl(value, port);
19 }
20
21 unsigned char inb(unsigned short port)
22 {
23         return __builtin_inb(port);
24 }
25
26 unsigned char inw(unsigned short port)
27 {
28         return __builtin_inw(port);
29 }
30
31 unsigned char inl(unsigned short port)
32 {
33         return __builtin_inl(port);
34 }
35
36 static unsigned int config_cmd(unsigned char bus, unsigned devfn, unsigned where)
37 {
38         return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3);
39 }
40
41 static unsigned char pcibios_read_config_byte(
42         unsigned char bus, unsigned devfn, unsigned where)
43 {
44         outl(config_cmd(bus, devfn, where), 0xCF8);
45         return inb(0xCFC + (where & 3));
46 }
47
48 static unsigned short pcibios_read_config_word(
49         unsigned char bus, unsigned devfn, unsigned where)
50 {
51         outl(config_cmd(bus, devfn, where), 0xCF8);
52         return inw(0xCFC + (where & 2));
53 }
54
55 static unsigned int pcibios_read_config_dword(
56         unsigned char bus, unsigned devfn, unsigned where)
57 {
58         outl(config_cmd(bus, devfn, where), 0xCF8);
59         return inl(0xCFC);
60 }
61
62
63 static void pcibios_write_config_byte(
64         unsigned char bus, unsigned devfn, unsigned where, unsigned char value)
65 {
66         outl(config_cmd(bus, devfn, where), 0xCF8);
67         outb(value, 0xCFC + (where & 3));
68 }
69
70 static void pcibios_write_config_word(
71         unsigned char bus, unsigned devfn, unsigned where, unsigned short value)
72 {
73         outl(config_cmd(bus, devfn, where), 0xCF8);
74         outw(value, 0xCFC + (where & 2));
75 }
76
77 static void pcibios_write_config_dword(
78         unsigned char bus, unsigned devfn, unsigned where, unsigned int value)
79 {
80         outl(config_cmd(bus, devfn, where), 0xCF8);
81         outl(value, 0xCFC);
82 }
83
84 /* Base Address */
85 #ifndef TTYS0_BASE
86 #define TTYS0_BASE 0x3f8
87 #endif
88
89 #ifndef TTYS0_BAUD
90 #define TTYS0_BAUD 115200
91 #endif
92
93 #if ((115200%TTYS0_BAUD) != 0)
94 #error Bad ttys0 baud rate
95 #endif
96
97 #define TTYS0_DIV       (115200/TTYS0_BAUD)
98
99 /* Line Control Settings */
100 #ifndef TTYS0_LCS
101 /* Set 8bit, 1 stop bit, no parity */
102 #define TTYS0_LCS       0x3
103 #endif
104
105 #define UART_LCS        TTYS0_LCS
106
107 /* Data */
108 #define UART_RBR 0x00
109 #define UART_TBR 0x00
110
111 /* Control */
112 #define UART_IER 0x01
113 #define UART_IIR 0x02
114 #define UART_FCR 0x02
115 #define UART_LCR 0x03
116 #define UART_MCR 0x04
117 #define UART_DLL 0x00
118 #define UART_DLM 0x01
119
120 /* Status */
121 #define UART_LSR 0x05
122 #define UART_MSR 0x06
123 #define UART_SCR 0x07
124
125 int uart_can_tx_byte(void)
126 {
127         return inb(TTYS0_BASE + UART_LSR) & 0x20;
128 }
129
130 void uart_wait_to_tx_byte(void)
131 {
132         while(!uart_can_tx_byte())
133                 ;
134 }
135
136 void uart_wait_until_sent(void)
137 {
138         while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) 
139                 ;
140 }
141
142 void uart_tx_byte(unsigned char data)
143 {
144         uart_wait_to_tx_byte();
145         outb(data, TTYS0_BASE + UART_TBR);
146         /* Make certain the data clears the fifos */
147         uart_wait_until_sent();
148 }
149
150 void uart_init(void)
151 {
152         /* disable interrupts */
153         outb(0x0, TTYS0_BASE + UART_IER);
154         /* enable fifo's */
155         outb(0x01, TTYS0_BASE + UART_FCR);
156         /* Set Baud Rate Divisor to 12 ==> 115200 Baud */
157         outb(0x80 | UART_LCS, TTYS0_BASE + UART_LCR);
158         outb(TTYS0_DIV & 0xFF,   TTYS0_BASE + UART_DLL);
159         outb((TTYS0_DIV >> 8) & 0xFF,    TTYS0_BASE + UART_DLM);
160         outb(UART_LCS, TTYS0_BASE + UART_LCR);
161 }
162
163 void __console_tx_char(unsigned char byte)
164 {
165         uart_tx_byte(byte);
166 }
167 void __console_tx_nibble(unsigned nibble)
168 {
169         unsigned char digit;
170         digit = nibble + '0';
171         if (digit > '9') {
172                 digit += 39;
173         }
174         __console_tx_char(digit);
175 }
176 void __console_tx_hex8(unsigned char byte)
177 {
178         __console_tx_nibble(byte >> 4);
179         __console_tx_nibble(byte & 0x0f);
180 }
181
182 void __console_tx_hex32(unsigned char value)
183 {
184         __console_tx_nibble((value >> 28) & 0x0f);
185         __console_tx_nibble((value >> 24) & 0x0f);
186         __console_tx_nibble((value >> 20) & 0x0f);
187         __console_tx_nibble((value >> 16) & 0x0f);
188         __console_tx_nibble((value >> 12) & 0x0f);
189         __console_tx_nibble((value >>  8) & 0x0f);
190         __console_tx_nibble((value >>  4) & 0x0f);
191         __console_tx_nibble(value & 0x0f);
192 }
193
194 #if HAVE_STRING_SUPPORT
195 void __console_tx_string(char *str)
196 {
197         unsigned char ch;
198         while((ch = *str++) != '\0') {
199                 __console_tx_byte(ch);
200         }
201 }
202 #else
203 void __console_tx_string(char *str)
204 {
205 }
206 #endif
207
208
209 void print_emerg_char(unsigned char byte) { __console_tx_char(byte); }
210 void print_emerg_hex8(unsigned char value) { __console_tx_hex8(value); }
211 void print_emerg_hex32(unsigned int value) { __console_tx_hex32(value); }
212 void print_emerg(char *str) { __console_tx_string(str); }
213
214 void print_alert_char(unsigned char byte) { __console_tx_char(byte); }
215 void print_alert_hex8(unsigned char value) { __console_tx_hex8(value); }
216 void print_alert_hex32(unsigned int value) { __console_tx_hex32(value); }
217 void print_alert(char *str) { __console_tx_string(str); }
218
219 void print_crit_char(unsigned char byte) { __console_tx_char(byte); }
220 void print_crit_hex8(unsigned char value) { __console_tx_hex8(value); }
221 void print_crit_hex32(unsigned int value) { __console_tx_hex32(value); }
222 void print_crit(char *str) { __console_tx_string(str); }
223
224 void print_err_char(unsigned char byte) { __console_tx_char(byte); }
225 void print_err_hex8(unsigned char value) { __console_tx_hex8(value); }
226 void print_err_hex32(unsigned int value) { __console_tx_hex32(value); }
227 void print_err(char *str) { __console_tx_string(str); }
228
229 void print_warning_char(unsigned char byte) { __console_tx_char(byte); }
230 void print_warning_hex8(unsigned char value) { __console_tx_hex8(value); }
231 void print_warning_hex32(unsigned int value) { __console_tx_hex32(value); }
232 void print_warning(char *str) { __console_tx_string(str); }
233
234 void print_notice_char(unsigned char byte) { __console_tx_char(byte); }
235 void print_notice_hex8(unsigned char value) { __console_tx_hex8(value); }
236 void print_notice_hex32(unsigned int value) { __console_tx_hex32(value); }
237 void print_notice(char *str) { __console_tx_string(str); }
238
239 void print_info_char(unsigned char byte) { __console_tx_char(byte); }
240 void print_info_hex8(unsigned char value) { __console_tx_hex8(value); }
241 void print_info_hex32(unsigned int value) { __console_tx_hex32(value); }
242 void print_info(char *str) { __console_tx_string(str); }
243
244 void print_debug_char(unsigned char byte) { __console_tx_char(byte); }
245 void print_debug_hex8(unsigned char value) { __console_tx_hex8(value); }
246 void print_debug_hex32(unsigned int value) { __console_tx_hex32(value); }
247 void print_debug(char *str) { __console_tx_string(str); }
248
249 void print_spew_char(unsigned char byte) { __console_tx_char(byte); }
250 void print_spew_hex8(unsigned char value) { __console_tx_hex8(value); }
251 void print_spew_hex32(unsigned int value) { __console_tx_hex32(value); }
252 void print_spew(char *str) { __console_tx_string(str); }
253
254 #define PIIX4_DEVFN 0x90
255 #define SMBUS_MEM_DEVICE_START 0x50
256 #define SMBUS_MEM_DEVICE_END 0x53
257 #define SMBUS_MEM_DEVICE_INC 1
258
259
260 #define PM_BUS 0
261 #define PM_DEVFN (PIIX4_DEVFN+3)
262
263 #define SMBUS_IO_BASE 0x1000
264 #define SMBHSTSTAT 0
265 #define SMBHSTCTL  2
266 #define SMBHSTCMD  3
267 #define SMBHSTADD  4
268 #define SMBHSTDAT0 5
269 #define SMBHSTDAT1 6
270 #define SMBBLKDAT  7
271
272 void smbus_enable(void)
273 {
274         /* iobase addr */
275         pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x90, SMBUS_IO_BASE | 1);
276         /* smbus enable */
277         pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0xd2, (0x4 << 1) | 1);
278         /* iospace enable */
279         pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
280 }
281
282 void smbus_setup(void)
283 {
284         outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
285 }
286
287 static void smbus_wait_until_ready(void)
288 {
289         while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
290                 /* nop */
291         }
292 }
293
294 static void smbus_wait_until_done(void)
295 {
296         unsigned char byte;
297         do {
298                 byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
299         }while((byte &1) == 1);
300         while( (byte & ~1) == 0) {
301                 byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
302         }
303 }
304
305 int smbus_read_byte(unsigned device, unsigned address)
306 {
307         unsigned char host_status_register;
308         unsigned char byte;
309         int result;
310
311         smbus_wait_until_ready();
312
313         /* setup transaction */
314         /* disable interrupts */
315         outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
316         /* set the device I'm talking too */
317         outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD);
318         /* set the command/address... */
319         outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
320         /* set up for a byte data read */
321         outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL);
322
323         /* clear any lingering errors, so the transaction will run */
324         outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
325
326         /* clear the data byte...*/
327         outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
328
329         /* start the command */
330         outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
331
332         /* poll for transaction completion */
333         smbus_wait_until_done();
334
335         host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
336
337         /* read results of transaction */
338         byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
339
340         result = byte;
341         if (host_status_register != 0x02) {
342                 result = -1;
343         }
344         return result;
345 }
346
347 #define I440GX_BUS 0
348 #define I440GX_DEVFN ((0x00 << 3) + 0)
349
350 #define USE_ECC 0
351
352 #define CAS_LATENCY 3
353
354         /* CAS latency 2 */
355 #if (CAS_LATENCY == 2)
356 #define CAS_NB 0x17
357         /* 
358          * 7 == 0111
359          * 1 == 0001
360          */
361 #define CAS_MODE 0x2a
362         /*
363          * a == 1010
364          * 2 == 0010
365          */
366 #endif
367
368         /* CAS latency 3 */
369 #if (CAS_LATENCY == 3) 
370 #define CAS_NB 0x13
371         /*
372          * 3 == 0011
373          * 1 == 0001
374          */
375 #define CAS_MODE 0x3a
376         /*
377          * a == 1010
378          * 3 == 0011
379          */
380 #endif
381
382 #ifndef CAS_NB
383 #error "Nothing defined" 
384 #endif
385
386 /* Default values for config registers */
387         
388 static void set_nbxcfg(void)
389 {
390         /* NBXCFG 0x50 - 0x53 */
391         /* f == 1111
392          * 0 == 0000
393          * 0 == 0000
394          * 0 == 0000
395          * 0 == 0000
396          * 1 == 0001
397          * 8 == 1000
398          * c == 1100
399          * SDRAM Row without ECC:
400          * row 0 == 1 No ECC
401          * row 1 == 1 No ECC
402          * row 2 == 1 No ECC
403          * row 3 == 1 No ECC
404          * row 4 == 1 No ECC
405          * row 5 == 1 No ECC
406          * row 6 == 1 No ECC
407          * row 7 == 1 No ECC
408          * Host Bus Fast Data Ready Enable == 0 Disabled
409          * IDSEL_REDIRECT == 0 (430TX compatibility disable?)
410          * WSC# Hanshake Disable == 0 enable (Use External IOAPIC)
411          * Host/DRAM Frequence == 00 100Mhz
412          * AGP to PCI Access Enable == 0 Disable
413          * PCI Agent to Aperture Access Disable == 0 Enable (Ignored)
414          * Aperture Access Global Enable == 0 Disable
415          * DRAM Data Integrity Mode == 11 (Error Checking/Correction)
416          * ECC Diagnostic Mode Enable == 0 Not Enabled
417          * MDA present == 0 Not Present
418          * USWC Write Post During During I/O Bridge Access Enable == 1 Enabled
419          * In Order Queue Depth (IQD) (RO) == ?? 
420          */
421         pcibios_write_config_dword(I440GX_BUS, I440GX_DEVFN, 0x50, 0xff00000c);
422 }
423
424 static void set_dramc(void)
425 {
426         /* 0 == 0000
427          * 8 == 1000
428          * Not registered SDRAM
429          * refresh disabled
430          */
431         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, 0x8);
432 }
433
434 static void set_pam(void)
435 {
436         /* PAM - Programmable Attribute Map Registers */
437         /* Ideally we want to enable all of these as DRAM and teach
438          * linux it is o.k. to use them...
439          */
440         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x59, 0x00);
441         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5a, 0x00);
442         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5b, 0x00);
443         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5d, 0x00);
444         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5e, 0x00);
445         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5f, 0x00);
446 }
447
448 static void set_drb(void)
449 {
450         /* DRB - DRAM Row Boundary Registers */
451         /* Conservative setting 8MB of ram on first DIMM... */
452         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60, 0x01);
453         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x61, 0x01);
454         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x62, 0x01);
455         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x63, 0x01);
456         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x64, 0x01);
457         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x65, 0x01);
458         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x66, 0x01);
459         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67, 0x01);
460 }
461
462 static void set_fdhc(void)
463 {
464         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x68, 0x00);
465 }
466 static void set_mbsc(void)
467 {
468         /* MBSC - Memory Buffer Strength Control */
469         /* 00c00003e820
470          * [47:44] 0 == 0000
471          * [43:40] 0 == 0000
472          * [39:36] c == 1100
473          * [35:32] 0 == 0000
474          * [31:28] 0 == 0000
475          * [27:24] 0 == 0000
476          * [23:20] 0 == 0000
477          * [19:16] 3 == 0011
478          * [15:12] e == 1110
479          * [11: 8] 8 == 1000
480          * [ 7: 4] 2 == 0010
481          * [ 3: 0] 0 == 0000
482          * MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths  ==  3x
483          * MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 3x
484          * MD[63:0]# Buffer Strength Control 2 == 3x
485          * MD[63:0]# Buffer Strength Control 1 == 3x
486          * MECC[7:0] Buffer Strength Control 2 == 3x
487          * MECC[7:0] Buffer Strength Control 1 == 3x
488          * CSB7# Buffer Strength == 3x  
489          * CSA7# Buffer Strength == 3x
490          * CSB6# Buffer Strength == 3x
491          * CSA6# Buffer Strength == 3x
492          * CSA5#/CSB5# Buffer Strength == 2x
493          * CSA4#/CSB4# Buffer Strength == 2x
494          * CSA3#/CSB3# Buffer Strength == 2x
495          * CSA2#/CSB2# Buffer Strength == 2x
496          * CSA1#/CSB1# Buffer Strength == 2x
497          * CSA0#/CSB0# Buffer Strength == 2x
498          * DQMA5 Buffer Strength == 2x
499          * DQMA1 Buffer Strength == 3x
500          * DQMB5 Buffer Strength == 2x
501          * DQMB1 Buffer Strength == 2x
502          * DQMA[7:6,4:2,0] Buffer Strength == 3x
503          * GCKE Buffer Strength == 1x
504          * FENA Buffer Strength == 3x
505          */
506         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x69, 0xB3);
507         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6a, 0xee);
508         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6b, 0xff);
509         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6c, 0xff);
510         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6d, 0xff);
511         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6e, 0x03);
512 }
513
514 static void set_smram(void)
515 {
516         /* 0x72 SMRAM */
517         /* 1 == 0001
518          * a == 1010
519          * SMM Compatible base segment == 010 (Hardcoded value)
520          */
521 }
522
523 static void set_esramc(void)
524 {
525         /* 0x73 ESMRAMC */
526 }
527
528 static void set_rps(void)
529 {
530         /* RPS - Row Page Size Register */
531         /* 0x0055
532          * [15:12] 0 == 0000
533          * [11: 8] 0 == 0000
534          * [ 7: 4] 5 == 0101
535          * [ 3: 0] 5 == 0101
536          * DRB[0] == 4KB
537          * DRB[1] == 4KB
538          * DRB[2] == 4KB
539          * DRB[3] == 4KB
540          * DRB[4] == 2KB
541          * DRB[5] == 2KB
542          * DRB[6] == 2KB
543          * DRB[7] == 2KB
544          */
545         pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, 0x5555);
546 }
547
548 static void set_sdramc(void)
549 {
550         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, CAS_NB);
551 }
552
553 static void set_pgpol(void)
554 {
555         /* PGPOL - Paging Policy Register */
556         /* 0xff07
557          * [15:12] f == 1111
558          * [11: 8] f == 1111
559          * [ 7: 4] 0 == 0000
560          * [ 3: 0] 7 == 0111
561          * row0 == 4banks
562          * row1 == 4banks
563          * row2 == 4banks
564          * row3 == 4banks
565          * row4 == 4banks
566          * row5 == 4banks
567          * row6 == 4banks
568          * row7 == 4banks
569          * Dram Idle Timer (DIT) == 32 clocks
570          */
571         pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, 0xff07);
572 }
573
574 static void set_mbfs(void)
575 {
576         /* MBFS - Memory Buffer Frequencey Select Register */
577         /* 0xffff7f                                          
578          * [23:20] f == 1111                                 
579          * [19:16] f == 1111                                 
580          * [15:12] f == 1111                                 
581          * [11: 8] f == 1111                                 
582          * [ 7: 4] 7 == 0111                                 
583          * [ 3: 0] f == 1111                                 
584          * MAA[14:0], WEA#, SRASA#, SCASA# == 100Mhz Buffers Enabled
585          * MAB[14,13,10,12:11,9:0], WEB#, SRASB#, SCASB# == 100Mhz Buffers Enabled
586          * MD[63:0] Control 2 == 100 Mhz Buffer Enable
587          * MD[63:0] Control 1 == 100 Mhz B
588          * MECC[7:0] Control 2 == 100 Mhz B
589          *
590          */
591         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0xff);
592         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0xff);
593         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0x7f);
594 }
595
596 static void set_dwtc(void)
597 {
598         /* DWTC - DRAM Write Thermal Throttle Control */
599         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe0, 0xb4);
600         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe1, 0xbe);
601         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe2, 0xff);
602         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe3, 0xd7);
603         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe4, 0x97);
604         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe5, 0x3e);
605         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe6, 0x00);
606         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe7, 0x80);
607 }
608
609 static void set_drtc(void)
610 {
611         /* DRTC - DRAM Read Thermal Throttle Control */
612         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe8, 0x2c);
613         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe9, 0xd3);
614         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xea, 0xf7);
615         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xeb, 0xcf);
616         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xec, 0x9d);
617         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xed, 0x3e);
618         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xee, 0x00);
619         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xef, 0x00);
620 }
621
622 static void set_pmcr(void)
623 {
624         /* PMCR -- BIOS sets 0x90 into it. 
625          * 0x10 is REQUIRED.
626          * we have never used it. So why did this ever work?
627          */
628         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x7a, 0x90);
629         
630 }
631 void sdram_set_registers(void)
632 {
633         set_nbxcfg();
634         set_dramc();
635         set_pam();
636         set_drb();
637         set_fdhc();
638         set_mbsc();
639         set_smram();
640         set_esramc();
641         set_rps();
642         set_sdramc();
643         set_pgpol();
644         set_mbfs();
645         set_dwtc();
646         set_drtc();
647         set_pmcr();
648 }
649
650 int log2(int value)
651 {
652         /* __builtin_bsr is a exactly equivalent to the x86 machine
653          * instruction with the exception that it returns -1  
654          * when the value presented to it is zero.
655          * Otherwise __builtin_bsr returns the zero based index of
656          * the highest bit set.
657          */
658         return __builtin_bsr(value);
659 }
660
661
662 static void spd_set_drb(void)
663 {
664         /*
665          * Effects:     Uses serial presence detect to set the
666          *              DRB registers which holds the ending memory address assigned
667          *              to each DIMM.
668          */
669         unsigned end_of_memory;
670         unsigned device;
671         unsigned drb_reg;
672         
673         end_of_memory = 0; /* in multiples of 8MiB */
674         device = SMBUS_MEM_DEVICE_START;
675         drb_reg = 0x60;
676         while (device <= SMBUS_MEM_DEVICE_END) {
677                 unsigned side1_bits, side2_bits;
678                 int byte, byte2;
679
680                 side1_bits = side2_bits = -1;
681
682                 /* rows */
683                 byte = smbus_read_byte(device, 3);
684                 if (byte >= 0) {
685                         side1_bits += byte & 0xf;
686
687                         /* columns */
688                         byte = smbus_read_byte(device, 4);
689                         side1_bits += byte & 0xf;
690
691                         /* banks */
692                         byte = smbus_read_byte(device, 17);
693                         side1_bits += log2(byte);
694
695                         /* Get the moduel data width and convert it to a power of two */
696                         /* low byte */
697                         byte = smbus_read_byte(device, 6);
698
699                         /* high byte */
700                         byte2 = smbus_read_byte(device, 7);
701 #if HAVE_CAST_SUPPORT
702                         side1_bits += log2((((unsigned long)byte2 << 8)| byte));
703 #else
704                         side1_bits += log2((byte2 << 8) | byte);
705 #endif
706                         
707                         /* now I have the ram size in bits as a power of two (less 1) */
708                         /* Make it mulitples of 8MB */
709                         side1_bits -= 25;
710                         
711                         /* side two */
712                         
713                         /* number of physical banks */
714                         byte = smbus_read_byte(device, 5);
715                         if (byte > 1) {
716                                 /* for now only handle the symmetrical case */
717                                 side2_bits = side1_bits;
718                         }
719                 }
720
721                 /* Compute the end address for the DRB register */
722                 /* Only process dimms < 2GB (2^8 * 8MB) */
723                 if (side1_bits < 8) {
724                         end_of_memory += (1 << side1_bits);
725                 }
726 #if HAVE_STRING_SUPPORT
727                 print_debug("end_of_memory: "); print_debug_hex32(end_of_memory); print_debug("\n");
728 #endif
729                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg, end_of_memory);
730
731                 if (side2_bits < 8 ) {
732                         end_of_memory += (1 << side2_bits);
733                 }
734 #if HAVE_STRING_SUPPORT
735                 print_debug("end_of_memory: "); print_debug_hex32(end_of_memory); print_debug("\n");
736 #endif
737                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg +1, end_of_memory);
738
739                 drb_reg += 2;
740                 device += SMBUS_MEM_DEVICE_INC;
741         }
742 }
743
744 void sdram_no_memory(void)
745 {
746 #if HAVE_STRING_SUPPORT
747         print_err("No memory!!\n");
748 #endif
749         while(1) ;
750 }
751
752 static void spd_set_dramc(void)
753 {
754         /*
755          * Effects:     Uses serial presence detect to set the
756          *              DRAMC register, which records if ram is registerd or not,
757          *              and controls the refresh rate.
758          *              The refresh rate is not set here, as memory refresh
759          *              cannot be enbaled until after memory is initialized.
760          *              see spd_enable_refresh.
761          */
762         /* auto detect if ram is registered or not. */
763         /* The DRAMC register also contorls the refresh rate but we can't
764          * set that here because we must leave refresh disabled.
765          * see: spd_enable_refresh
766          */
767         /* Find the first dimm and assume the rest are the same */
768         /* FIXME Check for illegal/unsupported ram configurations and abort */
769         unsigned device;
770         int byte;
771         unsigned dramc;
772         byte = -1;
773         device = SMBUS_MEM_DEVICE_START;
774
775         while ((byte < 0) && (device <= SMBUS_MEM_DEVICE_END)) {
776                 byte = smbus_read_byte(device, 21);
777                 device += SMBUS_MEM_DEVICE_INC;
778         }
779         if (byte < 0) {
780                 /* We couldn't find anything we must have no memory */
781                 sdram_no_memory();
782         }
783         dramc = 0x8;
784         if ((byte & 0x12) != 0) {
785                 /* this is a registered part. 
786                  * observation: for register parts, BIOS zeros (!) 
787                  * registers CA-CC. This has an undocumented meaning.
788                  */
789                 /* But it does make sense the oppisite of registered
790                  * sdram is buffered and 0xca - 0xcc control the buffers.
791                  * Clearing them aparently disables them.
792                  */
793                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0);
794                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0);
795                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0);
796                 dramc = 0x10;
797         }
798         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, dramc);
799 }
800
801 static void spd_enable_refresh(void)
802 {
803         /*
804          * Effects:     Uses serial presence detect to set the
805          *              refresh rate in the DRAMC register.
806          *              see spd_set_dramc for the other values.
807          * FIXME:       Check for illegal/unsupported ram configurations and abort
808          */
809 #if HAVE_STATIC_ARRAY_SUPPORT
810         static const unsigned char refresh_rates[] = {
811                 0x01, /* Normal        15.625 us -> 15.6 us */
812                 0x05, /* Reduced(.25X) 3.9 us    -> 7.8 us */
813                 0x05, /* Reduced(.5X)  7.8 us    -> 7.8 us */
814                 0x02, /* Extended(2x)  31.3 us   -> 31.2 us */
815                 0x03, /* Extended(4x)  62.5 us   -> 62.4 us */
816                 0x04, /* Extended(8x)  125 us    -> 124.8 us */
817         };
818 #endif
819         /* Find the first dimm and assume the rest are the same */
820         int status;
821         int byte;
822         unsigned device;
823         unsigned refresh_rate;
824         byte = -1;
825         status = -1;
826         device = SMBUS_MEM_DEVICE_START;
827         while ((byte < 0) && (device <= SMBUS_MEM_DEVICE_END)) {
828                 byte = smbus_read_byte(device, 12);
829                 device += SMBUS_MEM_DEVICE_INC;
830         }
831         if (byte < 0) {
832                 /* We couldn't find anything we must have no memory */
833                 sdram_no_memory();
834         }
835         byte &= 0x7f;
836         /* Default refresh rate be conservative */
837         refresh_rate = 5; 
838         /* see if the ram refresh is a supported one */
839         if (byte < 6) {
840 #if HAVE_STATIC_ARRAY_SUPPORT
841                 refresh_rate = refresh_rates[byte];
842 #endif
843         }
844         byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57);
845         byte &= 0xf8;
846         byte |= refresh_rate;
847         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, byte);
848 }
849
850 static void spd_set_sdramc(void)
851 {
852         return;
853 }
854
855 static void spd_set_rps(void)
856 {
857         /*
858          * Effects:     Uses serial presence detect to set the row size 
859          *              on a given DIMM
860          * FIXME:       Check for illegal/unsupported ram configurations and abort
861          */
862         /* The RPS register holds the size of a ``page'' of DRAM on each DIMM */
863         unsigned page_sizes;
864         unsigned index;
865         unsigned device;
866         unsigned char dramc;
867         /* default all page sizes to 2KB */
868         page_sizes = 0;
869         index = 0;
870         device = SMBUS_MEM_DEVICE_START;
871         for(; device <= SMBUS_MEM_DEVICE_END; index += 4, device += SMBUS_MEM_DEVICE_INC) {
872                 unsigned int status;
873                 unsigned int byte;
874                 int page_size;
875
876                 byte = smbus_read_byte(device, 3);
877                 if (byte < 0) continue;
878
879                 /* I now have the row page size as a power of 2 */
880                 page_size = byte & 0xf;
881                 /* make it in multiples of 2Kb */
882                 page_size -= 11;
883                 
884                 if (page_size <= 0) continue;
885                 
886                 /* FIXME: do something with page sizes greather than 8KB!! */
887                 page_sizes |= (page_size << index);
888                                 
889                 /* side two */
890                 byte = smbus_read_byte(device, 5);
891                 if (byte <= 1)  continue;
892                         
893                 /* For now only handle the symmetrical case */
894                 page_sizes |= (page_size << (index +2));
895         }
896         /* next block is for Ron's attempt to get registered to work. */
897         /* we have just verified that we have to have this code. It appears that
898          * the registered SDRAMs do indeed set the RPS wrong. sheesh.
899          */
900         /* at this point, page_sizes holds the RPS for all ram. 
901          * we have verified that for registered DRAM the values are 
902          * 1/2 the size they should be. So we test for registered
903          * and then double the sizes if needed. 
904          */
905
906         dramc = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57);
907         if (dramc & 0x10) {
908                 /* registered */
909
910                 /* BIOS makes weird page size for registered! */
911                 /* what we have found is you need to set the EVEN banks to 
912                  * twice the size. Fortunately there is a very easy way to 
913                  * do this. First, read the WORD value of register 0x74. 
914                  */
915                 page_sizes += 0x1111;
916         }
917
918         pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, page_sizes);
919 }
920
921 static void spd_set_pgpol(void)
922 {
923         /*
924          * Effects:     Uses serial presence detect to set the number of banks
925          *              on a given DIMM
926          * FIXME:       Check for illegal/unsupported ram configurations and abort
927          */
928         /* The PGPOL register stores the number of logical banks per DIMM,
929          * and number of clocks the DRAM controller waits in the idle
930          * state.
931          */
932         unsigned device;
933         unsigned bank_sizes;
934         unsigned bank;
935         unsigned reg;
936         /* default all bank counts 2 */
937         bank_sizes = 0;
938         bank = 0;
939         device = SMBUS_MEM_DEVICE_START;
940         for(; device <= SMBUS_MEM_DEVICE_END; 
941             bank += 2, device += SMBUS_MEM_DEVICE_INC) { 
942                 int byte;
943
944                 /* logical banks */
945                 byte = smbus_read_byte(device, 17);
946                 if (byte < 0) continue;
947                 if (byte < 4) continue;
948                 bank_sizes |= (1 << bank);
949                 
950                 /* side 2 */
951                 /* Number of physical banks */
952                 byte  = smbus_read_byte(device, 5);
953                 if (byte <= 1) continue;
954                 /* for now only handle the symmetrical case */
955                 bank_sizes |= (1 << (bank +1));
956         }
957         reg = bank_sizes << 8;
958         reg |= 0x7; /* 32 clocks idle time */
959         pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, reg);
960 }
961
962 static void spd_set_nbxcfg(void)
963 {
964         /*
965          * Effects:     Uses serial presence detect to set the
966          *              ECC support flags in the NBXCFG register
967          * FIXME:       Check for illegal/unsupported ram configurations and abort
968          */
969         unsigned reg;
970         unsigned index;
971         unsigned device;
972
973         /* Say all dimms have no ECC support */
974         reg = 0xff;
975         index = 0;
976         
977         device = SMBUS_MEM_DEVICE_START;
978         for(; device <= SMBUS_MEM_DEVICE_END; index += 2, device += SMBUS_MEM_DEVICE_INC) {
979                 int byte;
980
981                 byte = smbus_read_byte(device, 11);
982                 if (byte < 0) continue;
983 #if !USE_ECC 
984                 byte = 0; /* Disable ECC */
985 #endif
986                 /* 0 == None, 1 == Parity, 2 == ECC */
987                 if (byte != 2) continue;
988                 reg ^= (1 << index);
989
990                 /* side two */
991                 /* number of physical banks */
992                 byte = smbus_read_byte(device, 5);
993                 if (byte <= 1) continue;
994                 /* There is only the symmetrical case */
995                 reg ^= (1 << (index +1));
996         }
997         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x53, reg);
998         /* Now see if reg is 0xff.  If it is we are done.  If not,
999          * we need to set 0x18 into regster 0x50.l
1000          * we will do this in two steps, first or in 0x80 to 0x50.b,
1001          * then or in 0x1 to 0x51.b
1002          */
1003 #if HAVE_STRING_SUPPORT
1004         print_debug("spd_set_nbxcfg reg="); print_debug_hex8(reg); print_debug("\n");
1005 #endif
1006         if (reg != 0xff) {
1007                 unsigned char byte;
1008                 byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50);
1009                 byte |= 0x80;
1010                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50, byte);
1011                 byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51);
1012                 byte |= 1;
1013                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51, byte);
1014                 /* try this.
1015                  * We should be setting bit 2 in register 76 and we're not
1016                  * technically we should see if CL=2 for the ram,
1017                  * but registered is so screwed up that it's kind of a lost 
1018                  * cause.
1019                  */
1020                 byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76);
1021                 byte |= 4;
1022                 pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte);
1023 #if HAVE_STRING_SUPPORT
1024                 print_debug("spd_set_nbxcfg 0x76.b="); print_debug_hex8(byte); print_debug("\n");
1025 #endif
1026         }
1027 }
1028
1029 void sdram_set_spd_registers(void)
1030 {
1031         spd_set_drb();
1032         spd_set_dramc();
1033         spd_set_rps();
1034         spd_set_sdramc();
1035         spd_set_pgpol();
1036         spd_set_nbxcfg();
1037 }
1038
1039 void sdram_first_normal_reference(void)
1040 {
1041         return;
1042 }
1043
1044 void sdram_special_finishup(void)
1045 {
1046         return;
1047 }
1048
1049 static void set_ram_command(unsigned command)
1050 {
1051         unsigned char byte;
1052         command &= 0x7;
1053         byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76);
1054         byte &= 0x1f;
1055         byte |= (command << 5);
1056         pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte);
1057 #if HAVE_STRING_SUPPORT
1058         print_debug("set_ram_command 0x76.b="); print_debug_hex8(byte); print_debug("\n");
1059 #endif
1060 }
1061
1062 #define RAM_COMMAND_NONE        0x0
1063 #define RAM_COMMAND_NOOP        0x1
1064 #define RAM_COMMAND_PRECHARGE   0x2
1065 #define RAM_COMMAND_MRS         0x3
1066 #define RAM_COMMAND_CBR         0x4
1067
1068 void sdram_set_command_none(void)
1069 {
1070         set_ram_command(RAM_COMMAND_NONE);
1071 }
1072 void sdram_set_command_noop(void)
1073 {
1074         set_ram_command(RAM_COMMAND_NOOP);
1075 }
1076 void sdram_set_command_precharge(void)
1077 {
1078         set_ram_command(RAM_COMMAND_PRECHARGE);
1079 }
1080
1081 static unsigned long dimm_base(int n)
1082 {
1083         unsigned char byte;
1084         unsigned long result;
1085         if (n == 0) {
1086                 return 0;
1087         }
1088
1089         byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60 + (n - 1));
1090         result = byte;
1091         result <<= 23;
1092         return result;
1093 }
1094
1095 static void dimms_read(unsigned long offset)
1096 {
1097         int i;
1098         for(i = 0; i < 8; i++) {
1099                 unsigned long dummy;
1100                 unsigned long addr; 
1101                 unsigned long next_base;
1102
1103                 next_base = dimm_base(i +1);
1104                 addr =  dimm_base(i);
1105                 if (addr == next_base) {
1106                         continue;
1107                 }
1108                 addr += offset;
1109 #if HAVE_STRING_SUPPORT
1110                 print_debug("Reading "); 
1111                 print_debug_hex32(addr); 
1112                 print_debug("\n");
1113 #endif
1114 #if HAVE_POINTER_SUPPORT
1115                 dummy = RAM(unsigned long, addr);
1116 #endif
1117 #if HAVE_STRING_SUPPORT
1118                 print_debug("Reading "); 
1119                 print_debug_hex32(addr ^ 0xddf8); 
1120                 print_debug("\n");
1121 #endif
1122 #if HAVE_POINTER_SUPPORT
1123                 dummy = RAM(unsigned long, addr ^ 0xdff8);
1124 #endif
1125 #if HAVE_STRING_SUPPORT
1126                 print_debug("Read "); 
1127                 print_debug_hex32(addr); 
1128                 print_debug_hex32(addr ^ 0xddf8); 
1129                 print_debug("\n");
1130 #endif
1131         }
1132 }
1133
1134 void sdram_set_command_cbr(void)
1135 {
1136         set_ram_command(RAM_COMMAND_CBR);
1137 }
1138
1139 void sdram_assert_command(void)
1140 {
1141         dimms_read(0x400);
1142 }
1143
1144 void sdram_set_mode_register(void)
1145 {
1146         unsigned char byte;
1147         unsigned cas_mode;
1148         set_ram_command(RAM_COMMAND_MRS);
1149         byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76);
1150         cas_mode = byte & 0x4;
1151         cas_mode ^= 4;
1152         cas_mode <<= 2;
1153         cas_mode |= 0x2a;
1154         cas_mode <<= 3;
1155         dimms_read(cas_mode);
1156 }
1157
1158 void sdram_enable_refresh(void)
1159 {
1160         spd_enable_refresh();
1161 }
1162
1163
1164 unsigned long sdram_get_ecc_size_bytes(void)
1165 {
1166         unsigned char byte;
1167         unsigned long size;
1168         /* FIXME handle the no ram case. */
1169         /* Read the RAM SIZE */
1170         byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67);
1171         /* Convert it to bytes */
1172         size = byte;
1173         size <<= 23;
1174 #if !USE_ECC
1175         size = 0;
1176 #endif
1177         return size;
1178 }
1179
1180 /* Dummy udelay code acting as a place holder... */
1181 void udelay(int count)
1182 {
1183         int i;
1184         i = 5;
1185 }
1186
1187 void sdram_enable(void)
1188 {
1189 #if HAVE_STRING_SUPPORT
1190         print_debug("Ram Enable 1\n");
1191 #endif
1192
1193         /* noop command */
1194         sdram_set_command_noop();
1195         udelay(200);
1196         sdram_assert_command();
1197
1198         /* Precharge all */
1199         sdram_set_command_precharge();
1200         sdram_assert_command();
1201
1202         /* wait until the all banks idle state... */
1203 #if HAVE_STRING_SUPPORT
1204         print_debug("Ram Enable 2\n");
1205 #endif
1206         
1207         /* Now we need 8 AUTO REFRESH / CBR cycles to be performed */
1208         
1209         sdram_set_command_cbr();
1210         sdram_assert_command();
1211         sdram_assert_command();
1212         sdram_assert_command();
1213         sdram_assert_command();
1214         sdram_assert_command();
1215         sdram_assert_command();
1216         sdram_assert_command();
1217         sdram_assert_command();
1218         
1219 #if HAVE_STRING_SUPPORT
1220         print_debug("Ram Enable 3\n");
1221 #endif
1222         
1223         /* mode register set */
1224         sdram_set_mode_register();
1225         /* MAx[14:0] lines,
1226          * MAx[2:0 ] 010 == burst mode of 4
1227          * MAx[3:3 ] 1 == interleave wrap type
1228          * MAx[4:4 ] == CAS# latency bit
1229          * MAx[6:5 ] == 01
1230          * MAx[12:7] == 0
1231          */
1232
1233 #if HAVE_STRING_SUPPORT
1234         print_debug("Ram Enable 4\n");
1235 #endif
1236
1237         /* normal operation */
1238         sdram_set_command_none();
1239         
1240 #if HAVE_STRING_SUPPORT
1241         print_debug("Ram Enable 5\n");
1242 #endif
1243 }
1244
1245 /* Setup SDRAM */
1246 void sdram_initialize(void)
1247 {
1248 #if HAVE_STRING_SUPPORT
1249         print_debug("Ram1\n");
1250 #endif
1251         /* Set the registers we can set once to reasonable values */
1252         sdram_set_registers();
1253
1254 #if HAVE_STRING_SUPPORT
1255         print_debug("Ram2\n");
1256 #endif
1257         /* Now setup those things we can auto detect */
1258         sdram_set_spd_registers();
1259
1260 #if HAVE_STRING_SUPPORT
1261         print_debug("Ram3\n");
1262 #endif
1263         /* Now that everything is setup enable the SDRAM.
1264          * Some chipsets do the work for use while on others 
1265          * we need to it by hand.
1266          */
1267         sdram_enable();
1268
1269 #if HAVE_STRING_SUPPORT
1270         print_debug("Ram4\n");
1271 #endif
1272         sdram_first_normal_reference();
1273
1274 #if HAVE_STRING_SUPPORT
1275         print_debug("Ram5\n");
1276 #endif
1277         sdram_enable_refresh();
1278         sdram_special_finishup();
1279
1280 #if HAVE_STRING_SUPPORT
1281         print_debug("Ram6\n");
1282 #endif
1283 }