blob: 235375673d6d0b884bd3d421a680038286942c88 [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
Stefan Reinauer278534d2008-10-29 04:51:07 +000020#include <cpu/x86/mem.h>
21#include <cpu/x86/mtrr.h>
22#include <cpu/x86/cache.h>
23#include <spd.h>
24#include "raminit.h"
25#include "i945.h"
26
Stefan Reinauer278534d2008-10-29 04:51:07 +000027/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000028#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer278534d2008-10-29 04:51:07 +000029#define PRINTK_DEBUG(x...) printk_debug(x)
30#else
31#define PRINTK_DEBUG(x...)
32#endif
33
Stefan Reinauer278534d2008-10-29 04:51:07 +000034#define RAM_INITIALIZATION_COMPLETE (1 << 19)
35
36#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
37#define RAM_COMMAND_NOP (0x1 << 16)
38#define RAM_COMMAND_PRECHARGE (0x2 << 16)
39#define RAM_COMMAND_MRS (0x3 << 16)
40#define RAM_COMMAND_EMRS (0x4 << 16)
41#define RAM_COMMAND_CBR (0x6 << 16)
42#define RAM_COMMAND_NORMAL (0x7 << 16)
43
44#define RAM_EMRS_1 (0x0 << 21)
45#define RAM_EMRS_2 (0x1 << 21)
46#define RAM_EMRS_3 (0x2 << 21)
47
48static void do_ram_command(u32 command)
49{
50 u32 reg32;
51
52 reg32 = MCHBAR32(DCC);
53 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
54 reg32 |= command;
55
56 /* Also set Init Complete */
57 if (command == RAM_COMMAND_NORMAL)
58 reg32 |= RAM_INITIALIZATION_COMPLETE;
59
60 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
61
62 MCHBAR32(DCC) = reg32; /* This is the actual magic */
63
Stefan Reinauer779b3e32008-11-10 15:43:37 +000064 PRINTK_DEBUG("...done\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000065}
66
Stefan Reinauer278534d2008-10-29 04:51:07 +000067static void ram_read32(u32 offset)
68{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000069 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000070
71 read32(offset);
72}
73
Uwe Hermann01ce6012010-03-05 10:03:50 +000074#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer278534d2008-10-29 04:51:07 +000075static void sdram_dump_mchbar_registers(void)
76{
77 int i;
Stefan Reinauer779b3e32008-11-10 15:43:37 +000078 printk_debug("Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000079
80 for (i=0; i<0xfff; i+=4) {
81 if (MCHBAR32(i) == 0)
82 continue;
Stefan Reinauer779b3e32008-11-10 15:43:37 +000083 printk_debug("0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +000084 }
85}
86#endif
87
Stefan Reinauer24b4df52010-01-17 13:47:35 +000088static int memclk(void)
89{
90 int offset = 0;
91#ifdef CHIPSET_I945GM
92 offset++;
93#endif
94 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
95 case 1: return 400;
96 case 2: return 533;
97 case 3: return 667;
98 default: printk_debug("memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
99 }
100 return -1;
101}
102
103#ifdef CHIPSET_I945GM
104static int fsbclk(void)
105{
106 switch (MCHBAR32(CLKCFG) & 7) {
107 case 0: return 400;
108 case 1: return 533;
109 case 3: return 667;
110 default: printk_debug("fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
111 }
112 return -1;
113}
114#endif
115#ifdef CHIPSET_I945GC
116static int fsbclk(void)
117{
118 switch (MCHBAR32(CLKCFG) & 7) {
119 case 0: return 1066;
120 case 1: return 533;
121 case 2: return 800;
122 default: printk_debug("fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
123 }
124 return -1;
125}
126#endif
127
Stefan Reinauer278534d2008-10-29 04:51:07 +0000128static int sdram_capabilities_max_supported_memory_frequency(void)
129{
130 u32 reg32;
131
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000132#ifdef MAXIMUM_SUPPORTED_FREQUENCY
133 return MAXIMUM_SUPPORTED_FREQUENCY;
134#endif
135
136 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000137 reg32 &= (7 << 0);
138
139 switch (reg32) {
140 case 4: return 400;
141 case 3: return 533;
142 case 2: return 667;
143 }
144 /* Newer revisions of this chipset rather support faster memory clocks,
145 * so if it's a reserved value, return the fastest memory clock that we
146 * know of and can handle
147 */
148 return 667;
149}
150
151/**
152 * @brief determine whether chipset is capable of dual channel interleaved mode
153 *
154 * @return 1 if interleaving is supported, 0 otherwise
155 */
156static int sdram_capabilities_interleave(void)
157{
158 u32 reg32;
159
160 reg32 = pci_read_config8(PCI_DEV(0, 0x00,0), 0xe4);
161 reg32 >>= 25;
162 reg32 &= 1;
163
164 return (!reg32);
165}
166
167/**
168 * @brief determine whether chipset is capable of two memory channels
169 *
170 * @return 1 if dual channel operation is supported, 0 otherwise
171 */
172static int sdram_capabilities_dual_channel(void)
173{
174 u32 reg32;
175
176 reg32 = pci_read_config8(PCI_DEV(0, 0x00,0), 0xe4);
177 reg32 >>= 24;
178 reg32 &= 1;
179
180 return (!reg32);
181}
182
183static int sdram_capabilities_enhanced_addressing_xor(void)
184{
185 u8 reg8;
186
187 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
188 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000189
Stefan Reinauer278534d2008-10-29 04:51:07 +0000190 return (!reg8);
191}
192
193static int sdram_capabilities_two_dimms_per_channel(void)
194{
195 u8 reg8;
196
197 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
198 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000199
Stefan Reinauer278534d2008-10-29 04:51:07 +0000200 return (reg8 != 0);
201}
202
203static int sdram_capabilities_MEM4G_disable(void)
204{
205 u8 reg8;
206
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000207 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000208 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000209
Stefan Reinauer278534d2008-10-29 04:51:07 +0000210 return (reg8 != 0);
211}
212
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000213#define GFX_FREQUENCY_CAP_166MHZ 0x04
214#define GFX_FREQUENCY_CAP_200MHZ 0x03
215#define GFX_FREQUENCY_CAP_250MHZ 0x02
216#define GFX_FREQUENCY_CAP_ALL 0x00
217
218static int sdram_capabilities_core_frequencies(void)
219{
220 u8 reg8;
221
222 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
223 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
224 reg8 >>= 1;
225
226 return (reg8);
227}
228
Stefan Reinauer278534d2008-10-29 04:51:07 +0000229static void sdram_detect_errors(void)
230{
231 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000232 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000233
234 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000235
Stefan Reinauer278534d2008-10-29 04:51:07 +0000236 if (reg8 & ((1<<7)|(1<<2))) {
237 if (reg8 & (1<<2)) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000238 printk_debug("SLP S4# Assertion Width Violation.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000239
Stefan Reinauer278534d2008-10-29 04:51:07 +0000240 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000241
Stefan Reinauer278534d2008-10-29 04:51:07 +0000242 }
243
244 if (reg8 & (1<<7)) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000245 printk_debug("DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000246 reg8 &= ~(1<<7);
247 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000248 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000249 }
250
251 /* Set SLP_S3# Assertion Stretch Enable */
252 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
253 reg8 |= (1 << 3);
254 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
255
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000256 if (do_reset) {
257 printk_debug("Reset required.\n");
258 outb(0x00, 0xcf9);
259 outb(0x0e, 0xcf9);
260 for (;;) ; /* Wait for reset! */
261 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000262 }
263
264 /* Set DRAM initialization bit in ICH7 */
265 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
266 reg8 |= (1<<7);
267 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000268
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000269}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000270
271/**
272 * @brief Get generic DIMM parameters.
273 * @param sysinfo Central memory controller information structure
274 *
275 * This function gathers several pieces of information for each system DIMM:
276 * o DIMM width (x8 / x16)
277 * o DIMM sides (single sided / dual sided)
278 *
279 * Also, some non-supported scenarios are detected.
280 */
281
282static void sdram_get_dram_configuration(struct sys_info *sysinfo)
283{
284 u32 dimm_mask = 0;
285 int i;
286
287 /**
288 * i945 supports two DIMMs, in two configurations:
289 *
290 * - single channel with two dimms
291 * - dual channel with one dimm per channel
292 *
293 * In practice dual channel mainboards have their spd at 0x50, 0x52
294 * whereas single channel configurations have their spd at 0x50/x51
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000295 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000296 * The capability register knows a lot about the channel configuration
297 * but for now we stick with the information we gather from the SPD
298 * ROMs
299 */
300
301 if (sdram_capabilities_dual_channel()) {
302 sysinfo->dual_channel = 1;
303 printk_debug("This mainboard supports Dual Channel Operation.\n");
304 } else {
305 sysinfo->dual_channel = 0;
306 printk_debug("This mainboard supports only Single Channel Operation.\n");
307 }
308
309 /**
310 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000311 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000312 * return value:
313 * [0:7] lower DIMM population
314 * [8-15] higher DIMM population
315 * [16] dual channel?
316 *
317 * There are 5 different possible populations for a DIMM socket:
318 * 1. x16 double sided (X16DS)
319 * 2. x8 double sided (X8DS)
320 * 3. x16 single sided (X16SS)
321 * 4. x8 double stacked (X8DDS)
322 * 5. not populated (NC)
323 *
324 * For the return value we start counting at zero.
325 *
326 */
327
328 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
329 u8 reg8, device = DIMM_SPD_BASE + i;
330
331 /* Initialize the socket information with a sane value */
332 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
333
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000334 /* Dual Channel not supported, but Channel 1? Bail out */
335 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000336 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000337
338 /* Two DIMMs per channel not supported, but odd DIMM number? */
339 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000340 continue;
341
342 printk_debug("DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
343
344 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
345 printk_debug("N/A\n");
346 continue;
347 }
348
349 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
350 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000351 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000352
353 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
354 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000355 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000356 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000357 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000358
359 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000360 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000361 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
362 case 1:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000363 printk_debug("x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000364 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
365 break;
366 case 0:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000367 printk_debug("x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000368 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
369 break;
370 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000371 printk_debug ("Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000372 }
373 break;
374 case 0x10:
375 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
376 case 1:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000377 printk_debug("x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000378 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
379 break;
380 case 0:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000381 printk_debug("x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000382 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
383 break;
384 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000385 printk_debug ("Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000386 }
387 break;
388 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000389 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000390 }
391
392 dimm_mask |= (1 << i);
393 }
394
395 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000396 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000397 }
398
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000400 printk_info("Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000401 }
402}
403
404/**
405 * @brief determine if any DIMMs are stacked
406 *
407 * @param sysinfo central sysinfo data structure.
408 */
409static void sdram_verify_package_type(struct sys_info * sysinfo)
410{
411 int i;
412
413 /* Assume no stacked DIMMs are available until we find one */
414 sysinfo->package = 0;
415 for (i=0; i<2*DIMM_SOCKETS; i++) {
416 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
417 continue;
418
419 /* Is the current DIMM a stacked DIMM? */
420 if (spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS) & (1 << 4))
421 sysinfo->package = 1;
422 }
423}
424
425static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
426{
427 int i;
428 u8 cas_mask;
429
430 /* Setup CAS mask with all supported CAS Latencies */
431 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
432 SPD_CAS_LATENCY_DDR2_4 |
433 SPD_CAS_LATENCY_DDR2_5;
434
435 for (i=0; i<2*DIMM_SOCKETS; i++) {
436 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
437 cas_mask &= spd_read_byte(DIMM_SPD_BASE + i, SPD_ACCEPTABLE_CAS_LATENCIES);
438 }
439
440 if(!cas_mask) {
441 die("No DDR-II modules with accepted CAS latencies found.\n");
442 }
443
444 return cas_mask;
445}
446
447static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
448{
449 int i, j, idx;
450 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000451 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000452
453 const u8 ddr2_speeds_table[] = {
454 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
455 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
456 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
457 };
458
459 const u8 spd_lookup_table[] = {
460 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
461 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
462 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
463 };
464
465 switch (sdram_capabilities_max_supported_memory_frequency()) {
466 case 400: max_ram_speed = 0; break;
467 case 533: max_ram_speed = 1; break;
468 case 667: max_ram_speed = 2; break;
469 }
470
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000471 if (fsbclk() == 533)
472 max_ram_speed = 1;
473
Stefan Reinauer278534d2008-10-29 04:51:07 +0000474 sysinfo->memory_frequency = 0;
475 sysinfo->cas = 0;
476
477 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
478 lowest_common_cas = 3;
479 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
480 lowest_common_cas = 4;
481 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
482 lowest_common_cas = 5;
483 }
484 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
485
486 for (j = max_ram_speed; j>=0; j--) {
487 int freq_cas_mask = cas_mask;
488
489 PRINTK_DEBUG("Probing Speed %d\n", j);
490 for (i=0; i<2*DIMM_SOCKETS; i++) {
491 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000492
Stefan Reinauer278534d2008-10-29 04:51:07 +0000493 PRINTK_DEBUG(" DIMM: %d\n", i);
494 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
495 continue;
496 }
497
498 current_cas_mask = spd_read_byte(DIMM_SPD_BASE + i, SPD_ACCEPTABLE_CAS_LATENCIES);
499
500 while (current_cas_mask) {
501 int highest_supported_cas = 0, current_cas = 0;
502 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
503 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
504 highest_supported_cas = 5;
505 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
506 highest_supported_cas = 4;
507 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
508 highest_supported_cas = 3;
509 }
510 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
511 current_cas = 3;
512 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
513 current_cas = 4;
514 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
515 current_cas = 5;
516 }
517
518 idx = highest_supported_cas - current_cas;
519 PRINTK_DEBUG("idx=%d, ", idx);
520 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[2*idx]));
521 PRINTK_DEBUG("tAC=%x", spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[(2*idx)+1]));
522
523 if (spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
524 spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
525 PRINTK_DEBUG(": OK\n");
526 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000527 }
528
Stefan Reinauer278534d2008-10-29 04:51:07 +0000529 PRINTK_DEBUG(": Not fast enough!\n");
530
531 current_cas_mask &= ~(1 << (current_cas));
532 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000533
Stefan Reinauer278534d2008-10-29 04:51:07 +0000534 freq_cas_mask &= current_cas_mask;
535 if (!current_cas_mask) {
536 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
537 break;
538 }
539 }
540 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
541 if (freq_cas_mask) {
542 switch (j) {
543 case 0: sysinfo->memory_frequency = 400; break;
544 case 1: sysinfo->memory_frequency = 533; break;
545 case 2: sysinfo->memory_frequency = 667; break;
546 }
547 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
548 sysinfo->cas = 3;
549 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
550 sysinfo->cas = 4;
551 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
552 sysinfo->cas = 5;
553 }
554 break;
555 }
556 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000557
Stefan Reinauer278534d2008-10-29 04:51:07 +0000558 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauer977ed2d2009-01-20 22:46:52 +0000559 printk_debug("Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000560 sysinfo->memory_frequency, sysinfo->cas);
561 } else {
562 die("Could not find common memory frequency and CAS\n");
563 }
564}
565
566static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
567{
568 int i;
569 int tRAS_time;
570 int tRAS_cycles;
571 int freq_multiplier = 0;
572
573 switch (sysinfo->memory_frequency) {
574 case 400: freq_multiplier = 0x14; break; /* 5ns */
575 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
576 case 667: freq_multiplier = 0x0c; break; /* 3ns */
577 }
578
579 tRAS_cycles = 4; /* 4 clocks minimum */
580 tRAS_time = tRAS_cycles * freq_multiplier;
581
582 for (i=0; i<2*DIMM_SOCKETS; i++) {
583 u8 reg8;
584
585 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
586 continue;
587
588 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
589 if (!reg8) {
590 die("Invalid tRAS value.\n");
591 }
592
593 while ((tRAS_time >> 2) < reg8) {
594 tRAS_time += freq_multiplier;
595 tRAS_cycles++;
596 }
597 }
598 if(tRAS_cycles > 0x18) {
599 die("DDR-II Module does not support this frequency (tRAS error)\n");
600 }
601
602 printk_debug("tRAS = %d cycles\n", tRAS_cycles);
603 sysinfo->tras = tRAS_cycles;
604}
605
606static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
607{
608 int i;
609 int tRP_time;
610 int tRP_cycles;
611 int freq_multiplier = 0;
612
613 switch (sysinfo->memory_frequency) {
614 case 400: freq_multiplier = 0x14; break; /* 5ns */
615 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
616 case 667: freq_multiplier = 0x0c; break; /* 3ns */
617 }
618
619 tRP_cycles = 2; /* 2 clocks minimum */
620 tRP_time = tRP_cycles * freq_multiplier;
621
622 for (i=0; i<2*DIMM_SOCKETS; i++) {
623 u8 reg8;
624
625 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
626 continue;
627
628 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_ROW_PRECHARGE_TIME);
629 if (!reg8) {
630 die("Invalid tRP value.\n");
631 }
632
633 while (tRP_time < reg8) {
634 tRP_time += freq_multiplier;
635 tRP_cycles++;
636 }
637 }
638
639 if(tRP_cycles > 6) {
640 die("DDR-II Module does not support this frequency (tRP error)\n");
641 }
642
643 printk_debug("tRP = %d cycles\n", tRP_cycles);
644 sysinfo->trp = tRP_cycles;
645}
646
647static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
648{
649 int i;
650 int tRCD_time;
651 int tRCD_cycles;
652 int freq_multiplier = 0;
653
654 switch (sysinfo->memory_frequency) {
655 case 400: freq_multiplier = 0x14; break; /* 5ns */
656 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
657 case 667: freq_multiplier = 0x0c; break; /* 3ns */
658 }
659
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000660 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000661 tRCD_time = tRCD_cycles * freq_multiplier;
662
663 for (i=0; i<2*DIMM_SOCKETS; i++) {
664 u8 reg8;
665
666 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
667 continue;
668
669 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_RAS_TO_CAS_DELAY);
670 if (!reg8) {
671 die("Invalid tRCD value.\n");
672 }
673
674 while (tRCD_time < reg8) {
675 tRCD_time += freq_multiplier;
676 tRCD_cycles++;
677 }
678 }
679 if(tRCD_cycles > 6) {
680 die("DDR-II Module does not support this frequency (tRCD error)\n");
681 }
682
683 printk_debug("tRCD = %d cycles\n", tRCD_cycles);
684 sysinfo->trcd = tRCD_cycles;
685}
686
687static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
688{
689 int i;
690 int tWR_time;
691 int tWR_cycles;
692 int freq_multiplier = 0;
693
694 switch (sysinfo->memory_frequency) {
695 case 400: freq_multiplier = 0x14; break; /* 5ns */
696 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
697 case 667: freq_multiplier = 0x0c; break; /* 3ns */
698 }
699
700 tWR_cycles = 2; /* 2 clocks minimum */
701 tWR_time = tWR_cycles * freq_multiplier;
702
703 for (i=0; i<2*DIMM_SOCKETS; i++) {
704 u8 reg8;
705
706 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
707 continue;
708
709 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_WRITE_RECOVERY_TIME);
710 if (!reg8) {
711 die("Invalid tWR value.\n");
712 }
713
714 while (tWR_time < reg8) {
715 tWR_time += freq_multiplier;
716 tWR_cycles++;
717 }
718 }
719 if(tWR_cycles > 5) {
720 die("DDR-II Module does not support this frequency (tWR error)\n");
721 }
722
723 printk_debug("tWR = %d cycles\n", tWR_cycles);
724 sysinfo->twr = tWR_cycles;
725}
726
727static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
728{
729 int i, index = 0;
730
731 const u8 tRFC_cycles[] = {
732 /* 75 105 127.5 */
733 15, 21, 26, /* DDR2-400 */
734 20, 28, 34, /* DDR2-533 */
735 25, 35, 43 /* DDR2-667 */
736 };
737
738 for (i=0; i<2*DIMM_SOCKETS; i++) {
739 u8 reg8;
740
741 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
742 continue;
743
744 reg8 = sysinfo->banksize[i*2];
745 switch (reg8) {
746 case 0x04: reg8 = 0; break;
747 case 0x08: reg8 = 1; break;
748 case 0x10: reg8 = 2; break;
749 case 0x20: reg8 = 3; break;
750 }
751
752 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
753 reg8++;
754
755 if (reg8 > 3) {
756 /* Can this happen? Go back to 127.5ns just to be sure
757 * we don't run out of the array. This may be wrong
758 */
759 printk_debug("DIMM %d is 1Gb x16.. Please report.\n", i);
760 reg8 = 3;
761 }
762
763 if (reg8 > index)
764 index = reg8;
765
766 }
767 index--;
768 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000769 case 667: index += 3; /* Fallthrough */
770 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000771 case 400: break;
772 }
773
774 sysinfo->trfc = tRFC_cycles[index];
775 printk_debug("tRFC = %d cycles\n", tRFC_cycles[index]);
776}
777
Stefan Reinauer278534d2008-10-29 04:51:07 +0000778static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
779{
780 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000781
Stefan Reinauer278534d2008-10-29 04:51:07 +0000782 sysinfo->refresh = 0;
783
784 for (i=0; i<2*DIMM_SOCKETS; i++) {
785 int refresh;
786
787 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
788 continue;
789
790 refresh = spd_read_byte(DIMM_SPD_BASE + i, SPD_REFRESH) & ~(1 << 7);
791
792 /* 15.6us */
793 if (!refresh)
794 continue;
795
796 /* Refresh is slower than 15.6us, use 15.6us */
797 if (refresh > 2)
798 continue;
799
800 if (refresh == 2) {
801 sysinfo->refresh = 1;
802 break;
803 }
804
805 die("DDR-II module has unsupported refresh value\n");
806 }
807 printk_debug("Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
808}
809
810static void sdram_verify_burst_length(struct sys_info * sysinfo)
811{
812 int i;
813
814 for (i=0; i<2*DIMM_SOCKETS; i++) {
815 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
816 continue;
817
818 if (!(spd_read_byte(DIMM_SPD_BASE + i, SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
819 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
820 }
821}
822
823static void sdram_program_dram_width(struct sys_info * sysinfo)
824{
825 u16 c0dramw=0, c1dramw=0;
826 int idx;
827
828 if (sysinfo->dual_channel)
829 idx = 2;
830 else
831 idx = 1;
832
833 switch (sysinfo->dimm[0]) {
834 case 0: c0dramw = 0x0000; break; /* x16DS */
835 case 1: c0dramw = 0x0001; break; /* x8DS */
836 case 2: c0dramw = 0x0000; break; /* x16SS */
837 case 3: c0dramw = 0x0005; break; /* x8DDS */
838 case 4: c0dramw = 0x0000; break; /* NC */
839 }
840
841 switch (sysinfo->dimm[idx]) {
842 case 0: c1dramw = 0x0000; break; /* x16DS */
843 case 1: c1dramw = 0x0010; break; /* x8DS */
844 case 2: c1dramw = 0x0000; break; /* x16SS */
845 case 3: c1dramw = 0x0050; break; /* x8DDS */
846 case 4: c1dramw = 0x0000; break; /* NC */
847 }
848
849 if ( !sdram_capabilities_dual_channel() ) {
850 /* Single Channel */
851 c0dramw |= c1dramw;
852 c1dramw = 0;
853 }
854
855 MCHBAR16(C0DRAMW) = c0dramw;
856 MCHBAR16(C1DRAMW) = c1dramw;
857}
858
859static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
860{
861 int i;
862
863 for (i=0; i<16; i++)
864 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
865}
866
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000867static const u32 dq2030[] = {
868 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
869 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
870 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
871 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
872};
873
874static const u32 dq2330[] = {
875 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
876 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
877 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
878 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
879};
880
881static const u32 cmd2710[] = {
882 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
883 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
884 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
885 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
886};
887
888static const u32 cmd3210[] = {
889 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
890 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
891 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
892 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
893};
894
895static const u32 clk2030[] = {
896 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
897 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
898 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
899 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
900};
901
902static const u32 ctl3215[] = {
903 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
904 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
905 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
906 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
907};
908
909static const u32 ctl3220[] = {
910 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
911 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
912 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
913 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
914};
915
916static const u32 nc[] = {
917 0x00000000, 0x00000000, 0x00000000, 0x00000000,
918 0x00000000, 0x00000000, 0x00000000, 0x00000000,
919 0x00000000, 0x00000000, 0x00000000, 0x00000000,
920 0x00000000, 0x00000000, 0x00000000, 0x00000000
921};
922
923enum {
924 DQ2030,
925 DQ2330,
926 CMD2710,
927 CMD3210,
928 CLK2030,
929 CTL3215,
930 CTL3220,
931 NC,
932};
933
934static const u8 dual_channel_slew_group_lookup[] = {
935 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
936 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
937 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
938 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
939 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
940
941 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
942 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
943 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
944 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
945 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
946
947 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
948 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
949 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
950 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
951 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
952
953 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
954 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
955 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
956 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
957 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
958
959 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
960 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
961 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
962 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
963};
964
965static const u8 single_channel_slew_group_lookup[] = {
966 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
967 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
968 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
969 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
970 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
971
972 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
973 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
974 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
975 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
976 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
977
978 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
979 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
980 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
981 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
982 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
983
984 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
985 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
986 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
987 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
988 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
989
990 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
991 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
992 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
993 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
994};
995
996static const u32 *slew_group_lookup(int dual_channel, int index)
997{
998 const u8 *slew_group;
999 /* Dual Channel needs different tables. */
1000 if (dual_channel)
1001 slew_group = dual_channel_slew_group_lookup;
1002 else
1003 slew_group = single_channel_slew_group_lookup;
1004
1005 switch (slew_group[index]) {
1006 case DQ2030: return dq2030;
1007 case DQ2330: return dq2330;
1008 case CMD2710: return cmd2710;
1009 case CMD3210: return cmd3210;
1010 case CLK2030: return clk2030;
1011 case CTL3215: return ctl3215;
1012 case CTL3220: return ctl3220;
1013 case NC: return nc;
1014 }
1015
1016 return nc;
1017}
1018
1019#ifdef CHIPSET_I945GM
1020/* Strength multiplier tables */
1021static const u8 dual_channel_strength_multiplier[] = {
1022 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1023 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1024 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1025 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1026 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1027 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1028 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1029 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1030 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1031 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1032 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1033 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1034 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1035 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1036 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1037 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1038 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1039 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1040 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1041 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1043 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1044 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1045 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1046};
1047
1048static const u8 single_channel_strength_multiplier[] = {
1049 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1050 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1051 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1052 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1053 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1054 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1055 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1056 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1057 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1058 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1059 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1060 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1061 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1062 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1063 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1064 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1065 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1066 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1067 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1068 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1069 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1070 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1071 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1072 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1073};
1074#endif
1075#ifdef CHIPSET_I945GC
1076static const u8 dual_channel_strength_multiplier[] = {
1077 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1078 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1079 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1080 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1081 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1082 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1083 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1084 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1085 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1086 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1087 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1088 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1089 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1090 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1091 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1092 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1093 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1094 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1095 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1096 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1097 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1098 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1099 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1100 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1101};
1102
1103static const u8 single_channel_strength_multiplier[] = {
1104 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1105 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1106 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1107 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1108 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1109 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1110 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1111 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1112 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1113 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1114 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1115 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1116 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1117 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1118 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1119 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1120 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1121 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1122 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1123 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1124 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1125 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1126 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1127 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1128};
1129#endif
1130
Stefan Reinauer278534d2008-10-29 04:51:07 +00001131static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1132{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001133 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001134 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001135
1136 /* Set Strength Multipliers */
1137
1138 /* Dual Channel needs different tables. */
1139 if (sdram_capabilities_dual_channel()) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001140 printk_debug("Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001141 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001142 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001143 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1144 } else {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001145 printk_debug("Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001146 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001147 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001148 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1149 }
1150
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001151 printk_debug("Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001152
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001153 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1154 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1155 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1156 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1157 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1158 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1159 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1160 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001161
1162 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001163 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1164 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1165 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001166
Stefan Reinauer278534d2008-10-29 04:51:07 +00001167 sdram_write_slew_rates(G3SRPUT, ctl3220);
1168 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001169 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001170 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001171 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1172 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1173 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001174
1175 /* Channel 1 */
1176 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001177 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1178 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001179 } else {
1180 sdram_write_slew_rates(G7SRPUT, nc);
1181 sdram_write_slew_rates(G8SRPUT, nc);
1182 }
1183}
1184
1185static void sdram_enable_rcomp(void)
1186{
1187 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001188 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001189 udelay(300);
1190 reg32 = MCHBAR32(GBRCOMPCTL);
1191 reg32 &= ~(1 << 23);
1192 MCHBAR32(GBRCOMPCTL) = reg32;
1193}
1194
1195static void sdram_program_dll_timings(struct sys_info *sysinfo)
1196{
1197 u32 chan0dll = 0, chan1dll = 0;
1198 int i;
1199
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001200 printk_debug ("Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001201
Stefan Reinauer278534d2008-10-29 04:51:07 +00001202 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1203 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1204
1205 /* We drive both channels with the same speed */
1206 switch (sysinfo->memory_frequency) {
1207 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1208 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1209 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1210 }
1211
1212 for (i=0; i < 4; i++) {
1213 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1214 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1215 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1216 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1217 }
1218}
1219
1220static void sdram_force_rcomp(void)
1221{
1222 u32 reg32;
1223 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001224
Stefan Reinauer278534d2008-10-29 04:51:07 +00001225 reg32 = MCHBAR32(ODTC);
1226 reg32 |= (1 << 28);
1227 MCHBAR32(ODTC) = reg32;
1228
1229 reg32 = MCHBAR32(SMSRCTL);
1230 reg32 |= (1 << 0);
1231 MCHBAR32(SMSRCTL) = reg32;
1232
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001233 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001234 reg32 = MCHBAR32(GBRCOMPCTL);
1235 reg32 |= (1 << 8);
1236 MCHBAR32(GBRCOMPCTL) = reg32;
1237
1238 reg8 = i945_silicon_revision();
1239 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001240
Stefan Reinauer278534d2008-10-29 04:51:07 +00001241 reg32 = MCHBAR32(GBRCOMPCTL);
1242 reg32 |= (3 << 5);
1243 MCHBAR32(GBRCOMPCTL) = reg32;
1244 }
1245}
1246
1247static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1248{
1249 u8 reg8;
1250 u32 reg32;
1251
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001252 printk_debug ("Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001253 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001254 reg8 = MCHBAR8(C0HCTC);
1255 reg8 &= ~0x1f;
1256 reg8 |= ( 1 << 0);
1257 MCHBAR8(C0HCTC) = reg8;
1258
1259 reg8 = MCHBAR8(C1HCTC);
1260 reg8 &= ~0x1f;
1261 reg8 |= ( 1 << 0);
1262 MCHBAR8(C1HCTC) = reg8;
1263
Stefan Reinauer278534d2008-10-29 04:51:07 +00001264 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1265 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1266
1267 MCHBAR8(C0WDLLCMC) = 0;
1268 MCHBAR8(C1WDLLCMC) = 0;
1269
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001270 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001271 sdram_program_dram_width(sysinfo);
1272
1273 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1274
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001275 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001276 reg32 = MCHBAR32(GBRCOMPCTL);
1277 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1278 reg32 |= (3 << 27) | (3 << 0);
1279 MCHBAR32(GBRCOMPCTL) = reg32;
1280
1281 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1282
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001283 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001284 sdram_program_dll_timings(sysinfo);
1285
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001286 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001287 sdram_force_rcomp();
1288}
1289
1290static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1291{
1292 u32 reg32;
1293
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001294 printk_debug ("Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001295
Stefan Reinauer278534d2008-10-29 04:51:07 +00001296 reg32 = MCHBAR32(RCVENMT);
1297 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001298 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001299
1300 reg32 |= (1 << 11) | (1 << 9);
1301 MCHBAR32(RCVENMT) = reg32;
1302
1303 reg32 = MCHBAR32(DRTST);
1304 reg32 |= (1 << 3) | (1 << 2);
1305 MCHBAR32(DRTST) = reg32;
1306
1307 reg32 = MCHBAR32(DRTST);
1308 reg32 |= (1 << 6) | (1 << 4);
1309 MCHBAR32(DRTST) = reg32;
1310
1311 asm volatile ("nop; nop;");
1312
1313 reg32 = MCHBAR32(DRTST);
1314
1315 /* Is channel 0 populated? */
1316 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1317 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1318 reg32 |= (1 << 7) | (1 << 5);
1319 else
1320 reg32 |= (1 << 31);
1321
1322 /* Is channel 1 populated? */
1323 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1324 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1325 reg32 |= (1 << 9) | (1 << 8);
1326 else
1327 reg32 |= (1 << 30);
1328
1329 MCHBAR32(DRTST) = reg32;
1330
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001331 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001332 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1333 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1334 reg32 = MCHBAR32(C0DRC1);
1335 reg32 |= (1 << 8);
1336 MCHBAR32(C0DRC1) = reg32;
1337 }
1338 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1339 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1340 reg32 = MCHBAR32(C1DRC1);
1341 reg32 |= (1 << 8);
1342 MCHBAR32(C1DRC1) = reg32;
1343 }
1344}
1345
1346struct dimm_size {
1347 unsigned long side1;
1348 unsigned long side2;
1349};
1350
1351static struct dimm_size sdram_get_dimm_size(u16 device)
1352{
1353 /* Calculate the log base 2 size of a DIMM in bits */
1354 struct dimm_size sz;
1355 int value, low, rows, columns;
1356
1357 sz.side1 = 0;
1358 sz.side2 = 0;
1359
1360 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1361 if (rows < 0) goto hw_err;
1362 if ((rows & 0xf) == 0) goto val_err;
1363 sz.side1 += rows & 0xf;
1364
1365 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1366 if (columns < 0) goto hw_err;
1367 if ((columns & 0xf) == 0) goto val_err;
1368 sz.side1 += columns & 0xf;
1369
1370 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1371 if (value < 0) goto hw_err;
1372 if ((value & 0xff) == 0) goto val_err;
1373 sz.side1 += log2(value & 0xff);
1374
1375 /* Get the module data width and convert it to a power of two */
1376 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1377 if (value < 0) goto hw_err;
1378 value &= 0xff;
1379 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001380
Stefan Reinauer278534d2008-10-29 04:51:07 +00001381 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1382 if (low < 0) goto hw_err;
1383 value = value | (low & 0xff);
1384 if ((value != 72) && (value != 64)) goto val_err;
1385 sz.side1 += log2(value);
1386
1387 /* side 2 */
1388 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1389
1390 if (value < 0) goto hw_err;
1391 value &= 7;
1392 value++;
1393 if (value == 1) goto out;
1394 if (value != 2) goto val_err;
1395
1396 /* Start with the symmetrical case */
1397 sz.side2 = sz.side1;
1398
1399 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1400
1401 /* Don't die here, I have not come across any of these to test what
1402 * actually happens.
1403 */
1404 printk_err("Assymetric DIMMs are not supported by this chipset\n");
1405
1406 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1407 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1408
1409 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1410 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1411
1412 goto out;
1413
1414 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001415 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001416 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001417 /* If a hardware error occurs the spd rom probably does not exist.
1418 * In this case report that there is no memory
1419 */
1420 sz.side1 = 0;
1421 sz.side2 = 0;
1422 out:
1423 return sz;
1424}
1425
1426static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1427{
1428 int i;
1429
1430 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1431 struct dimm_size sz;
1432
1433 sysinfo->banksize[i * 2] = 0;
1434 sysinfo->banksize[(i * 2) + 1] = 0;
1435
1436 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1437 continue;
1438
1439 sz = sdram_get_dimm_size(DIMM_SPD_BASE + i);
1440
1441 sysinfo->banks[i] = spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1442
1443 if (sz.side1 < 30)
1444 die("DDR-II rank size smaller than 128MB is not supported.\n");
1445
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001446 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001447
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001448 printk_debug("DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
1449
Stefan Reinauer278534d2008-10-29 04:51:07 +00001450 if (!sz.side2)
1451 continue;
1452
1453 /* If there is a second side, it has to have at least 128M, too */
1454 if (sz.side2 < 30)
1455 die("DDR-II rank size smaller than 128MB is not supported.\n");
1456
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001457 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001458
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001459 printk_debug("DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001460 }
1461}
1462
1463static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1464{
1465 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001466 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001467
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001468 printk_debug ("Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001469
1470 cum0 = 0;
1471 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001472 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001473 MCHBAR8(C0DRB0+i) = cum0;
1474 }
1475
1476 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1477 cum1 = cum0;
1478
1479 /* Exception: Interleaved starts from the beginning */
1480 if (sysinfo->interleaved)
1481 cum1 = 0;
1482
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001483#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001484 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1485 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1486 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1487 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001488#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001489
1490 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001491 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001492 MCHBAR8(C1DRB0+i) = cum1;
1493 }
1494
1495 /* Set TOLUD Top Of Low Usable DRAM */
1496 if (sysinfo->interleaved)
1497 tolud = (cum0 + cum1) << 1;
1498 else
1499 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001500
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001501 /* The TOM register has a different format */
1502 tom = tolud >> 3;
1503
1504 /* Limit the value of TOLUD to leave some space for PCI memory. */
1505 if (tolud > 0xd0)
1506 tolud = 0xd0; /* 3.25GB : 0.75GB */
1507
1508 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1509
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001510 printk_debug("C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1511 printk_debug("C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001512 printk_debug("TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001513
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001514 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001515
1516 return 0;
1517}
1518
Stefan Reinauer278534d2008-10-29 04:51:07 +00001519static int sdram_set_row_attributes(struct sys_info *sysinfo)
1520{
1521 int i, value;
1522 u16 dra0=0, dra1=0, dra = 0;
1523
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001524 printk_debug ("Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001525 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1526 u16 device;
1527 u8 columnsrows;
1528
1529 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1530 continue;
1531 }
1532
1533 device = DIMM_SPD_BASE + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001534
1535 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1536 columnsrows = (value & 0x0f);
1537
1538 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1539 columnsrows |= (value & 0xf) << 4;
1540
1541 switch (columnsrows) {
1542 case 0x9d: dra = 2; break;
1543 case 0xad: dra = 3; break;
1544 case 0xbd: dra = 4; break;
1545 case 0xae: dra = 3; break;
1546 case 0xbe: dra = 4; break;
1547 default: die("Unsupported Rows/Columns. (DRA)");
1548 }
1549
1550 /* Double Sided DIMMs? */
1551 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1552 dra = (dra << 4) | dra;
1553 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001554
Stefan Reinauer278534d2008-10-29 04:51:07 +00001555 if (i < DIMM_SOCKETS)
1556 dra0 |= (dra << (i*8));
1557 else
1558 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1559 }
1560
1561 MCHBAR16(C0DRA0) = dra0;
1562 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001563
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001564 printk_debug("C0DRA = 0x%04x\n", dra0);
1565 printk_debug("C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001566
1567 return 0;
1568}
1569
1570static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1571{
1572 u32 off32;
1573 int i;
1574
1575 MCHBAR16(C1BNKARC) &= 0xff00;
1576 MCHBAR16(C0BNKARC) &= 0xff00;
1577
1578 off32 = C0BNKARC;
1579 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1580 /* Switch to second channel */
1581 if (i == DIMM_SOCKETS)
1582 off32 = C1BNKARC;
1583
1584 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1585 continue;
1586
1587 if (sysinfo->banks[i] != 8)
1588 continue;
1589
Stefan Reinauerde3206a2010-02-22 06:09:43 +00001590 printk_spew("DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001591
1592 if (i & 1)
1593 MCHBAR16(off32) |= 0x50;
1594 else
1595 MCHBAR16(off32) |= 0x05;
1596 }
1597}
1598
1599#define REFRESH_7_8US 1
1600#define REFRESH_15_6US 0
1601static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1602{
1603 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001604
Stefan Reinauer278534d2008-10-29 04:51:07 +00001605 if (sysinfo->refresh == REFRESH_7_8US) {
1606 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1607 } else {
1608 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1609 }
1610
1611 MCHBAR32(C0DRC0) &= ~(7 << 8);
1612 MCHBAR32(C0DRC0) |= reg32;
1613
1614 MCHBAR32(C1DRC0) &= ~(7 << 8);
1615 MCHBAR32(C1DRC0) |= reg32;
1616}
1617
1618static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1619{
1620 u32 reg32;
1621 int i;
1622
1623 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001624
Stefan Reinauer278534d2008-10-29 04:51:07 +00001625 for (i=0; i < 4; i++) {
1626 if (sysinfo->banksize[i] == 0) {
1627 reg32 |= (1 << (16 + i));
1628 }
1629 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001630
Stefan Reinauer278534d2008-10-29 04:51:07 +00001631 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001632
Stefan Reinauer278534d2008-10-29 04:51:07 +00001633 reg32 |= (1 << 11);
1634 MCHBAR32(C0DRC1) = reg32;
1635
1636 /* Do we have to do this if we're in Single Channel Mode? */
1637 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001638
Stefan Reinauer278534d2008-10-29 04:51:07 +00001639 for (i=4; i < 8; i++) {
1640 if (sysinfo->banksize[i] == 0) {
1641 reg32 |= (1 << (12 + i));
1642 }
1643 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001644
Stefan Reinauer278534d2008-10-29 04:51:07 +00001645 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001646
Stefan Reinauer278534d2008-10-29 04:51:07 +00001647 reg32 |= (1 << 11);
1648 MCHBAR32(C1DRC1) = reg32;
1649}
1650
1651static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1652{
1653 u32 reg32;
1654 int i;
1655
1656 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001657
Stefan Reinauer278534d2008-10-29 04:51:07 +00001658 for (i=0; i < 4; i++) {
1659 if (sysinfo->banksize[i] == 0) {
1660 reg32 |= (1 << (24 + i));
1661 }
1662 }
1663 MCHBAR32(C0DRC2) = reg32;
1664
1665 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001666
Stefan Reinauer278534d2008-10-29 04:51:07 +00001667 for (i=4; i < 8; i++) {
1668 if (sysinfo->banksize[i] == 0) {
1669 reg32 |= (1 << (20 + i));
1670 }
1671 }
1672 MCHBAR32(C1DRC2) = reg32;
1673}
1674
1675static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1676{
1677 u32 reg32, off32;
1678 u32 tWTR;
1679 u32 temp_drt;
1680 int i, page_size;
1681
1682 static const u8 const drt0_table[] = {
1683 /* CL 3, 4, 5 */
1684 3, 4, 5, /* FSB533/400, DDR533/400 */
1685 4, 5, 6, /* FSB667, DDR533/400 */
1686 4, 5, 6, /* FSB667, DDR667 */
1687 };
1688
1689 static const u8 const cas_table[] = {
1690 2, 1, 0, 3
1691 };
1692
1693 reg32 = MCHBAR32(C0DRC0);
1694 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001695 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001696 MCHBAR32(C0DRC0) = reg32;
1697
1698 reg32 = MCHBAR32(C1DRC0);
1699 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001700 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001701 MCHBAR32(C1DRC0) = reg32;
1702
1703 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1704 SYSINFO_DIMM_NOT_POPULATED) {
1705 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001706 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001707 MCHBAR32(C0DRC0) = reg32;
1708 }
1709
1710 sdram_program_refresh_rate(sysinfo);
1711
1712 sdram_program_cke_tristate(sysinfo);
1713
1714 sdram_program_odt_tristate(sysinfo);
1715
1716 /* Calculate DRT0 */
1717
1718 temp_drt = 0;
1719
1720 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1721 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1722 temp_drt |= (reg32 << 28);
1723
1724 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1725 reg32 += sysinfo->trp;
1726 temp_drt |= (reg32 << 4);
1727
1728 if (sysinfo->memory_frequency == 667) {
1729 tWTR = 3; /* 667MHz */
1730 } else {
1731 tWTR = 2; /* 400 and 533 */
1732 }
1733
1734 /* B2B Write to Read Command Spacing */
1735 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1736 temp_drt |= (reg32 << 24);
1737
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001738 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001739 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1740
1741 /* Program Write Auto Precharge to Activate */
1742 off32 = 0;
1743 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1744 off32 += 3;
1745 }
1746 if (sysinfo->memory_frequency == 667) {
1747 off32 += 3;
1748 }
1749 off32 += sysinfo->cas - 3;
1750 reg32 = drt0_table[off32];
1751 temp_drt |= (reg32 << 11);
1752
1753 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001754
Stefan Reinauer278534d2008-10-29 04:51:07 +00001755 temp_drt |= (8 << 0);
1756
1757 MCHBAR32(C0DRT0) = temp_drt;
1758 MCHBAR32(C1DRT0) = temp_drt;
1759
1760 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001761
Stefan Reinauer278534d2008-10-29 04:51:07 +00001762 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1763
1764 /* DRAM RASB Precharge */
1765 temp_drt |= (sysinfo->trp - 2) << 0;
1766
1767 /* DRAM RASB to CASB Delay */
1768 temp_drt |= (sysinfo->trcd - 2) << 4;
1769
1770 /* CASB Latency */
1771 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1772
1773 /* Refresh Cycle Time */
1774 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001775
Stefan Reinauer278534d2008-10-29 04:51:07 +00001776 /* Pre-All to Activate Delay */
1777 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001778
Stefan Reinauer278534d2008-10-29 04:51:07 +00001779 /* Precharge to Precharge Delay stays at 1 clock */
1780 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001781
Stefan Reinauer278534d2008-10-29 04:51:07 +00001782 /* Activate to Precharge Delay */
1783 temp_drt |= (sysinfo->tras << 19);
1784
1785 /* Read to Precharge (tRTP) */
1786 if (sysinfo->memory_frequency == 667) {
1787 temp_drt |= (1 << 28);
1788 } else {
1789 temp_drt |= (0 << 28);
1790 }
1791
1792 /* Determine page size */
1793 reg32 = 0;
1794 page_size = 1; /* Default: 1k pagesize */
1795 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1796 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1797 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1798 page_size = 2; /* 2k pagesize */
1799 }
1800
1801 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1802 reg32 = 1;
1803 }
1804 if (sysinfo->memory_frequency == 667) {
1805 reg32 = page_size;
1806 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001807
Stefan Reinauer278534d2008-10-29 04:51:07 +00001808 temp_drt |= (reg32 << 30);
1809
1810 MCHBAR32(C0DRT1) = temp_drt;
1811 MCHBAR32(C1DRT1) = temp_drt;
1812
1813 /* Program DRT2 */
1814 reg32 = MCHBAR32(C0DRT2);
1815 reg32 &= ~(1 << 8);
1816 MCHBAR32(C0DRT2) = reg32;
1817
1818 reg32 = MCHBAR32(C1DRT2);
1819 reg32 &= ~(1 << 8);
1820 MCHBAR32(C1DRT2) = reg32;
1821
1822 /* Calculate DRT3 */
1823 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1824
1825 /* Get old tRFC value */
1826 reg32 = MCHBAR32(C0DRT1) >> 10;
1827 reg32 &= 0x3f;
1828
1829 /* 788nS - tRFC */
1830 switch (sysinfo->memory_frequency) {
1831 case 400: /* 5nS */
1832 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1833 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1834 break;
1835 case 533: /* 3.75nS */
1836 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1837 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1838 break;
1839 case 667: /* 3nS */
1840 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1841 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1842 break;
1843 }
1844
1845 temp_drt |= reg32;
1846
1847 MCHBAR32(C0DRT3) = temp_drt;
1848 MCHBAR32(C1DRT3) = temp_drt;
1849}
1850
1851static void sdram_set_channel_mode(struct sys_info *sysinfo)
1852{
1853 u32 reg32;
1854
1855 printk_debug("Setting mode of operation for memory channels...");
1856
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001857 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001858 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1859 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1860 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1861 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1862 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001863 sysinfo->interleaved = 1;
1864 } else {
1865 sysinfo->interleaved = 0;
1866 }
1867
1868 reg32 = MCHBAR32(DCC);
1869 reg32 &= ~(7 << 0);
1870
1871 if(sysinfo->interleaved) {
1872 /* Dual Channel Interleaved */
1873 printk_debug("Dual Channel Interleaved.\n");
1874 reg32 |= (1 << 1);
1875 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1876 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1877 /* Channel 1 only */
1878 printk_debug("Single Channel 1 only.\n");
1879 reg32 |= (1 << 2);
1880 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1881 SYSINFO_DIMM_NOT_POPULATED) {
1882 /* Dual Channel Assymetric */
1883 printk_debug("Dual Channel Assymetric.\n");
1884 reg32 |= (1 << 0);
1885 } else {
1886 /* All bits 0 means Single Channel 0 operation */
1887 printk_debug("Single Channel 0 only.\n");
1888 }
1889
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001890 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001891
1892 MCHBAR32(DCC) = reg32;
1893
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001894 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001895}
1896
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001897static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001898{
1899 volatile u16 reg16;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001900
1901 MCHBAR32(PLLMON) = 0x80800000;
1902
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001903 sysinfo->fsb_frequency = fsbclk();
1904 if (sysinfo->fsb_frequency == -1)
1905 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001906
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001907 /* Program CPCTL according to FSB speed */
1908 /* Only write the lower byte */
1909 switch (sysinfo->fsb_frequency) {
1910 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1911 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1912 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1913 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001914
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001915 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001916
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001917 reg16 = MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001918}
1919
1920static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1921{
1922 u8 reg8;
1923 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001924 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001925
1926#define CRCLK_166MHz 0x00
1927#define CRCLK_200MHz 0x01
1928#define CRCLK_250MHz 0x03
1929#define CRCLK_400MHz 0x05
1930
1931#define CDCLK_200MHz 0x00
1932#define CDCLK_320MHz 0x40
1933
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001934#define VOLTAGE_1_05 0x00
1935#define VOLTAGE_1_50 0x01
1936
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001937 printk_debug ("Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001938
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001939 printk_debug("FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001940
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001941 voltage = VOLTAGE_1_05;
1942 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1943 voltage = VOLTAGE_1_50;
1944 printk_debug("Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001945
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001946 /* Gate graphics hardware for frequency change */
1947 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
1948 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
1949 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001950
1951 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001952 reg8 = sdram_capabilities_core_frequencies();
1953
Stefan Reinauer278534d2008-10-29 04:51:07 +00001954 freq = CRCLK_250MHz;
1955 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001956 case GFX_FREQUENCY_CAP_ALL:
1957 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001958 freq = CRCLK_250MHz;
1959 else
1960 freq = CRCLK_400MHz;
1961 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001962 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
1963 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
1964 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001965 }
1966
1967 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001968 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001969 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
1970 if (reg8==2)
1971 freq = CRCLK_166MHz;
1972 }
1973
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001974 printk_debug("Render: ");
1975 switch (freq) {
1976 case CRCLK_166MHz: printk_debug("166Mhz"); break;
1977 case CRCLK_200MHz: printk_debug("200Mhz"); break;
1978 case CRCLK_250MHz: printk_debug("250Mhz"); break;
1979 case CRCLK_400MHz: printk_debug("400Mhz"); break;
1980 }
1981
Stefan Reinauer278534d2008-10-29 04:51:07 +00001982 if (i945_silicon_revision() == 0) {
1983 sysinfo->mvco4x = 1;
1984 } else {
1985 sysinfo->mvco4x = 0;
1986 }
1987
Stefan Reinauer278534d2008-10-29 04:51:07 +00001988 second_vco = 0;
1989
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001990 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001991 second_vco = 1;
1992 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
1993 u16 mem = sysinfo->memory_frequency;
1994 u16 fsb = sysinfo->fsb_frequency;
1995
1996 if ( (fsb == 667 && mem == 533) ||
1997 (fsb == 533 && mem == 533) ||
1998 (fsb == 533 && mem == 400)) {
1999 second_vco = 1;
2000 }
2001
2002 if (fsb == 667 && mem == 533)
2003 sysinfo->mvco4x = 1;
2004 }
2005
2006 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002007 sysinfo->clkcfg_bit7=1;
2008 } else {
2009 sysinfo->clkcfg_bit7=0;
2010 }
2011
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002012 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002013 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2014 reg16 &= ~( (7 << 0) | (1 << 13) );
2015 reg16 |= freq;
2016 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2017
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002018 /* Graphics Core Display Clock */
2019 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2020 reg8 &= ~( (1<<7) | (7<<4) );
2021
2022 if (voltage == VOLTAGE_1_05) {
2023 reg8 |= CDCLK_200MHz;
2024 printk_debug(" Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002025 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002026 reg8 |= CDCLK_320MHz;
2027 printk_debug(" Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002028 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002029 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002030
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002031 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002032
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002033 reg8 |= (1<<3) | (1<<1);
2034 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2035
2036 reg8 |= 0x0f;
2037 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2038
2039 /* Ungate core render and display clocks */
2040 reg8 &= 0xf0;
2041 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002042}
2043
2044static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2045{
2046 u32 clkcfg;
2047 u8 reg8;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002048 u8 offset = 0;
2049#ifdef CHIPSET_I945GM
2050 offset++;
2051#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002052
2053 printk_debug ("Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002054
Stefan Reinauer278534d2008-10-29 04:51:07 +00002055 clkcfg = MCHBAR32(CLKCFG);
2056
2057 printk_debug("CLKCFG=0x%08x, ", clkcfg);
2058
2059 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2060
2061 if (sysinfo->mvco4x) {
2062 printk_debug("MVCO 4x, ");
2063 clkcfg &= ~(1 << 12);
2064 }
2065
2066 if (sysinfo->clkcfg_bit7) {
2067 printk_debug("second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002068
Stefan Reinauer278534d2008-10-29 04:51:07 +00002069 clkcfg |= (1 << 7);
2070 }
2071
2072 switch (sysinfo->memory_frequency) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002073 case 400: clkcfg |= ((1+offset) << 4); break;
2074 case 533: clkcfg |= ((2+offset) << 4); break;
2075 case 667: clkcfg |= ((3+offset) << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002076 default: die("Target Memory Frequency Error");
2077 }
2078
2079 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002080 printk_debug ("ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002081 return;
2082 }
2083
2084 MCHBAR32(CLKCFG) = clkcfg;
2085
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002086 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002087 * cache before we execute it.
2088 */
2089 goto cache_code;
2090vco_update:
2091 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2092 reg8 &= ~(1 << 7);
2093 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2094
Stefan Reinauer278534d2008-10-29 04:51:07 +00002095 clkcfg &= ~(1 << 10);
2096 MCHBAR32(CLKCFG) = clkcfg;
2097 clkcfg |= (1 << 10);
2098 MCHBAR32(CLKCFG) = clkcfg;
2099
Stefan Reinauer278534d2008-10-29 04:51:07 +00002100 __asm__ __volatile__ (
2101 " movl $0x100, %%ecx\n"
2102 "delay_update:\n"
2103 " nop\n"
2104 " nop\n"
2105 " nop\n"
2106 " nop\n"
2107 " loop delay_update\n"
2108 : /* No outputs */
2109 : /* No inputs */
2110 : "%ecx"
2111 );
2112
Stefan Reinauer278534d2008-10-29 04:51:07 +00002113 clkcfg &= ~(1 << 10);
2114 MCHBAR32(CLKCFG) = clkcfg;
2115
2116 goto out;
2117cache_code:
2118 goto vco_update;
2119out:
2120
2121 printk_debug("CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002122 printk_debug ("ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002123}
2124
2125static void sdram_program_clock_crossing(void)
2126{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002127 int idx = 0;
2128
2129 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002130 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002131 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002132#ifdef CHIPSET_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002133 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002134 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002135 0xffffffff, 0xffffffff, /* nonexistant */
2136 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002137
Stefan Reinauer278534d2008-10-29 04:51:07 +00002138 0x08040120, 0x00000000, /* DDR400 FSB533 */
2139 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002140 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002141
2142 0x04020120, 0x00000010, /* DDR400 FSB667 */
2143 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002144 0x00100401, 0x00000000, /* DDR667 FSB667 */
2145
2146 0xffffffff, 0xffffffff, /* nonexistant */
2147 0xffffffff, 0xffffffff, /* nonexistant */
2148 0xffffffff, 0xffffffff, /* nonexistant */
2149
2150 0xffffffff, 0xffffffff, /* nonexistant */
2151 0xffffffff, 0xffffffff, /* nonexistant */
2152 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002153 };
2154
2155 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002156 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002157 0xffffffff, 0xffffffff, /* nonexistant */
2158 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002159
Stefan Reinauer278534d2008-10-29 04:51:07 +00002160 0x00060108, 0x00000000, /* DDR400 FSB533 */
2161 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002162 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002163
2164 0x00040318, 0x00000000, /* DDR400 FSB667 */
2165 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002166 0x02010804, 0x00000000, /* DDR667 FSB667 */
2167
2168 0xffffffff, 0xffffffff, /* nonexistant */
2169 0xffffffff, 0xffffffff, /* nonexistant */
2170 0xffffffff, 0xffffffff, /* nonexistant */
2171
2172 0xffffffff, 0xffffffff, /* nonexistant */
2173 0xffffffff, 0xffffffff, /* nonexistant */
2174 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002175 };
2176
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002177#endif
2178#ifdef CHIPSET_I945GC
2179 /* i945 G/P */
2180 static const u32 data_clock_crossing[] = {
2181 0xffffffff, 0xffffffff, /* nonexistant */
2182 0xffffffff, 0xffffffff, /* nonexistant */
2183 0xffffffff, 0xffffffff, /* nonexistant */
2184
2185 0x10080201, 0x00000000, /* DDR400 FSB533 */
2186 0x00100401, 0x00000000, /* DDR533 FSB533 */
2187 0xffffffff, 0xffffffff, /* nonexistant */
2188
2189 0xffffffff, 0xffffffff, /* nonexistant */
2190 0xffffffff, 0xffffffff, /* nonexistant */
2191 0xffffffff, 0xffffffff, /* nonexistant */
2192
2193 0x04020108, 0x00000000, /* DDR400 FSB800 */
2194 0x00020108, 0x00000000, /* DDR533 FSB800 */
2195 0x00080201, 0x00000000, /* DDR667 FSB800 */
2196
2197 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2198 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2199 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2200 };
2201
2202 static const u32 command_clock_crossing[] = {
2203 0xffffffff, 0xffffffff, /* nonexistant */
2204 0xffffffff, 0xffffffff, /* nonexistant */
2205 0xffffffff, 0xffffffff, /* nonexistant */
2206
2207 0x00010800, 0x00000402, /* DDR400 FSB533 */
2208 0x01000400, 0x00000200, /* DDR533 FSB533 */
2209 0xffffffff, 0xffffffff, /* nonexistant */
2210
2211 0xffffffff, 0xffffffff, /* nonexistant */
2212 0xffffffff, 0xffffffff, /* nonexistant */
2213 0xffffffff, 0xffffffff, /* nonexistant */
2214
2215 0x02010804, 0x00000000, /* DDR400 FSB800 */
2216 0x00010402, 0x00000000, /* DDR533 FSB800 */
2217 0x04020180, 0x00000008, /* DDR667 FSB800 */
2218
2219 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2220 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2221 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2222 };
2223#endif
2224
Stefan Reinauer278534d2008-10-29 04:51:07 +00002225 printk_debug("Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002226
2227 printk_debug("MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002228 switch (memclk()) {
2229 case 400: printk_debug("400"); idx += 0; break;
2230 case 533: printk_debug("533"); idx += 2; break;
2231 case 667: printk_debug("667"); idx += 4; break;
2232 default: printk_debug("RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002233 }
2234
2235 printk_debug(" FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002236 switch (fsbclk()) {
2237 case 400: printk_debug("400"); idx += 0; break;
2238 case 533: printk_debug("533"); idx += 6; break;
2239 case 667: printk_debug("667"); idx += 12; break;
2240 case 800: printk_debug("800"); idx += 18; break;
2241 case 1066: printk_debug("1066"); idx += 24; break;
2242 default: printk_debug("RSVD %x\n", fsbclk()); return;
2243 }
2244
2245 if (command_clock_crossing[idx]==0xffffffff) {
2246 printk_debug("Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002247 }
2248
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002249 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2250 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2251
Stefan Reinauer278534d2008-10-29 04:51:07 +00002252 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2253 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2254 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2255 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2256
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002257 printk_debug("... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002258}
2259
2260static void sdram_disable_fast_dispatch(void)
2261{
2262 u32 reg32;
2263
2264 reg32 = MCHBAR32(FSBPMC3);
2265 reg32 |= (1 << 1);
2266 MCHBAR32(FSBPMC3) = reg32;
2267
2268 reg32 = MCHBAR32(SBTEST);
2269 reg32 |= (3 << 1);
2270 MCHBAR32(SBTEST) = reg32;
2271}
2272
2273static void sdram_pre_jedec_initialization(void)
2274{
2275 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002276
Stefan Reinauer278534d2008-10-29 04:51:07 +00002277 reg32 = MCHBAR32(WCC);
2278 reg32 &= 0x113ff3ff;
2279 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2280 MCHBAR32(WCC) = reg32;
2281
2282 MCHBAR32(SMVREFC) |= (1 << 6);
2283
2284 MCHBAR32(MMARB0) &= ~(3 << 17);
2285 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2286
2287 MCHBAR32(MMARB1) &= ~(7 << 8);
2288 MCHBAR32(MMARB1) |= (3 << 8);
2289
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002290 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002291 MCHBAR32(C0AIT) = 0x000006c4;
2292 MCHBAR32(C0AIT+4) = 0x871a066d;
2293
2294 MCHBAR32(C1AIT) = 0x000006c4;
2295 MCHBAR32(C1AIT+4) = 0x871a066d;
2296}
2297
2298#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2299#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2300#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2301#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2302#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2303#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2304#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2305#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2306
2307static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2308{
2309 u32 chan0 = 0, chan1 = 0;
2310 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2311
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002312 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002313 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002314 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002315 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2316 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2317 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2318
2319 if (sdram_capabilities_enhanced_addressing_xor()) {
2320 if (!sysinfo->interleaved) {
2321 /* Single Channel & Dual Channel Assymetric */
2322 if (chan0_populated) {
2323 if (chan0_dualsided) {
2324 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2325 } else {
2326 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2327 }
2328 }
2329 if (chan1_populated) {
2330 if (chan1_dualsided) {
2331 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2332 } else {
2333 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2334 }
2335 }
2336 } else {
2337 /* Interleaved has always both channels populated */
2338 if (chan0_dualsided) {
2339 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2340 } else {
2341 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2342 }
2343
2344 if (chan1_dualsided) {
2345 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2346 } else {
2347 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2348 }
2349 }
2350 } else {
2351 if (!sysinfo->interleaved) {
2352 /* Single Channel & Dual Channel Assymetric */
2353 if (chan0_populated) {
2354 if (chan0_dualsided) {
2355 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2356 } else {
2357 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2358 }
2359 }
2360 if (chan1_populated) {
2361 if (chan1_dualsided) {
2362 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2363 } else {
2364 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2365 }
2366 }
2367 } else {
2368 /* Interleaved has always both channels populated */
2369 if (chan0_dualsided) {
2370 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2371 } else {
2372 chan0 = EA_DUALCHANNEL_BANK_MODE;
2373 }
2374
2375 if (chan1_dualsided) {
2376 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2377 } else {
2378 chan1 = EA_DUALCHANNEL_BANK_MODE;
2379 }
2380 }
2381 }
2382
2383 MCHBAR32(C0DRC1) &= 0x00ffffff;
2384 MCHBAR32(C0DRC1) |= chan0;
2385 MCHBAR32(C1DRC1) &= 0x00ffffff;
2386 MCHBAR32(C1DRC1) |= chan1;
2387}
2388
2389static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2390{
2391 u32 reg32;
2392
2393 /* Enable Channel XORing for Dual Channel Interleave */
2394 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002395
Stefan Reinauer278534d2008-10-29 04:51:07 +00002396 reg32 = MCHBAR32(DCC);
2397#if CHANNEL_XOR_RANDOMIZATION
2398 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002399 reg32 |= (1 << 9);
2400#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002401 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002402#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002403 MCHBAR32(DCC) = reg32;
2404 }
2405
2406 /* DRAM mode optimizations */
2407 sdram_enhanced_addressing_mode(sysinfo);
2408
2409 reg32 = MCHBAR32(FSBPMC3);
2410 reg32 &= ~(1 << 1);
2411 MCHBAR32(FSBPMC3) = reg32;
2412
2413 reg32 = MCHBAR32(SBTEST);
2414 reg32 &= ~(1 << 2);
2415 MCHBAR32(SBTEST) = reg32;
2416
2417 reg32 = MCHBAR32(SBOCC);
2418 reg32 &= 0xffbdb6ff;
2419 reg32 |= (0xbdb6 << 8) | (1 << 0);
2420 MCHBAR32(SBOCC) = reg32;
2421}
2422
2423static void sdram_power_management(struct sys_info *sysinfo)
2424{
2425 u8 reg8;
2426 u16 reg16;
2427 u32 reg32;
2428 int integrated_graphics = 1;
2429 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002430
Stefan Reinauer278534d2008-10-29 04:51:07 +00002431 reg32 = MCHBAR32(C0DRT2);
2432 reg32 &= 0xffffff00;
2433 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002434 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002435 MCHBAR32(C0DRT2) = reg32;
2436
2437 reg32 = MCHBAR32(C1DRT2);
2438 reg32 &= 0xffffff00;
2439 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002440 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002441 MCHBAR32(C1DRT2) = reg32;
2442
2443 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002444
2445 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002446 MCHBAR32(C0DRC1) = reg32;
2447
2448 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002449
2450 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002451 MCHBAR32(C1DRC1) = reg32;
2452
2453 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002454 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2455 u16 peg_bits = (1 << 5) | (1 << 0);
2456
2457 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002458 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002459 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2460 u16 peg_bits = (1 << 5) | (1 << 0);
2461
Stefan Reinauer278534d2008-10-29 04:51:07 +00002462 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002463 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002464 }
2465
2466 reg16 = MCHBAR16(UPMC2);
2467 reg16 &= 0xfc00;
2468 reg16 |= 0x0100;
2469 MCHBAR16(UPMC2) = reg16;
2470
2471 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002472
Stefan Reinauer278534d2008-10-29 04:51:07 +00002473 for (i=0; i<5; i++) {
2474 MCHBAR32(UPMC3) &= ~(1 << 16);
2475 MCHBAR32(UPMC3) |= (1 << 16);
2476 }
2477
2478 MCHBAR32(GIPMC1) = 0x8000000c;
2479
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002480 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002481 reg16 &= ~(7 << 11);
2482 if (i945_silicon_revision()>2) {
2483 reg16 |= (6 << 11);
2484 } else {
2485 reg16 |= (4 << 11);
2486 }
2487 MCHBAR16(CPCTL) = reg16;
2488
Stefan Reinauer30140a52009-03-11 16:20:39 +00002489#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002490 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002491#else
2492 if (i945_silicon_revision() != 0) {
2493#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002494 switch (sysinfo->fsb_frequency) {
2495 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2496 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2497 }
2498 } else {
2499 switch (sysinfo->fsb_frequency) {
2500 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2501 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2502 }
2503 }
2504
2505 MCHBAR32(FSBPMC1) = 0x8000000c;
2506
2507 reg32 = MCHBAR32(C2C3TT);
2508 reg32 &= 0xffff0000;
2509 switch (sysinfo->fsb_frequency) {
2510 case 667: reg32 |= 0x0600; break;
2511 case 533: reg32 |= 0x0480; break;
2512 }
2513 MCHBAR32(C2C3TT) = reg32;
2514
2515 reg32 = MCHBAR32(C3C4TT);
2516 reg32 &= 0xffff0000;
2517 switch (sysinfo->fsb_frequency) {
2518 case 667: reg32 |= 0x0b80; break;
2519 case 533: reg32 |= 0x0980; break;
2520 }
2521 MCHBAR32(C3C4TT) = reg32;
2522
2523 if (i945_silicon_revision() == 0) {
2524 MCHBAR32(ECO) &= ~(1 << 16);
2525 } else {
2526 MCHBAR32(ECO) |= (1 << 16);
2527 }
2528
2529#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002530
Stefan Reinauer278534d2008-10-29 04:51:07 +00002531 if (i945_silicon_revision() == 0) {
2532 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2533 } else {
2534 MCHBAR32(FSBPMC3) |= (1 << 29);
2535 }
2536#endif
2537 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2538
2539 MCHBAR32(FSBPMC3) |= (1 << 21);
2540
2541 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2542
2543 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2544
2545 reg32 = MCHBAR32(FSBPMC4);
2546 reg32 &= ~(3 << 24);
2547 reg32 |= ( 2 << 24);
2548 MCHBAR32(FSBPMC4) = reg32;
2549
2550 MCHBAR32(FSBPMC4) |= (1 << 21);
2551
2552 MCHBAR32(FSBPMC4) |= (1 << 5);
2553
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002554 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2555 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002556 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2557 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002558 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002559 }
2560
2561 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2562 reg8 |= (1 << 4);
2563 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2564
2565 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2566 reg8 |= (1 << 2);
2567 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2568
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002569#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002570
Stefan Reinauer278534d2008-10-29 04:51:07 +00002571 if (integrated_graphics) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002572 printk_debug("C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002573 MCHBAR16(MIPMC4) = 0x0468;
2574 MCHBAR16(MIPMC5) = 0x046c;
2575 MCHBAR16(MIPMC6) = 0x046c;
2576 } else {
2577 MCHBAR16(MIPMC4) = 0x6468;
2578 MCHBAR16(MIPMC5) = 0x646c;
2579 MCHBAR16(MIPMC6) = 0x646c;
2580 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002581#else
2582 if (integrated_graphics) {
2583 MCHBAR16(MIPMC4) = 0x04f8;
2584 MCHBAR16(MIPMC5) = 0x04fc;
2585 MCHBAR16(MIPMC6) = 0x04fc;
2586 } else {
2587 MCHBAR16(MIPMC4) = 0x64f8;
2588 MCHBAR16(MIPMC5) = 0x64fc;
2589 MCHBAR16(MIPMC6) = 0x64fc;
2590 }
2591
2592#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002593
2594 reg32 = MCHBAR32(PMCFG);
2595 reg32 &= ~(3 << 17);
2596 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002597 MCHBAR32(PMCFG) = reg32;
2598
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002599 MCHBAR32(PMCFG) |= (1 << 4);
2600
Stefan Reinauer278534d2008-10-29 04:51:07 +00002601 reg32 = MCHBAR32(0xc30);
2602 reg32 &= 0xffffff00;
2603 reg32 |= 0x01;
2604 MCHBAR32(0xc30) = reg32;
2605
2606 MCHBAR32(0xb18) &= ~(1 << 21);
2607}
2608
2609static void sdram_thermal_management(void)
2610{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002611
Stefan Reinauer278534d2008-10-29 04:51:07 +00002612 MCHBAR8(TCO1) = 0x00;
2613 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002614
2615 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2616 * 0x30/0x32.
2617 */
2618
2619}
2620
2621static void sdram_save_receive_enable(void)
2622{
2623 int i;
2624 u32 reg32;
2625 u8 values[4];
2626
2627 /* The following values are stored to an unused CMOS
2628 * area and restored instead of recalculated in case
2629 * of an S3 resume.
2630 *
2631 * C0WL0REOST [7:0] -> 8 bit
2632 * C1WL0REOST [7:0] -> 8 bit
2633 * RCVENMT [11:8] [3:0] -> 8 bit
2634 * C0DRT1 [27:24] -> 4 bit
2635 * C1DRT1 [27:24] -> 4 bit
2636 */
2637
2638 values[0] = MCHBAR8(C0WL0REOST);
2639 values[1] = MCHBAR8(C1WL0REOST);
2640
2641 reg32 = MCHBAR32(RCVENMT);
2642 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2643
2644 reg32 = MCHBAR32(C0DRT1);
2645 values[3] = (reg32 >> 24) & 0x0f;
2646 reg32 = MCHBAR32(C1DRT1);
2647 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2648
2649 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
2650 * so we grad bytes 128 - 131 to save the receive enable values
2651 */
2652
2653 for (i=0; i<4; i++)
2654 cmos_write(values[i], 128 + i);
2655}
2656
2657static void sdram_recover_receive_enable(void)
2658{
2659 int i;
2660 u32 reg32;
2661 u8 values[4];
2662
2663 for (i=0; i<4; i++)
2664 values[i] = cmos_read(128 + i);
2665
2666 MCHBAR8(C0WL0REOST) = values[0];
2667 MCHBAR8(C1WL0REOST) = values[1];
2668
2669 reg32 = MCHBAR32(RCVENMT);
2670 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2671 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2672 MCHBAR32(RCVENMT) = reg32;
2673
2674 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2675 reg32 |= (u32)(values[3] & 0x0f) << 24;
2676 MCHBAR32(C0DRT1) = reg32;
2677
2678 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2679 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2680 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002681}
2682
2683#include "rcven.c"
2684
2685static void sdram_program_receive_enable(struct sys_info *sysinfo)
2686{
2687 MCHBAR32(REPC) |= (1 << 0);
2688
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002689 /* enable upper CMOS */
2690 RCBA32(0x3400) = (1 << 2);
2691
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002692 /* Program Receive Enable Timings */
2693 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2694 sdram_recover_receive_enable();
2695 } else {
2696 receive_enable_adjust(sysinfo);
2697 sdram_save_receive_enable();
2698 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002699
2700 MCHBAR32(C0DRC1) |= (1 << 6);
2701 MCHBAR32(C1DRC1) |= (1 << 6);
2702 MCHBAR32(C0DRC1) &= ~(1 << 6);
2703 MCHBAR32(C1DRC1) &= ~(1 << 6);
2704
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002705 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002706}
2707
2708/**
2709 * @brief Enable On-Die Termination for DDR2.
2710 *
2711 */
2712
2713static void sdram_on_die_termination(struct sys_info *sysinfo)
2714{
2715 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002716 0x00024911, 0xe0010000,
2717 0x00049211, 0xe0020000,
2718 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002719 };
2720
2721 u32 reg32;
2722 int cas;
2723
2724 reg32 = MCHBAR32(ODTC);
2725 reg32 &= ~(3 << 16);
2726 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2727 MCHBAR32(ODTC) = reg32;
2728
2729 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2730 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
2731 printk_debug("one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002732
Stefan Reinauer278534d2008-10-29 04:51:07 +00002733 reg32 = MCHBAR32(C0ODT);
2734 reg32 &= ~(7 << 28);
2735 MCHBAR32(C0ODT) = reg32;
2736 reg32 = MCHBAR32(C1ODT);
2737 reg32 &= ~(7 << 28);
2738 MCHBAR32(C1ODT) = reg32;
2739 }
2740
2741 cas = sysinfo->cas;
2742
2743 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2744 reg32 |= odt[(cas-3) * 2];
2745 MCHBAR32(C0ODT) = reg32;
2746
2747 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2748 reg32 |= odt[(cas-3) * 2];
2749 MCHBAR32(C1ODT) = reg32;
2750
2751 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2752 reg32 |= odt[((cas-3) * 2) + 1];
2753 MCHBAR32(C0ODT + 4) = reg32;
2754
2755 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2756 reg32 |= odt[((cas-3) * 2) + 1];
2757 MCHBAR32(C1ODT + 4) = reg32;
2758}
2759
2760/**
2761 * @brief Enable clocks to populated sockets
2762 */
2763
2764static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2765{
2766 u8 clocks[2] = { 0, 0 };
2767
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002768#ifdef CHIPSET_I945GM
2769#define CLOCKS_WIDTH 2
2770#endif
2771#ifdef CHIPSET_I945GC
2772#define CLOCKS_WIDTH 3
2773#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002774 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002775 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002776
2777 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002778 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002779
2780 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002781 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002782
2783 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002784 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002785
2786#ifdef OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002787 /* Usually system firmware turns off system memory clock signals
2788 * to unused SO-DIMM slots to reduce EMI and power consumption.
2789 * However, the Kontron 986LCD-M does not like unused clock
2790 * signals to be disabled.
2791 * If other similar mainboard occur, it would make sense to make
2792 * this an entry in the sysinfo structure, and pre-initialize that
Stefan Reinauer38f147e2010-02-08 12:20:50 +00002793 * structure in the mainboard's romstage.c main() function.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002794 * For now an #ifdef will do.
2795 */
2796
2797 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2798 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002799#endif
2800
2801 MCHBAR8(C0DCLKDIS) = clocks[0];
2802 MCHBAR8(C1DCLKDIS) = clocks[1];
2803}
2804
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002805#define RTT_ODT_NONE 0
2806#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002807#define RTT_ODT_75_OHM (1 << 5)
2808#define RTT_ODT_150_OHM (1 << 9)
2809
2810#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2811
2812#define MRS_CAS_3 (3 << 7)
2813#define MRS_CAS_4 (4 << 7)
2814#define MRS_CAS_5 (5 << 7)
2815
2816#define MRS_TWR_3 (2 << 12)
2817#define MRS_TWR_4 (3 << 12)
2818#define MRS_TWR_5 (4 << 12)
2819
2820#define MRS_BT (1 << 6)
2821
2822#define MRS_BL4 (2 << 3)
2823#define MRS_BL8 (3 << 3)
2824
2825static void sdram_jedec_enable(struct sys_info *sysinfo)
2826{
2827 int i, nonzero;
2828 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2829
2830 for (i = 0, nonzero = -1; i < 8; i++) {
2831 if (sysinfo->banksize[i] == 0) {
2832 continue;
2833 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002834
Stefan Reinauer278534d2008-10-29 04:51:07 +00002835 printk_debug("jedec enable sequence: bank %d\n", i);
2836 switch (i) {
2837 case 0:
2838 /* Start at address 0 */
2839 bankaddr = 0;
2840 break;
2841 case 4:
2842 if (sysinfo->interleaved) {
2843 bankaddr = 0x40;
2844 break;
2845 }
2846 default:
2847 if (nonzero != -1) {
2848 printk_debug("bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002849 bankaddr += sysinfo->banksize[nonzero] <<
2850 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002851 break;
2852 }
2853 /* No populated bank hit before. Start at address 0 */
2854 bankaddr = 0;
2855 }
2856
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002857 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002858 * for the next offset we have to calculate
2859 */
2860 nonzero = i;
2861
2862 /* Get CAS latency set up */
2863 switch (sysinfo->cas) {
2864 case 5: mrsaddr = MRS_CAS_5; break;
2865 case 4: mrsaddr = MRS_CAS_4; break;
2866 case 3: mrsaddr = MRS_CAS_3; break;
2867 default: die("Jedec Error (CAS).\n");
2868 }
2869
2870 /* Get tWR set */
2871 switch (sysinfo->twr) {
2872 case 5: mrsaddr |= MRS_TWR_5; break;
2873 case 4: mrsaddr |= MRS_TWR_4; break;
2874 case 3: mrsaddr |= MRS_TWR_3; break;
2875 default: die("Jedec Error (tWR).\n");
2876 }
2877
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002878 /* Set "Burst Type" */
2879 mrsaddr |= MRS_BT;
2880
Stefan Reinauer278534d2008-10-29 04:51:07 +00002881 /* Interleaved */
2882 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002883 mrsaddr = mrsaddr << 1;
2884 }
2885
2886 /* Only burst length 8 supported */
2887 mrsaddr |= MRS_BL8;
2888
2889 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002890 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002891 do_ram_command(RAM_COMMAND_NOP);
2892 ram_read32(bankaddr);
2893
2894 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002895 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002896 do_ram_command(RAM_COMMAND_PRECHARGE);
2897 ram_read32(bankaddr);
2898
2899 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002900 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002901 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2902 ram_read32(bankaddr);
2903
2904 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002905 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002906 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2907 ram_read32(bankaddr);
2908
2909 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002910 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002911 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2912 tmpaddr = bankaddr;
2913 if (!sdram_capabilities_dual_channel()) {
2914 tmpaddr |= RTT_ODT_75_OHM;
2915 } else if (sysinfo->interleaved) {
2916 tmpaddr |= (RTT_ODT_150_OHM << 1);
2917 } else {
2918 tmpaddr |= RTT_ODT_150_OHM;
2919 }
2920 ram_read32(tmpaddr);
2921
2922 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002923 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002924 do_ram_command(RAM_COMMAND_MRS);
2925 tmpaddr = bankaddr;
2926 tmpaddr |= mrsaddr;
2927 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002928 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002929 tmpaddr |= (1 << 12);
2930 else
2931 tmpaddr |= (1 << 11);
2932 ram_read32(tmpaddr);
2933
2934 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002935 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002936 do_ram_command(RAM_COMMAND_PRECHARGE);
2937 ram_read32(bankaddr);
2938
2939 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002940 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002941 do_ram_command(RAM_COMMAND_CBR);
2942
2943 /* CBR wants two READs */
2944 ram_read32(bankaddr);
2945 ram_read32(bankaddr);
2946
2947 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002948 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002949 do_ram_command(RAM_COMMAND_MRS);
2950
2951 tmpaddr = bankaddr;
2952 tmpaddr |= mrsaddr;
2953 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002954
Stefan Reinauer278534d2008-10-29 04:51:07 +00002955 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002956 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002957 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002958
Stefan Reinauer278534d2008-10-29 04:51:07 +00002959 tmpaddr = bankaddr;
2960 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002961
Stefan Reinauer278534d2008-10-29 04:51:07 +00002962 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
2963 } else if (sysinfo->interleaved) {
2964 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
2965 } else {
2966 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
2967 }
2968 ram_read32(tmpaddr);
2969
2970 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002971 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002972 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2973
2974 tmpaddr = bankaddr;
2975 if (!sdram_capabilities_dual_channel()) {
2976 tmpaddr |= RTT_ODT_75_OHM;
2977 } else if (sysinfo->interleaved) {
2978 tmpaddr |= (RTT_ODT_150_OHM << 1);
2979 } else {
2980 tmpaddr |= RTT_ODT_150_OHM;
2981 }
2982 ram_read32(tmpaddr);
2983 }
2984}
2985
2986static void sdram_init_complete(void)
2987{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002988 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002989 do_ram_command(RAM_COMMAND_NORMAL);
2990}
2991
2992static void sdram_setup_processor_side(void)
2993{
2994 if (i945_silicon_revision() == 0)
2995 MCHBAR32(FSBPMC3) |= (1 << 2);
2996
2997 MCHBAR8(0xb00) |= 1;
2998
2999 if (i945_silicon_revision() == 0)
3000 MCHBAR32(SLPCTL) |= (1 << 8);
3001}
3002
Stefan Reinauer278534d2008-10-29 04:51:07 +00003003/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003004 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003005 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003006void sdram_initialize(int boot_path)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003007{
3008 struct sys_info sysinfo;
3009 u8 reg8, cas_mask;
3010
3011 sdram_detect_errors();
3012
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003013 printk_debug ("Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003014
3015 memset(&sysinfo, 0, sizeof(sysinfo));
3016
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003017 sysinfo.boot_path = boot_path;
3018
Stefan Reinauer278534d2008-10-29 04:51:07 +00003019 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3020 sdram_get_dram_configuration(&sysinfo);
3021
3022 /* Check whether we have stacked DIMMs */
3023 sdram_verify_package_type(&sysinfo);
3024
3025 /* Determine common CAS */
3026 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003027
Stefan Reinauer278534d2008-10-29 04:51:07 +00003028 /* Choose Common Frequency */
3029 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003030
Stefan Reinauer278534d2008-10-29 04:51:07 +00003031 /* Determine smallest common tRAS */
3032 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003033
Stefan Reinauer278534d2008-10-29 04:51:07 +00003034 /* Determine tRP */
3035 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003036
Stefan Reinauer278534d2008-10-29 04:51:07 +00003037 /* Determine tRCD */
3038 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003039
Stefan Reinauer278534d2008-10-29 04:51:07 +00003040 /* Determine smallest refresh period */
3041 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003042
Stefan Reinauer278534d2008-10-29 04:51:07 +00003043 /* Verify all DIMMs support burst length 8 */
3044 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003045
Stefan Reinauer278534d2008-10-29 04:51:07 +00003046 /* determine tWR */
3047 sdram_detect_smallest_tWR(&sysinfo);
3048
3049 /* Determine DIMM size parameters (rows, columns banks) */
3050 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003051
Stefan Reinauer278534d2008-10-29 04:51:07 +00003052 /* determine tRFC */
3053 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003054
Stefan Reinauer278534d2008-10-29 04:51:07 +00003055 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003056 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003057
3058 /* Program Graphics Frequency */
3059 sdram_program_graphics_frequency(&sysinfo);
3060
3061 /* Program System Memory Frequency */
3062 sdram_program_memory_frequency(&sysinfo);
3063
3064 /* Determine Mode of Operation (Interleaved etc) */
3065 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003066
Stefan Reinauer278534d2008-10-29 04:51:07 +00003067 /* Program Clock Crossing values */
3068 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003069
Stefan Reinauer278534d2008-10-29 04:51:07 +00003070 /* Disable fast dispatch */
3071 sdram_disable_fast_dispatch();
3072
3073 /* Enable WIODLL Power Down in ACPI states */
3074 MCHBAR32(C0DMC) |= (1 << 24);
3075 MCHBAR32(C1DMC) |= (1 << 24);
3076
3077 /* Program DRAM Row Boundary/Attribute Registers */
3078
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003079 /* program row size DRB and set TOLUD */
3080 sdram_program_row_boundaries(&sysinfo);
3081
3082 /* program page size DRA */
3083 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003084
3085 /* Program CxBNKARC */
3086 sdram_set_bank_architecture(&sysinfo);
3087
3088 /* Program DRAM Timing and Control registers based on SPD */
3089 sdram_set_timing_and_control(&sysinfo);
3090
3091 /* On-Die Termination Adjustment */
3092 sdram_on_die_termination(&sysinfo);
3093
3094 /* Pre Jedec Initialization */
3095 sdram_pre_jedec_initialization();
3096
3097 /* Perform System Memory IO Initialization */
3098 sdram_initialize_system_memory_io(&sysinfo);
3099
3100 /* Perform System Memory IO Buffer Enable */
3101 sdram_enable_system_memory_io(&sysinfo);
3102
3103 /* Enable System Memory Clocks */
3104 sdram_enable_memory_clocks(&sysinfo);
3105
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003106 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003107 /* Jedec Initialization sequence */
3108 sdram_jedec_enable(&sysinfo);
3109 }
3110
3111 /* Program Power Management Registers */
3112 sdram_power_management(&sysinfo);
3113
3114 /* Post Jedec Init */
3115 sdram_post_jedec_initialization(&sysinfo);
3116
3117 /* Program DRAM Throttling */
3118 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003119
Stefan Reinauer278534d2008-10-29 04:51:07 +00003120 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003121 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003122
3123 /* Program Receive Enable Timings */
3124 sdram_program_receive_enable(&sysinfo);
3125
3126 /* Enable Periodic RCOMP */
3127 sdram_enable_rcomp();
3128
3129 /* Tell ICH7 that we're done */
3130 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3131 reg8 &= ~(1 << 7);
3132 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3133
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003134 printk_debug("RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003135
Stefan Reinauer278534d2008-10-29 04:51:07 +00003136 sdram_setup_processor_side();
3137}
3138
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003139unsigned long get_top_of_ram(void)
3140{
3141 /* This will not work if TSEG is in place! */
3142 u32 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
3143
3144 return (unsigned long) tom;
3145}
3146