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);
328 static void do_console_tx_string(const char *str) __attribute__((noinline))
331 while((ch = *str++) != '\0') {
332 __console_tx_byte(ch);
335 static void __console_tx_string(int loglevel, const char *str)
338 do_console_tx_string(str);
341 static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); }
342 static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); }
343 static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); }
344 static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); }
345 static void print_emerg(const char *str) { __console_tx_string(0 , str); }
346 static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); }
347 static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); }
348 static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); }
349 static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); }
350 static void print_alert(const char *str) { __console_tx_string(1 , str); }
351 static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); }
352 static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); }
353 static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); }
354 static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); }
355 static void print_crit(const char *str) { __console_tx_string(2 , str); }
356 static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); }
357 static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); }
358 static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); }
359 static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); }
360 static void print_err(const char *str) { __console_tx_string(3 , str); }
361 static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); }
362 static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); }
363 static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); }
364 static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); }
365 static void print_warning(const char *str) { __console_tx_string(4 , str); }
366 static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); }
367 static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); }
368 static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); }
369 static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); }
370 static void print_notice(const char *str) { __console_tx_string(5 , str); }
371 static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); }
372 static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); }
373 static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); }
374 static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); }
375 static void print_info(const char *str) { __console_tx_string(6 , str); }
376 static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); }
377 static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); }
378 static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); }
379 static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); }
380 static void print_debug(const char *str) { __console_tx_string(7 , str); }
381 static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); }
382 static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); }
383 static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); }
384 static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); }
385 static void print_spew(const char *str) { __console_tx_string(8 , str); }
386 static void console_init(void)
388 static const char console_test[] =
393 "Thu Oct 9 20:29:48 MDT 2003"
395 print_info(console_test);
397 static void die(const char *str)
404 static void write_phys(unsigned long addr, unsigned long value)
409 : "r" (addr), "r" (value)
413 static unsigned long read_phys(unsigned long addr)
415 volatile unsigned long *ptr;
419 static void ram_fill(unsigned long start, unsigned long stop)
423 print_debug("DRAM fill: ");
424 print_debug_hex32(start);
426 print_debug_hex32(stop);
428 for(addr = start; addr < stop ; addr += 4) {
430 if (!(addr & 0xffff)) {
431 print_debug_hex32(addr);
434 write_phys(addr, addr);
437 print_debug_hex32(addr);
438 print_debug("\r\nDRAM filled\r\n");
440 static void ram_verify(unsigned long start, unsigned long stop)
444 print_debug("DRAM verify: ");
445 print_debug_hex32(start);
446 print_debug_char('-');
447 print_debug_hex32(stop);
449 for(addr = start; addr < stop ; addr += 4) {
452 if (!(addr & 0xffff)) {
453 print_debug_hex32(addr);
456 value = read_phys(addr);
459 print_err_hex32(addr);
461 print_err_hex32(value);
466 print_debug_hex32(addr);
467 print_debug("\r\nDRAM verified\r\n");
469 void ram_check(unsigned long start, unsigned long stop)
473 print_debug("Testing DRAM : ");
474 print_debug_hex32(start);
476 print_debug_hex32(stop);
478 ram_fill(start, stop);
479 ram_verify(start, stop);
480 print_debug("Done.\r\n");
482 static int enumerate_ht_chain(unsigned link)
485 unsigned next_unitid, last_unitid;
486 int reset_needed = 0;
490 uint8_t hdr_type, pos;
491 last_unitid = next_unitid;
492 id = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x00 );
494 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
495 (((id >> 16) & 0xffff) == 0xffff) ||
496 (((id >> 16) & 0xffff) == 0x0000)) {
499 hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x0e );
502 if ((hdr_type == 0 ) ||
504 pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x34 );
508 cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 0 );
511 flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 );
512 if ((flags >> 13) == 0) {
515 flags |= next_unitid & 0x1f;
516 count = (flags >> 5) & 0x1f;
517 pci_write_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 , flags);
518 next_unitid += count;
522 pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 1 );
524 } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
527 static void enable_smbus(void)
530 dev = pci_locate_device((((( 0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0);
531 if (dev == (0xffffffffU) ) {
532 die("SMBUS controller not found\r\n");
535 print_debug("SMBus controller enabled\r\n");
536 pci_write_config32(dev, 0x58, 0x0f00 | 1);
537 enable = pci_read_config8(dev, 0x41);
538 pci_write_config8(dev, 0x41, enable | (1 << 7));
540 outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 );
542 static inline void smbus_delay(void)
546 static int smbus_wait_until_ready(void)
549 loops = (100*1000*10) ;
553 val = inw(0x0f00 + 0xe0 );
554 if ((val & 0x800) == 0) {
557 if(loops == ((100*1000*10) / 2)) {
558 outw(inw(0x0f00 + 0xe0 ),
564 static int smbus_wait_until_done(void)
567 loops = (100*1000*10) ;
572 val = inw(0x0f00 + 0xe0 );
573 if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
579 static int smbus_read_byte(unsigned device, unsigned address)
581 unsigned char global_control_register;
582 unsigned char global_status_register;
584 if (smbus_wait_until_ready() < 0) {
590 outw(inw(0x0f00 + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00 + 0xe2 );
592 outw(((device & 0x7f) << 1) | 1, 0x0f00 + 0xe4 );
594 outb(address & 0xFF, 0x0f00 + 0xe8 );
596 outw((inw(0x0f00 + 0xe2 ) & ~7) | (0x2), 0x0f00 + 0xe2 );
599 outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 );
601 outw(0, 0x0f00 + 0xe6 );
603 outw((inw(0x0f00 + 0xe2 ) | (1 << 3)), 0x0f00 + 0xe2 );
605 if (smbus_wait_until_done() < 0) {
608 global_status_register = inw(0x0f00 + 0xe0 );
610 byte = inw(0x0f00 + 0xe6 ) & 0xff;
611 if (global_status_register != (1 << 4)) {
616 static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
620 struct mem_controller {
622 device_t f0, f1, f2, f3;
626 typedef __builtin_msr_t msr_t;
627 static msr_t rdmsr(unsigned long index)
629 return __builtin_rdmsr(index);
631 static void wrmsr(unsigned long index, msr_t msr)
633 __builtin_wrmsr(index, msr.lo, msr.hi);
639 typedef struct tsc_struct tsc_t;
640 static tsc_t rdtsc(void)
644 : "=a" (res.lo), "=d"(res.hi)
650 void init_timer(void)
653 apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));
655 apic_write(0x3E0 , 0xB );
657 apic_write(0x380 , 0xffffffff);
659 void udelay(unsigned usecs)
661 uint32_t start, value, ticks;
664 start = apic_read(0x390 );
666 value = apic_read(0x390 );
667 } while((start - value) < ticks);
670 void mdelay(unsigned msecs)
673 for(i = 0; i < msecs; i++) {
677 void delay(unsigned secs)
680 for(i = 0; i < secs; i++) {
686 volatile unsigned long *local_apic;
687 unsigned long apic_id;
691 bsp = !!(msr.lo & (1 << 8));
694 static int cpu_init_detected(void)
697 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
698 return !!(htic & (1<<6) );
700 static int bios_reset_detected(void)
703 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
704 return (htic & (1<<4) ) && !(htic & (1<<5) );
706 static int cold_reset_detected(void)
709 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
710 return !(htic & (1<<4) );
712 static void distinguish_cpu_resets(unsigned node_id)
716 device = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 + node_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ;
717 htic = pci_read_config32(device, 0x6c );
718 htic |= (1<<4) | (1<<5) | (1<<6) ;
719 pci_write_config32(device, 0x6c , htic);
721 static void set_bios_reset(void)
724 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c );
726 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c , htic);
728 static void print_debug_pci_dev(unsigned dev)
730 print_debug("PCI: ");
731 print_debug_hex8((dev >> 16) & 0xff);
732 print_debug_char(':');
733 print_debug_hex8((dev >> 11) & 0x1f);
734 print_debug_char('.');
735 print_debug_hex8((dev >> 8) & 7);
737 static void print_pci_devices(void)
740 for(dev = ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ;
741 dev <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 0x7 ) & 0x7) << 8)) ;
742 dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) {
744 id = pci_read_config32(dev, 0x00 );
745 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
746 (((id >> 16) & 0xffff) == 0xffff) ||
747 (((id >> 16) & 0xffff) == 0x0000)) {
750 print_debug_pci_dev(dev);
754 static void dump_pci_device(unsigned dev)
757 print_debug_pci_dev(dev);
760 for(i = 0; i <= 255; i++) {
762 if ((i & 0x0f) == 0) {
764 print_debug_char(':');
766 val = pci_read_config8(dev, i);
767 print_debug_char(' ');
768 print_debug_hex8(val);
769 if ((i & 0x0f) == 0x0f) {
774 static void dump_pci_devices(void)
777 for(dev = ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ;
778 dev <= ( ((( 0 ) & 0xFF) << 16) | ((( 0x1f ) & 0x1f) << 11) | ((( 0x7 ) & 0x7) << 8)) ;
779 dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) {
781 id = pci_read_config32(dev, 0x00 );
782 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
783 (((id >> 16) & 0xffff) == 0xffff) ||
784 (((id >> 16) & 0xffff) == 0x0000)) {
787 dump_pci_device(dev);
790 static void dump_spd_registers(const struct mem_controller *ctrl)
794 for(i = 0; i < 4; i++) {
796 device = ctrl->channel0[i];
799 print_debug("dimm: ");
802 print_debug_hex8(device);
803 for(j = 0; j < 256; j++) {
806 if ((j & 0xf) == 0) {
811 status = smbus_read_byte(device, j);
813 print_debug("bad device\r\n");
816 byte = status & 0xff;
817 print_debug_hex8(byte);
818 print_debug_char(' ');
822 device = ctrl->channel1[i];
825 print_debug("dimm: ");
828 print_debug_hex8(device);
829 for(j = 0; j < 256; j++) {
832 if ((j & 0xf) == 0) {
837 status = smbus_read_byte(device, j);
839 print_debug("bad device\r\n");
842 byte = status & 0xff;
843 print_debug_hex8(byte);
844 print_debug_char(' ');
851 static unsigned int cpuid(unsigned int op)
854 unsigned dummy2,dummy3,dummy4;
857 : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4)
862 static int is_cpu_rev_a0(void)
864 return (cpuid(1) & 0xffff) == 0x0f10;
866 static int is_cpu_pre_c0(void)
868 return (cpuid(1) & 0xffef) < 0x0f48;
870 static void memreset_setup(void)
872 if (is_cpu_pre_c0()) {
874 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 28);
876 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 29);
880 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 29);
883 static void memreset(int controllers, const struct mem_controller *ctrl)
885 if (is_cpu_pre_c0()) {
888 outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 28);
892 static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
895 uint32_t ret=0x00010101;
896 static const unsigned int rows_2p[2][2] = {
897 { 0x00050101, 0x00010404 },
898 { 0x00010404, 0x00050101 }
901 print_debug("this mainboard is only designed for 2 cpus\r\n");
904 if (!(node>=maxnodes || row>=maxnodes)) {
905 ret=rows_2p[node][row];
909 static inline int spd_read_byte(unsigned device, unsigned address)
911 return smbus_read_byte(device, address);
914 static void coherent_ht_mainboard(unsigned cpus)
918 void cpu_ldtstop(unsigned cpus)
923 for(cnt=0; cnt<cpus; cnt++) {
925 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0x81,0x23);
927 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd4,0x00000701);
929 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd8,0x00000000);
931 tmp=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,0x90);
932 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,0x90, tmp | (1<<24) );
940 static void setup_resource_map(const unsigned int *register_values, int max)
943 print_debug("setting up resource map....\r\n");
944 for(i = 0; i < max; i += 3) {
948 dev = register_values[i] & ~0xff;
949 where = register_values[i] & 0xff;
950 reg = pci_read_config32(dev, where);
951 reg &= register_values[i+1];
952 reg |= register_values[i+2];
953 pci_write_config32(dev, where, reg);
955 print_debug("done.\r\n");
957 static void setup_default_resource_map(void)
959 static const unsigned int register_values[] = {
962 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
963 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
964 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
965 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
966 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
967 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
968 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
969 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
971 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
972 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
973 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
974 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
975 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
976 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
977 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
978 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
980 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x84 ) & 0xFF)) , 0x00000048, 0x00000000,
981 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x8C ) & 0xFF)) , 0x00000048, 0x00000000,
982 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0x00000048, 0x00000000,
983 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x9C ) & 0xFF)) , 0x00000048, 0x00000000,
984 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA4 ) & 0xFF)) , 0x00000048, 0x00000000,
985 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xAC ) & 0xFF)) , 0x00000048, 0x00000000,
986 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB4 ) & 0xFF)) , 0x00000048, 0x00000000,
987 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xBC ) & 0xFF)) , 0x00000048, 0x00ffff00,
989 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0x000000f0, 0x00000000,
990 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0x000000f0, 0x00000000,
991 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0x000000f0, 0x00000000,
992 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0x000000f0, 0x00000000,
993 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA0 ) & 0xFF)) , 0x000000f0, 0x00000000,
994 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xA8 ) & 0xFF)) , 0x000000f0, 0x00000000,
995 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB0 ) & 0xFF)) , 0x000000f0, 0x00000000,
996 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xB8 ) & 0xFF)) , 0x000000f0, 0x00fc0003,
998 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC4 ) & 0xFF)) , 0xFE000FC8, 0x01fff000,
999 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xCC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
1000 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD4 ) & 0xFF)) , 0xFE000FC8, 0x00000000,
1001 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xDC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
1003 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC0 ) & 0xFF)) , 0xFE000FCC, 0x00000003,
1004 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xC8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1005 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD0 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1006 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xD8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
1008 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE0 ) & 0xFF)) , 0x0000FC88, 0xff000003,
1009 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE4 ) & 0xFF)) , 0x0000FC88, 0x00000000,
1010 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xE8 ) & 0xFF)) , 0x0000FC88, 0x00000000,
1011 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0xEC ) & 0xFF)) , 0x0000FC88, 0x00000000,
1014 max = sizeof(register_values)/sizeof(register_values[0]);
1015 setup_resource_map(register_values, max);
1017 static void sdram_set_registers(const struct mem_controller *ctrl)
1019 static const unsigned int register_values[] = {
1022 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
1023 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
1024 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
1025 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
1026 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
1027 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
1028 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
1029 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
1031 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1032 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1033 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1034 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1035 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1036 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1037 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1038 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
1040 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x40 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1041 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x44 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1042 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x48 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1043 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x4C ) & 0xFF)) , 0x001f01fe, 0x00000000,
1044 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x50 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1045 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x54 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1046 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0x001f01fe, 0x00000000,
1047 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x001f01fe, 0x00000000,
1049 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1050 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x64 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1051 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x68 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1052 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x6C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1053 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x70 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1054 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x74 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1055 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x78 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1056 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x7C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
1058 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0xffff8888, 0x00000000,
1060 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0xe8088008, 0x02522001 ,
1062 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0),
1064 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0xf0000000,
1065 (4 << 25)|(0 << 24)|
1066 (0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)|
1067 (1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)|
1068 (2 << 14)|(0 << 13)|(0 << 12)|
1069 (0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)|
1070 (0 << 3) |(0 << 1) |(0 << 0),
1072 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0xc180f0f0,
1073 (0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)|
1074 (0 << 20)|(0 << 19)|(3 << 16)|(0 << 8)|(0 << 0),
1076 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000,
1078 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000,
1080 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000003e, 0x00000000,
1082 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xffffff00, 0x00000000,
1084 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x94 ) & 0xFF)) , 0xffff8000, 0x00000f70,
1085 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x90 ) & 0xFF)) , 0xffffff80, 0x00000002,
1086 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0x0000000f, 0x00068300,
1090 print_debug("setting up CPU");
1091 print_debug_hex8(ctrl->node_id);
1092 print_debug(" northbridge registers\r\n");
1093 max = sizeof(register_values)/sizeof(register_values[0]);
1094 for(i = 0; i < max; i += 3) {
1098 dev = (register_values[i] & ~0xff) - ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) + ctrl->f0;
1099 where = register_values[i] & 0xff;
1100 reg = pci_read_config32(dev, where);
1101 reg &= register_values[i+1];
1102 reg |= register_values[i+2];
1103 pci_write_config32(dev, where, reg);
1105 print_debug("done.\r\n");
1107 static int is_dual_channel(const struct mem_controller *ctrl)
1110 dcl = pci_read_config32(ctrl->f2, 0x90 );
1111 return dcl & (1<<16) ;
1113 static int is_opteron(const struct mem_controller *ctrl)
1117 nbcap = pci_read_config32(ctrl->f3, 0xE8 );
1118 return !!(nbcap & 0x0001 );
1120 static int is_registered(const struct mem_controller *ctrl)
1124 dcl = pci_read_config32(ctrl->f2, 0x90 );
1125 return !(dcl & (1<<18) );
1128 unsigned long side1;
1129 unsigned long side2;
1131 static struct dimm_size spd_get_dimm_size(unsigned device)
1134 struct dimm_size sz;
1139 value = spd_read_byte(device, 3);
1140 if (value < 0) goto out;
1141 sz.side1 += value & 0xf;
1142 value = spd_read_byte(device, 4);
1143 if (value < 0) goto out;
1144 sz.side1 += value & 0xf;
1145 value = spd_read_byte(device, 17);
1146 if (value < 0) goto out;
1147 sz.side1 += log2(value & 0xff);
1149 value = spd_read_byte(device, 7);
1150 if (value < 0) goto out;
1154 low = spd_read_byte(device, 6);
1155 if (low < 0) goto out;
1156 value = value | (low & 0xff);
1157 sz.side1 += log2(value);
1159 value = spd_read_byte(device, 5);
1160 if (value <= 1) goto out;
1162 sz.side2 = sz.side1;
1163 value = spd_read_byte(device, 3);
1164 if (value < 0) goto out;
1165 if ((value & 0xf0) == 0) goto out;
1166 sz.side2 -= (value & 0x0f);
1167 sz.side2 += ((value >> 4) & 0x0f);
1168 value = spd_read_byte(device, 4);
1169 if (value < 0) goto out;
1170 sz.side2 -= (value & 0x0f);
1171 sz.side2 += ((value >> 4) & 0x0f);
1175 static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index)
1177 uint32_t base0, base1, map;
1179 if (sz.side1 != sz.side2) {
1182 map = pci_read_config32(ctrl->f2, 0x80 );
1183 map &= ~(0xf << (index + 4));
1188 if (sz.side1 >= (25 +3)) {
1189 map |= (sz.side1 - (25 + 3)) << (index *4);
1190 base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1;
1193 if (sz.side2 >= (25 + 3)) {
1194 base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1;
1197 if (is_dual_channel(ctrl)) {
1198 base0 = (base0 << 1) | (base0 & 1);
1199 base1 = (base1 << 1) | (base1 & 1);
1202 base0 &= ~0x001ffffe;
1203 base1 &= ~0x001ffffe;
1205 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+0)<<2), base0);
1206 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+1)<<2), base1);
1207 pci_write_config32(ctrl->f2, 0x80 , map);
1211 dch = pci_read_config32(ctrl->f2, 0x94 );
1212 dch |= (1 << 26) << index;
1213 pci_write_config32(ctrl->f2, 0x94 , dch);
1216 static void spd_set_ram_size(const struct mem_controller *ctrl)
1220 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1221 struct dimm_size sz;
1222 sz = spd_get_dimm_size(ctrl->channel0[i]);
1223 set_dimm_size(ctrl, sz, i);
1226 static void route_dram_accesses(const struct mem_controller *ctrl,
1227 unsigned long base_k, unsigned long limit_k)
1234 unsigned limit_reg, base_reg;
1236 node_id = ctrl->node_id;
1237 index = (node_id << 3);
1238 limit = (limit_k << 2);
1239 limit &= 0xffff0000;
1240 limit -= 0x00010000;
1241 limit |= ( 0 << 8) | (node_id << 0);
1242 base = (base_k << 2);
1244 base |= (0 << 8) | (1<<1) | (1<<0);
1245 limit_reg = 0x44 + index;
1246 base_reg = 0x40 + index;
1247 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)) ) {
1248 pci_write_config32(device, limit_reg, limit);
1249 pci_write_config32(device, base_reg, base);
1252 static void set_top_mem(unsigned tom_k)
1257 print_debug("No memory - reset");
1259 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0x04 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0x41, 0xf1);
1264 print_debug("RAM: 0x");
1265 print_debug_hex32(tom_k);
1266 print_debug(" KB\r\n");
1269 msr.lo = (tom_k & 0x003fffff) << 10;
1270 msr.hi = (tom_k & 0xffc00000) >> 22;
1271 wrmsr(0xC001001D , msr);
1273 if (tom_k >= 0x003f0000) {
1276 msr.lo = (tom_k & 0x003fffff) << 10;
1277 msr.hi = (tom_k & 0xffc00000) >> 22;
1278 wrmsr(0xC001001A , msr);
1280 static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
1283 static const uint32_t csbase_low[] = {
1292 uint32_t csbase_inc;
1293 int chip_selects, index;
1296 unsigned common_size;
1297 uint32_t csbase, csmask;
1301 for(index = 0; index < 8; index++) {
1305 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2));
1313 if (common_size == 0) {
1317 if (common_size != size) {
1322 bits = log2(chip_selects);
1323 if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
1328 if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
1329 print_debug("8 4GB chip selects cannot be interleaved\r\n");
1333 if (is_dual_channel(ctrl)) {
1334 csbase_inc = csbase_low[log2(common_size) - 1] << 1;
1336 csbase_inc = csbase_low[log2(common_size)];
1340 csmask = (((common_size << bits) - 1) << 21);
1341 csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
1342 for(index = 0; index < 8; index++) {
1344 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2));
1349 pci_write_config32(ctrl->f2, 0x40 + (index << 2), csbase);
1350 pci_write_config32(ctrl->f2, 0x60 + (index << 2), csmask);
1351 csbase += csbase_inc;
1354 print_debug("Interleaved\r\n");
1356 return common_size << (15 + bits);
1358 static unsigned long order_chip_selects(const struct mem_controller *ctrl)
1366 unsigned index, canidate;
1367 uint32_t csbase, csmask;
1371 for(index = 0; index < 8; index++) {
1373 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2));
1380 if (value <= csbase) {
1385 if (tom & (1 << (index + 24))) {
1397 size = csbase >> 21;
1399 tom |= (1 << (canidate + 24));
1401 csbase = (tom << 21) | 1;
1405 csmask = ((size -1) << 21);
1408 pci_write_config32(ctrl->f2, 0x40 + (canidate << 2), csbase);
1410 pci_write_config32(ctrl->f2, 0x60 + (canidate << 2), csmask);
1414 return (tom & ~0xff000000) << 15;
1416 static void order_dimms(const struct mem_controller *ctrl)
1418 unsigned long tom, tom_k, base_k;
1420 tom_k = interleave_chip_selects(ctrl);
1422 tom_k = order_chip_selects(ctrl);
1426 for(node_id = 0; node_id < ctrl->node_id; node_id++) {
1427 uint32_t limit, base;
1429 index = node_id << 3;
1430 base = pci_read_config32(ctrl->f1, 0x40 + index);
1432 if ((base & 3) == 3) {
1433 limit = pci_read_config32(ctrl->f1, 0x44 + index);
1434 base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
1438 route_dram_accesses(ctrl, base_k, tom_k);
1441 static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
1443 print_debug("disabling dimm");
1444 print_debug_hex8(index);
1445 print_debug("\r\n");
1446 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+0)<<2), 0);
1447 pci_write_config32(ctrl->f2, 0x40 + (((index << 1)+1)<<2), 0);
1449 static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
1457 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1459 value = spd_read_byte(ctrl->channel0[i], 21);
1461 disable_dimm(ctrl, i);
1465 if (value & (1 << 1)) {
1473 if (unbuffered && registered) {
1474 die("Mixed buffered and registered dimms not supported");
1476 if (unbuffered && is_opteron(ctrl)) {
1477 die("Unbuffered Dimms not supported on Opteron");
1479 dcl = pci_read_config32(ctrl->f2, 0x90 );
1484 pci_write_config32(ctrl->f2, 0x90 , dcl);
1486 static void spd_enable_2channels(const struct mem_controller *ctrl)
1492 static const unsigned addresses[] = {
1514 nbcap = pci_read_config32(ctrl->f3, 0xE8 );
1515 if (!(nbcap & 0x0001 )) {
1518 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1519 unsigned device0, device1;
1522 device0 = ctrl->channel0[i];
1523 device1 = ctrl->channel1[i];
1526 for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
1528 addr = addresses[j];
1529 value0 = spd_read_byte(device0, addr);
1533 value1 = spd_read_byte(device1, addr);
1537 if (value0 != value1) {
1542 print_debug("Enabling dual channel memory\r\n");
1544 dcl = pci_read_config32(ctrl->f2, 0x90 );
1547 pci_write_config32(ctrl->f2, 0x90 , dcl);
1554 uint32_t dch_memclk;
1555 uint16_t dch_tref4k, dch_tref8k;
1559 static const struct mem_param *get_mem_param(unsigned min_cycle_time)
1561 static const struct mem_param speed[] = {
1563 .name = "100Mhz\r\n",
1565 .divisor = (10 <<1),
1568 .dch_memclk = 0 << 20 ,
1569 .dch_tref4k = 0x00 ,
1570 .dch_tref8k = 0x08 ,
1574 .name = "133Mhz\r\n",
1576 .divisor = (7<<1)+1,
1579 .dch_memclk = 2 << 20 ,
1580 .dch_tref4k = 0x01 ,
1581 .dch_tref8k = 0x09 ,
1585 .name = "166Mhz\r\n",
1590 .dch_memclk = 5 << 20 ,
1591 .dch_tref4k = 0x02 ,
1592 .dch_tref8k = 0x0A ,
1596 .name = "200Mhz\r\n",
1601 .dch_memclk = 7 << 20 ,
1602 .dch_tref4k = 0x03 ,
1603 .dch_tref8k = 0x0B ,
1610 const struct mem_param *param;
1611 for(param = &speed[0]; param->cycle_time ; param++) {
1612 if (min_cycle_time > (param+1)->cycle_time) {
1616 if (!param->cycle_time) {
1617 die("min_cycle_time to low");
1619 print_debug(param->name);
1622 static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
1625 const struct mem_param *param;
1626 unsigned min_cycle_time, min_latency;
1629 static const int latency_indicies[] = { 26, 23, 9 };
1630 static const unsigned char min_cycle_times[] = {
1636 value = pci_read_config32(ctrl->f3, 0xE8 );
1637 min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ];
1640 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1641 int new_cycle_time, new_latency;
1646 new_cycle_time = 0xa0;
1648 latencies = spd_read_byte(ctrl->channel0[i], 18);
1649 if (latencies <= 0) continue;
1651 latency = log2(latencies) -2;
1653 for(index = 0; index < 3; index++, latency++) {
1655 if ((latency < 2) || (latency > 4) ||
1656 (!(latencies & (1 << latency)))) {
1659 value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
1664 if ((value >= min_cycle_time) && (value < new_cycle_time)) {
1665 new_cycle_time = value;
1666 new_latency = latency;
1669 if (new_latency > 4){
1673 if (new_cycle_time > min_cycle_time) {
1674 min_cycle_time = new_cycle_time;
1677 if (new_latency > min_latency) {
1678 min_latency = new_latency;
1683 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
1689 latencies = spd_read_byte(ctrl->channel0[i], 18);
1690 if (latencies <= 0) {
1694 latency = log2(latencies) -2;
1696 for(index = 0; index < 3; index++, latency++) {
1697 if (!(latencies & (1 << latency))) {
1700 if (latency == min_latency)
1704 if ((latency != min_latency) || (index >= 3)) {
1709 value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
1712 if (value <= min_cycle_time) {
1717 disable_dimm(ctrl, i);
1720 param = get_mem_param(min_cycle_time);
1722 value = pci_read_config32(ctrl->f2, 0x94 );
1723 value &= ~(0x7 << 20 );
1724 value |= param->dch_memclk;
1725 pci_write_config32(ctrl->f2, 0x94 , value);
1726 static const unsigned latencies[] = { 1 , 5 , 2 };
1728 value = pci_read_config32(ctrl->f2, 0x88 );
1729 value &= ~(0x7 << 0 );
1730 value |= latencies[min_latency - 2] << 0 ;
1731 pci_write_config32(ctrl->f2, 0x88 , value);
1735 static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1737 unsigned clocks, old_clocks;
1740 value = spd_read_byte(ctrl->channel0[i], 41);
1741 if (value < 0) return -1;
1742 if ((value == 0) || (value == 0xff)) {
1745 clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1752 dtl = pci_read_config32(ctrl->f2, 0x88 );
1753 old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ;
1754 if (old_clocks > clocks) {
1755 clocks = old_clocks;
1757 dtl &= ~(0xf << 4 );
1758 dtl |= ((clocks - 7 ) << 4 );
1759 pci_write_config32(ctrl->f2, 0x88 , dtl);
1762 static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1764 unsigned clocks, old_clocks;
1767 value = spd_read_byte(ctrl->channel0[i], 42);
1768 if (value < 0) return -1;
1769 if ((value == 0) || (value == 0xff)) {
1770 value = param->tRFC;
1772 clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1779 dtl = pci_read_config32(ctrl->f2, 0x88 );
1780 old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ;
1781 if (old_clocks > clocks) {
1782 clocks = old_clocks;
1784 dtl &= ~(0xf << 8 );
1785 dtl |= ((clocks - 9 ) << 8 );
1786 pci_write_config32(ctrl->f2, 0x88 , dtl);
1789 static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1791 unsigned clocks, old_clocks;
1794 value = spd_read_byte(ctrl->channel0[i], 29);
1795 if (value < 0) return -1;
1796 clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
1803 dtl = pci_read_config32(ctrl->f2, 0x88 );
1804 old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ;
1805 if (old_clocks > clocks) {
1806 clocks = old_clocks;
1808 dtl &= ~(0x7 << 12 );
1809 dtl |= ((clocks - 0 ) << 12 );
1810 pci_write_config32(ctrl->f2, 0x88 , dtl);
1813 static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1815 unsigned clocks, old_clocks;
1818 value = spd_read_byte(ctrl->channel0[i], 28);
1819 if (value < 0) return -1;
1820 clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
1827 dtl = pci_read_config32(ctrl->f2, 0x88 );
1828 old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ;
1829 if (old_clocks > clocks) {
1830 clocks = old_clocks;
1832 dtl &= ~(0x7 << 16 );
1833 dtl |= ((clocks - 0 ) << 16 );
1834 pci_write_config32(ctrl->f2, 0x88 , dtl);
1837 static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1839 unsigned clocks, old_clocks;
1842 value = spd_read_byte(ctrl->channel0[i], 30);
1843 if (value < 0) return -1;
1844 clocks = ((value << 1) + param->divisor - 1)/param->divisor;
1851 dtl = pci_read_config32(ctrl->f2, 0x88 );
1852 old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ;
1853 if (old_clocks > clocks) {
1854 clocks = old_clocks;
1856 dtl &= ~(0xf << 20 );
1857 dtl |= ((clocks - 0 ) << 20 );
1858 pci_write_config32(ctrl->f2, 0x88 , dtl);
1861 static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1863 unsigned clocks, old_clocks;
1866 value = spd_read_byte(ctrl->channel0[i], 27);
1867 if (value < 0) return -1;
1868 clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
1875 dtl = pci_read_config32(ctrl->f2, 0x88 );
1876 old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ;
1877 if (old_clocks > clocks) {
1878 clocks = old_clocks;
1880 dtl &= ~(0x7 << 24 );
1881 dtl |= ((clocks - 0 ) << 24 );
1882 pci_write_config32(ctrl->f2, 0x88 , dtl);
1885 static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
1888 dtl = pci_read_config32(ctrl->f2, 0x88 );
1889 dtl &= ~(0x1 << 28 );
1890 dtl |= (param->dtl_twr - 2 ) << 28 ;
1891 pci_write_config32(ctrl->f2, 0x88 , dtl);
1893 static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param)
1896 dth = pci_read_config32(ctrl->f2, 0x8c );
1897 dth &= ~(0x1f << 8 );
1898 dth |= (param->dch_tref4k << 8 );
1899 pci_write_config32(ctrl->f2, 0x8c , dth);
1901 static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1905 unsigned tref, old_tref;
1906 value = spd_read_byte(ctrl->channel0[i], 3);
1907 if (value < 0) return -1;
1909 tref = param->dch_tref8k;
1911 tref = param->dch_tref4k;
1913 dth = pci_read_config32(ctrl->f2, 0x8c );
1914 old_tref = (dth >> 8 ) & 0x1f ;
1915 if ((value == 12) && (old_tref == param->dch_tref4k)) {
1916 tref = param->dch_tref4k;
1918 tref = param->dch_tref8k;
1920 dth &= ~(0x1f << 8 );
1921 dth |= (tref << 8 );
1922 pci_write_config32(ctrl->f2, 0x8c , dth);
1925 static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1930 value = spd_read_byte(ctrl->channel0[i], 13);
1936 dcl = pci_read_config32(ctrl->f2, 0x90 );
1937 dcl &= ~(1 << dimm);
1941 pci_write_config32(ctrl->f2, 0x90 , dcl);
1944 static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
1948 value = spd_read_byte(ctrl->channel0[i], 11);
1953 dcl = pci_read_config32(ctrl->f2, 0x90 );
1955 pci_write_config32(ctrl->f2, 0x90 , dcl);
1959 static int count_dimms(const struct mem_controller *ctrl)
1964 for(index = 0; index < 8; index += 2) {
1966 csbase = pci_read_config32(ctrl->f2, (0x40 + index << 2));
1973 static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
1978 dth = pci_read_config32(ctrl->f2, 0x8c );
1979 dth &= ~(0x1 << 0 );
1980 dth |= ((clocks - 1 ) << 0 );
1981 pci_write_config32(ctrl->f2, 0x8c , dth);
1983 static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
1990 dtl = pci_read_config32(ctrl->f2, 0x88 );
1991 latency = (dtl >> 0 ) & 0x7 ;
1992 divisor = param->divisor;
1993 if (is_opteron(ctrl)) {
1994 if (latency == 1 ) {
1995 if (divisor == ((6 << 0) + 0)) {
1999 else if (divisor > ((6 << 0)+0)) {
2004 else if (latency == 5 ) {
2007 else if (latency == 2 ) {
2008 if (divisor == ((6 << 0)+0)) {
2012 else if (divisor > ((6 << 0)+0)) {
2019 if (is_registered(ctrl)) {
2020 if (latency == 1 ) {
2023 else if (latency == 5 ) {
2026 else if (latency == 2 ) {
2031 if (latency == 1 ) {
2034 else if (latency == 5 ) {
2037 else if (latency == 2 ) {
2042 if ((clocks < 1 ) || (clocks > 6 )) {
2043 die("Unknown Trwt");
2046 dth = pci_read_config32(ctrl->f2, 0x8c );
2047 dth &= ~(0x7 << 4 );
2048 dth |= ((clocks - 1 ) << 4 );
2049 pci_write_config32(ctrl->f2, 0x8c , dth);
2052 static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param)
2057 if (is_registered(ctrl)) {
2062 dth = pci_read_config32(ctrl->f2, 0x8c );
2063 dth &= ~(0x7 << 20 );
2064 dth |= ((clocks - 1 ) << 20 );
2065 pci_write_config32(ctrl->f2, 0x8c , dth);
2067 static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
2071 unsigned rdpreamble;
2072 divisor = param->divisor;
2073 dch = pci_read_config32(ctrl->f2, 0x94 );
2074 dch &= ~(0xf << 8 );
2076 if (is_registered(ctrl)) {
2077 if (divisor == ((10 << 1)+0)) {
2079 rdpreamble = ((9 << 1)+ 0);
2081 else if (divisor == ((7 << 1)+1)) {
2083 rdpreamble = ((8 << 1)+0);
2085 else if (divisor == ((6 << 1)+0)) {
2087 rdpreamble = ((7 << 1)+1);
2089 else if (divisor == ((5 << 1)+0)) {
2091 rdpreamble = ((7 << 1)+0);
2098 for(i = 0; i < 4; i++) {
2099 if (ctrl->channel0[i]) {
2103 if (divisor == ((10 << 1)+0)) {
2107 rdpreamble = ((9 << 1)+0);
2110 rdpreamble = ((14 << 1)+0);
2113 else if (divisor == ((7 << 1)+1)) {
2117 rdpreamble = ((7 << 1)+0);
2120 rdpreamble = ((11 << 1)+0);
2123 else if (divisor == ((6 << 1)+0)) {
2127 rdpreamble = ((7 << 1)+0);
2130 rdpreamble = ((9 << 1)+0);
2133 else if (divisor == ((5 << 1)+0)) {
2137 rdpreamble = ((5 << 1)+0);
2140 rdpreamble = ((7 << 1)+0);
2144 if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) {
2145 die("Unknown rdpreamble");
2147 dch |= (rdpreamble - ((2<<1)+0) ) << 8 ;
2148 pci_write_config32(ctrl->f2, 0x94 , dch);
2150 static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param)
2156 dimms = count_dimms(ctrl);
2157 dch = pci_read_config32(ctrl->f2, 0x94 );
2158 dch &= ~(0xf << 0 );
2160 if (is_registered(ctrl)) {
2172 die("Too many unbuffered dimms");
2174 else if (dimms == 3) {
2183 dch |= ((async_lat - 0 ) << 0 );
2184 pci_write_config32(ctrl->f2, 0x94 , dch);
2186 static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param)
2190 dch = pci_read_config32(ctrl->f2, 0x94 );
2191 dch &= ~(0x7 << 16 );
2194 pci_write_config32(ctrl->f2, 0x94 , dch);
2196 static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
2202 init_Tref(ctrl, param);
2203 for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
2206 if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
2207 if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
2208 if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
2209 if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
2210 if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
2211 if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
2213 if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
2215 if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
2216 if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
2219 disable_dimm(ctrl, i);
2223 set_Twr(ctrl, param);
2225 set_Twtr(ctrl, param);
2226 set_Trwt(ctrl, param);
2227 set_Twcl(ctrl, param);
2229 set_read_preamble(ctrl, param);
2230 set_max_async_latency(ctrl, param);
2231 set_idle_cycle_limit(ctrl, param);
2233 static void sdram_set_spd_registers(const struct mem_controller *ctrl)
2235 const struct mem_param *param;
2236 spd_enable_2channels(ctrl);
2237 spd_set_ram_size(ctrl);
2238 spd_handle_unbuffered_dimms(ctrl);
2239 param = spd_set_memclk(ctrl);
2240 spd_set_dram_timing(ctrl, param);
2243 static void sdram_enable(int controllers, const struct mem_controller *ctrl)
2247 for(i = 0; i < controllers; i++) {
2249 dch = pci_read_config32(ctrl[i].f2, 0x94 );
2251 pci_write_config32(ctrl[i].f2, 0x94 , dch);
2254 memreset(controllers, ctrl);
2255 for(i = 0; i < controllers; i++) {
2258 dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2259 if (dcl & (1<<17) ) {
2261 print_debug("ECC enabled\r\n");
2262 mnc = pci_read_config32(ctrl[i].f3, 0x44 );
2264 if (dcl & (1<<16) ) {
2267 pci_write_config32(ctrl[i].f3, 0x44 , mnc);
2270 pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2276 pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2278 for(i = 0; i < controllers; i++) {
2280 print_debug("Initializing memory: ");
2283 dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2285 if ((loops & 1023) == 0) {
2288 } while(((dcl & (1<<8) ) != 0) && (loops < 300000 ));
2289 if (loops >= 300000 ) {
2290 print_debug(" failed\r\n");
2292 print_debug(" done\r\n");
2294 if (dcl & (1<<17) ) {
2295 print_debug("Clearing memory: ");
2296 if (!is_cpu_pre_c0()) {
2298 dcl &= ~((1<<11) | (1<<10) );
2299 pci_write_config32(ctrl[i].f2, 0x90 , dcl);
2301 dcl = pci_read_config32(ctrl[i].f2, 0x90 );
2302 } while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) );
2304 uint32_t base, last_scrub_k, scrub_k;
2305 uint32_t cnt,zstart,zend;
2308 pci_write_config32(ctrl[i].f3, 0x58 ,
2309 (0 << 16) | (0 << 8) | (0 << 0));
2311 msr_201 = rdmsr(0x201);
2312 zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
2313 zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
2316 print_debug("addr ");
2317 print_debug_hex32(zstart);
2319 print_debug_hex32(zend);
2320 print_debug("\r\n");
2323 msr = rdmsr(0x2ff );
2327 msr = rdmsr(0xc0010015);
2329 wrmsr(0xc0010015,msr);
2330 for(;zstart<zend;zstart+=4) {
2337 "movl %%cr0, %0\n\t"
2338 "orl $0x40000000, %0\n\t"
2339 "movl %0, %%cr0\n\t"
2344 msr.lo = 1 + ((zstart&0x0ff)<<24);
2345 msr.hi = (zstart&0x0ff00)>>8;
2348 msr.hi = 0x000000ff;
2349 msr.lo = 0xfc000800;
2353 "movl %%cr0, %0\n\t"
2354 "andl $0x9fffffff, %0\n\t"
2355 "movl %0, %%cr0\n\t"
2359 msr.lo = (zstart&0xff) << 24;
2360 msr.hi = (zstart&0xff00) >> 8;
2361 wrmsr(0xc0000100,msr);
2362 print_debug_char((zstart > 0x0ff)?'+':'-');
2367 "movl %0, %%fs:(%1)\n\t"
2372 : "a" (0), "D" (0), "c" (0x01000000)
2378 "movl %%cr0, %0\n\t"
2379 "orl $0x40000000, %0\n\t"
2380 "movl %0, %%cr0\n\t"
2385 msr = rdmsr(0x2ff );
2392 wrmsr(0x201,msr_201);
2396 wrmsr(0xc0000100,msr);
2399 "movl %%cr0, %0\n\t"
2400 "andl $0x9fffffff, %0\n\t"
2401 "movl %0, %%cr0\n\t"
2406 msr = rdmsr(0xc0010015);
2408 wrmsr(0xc0010015,msr);
2410 base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
2413 pci_write_config32(ctrl[i].f3, 0x5C , base << 8);
2414 pci_write_config32(ctrl[i].f3, 0x60 , base >> 24);
2416 pci_write_config32(ctrl[i].f3, 0x58 ,
2417 (22 << 16) | (22 << 8) | (22 << 0));
2418 print_debug("done\r\n");
2428 typedef uint32_t u32;
2429 typedef int8_t bool;
2430 static void disable_probes(void)
2435 print_debug("Disabling read/write/fill probes for UP... ");
2436 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68);
2437 val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
2438 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68, val);
2439 print_debug("done.\r\n");
2442 static void wait_ap_stop(u8 node)
2446 for(i=0;i< 1000 ;i++) {
2448 regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c);
2449 if((regx & (1<<4))==1) break;
2451 reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c);
2453 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, reg);
2455 static void notify_bsp_ap_is_stopped(void)
2458 unsigned long apic_id;
2459 apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 ));
2464 reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C);
2466 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C, reg);
2471 static void enable_routing(u8 node)
2476 print_debug("Enabling routing table for node ");
2477 print_debug_hex32(node);
2478 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c);
2479 val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
2480 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, val);
2486 print_debug(" done.\r\n");
2488 static void rename_temp_node(u8 node)
2491 print_debug("Renaming current temp node to ");
2492 print_debug_hex32(node);
2493 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60);
2496 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60, val);
2497 print_debug(" done.\r\n");
2499 static bool check_connection(u8 src, u8 dest, u8 link)
2505 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x98+link);
2506 if ( (val&0x17) != 0x03)
2509 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0);
2510 if(val != 0x11001022)
2514 static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
2516 static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
2517 static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
2518 uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
2519 uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
2523 freq_cap1 = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 0x0a );
2524 freq_cap2 = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 0x0a );
2527 freq = log2(freq_cap1 & freq_cap2 & 0xff);
2529 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 0x09 , freq);
2530 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 0x09 , freq);
2532 width_cap1 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 );
2533 width_cap2 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 6 );
2535 ln_width1 = link_width_to_pow2[width_cap1 & 7];
2536 ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
2537 if (ln_width1 > ln_width2) {
2538 ln_width1 = ln_width2;
2540 width = pow2_to_link_width[ln_width1];
2542 ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
2543 ln_width2 = link_width_to_pow2[width_cap2 & 7];
2544 if (ln_width1 > ln_width2) {
2545 ln_width1 = ln_width2;
2547 width |= pow2_to_link_width[ln_width1] << 4;
2550 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 + 1, width);
2552 width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
2553 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link2 + 6 + 1, width);
2555 static void fill_row(u8 node, u8 row, u32 value)
2557 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x40+(row<<2), value);
2559 static void setup_row(u8 source, u8 dest, u8 cpus)
2561 fill_row(source,dest,generate_row(source,dest,cpus));
2563 static void setup_temp_row(u8 source, u8 dest, u8 cpus)
2565 fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) );
2567 static void setup_node(u8 node, u8 cpus)
2570 for(row=0; row<cpus; row++)
2571 setup_row(node, row, cpus);
2573 static void setup_remote_row(u8 source, u8 dest, u8 cpus)
2575 fill_row(7, dest, generate_row(source, dest, cpus));
2577 static void setup_remote_node(u8 node, u8 cpus)
2579 static const uint8_t pci_reg[] = {
2580 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
2581 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
2582 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
2583 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
2584 0xc4, 0xcc, 0xd4, 0xdc,
2585 0xc0, 0xc8, 0xd0, 0xd8,
2586 0xe0, 0xe4, 0xe8, 0xec,
2590 print_debug("setup_remote_node\r\n");
2591 for(row=0; row<cpus; row++)
2592 setup_remote_row(node, row, cpus);
2594 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
2598 value = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , reg);
2599 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) , reg, value);
2601 print_debug("setup_remote_done\r\n");
2603 static u8 setup_uniprocessor(void)
2605 print_debug("Enabling UP settings\r\n");
2609 static u8 setup_smp(void)
2612 print_debug("Enabling SMP settings\r\n");
2613 setup_row(0,0,cpus);
2615 setup_temp_row(0,1,cpus);
2617 if (!check_connection(0, 7, 0x20 )) {
2618 print_debug("No connection to Node 1.\r\n");
2619 fill_row( 0 ,7,0x00010101 ) ;
2620 setup_uniprocessor();
2624 optimize_connection(0, 0x20 , 7, 0x20 );
2625 setup_node(0, cpus);
2626 setup_remote_node(1, cpus);
2627 rename_temp_node(1);
2630 fill_row( 0 ,7,0x00010101 ) ;
2632 print_debug_hex32(cpus);
2633 print_debug(" nodes initialized.\r\n");
2636 static unsigned detect_mp_capabilities(unsigned cpus)
2638 unsigned node, row, mask;
2640 print_debug("detect_mp_capabilities: ");
2641 print_debug_hex32(cpus);
2642 print_debug("\r\n");
2647 for (node=0; node<cpus; node++) {
2648 if ((pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0xe8) & mask)!=mask)
2654 print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
2655 for (node=cpus; node>0; node--)
2656 for (row=cpus; row>0; row--)
2657 fill_row(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node-1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , row-1, 0x00010101 );
2659 return setup_uniprocessor();
2661 static void coherent_ht_finalize(unsigned cpus)
2667 print_debug("coherent_ht_finalize\r\n");
2668 rev_a0= is_cpu_rev_a0();
2669 for (node=0; node<cpus; node++) {
2671 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60);
2672 val &= (~0x000F0070);
2673 val |= ((cpus-1)<<16)|((cpus-1)<<4);
2674 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x60,val);
2675 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x68);
2677 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x68,val);
2679 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x94,0);
2680 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0xb4,0);
2681 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0xd4,0);
2684 print_debug("done\r\n");
2686 static int setup_coherent_ht_domain(void)
2689 int reset_needed = 0;
2692 cpus=detect_mp_capabilities(cpus);
2693 coherent_ht_finalize(cpus);
2695 coherent_ht_mainboard(cpus);
2696 return reset_needed;
2698 void sdram_no_memory(void)
2700 print_err("No memory!!\r\n");
2706 void sdram_initialize(int controllers, const struct mem_controller *ctrl)
2710 for(i = 0; i < controllers; i++) {
2711 print_debug("Ram1.");
2712 print_debug_hex8(i);
2713 print_debug("\r\n");
2714 sdram_set_registers(ctrl + i);
2717 for(i = 0; i < controllers; i++) {
2718 print_debug("Ram2.");
2719 print_debug_hex8(i);
2720 print_debug("\r\n");
2721 sdram_set_spd_registers(ctrl + i);
2724 print_debug("Ram3\r\n");
2725 sdram_enable(controllers, ctrl);
2726 print_debug("Ram4\r\n");
2728 static void enable_lapic(void)
2732 msr.hi &= 0xffffff00;
2733 msr.lo &= 0x000007ff;
2734 msr.lo |= 0xfee00000 | (1 << 11);
2737 static void stop_this_cpu(void)
2740 apicid = apic_read(0x020 ) >> 24;
2742 apic_write(0x310 , (( apicid )<<24) );
2743 apic_write(0x300 , 0x08000 | 0x04000 | 0x00500 );
2745 apic_wait_icr_idle();
2747 apic_write(0x310 , (( apicid )<<24) );
2748 apic_write(0x300 , 0x08000 | 0x00500 );
2750 apic_wait_icr_idle();
2756 static void pc87360_enable_serial(void)
2758 pnp_set_logical_device(0x2e , 0x03 );
2759 pnp_set_enable(0x2e , 1);
2760 pnp_set_iobase0(0x2e , 0x3f8);
2762 static void main(void)
2765 static const struct mem_controller cpu[] = {
2768 .f0 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,
2769 .f1 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ,
2770 .f2 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,
2771 .f3 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,
2772 .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
2773 .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
2777 .f0 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,
2778 .f1 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ,
2779 .f2 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 2 ) & 0x7) << 8)) ,
2780 .f3 = ( ((( 0 ) & 0xFF) << 16) | ((( 0x19 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,
2781 .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
2782 .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
2785 if (cpu_init_detected()) {
2786 asm("jmp __cpu_reset");
2793 pc87360_enable_serial();
2796 setup_default_resource_map();
2797 setup_coherent_ht_domain();
2798 enumerate_ht_chain(0);
2799 distinguish_cpu_resets(0);
2803 sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);