1typedef unsigned char uint8_t; 2typedef signed char int8_t; 3typedef unsigned short uint16_t; 4typedef signed short int16_t; 5typedef unsigned int uint32_t; 6typedef signed int int32_t; 7 8typedef unsigned char uint_least8_t; 9typedef signed char int_least8_t; 10typedef unsigned short uint_least16_t; 11typedef signed short int_least16_t; 12typedef unsigned int uint_least32_t; 13typedef signed int int_least32_t; 14 15typedef unsigned char uint_fast8_t; 16typedef signed char int_fast8_t; 17typedef unsigned int uint_fast16_t; 18typedef signed int int_fast16_t; 19typedef unsigned int uint_fast32_t; 20typedef signed int int_fast32_t; 21 22typedef int intptr_t; 23typedef unsigned int uintptr_t; 24 25typedef long int intmax_t; 26typedef unsigned long int uintmax_t; 27 28static inline unsigned long apic_read(unsigned long reg) 29{ 30 return *((volatile unsigned long *)(0xfee00000 +reg)); 31} 32static inline void apic_write(unsigned long reg, unsigned long v) 33{ 34 *((volatile unsigned long *)(0xfee00000 +reg)) = v; 35} 36static inline void apic_wait_icr_idle(void) 37{ 38 do { } while ( apic_read( 0x300 ) & 0x01000 ); 39} 40 41static void outb(unsigned char value, unsigned short port) 42{ 43 __builtin_outb(value, port); 44} 45static void outw(unsigned short value, unsigned short port) 46{ 47 __builtin_outw(value, port); 48} 49static void outl(unsigned int value, unsigned short port) 50{ 51 __builtin_outl(value, port); 52} 53static unsigned char inb(unsigned short port) 54{ 55 return __builtin_inb(port); 56} 57static unsigned char inw(unsigned short port) 58{ 59 return __builtin_inw(port); 60} 61static unsigned char inl(unsigned short port) 62{ 63 return __builtin_inl(port); 64} 65static inline void outsb(uint16_t port, const void *addr, unsigned long count) 66{ 67 __asm__ __volatile__ ( 68 "cld ; rep ; outsb " 69 : "=S" (addr), "=c" (count) 70 : "d"(port), "0"(addr), "1" (count) 71 ); 72} 73static inline void outsw(uint16_t port, const void *addr, unsigned long count) 74{ 75 __asm__ __volatile__ ( 76 "cld ; rep ; outsw " 77 : "=S" (addr), "=c" (count) 78 : "d"(port), "0"(addr), "1" (count) 79 ); 80} 81static inline void outsl(uint16_t port, const void *addr, unsigned long count) 82{ 83 __asm__ __volatile__ ( 84 "cld ; rep ; outsl " 85 : "=S" (addr), "=c" (count) 86 : "d"(port), "0"(addr), "1" (count) 87 ); 88} 89static inline void insb(uint16_t port, void *addr, unsigned long count) 90{ 91 __asm__ __volatile__ ( 92 "cld ; rep ; insb " 93 : "=D" (addr), "=c" (count) 94 : "d"(port), "0"(addr), "1" (count) 95 ); 96} 97static inline void insw(uint16_t port, void *addr, unsigned long count) 98{ 99 __asm__ __volatile__ ( 100 "cld ; rep ; insw " 101 : "=D" (addr), "=c" (count) 102 : "d"(port), "0"(addr), "1" (count) 103 ); 104} 105static inline void insl(uint16_t port, void *addr, unsigned long count) 106{ 107 __asm__ __volatile__ ( 108 "cld ; rep ; insl " 109 : "=D" (addr), "=c" (count) 110 : "d"(port), "0"(addr), "1" (count) 111 ); 112} 113static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg) 114{ 115 outb(reg, port); 116 outb(value, port +1); 117} 118static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg) 119{ 120 outb(reg, port); 121 return inb(port +1); 122} 123static inline void pnp_set_logical_device(unsigned char port, int device) 124{ 125 pnp_write_config(port, device, 0x07); 126} 127static inline void pnp_set_enable(unsigned char port, int enable) 128{ 129 pnp_write_config(port, enable?0x1:0x0, 0x30); 130} 131static inline int pnp_read_enable(unsigned char port) 132{ 133 return !!pnp_read_config(port, 0x30); 134} 135static inline void pnp_set_iobase0(unsigned char port, unsigned iobase) 136{ 137 pnp_write_config(port, (iobase >> 8) & 0xff, 0x60); 138 pnp_write_config(port, iobase & 0xff, 0x61); 139} 140static inline void pnp_set_iobase1(unsigned char port, unsigned iobase) 141{ 142 pnp_write_config(port, (iobase >> 8) & 0xff, 0x62); 143 pnp_write_config(port, iobase & 0xff, 0x63); 144} 145static inline void pnp_set_irq0(unsigned char port, unsigned irq) 146{ 147 pnp_write_config(port, irq, 0x70); 148} 149static inline void pnp_set_irq1(unsigned char port, unsigned irq) 150{ 151 pnp_write_config(port, irq, 0x72); 152} 153static inline void pnp_set_drq(unsigned char port, unsigned drq) 154{ 155 pnp_write_config(port, drq & 0xff, 0x74); 156} 157static void hlt(void) 158{ 159 __builtin_hlt(); 160} 161typedef __builtin_div_t div_t; 162typedef __builtin_ldiv_t ldiv_t; 163typedef __builtin_udiv_t udiv_t; 164typedef __builtin_uldiv_t uldiv_t; 165static div_t div(int numer, int denom) 166{ 167 return __builtin_div(numer, denom); 168} 169static ldiv_t ldiv(long numer, long denom) 170{ 171 return __builtin_ldiv(numer, denom); 172} 173static udiv_t udiv(unsigned numer, unsigned denom) 174{ 175 return __builtin_udiv(numer, denom); 176} 177static uldiv_t uldiv(unsigned long numer, unsigned long denom) 178{ 179 return __builtin_uldiv(numer, denom); 180} 181int log2(int value) 182{ 183 184 return __builtin_bsr(value); 185} 186typedef unsigned device_t; 187static unsigned char pci_read_config8(device_t dev, unsigned where) 188{ 189 unsigned addr; 190 addr = dev | where; 191 outl(0x80000000 | (addr & ~3), 0xCF8); 192 return inb(0xCFC + (addr & 3)); 193} 194static unsigned short pci_read_config16(device_t dev, unsigned where) 195{ 196 unsigned addr; 197 addr = dev | where; 198 outl(0x80000000 | (addr & ~3), 0xCF8); 199 return inw(0xCFC + (addr & 2)); 200} 201static unsigned int pci_read_config32(device_t dev, unsigned where) 202{ 203 unsigned addr; 204 addr = dev | where; 205 outl(0x80000000 | (addr & ~3), 0xCF8); 206 return inl(0xCFC); 207} 208static void pci_write_config8(device_t dev, unsigned where, unsigned char value) 209{ 210 unsigned addr; 211 addr = dev | where; 212 outl(0x80000000 | (addr & ~3), 0xCF8); 213 outb(value, 0xCFC + (addr & 3)); 214} 215static void pci_write_config16(device_t dev, unsigned where, unsigned short value) 216{ 217 unsigned addr; 218 addr = dev | where; 219 outl(0x80000000 | (addr & ~3), 0xCF8); 220 outw(value, 0xCFC + (addr & 2)); 221} 222static void pci_write_config32(device_t dev, unsigned where, unsigned int value) 223{ 224 unsigned addr; 225 addr = dev | where; 226 outl(0x80000000 | (addr & ~3), 0xCF8); 227 outl(value, 0xCFC); 228} 229static device_t pci_locate_device(unsigned pci_id, device_t dev) 230{ 231 for(; dev <= ( ((( 255 ) & 0xFF) << 16) | ((( 31 ) & 0x1f) << 11) | ((( 7 ) & 0x7) << 8)) ; dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 ) & 0x7) << 8)) ) { 232 unsigned int id; 233 id = pci_read_config32(dev, 0); 234 if (id == pci_id) { 235 return dev; 236 } 237 } 238 return (0xffffffffU) ; 239} 240 241 242 243 244 245static int uart_can_tx_byte(void) 246{ 247 return inb(1016 + 0x05 ) & 0x20; 248} 249static void uart_wait_to_tx_byte(void) 250{ 251 while(!uart_can_tx_byte()) 252 ; 253} 254static void uart_wait_until_sent(void) 255{ 256 while(!(inb(1016 + 0x05 ) & 0x40)) 257 ; 258} 259static void uart_tx_byte(unsigned char data) 260{ 261 uart_wait_to_tx_byte(); 262 outb(data, 1016 + 0x00 ); 263 264 uart_wait_until_sent(); 265} 266static void uart_init(void) 267{ 268 269 outb(0x0, 1016 + 0x01 ); 270 271 outb(0x01, 1016 + 0x02 ); 272 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 ); 277} 278 279static void __console_tx_byte(unsigned char byte) 280{ 281 uart_tx_byte(byte); 282} 283static void __console_tx_nibble(unsigned nibble) 284{ 285 unsigned char digit; 286 digit = nibble + '0'; 287 if (digit > '9') { 288 digit += 39; 289 } 290 __console_tx_byte(digit); 291} 292static void __console_tx_char(int loglevel, unsigned char byte) 293{ 294 if (8 > loglevel) { 295 uart_tx_byte(byte); 296 } 297} 298static void __console_tx_hex8(int loglevel, unsigned char value) 299{ 300 if (8 > loglevel) { 301 __console_tx_nibble((value >> 4U) & 0x0fU); 302 __console_tx_nibble(value & 0x0fU); 303 } 304} 305static void __console_tx_hex16(int loglevel, unsigned short value) 306{ 307 if (8 > loglevel) { 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); 312 } 313} 314static void __console_tx_hex32(int loglevel, unsigned int value) 315{ 316 if (8 > loglevel) { 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); 325 } 326} 327 328static void do_console_tx_string(const char *str) __attribute__((noinline)) 329{ 330 unsigned char ch; 331 while((ch = *str++) != '\0') { 332 __console_tx_byte(ch); 333 } 334} 335static void __console_tx_string(int loglevel, const char *str) 336{ 337 if (8 > loglevel) { 338 do_console_tx_string(str); 339 } 340} 341static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); } 342static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); } 343static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); } 344static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); } 345static void print_emerg(const char *str) { __console_tx_string(0 , str); } 346static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); } 347static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); } 348static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); } 349static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); } 350static void print_alert(const char *str) { __console_tx_string(1 , str); } 351static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); } 352static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); } 353static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); } 354static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); } 355static void print_crit(const char *str) { __console_tx_string(2 , str); } 356static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); } 357static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); } 358static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); } 359static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); } 360static void print_err(const char *str) { __console_tx_string(3 , str); } 361static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); } 362static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); } 363static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); } 364static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); } 365static void print_warning(const char *str) { __console_tx_string(4 , str); } 366static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); } 367static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); } 368static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); } 369static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); } 370static void print_notice(const char *str) { __console_tx_string(5 , str); } 371static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); } 372static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); } 373static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); } 374static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); } 375static void print_info(const char *str) { __console_tx_string(6 , str); } 376static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); } 377static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); } 378static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); } 379static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); } 380static void print_debug(const char *str) { __console_tx_string(7 , str); } 381static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); } 382static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); } 383static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); } 384static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); } 385static void print_spew(const char *str) { __console_tx_string(8 , str); } 386static void console_init(void) 387{ 388 static const char console_test[] = 389 "\r\n\r\nLinuxBIOS-" 390 "1.1.4" 391 ".0Fallback" 392 " " 393 "Thu Oct 9 20:29:48 MDT 2003" 394 " starting...\r\n"; 395 print_info(console_test); 396} 397static void die(const char *str) 398{ 399 print_emerg(str); 400 do { 401 hlt(); 402 } while(1); 403} 404static void write_phys(unsigned long addr, unsigned long value) 405{ 406 asm volatile( 407 "movnti %1, (%0)" 408 : 409 : "r" (addr), "r" (value) 410 : 411 ); 412} 413static unsigned long read_phys(unsigned long addr) 414{ 415 volatile unsigned long *ptr; 416 ptr = (void *)addr; 417 return *ptr; 418} 419static void ram_fill(unsigned long start, unsigned long stop) 420{ 421 unsigned long addr; 422 423 print_debug("DRAM fill: "); 424 print_debug_hex32(start); 425 print_debug("-"); 426 print_debug_hex32(stop); 427 print_debug("\r\n"); 428 for(addr = start; addr < stop ; addr += 4) { 429 430 if (!(addr & 0xffff)) { 431 print_debug_hex32(addr); 432 print_debug("\r"); 433 } 434 write_phys(addr, addr); 435 }; 436 437 print_debug_hex32(addr); 438 print_debug("\r\nDRAM filled\r\n"); 439} 440static void ram_verify(unsigned long start, unsigned long stop) 441{ 442 unsigned long addr; 443 444 print_debug("DRAM verify: "); 445 print_debug_hex32(start); 446 print_debug_char('-'); 447 print_debug_hex32(stop); 448 print_debug("\r\n"); 449 for(addr = start; addr < stop ; addr += 4) { 450 unsigned long value; 451 452 if (!(addr & 0xffff)) { 453 print_debug_hex32(addr); 454 print_debug("\r"); 455 } 456 value = read_phys(addr); 457 if (value != addr) { 458 459 print_err_hex32(addr); 460 print_err_char(':'); 461 print_err_hex32(value); 462 print_err("\r\n"); 463 } 464 } 465 466 print_debug_hex32(addr); 467 print_debug("\r\nDRAM verified\r\n"); 468} 469void ram_check(unsigned long start, unsigned long stop) 470{ 471 int result; 472 473 print_debug("Testing DRAM : "); 474 print_debug_hex32(start); 475 print_debug("-"); 476 print_debug_hex32(stop); 477 print_debug("\r\n"); 478 ram_fill(start, stop); 479 ram_verify(start, stop); 480 print_debug("Done.\r\n"); 481} 482static int enumerate_ht_chain(unsigned link) 483{ 484 485 unsigned next_unitid, last_unitid; 486 int reset_needed = 0; 487 next_unitid = 1; 488 do { 489 uint32_t id; 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 ); 493 494 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || 495 (((id >> 16) & 0xffff) == 0xffff) || 496 (((id >> 16) & 0xffff) == 0x0000)) { 497 break; 498 } 499 hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x0e ); 500 pos = 0; 501 hdr_type &= 0x7f; 502 if ((hdr_type == 0 ) || 503 (hdr_type == 1 )) { 504 pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x34 ); 505 } 506 while(pos != 0) { 507 uint8_t cap; 508 cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 0 ); 509 if (cap == 0x08 ) { 510 uint16_t flags; 511 flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 2 ); 512 if ((flags >> 13) == 0) { 513 unsigned count; 514 flags &= ~0x1f; 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; 519 break; 520 } 521 } 522 pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , pos + 1 ); 523 } 524 } while((last_unitid != next_unitid) && (next_unitid <= 0x1f)); 525 return reset_needed; 526} 527static void enable_smbus(void) 528{ 529 device_t dev; 530 dev = pci_locate_device((((( 0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0); 531 if (dev == (0xffffffffU) ) { 532 die("SMBUS controller not found\r\n"); 533 } 534 uint8_t enable; 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)); 539 540 outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 ); 541} 542static inline void smbus_delay(void) 543{ 544 outb(0x80, 0x80); 545} 546static int smbus_wait_until_ready(void) 547{ 548 unsigned long loops; 549 loops = (100*1000*10) ; 550 do { 551 unsigned short val; 552 smbus_delay(); 553 val = inw(0x0f00 + 0xe0 ); 554 if ((val & 0x800) == 0) { 555 break; 556 } 557 if(loops == ((100*1000*10) / 2)) { 558 outw(inw(0x0f00 + 0xe0 ), 559 0x0f00 + 0xe0 ); 560 } 561 } while(--loops); 562 return loops?0:-2; 563} 564static int smbus_wait_until_done(void) 565{ 566 unsigned long loops; 567 loops = (100*1000*10) ; 568 do { 569 unsigned short val; 570 smbus_delay(); 571 572 val = inw(0x0f00 + 0xe0 ); 573 if (((val & 0x8) == 0) | ((val & 0x437) != 0)) { 574 break; 575 } 576 } while(--loops); 577 return loops?0:-3; 578} 579static int smbus_read_byte(unsigned device, unsigned address) 580{ 581 unsigned char global_control_register; 582 unsigned char global_status_register; 583 unsigned char byte; 584 if (smbus_wait_until_ready() < 0) { 585 return -2; 586 } 587 588 589 590 outw(inw(0x0f00 + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00 + 0xe2 ); 591 592 outw(((device & 0x7f) << 1) | 1, 0x0f00 + 0xe4 ); 593 594 outb(address & 0xFF, 0x0f00 + 0xe8 ); 595 596 outw((inw(0x0f00 + 0xe2 ) & ~7) | (0x2), 0x0f00 + 0xe2 ); 597 598 599 outw(inw(0x0f00 + 0xe0 ), 0x0f00 + 0xe0 ); 600 601 outw(0, 0x0f00 + 0xe6 ); 602 603 outw((inw(0x0f00 + 0xe2 ) | (1 << 3)), 0x0f00 + 0xe2 ); 604 605 if (smbus_wait_until_done() < 0) { 606 return -3; 607 } 608 global_status_register = inw(0x0f00 + 0xe0 ); 609 610 byte = inw(0x0f00 + 0xe6 ) & 0xff; 611 if (global_status_register != (1 << 4)) { 612 return -1; 613 } 614 return byte; 615} 616static void smbus_write_byte(unsigned device, unsigned address, unsigned char val) 617{ 618 return; 619} 620struct mem_controller { 621 unsigned node_id; 622 device_t f0, f1, f2, f3; 623 uint8_t channel0[4]; 624 uint8_t channel1[4]; 625}; 626typedef __builtin_msr_t msr_t; 627static msr_t rdmsr(unsigned long index) 628{ 629 return __builtin_rdmsr(index); 630} 631static void wrmsr(unsigned long index, msr_t msr) 632{ 633 __builtin_wrmsr(index, msr.lo, msr.hi); 634} 635struct tsc_struct { 636 unsigned lo; 637 unsigned hi; 638}; 639typedef struct tsc_struct tsc_t; 640static tsc_t rdtsc(void) 641{ 642 tsc_t res; 643 asm ("rdtsc" 644 : "=a" (res.lo), "=d"(res.hi) 645 : 646 : 647 ); 648 return res; 649} 650void init_timer(void) 651{ 652 653 apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0)); 654 655 apic_write(0x3E0 , 0xB ); 656 657 apic_write(0x380 , 0xffffffff); 658} 659void udelay(unsigned usecs) 660{ 661 uint32_t start, value, ticks; 662 663 ticks = usecs * 200; 664 start = apic_read(0x390 ); 665 do { 666 value = apic_read(0x390 ); 667 } while((start - value) < ticks); 668 669} 670void mdelay(unsigned msecs) 671{ 672 unsigned i; 673 for(i = 0; i < msecs; i++) { 674 udelay(1000); 675 } 676} 677void delay(unsigned secs) 678{ 679 unsigned i; 680 for(i = 0; i < secs; i++) { 681 mdelay(1000); 682 } 683} 684int boot_cpu(void) 685{ 686 volatile unsigned long *local_apic; 687 unsigned long apic_id; 688 int bsp; 689 msr_t msr; 690 msr = rdmsr(0x1b); 691 bsp = !!(msr.lo & (1 << 8)); 692 return bsp; 693} 694static int cpu_init_detected(void) 695{ 696 unsigned long htic; 697 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); 698 return !!(htic & (1<<6) ); 699} 700static int bios_reset_detected(void) 701{ 702 unsigned long htic; 703 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); 704 return (htic & (1<<4) ) && !(htic & (1<<5) ); 705} 706static int cold_reset_detected(void) 707{ 708 unsigned long htic; 709 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); 710 return !(htic & (1<<4) ); 711} 712static void distinguish_cpu_resets(unsigned node_id) 713{ 714 uint32_t htic; 715 device_t device; 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); 720} 721static void set_bios_reset(void) 722{ 723 unsigned long htic; 724 htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c ); 725 htic &= ~(1<<5) ; 726 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c , htic); 727} 728static void print_debug_pci_dev(unsigned dev) 729{ 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); 736} 737static void print_pci_devices(void) 738{ 739 device_t dev; 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)) ) { 743 uint32_t id; 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)) { 748 continue; 749 } 750 print_debug_pci_dev(dev); 751 print_debug("\r\n"); 752 } 753} 754static void dump_pci_device(unsigned dev) 755{ 756 int i; 757 print_debug_pci_dev(dev); 758 print_debug("\r\n"); 759 760 for(i = 0; i <= 255; i++) { 761 unsigned char val; 762 if ((i & 0x0f) == 0) { 763 print_debug_hex8(i); 764 print_debug_char(':'); 765 } 766 val = pci_read_config8(dev, i); 767 print_debug_char(' '); 768 print_debug_hex8(val); 769 if ((i & 0x0f) == 0x0f) { 770 print_debug("\r\n"); 771 } 772 } 773} 774static void dump_pci_devices(void) 775{ 776 device_t dev; 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)) ) { 780 uint32_t id; 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)) { 785 continue; 786 } 787 dump_pci_device(dev); 788 } 789} 790static void dump_spd_registers(const struct mem_controller *ctrl) 791{ 792 int i; 793 print_debug("\r\n"); 794 for(i = 0; i < 4; i++) { 795 unsigned device; 796 device = ctrl->channel0[i]; 797 if (device) { 798 int j; 799 print_debug("dimm: "); 800 print_debug_hex8(i); 801 print_debug(".0: "); 802 print_debug_hex8(device); 803 for(j = 0; j < 256; j++) { 804 int status; 805 unsigned char byte; 806 if ((j & 0xf) == 0) { 807 print_debug("\r\n"); 808 print_debug_hex8(j); 809 print_debug(": "); 810 } 811 status = smbus_read_byte(device, j); 812 if (status < 0) { 813 print_debug("bad device\r\n"); 814 break; 815 } 816 byte = status & 0xff; 817 print_debug_hex8(byte); 818 print_debug_char(' '); 819 } 820 print_debug("\r\n"); 821 } 822 device = ctrl->channel1[i]; 823 if (device) { 824 int j; 825 print_debug("dimm: "); 826 print_debug_hex8(i); 827 print_debug(".1: "); 828 print_debug_hex8(device); 829 for(j = 0; j < 256; j++) { 830 int status; 831 unsigned char byte; 832 if ((j & 0xf) == 0) { 833 print_debug("\r\n"); 834 print_debug_hex8(j); 835 print_debug(": "); 836 } 837 status = smbus_read_byte(device, j); 838 if (status < 0) { 839 print_debug("bad device\r\n"); 840 break; 841 } 842 byte = status & 0xff; 843 print_debug_hex8(byte); 844 print_debug_char(' '); 845 } 846 print_debug("\r\n"); 847 } 848 } 849} 850 851static unsigned int cpuid(unsigned int op) 852{ 853 unsigned int ret; 854 unsigned dummy2,dummy3,dummy4; 855 asm volatile ( 856 "cpuid" 857 : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4) 858 : "a" (op) 859 ); 860 return ret; 861} 862static int is_cpu_rev_a0(void) 863{ 864 return (cpuid(1) & 0xffff) == 0x0f10; 865} 866static int is_cpu_pre_c0(void) 867{ 868 return (cpuid(1) & 0xffef) < 0x0f48; 869} 870static void memreset_setup(void) 871{ 872 if (is_cpu_pre_c0()) { 873 874 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 28); 875 876 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00 + 0xc0 + 29); 877 } 878 else { 879 880 outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 29); 881 } 882} 883static void memreset(int controllers, const struct mem_controller *ctrl) 884{ 885 if (is_cpu_pre_c0()) { 886 udelay(800); 887 888 outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00 + 0xc0 + 28); 889 udelay(90); 890 } 891} 892static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes) 893{ 894 895 uint32_t ret=0x00010101; 896 static const unsigned int rows_2p[2][2] = { 897 { 0x00050101, 0x00010404 }, 898 { 0x00010404, 0x00050101 } 899 }; 900 if(maxnodes>2) { 901 print_debug("this mainboard is only designed for 2 cpus\r\n"); 902 maxnodes=2; 903 } 904 if (!(node>=maxnodes || row>=maxnodes)) { 905 ret=rows_2p[node][row]; 906 } 907 return ret; 908} 909static inline int spd_read_byte(unsigned device, unsigned address) 910{ 911 return smbus_read_byte(device, address); 912} 913 914static void coherent_ht_mainboard(unsigned cpus) 915{ 916} 917 918void cpu_ldtstop(unsigned cpus) 919{ 920 uint32_t tmp; 921 device_t dev; 922 unsigned cnt; 923 for(cnt=0; cnt<cpus; cnt++) { 924 925 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0x81,0x23); 926 927 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd4,0x00000701); 928 929 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) ,0xd8,0x00000000); 930 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) ); 933 } 934} 935 936 937 938 939 940static void setup_resource_map(const unsigned int *register_values, int max) 941{ 942 int i; 943 print_debug("setting up resource map....\r\n"); 944 for(i = 0; i < max; i += 3) { 945 device_t dev; 946 unsigned where; 947 unsigned long reg; 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); 954 } 955 print_debug("done.\r\n"); 956} 957static void setup_default_resource_map(void) 958{ 959 static const unsigned int register_values[] = { 960 961 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, 970 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, 979 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, 988 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, 997 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, 1002 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, 1007 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, 1012 }; 1013 int max; 1014 max = sizeof(register_values)/sizeof(register_values[0]); 1015 setup_resource_map(register_values, max); 1016} 1017static void sdram_set_registers(const struct mem_controller *ctrl) 1018{ 1019 static const unsigned int register_values[] = { 1020 1021 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, 1030 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, 1039 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, 1048 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, 1057 1058 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x80 ) & 0xFF)) , 0xffff8888, 0x00000000, 1059 1060 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x88 ) & 0xFF)) , 0xe8088008, 0x02522001 , 1061 1062 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0), 1063 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), 1071 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), 1075 1076 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 2 ) & 0x07) << 8) | (( 0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000, 1077 1078 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000, 1079 1080 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x5C ) & 0xFF)) , 0x0000003e, 0x00000000, 1081 1082 ( ((( 0 ) & 0xFF) << 16) | ((( 0x18 ) & 0x1f) << 11) | ((( 3 ) & 0x07) << 8) | (( 0x60 ) & 0xFF)) , 0xffffff00, 0x00000000, 1083 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, 1087 }; 1088 int i; 1089 int max; 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) { 1095 device_t dev; 1096 unsigned where; 1097 unsigned long reg; 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); 1104 } 1105 print_debug("done.\r\n"); 1106} 1107static int is_dual_channel(const struct mem_controller *ctrl) 1108{ 1109 uint32_t dcl; 1110 dcl = pci_read_config32(ctrl->f2, 0x90 ); 1111 return dcl & (1<<16) ; 1112} 1113static int is_opteron(const struct mem_controller *ctrl) 1114{ 1115 1116 uint32_t nbcap; 1117 nbcap = pci_read_config32(ctrl->f3, 0xE8 ); 1118 return !!(nbcap & 0x0001 ); 1119} 1120static int is_registered(const struct mem_controller *ctrl) 1121{ 1122 1123 uint32_t dcl; 1124 dcl = pci_read_config32(ctrl->f2, 0x90 ); 1125 return !(dcl & (1<<18) ); 1126} 1127struct dimm_size { 1128 unsigned long side1; 1129 unsigned long side2; 1130}; 1131static struct dimm_size spd_get_dimm_size(unsigned device) 1132{ 1133 1134 struct dimm_size sz; 1135 int value, low; 1136 sz.side1 = 0; 1137 sz.side2 = 0; 1138 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); 1148 1149 value = spd_read_byte(device, 7); 1150 if (value < 0) goto out; 1151 value &= 0xff; 1152 value <<= 8; 1153 1154 low = spd_read_byte(device, 6); 1155 if (low < 0) goto out; 1156 value = value | (low & 0xff); 1157 sz.side1 += log2(value); 1158 1159 value = spd_read_byte(device, 5); 1160 if (value <= 1) goto out; 1161 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); 1172 out: 1173 return sz; 1174} 1175static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index) 1176{ 1177 uint32_t base0, base1, map; 1178 uint32_t dch; 1179 if (sz.side1 != sz.side2) { 1180 sz.side2 = 0; 1181 } 1182 map = pci_read_config32(ctrl->f2, 0x80 ); 1183 map &= ~(0xf << (index + 4)); 1184 1185 1186 base0 = base1 = 0; 1187 1188 if (sz.side1 >= (25 +3)) { 1189 map |= (sz.side1 - (25 + 3)) << (index *4); 1190 base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1; 1191 } 1192 1193 if (sz.side2 >= (25 + 3)) { 1194 base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1; 1195 } 1196 1197 if (is_dual_channel(ctrl)) { 1198 base0 = (base0 << 1) | (base0 & 1); 1199 base1 = (base1 << 1) | (base1 & 1); 1200 } 1201 1202 base0 &= ~0x001ffffe; 1203 base1 &= ~0x001ffffe; 1204 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); 1208 1209 1210 if (base0) { 1211 dch = pci_read_config32(ctrl->f2, 0x94 ); 1212 dch |= (1 << 26) << index; 1213 pci_write_config32(ctrl->f2, 0x94 , dch); 1214 } 1215} 1216static void spd_set_ram_size(const struct mem_controller *ctrl) 1217{ 1218 int i; 1219 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); 1224 } 1225} 1226static void route_dram_accesses(const struct mem_controller *ctrl, 1227 unsigned long base_k, unsigned long limit_k) 1228{ 1229 1230 unsigned node_id; 1231 unsigned limit; 1232 unsigned base; 1233 unsigned index; 1234 unsigned limit_reg, base_reg; 1235 device_t device; 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); 1243 base &= 0xffff0000; 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); 1250 } 1251} 1252static void set_top_mem(unsigned tom_k) 1253{ 1254 1255 if (!tom_k) { 1256 set_bios_reset(); 1257 print_debug("No memory - reset"); 1258 1259 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0x04 ) & 0x1f) << 11) | ((( 3 ) & 0x7) << 8)) , 0x41, 0xf1); 1260 1261 outb(0x0e, 0x0cf9); 1262 } 1263 1264 print_debug("RAM: 0x"); 1265 print_debug_hex32(tom_k); 1266 print_debug(" KB\r\n"); 1267 1268 msr_t msr; 1269 msr.lo = (tom_k & 0x003fffff) << 10; 1270 msr.hi = (tom_k & 0xffc00000) >> 22; 1271 wrmsr(0xC001001D , msr); 1272 1273 if (tom_k >= 0x003f0000) { 1274 tom_k = 0x3f0000; 1275 } 1276 msr.lo = (tom_k & 0x003fffff) << 10; 1277 msr.hi = (tom_k & 0xffc00000) >> 22; 1278 wrmsr(0xC001001A , msr); 1279} 1280static unsigned long interleave_chip_selects(const struct mem_controller *ctrl) 1281{ 1282 1283 static const uint32_t csbase_low[] = { 1284 (1 << (13 - 4)), 1285 (1 << (14 - 4)), 1286 (1 << (14 - 4)), 1287 (1 << (15 - 4)), 1288 (1 << (15 - 4)), 1289 (1 << (16 - 4)), 1290 (1 << (16 - 4)), 1291 }; 1292 uint32_t csbase_inc; 1293 int chip_selects, index; 1294 int bits; 1295 int dual_channel; 1296 unsigned common_size; 1297 uint32_t csbase, csmask; 1298 1299 chip_selects = 0; 1300 common_size = 0; 1301 for(index = 0; index < 8; index++) { 1302 unsigned size; 1303 uint32_t value; 1304 1305 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2)); 1306 1307 1308 if (!(value & 1)) { 1309 continue; 1310 } 1311 chip_selects++; 1312 size = value >> 21; 1313 if (common_size == 0) { 1314 common_size = size; 1315 } 1316 1317 if (common_size != size) { 1318 return 0; 1319 } 1320 } 1321 1322 bits = log2(chip_selects); 1323 if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) { 1324 return 0; 1325 1326 } 1327 1328 if ((bits == 3) && (common_size == (1 << (32 - 3)))) { 1329 print_debug("8 4GB chip selects cannot be interleaved\r\n"); 1330 return 0; 1331 } 1332 1333 if (is_dual_channel(ctrl)) { 1334 csbase_inc = csbase_low[log2(common_size) - 1] << 1; 1335 } else { 1336 csbase_inc = csbase_low[log2(common_size)]; 1337 } 1338 1339 csbase = 0 | 1; 1340 csmask = (((common_size << bits) - 1) << 21); 1341 csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc); 1342 for(index = 0; index < 8; index++) { 1343 uint32_t value; 1344 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2)); 1345 1346 if (!(value & 1)) { 1347 continue; 1348 } 1349 pci_write_config32(ctrl->f2, 0x40 + (index << 2), csbase); 1350 pci_write_config32(ctrl->f2, 0x60 + (index << 2), csmask); 1351 csbase += csbase_inc; 1352 } 1353 1354 print_debug("Interleaved\r\n"); 1355 1356 return common_size << (15 + bits); 1357} 1358static unsigned long order_chip_selects(const struct mem_controller *ctrl) 1359{ 1360 unsigned long tom; 1361 1362 1363 tom = 0; 1364 for(;;) { 1365 1366 unsigned index, canidate; 1367 uint32_t csbase, csmask; 1368 unsigned size; 1369 csbase = 0; 1370 canidate = 0; 1371 for(index = 0; index < 8; index++) { 1372 uint32_t value; 1373 value = pci_read_config32(ctrl->f2, 0x40 + (index << 2)); 1374 1375 if (!(value & 1)) { 1376 continue; 1377 } 1378 1379 1380 if (value <= csbase) { 1381 continue; 1382 } 1383 1384 1385 if (tom & (1 << (index + 24))) { 1386 continue; 1387 } 1388 1389 csbase = value; 1390 canidate = index; 1391 } 1392 1393 if (csbase == 0) { 1394 break; 1395 } 1396 1397 size = csbase >> 21; 1398 1399 tom |= (1 << (canidate + 24)); 1400 1401 csbase = (tom << 21) | 1; 1402 1403 tom += size; 1404 1405 csmask = ((size -1) << 21); 1406 csmask |= 0xfe00; 1407 1408 pci_write_config32(ctrl->f2, 0x40 + (canidate << 2), csbase); 1409 1410 pci_write_config32(ctrl->f2, 0x60 + (canidate << 2), csmask); 1411 1412 } 1413 1414 return (tom & ~0xff000000) << 15; 1415} 1416static void order_dimms(const struct mem_controller *ctrl) 1417{ 1418 unsigned long tom, tom_k, base_k; 1419 unsigned node_id; 1420 tom_k = interleave_chip_selects(ctrl); 1421 if (!tom_k) { 1422 tom_k = order_chip_selects(ctrl); 1423 } 1424 1425 base_k = 0; 1426 for(node_id = 0; node_id < ctrl->node_id; node_id++) { 1427 uint32_t limit, base; 1428 unsigned index; 1429 index = node_id << 3; 1430 base = pci_read_config32(ctrl->f1, 0x40 + index); 1431 1432 if ((base & 3) == 3) { 1433 limit = pci_read_config32(ctrl->f1, 0x44 + index); 1434 base_k = ((limit + 0x00010000) & 0xffff0000) >> 2; 1435 } 1436 } 1437 tom_k += base_k; 1438 route_dram_accesses(ctrl, base_k, tom_k); 1439 set_top_mem(tom_k); 1440} 1441static void disable_dimm(const struct mem_controller *ctrl, unsigned index) 1442{ 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); 1448} 1449static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl) 1450{ 1451 int i; 1452 int registered; 1453 int unbuffered; 1454 uint32_t dcl; 1455 unbuffered = 0; 1456 registered = 0; 1457 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { 1458 int value; 1459 value = spd_read_byte(ctrl->channel0[i], 21); 1460 if (value < 0) { 1461 disable_dimm(ctrl, i); 1462 continue; 1463 } 1464 1465 if (value & (1 << 1)) { 1466 registered = 1; 1467 } 1468 1469 else { 1470 unbuffered = 1; 1471 } 1472 } 1473 if (unbuffered && registered) { 1474 die("Mixed buffered and registered dimms not supported"); 1475 } 1476 if (unbuffered && is_opteron(ctrl)) { 1477 die("Unbuffered Dimms not supported on Opteron"); 1478 } 1479 dcl = pci_read_config32(ctrl->f2, 0x90 ); 1480 dcl &= ~(1<<18) ; 1481 if (unbuffered) { 1482 dcl |= (1<<18) ; 1483 } 1484 pci_write_config32(ctrl->f2, 0x90 , dcl); 1485} 1486static void spd_enable_2channels(const struct mem_controller *ctrl) 1487{ 1488 int i; 1489 uint32_t nbcap; 1490 1491 1492 static const unsigned addresses[] = { 1493 2, 1494 3, 1495 4, 1496 5, 1497 6, 1498 7, 1499 9, 1500 11, 1501 13, 1502 17, 1503 18, 1504 21, 1505 23, 1506 26, 1507 27, 1508 28, 1509 29, 1510 30, 1511 41, 1512 42, 1513 }; 1514 nbcap = pci_read_config32(ctrl->f3, 0xE8 ); 1515 if (!(nbcap & 0x0001 )) { 1516 return; 1517 } 1518 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { 1519 unsigned device0, device1; 1520 int value0, value1; 1521 int j; 1522 device0 = ctrl->channel0[i]; 1523 device1 = ctrl->channel1[i]; 1524 if (!device1) 1525 return; 1526 for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) { 1527 unsigned addr; 1528 addr = addresses[j]; 1529 value0 = spd_read_byte(device0, addr); 1530 if (value0 < 0) { 1531 break; 1532 } 1533 value1 = spd_read_byte(device1, addr); 1534 if (value1 < 0) { 1535 return; 1536 } 1537 if (value0 != value1) { 1538 return; 1539 } 1540 } 1541 } 1542 print_debug("Enabling dual channel memory\r\n"); 1543 uint32_t dcl; 1544 dcl = pci_read_config32(ctrl->f2, 0x90 ); 1545 dcl &= ~(1<<19) ; 1546 dcl |= (1<<16) ; 1547 pci_write_config32(ctrl->f2, 0x90 , dcl); 1548} 1549struct mem_param { 1550 uint8_t cycle_time; 1551 uint8_t divisor; 1552 uint8_t tRC; 1553 uint8_t tRFC; 1554 uint32_t dch_memclk; 1555 uint16_t dch_tref4k, dch_tref8k; 1556 uint8_t dtl_twr; 1557 char name[9]; 1558}; 1559static const struct mem_param *get_mem_param(unsigned min_cycle_time) 1560{ 1561 static const struct mem_param speed[] = { 1562 { 1563 .name = "100Mhz\r\n", 1564 .cycle_time = 0xa0, 1565 .divisor = (10 <<1), 1566 .tRC = 0x46, 1567 .tRFC = 0x50, 1568 .dch_memclk = 0 << 20 , 1569 .dch_tref4k = 0x00 , 1570 .dch_tref8k = 0x08 , 1571 .dtl_twr = 2, 1572 }, 1573 { 1574 .name = "133Mhz\r\n", 1575 .cycle_time = 0x75, 1576 .divisor = (7<<1)+1, 1577 .tRC = 0x41, 1578 .tRFC = 0x4B, 1579 .dch_memclk = 2 << 20 , 1580 .dch_tref4k = 0x01 , 1581 .dch_tref8k = 0x09 , 1582 .dtl_twr = 2, 1583 }, 1584 { 1585 .name = "166Mhz\r\n", 1586 .cycle_time = 0x60, 1587 .divisor = (6<<1), 1588 .tRC = 0x3C, 1589 .tRFC = 0x48, 1590 .dch_memclk = 5 << 20 , 1591 .dch_tref4k = 0x02 , 1592 .dch_tref8k = 0x0A , 1593 .dtl_twr = 3, 1594 }, 1595 { 1596 .name = "200Mhz\r\n", 1597 .cycle_time = 0x50, 1598 .divisor = (5<<1), 1599 .tRC = 0x37, 1600 .tRFC = 0x46, 1601 .dch_memclk = 7 << 20 , 1602 .dch_tref4k = 0x03 , 1603 .dch_tref8k = 0x0B , 1604 .dtl_twr = 3, 1605 }, 1606 { 1607 .cycle_time = 0x00, 1608 }, 1609 }; 1610 const struct mem_param *param; 1611 for(param = &speed[0]; param->cycle_time ; param++) { 1612 if (min_cycle_time > (param+1)->cycle_time) { 1613 break; 1614 } 1615 } 1616 if (!param->cycle_time) { 1617 die("min_cycle_time to low"); 1618 } 1619 print_debug(param->name); 1620 return param; 1621} 1622static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) 1623{ 1624 1625 const struct mem_param *param; 1626 unsigned min_cycle_time, min_latency; 1627 int i; 1628 uint32_t value; 1629 static const int latency_indicies[] = { 26, 23, 9 }; 1630 static const unsigned char min_cycle_times[] = { 1631 [0 ] = 0x50, 1632 [1 ] = 0x60, 1633 [2 ] = 0x75, 1634 [3 ] = 0xa0, 1635 }; 1636 value = pci_read_config32(ctrl->f3, 0xE8 ); 1637 min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ]; 1638 min_latency = 2; 1639 1640 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { 1641 int new_cycle_time, new_latency; 1642 int index; 1643 int latencies; 1644 int latency; 1645 1646 new_cycle_time = 0xa0; 1647 new_latency = 5; 1648 latencies = spd_read_byte(ctrl->channel0[i], 18); 1649 if (latencies <= 0) continue; 1650 1651 latency = log2(latencies) -2; 1652 1653 for(index = 0; index < 3; index++, latency++) { 1654 int value; 1655 if ((latency < 2) || (latency > 4) || 1656 (!(latencies & (1 << latency)))) { 1657 continue; 1658 } 1659 value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); 1660 if (value < 0) { 1661 continue; 1662 } 1663 1664 if ((value >= min_cycle_time) && (value < new_cycle_time)) { 1665 new_cycle_time = value; 1666 new_latency = latency; 1667 } 1668 } 1669 if (new_latency > 4){ 1670 continue; 1671 } 1672 1673 if (new_cycle_time > min_cycle_time) { 1674 min_cycle_time = new_cycle_time; 1675 } 1676 1677 if (new_latency > min_latency) { 1678 min_latency = new_latency; 1679 } 1680 } 1681 1682 1683 for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { 1684 int latencies; 1685 int latency; 1686 int index; 1687 int value; 1688 int dimm; 1689 latencies = spd_read_byte(ctrl->channel0[i], 18); 1690 if (latencies <= 0) { 1691 goto dimm_err; 1692 } 1693 1694 latency = log2(latencies) -2; 1695 1696 for(index = 0; index < 3; index++, latency++) { 1697 if (!(latencies & (1 << latency))) { 1698 continue; 1699 } 1700 if (latency == min_latency) 1701 break; 1702 } 1703 1704 if ((latency != min_latency) || (index >= 3)) { 1705 goto dimm_err; 1706 } 1707 1708 1709 value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); 1710 1711 1712 if (value <= min_cycle_time) { 1713 continue; 1714 } 1715 1716 dimm_err: 1717 disable_dimm(ctrl, i); 1718 } 1719 1720 param = get_mem_param(min_cycle_time); 1721 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 }; 1727 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); 1732 1733 return param; 1734} 1735static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1736{ 1737 unsigned clocks, old_clocks; 1738 uint32_t dtl; 1739 int value; 1740 value = spd_read_byte(ctrl->channel0[i], 41); 1741 if (value < 0) return -1; 1742 if ((value == 0) || (value == 0xff)) { 1743 value = param->tRC; 1744 } 1745 clocks = ((value << 1) + param->divisor - 1)/param->divisor; 1746 if (clocks < 7 ) { 1747 clocks = 7 ; 1748 } 1749 if (clocks > 22 ) { 1750 return -1; 1751 } 1752 dtl = pci_read_config32(ctrl->f2, 0x88 ); 1753 old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ; 1754 if (old_clocks > clocks) { 1755 clocks = old_clocks; 1756 } 1757 dtl &= ~(0xf << 4 ); 1758 dtl |= ((clocks - 7 ) << 4 ); 1759 pci_write_config32(ctrl->f2, 0x88 , dtl); 1760 return 0; 1761} 1762static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1763{ 1764 unsigned clocks, old_clocks; 1765 uint32_t dtl; 1766 int value; 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; 1771 } 1772 clocks = ((value << 1) + param->divisor - 1)/param->divisor; 1773 if (clocks < 9 ) { 1774 clocks = 9 ; 1775 } 1776 if (clocks > 24 ) { 1777 return -1; 1778 } 1779 dtl = pci_read_config32(ctrl->f2, 0x88 ); 1780 old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ; 1781 if (old_clocks > clocks) { 1782 clocks = old_clocks; 1783 } 1784 dtl &= ~(0xf << 8 ); 1785 dtl |= ((clocks - 9 ) << 8 ); 1786 pci_write_config32(ctrl->f2, 0x88 , dtl); 1787 return 0; 1788} 1789static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1790{ 1791 unsigned clocks, old_clocks; 1792 uint32_t dtl; 1793 int value; 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); 1797 if (clocks < 2 ) { 1798 clocks = 2 ; 1799 } 1800 if (clocks > 6 ) { 1801 return -1; 1802 } 1803 dtl = pci_read_config32(ctrl->f2, 0x88 ); 1804 old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ; 1805 if (old_clocks > clocks) { 1806 clocks = old_clocks; 1807 } 1808 dtl &= ~(0x7 << 12 ); 1809 dtl |= ((clocks - 0 ) << 12 ); 1810 pci_write_config32(ctrl->f2, 0x88 , dtl); 1811 return 0; 1812} 1813static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1814{ 1815 unsigned clocks, old_clocks; 1816 uint32_t dtl; 1817 int value; 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); 1821 if (clocks < 2 ) { 1822 clocks = 2 ; 1823 } 1824 if (clocks > 4 ) { 1825 return -1; 1826 } 1827 dtl = pci_read_config32(ctrl->f2, 0x88 ); 1828 old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ; 1829 if (old_clocks > clocks) { 1830 clocks = old_clocks; 1831 } 1832 dtl &= ~(0x7 << 16 ); 1833 dtl |= ((clocks - 0 ) << 16 ); 1834 pci_write_config32(ctrl->f2, 0x88 , dtl); 1835 return 0; 1836} 1837static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1838{ 1839 unsigned clocks, old_clocks; 1840 uint32_t dtl; 1841 int value; 1842 value = spd_read_byte(ctrl->channel0[i], 30); 1843 if (value < 0) return -1; 1844 clocks = ((value << 1) + param->divisor - 1)/param->divisor; 1845 if (clocks < 5 ) { 1846 clocks = 5 ; 1847 } 1848 if (clocks > 15 ) { 1849 return -1; 1850 } 1851 dtl = pci_read_config32(ctrl->f2, 0x88 ); 1852 old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ; 1853 if (old_clocks > clocks) { 1854 clocks = old_clocks; 1855 } 1856 dtl &= ~(0xf << 20 ); 1857 dtl |= ((clocks - 0 ) << 20 ); 1858 pci_write_config32(ctrl->f2, 0x88 , dtl); 1859 return 0; 1860} 1861static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1862{ 1863 unsigned clocks, old_clocks; 1864 uint32_t dtl; 1865 int value; 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); 1869 if (clocks < 2 ) { 1870 clocks = 2 ; 1871 } 1872 if (clocks > 6 ) { 1873 return -1; 1874 } 1875 dtl = pci_read_config32(ctrl->f2, 0x88 ); 1876 old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ; 1877 if (old_clocks > clocks) { 1878 clocks = old_clocks; 1879 } 1880 dtl &= ~(0x7 << 24 ); 1881 dtl |= ((clocks - 0 ) << 24 ); 1882 pci_write_config32(ctrl->f2, 0x88 , dtl); 1883 return 0; 1884} 1885static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param) 1886{ 1887 uint32_t dtl; 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); 1892} 1893static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param) 1894{ 1895 uint32_t dth; 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); 1900} 1901static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1902{ 1903 uint32_t dth; 1904 int value; 1905 unsigned tref, old_tref; 1906 value = spd_read_byte(ctrl->channel0[i], 3); 1907 if (value < 0) return -1; 1908 value &= 0xf; 1909 tref = param->dch_tref8k; 1910 if (value == 12) { 1911 tref = param->dch_tref4k; 1912 } 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; 1917 } else { 1918 tref = param->dch_tref8k; 1919 } 1920 dth &= ~(0x1f << 8 ); 1921 dth |= (tref << 8 ); 1922 pci_write_config32(ctrl->f2, 0x8c , dth); 1923 return 0; 1924} 1925static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1926{ 1927 uint32_t dcl; 1928 int value; 1929 int dimm; 1930 value = spd_read_byte(ctrl->channel0[i], 13); 1931 if (value < 0) { 1932 return -1; 1933 } 1934 dimm = i; 1935 dimm += 20 ; 1936 dcl = pci_read_config32(ctrl->f2, 0x90 ); 1937 dcl &= ~(1 << dimm); 1938 if (value == 4) { 1939 dcl |= (1 << dimm); 1940 } 1941 pci_write_config32(ctrl->f2, 0x90 , dcl); 1942 return 0; 1943} 1944static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i) 1945{ 1946 uint32_t dcl; 1947 int value; 1948 value = spd_read_byte(ctrl->channel0[i], 11); 1949 if (value < 0) { 1950 return -1; 1951 } 1952 if (value != 2) { 1953 dcl = pci_read_config32(ctrl->f2, 0x90 ); 1954 dcl &= ~(1<<17) ; 1955 pci_write_config32(ctrl->f2, 0x90 , dcl); 1956 } 1957 return 0; 1958} 1959static int count_dimms(const struct mem_controller *ctrl) 1960{ 1961 int dimms; 1962 unsigned index; 1963 dimms = 0; 1964 for(index = 0; index < 8; index += 2) { 1965 uint32_t csbase; 1966 csbase = pci_read_config32(ctrl->f2, (0x40 + index << 2)); 1967 if (csbase & 1) { 1968 dimms += 1; 1969 } 1970 } 1971 return dimms; 1972} 1973static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param) 1974{ 1975 uint32_t dth; 1976 unsigned clocks; 1977 clocks = 1; 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); 1982} 1983static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param) 1984{ 1985 uint32_t dth, dtl; 1986 unsigned divisor; 1987 unsigned latency; 1988 unsigned clocks; 1989 clocks = 0; 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)) { 1996 1997 clocks = 3; 1998 } 1999 else if (divisor > ((6 << 0)+0)) { 2000
2001 clocks = 2; 2002 } 2003 } 2004 else if (latency == 5 ) { 2005 clocks = 3; 2006 } 2007 else if (latency == 2 ) { 2008 if (divisor == ((6 << 0)+0)) { 2009 2010 clocks = 4; 2011 } 2012 else if (divisor > ((6 << 0)+0)) { 2013 2014 clocks = 3; 2015 } 2016 } 2017 } 2018 else { 2019 if (is_registered(ctrl)) { 2020 if (latency == 1 ) { 2021 clocks = 2; 2022 } 2023 else if (latency == 5 ) { 2024 clocks = 3; 2025 } 2026 else if (latency == 2 ) { 2027 clocks = 3; 2028 } 2029 } 2030 else { 2031 if (latency == 1 ) { 2032 clocks = 3; 2033 } 2034 else if (latency == 5 ) { 2035 clocks = 4; 2036 } 2037 else if (latency == 2 ) { 2038 clocks = 4; 2039 } 2040 } 2041 } 2042 if ((clocks < 1 ) || (clocks > 6 )) { 2043 die("Unknown Trwt"); 2044 } 2045 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); 2050 return; 2051} 2052static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param) 2053{ 2054 2055 uint32_t dth; 2056 unsigned clocks; 2057 if (is_registered(ctrl)) { 2058 clocks = 2; 2059 } else { 2060 clocks = 1; 2061 } 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); 2066} 2067static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param) 2068{ 2069 uint32_t dch; 2070 unsigned divisor; 2071 unsigned rdpreamble; 2072 divisor = param->divisor; 2073 dch = pci_read_config32(ctrl->f2, 0x94 ); 2074 dch &= ~(0xf << 8 ); 2075 rdpreamble = 0; 2076 if (is_registered(ctrl)) { 2077 if (divisor == ((10 << 1)+0)) { 2078 2079 rdpreamble = ((9 << 1)+ 0); 2080 } 2081 else if (divisor == ((7 << 1)+1)) { 2082 2083 rdpreamble = ((8 << 1)+0); 2084 } 2085 else if (divisor == ((6 << 1)+0)) { 2086 2087 rdpreamble = ((7 << 1)+1); 2088 } 2089 else if (divisor == ((5 << 1)+0)) { 2090 2091 rdpreamble = ((7 << 1)+0); 2092 } 2093 } 2094 else { 2095 int slots; 2096 int i; 2097 slots = 0; 2098 for(i = 0; i < 4; i++) { 2099 if (ctrl->channel0[i]) { 2100 slots += 1; 2101 } 2102 } 2103 if (divisor == ((10 << 1)+0)) { 2104 2105 if (slots <= 2) { 2106 2107 rdpreamble = ((9 << 1)+0); 2108 } else { 2109 2110 rdpreamble = ((14 << 1)+0); 2111 } 2112 } 2113 else if (divisor == ((7 << 1)+1)) { 2114 2115 if (slots <= 2) { 2116 2117 rdpreamble = ((7 << 1)+0); 2118 } else { 2119 2120 rdpreamble = ((11 << 1)+0); 2121 } 2122 } 2123 else if (divisor == ((6 << 1)+0)) { 2124 2125 if (slots <= 2) { 2126 2127 rdpreamble = ((7 << 1)+0); 2128 } else { 2129 2130 rdpreamble = ((9 << 1)+0); 2131 } 2132 } 2133 else if (divisor == ((5 << 1)+0)) { 2134 2135 if (slots <= 2) { 2136 2137 rdpreamble = ((5 << 1)+0); 2138 } else { 2139 2140 rdpreamble = ((7 << 1)+0); 2141 } 2142 } 2143 } 2144 if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) { 2145 die("Unknown rdpreamble"); 2146 } 2147 dch |= (rdpreamble - ((2<<1)+0) ) << 8 ; 2148 pci_write_config32(ctrl->f2, 0x94 , dch); 2149} 2150static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param) 2151{ 2152 uint32_t dch; 2153 int i; 2154 unsigned async_lat; 2155 int dimms; 2156 dimms = count_dimms(ctrl); 2157 dch = pci_read_config32(ctrl->f2, 0x94 ); 2158 dch &= ~(0xf << 0 ); 2159 async_lat = 0; 2160 if (is_registered(ctrl)) { 2161 if (dimms == 4) { 2162 2163 async_lat = 9; 2164 } 2165 else { 2166 2167 async_lat = 8; 2168 } 2169 } 2170 else { 2171 if (dimms > 3) { 2172 die("Too many unbuffered dimms"); 2173 } 2174 else if (dimms == 3) { 2175 2176 async_lat = 7; 2177 } 2178 else { 2179 2180 async_lat = 6; 2181 } 2182 } 2183 dch |= ((async_lat - 0 ) << 0 ); 2184 pci_write_config32(ctrl->f2, 0x94 , dch); 2185} 2186static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param) 2187{ 2188 uint32_t dch; 2189 2190 dch = pci_read_config32(ctrl->f2, 0x94 ); 2191 dch &= ~(0x7 << 16 ); 2192 dch |= 3 << 16 ; 2193 dch |= (1 << 19) ; 2194 pci_write_config32(ctrl->f2, 0x94 , dch); 2195} 2196static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param) 2197{ 2198 int dimms; 2199 int i; 2200 int rc; 2201 2202 init_Tref(ctrl, param); 2203 for(i = 0; (i < 4) && ctrl->channel0[i]; i++) { 2204 int rc; 2205 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; 2212 2213 if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err; 2214 2215 if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err; 2216 if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err; 2217 continue; 2218 dimm_err: 2219 disable_dimm(ctrl, i); 2220 2221 } 2222 2223 set_Twr(ctrl, param); 2224 2225 set_Twtr(ctrl, param); 2226 set_Trwt(ctrl, param); 2227 set_Twcl(ctrl, param); 2228 2229 set_read_preamble(ctrl, param); 2230 set_max_async_latency(ctrl, param); 2231 set_idle_cycle_limit(ctrl, param); 2232} 2233static void sdram_set_spd_registers(const struct mem_controller *ctrl) 2234{ 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); 2241 order_dimms(ctrl); 2242} 2243static void sdram_enable(int controllers, const struct mem_controller *ctrl) 2244{ 2245 int i; 2246 2247 for(i = 0; i < controllers; i++) { 2248 uint32_t dch; 2249 dch = pci_read_config32(ctrl[i].f2, 0x94 ); 2250 dch |= (1 << 25) ; 2251 pci_write_config32(ctrl[i].f2, 0x94 , dch); 2252 } 2253 2254 memreset(controllers, ctrl); 2255 for(i = 0; i < controllers; i++) { 2256 uint32_t dcl; 2257 2258 dcl = pci_read_config32(ctrl[i].f2, 0x90 ); 2259 if (dcl & (1<<17) ) { 2260 uint32_t mnc; 2261 print_debug("ECC enabled\r\n"); 2262 mnc = pci_read_config32(ctrl[i].f3, 0x44 ); 2263 mnc |= (1 << 22) ; 2264 if (dcl & (1<<16) ) { 2265 mnc |= (1 << 23) ; 2266 } 2267 pci_write_config32(ctrl[i].f3, 0x44 , mnc); 2268 } 2269 dcl |= (1<<3) ; 2270 pci_write_config32(ctrl[i].f2, 0x90 , dcl); 2271 dcl &= ~(1<<3) ; 2272 dcl &= ~(1<<0) ; 2273 dcl &= ~(1<<1) ; 2274 dcl &= ~(1<<2) ; 2275 dcl |= (1<<8) ; 2276 pci_write_config32(ctrl[i].f2, 0x90 , dcl); 2277 } 2278 for(i = 0; i < controllers; i++) { 2279 uint32_t dcl; 2280 print_debug("Initializing memory: "); 2281 int loops = 0; 2282 do { 2283 dcl = pci_read_config32(ctrl[i].f2, 0x90 ); 2284 loops += 1; 2285 if ((loops & 1023) == 0) { 2286 print_debug("."); 2287 } 2288 } while(((dcl & (1<<8) ) != 0) && (loops < 300000 )); 2289 if (loops >= 300000 ) { 2290 print_debug(" failed\r\n"); 2291 } else { 2292 print_debug(" done\r\n"); 2293 } 2294 if (dcl & (1<<17) ) { 2295 print_debug("Clearing memory: "); 2296 if (!is_cpu_pre_c0()) { 2297 2298 dcl &= ~((1<<11) | (1<<10) ); 2299 pci_write_config32(ctrl[i].f2, 0x90 , dcl); 2300 do { 2301 dcl = pci_read_config32(ctrl[i].f2, 0x90 ); 2302 } while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) ); 2303 } 2304 uint32_t base, last_scrub_k, scrub_k; 2305 uint32_t cnt,zstart,zend; 2306 msr_t msr,msr_201; 2307 2308 pci_write_config32(ctrl[i].f3, 0x58 , 2309 (0 << 16) | (0 << 8) | (0 << 0)); 2310 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)); 2314 zstart >>= 16; 2315 zend >>=16; 2316 print_debug("addr "); 2317 print_debug_hex32(zstart); 2318 print_debug("-"); 2319 print_debug_hex32(zend); 2320 print_debug("\r\n"); 2321 2322 2323 msr = rdmsr(0x2ff ); 2324 msr.lo &= ~(1<<10); 2325 wrmsr(0x2ff , msr); 2326 2327 msr = rdmsr(0xc0010015); 2328 msr.lo |= (1<<17); 2329 wrmsr(0xc0010015,msr); 2330 for(;zstart<zend;zstart+=4) { 2331 2332 if(zstart == 0x0fc) 2333 continue; 2334 2335 2336 __asm__ volatile( 2337 "movl %%cr0, %0\n\t" 2338 "orl $0x40000000, %0\n\t" 2339 "movl %0, %%cr0\n\t" 2340 :"=r" (cnt) 2341 ); 2342 2343 2344 msr.lo = 1 + ((zstart&0x0ff)<<24); 2345 msr.hi = (zstart&0x0ff00)>>8; 2346 wrmsr(0x200,msr); 2347 2348 msr.hi = 0x000000ff; 2349 msr.lo = 0xfc000800; 2350 wrmsr(0x201,msr); 2351 2352 __asm__ volatile( 2353 "movl %%cr0, %0\n\t" 2354 "andl $0x9fffffff, %0\n\t" 2355 "movl %0, %%cr0\n\t" 2356 :"=r" (cnt) 2357 ); 2358 2359 msr.lo = (zstart&0xff) << 24; 2360 msr.hi = (zstart&0xff00) >> 8; 2361 wrmsr(0xc0000100,msr); 2362 print_debug_char((zstart > 0x0ff)?'+':'-'); 2363 2364 2365 __asm__ volatile( 2366 "1: \n\t" 2367 "movl %0, %%fs:(%1)\n\t" 2368 "addl $4,%1\n\t" 2369 "subl $1,%2\n\t" 2370 "jnz 1b\n\t" 2371 : 2372 : "a" (0), "D" (0), "c" (0x01000000) 2373 ); 2374 } 2375 2376 2377 __asm__ volatile( 2378 "movl %%cr0, %0\n\t" 2379 "orl $0x40000000, %0\n\t" 2380 "movl %0, %%cr0\n\t" 2381 :"=r" (cnt) 2382 ); 2383 2384 2385 msr = rdmsr(0x2ff ); 2386 msr.lo |= 0x0400; 2387 wrmsr(0x2ff , msr); 2388 2389 msr.lo = 6; 2390 msr.hi = 0; 2391 wrmsr(0x200,msr); 2392 wrmsr(0x201,msr_201); 2393 2394 msr.lo = 0; 2395 msr.hi = 0; 2396 wrmsr(0xc0000100,msr); 2397 2398 __asm__ volatile( 2399 "movl %%cr0, %0\n\t" 2400 "andl $0x9fffffff, %0\n\t" 2401 "movl %0, %%cr0\n\t" 2402 :"=r" (cnt) 2403 ); 2404 2405 2406 msr = rdmsr(0xc0010015); 2407 msr.lo &= ~(1<<17); 2408 wrmsr(0xc0010015,msr); 2409 2410 base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3)); 2411 base &= 0xffff0000; 2412 2413 pci_write_config32(ctrl[i].f3, 0x5C , base << 8); 2414 pci_write_config32(ctrl[i].f3, 0x60 , base >> 24); 2415 2416 pci_write_config32(ctrl[i].f3, 0x58 , 2417 (22 << 16) | (22 << 8) | (22 << 0)); 2418 print_debug("done\r\n"); 2419 } 2420 } 2421} 2422 2423 2424 2425 2426 2427typedef uint8_t u8; 2428typedef uint32_t u32; 2429typedef int8_t bool; 2430static void disable_probes(void) 2431{ 2432 2433 2434 u32 val; 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"); 2440} 2441 2442static void wait_ap_stop(u8 node) 2443{ 2444 unsigned long reg; 2445 unsigned long i; 2446 for(i=0;i< 1000 ;i++) { 2447 unsigned long regx; 2448 regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c); 2449 if((regx & (1<<4))==1) break; 2450 } 2451 reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x6c); 2452 reg &= ~(1<<4); 2453 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6c, reg); 2454} 2455static void notify_bsp_ap_is_stopped(void) 2456{ 2457 unsigned long reg; 2458 unsigned long apic_id; 2459 apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 )); 2460 apic_id >>= 24; 2461 2462 if(apic_id != 0) { 2463 2464 reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C); 2465 reg |= 1<<4; 2466 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x6C, reg); 2467 } 2468 2469} 2470 2471static void enable_routing(u8 node) 2472{ 2473 u32 val; 2474 2475 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); 2481 2482 if(node!=0) { 2483 wait_ap_stop(node); 2484 } 2485 2486 print_debug(" done.\r\n"); 2487} 2488static void rename_temp_node(u8 node) 2489{ 2490 uint32_t val; 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); 2494 val &= (~7); 2495 val |= node; 2496 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x60, val); 2497 print_debug(" done.\r\n"); 2498} 2499static bool check_connection(u8 src, u8 dest, u8 link) 2500{ 2501 2502 u32 val; 2503 2504 2505 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x98+link); 2506 if ( (val&0x17) != 0x03) 2507 return 0; 2508 2509 val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0); 2510 if(val != 0x11001022) 2511 return 0; 2512 return 1; 2513} 2514static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2) 2515{ 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; 2520 uint8_t freq; 2521 2522 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 ); 2525 2526 2527 freq = log2(freq_cap1 & freq_cap2 & 0xff); 2528 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); 2531 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 ); 2534 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; 2539 } 2540 width = pow2_to_link_width[ln_width1]; 2541 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; 2546 } 2547 width |= pow2_to_link_width[ln_width1] << 4; 2548 2549 2550 pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1 ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x80 + link1 + 6 + 1, width); 2551 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); 2554} 2555static void fill_row(u8 node, u8 row, u32 value) 2556{ 2557 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) , 0x40+(row<<2), value); 2558} 2559static void setup_row(u8 source, u8 dest, u8 cpus) 2560{ 2561 fill_row(source,dest,generate_row(source,dest,cpus)); 2562} 2563static void setup_temp_row(u8 source, u8 dest, u8 cpus) 2564{ 2565 fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) ); 2566} 2567static void setup_node(u8 node, u8 cpus) 2568{ 2569 u8 row; 2570 for(row=0; row<cpus; row++) 2571 setup_row(node, row, cpus); 2572} 2573static void setup_remote_row(u8 source, u8 dest, u8 cpus) 2574{ 2575 fill_row(7, dest, generate_row(source, dest, cpus)); 2576} 2577static void setup_remote_node(u8 node, u8 cpus) 2578{ 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, 2587 }; 2588 uint8_t row; 2589 int i; 2590 print_debug("setup_remote_node\r\n"); 2591 for(row=0; row<cpus; row++) 2592 setup_remote_row(node, row, cpus); 2593 2594 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) { 2595 uint32_t value; 2596 uint8_t reg; 2597 reg = pci_reg[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); 2600 } 2601 print_debug("setup_remote_done\r\n"); 2602} 2603static u8 setup_uniprocessor(void) 2604{ 2605 print_debug("Enabling UP settings\r\n"); 2606 disable_probes(); 2607 return 1; 2608} 2609static u8 setup_smp(void) 2610{ 2611 u8 cpus=2; 2612 print_debug("Enabling SMP settings\r\n"); 2613 setup_row(0,0,cpus); 2614 2615 setup_temp_row(0,1,cpus); 2616 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(); 2621 return 1; 2622 } 2623 2624 optimize_connection(0, 0x20 , 7, 0x20 ); 2625 setup_node(0, cpus); 2626 setup_remote_node(1, cpus); 2627 rename_temp_node(1); 2628 enable_routing(1); 2629 2630 fill_row( 0 ,7,0x00010101 ) ; 2631 2632 print_debug_hex32(cpus); 2633 print_debug(" nodes initialized.\r\n"); 2634 return cpus; 2635} 2636static unsigned detect_mp_capabilities(unsigned cpus) 2637{ 2638 unsigned node, row, mask; 2639 bool mp_cap= (-1) ; 2640 print_debug("detect_mp_capabilities: "); 2641 print_debug_hex32(cpus); 2642 print_debug("\r\n"); 2643 if (cpus>2) 2644 mask=0x06; 2645 else 2646 mask=0x02; 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) 2649 mp_cap= (0) ; 2650 } 2651 if (mp_cap) 2652 return cpus; 2653 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 ); 2658 2659 return setup_uniprocessor(); 2660} 2661static void coherent_ht_finalize(unsigned cpus) 2662{ 2663 int node; 2664 bool rev_a0; 2665 2666 2667 print_debug("coherent_ht_finalize\r\n"); 2668 rev_a0= is_cpu_rev_a0(); 2669 for (node=0; node<cpus; node++) { 2670 u32 val; 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); 2676 val |= 0x00008000; 2677 pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node ) & 0x1f) << 11) | ((( 0 ) & 0x7) << 8)) ,0x68,val); 2678 if (rev_a0) { 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); 2682 } 2683 } 2684 print_debug("done\r\n"); 2685} 2686static int setup_coherent_ht_domain(void) 2687{ 2688 unsigned cpus; 2689 int reset_needed = 0; 2690 enable_routing(0) ; 2691 cpus=setup_smp(); 2692 cpus=detect_mp_capabilities(cpus); 2693 coherent_ht_finalize(cpus); 2694 2695 coherent_ht_mainboard(cpus); 2696 return reset_needed; 2697} 2698void sdram_no_memory(void) 2699{ 2700 print_err("No memory!!\r\n"); 2701 while(1) { 2702 hlt(); 2703 } 2704} 2705 2706void sdram_initialize(int controllers, const struct mem_controller *ctrl) 2707{ 2708 int i; 2709 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); 2715 } 2716 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); 2722 } 2723 2724 print_debug("Ram3\r\n"); 2725 sdram_enable(controllers, ctrl); 2726 print_debug("Ram4\r\n"); 2727} 2728static void enable_lapic(void) 2729{ 2730 msr_t msr; 2731 msr = rdmsr(0x1b); 2732 msr.hi &= 0xffffff00; 2733 msr.lo &= 0x000007ff; 2734 msr.lo |= 0xfee00000 | (1 << 11); 2735 wrmsr(0x1b, msr); 2736} 2737static void stop_this_cpu(void) 2738{ 2739 unsigned apicid; 2740 apicid = apic_read(0x020 ) >> 24; 2741 2742 apic_write(0x310 , (( apicid )<<24) ); 2743 apic_write(0x300 , 0x08000 | 0x04000 | 0x00500 ); 2744 2745 apic_wait_icr_idle(); 2746 2747 apic_write(0x310 , (( apicid )<<24) ); 2748 apic_write(0x300 , 0x08000 | 0x00500 ); 2749 2750 apic_wait_icr_idle(); 2751 2752 for(;;) { 2753 hlt(); 2754 } 2755} 2756static void pc87360_enable_serial(void) 2757{ 2758 pnp_set_logical_device(0x2e , 0x03 ); 2759 pnp_set_enable(0x2e , 1); 2760 pnp_set_iobase0(0x2e , 0x3f8); 2761} 2762static void main(void) 2763{ 2764 2765 static const struct mem_controller cpu[] = { 2766 { 2767 .node_id = 0, 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 }, 2774 }, 2775 { 2776 .node_id = 1, 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 }, 2783 }, 2784 }; 2785 if (cpu_init_detected()) { 2786 asm("jmp __cpu_reset"); 2787 } 2788 enable_lapic(); 2789 init_timer(); 2790 if (!boot_cpu()) { 2791 stop_this_cpu(); 2792 } 2793 pc87360_enable_serial(); 2794 uart_init(); 2795 console_init(); 2796 setup_default_resource_map(); 2797 setup_coherent_ht_domain(); 2798 enumerate_ht_chain(0); 2799 distinguish_cpu_resets(0); 2800 2801 enable_smbus(); 2802 memreset_setup(); 2803 sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu); 2804 2805} 2806

