2 * This file is part of the coreboot project.
4 * Copyright (C) 2009-2010 iWave Systems
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <cpu/x86/mtrr.h>
22 #include <cpu/x86/cache.h>
27 #define DEBUG_RAM_SETUP
28 #define SOFTSTRSP(base, off) *((volatile u8 *)((base) + (off)))
30 /* Debugging macros. */
31 #if defined(DEBUG_RAM_SETUP)
32 #define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
34 #define PRINTK_DEBUG(x...)
37 #define BOOT_MODE_RESUME 1
38 #define BOOT_MODE_NORMAL 0
40 #include "port_access.c"
42 static void detect_fsb(struct sys_info *sysinfo)
46 reg32 = sch_port_access_read(5, 3, 4);
48 sysinfo->fsb_frequency = 533;
50 sysinfo->fsb_frequency = 400;
53 static u32 detect_softstrap_base(void)
57 reg32 = sch_port_access_read(4, 0x71, 2);
62 base_addr = 0xFFFB0000;
65 base_addr = 0xFFFC0000;
68 base_addr = 0xFFFD0000;
71 base_addr = 0xFFFE0000;
77 static void detect_softstraps(struct sys_info *sysinfo)
80 u32 sbase = detect_softstrap_base();
82 reg8 = SOFTSTRSP(sbase, 0x87f2);
83 sysinfo->ranks = reg8;
85 sysinfo->ram_param_source = RAM_PARAM_SOURCE_SPD;
86 /* FIXME: Implement SPD reading. */
87 die("No support for reading DIMM config from SPD yet!");
90 sysinfo->ram_param_source = RAM_PARAM_SOURCE_SOFTSTRAP;
91 /* Timings from soft strap */
92 reg8 = SOFTSTRSP(sbase, 0x87f0);
102 /* Geometry from Softstrap */
103 reg8 = SOFTSTRSP(sbase, 0x87f1);
107 sysinfo->device_density = temp;
110 sysinfo->data_width = temp;
112 /* Refresh rate default 7.8us */
113 sysinfo->refresh = 3;
117 static void program_sch_dram_data(struct sys_info *sysinfo)
122 * Program DRP DRAM Rank Population and Interface Register as per data
123 * in sysinfo SCH port 1 register 0..0xFF.
126 sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
127 reg32 &= ~(DRP_FIELDS); /* Clear all DRP fields we'll change. */
128 /* Rank0 Device Width, Density, Enable */
129 reg32 |= sysinfo->data_width | (sysinfo->device_density << 1) | (1 << 3);
130 /* Rank1 Device Width, Density, Enable */
131 reg32 |= (sysinfo->data_width << 4)
132 | ((sysinfo->device_density) << 5) | (1 << 7);
133 sch_port_access_write(SCH_MSG_DUNIT_PORT,
134 SCH_MSG_DUNIT_REG_DRP, 4, reg32);
137 * Program DTR DRAM Timing Register as per data in sysinfo SCH port 1
140 * tRD_dly = 2 (15:13 = 010b)
144 sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4);
145 reg32 &= ~(DTR_FIELDS); /* Clear all DTR fields we'll change. */
147 reg32 = (sysinfo->trp);
148 reg32 |= (sysinfo->trcd) << 2;
149 reg32 |= (sysinfo->cl) << 4;
150 reg32 |= 0X4000; /* tRD_dly = 2 (15:13 = 010b) */
151 sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4,
155 * DCO DRAM Controller Operation Register as per data in sysinfo
156 * SCH port 1 register 2 0xF.
159 sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4);
160 reg32 &= ~(DCO_FIELDS); /* Clear all DTR fields we'll change. */
162 if (sysinfo->fsb_frequency == 533)
166 reg32 = 0x006911c; // FIXME ?
168 sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4,
172 static void program_dll_config(struct sys_info *sysinfo)
174 if (sysinfo->fsb_frequency == 533) {
175 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x21, 4, 0x46464646);
176 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x22, 4, 0x46464646);
178 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x21, 4, 0x58585858);
179 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x22, 4, 0x58585858);
181 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x23, 4, 0x2222);
182 if (sysinfo->fsb_frequency == 533)
183 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x20, 4, 0x993B);
185 sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x20, 4, 0xCC3B);
188 static void do_jedec_init(struct sys_info *sysinfo)
190 u32 reg32, rank, cmd, temp, num_ranks;
192 /* Performs JEDEC memory initializattion for all memory rows */
195 sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
196 reg32 |= DRP_CKE_DIS;
197 sch_port_access_write(SCH_MSG_DUNIT_PORT,
198 SCH_MSG_DUNIT_REG_DRP, 4, reg32);
200 sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
202 num_ranks = sysinfo->ranks;
206 reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT,
207 SCH_MSG_DUNIT_REG_DRP, 4);
208 reg32 &= ~(DRP_SCK_DIS); /* Enable all SCK/SCKB by def. */
209 sch_port_access_write(1, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
210 /* Program misc. SCH registers on rank 0 initialization. */
211 reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT,
212 SCH_MSG_DUNIT_REG_DRP, 4);
214 program_dll_config(sysinfo);
216 printk(BIOS_DEBUG, "Setting up RAM \n");
220 * reg32 = inb(ACPI_BASE + 8); PM1 Timer
224 * reg32 = inb(ACPI_BASE + 8);PM1 Timer
226 * } while (reg32 < 0x2EE);
231 cmd |= SCH_DRAMINIT_CMD_NOP;
232 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
233 SCH_MSG_DUNIT_PORT, 0, cmd);
235 reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT,
236 SCH_MSG_DUNIT_REG_DRP, 4);
237 reg32 &= 0xFFFF9FFF; /* Clear both the CKE static disables. */
238 sch_port_access_write(SCH_MSG_DUNIT_PORT,
239 SCH_MSG_DUNIT_REG_DRP, 4, reg32);
241 * Wait 400ns (not needed when executing from flash).
244 reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT,
245 SCH_MSG_DUNIT_REG_DRP, 4);
247 cmd |= SCH_DRAMINIT_CMD_PALL;
248 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
249 SCH_MSG_DUNIT_PORT, 0, cmd);
252 * EMRS(2); High temp self refresh=disabled,
253 * partial array self refresh=full.
256 cmd |= SCH_DRAMINIT_CMD_EMRS2;
257 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
258 SCH_MSG_DUNIT_PORT, 0, cmd);
260 /* EMRS(3) (no command). */
262 cmd |= SCH_DRAMINIT_CMD_EMRS3;
263 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
264 SCH_MSG_DUNIT_PORT, 0, cmd);
266 /* EMRS(1); Enable DLL (Leave all bits in the command at 0). */
268 cmd |= SCH_DRAMINIT_CMD_EMRS1;
269 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
270 SCH_MSG_DUNIT_PORT, 0, cmd);
272 /* MRS; Reset DLL (Set memory address bit 8). */
274 cmd |= SCH_DRAMINIT_CMD_MRS;
275 cmd |= (SCH_JEDEC_DLLRESET << SCH_DRAMINIT_ADDR_OFFSET);
276 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
277 SCH_MSG_DUNIT_PORT, 0, cmd);
281 cmd |= SCH_DRAMINIT_CMD_PALL;
282 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
283 SCH_MSG_DUNIT_PORT, 0, cmd);
285 /* Issue 2 auto-refresh commands. */
287 cmd |= SCH_DRAMINIT_CMD_AREF;
288 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
289 SCH_MSG_DUNIT_PORT, 0, cmd);
290 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
291 SCH_MSG_DUNIT_PORT, 0, cmd);
293 /* MRS command including tCL, tWR, burst length (always 4). */
295 cmd |= (SCH_DRAMINIT_CMD_MRS + JEDEC_STATIC_PARAM); /* Static param */
297 temp += TCL_LOW; /* Adjust for the TCL base. */
298 temp = temp << ((SCH_JEDEC_CL_OFFSET
299 + SCH_DRAMINIT_ADDR_OFFSET)); /* Ready the CAS latency */
301 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
302 SCH_MSG_DUNIT_PORT, 0, cmd);
305 * Wait 200 clocks (max of 1us, so no need to delay).
306 * Issue EMRS(1):OCD default.
309 cmd |= SCH_DRAMINIT_CMD_EMRS1;
310 cmd |= (SCH_JEDEC_OCD_DEFAULT << SCH_DRAMINIT_ADDR_OFFSET);
311 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
312 SCH_MSG_DUNIT_PORT, 0, cmd);
314 /* Issue EMRS(1): OCD cal. mode exit. */
316 cmd |= SCH_DRAMINIT_CMD_EMRS1;
317 cmd |= (SCH_JEDEC_DQS_DIS << SCH_DRAMINIT_ADDR_OFFSET);
318 sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT,
319 SCH_MSG_DUNIT_PORT, 0, cmd);
320 rank += SCH_DRAMINIT_RANK_MASK;
326 * @param boot_mode 0 = normal, 1 = resume
328 void sdram_initialize(int boot_mode)
330 struct sys_info sysinfo;
333 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
335 memset(&sysinfo, 0, sizeof(sysinfo));
337 detect_fsb(&sysinfo);
338 detect_softstraps(&sysinfo);
340 program_sch_dram_data(&sysinfo);
343 if (boot_mode == BOOT_MODE_NORMAL)
344 do_jedec_init(&sysinfo);
346 program_dll_config(&sysinfo);
348 /* RAM init complete. */
350 sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4);
352 reg32 |= ((sysinfo.refresh) << 2);
354 sch_port_access_write(SCH_MSG_DUNIT_PORT,
355 SCH_MSG_DUNIT_REG_DCO, 4, reg32);
357 /* Setting up TOM. */
359 reg32 = reg32 >> sysinfo.data_width;
360 reg32 = reg32 << sysinfo.device_density;
361 reg32 = reg32 << sysinfo.ranks;
363 sch_port_access_write(2, 8, 4, reg32);
366 if (boot_mode == BOOT_MODE_RESUME)
367 sch_port_access_write_ram_cmd(SCH_OPCODE_WAKEFULLON,
368 SCH_MSG_DUNIT_PORT, 0, 0);
370 sch_port_access_write(2, 0, 4, 0x98);
371 sch_port_access_write(2, 3, 4, 0x7);
372 sch_port_access_write(3, 2, 4, 0x408);
373 sch_port_access_write(4, 0x71, 4, 0x600);