diff options
Diffstat (limited to 'src/northbridge/via')
-rw-r--r-- | src/northbridge/via/vt8601/raminit.c | 434 |
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) { |