Changeset 5194
- Timestamp:
- Mar 6, 2010 7:16:25 PM (3 years ago)
- Location:
- trunk/src/northbridge/intel/i440bx
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/northbridge/intel/i440bx/i440bx.h
r3052 r5194 33 33 * Reserved or Intel Reserved and should not be touched. 34 34 */ 35 35 36 #define NBXCFG 0x50 /* 440BX Configuration (0x0000:00S0_0000_000S_0S00b). */ 36 37 #define DRAMC 0x57 /* DRAM Control (00S0_0000b). */ 37 38 #define DRAMT 0x58 /* DRAM Timing (0x03). */ 38 39 #define PAM 0x59 /* Programmable Attribute Map, 7 registers (0x00). */ 40 #define PAM0 0x59 41 #define PAM1 0x5a 42 #define PAM2 0x5b 43 #define PAM3 0x5c 44 #define PAM4 0x5d 45 #define PAM5 0x5e 46 #define PAM6 0x5f 39 47 #define DRB 0x60 /* DRAM Row Boundary, 8 registers (0x01). */ 48 #define DRB0 0x60 49 #define DRB1 0x61 50 #define DRB2 0x62 51 #define DRB3 0x63 52 #define DRB4 0x64 53 #define DRB5 0x65 54 #define DRB6 0x66 55 #define DRB7 0x67 40 56 #define FDHC 0x68 /* Fixed SDRAM Hole Control (0x00). */ 41 57 #define MBSC 0x69 /* Memory Buffer Strength Control (0x0000-0000-0000). */ … … 51 67 #define ERRSTS 0x91 /* Error Status (0x0000). */ 52 68 // TODO: AGP stuff. 69 #define ACAPID 0xa0 /* AGP Capability Identifier (0x00100002 or 0x00000000) */ 70 #define AGPSTAT 0xa4 /* AGP Status Register (0x1f000203, read only) */ 71 #define AGPCMD 0xa8 /* AGP Command Register (0x00000000) */ 72 #define AGPCTRL 0xb0 /* AGP Control Register (0x00000000) */ 73 #define APSIZE 0xb4 /* Aperture Size Control Register (0x00) */ 74 #define ATTBASE 0xb8 /* Aperture Translation Table (0x00000000) */ 75 53 76 #define MBFS 0xca /* Memory Buffer Frequency Select (0x000000). */ 54 77 #define BSPAD 0xd0 /* BIOS Scratch Pad (0x000..000). */ 78 #define BSPAD0 0xd0 /* These are free for our use. */ 79 #define BSPAD1 0xd1 80 #define BSPAD2 0xd2 81 #define BSPAD3 0xd3 82 #define BSPAD4 0xd4 83 #define BSPAD5 0xd5 84 #define BSPAD6 0xd6 85 #define BSPAD7 0xd7 55 86 #define DWTC 0xe0 /* DRAM Write Thermal Throttling Control (0x000..000). */ 56 87 #define DRTC 0xe8 /* DRAM Read Thermal Throttling Control (0x000..000). */ 57 88 #define BUFFC 0xf0 /* Buffer Control Register (0x0000). */ 58 89 59 /* For convenience: */60 #define DRB0 0x6061 #define DRB1 0x6162 #define DRB2 0x6263 #define DRB3 0x6364 #define DRB4 0x6465 #define DRB5 0x6566 #define DRB6 0x6667 #define DRB7 0x6768 69 #define PAM0 0x5970 #define PAM1 0x5a71 #define PAM2 0x5b72 #define PAM3 0x5c73 #define PAM4 0x5d74 #define PAM5 0x5e75 #define PAM6 0x5f76 -
trunk/src/northbridge/intel/i440bx/raminit.c
r5185 r5194 3 3 * 4 4 * Copyright (C) 2007-2008 Uwe Hermann <uwe@hermann-uwe.de> 5 * Copyright (C) 2010 Keith Hui <buurin@gmail.com> 5 6 * 6 7 * This program is free software; you can redistribute it and/or modify … … 24 25 #include <stdlib.h> 25 26 #include "i440bx.h" 27 #include "raminit.h" 26 28 27 29 /*----------------------------------------------------------------------------- … … 186 188 * 11 = Read/Write (all access goes to DRAM) 187 189 */ 188 // TODO 189 PAM0, 0x00, 0x00, 190 PAM1, 0x00, 0x00, 191 PAM2, 0x00, 0x00, 192 PAM3, 0x00, 0x00, 193 PAM4, 0x00, 0x00, 194 PAM5, 0x00, 0x00, 195 PAM6, 0x00, 0x00, 190 191 /* 192 * Map all legacy regions to RAM (read/write). This is required if 193 * you want to use the RAM area from 768 KB - 1 MB. If the PAM 194 * registers are not set here appropriately, the RAM in that region 195 * will not be accessible, thus a RAM check of it will also fail. 196 * 197 * TODO: This was set in sdram_set_spd_registers(). 198 * Test if it still works when set here. 199 */ 200 PAM0, 0x00, 0x30, 201 PAM1, 0x00, 0x33, 202 PAM2, 0x00, 0x33, 203 PAM3, 0x00, 0x33, 204 PAM4, 0x00, 0x33, 205 PAM5, 0x00, 0x33, 206 PAM6, 0x00, 0x33, 196 207 197 208 /* DRB[0:7] - DRAM Row Boundary Registers … … 341 352 // PMCR, 0x00, 0x10, 342 353 PMCR, 0x00, 0x00, 354 355 /* Enable SCRR.SRRAEN and let BX choose the SRR. */ 356 SCRR + 1, 0x00, 0x10, 343 357 }; 344 358 … … 375 389 dimm_start = 0; 376 390 for (i = 0; i < (DIMM_SOCKETS * 2); i++) { 377 addr_offset = 0;378 caslatency = 3; /* TODO: Dynamically get CAS latency later. */391 addr_offset = 0; 392 caslatency = 3; /* TODO: Dynamically get CAS latency later. */ 379 393 if (command == RAM_COMMAND_MRS) { 380 394 /* … … 412 426 } 413 427 428 static void set_dram_buffer_strength(void) 429 { 430 /* TODO: This needs to be set according to the DRAM tech 431 * (x8, x16, or x32). Argh, Intel provides no docs on this! 432 * Currently, it needs to be pulled from the output of 433 * lspci -xxx Rx92 434 * 435 * Relevant registers: MBSC, MBFS, BUFFC. 436 */ 437 438 pci_write_config8(NB, MBSC, 0x03); 439 } 440 414 441 /*----------------------------------------------------------------------------- 415 442 DIMM-independant configuration functions. … … 459 486 reg |= register_values[i + 2] & ~(register_values[i + 1]); 460 487 pci_write_config8(NB, register_values[i], reg); 461 488 #if 0 462 489 PRINT_DEBUG(" Set register 0x"); 463 490 PRINT_DEBUG_HEX8(register_values[i]); … … 465 492 PRINT_DEBUG_HEX8(reg); 466 493 PRINT_DEBUG("\r\n"); 494 #endif 467 495 } 468 496 } 469 497 498 struct dimm_size { 499 unsigned long side1; 500 unsigned long side2; 501 }; 502 503 static struct dimm_size spd_get_dimm_size(unsigned int device) 504 { 505 struct dimm_size sz; 506 int i, module_density, dimm_banks; 507 sz.side1 = 0; 508 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE); 509 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS); 510 511 /* Find the size of side1. */ 512 /* Find the larger value. The larger value is always side1. */ 513 for (i = 512; i >= 0; i >>= 1) { 514 if ((module_density & i) == i) { 515 sz.side1 = i; 516 break; 517 } 518 } 519 520 /* Set to 0 in case it's single sided. */ 521 sz.side2 = 0; 522 523 /* Test if it's a dual-sided DIMM. */ 524 if (dimm_banks > 1) { 525 /* Test if there's a second value. If so it's asymmetrical. */ 526 if (module_density != i) { 527 /* 528 * Find second value, picking up where we left off. 529 * i >>= 1 done initially to make sure we don't get 530 * the same value again. 531 */ 532 for (i >>= 1; i >= 0; i >>= 1) { 533 if (module_density == (sz.side1 | i)) { 534 sz.side2 = i; 535 break; 536 } 537 } 538 /* If not, it's symmetrical. */ 539 } else { 540 sz.side2 = sz.side1; 541 } 542 } 543 544 /* 545 * SPD byte 31 is the memory size divided by 4 so we 546 * need to muliply by 4 to get the total size. 547 */ 548 sz.side1 *= 4; 549 sz.side2 *= 4; 550 551 return sz; 552 } 553 /* 554 * Sets DRAM attributes one DIMM at a time, based on SPD data. 555 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC. 556 */ 557 static void set_dram_row_attributes(void) 558 { 559 int i, dra, drb, col, width, value, rps, edosd, ecc, nbxecc; 560 u8 bpr; /* Top 8 bits of PGPOL */ 561 562 edosd = 0; 563 rps = 0; 564 drb = 0; 565 bpr = 0; 566 nbxecc = 0xff; 567 568 for (i = 0; i < DIMM_SOCKETS; i++) { 569 unsigned int device; 570 device = DIMM_SPD_BASE + i; 571 bpr >>= 2; 572 573 /* First check if a DIMM is actually present. */ 574 value = spd_read_byte(device, SPD_MEMORY_TYPE); 575 /* This is 440BX! We do EDO too! */ 576 if (value == SPD_MEMORY_TYPE_EDO 577 || value == SPD_MEMORY_TYPE_SDRAM) { 578 579 PRINT_DEBUG("Found "); 580 if (value == SPD_MEMORY_TYPE_EDO) { 581 edosd |= 0x02; 582 } else if (value == SPD_MEMORY_TYPE_SDRAM) { 583 edosd |= 0x04; 584 } 585 PRINT_DEBUG("DIMM in slot "); 586 PRINT_DEBUG_HEX8(i); 587 PRINT_DEBUG("\r\n"); 588 589 if (edosd == 0x06) { 590 print_err("Mixing EDO/SDRAM unsupported!\r\n"); 591 die("HALT\r\n"); 592 } 593 594 /* "DRA" is our RPS for the two rows on this DIMM. */ 595 dra = 0; 596 597 /* Columns */ 598 col = spd_read_byte(device, SPD_NUM_COLUMNS); 599 600 /* 601 * Is this an ECC DIMM? Actually will be a 2 if so. 602 * TODO: Other register than NBXCFG also needs this 603 * ECC information. 604 */ 605 ecc = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE); 606 607 /* Data width */ 608 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); 609 610 /* Exclude error checking data width from page size calculations */ 611 if (ecc) { 612 value = spd_read_byte(device, 613 SPD_ERROR_CHECKING_SDRAM_WIDTH); 614 width -= value; 615 /* ### ECC */ 616 /* Clear top 2 bits to help set up NBXCFG. */ 617 ecc &= 0x3f; 618 } else { 619 /* Without ECC, top 2 bits should be 11. */ 620 ecc |= 0xc0; 621 } 622 623 /* Calculate page size in bits. */ 624 value = ((1 << col) * width); 625 626 /* Convert to KB. */ 627 dra = (value >> 13); 628 629 /* Number of banks of DIMM (single or double sided). */ 630 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); 631 632 /* Once we have dra, col is done and can be reused. 633 * So it's reused for number of banks. 634 */ 635 col = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); 636 637 if (value == 1) { 638 /* 639 * Second bank of 1-bank DIMMs "doesn't have 640 * ECC" - or anything. 641 */ 642 ecc |= 0x80; 643 if (dra == 2) { 644 dra = 0x0; /* 2KB */ 645 } else if (dra == 4) { 646 dra = 0x1; /* 4KB */ 647 } else if (dra == 8) { 648 dra = 0x2; /* 8KB */ 649 } else { 650 dra = -1; 651 } 652 /* 653 * Sets a flag in PGPOL[BPR] if this DIMM has 654 * 4 banks per row. 655 */ 656 if (col == 4) 657 bpr |= 0x40; 658 } else if (value == 2) { 659 if (dra == 2) { 660 dra = 0x0; /* 2KB */ 661 } else if (dra == 4) { 662 dra = 0x05; /* 4KB */ 663 } else if (dra == 8) { 664 dra = 0x0a; /* 8KB */ 665 } else { 666 dra = -1; 667 } 668 /* Ditto */ 669 if (col == 4) 670 bpr |= 0xc0; 671 } else { 672 print_err("# of banks of DIMM unsupported!\r\n"); 673 die("HALT\r\n"); 674 } 675 if (dra == -1) { 676 print_err("Page size not supported\r\n"); 677 die("HALT\r\n"); 678 } 679 680 /* 681 * 440BX supports asymmetrical dual-sided DIMMs, 682 * but can't handle DIMMs smaller than 8MB per 683 * side or larger than 128MB per side. 684 */ 685 struct dimm_size sz = spd_get_dimm_size(device); 686 if ((sz.side1 < 8)) { 687 print_err("DIMMs smaller than 8MB per side\r\n" 688 "are not supported on this NB.\r\n"); 689 die("HALT\r\n"); 690 } 691 if ((sz.side1 > 128)) { 692 print_err ("DIMMs > 128MB per side\r\n" 693 "are not supported on this NB\r\n"); 694 die("HALT\r\n"); 695 } 696 697 /* Divide size by 8 to set up the DRB registers. */ 698 drb += (sz.side1 / 8); 699 700 /* 701 * Build the DRB for the next row in MSB so it gets 702 * placed in DRB[n+1] where it belongs when written 703 * as a 16-bit word. 704 */ 705 drb &= 0xff; 706 drb |= (drb + (sz.side2 / 8)) << 8; 707 } else { 708 #if 0 709 PRINT_DEBUG("No DIMM found in slot "); 710 PRINT_DEBUG_HEX8(i); 711 PRINT_DEBUG("\r\n"); 712 #endif 713 714 /* If there's no DIMM in the slot, set dra to 0x00. */ 715 dra = 0x00; 716 ecc = 0xc0; 717 /* Still have to propagate DRB over. */ 718 drb &= 0xff; 719 drb |= (drb << 8); 720 } 721 722 pci_write_config16(NB, DRB + (2 * i), drb); 723 #if 0 724 PRINT_DEBUG("DRB has been set to 0x"); 725 PRINT_DEBUG_HEX16(drb); 726 PRINT_DEBUG("\r\n"); 727 #endif 728 729 /* Brings the upper DRB back down to be base for 730 * DRB calculations for the next two rows. 731 */ 732 drb >>= 8; 733 734 rps |= (dra & 0x0f) << (i * 4); 735 nbxecc = (nbxecc >> 2) | (ecc & 0xc0); 736 } 737 738 /* Set paging policy register. */ 739 pci_write_config8(NB, PGPOL + 1, bpr); 740 PRINT_DEBUG("PGPOL[BPR] has been set to 0x"); 741 PRINT_DEBUG_HEX8(bpr); 742 PRINT_DEBUG("\r\n"); 743 744 /* Set DRAM row page size register. */ 745 pci_write_config16(NB, RPS, rps); 746 PRINT_DEBUG("RPS has been set to 0x"); 747 PRINT_DEBUG_HEX16(rps); 748 PRINT_DEBUG("\r\n"); 749 750 /* ### ECC */ 751 pci_write_config8(NB, NBXCFG + 3, nbxecc); 752 PRINT_DEBUG("NBXECC[31:24] has been set to 0x"); 753 PRINT_DEBUG_HEX8(nbxecc); 754 PRINT_DEBUG("\r\n"); 755 756 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM). 757 * TODO: Registered SDRAM support. 758 */ 759 edosd &= 0x07; 760 if (edosd & 0x02) { 761 edosd |= 0x00; 762 } else if (edosd & 0x04) { 763 edosd |= 0x08; 764 } 765 edosd &= 0x18; 766 767 /* edosd is now in the form needed for DRAMC[4:3]. */ 768 value = pci_read_config8(NB, DRAMC) & 0xe7; 769 value |= edosd; 770 pci_write_config8(NB, DRAMC, value); 771 PRINT_DEBUG("DRAMC has been set to 0x"); 772 PRINT_DEBUG_HEX8(value); 773 PRINT_DEBUG("\r\n"); 774 } 775 470 776 static void sdram_set_spd_registers(void) 471 777 { 472 /* TODO: Don't hardcode the values here, get info via SPD. */ 473 474 /* Map all legacy regions to RAM (read/write). This is required if 475 * you want to use the RAM area from 768 KB - 1 MB. If the PAM 476 * registers are not set here appropriately, the RAM in that region 477 * will not be accessible, thus a RAM check of it will also fail. 478 */ 479 pci_write_config8(NB, PAM0, 0x30); 480 pci_write_config8(NB, PAM1, 0x33); 481 pci_write_config8(NB, PAM2, 0x33); 482 pci_write_config8(NB, PAM3, 0x33); 483 pci_write_config8(NB, PAM4, 0x33); 484 pci_write_config8(NB, PAM5, 0x33); 485 pci_write_config8(NB, PAM6, 0x33); 486 487 /* TODO: Set DRB0-DRB7. */ 488 /* Currently this is hardcoded to one 64 MB DIMM in slot 0. */ 489 pci_write_config8(NB, DRB0, 0x08); 490 pci_write_config8(NB, DRB1, 0x08); 491 pci_write_config8(NB, DRB2, 0x08); 492 pci_write_config8(NB, DRB3, 0x08); 493 pci_write_config8(NB, DRB4, 0x08); 494 pci_write_config8(NB, DRB5, 0x08); 495 pci_write_config8(NB, DRB6, 0x08); 496 pci_write_config8(NB, DRB7, 0x08); 497 498 /* TODO: Set DRAMC. Don't enable refresh for now. */ 499 pci_write_config8(NB, DRAMC, 0x08); 500 501 /* TODO: Set RPS. Needs to be fixed for multiple DIMM support. */ 502 pci_write_config16(NB, RPS, 0x0001); 778 /* Setup DRAM row boundary registers and other attributes. */ 779 set_dram_row_attributes(); 503 780 504 781 /* TODO: Set SDRAMC. */ 505 782 pci_write_config16(NB, SDRAMC, 0x0010); /* SDRAMPWR=1: 4 DIMM config */ 506 783 507 /* TODO: Set PGPOL. */ 508 // pci_write_config16(NB, PGPOL, 0x0107); 509 pci_write_config16(NB, PGPOL, 0x0123); 510 511 /* TODO: Set NBXCFG. */ 512 // pci_write_config32(NB, NBXCFG, 0x0100220c); // FIXME? 513 pci_write_config32(NB, NBXCFG, 0xff00800c); 784 /* TODO */ 785 set_dram_buffer_strength(); 514 786 515 787 /* TODO: Set PMCR? */ … … 518 790 519 791 /* TODO? */ 520 pci_write_config8(NB, PCI_LATENCY_TIMER, 0x40);521 792 pci_write_config8(NB, DRAMT, 0x03); 522 pci_write_config8(NB, MBSC, 0x03);523 pci_write_config8(NB, SCRR, 0x38);524 793 } 525 794
Note: See TracChangeset
for help on using the changeset viewer.
