2 * This file is part of the coreboot project.
4 * Copyright (C) 2008-2010 Joseph Smith <joe@settoplinux.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <sdram_mode.h>
25 #include "lib/debug.c"
28 /*-----------------------------------------------------------------------------
29 Macros and definitions.
30 -----------------------------------------------------------------------------*/
32 /* Uncomment this to enable debugging output. */
33 /* #define DEBUG_RAM_SETUP 1 */
35 /* Debugging macros. */
36 #if defined(DEBUG_RAM_SETUP)
37 #define PRINT_DEBUG(x) print_debug(x)
38 #define PRINT_DEBUG_HEX8(x) print_debug_hex8(x)
39 #define PRINT_DEBUG_HEX16(x) print_debug_hex16(x)
40 #define PRINT_DEBUG_HEX32(x) print_debug_hex32(x)
41 #define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
43 #define PRINT_DEBUG(x)
44 #define PRINT_DEBUG_HEX8(x)
45 #define PRINT_DEBUG_HEX16(x)
46 #define PRINT_DEBUG_HEX32(x)
50 /* DRC[10:8] - Refresh Mode Select (RMS).
51 * 0x0 for Refresh Disabled (Self Refresh)
52 * 0x1 for Refresh interval 15.6 us for 133MHz
53 * 0x2 for Refresh interval 7.8 us for 133MHz
54 * 0x7 /* Refresh interval 128 Clocks. (Fast Refresh Mode)
56 #define RAM_COMMAND_REFRESH 0x1
58 /* DRC[6:4] - SDRAM Mode Select (SMS). */
59 #define RAM_COMMAND_SELF_REFRESH 0x0
60 #define RAM_COMMAND_NOP 0x1
61 #define RAM_COMMAND_PRECHARGE 0x2
62 #define RAM_COMMAND_MRS 0x3
63 #define RAM_COMMAND_CBR 0x6
64 #define RAM_COMMAND_NORMAL 0x7
66 /* DRC[29] - Initialization Complete (IC). */
67 #define RAM_COMMAND_IC 0x1
69 /*-----------------------------------------------------------------------------
70 DIMM-initialization functions.
71 -----------------------------------------------------------------------------*/
73 static void do_ram_command(uint32_t command)
77 /* Configure the RAM command. */
78 reg32 = pci_read_config32(NORTHBRIDGE, DRC);
79 /* Clear bits 29, 10-8, 6-4. */
81 reg32 |= command << 4;
82 pci_write_config32(NORTHBRIDGE, DRC, reg32);
83 PRINT_DEBUG("RAM command 0x");
84 PRINT_DEBUG_HEX32(reg32);
88 static void ram_read32(uint8_t dimm_start, uint32_t offset)
90 if (offset == 0x55aa55aa) {
91 PRINT_DEBUG(" Reading RAM at 0x");
92 PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
93 PRINT_DEBUG(" => 0x");
94 PRINT_DEBUG_HEX32(read32(dimm_start * 32 * 1024 * 1024));
97 PRINT_DEBUG(" Writing RAM at 0x");
98 PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
99 PRINT_DEBUG(" <= 0x");
100 PRINT_DEBUG_HEX32(offset);
102 write32(dimm_start * 32 * 1024 * 1024, offset);
104 PRINT_DEBUG(" Reading RAM at 0x");
105 PRINT_DEBUG_HEX32(dimm_start * 32 * 1024 * 1024);
106 PRINT_DEBUG(" => 0x");
107 PRINT_DEBUG_HEX32(read32(dimm_start * 32 * 1024 * 1024));
110 PRINT_DEBUG(" Sending RAM command to 0x");
111 PRINT_DEBUG_HEX32((dimm_start * 32 * 1024 * 1024) + offset);
113 read32((dimm_start * 32 * 1024 * 1024) + offset);
117 static void initialize_dimm_rows(void)
120 uint8_t dimm_start, dimm_end;
125 for (row = 0; row < (DIMM_SOCKETS * 2); row++) {
129 device = DIMM_SPD_BASE;
132 device = DIMM_SPD_BASE;
135 device = DIMM_SPD_BASE + 1;
138 device = DIMM_SPD_BASE + 1;
142 dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row);
144 if (dimm_end > dimm_start) {
145 print_debug("Initializing SDRAM Row ");
146 print_debug_hex8(row);
150 PRINT_DEBUG(" NOP ");
151 do_ram_command(RAM_COMMAND_NOP);
152 ram_read32(dimm_start, 0);
155 /* Pre-charge all banks (at least 200 us after NOP) */
156 PRINT_DEBUG(" Pre-charging all banks ");
157 do_ram_command(RAM_COMMAND_PRECHARGE);
158 ram_read32(dimm_start, 0);
161 /* 8 CBR refreshes (Auto Refresh) */
162 PRINT_DEBUG(" 8 CBR refreshes ");
163 for (i = 0; i < 8; i++) {
164 do_ram_command(RAM_COMMAND_CBR);
165 ram_read32(dimm_start, 0);
170 /* TODO: Set offset 0x1d0 according to DRT values */
171 PRINT_DEBUG(" MRS ");
172 do_ram_command(RAM_COMMAND_MRS);
173 ram_read32(dimm_start, 0x1d0);
176 /* Set GMCH-M Mode Select bits back to NORMAL operation mode */
177 PRINT_DEBUG(" Normal operation mode ");
178 do_ram_command(RAM_COMMAND_NORMAL);
179 ram_read32(dimm_start, 0);
182 /* Perform a dummy memory read/write cycle */
183 PRINT_DEBUG(" Performing dummy read/write\r\n");
184 ram_read32(dimm_start, 0x55aa55aa);
187 /* Set the start of the next DIMM. */
188 dimm_start = dimm_end;
192 /*-----------------------------------------------------------------------------
193 DIMM-independant configuration functions.
194 -----------------------------------------------------------------------------*/
201 static struct dimm_size spd_get_dimm_size(unsigned device)
204 int i, module_density, dimm_banks;
206 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
207 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
209 /* Find the size of side1. */
210 /* Find the larger value. The larger value is always side1. */
211 for (i = 512; i >= 0; i >>= 1) {
212 if ((module_density & i) == i) {
218 /* Set to 0 in case it's single sided. */
221 /* Test if it's a dual-sided DIMM. */
222 if (dimm_banks > 1) {
223 /* Test to see if there's a second value, if so it's asymmetrical. */
224 if (module_density != i) {
225 /* Find the second value, picking up where we left off. */
226 /* i >>= 1 done initially to make sure we don't get the same value again. */
227 for (i >>= 1; i >= 0; i >>= 1) {
228 if (module_density == (sz.side1 | i)) {
233 /* If not, it's symmetrical */
239 /* SPD byte 31 is the memory size divided by 4 so we
240 * need to muliply by 4 to get the total size.
247 static void set_dram_row_boundaries(void)
249 int i, value, drb1, drb2;
251 for (i = 0; i < DIMM_SOCKETS; i++) {
254 device = DIMM_SPD_BASE + i;
258 /* First check if a DIMM is actually present. */
259 if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
260 print_debug("Found DIMM in slot ");
264 sz = spd_get_dimm_size(device);
266 /* WISHLIST: would be nice to display it as decimal? */
267 print_debug("DIMM is 0x");
268 print_debug_hex16(sz.side1);
269 print_debug(" on side 1\r\n");
270 print_debug("DIMM is 0x");
271 print_debug_hex16(sz.side2);
272 print_debug(" on side 2\r\n");
274 /* - Memory compatibility checks - */
275 /* Test for PC133 (i82830 only supports PC133) */
276 /* PC133 SPD9 - cycle time is always 75 */
277 if (spd_read_byte(device, SPD_MIN_CYCLE_TIME_AT_CAS_MAX) != 0x75) {
278 print_err("SPD9 DIMM Is Not PC133 Compatable\r\n");
281 /* PC133 SPD10 - access time is always 54 */
282 if (spd_read_byte(device, SPD_ACCESS_TIME_FROM_CLOCK) != 0x54) {
283 print_err("SPD10 DIMM Is Not PC133 Compatable\r\n");
287 /* The i82830 only supports a symmetrical dual-sided dimms
288 * and can't handle DIMMs smaller than 32MB per
289 * side or larger than 256MB per side.
291 if ((sz.side2 != 0) && (sz.side1 != sz.side2)) {
292 print_err("This northbridge only supports\r\n");
293 print_err("symmetrical dual-sided DIMMs\r\n");
294 print_err("booting as a single-sided DIMM\r\n");
297 if ((sz.side1 < 32)) {
298 print_err("DIMMs smaller than 32MB per side\r\n");
299 print_err("are not supported on this northbridge\r\n");
303 if ((sz.side1 > 256)) {
305 ("DIMMs larger than 256MB per side\r\n");
307 ("are not supported on this northbridge\r\n");
310 /* - End Memory compatibility checks - */
312 /* We need to divide size by 32 to set up the
316 drb1 = sz.side1 / 32;
318 drb2 = sz.side2 / 32;
320 PRINT_DEBUG("No DIMM found in slot ");
324 /* If there's no DIMM in the slot, set value to 0. */
328 /* Set the value for DRAM Row Boundary Registers */
330 pci_write_config8(NORTHBRIDGE, DRB, drb1);
331 pci_write_config8(NORTHBRIDGE, DRB + 1, drb1 + drb2);
332 PRINT_DEBUG("DRB 0x");
333 PRINT_DEBUG_HEX8(DRB);
334 PRINT_DEBUG(" has been set to 0x");
335 PRINT_DEBUG_HEX8(drb1);
337 PRINT_DEBUG("DRB1 0x");
338 PRINT_DEBUG_HEX8(DRB + 1);
339 PRINT_DEBUG(" has been set to 0x");
340 PRINT_DEBUG_HEX8(drb1 + drb2);
343 value = pci_read_config8(NORTHBRIDGE, DRB + 1);
344 pci_write_config8(NORTHBRIDGE, DRB + 2, value + drb1);
345 pci_write_config8(NORTHBRIDGE, DRB + 3, value + drb1 + drb2);
346 PRINT_DEBUG("DRB2 0x");
347 PRINT_DEBUG_HEX8(DRB + 2);
348 PRINT_DEBUG(" has been set to 0x");
349 PRINT_DEBUG_HEX8(value + drb1);
351 PRINT_DEBUG("DRB3 0x");
352 PRINT_DEBUG_HEX8(DRB + 3);
353 PRINT_DEBUG(" has been set to 0x");
354 PRINT_DEBUG_HEX8(value + drb1 + drb2);
357 /* We need to set the highest DRB value to 0x64 and 0x65.
358 * These are supposed to be "Reserved" but memory will
359 * not initialize properly if we don't.
361 value = pci_read_config8(NORTHBRIDGE, DRB + 3);
362 pci_write_config8(NORTHBRIDGE, DRB + 4, value);
363 pci_write_config8(NORTHBRIDGE, DRB + 5, value);
368 static void set_dram_row_attributes(void)
370 int i, dra, col, width, value;
372 for (i = 0; i < DIMM_SOCKETS; i++) {
374 device = DIMM_SPD_BASE + i;
376 /* First check if a DIMM is actually present. */
377 if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
378 print_debug("Found DIMM in slot ");
380 print_debug(", setting DRA...\r\n");
385 col = spd_read_byte(device, SPD_NUM_COLUMNS);
388 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
390 /* calculate page size in bits */
391 value = ((1 << col) * width);
393 /* convert to Kilobytes */
394 dra = ((value / 8) >> 10);
396 /* # of banks of DIMM (single or double sided) */
397 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
401 dra = 0xF0; /* 2KB */
402 } else if (dra == 4) {
403 dra = 0xF1; /* 4KB */
404 } else if (dra == 8) {
405 dra = 0xF2; /* 8KB */
406 } else if (dra == 16) {
407 dra = 0xF3; /* 16KB */
409 print_err("Page size not supported\r\n");
412 } else if (value == 2) {
414 dra = 0x00; /* 2KB */
415 } else if (dra == 4) {
416 dra = 0x11; /* 4KB */
417 } else if (dra == 8) {
418 dra = 0x22; /* 8KB */
419 } else if (dra == 16) {
420 dra = 0x33; /* 16KB */
422 print_err("Page size not supported\r\n");
426 print_err("# of banks of DIMM not supported\r\n");
431 PRINT_DEBUG("No DIMM found in slot ");
433 PRINT_DEBUG(", setting DRA to 0xFF\r\n");
435 /* If there's no DIMM in the slot, set dra value to 0xFF. */
439 /* Set the value for DRAM Row Attribute Registers */
440 pci_write_config8(NORTHBRIDGE, DRA + i, dra);
441 PRINT_DEBUG("DRA 0x");
442 PRINT_DEBUG_HEX8(DRA + i);
443 PRINT_DEBUG(" has been set to 0x");
444 PRINT_DEBUG_HEX8(dra);
449 static void set_dram_timing(void)
451 /* Set the value for DRAM Timing Register */
452 /* TODO: Configure the value according to SPD values. */
453 pci_write_config32(NORTHBRIDGE, DRT, 0x00000010);
456 static void set_dram_buffer_strength(void)
458 /* TODO: This needs to be set according to the DRAM tech
459 * (x8, x16, or x32). Argh, Intel provides no docs on this!
460 * Currently, it needs to be pulled from the output of
464 /* Set the value for System Memory Buffer Strength Control Registers */
465 pci_write_config32(NORTHBRIDGE, BUFF_SC, 0xFC9B491B);
468 /*-----------------------------------------------------------------------------
470 -----------------------------------------------------------------------------*/
472 static void sdram_set_registers(void)
474 PRINT_DEBUG("Setting initial sdram registers....\r\n");
476 /* Calculate the value for DRT DRAM Timing Register */
479 /* Setup System Memory Buffer Strength Control Registers */
480 set_dram_buffer_strength();
482 /* Setup DRAM Row Boundary Registers */
483 set_dram_row_boundaries();
485 /* Setup DRAM Row Attribute Registers */
486 set_dram_row_attributes();
488 PRINT_DEBUG("Initial sdram registers have been set.\r\n");
491 static void northbridge_set_registers(void)
496 PRINT_DEBUG("Setting initial nothbridge registers....\r\n");
498 /* Set the value for Fixed DRAM Hole Control Register */
499 pci_write_config8(NORTHBRIDGE, FDHC, 0x00);
501 /* Set the value for Programable Attribute Map Registers
502 * Ideally, this should be R/W for as many ranges as possible.
504 pci_write_config8(NORTHBRIDGE, PAM0, 0x30);
505 pci_write_config8(NORTHBRIDGE, PAM1, 0x33);
506 pci_write_config8(NORTHBRIDGE, PAM2, 0x33);
507 pci_write_config8(NORTHBRIDGE, PAM3, 0x33);
508 pci_write_config8(NORTHBRIDGE, PAM4, 0x33);
509 pci_write_config8(NORTHBRIDGE, PAM5, 0x33);
510 pci_write_config8(NORTHBRIDGE, PAM6, 0x33);
512 /* Set the value for System Management RAM Control Register */
513 pci_write_config8(NORTHBRIDGE, SMRAM, 0x02);
515 /* Set the value for GMCH Control Register #0 */
516 pci_write_config16(NORTHBRIDGE, GCC0, 0xA072);
518 /* Set the value for Aperture Base Configuration Register */
519 pci_write_config32(NORTHBRIDGE, APBASE, 0x00000008);
521 /* Set the value for GMCH Control Register #1 */
522 switch (CONFIG_VIDEO_MB) {
523 case 512: /* 512K of memory */
526 case 1: /* 1M of memory */
529 case 8: /* 8M of memory */
532 default: /* No memory */
533 pci_write_config16(NORTHBRIDGE, GCC1, 0x0002);
537 value = pci_read_config16(NORTHBRIDGE, GCC1);
538 value |= igd_memory << 4;
539 pci_write_config16(NORTHBRIDGE, GCC1, value);
541 PRINT_DEBUG("Initial northbridge registers have been set.\r\n");
544 static void sdram_initialize(void)
549 /* Setup Initial SDRAM Registers */
550 sdram_set_registers();
552 /* 0. Wait until power/voltages and clocks are stable (200us). */
555 /* Initialize each row of memory one at a time */
556 initialize_dimm_rows();
559 PRINT_DEBUG("Enabling Refresh\r\n");
560 reg32 = pci_read_config32(NORTHBRIDGE, DRC);
561 reg32 |= (RAM_COMMAND_REFRESH << 8);
562 pci_write_config32(NORTHBRIDGE, DRC, reg32);
564 /* Set initialization complete */
565 PRINT_DEBUG("Setting initialization complete\r\n");
566 reg32 = pci_read_config32(NORTHBRIDGE, DRC);
567 reg32 |= (RAM_COMMAND_IC << 29);
568 pci_write_config32(NORTHBRIDGE, DRC, reg32);
570 /* Setup Initial Northbridge Registers */
571 northbridge_set_registers();
573 PRINT_DEBUG("Northbridge following SDRAM init:\r\n");