blob: 7e2cf81d280a9fb043f6d65d676eb6b8d9009066 [file] [log] [blame]
Stefan Reinauer278534d2008-10-29 04:51:07 +00001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer71a3d962009-07-21 21:44:24 +00004 * Copyright (C) 2007-2009 coresystems GmbH
Stefan Reinauer278534d2008-10-29 04:51:07 +00005 *
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; version 2 of the License.
9 *
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.
14 *
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
18 */
19
Patrick Georgid0835952010-10-05 09:07:10 +000020#include <console/console.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000021#include <cpu/x86/mtrr.h>
22#include <cpu/x86/cache.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000023#include <pc80/mc146818rtc.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000024#include <spd.h>
Patrick Georgid0835952010-10-05 09:07:10 +000025#include <string.h>
26#include <arch/romcc_io.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000027#include "raminit.h"
28#include "i945.h"
29
Stefan Reinauer278534d2008-10-29 04:51:07 +000030/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000031#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000032#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Stefan Reinauer278534d2008-10-29 04:51:07 +000033#else
34#define PRINTK_DEBUG(x...)
35#endif
36
Stefan Reinauer278534d2008-10-29 04:51:07 +000037#define RAM_INITIALIZATION_COMPLETE (1 << 19)
38
39#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
40#define RAM_COMMAND_NOP (0x1 << 16)
41#define RAM_COMMAND_PRECHARGE (0x2 << 16)
42#define RAM_COMMAND_MRS (0x3 << 16)
43#define RAM_COMMAND_EMRS (0x4 << 16)
44#define RAM_COMMAND_CBR (0x6 << 16)
45#define RAM_COMMAND_NORMAL (0x7 << 16)
46
47#define RAM_EMRS_1 (0x0 << 21)
48#define RAM_EMRS_2 (0x1 << 21)
49#define RAM_EMRS_3 (0x2 << 21)
50
Patrick Georgid0835952010-10-05 09:07:10 +000051static inline int spd_read_byte(unsigned device, unsigned address)
52{
53 return smbus_read_byte(device, address);
54}
55
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000056static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000057{
58 u32 reg32;
59
60 reg32 = MCHBAR32(DCC);
61 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
62 reg32 |= command;
63
64 /* Also set Init Complete */
65 if (command == RAM_COMMAND_NORMAL)
66 reg32 |= RAM_INITIALIZATION_COMPLETE;
67
68 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
69
70 MCHBAR32(DCC) = reg32; /* This is the actual magic */
71
Stefan Reinauer779b3e32008-11-10 15:43:37 +000072 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000073
74 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000075}
76
Stefan Reinauer278534d2008-10-29 04:51:07 +000077static void ram_read32(u32 offset)
78{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000079 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000080
81 read32(offset);
82}
83
Uwe Hermann01ce6012010-03-05 10:03:50 +000084#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer278534d2008-10-29 04:51:07 +000085static void sdram_dump_mchbar_registers(void)
86{
87 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000088 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000089
90 for (i=0; i<0xfff; i+=4) {
91 if (MCHBAR32(i) == 0)
92 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000093 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +000094 }
95}
96#endif
97
Stefan Reinauer24b4df52010-01-17 13:47:35 +000098static int memclk(void)
99{
100 int offset = 0;
Peter Stugee4bc0f62010-10-01 09:13:18 +0000101#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000102 offset++;
103#endif
104 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
105 case 1: return 400;
106 case 2: return 533;
107 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000108 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000109 }
110 return -1;
111}
112
Peter Stugee4bc0f62010-10-01 09:13:18 +0000113#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Peter Stuge76d91432010-10-01 10:02:33 +0000114static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000115{
116 switch (MCHBAR32(CLKCFG) & 7) {
117 case 0: return 400;
118 case 1: return 533;
119 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000120 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000121 }
Peter Stuge76d91432010-10-01 10:02:33 +0000122 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000123}
Peter Stugee4bc0f62010-10-01 09:13:18 +0000124#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Peter Stuge76d91432010-10-01 10:02:33 +0000125static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000126{
127 switch (MCHBAR32(CLKCFG) & 7) {
128 case 0: return 1066;
129 case 1: return 533;
130 case 2: return 800;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000131 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000132 }
Peter Stuge76d91432010-10-01 10:02:33 +0000133 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000134}
135#endif
136
Stefan Reinauer278534d2008-10-29 04:51:07 +0000137static int sdram_capabilities_max_supported_memory_frequency(void)
138{
139 u32 reg32;
140
Patrick Georgi77d66832010-10-01 08:02:45 +0000141#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
142 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000143#endif
144
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000145 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000146 reg32 &= (7 << 0);
147
148 switch (reg32) {
149 case 4: return 400;
150 case 3: return 533;
151 case 2: return 667;
152 }
153 /* Newer revisions of this chipset rather support faster memory clocks,
154 * so if it's a reserved value, return the fastest memory clock that we
155 * know of and can handle
156 */
157 return 667;
158}
159
160/**
161 * @brief determine whether chipset is capable of dual channel interleaved mode
162 *
163 * @return 1 if interleaving is supported, 0 otherwise
164 */
165static int sdram_capabilities_interleave(void)
166{
167 u32 reg32;
168
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000169 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000170 reg32 >>= 25;
171 reg32 &= 1;
172
173 return (!reg32);
174}
175
176/**
177 * @brief determine whether chipset is capable of two memory channels
178 *
179 * @return 1 if dual channel operation is supported, 0 otherwise
180 */
181static int sdram_capabilities_dual_channel(void)
182{
183 u32 reg32;
184
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000185 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000186 reg32 >>= 24;
187 reg32 &= 1;
188
189 return (!reg32);
190}
191
192static int sdram_capabilities_enhanced_addressing_xor(void)
193{
194 u8 reg8;
195
196 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
197 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000198
Stefan Reinauer278534d2008-10-29 04:51:07 +0000199 return (!reg8);
200}
201
202static int sdram_capabilities_two_dimms_per_channel(void)
203{
204 u8 reg8;
205
206 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
207 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000208
Stefan Reinauer278534d2008-10-29 04:51:07 +0000209 return (reg8 != 0);
210}
211
Stefan Reinauer14e22772010-04-27 06:56:47 +0000212// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000213#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000214static int sdram_capabilities_MEM4G_disable(void)
215{
216 u8 reg8;
217
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000218 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000219 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000220
Stefan Reinauer278534d2008-10-29 04:51:07 +0000221 return (reg8 != 0);
222}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000223#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000224
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000225#define GFX_FREQUENCY_CAP_166MHZ 0x04
226#define GFX_FREQUENCY_CAP_200MHZ 0x03
227#define GFX_FREQUENCY_CAP_250MHZ 0x02
228#define GFX_FREQUENCY_CAP_ALL 0x00
229
230static int sdram_capabilities_core_frequencies(void)
231{
232 u8 reg8;
233
234 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
235 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
236 reg8 >>= 1;
237
238 return (reg8);
239}
240
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000241static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000242{
243 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000244 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000245
246 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000247
Stefan Reinauer278534d2008-10-29 04:51:07 +0000248 if (reg8 & ((1<<7)|(1<<2))) {
249 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000250 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000251 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000252 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000253 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000254
Stefan Reinauer278534d2008-10-29 04:51:07 +0000255 }
256
257 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000258 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000259 reg8 &= ~(1<<7);
260 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000261 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000262 }
263
264 /* Set SLP_S3# Assertion Stretch Enable */
265 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
266 reg8 |= (1 << 3);
267 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
268
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000269 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000270 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000271 outb(0x00, 0xcf9);
272 outb(0x0e, 0xcf9);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000273 for (;;) asm("hlt"); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000274 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000275 }
276
277 /* Set DRAM initialization bit in ICH7 */
278 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
279 reg8 |= (1<<7);
280 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000281
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000282 /* clear self refresh if not wake-up from suspend */
283 if (sysinfo->boot_path != 2) {
284 MCHBAR8(0xf14) |= 3;
285 } else {
286 /* Validate self refresh config */
287 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
288 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
289 !(MCHBAR8(0xf14) & (1<<0))) {
290 do_reset = 1;
291 }
292 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
293 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
294 !(MCHBAR8(0xf14) & (1<<1))) {
295 do_reset = 1;
296 }
297 }
298
299 if (do_reset) {
300 printk(BIOS_DEBUG, "Reset required.\n");
301 outb(0x00, 0xcf9);
302 outb(0x0e, 0xcf9);
303 for (;;) asm("hlt"); /* Wait for reset! */
304 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000305}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000306
307/**
308 * @brief Get generic DIMM parameters.
309 * @param sysinfo Central memory controller information structure
310 *
311 * This function gathers several pieces of information for each system DIMM:
312 * o DIMM width (x8 / x16)
313 * o DIMM sides (single sided / dual sided)
314 *
315 * Also, some non-supported scenarios are detected.
316 */
317
318static void sdram_get_dram_configuration(struct sys_info *sysinfo)
319{
320 u32 dimm_mask = 0;
321 int i;
322
323 /**
324 * i945 supports two DIMMs, in two configurations:
325 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000326 * - single channel with two DIMMs
327 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000328 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000329 * In practice dual channel mainboards have their SPD at 0x50/0x52
330 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000331 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000332 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000333 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000334 */
335
336 if (sdram_capabilities_dual_channel()) {
337 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000338 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000339 } else {
340 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000341 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000342 }
343
344 /**
345 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000346 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000347 * return value:
348 * [0:7] lower DIMM population
349 * [8-15] higher DIMM population
350 * [16] dual channel?
351 *
352 * There are 5 different possible populations for a DIMM socket:
353 * 1. x16 double sided (X16DS)
354 * 2. x8 double sided (X8DS)
355 * 3. x16 single sided (X16SS)
356 * 4. x8 double stacked (X8DDS)
357 * 5. not populated (NC)
358 *
359 * For the return value we start counting at zero.
360 *
361 */
362
363 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
Uwe Hermannd773fd32010-11-20 20:23:08 +0000364 u8 reg8, device = DIMM0 + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000365
366 /* Initialize the socket information with a sane value */
367 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
368
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000369 /* Dual Channel not supported, but Channel 1? Bail out */
370 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000371 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000372
373 /* Two DIMMs per channel not supported, but odd DIMM number? */
374 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000375 continue;
376
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000377 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000378
379 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000380 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000381 continue;
382 }
383
384 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
385 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000386 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000387
388 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
389 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000390 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000391 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000392 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000393
394 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000395 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000396 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
397 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000398 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
400 break;
401 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000402 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
404 break;
405 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000406 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000407 }
408 break;
409 case 0x10:
410 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
411 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000412 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000413 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
414 break;
415 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000416 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000417 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
418 break;
419 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000420 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000421 }
422 break;
423 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000424 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000425 }
426
427 dimm_mask |= (1 << i);
428 }
429
430 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000431 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000432 }
433
Stefan Reinauer278534d2008-10-29 04:51:07 +0000434 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000435 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000436 }
437}
438
439/**
440 * @brief determine if any DIMMs are stacked
441 *
442 * @param sysinfo central sysinfo data structure.
443 */
444static void sdram_verify_package_type(struct sys_info * sysinfo)
445{
446 int i;
447
448 /* Assume no stacked DIMMs are available until we find one */
449 sysinfo->package = 0;
450 for (i=0; i<2*DIMM_SOCKETS; i++) {
451 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
452 continue;
453
454 /* Is the current DIMM a stacked DIMM? */
Uwe Hermannd773fd32010-11-20 20:23:08 +0000455 if (spd_read_byte(DIMM0 + i, SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000456 sysinfo->package = 1;
457 }
458}
459
460static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
461{
462 int i;
463 u8 cas_mask;
464
465 /* Setup CAS mask with all supported CAS Latencies */
466 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
467 SPD_CAS_LATENCY_DDR2_4 |
468 SPD_CAS_LATENCY_DDR2_5;
469
470 for (i=0; i<2*DIMM_SOCKETS; i++) {
471 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Uwe Hermannd773fd32010-11-20 20:23:08 +0000472 cas_mask &= spd_read_byte(DIMM0 + i, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000473 }
474
475 if(!cas_mask) {
476 die("No DDR-II modules with accepted CAS latencies found.\n");
477 }
478
479 return cas_mask;
480}
481
482static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
483{
484 int i, j, idx;
485 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000486 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000487
488 const u8 ddr2_speeds_table[] = {
489 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
490 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
491 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
492 };
493
494 const u8 spd_lookup_table[] = {
495 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
496 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
497 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
498 };
499
500 switch (sdram_capabilities_max_supported_memory_frequency()) {
501 case 400: max_ram_speed = 0; break;
502 case 533: max_ram_speed = 1; break;
503 case 667: max_ram_speed = 2; break;
504 }
505
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000506 if (fsbclk() == 533)
507 max_ram_speed = 1;
508
Stefan Reinauer278534d2008-10-29 04:51:07 +0000509 sysinfo->memory_frequency = 0;
510 sysinfo->cas = 0;
511
512 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
513 lowest_common_cas = 3;
514 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
515 lowest_common_cas = 4;
516 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
517 lowest_common_cas = 5;
518 }
519 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
520
521 for (j = max_ram_speed; j>=0; j--) {
522 int freq_cas_mask = cas_mask;
523
524 PRINTK_DEBUG("Probing Speed %d\n", j);
525 for (i=0; i<2*DIMM_SOCKETS; i++) {
526 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000527
Stefan Reinauer278534d2008-10-29 04:51:07 +0000528 PRINTK_DEBUG(" DIMM: %d\n", i);
529 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
530 continue;
531 }
532
Uwe Hermannd773fd32010-11-20 20:23:08 +0000533 current_cas_mask = spd_read_byte(DIMM0 + i, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000534
535 while (current_cas_mask) {
536 int highest_supported_cas = 0, current_cas = 0;
537 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
538 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
539 highest_supported_cas = 5;
540 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
541 highest_supported_cas = 4;
542 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
543 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000544 } else {
545 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000546 }
547 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
548 current_cas = 3;
549 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
550 current_cas = 4;
551 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
552 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000553 } else {
554 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000555 }
556
557 idx = highest_supported_cas - current_cas;
558 PRINTK_DEBUG("idx=%d, ", idx);
Uwe Hermannd773fd32010-11-20 20:23:08 +0000559 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(DIMM0 + i, spd_lookup_table[2*idx]));
560 PRINTK_DEBUG("tAC=%x", spd_read_byte(DIMM0 + i, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000561
Uwe Hermannd773fd32010-11-20 20:23:08 +0000562 if (spd_read_byte(DIMM0 + i, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
563 spd_read_byte(DIMM0 + i, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000564 PRINTK_DEBUG(": OK\n");
565 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000566 }
567
Stefan Reinauer278534d2008-10-29 04:51:07 +0000568 PRINTK_DEBUG(": Not fast enough!\n");
569
570 current_cas_mask &= ~(1 << (current_cas));
571 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000572
Stefan Reinauer278534d2008-10-29 04:51:07 +0000573 freq_cas_mask &= current_cas_mask;
574 if (!current_cas_mask) {
575 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
576 break;
577 }
578 }
579 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
580 if (freq_cas_mask) {
581 switch (j) {
582 case 0: sysinfo->memory_frequency = 400; break;
583 case 1: sysinfo->memory_frequency = 533; break;
584 case 2: sysinfo->memory_frequency = 667; break;
585 }
586 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
587 sysinfo->cas = 3;
588 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
589 sysinfo->cas = 4;
590 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
591 sysinfo->cas = 5;
592 }
593 break;
594 }
595 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000596
Stefan Reinauer278534d2008-10-29 04:51:07 +0000597 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000598 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000599 sysinfo->memory_frequency, sysinfo->cas);
600 } else {
601 die("Could not find common memory frequency and CAS\n");
602 }
603}
604
605static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
606{
607 int i;
608 int tRAS_time;
609 int tRAS_cycles;
610 int freq_multiplier = 0;
611
612 switch (sysinfo->memory_frequency) {
613 case 400: freq_multiplier = 0x14; break; /* 5ns */
614 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
615 case 667: freq_multiplier = 0x0c; break; /* 3ns */
616 }
617
618 tRAS_cycles = 4; /* 4 clocks minimum */
619 tRAS_time = tRAS_cycles * freq_multiplier;
620
621 for (i=0; i<2*DIMM_SOCKETS; i++) {
622 u8 reg8;
623
624 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
625 continue;
626
Uwe Hermannd773fd32010-11-20 20:23:08 +0000627 reg8 = spd_read_byte(DIMM0 + i, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000628 if (!reg8) {
629 die("Invalid tRAS value.\n");
630 }
631
632 while ((tRAS_time >> 2) < reg8) {
633 tRAS_time += freq_multiplier;
634 tRAS_cycles++;
635 }
636 }
637 if(tRAS_cycles > 0x18) {
638 die("DDR-II Module does not support this frequency (tRAS error)\n");
639 }
640
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000641 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000642 sysinfo->tras = tRAS_cycles;
643}
644
645static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
646{
647 int i;
648 int tRP_time;
649 int tRP_cycles;
650 int freq_multiplier = 0;
651
652 switch (sysinfo->memory_frequency) {
653 case 400: freq_multiplier = 0x14; break; /* 5ns */
654 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
655 case 667: freq_multiplier = 0x0c; break; /* 3ns */
656 }
657
658 tRP_cycles = 2; /* 2 clocks minimum */
659 tRP_time = tRP_cycles * freq_multiplier;
660
661 for (i=0; i<2*DIMM_SOCKETS; i++) {
662 u8 reg8;
663
664 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
665 continue;
666
Uwe Hermannd773fd32010-11-20 20:23:08 +0000667 reg8 = spd_read_byte(DIMM0 + i, SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000668 if (!reg8) {
669 die("Invalid tRP value.\n");
670 }
671
672 while (tRP_time < reg8) {
673 tRP_time += freq_multiplier;
674 tRP_cycles++;
675 }
676 }
677
678 if(tRP_cycles > 6) {
679 die("DDR-II Module does not support this frequency (tRP error)\n");
680 }
681
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000682 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000683 sysinfo->trp = tRP_cycles;
684}
685
686static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
687{
688 int i;
689 int tRCD_time;
690 int tRCD_cycles;
691 int freq_multiplier = 0;
692
693 switch (sysinfo->memory_frequency) {
694 case 400: freq_multiplier = 0x14; break; /* 5ns */
695 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
696 case 667: freq_multiplier = 0x0c; break; /* 3ns */
697 }
698
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000699 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000700 tRCD_time = tRCD_cycles * freq_multiplier;
701
702 for (i=0; i<2*DIMM_SOCKETS; i++) {
703 u8 reg8;
704
705 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
706 continue;
707
Uwe Hermannd773fd32010-11-20 20:23:08 +0000708 reg8 = spd_read_byte(DIMM0 + i, SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000709 if (!reg8) {
710 die("Invalid tRCD value.\n");
711 }
712
713 while (tRCD_time < reg8) {
714 tRCD_time += freq_multiplier;
715 tRCD_cycles++;
716 }
717 }
718 if(tRCD_cycles > 6) {
719 die("DDR-II Module does not support this frequency (tRCD error)\n");
720 }
721
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000722 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000723 sysinfo->trcd = tRCD_cycles;
724}
725
726static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
727{
728 int i;
729 int tWR_time;
730 int tWR_cycles;
731 int freq_multiplier = 0;
732
733 switch (sysinfo->memory_frequency) {
734 case 400: freq_multiplier = 0x14; break; /* 5ns */
735 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
736 case 667: freq_multiplier = 0x0c; break; /* 3ns */
737 }
738
739 tWR_cycles = 2; /* 2 clocks minimum */
740 tWR_time = tWR_cycles * freq_multiplier;
741
742 for (i=0; i<2*DIMM_SOCKETS; i++) {
743 u8 reg8;
744
745 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
746 continue;
747
Uwe Hermannd773fd32010-11-20 20:23:08 +0000748 reg8 = spd_read_byte(DIMM0 + i, SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000749 if (!reg8) {
750 die("Invalid tWR value.\n");
751 }
752
753 while (tWR_time < reg8) {
754 tWR_time += freq_multiplier;
755 tWR_cycles++;
756 }
757 }
758 if(tWR_cycles > 5) {
759 die("DDR-II Module does not support this frequency (tWR error)\n");
760 }
761
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000762 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000763 sysinfo->twr = tWR_cycles;
764}
765
766static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
767{
768 int i, index = 0;
769
770 const u8 tRFC_cycles[] = {
771 /* 75 105 127.5 */
772 15, 21, 26, /* DDR2-400 */
773 20, 28, 34, /* DDR2-533 */
774 25, 35, 43 /* DDR2-667 */
775 };
776
777 for (i=0; i<2*DIMM_SOCKETS; i++) {
778 u8 reg8;
779
780 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
781 continue;
782
783 reg8 = sysinfo->banksize[i*2];
784 switch (reg8) {
785 case 0x04: reg8 = 0; break;
786 case 0x08: reg8 = 1; break;
787 case 0x10: reg8 = 2; break;
788 case 0x20: reg8 = 3; break;
789 }
790
791 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
792 reg8++;
793
794 if (reg8 > 3) {
795 /* Can this happen? Go back to 127.5ns just to be sure
796 * we don't run out of the array. This may be wrong
797 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000798 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000799 reg8 = 3;
800 }
801
802 if (reg8 > index)
803 index = reg8;
804
805 }
806 index--;
807 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000808 case 667: index += 3; /* Fallthrough */
809 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000810 case 400: break;
811 }
812
813 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000814 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000815}
816
Stefan Reinauer278534d2008-10-29 04:51:07 +0000817static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
818{
819 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000820
Stefan Reinauer278534d2008-10-29 04:51:07 +0000821 sysinfo->refresh = 0;
822
823 for (i=0; i<2*DIMM_SOCKETS; i++) {
824 int refresh;
825
826 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
827 continue;
828
Uwe Hermannd773fd32010-11-20 20:23:08 +0000829 refresh = spd_read_byte(DIMM0 + i, SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000830
831 /* 15.6us */
832 if (!refresh)
833 continue;
834
835 /* Refresh is slower than 15.6us, use 15.6us */
836 if (refresh > 2)
837 continue;
838
839 if (refresh == 2) {
840 sysinfo->refresh = 1;
841 break;
842 }
843
844 die("DDR-II module has unsupported refresh value\n");
845 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000846 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000847}
848
849static void sdram_verify_burst_length(struct sys_info * sysinfo)
850{
851 int i;
852
853 for (i=0; i<2*DIMM_SOCKETS; i++) {
854 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
855 continue;
856
Uwe Hermannd773fd32010-11-20 20:23:08 +0000857 if (!(spd_read_byte(DIMM0 + i, SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000858 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
859 }
860}
861
862static void sdram_program_dram_width(struct sys_info * sysinfo)
863{
864 u16 c0dramw=0, c1dramw=0;
865 int idx;
866
867 if (sysinfo->dual_channel)
868 idx = 2;
869 else
870 idx = 1;
871
872 switch (sysinfo->dimm[0]) {
873 case 0: c0dramw = 0x0000; break; /* x16DS */
874 case 1: c0dramw = 0x0001; break; /* x8DS */
875 case 2: c0dramw = 0x0000; break; /* x16SS */
876 case 3: c0dramw = 0x0005; break; /* x8DDS */
877 case 4: c0dramw = 0x0000; break; /* NC */
878 }
879
880 switch (sysinfo->dimm[idx]) {
881 case 0: c1dramw = 0x0000; break; /* x16DS */
882 case 1: c1dramw = 0x0010; break; /* x8DS */
883 case 2: c1dramw = 0x0000; break; /* x16SS */
884 case 3: c1dramw = 0x0050; break; /* x8DDS */
885 case 4: c1dramw = 0x0000; break; /* NC */
886 }
887
888 if ( !sdram_capabilities_dual_channel() ) {
889 /* Single Channel */
890 c0dramw |= c1dramw;
891 c1dramw = 0;
892 }
893
894 MCHBAR16(C0DRAMW) = c0dramw;
895 MCHBAR16(C1DRAMW) = c1dramw;
896}
897
898static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
899{
900 int i;
901
902 for (i=0; i<16; i++)
903 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
904}
905
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000906static const u32 dq2030[] = {
907 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
908 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
909 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
910 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
911};
912
913static const u32 dq2330[] = {
914 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
915 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
916 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
917 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
918};
919
920static const u32 cmd2710[] = {
921 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
922 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
923 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
924 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
925};
926
927static const u32 cmd3210[] = {
928 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
929 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
930 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
931 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
932};
933
934static const u32 clk2030[] = {
935 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
936 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
937 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
938 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
939};
940
941static const u32 ctl3215[] = {
942 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
943 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
944 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
945 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
946};
947
948static const u32 ctl3220[] = {
949 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
950 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
951 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
952 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
953};
954
955static const u32 nc[] = {
956 0x00000000, 0x00000000, 0x00000000, 0x00000000,
957 0x00000000, 0x00000000, 0x00000000, 0x00000000,
958 0x00000000, 0x00000000, 0x00000000, 0x00000000,
959 0x00000000, 0x00000000, 0x00000000, 0x00000000
960};
961
962enum {
963 DQ2030,
964 DQ2330,
965 CMD2710,
966 CMD3210,
967 CLK2030,
968 CTL3215,
969 CTL3220,
970 NC,
971};
972
973static const u8 dual_channel_slew_group_lookup[] = {
974 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
975 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
976 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
977 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
978 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
979
980 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
981 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
982 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
983 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
984 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
985
986 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
987 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
988 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
989 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
990 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
991
992 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
993 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
994 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
995 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
996 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
997
998 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
999 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1000 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1001 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
1002};
1003
1004static const u8 single_channel_slew_group_lookup[] = {
1005 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1006 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1007 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1008 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1009 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1010
1011 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1012 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1013 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1014 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1015 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1016
1017 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1018 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1019 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1020 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1021 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1022
1023 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1024 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1025 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1026 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1027 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1028
1029 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1030 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1031 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1032 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1033};
1034
1035static const u32 *slew_group_lookup(int dual_channel, int index)
1036{
1037 const u8 *slew_group;
1038 /* Dual Channel needs different tables. */
1039 if (dual_channel)
1040 slew_group = dual_channel_slew_group_lookup;
1041 else
1042 slew_group = single_channel_slew_group_lookup;
1043
1044 switch (slew_group[index]) {
1045 case DQ2030: return dq2030;
1046 case DQ2330: return dq2330;
1047 case CMD2710: return cmd2710;
1048 case CMD3210: return cmd3210;
1049 case CLK2030: return clk2030;
1050 case CTL3215: return ctl3215;
1051 case CTL3220: return ctl3220;
1052 case NC: return nc;
1053 }
1054
1055 return nc;
1056}
1057
Peter Stugee4bc0f62010-10-01 09:13:18 +00001058#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001059/* Strength multiplier tables */
1060static const u8 dual_channel_strength_multiplier[] = {
1061 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1062 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1063 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1064 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1065 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1066 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1067 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1068 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1069 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1070 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1071 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1072 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1073 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1074 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1075 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1076 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1077 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1078 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1079 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1080 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1082 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1083 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1084 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1085};
1086
1087static const u8 single_channel_strength_multiplier[] = {
1088 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1089 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1090 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1091 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1092 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1093 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1094 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1095 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1096 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1097 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1098 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1099 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1100 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1101 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1102 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1103 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1104 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1105 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1106 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1107 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1108 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1109 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1110 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1111 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1112};
Peter Stugee4bc0f62010-10-01 09:13:18 +00001113#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001114static const u8 dual_channel_strength_multiplier[] = {
1115 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1116 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1117 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1118 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1119 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1120 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1121 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1122 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1123 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1124 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1125 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1126 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1127 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1128 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1129 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1130 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1131 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1132 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1133 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1134 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1135 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1136 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1137 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1138 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1139};
1140
1141static const u8 single_channel_strength_multiplier[] = {
1142 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1143 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1144 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1145 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1146 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1147 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1148 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1149 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1150 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1151 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1152 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1153 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1154 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1155 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1156 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1157 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1158 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1159 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1160 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1161 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1162 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1163 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1164 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1165 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1166};
1167#endif
1168
Stefan Reinauer278534d2008-10-29 04:51:07 +00001169static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1170{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001171 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001172 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001173
1174 /* Set Strength Multipliers */
1175
1176 /* Dual Channel needs different tables. */
1177 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001178 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001179 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001180 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001181 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1182 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001183 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001184 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001185 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001186 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1187 }
1188
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001189 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001190
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001191 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1192 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1193 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1194 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1195 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1196 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1197 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1198 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001199
1200 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001201 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1202 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1203 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001204
Stefan Reinauer278534d2008-10-29 04:51:07 +00001205 sdram_write_slew_rates(G3SRPUT, ctl3220);
1206 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001207 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001208 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001209 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1210 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1211 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001212
1213 /* Channel 1 */
1214 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001215 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1216 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001217 } else {
1218 sdram_write_slew_rates(G7SRPUT, nc);
1219 sdram_write_slew_rates(G8SRPUT, nc);
1220 }
1221}
1222
1223static void sdram_enable_rcomp(void)
1224{
1225 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001226 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001227 udelay(300);
1228 reg32 = MCHBAR32(GBRCOMPCTL);
1229 reg32 &= ~(1 << 23);
1230 MCHBAR32(GBRCOMPCTL) = reg32;
1231}
1232
1233static void sdram_program_dll_timings(struct sys_info *sysinfo)
1234{
1235 u32 chan0dll = 0, chan1dll = 0;
1236 int i;
1237
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001238 printk(BIOS_DEBUG, "Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001239
Stefan Reinauer278534d2008-10-29 04:51:07 +00001240 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1241 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1242
1243 /* We drive both channels with the same speed */
1244 switch (sysinfo->memory_frequency) {
1245 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1246 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1247 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1248 }
1249
1250 for (i=0; i < 4; i++) {
1251 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1252 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1253 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1254 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1255 }
1256}
1257
1258static void sdram_force_rcomp(void)
1259{
1260 u32 reg32;
1261 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001262
Stefan Reinauer278534d2008-10-29 04:51:07 +00001263 reg32 = MCHBAR32(ODTC);
1264 reg32 |= (1 << 28);
1265 MCHBAR32(ODTC) = reg32;
1266
1267 reg32 = MCHBAR32(SMSRCTL);
1268 reg32 |= (1 << 0);
1269 MCHBAR32(SMSRCTL) = reg32;
1270
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001271 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001272 reg32 = MCHBAR32(GBRCOMPCTL);
1273 reg32 |= (1 << 8);
1274 MCHBAR32(GBRCOMPCTL) = reg32;
1275
1276 reg8 = i945_silicon_revision();
1277 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001278
Stefan Reinauer278534d2008-10-29 04:51:07 +00001279 reg32 = MCHBAR32(GBRCOMPCTL);
1280 reg32 |= (3 << 5);
1281 MCHBAR32(GBRCOMPCTL) = reg32;
1282 }
1283}
1284
1285static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1286{
1287 u8 reg8;
1288 u32 reg32;
1289
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001290 printk(BIOS_DEBUG, "Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001291 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001292 reg8 = MCHBAR8(C0HCTC);
1293 reg8 &= ~0x1f;
1294 reg8 |= ( 1 << 0);
1295 MCHBAR8(C0HCTC) = reg8;
1296
1297 reg8 = MCHBAR8(C1HCTC);
1298 reg8 &= ~0x1f;
1299 reg8 |= ( 1 << 0);
1300 MCHBAR8(C1HCTC) = reg8;
1301
Stefan Reinauer278534d2008-10-29 04:51:07 +00001302 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1303 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1304
1305 MCHBAR8(C0WDLLCMC) = 0;
1306 MCHBAR8(C1WDLLCMC) = 0;
1307
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001308 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001309 sdram_program_dram_width(sysinfo);
1310
1311 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1312
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001313 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001314 reg32 = MCHBAR32(GBRCOMPCTL);
1315 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1316 reg32 |= (3 << 27) | (3 << 0);
1317 MCHBAR32(GBRCOMPCTL) = reg32;
1318
1319 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1320
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001321 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001322 sdram_program_dll_timings(sysinfo);
1323
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001324 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001325 sdram_force_rcomp();
1326}
1327
1328static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1329{
1330 u32 reg32;
1331
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001332 printk(BIOS_DEBUG, "Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001333
Stefan Reinauer278534d2008-10-29 04:51:07 +00001334 reg32 = MCHBAR32(RCVENMT);
1335 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001336 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001337
1338 reg32 |= (1 << 11) | (1 << 9);
1339 MCHBAR32(RCVENMT) = reg32;
1340
1341 reg32 = MCHBAR32(DRTST);
1342 reg32 |= (1 << 3) | (1 << 2);
1343 MCHBAR32(DRTST) = reg32;
1344
1345 reg32 = MCHBAR32(DRTST);
1346 reg32 |= (1 << 6) | (1 << 4);
1347 MCHBAR32(DRTST) = reg32;
1348
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001349 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001350
1351 reg32 = MCHBAR32(DRTST);
1352
1353 /* Is channel 0 populated? */
1354 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1355 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1356 reg32 |= (1 << 7) | (1 << 5);
1357 else
1358 reg32 |= (1 << 31);
1359
1360 /* Is channel 1 populated? */
1361 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1362 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1363 reg32 |= (1 << 9) | (1 << 8);
1364 else
1365 reg32 |= (1 << 30);
1366
1367 MCHBAR32(DRTST) = reg32;
1368
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001369 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001370 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1371 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1372 reg32 = MCHBAR32(C0DRC1);
1373 reg32 |= (1 << 8);
1374 MCHBAR32(C0DRC1) = reg32;
1375 }
1376 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1377 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1378 reg32 = MCHBAR32(C1DRC1);
1379 reg32 |= (1 << 8);
1380 MCHBAR32(C1DRC1) = reg32;
1381 }
1382}
1383
1384struct dimm_size {
1385 unsigned long side1;
1386 unsigned long side2;
1387};
1388
1389static struct dimm_size sdram_get_dimm_size(u16 device)
1390{
1391 /* Calculate the log base 2 size of a DIMM in bits */
1392 struct dimm_size sz;
1393 int value, low, rows, columns;
1394
1395 sz.side1 = 0;
1396 sz.side2 = 0;
1397
1398 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1399 if (rows < 0) goto hw_err;
1400 if ((rows & 0xf) == 0) goto val_err;
1401 sz.side1 += rows & 0xf;
1402
1403 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1404 if (columns < 0) goto hw_err;
1405 if ((columns & 0xf) == 0) goto val_err;
1406 sz.side1 += columns & 0xf;
1407
1408 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1409 if (value < 0) goto hw_err;
1410 if ((value & 0xff) == 0) goto val_err;
1411 sz.side1 += log2(value & 0xff);
1412
1413 /* Get the module data width and convert it to a power of two */
1414 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1415 if (value < 0) goto hw_err;
1416 value &= 0xff;
1417 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001418
Stefan Reinauer278534d2008-10-29 04:51:07 +00001419 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1420 if (low < 0) goto hw_err;
1421 value = value | (low & 0xff);
1422 if ((value != 72) && (value != 64)) goto val_err;
1423 sz.side1 += log2(value);
1424
1425 /* side 2 */
1426 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1427
1428 if (value < 0) goto hw_err;
1429 value &= 7;
1430 value++;
1431 if (value == 1) goto out;
1432 if (value != 2) goto val_err;
1433
1434 /* Start with the symmetrical case */
1435 sz.side2 = sz.side1;
1436
1437 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1438
1439 /* Don't die here, I have not come across any of these to test what
1440 * actually happens.
1441 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001442 printk(BIOS_ERR, "Assymetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001443
1444 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1445 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1446
1447 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1448 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1449
1450 goto out;
1451
1452 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001453 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001454 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001455 /* If a hardware error occurs the spd rom probably does not exist.
1456 * In this case report that there is no memory
1457 */
1458 sz.side1 = 0;
1459 sz.side2 = 0;
1460 out:
1461 return sz;
1462}
1463
1464static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1465{
1466 int i;
1467
1468 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1469 struct dimm_size sz;
1470
1471 sysinfo->banksize[i * 2] = 0;
1472 sysinfo->banksize[(i * 2) + 1] = 0;
1473
1474 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1475 continue;
1476
Uwe Hermannd773fd32010-11-20 20:23:08 +00001477 sz = sdram_get_dimm_size(DIMM0 + i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001478
Uwe Hermannd773fd32010-11-20 20:23:08 +00001479 sysinfo->banks[i] = spd_read_byte(DIMM0 + i, SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001480
1481 if (sz.side1 < 30)
1482 die("DDR-II rank size smaller than 128MB is not supported.\n");
1483
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001484 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001485
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001486 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001487
Stefan Reinauer278534d2008-10-29 04:51:07 +00001488 if (!sz.side2)
1489 continue;
1490
1491 /* If there is a second side, it has to have at least 128M, too */
1492 if (sz.side2 < 30)
1493 die("DDR-II rank size smaller than 128MB is not supported.\n");
1494
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001495 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001496
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001497 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001498 }
1499}
1500
1501static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1502{
1503 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001504 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001505
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001506 printk(BIOS_DEBUG, "Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001507
1508 cum0 = 0;
1509 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001510 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001511 MCHBAR8(C0DRB0+i) = cum0;
1512 }
1513
1514 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1515 cum1 = cum0;
1516
1517 /* Exception: Interleaved starts from the beginning */
1518 if (sysinfo->interleaved)
1519 cum1 = 0;
1520
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001521#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001522 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1523 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1524 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1525 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001526#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001527
1528 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001529 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001530 MCHBAR8(C1DRB0+i) = cum1;
1531 }
1532
1533 /* Set TOLUD Top Of Low Usable DRAM */
1534 if (sysinfo->interleaved)
1535 tolud = (cum0 + cum1) << 1;
1536 else
1537 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001538
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001539 /* The TOM register has a different format */
1540 tom = tolud >> 3;
1541
1542 /* Limit the value of TOLUD to leave some space for PCI memory. */
1543 if (tolud > 0xd0)
1544 tolud = 0xd0; /* 3.25GB : 0.75GB */
1545
1546 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1547
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001548 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1549 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1550 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001551
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001552 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001553
1554 return 0;
1555}
1556
Stefan Reinauer278534d2008-10-29 04:51:07 +00001557static int sdram_set_row_attributes(struct sys_info *sysinfo)
1558{
1559 int i, value;
1560 u16 dra0=0, dra1=0, dra = 0;
1561
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001562 printk(BIOS_DEBUG, "Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001563 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1564 u16 device;
1565 u8 columnsrows;
1566
1567 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1568 continue;
1569 }
1570
Uwe Hermannd773fd32010-11-20 20:23:08 +00001571 device = DIMM0 + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001572
1573 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1574 columnsrows = (value & 0x0f);
1575
1576 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1577 columnsrows |= (value & 0xf) << 4;
1578
1579 switch (columnsrows) {
1580 case 0x9d: dra = 2; break;
1581 case 0xad: dra = 3; break;
1582 case 0xbd: dra = 4; break;
1583 case 0xae: dra = 3; break;
1584 case 0xbe: dra = 4; break;
1585 default: die("Unsupported Rows/Columns. (DRA)");
1586 }
1587
1588 /* Double Sided DIMMs? */
1589 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1590 dra = (dra << 4) | dra;
1591 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001592
Stefan Reinauer278534d2008-10-29 04:51:07 +00001593 if (i < DIMM_SOCKETS)
1594 dra0 |= (dra << (i*8));
1595 else
1596 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1597 }
1598
1599 MCHBAR16(C0DRA0) = dra0;
1600 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001601
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001602 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1603 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001604
1605 return 0;
1606}
1607
1608static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1609{
1610 u32 off32;
1611 int i;
1612
1613 MCHBAR16(C1BNKARC) &= 0xff00;
1614 MCHBAR16(C0BNKARC) &= 0xff00;
1615
1616 off32 = C0BNKARC;
1617 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1618 /* Switch to second channel */
1619 if (i == DIMM_SOCKETS)
1620 off32 = C1BNKARC;
1621
1622 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1623 continue;
1624
1625 if (sysinfo->banks[i] != 8)
1626 continue;
1627
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001628 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001629
1630 if (i & 1)
1631 MCHBAR16(off32) |= 0x50;
1632 else
1633 MCHBAR16(off32) |= 0x05;
1634 }
1635}
1636
1637#define REFRESH_7_8US 1
1638#define REFRESH_15_6US 0
1639static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1640{
1641 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001642
Stefan Reinauer278534d2008-10-29 04:51:07 +00001643 if (sysinfo->refresh == REFRESH_7_8US) {
1644 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1645 } else {
1646 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1647 }
1648
1649 MCHBAR32(C0DRC0) &= ~(7 << 8);
1650 MCHBAR32(C0DRC0) |= reg32;
1651
1652 MCHBAR32(C1DRC0) &= ~(7 << 8);
1653 MCHBAR32(C1DRC0) |= reg32;
1654}
1655
1656static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1657{
1658 u32 reg32;
1659 int i;
1660
1661 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001662
Stefan Reinauer278534d2008-10-29 04:51:07 +00001663 for (i=0; i < 4; i++) {
1664 if (sysinfo->banksize[i] == 0) {
1665 reg32 |= (1 << (16 + i));
1666 }
1667 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001668
Stefan Reinauer278534d2008-10-29 04:51:07 +00001669 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001670
Stefan Reinauer278534d2008-10-29 04:51:07 +00001671 reg32 |= (1 << 11);
1672 MCHBAR32(C0DRC1) = reg32;
1673
1674 /* Do we have to do this if we're in Single Channel Mode? */
1675 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001676
Stefan Reinauer278534d2008-10-29 04:51:07 +00001677 for (i=4; i < 8; i++) {
1678 if (sysinfo->banksize[i] == 0) {
1679 reg32 |= (1 << (12 + i));
1680 }
1681 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001682
Stefan Reinauer278534d2008-10-29 04:51:07 +00001683 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001684
Stefan Reinauer278534d2008-10-29 04:51:07 +00001685 reg32 |= (1 << 11);
1686 MCHBAR32(C1DRC1) = reg32;
1687}
1688
1689static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1690{
1691 u32 reg32;
1692 int i;
1693
1694 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001695
Stefan Reinauer278534d2008-10-29 04:51:07 +00001696 for (i=0; i < 4; i++) {
1697 if (sysinfo->banksize[i] == 0) {
1698 reg32 |= (1 << (24 + i));
1699 }
1700 }
1701 MCHBAR32(C0DRC2) = reg32;
1702
1703 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001704
Stefan Reinauer278534d2008-10-29 04:51:07 +00001705 for (i=4; i < 8; i++) {
1706 if (sysinfo->banksize[i] == 0) {
1707 reg32 |= (1 << (20 + i));
1708 }
1709 }
1710 MCHBAR32(C1DRC2) = reg32;
1711}
1712
1713static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1714{
1715 u32 reg32, off32;
1716 u32 tWTR;
1717 u32 temp_drt;
1718 int i, page_size;
1719
1720 static const u8 const drt0_table[] = {
1721 /* CL 3, 4, 5 */
1722 3, 4, 5, /* FSB533/400, DDR533/400 */
1723 4, 5, 6, /* FSB667, DDR533/400 */
1724 4, 5, 6, /* FSB667, DDR667 */
1725 };
1726
1727 static const u8 const cas_table[] = {
1728 2, 1, 0, 3
1729 };
1730
1731 reg32 = MCHBAR32(C0DRC0);
1732 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001733 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001734 MCHBAR32(C0DRC0) = reg32;
1735
1736 reg32 = MCHBAR32(C1DRC0);
1737 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001738 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001739 MCHBAR32(C1DRC0) = reg32;
1740
1741 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1742 SYSINFO_DIMM_NOT_POPULATED) {
1743 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001744 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001745 MCHBAR32(C0DRC0) = reg32;
1746 }
1747
1748 sdram_program_refresh_rate(sysinfo);
1749
1750 sdram_program_cke_tristate(sysinfo);
1751
1752 sdram_program_odt_tristate(sysinfo);
1753
1754 /* Calculate DRT0 */
1755
1756 temp_drt = 0;
1757
1758 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1759 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1760 temp_drt |= (reg32 << 28);
1761
1762 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1763 reg32 += sysinfo->trp;
1764 temp_drt |= (reg32 << 4);
1765
1766 if (sysinfo->memory_frequency == 667) {
1767 tWTR = 3; /* 667MHz */
1768 } else {
1769 tWTR = 2; /* 400 and 533 */
1770 }
1771
1772 /* B2B Write to Read Command Spacing */
1773 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1774 temp_drt |= (reg32 << 24);
1775
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001776 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001777 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1778
1779 /* Program Write Auto Precharge to Activate */
1780 off32 = 0;
1781 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1782 off32 += 3;
1783 }
1784 if (sysinfo->memory_frequency == 667) {
1785 off32 += 3;
1786 }
1787 off32 += sysinfo->cas - 3;
1788 reg32 = drt0_table[off32];
1789 temp_drt |= (reg32 << 11);
1790
1791 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001792
Stefan Reinauer278534d2008-10-29 04:51:07 +00001793 temp_drt |= (8 << 0);
1794
1795 MCHBAR32(C0DRT0) = temp_drt;
1796 MCHBAR32(C1DRT0) = temp_drt;
1797
1798 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001799
Stefan Reinauer278534d2008-10-29 04:51:07 +00001800 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1801
1802 /* DRAM RASB Precharge */
1803 temp_drt |= (sysinfo->trp - 2) << 0;
1804
1805 /* DRAM RASB to CASB Delay */
1806 temp_drt |= (sysinfo->trcd - 2) << 4;
1807
1808 /* CASB Latency */
1809 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1810
1811 /* Refresh Cycle Time */
1812 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001813
Stefan Reinauer278534d2008-10-29 04:51:07 +00001814 /* Pre-All to Activate Delay */
1815 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001816
Stefan Reinauer278534d2008-10-29 04:51:07 +00001817 /* Precharge to Precharge Delay stays at 1 clock */
1818 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001819
Stefan Reinauer278534d2008-10-29 04:51:07 +00001820 /* Activate to Precharge Delay */
1821 temp_drt |= (sysinfo->tras << 19);
1822
1823 /* Read to Precharge (tRTP) */
1824 if (sysinfo->memory_frequency == 667) {
1825 temp_drt |= (1 << 28);
1826 } else {
1827 temp_drt |= (0 << 28);
1828 }
1829
1830 /* Determine page size */
1831 reg32 = 0;
1832 page_size = 1; /* Default: 1k pagesize */
1833 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1834 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1835 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1836 page_size = 2; /* 2k pagesize */
1837 }
1838
1839 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1840 reg32 = 1;
1841 }
1842 if (sysinfo->memory_frequency == 667) {
1843 reg32 = page_size;
1844 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001845
Stefan Reinauer278534d2008-10-29 04:51:07 +00001846 temp_drt |= (reg32 << 30);
1847
1848 MCHBAR32(C0DRT1) = temp_drt;
1849 MCHBAR32(C1DRT1) = temp_drt;
1850
1851 /* Program DRT2 */
1852 reg32 = MCHBAR32(C0DRT2);
1853 reg32 &= ~(1 << 8);
1854 MCHBAR32(C0DRT2) = reg32;
1855
1856 reg32 = MCHBAR32(C1DRT2);
1857 reg32 &= ~(1 << 8);
1858 MCHBAR32(C1DRT2) = reg32;
1859
1860 /* Calculate DRT3 */
1861 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1862
1863 /* Get old tRFC value */
1864 reg32 = MCHBAR32(C0DRT1) >> 10;
1865 reg32 &= 0x3f;
1866
1867 /* 788nS - tRFC */
1868 switch (sysinfo->memory_frequency) {
1869 case 400: /* 5nS */
1870 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1871 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1872 break;
1873 case 533: /* 3.75nS */
1874 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1875 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1876 break;
1877 case 667: /* 3nS */
1878 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1879 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1880 break;
1881 }
1882
1883 temp_drt |= reg32;
1884
1885 MCHBAR32(C0DRT3) = temp_drt;
1886 MCHBAR32(C1DRT3) = temp_drt;
1887}
1888
1889static void sdram_set_channel_mode(struct sys_info *sysinfo)
1890{
1891 u32 reg32;
1892
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001893 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001894
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001895 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001896 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1897 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1898 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1899 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1900 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001901 sysinfo->interleaved = 1;
1902 } else {
1903 sysinfo->interleaved = 0;
1904 }
1905
1906 reg32 = MCHBAR32(DCC);
1907 reg32 &= ~(7 << 0);
1908
1909 if(sysinfo->interleaved) {
1910 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001911 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001912 reg32 |= (1 << 1);
1913 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1914 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1915 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001916 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001917 reg32 |= (1 << 2);
1918 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1919 SYSINFO_DIMM_NOT_POPULATED) {
1920 /* Dual Channel Assymetric */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001921 printk(BIOS_DEBUG, "Dual Channel Assymetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001922 reg32 |= (1 << 0);
1923 } else {
1924 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001925 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001926 }
1927
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001928 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001929 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001930
1931 MCHBAR32(DCC) = reg32;
1932
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001933 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001934}
1935
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001936static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001937{
1938 volatile u16 reg16;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001939
1940 MCHBAR32(PLLMON) = 0x80800000;
1941
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001942 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001943 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001944 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001945
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001946 /* Program CPCTL according to FSB speed */
1947 /* Only write the lower byte */
1948 switch (sysinfo->fsb_frequency) {
1949 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1950 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1951 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1952 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001953
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001954 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001955
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001956 reg16 = MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001957}
1958
1959static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1960{
1961 u8 reg8;
1962 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001963 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001964
1965#define CRCLK_166MHz 0x00
1966#define CRCLK_200MHz 0x01
1967#define CRCLK_250MHz 0x03
1968#define CRCLK_400MHz 0x05
1969
1970#define CDCLK_200MHz 0x00
1971#define CDCLK_320MHz 0x40
1972
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001973#define VOLTAGE_1_05 0x00
1974#define VOLTAGE_1_50 0x01
1975
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001976 printk(BIOS_DEBUG, "Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001977
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001978 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001979
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001980 voltage = VOLTAGE_1_05;
1981 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1982 voltage = VOLTAGE_1_50;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001983 printk(BIOS_DEBUG, "Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001984
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001985 /* Gate graphics hardware for frequency change */
1986 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
1987 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
1988 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001989
1990 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001991 reg8 = sdram_capabilities_core_frequencies();
1992
Stefan Reinauer278534d2008-10-29 04:51:07 +00001993 freq = CRCLK_250MHz;
1994 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001995 case GFX_FREQUENCY_CAP_ALL:
1996 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001997 freq = CRCLK_250MHz;
1998 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001999 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002000 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002001 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2002 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2003 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002004 }
2005
2006 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002007 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002008 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
2009 if (reg8==2)
2010 freq = CRCLK_166MHz;
2011 }
2012
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002013 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002014 switch (freq) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002015 case CRCLK_166MHz: printk(BIOS_DEBUG, "166Mhz"); break;
2016 case CRCLK_200MHz: printk(BIOS_DEBUG, "200Mhz"); break;
2017 case CRCLK_250MHz: printk(BIOS_DEBUG, "250Mhz"); break;
2018 case CRCLK_400MHz: printk(BIOS_DEBUG, "400Mhz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002019 }
2020
Stefan Reinauer278534d2008-10-29 04:51:07 +00002021 if (i945_silicon_revision() == 0) {
2022 sysinfo->mvco4x = 1;
2023 } else {
2024 sysinfo->mvco4x = 0;
2025 }
2026
Stefan Reinauer278534d2008-10-29 04:51:07 +00002027 second_vco = 0;
2028
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002029 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002030 second_vco = 1;
2031 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2032 u16 mem = sysinfo->memory_frequency;
2033 u16 fsb = sysinfo->fsb_frequency;
2034
2035 if ( (fsb == 667 && mem == 533) ||
2036 (fsb == 533 && mem == 533) ||
2037 (fsb == 533 && mem == 400)) {
2038 second_vco = 1;
2039 }
2040
2041 if (fsb == 667 && mem == 533)
2042 sysinfo->mvco4x = 1;
2043 }
2044
2045 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002046 sysinfo->clkcfg_bit7=1;
2047 } else {
2048 sysinfo->clkcfg_bit7=0;
2049 }
2050
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002051 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002052 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2053 reg16 &= ~( (7 << 0) | (1 << 13) );
2054 reg16 |= freq;
2055 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2056
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002057 /* Graphics Core Display Clock */
2058 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2059 reg8 &= ~( (1<<7) | (7<<4) );
2060
2061 if (voltage == VOLTAGE_1_05) {
2062 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002063 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002064 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002065 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002066 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002067 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002068 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002069
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002070 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002071
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002072 reg8 |= (1<<3) | (1<<1);
2073 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2074
2075 reg8 |= 0x0f;
2076 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2077
2078 /* Ungate core render and display clocks */
2079 reg8 &= 0xf0;
2080 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002081}
2082
2083static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2084{
2085 u32 clkcfg;
2086 u8 reg8;
2087
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002088 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002089
Stefan Reinauer278534d2008-10-29 04:51:07 +00002090 clkcfg = MCHBAR32(CLKCFG);
2091
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002092 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002093
2094 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2095
2096 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002097 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002098 clkcfg &= ~(1 << 12);
2099 }
2100
2101 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002102 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002103
Stefan Reinauer278534d2008-10-29 04:51:07 +00002104 clkcfg |= (1 << 7);
2105 }
2106
2107 switch (sysinfo->memory_frequency) {
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002108 case 400: clkcfg |= (2 << 4); break;
2109 case 533: clkcfg |= (3 << 4); break;
2110 case 667: clkcfg |= (4 << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002111 default: die("Target Memory Frequency Error");
2112 }
2113
2114 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002115 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002116 return;
2117 }
2118
2119 MCHBAR32(CLKCFG) = clkcfg;
2120
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002121 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002122 * cache before we execute it.
2123 */
2124 goto cache_code;
2125vco_update:
2126 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2127 reg8 &= ~(1 << 7);
2128 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2129
Stefan Reinauer278534d2008-10-29 04:51:07 +00002130 clkcfg &= ~(1 << 10);
2131 MCHBAR32(CLKCFG) = clkcfg;
2132 clkcfg |= (1 << 10);
2133 MCHBAR32(CLKCFG) = clkcfg;
2134
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002135 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002136 " movl $0x100, %%ecx\n"
2137 "delay_update:\n"
2138 " nop\n"
2139 " nop\n"
2140 " nop\n"
2141 " nop\n"
2142 " loop delay_update\n"
2143 : /* No outputs */
2144 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002145 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002146 );
2147
Stefan Reinauer278534d2008-10-29 04:51:07 +00002148 clkcfg &= ~(1 << 10);
2149 MCHBAR32(CLKCFG) = clkcfg;
2150
2151 goto out;
2152cache_code:
2153 goto vco_update;
2154out:
2155
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002156 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
2157 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002158}
2159
2160static void sdram_program_clock_crossing(void)
2161{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002162 int idx = 0;
2163
2164 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002165 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002166 */
Peter Stugee4bc0f62010-10-01 09:13:18 +00002167#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002168 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002169 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002170 0xffffffff, 0xffffffff, /* nonexistant */
2171 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002172
Stefan Reinauer278534d2008-10-29 04:51:07 +00002173 0x08040120, 0x00000000, /* DDR400 FSB533 */
2174 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002175 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002176
2177 0x04020120, 0x00000010, /* DDR400 FSB667 */
2178 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002179 0x00100401, 0x00000000, /* DDR667 FSB667 */
2180
2181 0xffffffff, 0xffffffff, /* nonexistant */
2182 0xffffffff, 0xffffffff, /* nonexistant */
2183 0xffffffff, 0xffffffff, /* nonexistant */
2184
2185 0xffffffff, 0xffffffff, /* nonexistant */
2186 0xffffffff, 0xffffffff, /* nonexistant */
2187 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002188 };
2189
2190 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002191 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002192 0xffffffff, 0xffffffff, /* nonexistant */
2193 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002194
Stefan Reinauer278534d2008-10-29 04:51:07 +00002195 0x00060108, 0x00000000, /* DDR400 FSB533 */
2196 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002197 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002198
2199 0x00040318, 0x00000000, /* DDR400 FSB667 */
2200 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002201 0x02010804, 0x00000000, /* DDR667 FSB667 */
2202
2203 0xffffffff, 0xffffffff, /* nonexistant */
2204 0xffffffff, 0xffffffff, /* nonexistant */
2205 0xffffffff, 0xffffffff, /* nonexistant */
2206
2207 0xffffffff, 0xffffffff, /* nonexistant */
2208 0xffffffff, 0xffffffff, /* nonexistant */
2209 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002210 };
2211
Peter Stugee4bc0f62010-10-01 09:13:18 +00002212#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002213 /* i945 G/P */
2214 static const u32 data_clock_crossing[] = {
2215 0xffffffff, 0xffffffff, /* nonexistant */
2216 0xffffffff, 0xffffffff, /* nonexistant */
2217 0xffffffff, 0xffffffff, /* nonexistant */
2218
2219 0x10080201, 0x00000000, /* DDR400 FSB533 */
2220 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002221 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002222
2223 0xffffffff, 0xffffffff, /* nonexistant */
2224 0xffffffff, 0xffffffff, /* nonexistant */
2225 0xffffffff, 0xffffffff, /* nonexistant */
2226
2227 0x04020108, 0x00000000, /* DDR400 FSB800 */
2228 0x00020108, 0x00000000, /* DDR533 FSB800 */
2229 0x00080201, 0x00000000, /* DDR667 FSB800 */
2230
2231 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2232 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2233 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2234 };
2235
2236 static const u32 command_clock_crossing[] = {
2237 0xffffffff, 0xffffffff, /* nonexistant */
2238 0xffffffff, 0xffffffff, /* nonexistant */
2239 0xffffffff, 0xffffffff, /* nonexistant */
2240
2241 0x00010800, 0x00000402, /* DDR400 FSB533 */
2242 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002243 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002244
2245 0xffffffff, 0xffffffff, /* nonexistant */
2246 0xffffffff, 0xffffffff, /* nonexistant */
2247 0xffffffff, 0xffffffff, /* nonexistant */
2248
2249 0x02010804, 0x00000000, /* DDR400 FSB800 */
2250 0x00010402, 0x00000000, /* DDR533 FSB800 */
2251 0x04020180, 0x00000008, /* DDR667 FSB800 */
2252
2253 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2254 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2255 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2256 };
2257#endif
2258
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002259 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002260
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002261 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002262 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002263 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2264 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2265 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2266 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002267 }
2268
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002269 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002270 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002271 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2272 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2273 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2274 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2275 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2276 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002277 }
2278
2279 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002280 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002281 }
2282
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002283 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2284 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2285
Stefan Reinauer278534d2008-10-29 04:51:07 +00002286 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2287 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2288 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2289 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2290
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002291 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002292}
2293
2294static void sdram_disable_fast_dispatch(void)
2295{
2296 u32 reg32;
2297
2298 reg32 = MCHBAR32(FSBPMC3);
2299 reg32 |= (1 << 1);
2300 MCHBAR32(FSBPMC3) = reg32;
2301
2302 reg32 = MCHBAR32(SBTEST);
2303 reg32 |= (3 << 1);
2304 MCHBAR32(SBTEST) = reg32;
2305}
2306
2307static void sdram_pre_jedec_initialization(void)
2308{
2309 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002310
Stefan Reinauer278534d2008-10-29 04:51:07 +00002311 reg32 = MCHBAR32(WCC);
2312 reg32 &= 0x113ff3ff;
2313 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2314 MCHBAR32(WCC) = reg32;
2315
2316 MCHBAR32(SMVREFC) |= (1 << 6);
2317
2318 MCHBAR32(MMARB0) &= ~(3 << 17);
2319 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2320
2321 MCHBAR32(MMARB1) &= ~(7 << 8);
2322 MCHBAR32(MMARB1) |= (3 << 8);
2323
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002324 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002325 MCHBAR32(C0AIT) = 0x000006c4;
2326 MCHBAR32(C0AIT+4) = 0x871a066d;
2327
2328 MCHBAR32(C1AIT) = 0x000006c4;
2329 MCHBAR32(C1AIT+4) = 0x871a066d;
2330}
2331
2332#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2333#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2334#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2335#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2336#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2337#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2338#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2339#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2340
2341static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2342{
2343 u32 chan0 = 0, chan1 = 0;
2344 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2345
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002346 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002347 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002348 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002349 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2350 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2351 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2352
2353 if (sdram_capabilities_enhanced_addressing_xor()) {
2354 if (!sysinfo->interleaved) {
2355 /* Single Channel & Dual Channel Assymetric */
2356 if (chan0_populated) {
2357 if (chan0_dualsided) {
2358 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2359 } else {
2360 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2361 }
2362 }
2363 if (chan1_populated) {
2364 if (chan1_dualsided) {
2365 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2366 } else {
2367 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2368 }
2369 }
2370 } else {
2371 /* Interleaved has always both channels populated */
2372 if (chan0_dualsided) {
2373 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2374 } else {
2375 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2376 }
2377
2378 if (chan1_dualsided) {
2379 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2380 } else {
2381 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2382 }
2383 }
2384 } else {
2385 if (!sysinfo->interleaved) {
2386 /* Single Channel & Dual Channel Assymetric */
2387 if (chan0_populated) {
2388 if (chan0_dualsided) {
2389 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2390 } else {
2391 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2392 }
2393 }
2394 if (chan1_populated) {
2395 if (chan1_dualsided) {
2396 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2397 } else {
2398 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2399 }
2400 }
2401 } else {
2402 /* Interleaved has always both channels populated */
2403 if (chan0_dualsided) {
2404 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2405 } else {
2406 chan0 = EA_DUALCHANNEL_BANK_MODE;
2407 }
2408
2409 if (chan1_dualsided) {
2410 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2411 } else {
2412 chan1 = EA_DUALCHANNEL_BANK_MODE;
2413 }
2414 }
2415 }
2416
2417 MCHBAR32(C0DRC1) &= 0x00ffffff;
2418 MCHBAR32(C0DRC1) |= chan0;
2419 MCHBAR32(C1DRC1) &= 0x00ffffff;
2420 MCHBAR32(C1DRC1) |= chan1;
2421}
2422
2423static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2424{
2425 u32 reg32;
2426
2427 /* Enable Channel XORing for Dual Channel Interleave */
2428 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002429
Stefan Reinauer278534d2008-10-29 04:51:07 +00002430 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002431#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002432 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002433 reg32 |= (1 << 9);
2434#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002435 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002436#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002437 MCHBAR32(DCC) = reg32;
2438 }
2439
2440 /* DRAM mode optimizations */
2441 sdram_enhanced_addressing_mode(sysinfo);
2442
2443 reg32 = MCHBAR32(FSBPMC3);
2444 reg32 &= ~(1 << 1);
2445 MCHBAR32(FSBPMC3) = reg32;
2446
2447 reg32 = MCHBAR32(SBTEST);
2448 reg32 &= ~(1 << 2);
2449 MCHBAR32(SBTEST) = reg32;
2450
2451 reg32 = MCHBAR32(SBOCC);
2452 reg32 &= 0xffbdb6ff;
2453 reg32 |= (0xbdb6 << 8) | (1 << 0);
2454 MCHBAR32(SBOCC) = reg32;
2455}
2456
2457static void sdram_power_management(struct sys_info *sysinfo)
2458{
2459 u8 reg8;
2460 u16 reg16;
2461 u32 reg32;
2462 int integrated_graphics = 1;
2463 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002464
Stefan Reinauer278534d2008-10-29 04:51:07 +00002465 reg32 = MCHBAR32(C0DRT2);
2466 reg32 &= 0xffffff00;
2467 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002468 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002469 MCHBAR32(C0DRT2) = reg32;
2470
2471 reg32 = MCHBAR32(C1DRT2);
2472 reg32 &= 0xffffff00;
2473 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002474 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002475 MCHBAR32(C1DRT2) = reg32;
2476
2477 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002478
2479 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002480 MCHBAR32(C0DRC1) = reg32;
2481
2482 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002483
2484 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002485 MCHBAR32(C1DRC1) = reg32;
2486
2487 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002488 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2489 u16 peg_bits = (1 << 5) | (1 << 0);
2490
2491 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002492 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002493 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2494 u16 peg_bits = (1 << 5) | (1 << 0);
2495
Stefan Reinauer278534d2008-10-29 04:51:07 +00002496 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002497 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002498 }
2499
2500 reg16 = MCHBAR16(UPMC2);
2501 reg16 &= 0xfc00;
2502 reg16 |= 0x0100;
2503 MCHBAR16(UPMC2) = reg16;
2504
2505 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002506
Stefan Reinauer278534d2008-10-29 04:51:07 +00002507 for (i=0; i<5; i++) {
2508 MCHBAR32(UPMC3) &= ~(1 << 16);
2509 MCHBAR32(UPMC3) |= (1 << 16);
2510 }
2511
2512 MCHBAR32(GIPMC1) = 0x8000000c;
2513
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002514 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002515 reg16 &= ~(7 << 11);
2516 if (i945_silicon_revision()>2) {
2517 reg16 |= (6 << 11);
2518 } else {
2519 reg16 |= (4 << 11);
2520 }
2521 MCHBAR16(CPCTL) = reg16;
2522
Stefan Reinauer30140a52009-03-11 16:20:39 +00002523#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002524 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002525#else
2526 if (i945_silicon_revision() != 0) {
2527#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002528 switch (sysinfo->fsb_frequency) {
2529 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2530 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2531 }
2532 } else {
2533 switch (sysinfo->fsb_frequency) {
2534 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2535 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2536 }
2537 }
2538
2539 MCHBAR32(FSBPMC1) = 0x8000000c;
2540
2541 reg32 = MCHBAR32(C2C3TT);
2542 reg32 &= 0xffff0000;
2543 switch (sysinfo->fsb_frequency) {
2544 case 667: reg32 |= 0x0600; break;
2545 case 533: reg32 |= 0x0480; break;
2546 }
2547 MCHBAR32(C2C3TT) = reg32;
2548
2549 reg32 = MCHBAR32(C3C4TT);
2550 reg32 &= 0xffff0000;
2551 switch (sysinfo->fsb_frequency) {
2552 case 667: reg32 |= 0x0b80; break;
2553 case 533: reg32 |= 0x0980; break;
2554 }
2555 MCHBAR32(C3C4TT) = reg32;
2556
2557 if (i945_silicon_revision() == 0) {
2558 MCHBAR32(ECO) &= ~(1 << 16);
2559 } else {
2560 MCHBAR32(ECO) |= (1 << 16);
2561 }
2562
2563#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002564
Stefan Reinauer278534d2008-10-29 04:51:07 +00002565 if (i945_silicon_revision() == 0) {
2566 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2567 } else {
2568 MCHBAR32(FSBPMC3) |= (1 << 29);
2569 }
2570#endif
2571 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2572
2573 MCHBAR32(FSBPMC3) |= (1 << 21);
2574
2575 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2576
2577 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2578
2579 reg32 = MCHBAR32(FSBPMC4);
2580 reg32 &= ~(3 << 24);
2581 reg32 |= ( 2 << 24);
2582 MCHBAR32(FSBPMC4) = reg32;
2583
2584 MCHBAR32(FSBPMC4) |= (1 << 21);
2585
2586 MCHBAR32(FSBPMC4) |= (1 << 5);
2587
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002588 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2589 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002590 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2591 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002592 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002593 }
2594
2595 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2596 reg8 |= (1 << 4);
2597 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2598
2599 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2600 reg8 |= (1 << 2);
2601 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2602
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002603#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002604
Stefan Reinauer278534d2008-10-29 04:51:07 +00002605 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002606 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002607 MCHBAR16(MIPMC4) = 0x0468;
2608 MCHBAR16(MIPMC5) = 0x046c;
2609 MCHBAR16(MIPMC6) = 0x046c;
2610 } else {
2611 MCHBAR16(MIPMC4) = 0x6468;
2612 MCHBAR16(MIPMC5) = 0x646c;
2613 MCHBAR16(MIPMC6) = 0x646c;
2614 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002615#else
2616 if (integrated_graphics) {
2617 MCHBAR16(MIPMC4) = 0x04f8;
2618 MCHBAR16(MIPMC5) = 0x04fc;
2619 MCHBAR16(MIPMC6) = 0x04fc;
2620 } else {
2621 MCHBAR16(MIPMC4) = 0x64f8;
2622 MCHBAR16(MIPMC5) = 0x64fc;
2623 MCHBAR16(MIPMC6) = 0x64fc;
2624 }
2625
2626#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002627
2628 reg32 = MCHBAR32(PMCFG);
2629 reg32 &= ~(3 << 17);
2630 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002631 MCHBAR32(PMCFG) = reg32;
2632
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002633 MCHBAR32(PMCFG) |= (1 << 4);
2634
Stefan Reinauer278534d2008-10-29 04:51:07 +00002635 reg32 = MCHBAR32(0xc30);
2636 reg32 &= 0xffffff00;
2637 reg32 |= 0x01;
2638 MCHBAR32(0xc30) = reg32;
2639
2640 MCHBAR32(0xb18) &= ~(1 << 21);
2641}
2642
2643static void sdram_thermal_management(void)
2644{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002645
Stefan Reinauer278534d2008-10-29 04:51:07 +00002646 MCHBAR8(TCO1) = 0x00;
2647 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002648
2649 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2650 * 0x30/0x32.
2651 */
2652
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002653 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002654}
2655
2656static void sdram_save_receive_enable(void)
2657{
2658 int i;
2659 u32 reg32;
2660 u8 values[4];
2661
2662 /* The following values are stored to an unused CMOS
2663 * area and restored instead of recalculated in case
2664 * of an S3 resume.
2665 *
2666 * C0WL0REOST [7:0] -> 8 bit
2667 * C1WL0REOST [7:0] -> 8 bit
2668 * RCVENMT [11:8] [3:0] -> 8 bit
2669 * C0DRT1 [27:24] -> 4 bit
2670 * C1DRT1 [27:24] -> 4 bit
2671 */
2672
2673 values[0] = MCHBAR8(C0WL0REOST);
2674 values[1] = MCHBAR8(C1WL0REOST);
2675
2676 reg32 = MCHBAR32(RCVENMT);
2677 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2678
2679 reg32 = MCHBAR32(C0DRT1);
2680 values[3] = (reg32 >> 24) & 0x0f;
2681 reg32 = MCHBAR32(C1DRT1);
2682 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2683
2684 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002685 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002686 */
2687
2688 for (i=0; i<4; i++)
2689 cmos_write(values[i], 128 + i);
2690}
2691
2692static void sdram_recover_receive_enable(void)
2693{
2694 int i;
2695 u32 reg32;
2696 u8 values[4];
2697
2698 for (i=0; i<4; i++)
2699 values[i] = cmos_read(128 + i);
2700
2701 MCHBAR8(C0WL0REOST) = values[0];
2702 MCHBAR8(C1WL0REOST) = values[1];
2703
2704 reg32 = MCHBAR32(RCVENMT);
2705 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2706 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2707 MCHBAR32(RCVENMT) = reg32;
2708
2709 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2710 reg32 |= (u32)(values[3] & 0x0f) << 24;
2711 MCHBAR32(C0DRT1) = reg32;
2712
2713 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2714 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2715 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002716}
2717
2718#include "rcven.c"
2719
2720static void sdram_program_receive_enable(struct sys_info *sysinfo)
2721{
2722 MCHBAR32(REPC) |= (1 << 0);
2723
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002724 /* enable upper CMOS */
2725 RCBA32(0x3400) = (1 << 2);
2726
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002727 /* Program Receive Enable Timings */
2728 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2729 sdram_recover_receive_enable();
2730 } else {
2731 receive_enable_adjust(sysinfo);
2732 sdram_save_receive_enable();
2733 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002734
2735 MCHBAR32(C0DRC1) |= (1 << 6);
2736 MCHBAR32(C1DRC1) |= (1 << 6);
2737 MCHBAR32(C0DRC1) &= ~(1 << 6);
2738 MCHBAR32(C1DRC1) &= ~(1 << 6);
2739
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002740 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002741}
2742
2743/**
2744 * @brief Enable On-Die Termination for DDR2.
2745 *
2746 */
2747
2748static void sdram_on_die_termination(struct sys_info *sysinfo)
2749{
2750 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002751 0x00024911, 0xe0010000,
2752 0x00049211, 0xe0020000,
2753 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002754 };
2755
2756 u32 reg32;
2757 int cas;
2758
2759 reg32 = MCHBAR32(ODTC);
2760 reg32 &= ~(3 << 16);
2761 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2762 MCHBAR32(ODTC) = reg32;
2763
2764 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2765 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002766 printk(BIOS_DEBUG, "one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002767
Stefan Reinauer278534d2008-10-29 04:51:07 +00002768 reg32 = MCHBAR32(C0ODT);
2769 reg32 &= ~(7 << 28);
2770 MCHBAR32(C0ODT) = reg32;
2771 reg32 = MCHBAR32(C1ODT);
2772 reg32 &= ~(7 << 28);
2773 MCHBAR32(C1ODT) = reg32;
2774 }
2775
2776 cas = sysinfo->cas;
2777
2778 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2779 reg32 |= odt[(cas-3) * 2];
2780 MCHBAR32(C0ODT) = reg32;
2781
2782 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2783 reg32 |= odt[(cas-3) * 2];
2784 MCHBAR32(C1ODT) = reg32;
2785
2786 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2787 reg32 |= odt[((cas-3) * 2) + 1];
2788 MCHBAR32(C0ODT + 4) = reg32;
2789
2790 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2791 reg32 |= odt[((cas-3) * 2) + 1];
2792 MCHBAR32(C1ODT + 4) = reg32;
2793}
2794
2795/**
2796 * @brief Enable clocks to populated sockets
2797 */
2798
2799static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2800{
2801 u8 clocks[2] = { 0, 0 };
2802
Peter Stugee4bc0f62010-10-01 09:13:18 +00002803#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002804#define CLOCKS_WIDTH 2
Peter Stugee4bc0f62010-10-01 09:13:18 +00002805#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002806#define CLOCKS_WIDTH 3
2807#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002808 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002809 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002810
2811 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002812 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002813
2814 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002815 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002816
2817 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002818 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002819
Patrick Georgi77d66832010-10-01 08:02:45 +00002820#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002821 /* Usually system firmware turns off system memory clock signals
2822 * to unused SO-DIMM slots to reduce EMI and power consumption.
2823 * However, the Kontron 986LCD-M does not like unused clock
2824 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002825 */
2826
2827 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2828 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002829#endif
2830
2831 MCHBAR8(C0DCLKDIS) = clocks[0];
2832 MCHBAR8(C1DCLKDIS) = clocks[1];
2833}
2834
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002835#define RTT_ODT_NONE 0
2836#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002837#define RTT_ODT_75_OHM (1 << 5)
2838#define RTT_ODT_150_OHM (1 << 9)
2839
2840#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2841
2842#define MRS_CAS_3 (3 << 7)
2843#define MRS_CAS_4 (4 << 7)
2844#define MRS_CAS_5 (5 << 7)
2845
2846#define MRS_TWR_3 (2 << 12)
2847#define MRS_TWR_4 (3 << 12)
2848#define MRS_TWR_5 (4 << 12)
2849
2850#define MRS_BT (1 << 6)
2851
2852#define MRS_BL4 (2 << 3)
2853#define MRS_BL8 (3 << 3)
2854
2855static void sdram_jedec_enable(struct sys_info *sysinfo)
2856{
2857 int i, nonzero;
2858 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2859
2860 for (i = 0, nonzero = -1; i < 8; i++) {
2861 if (sysinfo->banksize[i] == 0) {
2862 continue;
2863 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002864
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002865 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002866 switch (i) {
2867 case 0:
2868 /* Start at address 0 */
2869 bankaddr = 0;
2870 break;
2871 case 4:
2872 if (sysinfo->interleaved) {
2873 bankaddr = 0x40;
2874 break;
2875 }
2876 default:
2877 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002878 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002879 bankaddr += sysinfo->banksize[nonzero] <<
2880 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002881 break;
2882 }
2883 /* No populated bank hit before. Start at address 0 */
2884 bankaddr = 0;
2885 }
2886
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002887 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002888 * for the next offset we have to calculate
2889 */
2890 nonzero = i;
2891
2892 /* Get CAS latency set up */
2893 switch (sysinfo->cas) {
2894 case 5: mrsaddr = MRS_CAS_5; break;
2895 case 4: mrsaddr = MRS_CAS_4; break;
2896 case 3: mrsaddr = MRS_CAS_3; break;
2897 default: die("Jedec Error (CAS).\n");
2898 }
2899
2900 /* Get tWR set */
2901 switch (sysinfo->twr) {
2902 case 5: mrsaddr |= MRS_TWR_5; break;
2903 case 4: mrsaddr |= MRS_TWR_4; break;
2904 case 3: mrsaddr |= MRS_TWR_3; break;
2905 default: die("Jedec Error (tWR).\n");
2906 }
2907
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002908 /* Set "Burst Type" */
2909 mrsaddr |= MRS_BT;
2910
Stefan Reinauer278534d2008-10-29 04:51:07 +00002911 /* Interleaved */
2912 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002913 mrsaddr = mrsaddr << 1;
2914 }
2915
2916 /* Only burst length 8 supported */
2917 mrsaddr |= MRS_BL8;
2918
2919 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002920 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002921 do_ram_command(RAM_COMMAND_NOP);
2922 ram_read32(bankaddr);
2923
2924 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002925 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002926 do_ram_command(RAM_COMMAND_PRECHARGE);
2927 ram_read32(bankaddr);
2928
2929 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002930 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002931 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2932 ram_read32(bankaddr);
2933
2934 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002935 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002936 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2937 ram_read32(bankaddr);
2938
2939 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002940 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002941 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2942 tmpaddr = bankaddr;
2943 if (!sdram_capabilities_dual_channel()) {
2944 tmpaddr |= RTT_ODT_75_OHM;
2945 } else if (sysinfo->interleaved) {
2946 tmpaddr |= (RTT_ODT_150_OHM << 1);
2947 } else {
2948 tmpaddr |= RTT_ODT_150_OHM;
2949 }
2950 ram_read32(tmpaddr);
2951
2952 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002953 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002954 do_ram_command(RAM_COMMAND_MRS);
2955 tmpaddr = bankaddr;
2956 tmpaddr |= mrsaddr;
2957 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002958 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002959 tmpaddr |= (1 << 12);
2960 else
2961 tmpaddr |= (1 << 11);
2962 ram_read32(tmpaddr);
2963
2964 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002965 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002966 do_ram_command(RAM_COMMAND_PRECHARGE);
2967 ram_read32(bankaddr);
2968
2969 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002970 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002971 do_ram_command(RAM_COMMAND_CBR);
2972
2973 /* CBR wants two READs */
2974 ram_read32(bankaddr);
2975 ram_read32(bankaddr);
2976
2977 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002978 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002979 do_ram_command(RAM_COMMAND_MRS);
2980
2981 tmpaddr = bankaddr;
2982 tmpaddr |= mrsaddr;
2983 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002984
Stefan Reinauer278534d2008-10-29 04:51:07 +00002985 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002986 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002987 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002988
Stefan Reinauer278534d2008-10-29 04:51:07 +00002989 tmpaddr = bankaddr;
2990 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002991
Stefan Reinauer278534d2008-10-29 04:51:07 +00002992 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
2993 } else if (sysinfo->interleaved) {
2994 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
2995 } else {
2996 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
2997 }
2998 ram_read32(tmpaddr);
2999
3000 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003001 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003002 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3003
3004 tmpaddr = bankaddr;
3005 if (!sdram_capabilities_dual_channel()) {
3006 tmpaddr |= RTT_ODT_75_OHM;
3007 } else if (sysinfo->interleaved) {
3008 tmpaddr |= (RTT_ODT_150_OHM << 1);
3009 } else {
3010 tmpaddr |= RTT_ODT_150_OHM;
3011 }
3012 ram_read32(tmpaddr);
3013 }
3014}
3015
3016static void sdram_init_complete(void)
3017{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003018 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003019 do_ram_command(RAM_COMMAND_NORMAL);
3020}
3021
3022static void sdram_setup_processor_side(void)
3023{
3024 if (i945_silicon_revision() == 0)
3025 MCHBAR32(FSBPMC3) |= (1 << 2);
3026
3027 MCHBAR8(0xb00) |= 1;
3028
3029 if (i945_silicon_revision() == 0)
3030 MCHBAR32(SLPCTL) |= (1 << 8);
3031}
3032
Stefan Reinauer278534d2008-10-29 04:51:07 +00003033/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003034 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003035 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003036void sdram_initialize(int boot_path)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003037{
3038 struct sys_info sysinfo;
3039 u8 reg8, cas_mask;
3040
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003041 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003042
3043 memset(&sysinfo, 0, sizeof(sysinfo));
3044
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003045 sysinfo.boot_path = boot_path;
3046
Stefan Reinauer278534d2008-10-29 04:51:07 +00003047 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3048 sdram_get_dram_configuration(&sysinfo);
3049
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003050 /* If error, do cold boot */
3051 sdram_detect_errors(&sysinfo);
3052
Stefan Reinauer278534d2008-10-29 04:51:07 +00003053 /* Check whether we have stacked DIMMs */
3054 sdram_verify_package_type(&sysinfo);
3055
3056 /* Determine common CAS */
3057 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003058
Stefan Reinauer278534d2008-10-29 04:51:07 +00003059 /* Choose Common Frequency */
3060 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003061
Stefan Reinauer278534d2008-10-29 04:51:07 +00003062 /* Determine smallest common tRAS */
3063 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003064
Stefan Reinauer278534d2008-10-29 04:51:07 +00003065 /* Determine tRP */
3066 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003067
Stefan Reinauer278534d2008-10-29 04:51:07 +00003068 /* Determine tRCD */
3069 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003070
Stefan Reinauer278534d2008-10-29 04:51:07 +00003071 /* Determine smallest refresh period */
3072 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003073
Stefan Reinauer278534d2008-10-29 04:51:07 +00003074 /* Verify all DIMMs support burst length 8 */
3075 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003076
Stefan Reinauer278534d2008-10-29 04:51:07 +00003077 /* determine tWR */
3078 sdram_detect_smallest_tWR(&sysinfo);
3079
3080 /* Determine DIMM size parameters (rows, columns banks) */
3081 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003082
Stefan Reinauer278534d2008-10-29 04:51:07 +00003083 /* determine tRFC */
3084 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003085
Stefan Reinauer278534d2008-10-29 04:51:07 +00003086 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003087 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003088
3089 /* Program Graphics Frequency */
3090 sdram_program_graphics_frequency(&sysinfo);
3091
3092 /* Program System Memory Frequency */
3093 sdram_program_memory_frequency(&sysinfo);
3094
3095 /* Determine Mode of Operation (Interleaved etc) */
3096 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003097
Stefan Reinauer278534d2008-10-29 04:51:07 +00003098 /* Program Clock Crossing values */
3099 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003100
Stefan Reinauer278534d2008-10-29 04:51:07 +00003101 /* Disable fast dispatch */
3102 sdram_disable_fast_dispatch();
3103
3104 /* Enable WIODLL Power Down in ACPI states */
3105 MCHBAR32(C0DMC) |= (1 << 24);
3106 MCHBAR32(C1DMC) |= (1 << 24);
3107
3108 /* Program DRAM Row Boundary/Attribute Registers */
3109
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003110 /* program row size DRB and set TOLUD */
3111 sdram_program_row_boundaries(&sysinfo);
3112
3113 /* program page size DRA */
3114 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003115
3116 /* Program CxBNKARC */
3117 sdram_set_bank_architecture(&sysinfo);
3118
3119 /* Program DRAM Timing and Control registers based on SPD */
3120 sdram_set_timing_and_control(&sysinfo);
3121
3122 /* On-Die Termination Adjustment */
3123 sdram_on_die_termination(&sysinfo);
3124
3125 /* Pre Jedec Initialization */
3126 sdram_pre_jedec_initialization();
3127
3128 /* Perform System Memory IO Initialization */
3129 sdram_initialize_system_memory_io(&sysinfo);
3130
3131 /* Perform System Memory IO Buffer Enable */
3132 sdram_enable_system_memory_io(&sysinfo);
3133
3134 /* Enable System Memory Clocks */
3135 sdram_enable_memory_clocks(&sysinfo);
3136
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003137 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003138 /* Jedec Initialization sequence */
3139 sdram_jedec_enable(&sysinfo);
3140 }
3141
3142 /* Program Power Management Registers */
3143 sdram_power_management(&sysinfo);
3144
3145 /* Post Jedec Init */
3146 sdram_post_jedec_initialization(&sysinfo);
3147
3148 /* Program DRAM Throttling */
3149 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003150
Stefan Reinauer278534d2008-10-29 04:51:07 +00003151 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003152 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003153
3154 /* Program Receive Enable Timings */
3155 sdram_program_receive_enable(&sysinfo);
3156
3157 /* Enable Periodic RCOMP */
3158 sdram_enable_rcomp();
3159
3160 /* Tell ICH7 that we're done */
3161 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3162 reg8 &= ~(1 << 7);
3163 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3164
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003165 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003166
Stefan Reinauer278534d2008-10-29 04:51:07 +00003167 sdram_setup_processor_side();
3168}
3169
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003170unsigned long get_top_of_ram(void)
3171{
3172 /* This will not work if TSEG is in place! */
3173 u32 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
3174
3175 return (unsigned long) tom;
3176}
3177