summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/via/vt8601/raminit.c434
1 files changed, 226 insertions, 208 deletions
diff --git a/src/northbridge/via/vt8601/raminit.c b/src/northbridge/via/vt8601/raminit.c
index 5b87b9ec3e..21e7b05fa9 100644
--- a/src/northbridge/via/vt8601/raminit.c
+++ b/src/northbridge/via/vt8601/raminit.c
@@ -312,30 +312,32 @@ msg_bytes:
#ifndef DIMM_CL2
#define DIMM_CL2 0
#endif
-/* Stable ~1 usec delay by hitting unused ISA port. */
-#define UDELAY(x) movl $x,%ecx; 9: outb %al,$0x81; loop 9b
void dimms_read(unsigned long x) {
-
+ uint8_t c;
unsigned long eax;
volatile unsigned long y;
eax = x;
- for(; eax < 0x60000000; eax += 0x10000000){
+ for(c = 0; c < 6; c++) {
+
print_err("dimms_read: ");
print_err_hex32(eax);
print_err("\r\n");
y = * (volatile unsigned long *) eax;
+ eax += 0x10000000;
}
}
- void dimms_write(int x) {
- print_err("dimms_write: \r\n");
- unsigned long eax = x;
- for(; eax < 0x60000000; eax += 0x10000000) {
- print_err("dimms_read: ");
- print_err_hex32(eax);
- print_err("\r\n");
- *(volatile unsigned long *) eax = 0;
- }
+
+void dimms_write(int x) {
+ uint8_t c;
+ unsigned long eax = x;
+ for(c = 0; c < 6; c++) {
+ print_err("dimms_write: ");
+ print_err_hex32(eax);
+ print_err("\r\n");
+ *(volatile unsigned long *) eax = 0;
+ eax += 0x10000000;
+ }
}
#define setnorthb pci_write_config8
@@ -364,223 +366,239 @@ dumpnorth(device_t north) {
}
}
static void sdram_set_registers(const struct mem_controller *ctrl) {
-static const uint16_t raminit_ma_reg_table[] = {
- /* Values for MA type register to try */
- 0x0000, 0x8088, 0xe0ee,
- 0xffff // end mark
-};
+ static const uint16_t raminit_ma_reg_table[] = {
+ /* Values for MA type register to try */
+ 0x0000, 0x8088, 0xe0ee,
+ 0xffff // end mark
+ };
- device_t north = 0;
+ device_t north = 0;
uint8_t c, r;
- print_err("vt8601 init starting\n");
- north = pci_locate_device(PCI_ID(0x1106, 0x8601), 0);
- print_err_hex32(north);
- print_err(" is the north\n");
- print_err_hex16(pci_read_config16(north, 0));
- print_err(" ");
- print_err_hex16(pci_read_config16(north, 2));
- print_err("\r\n");
+ print_err("vt8601 init starting\n");
+ north = pci_locate_device(PCI_ID(0x1106, 0x8601), 0);
+ north = 0;
+ print_err_hex32(north);
+ print_err(" is the north\n");
+ print_err_hex16(pci_read_config16(north, 0));
+ print_err(" ");
+ print_err_hex16(pci_read_config16(north, 2));
+ print_err("\r\n");
- // memory clk enable. We are not using ECC
- pci_write_config8(north,0x78, 0x01);
- print_err_hex8(pci_read_config8(north, 0x78));
- // dram control, see the book.
+ // memory clk enable. We are not using ECC
+ pci_write_config8(north,0x78, 0x01);
+ print_err_hex8(pci_read_config8(north, 0x78));
+ // dram control, see the book.
#if DIMM_PC133
- pci_write_config8(north,0x68, 0x52);
+ pci_write_config8(north,0x68, 0x52);
#else
- pci_write_config8(north,0x68, 0x42);
+ pci_write_config8(north,0x68, 0x42);
#endif
- // dram control, see the book.
- pci_write_config8(north,0x6B, 0x0c);
- // Initial setting, 256MB in each bank, will be rewritten later.
- pci_write_config8(north,0x5A, 0x20);
- print_err_hex8(pci_read_config8(north, 0x5a));
- pci_write_config8(north,0x5B, 0x40);
- pci_write_config8(north,0x5C, 0x60);
- pci_write_config8(north,0x5D, 0x80);
- pci_write_config8(north,0x5E, 0xA0);
- pci_write_config8(north,0x5F, 0xC0);
- // It seems we have to take care of these 2 registers as if
- // they are bank 6 and 7.
- pci_write_config8(north,0x56, 0xC0);
- pci_write_config8(north,0x57, 0xC0);
-
- // SDRAM in all banks
- pci_write_config8(north,0x60, 0x3F);
- // DRAM timing. I'm suspicious of this
- // This is for all banks, 64 is 0,1. 65 is 2,3. 66 is 4,5.
- // ras precharge 4T, RAS pulse 5T
- // cas2 is 0xd6, cas3 is 0xe6
- // we're also backing off write pulse width to 2T, so result is 0xee
+ // dram control, see the book.
+ pci_write_config8(north,0x6B, 0x0c);
+ // Initial setting, 256MB in each bank, will be rewritten later.
+ pci_write_config8(north,0x5A, 0x20);
+ print_err_hex8(pci_read_config8(north, 0x5a));
+ pci_write_config8(north,0x5B, 0x40);
+ pci_write_config8(north,0x5C, 0x60);
+ pci_write_config8(north,0x5D, 0x80);
+ pci_write_config8(north,0x5E, 0xA0);
+ pci_write_config8(north,0x5F, 0xC0);
+ // It seems we have to take care of these 2 registers as if
+ // they are bank 6 and 7.
+ pci_write_config8(north,0x56, 0xC0);
+ pci_write_config8(north,0x57, 0xC0);
+
+ // SDRAM in all banks
+ pci_write_config8(north,0x60, 0x3F);
+ // DRAM timing. I'm suspicious of this
+ // This is for all banks, 64 is 0,1. 65 is 2,3. 66 is 4,5.
+ // ras precharge 4T, RAS pulse 5T
+ // cas2 is 0xd6, cas3 is 0xe6
+ // we're also backing off write pulse width to 2T, so result is 0xee
#if DIMM_CL2
- pci_write_config8(north,0x64, 0xd4);
- pci_write_config8(north,0x65, 0xd4);
- pci_write_config8(north,0x66, 0xd4);
+ pci_write_config8(north,0x64, 0xd4);
+ pci_write_config8(north,0x65, 0xd4);
+ pci_write_config8(north,0x66, 0xd4);
#else // CL=3
- pci_write_config8(north,0x64, 0xe4);
- pci_write_config8(north,0x65, 0xe4);
- pci_write_config8(north,0x66, 0xe4);
+ pci_write_config8(north,0x64, 0xe4);
+ pci_write_config8(north,0x65, 0xe4);
+ pci_write_config8(north,0x66, 0xe4);
#endif
- dumpnorth(north);
- // dram frequency select.
- // enable 4K pages for 64M dram.
+
+ // dram frequency select.
+ // enable 4K pages for 64M dram.
#if DIMM_PC133
- pci_write_config8(north,0x69, 0x3c);
+ pci_write_config8(north,0x69, 0x3c);
#else
- pci_write_config8(north,0x69, 0xac);
+ pci_write_config8(north,0x69, 0xac);
#endif
- // refresh counter, disabled.
- pci_write_config8(north,0x6A, 0x00);
- // clkenable configuration. kevinh FIXME - add precharge
- pci_write_config8(north,0x6C, 0x00);
- // dram read latch delay of 1 ns, MD drive 8 mA,
- // high drive strength on MA[2: 13], we#, cas#, ras#
- // As per Cindy Lee, set to 0x37, not 0x57
- pci_write_config8(north,0x6D, 0x7f);
-
- /* Initialize all banks at once */
-
-/* begin to initialize*/
- // I forget why we need this, but we do
- dimms_write(0xa55a5aa5);
-
-/* set NOP*/
- pci_write_config8(north,0x6C, 0x01);
-
-/* wait 200us*/
- // You need to do the memory reference. That causes the nop cycle.
- dimms_read(0);
- udelay(400);
-
-/* set precharge */
- pci_write_config8(north,0x6C, 0x02);
-
-/* dummy reads*/
- dimms_read(0);
- udelay(200);
-
-/* set CBR*/
- pci_write_config8(north,0x6C, 0x04);
+ // refresh counter, disabled.
+ pci_write_config8(north,0x6A, 0x00);
+ // clkenable configuration. kevinh FIXME - add precharge
+ pci_write_config8(north,0x6C, 0x00);
+ // dram read latch delay of 1 ns, MD drive 8 mA,
+ // high drive strength on MA[2: 13], we#, cas#, ras#
+ // As per Cindy Lee, set to 0x37, not 0x57
+ pci_write_config8(north,0x6D, 0x7f);
+
+ /* Initialize all banks at once */
+
+ /* begin to initialize*/
+ // I forget why we need this, but we do
+ dimms_write(0xa55a5aa5);
+
+ /* set NOP*/
+ pci_write_config8(north,0x6C, 0x01);
+ print_err("NOP\r\n");
+ /* wait 200us*/
+ // You need to do the memory reference. That causes the nop cycle.
+ dimms_read(0);
+ udelay(400);
+ print_err("PRECHARGE\r\n");
+ /* set precharge */
+ pci_write_config8(north,0x6C, 0x02);
+ print_err("DUMMY READS\r\n");
+ /* dummy reads*/
+ dimms_read(0);
+ udelay(200);
+ print_err("CBR\r\n");
+ /* set CBR*/
+ pci_write_config8(north,0x6C, 0x04);
-/* do 8 reads and wait >100us between each - from via*/
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
- dimms_read(0);
- udelay(200);
-
-/* set MRS*/
- pci_write_config8(north,0x6c, 0x03);
+ /* do 8 reads and wait >100us between each - from via*/
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ dimms_read(0);
+ udelay(200);
+ print_err("MRS\r\n");
+ /* set MRS*/
+ pci_write_config8(north,0x6c, 0x03);
#if DIMM_CL2
- dimms_read(0x150);
+ dimms_read(0x150);
#else // CL=3
- dimms_read(0x1d0);
+ dimms_read(0x1d0);
#endif
- udelay(200);
-
-/* set to normal mode */
- pci_write_config8(north,0x6C, 0x08);
-
- dimms_write(0x55aa55aa);
- dimms_read(0);
- udelay(200);
-
- // Set the refresh rate.
+ udelay(200);
+ print_err("NORMAL\r\n");
+ /* set to normal mode */
+ pci_write_config8(north,0x6C, 0x08);
+
+ dimms_write(0x55aa55aa);
+ dimms_read(0);
+ udelay(200);
+ print_err("set ref. rate\r\n");
+ // Set the refresh rate.
#if DIMM_PC133
- pci_write_config8(north,0x6A, 0x86);
+ pci_write_config8(north,0x6A, 0x86);
#else
- pci_write_config8(north,0x6A, 0x65);
+ pci_write_config8(north,0x6A, 0x65);
#endif
- // enable multi-page open
- pci_write_config8(north,0x6B, 0x0d);
-
- /* Begin auto-detection
- * Find the first bank with DIMM equipped. */
-
- /* Maximum possible memory in bank 0, none in other banks.
- * Starting from bank 0, we's fill 0 in these registers
- * until memory is found. */
- pci_write_config8(north,0x5A, 0xff);
- pci_write_config8(north,0x5B, 0xff);
- pci_write_config8(north,0x5C, 0xff);
- pci_write_config8(north,0x5D, 0xff);
- pci_write_config8(north,0x5E, 0xff);
- pci_write_config8(north,0x5F, 0xff);
- pci_write_config8(north,0x56, 0xff);
- pci_write_config8(north,0x57, 0xff);
-
- /* this code is broken ... ignores 56, 57 */
- for(c = 0x5a; c < 0x60; c++) {
- /* Write different values to 0 and 8, then read from 0.
- * If values of address 0 match, we have something there. */
- *(volatile unsigned long *) 0 = 0x12345678;
-
- /* LEAVE THIS HERE. IT IS ESSENTIAL. OTHERWISE BUFFERING
- * WILL FOOL YOU!
- */
- *(volatile unsigned long *) 8 = 0x87654321;
- if (*(volatile unsigned long *) 0 != 0x12345678) {
-
- /* No memory in this bank. Tell it to the bridge. */
- pci_write_config8(north,c, 0);
- } else {
- uint8_t best = 0;
-
- /* Detect MA mapping type of the first bank. */
-
- for(r = 0; r < 3; r++) {
- volatile unsigned long esi = 0;
- volatile unsigned long eax = 0;
- pci_write_config8(north,0x58, raminit_ma_reg_table[r]);
- * (volatile unsigned long *) eax = 0;
- // Write to addresses with only one address bit
- // on, from 0x80000000 to 0x00000008 (lower 3 bits
- // are ignored, assuming 64-bit bus). Then what
- // is read at address 0 is the value written to
- // the lowest address where it gets
- // wrap-around. That address is either the size of
- // the bank, or a missing bit due to incorrect MA
- // mapping.
- eax = 0x80000000;
- while (eax != 4) {
- eax = * (volatile unsigned long *) eax;
- eax >>= 1;
- }
- eax = 0;
- /* oh boy ... what is this.
- movl 0, %eax
- cmpl %eax, %esi
- jnc 3f
- */
- if (eax < esi) { /* ??*/
+ print_err("enable multi-page open\r\n");
+ // enable multi-page open
+ pci_write_config8(north,0x6B, 0x0d);
+
+ /* Begin auto-detection
+ * Find the first bank with DIMM equipped. */
+
+ /* Maximum possible memory in bank 0, none in other banks.
+ * Starting from bank 0, we's fill 0 in these registers
+ * until memory is found. */
+ pci_write_config8(north,0x5A, 0xff);
+ pci_write_config8(north,0x5B, 0xff);
+ pci_write_config8(north,0x5C, 0xff);
+ pci_write_config8(north,0x5D, 0xff);
+ pci_write_config8(north,0x5E, 0xff);
+ pci_write_config8(north,0x5F, 0xff);
+ pci_write_config8(north,0x56, 0xff);
+ pci_write_config8(north,0x57, 0xff);
+ dumpnorth(north);
+ print_err("MA\r\n");
+ /* this code is broken ... ignores 56, 57 */
+ for(c = 0x5a; c < 0x60; c++) {
+ /* Write different values to 0 and 8, then read from 0.
+ * If values of address 0 match, we have something there. */
+ print_err("write to 0\r\n");
+ *(volatile unsigned long *) 0 = 0x12345678;
+
+ /* LEAVE THIS HERE. IT IS ESSENTIAL. OTHERWISE BUFFERING
+ * WILL FOOL YOU!
+ */
+ print_err("write to 8\r\n");
+ *(volatile unsigned long *) 8 = 0x87654321;
+
+ if (*(volatile unsigned long *) 0 != 0x12345678) {
+ print_err("no memory in this bank\r\n");
+ /* No memory in this bank. Tell it to the bridge. */
+ pci_write_config8(north,c, 0);
+ } else {
+ uint8_t best = 0;
+
+ /* Detect MA mapping type of the first bank. */
+
+ for(r = 0; r < 3; r++) {
+ volatile unsigned long esi = 0;
+ volatile unsigned long eax = 0;
+ pci_write_config8(north,0x58, raminit_ma_reg_table[r]);
+
+ * (volatile unsigned long *) eax = 0;
+ print_err(" done write to eax\r\n");
+ // Write to addresses with only one address bit
+ // on, from 0x80000000 to 0x00000008 (lower 3 bits
+ // are ignored, assuming 64-bit bus). Then what
+ // is read at address 0 is the value written to
+ // the lowest address where it gets
+ // wrap-around. That address is either the size of
+ // the bank, or a missing bit due to incorrect MA
+ // mapping.
+ eax = 0x80000000;
+ while (eax != 4) {
+ * (volatile unsigned long *) eax = eax;
+ //print_err_hex32(eax);
+ outb(eax&0xff, 0x80);
+ eax >>= 1;
+ }
+ print_err(" done read to eax\r\n");
+ eax = 0;
+ /* oh boy ... what is this.
+ movl 0, %eax
+ cmpl %eax, %esi
+ jnc 3f
+ */
+ print_err("eax and esi: ");
+ print_err_hex32(eax); print_err(" ");
+ print_err_hex32(esi); print_err("\r\n");
+
+ if (eax < esi) { /* ??*/
- // This is the current best MA mapping.
- // Save the address and its MA mapping value.
- best = r;
- esi = eax;
- }
- }
+ // This is the current best MA mapping.
+ // Save the address and its MA mapping value.
+ best = r;
+ esi = eax;
+ }
+ }
- pci_write_config8(north,0x58, raminit_ma_reg_table[best]);
- print_err("enabled first bank of ram ... ma is ");
- print_err_hex8(pci_read_config8(north, 0x58));
- print_err("\r\n");
- }
- }
- print_err("vt8601 done\n");
-
+ pci_write_config8(north,0x58, raminit_ma_reg_table[best]);
+ print_err("enabled first bank of ram ... ma is ");
+ print_err_hex8(pci_read_config8(north, 0x58));
+ print_err("\r\n");
+ }
+ }
+ print_err("vt8601 done\n");
+ dumpnorth(north);
+ udelay(1000);
}
static void sdram_set_spd_registers(const struct mem_controller *ctrl) {