static void program_sch_dram_data(struct sys_info *sysinfo) { u32 reg32; /* * Program DRP DRAM Rank Population and Interface Register as per data * in sysinfo SCH port 1 register 0..0xFF. */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); reg32 &= ~(DRP_FIELDS); /* Clear all DRP fields we'll change. */ /* Rank0 Device Width, Density, Enable */ reg32 |= sysinfo->data_width | (sysinfo->device_density << 1) | (1 << 3); /* Rank1 Device Width, Density, Enable */ reg32 |= (sysinfo->data_width << 4) | ((sysinfo->device_density) << 5) | (1 << 7); sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32); /* * Program DTR DRAM Timing Register as per data in sysinfo SCH port 1 * register 1. * * tRD_dly = 2 (15:13 = 010b) * 0X3F */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4); reg32 &= ~(DTR_FIELDS); /* Clear all DTR fields we'll change. */ reg32 = (sysinfo->trp); reg32 |= (sysinfo->trcd) << 2; reg32 |= (sysinfo->cl) << 4; reg32 |= 0X4000; /* tRD_dly = 2 (15:13 = 010b) */ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4, reg32); /* * DCO DRAM Controller Operation Register as per data in sysinfo * SCH port 1 register 2 0xF. */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4); reg32 &= ~(DCO_FIELDS); /* Clear all DTR fields we'll change. */ if (sysinfo->fsb_frequency == 533) reg32 |= 1; else reg32 &= ~(BIT(0)); reg32 = 0x006911c; // FIXME ? sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4, reg32); }
static u32 detect_softstrap_base(void) { u32 reg32, base_addr; reg32 = sch_port_access_read(4, 0x71, 2); reg32 &= 0x700; reg32 = reg32 >> 7; switch (reg32) { case 7: base_addr = 0xFFFB0000; break; case 6: base_addr = 0xFFFC0000; break; case 5: base_addr = 0xFFFD0000; break; case 4: base_addr = 0xFFFE0000; break; default: base_addr = 0; die("No valid softstrap base found.\n"); } return base_addr; }
static void poulsbo_setup_Stage1Regs(void) { u32 reg32; printk(BIOS_DEBUG, "E000/F000 Routing "); reg32 = sch_port_access_read(2, 3, 4); sch_port_access_write(2, 3, 4, (reg32 | 0x6)); }
static void detect_fsb(struct sys_info *sysinfo) { u32 reg32; reg32 = sch_port_access_read(5, 3, 4); if (reg32 & BIT(3)) sysinfo->fsb_frequency = 533; else sysinfo->fsb_frequency = 400; }
/** * @param boot_mode 0 = normal, 1 = resume */ void sdram_initialize(int boot_mode) { struct sys_info sysinfo; u32 reg32; printk(BIOS_DEBUG, "Setting up RAM controller.\n"); memset(&sysinfo, 0, sizeof(sysinfo)); detect_fsb(&sysinfo); detect_softstraps(&sysinfo); program_sch_dram_data(&sysinfo); /* cold boot */ if (boot_mode == BOOT_MODE_NORMAL) do_jedec_init(&sysinfo); else program_dll_config(&sysinfo); /* RAM init complete. */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4); reg32 |= DCO_IC; reg32 |= ((sysinfo.refresh) << 2); reg32 = 0x006919c; sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4, reg32); /* Setting up TOM. */ reg32 = 0x10000000; reg32 = reg32 >> sysinfo.data_width; reg32 = reg32 << sysinfo.device_density; reg32 = reg32 << sysinfo.ranks; reg32 = 0x40000000; sch_port_access_write(2, 8, 4, reg32); /* Resume mode. */ if (boot_mode == BOOT_MODE_RESUME) sch_port_access_write_ram_cmd(SCH_OPCODE_WAKEFULLON, SCH_MSG_DUNIT_PORT, 0, 0); sch_port_access_write(2, 0, 4, 0x98); sch_port_access_write(2, 3, 4, 0x7); sch_port_access_write(3, 2, 4, 0x408); sch_port_access_write(4, 0x71, 4, 0x600); }
static void do_jedec_init(struct sys_info *sysinfo) { u32 reg32, rank, cmd, temp, num_ranks; /* Performs JEDEC memory initializattion for all memory rows */ /* Set CKE0/1 low */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); reg32 |= DRP_CKE_DIS; sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32); reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); rank = 0; num_ranks = sysinfo->ranks; do { /* Start clocks */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); reg32 &= ~(DRP_SCK_DIS); /* Enable all SCK/SCKB by def. */ sch_port_access_write(1, SCH_MSG_DUNIT_REG_DRP, 4, reg32); /* Program misc. SCH registers on rank 0 initialization. */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); if (rank == 0) program_dll_config(sysinfo); printk(BIOS_DEBUG, "Setting up RAM \n"); /* * Wait 200us * reg32 = inb(ACPI_BASE + 8); PM1 Timer * reg32 &=0xFFFFFF; * reg32 +=0x2EE; * do { * reg32 = inb(ACPI_BASE + 8);PM1 Timer * reg32 &= 0xFFFFFF; * } while (reg32 < 0x2EE); */ /* Apply NOP. */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_NOP; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* Set CKE=high. */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); reg32 &= 0xFFFF9FFF; /* Clear both the CKE static disables. */ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32); /* * Wait 400ns (not needed when executing from flash). * Precharge all. */ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4); cmd = rank; cmd |= SCH_DRAMINIT_CMD_PALL; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* * EMRS(2); High temp self refresh=disabled, * partial array self refresh=full. */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_EMRS2; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* EMRS(3) (no command). */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_EMRS3; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* EMRS(1); Enable DLL (Leave all bits in the command at 0). */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_EMRS1; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* MRS; Reset DLL (Set memory address bit 8). */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_MRS; cmd |= (SCH_JEDEC_DLLRESET << SCH_DRAMINIT_ADDR_OFFSET); sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* Precharge all. */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_PALL; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* Issue 2 auto-refresh commands. */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_AREF; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* MRS command including tCL, tWR, burst length (always 4). */ cmd = rank; cmd |= (SCH_DRAMINIT_CMD_MRS + JEDEC_STATIC_PARAM); /* Static param */ temp = sysinfo->cl; temp += TCL_LOW; /* Adjust for the TCL base. */ temp = temp << ((SCH_JEDEC_CL_OFFSET + SCH_DRAMINIT_ADDR_OFFSET)); /* Ready the CAS latency */ cmd |= temp; sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* * Wait 200 clocks (max of 1us, so no need to delay). * Issue EMRS(1):OCD default. */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_EMRS1; cmd |= (SCH_JEDEC_OCD_DEFAULT << SCH_DRAMINIT_ADDR_OFFSET); sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); /* Issue EMRS(1): OCD cal. mode exit. */ cmd = rank; cmd |= SCH_DRAMINIT_CMD_EMRS1; cmd |= (SCH_JEDEC_DQS_DIS << SCH_DRAMINIT_ADDR_OFFSET); sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd); rank += SCH_DRAMINIT_RANK_MASK; num_ranks--; } while (num_ranks); }