On Sat, Dec 02, 2006 at 09:30:58AM +0100, Segher Boessenkool wrote: > It looks reasonable. You want to shift by 3 though, not 23, > not 15, so you read from 0x1d0 for writing to the MRS.
OK, a few questions: * Do I read32() from somewhere for _every_ RAM command or only for MRS? * The v1 code seems to read from the highest RAM address for each DRB register. In my case: Get contents of DRB6 (0x8), shift left by 23 as the DRB registers store multiples of 8 MB, so I get my 64 MB. Correct? Now; do I read32() from * (8 << 23) * (8 << 23) + 0x1d0 * 0x0 + 0x1d0 * 0x0 + 0x1d0 AND (8 << 23) + 0x1d0 * 0x0 * ??? Do I read from x for most commands but from (x + 0x1d0) for MRS? Or should I read from (x + 0x1d0) for all commands? I've tried a lot of variations here, but nothing worked. Maybe some other parts of the code are still broken? > It seems the i440 might want the address bits inverted on > the high banks in some configurations, btw; so if it won't > work, you can try 0x1d0 ^ 0xff8 or so. Doesn't seem to work either. Attached my latest code and a minicom log... Uwe. -- http://www.hermann-uwe.de | http://www.holsham-traders.de http://www.crazy-hacks.org | http://www.unmaintained-free-software.org
#include <spd.h> #include <sdram_mode.h> #include "i440bx.h" /*----------------------------------------------------------------------------- Definitions. -----------------------------------------------------------------------------*/ /* Uncomment this to enable local debugging messages. */ #define DEBUG_RAM_CONFIG 1 /* Debugging macros. */ #if defined(DEBUG_RAM_CONFIG) #define RAM_DEBUG_MESSAGE(x) print_debug(x) #define RAM_DEBUG_HEX32(x) print_debug_hex32(x) #define RAM_DEBUG_HEX8(x) print_debug_hex8(x) #define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0)) #else #define RAM_DEBUG_MESSAGE(x) #define RAM_DEBUG_HEX32(x) #define RAM_DEBUG_HEX8(x) #define DUMPNORTH() #endif /* SDRAMC[7:5] - SDRAM Mode Select (SMS). */ #define RAM_COMMAND_NORMAL 0x0 #define RAM_COMMAND_NOP 0x1 #define RAM_COMMAND_PRECHARGE 0x2 #define RAM_COMMAND_MRS 0x3 #define RAM_COMMAND_CBR 0x4 /* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as * defined in DRAMC[2:0]. * * [0] == Normal 15.625 us -> 15.6 us * [1] == Reduced(.25X) 3.9 us -> 7.8 ns * [2] == Reduced(.5X) 7.8 us -> 7.8 us * [3] == Extended(2x) 31.3 us -> 31.2 us * [4] == Extended(4x) 62.5 us -> 62.4 us * [5] == Extended(8x) 125 us -> 124.8 us */ static const uint32_t refresh_rate_map[] = { 1, 5, 5, 2, 3, 4 }; /*----------------------------------------------------------------------------- Delay functions. -----------------------------------------------------------------------------*/ #define SLOW_DOWN_IO inb(0x80); static void do_delay(void) { int i; for (i = 0; i < 16; i++) { SLOW_DOWN_IO } } #define DO_DELAY do_delay(); #define EXTRA_DELAY DO_DELAY /*----------------------------------------------------------------------------- SDRAM configuration functions. -----------------------------------------------------------------------------*/ static void do_ram_command(const struct mem_controller *ctrl, uint32_t command, uint16_t jedec_mode_bits) { int i; uint16_t reg; /* Configure the RAM command. */ reg = pci_read_config16(ctrl->d0, SDRAMC); reg &= 0xff1f; /* Clear bits 7-5. */ reg |= (uint16_t)(command << 5); pci_write_config16(ctrl->d0, SDRAMC, reg); /* RAM_COMMAND_NORMAL affects only the memory controller and doesn't need to be "sent" to the DIMMs. */ /* if (command == RAM_COMMAND_NORMAL) return; */ /* Note: 2^23 == 8 MB (440BX stores multiples of 8 MB in DRB regs). */ /* We shift 8 by 23 to make a total of 64 MB. */ RAM_DEBUG_MESSAGE(" Sending RAM command to 0x"); RAM_DEBUG_HEX32((0x8 << 23) + jedec_mode_bits); RAM_DEBUG_MESSAGE("\r\n"); /* read32(0x0 + jedec_mode_bits); */ read32((0x8 << 23) + jedec_mode_bits); } /*----------------------------------------------------------------------------- DIMM-independant configuration functions. -----------------------------------------------------------------------------*/ static void spd_enable_refresh(const struct mem_controller *ctrl) { uint8_t reg; int i, value; reg = pci_read_config8(ctrl->d0, DRAMC); for (i = 0; i < MAX_DIMM_SOCKETS_PER_CHANNEL; i++) { value = spd_read_byte(ctrl->channel0[i], SPD_REFRESH); if (value < 0) continue; reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)]; } pci_write_config8(ctrl->d0, DRAMC, reg); } /*----------------------------------------------------------------------------- Public interface. -----------------------------------------------------------------------------*/ static void sdram_set_registers(const struct mem_controller *ctrl) { RAM_DEBUG_MESSAGE("Northbridge prior to SDRAM init:\r\n"); DUMPNORTH(); pci_write_config8(ctrl->d0, PAM0, 0x10); pci_write_config8(ctrl->d0, PAM1, 0x11); pci_write_config8(ctrl->d0, PAM2, 0x01); pci_write_config8(ctrl->d0, PAM3, 0x00); pci_write_config8(ctrl->d0, PAM4, 0x00); pci_write_config8(ctrl->d0, PAM5, 0x00); pci_write_config8(ctrl->d0, PAM6, 0x00); pci_write_config8(ctrl->d0, 0x13, 0xd8); pci_write_config8(ctrl->d0, 0x92, 0x00); pci_write_config8(ctrl->d0, 0x0d, 0x40); pci_write_config8(ctrl->d0, 0x13, 0xd8); pci_write_config8(ctrl->d0, DRAMT, 0x00); pci_write_config8(ctrl->d0, 0x6d, 0x2a); pci_write_config8(ctrl->d0, 0x70, 0x20); pci_write_config8(ctrl->d0, SMRAM, 0x0a); pci_write_config8(ctrl->d0, 0x80, 0x02); pci_write_config8(ctrl->d0, 0x90, 0x98); pci_write_config8(ctrl->d0, 0x91, 0xcc); pci_write_config8(ctrl->d0, 0xb0, 0x80); pci_write_config8(ctrl->d0, 0xb1, 0x20); pci_write_config8(ctrl->d0, 0xb4, 0x30); pci_write_config8(ctrl->d0, 0xba, 0x45); pci_write_config8(ctrl->d0, 0xbb, 0x03); pci_write_config8(ctrl->d0, 0xbc, 0x20); pci_write_config8(ctrl->d0, 0xbd, 0x10); pci_write_config8(ctrl->d0, 0xc4, 0xff); pci_write_config8(ctrl->d0, 0xc5, 0xfd); pci_write_config8(ctrl->d0, 0xc6, 0xff); pci_write_config8(ctrl->d0, 0xc7, 0xff); pci_write_config8(ctrl->d0, 0xc8, 0x18); pci_write_config8(ctrl->d0, 0xc9, 0x0c); pci_write_config8(ctrl->d0, 0xca, 0xff); pci_write_config8(ctrl->d0, 0xcb, 0xff); pci_write_config8(ctrl->d0, 0xcc, 0x61); pci_write_config8(ctrl->d0, 0xe0, 0x4c); pci_write_config8(ctrl->d0, 0xe1, 0xad); pci_write_config8(ctrl->d0, 0xe2, 0xff); pci_write_config8(ctrl->d0, 0xe3, 0xbb); pci_write_config8(ctrl->d0, 0xe4, 0x8a); pci_write_config8(ctrl->d0, 0xe5, 0x3e); pci_write_config8(ctrl->d0, 0xe6, 0x00); /* pci_write_config8(ctrl->d0, 0xe7, 0x80); */ pci_write_config8(ctrl->d0, 0xe8, 0x2c); pci_write_config8(ctrl->d0, 0xe9, 0xd3); pci_write_config8(ctrl->d0, 0xea, 0xf7); pci_write_config8(ctrl->d0, 0xeb, 0xcf); pci_write_config8(ctrl->d0, 0xec, 0x9d); pci_write_config8(ctrl->d0, 0xed, 0x3e); pci_write_config8(ctrl->d0, 0xee, 0x00); pci_write_config8(ctrl->d0, 0xef, 0x00); /* Now set bit 7 of 0xe7 (must come last). */ pci_write_config8(ctrl->d0, 0xe7, 0x80); pci_write_config8(ctrl->d0, 0xf0, 0x40); pci_write_config8(ctrl->d0, 0xf1, 0x01); pci_write_config8(ctrl->d0, 0xf7, 0x60); /* TODO: Do this later? */ pci_write_config8(ctrl->d0, PMCR, 0x10); } static void sdram_set_spd_registers(const struct mem_controller *ctrl) { pci_write_config8(ctrl->d0, DRB0, 0x00); pci_write_config8(ctrl->d0, DRB1, 0x00); pci_write_config8(ctrl->d0, DRB2, 0x00); pci_write_config8(ctrl->d0, DRB3, 0x00); pci_write_config8(ctrl->d0, DRB4, 0x00); pci_write_config8(ctrl->d0, DRB5, 0x00); pci_write_config8(ctrl->d0, DRB6, 0x08); pci_write_config8(ctrl->d0, DRB7, 0x08); /* Don't enable refresh for now. */ pci_write_config8(ctrl->d0, DRAMC, 0x08); pci_write_config16(ctrl->d0, RPS, 0x1000); pci_write_config16(ctrl->d0, SDRAMC, 0x0110); pci_write_config16(ctrl->d0, PGPOL, 0xff23); pci_write_config32(ctrl->d0, NBXCFG, 0xff008a0c); } static void sdram_enable(int controllers, const struct mem_controller *ctrl) { /* 1. & 2. Power up and start clocks. */ RAM_DEBUG_MESSAGE("Ram Enable 1: Power up\r\n"); RAM_DEBUG_MESSAGE("Ram Enable 2: Start clocks\r\n"); /* A 200us delay is needed. */ DO_DELAY EXTRA_DELAY /* 3. Apply NOP. */ RAM_DEBUG_MESSAGE("Ram Enable 3: Apply NOP\r\n"); do_ram_command(ctrl, RAM_COMMAND_NOP, 0); EXTRA_DELAY /* 4. Precharge all. */ RAM_DEBUG_MESSAGE("Ram Enable 4: Precharge all\r\n"); do_ram_command(ctrl, RAM_COMMAND_PRECHARGE, 0); EXTRA_DELAY /* 5. Issue EMRS to enable DLL (not needed on 440BX). */ /* 6. Reset DLL (not needed on 440BX). */ /* 7. Precharge all (not needed on 440BX). */ /* 8. Perform eight AUTO REFRESH / CBR cycles. */ RAM_DEBUG_MESSAGE("Ram Enable 8: CBR\r\n"); do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY do_ram_command(ctrl, RAM_COMMAND_CBR, 0); EXTRA_DELAY /* 9. Mode register set. */ RAM_DEBUG_MESSAGE("Ram Enable 9: Mode register set\r\n"); do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0); /* do_ram_command(ctrl, RAM_COMMAND_MRS, 0x150); */ /* do_ram_command(ctrl, RAM_COMMAND_MRS, 0x1d0 ^ 0xff8); */ EXTRA_DELAY EXTRA_DELAY /* 10. DDR Receive FIFO Resync (not needed on 440BX). */ /* 11. Normal operation. */ RAM_DEBUG_MESSAGE("Ram Enable 11: Normal operation\r\n"); do_ram_command(ctrl, RAM_COMMAND_NORMAL, 0); EXTRA_DELAY /* Finally enable refresh. */ RAM_DEBUG_MESSAGE("Finally enabling refresh\r\n"); spd_enable_refresh(ctrl); EXTRA_DELAY RAM_DEBUG_MESSAGE("Northbridge following SDRAM init:\r\n"); DUMPNORTH(); }
minicom.cap
Description: application/cap
signature.asc
Description: Digital signature
-- linuxbios mailing list linuxbios@linuxbios.org http://www.openbios.org/mailman/listinfo/linuxbios