1 typedef unsigned char uint8_t;
2 typedef signed char int8_t;
3 typedef unsigned short uint16_t;
4 typedef signed short int16_t;
5 typedef unsigned int uint32_t;
6 typedef signed int int32_t;
8 typedef unsigned char uint_least8_t;
9 typedef signed char int_least8_t;
10 typedef unsigned short uint_least16_t;
11 typedef signed short int_least16_t;
12 typedef unsigned int uint_least32_t;
13 typedef signed int int_least32_t;
15 typedef unsigned char uint_fast8_t;
16 typedef signed char int_fast8_t;
17 typedef unsigned int uint_fast16_t;
18 typedef signed int int_fast16_t;
19 typedef unsigned int uint_fast32_t;
20 typedef signed int int_fast32_t;
23 typedef unsigned int uintptr_t;
25 typedef long int intmax_t;
26 typedef unsigned long int uintmax_t;
28 static inline unsigned long apic_read(unsigned long reg)
30 return *((volatile unsigned long *)(0xfee00000 +reg));
32 static inline void apic_write(unsigned long reg, unsigned long v)
34 *((volatile unsigned long *)(0xfee00000 +reg)) = v;
36 static inline void apic_wait_icr_idle(void)
38 do { } while ( apic_read( 0x300 ) & 0x01000 );
41 static void outb(unsigned char value, unsigned short port)
43 __builtin_outb(value, port);
45 static void outw(unsigned short value, unsigned short port)
47 __builtin_outw(value, port);
49 static void outl(unsigned int value, unsigned short port)
51 __builtin_outl(value, port);
53 static unsigned char inb(unsigned short port)
55 return __builtin_inb(port);
57 static unsigned char inw(unsigned short port)
59 return __builtin_inw(port);
61 static unsigned char inl(unsigned short port)
63 return __builtin_inl(port);
65 static inline void outsb(uint16_t port, const void *addr, unsigned long count)
67 __asm__ __volatile__ (
69 : "=S" (addr), "=c" (count)
70 : "d"(port), "0"(addr), "1" (count)
73 static inline void outsw(uint16_t port, const void *addr, unsigned long count)
75 __asm__ __volatile__ (
77 : "=S" (addr), "=c" (count)
78 : "d"(port), "0"(addr), "1" (count)
81 static inline void outsl(uint16_t port, const void *addr, unsigned long count)
83 __asm__ __volatile__ (
85 : "=S" (addr), "=c" (count)
86 : "d"(port), "0"(addr), "1" (count)
89 static inline void insb(uint16_t port, void *addr, unsigned long count)
91 __asm__ __volatile__ (
93 : "=D" (addr), "=c" (count)
94 : "d"(port), "0"(addr), "1" (count)
97 static inline void insw(uint16_t port, void *addr, unsigned long count)
99 __asm__ __volatile__ (
101 : "=D" (addr), "=c" (count)
102 : "d"(port), "0"(addr), "1" (count)
105 static inline void insl(uint16_t port, void *addr, unsigned long count)
107 __asm__ __volatile__ (
109 : "=D" (addr), "=c" (count)
110 : "d"(port), "0"(addr), "1" (count)
113 static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
116 outb(value, port +1);
118 static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg)
123 static inline void pnp_set_logical_device(unsigned char port, int device)
125 pnp_write_config(port, device, 0x07);
127 static inline void pnp_set_enable(unsigned char port, int enable)
129 pnp_write_config(port, enable?0x1:0x0, 0x30);
131 static inline int pnp_read_enable(unsigned char port)
133 return !!pnp_read_config(port, 0x30);
135 static inline void pnp_set_iobase0(unsigned char port, unsigned iobase)
137 pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
138 pnp_write_config(port, iobase & 0xff, 0x61);
140 static inline void pnp_set_iobase1(unsigned char port, unsigned iobase)
142 pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
143 pnp_write_config(port, iobase & 0xff, 0x63);
145 static inline void pnp_set_irq0(unsigned char port, unsigned irq)
147 pnp_write_config(port, irq, 0x70);
149 static inline void pnp_set_irq1(unsigned char port, unsigned irq)
151 pnp_write_config(port, irq, 0x72);
153 static inline void pnp_set_drq(unsigned char port, unsigned drq)
155 pnp_write_config(port, drq & 0xff, 0x74);
157 static void hlt(void)
161 typedef __builtin_div_t div_t;
162 typedef __builtin_ldiv_t ldiv_t;
163 typedef __builtin_udiv_t udiv_t;
164 typedef __builtin_uldiv_t uldiv_t;
165 static div_t div(int numer, int denom)
167 return __builtin_div(numer, denom);
169 static ldiv_t ldiv(long numer, long denom)
171 return __builtin_ldiv(numer, denom);
173 static udiv_t udiv(unsigned numer, unsigned denom)
175 return __builtin_udiv(numer, denom);
177 static uldiv_t uldiv(unsigned long numer, unsigned long denom)
179 return __builtin_uldiv(numer, denom);
184 return __builtin_bsr(value);
186 typedef unsigned device_t;
187 static unsigned char pci_read_config8(device_t dev, unsigned where)
191 outl(0x80000000 | (addr & ~3), 0xCF8);
192 return inb(0xCFC + (addr & 3));
194 static unsigned short pci_read_config16(device_t dev, unsigned where)
198 outl(0x80000000 | (addr & ~3), 0xCF8);
199 return inw(0xCFC + (addr & 2));
201 static unsigned int pci_read_config32(device_t dev, unsigned where)
205 outl(0x80000000 | (addr & ~3), 0xCF8);
208 static void pci_write_config8(device_t dev, unsigned where, unsigned char value)
212 outl(0x80000000 | (addr & ~3), 0xCF8);
213 outb(value, 0xCFC + (addr & 3));
215 static void pci_write_config16(device_t dev, unsigned where, unsigned short value)
219 outl(0x80000000 | (addr & ~3), 0xCF8);
220 outw(value, 0xCFC + (addr & 2));
222 static void pci_write_config32(device_t dev, unsigned where, unsigned int value)
226 outl(0x80000000 | (addr & ~3), 0xCF8);
229 static device_t pci_locate_device(unsigned pci_id, device_t dev)
231 for(; dev <= ( ((( 255 ) & 0xFF) << 16) | ((( 31 ) & 0x1f) << 11) | ((( 7 ) & 0x7) << 8)) ; dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) {
233 id = pci_read_config32(dev, 0);
238 return (0xffffffffU) ;
245 static int uart_can_tx_byte(void)
247 return inb(1016 + 0x05 ) & 0x20;
249 static void uart_wait_to_tx_byte(void)
251 while(!uart_can_tx_byte())
254 static void uart_wait_until_sent(void)
256 while(!(inb(1016 + 0x05 ) & 0x40))
259 static void uart_tx_byte(unsigned char data)
261 uart_wait_to_tx_byte();
262 outb(data, 1016 + 0x00 );
264 uart_wait_until_sent();
266 static void uart_init(void)
269 outb(0x0, 1016 + 0x01 );
271 outb(0x01, 1016 + 0x02 );
273 outb(0x80 | 3 , 1016 + 0x03 );
274 outb((115200/ 115200 ) & 0xFF, 1016 + 0x00 );
275 outb(((115200/ 115200 ) >> 8) & 0xFF, 1016 + 0x01 );
276 outb(3 , 1016 + 0x03 );
279 static void __console_tx_byte(unsigned char byte)
283 static void __console_tx_nibble(unsigned nibble)
286 digit = nibble + '0';
290 __console_tx_byte(digit);
292 static void __console_tx_char(int loglevel, unsigned char byte)
298 static void __console_tx_hex8(int loglevel, unsigned char value)
301 __console_tx_nibble((value >> 4U) & 0x0fU);
302 __console_tx_nibble(value & 0x0fU);
305 static void __console_tx_hex16(int loglevel, unsigned short value)
308 __console_tx_nibble((value >> 12U) & 0x0fU);
309 __console_tx_nibble((value >> 8U) & 0x0fU);
310 __console_tx_nibble((value >> 4U) & 0x0fU);
311 __console_tx_nibble(value & 0x0fU);
314 static void __console_tx_hex32(int loglevel, unsigned int value)
317 __console_tx_nibble((value >> 28U) & 0x0fU);
318 __console_tx_nibble((value >> 24U) & 0x0fU);
319 __console_tx_nibble((value >> 20U) & 0x0fU);
320 __console_tx_nibble((value >> 16U) & 0x0fU);
321 __console_tx_nibble((value >> 12U) & 0x0fU);
322 __console_tx_nibble((value >> 8U) & 0x0fU);
323 __console_tx_nibble((value >> 4U) & 0x0fU);
324 __console_tx_nibble(value & 0x0fU);
327 static void __console_tx_string(int loglevel, const char *str)
331 while((ch = *str++) != '\0') {
332 __console_tx_byte(ch);
336 static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); }
337 static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); }
338 static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); }
339 static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); }
340 static void print_emerg(const char *str) { __console_tx_string(0 , str); }
341 static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); }
342 static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); }
343 static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); }
344 static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); }
345 static void print_alert(const char *str) { __console_tx_string(1 , str); }
346 static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); }
347 static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); }
348 static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); }
349 static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); }
350 static void print_crit(const char *str) { __console_tx_string(2 , str); }
351 static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); }
352 static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); }
353 static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); }
354 static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); }
355 static void print_err(const char *str) { __console_tx_string(3 , str); }
356 static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); }
357 static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); }
358 static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); }
359 static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); }
360 static void print_warning(const char *str) { __console_tx_string(4 , str); }
361 static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); }
362 static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); }
363 static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); }
364 static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); }
365 static void print_notice(const char *str) { __console_tx_string(5 , str); }
366 static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); }
367 static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); }
368 static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); }
369 static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); }
370 static void print_info(const char *str) { __console_tx_string(6 , str); }
371 static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); }
372 static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); }
373 static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); }
374 static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); }
375 static void print_debug(const char *str) { __console_tx_string(7 , str); }
376 static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); }
377 static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); }
378 static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); }
379 static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); }
380 static void print_spew(const char *str) { __console_tx_string(8 , str); }
381 static void console_init(void)
383 static const char console_test[] =
388 "Thu Oct 9 20:29:48 MDT 2003"
390 print_info(console_test);
392 static void die(const char *str)
399 static void write_phys(unsigned long addr, unsigned long value)
404 : "r" (addr), "r" (value)
408 static unsigned long read_phys(unsigned long addr)
410 volatile unsigned long *ptr;
414 static void ram_fill(unsigned long start, unsigned long stop)
418 print_debug("DRAM fill: ");
419 print_debug_hex32(start);
421 print_debug_hex32(stop);
423 for(addr = start; addr < stop ; addr += 4) {
425 if (!(addr & 0xffff)) {
426 print_debug_hex32(addr);
429 write_phys(addr, addr);
432 print_debug_hex32(addr);
433 print_debug("\r\nDRAM filled\r\n");
435 static void ram_verify(unsigned long start, unsigned long stop)
439 print_debug("DRAM verify: ");
440 print_debug_hex32(start);
441 print_debug_char('-');
442 print_debug_hex32(stop);
444 for(addr = start; addr < stop ; addr += 4) {
447 if (!(addr & 0xffff)) {
448 print_debug_hex32(addr);
451 value = read_phys(addr);
454 print_err_hex32(addr);
456 print_err_hex32(value);
461 print_debug_hex32(addr);
462 print_debug("\r\nDRAM verified\r\n");
464 void ram_check(unsigned long start, unsigned long stop)
468 print_debug("Testing DRAM : ");
469 print_debug_hex32(start);
471 print_debug_hex32(stop);
473 ram_fill(start, stop);
474 ram_verify(start, stop);
475 print_debug("Done.\r\n");
477 static int enumerate_ht_chain(unsigned link)
480 unsigned next_unitid, last_unitid;
481 int reset_needed = 0;
485 uint8_t hdr_type, pos;
486 last_unitid = next_unitid;
487 id = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x00 );
489 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
490 (((id >> 16) & 0xffff) == 0xffff) ||
491 (((id >> 16) & 0xffff) == 0x0000)) {
494 hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x0e );
497 if ((hdr_type == 0 ) ||
499 pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x34 );
503 cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 0 );
506 flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 );
507 if ((flags >> 13) == 0) {
510 flags |= next_unitid & 0x1f;
511 count = (flags >> 5) & 0x1f;
512 pci_write_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 , flags);
513 next_unitid += count;
517 pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 1 );
519 } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
522 static void enable_smbus(void)
525 dev = pci_locate_device((((( 0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0);
526 if (dev == (0xffffffffU) ) {
527 die("SMBUS controller not found\r\n");
530 print_debug("SMBus controller enabled\r\n");
531 pci_write_config32(dev, 0x58, 0x0f00 | 1);
532 enable = pci_read_config8(dev, 0x41);
533 pci_write_config8(dev, 0x41, enable | (1 << 7));
535 outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 );
537 static inline void smbus_delay(void)
541 static int smbus_wait_until_ready(void)
544 loops = (100*1000*10) ;
548 val = inw(0x0f00 + 0xe0 );
549 if ((val & 0x800) == 0) {
552 if(loops == ((100*1000*10) / 2)) {
553 outw(inw(0x0f00 + 0xe0 ),
559 static int smbus_wait_until_done(void)
562 loops = (100*1000*10) ;
567 val = inw(0x0f00 + 0xe0 );
568 if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
574 static int smbus_read_byte(unsigned device, unsigned address)
576 unsigned char global_control_register;
577 unsigned char global_status_register;
579 if (smbus_wait_until_ready() < 0) {
585 outw(inw(0x0f00 + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00 + 0xe2 );
587 outw(((device & 0x7f) << 1) | 1, 0x0f00 + 0xe4 );
589 outb(address & 0xFF, 0x0f00 + 0xe8 );
591 outw((inw(0x0f00 + 0xe2 ) & ~7) | (0x2), 0x0f00 + 0xe2 );
594 outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 );
596 outw(0, 0x0f00 + 0xe6 );
598 outw((inw(0x0f00 + 0xe2 ) | (1 << 3)), 0x0f00 + 0xe2 );
600 if (smbus_wait_until_done() < 0) {
603 global_status_register = inw(0x0f00 + 0xe0 );
605 byte = inw(0x0f00 + 0xe6 ) & 0xff;
606 if (global_status_register != (1 << 4)) {
611 static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
615 struct mem_controller {
617 device_t f0, f1, f2, f3;
621 typedef __builtin_msr_t msr_t;
622 static msr_t rdmsr(unsigned long index)
624 return __builtin_rdmsr(index);
626 static void wrmsr(unsigned long index, msr_t msr)
628 __builtin_wrmsr(index, msr.lo, msr.hi);
634 typedef struct tsc_struct tsc_t;
635 static tsc_t rdtsc(void)
639 : "=a" (res.lo), "=d"(res.hi)
645 void init_timer(void)
648 apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));
650 apic_write(0x3E0 , 0xB );
652 apic_write(0x380 , 0xffffffff);
654 void udelay(unsigned usecs)
656 uint32_t start, value, ticks;
659 start = apic_read(0x390 );
661 value = apic_read(0x390 );
662 } while((start - value) < ticks);
665 void mdelay(unsigned msecs)
668 for(i = 0; i < msecs; i++) {
672 void delay(unsigned secs)
675 for(i = 0; i < secs; i++) {
681 volatile unsigned long *local_apic;
682 unsigned long apic_id;
686 bsp = !!(msr.lo & (1 << 8));
689 static int cpu_init_detected(void)
692 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
693 return !!(htic & (1<<6) );
695 static int bios_reset_detected(void)
698 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
699 return (htic & (1<<4) ) && !(htic & (1<<5) );
701 static int cold_reset_detected(void)
704 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
705 return !(htic & (1<<4) );
707 static void distinguish_cpu_resets(unsigned node_id)
711 device = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 + node_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ;
712 htic = pci_read_config32(device, 0x6c );
713 htic |= (1<<4) | (1<<5) | (1<<6) ;
714 pci_write_config32(device, 0x6c , htic);
716 static void set_bios_reset(void)
719 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
721 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c , htic);
723 static void print_debug_pci_dev(unsigned dev)
725 print_debug("PCI: ");
726 print_debug_hex8((dev >> 16) & 0xff);
727 print_debug_char(':');
728 print_debug_hex8((dev >> 11) & 0x1f);
729 print_debug_char('.');
730 print_debug_hex8((dev >> 8) & 7);
732 static void print_pci_devices(void)
735 for(dev = ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ;
736 dev <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 0x7 ) & 0x7) << 8)) ;
737 dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) {
739 id = pci_read_config32(dev, 0x00 );
740 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
741 (((id >> 16) & 0xffff) == 0xffff) ||
742 (((id >> 16) & 0xffff) == 0x0000)) {
745 print_debug_pci_dev(dev);
749 static void dump_pci_device(unsigned dev)
752 print_debug_pci_dev(dev);
755 for(i = 0; i <= 255; i++) {
757 if ((i & 0x0f) == 0) {
759 print_debug_char(':');
761 val = pci_read_config8(dev, i);
762 print_debug_char(' ');
763 print_debug_hex8(val);
764 if ((i & 0x0f) == 0x0f) {
769 static void dump_pci_devices(void)
772 for(dev = ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ;
773 dev <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 0x7 ) & 0x7) << 8)) ;
774 dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) {
776 id = pci_read_config32(dev, 0x00 );
777 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
778 (((id >> 16) & 0xffff) == 0xffff) ||
779 (((id >> 16) & 0xffff) == 0x0000)) {
782 dump_pci_device(dev);
785 static void dump_spd_registers(const struct mem_controller *ctrl)
789 for(i = 0; i < 4; i++) {
791 device = ctrl->channel0[i];
794 print_debug("dimm: ");
797 print_debug_hex8(device);
798 for(j = 0; j < 256; j++) {
801 if ((j & 0xf) == 0) {
806 status = smbus_read_byte(device, j);
808 print_debug("bad device\r\n");
811 byte = status & 0xff;
812 print_debug_hex8(byte);
813 print_debug_char(' ');
817 device = ctrl->channel1[i];
820 print_debug("dimm: ");
823 print_debug_hex8(device);
824 for(j = 0; j < 256; j++) {
827 if ((j & 0xf) == 0) {
832 status = smbus_read_byte(device, j);
834 print_debug("bad device\r\n");
837 byte = status & 0xff;
838 print_debug_hex8(byte);
839 print_debug_char(' ');
846 static unsigned int cpuid(unsigned int op)
849 unsigned dummy2,dummy3,dummy4;
852 : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4)
857 static int is_cpu_rev_a0(void)
859 return (cpuid(1) & 0xffff) == 0x0f10;
861 static int is_cpu_pre_c0(void)
863 return (cpuid(1) & 0xffef) < 0x0f48;
865 static void memreset_setup(void)
867 if (is_cpu_pre_c0()) {
869 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 28);
871 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 29);
875 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 29);
878 static void memreset(int controllers, const struct mem_controller *ctrl)
880 if (is_cpu_pre_c0()) {
883 outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 28);
887 static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
890 uint32_t ret=0x00010101;
891 static const unsigned int rows_2p[2][2] = {
892 { 0x00050101, 0x00010404 },
893 { 0x00010404, 0x00050101 }
896 print_debug("this mainboard is only designed for 2 cpus\r\n");
899 if (!(node>=maxnodes || row>=maxnodes)) {
900 ret=rows_2p[node][row];
904 static inline int spd_read_byte(unsigned device, unsigned address)
906 return smbus_read_byte(device, address);
909 static void coherent_ht_mainboard(unsigned cpus)
913 void cpu_ldtstop(unsigned cpus)
918 for(cnt=0; cnt<cpus; cnt++) {
920 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0x81,0x23);
922 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd4,0x00000701);
924 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd8,0x00000000);
926 tmp=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,0x90);
927 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,0x90, tmp | (1<<24) );
935 static void setup_resource_map(const unsigned int *register_values, int max)
938 print_debug("setting up resource map....\r\n");
939 for(i = 0; i < max; i += 3) {
943 dev = register_values[i] & ~0xff;
944 where = register_values[i] & 0xff;
945 reg = pci_read_config32(dev, where);
946 reg &= register_values[i+1];
947 reg |= register_values[i+2];
948 pci_write_config32(dev, where, reg);
950 print_debug("done.\r\n");
952 static void setup_default_resource_map(void)
954 static const unsigned int register_values[] = {
957 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
958 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
959 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
960 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
961 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
962 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
963 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
964 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
966 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
967 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
968 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
969 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
970 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
971 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
972 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
973 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
975 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x84 ) & 0xFF)) , 0x00000048, 0x00000000,
976 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x8C ) & 0xFF)) , 0x00000048, 0x00000000,
977 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0x00000048, 0x00000000,
978 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x9C ) & 0xFF)) , 0x00000048, 0x00000000,
979 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA4 ) & 0xFF)) , 0x00000048, 0x00000000,
980 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xAC ) & 0xFF)) , 0x00000048, 0x00000000,
981 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB4 ) & 0xFF)) , 0x00000048, 0x00000000,
982 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xBC ) & 0xFF)) , 0x00000048, 0x00ffff00,
984 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0x000000f0, 0x00000000,
985 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0x000000f0, 0x00000000,
986 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0x000000f0, 0x00000000,
987 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0x000000f0, 0x00000000,
988 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA0 ) & 0xFF)) , 0x000000f0, 0x00000000,
989 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA8 ) & 0xFF)) , 0x000000f0, 0x00000000,
990 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB0 ) & 0xFF)) , 0x000000f0, 0x00000000,
991 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB8 ) & 0xFF)) , 0x000000f0, 0x00fc0003,
993 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC4 ) & 0xFF)) , 0xFE000FC8, 0x01fff000,
994 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xCC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
995 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD4 ) & 0xFF)) , 0xFE000FC8, 0x00000000,
996 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xDC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
998 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC0 ) & 0xFF)) , 0xFE000FCC, 0x00000003,
999 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1000 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD0 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1001 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1003 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE0 ) & 0xFF)) , 0x0000FC88, 0xff000003,
1004 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE4 ) & 0xFF)) , 0x0000FC88, 0x00000000,
1005 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE8 ) & 0xFF)) , 0x0000FC88, 0x00000000,
1006 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xEC ) & 0xFF)) , 0x0000FC88, 0x00000000,
1009 max = sizeof(register_values)/sizeof(register_values[0]);
1010 setup_resource_map(register_values, max);
1012 static void sdram_set_registers(const struct mem_controller *ctrl)
1014 static const unsigned int register_values[] = {
1017 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
1018 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
1019 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
1020 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
1021 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
1022 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
1023 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
1024 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
1026 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1027 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1028 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1029 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1030 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1031 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1032 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1033 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1035 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1036 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1037 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1038 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x001f01fe, 0x00000000,
1039 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1040 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1041 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1042 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x001f01fe, 0x00000000,
1044 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1045 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1046 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1047 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1048 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1049 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1050 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1051 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1053 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0xffff8888, 0x00000000,
1055 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0xe8088008, 0x02522001 ,
1057 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0),
1059 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0xf0000000,
1060 (4 << 25)|(0 << 24)|
1061 (0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)|
1062 (1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)|
1063 (2 << 14)|(0 << 13)|(0 << 12)|
1064 (0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)|
1065 (0 << 3) |(0 << 1) |(0 << 0),
1067 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0xc180f0f0,
1068 (0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)|
1069 (0 << 20)|(0 << 19)|(3 << 16)|(0 << 8)|(0 << 0),
1071 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000,
1073 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000,
1075 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000003e, 0x00000000,
1077 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xffffff00, 0x00000000,
1079 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0xffff8000, 0x00000f70,
1080 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0xffffff80, 0x00000002,
1081 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0x0000000f, 0x00068300,
1085 print_debug("setting up CPU");
1086 print_debug_hex8(ctrl->node_id);
1087 print_debug(" northbridge registers\r\n");
1088 max = sizeof(register_values)/sizeof(register_values[0]);
1089 for(i = 0; i < max; i += 3) {
1093 dev = (register_values[i] & ~0xff) - ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) + ctrl->f0;
1094 where = register_values[i] & 0xff;
1095 reg = pci_read_config32(dev, where);
1096 reg &= register_values[i+1];
1097 reg |= register_values[i+2];
1098 pci_write_config32(dev, where, reg);
1100 print_debug("done.\r\n");
1102 static int is_dual_channel(const struct mem_controller *ctrl)
1105 dcl = pci_read_config32(ctrl->f2, 0x90 );
1106 return dcl & (1<<16) ;
1108 static int is_opteron(const struct mem_controller *ctrl)
1112 nbcap = pci_read_config32(ctrl->f3, 0xE8 );
1113 return !!(nbcap & 0x0001 );
1115 static int is_registered(const struct mem_controller *ctrl)
1119 dcl = pci_read_config32(ctrl->f2, 0x90 );
1120 return !(dcl & (1<<18) );
1123 unsigned long side1;
1124 unsigned long side2;
1126 static struct dimm_size spd_get_dimm_size(unsigned device)
1129 struct dimm_size sz;
1134 value = spd_read_byte(device, 3);
1135 if (value < 0) goto out;
1136 sz.side1 += value & 0xf;
1137 value = spd_read_byte(device, 4);
1138 if (value < 0) goto out;
1139 sz.side1 += value & 0xf;
1140 value = spd_read_byte(device, 17);
1141 if (value < 0) goto out;
1142 sz.side1 += log2(value & 0xff);
1144 value = spd_read_byte(device, 7);
1145 if (value < 0) goto out;
1149 low = spd_read_byte(device, 6);
1150 if (low < 0) goto out;
1151 value = value | (low & 0xff);
1152 sz.side1 += log2(value);
1154 value = spd_read_byte(device, 5);
1155 if (value <= 1) goto out;
1157 sz.side2 = sz.side1;
1158 value = spd_read_byte(device, 3);
1159 if (value < 0) goto out;
1160 if ((value & 0xf0) == 0) goto out;
1161 sz.side2 -= (value & 0x0f);
1162 sz.side2 += ((value >> 4) & 0x0f);
1163 value = spd_read_byte(device, 4);
1164 if (value < 0) goto out;
1165 sz.side2 -= (value & 0x0f);
1166 sz.side2 += ((value >> 4) & 0x0f);
1170 static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index)
1172 uint32_t base0, base1, map;
1174 if (sz.side1 != sz.side2) {
1177 map = pci_read_config32(ctrl->f2, 0x80 );
1178 map &= ~(0xf << (index + 4));
1183 if (sz.side1 >= (25 +3)) {
1184 map |= (sz.side1 - (25 + 3)) << (index *4);
1185 base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1;
1188 if (sz.side2 >= (25 + 3)) {
1189 base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1;
1192 if (is_dual_channel(ctrl)) {
1193 base0 = (base0 << 1) | (base0 & 1);
1194 base1 = (base1 << 1) | (base1 & 1);
1197 base0 &= ~0x001ffffe;
1198 base1 &= ~0x001ffffe;
1200 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+0)<<2), base0);
1201 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+1)<<2), base1);
1202 pci_write_config32(ctrl->f2, 0x80 , map);
1206 dch = pci_read_config32(ctrl->f2, 0x94 );
1207 dch |= (1 << 26) << index;
1208 pci_write_config32(ctrl->f2, 0x94 , dch);
1211 static void spd_set_ram_size(const struct mem_controller *ctrl)
1215 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1216 struct dimm_size sz;
1217 sz = spd_get_dimm_size(ctrl->channel0[i]);
1218 set_dimm_size(ctrl, sz, i);
1221 static void route_dram_accesses(const struct mem_controller *ctrl,
1222 unsigned long base_k, unsigned long limit_k)
1229 unsigned limit_reg, base_reg;
1231 node_id = ctrl->node_id;
1232 index = (node_id << 3);
1233 limit = (limit_k << 2);
1234 limit &= 0xffff0000;
1235 limit -= 0x00010000;
1236 limit |= ( 0 << 8) | (node_id << 0);
1237 base = (base_k << 2);
1239 base |= (0 << 8) | (1<<1) | (1<<0);
1240 limit_reg = 0x44 + index;
1241 base_reg = 0x40 + index;
1242 for(device = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ; device <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ; device += ( ((( 0 ) & 0xFF) << 16) | ((( 1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ) {
1243 pci_write_config32(device, limit_reg, limit);
1244 pci_write_config32(device, base_reg, base);
1247 static void set_top_mem(unsigned tom_k)
1252 print_debug("No memory - reset");
1254 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0x04 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0x41, 0xf1);
1259 print_debug("RAM: 0x");
1260 print_debug_hex32(tom_k);
1261 print_debug(" KB\r\n");
1264 msr.lo = (tom_k & 0x003fffff) << 10;
1265 msr.hi = (tom_k & 0xffc00000) >> 22;
1266 wrmsr(0xC001001D , msr);
1268 if (tom_k >= 0x003f0000) {
1271 msr.lo = (tom_k & 0x003fffff) << 10;
1272 msr.hi = (tom_k & 0xffc00000) >> 22;
1273 wrmsr(0xC001001A , msr);
1275 static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
1278 static const uint32_t csbase_low[] = {
1287 uint32_t csbase_inc;
1288 int chip_selects, index;
1291 unsigned common_size;
1292 uint32_t csbase, csmask;
1296 for(index = 0; index < 8; index++) {
1300 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2));
1308 if (common_size == 0) {
1312 if (common_size != size) {
1317 bits = log2(chip_selects);
1318 if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
1323 if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
1324 print_debug("8 4GB chip selects cannot be interleaved\r\n");
1328 if (is_dual_channel(ctrl)) {
1329 csbase_inc = csbase_low[log2(common_size) - 1] << 1;
1331 csbase_inc = csbase_low[log2(common_size)];
1335 csmask = (((common_size << bits) - 1) << 21);
1336 csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
1337 for(index = 0; index < 8; index++) {
1339 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2));
1344 pci_write_config32(ctrl->f2, 0x40 + (index << 2), csbase);
1345 pci_write_config32(ctrl->f2, 0x60 + (index << 2), csmask);
1346 csbase += csbase_inc;
1349 print_debug("Interleaved\r\n");
1351 return common_size << (15 + bits);
1353 static unsigned long order_chip_selects(const struct mem_controller *ctrl)
1361 unsigned index, canidate;
1362 uint32_t csbase, csmask;
1366 for(index = 0; index < 8; index++) {
1368 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2));
1375 if (value <= csbase) {
1380 if (tom & (1 << (index + 24))) {
1392 size = csbase >> 21;
1394 tom |= (1 << (canidate + 24));
1396 csbase = (tom << 21) | 1;
1400 csmask = ((size -1) << 21);
1403 pci_write_config32(ctrl->f2, 0x40 + (canidate << 2), csbase);
1405 pci_write_config32(ctrl->f2, 0x60 + (canidate << 2), csmask);
1409 return (tom & ~0xff000000) << 15;
1411 static void order_dimms(const struct mem_controller *ctrl)
1413 unsigned long tom, tom_k, base_k;
1415 tom_k = interleave_chip_selects(ctrl);
1417 tom_k = order_chip_selects(ctrl);
1421 for(node_id = 0; node_id < ctrl->node_id; node_id++) {
1422 uint32_t limit, base;
1424 index = node_id << 3;
1425 base = pci_read_config32(ctrl->f1, 0x40 + index);
1427 if ((base & 3) == 3) {
1428 limit = pci_read_config32(ctrl->f1, 0x44 + index);
1429 base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
1433 route_dram_accesses(ctrl, base_k, tom_k);
1436 static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
1438 print_debug("disabling dimm");
1439 print_debug_hex8(index);
1440 print_debug("\r\n");
1441 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+0)<<2), 0);
1442 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+1)<<2), 0);
1444 static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
1452 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1454 value = spd_read_byte(ctrl->channel0[i], 21);
1456 disable_dimm(ctrl, i);
1460 if (value & (1 << 1)) {
1468 if (unbuffered && registered) {
1469 die("Mixed buffered and registered dimms not supported");
1471 if (unbuffered && is_opteron(ctrl)) {
1472 die("Unbuffered Dimms not supported on Opteron");
1474 dcl = pci_read_config32(ctrl->f2, 0x90 );
1479 pci_write_config32(ctrl->f2, 0x90 , dcl);
1481 static void spd_enable_2channels(const struct mem_controller *ctrl)
1487 static const unsigned addresses[] = {
1509 nbcap = pci_read_config32(ctrl->f3, 0xE8 );
1510 if (!(nbcap & 0x0001 )) {
1513 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1514 unsigned device0, device1;
1517 device0 = ctrl->channel0[i];
1518 device1 = ctrl->channel1[i];
1521 for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
1523 addr = addresses[j];
1524 value0 = spd_read_byte(device0, addr);
1528 value1 = spd_read_byte(device1, addr);
1532 if (value0 != value1) {
1537 print_debug("Enabling dual channel memory\r\n");
1539 dcl = pci_read_config32(ctrl->f2, 0x90 );
1542 pci_write_config32(ctrl->f2, 0x90 , dcl);
1549 uint32_t dch_memclk;
1550 uint16_t dch_tref4k, dch_tref8k;
1554 static const struct mem_param *get_mem_param(unsigned min_cycle_time)
1556 static const struct mem_param speed[] = {
1558 .name = "100Mhz\r\n",
1560 .divisor = (10 <<1),
1563 .dch_memclk = 0 << 20 ,
1564 .dch_tref4k = 0x00 ,
1565 .dch_tref8k = 0x08 ,
1569 .name = "133Mhz\r\n",
1571 .divisor = (7<<1)+1,
1574 .dch_memclk = 2 << 20 ,
1575 .dch_tref4k = 0x01 ,
1576 .dch_tref8k = 0x09 ,
1580 .name = "166Mhz\r\n",
1585 .dch_memclk = 5 << 20 ,
1586 .dch_tref4k = 0x02 ,
1587 .dch_tref8k = 0x0A ,
1591 .name = "200Mhz\r\n",
1596 .dch_memclk = 7 << 20 ,
1597 .dch_tref4k = 0x03 ,
1598 .dch_tref8k = 0x0B ,
1605 const struct mem_param *param;
1606 for(param = &speed[0]; param->cycle_time ; param++) {
1607 if (min_cycle_time > (param+1)->cycle_time) {
1611 if (!param->cycle_time) {
1612 die("min_cycle_time to low");
1614 print_debug(param->name);
1617 static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
1620 const struct mem_param *param;
1621 unsigned min_cycle_time, min_latency;
1624 static const int latency_indicies[] = { 26, 23, 9 };
1625 static const unsigned char min_cycle_times[] = {
1631 value = pci_read_config32(ctrl->f3, 0xE8 );
1632 min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ];
1635 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1636 int new_cycle_time, new_latency;
1641 new_cycle_time = 0xa0;
1643 latencies = spd_read_byte(ctrl->channel0[i], 18);
1644 if (latencies <= 0) continue;
1646 latency = log2(latencies) -2;
1648 for(index = 0; index < 3; index++, latency++) {
1650 if ((latency < 2) || (latency > 4) ||
1651 (!(latencies & (1 << latency)))) {
1654 value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
1659 if ((value >= min_cycle_time) && (value < new_cycle_time)) {
1660 new_cycle_time = value;
1661 new_latency = latency;
1664 if (new_latency > 4){
1668 if (new_cycle_time > min_cycle_time) {
1669 min_cycle_time = new_cycle_time;
1672 if (new_latency > min_latency) {
1673 min_latency = new_latency;
1678 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1684 latencies = spd_read_byte(ctrl->channel0[i], 18);
1685 if (latencies <= 0) {
1689 latency = log2(latencies) -2;
1691 for(index = 0; index < 3; index++, latency++) {
1692 if (!(latencies & (1 << latency))) {
1695 if (latency == min_latency)
1699 if ((latency != min_latency) || (index >= 3)) {
1704 value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
1707 if (value <= min_cycle_time) {
1712 disable_dimm(ctrl, i);
1715 param = get_mem_param(min_cycle_time);
1717 value = pci_read_config32(ctrl->f2, 0x94 );
1718 value &= ~(0x7 << 20 );
1719 value |= param->dch_memclk;
1720 pci_write_config32(ctrl->f2, 0x94 , value);
1721 static const unsigned latencies[] = { 1 , 5 , 2 };
1723 value = pci_read_config32(ctrl->f2, 0x88 );
1724 value &= ~(0x7 << 0 );
1725 value |= latencies[min_latency - 2] << 0 ;
1726 pci_write_config32(ctrl->f2, 0x88 , value);
1730 static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1732 unsigned clocks, old_clocks;
1735 value = spd_read_byte(ctrl->channel0[i], 41);
1736 if (value < 0) return -1;
1737 if ((value == 0) || (value == 0xff)) {
1740 clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1747 dtl = pci_read_config32(ctrl->f2, 0x88 );
1748 old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ;
1749 if (old_clocks > clocks) {
1750 clocks = old_clocks;
1752 dtl &= ~(0xf << 4 );
1753 dtl |= ((clocks - 7 ) << 4 );
1754 pci_write_config32(ctrl->f2, 0x88 , dtl);
1757 static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1759 unsigned clocks, old_clocks;
1762 value = spd_read_byte(ctrl->channel0[i], 42);
1763 if (value < 0) return -1;
1764 if ((value == 0) || (value == 0xff)) {
1765 value = param->tRFC;
1767 clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1774 dtl = pci_read_config32(ctrl->f2, 0x88 );
1775 old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ;
1776 if (old_clocks > clocks) {
1777 clocks = old_clocks;
1779 dtl &= ~(0xf << 8 );
1780 dtl |= ((clocks - 9 ) << 8 );
1781 pci_write_config32(ctrl->f2, 0x88 , dtl);
1784 static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1786 unsigned clocks, old_clocks;
1789 value = spd_read_byte(ctrl->channel0[i], 29);
1790 if (value < 0) return -1;
1791 clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
1798 dtl = pci_read_config32(ctrl->f2, 0x88 );
1799 old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ;
1800 if (old_clocks > clocks) {
1801 clocks = old_clocks;
1803 dtl &= ~(0x7 << 12 );
1804 dtl |= ((clocks - 0 ) << 12 );
1805 pci_write_config32(ctrl->f2, 0x88 , dtl);
1808 static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1810 unsigned clocks, old_clocks;
1813 value = spd_read_byte(ctrl->channel0[i], 28);
1814 if (value < 0) return -1;
1815 clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
1822 dtl = pci_read_config32(ctrl->f2, 0x88 );
1823 old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ;
1824 if (old_clocks > clocks) {
1825 clocks = old_clocks;
1827 dtl &= ~(0x7 << 16 );
1828 dtl |= ((clocks - 0 ) << 16 );
1829 pci_write_config32(ctrl->f2, 0x88 , dtl);
1832 static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1834 unsigned clocks, old_clocks;
1837 value = spd_read_byte(ctrl->channel0[i], 30);
1838 if (value < 0) return -1;
1839 clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1846 dtl = pci_read_config32(ctrl->f2, 0x88 );
1847 old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ;
1848 if (old_clocks > clocks) {
1849 clocks = old_clocks;
1851 dtl &= ~(0xf << 20 );
1852 dtl |= ((clocks - 0 ) << 20 );
1853 pci_write_config32(ctrl->f2, 0x88 , dtl);
1856 static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1858 unsigned clocks, old_clocks;
1861 value = spd_read_byte(ctrl->channel0[i], 27);
1862 if (value < 0) return -1;
1863 clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
1870 dtl = pci_read_config32(ctrl->f2, 0x88 );
1871 old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ;
1872 if (old_clocks > clocks) {
1873 clocks = old_clocks;
1875 dtl &= ~(0x7 << 24 );
1876 dtl |= ((clocks - 0 ) << 24 );
1877 pci_write_config32(ctrl->f2, 0x88 , dtl);
1880 static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
1883 dtl = pci_read_config32(ctrl->f2, 0x88 );
1884 dtl &= ~(0x1 << 28 );
1885 dtl |= (param->dtl_twr - 2 ) << 28 ;
1886 pci_write_config32(ctrl->f2, 0x88 , dtl);
1888 static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param)
1891 dth = pci_read_config32(ctrl->f2, 0x8c );
1892 dth &= ~(0x1f << 8 );
1893 dth |= (param->dch_tref4k << 8 );
1894 pci_write_config32(ctrl->f2, 0x8c , dth);
1896 static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1900 unsigned tref, old_tref;
1901 value = spd_read_byte(ctrl->channel0[i], 3);
1902 if (value < 0) return -1;
1904 tref = param->dch_tref8k;
1906 tref = param->dch_tref4k;
1908 dth = pci_read_config32(ctrl->f2, 0x8c );
1909 old_tref = (dth >> 8 ) & 0x1f ;
1910 if ((value == 12) && (old_tref == param->dch_tref4k)) {
1911 tref = param->dch_tref4k;
1913 tref = param->dch_tref8k;
1915 dth &= ~(0x1f << 8 );
1916 dth |= (tref << 8 );
1917 pci_write_config32(ctrl->f2, 0x8c , dth);
1920 static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1925 value = spd_read_byte(ctrl->channel0[i], 13);
1931 dcl = pci_read_config32(ctrl->f2, 0x90 );
1932 dcl &= ~(1 << dimm);
1936 pci_write_config32(ctrl->f2, 0x90 , dcl);
1939 static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1943 value = spd_read_byte(ctrl->channel0[i], 11);
1948 dcl = pci_read_config32(ctrl->f2, 0x90 );
1950 pci_write_config32(ctrl->f2, 0x90 , dcl);
1954 static int count_dimms(const struct mem_controller *ctrl)
1959 for(index = 0; index < 8; index += 2) {
1961 csbase = pci_read_config32(ctrl->f2, (0x40 + index << 2));
1968 static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
1973 dth = pci_read_config32(ctrl->f2, 0x8c );
1974 dth &= ~(0x1 << 0 );
1975 dth |= ((clocks - 1 ) << 0 );
1976 pci_write_config32(ctrl->f2, 0x8c , dth);
1978 static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
1985 dtl = pci_read_config32(ctrl->f2, 0x88 );
1986 latency = (dtl >> 0 ) & 0x7 ;
1987 divisor = param->divisor;
1988 if (is_opteron(ctrl)) {
1989 if (latency == 1 ) {
1990 if (divisor == ((6 << 0) + 0)) {
1994 else if (divisor > ((6 << 0)+0)) {
1999 else if (latency == 5 ) {
2002 else if (latency == 2 ) {
2003 if (divisor == ((6 << 0)+0)) {
2007 else if (divisor > ((6 << 0)+0)) {
2014 if (is_registered(ctrl)) {
2015 if (latency == 1 ) {
2018 else if (latency == 5 ) {
2021 else if (latency == 2 ) {
2026 if (latency == 1 ) {
2029 else if (latency == 5 ) {
2032 else if (latency == 2 ) {
2037 if ((clocks < 1 ) || (clocks > 6 )) {
2038 die("Unknown Trwt");
2041 dth = pci_read_config32(ctrl->f2, 0x8c );
2042 dth &= ~(0x7 << 4 );
2043 dth |= ((clocks - 1 ) << 4 );
2044 pci_write_config32(ctrl->f2, 0x8c , dth);
2047 static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param)
2052 if (is_registered(ctrl)) {
2057 dth = pci_read_config32(ctrl->f2, 0x8c );
2058 dth &= ~(0x7 << 20 );
2059 dth |= ((clocks - 1 ) << 20 );
2060 pci_write_config32(ctrl->f2, 0x8c , dth);
2062 static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
2066 unsigned rdpreamble;
2067 divisor = param->divisor;
2068 dch = pci_read_config32(ctrl->f2, 0x94 );
2069 dch &= ~(0xf << 8 );
2071 if (is_registered(ctrl)) {
2072 if (divisor == ((10 << 1)+0)) {
2074 rdpreamble = ((9 << 1)+ 0);
2076 else if (divisor == ((7 << 1)+1)) {
2078 rdpreamble = ((8 << 1)+0);
2080 else if (divisor == ((6 << 1)+0)) {
2082 rdpreamble = ((7 << 1)+1);
2084 else if (divisor == ((5 << 1)+0)) {
2086 rdpreamble = ((7 << 1)+0);
2093 for(i = 0; i < 4; i++) {
2094 if (ctrl->channel0[i]) {
2098 if (divisor == ((10 << 1)+0)) {
2102 rdpreamble = ((9 << 1)+0);
2105 rdpreamble = ((14 << 1)+0);
2108 else if (divisor == ((7 << 1)+1)) {
2112 rdpreamble = ((7 << 1)+0);
2115 rdpreamble = ((11 << 1)+0);
2118 else if (divisor == ((6 << 1)+0)) {
2122 rdpreamble = ((7 << 1)+0);
2125 rdpreamble = ((9 << 1)+0);
2128 else if (divisor == ((5 << 1)+0)) {
2132 rdpreamble = ((5 << 1)+0);
2135 rdpreamble = ((7 << 1)+0);
2139 if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) {
2140 die("Unknown rdpreamble");
2142 dch |= (rdpreamble - ((2<<1)+0) ) << 8 ;
2143 pci_write_config32(ctrl->f2, 0x94 , dch);
2145 static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param)
2151 dimms = count_dimms(ctrl);
2152 dch = pci_read_config32(ctrl->f2, 0x94 );
2153 dch &= ~(0xf << 0 );
2155 if (is_registered(ctrl)) {
2167 die("Too many unbuffered dimms");
2169 else if (dimms == 3) {
2178 dch |= ((async_lat - 0 ) << 0 );
2179 pci_write_config32(ctrl->f2, 0x94 , dch);
2181 static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param)
2185 dch = pci_read_config32(ctrl->f2, 0x94 );
2186 dch &= ~(0x7 << 16 );
2189 pci_write_config32(ctrl->f2, 0x94 , dch);
2191 static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
2197 init_Tref(ctrl, param);
2198 for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
2201 if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
2202 if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
2203 if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
2204 if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
2205 if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
2206 if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
2208 if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
2210 if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
2211 if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
2214 disable_dimm(ctrl, i);
2218 set_Twr(ctrl, param);
2220 set_Twtr(ctrl, param);
2221 set_Trwt(ctrl, param);
2222 set_Twcl(ctrl, param);
2224 set_read_preamble(ctrl, param);
2225 set_max_async_latency(ctrl, param);
2226 set_idle_cycle_limit(ctrl, param);
2228 static void sdram_set_spd_registers(const struct mem_controller *ctrl)
2230 const struct mem_param *param;
2231 spd_enable_2channels(ctrl);
2232 spd_set_ram_size(ctrl);
2233 spd_handle_unbuffered_dimms(ctrl);
2234 param = spd_set_memclk(ctrl);
2235 spd_set_dram_timing(ctrl, param);
2238 static void sdram_enable(int controllers, const struct mem_controller *ctrl)
2242 for(i = 0; i < controllers; i++) {
2244 dch = pci_read_config32(ctrl[i].f2, 0x94 );
2246 pci_write_config32(ctrl[i].f2, 0x94 , dch);
2249 memreset(controllers, ctrl);
2250 for(i = 0; i < controllers; i++) {
2253 dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2254 if (dcl & (1<<17) ) {
2256 print_debug("ECC enabled\r\n");
2257 mnc = pci_read_config32(ctrl[i].f3, 0x44 );
2259 if (dcl & (1<<16) ) {
2262 pci_write_config32(ctrl[i].f3, 0x44 , mnc);
2265 pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2271 pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2273 for(i = 0; i < controllers; i++) {
2275 print_debug("Initializing memory: ");
2278 dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2280 if ((loops & 1023) == 0) {
2283 } while(((dcl & (1<<8) ) != 0) && (loops < 300000 ));
2284 if (loops >= 300000 ) {
2285 print_debug(" failed\r\n");
2287 print_debug(" done\r\n");
2289 if (dcl & (1<<17) ) {
2290 print_debug("Clearing memory: ");
2291 if (!is_cpu_pre_c0()) {
2293 dcl &= ~((1<<11) | (1<<10) );
2294 pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2296 dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2297 } while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) );
2299 uint32_t base, last_scrub_k, scrub_k;
2300 uint32_t cnt,zstart,zend;
2303 pci_write_config32(ctrl[i].f3, 0x58 ,
2304 (0 << 16) | (0 << 8) | (0 << 0));
2306 msr_201 = rdmsr(0x201);
2307 zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
2308 zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
2311 print_debug("addr ");
2312 print_debug_hex32(zstart);
2314 print_debug_hex32(zend);
2315 print_debug("\r\n");
2318 msr = rdmsr(0x2ff );
2322 msr = rdmsr(0xc0010015);
2324 wrmsr(0xc0010015,msr);
2325 for(;zstart<zend;zstart+=4) {
2332 "movl %%cr0, %0\n\t"
2333 "orl $0x40000000, %0\n\t"
2334 "movl %0, %%cr0\n\t"
2339 msr.lo = 1 + ((zstart&0x0ff)<<24);
2340 msr.hi = (zstart&0x0ff00)>>8;
2343 msr.hi = 0x000000ff;
2344 msr.lo = 0xfc000800;
2348 "movl %%cr0, %0\n\t"
2349 "andl $0x9fffffff, %0\n\t"
2350 "movl %0, %%cr0\n\t"
2354 msr.lo = (zstart&0xff) << 24;
2355 msr.hi = (zstart&0xff00) >> 8;
2356 wrmsr(0xc0000100,msr);
2357 print_debug_char((zstart > 0x0ff)?'+':'-');
2362 "movl %0, %%fs:(%1)\n\t"
2367 : "a" (0), "D" (0), "c" (0x01000000)
2373 "movl %%cr0, %0\n\t"
2374 "orl $0x40000000, %0\n\t"
2375 "movl %0, %%cr0\n\t"
2380 msr = rdmsr(0x2ff );
2387 wrmsr(0x201,msr_201);
2391 wrmsr(0xc0000100,msr);
2394 "movl %%cr0, %0\n\t"
2395 "andl $0x9fffffff, %0\n\t"
2396 "movl %0, %%cr0\n\t"
2401 msr = rdmsr(0xc0010015);
2403 wrmsr(0xc0010015,msr);
2405 base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
2408 pci_write_config32(ctrl[i].f3, 0x5C , base << 8);
2409 pci_write_config32(ctrl[i].f3, 0x60 , base >> 24);
2411 pci_write_config32(ctrl[i].f3, 0x58 ,
2412 (22 << 16) | (22 << 8) | (22 << 0));
2413 print_debug("done\r\n");
2423 typedef uint32_t u32;
2424 typedef int8_t bool;
2425 static void disable_probes(void)
2430 print_debug("Disabling read/write/fill probes for UP... ");
2431 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68);
2432 val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
2433 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68, val);
2434 print_debug("done.\r\n");
2437 static void wait_ap_stop(u8 node)
2441 for(i=0;i< 1000 ;i++) {
2443 regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c);
2444 if((regx & (1<<4))==1) break;
2446 reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c);
2448 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, reg);
2450 static void notify_bsp_ap_is_stopped(void)
2453 unsigned long apic_id;
2454 apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 ));
2459 reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C);
2461 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C, reg);
2466 static void enable_routing(u8 node)
2471 print_debug("Enabling routing table for node ");
2472 print_debug_hex32(node);
2473 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c);
2474 val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
2475 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, val);
2481 print_debug(" done.\r\n");
2483 static void rename_temp_node(u8 node)
2486 print_debug("Renaming current temp node to ");
2487 print_debug_hex32(node);
2488 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60);
2491 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60, val);
2492 print_debug(" done.\r\n");
2494 static bool check_connection(u8 src, u8 dest, u8 link)
2500 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x98+link);
2501 if ( (val&0x17) != 0x03)
2504 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0);
2505 if(val != 0x11001022)
2509 static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
2511 static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
2512 static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
2513 uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
2514 uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
2518 freq_cap1 = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 0x0a );
2519 freq_cap2 = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 0x0a );
2522 freq = log2(freq_cap1 & freq_cap2 & 0xff);
2524 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 0x09 , freq);
2525 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 0x09 , freq);
2527 width_cap1 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 );
2528 width_cap2 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 6 );
2530 ln_width1 = link_width_to_pow2[width_cap1 & 7];
2531 ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
2532 if (ln_width1 > ln_width2) {
2533 ln_width1 = ln_width2;
2535 width = pow2_to_link_width[ln_width1];
2537 ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
2538 ln_width2 = link_width_to_pow2[width_cap2 & 7];
2539 if (ln_width1 > ln_width2) {
2540 ln_width1 = ln_width2;
2542 width |= pow2_to_link_width[ln_width1] << 4;
2545 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 + 1, width);
2547 width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
2548 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 6 + 1, width);
2550 static void fill_row(u8 node, u8 row, u32 value)
2552 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x40+(row<<2), value);
2554 static void setup_row(u8 source, u8 dest, u8 cpus)
2556 fill_row(source,dest,generate_row(source,dest,cpus));
2558 static void setup_temp_row(u8 source, u8 dest, u8 cpus)
2560 fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) );
2562 static void setup_node(u8 node, u8 cpus)
2565 for(row=0; row<cpus; row++)
2566 setup_row(node, row, cpus);
2568 static void setup_remote_row(u8 source, u8 dest, u8 cpus)
2570 fill_row(7, dest, generate_row(source, dest, cpus));
2572 static void setup_remote_node(u8 node, u8 cpus)
2574 static const uint8_t pci_reg[] = {
2575 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
2576 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
2577 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
2578 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
2579 0xc4, 0xcc, 0xd4, 0xdc,
2580 0xc0, 0xc8, 0xd0, 0xd8,
2581 0xe0, 0xe4, 0xe8, 0xec,
2585 print_debug("setup_remote_node\r\n");
2586 for(row=0; row<cpus; row++)
2587 setup_remote_row(node, row, cpus);
2589 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
2593 value = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , reg);
2594 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , reg, value);
2596 print_debug("setup_remote_done\r\n");
2598 static u8 setup_uniprocessor(void)
2600 print_debug("Enabling UP settings\r\n");
2604 static u8 setup_smp(void)
2607 print_debug("Enabling SMP settings\r\n");
2608 setup_row(0,0,cpus);
2610 setup_temp_row(0,1,cpus);
2612 if (!check_connection(0, 7, 0x20 )) {
2613 print_debug("No connection to Node 1.\r\n");
2614 fill_row( 0 ,7,0x00010101 ) ;
2615 setup_uniprocessor();
2619 optimize_connection(0, 0x20 , 7, 0x20 );
2620 setup_node(0, cpus);
2621 setup_remote_node(1, cpus);
2622 rename_temp_node(1);
2625 fill_row( 0 ,7,0x00010101 ) ;
2627 print_debug_hex32(cpus);
2628 print_debug(" nodes initialized.\r\n");
2631 static unsigned detect_mp_capabilities(unsigned cpus)
2633 unsigned node, row, mask;
2635 print_debug("detect_mp_capabilities: ");
2636 print_debug_hex32(cpus);
2637 print_debug("\r\n");
2642 for (node=0; node<cpus; node++) {
2643 if ((pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0xe8) & mask)!=mask)
2649 print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
2650 for (node=cpus; node>0; node--)
2651 for (row=cpus; row>0; row--)
2652 fill_row(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node-1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , row-1, 0x00010101 );
2654 return setup_uniprocessor();
2656 static void coherent_ht_finalize(unsigned cpus)
2662 print_debug("coherent_ht_finalize\r\n");
2663 rev_a0= is_cpu_rev_a0();
2664 for (node=0; node<cpus; node++) {
2666 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60);
2667 val &= (~0x000F0070);
2668 val |= ((cpus-1)<<16)|((cpus-1)<<4);
2669 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x60,val);
2670 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68);
2672 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x68,val);
2674 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x94,0);
2675 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0xb4,0);
2676 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0xd4,0);
2679 print_debug("done\r\n");
2681 static int setup_coherent_ht_domain(void)
2684 int reset_needed = 0;
2687 cpus=detect_mp_capabilities(cpus);
2688 coherent_ht_finalize(cpus);
2690 coherent_ht_mainboard(cpus);
2691 return reset_needed;
2693 void sdram_no_memory(void)
2695 print_err("No memory!!\r\n");
2701 void sdram_initialize(int controllers, const struct mem_controller *ctrl)
2705 for(i = 0; i < controllers; i++) {
2706 print_debug("Ram1.");
2707 print_debug_hex8(i);
2708 print_debug("\r\n");
2709 sdram_set_registers(ctrl + i);
2712 for(i = 0; i < controllers; i++) {
2713 print_debug("Ram2.");
2714 print_debug_hex8(i);
2715 print_debug("\r\n");
2716 sdram_set_spd_registers(ctrl + i);
2719 print_debug("Ram3\r\n");
2720 sdram_enable(controllers, ctrl);
2721 print_debug("Ram4\r\n");
2723 static void enable_lapic(void)
2727 msr.hi &= 0xffffff00;
2728 msr.lo &= 0x000007ff;
2729 msr.lo |= 0xfee00000 | (1 << 11);
2732 static void stop_this_cpu(void)
2735 apicid = apic_read(0x020 ) >> 24;
2737 apic_write(0x310 , (( apicid )<<24) );
2738 apic_write(0x300 , 0x08000 | 0x04000 | 0x00500 );
2740 apic_wait_icr_idle();
2742 apic_write(0x310 , (( apicid )<<24) );
2743 apic_write(0x300 , 0x08000 | 0x00500 );
2745 apic_wait_icr_idle();
2751 static void pc87360_enable_serial(void)
2753 pnp_set_logical_device(0x2e , 0x03 );
2754 pnp_set_enable(0x2e , 1);
2755 pnp_set_iobase0(0x2e , 0x3f8);
2757 static void main(void)
2760 static const struct mem_controller cpu[] = {
2763 .f0 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,
2764 .f1 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ,
2765 .f2 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,
2766 .f3 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,
2767 .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
2768 .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
2772 .f0 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,
2773 .f1 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ,
2774 .f2 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,
2775 .f3 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,
2776 .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
2777 .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
2780 if (cpu_init_detected()) {
2781 asm("jmp __cpu_reset");
2788 pc87360_enable_serial();
2791 setup_default_resource_map();
2792 setup_coherent_ht_domain();
2793 enumerate_ht_chain(0);
2794 distinguish_cpu_resets(0);
2798 sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);