blob: be63e7adcca321a17c1fac51ad3b1d11ef9a22de [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 Reinauer71a3d962009-07-21 21:44:24 +000027#define DEBUG_RAM_SETUP
Stefan Reinauer278534d2008-10-29 04:51:07 +000028
29/* Debugging macros. */
30#if defined(DEBUG_RAM_SETUP)
31#define PRINTK_DEBUG(x...) printk_debug(x)
32#else
33#define PRINTK_DEBUG(x...)
34#endif
35
Stefan Reinauer278534d2008-10-29 04:51:07 +000036#define RAM_INITIALIZATION_COMPLETE (1 << 19)
37
38#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
39#define RAM_COMMAND_NOP (0x1 << 16)
40#define RAM_COMMAND_PRECHARGE (0x2 << 16)
41#define RAM_COMMAND_MRS (0x3 << 16)
42#define RAM_COMMAND_EMRS (0x4 << 16)
43#define RAM_COMMAND_CBR (0x6 << 16)
44#define RAM_COMMAND_NORMAL (0x7 << 16)
45
46#define RAM_EMRS_1 (0x0 << 21)
47#define RAM_EMRS_2 (0x1 << 21)
48#define RAM_EMRS_3 (0x2 << 21)
49
50static void do_ram_command(u32 command)
51{
52 u32 reg32;
53
54 reg32 = MCHBAR32(DCC);
55 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
56 reg32 |= command;
57
58 /* Also set Init Complete */
59 if (command == RAM_COMMAND_NORMAL)
60 reg32 |= RAM_INITIALIZATION_COMPLETE;
61
62 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
63
64 MCHBAR32(DCC) = reg32; /* This is the actual magic */
65
Stefan Reinauer779b3e32008-11-10 15:43:37 +000066 PRINTK_DEBUG("...done\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000067}
68
Stefan Reinauer278534d2008-10-29 04:51:07 +000069static void ram_read32(u32 offset)
70{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000071 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000072
73 read32(offset);
74}
75
76#ifdef DEBUG_RAM_SETUP
77static void sdram_dump_mchbar_registers(void)
78{
79 int i;
Stefan Reinauer779b3e32008-11-10 15:43:37 +000080 printk_debug("Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000081
82 for (i=0; i<0xfff; i+=4) {
83 if (MCHBAR32(i) == 0)
84 continue;
Stefan Reinauer779b3e32008-11-10 15:43:37 +000085 printk_debug("0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +000086 }
87}
88#endif
89
Stefan Reinauer24b4df52010-01-17 13:47:35 +000090static int memclk(void)
91{
92 int offset = 0;
93#ifdef CHIPSET_I945GM
94 offset++;
95#endif
96 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
97 case 1: return 400;
98 case 2: return 533;
99 case 3: return 667;
100 default: printk_debug("memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
101 }
102 return -1;
103}
104
105#ifdef CHIPSET_I945GM
106static int fsbclk(void)
107{
108 switch (MCHBAR32(CLKCFG) & 7) {
109 case 0: return 400;
110 case 1: return 533;
111 case 3: return 667;
112 default: printk_debug("fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
113 }
114 return -1;
115}
116#endif
117#ifdef CHIPSET_I945GC
118static int fsbclk(void)
119{
120 switch (MCHBAR32(CLKCFG) & 7) {
121 case 0: return 1066;
122 case 1: return 533;
123 case 2: return 800;
124 default: printk_debug("fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
125 }
126 return -1;
127}
128#endif
129
Stefan Reinauer278534d2008-10-29 04:51:07 +0000130static int sdram_capabilities_max_supported_memory_frequency(void)
131{
132 u32 reg32;
133
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000134#ifdef MAXIMUM_SUPPORTED_FREQUENCY
135 return MAXIMUM_SUPPORTED_FREQUENCY;
136#endif
137
138 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000139 reg32 &= (7 << 0);
140
141 switch (reg32) {
142 case 4: return 400;
143 case 3: return 533;
144 case 2: return 667;
145 }
146 /* Newer revisions of this chipset rather support faster memory clocks,
147 * so if it's a reserved value, return the fastest memory clock that we
148 * know of and can handle
149 */
150 return 667;
151}
152
153/**
154 * @brief determine whether chipset is capable of dual channel interleaved mode
155 *
156 * @return 1 if interleaving is supported, 0 otherwise
157 */
158static int sdram_capabilities_interleave(void)
159{
160 u32 reg32;
161
162 reg32 = pci_read_config8(PCI_DEV(0, 0x00,0), 0xe4);
163 reg32 >>= 25;
164 reg32 &= 1;
165
166 return (!reg32);
167}
168
169/**
170 * @brief determine whether chipset is capable of two memory channels
171 *
172 * @return 1 if dual channel operation is supported, 0 otherwise
173 */
174static int sdram_capabilities_dual_channel(void)
175{
176 u32 reg32;
177
178 reg32 = pci_read_config8(PCI_DEV(0, 0x00,0), 0xe4);
179 reg32 >>= 24;
180 reg32 &= 1;
181
182 return (!reg32);
183}
184
185static int sdram_capabilities_enhanced_addressing_xor(void)
186{
187 u8 reg8;
188
189 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
190 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000191
Stefan Reinauer278534d2008-10-29 04:51:07 +0000192 return (!reg8);
193}
194
195static int sdram_capabilities_two_dimms_per_channel(void)
196{
197 u8 reg8;
198
199 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
200 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000201
Stefan Reinauer278534d2008-10-29 04:51:07 +0000202 return (reg8 != 0);
203}
204
205static int sdram_capabilities_MEM4G_disable(void)
206{
207 u8 reg8;
208
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000209 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000210 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000211
Stefan Reinauer278534d2008-10-29 04:51:07 +0000212 return (reg8 != 0);
213}
214
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000215#define GFX_FREQUENCY_CAP_166MHZ 0x04
216#define GFX_FREQUENCY_CAP_200MHZ 0x03
217#define GFX_FREQUENCY_CAP_250MHZ 0x02
218#define GFX_FREQUENCY_CAP_ALL 0x00
219
220static int sdram_capabilities_core_frequencies(void)
221{
222 u8 reg8;
223
224 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
225 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
226 reg8 >>= 1;
227
228 return (reg8);
229}
230
Stefan Reinauer278534d2008-10-29 04:51:07 +0000231static void sdram_detect_errors(void)
232{
233 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000234 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000235
236 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000237
Stefan Reinauer278534d2008-10-29 04:51:07 +0000238 if (reg8 & ((1<<7)|(1<<2))) {
239 if (reg8 & (1<<2)) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000240 printk_debug("SLP S4# Assertion Width Violation.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000241
Stefan Reinauer278534d2008-10-29 04:51:07 +0000242 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000243
Stefan Reinauer278534d2008-10-29 04:51:07 +0000244 }
245
246 if (reg8 & (1<<7)) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000247 printk_debug("DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000248 reg8 &= ~(1<<7);
249 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000250 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000251 }
252
253 /* Set SLP_S3# Assertion Stretch Enable */
254 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
255 reg8 |= (1 << 3);
256 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
257
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000258 if (do_reset) {
259 printk_debug("Reset required.\n");
260 outb(0x00, 0xcf9);
261 outb(0x0e, 0xcf9);
262 for (;;) ; /* Wait for reset! */
263 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000264 }
265
266 /* Set DRAM initialization bit in ICH7 */
267 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
268 reg8 |= (1<<7);
269 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000270
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000271}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000272
273/**
274 * @brief Get generic DIMM parameters.
275 * @param sysinfo Central memory controller information structure
276 *
277 * This function gathers several pieces of information for each system DIMM:
278 * o DIMM width (x8 / x16)
279 * o DIMM sides (single sided / dual sided)
280 *
281 * Also, some non-supported scenarios are detected.
282 */
283
284static void sdram_get_dram_configuration(struct sys_info *sysinfo)
285{
286 u32 dimm_mask = 0;
287 int i;
288
289 /**
290 * i945 supports two DIMMs, in two configurations:
291 *
292 * - single channel with two dimms
293 * - dual channel with one dimm per channel
294 *
295 * In practice dual channel mainboards have their spd at 0x50, 0x52
296 * whereas single channel configurations have their spd at 0x50/x51
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000297 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000298 * The capability register knows a lot about the channel configuration
299 * but for now we stick with the information we gather from the SPD
300 * ROMs
301 */
302
303 if (sdram_capabilities_dual_channel()) {
304 sysinfo->dual_channel = 1;
305 printk_debug("This mainboard supports Dual Channel Operation.\n");
306 } else {
307 sysinfo->dual_channel = 0;
308 printk_debug("This mainboard supports only Single Channel Operation.\n");
309 }
310
311 /**
312 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000313 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000314 * return value:
315 * [0:7] lower DIMM population
316 * [8-15] higher DIMM population
317 * [16] dual channel?
318 *
319 * There are 5 different possible populations for a DIMM socket:
320 * 1. x16 double sided (X16DS)
321 * 2. x8 double sided (X8DS)
322 * 3. x16 single sided (X16SS)
323 * 4. x8 double stacked (X8DDS)
324 * 5. not populated (NC)
325 *
326 * For the return value we start counting at zero.
327 *
328 */
329
330 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
331 u8 reg8, device = DIMM_SPD_BASE + i;
332
333 /* Initialize the socket information with a sane value */
334 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
335
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000336 /* Dual Channel not supported, but Channel 1? Bail out */
337 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000338 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000339
340 /* Two DIMMs per channel not supported, but odd DIMM number? */
341 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000342 continue;
343
344 printk_debug("DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
345
346 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
347 printk_debug("N/A\n");
348 continue;
349 }
350
351 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
352 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000353 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000354
355 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
356 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000357 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000358 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000359 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000360
361 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000362 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000363 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
364 case 1:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000365 printk_debug("x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000366 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
367 break;
368 case 0:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000369 printk_debug("x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000370 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
371 break;
372 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000373 printk_debug ("Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000374 }
375 break;
376 case 0x10:
377 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
378 case 1:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000379 printk_debug("x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000380 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
381 break;
382 case 0:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000383 printk_debug("x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000384 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
385 break;
386 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000387 printk_debug ("Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000388 }
389 break;
390 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000391 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000392 }
393
394 dimm_mask |= (1 << i);
395 }
396
397 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000398 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399 }
400
Stefan Reinauer278534d2008-10-29 04:51:07 +0000401 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000402 printk_info("Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403 }
404}
405
406/**
407 * @brief determine if any DIMMs are stacked
408 *
409 * @param sysinfo central sysinfo data structure.
410 */
411static void sdram_verify_package_type(struct sys_info * sysinfo)
412{
413 int i;
414
415 /* Assume no stacked DIMMs are available until we find one */
416 sysinfo->package = 0;
417 for (i=0; i<2*DIMM_SOCKETS; i++) {
418 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
419 continue;
420
421 /* Is the current DIMM a stacked DIMM? */
422 if (spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS) & (1 << 4))
423 sysinfo->package = 1;
424 }
425}
426
427static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
428{
429 int i;
430 u8 cas_mask;
431
432 /* Setup CAS mask with all supported CAS Latencies */
433 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
434 SPD_CAS_LATENCY_DDR2_4 |
435 SPD_CAS_LATENCY_DDR2_5;
436
437 for (i=0; i<2*DIMM_SOCKETS; i++) {
438 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
439 cas_mask &= spd_read_byte(DIMM_SPD_BASE + i, SPD_ACCEPTABLE_CAS_LATENCIES);
440 }
441
442 if(!cas_mask) {
443 die("No DDR-II modules with accepted CAS latencies found.\n");
444 }
445
446 return cas_mask;
447}
448
449static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
450{
451 int i, j, idx;
452 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000453 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000454
455 const u8 ddr2_speeds_table[] = {
456 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
457 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
458 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
459 };
460
461 const u8 spd_lookup_table[] = {
462 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
463 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
464 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
465 };
466
467 switch (sdram_capabilities_max_supported_memory_frequency()) {
468 case 400: max_ram_speed = 0; break;
469 case 533: max_ram_speed = 1; break;
470 case 667: max_ram_speed = 2; break;
471 }
472
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000473 if (fsbclk() == 533)
474 max_ram_speed = 1;
475
Stefan Reinauer278534d2008-10-29 04:51:07 +0000476 sysinfo->memory_frequency = 0;
477 sysinfo->cas = 0;
478
479 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
480 lowest_common_cas = 3;
481 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
482 lowest_common_cas = 4;
483 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
484 lowest_common_cas = 5;
485 }
486 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
487
488 for (j = max_ram_speed; j>=0; j--) {
489 int freq_cas_mask = cas_mask;
490
491 PRINTK_DEBUG("Probing Speed %d\n", j);
492 for (i=0; i<2*DIMM_SOCKETS; i++) {
493 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000494
Stefan Reinauer278534d2008-10-29 04:51:07 +0000495 PRINTK_DEBUG(" DIMM: %d\n", i);
496 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
497 continue;
498 }
499
500 current_cas_mask = spd_read_byte(DIMM_SPD_BASE + i, SPD_ACCEPTABLE_CAS_LATENCIES);
501
502 while (current_cas_mask) {
503 int highest_supported_cas = 0, current_cas = 0;
504 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
505 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
506 highest_supported_cas = 5;
507 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
508 highest_supported_cas = 4;
509 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
510 highest_supported_cas = 3;
511 }
512 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
513 current_cas = 3;
514 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
515 current_cas = 4;
516 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
517 current_cas = 5;
518 }
519
520 idx = highest_supported_cas - current_cas;
521 PRINTK_DEBUG("idx=%d, ", idx);
522 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[2*idx]));
523 PRINTK_DEBUG("tAC=%x", spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[(2*idx)+1]));
524
525 if (spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
526 spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
527 PRINTK_DEBUG(": OK\n");
528 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000529 }
530
Stefan Reinauer278534d2008-10-29 04:51:07 +0000531 PRINTK_DEBUG(": Not fast enough!\n");
532
533 current_cas_mask &= ~(1 << (current_cas));
534 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000535
Stefan Reinauer278534d2008-10-29 04:51:07 +0000536 freq_cas_mask &= current_cas_mask;
537 if (!current_cas_mask) {
538 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
539 break;
540 }
541 }
542 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
543 if (freq_cas_mask) {
544 switch (j) {
545 case 0: sysinfo->memory_frequency = 400; break;
546 case 1: sysinfo->memory_frequency = 533; break;
547 case 2: sysinfo->memory_frequency = 667; break;
548 }
549 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
550 sysinfo->cas = 3;
551 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
552 sysinfo->cas = 4;
553 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
554 sysinfo->cas = 5;
555 }
556 break;
557 }
558 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000559
Stefan Reinauer278534d2008-10-29 04:51:07 +0000560 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauer977ed2d2009-01-20 22:46:52 +0000561 printk_debug("Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000562 sysinfo->memory_frequency, sysinfo->cas);
563 } else {
564 die("Could not find common memory frequency and CAS\n");
565 }
566}
567
568static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
569{
570 int i;
571 int tRAS_time;
572 int tRAS_cycles;
573 int freq_multiplier = 0;
574
575 switch (sysinfo->memory_frequency) {
576 case 400: freq_multiplier = 0x14; break; /* 5ns */
577 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
578 case 667: freq_multiplier = 0x0c; break; /* 3ns */
579 }
580
581 tRAS_cycles = 4; /* 4 clocks minimum */
582 tRAS_time = tRAS_cycles * freq_multiplier;
583
584 for (i=0; i<2*DIMM_SOCKETS; i++) {
585 u8 reg8;
586
587 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
588 continue;
589
590 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
591 if (!reg8) {
592 die("Invalid tRAS value.\n");
593 }
594
595 while ((tRAS_time >> 2) < reg8) {
596 tRAS_time += freq_multiplier;
597 tRAS_cycles++;
598 }
599 }
600 if(tRAS_cycles > 0x18) {
601 die("DDR-II Module does not support this frequency (tRAS error)\n");
602 }
603
604 printk_debug("tRAS = %d cycles\n", tRAS_cycles);
605 sysinfo->tras = tRAS_cycles;
606}
607
608static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
609{
610 int i;
611 int tRP_time;
612 int tRP_cycles;
613 int freq_multiplier = 0;
614
615 switch (sysinfo->memory_frequency) {
616 case 400: freq_multiplier = 0x14; break; /* 5ns */
617 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
618 case 667: freq_multiplier = 0x0c; break; /* 3ns */
619 }
620
621 tRP_cycles = 2; /* 2 clocks minimum */
622 tRP_time = tRP_cycles * freq_multiplier;
623
624 for (i=0; i<2*DIMM_SOCKETS; i++) {
625 u8 reg8;
626
627 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
628 continue;
629
630 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_ROW_PRECHARGE_TIME);
631 if (!reg8) {
632 die("Invalid tRP value.\n");
633 }
634
635 while (tRP_time < reg8) {
636 tRP_time += freq_multiplier;
637 tRP_cycles++;
638 }
639 }
640
641 if(tRP_cycles > 6) {
642 die("DDR-II Module does not support this frequency (tRP error)\n");
643 }
644
645 printk_debug("tRP = %d cycles\n", tRP_cycles);
646 sysinfo->trp = tRP_cycles;
647}
648
649static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
650{
651 int i;
652 int tRCD_time;
653 int tRCD_cycles;
654 int freq_multiplier = 0;
655
656 switch (sysinfo->memory_frequency) {
657 case 400: freq_multiplier = 0x14; break; /* 5ns */
658 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
659 case 667: freq_multiplier = 0x0c; break; /* 3ns */
660 }
661
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000662 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000663 tRCD_time = tRCD_cycles * freq_multiplier;
664
665 for (i=0; i<2*DIMM_SOCKETS; i++) {
666 u8 reg8;
667
668 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
669 continue;
670
671 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_RAS_TO_CAS_DELAY);
672 if (!reg8) {
673 die("Invalid tRCD value.\n");
674 }
675
676 while (tRCD_time < reg8) {
677 tRCD_time += freq_multiplier;
678 tRCD_cycles++;
679 }
680 }
681 if(tRCD_cycles > 6) {
682 die("DDR-II Module does not support this frequency (tRCD error)\n");
683 }
684
685 printk_debug("tRCD = %d cycles\n", tRCD_cycles);
686 sysinfo->trcd = tRCD_cycles;
687}
688
689static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
690{
691 int i;
692 int tWR_time;
693 int tWR_cycles;
694 int freq_multiplier = 0;
695
696 switch (sysinfo->memory_frequency) {
697 case 400: freq_multiplier = 0x14; break; /* 5ns */
698 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
699 case 667: freq_multiplier = 0x0c; break; /* 3ns */
700 }
701
702 tWR_cycles = 2; /* 2 clocks minimum */
703 tWR_time = tWR_cycles * freq_multiplier;
704
705 for (i=0; i<2*DIMM_SOCKETS; i++) {
706 u8 reg8;
707
708 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
709 continue;
710
711 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_WRITE_RECOVERY_TIME);
712 if (!reg8) {
713 die("Invalid tWR value.\n");
714 }
715
716 while (tWR_time < reg8) {
717 tWR_time += freq_multiplier;
718 tWR_cycles++;
719 }
720 }
721 if(tWR_cycles > 5) {
722 die("DDR-II Module does not support this frequency (tWR error)\n");
723 }
724
725 printk_debug("tWR = %d cycles\n", tWR_cycles);
726 sysinfo->twr = tWR_cycles;
727}
728
729static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
730{
731 int i, index = 0;
732
733 const u8 tRFC_cycles[] = {
734 /* 75 105 127.5 */
735 15, 21, 26, /* DDR2-400 */
736 20, 28, 34, /* DDR2-533 */
737 25, 35, 43 /* DDR2-667 */
738 };
739
740 for (i=0; i<2*DIMM_SOCKETS; i++) {
741 u8 reg8;
742
743 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
744 continue;
745
746 reg8 = sysinfo->banksize[i*2];
747 switch (reg8) {
748 case 0x04: reg8 = 0; break;
749 case 0x08: reg8 = 1; break;
750 case 0x10: reg8 = 2; break;
751 case 0x20: reg8 = 3; break;
752 }
753
754 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
755 reg8++;
756
757 if (reg8 > 3) {
758 /* Can this happen? Go back to 127.5ns just to be sure
759 * we don't run out of the array. This may be wrong
760 */
761 printk_debug("DIMM %d is 1Gb x16.. Please report.\n", i);
762 reg8 = 3;
763 }
764
765 if (reg8 > index)
766 index = reg8;
767
768 }
769 index--;
770 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000771 case 667: index += 3; /* Fallthrough */
772 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000773 case 400: break;
774 }
775
776 sysinfo->trfc = tRFC_cycles[index];
777 printk_debug("tRFC = %d cycles\n", tRFC_cycles[index]);
778}
779
Stefan Reinauer278534d2008-10-29 04:51:07 +0000780static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
781{
782 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000783
Stefan Reinauer278534d2008-10-29 04:51:07 +0000784 sysinfo->refresh = 0;
785
786 for (i=0; i<2*DIMM_SOCKETS; i++) {
787 int refresh;
788
789 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
790 continue;
791
792 refresh = spd_read_byte(DIMM_SPD_BASE + i, SPD_REFRESH) & ~(1 << 7);
793
794 /* 15.6us */
795 if (!refresh)
796 continue;
797
798 /* Refresh is slower than 15.6us, use 15.6us */
799 if (refresh > 2)
800 continue;
801
802 if (refresh == 2) {
803 sysinfo->refresh = 1;
804 break;
805 }
806
807 die("DDR-II module has unsupported refresh value\n");
808 }
809 printk_debug("Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
810}
811
812static void sdram_verify_burst_length(struct sys_info * sysinfo)
813{
814 int i;
815
816 for (i=0; i<2*DIMM_SOCKETS; i++) {
817 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
818 continue;
819
820 if (!(spd_read_byte(DIMM_SPD_BASE + i, SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
821 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
822 }
823}
824
825static void sdram_program_dram_width(struct sys_info * sysinfo)
826{
827 u16 c0dramw=0, c1dramw=0;
828 int idx;
829
830 if (sysinfo->dual_channel)
831 idx = 2;
832 else
833 idx = 1;
834
835 switch (sysinfo->dimm[0]) {
836 case 0: c0dramw = 0x0000; break; /* x16DS */
837 case 1: c0dramw = 0x0001; break; /* x8DS */
838 case 2: c0dramw = 0x0000; break; /* x16SS */
839 case 3: c0dramw = 0x0005; break; /* x8DDS */
840 case 4: c0dramw = 0x0000; break; /* NC */
841 }
842
843 switch (sysinfo->dimm[idx]) {
844 case 0: c1dramw = 0x0000; break; /* x16DS */
845 case 1: c1dramw = 0x0010; break; /* x8DS */
846 case 2: c1dramw = 0x0000; break; /* x16SS */
847 case 3: c1dramw = 0x0050; break; /* x8DDS */
848 case 4: c1dramw = 0x0000; break; /* NC */
849 }
850
851 if ( !sdram_capabilities_dual_channel() ) {
852 /* Single Channel */
853 c0dramw |= c1dramw;
854 c1dramw = 0;
855 }
856
857 MCHBAR16(C0DRAMW) = c0dramw;
858 MCHBAR16(C1DRAMW) = c1dramw;
859}
860
861static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
862{
863 int i;
864
865 for (i=0; i<16; i++)
866 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
867}
868
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000869static const u32 dq2030[] = {
870 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
871 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
872 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
873 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
874};
875
876static const u32 dq2330[] = {
877 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
878 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
879 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
880 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
881};
882
883static const u32 cmd2710[] = {
884 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
885 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
886 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
887 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
888};
889
890static const u32 cmd3210[] = {
891 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
892 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
893 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
894 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
895};
896
897static const u32 clk2030[] = {
898 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
899 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
900 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
901 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
902};
903
904static const u32 ctl3215[] = {
905 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
906 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
907 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
908 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
909};
910
911static const u32 ctl3220[] = {
912 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
913 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
914 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
915 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
916};
917
918static const u32 nc[] = {
919 0x00000000, 0x00000000, 0x00000000, 0x00000000,
920 0x00000000, 0x00000000, 0x00000000, 0x00000000,
921 0x00000000, 0x00000000, 0x00000000, 0x00000000,
922 0x00000000, 0x00000000, 0x00000000, 0x00000000
923};
924
925enum {
926 DQ2030,
927 DQ2330,
928 CMD2710,
929 CMD3210,
930 CLK2030,
931 CTL3215,
932 CTL3220,
933 NC,
934};
935
936static const u8 dual_channel_slew_group_lookup[] = {
937 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
938 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
939 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
940 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
941 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
942
943 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
944 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
945 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
946 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
947 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
948
949 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
950 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
951 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
952 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
953 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
954
955 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
956 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
957 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
958 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
959 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
960
961 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
962 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
963 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
964 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
965};
966
967static const u8 single_channel_slew_group_lookup[] = {
968 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
969 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
970 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
971 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
972 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
973
974 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
975 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
976 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
977 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
978 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
979
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, DQ2330, CMD3210,
983 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
984 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
985
986 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
987 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
988 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
989 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
990 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
991
992 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
993 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
994 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
995 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
996};
997
998static const u32 *slew_group_lookup(int dual_channel, int index)
999{
1000 const u8 *slew_group;
1001 /* Dual Channel needs different tables. */
1002 if (dual_channel)
1003 slew_group = dual_channel_slew_group_lookup;
1004 else
1005 slew_group = single_channel_slew_group_lookup;
1006
1007 switch (slew_group[index]) {
1008 case DQ2030: return dq2030;
1009 case DQ2330: return dq2330;
1010 case CMD2710: return cmd2710;
1011 case CMD3210: return cmd3210;
1012 case CLK2030: return clk2030;
1013 case CTL3215: return ctl3215;
1014 case CTL3220: return ctl3220;
1015 case NC: return nc;
1016 }
1017
1018 return nc;
1019}
1020
1021#ifdef CHIPSET_I945GM
1022/* Strength multiplier tables */
1023static const u8 dual_channel_strength_multiplier[] = {
1024 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1025 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1026 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1027 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1028 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1029 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1030 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1031 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1032 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1033 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1034 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1035 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1036 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1037 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1038 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1039 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1040 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1041 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1042 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1043 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1044 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1045 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1046 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1047 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1048};
1049
1050static const u8 single_channel_strength_multiplier[] = {
1051 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1052 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1053 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1054 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1055 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1056 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1057 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1058 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1059 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1060 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
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, 0x33, 0x11,
1064 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1065 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1066 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1067 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1068 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1069 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1070 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1071 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1072 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1073 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1074 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1075};
1076#endif
1077#ifdef CHIPSET_I945GC
1078static const u8 dual_channel_strength_multiplier[] = {
1079 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1080 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1081 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1082 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1083 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1084 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1085 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1086 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1087 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1088 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1089 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1090 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1091 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1092 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1093 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1094 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1095 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1096 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1097 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1098 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1099 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1100 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1101 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1102 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1103};
1104
1105static const u8 single_channel_strength_multiplier[] = {
1106 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1107 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1108 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1109 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1110 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1111 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1112 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1113 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1114 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1115 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1116 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1117 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1118 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1119 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1120 0x44, 0x22, 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, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1124 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1125 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1126 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1127 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1128 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1129 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1130};
1131#endif
1132
Stefan Reinauer278534d2008-10-29 04:51:07 +00001133static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1134{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001135 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001136 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001137
1138 /* Set Strength Multipliers */
1139
1140 /* Dual Channel needs different tables. */
1141 if (sdram_capabilities_dual_channel()) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001142 printk_debug("Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001143 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001144 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001145 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1146 } else {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001147 printk_debug("Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001148 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001149 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001150 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1151 }
1152
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001153 printk_debug("Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001154
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001155 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1156 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1157 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1158 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1159 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1160 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1161 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1162 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001163
1164 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001165 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1166 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1167 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001168
Stefan Reinauer278534d2008-10-29 04:51:07 +00001169 sdram_write_slew_rates(G3SRPUT, ctl3220);
1170 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001171 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001172 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001173 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1174 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1175 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001176
1177 /* Channel 1 */
1178 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001179 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1180 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001181 } else {
1182 sdram_write_slew_rates(G7SRPUT, nc);
1183 sdram_write_slew_rates(G8SRPUT, nc);
1184 }
1185}
1186
1187static void sdram_enable_rcomp(void)
1188{
1189 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001190 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001191 udelay(300);
1192 reg32 = MCHBAR32(GBRCOMPCTL);
1193 reg32 &= ~(1 << 23);
1194 MCHBAR32(GBRCOMPCTL) = reg32;
1195}
1196
1197static void sdram_program_dll_timings(struct sys_info *sysinfo)
1198{
1199 u32 chan0dll = 0, chan1dll = 0;
1200 int i;
1201
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001202 printk_debug ("Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001203
Stefan Reinauer278534d2008-10-29 04:51:07 +00001204 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1205 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1206
1207 /* We drive both channels with the same speed */
1208 switch (sysinfo->memory_frequency) {
1209 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1210 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1211 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1212 }
1213
1214 for (i=0; i < 4; i++) {
1215 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1216 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1217 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1218 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1219 }
1220}
1221
1222static void sdram_force_rcomp(void)
1223{
1224 u32 reg32;
1225 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001226
Stefan Reinauer278534d2008-10-29 04:51:07 +00001227 reg32 = MCHBAR32(ODTC);
1228 reg32 |= (1 << 28);
1229 MCHBAR32(ODTC) = reg32;
1230
1231 reg32 = MCHBAR32(SMSRCTL);
1232 reg32 |= (1 << 0);
1233 MCHBAR32(SMSRCTL) = reg32;
1234
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001235 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001236 reg32 = MCHBAR32(GBRCOMPCTL);
1237 reg32 |= (1 << 8);
1238 MCHBAR32(GBRCOMPCTL) = reg32;
1239
1240 reg8 = i945_silicon_revision();
1241 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001242
Stefan Reinauer278534d2008-10-29 04:51:07 +00001243 reg32 = MCHBAR32(GBRCOMPCTL);
1244 reg32 |= (3 << 5);
1245 MCHBAR32(GBRCOMPCTL) = reg32;
1246 }
1247}
1248
1249static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1250{
1251 u8 reg8;
1252 u32 reg32;
1253
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001254 printk_debug ("Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001255 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001256 reg8 = MCHBAR8(C0HCTC);
1257 reg8 &= ~0x1f;
1258 reg8 |= ( 1 << 0);
1259 MCHBAR8(C0HCTC) = reg8;
1260
1261 reg8 = MCHBAR8(C1HCTC);
1262 reg8 &= ~0x1f;
1263 reg8 |= ( 1 << 0);
1264 MCHBAR8(C1HCTC) = reg8;
1265
Stefan Reinauer278534d2008-10-29 04:51:07 +00001266 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1267 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1268
1269 MCHBAR8(C0WDLLCMC) = 0;
1270 MCHBAR8(C1WDLLCMC) = 0;
1271
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001272 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001273 sdram_program_dram_width(sysinfo);
1274
1275 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1276
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001277 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001278 reg32 = MCHBAR32(GBRCOMPCTL);
1279 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1280 reg32 |= (3 << 27) | (3 << 0);
1281 MCHBAR32(GBRCOMPCTL) = reg32;
1282
1283 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1284
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001285 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001286 sdram_program_dll_timings(sysinfo);
1287
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001288 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001289 sdram_force_rcomp();
1290}
1291
1292static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1293{
1294 u32 reg32;
1295
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001296 printk_debug ("Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001297
Stefan Reinauer278534d2008-10-29 04:51:07 +00001298 reg32 = MCHBAR32(RCVENMT);
1299 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001300 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001301
1302 reg32 |= (1 << 11) | (1 << 9);
1303 MCHBAR32(RCVENMT) = reg32;
1304
1305 reg32 = MCHBAR32(DRTST);
1306 reg32 |= (1 << 3) | (1 << 2);
1307 MCHBAR32(DRTST) = reg32;
1308
1309 reg32 = MCHBAR32(DRTST);
1310 reg32 |= (1 << 6) | (1 << 4);
1311 MCHBAR32(DRTST) = reg32;
1312
1313 asm volatile ("nop; nop;");
1314
1315 reg32 = MCHBAR32(DRTST);
1316
1317 /* Is channel 0 populated? */
1318 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1319 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1320 reg32 |= (1 << 7) | (1 << 5);
1321 else
1322 reg32 |= (1 << 31);
1323
1324 /* Is channel 1 populated? */
1325 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1326 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1327 reg32 |= (1 << 9) | (1 << 8);
1328 else
1329 reg32 |= (1 << 30);
1330
1331 MCHBAR32(DRTST) = reg32;
1332
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001333 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001334 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1335 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1336 reg32 = MCHBAR32(C0DRC1);
1337 reg32 |= (1 << 8);
1338 MCHBAR32(C0DRC1) = reg32;
1339 }
1340 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1341 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1342 reg32 = MCHBAR32(C1DRC1);
1343 reg32 |= (1 << 8);
1344 MCHBAR32(C1DRC1) = reg32;
1345 }
1346}
1347
1348struct dimm_size {
1349 unsigned long side1;
1350 unsigned long side2;
1351};
1352
1353static struct dimm_size sdram_get_dimm_size(u16 device)
1354{
1355 /* Calculate the log base 2 size of a DIMM in bits */
1356 struct dimm_size sz;
1357 int value, low, rows, columns;
1358
1359 sz.side1 = 0;
1360 sz.side2 = 0;
1361
1362 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1363 if (rows < 0) goto hw_err;
1364 if ((rows & 0xf) == 0) goto val_err;
1365 sz.side1 += rows & 0xf;
1366
1367 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1368 if (columns < 0) goto hw_err;
1369 if ((columns & 0xf) == 0) goto val_err;
1370 sz.side1 += columns & 0xf;
1371
1372 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1373 if (value < 0) goto hw_err;
1374 if ((value & 0xff) == 0) goto val_err;
1375 sz.side1 += log2(value & 0xff);
1376
1377 /* Get the module data width and convert it to a power of two */
1378 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1379 if (value < 0) goto hw_err;
1380 value &= 0xff;
1381 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001382
Stefan Reinauer278534d2008-10-29 04:51:07 +00001383 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1384 if (low < 0) goto hw_err;
1385 value = value | (low & 0xff);
1386 if ((value != 72) && (value != 64)) goto val_err;
1387 sz.side1 += log2(value);
1388
1389 /* side 2 */
1390 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1391
1392 if (value < 0) goto hw_err;
1393 value &= 7;
1394 value++;
1395 if (value == 1) goto out;
1396 if (value != 2) goto val_err;
1397
1398 /* Start with the symmetrical case */
1399 sz.side2 = sz.side1;
1400
1401 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1402
1403 /* Don't die here, I have not come across any of these to test what
1404 * actually happens.
1405 */
1406 printk_err("Assymetric DIMMs are not supported by this chipset\n");
1407
1408 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1409 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1410
1411 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1412 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1413
1414 goto out;
1415
1416 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001417 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001418 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001419 /* If a hardware error occurs the spd rom probably does not exist.
1420 * In this case report that there is no memory
1421 */
1422 sz.side1 = 0;
1423 sz.side2 = 0;
1424 out:
1425 return sz;
1426}
1427
1428static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1429{
1430 int i;
1431
1432 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1433 struct dimm_size sz;
1434
1435 sysinfo->banksize[i * 2] = 0;
1436 sysinfo->banksize[(i * 2) + 1] = 0;
1437
1438 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1439 continue;
1440
1441 sz = sdram_get_dimm_size(DIMM_SPD_BASE + i);
1442
1443 sysinfo->banks[i] = spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1444
1445 if (sz.side1 < 30)
1446 die("DDR-II rank size smaller than 128MB is not supported.\n");
1447
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001448 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001449
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001450 printk_debug("DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
1451
Stefan Reinauer278534d2008-10-29 04:51:07 +00001452 if (!sz.side2)
1453 continue;
1454
1455 /* If there is a second side, it has to have at least 128M, too */
1456 if (sz.side2 < 30)
1457 die("DDR-II rank size smaller than 128MB is not supported.\n");
1458
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001459 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001460
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001461 printk_debug("DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001462 }
1463}
1464
1465static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1466{
1467 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001468 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001469
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001470 printk_debug ("Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001471
1472 cum0 = 0;
1473 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001474 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001475 MCHBAR8(C0DRB0+i) = cum0;
1476 }
1477
1478 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1479 cum1 = cum0;
1480
1481 /* Exception: Interleaved starts from the beginning */
1482 if (sysinfo->interleaved)
1483 cum1 = 0;
1484
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001485#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001486 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1487 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1488 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1489 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001490#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001491
1492 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001493 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001494 MCHBAR8(C1DRB0+i) = cum1;
1495 }
1496
1497 /* Set TOLUD Top Of Low Usable DRAM */
1498 if (sysinfo->interleaved)
1499 tolud = (cum0 + cum1) << 1;
1500 else
1501 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001502
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001503 /* The TOM register has a different format */
1504 tom = tolud >> 3;
1505
1506 /* Limit the value of TOLUD to leave some space for PCI memory. */
1507 if (tolud > 0xd0)
1508 tolud = 0xd0; /* 3.25GB : 0.75GB */
1509
1510 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1511
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001512 printk_debug("C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1513 printk_debug("C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001514 printk_debug("TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001515
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001516 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001517
1518 return 0;
1519}
1520
Stefan Reinauer278534d2008-10-29 04:51:07 +00001521static int sdram_set_row_attributes(struct sys_info *sysinfo)
1522{
1523 int i, value;
1524 u16 dra0=0, dra1=0, dra = 0;
1525
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001526 printk_debug ("Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001527 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1528 u16 device;
1529 u8 columnsrows;
1530
1531 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1532 continue;
1533 }
1534
1535 device = DIMM_SPD_BASE + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001536
1537 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1538 columnsrows = (value & 0x0f);
1539
1540 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1541 columnsrows |= (value & 0xf) << 4;
1542
1543 switch (columnsrows) {
1544 case 0x9d: dra = 2; break;
1545 case 0xad: dra = 3; break;
1546 case 0xbd: dra = 4; break;
1547 case 0xae: dra = 3; break;
1548 case 0xbe: dra = 4; break;
1549 default: die("Unsupported Rows/Columns. (DRA)");
1550 }
1551
1552 /* Double Sided DIMMs? */
1553 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1554 dra = (dra << 4) | dra;
1555 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001556
Stefan Reinauer278534d2008-10-29 04:51:07 +00001557 if (i < DIMM_SOCKETS)
1558 dra0 |= (dra << (i*8));
1559 else
1560 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1561 }
1562
1563 MCHBAR16(C0DRA0) = dra0;
1564 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001565
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001566 printk_debug("C0DRA = 0x%04x\n", dra0);
1567 printk_debug("C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001568
1569 return 0;
1570}
1571
1572static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1573{
1574 u32 off32;
1575 int i;
1576
1577 MCHBAR16(C1BNKARC) &= 0xff00;
1578 MCHBAR16(C0BNKARC) &= 0xff00;
1579
1580 off32 = C0BNKARC;
1581 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1582 /* Switch to second channel */
1583 if (i == DIMM_SOCKETS)
1584 off32 = C1BNKARC;
1585
1586 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1587 continue;
1588
1589 if (sysinfo->banks[i] != 8)
1590 continue;
1591
Stefan Reinauerde3206a2010-02-22 06:09:43 +00001592 printk_spew("DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001593
1594 if (i & 1)
1595 MCHBAR16(off32) |= 0x50;
1596 else
1597 MCHBAR16(off32) |= 0x05;
1598 }
1599}
1600
1601#define REFRESH_7_8US 1
1602#define REFRESH_15_6US 0
1603static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1604{
1605 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001606
Stefan Reinauer278534d2008-10-29 04:51:07 +00001607 if (sysinfo->refresh == REFRESH_7_8US) {
1608 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1609 } else {
1610 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1611 }
1612
1613 MCHBAR32(C0DRC0) &= ~(7 << 8);
1614 MCHBAR32(C0DRC0) |= reg32;
1615
1616 MCHBAR32(C1DRC0) &= ~(7 << 8);
1617 MCHBAR32(C1DRC0) |= reg32;
1618}
1619
1620static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1621{
1622 u32 reg32;
1623 int i;
1624
1625 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001626
Stefan Reinauer278534d2008-10-29 04:51:07 +00001627 for (i=0; i < 4; i++) {
1628 if (sysinfo->banksize[i] == 0) {
1629 reg32 |= (1 << (16 + i));
1630 }
1631 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001632
Stefan Reinauer278534d2008-10-29 04:51:07 +00001633 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001634
Stefan Reinauer278534d2008-10-29 04:51:07 +00001635 reg32 |= (1 << 11);
1636 MCHBAR32(C0DRC1) = reg32;
1637
1638 /* Do we have to do this if we're in Single Channel Mode? */
1639 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001640
Stefan Reinauer278534d2008-10-29 04:51:07 +00001641 for (i=4; i < 8; i++) {
1642 if (sysinfo->banksize[i] == 0) {
1643 reg32 |= (1 << (12 + i));
1644 }
1645 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001646
Stefan Reinauer278534d2008-10-29 04:51:07 +00001647 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001648
Stefan Reinauer278534d2008-10-29 04:51:07 +00001649 reg32 |= (1 << 11);
1650 MCHBAR32(C1DRC1) = reg32;
1651}
1652
1653static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1654{
1655 u32 reg32;
1656 int i;
1657
1658 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001659
Stefan Reinauer278534d2008-10-29 04:51:07 +00001660 for (i=0; i < 4; i++) {
1661 if (sysinfo->banksize[i] == 0) {
1662 reg32 |= (1 << (24 + i));
1663 }
1664 }
1665 MCHBAR32(C0DRC2) = reg32;
1666
1667 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001668
Stefan Reinauer278534d2008-10-29 04:51:07 +00001669 for (i=4; i < 8; i++) {
1670 if (sysinfo->banksize[i] == 0) {
1671 reg32 |= (1 << (20 + i));
1672 }
1673 }
1674 MCHBAR32(C1DRC2) = reg32;
1675}
1676
1677static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1678{
1679 u32 reg32, off32;
1680 u32 tWTR;
1681 u32 temp_drt;
1682 int i, page_size;
1683
1684 static const u8 const drt0_table[] = {
1685 /* CL 3, 4, 5 */
1686 3, 4, 5, /* FSB533/400, DDR533/400 */
1687 4, 5, 6, /* FSB667, DDR533/400 */
1688 4, 5, 6, /* FSB667, DDR667 */
1689 };
1690
1691 static const u8 const cas_table[] = {
1692 2, 1, 0, 3
1693 };
1694
1695 reg32 = MCHBAR32(C0DRC0);
1696 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001697 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001698 MCHBAR32(C0DRC0) = reg32;
1699
1700 reg32 = MCHBAR32(C1DRC0);
1701 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001702 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001703 MCHBAR32(C1DRC0) = reg32;
1704
1705 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1706 SYSINFO_DIMM_NOT_POPULATED) {
1707 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001708 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001709 MCHBAR32(C0DRC0) = reg32;
1710 }
1711
1712 sdram_program_refresh_rate(sysinfo);
1713
1714 sdram_program_cke_tristate(sysinfo);
1715
1716 sdram_program_odt_tristate(sysinfo);
1717
1718 /* Calculate DRT0 */
1719
1720 temp_drt = 0;
1721
1722 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1723 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1724 temp_drt |= (reg32 << 28);
1725
1726 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1727 reg32 += sysinfo->trp;
1728 temp_drt |= (reg32 << 4);
1729
1730 if (sysinfo->memory_frequency == 667) {
1731 tWTR = 3; /* 667MHz */
1732 } else {
1733 tWTR = 2; /* 400 and 533 */
1734 }
1735
1736 /* B2B Write to Read Command Spacing */
1737 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1738 temp_drt |= (reg32 << 24);
1739
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001740 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001741 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1742
1743 /* Program Write Auto Precharge to Activate */
1744 off32 = 0;
1745 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1746 off32 += 3;
1747 }
1748 if (sysinfo->memory_frequency == 667) {
1749 off32 += 3;
1750 }
1751 off32 += sysinfo->cas - 3;
1752 reg32 = drt0_table[off32];
1753 temp_drt |= (reg32 << 11);
1754
1755 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001756
Stefan Reinauer278534d2008-10-29 04:51:07 +00001757 temp_drt |= (8 << 0);
1758
1759 MCHBAR32(C0DRT0) = temp_drt;
1760 MCHBAR32(C1DRT0) = temp_drt;
1761
1762 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001763
Stefan Reinauer278534d2008-10-29 04:51:07 +00001764 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1765
1766 /* DRAM RASB Precharge */
1767 temp_drt |= (sysinfo->trp - 2) << 0;
1768
1769 /* DRAM RASB to CASB Delay */
1770 temp_drt |= (sysinfo->trcd - 2) << 4;
1771
1772 /* CASB Latency */
1773 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1774
1775 /* Refresh Cycle Time */
1776 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001777
Stefan Reinauer278534d2008-10-29 04:51:07 +00001778 /* Pre-All to Activate Delay */
1779 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001780
Stefan Reinauer278534d2008-10-29 04:51:07 +00001781 /* Precharge to Precharge Delay stays at 1 clock */
1782 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001783
Stefan Reinauer278534d2008-10-29 04:51:07 +00001784 /* Activate to Precharge Delay */
1785 temp_drt |= (sysinfo->tras << 19);
1786
1787 /* Read to Precharge (tRTP) */
1788 if (sysinfo->memory_frequency == 667) {
1789 temp_drt |= (1 << 28);
1790 } else {
1791 temp_drt |= (0 << 28);
1792 }
1793
1794 /* Determine page size */
1795 reg32 = 0;
1796 page_size = 1; /* Default: 1k pagesize */
1797 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1798 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1799 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1800 page_size = 2; /* 2k pagesize */
1801 }
1802
1803 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1804 reg32 = 1;
1805 }
1806 if (sysinfo->memory_frequency == 667) {
1807 reg32 = page_size;
1808 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001809
Stefan Reinauer278534d2008-10-29 04:51:07 +00001810 temp_drt |= (reg32 << 30);
1811
1812 MCHBAR32(C0DRT1) = temp_drt;
1813 MCHBAR32(C1DRT1) = temp_drt;
1814
1815 /* Program DRT2 */
1816 reg32 = MCHBAR32(C0DRT2);
1817 reg32 &= ~(1 << 8);
1818 MCHBAR32(C0DRT2) = reg32;
1819
1820 reg32 = MCHBAR32(C1DRT2);
1821 reg32 &= ~(1 << 8);
1822 MCHBAR32(C1DRT2) = reg32;
1823
1824 /* Calculate DRT3 */
1825 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1826
1827 /* Get old tRFC value */
1828 reg32 = MCHBAR32(C0DRT1) >> 10;
1829 reg32 &= 0x3f;
1830
1831 /* 788nS - tRFC */
1832 switch (sysinfo->memory_frequency) {
1833 case 400: /* 5nS */
1834 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1835 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1836 break;
1837 case 533: /* 3.75nS */
1838 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1839 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1840 break;
1841 case 667: /* 3nS */
1842 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1843 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1844 break;
1845 }
1846
1847 temp_drt |= reg32;
1848
1849 MCHBAR32(C0DRT3) = temp_drt;
1850 MCHBAR32(C1DRT3) = temp_drt;
1851}
1852
1853static void sdram_set_channel_mode(struct sys_info *sysinfo)
1854{
1855 u32 reg32;
1856
1857 printk_debug("Setting mode of operation for memory channels...");
1858
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001859 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001860 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1861 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1862 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1863 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1864 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001865 sysinfo->interleaved = 1;
1866 } else {
1867 sysinfo->interleaved = 0;
1868 }
1869
1870 reg32 = MCHBAR32(DCC);
1871 reg32 &= ~(7 << 0);
1872
1873 if(sysinfo->interleaved) {
1874 /* Dual Channel Interleaved */
1875 printk_debug("Dual Channel Interleaved.\n");
1876 reg32 |= (1 << 1);
1877 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1878 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1879 /* Channel 1 only */
1880 printk_debug("Single Channel 1 only.\n");
1881 reg32 |= (1 << 2);
1882 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1883 SYSINFO_DIMM_NOT_POPULATED) {
1884 /* Dual Channel Assymetric */
1885 printk_debug("Dual Channel Assymetric.\n");
1886 reg32 |= (1 << 0);
1887 } else {
1888 /* All bits 0 means Single Channel 0 operation */
1889 printk_debug("Single Channel 0 only.\n");
1890 }
1891
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001892 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001893
1894 MCHBAR32(DCC) = reg32;
1895
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001896 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001897}
1898
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001899static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001900{
1901 volatile u16 reg16;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001902
1903 MCHBAR32(PLLMON) = 0x80800000;
1904
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001905 sysinfo->fsb_frequency = fsbclk();
1906 if (sysinfo->fsb_frequency == -1)
1907 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001908
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001909 /* Program CPCTL according to FSB speed */
1910 /* Only write the lower byte */
1911 switch (sysinfo->fsb_frequency) {
1912 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1913 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1914 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1915 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001916
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001917 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001918
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001919 reg16 = MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001920}
1921
1922static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1923{
1924 u8 reg8;
1925 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001926 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001927
1928#define CRCLK_166MHz 0x00
1929#define CRCLK_200MHz 0x01
1930#define CRCLK_250MHz 0x03
1931#define CRCLK_400MHz 0x05
1932
1933#define CDCLK_200MHz 0x00
1934#define CDCLK_320MHz 0x40
1935
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001936#define VOLTAGE_1_05 0x00
1937#define VOLTAGE_1_50 0x01
1938
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001939 printk_debug ("Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001940
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001941 printk_debug("FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001942
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001943 voltage = VOLTAGE_1_05;
1944 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1945 voltage = VOLTAGE_1_50;
1946 printk_debug("Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001947
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001948 /* Gate graphics hardware for frequency change */
1949 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
1950 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
1951 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001952
1953 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001954 reg8 = sdram_capabilities_core_frequencies();
1955
Stefan Reinauer278534d2008-10-29 04:51:07 +00001956 freq = CRCLK_250MHz;
1957 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001958 case GFX_FREQUENCY_CAP_ALL:
1959 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001960 freq = CRCLK_250MHz;
1961 else
1962 freq = CRCLK_400MHz;
1963 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001964 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
1965 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
1966 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001967 }
1968
1969 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001970 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001971 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
1972 if (reg8==2)
1973 freq = CRCLK_166MHz;
1974 }
1975
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001976 printk_debug("Render: ");
1977 switch (freq) {
1978 case CRCLK_166MHz: printk_debug("166Mhz"); break;
1979 case CRCLK_200MHz: printk_debug("200Mhz"); break;
1980 case CRCLK_250MHz: printk_debug("250Mhz"); break;
1981 case CRCLK_400MHz: printk_debug("400Mhz"); break;
1982 }
1983
Stefan Reinauer278534d2008-10-29 04:51:07 +00001984 if (i945_silicon_revision() == 0) {
1985 sysinfo->mvco4x = 1;
1986 } else {
1987 sysinfo->mvco4x = 0;
1988 }
1989
Stefan Reinauer278534d2008-10-29 04:51:07 +00001990 second_vco = 0;
1991
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001992 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001993 second_vco = 1;
1994 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
1995 u16 mem = sysinfo->memory_frequency;
1996 u16 fsb = sysinfo->fsb_frequency;
1997
1998 if ( (fsb == 667 && mem == 533) ||
1999 (fsb == 533 && mem == 533) ||
2000 (fsb == 533 && mem == 400)) {
2001 second_vco = 1;
2002 }
2003
2004 if (fsb == 667 && mem == 533)
2005 sysinfo->mvco4x = 1;
2006 }
2007
2008 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002009 sysinfo->clkcfg_bit7=1;
2010 } else {
2011 sysinfo->clkcfg_bit7=0;
2012 }
2013
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002014 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002015 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2016 reg16 &= ~( (7 << 0) | (1 << 13) );
2017 reg16 |= freq;
2018 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2019
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002020 /* Graphics Core Display Clock */
2021 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2022 reg8 &= ~( (1<<7) | (7<<4) );
2023
2024 if (voltage == VOLTAGE_1_05) {
2025 reg8 |= CDCLK_200MHz;
2026 printk_debug(" Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002027 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002028 reg8 |= CDCLK_320MHz;
2029 printk_debug(" Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002030 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002031 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002032
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002033 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002034
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002035 reg8 |= (1<<3) | (1<<1);
2036 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2037
2038 reg8 |= 0x0f;
2039 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2040
2041 /* Ungate core render and display clocks */
2042 reg8 &= 0xf0;
2043 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002044}
2045
2046static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2047{
2048 u32 clkcfg;
2049 u8 reg8;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002050 u8 offset = 0;
2051#ifdef CHIPSET_I945GM
2052 offset++;
2053#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002054
2055 printk_debug ("Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002056
Stefan Reinauer278534d2008-10-29 04:51:07 +00002057 clkcfg = MCHBAR32(CLKCFG);
2058
2059 printk_debug("CLKCFG=0x%08x, ", clkcfg);
2060
2061 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2062
2063 if (sysinfo->mvco4x) {
2064 printk_debug("MVCO 4x, ");
2065 clkcfg &= ~(1 << 12);
2066 }
2067
2068 if (sysinfo->clkcfg_bit7) {
2069 printk_debug("second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002070
Stefan Reinauer278534d2008-10-29 04:51:07 +00002071 clkcfg |= (1 << 7);
2072 }
2073
2074 switch (sysinfo->memory_frequency) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002075 case 400: clkcfg |= ((1+offset) << 4); break;
2076 case 533: clkcfg |= ((2+offset) << 4); break;
2077 case 667: clkcfg |= ((3+offset) << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002078 default: die("Target Memory Frequency Error");
2079 }
2080
2081 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002082 printk_debug ("ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002083 return;
2084 }
2085
2086 MCHBAR32(CLKCFG) = clkcfg;
2087
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002088 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002089 * cache before we execute it.
2090 */
2091 goto cache_code;
2092vco_update:
2093 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2094 reg8 &= ~(1 << 7);
2095 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2096
Stefan Reinauer278534d2008-10-29 04:51:07 +00002097 clkcfg &= ~(1 << 10);
2098 MCHBAR32(CLKCFG) = clkcfg;
2099 clkcfg |= (1 << 10);
2100 MCHBAR32(CLKCFG) = clkcfg;
2101
Stefan Reinauer278534d2008-10-29 04:51:07 +00002102 __asm__ __volatile__ (
2103 " movl $0x100, %%ecx\n"
2104 "delay_update:\n"
2105 " nop\n"
2106 " nop\n"
2107 " nop\n"
2108 " nop\n"
2109 " loop delay_update\n"
2110 : /* No outputs */
2111 : /* No inputs */
2112 : "%ecx"
2113 );
2114
Stefan Reinauer278534d2008-10-29 04:51:07 +00002115 clkcfg &= ~(1 << 10);
2116 MCHBAR32(CLKCFG) = clkcfg;
2117
2118 goto out;
2119cache_code:
2120 goto vco_update;
2121out:
2122
2123 printk_debug("CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002124 printk_debug ("ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002125}
2126
2127static void sdram_program_clock_crossing(void)
2128{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002129 int idx = 0;
2130
2131 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002132 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002133 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002134#ifdef CHIPSET_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002135 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002136 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002137 0xffffffff, 0xffffffff, /* nonexistant */
2138 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002139
Stefan Reinauer278534d2008-10-29 04:51:07 +00002140 0x08040120, 0x00000000, /* DDR400 FSB533 */
2141 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002142 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002143
2144 0x04020120, 0x00000010, /* DDR400 FSB667 */
2145 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002146 0x00100401, 0x00000000, /* DDR667 FSB667 */
2147
2148 0xffffffff, 0xffffffff, /* nonexistant */
2149 0xffffffff, 0xffffffff, /* nonexistant */
2150 0xffffffff, 0xffffffff, /* nonexistant */
2151
2152 0xffffffff, 0xffffffff, /* nonexistant */
2153 0xffffffff, 0xffffffff, /* nonexistant */
2154 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002155 };
2156
2157 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002158 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002159 0xffffffff, 0xffffffff, /* nonexistant */
2160 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002161
Stefan Reinauer278534d2008-10-29 04:51:07 +00002162 0x00060108, 0x00000000, /* DDR400 FSB533 */
2163 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002164 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002165
2166 0x00040318, 0x00000000, /* DDR400 FSB667 */
2167 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002168 0x02010804, 0x00000000, /* DDR667 FSB667 */
2169
2170 0xffffffff, 0xffffffff, /* nonexistant */
2171 0xffffffff, 0xffffffff, /* nonexistant */
2172 0xffffffff, 0xffffffff, /* nonexistant */
2173
2174 0xffffffff, 0xffffffff, /* nonexistant */
2175 0xffffffff, 0xffffffff, /* nonexistant */
2176 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002177 };
2178
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002179#endif
2180#ifdef CHIPSET_I945GC
2181 /* i945 G/P */
2182 static const u32 data_clock_crossing[] = {
2183 0xffffffff, 0xffffffff, /* nonexistant */
2184 0xffffffff, 0xffffffff, /* nonexistant */
2185 0xffffffff, 0xffffffff, /* nonexistant */
2186
2187 0x10080201, 0x00000000, /* DDR400 FSB533 */
2188 0x00100401, 0x00000000, /* DDR533 FSB533 */
2189 0xffffffff, 0xffffffff, /* nonexistant */
2190
2191 0xffffffff, 0xffffffff, /* nonexistant */
2192 0xffffffff, 0xffffffff, /* nonexistant */
2193 0xffffffff, 0xffffffff, /* nonexistant */
2194
2195 0x04020108, 0x00000000, /* DDR400 FSB800 */
2196 0x00020108, 0x00000000, /* DDR533 FSB800 */
2197 0x00080201, 0x00000000, /* DDR667 FSB800 */
2198
2199 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2200 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2201 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2202 };
2203
2204 static const u32 command_clock_crossing[] = {
2205 0xffffffff, 0xffffffff, /* nonexistant */
2206 0xffffffff, 0xffffffff, /* nonexistant */
2207 0xffffffff, 0xffffffff, /* nonexistant */
2208
2209 0x00010800, 0x00000402, /* DDR400 FSB533 */
2210 0x01000400, 0x00000200, /* DDR533 FSB533 */
2211 0xffffffff, 0xffffffff, /* nonexistant */
2212
2213 0xffffffff, 0xffffffff, /* nonexistant */
2214 0xffffffff, 0xffffffff, /* nonexistant */
2215 0xffffffff, 0xffffffff, /* nonexistant */
2216
2217 0x02010804, 0x00000000, /* DDR400 FSB800 */
2218 0x00010402, 0x00000000, /* DDR533 FSB800 */
2219 0x04020180, 0x00000008, /* DDR667 FSB800 */
2220
2221 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2222 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2223 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2224 };
2225#endif
2226
Stefan Reinauer278534d2008-10-29 04:51:07 +00002227 printk_debug("Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002228
2229 printk_debug("MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002230 switch (memclk()) {
2231 case 400: printk_debug("400"); idx += 0; break;
2232 case 533: printk_debug("533"); idx += 2; break;
2233 case 667: printk_debug("667"); idx += 4; break;
2234 default: printk_debug("RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002235 }
2236
2237 printk_debug(" FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002238 switch (fsbclk()) {
2239 case 400: printk_debug("400"); idx += 0; break;
2240 case 533: printk_debug("533"); idx += 6; break;
2241 case 667: printk_debug("667"); idx += 12; break;
2242 case 800: printk_debug("800"); idx += 18; break;
2243 case 1066: printk_debug("1066"); idx += 24; break;
2244 default: printk_debug("RSVD %x\n", fsbclk()); return;
2245 }
2246
2247 if (command_clock_crossing[idx]==0xffffffff) {
2248 printk_debug("Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002249 }
2250
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002251 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2252 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2253
Stefan Reinauer278534d2008-10-29 04:51:07 +00002254 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2255 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2256 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2257 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2258
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002259 printk_debug("... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002260}
2261
2262static void sdram_disable_fast_dispatch(void)
2263{
2264 u32 reg32;
2265
2266 reg32 = MCHBAR32(FSBPMC3);
2267 reg32 |= (1 << 1);
2268 MCHBAR32(FSBPMC3) = reg32;
2269
2270 reg32 = MCHBAR32(SBTEST);
2271 reg32 |= (3 << 1);
2272 MCHBAR32(SBTEST) = reg32;
2273}
2274
2275static void sdram_pre_jedec_initialization(void)
2276{
2277 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002278
Stefan Reinauer278534d2008-10-29 04:51:07 +00002279 reg32 = MCHBAR32(WCC);
2280 reg32 &= 0x113ff3ff;
2281 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2282 MCHBAR32(WCC) = reg32;
2283
2284 MCHBAR32(SMVREFC) |= (1 << 6);
2285
2286 MCHBAR32(MMARB0) &= ~(3 << 17);
2287 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2288
2289 MCHBAR32(MMARB1) &= ~(7 << 8);
2290 MCHBAR32(MMARB1) |= (3 << 8);
2291
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002292 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002293 MCHBAR32(C0AIT) = 0x000006c4;
2294 MCHBAR32(C0AIT+4) = 0x871a066d;
2295
2296 MCHBAR32(C1AIT) = 0x000006c4;
2297 MCHBAR32(C1AIT+4) = 0x871a066d;
2298}
2299
2300#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2301#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2302#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2303#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2304#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2305#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2306#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2307#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2308
2309static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2310{
2311 u32 chan0 = 0, chan1 = 0;
2312 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2313
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002314 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002315 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002316 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002317 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2318 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2319 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2320
2321 if (sdram_capabilities_enhanced_addressing_xor()) {
2322 if (!sysinfo->interleaved) {
2323 /* Single Channel & Dual Channel Assymetric */
2324 if (chan0_populated) {
2325 if (chan0_dualsided) {
2326 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2327 } else {
2328 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2329 }
2330 }
2331 if (chan1_populated) {
2332 if (chan1_dualsided) {
2333 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2334 } else {
2335 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2336 }
2337 }
2338 } else {
2339 /* Interleaved has always both channels populated */
2340 if (chan0_dualsided) {
2341 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2342 } else {
2343 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2344 }
2345
2346 if (chan1_dualsided) {
2347 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2348 } else {
2349 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2350 }
2351 }
2352 } else {
2353 if (!sysinfo->interleaved) {
2354 /* Single Channel & Dual Channel Assymetric */
2355 if (chan0_populated) {
2356 if (chan0_dualsided) {
2357 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2358 } else {
2359 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2360 }
2361 }
2362 if (chan1_populated) {
2363 if (chan1_dualsided) {
2364 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2365 } else {
2366 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2367 }
2368 }
2369 } else {
2370 /* Interleaved has always both channels populated */
2371 if (chan0_dualsided) {
2372 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2373 } else {
2374 chan0 = EA_DUALCHANNEL_BANK_MODE;
2375 }
2376
2377 if (chan1_dualsided) {
2378 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2379 } else {
2380 chan1 = EA_DUALCHANNEL_BANK_MODE;
2381 }
2382 }
2383 }
2384
2385 MCHBAR32(C0DRC1) &= 0x00ffffff;
2386 MCHBAR32(C0DRC1) |= chan0;
2387 MCHBAR32(C1DRC1) &= 0x00ffffff;
2388 MCHBAR32(C1DRC1) |= chan1;
2389}
2390
2391static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2392{
2393 u32 reg32;
2394
2395 /* Enable Channel XORing for Dual Channel Interleave */
2396 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002397
Stefan Reinauer278534d2008-10-29 04:51:07 +00002398 reg32 = MCHBAR32(DCC);
2399#if CHANNEL_XOR_RANDOMIZATION
2400 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002401 reg32 |= (1 << 9);
2402#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002403 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002404#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002405 MCHBAR32(DCC) = reg32;
2406 }
2407
2408 /* DRAM mode optimizations */
2409 sdram_enhanced_addressing_mode(sysinfo);
2410
2411 reg32 = MCHBAR32(FSBPMC3);
2412 reg32 &= ~(1 << 1);
2413 MCHBAR32(FSBPMC3) = reg32;
2414
2415 reg32 = MCHBAR32(SBTEST);
2416 reg32 &= ~(1 << 2);
2417 MCHBAR32(SBTEST) = reg32;
2418
2419 reg32 = MCHBAR32(SBOCC);
2420 reg32 &= 0xffbdb6ff;
2421 reg32 |= (0xbdb6 << 8) | (1 << 0);
2422 MCHBAR32(SBOCC) = reg32;
2423}
2424
2425static void sdram_power_management(struct sys_info *sysinfo)
2426{
2427 u8 reg8;
2428 u16 reg16;
2429 u32 reg32;
2430 int integrated_graphics = 1;
2431 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002432
Stefan Reinauer278534d2008-10-29 04:51:07 +00002433 reg32 = MCHBAR32(C0DRT2);
2434 reg32 &= 0xffffff00;
2435 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002436 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002437 MCHBAR32(C0DRT2) = reg32;
2438
2439 reg32 = MCHBAR32(C1DRT2);
2440 reg32 &= 0xffffff00;
2441 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002442 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002443 MCHBAR32(C1DRT2) = reg32;
2444
2445 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002446
2447 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002448 MCHBAR32(C0DRC1) = reg32;
2449
2450 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002451
2452 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002453 MCHBAR32(C1DRC1) = reg32;
2454
2455 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002456 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2457 u16 peg_bits = (1 << 5) | (1 << 0);
2458
2459 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002460 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002461 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2462 u16 peg_bits = (1 << 5) | (1 << 0);
2463
Stefan Reinauer278534d2008-10-29 04:51:07 +00002464 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002465 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002466 }
2467
2468 reg16 = MCHBAR16(UPMC2);
2469 reg16 &= 0xfc00;
2470 reg16 |= 0x0100;
2471 MCHBAR16(UPMC2) = reg16;
2472
2473 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002474
Stefan Reinauer278534d2008-10-29 04:51:07 +00002475 for (i=0; i<5; i++) {
2476 MCHBAR32(UPMC3) &= ~(1 << 16);
2477 MCHBAR32(UPMC3) |= (1 << 16);
2478 }
2479
2480 MCHBAR32(GIPMC1) = 0x8000000c;
2481
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002482 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002483 reg16 &= ~(7 << 11);
2484 if (i945_silicon_revision()>2) {
2485 reg16 |= (6 << 11);
2486 } else {
2487 reg16 |= (4 << 11);
2488 }
2489 MCHBAR16(CPCTL) = reg16;
2490
Stefan Reinauer30140a52009-03-11 16:20:39 +00002491#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002492 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002493#else
2494 if (i945_silicon_revision() != 0) {
2495#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002496 switch (sysinfo->fsb_frequency) {
2497 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2498 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2499 }
2500 } else {
2501 switch (sysinfo->fsb_frequency) {
2502 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2503 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2504 }
2505 }
2506
2507 MCHBAR32(FSBPMC1) = 0x8000000c;
2508
2509 reg32 = MCHBAR32(C2C3TT);
2510 reg32 &= 0xffff0000;
2511 switch (sysinfo->fsb_frequency) {
2512 case 667: reg32 |= 0x0600; break;
2513 case 533: reg32 |= 0x0480; break;
2514 }
2515 MCHBAR32(C2C3TT) = reg32;
2516
2517 reg32 = MCHBAR32(C3C4TT);
2518 reg32 &= 0xffff0000;
2519 switch (sysinfo->fsb_frequency) {
2520 case 667: reg32 |= 0x0b80; break;
2521 case 533: reg32 |= 0x0980; break;
2522 }
2523 MCHBAR32(C3C4TT) = reg32;
2524
2525 if (i945_silicon_revision() == 0) {
2526 MCHBAR32(ECO) &= ~(1 << 16);
2527 } else {
2528 MCHBAR32(ECO) |= (1 << 16);
2529 }
2530
2531#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002532
Stefan Reinauer278534d2008-10-29 04:51:07 +00002533 if (i945_silicon_revision() == 0) {
2534 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2535 } else {
2536 MCHBAR32(FSBPMC3) |= (1 << 29);
2537 }
2538#endif
2539 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2540
2541 MCHBAR32(FSBPMC3) |= (1 << 21);
2542
2543 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2544
2545 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2546
2547 reg32 = MCHBAR32(FSBPMC4);
2548 reg32 &= ~(3 << 24);
2549 reg32 |= ( 2 << 24);
2550 MCHBAR32(FSBPMC4) = reg32;
2551
2552 MCHBAR32(FSBPMC4) |= (1 << 21);
2553
2554 MCHBAR32(FSBPMC4) |= (1 << 5);
2555
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002556 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2557 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002558 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2559 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002560 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002561 }
2562
2563 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2564 reg8 |= (1 << 4);
2565 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2566
2567 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2568 reg8 |= (1 << 2);
2569 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2570
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002571#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002572
Stefan Reinauer278534d2008-10-29 04:51:07 +00002573 if (integrated_graphics) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002574 printk_debug("C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002575 MCHBAR16(MIPMC4) = 0x0468;
2576 MCHBAR16(MIPMC5) = 0x046c;
2577 MCHBAR16(MIPMC6) = 0x046c;
2578 } else {
2579 MCHBAR16(MIPMC4) = 0x6468;
2580 MCHBAR16(MIPMC5) = 0x646c;
2581 MCHBAR16(MIPMC6) = 0x646c;
2582 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002583#else
2584 if (integrated_graphics) {
2585 MCHBAR16(MIPMC4) = 0x04f8;
2586 MCHBAR16(MIPMC5) = 0x04fc;
2587 MCHBAR16(MIPMC6) = 0x04fc;
2588 } else {
2589 MCHBAR16(MIPMC4) = 0x64f8;
2590 MCHBAR16(MIPMC5) = 0x64fc;
2591 MCHBAR16(MIPMC6) = 0x64fc;
2592 }
2593
2594#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002595
2596 reg32 = MCHBAR32(PMCFG);
2597 reg32 &= ~(3 << 17);
2598 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002599 MCHBAR32(PMCFG) = reg32;
2600
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002601 MCHBAR32(PMCFG) |= (1 << 4);
2602
Stefan Reinauer278534d2008-10-29 04:51:07 +00002603 reg32 = MCHBAR32(0xc30);
2604 reg32 &= 0xffffff00;
2605 reg32 |= 0x01;
2606 MCHBAR32(0xc30) = reg32;
2607
2608 MCHBAR32(0xb18) &= ~(1 << 21);
2609}
2610
2611static void sdram_thermal_management(void)
2612{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002613
Stefan Reinauer278534d2008-10-29 04:51:07 +00002614 MCHBAR8(TCO1) = 0x00;
2615 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002616
2617 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2618 * 0x30/0x32.
2619 */
2620
2621}
2622
2623static void sdram_save_receive_enable(void)
2624{
2625 int i;
2626 u32 reg32;
2627 u8 values[4];
2628
2629 /* The following values are stored to an unused CMOS
2630 * area and restored instead of recalculated in case
2631 * of an S3 resume.
2632 *
2633 * C0WL0REOST [7:0] -> 8 bit
2634 * C1WL0REOST [7:0] -> 8 bit
2635 * RCVENMT [11:8] [3:0] -> 8 bit
2636 * C0DRT1 [27:24] -> 4 bit
2637 * C1DRT1 [27:24] -> 4 bit
2638 */
2639
2640 values[0] = MCHBAR8(C0WL0REOST);
2641 values[1] = MCHBAR8(C1WL0REOST);
2642
2643 reg32 = MCHBAR32(RCVENMT);
2644 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2645
2646 reg32 = MCHBAR32(C0DRT1);
2647 values[3] = (reg32 >> 24) & 0x0f;
2648 reg32 = MCHBAR32(C1DRT1);
2649 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2650
2651 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
2652 * so we grad bytes 128 - 131 to save the receive enable values
2653 */
2654
2655 for (i=0; i<4; i++)
2656 cmos_write(values[i], 128 + i);
2657}
2658
2659static void sdram_recover_receive_enable(void)
2660{
2661 int i;
2662 u32 reg32;
2663 u8 values[4];
2664
2665 for (i=0; i<4; i++)
2666 values[i] = cmos_read(128 + i);
2667
2668 MCHBAR8(C0WL0REOST) = values[0];
2669 MCHBAR8(C1WL0REOST) = values[1];
2670
2671 reg32 = MCHBAR32(RCVENMT);
2672 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2673 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2674 MCHBAR32(RCVENMT) = reg32;
2675
2676 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2677 reg32 |= (u32)(values[3] & 0x0f) << 24;
2678 MCHBAR32(C0DRT1) = reg32;
2679
2680 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2681 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2682 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002683}
2684
2685#include "rcven.c"
2686
2687static void sdram_program_receive_enable(struct sys_info *sysinfo)
2688{
2689 MCHBAR32(REPC) |= (1 << 0);
2690
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002691 /* enable upper CMOS */
2692 RCBA32(0x3400) = (1 << 2);
2693
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002694 /* Program Receive Enable Timings */
2695 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2696 sdram_recover_receive_enable();
2697 } else {
2698 receive_enable_adjust(sysinfo);
2699 sdram_save_receive_enable();
2700 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002701
2702 MCHBAR32(C0DRC1) |= (1 << 6);
2703 MCHBAR32(C1DRC1) |= (1 << 6);
2704 MCHBAR32(C0DRC1) &= ~(1 << 6);
2705 MCHBAR32(C1DRC1) &= ~(1 << 6);
2706
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002707 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002708}
2709
2710/**
2711 * @brief Enable On-Die Termination for DDR2.
2712 *
2713 */
2714
2715static void sdram_on_die_termination(struct sys_info *sysinfo)
2716{
2717 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002718 0x00024911, 0xe0010000,
2719 0x00049211, 0xe0020000,
2720 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002721 };
2722
2723 u32 reg32;
2724 int cas;
2725
2726 reg32 = MCHBAR32(ODTC);
2727 reg32 &= ~(3 << 16);
2728 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2729 MCHBAR32(ODTC) = reg32;
2730
2731 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2732 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
2733 printk_debug("one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002734
Stefan Reinauer278534d2008-10-29 04:51:07 +00002735 reg32 = MCHBAR32(C0ODT);
2736 reg32 &= ~(7 << 28);
2737 MCHBAR32(C0ODT) = reg32;
2738 reg32 = MCHBAR32(C1ODT);
2739 reg32 &= ~(7 << 28);
2740 MCHBAR32(C1ODT) = reg32;
2741 }
2742
2743 cas = sysinfo->cas;
2744
2745 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2746 reg32 |= odt[(cas-3) * 2];
2747 MCHBAR32(C0ODT) = reg32;
2748
2749 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2750 reg32 |= odt[(cas-3) * 2];
2751 MCHBAR32(C1ODT) = reg32;
2752
2753 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2754 reg32 |= odt[((cas-3) * 2) + 1];
2755 MCHBAR32(C0ODT + 4) = reg32;
2756
2757 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2758 reg32 |= odt[((cas-3) * 2) + 1];
2759 MCHBAR32(C1ODT + 4) = reg32;
2760}
2761
2762/**
2763 * @brief Enable clocks to populated sockets
2764 */
2765
2766static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2767{
2768 u8 clocks[2] = { 0, 0 };
2769
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002770#ifdef CHIPSET_I945GM
2771#define CLOCKS_WIDTH 2
2772#endif
2773#ifdef CHIPSET_I945GC
2774#define CLOCKS_WIDTH 3
2775#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002776 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002777 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002778
2779 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002780 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002781
2782 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002783 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002784
2785 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002786 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002787
2788#ifdef OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002789 /* Usually system firmware turns off system memory clock signals
2790 * to unused SO-DIMM slots to reduce EMI and power consumption.
2791 * However, the Kontron 986LCD-M does not like unused clock
2792 * signals to be disabled.
2793 * If other similar mainboard occur, it would make sense to make
2794 * this an entry in the sysinfo structure, and pre-initialize that
Stefan Reinauer38f147e2010-02-08 12:20:50 +00002795 * structure in the mainboard's romstage.c main() function.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002796 * For now an #ifdef will do.
2797 */
2798
2799 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2800 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002801#endif
2802
2803 MCHBAR8(C0DCLKDIS) = clocks[0];
2804 MCHBAR8(C1DCLKDIS) = clocks[1];
2805}
2806
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002807#define RTT_ODT_NONE 0
2808#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002809#define RTT_ODT_75_OHM (1 << 5)
2810#define RTT_ODT_150_OHM (1 << 9)
2811
2812#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2813
2814#define MRS_CAS_3 (3 << 7)
2815#define MRS_CAS_4 (4 << 7)
2816#define MRS_CAS_5 (5 << 7)
2817
2818#define MRS_TWR_3 (2 << 12)
2819#define MRS_TWR_4 (3 << 12)
2820#define MRS_TWR_5 (4 << 12)
2821
2822#define MRS_BT (1 << 6)
2823
2824#define MRS_BL4 (2 << 3)
2825#define MRS_BL8 (3 << 3)
2826
2827static void sdram_jedec_enable(struct sys_info *sysinfo)
2828{
2829 int i, nonzero;
2830 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2831
2832 for (i = 0, nonzero = -1; i < 8; i++) {
2833 if (sysinfo->banksize[i] == 0) {
2834 continue;
2835 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002836
Stefan Reinauer278534d2008-10-29 04:51:07 +00002837 printk_debug("jedec enable sequence: bank %d\n", i);
2838 switch (i) {
2839 case 0:
2840 /* Start at address 0 */
2841 bankaddr = 0;
2842 break;
2843 case 4:
2844 if (sysinfo->interleaved) {
2845 bankaddr = 0x40;
2846 break;
2847 }
2848 default:
2849 if (nonzero != -1) {
2850 printk_debug("bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002851 bankaddr += sysinfo->banksize[nonzero] <<
2852 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002853 break;
2854 }
2855 /* No populated bank hit before. Start at address 0 */
2856 bankaddr = 0;
2857 }
2858
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002859 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002860 * for the next offset we have to calculate
2861 */
2862 nonzero = i;
2863
2864 /* Get CAS latency set up */
2865 switch (sysinfo->cas) {
2866 case 5: mrsaddr = MRS_CAS_5; break;
2867 case 4: mrsaddr = MRS_CAS_4; break;
2868 case 3: mrsaddr = MRS_CAS_3; break;
2869 default: die("Jedec Error (CAS).\n");
2870 }
2871
2872 /* Get tWR set */
2873 switch (sysinfo->twr) {
2874 case 5: mrsaddr |= MRS_TWR_5; break;
2875 case 4: mrsaddr |= MRS_TWR_4; break;
2876 case 3: mrsaddr |= MRS_TWR_3; break;
2877 default: die("Jedec Error (tWR).\n");
2878 }
2879
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002880 /* Set "Burst Type" */
2881 mrsaddr |= MRS_BT;
2882
Stefan Reinauer278534d2008-10-29 04:51:07 +00002883 /* Interleaved */
2884 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002885 mrsaddr = mrsaddr << 1;
2886 }
2887
2888 /* Only burst length 8 supported */
2889 mrsaddr |= MRS_BL8;
2890
2891 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002892 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002893 do_ram_command(RAM_COMMAND_NOP);
2894 ram_read32(bankaddr);
2895
2896 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002897 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002898 do_ram_command(RAM_COMMAND_PRECHARGE);
2899 ram_read32(bankaddr);
2900
2901 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002902 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002903 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2904 ram_read32(bankaddr);
2905
2906 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002907 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002908 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2909 ram_read32(bankaddr);
2910
2911 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002912 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002913 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2914 tmpaddr = bankaddr;
2915 if (!sdram_capabilities_dual_channel()) {
2916 tmpaddr |= RTT_ODT_75_OHM;
2917 } else if (sysinfo->interleaved) {
2918 tmpaddr |= (RTT_ODT_150_OHM << 1);
2919 } else {
2920 tmpaddr |= RTT_ODT_150_OHM;
2921 }
2922 ram_read32(tmpaddr);
2923
2924 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002925 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002926 do_ram_command(RAM_COMMAND_MRS);
2927 tmpaddr = bankaddr;
2928 tmpaddr |= mrsaddr;
2929 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002930 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002931 tmpaddr |= (1 << 12);
2932 else
2933 tmpaddr |= (1 << 11);
2934 ram_read32(tmpaddr);
2935
2936 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002937 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002938 do_ram_command(RAM_COMMAND_PRECHARGE);
2939 ram_read32(bankaddr);
2940
2941 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002942 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002943 do_ram_command(RAM_COMMAND_CBR);
2944
2945 /* CBR wants two READs */
2946 ram_read32(bankaddr);
2947 ram_read32(bankaddr);
2948
2949 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002950 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002951 do_ram_command(RAM_COMMAND_MRS);
2952
2953 tmpaddr = bankaddr;
2954 tmpaddr |= mrsaddr;
2955 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002956
Stefan Reinauer278534d2008-10-29 04:51:07 +00002957 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002958 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002959 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002960
Stefan Reinauer278534d2008-10-29 04:51:07 +00002961 tmpaddr = bankaddr;
2962 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002963
Stefan Reinauer278534d2008-10-29 04:51:07 +00002964 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
2965 } else if (sysinfo->interleaved) {
2966 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
2967 } else {
2968 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
2969 }
2970 ram_read32(tmpaddr);
2971
2972 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002973 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002974 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2975
2976 tmpaddr = bankaddr;
2977 if (!sdram_capabilities_dual_channel()) {
2978 tmpaddr |= RTT_ODT_75_OHM;
2979 } else if (sysinfo->interleaved) {
2980 tmpaddr |= (RTT_ODT_150_OHM << 1);
2981 } else {
2982 tmpaddr |= RTT_ODT_150_OHM;
2983 }
2984 ram_read32(tmpaddr);
2985 }
2986}
2987
2988static void sdram_init_complete(void)
2989{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002990 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002991 do_ram_command(RAM_COMMAND_NORMAL);
2992}
2993
2994static void sdram_setup_processor_side(void)
2995{
2996 if (i945_silicon_revision() == 0)
2997 MCHBAR32(FSBPMC3) |= (1 << 2);
2998
2999 MCHBAR8(0xb00) |= 1;
3000
3001 if (i945_silicon_revision() == 0)
3002 MCHBAR32(SLPCTL) |= (1 << 8);
3003}
3004
Stefan Reinauer278534d2008-10-29 04:51:07 +00003005/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003006 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003007 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003008void sdram_initialize(int boot_path)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003009{
3010 struct sys_info sysinfo;
3011 u8 reg8, cas_mask;
3012
3013 sdram_detect_errors();
3014
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003015 printk_debug ("Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003016
3017 memset(&sysinfo, 0, sizeof(sysinfo));
3018
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003019 sysinfo.boot_path = boot_path;
3020
Stefan Reinauer278534d2008-10-29 04:51:07 +00003021 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3022 sdram_get_dram_configuration(&sysinfo);
3023
3024 /* Check whether we have stacked DIMMs */
3025 sdram_verify_package_type(&sysinfo);
3026
3027 /* Determine common CAS */
3028 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003029
Stefan Reinauer278534d2008-10-29 04:51:07 +00003030 /* Choose Common Frequency */
3031 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003032
Stefan Reinauer278534d2008-10-29 04:51:07 +00003033 /* Determine smallest common tRAS */
3034 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003035
Stefan Reinauer278534d2008-10-29 04:51:07 +00003036 /* Determine tRP */
3037 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003038
Stefan Reinauer278534d2008-10-29 04:51:07 +00003039 /* Determine tRCD */
3040 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003041
Stefan Reinauer278534d2008-10-29 04:51:07 +00003042 /* Determine smallest refresh period */
3043 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003044
Stefan Reinauer278534d2008-10-29 04:51:07 +00003045 /* Verify all DIMMs support burst length 8 */
3046 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003047
Stefan Reinauer278534d2008-10-29 04:51:07 +00003048 /* determine tWR */
3049 sdram_detect_smallest_tWR(&sysinfo);
3050
3051 /* Determine DIMM size parameters (rows, columns banks) */
3052 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003053
Stefan Reinauer278534d2008-10-29 04:51:07 +00003054 /* determine tRFC */
3055 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003056
Stefan Reinauer278534d2008-10-29 04:51:07 +00003057 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003058 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003059
3060 /* Program Graphics Frequency */
3061 sdram_program_graphics_frequency(&sysinfo);
3062
3063 /* Program System Memory Frequency */
3064 sdram_program_memory_frequency(&sysinfo);
3065
3066 /* Determine Mode of Operation (Interleaved etc) */
3067 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003068
Stefan Reinauer278534d2008-10-29 04:51:07 +00003069 /* Program Clock Crossing values */
3070 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003071
Stefan Reinauer278534d2008-10-29 04:51:07 +00003072 /* Disable fast dispatch */
3073 sdram_disable_fast_dispatch();
3074
3075 /* Enable WIODLL Power Down in ACPI states */
3076 MCHBAR32(C0DMC) |= (1 << 24);
3077 MCHBAR32(C1DMC) |= (1 << 24);
3078
3079 /* Program DRAM Row Boundary/Attribute Registers */
3080
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003081 /* program row size DRB and set TOLUD */
3082 sdram_program_row_boundaries(&sysinfo);
3083
3084 /* program page size DRA */
3085 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003086
3087 /* Program CxBNKARC */
3088 sdram_set_bank_architecture(&sysinfo);
3089
3090 /* Program DRAM Timing and Control registers based on SPD */
3091 sdram_set_timing_and_control(&sysinfo);
3092
3093 /* On-Die Termination Adjustment */
3094 sdram_on_die_termination(&sysinfo);
3095
3096 /* Pre Jedec Initialization */
3097 sdram_pre_jedec_initialization();
3098
3099 /* Perform System Memory IO Initialization */
3100 sdram_initialize_system_memory_io(&sysinfo);
3101
3102 /* Perform System Memory IO Buffer Enable */
3103 sdram_enable_system_memory_io(&sysinfo);
3104
3105 /* Enable System Memory Clocks */
3106 sdram_enable_memory_clocks(&sysinfo);
3107
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003108 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003109 /* Jedec Initialization sequence */
3110 sdram_jedec_enable(&sysinfo);
3111 }
3112
3113 /* Program Power Management Registers */
3114 sdram_power_management(&sysinfo);
3115
3116 /* Post Jedec Init */
3117 sdram_post_jedec_initialization(&sysinfo);
3118
3119 /* Program DRAM Throttling */
3120 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003121
Stefan Reinauer278534d2008-10-29 04:51:07 +00003122 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003123 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003124
3125 /* Program Receive Enable Timings */
3126 sdram_program_receive_enable(&sysinfo);
3127
3128 /* Enable Periodic RCOMP */
3129 sdram_enable_rcomp();
3130
3131 /* Tell ICH7 that we're done */
3132 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3133 reg8 &= ~(1 << 7);
3134 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3135
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003136 printk_debug("RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003137
Stefan Reinauer278534d2008-10-29 04:51:07 +00003138 sdram_setup_processor_side();
3139}
3140
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003141unsigned long get_top_of_ram(void)
3142{
3143 /* This will not work if TSEG is in place! */
3144 u32 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
3145
3146 return (unsigned long) tom;
3147}
3148