diff options
-rw-r--r-- | src/mainboard/via/epia/auto.c | 13 | ||||
-rw-r--r-- | src/northbridge/via/vt8601/raminit.c | 251 |
2 files changed, 248 insertions, 16 deletions
diff --git a/src/mainboard/via/epia/auto.c b/src/mainboard/via/epia/auto.c index 3ac96078e5..f8ad4e3e7d 100644 --- a/src/mainboard/via/epia/auto.c +++ b/src/mainboard/via/epia/auto.c @@ -11,6 +11,8 @@ #include "arch/i386/lib/console.c" #include "ram/ramtest.c" #include "northbridge/via/vt8601/raminit.h" +/* + */ void udelay(int usecs) { int i; for(i = 0; i < usecs; i++) @@ -43,21 +45,24 @@ static inline int spd_read_byte(unsigned device, unsigned address) #include "northbridge/via/vt8601/raminit.c" -#include "sdram/generic_sdram.c" /* +#include "sdram/generic_sdram.c" */ static void main(void) { - struct mem_controller cpu[1]; - // init_timer(); + /* init_timer();*/ uart_init(); console_init(); enable_smbus(); + /* memreset_setup(); -// sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu); + this is way more generic than we need. + sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu); + */ + sdram_set_registers((const struct mem_controller *) 0); /* Check all of memory */ 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) { |