1 struct syscall_result {
6 static struct syscall_result syscall_return(long result)
8 struct syscall_result res;
9 if (((unsigned long)result) >= ((unsigned long)-125)) {
19 static struct syscall_result syscall0(unsigned long nr)
26 return syscall_return(res);
29 static struct syscall_result syscall1(unsigned long nr, unsigned long arg1)
35 : "a" (nr), "b" (arg1));
36 return syscall_return(res);
40 static struct syscall_result syscall2(unsigned long nr, unsigned long arg1, unsigned long arg2)
46 : "a" (nr), "b" (arg1), "c" (arg2));
47 return syscall_return(res);
52 static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2,
59 : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3));
60 return syscall_return(res);
64 static struct syscall_result syscall4(unsigned long nr, unsigned long arg1, unsigned long arg2,
65 unsigned long arg3, unsigned long arg4)
71 : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4));
72 return syscall_return(res);
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)
83 : "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3),
84 "S" (arg4), "D" (arg5));
85 return syscall_return(res);
106 #define NR_oldstat 18
116 #define NR_oldfstat 28
137 #define NR_geteuid 49
138 #define NR_getegid 50
140 #define NR_umount2 52
145 #define NR_setpgid 57
147 #define NR_oldolduname 59
152 #define NR_getppid 64
153 #define NR_getpgrp 65
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
171 #define NR_symlink 83
172 #define NR_oldlstat 84
173 #define NR_readlink 85
177 #define NR_readdir 89
180 #define NR_truncate 92
181 #define NR_ftruncate 93
184 #define NR_getpriority 96
185 #define NR_setpriority 97
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
197 #define NR_olduname 109
199 #define NR_vhangup 111
201 #define NR_vm86old 113
203 #define NR_swapoff 115
204 #define NR_sysinfo 116
207 #define NR_sigreturn 119
209 #define NR_setdomainname 121
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
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
234 #define NR_writev 146
235 #define NR_getsid 147
236 #define NR_fdatasync 148
237 #define NR__sysctl 149
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
255 #define NR_query_module 167
257 #define NR_nfsservctl 169
258 #define NR_setresgid 170
259 #define NR_getresgid 171
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
269 #define NR_pwrite 181
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 */
280 typedef long ssize_t;
281 typedef unsigned long size_t;
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 */
288 static ssize_t write(int fd, const void *buf, size_t count)
290 struct syscall_result res;
291 res = syscall3(NR_write, fd, (unsigned long)buf, count);
295 static void _exit(int status)
297 struct syscall_result res;
298 res = syscall1(NR_exit, status);
301 static const char *addr_of_char(unsigned char ch)
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,
340 static void console_tx_byte(unsigned char ch)
342 write(STDOUT_FILENO, addr_of_char(ch), 1);
345 static void console_tx_nibble(unsigned nibble)
348 digit = nibble + '0';
352 console_tx_byte(digit);
355 static void console_tx_char(unsigned char byte)
357 console_tx_byte(byte);
360 static void console_tx_hex8(unsigned char value)
362 console_tx_nibble((value >> 4U) & 0x0fU);
363 console_tx_nibble(value & 0x0fU);
366 static void console_tx_hex16(unsigned short value)
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);
374 static void console_tx_hex32(unsigned short value)
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);
386 static void console_tx_string(const char *str)
389 while((ch = *str++) != '\0') {
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); }
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); }
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.
415 return __builtin_bsr(value);
419 static void die(const char *str)
428 static int smbus_read_byte(unsigned device, unsigned address)
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,
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,
465 return dimm[(device << 8) + address];
468 #define SMBUS_MEM_DEVICE_START 0x00
469 #define SMBUS_MEM_DEVICE_END 0x01
470 #define SMBUS_MEM_DEVICE_INC 1
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
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
496 typedef unsigned char uint8_t;
497 typedef unsigned int uint32_t;
499 static unsigned spd_to_dimm(unsigned device)
501 return (device - SMBUS_MEM_DEVICE_START);
504 static void disable_dimm(unsigned index)
506 print_debug("disabling dimm");
507 print_debug_hex8(index);
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);
521 static const struct mem_param *get_mem_param(unsigned min_cycle_time)
523 static const struct mem_param speed[] = {
526 .dch_memclk = DCH_MEMCLK_100MHZ << DCH_MEMCLK_SHIFT,
530 .dch_memclk = DCH_MEMCLK_133MHZ << DCH_MEMCLK_SHIFT,
534 .dch_memclk = DCH_MEMCLK_166MHZ << DCH_MEMCLK_SHIFT,
538 .dch_memclk = DCH_MEMCLK_200MHZ << DCH_MEMCLK_SHIFT,
544 const struct mem_param *param;
545 for(param = &speed[0]; param->cycle_time ; param++) {
546 if (min_cycle_time > (param+1)->cycle_time) {
550 if (!param->cycle_time) {
551 die("min_cycle_time to low");
557 static void debug(int c)
560 print_debug_char('\r');
561 print_debug_char('\n');
564 static const struct mem_param *spd_set_memclk(void)
566 /* Compute the minimum cycle time for these dimms */
567 const struct mem_param *param;
568 unsigned min_cycle_time, min_latency;
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 */
582 value = pci_read_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP);
586 min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
590 print_debug("min_cycle_time: ");
591 print_debug_hex8(min_cycle_time);
592 print_debug(" min_latency: ");
593 print_debug_hex8(min_latency);
597 /* Compute the least latency with the fastest clock supported
598 * by both the memory controller and the dimms.
600 for(device = SMBUS_MEM_DEVICE_START;
601 device <= SMBUS_MEM_DEVICE_END;
602 device += SMBUS_MEM_DEVICE_INC)
604 int new_cycle_time, new_latency;
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
621 new_cycle_time = 0xa0;
624 latencies = smbus_read_byte(device, 18);
625 if (latencies <= 0) continue;
628 /* Compute the lowest cas latency supported */
629 latency = log2(latencies) -2;
631 /* Loop through and find a fast clock with a low latency */
632 for(index = 0; index < 3; index++, latency++) {
635 if ((latency < 2) || (latency > 4) ||
636 (!(latencies & (1 << latency)))) {
640 value = smbus_read_byte(device, latency_indicies[index]);
641 if (value < 0) continue;
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;
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);
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);
670 if (new_latency > 4){
674 /* Does min_latency need to be increased? */
675 if (new_cycle_time > min_cycle_time) {
676 min_cycle_time = new_cycle_time;
678 /* Does min_cycle_time need to be increased? */
679 if (new_latency > min_latency) {
680 min_latency = new_latency;
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);
692 /* Make a second pass through the dimms and disable
693 * any that cannot support the selected memclk and cas latency.
695 for(device = SMBUS_MEM_DEVICE_START;
696 device <= SMBUS_MEM_DEVICE_END;
697 device += SMBUS_MEM_DEVICE_INC)
704 latencies = smbus_read_byte(device, 18);
705 if (latencies <= 0) {
709 /* Compute the lowest cas latency supported */
710 latency = log2(latencies) -2;
712 /* Walk through searching for the selected latency */
713 for(index = 0; index < 3; index++, latency++) {
714 if (!(latencies & (1 << latency))) {
717 if (latency == min_latency)
720 /* If I can't find the latency or my index is bad error */
721 if ((latency != min_latency) || (index >= 3)) {
725 /* Read the min_cycle_time for this latency */
726 value = smbus_read_byte(device, latency_indicies[index]);
728 /* All is good if the selected clock speed
729 * is what I need or slower.
731 if (value <= min_cycle_time) {
734 /* Otherwise I have an error, disable the dimm */
736 disable_dimm(spd_to_dimm(device));
739 print_debug("min_cycle_time: ");
740 print_debug_hex8(min_cycle_time);
741 print_debug(" min_latency: ");
742 print_debug_hex8(min_latency);
745 /* Now that I know the minimum cycle time lookup the memory parameters */
746 param = get_mem_param(min_cycle_time);
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);
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);
759 value |= latencies[min_latency - 2];
760 pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW, value);
766 static void main(void)
768 const struct mem_param *param;
769 param = spd_set_memclk();