diff options
author | Ronald G. Minnich <rminnich@gmail.com> | 2003-09-26 17:16:14 +0000 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2003-09-26 17:16:14 +0000 |
commit | 11dbdf5d782b94fb40c6f57488333d927d244975 (patch) | |
tree | 745b2976c49bfe47a40804413bacf42bb9fac97a /src/northbridge | |
parent | 430111b9d1472ef72d9960020eb3eb28e276ca7e (diff) | |
download | coreboot-11dbdf5d782b94fb40c6f57488333d927d244975.tar.xz |
just to get us back where we were.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1151 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge')
-rw-r--r-- | src/northbridge/via/vt8601/raminit.c | 251 |
1 files changed, 239 insertions, 12 deletions
diff --git a/src/northbridge/via/vt8601/raminit.c b/src/northbridge/via/vt8601/raminit.c index 864fbbe282..58723091b6 100644 --- a/src/northbridge/via/vt8601/raminit.c +++ b/src/northbridge/via/vt8601/raminit.c @@ -33,18 +33,6 @@ it with the version available from LANL. * 5/19/03 by SONE Takeshi <ts1@tsn.or.jp> */ -// Set to 1 if your DIMMs are PC133 -// Note that I'm assuming CPU's FSB frequency is 133MHz. If your CPU runs -// at another bus speed, you might need to change some of register values. -#ifndef DIMM_PC133 -#define DIMM_PC133 0 -#endif - -// Set to 1 if your DIMMs are CL=2 -#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 @@ -310,7 +298,246 @@ msg_bytes: .previous #endif + /* this is an early hack. We're going to just try to get memory + * working as it was before. I need help for SPD! RGM + */ +// Set to 1 if your DIMMs are PC133 +// Note that I'm assuming CPU's FSB frequency is 133MHz. If your CPU runs +// at another bus speed, you might need to change some of register values. +#ifndef DIMM_PC133 +#define DIMM_PC133 0 +#endif + +// Set to 1 if your DIMMs are CL=2 +#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) { + unsigned long eax; + volatile unsigned long y; + eax = x; + for(; eax < 0x60000000; eax += 0x10000000) + y = * (volatile unsigned long *) eax; +} + void dimms_write(int x) { + unsigned long eax = x; + for(; eax < 0x60000000; eax += 0x10000000) + *(volatile unsigned long *) eax = 0; +} + 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 +}; + + device_t north = 0; + uint8_t c, r; + + print_err("vt8601 init starting\n"); + north = pci_locate_device(PCI_ID(0x1106, 0x8601), north); + print_err_hex32(north); + print_err(" is the north\n"); + // memory clk enable. We are not using ECC + pci_write_config8(north,0x78, 0x01); + // dram control, see the book. +#if DIMM_PC133 + pci_write_config8(north,0x68, 0x52); +#else + 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); + 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); +#else // CL=3 + pci_write_config8(north,0x64, 0xe4); + pci_write_config8(north,0x65, 0xe4); + pci_write_config8(north,0x66, 0xe4); +#endif + + // dram frequency select. + // enable 4K pages for 64M dram. +#if DIMM_PC133 + pci_write_config8(north,0x69, 0x3c); +#else + 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); + +/* 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); +#if DIMM_CL2 + dimms_read(0x150); +#else // CL=3 + 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. +#if DIMM_PC133 + pci_write_config8(north,0x6A, 0x86); +#else + 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) { /* ??*/ + + // 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 ...\n"); + } + } + + print_err("vt8601 done\n"); + } static void sdram_set_spd_registers(const struct mem_controller *ctrl) { |