2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2007 Corey Osgood <corey@slightlyhackish.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <sdram_mode.h>
27 /*-----------------------------------------------------------------------------
28 Macros and definitions.
29 -----------------------------------------------------------------------------*/
31 /* Uncomment this to enable debugging output. */
32 // #define DEBUG_RAM_SETUP 1
34 /* Debugging macros. */
35 #if defined(DEBUG_RAM_SETUP)
36 #define PRINT_DEBUG(x) print_debug(x)
37 #define PRINT_DEBUG_HEX8(x) print_debug_hex8(x)
38 #define PRINT_DEBUG_HEX16(x) print_debug_hex16(x)
39 #define PRINT_DEBUG_HEX32(x) print_debug_hex32(x)
40 #define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
42 #define PRINT_DEBUG(x)
43 #define PRINT_DEBUG_HEX8(x)
44 #define PRINT_DEBUG_HEX16(x)
45 #define PRINT_DEBUG_HEX32(x)
49 /* DRAMT[7:5] - SDRAM Mode Select (SMS). */
50 #define RAM_COMMAND_SELF_REFRESH 0x0 /* Disable refresh */
51 #define RAM_COMMAND_NORMAL 0x1 /* Refresh: 15.6/11.7us for 100/133MHz */
52 #define RAM_COMMAND_NORMAL_FR 0x2 /* Refresh: 7.8/5.85us for 100/133MHz */
53 #define RAM_COMMAND_NOP 0x4 /* NOP command */
54 #define RAM_COMMAND_PRECHARGE 0x5 /* All bank precharge */
55 #define RAM_COMMAND_MRS 0x6 /* Mode register set */
56 #define RAM_COMMAND_CBR 0x7 /* CBR */
58 /*-----------------------------------------------------------------------------
59 SDRAM configuration functions.
60 -----------------------------------------------------------------------------*/
63 * Send the specified RAM command to all DIMMs.
68 static void do_ram_command(uint32_t command, uint32_t addr_offset,
73 /* TODO: Support for multiple DIMMs. */
75 /* Configure the RAM command. */
76 reg = pci_read_config8(PCI_DEV(0, 0, 0), DRAMT);
77 reg &= 0x1f; /* Clear bits 7-5. */
79 pci_write_config8(PCI_DEV(0, 0, 0), DRAMT, reg);
81 /* RAM_COMMAND_NORMAL affects only the memory controller and
82 doesn't need to be "sent" to the DIMMs. */
83 /* if (command == RAM_COMMAND_NORMAL) return; */
85 PRINT_DEBUG(" Sending RAM command 0x");
86 PRINT_DEBUG_HEX8(reg);
87 PRINT_DEBUG(" to 0x");
88 PRINT_DEBUG_HEX32(0 + addr_offset); // FIXME
91 /* Read from (DIMM start address + addr_offset). */
92 read32(0 + addr_offset); //first offset is always 0
93 read32(row_offset + addr_offset);
96 /*-----------------------------------------------------------------------------
97 DIMM-independant configuration functions.
98 -----------------------------------------------------------------------------*/
101 * Set DRP - DRAM Row Population Register (Device 0).
103 static void spd_set_dram_size(uint32_t row_offset)
105 /* The variables drp and dimm_size have to be ints since all the
106 * SMBus-related functions return ints, and its just easier this way.
108 int i, drp, dimm_size;
112 for (i = 0; i < DIMM_SOCKETS; i++) {
113 /* First check if a DIMM is actually present. */
114 if (smbus_read_byte(DIMM_SPD_BASE + i, 2) == 4) {
115 print_debug("Found DIMM in slot ");
119 dimm_size = smbus_read_byte(DIMM_SPD_BASE + i, 31);
121 /* WISHLIST: would be nice to display it as decimal? */
122 print_debug("DIMM is 0x");
123 print_debug_hex8(dimm_size * 4);
124 print_debug("MB\r\n");
126 /* The i810 can't handle DIMMs larger than 128MB per
127 * side. This will fail if the DIMM uses a
128 * non-supported DRAM tech, and can't be used until
129 * buffers are done dynamically.
130 * Note: the factory BIOS just dies if it spots this :D
132 if (dimm_size > 32) {
133 print_err("DIMM row sizes larger than 128MB not"
134 "supported on i810\r\n");
136 ("Attempting to treat as 128MB DIMM\r\n");
140 /* Set the row offset, in KBytes (should this be
141 * Kbits?). Note that this offset is the start of the
144 row_offset = (dimm_size * 4 * 1024);
146 /* This is the way I was doing this, it's provided
147 * mainly as an alternative to the "new" way.
152 if (dimm_size == 0x2)
155 else if (dimm_size == 0x4)
158 else if (dimm_size == 0x8)
161 else if (dimm_size == 0x10)
164 else if (dimm_size == 0x20)
167 print_debug("Ram Size not supported\r\n");
170 /* This array is provided in raminit.h, because it got
171 * extremely messy. The above way is cleaner, but
172 * doesn't support any asymetrical/odd configurations.
174 dimm_size = translate_spd_to_i82810[dimm_size];
176 print_debug("After translation, dimm_size is 0x");
177 print_debug_hex8(dimm_size);
180 /* If the DIMM is dual-sided, the DRP value is +2 */
181 /* TODO: Figure out asymetrical configurations. */
182 if ((smbus_read_byte(DIMM_SPD_BASE + i, 127) | 0xf) ==
184 print_debug("DIMM is dual-sided\r\n");
188 print_debug("No DIMM found in slot ");
192 /* If there's no DIMM in the slot, set value to 0. */
196 /* Put in dimm_size to reflect the current DIMM. */
197 drp |= dimm_size << (i * 4);
200 print_debug("DRP calculated to 0x");
201 print_debug_hex8(drp);
204 pci_write_config8(PCI_DEV(0, 0, 0), DRP, drp);
207 static void set_dram_timing(void)
209 /* TODO, for now using default, hopefully safe values. */
210 // pci_write_config8(PCI_DEV(0, 0, 0), DRAMT, 0x00);
214 * TODO: BUFF_SC needs to be set according to the DRAM tech (x8, x16,
215 * or x32), but the datasheet doesn't list all the detaisl. Currently, it
216 * needs to be pulled from the output of 'lspci -xxx Rx92'.
218 * Common results (tested on actual hardware) are:
220 * (DRP: c = 128MB dual sided, d = 128MB single sided, f = 256MB dual sided)
222 * BUFF_SC TOM DRP DIMM0 DIMM1
223 * ----------------------------------------------------------------------------
224 * 0x3356 128MB 0x0c 128MB dual-sided -
225 * 0xcc56 128MB 0xc0 - 128MB dual-sided
226 * 0x77da 128MB 0x0d 128MB single-sided -
227 * 0xddda 128MB 0xd0 - 128MB single-sided
228 * 0x0001 256MB 0xcc 128MB dual-sided 128MB dual-sided
229 * 0x55c6 256MB 0xdd 128MB single-sided 128MB single-sided
230 * 0x4445 256MB 0xcd 128MB single-sided 128MB dual-sided
231 * 0x1145 256MB 0xdc 128MB dual-sided 128MB single-sided
232 * 0x3356 256MB 0x0f 256MB dual-sided -
233 * 0xcc56 256MB 0xf0 - 256MB dual-sided
234 * 0x0001 384MB 0xcf 256MB dual-sided 128MB dual-sided
235 * 0x0001 384MB 0xfc 128MB dual-sided 256MB dual-sided
236 * 0x1145 384MB 0xdf 256MB dual-sided 128MB single-sided
237 * 0x4445 384MB 0xfd 128MB single-sided 256MB dual-sided
238 * 0x0001 512MB 0xff 256MB dual-sided 256MB dual-sided
240 static void set_dram_buffer_strength(void)
242 pci_write_config16(PCI_DEV(0, 0, 0), BUFF_SC, 0x77da);
245 /*-----------------------------------------------------------------------------
247 -----------------------------------------------------------------------------*/
252 static void sdram_set_registers(void)
257 pci_write_config8(PCI_DEV(0, 0, 0), GMCHCFG, 0x60);
259 /* PAMR: Programmable Attributes Register
260 * Every pair of bits controls an address range:
261 * 00 = Disabled, all accesses are forwarded to the ICH
267 * 7:6 000F0000 - 000FFFFF
268 * 5:4 000E0000 - 000EFFFF
269 * 3:2 000D0000 - 000DFFFF
270 * 1:0 000C0000 - 000CFFFF
273 /* Ideally, this should be R/W for as many ranges as possible. */
274 pci_write_config8(PCI_DEV(0, 0, 0), PAM, 0xff);
276 /* Enabling the VGA Framebuffer currently screws up the rest of the boot.
279 /* Enable 1MB framebuffer. */
280 //pci_write_config8(PCI_DEV(0, 0, 0), SMRAM, 0xC0);
282 //val = pci_read_config16(PCI_DEV(0, 0, 0), MISSC);
283 /* Preserve reserved bits. */
285 /* Set graphics cache window to 32MB, no power throttling. */
287 //pci_write_config16(PCI_DEV(0, 0, 0), MISSC, val);
289 //val = pci_read_config8(PCI_DEV(0, 0, 0), MISSC2);
290 /* Enable graphics palettes and clock gating (not optional!) */
292 //pci_write_config8(PCI_DEV(0, 0, 0), MISSC2, val);
298 static void sdram_set_spd_registers(void)
300 /* spd_set_dram_size() moved into sdram_enable() to prevent having
301 * to pass a variable between here and there.
303 set_dram_buffer_strength();
311 static void sdram_enable(void)
315 /* Todo: this will currently work with either one dual sided or two
316 * single sided DIMMs. Needs to work with 2 dual sided DIMMs in the
321 spd_set_dram_size(row_offset);
324 PRINT_DEBUG("RAM Enable 1: Apply NOP\r\n");
325 do_ram_command(RAM_COMMAND_NOP, 0, row_offset);
328 /* 2. Precharge all. Wait tRP. */
329 PRINT_DEBUG("RAM Enable 2: Precharge all\r\n");
330 do_ram_command(RAM_COMMAND_PRECHARGE, 0, row_offset);
333 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
334 PRINT_DEBUG("RAM Enable 3: CBR\r\n");
335 do_ram_command(RAM_COMMAND_CBR, 0, row_offset);
336 for (i = 0; i < 8; i++) {
342 /* 4. Mode register set. Wait two memory cycles. */
343 PRINT_DEBUG("RAM Enable 4: Mode register set\r\n");
344 do_ram_command(RAM_COMMAND_MRS, 0x1d0, row_offset);
347 /* 5. Normal operation (enables refresh) */
348 PRINT_DEBUG("RAM Enable 5: Normal operation\r\n");
349 do_ram_command(RAM_COMMAND_NORMAL, 0, row_offset);
352 PRINT_DEBUG("Northbridge following SDRAM init:\r\n");