blob: 124ef147c396522aed26950e0ad07b5786109af5 [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
401 /* The chipset might be able to do this. What the heck, legacy bios
402 * just beeps when a single DIMM is in the Channel 1 socket. So let's
403 * not bother until someone needs this enough to cope with it.
404 */
405 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000406 printk_err("Channel 0 has no memory populated. This setup is not usable. Please move the DIMM.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000407 }
408}
409
410/**
411 * @brief determine if any DIMMs are stacked
412 *
413 * @param sysinfo central sysinfo data structure.
414 */
415static void sdram_verify_package_type(struct sys_info * sysinfo)
416{
417 int i;
418
419 /* Assume no stacked DIMMs are available until we find one */
420 sysinfo->package = 0;
421 for (i=0; i<2*DIMM_SOCKETS; i++) {
422 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
423 continue;
424
425 /* Is the current DIMM a stacked DIMM? */
426 if (spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_DIMM_BANKS) & (1 << 4))
427 sysinfo->package = 1;
428 }
429}
430
431static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
432{
433 int i;
434 u8 cas_mask;
435
436 /* Setup CAS mask with all supported CAS Latencies */
437 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
438 SPD_CAS_LATENCY_DDR2_4 |
439 SPD_CAS_LATENCY_DDR2_5;
440
441 for (i=0; i<2*DIMM_SOCKETS; i++) {
442 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
443 cas_mask &= spd_read_byte(DIMM_SPD_BASE + i, SPD_ACCEPTABLE_CAS_LATENCIES);
444 }
445
446 if(!cas_mask) {
447 die("No DDR-II modules with accepted CAS latencies found.\n");
448 }
449
450 return cas_mask;
451}
452
453static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
454{
455 int i, j, idx;
456 int lowest_common_cas = 0;
457 int max_ram_speed;
458
459 const u8 ddr2_speeds_table[] = {
460 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
461 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
462 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
463 };
464
465 const u8 spd_lookup_table[] = {
466 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
467 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
468 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
469 };
470
471 switch (sdram_capabilities_max_supported_memory_frequency()) {
472 case 400: max_ram_speed = 0; break;
473 case 533: max_ram_speed = 1; break;
474 case 667: max_ram_speed = 2; break;
475 }
476
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000477 if (fsbclk() == 533)
478 max_ram_speed = 1;
479
Stefan Reinauer278534d2008-10-29 04:51:07 +0000480 sysinfo->memory_frequency = 0;
481 sysinfo->cas = 0;
482
483 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
484 lowest_common_cas = 3;
485 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
486 lowest_common_cas = 4;
487 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
488 lowest_common_cas = 5;
489 }
490 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
491
492 for (j = max_ram_speed; j>=0; j--) {
493 int freq_cas_mask = cas_mask;
494
495 PRINTK_DEBUG("Probing Speed %d\n", j);
496 for (i=0; i<2*DIMM_SOCKETS; i++) {
497 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000498
Stefan Reinauer278534d2008-10-29 04:51:07 +0000499 PRINTK_DEBUG(" DIMM: %d\n", i);
500 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
501 continue;
502 }
503
504 current_cas_mask = spd_read_byte(DIMM_SPD_BASE + i, SPD_ACCEPTABLE_CAS_LATENCIES);
505
506 while (current_cas_mask) {
507 int highest_supported_cas = 0, current_cas = 0;
508 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
509 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
510 highest_supported_cas = 5;
511 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
512 highest_supported_cas = 4;
513 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
514 highest_supported_cas = 3;
515 }
516 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
517 current_cas = 3;
518 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
519 current_cas = 4;
520 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
521 current_cas = 5;
522 }
523
524 idx = highest_supported_cas - current_cas;
525 PRINTK_DEBUG("idx=%d, ", idx);
526 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[2*idx]));
527 PRINTK_DEBUG("tAC=%x", spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[(2*idx)+1]));
528
529 if (spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
530 spd_read_byte(DIMM_SPD_BASE + i, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
531 PRINTK_DEBUG(": OK\n");
532 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000533 }
534
Stefan Reinauer278534d2008-10-29 04:51:07 +0000535 PRINTK_DEBUG(": Not fast enough!\n");
536
537 current_cas_mask &= ~(1 << (current_cas));
538 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000539
Stefan Reinauer278534d2008-10-29 04:51:07 +0000540 freq_cas_mask &= current_cas_mask;
541 if (!current_cas_mask) {
542 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
543 break;
544 }
545 }
546 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
547 if (freq_cas_mask) {
548 switch (j) {
549 case 0: sysinfo->memory_frequency = 400; break;
550 case 1: sysinfo->memory_frequency = 533; break;
551 case 2: sysinfo->memory_frequency = 667; break;
552 }
553 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
554 sysinfo->cas = 3;
555 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
556 sysinfo->cas = 4;
557 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
558 sysinfo->cas = 5;
559 }
560 break;
561 }
562 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000563
Stefan Reinauer278534d2008-10-29 04:51:07 +0000564 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauer977ed2d2009-01-20 22:46:52 +0000565 printk_debug("Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000566 sysinfo->memory_frequency, sysinfo->cas);
567 } else {
568 die("Could not find common memory frequency and CAS\n");
569 }
570}
571
572static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
573{
574 int i;
575 int tRAS_time;
576 int tRAS_cycles;
577 int freq_multiplier = 0;
578
579 switch (sysinfo->memory_frequency) {
580 case 400: freq_multiplier = 0x14; break; /* 5ns */
581 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
582 case 667: freq_multiplier = 0x0c; break; /* 3ns */
583 }
584
585 tRAS_cycles = 4; /* 4 clocks minimum */
586 tRAS_time = tRAS_cycles * freq_multiplier;
587
588 for (i=0; i<2*DIMM_SOCKETS; i++) {
589 u8 reg8;
590
591 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
592 continue;
593
594 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
595 if (!reg8) {
596 die("Invalid tRAS value.\n");
597 }
598
599 while ((tRAS_time >> 2) < reg8) {
600 tRAS_time += freq_multiplier;
601 tRAS_cycles++;
602 }
603 }
604 if(tRAS_cycles > 0x18) {
605 die("DDR-II Module does not support this frequency (tRAS error)\n");
606 }
607
608 printk_debug("tRAS = %d cycles\n", tRAS_cycles);
609 sysinfo->tras = tRAS_cycles;
610}
611
612static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
613{
614 int i;
615 int tRP_time;
616 int tRP_cycles;
617 int freq_multiplier = 0;
618
619 switch (sysinfo->memory_frequency) {
620 case 400: freq_multiplier = 0x14; break; /* 5ns */
621 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
622 case 667: freq_multiplier = 0x0c; break; /* 3ns */
623 }
624
625 tRP_cycles = 2; /* 2 clocks minimum */
626 tRP_time = tRP_cycles * freq_multiplier;
627
628 for (i=0; i<2*DIMM_SOCKETS; i++) {
629 u8 reg8;
630
631 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
632 continue;
633
634 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_ROW_PRECHARGE_TIME);
635 if (!reg8) {
636 die("Invalid tRP value.\n");
637 }
638
639 while (tRP_time < reg8) {
640 tRP_time += freq_multiplier;
641 tRP_cycles++;
642 }
643 }
644
645 if(tRP_cycles > 6) {
646 die("DDR-II Module does not support this frequency (tRP error)\n");
647 }
648
649 printk_debug("tRP = %d cycles\n", tRP_cycles);
650 sysinfo->trp = tRP_cycles;
651}
652
653static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
654{
655 int i;
656 int tRCD_time;
657 int tRCD_cycles;
658 int freq_multiplier = 0;
659
660 switch (sysinfo->memory_frequency) {
661 case 400: freq_multiplier = 0x14; break; /* 5ns */
662 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
663 case 667: freq_multiplier = 0x0c; break; /* 3ns */
664 }
665
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000666 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000667 tRCD_time = tRCD_cycles * freq_multiplier;
668
669 for (i=0; i<2*DIMM_SOCKETS; i++) {
670 u8 reg8;
671
672 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
673 continue;
674
675 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_MIN_RAS_TO_CAS_DELAY);
676 if (!reg8) {
677 die("Invalid tRCD value.\n");
678 }
679
680 while (tRCD_time < reg8) {
681 tRCD_time += freq_multiplier;
682 tRCD_cycles++;
683 }
684 }
685 if(tRCD_cycles > 6) {
686 die("DDR-II Module does not support this frequency (tRCD error)\n");
687 }
688
689 printk_debug("tRCD = %d cycles\n", tRCD_cycles);
690 sysinfo->trcd = tRCD_cycles;
691}
692
693static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
694{
695 int i;
696 int tWR_time;
697 int tWR_cycles;
698 int freq_multiplier = 0;
699
700 switch (sysinfo->memory_frequency) {
701 case 400: freq_multiplier = 0x14; break; /* 5ns */
702 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
703 case 667: freq_multiplier = 0x0c; break; /* 3ns */
704 }
705
706 tWR_cycles = 2; /* 2 clocks minimum */
707 tWR_time = tWR_cycles * freq_multiplier;
708
709 for (i=0; i<2*DIMM_SOCKETS; i++) {
710 u8 reg8;
711
712 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
713 continue;
714
715 reg8 = spd_read_byte(DIMM_SPD_BASE + i, SPD_WRITE_RECOVERY_TIME);
716 if (!reg8) {
717 die("Invalid tWR value.\n");
718 }
719
720 while (tWR_time < reg8) {
721 tWR_time += freq_multiplier;
722 tWR_cycles++;
723 }
724 }
725 if(tWR_cycles > 5) {
726 die("DDR-II Module does not support this frequency (tWR error)\n");
727 }
728
729 printk_debug("tWR = %d cycles\n", tWR_cycles);
730 sysinfo->twr = tWR_cycles;
731}
732
733static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
734{
735 int i, index = 0;
736
737 const u8 tRFC_cycles[] = {
738 /* 75 105 127.5 */
739 15, 21, 26, /* DDR2-400 */
740 20, 28, 34, /* DDR2-533 */
741 25, 35, 43 /* DDR2-667 */
742 };
743
744 for (i=0; i<2*DIMM_SOCKETS; i++) {
745 u8 reg8;
746
747 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
748 continue;
749
750 reg8 = sysinfo->banksize[i*2];
751 switch (reg8) {
752 case 0x04: reg8 = 0; break;
753 case 0x08: reg8 = 1; break;
754 case 0x10: reg8 = 2; break;
755 case 0x20: reg8 = 3; break;
756 }
757
758 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
759 reg8++;
760
761 if (reg8 > 3) {
762 /* Can this happen? Go back to 127.5ns just to be sure
763 * we don't run out of the array. This may be wrong
764 */
765 printk_debug("DIMM %d is 1Gb x16.. Please report.\n", i);
766 reg8 = 3;
767 }
768
769 if (reg8 > index)
770 index = reg8;
771
772 }
773 index--;
774 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000775 case 667: index += 3; /* Fallthrough */
776 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000777 case 400: break;
778 }
779
780 sysinfo->trfc = tRFC_cycles[index];
781 printk_debug("tRFC = %d cycles\n", tRFC_cycles[index]);
782}
783
Stefan Reinauer278534d2008-10-29 04:51:07 +0000784static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
785{
786 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000787
Stefan Reinauer278534d2008-10-29 04:51:07 +0000788 sysinfo->refresh = 0;
789
790 for (i=0; i<2*DIMM_SOCKETS; i++) {
791 int refresh;
792
793 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
794 continue;
795
796 refresh = spd_read_byte(DIMM_SPD_BASE + i, SPD_REFRESH) & ~(1 << 7);
797
798 /* 15.6us */
799 if (!refresh)
800 continue;
801
802 /* Refresh is slower than 15.6us, use 15.6us */
803 if (refresh > 2)
804 continue;
805
806 if (refresh == 2) {
807 sysinfo->refresh = 1;
808 break;
809 }
810
811 die("DDR-II module has unsupported refresh value\n");
812 }
813 printk_debug("Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
814}
815
816static void sdram_verify_burst_length(struct sys_info * sysinfo)
817{
818 int i;
819
820 for (i=0; i<2*DIMM_SOCKETS; i++) {
821 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
822 continue;
823
824 if (!(spd_read_byte(DIMM_SPD_BASE + i, SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
825 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
826 }
827}
828
829static void sdram_program_dram_width(struct sys_info * sysinfo)
830{
831 u16 c0dramw=0, c1dramw=0;
832 int idx;
833
834 if (sysinfo->dual_channel)
835 idx = 2;
836 else
837 idx = 1;
838
839 switch (sysinfo->dimm[0]) {
840 case 0: c0dramw = 0x0000; break; /* x16DS */
841 case 1: c0dramw = 0x0001; break; /* x8DS */
842 case 2: c0dramw = 0x0000; break; /* x16SS */
843 case 3: c0dramw = 0x0005; break; /* x8DDS */
844 case 4: c0dramw = 0x0000; break; /* NC */
845 }
846
847 switch (sysinfo->dimm[idx]) {
848 case 0: c1dramw = 0x0000; break; /* x16DS */
849 case 1: c1dramw = 0x0010; break; /* x8DS */
850 case 2: c1dramw = 0x0000; break; /* x16SS */
851 case 3: c1dramw = 0x0050; break; /* x8DDS */
852 case 4: c1dramw = 0x0000; break; /* NC */
853 }
854
855 if ( !sdram_capabilities_dual_channel() ) {
856 /* Single Channel */
857 c0dramw |= c1dramw;
858 c1dramw = 0;
859 }
860
861 MCHBAR16(C0DRAMW) = c0dramw;
862 MCHBAR16(C1DRAMW) = c1dramw;
863}
864
865static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
866{
867 int i;
868
869 for (i=0; i<16; i++)
870 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
871}
872
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000873static const u32 dq2030[] = {
874 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
875 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
876 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
877 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
878};
879
880static const u32 dq2330[] = {
881 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
882 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
883 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
884 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
885};
886
887static const u32 cmd2710[] = {
888 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
889 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
890 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
891 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
892};
893
894static const u32 cmd3210[] = {
895 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
896 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
897 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
898 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
899};
900
901static const u32 clk2030[] = {
902 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
903 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
904 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
905 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
906};
907
908static const u32 ctl3215[] = {
909 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
910 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
911 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
912 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
913};
914
915static const u32 ctl3220[] = {
916 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
917 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
918 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
919 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
920};
921
922static const u32 nc[] = {
923 0x00000000, 0x00000000, 0x00000000, 0x00000000,
924 0x00000000, 0x00000000, 0x00000000, 0x00000000,
925 0x00000000, 0x00000000, 0x00000000, 0x00000000,
926 0x00000000, 0x00000000, 0x00000000, 0x00000000
927};
928
929enum {
930 DQ2030,
931 DQ2330,
932 CMD2710,
933 CMD3210,
934 CLK2030,
935 CTL3215,
936 CTL3220,
937 NC,
938};
939
940static const u8 dual_channel_slew_group_lookup[] = {
941 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
942 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
943 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
944 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
945 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
946
947 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
948 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
949 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
950 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
951 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
952
953 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
954 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
955 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
956 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
957 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
958
959 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
960 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
961 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
962 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
963 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
964
965 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
966 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
967 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
968 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
969};
970
971static const u8 single_channel_slew_group_lookup[] = {
972 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
973 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
974 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
975 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
976 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
977
978 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
979 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
980 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
981 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
982 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
983
984 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
985 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
986 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
987 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
988 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
989
990 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
991 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
992 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
993 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
994 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
995
996 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
997 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
998 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
999 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1000};
1001
1002static const u32 *slew_group_lookup(int dual_channel, int index)
1003{
1004 const u8 *slew_group;
1005 /* Dual Channel needs different tables. */
1006 if (dual_channel)
1007 slew_group = dual_channel_slew_group_lookup;
1008 else
1009 slew_group = single_channel_slew_group_lookup;
1010
1011 switch (slew_group[index]) {
1012 case DQ2030: return dq2030;
1013 case DQ2330: return dq2330;
1014 case CMD2710: return cmd2710;
1015 case CMD3210: return cmd3210;
1016 case CLK2030: return clk2030;
1017 case CTL3215: return ctl3215;
1018 case CTL3220: return ctl3220;
1019 case NC: return nc;
1020 }
1021
1022 return nc;
1023}
1024
1025#ifdef CHIPSET_I945GM
1026/* Strength multiplier tables */
1027static const u8 dual_channel_strength_multiplier[] = {
1028 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1029 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1030 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1031 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1032 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1033 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1034 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1035 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1036 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1037 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1038 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1039 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1040 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1041 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1042 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1043 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1044 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1045 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1046 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1047 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1048 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1049 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1050 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1051 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1052};
1053
1054static const u8 single_channel_strength_multiplier[] = {
1055 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1056 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1057 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1058 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1059 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1060 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1061 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1062 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1063 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1064 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1065 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1066 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1067 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1068 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1069 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1070 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1071 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1072 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1073 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1074 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1075 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1076 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1077 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1078 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1079};
1080#endif
1081#ifdef CHIPSET_I945GC
1082static const u8 dual_channel_strength_multiplier[] = {
1083 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1084 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1085 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1086 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1087 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1088 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1089 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1090 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1091 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1092 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1093 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1094 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1095 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1096 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1097 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1098 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1099 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1100 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1101 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1102 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1103 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1104 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1105 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1106 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1107};
1108
1109static const u8 single_channel_strength_multiplier[] = {
1110 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1111 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1112 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1113 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1114 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1115 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1116 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1117 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1118 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1119 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1120 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1121 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1122 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1123 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1124 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1125 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1126 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1127 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1128 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1129 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1130 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1131 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1132 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1133 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1134};
1135#endif
1136
Stefan Reinauer278534d2008-10-29 04:51:07 +00001137static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1138{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001139 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001140 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001141
1142 /* Set Strength Multipliers */
1143
1144 /* Dual Channel needs different tables. */
1145 if (sdram_capabilities_dual_channel()) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001146 printk_debug("Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001147 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001148 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001149 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1150 } else {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001151 printk_debug("Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001152 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001153 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001154 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1155 }
1156
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001157 printk_debug("Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001158
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001159 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1160 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1161 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1162 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1163 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1164 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1165 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1166 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001167
1168 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001169 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1170 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1171 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001172
Stefan Reinauer278534d2008-10-29 04:51:07 +00001173 sdram_write_slew_rates(G3SRPUT, ctl3220);
1174 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001175 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001176 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001177 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1178 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1179 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001180
1181 /* Channel 1 */
1182 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001183 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1184 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001185 } else {
1186 sdram_write_slew_rates(G7SRPUT, nc);
1187 sdram_write_slew_rates(G8SRPUT, nc);
1188 }
1189}
1190
1191static void sdram_enable_rcomp(void)
1192{
1193 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001194 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001195 udelay(300);
1196 reg32 = MCHBAR32(GBRCOMPCTL);
1197 reg32 &= ~(1 << 23);
1198 MCHBAR32(GBRCOMPCTL) = reg32;
1199}
1200
1201static void sdram_program_dll_timings(struct sys_info *sysinfo)
1202{
1203 u32 chan0dll = 0, chan1dll = 0;
1204 int i;
1205
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001206 printk_debug ("Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001207
Stefan Reinauer278534d2008-10-29 04:51:07 +00001208 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1209 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1210
1211 /* We drive both channels with the same speed */
1212 switch (sysinfo->memory_frequency) {
1213 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1214 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1215 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1216 }
1217
1218 for (i=0; i < 4; i++) {
1219 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1220 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1221 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1222 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1223 }
1224}
1225
1226static void sdram_force_rcomp(void)
1227{
1228 u32 reg32;
1229 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001230
Stefan Reinauer278534d2008-10-29 04:51:07 +00001231 reg32 = MCHBAR32(ODTC);
1232 reg32 |= (1 << 28);
1233 MCHBAR32(ODTC) = reg32;
1234
1235 reg32 = MCHBAR32(SMSRCTL);
1236 reg32 |= (1 << 0);
1237 MCHBAR32(SMSRCTL) = reg32;
1238
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001239 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001240 reg32 = MCHBAR32(GBRCOMPCTL);
1241 reg32 |= (1 << 8);
1242 MCHBAR32(GBRCOMPCTL) = reg32;
1243
1244 reg8 = i945_silicon_revision();
1245 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001246
Stefan Reinauer278534d2008-10-29 04:51:07 +00001247 reg32 = MCHBAR32(GBRCOMPCTL);
1248 reg32 |= (3 << 5);
1249 MCHBAR32(GBRCOMPCTL) = reg32;
1250 }
1251}
1252
1253static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1254{
1255 u8 reg8;
1256 u32 reg32;
1257
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001258 printk_debug ("Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001259 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001260 reg8 = MCHBAR8(C0HCTC);
1261 reg8 &= ~0x1f;
1262 reg8 |= ( 1 << 0);
1263 MCHBAR8(C0HCTC) = reg8;
1264
1265 reg8 = MCHBAR8(C1HCTC);
1266 reg8 &= ~0x1f;
1267 reg8 |= ( 1 << 0);
1268 MCHBAR8(C1HCTC) = reg8;
1269
Stefan Reinauer278534d2008-10-29 04:51:07 +00001270 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1271 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1272
1273 MCHBAR8(C0WDLLCMC) = 0;
1274 MCHBAR8(C1WDLLCMC) = 0;
1275
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001276 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001277 sdram_program_dram_width(sysinfo);
1278
1279 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1280
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001281 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001282 reg32 = MCHBAR32(GBRCOMPCTL);
1283 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1284 reg32 |= (3 << 27) | (3 << 0);
1285 MCHBAR32(GBRCOMPCTL) = reg32;
1286
1287 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1288
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001289 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001290 sdram_program_dll_timings(sysinfo);
1291
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001292 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001293 sdram_force_rcomp();
1294}
1295
1296static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1297{
1298 u32 reg32;
1299
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001300 printk_debug ("Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001301
Stefan Reinauer278534d2008-10-29 04:51:07 +00001302 reg32 = MCHBAR32(RCVENMT);
1303 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001304 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001305
1306 reg32 |= (1 << 11) | (1 << 9);
1307 MCHBAR32(RCVENMT) = reg32;
1308
1309 reg32 = MCHBAR32(DRTST);
1310 reg32 |= (1 << 3) | (1 << 2);
1311 MCHBAR32(DRTST) = reg32;
1312
1313 reg32 = MCHBAR32(DRTST);
1314 reg32 |= (1 << 6) | (1 << 4);
1315 MCHBAR32(DRTST) = reg32;
1316
1317 asm volatile ("nop; nop;");
1318
1319 reg32 = MCHBAR32(DRTST);
1320
1321 /* Is channel 0 populated? */
1322 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1323 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1324 reg32 |= (1 << 7) | (1 << 5);
1325 else
1326 reg32 |= (1 << 31);
1327
1328 /* Is channel 1 populated? */
1329 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1330 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1331 reg32 |= (1 << 9) | (1 << 8);
1332 else
1333 reg32 |= (1 << 30);
1334
1335 MCHBAR32(DRTST) = reg32;
1336
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001337 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001338 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1339 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1340 reg32 = MCHBAR32(C0DRC1);
1341 reg32 |= (1 << 8);
1342 MCHBAR32(C0DRC1) = reg32;
1343 }
1344 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1345 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1346 reg32 = MCHBAR32(C1DRC1);
1347 reg32 |= (1 << 8);
1348 MCHBAR32(C1DRC1) = reg32;
1349 }
1350}
1351
1352struct dimm_size {
1353 unsigned long side1;
1354 unsigned long side2;
1355};
1356
1357static struct dimm_size sdram_get_dimm_size(u16 device)
1358{
1359 /* Calculate the log base 2 size of a DIMM in bits */
1360 struct dimm_size sz;
1361 int value, low, rows, columns;
1362
1363 sz.side1 = 0;
1364 sz.side2 = 0;
1365
1366 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1367 if (rows < 0) goto hw_err;
1368 if ((rows & 0xf) == 0) goto val_err;
1369 sz.side1 += rows & 0xf;
1370
1371 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1372 if (columns < 0) goto hw_err;
1373 if ((columns & 0xf) == 0) goto val_err;
1374 sz.side1 += columns & 0xf;
1375
1376 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1377 if (value < 0) goto hw_err;
1378 if ((value & 0xff) == 0) goto val_err;
1379 sz.side1 += log2(value & 0xff);
1380
1381 /* Get the module data width and convert it to a power of two */
1382 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1383 if (value < 0) goto hw_err;
1384 value &= 0xff;
1385 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001386
Stefan Reinauer278534d2008-10-29 04:51:07 +00001387 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1388 if (low < 0) goto hw_err;
1389 value = value | (low & 0xff);
1390 if ((value != 72) && (value != 64)) goto val_err;
1391 sz.side1 += log2(value);
1392
1393 /* side 2 */
1394 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1395
1396 if (value < 0) goto hw_err;
1397 value &= 7;
1398 value++;
1399 if (value == 1) goto out;
1400 if (value != 2) goto val_err;
1401
1402 /* Start with the symmetrical case */
1403 sz.side2 = sz.side1;
1404
1405 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1406
1407 /* Don't die here, I have not come across any of these to test what
1408 * actually happens.
1409 */
1410 printk_err("Assymetric DIMMs are not supported by this chipset\n");
1411
1412 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1413 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1414
1415 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1416 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1417
1418 goto out;
1419
1420 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001421 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001422 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001423 /* If a hardware error occurs the spd rom probably does not exist.
1424 * In this case report that there is no memory
1425 */
1426 sz.side1 = 0;
1427 sz.side2 = 0;
1428 out:
1429 return sz;
1430}
1431
1432static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1433{
1434 int i;
1435
1436 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1437 struct dimm_size sz;
1438
1439 sysinfo->banksize[i * 2] = 0;
1440 sysinfo->banksize[(i * 2) + 1] = 0;
1441
1442 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1443 continue;
1444
1445 sz = sdram_get_dimm_size(DIMM_SPD_BASE + i);
1446
1447 sysinfo->banks[i] = spd_read_byte(DIMM_SPD_BASE + i, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1448
1449 if (sz.side1 < 30)
1450 die("DDR-II rank size smaller than 128MB is not supported.\n");
1451
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001452 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001453
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001454 printk_debug("DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
1455
Stefan Reinauer278534d2008-10-29 04:51:07 +00001456 if (!sz.side2)
1457 continue;
1458
1459 /* If there is a second side, it has to have at least 128M, too */
1460 if (sz.side2 < 30)
1461 die("DDR-II rank size smaller than 128MB is not supported.\n");
1462
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001463 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001464
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001465 printk_debug("DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001466 }
1467}
1468
1469static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1470{
1471 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001472 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001473
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001474 printk_debug ("Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001475
1476 cum0 = 0;
1477 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001478 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001479 MCHBAR8(C0DRB0+i) = cum0;
1480 }
1481
1482 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1483 cum1 = cum0;
1484
1485 /* Exception: Interleaved starts from the beginning */
1486 if (sysinfo->interleaved)
1487 cum1 = 0;
1488
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001489#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001490 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1491 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1492 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1493 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001494#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001495
1496 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001497 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001498 MCHBAR8(C1DRB0+i) = cum1;
1499 }
1500
1501 /* Set TOLUD Top Of Low Usable DRAM */
1502 if (sysinfo->interleaved)
1503 tolud = (cum0 + cum1) << 1;
1504 else
1505 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001506
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001507 /* The TOM register has a different format */
1508 tom = tolud >> 3;
1509
1510 /* Limit the value of TOLUD to leave some space for PCI memory. */
1511 if (tolud > 0xd0)
1512 tolud = 0xd0; /* 3.25GB : 0.75GB */
1513
1514 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1515
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001516 printk_debug("C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1517 printk_debug("C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001518 printk_debug("TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001519
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001520 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001521
1522 return 0;
1523}
1524
Stefan Reinauer278534d2008-10-29 04:51:07 +00001525static int sdram_set_row_attributes(struct sys_info *sysinfo)
1526{
1527 int i, value;
1528 u16 dra0=0, dra1=0, dra = 0;
1529
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001530 printk_debug ("Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001531 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1532 u16 device;
1533 u8 columnsrows;
1534
1535 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1536 continue;
1537 }
1538
1539 device = DIMM_SPD_BASE + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001540
1541 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1542 columnsrows = (value & 0x0f);
1543
1544 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1545 columnsrows |= (value & 0xf) << 4;
1546
1547 switch (columnsrows) {
1548 case 0x9d: dra = 2; break;
1549 case 0xad: dra = 3; break;
1550 case 0xbd: dra = 4; break;
1551 case 0xae: dra = 3; break;
1552 case 0xbe: dra = 4; break;
1553 default: die("Unsupported Rows/Columns. (DRA)");
1554 }
1555
1556 /* Double Sided DIMMs? */
1557 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1558 dra = (dra << 4) | dra;
1559 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001560
Stefan Reinauer278534d2008-10-29 04:51:07 +00001561 if (i < DIMM_SOCKETS)
1562 dra0 |= (dra << (i*8));
1563 else
1564 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1565 }
1566
1567 MCHBAR16(C0DRA0) = dra0;
1568 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001569
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001570 printk_debug("C0DRA = 0x%04x\n", dra0);
1571 printk_debug("C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001572
1573 return 0;
1574}
1575
1576static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1577{
1578 u32 off32;
1579 int i;
1580
1581 MCHBAR16(C1BNKARC) &= 0xff00;
1582 MCHBAR16(C0BNKARC) &= 0xff00;
1583
1584 off32 = C0BNKARC;
1585 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1586 /* Switch to second channel */
1587 if (i == DIMM_SOCKETS)
1588 off32 = C1BNKARC;
1589
1590 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1591 continue;
1592
1593 if (sysinfo->banks[i] != 8)
1594 continue;
1595
1596 printk_spew("DIMM%d has 8 banks.\n");
1597
1598 if (i & 1)
1599 MCHBAR16(off32) |= 0x50;
1600 else
1601 MCHBAR16(off32) |= 0x05;
1602 }
1603}
1604
1605#define REFRESH_7_8US 1
1606#define REFRESH_15_6US 0
1607static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1608{
1609 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001610
Stefan Reinauer278534d2008-10-29 04:51:07 +00001611 if (sysinfo->refresh == REFRESH_7_8US) {
1612 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1613 } else {
1614 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1615 }
1616
1617 MCHBAR32(C0DRC0) &= ~(7 << 8);
1618 MCHBAR32(C0DRC0) |= reg32;
1619
1620 MCHBAR32(C1DRC0) &= ~(7 << 8);
1621 MCHBAR32(C1DRC0) |= reg32;
1622}
1623
1624static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1625{
1626 u32 reg32;
1627 int i;
1628
1629 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001630
Stefan Reinauer278534d2008-10-29 04:51:07 +00001631 for (i=0; i < 4; i++) {
1632 if (sysinfo->banksize[i] == 0) {
1633 reg32 |= (1 << (16 + i));
1634 }
1635 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001636
Stefan Reinauer278534d2008-10-29 04:51:07 +00001637 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001638
Stefan Reinauer278534d2008-10-29 04:51:07 +00001639 reg32 |= (1 << 11);
1640 MCHBAR32(C0DRC1) = reg32;
1641
1642 /* Do we have to do this if we're in Single Channel Mode? */
1643 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001644
Stefan Reinauer278534d2008-10-29 04:51:07 +00001645 for (i=4; i < 8; i++) {
1646 if (sysinfo->banksize[i] == 0) {
1647 reg32 |= (1 << (12 + i));
1648 }
1649 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001650
Stefan Reinauer278534d2008-10-29 04:51:07 +00001651 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001652
Stefan Reinauer278534d2008-10-29 04:51:07 +00001653 reg32 |= (1 << 11);
1654 MCHBAR32(C1DRC1) = reg32;
1655}
1656
1657static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1658{
1659 u32 reg32;
1660 int i;
1661
1662 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001663
Stefan Reinauer278534d2008-10-29 04:51:07 +00001664 for (i=0; i < 4; i++) {
1665 if (sysinfo->banksize[i] == 0) {
1666 reg32 |= (1 << (24 + i));
1667 }
1668 }
1669 MCHBAR32(C0DRC2) = reg32;
1670
1671 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001672
Stefan Reinauer278534d2008-10-29 04:51:07 +00001673 for (i=4; i < 8; i++) {
1674 if (sysinfo->banksize[i] == 0) {
1675 reg32 |= (1 << (20 + i));
1676 }
1677 }
1678 MCHBAR32(C1DRC2) = reg32;
1679}
1680
1681static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1682{
1683 u32 reg32, off32;
1684 u32 tWTR;
1685 u32 temp_drt;
1686 int i, page_size;
1687
1688 static const u8 const drt0_table[] = {
1689 /* CL 3, 4, 5 */
1690 3, 4, 5, /* FSB533/400, DDR533/400 */
1691 4, 5, 6, /* FSB667, DDR533/400 */
1692 4, 5, 6, /* FSB667, DDR667 */
1693 };
1694
1695 static const u8 const cas_table[] = {
1696 2, 1, 0, 3
1697 };
1698
1699 reg32 = MCHBAR32(C0DRC0);
1700 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001701 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001702 MCHBAR32(C0DRC0) = reg32;
1703
1704 reg32 = MCHBAR32(C1DRC0);
1705 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001706 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001707 MCHBAR32(C1DRC0) = reg32;
1708
1709 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1710 SYSINFO_DIMM_NOT_POPULATED) {
1711 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001712 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001713 MCHBAR32(C0DRC0) = reg32;
1714 }
1715
1716 sdram_program_refresh_rate(sysinfo);
1717
1718 sdram_program_cke_tristate(sysinfo);
1719
1720 sdram_program_odt_tristate(sysinfo);
1721
1722 /* Calculate DRT0 */
1723
1724 temp_drt = 0;
1725
1726 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1727 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1728 temp_drt |= (reg32 << 28);
1729
1730 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1731 reg32 += sysinfo->trp;
1732 temp_drt |= (reg32 << 4);
1733
1734 if (sysinfo->memory_frequency == 667) {
1735 tWTR = 3; /* 667MHz */
1736 } else {
1737 tWTR = 2; /* 400 and 533 */
1738 }
1739
1740 /* B2B Write to Read Command Spacing */
1741 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1742 temp_drt |= (reg32 << 24);
1743
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001744 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001745 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1746
1747 /* Program Write Auto Precharge to Activate */
1748 off32 = 0;
1749 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1750 off32 += 3;
1751 }
1752 if (sysinfo->memory_frequency == 667) {
1753 off32 += 3;
1754 }
1755 off32 += sysinfo->cas - 3;
1756 reg32 = drt0_table[off32];
1757 temp_drt |= (reg32 << 11);
1758
1759 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001760
Stefan Reinauer278534d2008-10-29 04:51:07 +00001761 temp_drt |= (8 << 0);
1762
1763 MCHBAR32(C0DRT0) = temp_drt;
1764 MCHBAR32(C1DRT0) = temp_drt;
1765
1766 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001767
Stefan Reinauer278534d2008-10-29 04:51:07 +00001768 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1769
1770 /* DRAM RASB Precharge */
1771 temp_drt |= (sysinfo->trp - 2) << 0;
1772
1773 /* DRAM RASB to CASB Delay */
1774 temp_drt |= (sysinfo->trcd - 2) << 4;
1775
1776 /* CASB Latency */
1777 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1778
1779 /* Refresh Cycle Time */
1780 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001781
Stefan Reinauer278534d2008-10-29 04:51:07 +00001782 /* Pre-All to Activate Delay */
1783 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001784
Stefan Reinauer278534d2008-10-29 04:51:07 +00001785 /* Precharge to Precharge Delay stays at 1 clock */
1786 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001787
Stefan Reinauer278534d2008-10-29 04:51:07 +00001788 /* Activate to Precharge Delay */
1789 temp_drt |= (sysinfo->tras << 19);
1790
1791 /* Read to Precharge (tRTP) */
1792 if (sysinfo->memory_frequency == 667) {
1793 temp_drt |= (1 << 28);
1794 } else {
1795 temp_drt |= (0 << 28);
1796 }
1797
1798 /* Determine page size */
1799 reg32 = 0;
1800 page_size = 1; /* Default: 1k pagesize */
1801 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1802 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1803 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1804 page_size = 2; /* 2k pagesize */
1805 }
1806
1807 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1808 reg32 = 1;
1809 }
1810 if (sysinfo->memory_frequency == 667) {
1811 reg32 = page_size;
1812 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001813
Stefan Reinauer278534d2008-10-29 04:51:07 +00001814 temp_drt |= (reg32 << 30);
1815
1816 MCHBAR32(C0DRT1) = temp_drt;
1817 MCHBAR32(C1DRT1) = temp_drt;
1818
1819 /* Program DRT2 */
1820 reg32 = MCHBAR32(C0DRT2);
1821 reg32 &= ~(1 << 8);
1822 MCHBAR32(C0DRT2) = reg32;
1823
1824 reg32 = MCHBAR32(C1DRT2);
1825 reg32 &= ~(1 << 8);
1826 MCHBAR32(C1DRT2) = reg32;
1827
1828 /* Calculate DRT3 */
1829 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1830
1831 /* Get old tRFC value */
1832 reg32 = MCHBAR32(C0DRT1) >> 10;
1833 reg32 &= 0x3f;
1834
1835 /* 788nS - tRFC */
1836 switch (sysinfo->memory_frequency) {
1837 case 400: /* 5nS */
1838 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1839 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1840 break;
1841 case 533: /* 3.75nS */
1842 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1843 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1844 break;
1845 case 667: /* 3nS */
1846 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1847 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1848 break;
1849 }
1850
1851 temp_drt |= reg32;
1852
1853 MCHBAR32(C0DRT3) = temp_drt;
1854 MCHBAR32(C1DRT3) = temp_drt;
1855}
1856
1857static void sdram_set_channel_mode(struct sys_info *sysinfo)
1858{
1859 u32 reg32;
1860
1861 printk_debug("Setting mode of operation for memory channels...");
1862
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001863 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001864 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1865 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1866 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1867 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1868 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001869 sysinfo->interleaved = 1;
1870 } else {
1871 sysinfo->interleaved = 0;
1872 }
1873
1874 reg32 = MCHBAR32(DCC);
1875 reg32 &= ~(7 << 0);
1876
1877 if(sysinfo->interleaved) {
1878 /* Dual Channel Interleaved */
1879 printk_debug("Dual Channel Interleaved.\n");
1880 reg32 |= (1 << 1);
1881 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1882 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1883 /* Channel 1 only */
1884 printk_debug("Single Channel 1 only.\n");
1885 reg32 |= (1 << 2);
1886 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1887 SYSINFO_DIMM_NOT_POPULATED) {
1888 /* Dual Channel Assymetric */
1889 printk_debug("Dual Channel Assymetric.\n");
1890 reg32 |= (1 << 0);
1891 } else {
1892 /* All bits 0 means Single Channel 0 operation */
1893 printk_debug("Single Channel 0 only.\n");
1894 }
1895
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001896 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001897
1898 MCHBAR32(DCC) = reg32;
1899
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001900 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001901}
1902
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001903static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001904{
1905 volatile u16 reg16;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001906
1907 MCHBAR32(PLLMON) = 0x80800000;
1908
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001909 sysinfo->fsb_frequency = fsbclk();
1910 if (sysinfo->fsb_frequency == -1)
1911 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001912
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001913 /* Program CPCTL according to FSB speed */
1914 /* Only write the lower byte */
1915 switch (sysinfo->fsb_frequency) {
1916 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1917 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1918 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1919 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001920
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001921 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001922
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001923 reg16 = MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001924}
1925
1926static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1927{
1928 u8 reg8;
1929 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001930 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001931
1932#define CRCLK_166MHz 0x00
1933#define CRCLK_200MHz 0x01
1934#define CRCLK_250MHz 0x03
1935#define CRCLK_400MHz 0x05
1936
1937#define CDCLK_200MHz 0x00
1938#define CDCLK_320MHz 0x40
1939
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001940#define VOLTAGE_1_05 0x00
1941#define VOLTAGE_1_50 0x01
1942
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001943 printk_debug ("Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001944
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001945 printk_debug("FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001946
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001947 voltage = VOLTAGE_1_05;
1948 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1949 voltage = VOLTAGE_1_50;
1950 printk_debug("Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001951
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001952 /* Gate graphics hardware for frequency change */
1953 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
1954 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
1955 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001956
1957 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001958 reg8 = sdram_capabilities_core_frequencies();
1959
Stefan Reinauer278534d2008-10-29 04:51:07 +00001960 freq = CRCLK_250MHz;
1961 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001962 case GFX_FREQUENCY_CAP_ALL:
1963 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001964 freq = CRCLK_250MHz;
1965 else
1966 freq = CRCLK_400MHz;
1967 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001968 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
1969 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
1970 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001971 }
1972
1973 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001974 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001975 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
1976 if (reg8==2)
1977 freq = CRCLK_166MHz;
1978 }
1979
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001980 printk_debug("Render: ");
1981 switch (freq) {
1982 case CRCLK_166MHz: printk_debug("166Mhz"); break;
1983 case CRCLK_200MHz: printk_debug("200Mhz"); break;
1984 case CRCLK_250MHz: printk_debug("250Mhz"); break;
1985 case CRCLK_400MHz: printk_debug("400Mhz"); break;
1986 }
1987
Stefan Reinauer278534d2008-10-29 04:51:07 +00001988 if (i945_silicon_revision() == 0) {
1989 sysinfo->mvco4x = 1;
1990 } else {
1991 sysinfo->mvco4x = 0;
1992 }
1993
Stefan Reinauer278534d2008-10-29 04:51:07 +00001994 second_vco = 0;
1995
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001996 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001997 second_vco = 1;
1998 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
1999 u16 mem = sysinfo->memory_frequency;
2000 u16 fsb = sysinfo->fsb_frequency;
2001
2002 if ( (fsb == 667 && mem == 533) ||
2003 (fsb == 533 && mem == 533) ||
2004 (fsb == 533 && mem == 400)) {
2005 second_vco = 1;
2006 }
2007
2008 if (fsb == 667 && mem == 533)
2009 sysinfo->mvco4x = 1;
2010 }
2011
2012 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002013 sysinfo->clkcfg_bit7=1;
2014 } else {
2015 sysinfo->clkcfg_bit7=0;
2016 }
2017
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002018 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002019 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2020 reg16 &= ~( (7 << 0) | (1 << 13) );
2021 reg16 |= freq;
2022 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2023
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002024 /* Graphics Core Display Clock */
2025 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2026 reg8 &= ~( (1<<7) | (7<<4) );
2027
2028 if (voltage == VOLTAGE_1_05) {
2029 reg8 |= CDCLK_200MHz;
2030 printk_debug(" Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002031 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002032 reg8 |= CDCLK_320MHz;
2033 printk_debug(" Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002034 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002035 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002036
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002037 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002038
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002039 reg8 |= (1<<3) | (1<<1);
2040 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2041
2042 reg8 |= 0x0f;
2043 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2044
2045 /* Ungate core render and display clocks */
2046 reg8 &= 0xf0;
2047 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002048}
2049
2050static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2051{
2052 u32 clkcfg;
2053 u8 reg8;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002054 u8 offset = 0;
2055#ifdef CHIPSET_I945GM
2056 offset++;
2057#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002058
2059 printk_debug ("Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002060
Stefan Reinauer278534d2008-10-29 04:51:07 +00002061 clkcfg = MCHBAR32(CLKCFG);
2062
2063 printk_debug("CLKCFG=0x%08x, ", clkcfg);
2064
2065 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2066
2067 if (sysinfo->mvco4x) {
2068 printk_debug("MVCO 4x, ");
2069 clkcfg &= ~(1 << 12);
2070 }
2071
2072 if (sysinfo->clkcfg_bit7) {
2073 printk_debug("second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002074
Stefan Reinauer278534d2008-10-29 04:51:07 +00002075 clkcfg |= (1 << 7);
2076 }
2077
2078 switch (sysinfo->memory_frequency) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002079 case 400: clkcfg |= ((1+offset) << 4); break;
2080 case 533: clkcfg |= ((2+offset) << 4); break;
2081 case 667: clkcfg |= ((3+offset) << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002082 default: die("Target Memory Frequency Error");
2083 }
2084
2085 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002086 printk_debug ("ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002087 return;
2088 }
2089
2090 MCHBAR32(CLKCFG) = clkcfg;
2091
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002092 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002093 * cache before we execute it.
2094 */
2095 goto cache_code;
2096vco_update:
2097 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2098 reg8 &= ~(1 << 7);
2099 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2100
Stefan Reinauer278534d2008-10-29 04:51:07 +00002101 clkcfg &= ~(1 << 10);
2102 MCHBAR32(CLKCFG) = clkcfg;
2103 clkcfg |= (1 << 10);
2104 MCHBAR32(CLKCFG) = clkcfg;
2105
Stefan Reinauer278534d2008-10-29 04:51:07 +00002106 __asm__ __volatile__ (
2107 " movl $0x100, %%ecx\n"
2108 "delay_update:\n"
2109 " nop\n"
2110 " nop\n"
2111 " nop\n"
2112 " nop\n"
2113 " loop delay_update\n"
2114 : /* No outputs */
2115 : /* No inputs */
2116 : "%ecx"
2117 );
2118
Stefan Reinauer278534d2008-10-29 04:51:07 +00002119 clkcfg &= ~(1 << 10);
2120 MCHBAR32(CLKCFG) = clkcfg;
2121
2122 goto out;
2123cache_code:
2124 goto vco_update;
2125out:
2126
2127 printk_debug("CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002128 printk_debug ("ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002129}
2130
2131static void sdram_program_clock_crossing(void)
2132{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002133 int idx = 0;
2134
2135 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002136 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002137 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002138#ifdef CHIPSET_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002139 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002140 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002141 0xffffffff, 0xffffffff, /* nonexistant */
2142 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002143
Stefan Reinauer278534d2008-10-29 04:51:07 +00002144 0x08040120, 0x00000000, /* DDR400 FSB533 */
2145 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002146 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002147
2148 0x04020120, 0x00000010, /* DDR400 FSB667 */
2149 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002150 0x00100401, 0x00000000, /* DDR667 FSB667 */
2151
2152 0xffffffff, 0xffffffff, /* nonexistant */
2153 0xffffffff, 0xffffffff, /* nonexistant */
2154 0xffffffff, 0xffffffff, /* nonexistant */
2155
2156 0xffffffff, 0xffffffff, /* nonexistant */
2157 0xffffffff, 0xffffffff, /* nonexistant */
2158 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002159 };
2160
2161 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002162 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002163 0xffffffff, 0xffffffff, /* nonexistant */
2164 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002165
Stefan Reinauer278534d2008-10-29 04:51:07 +00002166 0x00060108, 0x00000000, /* DDR400 FSB533 */
2167 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002168 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002169
2170 0x00040318, 0x00000000, /* DDR400 FSB667 */
2171 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002172 0x02010804, 0x00000000, /* DDR667 FSB667 */
2173
2174 0xffffffff, 0xffffffff, /* nonexistant */
2175 0xffffffff, 0xffffffff, /* nonexistant */
2176 0xffffffff, 0xffffffff, /* nonexistant */
2177
2178 0xffffffff, 0xffffffff, /* nonexistant */
2179 0xffffffff, 0xffffffff, /* nonexistant */
2180 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002181 };
2182
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002183#endif
2184#ifdef CHIPSET_I945GC
2185 /* i945 G/P */
2186 static const u32 data_clock_crossing[] = {
2187 0xffffffff, 0xffffffff, /* nonexistant */
2188 0xffffffff, 0xffffffff, /* nonexistant */
2189 0xffffffff, 0xffffffff, /* nonexistant */
2190
2191 0x10080201, 0x00000000, /* DDR400 FSB533 */
2192 0x00100401, 0x00000000, /* DDR533 FSB533 */
2193 0xffffffff, 0xffffffff, /* nonexistant */
2194
2195 0xffffffff, 0xffffffff, /* nonexistant */
2196 0xffffffff, 0xffffffff, /* nonexistant */
2197 0xffffffff, 0xffffffff, /* nonexistant */
2198
2199 0x04020108, 0x00000000, /* DDR400 FSB800 */
2200 0x00020108, 0x00000000, /* DDR533 FSB800 */
2201 0x00080201, 0x00000000, /* DDR667 FSB800 */
2202
2203 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2204 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2205 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2206 };
2207
2208 static const u32 command_clock_crossing[] = {
2209 0xffffffff, 0xffffffff, /* nonexistant */
2210 0xffffffff, 0xffffffff, /* nonexistant */
2211 0xffffffff, 0xffffffff, /* nonexistant */
2212
2213 0x00010800, 0x00000402, /* DDR400 FSB533 */
2214 0x01000400, 0x00000200, /* DDR533 FSB533 */
2215 0xffffffff, 0xffffffff, /* nonexistant */
2216
2217 0xffffffff, 0xffffffff, /* nonexistant */
2218 0xffffffff, 0xffffffff, /* nonexistant */
2219 0xffffffff, 0xffffffff, /* nonexistant */
2220
2221 0x02010804, 0x00000000, /* DDR400 FSB800 */
2222 0x00010402, 0x00000000, /* DDR533 FSB800 */
2223 0x04020180, 0x00000008, /* DDR667 FSB800 */
2224
2225 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2226 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2227 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2228 };
2229#endif
2230
Stefan Reinauer278534d2008-10-29 04:51:07 +00002231 printk_debug("Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002232
2233 printk_debug("MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002234 switch (memclk()) {
2235 case 400: printk_debug("400"); idx += 0; break;
2236 case 533: printk_debug("533"); idx += 2; break;
2237 case 667: printk_debug("667"); idx += 4; break;
2238 default: printk_debug("RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002239 }
2240
2241 printk_debug(" FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002242 switch (fsbclk()) {
2243 case 400: printk_debug("400"); idx += 0; break;
2244 case 533: printk_debug("533"); idx += 6; break;
2245 case 667: printk_debug("667"); idx += 12; break;
2246 case 800: printk_debug("800"); idx += 18; break;
2247 case 1066: printk_debug("1066"); idx += 24; break;
2248 default: printk_debug("RSVD %x\n", fsbclk()); return;
2249 }
2250
2251 if (command_clock_crossing[idx]==0xffffffff) {
2252 printk_debug("Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002253 }
2254
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002255 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2256 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2257
Stefan Reinauer278534d2008-10-29 04:51:07 +00002258 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2259 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2260 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2261 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2262
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002263 printk_debug("... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002264}
2265
2266static void sdram_disable_fast_dispatch(void)
2267{
2268 u32 reg32;
2269
2270 reg32 = MCHBAR32(FSBPMC3);
2271 reg32 |= (1 << 1);
2272 MCHBAR32(FSBPMC3) = reg32;
2273
2274 reg32 = MCHBAR32(SBTEST);
2275 reg32 |= (3 << 1);
2276 MCHBAR32(SBTEST) = reg32;
2277}
2278
2279static void sdram_pre_jedec_initialization(void)
2280{
2281 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002282
Stefan Reinauer278534d2008-10-29 04:51:07 +00002283 reg32 = MCHBAR32(WCC);
2284 reg32 &= 0x113ff3ff;
2285 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2286 MCHBAR32(WCC) = reg32;
2287
2288 MCHBAR32(SMVREFC) |= (1 << 6);
2289
2290 MCHBAR32(MMARB0) &= ~(3 << 17);
2291 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2292
2293 MCHBAR32(MMARB1) &= ~(7 << 8);
2294 MCHBAR32(MMARB1) |= (3 << 8);
2295
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002296 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002297 MCHBAR32(C0AIT) = 0x000006c4;
2298 MCHBAR32(C0AIT+4) = 0x871a066d;
2299
2300 MCHBAR32(C1AIT) = 0x000006c4;
2301 MCHBAR32(C1AIT+4) = 0x871a066d;
2302}
2303
2304#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2305#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2306#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2307#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2308#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2309#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2310#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2311#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2312
2313static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2314{
2315 u32 chan0 = 0, chan1 = 0;
2316 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2317
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002318 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002319 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002320 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002321 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2322 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2323 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2324
2325 if (sdram_capabilities_enhanced_addressing_xor()) {
2326 if (!sysinfo->interleaved) {
2327 /* Single Channel & Dual Channel Assymetric */
2328 if (chan0_populated) {
2329 if (chan0_dualsided) {
2330 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2331 } else {
2332 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2333 }
2334 }
2335 if (chan1_populated) {
2336 if (chan1_dualsided) {
2337 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2338 } else {
2339 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2340 }
2341 }
2342 } else {
2343 /* Interleaved has always both channels populated */
2344 if (chan0_dualsided) {
2345 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2346 } else {
2347 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2348 }
2349
2350 if (chan1_dualsided) {
2351 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2352 } else {
2353 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2354 }
2355 }
2356 } else {
2357 if (!sysinfo->interleaved) {
2358 /* Single Channel & Dual Channel Assymetric */
2359 if (chan0_populated) {
2360 if (chan0_dualsided) {
2361 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2362 } else {
2363 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2364 }
2365 }
2366 if (chan1_populated) {
2367 if (chan1_dualsided) {
2368 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2369 } else {
2370 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2371 }
2372 }
2373 } else {
2374 /* Interleaved has always both channels populated */
2375 if (chan0_dualsided) {
2376 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2377 } else {
2378 chan0 = EA_DUALCHANNEL_BANK_MODE;
2379 }
2380
2381 if (chan1_dualsided) {
2382 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2383 } else {
2384 chan1 = EA_DUALCHANNEL_BANK_MODE;
2385 }
2386 }
2387 }
2388
2389 MCHBAR32(C0DRC1) &= 0x00ffffff;
2390 MCHBAR32(C0DRC1) |= chan0;
2391 MCHBAR32(C1DRC1) &= 0x00ffffff;
2392 MCHBAR32(C1DRC1) |= chan1;
2393}
2394
2395static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2396{
2397 u32 reg32;
2398
2399 /* Enable Channel XORing for Dual Channel Interleave */
2400 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002401
Stefan Reinauer278534d2008-10-29 04:51:07 +00002402 reg32 = MCHBAR32(DCC);
2403#if CHANNEL_XOR_RANDOMIZATION
2404 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002405 reg32 |= (1 << 9);
2406#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002407 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002408#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002409 MCHBAR32(DCC) = reg32;
2410 }
2411
2412 /* DRAM mode optimizations */
2413 sdram_enhanced_addressing_mode(sysinfo);
2414
2415 reg32 = MCHBAR32(FSBPMC3);
2416 reg32 &= ~(1 << 1);
2417 MCHBAR32(FSBPMC3) = reg32;
2418
2419 reg32 = MCHBAR32(SBTEST);
2420 reg32 &= ~(1 << 2);
2421 MCHBAR32(SBTEST) = reg32;
2422
2423 reg32 = MCHBAR32(SBOCC);
2424 reg32 &= 0xffbdb6ff;
2425 reg32 |= (0xbdb6 << 8) | (1 << 0);
2426 MCHBAR32(SBOCC) = reg32;
2427}
2428
2429static void sdram_power_management(struct sys_info *sysinfo)
2430{
2431 u8 reg8;
2432 u16 reg16;
2433 u32 reg32;
2434 int integrated_graphics = 1;
2435 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002436
Stefan Reinauer278534d2008-10-29 04:51:07 +00002437 reg32 = MCHBAR32(C0DRT2);
2438 reg32 &= 0xffffff00;
2439 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002440 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002441 MCHBAR32(C0DRT2) = reg32;
2442
2443 reg32 = MCHBAR32(C1DRT2);
2444 reg32 &= 0xffffff00;
2445 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002446 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002447 MCHBAR32(C1DRT2) = reg32;
2448
2449 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002450
2451 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002452 MCHBAR32(C0DRC1) = reg32;
2453
2454 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002455
2456 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002457 MCHBAR32(C1DRC1) = reg32;
2458
2459 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002460 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2461 u16 peg_bits = (1 << 5) | (1 << 0);
2462
2463 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002464 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002465 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2466 u16 peg_bits = (1 << 5) | (1 << 0);
2467
Stefan Reinauer278534d2008-10-29 04:51:07 +00002468 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002469 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002470 }
2471
2472 reg16 = MCHBAR16(UPMC2);
2473 reg16 &= 0xfc00;
2474 reg16 |= 0x0100;
2475 MCHBAR16(UPMC2) = reg16;
2476
2477 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002478
Stefan Reinauer278534d2008-10-29 04:51:07 +00002479 for (i=0; i<5; i++) {
2480 MCHBAR32(UPMC3) &= ~(1 << 16);
2481 MCHBAR32(UPMC3) |= (1 << 16);
2482 }
2483
2484 MCHBAR32(GIPMC1) = 0x8000000c;
2485
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002486 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002487 reg16 &= ~(7 << 11);
2488 if (i945_silicon_revision()>2) {
2489 reg16 |= (6 << 11);
2490 } else {
2491 reg16 |= (4 << 11);
2492 }
2493 MCHBAR16(CPCTL) = reg16;
2494
Stefan Reinauer30140a52009-03-11 16:20:39 +00002495#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002496 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002497#else
2498 if (i945_silicon_revision() != 0) {
2499#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002500 switch (sysinfo->fsb_frequency) {
2501 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2502 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2503 }
2504 } else {
2505 switch (sysinfo->fsb_frequency) {
2506 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2507 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2508 }
2509 }
2510
2511 MCHBAR32(FSBPMC1) = 0x8000000c;
2512
2513 reg32 = MCHBAR32(C2C3TT);
2514 reg32 &= 0xffff0000;
2515 switch (sysinfo->fsb_frequency) {
2516 case 667: reg32 |= 0x0600; break;
2517 case 533: reg32 |= 0x0480; break;
2518 }
2519 MCHBAR32(C2C3TT) = reg32;
2520
2521 reg32 = MCHBAR32(C3C4TT);
2522 reg32 &= 0xffff0000;
2523 switch (sysinfo->fsb_frequency) {
2524 case 667: reg32 |= 0x0b80; break;
2525 case 533: reg32 |= 0x0980; break;
2526 }
2527 MCHBAR32(C3C4TT) = reg32;
2528
2529 if (i945_silicon_revision() == 0) {
2530 MCHBAR32(ECO) &= ~(1 << 16);
2531 } else {
2532 MCHBAR32(ECO) |= (1 << 16);
2533 }
2534
2535#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002536
Stefan Reinauer278534d2008-10-29 04:51:07 +00002537 if (i945_silicon_revision() == 0) {
2538 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2539 } else {
2540 MCHBAR32(FSBPMC3) |= (1 << 29);
2541 }
2542#endif
2543 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2544
2545 MCHBAR32(FSBPMC3) |= (1 << 21);
2546
2547 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2548
2549 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2550
2551 reg32 = MCHBAR32(FSBPMC4);
2552 reg32 &= ~(3 << 24);
2553 reg32 |= ( 2 << 24);
2554 MCHBAR32(FSBPMC4) = reg32;
2555
2556 MCHBAR32(FSBPMC4) |= (1 << 21);
2557
2558 MCHBAR32(FSBPMC4) |= (1 << 5);
2559
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002560 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2561 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002562 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2563 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002564 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002565 }
2566
2567 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2568 reg8 |= (1 << 4);
2569 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2570
2571 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2572 reg8 |= (1 << 2);
2573 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2574
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002575#if C2_SELF_REFRESH_DISABLE
2576
Stefan Reinauer278534d2008-10-29 04:51:07 +00002577 if (integrated_graphics) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002578 printk_debug("C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002579 MCHBAR16(MIPMC4) = 0x0468;
2580 MCHBAR16(MIPMC5) = 0x046c;
2581 MCHBAR16(MIPMC6) = 0x046c;
2582 } else {
2583 MCHBAR16(MIPMC4) = 0x6468;
2584 MCHBAR16(MIPMC5) = 0x646c;
2585 MCHBAR16(MIPMC6) = 0x646c;
2586 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002587#else
2588 if (integrated_graphics) {
2589 MCHBAR16(MIPMC4) = 0x04f8;
2590 MCHBAR16(MIPMC5) = 0x04fc;
2591 MCHBAR16(MIPMC6) = 0x04fc;
2592 } else {
2593 MCHBAR16(MIPMC4) = 0x64f8;
2594 MCHBAR16(MIPMC5) = 0x64fc;
2595 MCHBAR16(MIPMC6) = 0x64fc;
2596 }
2597
2598#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002599
2600 reg32 = MCHBAR32(PMCFG);
2601 reg32 &= ~(3 << 17);
2602 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002603 MCHBAR32(PMCFG) = reg32;
2604
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002605 MCHBAR32(PMCFG) |= (1 << 4);
2606
Stefan Reinauer278534d2008-10-29 04:51:07 +00002607 reg32 = MCHBAR32(0xc30);
2608 reg32 &= 0xffffff00;
2609 reg32 |= 0x01;
2610 MCHBAR32(0xc30) = reg32;
2611
2612 MCHBAR32(0xb18) &= ~(1 << 21);
2613}
2614
2615static void sdram_thermal_management(void)
2616{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002617
Stefan Reinauer278534d2008-10-29 04:51:07 +00002618 MCHBAR8(TCO1) = 0x00;
2619 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002620
2621 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2622 * 0x30/0x32.
2623 */
2624
2625}
2626
2627static void sdram_save_receive_enable(void)
2628{
2629 int i;
2630 u32 reg32;
2631 u8 values[4];
2632
2633 /* The following values are stored to an unused CMOS
2634 * area and restored instead of recalculated in case
2635 * of an S3 resume.
2636 *
2637 * C0WL0REOST [7:0] -> 8 bit
2638 * C1WL0REOST [7:0] -> 8 bit
2639 * RCVENMT [11:8] [3:0] -> 8 bit
2640 * C0DRT1 [27:24] -> 4 bit
2641 * C1DRT1 [27:24] -> 4 bit
2642 */
2643
2644 values[0] = MCHBAR8(C0WL0REOST);
2645 values[1] = MCHBAR8(C1WL0REOST);
2646
2647 reg32 = MCHBAR32(RCVENMT);
2648 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2649
2650 reg32 = MCHBAR32(C0DRT1);
2651 values[3] = (reg32 >> 24) & 0x0f;
2652 reg32 = MCHBAR32(C1DRT1);
2653 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2654
2655 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
2656 * so we grad bytes 128 - 131 to save the receive enable values
2657 */
2658
2659 for (i=0; i<4; i++)
2660 cmos_write(values[i], 128 + i);
2661}
2662
2663static void sdram_recover_receive_enable(void)
2664{
2665 int i;
2666 u32 reg32;
2667 u8 values[4];
2668
2669 for (i=0; i<4; i++)
2670 values[i] = cmos_read(128 + i);
2671
2672 MCHBAR8(C0WL0REOST) = values[0];
2673 MCHBAR8(C1WL0REOST) = values[1];
2674
2675 reg32 = MCHBAR32(RCVENMT);
2676 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2677 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2678 MCHBAR32(RCVENMT) = reg32;
2679
2680 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2681 reg32 |= (u32)(values[3] & 0x0f) << 24;
2682 MCHBAR32(C0DRT1) = reg32;
2683
2684 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2685 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2686 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002687}
2688
2689#include "rcven.c"
2690
2691static void sdram_program_receive_enable(struct sys_info *sysinfo)
2692{
2693 MCHBAR32(REPC) |= (1 << 0);
2694
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002695 /* enable upper CMOS */
2696 RCBA32(0x3400) = (1 << 2);
2697
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002698 /* Program Receive Enable Timings */
2699 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2700 sdram_recover_receive_enable();
2701 } else {
2702 receive_enable_adjust(sysinfo);
2703 sdram_save_receive_enable();
2704 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002705
2706 MCHBAR32(C0DRC1) |= (1 << 6);
2707 MCHBAR32(C1DRC1) |= (1 << 6);
2708 MCHBAR32(C0DRC1) &= ~(1 << 6);
2709 MCHBAR32(C1DRC1) &= ~(1 << 6);
2710
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002711 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002712}
2713
2714/**
2715 * @brief Enable On-Die Termination for DDR2.
2716 *
2717 */
2718
2719static void sdram_on_die_termination(struct sys_info *sysinfo)
2720{
2721 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002722 0x00024911, 0xe0010000,
2723 0x00049211, 0xe0020000,
2724 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002725 };
2726
2727 u32 reg32;
2728 int cas;
2729
2730 reg32 = MCHBAR32(ODTC);
2731 reg32 &= ~(3 << 16);
2732 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2733 MCHBAR32(ODTC) = reg32;
2734
2735 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2736 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
2737 printk_debug("one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002738
Stefan Reinauer278534d2008-10-29 04:51:07 +00002739 reg32 = MCHBAR32(C0ODT);
2740 reg32 &= ~(7 << 28);
2741 MCHBAR32(C0ODT) = reg32;
2742 reg32 = MCHBAR32(C1ODT);
2743 reg32 &= ~(7 << 28);
2744 MCHBAR32(C1ODT) = reg32;
2745 }
2746
2747 cas = sysinfo->cas;
2748
2749 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2750 reg32 |= odt[(cas-3) * 2];
2751 MCHBAR32(C0ODT) = reg32;
2752
2753 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2754 reg32 |= odt[(cas-3) * 2];
2755 MCHBAR32(C1ODT) = reg32;
2756
2757 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2758 reg32 |= odt[((cas-3) * 2) + 1];
2759 MCHBAR32(C0ODT + 4) = reg32;
2760
2761 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2762 reg32 |= odt[((cas-3) * 2) + 1];
2763 MCHBAR32(C1ODT + 4) = reg32;
2764}
2765
2766/**
2767 * @brief Enable clocks to populated sockets
2768 */
2769
2770static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2771{
2772 u8 clocks[2] = { 0, 0 };
2773
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002774#ifdef CHIPSET_I945GM
2775#define CLOCKS_WIDTH 2
2776#endif
2777#ifdef CHIPSET_I945GC
2778#define CLOCKS_WIDTH 3
2779#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002780 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002781 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002782
2783 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002784 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002785
2786 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002787 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002788
2789 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002790 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002791
2792#ifdef OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002793 /* Usually system firmware turns off system memory clock signals
2794 * to unused SO-DIMM slots to reduce EMI and power consumption.
2795 * However, the Kontron 986LCD-M does not like unused clock
2796 * signals to be disabled.
2797 * If other similar mainboard occur, it would make sense to make
2798 * this an entry in the sysinfo structure, and pre-initialize that
Stefan Reinauer38f147e2010-02-08 12:20:50 +00002799 * structure in the mainboard's romstage.c main() function.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002800 * For now an #ifdef will do.
2801 */
2802
2803 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2804 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002805#endif
2806
2807 MCHBAR8(C0DCLKDIS) = clocks[0];
2808 MCHBAR8(C1DCLKDIS) = clocks[1];
2809}
2810
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002811#define RTT_ODT_NONE 0
2812#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002813#define RTT_ODT_75_OHM (1 << 5)
2814#define RTT_ODT_150_OHM (1 << 9)
2815
2816#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2817
2818#define MRS_CAS_3 (3 << 7)
2819#define MRS_CAS_4 (4 << 7)
2820#define MRS_CAS_5 (5 << 7)
2821
2822#define MRS_TWR_3 (2 << 12)
2823#define MRS_TWR_4 (3 << 12)
2824#define MRS_TWR_5 (4 << 12)
2825
2826#define MRS_BT (1 << 6)
2827
2828#define MRS_BL4 (2 << 3)
2829#define MRS_BL8 (3 << 3)
2830
2831static void sdram_jedec_enable(struct sys_info *sysinfo)
2832{
2833 int i, nonzero;
2834 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2835
2836 for (i = 0, nonzero = -1; i < 8; i++) {
2837 if (sysinfo->banksize[i] == 0) {
2838 continue;
2839 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002840
Stefan Reinauer278534d2008-10-29 04:51:07 +00002841 printk_debug("jedec enable sequence: bank %d\n", i);
2842 switch (i) {
2843 case 0:
2844 /* Start at address 0 */
2845 bankaddr = 0;
2846 break;
2847 case 4:
2848 if (sysinfo->interleaved) {
2849 bankaddr = 0x40;
2850 break;
2851 }
2852 default:
2853 if (nonzero != -1) {
2854 printk_debug("bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002855 bankaddr += sysinfo->banksize[nonzero] <<
2856 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002857 break;
2858 }
2859 /* No populated bank hit before. Start at address 0 */
2860 bankaddr = 0;
2861 }
2862
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002863 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002864 * for the next offset we have to calculate
2865 */
2866 nonzero = i;
2867
2868 /* Get CAS latency set up */
2869 switch (sysinfo->cas) {
2870 case 5: mrsaddr = MRS_CAS_5; break;
2871 case 4: mrsaddr = MRS_CAS_4; break;
2872 case 3: mrsaddr = MRS_CAS_3; break;
2873 default: die("Jedec Error (CAS).\n");
2874 }
2875
2876 /* Get tWR set */
2877 switch (sysinfo->twr) {
2878 case 5: mrsaddr |= MRS_TWR_5; break;
2879 case 4: mrsaddr |= MRS_TWR_4; break;
2880 case 3: mrsaddr |= MRS_TWR_3; break;
2881 default: die("Jedec Error (tWR).\n");
2882 }
2883
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002884 /* Set "Burst Type" */
2885 mrsaddr |= MRS_BT;
2886
Stefan Reinauer278534d2008-10-29 04:51:07 +00002887 /* Interleaved */
2888 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002889 mrsaddr = mrsaddr << 1;
2890 }
2891
2892 /* Only burst length 8 supported */
2893 mrsaddr |= MRS_BL8;
2894
2895 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002896 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002897 do_ram_command(RAM_COMMAND_NOP);
2898 ram_read32(bankaddr);
2899
2900 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002901 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002902 do_ram_command(RAM_COMMAND_PRECHARGE);
2903 ram_read32(bankaddr);
2904
2905 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002906 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002907 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2908 ram_read32(bankaddr);
2909
2910 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002911 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002912 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2913 ram_read32(bankaddr);
2914
2915 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002916 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002917 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2918 tmpaddr = bankaddr;
2919 if (!sdram_capabilities_dual_channel()) {
2920 tmpaddr |= RTT_ODT_75_OHM;
2921 } else if (sysinfo->interleaved) {
2922 tmpaddr |= (RTT_ODT_150_OHM << 1);
2923 } else {
2924 tmpaddr |= RTT_ODT_150_OHM;
2925 }
2926 ram_read32(tmpaddr);
2927
2928 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002929 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002930 do_ram_command(RAM_COMMAND_MRS);
2931 tmpaddr = bankaddr;
2932 tmpaddr |= mrsaddr;
2933 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002934 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002935 tmpaddr |= (1 << 12);
2936 else
2937 tmpaddr |= (1 << 11);
2938 ram_read32(tmpaddr);
2939
2940 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002941 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002942 do_ram_command(RAM_COMMAND_PRECHARGE);
2943 ram_read32(bankaddr);
2944
2945 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002946 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002947 do_ram_command(RAM_COMMAND_CBR);
2948
2949 /* CBR wants two READs */
2950 ram_read32(bankaddr);
2951 ram_read32(bankaddr);
2952
2953 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002954 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002955 do_ram_command(RAM_COMMAND_MRS);
2956
2957 tmpaddr = bankaddr;
2958 tmpaddr |= mrsaddr;
2959 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002960
Stefan Reinauer278534d2008-10-29 04:51:07 +00002961 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002962 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002963 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002964
Stefan Reinauer278534d2008-10-29 04:51:07 +00002965 tmpaddr = bankaddr;
2966 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002967
Stefan Reinauer278534d2008-10-29 04:51:07 +00002968 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
2969 } else if (sysinfo->interleaved) {
2970 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
2971 } else {
2972 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
2973 }
2974 ram_read32(tmpaddr);
2975
2976 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002977 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002978 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2979
2980 tmpaddr = bankaddr;
2981 if (!sdram_capabilities_dual_channel()) {
2982 tmpaddr |= RTT_ODT_75_OHM;
2983 } else if (sysinfo->interleaved) {
2984 tmpaddr |= (RTT_ODT_150_OHM << 1);
2985 } else {
2986 tmpaddr |= RTT_ODT_150_OHM;
2987 }
2988 ram_read32(tmpaddr);
2989 }
2990}
2991
2992static void sdram_init_complete(void)
2993{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002994 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002995 do_ram_command(RAM_COMMAND_NORMAL);
2996}
2997
2998static void sdram_setup_processor_side(void)
2999{
3000 if (i945_silicon_revision() == 0)
3001 MCHBAR32(FSBPMC3) |= (1 << 2);
3002
3003 MCHBAR8(0xb00) |= 1;
3004
3005 if (i945_silicon_revision() == 0)
3006 MCHBAR32(SLPCTL) |= (1 << 8);
3007}
3008
Stefan Reinauer278534d2008-10-29 04:51:07 +00003009/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003010 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003011 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003012void sdram_initialize(int boot_path)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003013{
3014 struct sys_info sysinfo;
3015 u8 reg8, cas_mask;
3016
3017 sdram_detect_errors();
3018
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003019 printk_debug ("Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003020
3021 memset(&sysinfo, 0, sizeof(sysinfo));
3022
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003023 sysinfo.boot_path = boot_path;
3024
Stefan Reinauer278534d2008-10-29 04:51:07 +00003025 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3026 sdram_get_dram_configuration(&sysinfo);
3027
3028 /* Check whether we have stacked DIMMs */
3029 sdram_verify_package_type(&sysinfo);
3030
3031 /* Determine common CAS */
3032 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003033
Stefan Reinauer278534d2008-10-29 04:51:07 +00003034 /* Choose Common Frequency */
3035 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003036
Stefan Reinauer278534d2008-10-29 04:51:07 +00003037 /* Determine smallest common tRAS */
3038 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003039
Stefan Reinauer278534d2008-10-29 04:51:07 +00003040 /* Determine tRP */
3041 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003042
Stefan Reinauer278534d2008-10-29 04:51:07 +00003043 /* Determine tRCD */
3044 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003045
Stefan Reinauer278534d2008-10-29 04:51:07 +00003046 /* Determine smallest refresh period */
3047 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003048
Stefan Reinauer278534d2008-10-29 04:51:07 +00003049 /* Verify all DIMMs support burst length 8 */
3050 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003051
Stefan Reinauer278534d2008-10-29 04:51:07 +00003052 /* determine tWR */
3053 sdram_detect_smallest_tWR(&sysinfo);
3054
3055 /* Determine DIMM size parameters (rows, columns banks) */
3056 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003057
Stefan Reinauer278534d2008-10-29 04:51:07 +00003058 /* determine tRFC */
3059 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003060
Stefan Reinauer278534d2008-10-29 04:51:07 +00003061 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003062 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003063
3064 /* Program Graphics Frequency */
3065 sdram_program_graphics_frequency(&sysinfo);
3066
3067 /* Program System Memory Frequency */
3068 sdram_program_memory_frequency(&sysinfo);
3069
3070 /* Determine Mode of Operation (Interleaved etc) */
3071 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003072
Stefan Reinauer278534d2008-10-29 04:51:07 +00003073 /* Program Clock Crossing values */
3074 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003075
Stefan Reinauer278534d2008-10-29 04:51:07 +00003076 /* Disable fast dispatch */
3077 sdram_disable_fast_dispatch();
3078
3079 /* Enable WIODLL Power Down in ACPI states */
3080 MCHBAR32(C0DMC) |= (1 << 24);
3081 MCHBAR32(C1DMC) |= (1 << 24);
3082
3083 /* Program DRAM Row Boundary/Attribute Registers */
3084
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003085 /* program row size DRB and set TOLUD */
3086 sdram_program_row_boundaries(&sysinfo);
3087
3088 /* program page size DRA */
3089 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003090
3091 /* Program CxBNKARC */
3092 sdram_set_bank_architecture(&sysinfo);
3093
3094 /* Program DRAM Timing and Control registers based on SPD */
3095 sdram_set_timing_and_control(&sysinfo);
3096
3097 /* On-Die Termination Adjustment */
3098 sdram_on_die_termination(&sysinfo);
3099
3100 /* Pre Jedec Initialization */
3101 sdram_pre_jedec_initialization();
3102
3103 /* Perform System Memory IO Initialization */
3104 sdram_initialize_system_memory_io(&sysinfo);
3105
3106 /* Perform System Memory IO Buffer Enable */
3107 sdram_enable_system_memory_io(&sysinfo);
3108
3109 /* Enable System Memory Clocks */
3110 sdram_enable_memory_clocks(&sysinfo);
3111
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003112 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003113 /* Jedec Initialization sequence */
3114 sdram_jedec_enable(&sysinfo);
3115 }
3116
3117 /* Program Power Management Registers */
3118 sdram_power_management(&sysinfo);
3119
3120 /* Post Jedec Init */
3121 sdram_post_jedec_initialization(&sysinfo);
3122
3123 /* Program DRAM Throttling */
3124 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003125
Stefan Reinauer278534d2008-10-29 04:51:07 +00003126 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003127 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003128
3129 /* Program Receive Enable Timings */
3130 sdram_program_receive_enable(&sysinfo);
3131
3132 /* Enable Periodic RCOMP */
3133 sdram_enable_rcomp();
3134
3135 /* Tell ICH7 that we're done */
3136 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3137 reg8 &= ~(1 << 7);
3138 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3139
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003140 printk_debug("RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003141
Stefan Reinauer278534d2008-10-29 04:51:07 +00003142 sdram_setup_processor_side();
3143}
3144
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003145unsigned long get_top_of_ram(void)
3146{
3147 /* This will not work if TSEG is in place! */
3148 u32 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
3149
3150 return (unsigned long) tom;
3151}
3152