static void sdram_enable(device_t dev, u8 *rank_address) { u8 i; /* 1. Apply NOP. */ PRINT_DEBUG_MEM("RAM Enable 1: Apply NOP\n"); do_ram_command(dev, RAM_COMMAND_NOP); udelay(100); read32(rank_address + 0x10); /* 2. Precharge all. */ udelay(400); PRINT_DEBUG_MEM("RAM Enable 2: Precharge all\n"); do_ram_command(dev, RAM_COMMAND_PRECHARGE); read32(rank_address + 0x10); /* 3. Mode register set. */ PRINT_DEBUG_MEM("RAM Enable 3: Mode register set\n"); do_ram_command(dev, RAM_COMMAND_MRS); read32(rank_address + 0x120000); /* EMRS DLL Enable */ read32(rank_address + 0x800); /* MRS DLL Reset */ /* 4. Precharge all again. */ PRINT_DEBUG_MEM("RAM Enable 4: Precharge all\n"); do_ram_command(dev, RAM_COMMAND_PRECHARGE); read32(rank_address + 0x0); /* 5. Perform 8 refresh cycles. Wait tRC each time. */ PRINT_DEBUG_MEM("RAM Enable 5: CBR\n"); do_ram_command(dev, RAM_COMMAND_CBR); for (i = 0; i < 8; i++) { read32(rank_address + 0x20); udelay(100); } /* 6. Mode register set. */ PRINT_DEBUG_MEM("RAM Enable 6: Mode register set\n"); /* Safe value for now, BL=8, WR=5, CAS=4 */ /* * (E)MRS values are from the BPG. No direct explanation is given, but * they should somehow conform to the JEDEC DDR2 SDRAM Specification * (JESD79-2C). */ do_ram_command(dev, RAM_COMMAND_MRS); read32(rank_address + 0x002258); /* MRS command */ read32(rank_address + 0x121c20); /* EMRS OCD Default */ read32(rank_address + 0x120020); /* EMRS OCD Calibration Mode Exit */ /* 8. Normal operation */ PRINT_DEBUG_MEM("RAM Enable 7: Normal operation\n"); do_ram_command(dev, RAM_COMMAND_NORMAL); read32(rank_address + 0x30); }
static void initialize_dimm_rows(void) { int i, row; u8 dimm_start, dimm_end; unsigned device; dimm_start = 0; for (row = 0; row < (DIMM_SOCKETS * 2); row++) { switch (row) { case 0: device = DIMM0; break; case 1: device = DIMM0; break; case 2: device = DIMM0 + 1; break; case 3: device = DIMM0 + 1; break; } dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row); if (dimm_end > dimm_start) { printk(BIOS_DEBUG, "Initializing SDRAM Row %u\n", row); /* NOP command */ PRINTK_DEBUG(" NOP\n"); do_ram_command(RAM_COMMAND_NOP); ram_read32(dimm_start, 0); udelay(200); /* Pre-charge all banks (at least 200 us after NOP) */ PRINTK_DEBUG(" Pre-charging all banks\n"); do_ram_command(RAM_COMMAND_PRECHARGE); ram_read32(dimm_start, 0); udelay(1); /* 8 CBR refreshes (Auto Refresh) */ PRINTK_DEBUG(" 8 CBR refreshes\n"); for (i = 0; i < 8; i++) { do_ram_command(RAM_COMMAND_CBR); ram_read32(dimm_start, 0); udelay(1); } /* MRS command */ /* TODO: Set offset 0x1d0 according to DRT values */ PRINTK_DEBUG(" MRS\n"); do_ram_command(RAM_COMMAND_MRS); ram_read32(dimm_start, 0x1d0); udelay(2); /* Set GMCH-M Mode Select bits back to NORMAL operation mode */ PRINTK_DEBUG(" Normal operation mode\n"); do_ram_command(RAM_COMMAND_NORMAL); ram_read32(dimm_start, 0); udelay(1); /* Perform a dummy memory read/write cycle */ PRINTK_DEBUG(" Performing dummy read/write\n"); ram_read32(dimm_start, 0x55aa55aa); udelay(1); } /* Set the start of the next DIMM. */ dimm_start = dimm_end; } }