Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / util / romcc / tests / simple_test54.c
1 struct syscall_result {
2         long val;
3         int errno;
4 };
5
6 static struct syscall_result syscall_return(long result)
7 {
8         struct syscall_result res;
9         if (((unsigned long)result) >= ((unsigned long)-125)) {
10                 res.errno = - result;
11                 res.val = -1;
12         } else {
13                 res.errno = 0;
14                 res.val = result;
15         }
16         return res;
17 }
18
19 static struct syscall_result syscall0(unsigned long nr)
20 {
21         long res;
22         asm volatile(
23                 "int $0x80"
24                 : "=a" (res)
25                 : "a" (nr));
26         return syscall_return(res);
27 }
28
29 static struct syscall_result syscall1(unsigned long nr, unsigned long arg1)
30 {
31         long res;
32         asm volatile(
33                 "int $0x80"
34                 : "=a" (res)
35                 : "a" (nr), "b" (arg1));
36         return syscall_return(res);
37
38 }
39
40 static struct syscall_result syscall2(unsigned long nr, unsigned long arg1, unsigned long arg2)
41 {
42         long res;
43         asm volatile(
44                 "int $0x80"
45                 : "=a" (res)
46                 : "a" (nr), "b" (arg1), "c" (arg2));
47         return syscall_return(res);
48
49 }
50
51
52 static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2,
53         unsigned long arg3)
54 {
55         long res;
56         asm volatile(
57                 "int $0x80"
58                 : "=a" (res)
59                 : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3));
60         return syscall_return(res);
61
62 }
63
64 static struct syscall_result syscall4(unsigned long nr, unsigned long arg1, unsigned long arg2,
65         unsigned long arg3, unsigned long arg4)
66 {
67         long res;
68         asm volatile(
69                 "int $0x80"
70                 : "=a" (res)
71                 : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4));
72         return syscall_return(res);
73
74 }
75
76 static struct syscall_result syscall5(unsigned long nr, unsigned long arg1, unsigned long arg2,
77         unsigned long arg3, unsigned long arg4, unsigned long arg5)
78 {
79         long res;
80         asm volatile(
81                 "int $0x80"
82                 : "=a" (res)
83                 : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3),
84                 "S" (arg4), "D" (arg5));
85         return syscall_return(res);
86
87 }
88
89 #define NR_exit                 1
90 #define NR_fork                 2
91 #define NR_read                 3
92 #define NR_write                4
93 #define NR_open                 5
94 #define NR_close                6
95 #define NR_waitpid              7
96 #define NR_creat                8
97 #define NR_link                 9
98 #define NR_unlink              10
99 #define NR_execve              11
100 #define NR_chdir               12
101 #define NR_time                13
102 #define NR_mknod               14
103 #define NR_chmod               15
104 #define NR_lchown              16
105 #define NR_break               17
106 #define NR_oldstat             18
107 #define NR_lseek               19
108 #define NR_getpid              20
109 #define NR_mount               21
110 #define NR_umount              22
111 #define NR_setuid              23
112 #define NR_getuid              24
113 #define NR_stime               25
114 #define NR_ptrace              26
115 #define NR_alarm               27
116 #define NR_oldfstat            28
117 #define NR_pause               29
118 #define NR_utime               30
119 #define NR_stty                31
120 #define NR_gtty                32
121 #define NR_access              33
122 #define NR_nice                34
123 #define NR_ftime               35
124 #define NR_sync                36
125 #define NR_kill                37
126 #define NR_rename              38
127 #define NR_mkdir               39
128 #define NR_rmdir               40
129 #define NR_dup                 41
130 #define NR_pipe                42
131 #define NR_times               43
132 #define NR_prof                44
133 #define NR_brk                 45
134 #define NR_setgid              46
135 #define NR_getgid              47
136 #define NR_signal              48
137 #define NR_geteuid             49
138 #define NR_getegid             50
139 #define NR_acct                51
140 #define NR_umount2             52
141 #define NR_lock                53
142 #define NR_ioctl               54
143 #define NR_fcntl               55
144 #define NR_mpx                 56
145 #define NR_setpgid             57
146 #define NR_ulimit              58
147 #define NR_oldolduname         59
148 #define NR_umask               60
149 #define NR_chroot              61
150 #define NR_ustat               62
151 #define NR_dup2                63
152 #define NR_getppid             64
153 #define NR_getpgrp             65
154 #define NR_setsid              66
155 #define NR_sigaction           67
156 #define NR_sgetmask            68
157 #define NR_ssetmask            69
158 #define NR_setreuid            70
159 #define NR_setregid            71
160 #define NR_sigsuspend          72
161 #define NR_sigpending          73
162 #define NR_sethostname         74
163 #define NR_setrlimit           75
164 #define NR_getrlimit           76
165 #define NR_getrusage           77
166 #define NR_gettimeofday        78
167 #define NR_settimeofday        79
168 #define NR_getgroups           80
169 #define NR_setgroups           81
170 #define NR_select              82
171 #define NR_symlink             83
172 #define NR_oldlstat            84
173 #define NR_readlink            85
174 #define NR_uselib              86
175 #define NR_swapon              87
176 #define NR_reboot              88
177 #define NR_readdir             89
178 #define NR_mmap                90
179 #define NR_munmap              91
180 #define NR_truncate            92
181 #define NR_ftruncate           93
182 #define NR_fchmod              94
183 #define NR_fchown              95
184 #define NR_getpriority         96
185 #define NR_setpriority         97
186 #define NR_profil              98
187 #define NR_statfs              99
188 #define NR_fstatfs            100
189 #define NR_ioperm             101
190 #define NR_socketcall         102
191 #define NR_syslog             103
192 #define NR_setitimer          104
193 #define NR_getitimer          105
194 #define NR_stat               106
195 #define NR_lstat              107
196 #define NR_fstat              108
197 #define NR_olduname           109
198 #define NR_iopl               110
199 #define NR_vhangup            111
200 #define NR_idle               112
201 #define NR_vm86old            113
202 #define NR_wait4              114
203 #define NR_swapoff            115
204 #define NR_sysinfo            116
205 #define NR_ipc                117
206 #define NR_fsync              118
207 #define NR_sigreturn          119
208 #define NR_clone              120
209 #define NR_setdomainname      121
210 #define NR_uname              122
211 #define NR_modify_ldt         123
212 #define NR_adjtimex           124
213 #define NR_mprotect           125
214 #define NR_sigprocmask        126
215 #define NR_create_module      127
216 #define NR_init_module        128
217 #define NR_delete_module      129
218 #define NR_get_kernel_syms    130
219 #define NR_quotactl           131
220 #define NR_getpgid            132
221 #define NR_fchdir             133
222 #define NR_bdflush            134
223 #define NR_sysfs              135
224 #define NR_personality        136
225 #define NR_afs_syscall        137 /* Syscall for Andrew File System */
226 #define NR_setfsuid           138
227 #define NR_setfsgid           139
228 #define NR__llseek            140
229 #define NR_getdents           141
230 #define NR__newselect         142
231 #define NR_flock              143
232 #define NR_msync              144
233 #define NR_readv              145
234 #define NR_writev             146
235 #define NR_getsid             147
236 #define NR_fdatasync          148
237 #define NR__sysctl            149
238 #define NR_mlock              150
239 #define NR_munlock            151
240 #define NR_mlockall           152
241 #define NR_munlockall         153
242 #define NR_sched_setparam             154
243 #define NR_sched_getparam             155
244 #define NR_sched_setscheduler         156
245 #define NR_sched_getscheduler         157
246 #define NR_sched_yield                158
247 #define NR_sched_get_priority_max     159
248 #define NR_sched_get_priority_min     160
249 #define NR_sched_rr_get_interval      161
250 #define NR_nanosleep          162
251 #define NR_mremap             163
252 #define NR_setresuid          164
253 #define NR_getresuid          165
254 #define NR_vm86               166
255 #define NR_query_module       167
256 #define NR_poll               168
257 #define NR_nfsservctl         169
258 #define NR_setresgid          170
259 #define NR_getresgid          171
260 #define NR_prctl              172
261 #define NR_rt_sigreturn       173
262 #define NR_rt_sigaction       174
263 #define NR_rt_sigprocmask     175
264 #define NR_rt_sigpending      176
265 #define NR_rt_sigtimedwait    177
266 #define NR_rt_sigqueueinfo    178
267 #define NR_rt_sigsuspend      179
268 #define NR_pread              180
269 #define NR_pwrite             181
270 #define NR_chown              182
271 #define NR_getcwd             183
272 #define NR_capget             184
273 #define NR_capset             185
274 #define NR_sigaltstack        186
275 #define NR_sendfile           187
276 #define NR_getpmsg            188     /* some people actually want streams */
277 #define NR_putpmsg            189     /* some people actually want streams */
278 #define NR_vfork              190
279
280 typedef long ssize_t;
281 typedef unsigned long size_t;
282
283 /* Standard file descriptors */
284 #define STDIN_FILENO    0  /* Standard input */
285 #define STDOUT_FILENO   1  /* Standard output */
286 #define STDERR_FILENO   2  /* Standard error output */
287
288 static ssize_t write(int fd, const void *buf, size_t count)
289 {
290         struct syscall_result res;
291         res = syscall3(NR_write, fd, (unsigned long)buf, count);
292         return res.val;
293 }
294
295 static void _exit(int status)
296 {
297         struct syscall_result res;
298         res = syscall1(NR_exit, status);
299 }
300
301 static const char *addr_of_char(unsigned char ch)
302 {
303         static const char byte[] = {
304                 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
305                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
306                 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
307                 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
308                 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
309                 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
310                 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
311                 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
312                 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
313                 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
314                 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
315                 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
316                 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
317                 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
318                 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
319                 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
320                 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
321                 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
322                 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
323                 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
324                 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
325                 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
326                 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
327                 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
328                 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
329                 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
330                 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
331                 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
332                 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
333                 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
334                 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
335                 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
336         };
337         return byte + ch;
338 }
339
340 static void console_tx_byte(unsigned char ch)
341 {
342         write(STDOUT_FILENO, addr_of_char(ch), 1);
343 }
344
345 static void console_tx_nibble(unsigned nibble)
346 {
347         unsigned char digit;
348         digit = nibble + '0';
349         if (digit > '9') {
350                 digit += 39;
351         }
352         console_tx_byte(digit);
353 }
354
355 static void console_tx_char(unsigned char byte)
356 {
357         console_tx_byte(byte);
358 }
359
360 static void console_tx_hex8(unsigned char value)
361 {
362         console_tx_nibble((value >> 4U) & 0x0fU);
363         console_tx_nibble(value & 0x0fU);
364 }
365
366 static void console_tx_hex16(unsigned short value)
367 {
368         console_tx_nibble((value >> 12U) & 0x0FU);
369         console_tx_nibble((value >>  8U) & 0x0FU);
370         console_tx_nibble((value >>  4U) & 0x0FU);
371         console_tx_nibble(value & 0x0FU);
372 }
373
374 static void console_tx_hex32(unsigned short value)
375 {
376         console_tx_nibble((value >> 28U) & 0x0FU);
377         console_tx_nibble((value >> 24U) & 0x0FU);
378         console_tx_nibble((value >> 20U) & 0x0FU);
379         console_tx_nibble((value >> 16U) & 0x0FU);
380         console_tx_nibble((value >> 12U) & 0x0FU);
381         console_tx_nibble((value >>  8U) & 0x0FU);
382         console_tx_nibble((value >>  4U) & 0x0FU);
383         console_tx_nibble(value & 0x0FU);
384 }
385
386 static void console_tx_string(const char *str)
387 {
388         unsigned char ch;
389         while((ch = *str++) != '\0') {
390                 console_tx_byte(ch);
391         }
392 }
393
394 static void print_emerg_char(unsigned char byte) { console_tx_char(byte); }
395 static void print_emerg_hex8(unsigned char value) { console_tx_hex8(value); }
396 static void print_emerg_hex16(unsigned short value){ console_tx_hex16(value); }
397 static void print_emerg_hex32(unsigned int value) { console_tx_hex32(value); }
398 static void print_emerg(const char *str) { console_tx_string(str); }
399
400 static void print_debug_char(unsigned char byte) { console_tx_char(byte); }
401 static void print_debug_hex8(unsigned char value) { console_tx_hex8(value); }
402 static void print_debug_hex16(unsigned short value){ console_tx_hex16(value); }
403 static void print_debug_hex32(unsigned int value) { console_tx_hex32(value); }
404 static void print_debug(const char *str) { console_tx_string(str); }
405
406
407 int log2(int value)
408 {
409         /* __builtin_bsr is a exactly equivalent to the x86 machine
410          * instruction with the exception that it returns -1
411          * when the value presented to it is zero.
412          * Otherwise __builtin_bsr returns the zero based index of
413          * the highest bit set.
414          */
415         return __builtin_bsr(value);
416 }
417
418
419 static void die(const char *str)
420 {
421         print_emerg(str);
422         do {
423                 asm(" ");
424         } while(1);
425
426 }
427
428 static int smbus_read_byte(unsigned device, unsigned address)
429 {
430         static const unsigned char dimm[] = {
431 0x80, 0x08, 0x07, 0x0d, 0x0a, 0x02, 0x48, 0x00, 0x04, 0x60, 0x70, 0x02, 0x82, 0x08, 0x08, 0x01,
432 0x0e, 0x04, 0x0c, 0x01, 0x02, 0x20, 0x00, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48, 0x2a, 0x40,
433 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
435 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
436 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
437 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
438 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
439 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
440 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
441 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
442 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
443 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
444 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
445 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
446 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
447
448 0x80, 0x08, 0x07, 0x0d, 0x0a, 0x02, 0x48, 0x00, 0x04, 0x60, 0x70, 0x02, 0x82, 0x08, 0x08, 0x01,
449 0x0e, 0x04, 0x0c, 0x01, 0x02, 0x20, 0x00, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48, 0x2a, 0x40,
450 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
452 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
454 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
455 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
456 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
457 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
458 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
459 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
460 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
461 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
462 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
463 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
464         };
465         return dimm[(device << 8) + address];
466 }
467
468 #define SMBUS_MEM_DEVICE_START 0x00
469 #define SMBUS_MEM_DEVICE_END   0x01
470 #define SMBUS_MEM_DEVICE_INC   1
471
472 /* Function 2 */
473 #define DRAM_CONFIG_HIGH   0x94
474 #define  DCH_MEMCLK_SHIFT  20
475 #define  DCH_MEMCLK_MASK   7
476 #define  DCH_MEMCLK_100MHZ 0
477 #define  DCH_MEMCLK_133MHZ 2
478 #define  DCH_MEMCLK_166MHZ 5
479 #define  DCH_MEMCLK_200MHZ 7
480
481 /* Function 3 */
482 #define NORTHBRIDGE_CAP    0xE8
483 #define  NBCAP_128Bit         0x0001
484 #define  NBCAP_MP             0x0002
485 #define  NBCAP_BIG_MP         0x0004
486 #define  NBCAP_ECC            0x0004
487 #define  NBCAP_CHIPKILL_ECC   0x0010
488 #define  NBCAP_MEMCLK_SHIFT   5
489 #define  NBCAP_MEMCLK_MASK    3
490 #define  NBCAP_MEMCLK_100MHZ  3
491 #define  NBCAP_MEMCLK_133MHZ  2
492 #define  NBCAP_MEMCLK_166MHZ  1
493 #define  NBCAP_MEMCLK_200MHZ  0
494 #define  NBCAP_MEMCTRL        0x0100
495
496 typedef unsigned char uint8_t;
497 typedef unsigned int uint32_t;
498
499 static unsigned spd_to_dimm(unsigned device)
500 {
501         return (device - SMBUS_MEM_DEVICE_START);
502 }
503
504 static void disable_dimm(unsigned index)
505 {
506         print_debug("disabling dimm");
507         print_debug_hex8(index);
508         print_debug("\r\n");
509 #if 0
510         pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CSBASE + (((index << 1)+0)<<2), 0);
511         pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CSBASE + (((index << 1)+1)<<2), 0);
512 #endif
513 }
514
515
516 struct mem_param {
517         uint8_t cycle_time;
518         uint32_t dch_memclk;
519 };
520
521 static const struct mem_param *get_mem_param(unsigned min_cycle_time)
522 {
523         static const struct mem_param speed[] = {
524                 {
525                         .cycle_time = 0xa0,
526                         .dch_memclk = DCH_MEMCLK_100MHZ << DCH_MEMCLK_SHIFT,
527                 },
528                 {
529                         .cycle_time = 0x75,
530                         .dch_memclk = DCH_MEMCLK_133MHZ << DCH_MEMCLK_SHIFT,
531                 },
532                 {
533                         .cycle_time = 0x60,
534                         .dch_memclk = DCH_MEMCLK_166MHZ << DCH_MEMCLK_SHIFT,
535                 },
536                 {
537                         .cycle_time = 0x50,
538                         .dch_memclk = DCH_MEMCLK_200MHZ << DCH_MEMCLK_SHIFT,
539                 },
540                 {
541                         .cycle_time = 0x00,
542                 },
543         };
544         const struct mem_param *param;
545         for(param = &speed[0]; param->cycle_time ; param++) {
546                 if (min_cycle_time > (param+1)->cycle_time) {
547                         break;
548                 }
549         }
550         if (!param->cycle_time) {
551                 die("min_cycle_time to low");
552         }
553         return param;
554 }
555
556 #if 1
557 static void debug(int c)
558 {
559         print_debug_char(c);
560         print_debug_char('\r');
561         print_debug_char('\n');
562 }
563 #endif
564 static const struct mem_param *spd_set_memclk(void)
565 {
566         /* Compute the minimum cycle time for these dimms */
567         const struct mem_param *param;
568         unsigned min_cycle_time, min_latency;
569         unsigned device;
570         uint32_t value;
571
572         static const int latency_indicies[] = { 26, 23, 9 };
573         static const unsigned char min_cycle_times[] = {
574                 [NBCAP_MEMCLK_200MHZ] = 0x50, /* 5ns */
575                 [NBCAP_MEMCLK_166MHZ] = 0x60, /* 6ns */
576                 [NBCAP_MEMCLK_133MHZ] = 0x75, /* 7.5ns */
577                 [NBCAP_MEMCLK_100MHZ] = 0xa0, /* 10ns */
578         };
579
580
581 #if 0
582         value = pci_read_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP);
583 #else
584         value = 0x50;
585 #endif
586         min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
587         min_latency = 2;
588
589 #if 1
590         print_debug("min_cycle_time: ");
591         print_debug_hex8(min_cycle_time);
592         print_debug(" min_latency: ");
593         print_debug_hex8(min_latency);
594         print_debug("\r\n");
595 #endif
596
597         /* Compute the least latency with the fastest clock supported
598          * by both the memory controller and the dimms.
599          */
600         for(device = SMBUS_MEM_DEVICE_START;
601                 device <= SMBUS_MEM_DEVICE_END;
602                 device += SMBUS_MEM_DEVICE_INC)
603         {
604                 int new_cycle_time, new_latency;
605                 int index;
606                 int latencies;
607                 int latency;
608
609                 debug('A');
610                 /* First find the supported CAS latencies
611                  * Byte 18 for DDR SDRAM is interpreted:
612                  * bit 0 == CAS Latency = 1.0
613                  * bit 1 == CAS Latency = 1.5
614                  * bit 2 == CAS Latency = 2.0
615                  * bit 3 == CAS Latency = 2.5
616                  * bit 4 == CAS Latency = 3.0
617                  * bit 5 == CAS Latency = 3.5
618                  * bit 6 == TBD
619                  * bit 7 == TBD
620                  */
621                 new_cycle_time = 0xa0;
622                 new_latency = 5;
623
624                 latencies = smbus_read_byte(device, 18);
625                 if (latencies <= 0) continue;
626
627                 debug('B');
628                 /* Compute the lowest cas latency supported */
629                 latency = log2(latencies) -2;
630
631                 /* Loop through and find a fast clock with a low latency */
632                 for(index = 0; index < 3; index++, latency++) {
633                         int value;
634                         debug('C');
635                         if ((latency < 2) || (latency > 4) ||
636                                 (!(latencies & (1 << latency)))) {
637                                 continue;
638                         }
639                         debug('D');
640                         value = smbus_read_byte(device, latency_indicies[index]);
641                         if (value < 0) continue;
642
643                         debug('E');
644                         /* Only increase the latency if we decreas the clock */
645                         if ((value >= min_cycle_time) && (value < new_cycle_time)) {
646                                 new_cycle_time = value;
647                                 new_latency = latency;
648 #if 1
649                                 print_debug("device: ");
650                                 print_debug_hex8(device);
651                                 print_debug(" new_cycle_time: ");
652                                 print_debug_hex8(new_cycle_time);
653                                 print_debug(" new_latency: ");
654                                 print_debug_hex8(new_latency);
655                                 print_debug("\r\n");
656 #endif
657                         }
658                         debug('G');
659                 }
660                 debug('H');
661 #if 1
662                 print_debug("device: ");
663                 print_debug_hex8(device);
664                 print_debug(" new_cycle_time: ");
665                 print_debug_hex8(new_cycle_time);
666                 print_debug(" new_latency: ");
667                 print_debug_hex8(new_latency);
668                 print_debug("\r\n");
669 #endif
670                 if (new_latency > 4){
671                         continue;
672                 }
673                 debug('I');
674                 /* Does min_latency need to be increased? */
675                 if (new_cycle_time > min_cycle_time) {
676                         min_cycle_time = new_cycle_time;
677                 }
678                 /* Does min_cycle_time need to be increased? */
679                 if (new_latency > min_latency) {
680                         min_latency = new_latency;
681                 }
682 #if 1
683                 print_debug("device: ");
684                 print_debug_hex8(device);
685                 print_debug(" min_cycle_time: ");
686                 print_debug_hex8(min_cycle_time);
687                 print_debug(" min_latency: ");
688                 print_debug_hex8(min_latency);
689                 print_debug("\r\n");
690 #endif
691         }
692         /* Make a second pass through the dimms and disable
693          * any that cannot support the selected memclk and cas latency.
694          */
695         for(device = SMBUS_MEM_DEVICE_START;
696                 device <= SMBUS_MEM_DEVICE_END;
697                 device += SMBUS_MEM_DEVICE_INC)
698         {
699                 int latencies;
700                 int latency;
701                 int index;
702                 int value;
703                 int dimm;
704                 latencies = smbus_read_byte(device, 18);
705                 if (latencies <= 0) {
706                         goto dimm_err;
707                 }
708
709                 /* Compute the lowest cas latency supported */
710                 latency = log2(latencies) -2;
711
712                 /* Walk through searching for the selected latency */
713                 for(index = 0; index < 3; index++, latency++) {
714                         if (!(latencies & (1 << latency))) {
715                                 continue;
716                         }
717                         if (latency == min_latency)
718                                 break;
719                 }
720                 /* If I can't find the latency or my index is bad error */
721                 if ((latency != min_latency) || (index >= 3)) {
722                         goto dimm_err;
723                 }
724
725                 /* Read the min_cycle_time for this latency */
726                 value = smbus_read_byte(device, latency_indicies[index]);
727
728                 /* All is good if the selected clock speed
729                  * is what I need or slower.
730                  */
731                 if (value <= min_cycle_time) {
732                         continue;
733                 }
734                 /* Otherwise I have an error, disable the dimm */
735         dimm_err:
736                 disable_dimm(spd_to_dimm(device));
737         }
738 #if 1
739         print_debug("min_cycle_time: ");
740         print_debug_hex8(min_cycle_time);
741         print_debug(" min_latency: ");
742         print_debug_hex8(min_latency);
743         print_debug("\r\n");
744 #endif
745         /* Now that I know the minimum cycle time lookup the memory parameters */
746         param = get_mem_param(min_cycle_time);
747
748 #if 0
749         /* Update DRAM Config High with our selected memory speed */
750         value = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_HIGH);
751         value &= ~(DCH_MEMCLK_MASK << DCH_MEMCLK_SHIFT);
752         value |= param->dch_memclk;
753         pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_HIGH, value);
754
755         static const unsigned latencies[] = { 1, 5, 2 };
756         /* Update DRAM Timing Low wiht our selected cas latency */
757         value = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW);
758         value &= ~7;
759         value |= latencies[min_latency - 2];
760         pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW, value);
761 #endif
762
763         return param;
764 }
765
766 static void main(void)
767 {
768         const struct mem_param *param;
769         param = spd_set_memclk();
770         _exit(0);
771 }