blob: 885b49df71c926b6ce1e1711fc0a806ff2978370 [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
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Stefan Reinauer278534d2008-10-29 04:51:07 +000018 */
19
Patrick Georgid0835952010-10-05 09:07:10 +000020#include <console/console.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000021#include <cpu/x86/mtrr.h>
22#include <cpu/x86/cache.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000023#include <pc80/mc146818rtc.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000024#include <spd.h>
Patrick Georgid0835952010-10-05 09:07:10 +000025#include <string.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070026#include <arch/io.h>
Alexandru Gagniucaf4bd592014-01-12 15:42:58 -060027#include <lib.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000028#include "raminit.h"
29#include "i945.h"
Rudolf Marekc4369532010-12-13 19:59:13 +000030#include <cbmem.h>
31
Stefan Reinauer278534d2008-10-29 04:51:07 +000032/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000033#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000034#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Stefan Reinauer278534d2008-10-29 04:51:07 +000035#else
36#define PRINTK_DEBUG(x...)
37#endif
38
Stefan Reinauer278534d2008-10-29 04:51:07 +000039#define RAM_INITIALIZATION_COMPLETE (1 << 19)
40
41#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
42#define RAM_COMMAND_NOP (0x1 << 16)
43#define RAM_COMMAND_PRECHARGE (0x2 << 16)
44#define RAM_COMMAND_MRS (0x3 << 16)
45#define RAM_COMMAND_EMRS (0x4 << 16)
46#define RAM_COMMAND_CBR (0x6 << 16)
47#define RAM_COMMAND_NORMAL (0x7 << 16)
48
49#define RAM_EMRS_1 (0x0 << 21)
50#define RAM_EMRS_2 (0x1 << 21)
51#define RAM_EMRS_3 (0x2 << 21)
52
Sven Schnelle541269b2011-02-21 09:39:17 +000053static int get_dimm_spd_address(struct sys_info *sysinfo, int device)
54{
55 if (sysinfo->spd_addresses)
56 return sysinfo->spd_addresses[device];
57 else
58 return DIMM0 + device;
59
60}
61
Patrick Georgid0835952010-10-05 09:07:10 +000062static inline int spd_read_byte(unsigned device, unsigned address)
63{
64 return smbus_read_byte(device, address);
65}
66
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000067static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000068{
69 u32 reg32;
70
71 reg32 = MCHBAR32(DCC);
72 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
73 reg32 |= command;
74
75 /* Also set Init Complete */
76 if (command == RAM_COMMAND_NORMAL)
77 reg32 |= RAM_INITIALIZATION_COMPLETE;
78
79 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
80
81 MCHBAR32(DCC) = reg32; /* This is the actual magic */
82
Stefan Reinauer779b3e32008-11-10 15:43:37 +000083 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000084
85 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000086}
87
Stefan Reinauer278534d2008-10-29 04:51:07 +000088static void ram_read32(u32 offset)
89{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000090 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000091
92 read32(offset);
93}
94
Uwe Hermann01ce6012010-03-05 10:03:50 +000095#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer3c0bfaf2010-12-27 11:34:57 +000096void sdram_dump_mchbar_registers(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000097{
98 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000099 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000100
101 for (i=0; i<0xfff; i+=4) {
102 if (MCHBAR32(i) == 0)
103 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000104 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000105 }
106}
107#endif
108
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000109static int memclk(void)
110{
111 int offset = 0;
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200112#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000113 offset++;
114#endif
115 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
116 case 1: return 400;
117 case 2: return 533;
118 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000119 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000120 }
121 return -1;
122}
123
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200124#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Peter Stuge76d91432010-10-01 10:02:33 +0000125static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000126{
127 switch (MCHBAR32(CLKCFG) & 7) {
128 case 0: return 400;
129 case 1: return 533;
130 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000131 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000132 }
Peter Stuge76d91432010-10-01 10:02:33 +0000133 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000134}
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200135#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Peter Stuge76d91432010-10-01 10:02:33 +0000136static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000137{
138 switch (MCHBAR32(CLKCFG) & 7) {
139 case 0: return 1066;
140 case 1: return 533;
141 case 2: return 800;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000142 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000143 }
Peter Stuge76d91432010-10-01 10:02:33 +0000144 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000145}
146#endif
147
Stefan Reinauer278534d2008-10-29 04:51:07 +0000148static int sdram_capabilities_max_supported_memory_frequency(void)
149{
150 u32 reg32;
151
Patrick Georgi77d66832010-10-01 08:02:45 +0000152#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
153 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000154#endif
155
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000156 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000157 reg32 &= (7 << 0);
158
159 switch (reg32) {
160 case 4: return 400;
161 case 3: return 533;
162 case 2: return 667;
163 }
164 /* Newer revisions of this chipset rather support faster memory clocks,
165 * so if it's a reserved value, return the fastest memory clock that we
166 * know of and can handle
167 */
168 return 667;
169}
170
171/**
172 * @brief determine whether chipset is capable of dual channel interleaved mode
173 *
174 * @return 1 if interleaving is supported, 0 otherwise
175 */
176static int sdram_capabilities_interleave(void)
177{
178 u32 reg32;
179
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000180 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000181 reg32 >>= 25;
182 reg32 &= 1;
183
184 return (!reg32);
185}
186
187/**
188 * @brief determine whether chipset is capable of two memory channels
189 *
190 * @return 1 if dual channel operation is supported, 0 otherwise
191 */
192static int sdram_capabilities_dual_channel(void)
193{
194 u32 reg32;
195
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000196 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000197 reg32 >>= 24;
198 reg32 &= 1;
199
200 return (!reg32);
201}
202
203static int sdram_capabilities_enhanced_addressing_xor(void)
204{
205 u8 reg8;
206
207 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
208 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000209
Stefan Reinauer278534d2008-10-29 04:51:07 +0000210 return (!reg8);
211}
212
213static int sdram_capabilities_two_dimms_per_channel(void)
214{
215 u8 reg8;
216
217 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
218 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000219
Stefan Reinauer278534d2008-10-29 04:51:07 +0000220 return (reg8 != 0);
221}
222
Stefan Reinauer14e22772010-04-27 06:56:47 +0000223// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000224#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000225static int sdram_capabilities_MEM4G_disable(void)
226{
227 u8 reg8;
228
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000229 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000230 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000231
Stefan Reinauer278534d2008-10-29 04:51:07 +0000232 return (reg8 != 0);
233}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000234#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000235
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000236#define GFX_FREQUENCY_CAP_166MHZ 0x04
237#define GFX_FREQUENCY_CAP_200MHZ 0x03
238#define GFX_FREQUENCY_CAP_250MHZ 0x02
239#define GFX_FREQUENCY_CAP_ALL 0x00
240
241static int sdram_capabilities_core_frequencies(void)
242{
243 u8 reg8;
244
245 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
246 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
247 reg8 >>= 1;
248
249 return (reg8);
250}
251
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000252static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000253{
254 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000255 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000256
257 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000258
Stefan Reinauer278534d2008-10-29 04:51:07 +0000259 if (reg8 & ((1<<7)|(1<<2))) {
260 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000261 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000262 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000263 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000264 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000265
Stefan Reinauer278534d2008-10-29 04:51:07 +0000266 }
267
268 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000269 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000270 reg8 &= ~(1<<7);
271 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000272 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000273 }
274
275 /* Set SLP_S3# Assertion Stretch Enable */
276 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
277 reg8 |= (1 << 3);
278 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
279
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000280 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000281 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000282 outb(0x00, 0xcf9);
283 outb(0x0e, 0xcf9);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000284 for (;;) asm("hlt"); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000285 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000286 }
287
288 /* Set DRAM initialization bit in ICH7 */
289 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
290 reg8 |= (1<<7);
291 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000292
Peter Stuge751508a2012-01-27 22:17:09 +0100293 /* clear self refresh status if check is disabled or not a resume */
Patrick Georgi86a11102013-03-15 14:11:37 +0100294 if (!CONFIG_CHECK_SLFRCS_ON_RESUME || sysinfo->boot_path != BOOT_PATH_RESUME) {
295 MCHBAR8(SLFRCS) |= 3;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000296 } else {
297 /* Validate self refresh config */
298 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
299 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100300 !(MCHBAR8(SLFRCS) & (1<<0))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000301 do_reset = 1;
302 }
303 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
304 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100305 !(MCHBAR8(SLFRCS) & (1<<1))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000306 do_reset = 1;
307 }
308 }
309
310 if (do_reset) {
311 printk(BIOS_DEBUG, "Reset required.\n");
312 outb(0x00, 0xcf9);
313 outb(0x0e, 0xcf9);
314 for (;;) asm("hlt"); /* Wait for reset! */
315 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000316}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000317
318/**
319 * @brief Get generic DIMM parameters.
320 * @param sysinfo Central memory controller information structure
321 *
322 * This function gathers several pieces of information for each system DIMM:
323 * o DIMM width (x8 / x16)
324 * o DIMM sides (single sided / dual sided)
325 *
326 * Also, some non-supported scenarios are detected.
327 */
328
329static void sdram_get_dram_configuration(struct sys_info *sysinfo)
330{
331 u32 dimm_mask = 0;
332 int i;
333
334 /**
335 * i945 supports two DIMMs, in two configurations:
336 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000337 * - single channel with two DIMMs
338 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000339 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000340 * In practice dual channel mainboards have their SPD at 0x50/0x52
341 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000342 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000343 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000344 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000345 */
346
347 if (sdram_capabilities_dual_channel()) {
348 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000349 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000350 } else {
351 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000352 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000353 }
354
355 /**
356 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000357 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000358 * return value:
359 * [0:7] lower DIMM population
360 * [8-15] higher DIMM population
361 * [16] dual channel?
362 *
363 * There are 5 different possible populations for a DIMM socket:
364 * 1. x16 double sided (X16DS)
365 * 2. x8 double sided (X8DS)
366 * 3. x16 single sided (X16SS)
367 * 4. x8 double stacked (X8DDS)
368 * 5. not populated (NC)
369 *
370 * For the return value we start counting at zero.
371 *
372 */
373
374 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000375 int device = get_dimm_spd_address(sysinfo, i);
376 u8 reg8;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000377
378 /* Initialize the socket information with a sane value */
379 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
380
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000381 /* Dual Channel not supported, but Channel 1? Bail out */
382 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000383 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000384
385 /* Two DIMMs per channel not supported, but odd DIMM number? */
386 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000387 continue;
388
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000389 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000390
391 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000392 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000393 continue;
394 }
395
396 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
397 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000398 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399
400 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
401 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000402 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000404 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000405
406 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000407 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000408 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
409 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000410 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000411 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
412 break;
413 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000414 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000415 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
416 break;
417 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000418 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000419 }
420 break;
421 case 0x10:
422 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
423 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000424 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000425 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
426 break;
427 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000428 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000429 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
430 break;
431 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000432 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000433 }
434 break;
435 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000436 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000437 }
438
439 dimm_mask |= (1 << i);
440 }
441
442 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000443 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000444 }
445
Stefan Reinauer278534d2008-10-29 04:51:07 +0000446 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000447 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000448 }
449}
450
451/**
452 * @brief determine if any DIMMs are stacked
453 *
454 * @param sysinfo central sysinfo data structure.
455 */
456static void sdram_verify_package_type(struct sys_info * sysinfo)
457{
458 int i;
459
460 /* Assume no stacked DIMMs are available until we find one */
461 sysinfo->package = 0;
462 for (i=0; i<2*DIMM_SOCKETS; i++) {
463 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
464 continue;
465
466 /* Is the current DIMM a stacked DIMM? */
Sven Schnelle541269b2011-02-21 09:39:17 +0000467 if (spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000468 sysinfo->package = 1;
469 }
470}
471
472static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
473{
474 int i;
475 u8 cas_mask;
476
477 /* Setup CAS mask with all supported CAS Latencies */
478 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
479 SPD_CAS_LATENCY_DDR2_4 |
480 SPD_CAS_LATENCY_DDR2_5;
481
482 for (i=0; i<2*DIMM_SOCKETS; i++) {
483 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Sven Schnelle541269b2011-02-21 09:39:17 +0000484 cas_mask &= spd_read_byte(get_dimm_spd_address(sysinfo, i),
485 SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000486 }
487
488 if(!cas_mask) {
489 die("No DDR-II modules with accepted CAS latencies found.\n");
490 }
491
492 return cas_mask;
493}
494
495static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
496{
497 int i, j, idx;
498 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000499 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000500
501 const u8 ddr2_speeds_table[] = {
502 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
503 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
504 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
505 };
506
507 const u8 spd_lookup_table[] = {
508 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
509 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
510 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
511 };
512
513 switch (sdram_capabilities_max_supported_memory_frequency()) {
514 case 400: max_ram_speed = 0; break;
515 case 533: max_ram_speed = 1; break;
516 case 667: max_ram_speed = 2; break;
517 }
518
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000519 if (fsbclk() == 533)
520 max_ram_speed = 1;
521
Stefan Reinauer278534d2008-10-29 04:51:07 +0000522 sysinfo->memory_frequency = 0;
523 sysinfo->cas = 0;
524
525 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
526 lowest_common_cas = 3;
527 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
528 lowest_common_cas = 4;
529 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
530 lowest_common_cas = 5;
531 }
532 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
533
534 for (j = max_ram_speed; j>=0; j--) {
535 int freq_cas_mask = cas_mask;
536
537 PRINTK_DEBUG("Probing Speed %d\n", j);
538 for (i=0; i<2*DIMM_SOCKETS; i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000539 int device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000540 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000541
Stefan Reinauer278534d2008-10-29 04:51:07 +0000542 PRINTK_DEBUG(" DIMM: %d\n", i);
543 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
544 continue;
545 }
546
Sven Schnelle541269b2011-02-21 09:39:17 +0000547 current_cas_mask = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000548
549 while (current_cas_mask) {
550 int highest_supported_cas = 0, current_cas = 0;
551 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
552 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
553 highest_supported_cas = 5;
554 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
555 highest_supported_cas = 4;
556 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
557 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000558 } else {
559 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000560 }
561 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
562 current_cas = 3;
563 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
564 current_cas = 4;
565 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
566 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000567 } else {
568 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000569 }
570
571 idx = highest_supported_cas - current_cas;
572 PRINTK_DEBUG("idx=%d, ", idx);
Sven Schnelle541269b2011-02-21 09:39:17 +0000573 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(device, spd_lookup_table[2*idx]));
574 PRINTK_DEBUG("tAC=%x", spd_read_byte(device, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000575
Sven Schnelle541269b2011-02-21 09:39:17 +0000576 if (spd_read_byte(device, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
577 spd_read_byte(device, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000578 PRINTK_DEBUG(": OK\n");
579 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000580 }
581
Stefan Reinauer278534d2008-10-29 04:51:07 +0000582 PRINTK_DEBUG(": Not fast enough!\n");
583
584 current_cas_mask &= ~(1 << (current_cas));
585 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000586
Stefan Reinauer278534d2008-10-29 04:51:07 +0000587 freq_cas_mask &= current_cas_mask;
588 if (!current_cas_mask) {
589 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
590 break;
591 }
592 }
593 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
594 if (freq_cas_mask) {
595 switch (j) {
596 case 0: sysinfo->memory_frequency = 400; break;
597 case 1: sysinfo->memory_frequency = 533; break;
598 case 2: sysinfo->memory_frequency = 667; break;
599 }
600 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
601 sysinfo->cas = 3;
602 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
603 sysinfo->cas = 4;
604 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
605 sysinfo->cas = 5;
606 }
607 break;
608 }
609 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000610
Stefan Reinauer278534d2008-10-29 04:51:07 +0000611 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000612 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000613 sysinfo->memory_frequency, sysinfo->cas);
614 } else {
615 die("Could not find common memory frequency and CAS\n");
616 }
617}
618
619static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
620{
621 int i;
622 int tRAS_time;
623 int tRAS_cycles;
624 int freq_multiplier = 0;
625
626 switch (sysinfo->memory_frequency) {
627 case 400: freq_multiplier = 0x14; break; /* 5ns */
628 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
629 case 667: freq_multiplier = 0x0c; break; /* 3ns */
630 }
631
632 tRAS_cycles = 4; /* 4 clocks minimum */
633 tRAS_time = tRAS_cycles * freq_multiplier;
634
635 for (i=0; i<2*DIMM_SOCKETS; i++) {
636 u8 reg8;
637
638 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
639 continue;
640
Sven Schnelle541269b2011-02-21 09:39:17 +0000641 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000642 if (!reg8) {
643 die("Invalid tRAS value.\n");
644 }
645
646 while ((tRAS_time >> 2) < reg8) {
647 tRAS_time += freq_multiplier;
648 tRAS_cycles++;
649 }
650 }
651 if(tRAS_cycles > 0x18) {
652 die("DDR-II Module does not support this frequency (tRAS error)\n");
653 }
654
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000655 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000656 sysinfo->tras = tRAS_cycles;
657}
658
659static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
660{
661 int i;
662 int tRP_time;
663 int tRP_cycles;
664 int freq_multiplier = 0;
665
666 switch (sysinfo->memory_frequency) {
667 case 400: freq_multiplier = 0x14; break; /* 5ns */
668 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
669 case 667: freq_multiplier = 0x0c; break; /* 3ns */
670 }
671
672 tRP_cycles = 2; /* 2 clocks minimum */
673 tRP_time = tRP_cycles * freq_multiplier;
674
675 for (i=0; i<2*DIMM_SOCKETS; i++) {
676 u8 reg8;
677
678 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
679 continue;
680
Sven Schnelle541269b2011-02-21 09:39:17 +0000681 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000682 if (!reg8) {
683 die("Invalid tRP value.\n");
684 }
685
686 while (tRP_time < reg8) {
687 tRP_time += freq_multiplier;
688 tRP_cycles++;
689 }
690 }
691
692 if(tRP_cycles > 6) {
693 die("DDR-II Module does not support this frequency (tRP error)\n");
694 }
695
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000696 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000697 sysinfo->trp = tRP_cycles;
698}
699
700static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
701{
702 int i;
703 int tRCD_time;
704 int tRCD_cycles;
705 int freq_multiplier = 0;
706
707 switch (sysinfo->memory_frequency) {
708 case 400: freq_multiplier = 0x14; break; /* 5ns */
709 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
710 case 667: freq_multiplier = 0x0c; break; /* 3ns */
711 }
712
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000713 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000714 tRCD_time = tRCD_cycles * freq_multiplier;
715
716 for (i=0; i<2*DIMM_SOCKETS; i++) {
717 u8 reg8;
718
719 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
720 continue;
721
Sven Schnelle541269b2011-02-21 09:39:17 +0000722 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000723 if (!reg8) {
724 die("Invalid tRCD value.\n");
725 }
726
727 while (tRCD_time < reg8) {
728 tRCD_time += freq_multiplier;
729 tRCD_cycles++;
730 }
731 }
732 if(tRCD_cycles > 6) {
733 die("DDR-II Module does not support this frequency (tRCD error)\n");
734 }
735
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000736 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000737 sysinfo->trcd = tRCD_cycles;
738}
739
740static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
741{
742 int i;
743 int tWR_time;
744 int tWR_cycles;
745 int freq_multiplier = 0;
746
747 switch (sysinfo->memory_frequency) {
748 case 400: freq_multiplier = 0x14; break; /* 5ns */
749 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
750 case 667: freq_multiplier = 0x0c; break; /* 3ns */
751 }
752
753 tWR_cycles = 2; /* 2 clocks minimum */
754 tWR_time = tWR_cycles * freq_multiplier;
755
756 for (i=0; i<2*DIMM_SOCKETS; i++) {
757 u8 reg8;
758
759 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
760 continue;
761
Sven Schnelle541269b2011-02-21 09:39:17 +0000762 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000763 if (!reg8) {
764 die("Invalid tWR value.\n");
765 }
766
767 while (tWR_time < reg8) {
768 tWR_time += freq_multiplier;
769 tWR_cycles++;
770 }
771 }
772 if(tWR_cycles > 5) {
773 die("DDR-II Module does not support this frequency (tWR error)\n");
774 }
775
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000776 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000777 sysinfo->twr = tWR_cycles;
778}
779
780static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
781{
782 int i, index = 0;
783
784 const u8 tRFC_cycles[] = {
785 /* 75 105 127.5 */
786 15, 21, 26, /* DDR2-400 */
787 20, 28, 34, /* DDR2-533 */
788 25, 35, 43 /* DDR2-667 */
789 };
790
791 for (i=0; i<2*DIMM_SOCKETS; i++) {
792 u8 reg8;
793
794 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
795 continue;
796
797 reg8 = sysinfo->banksize[i*2];
798 switch (reg8) {
799 case 0x04: reg8 = 0; break;
800 case 0x08: reg8 = 1; break;
801 case 0x10: reg8 = 2; break;
802 case 0x20: reg8 = 3; break;
803 }
804
805 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
806 reg8++;
807
808 if (reg8 > 3) {
809 /* Can this happen? Go back to 127.5ns just to be sure
810 * we don't run out of the array. This may be wrong
811 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000812 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000813 reg8 = 3;
814 }
815
816 if (reg8 > index)
817 index = reg8;
818
819 }
820 index--;
821 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000822 case 667: index += 3; /* Fallthrough */
823 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000824 case 400: break;
825 }
826
827 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000828 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000829}
830
Stefan Reinauer278534d2008-10-29 04:51:07 +0000831static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
832{
833 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000834
Stefan Reinauer278534d2008-10-29 04:51:07 +0000835 sysinfo->refresh = 0;
836
837 for (i=0; i<2*DIMM_SOCKETS; i++) {
838 int refresh;
839
840 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
841 continue;
842
Sven Schnelle541269b2011-02-21 09:39:17 +0000843 refresh = spd_read_byte(get_dimm_spd_address(sysinfo, i),
844 SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000845
846 /* 15.6us */
847 if (!refresh)
848 continue;
849
850 /* Refresh is slower than 15.6us, use 15.6us */
851 if (refresh > 2)
852 continue;
853
854 if (refresh == 2) {
855 sysinfo->refresh = 1;
856 break;
857 }
858
859 die("DDR-II module has unsupported refresh value\n");
860 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000861 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000862}
863
864static void sdram_verify_burst_length(struct sys_info * sysinfo)
865{
866 int i;
867
868 for (i=0; i<2*DIMM_SOCKETS; i++) {
869 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
870 continue;
871
Sven Schnelle541269b2011-02-21 09:39:17 +0000872 if (!(spd_read_byte(get_dimm_spd_address(sysinfo, i),
873 SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000874 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
875 }
876}
877
878static void sdram_program_dram_width(struct sys_info * sysinfo)
879{
880 u16 c0dramw=0, c1dramw=0;
881 int idx;
882
883 if (sysinfo->dual_channel)
884 idx = 2;
885 else
886 idx = 1;
887
888 switch (sysinfo->dimm[0]) {
889 case 0: c0dramw = 0x0000; break; /* x16DS */
890 case 1: c0dramw = 0x0001; break; /* x8DS */
891 case 2: c0dramw = 0x0000; break; /* x16SS */
892 case 3: c0dramw = 0x0005; break; /* x8DDS */
893 case 4: c0dramw = 0x0000; break; /* NC */
894 }
895
896 switch (sysinfo->dimm[idx]) {
897 case 0: c1dramw = 0x0000; break; /* x16DS */
898 case 1: c1dramw = 0x0010; break; /* x8DS */
899 case 2: c1dramw = 0x0000; break; /* x16SS */
900 case 3: c1dramw = 0x0050; break; /* x8DDS */
901 case 4: c1dramw = 0x0000; break; /* NC */
902 }
903
904 if ( !sdram_capabilities_dual_channel() ) {
905 /* Single Channel */
906 c0dramw |= c1dramw;
907 c1dramw = 0;
908 }
909
910 MCHBAR16(C0DRAMW) = c0dramw;
911 MCHBAR16(C1DRAMW) = c1dramw;
912}
913
914static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
915{
916 int i;
917
918 for (i=0; i<16; i++)
919 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
920}
921
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000922static const u32 dq2030[] = {
923 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
924 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
925 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
926 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
927};
928
929static const u32 dq2330[] = {
930 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
931 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
932 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
933 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
934};
935
936static const u32 cmd2710[] = {
937 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
938 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
939 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
940 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
941};
942
943static const u32 cmd3210[] = {
944 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
945 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
946 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
947 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
948};
949
950static const u32 clk2030[] = {
951 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
952 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
953 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
954 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
955};
956
957static const u32 ctl3215[] = {
958 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
959 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
960 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
961 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
962};
963
964static const u32 ctl3220[] = {
965 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
966 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
967 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
968 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
969};
970
971static const u32 nc[] = {
972 0x00000000, 0x00000000, 0x00000000, 0x00000000,
973 0x00000000, 0x00000000, 0x00000000, 0x00000000,
974 0x00000000, 0x00000000, 0x00000000, 0x00000000,
975 0x00000000, 0x00000000, 0x00000000, 0x00000000
976};
977
978enum {
979 DQ2030,
980 DQ2330,
981 CMD2710,
982 CMD3210,
983 CLK2030,
984 CTL3215,
985 CTL3220,
986 NC,
987};
988
989static const u8 dual_channel_slew_group_lookup[] = {
990 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
991 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
992 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
993 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
994 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
995
996 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
997 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
998 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
999 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1000 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1001
1002 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1003 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1004 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1005 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
1006 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1007
1008 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1009 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1010 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1011 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1012 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
1013
1014 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1015 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1016 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1017 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
1018};
1019
1020static const u8 single_channel_slew_group_lookup[] = {
1021 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1022 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1023 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1024 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1025 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1026
1027 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1028 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1029 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1030 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1031 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1032
1033 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1034 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1035 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1036 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1037 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1038
1039 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1040 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1041 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1042 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1043 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1044
1045 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1046 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1047 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1048 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1049};
1050
1051static const u32 *slew_group_lookup(int dual_channel, int index)
1052{
1053 const u8 *slew_group;
1054 /* Dual Channel needs different tables. */
1055 if (dual_channel)
1056 slew_group = dual_channel_slew_group_lookup;
1057 else
1058 slew_group = single_channel_slew_group_lookup;
1059
1060 switch (slew_group[index]) {
1061 case DQ2030: return dq2030;
1062 case DQ2330: return dq2330;
1063 case CMD2710: return cmd2710;
1064 case CMD3210: return cmd3210;
1065 case CLK2030: return clk2030;
1066 case CTL3215: return ctl3215;
1067 case CTL3220: return ctl3220;
1068 case NC: return nc;
1069 }
1070
1071 return nc;
1072}
1073
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001074#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001075/* Strength multiplier tables */
1076static const u8 dual_channel_strength_multiplier[] = {
1077 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1078 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1079 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1080 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1081 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1082 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1083 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1084 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1085 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1086 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1087 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1088 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1089 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1090 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1091 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1092 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1093 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1094 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1095 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1096 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1097 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1098 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1099 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1100 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1101};
1102
1103static const u8 single_channel_strength_multiplier[] = {
1104 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1105 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1106 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1107 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1108 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1109 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1110 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1111 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1112 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1113 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1114 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1115 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1116 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1117 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1118 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1119 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1120 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1121 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1122 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1123 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1124 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1125 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1126 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1127 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1128};
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001129#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001130static const u8 dual_channel_strength_multiplier[] = {
1131 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1132 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1133 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1134 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1135 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1136 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1137 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1138 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1139 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1140 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1141 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1142 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1143 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1144 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1145 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1146 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1147 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1148 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1149 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1150 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1151 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1152 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1153 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1154 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1155};
1156
1157static const u8 single_channel_strength_multiplier[] = {
1158 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1159 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1160 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1161 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1162 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1163 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1164 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1165 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1166 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1167 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1168 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1169 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1170 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1171 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1172 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1173 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1174 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1175 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1176 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1177 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1178 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1179 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1180 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1181 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1182};
1183#endif
1184
Stefan Reinauer278534d2008-10-29 04:51:07 +00001185static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1186{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001187 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001188 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001189
1190 /* Set Strength Multipliers */
1191
1192 /* Dual Channel needs different tables. */
1193 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001194 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001195 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001196 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001197 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1198 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001199 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001200 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001201 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001202 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1203 }
1204
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001205 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001206
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001207 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1208 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1209 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1210 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1211 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1212 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1213 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1214 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001215
1216 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001217 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1218 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1219 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001220
Stefan Reinauer278534d2008-10-29 04:51:07 +00001221 sdram_write_slew_rates(G3SRPUT, ctl3220);
1222 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001223 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001224 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001225 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1226 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1227 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001228
1229 /* Channel 1 */
1230 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001231 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1232 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001233 } else {
1234 sdram_write_slew_rates(G7SRPUT, nc);
1235 sdram_write_slew_rates(G8SRPUT, nc);
1236 }
1237}
1238
1239static void sdram_enable_rcomp(void)
1240{
1241 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001242 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001243 udelay(300);
1244 reg32 = MCHBAR32(GBRCOMPCTL);
1245 reg32 &= ~(1 << 23);
1246 MCHBAR32(GBRCOMPCTL) = reg32;
1247}
1248
1249static void sdram_program_dll_timings(struct sys_info *sysinfo)
1250{
1251 u32 chan0dll = 0, chan1dll = 0;
1252 int i;
1253
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001254 printk(BIOS_DEBUG, "Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001255
Stefan Reinauer278534d2008-10-29 04:51:07 +00001256 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1257 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1258
1259 /* We drive both channels with the same speed */
1260 switch (sysinfo->memory_frequency) {
1261 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1262 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1263 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1264 }
1265
1266 for (i=0; i < 4; i++) {
1267 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1268 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1269 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1270 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1271 }
1272}
1273
1274static void sdram_force_rcomp(void)
1275{
1276 u32 reg32;
1277 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001278
Stefan Reinauer278534d2008-10-29 04:51:07 +00001279 reg32 = MCHBAR32(ODTC);
1280 reg32 |= (1 << 28);
1281 MCHBAR32(ODTC) = reg32;
1282
1283 reg32 = MCHBAR32(SMSRCTL);
1284 reg32 |= (1 << 0);
1285 MCHBAR32(SMSRCTL) = reg32;
1286
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001287 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001288 reg32 = MCHBAR32(GBRCOMPCTL);
1289 reg32 |= (1 << 8);
1290 MCHBAR32(GBRCOMPCTL) = reg32;
1291
1292 reg8 = i945_silicon_revision();
1293 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001294
Stefan Reinauer278534d2008-10-29 04:51:07 +00001295 reg32 = MCHBAR32(GBRCOMPCTL);
1296 reg32 |= (3 << 5);
1297 MCHBAR32(GBRCOMPCTL) = reg32;
1298 }
1299}
1300
1301static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1302{
1303 u8 reg8;
1304 u32 reg32;
1305
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001306 printk(BIOS_DEBUG, "Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001307 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001308 reg8 = MCHBAR8(C0HCTC);
1309 reg8 &= ~0x1f;
1310 reg8 |= ( 1 << 0);
1311 MCHBAR8(C0HCTC) = reg8;
1312
1313 reg8 = MCHBAR8(C1HCTC);
1314 reg8 &= ~0x1f;
1315 reg8 |= ( 1 << 0);
1316 MCHBAR8(C1HCTC) = reg8;
1317
Stefan Reinauer278534d2008-10-29 04:51:07 +00001318 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1319 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1320
1321 MCHBAR8(C0WDLLCMC) = 0;
1322 MCHBAR8(C1WDLLCMC) = 0;
1323
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001324 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001325 sdram_program_dram_width(sysinfo);
1326
1327 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1328
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001329 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001330 reg32 = MCHBAR32(GBRCOMPCTL);
1331 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1332 reg32 |= (3 << 27) | (3 << 0);
1333 MCHBAR32(GBRCOMPCTL) = reg32;
1334
1335 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1336
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001337 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001338 sdram_program_dll_timings(sysinfo);
1339
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001340 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001341 sdram_force_rcomp();
1342}
1343
1344static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1345{
1346 u32 reg32;
1347
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001348 printk(BIOS_DEBUG, "Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001349
Stefan Reinauer278534d2008-10-29 04:51:07 +00001350 reg32 = MCHBAR32(RCVENMT);
1351 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001352 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001353
1354 reg32 |= (1 << 11) | (1 << 9);
1355 MCHBAR32(RCVENMT) = reg32;
1356
1357 reg32 = MCHBAR32(DRTST);
1358 reg32 |= (1 << 3) | (1 << 2);
1359 MCHBAR32(DRTST) = reg32;
1360
1361 reg32 = MCHBAR32(DRTST);
1362 reg32 |= (1 << 6) | (1 << 4);
1363 MCHBAR32(DRTST) = reg32;
1364
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001365 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001366
1367 reg32 = MCHBAR32(DRTST);
1368
1369 /* Is channel 0 populated? */
1370 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1371 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1372 reg32 |= (1 << 7) | (1 << 5);
1373 else
1374 reg32 |= (1 << 31);
1375
1376 /* Is channel 1 populated? */
1377 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1378 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1379 reg32 |= (1 << 9) | (1 << 8);
1380 else
1381 reg32 |= (1 << 30);
1382
1383 MCHBAR32(DRTST) = reg32;
1384
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001385 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001386 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1387 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1388 reg32 = MCHBAR32(C0DRC1);
1389 reg32 |= (1 << 8);
1390 MCHBAR32(C0DRC1) = reg32;
1391 }
1392 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1393 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1394 reg32 = MCHBAR32(C1DRC1);
1395 reg32 |= (1 << 8);
1396 MCHBAR32(C1DRC1) = reg32;
1397 }
1398}
1399
1400struct dimm_size {
1401 unsigned long side1;
1402 unsigned long side2;
1403};
1404
Sven Schnelle541269b2011-02-21 09:39:17 +00001405static struct dimm_size sdram_get_dimm_size(struct sys_info *sysinfo, u16 dimmno)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001406{
1407 /* Calculate the log base 2 size of a DIMM in bits */
1408 struct dimm_size sz;
Sven Schnelle541269b2011-02-21 09:39:17 +00001409 int value, low, rows, columns, device;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001410
Sven Schnelle541269b2011-02-21 09:39:17 +00001411 device = get_dimm_spd_address(sysinfo, dimmno);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001412 sz.side1 = 0;
1413 sz.side2 = 0;
1414
1415 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1416 if (rows < 0) goto hw_err;
1417 if ((rows & 0xf) == 0) goto val_err;
1418 sz.side1 += rows & 0xf;
1419
1420 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1421 if (columns < 0) goto hw_err;
1422 if ((columns & 0xf) == 0) goto val_err;
1423 sz.side1 += columns & 0xf;
1424
1425 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1426 if (value < 0) goto hw_err;
1427 if ((value & 0xff) == 0) goto val_err;
1428 sz.side1 += log2(value & 0xff);
1429
1430 /* Get the module data width and convert it to a power of two */
1431 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1432 if (value < 0) goto hw_err;
1433 value &= 0xff;
1434 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001435
Stefan Reinauer278534d2008-10-29 04:51:07 +00001436 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1437 if (low < 0) goto hw_err;
1438 value = value | (low & 0xff);
1439 if ((value != 72) && (value != 64)) goto val_err;
1440 sz.side1 += log2(value);
1441
1442 /* side 2 */
1443 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1444
1445 if (value < 0) goto hw_err;
1446 value &= 7;
1447 value++;
1448 if (value == 1) goto out;
1449 if (value != 2) goto val_err;
1450
1451 /* Start with the symmetrical case */
1452 sz.side2 = sz.side1;
1453
1454 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1455
1456 /* Don't die here, I have not come across any of these to test what
1457 * actually happens.
1458 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001459 printk(BIOS_ERR, "Assymetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001460
1461 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1462 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1463
1464 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1465 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1466
1467 goto out;
1468
1469 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001470 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001471 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001472 /* If a hardware error occurs the spd rom probably does not exist.
1473 * In this case report that there is no memory
1474 */
1475 sz.side1 = 0;
1476 sz.side2 = 0;
Patrick Georgic5fc7db2012-03-07 15:55:47 +01001477out:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001478 return sz;
1479}
1480
1481static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1482{
1483 int i;
1484
1485 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1486 struct dimm_size sz;
1487
1488 sysinfo->banksize[i * 2] = 0;
1489 sysinfo->banksize[(i * 2) + 1] = 0;
1490
1491 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1492 continue;
1493
Sven Schnelle541269b2011-02-21 09:39:17 +00001494 sz = sdram_get_dimm_size(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001495
Sven Schnelle541269b2011-02-21 09:39:17 +00001496 sysinfo->banks[i] = spd_read_byte(get_dimm_spd_address(sysinfo, i),
1497 SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001498
1499 if (sz.side1 < 30)
1500 die("DDR-II rank size smaller than 128MB is not supported.\n");
1501
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001502 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001503
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001504 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001505
Stefan Reinauer278534d2008-10-29 04:51:07 +00001506 if (!sz.side2)
1507 continue;
1508
1509 /* If there is a second side, it has to have at least 128M, too */
1510 if (sz.side2 < 30)
1511 die("DDR-II rank size smaller than 128MB is not supported.\n");
1512
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001513 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001514
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001515 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001516 }
1517}
1518
1519static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1520{
1521 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001522 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001523
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001524 printk(BIOS_DEBUG, "Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001525
1526 cum0 = 0;
1527 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001528 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001529 MCHBAR8(C0DRB0+i) = cum0;
1530 }
1531
1532 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1533 cum1 = cum0;
1534
1535 /* Exception: Interleaved starts from the beginning */
1536 if (sysinfo->interleaved)
1537 cum1 = 0;
1538
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001539#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001540 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1541 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1542 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1543 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001544#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001545
1546 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001547 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001548 MCHBAR8(C1DRB0+i) = cum1;
1549 }
1550
1551 /* Set TOLUD Top Of Low Usable DRAM */
1552 if (sysinfo->interleaved)
1553 tolud = (cum0 + cum1) << 1;
1554 else
1555 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001556
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001557 /* The TOM register has a different format */
1558 tom = tolud >> 3;
1559
1560 /* Limit the value of TOLUD to leave some space for PCI memory. */
1561 if (tolud > 0xd0)
1562 tolud = 0xd0; /* 3.25GB : 0.75GB */
1563
1564 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1565
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001566 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1567 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1568 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001569
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001570 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001571
1572 return 0;
1573}
1574
Stefan Reinauer278534d2008-10-29 04:51:07 +00001575static int sdram_set_row_attributes(struct sys_info *sysinfo)
1576{
1577 int i, value;
1578 u16 dra0=0, dra1=0, dra = 0;
1579
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001580 printk(BIOS_DEBUG, "Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001581 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1582 u16 device;
1583 u8 columnsrows;
1584
1585 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1586 continue;
1587 }
1588
Sven Schnelle541269b2011-02-21 09:39:17 +00001589 device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001590
1591 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1592 columnsrows = (value & 0x0f);
1593
1594 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1595 columnsrows |= (value & 0xf) << 4;
1596
1597 switch (columnsrows) {
1598 case 0x9d: dra = 2; break;
1599 case 0xad: dra = 3; break;
1600 case 0xbd: dra = 4; break;
1601 case 0xae: dra = 3; break;
1602 case 0xbe: dra = 4; break;
1603 default: die("Unsupported Rows/Columns. (DRA)");
1604 }
1605
1606 /* Double Sided DIMMs? */
1607 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1608 dra = (dra << 4) | dra;
1609 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001610
Stefan Reinauer278534d2008-10-29 04:51:07 +00001611 if (i < DIMM_SOCKETS)
1612 dra0 |= (dra << (i*8));
1613 else
1614 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1615 }
1616
1617 MCHBAR16(C0DRA0) = dra0;
1618 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001619
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001620 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1621 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001622
1623 return 0;
1624}
1625
1626static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1627{
1628 u32 off32;
1629 int i;
1630
1631 MCHBAR16(C1BNKARC) &= 0xff00;
1632 MCHBAR16(C0BNKARC) &= 0xff00;
1633
1634 off32 = C0BNKARC;
1635 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1636 /* Switch to second channel */
1637 if (i == DIMM_SOCKETS)
1638 off32 = C1BNKARC;
1639
1640 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1641 continue;
1642
1643 if (sysinfo->banks[i] != 8)
1644 continue;
1645
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001646 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001647
1648 if (i & 1)
1649 MCHBAR16(off32) |= 0x50;
1650 else
1651 MCHBAR16(off32) |= 0x05;
1652 }
1653}
1654
1655#define REFRESH_7_8US 1
1656#define REFRESH_15_6US 0
1657static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1658{
1659 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001660
Stefan Reinauer278534d2008-10-29 04:51:07 +00001661 if (sysinfo->refresh == REFRESH_7_8US) {
1662 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1663 } else {
1664 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1665 }
1666
1667 MCHBAR32(C0DRC0) &= ~(7 << 8);
1668 MCHBAR32(C0DRC0) |= reg32;
1669
1670 MCHBAR32(C1DRC0) &= ~(7 << 8);
1671 MCHBAR32(C1DRC0) |= reg32;
1672}
1673
1674static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1675{
1676 u32 reg32;
1677 int i;
1678
1679 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001680
Stefan Reinauer278534d2008-10-29 04:51:07 +00001681 for (i=0; i < 4; i++) {
1682 if (sysinfo->banksize[i] == 0) {
1683 reg32 |= (1 << (16 + i));
1684 }
1685 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001686
Stefan Reinauer278534d2008-10-29 04:51:07 +00001687 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001688
Stefan Reinauer278534d2008-10-29 04:51:07 +00001689 reg32 |= (1 << 11);
1690 MCHBAR32(C0DRC1) = reg32;
1691
1692 /* Do we have to do this if we're in Single Channel Mode? */
1693 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001694
Stefan Reinauer278534d2008-10-29 04:51:07 +00001695 for (i=4; i < 8; i++) {
1696 if (sysinfo->banksize[i] == 0) {
1697 reg32 |= (1 << (12 + i));
1698 }
1699 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001700
Stefan Reinauer278534d2008-10-29 04:51:07 +00001701 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001702
Stefan Reinauer278534d2008-10-29 04:51:07 +00001703 reg32 |= (1 << 11);
1704 MCHBAR32(C1DRC1) = reg32;
1705}
1706
1707static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1708{
1709 u32 reg32;
1710 int i;
1711
1712 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001713
Stefan Reinauer278534d2008-10-29 04:51:07 +00001714 for (i=0; i < 4; i++) {
1715 if (sysinfo->banksize[i] == 0) {
1716 reg32 |= (1 << (24 + i));
1717 }
1718 }
1719 MCHBAR32(C0DRC2) = reg32;
1720
1721 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001722
Stefan Reinauer278534d2008-10-29 04:51:07 +00001723 for (i=4; i < 8; i++) {
1724 if (sysinfo->banksize[i] == 0) {
1725 reg32 |= (1 << (20 + i));
1726 }
1727 }
1728 MCHBAR32(C1DRC2) = reg32;
1729}
1730
1731static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1732{
1733 u32 reg32, off32;
1734 u32 tWTR;
1735 u32 temp_drt;
1736 int i, page_size;
1737
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001738 static const u8 drt0_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001739 /* CL 3, 4, 5 */
1740 3, 4, 5, /* FSB533/400, DDR533/400 */
1741 4, 5, 6, /* FSB667, DDR533/400 */
1742 4, 5, 6, /* FSB667, DDR667 */
1743 };
1744
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001745 static const u8 cas_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001746 2, 1, 0, 3
1747 };
1748
1749 reg32 = MCHBAR32(C0DRC0);
1750 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001751 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001752 MCHBAR32(C0DRC0) = reg32;
1753
1754 reg32 = MCHBAR32(C1DRC0);
1755 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001756 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001757 MCHBAR32(C1DRC0) = reg32;
1758
1759 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1760 SYSINFO_DIMM_NOT_POPULATED) {
1761 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001762 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001763 MCHBAR32(C0DRC0) = reg32;
1764 }
1765
1766 sdram_program_refresh_rate(sysinfo);
1767
1768 sdram_program_cke_tristate(sysinfo);
1769
1770 sdram_program_odt_tristate(sysinfo);
1771
1772 /* Calculate DRT0 */
1773
1774 temp_drt = 0;
1775
1776 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1777 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1778 temp_drt |= (reg32 << 28);
1779
1780 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1781 reg32 += sysinfo->trp;
1782 temp_drt |= (reg32 << 4);
1783
1784 if (sysinfo->memory_frequency == 667) {
1785 tWTR = 3; /* 667MHz */
1786 } else {
1787 tWTR = 2; /* 400 and 533 */
1788 }
1789
1790 /* B2B Write to Read Command Spacing */
1791 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1792 temp_drt |= (reg32 << 24);
1793
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001794 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001795 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1796
1797 /* Program Write Auto Precharge to Activate */
1798 off32 = 0;
1799 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1800 off32 += 3;
1801 }
1802 if (sysinfo->memory_frequency == 667) {
1803 off32 += 3;
1804 }
1805 off32 += sysinfo->cas - 3;
1806 reg32 = drt0_table[off32];
1807 temp_drt |= (reg32 << 11);
1808
1809 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001810
Stefan Reinauer278534d2008-10-29 04:51:07 +00001811 temp_drt |= (8 << 0);
1812
1813 MCHBAR32(C0DRT0) = temp_drt;
1814 MCHBAR32(C1DRT0) = temp_drt;
1815
1816 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001817
Stefan Reinauer278534d2008-10-29 04:51:07 +00001818 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1819
1820 /* DRAM RASB Precharge */
1821 temp_drt |= (sysinfo->trp - 2) << 0;
1822
1823 /* DRAM RASB to CASB Delay */
1824 temp_drt |= (sysinfo->trcd - 2) << 4;
1825
1826 /* CASB Latency */
1827 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1828
1829 /* Refresh Cycle Time */
1830 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001831
Stefan Reinauer278534d2008-10-29 04:51:07 +00001832 /* Pre-All to Activate Delay */
1833 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001834
Stefan Reinauer278534d2008-10-29 04:51:07 +00001835 /* Precharge to Precharge Delay stays at 1 clock */
1836 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001837
Stefan Reinauer278534d2008-10-29 04:51:07 +00001838 /* Activate to Precharge Delay */
1839 temp_drt |= (sysinfo->tras << 19);
1840
1841 /* Read to Precharge (tRTP) */
1842 if (sysinfo->memory_frequency == 667) {
1843 temp_drt |= (1 << 28);
1844 } else {
1845 temp_drt |= (0 << 28);
1846 }
1847
1848 /* Determine page size */
1849 reg32 = 0;
1850 page_size = 1; /* Default: 1k pagesize */
1851 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1852 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1853 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1854 page_size = 2; /* 2k pagesize */
1855 }
1856
1857 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1858 reg32 = 1;
1859 }
1860 if (sysinfo->memory_frequency == 667) {
1861 reg32 = page_size;
1862 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001863
Stefan Reinauer278534d2008-10-29 04:51:07 +00001864 temp_drt |= (reg32 << 30);
1865
1866 MCHBAR32(C0DRT1) = temp_drt;
1867 MCHBAR32(C1DRT1) = temp_drt;
1868
1869 /* Program DRT2 */
1870 reg32 = MCHBAR32(C0DRT2);
1871 reg32 &= ~(1 << 8);
1872 MCHBAR32(C0DRT2) = reg32;
1873
1874 reg32 = MCHBAR32(C1DRT2);
1875 reg32 &= ~(1 << 8);
1876 MCHBAR32(C1DRT2) = reg32;
1877
1878 /* Calculate DRT3 */
1879 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1880
1881 /* Get old tRFC value */
1882 reg32 = MCHBAR32(C0DRT1) >> 10;
1883 reg32 &= 0x3f;
1884
1885 /* 788nS - tRFC */
1886 switch (sysinfo->memory_frequency) {
1887 case 400: /* 5nS */
1888 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1889 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1890 break;
1891 case 533: /* 3.75nS */
1892 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1893 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1894 break;
1895 case 667: /* 3nS */
1896 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1897 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1898 break;
1899 }
1900
1901 temp_drt |= reg32;
1902
1903 MCHBAR32(C0DRT3) = temp_drt;
1904 MCHBAR32(C1DRT3) = temp_drt;
1905}
1906
1907static void sdram_set_channel_mode(struct sys_info *sysinfo)
1908{
1909 u32 reg32;
1910
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001911 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001912
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001913 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001914 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1915 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1916 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1917 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1918 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001919 sysinfo->interleaved = 1;
1920 } else {
1921 sysinfo->interleaved = 0;
1922 }
1923
1924 reg32 = MCHBAR32(DCC);
1925 reg32 &= ~(7 << 0);
1926
1927 if(sysinfo->interleaved) {
1928 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001929 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001930 reg32 |= (1 << 1);
1931 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1932 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1933 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001934 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001935 reg32 |= (1 << 2);
1936 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1937 SYSINFO_DIMM_NOT_POPULATED) {
1938 /* Dual Channel Assymetric */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001939 printk(BIOS_DEBUG, "Dual Channel Assymetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001940 reg32 |= (1 << 0);
1941 } else {
1942 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001943 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001944 }
1945
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001946 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001947 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001948
1949 MCHBAR32(DCC) = reg32;
1950
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001951 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001952}
1953
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001954static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001955{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001956 MCHBAR32(PLLMON) = 0x80800000;
1957
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001958 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001959 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001960 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001961
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001962 /* Program CPCTL according to FSB speed */
1963 /* Only write the lower byte */
1964 switch (sysinfo->fsb_frequency) {
1965 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1966 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1967 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1968 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001969
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001970 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001971
Paul Menzel0ce5ebf2013-10-21 21:22:09 +02001972 MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001973}
1974
1975static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1976{
1977 u8 reg8;
1978 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001979 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001980
1981#define CRCLK_166MHz 0x00
1982#define CRCLK_200MHz 0x01
1983#define CRCLK_250MHz 0x03
1984#define CRCLK_400MHz 0x05
1985
1986#define CDCLK_200MHz 0x00
1987#define CDCLK_320MHz 0x40
1988
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001989#define VOLTAGE_1_05 0x00
1990#define VOLTAGE_1_50 0x01
1991
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001992 printk(BIOS_DEBUG, "Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001993
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001994 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001995
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001996 voltage = VOLTAGE_1_05;
1997 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1998 voltage = VOLTAGE_1_50;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001999 printk(BIOS_DEBUG, "Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002000
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002001 /* Gate graphics hardware for frequency change */
2002 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
2003 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
2004 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002005
2006 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002007 reg8 = sdram_capabilities_core_frequencies();
2008
Stefan Reinauer278534d2008-10-29 04:51:07 +00002009 freq = CRCLK_250MHz;
2010 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002011 case GFX_FREQUENCY_CAP_ALL:
2012 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002013 freq = CRCLK_250MHz;
2014 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002015 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002016 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002017 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2018 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2019 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002020 }
2021
2022 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002023 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002024 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
2025 if (reg8==2)
2026 freq = CRCLK_166MHz;
2027 }
2028
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002029 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002030 switch (freq) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002031 case CRCLK_166MHz: printk(BIOS_DEBUG, "166Mhz"); break;
2032 case CRCLK_200MHz: printk(BIOS_DEBUG, "200Mhz"); break;
2033 case CRCLK_250MHz: printk(BIOS_DEBUG, "250Mhz"); break;
2034 case CRCLK_400MHz: printk(BIOS_DEBUG, "400Mhz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002035 }
2036
Stefan Reinauer278534d2008-10-29 04:51:07 +00002037 if (i945_silicon_revision() == 0) {
2038 sysinfo->mvco4x = 1;
2039 } else {
2040 sysinfo->mvco4x = 0;
2041 }
2042
Stefan Reinauer278534d2008-10-29 04:51:07 +00002043 second_vco = 0;
2044
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002045 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002046 second_vco = 1;
2047 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2048 u16 mem = sysinfo->memory_frequency;
2049 u16 fsb = sysinfo->fsb_frequency;
2050
2051 if ( (fsb == 667 && mem == 533) ||
2052 (fsb == 533 && mem == 533) ||
2053 (fsb == 533 && mem == 400)) {
2054 second_vco = 1;
2055 }
2056
2057 if (fsb == 667 && mem == 533)
2058 sysinfo->mvco4x = 1;
2059 }
2060
2061 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002062 sysinfo->clkcfg_bit7=1;
2063 } else {
2064 sysinfo->clkcfg_bit7=0;
2065 }
2066
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002067 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002068 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2069 reg16 &= ~( (7 << 0) | (1 << 13) );
2070 reg16 |= freq;
2071 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2072
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002073 /* Graphics Core Display Clock */
2074 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2075 reg8 &= ~( (1<<7) | (7<<4) );
2076
2077 if (voltage == VOLTAGE_1_05) {
2078 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002079 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002080 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002081 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002082 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002083 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002084 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002085
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002086 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002087
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002088 reg8 |= (1<<3) | (1<<1);
2089 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2090
2091 reg8 |= 0x0f;
2092 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2093
2094 /* Ungate core render and display clocks */
2095 reg8 &= 0xf0;
2096 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002097}
2098
2099static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2100{
2101 u32 clkcfg;
2102 u8 reg8;
2103
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002104 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002105
Stefan Reinauer278534d2008-10-29 04:51:07 +00002106 clkcfg = MCHBAR32(CLKCFG);
2107
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002108 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002109
2110 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2111
2112 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002113 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002114 clkcfg &= ~(1 << 12);
2115 }
2116
2117 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002118 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002119
Stefan Reinauer278534d2008-10-29 04:51:07 +00002120 clkcfg |= (1 << 7);
2121 }
2122
2123 switch (sysinfo->memory_frequency) {
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002124 case 400: clkcfg |= (2 << 4); break;
2125 case 533: clkcfg |= (3 << 4); break;
2126 case 667: clkcfg |= (4 << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002127 default: die("Target Memory Frequency Error");
2128 }
2129
2130 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002131 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002132 return;
2133 }
2134
2135 MCHBAR32(CLKCFG) = clkcfg;
2136
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002137 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002138 * cache before we execute it.
2139 */
2140 goto cache_code;
2141vco_update:
2142 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2143 reg8 &= ~(1 << 7);
2144 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2145
Stefan Reinauer278534d2008-10-29 04:51:07 +00002146 clkcfg &= ~(1 << 10);
2147 MCHBAR32(CLKCFG) = clkcfg;
2148 clkcfg |= (1 << 10);
2149 MCHBAR32(CLKCFG) = clkcfg;
2150
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002151 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002152 " movl $0x100, %%ecx\n"
2153 "delay_update:\n"
2154 " nop\n"
2155 " nop\n"
2156 " nop\n"
2157 " nop\n"
2158 " loop delay_update\n"
2159 : /* No outputs */
2160 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002161 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002162 );
2163
Stefan Reinauer278534d2008-10-29 04:51:07 +00002164 clkcfg &= ~(1 << 10);
2165 MCHBAR32(CLKCFG) = clkcfg;
2166
2167 goto out;
2168cache_code:
2169 goto vco_update;
2170out:
2171
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002172 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
2173 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002174}
2175
2176static void sdram_program_clock_crossing(void)
2177{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002178 int idx = 0;
2179
2180 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002181 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002182 */
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002183#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002184 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002185 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002186 0xffffffff, 0xffffffff, /* nonexistant */
2187 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002188
Stefan Reinauer278534d2008-10-29 04:51:07 +00002189 0x08040120, 0x00000000, /* DDR400 FSB533 */
2190 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002191 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002192
2193 0x04020120, 0x00000010, /* DDR400 FSB667 */
2194 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002195 0x00100401, 0x00000000, /* DDR667 FSB667 */
2196
2197 0xffffffff, 0xffffffff, /* nonexistant */
2198 0xffffffff, 0xffffffff, /* nonexistant */
2199 0xffffffff, 0xffffffff, /* nonexistant */
2200
2201 0xffffffff, 0xffffffff, /* nonexistant */
2202 0xffffffff, 0xffffffff, /* nonexistant */
2203 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002204 };
2205
2206 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002207 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002208 0xffffffff, 0xffffffff, /* nonexistant */
2209 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002210
Stefan Reinauer278534d2008-10-29 04:51:07 +00002211 0x00060108, 0x00000000, /* DDR400 FSB533 */
2212 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002213 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002214
2215 0x00040318, 0x00000000, /* DDR400 FSB667 */
2216 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002217 0x02010804, 0x00000000, /* DDR667 FSB667 */
2218
2219 0xffffffff, 0xffffffff, /* nonexistant */
2220 0xffffffff, 0xffffffff, /* nonexistant */
2221 0xffffffff, 0xffffffff, /* nonexistant */
2222
2223 0xffffffff, 0xffffffff, /* nonexistant */
2224 0xffffffff, 0xffffffff, /* nonexistant */
2225 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002226 };
2227
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002228#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002229 /* i945 G/P */
2230 static const u32 data_clock_crossing[] = {
2231 0xffffffff, 0xffffffff, /* nonexistant */
2232 0xffffffff, 0xffffffff, /* nonexistant */
2233 0xffffffff, 0xffffffff, /* nonexistant */
2234
2235 0x10080201, 0x00000000, /* DDR400 FSB533 */
2236 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002237 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002238
2239 0xffffffff, 0xffffffff, /* nonexistant */
2240 0xffffffff, 0xffffffff, /* nonexistant */
2241 0xffffffff, 0xffffffff, /* nonexistant */
2242
2243 0x04020108, 0x00000000, /* DDR400 FSB800 */
2244 0x00020108, 0x00000000, /* DDR533 FSB800 */
2245 0x00080201, 0x00000000, /* DDR667 FSB800 */
2246
2247 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2248 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2249 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2250 };
2251
2252 static const u32 command_clock_crossing[] = {
2253 0xffffffff, 0xffffffff, /* nonexistant */
2254 0xffffffff, 0xffffffff, /* nonexistant */
2255 0xffffffff, 0xffffffff, /* nonexistant */
2256
2257 0x00010800, 0x00000402, /* DDR400 FSB533 */
2258 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002259 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002260
2261 0xffffffff, 0xffffffff, /* nonexistant */
2262 0xffffffff, 0xffffffff, /* nonexistant */
2263 0xffffffff, 0xffffffff, /* nonexistant */
2264
2265 0x02010804, 0x00000000, /* DDR400 FSB800 */
2266 0x00010402, 0x00000000, /* DDR533 FSB800 */
2267 0x04020180, 0x00000008, /* DDR667 FSB800 */
2268
2269 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2270 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2271 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2272 };
2273#endif
2274
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002275 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002276
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002277 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002278 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002279 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2280 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2281 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2282 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002283 }
2284
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002285 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002286 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002287 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2288 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2289 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2290 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2291 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2292 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002293 }
2294
2295 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002296 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002297 }
2298
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002299 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2300 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2301
Stefan Reinauer278534d2008-10-29 04:51:07 +00002302 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2303 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2304 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2305 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2306
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002307 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002308}
2309
2310static void sdram_disable_fast_dispatch(void)
2311{
2312 u32 reg32;
2313
2314 reg32 = MCHBAR32(FSBPMC3);
2315 reg32 |= (1 << 1);
2316 MCHBAR32(FSBPMC3) = reg32;
2317
2318 reg32 = MCHBAR32(SBTEST);
2319 reg32 |= (3 << 1);
2320 MCHBAR32(SBTEST) = reg32;
2321}
2322
2323static void sdram_pre_jedec_initialization(void)
2324{
2325 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002326
Stefan Reinauer278534d2008-10-29 04:51:07 +00002327 reg32 = MCHBAR32(WCC);
2328 reg32 &= 0x113ff3ff;
2329 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2330 MCHBAR32(WCC) = reg32;
2331
2332 MCHBAR32(SMVREFC) |= (1 << 6);
2333
2334 MCHBAR32(MMARB0) &= ~(3 << 17);
2335 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2336
2337 MCHBAR32(MMARB1) &= ~(7 << 8);
2338 MCHBAR32(MMARB1) |= (3 << 8);
2339
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002340 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002341 MCHBAR32(C0AIT) = 0x000006c4;
2342 MCHBAR32(C0AIT+4) = 0x871a066d;
2343
2344 MCHBAR32(C1AIT) = 0x000006c4;
2345 MCHBAR32(C1AIT+4) = 0x871a066d;
2346}
2347
2348#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2349#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2350#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2351#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2352#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2353#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2354#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2355#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2356
2357static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2358{
2359 u32 chan0 = 0, chan1 = 0;
2360 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2361
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002362 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002363 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002364 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002365 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2366 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2367 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2368
2369 if (sdram_capabilities_enhanced_addressing_xor()) {
2370 if (!sysinfo->interleaved) {
2371 /* Single Channel & Dual Channel Assymetric */
2372 if (chan0_populated) {
2373 if (chan0_dualsided) {
2374 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2375 } else {
2376 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2377 }
2378 }
2379 if (chan1_populated) {
2380 if (chan1_dualsided) {
2381 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2382 } else {
2383 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2384 }
2385 }
2386 } else {
2387 /* Interleaved has always both channels populated */
2388 if (chan0_dualsided) {
2389 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2390 } else {
2391 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2392 }
2393
2394 if (chan1_dualsided) {
2395 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2396 } else {
2397 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2398 }
2399 }
2400 } else {
2401 if (!sysinfo->interleaved) {
2402 /* Single Channel & Dual Channel Assymetric */
2403 if (chan0_populated) {
2404 if (chan0_dualsided) {
2405 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2406 } else {
2407 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2408 }
2409 }
2410 if (chan1_populated) {
2411 if (chan1_dualsided) {
2412 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2413 } else {
2414 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2415 }
2416 }
2417 } else {
2418 /* Interleaved has always both channels populated */
2419 if (chan0_dualsided) {
2420 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2421 } else {
2422 chan0 = EA_DUALCHANNEL_BANK_MODE;
2423 }
2424
2425 if (chan1_dualsided) {
2426 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2427 } else {
2428 chan1 = EA_DUALCHANNEL_BANK_MODE;
2429 }
2430 }
2431 }
2432
2433 MCHBAR32(C0DRC1) &= 0x00ffffff;
2434 MCHBAR32(C0DRC1) |= chan0;
2435 MCHBAR32(C1DRC1) &= 0x00ffffff;
2436 MCHBAR32(C1DRC1) |= chan1;
2437}
2438
2439static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2440{
2441 u32 reg32;
2442
2443 /* Enable Channel XORing for Dual Channel Interleave */
2444 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002445
Stefan Reinauer278534d2008-10-29 04:51:07 +00002446 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002447#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002448 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002449 reg32 |= (1 << 9);
2450#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002451 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002452#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002453 MCHBAR32(DCC) = reg32;
2454 }
2455
2456 /* DRAM mode optimizations */
2457 sdram_enhanced_addressing_mode(sysinfo);
2458
2459 reg32 = MCHBAR32(FSBPMC3);
2460 reg32 &= ~(1 << 1);
2461 MCHBAR32(FSBPMC3) = reg32;
2462
2463 reg32 = MCHBAR32(SBTEST);
2464 reg32 &= ~(1 << 2);
2465 MCHBAR32(SBTEST) = reg32;
2466
2467 reg32 = MCHBAR32(SBOCC);
2468 reg32 &= 0xffbdb6ff;
2469 reg32 |= (0xbdb6 << 8) | (1 << 0);
2470 MCHBAR32(SBOCC) = reg32;
2471}
2472
2473static void sdram_power_management(struct sys_info *sysinfo)
2474{
2475 u8 reg8;
2476 u16 reg16;
2477 u32 reg32;
2478 int integrated_graphics = 1;
2479 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002480
Stefan Reinauer278534d2008-10-29 04:51:07 +00002481 reg32 = MCHBAR32(C0DRT2);
2482 reg32 &= 0xffffff00;
2483 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002484 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002485 MCHBAR32(C0DRT2) = reg32;
2486
2487 reg32 = MCHBAR32(C1DRT2);
2488 reg32 &= 0xffffff00;
2489 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002490 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002491 MCHBAR32(C1DRT2) = reg32;
2492
2493 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002494
2495 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002496 MCHBAR32(C0DRC1) = reg32;
2497
2498 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002499
2500 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002501 MCHBAR32(C1DRC1) = reg32;
2502
2503 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002504 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2505 u16 peg_bits = (1 << 5) | (1 << 0);
2506
2507 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002508 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002509 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2510 u16 peg_bits = (1 << 5) | (1 << 0);
2511
Stefan Reinauer278534d2008-10-29 04:51:07 +00002512 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002513 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002514 }
2515
2516 reg16 = MCHBAR16(UPMC2);
2517 reg16 &= 0xfc00;
2518 reg16 |= 0x0100;
2519 MCHBAR16(UPMC2) = reg16;
2520
2521 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002522
Stefan Reinauer278534d2008-10-29 04:51:07 +00002523 for (i=0; i<5; i++) {
2524 MCHBAR32(UPMC3) &= ~(1 << 16);
2525 MCHBAR32(UPMC3) |= (1 << 16);
2526 }
2527
2528 MCHBAR32(GIPMC1) = 0x8000000c;
2529
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002530 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002531 reg16 &= ~(7 << 11);
2532 if (i945_silicon_revision()>2) {
2533 reg16 |= (6 << 11);
2534 } else {
2535 reg16 |= (4 << 11);
2536 }
2537 MCHBAR16(CPCTL) = reg16;
2538
Stefan Reinauer30140a52009-03-11 16:20:39 +00002539#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002540 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002541#else
2542 if (i945_silicon_revision() != 0) {
2543#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002544 switch (sysinfo->fsb_frequency) {
2545 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2546 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2547 }
2548 } else {
2549 switch (sysinfo->fsb_frequency) {
2550 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2551 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2552 }
2553 }
2554
2555 MCHBAR32(FSBPMC1) = 0x8000000c;
2556
2557 reg32 = MCHBAR32(C2C3TT);
2558 reg32 &= 0xffff0000;
2559 switch (sysinfo->fsb_frequency) {
2560 case 667: reg32 |= 0x0600; break;
2561 case 533: reg32 |= 0x0480; break;
2562 }
2563 MCHBAR32(C2C3TT) = reg32;
2564
2565 reg32 = MCHBAR32(C3C4TT);
2566 reg32 &= 0xffff0000;
2567 switch (sysinfo->fsb_frequency) {
2568 case 667: reg32 |= 0x0b80; break;
2569 case 533: reg32 |= 0x0980; break;
2570 }
2571 MCHBAR32(C3C4TT) = reg32;
2572
2573 if (i945_silicon_revision() == 0) {
2574 MCHBAR32(ECO) &= ~(1 << 16);
2575 } else {
2576 MCHBAR32(ECO) |= (1 << 16);
2577 }
2578
2579#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002580
Stefan Reinauer278534d2008-10-29 04:51:07 +00002581 if (i945_silicon_revision() == 0) {
2582 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2583 } else {
2584 MCHBAR32(FSBPMC3) |= (1 << 29);
2585 }
2586#endif
2587 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2588
2589 MCHBAR32(FSBPMC3) |= (1 << 21);
2590
2591 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2592
2593 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2594
2595 reg32 = MCHBAR32(FSBPMC4);
2596 reg32 &= ~(3 << 24);
2597 reg32 |= ( 2 << 24);
2598 MCHBAR32(FSBPMC4) = reg32;
2599
2600 MCHBAR32(FSBPMC4) |= (1 << 21);
2601
2602 MCHBAR32(FSBPMC4) |= (1 << 5);
2603
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002604 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2605 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002606 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2607 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002608 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002609 }
2610
2611 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2612 reg8 |= (1 << 4);
2613 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2614
2615 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2616 reg8 |= (1 << 2);
2617 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2618
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002619#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002620
Stefan Reinauer278534d2008-10-29 04:51:07 +00002621 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002622 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002623 MCHBAR16(MIPMC4) = 0x0468;
2624 MCHBAR16(MIPMC5) = 0x046c;
2625 MCHBAR16(MIPMC6) = 0x046c;
2626 } else {
2627 MCHBAR16(MIPMC4) = 0x6468;
2628 MCHBAR16(MIPMC5) = 0x646c;
2629 MCHBAR16(MIPMC6) = 0x646c;
2630 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002631#else
2632 if (integrated_graphics) {
2633 MCHBAR16(MIPMC4) = 0x04f8;
2634 MCHBAR16(MIPMC5) = 0x04fc;
2635 MCHBAR16(MIPMC6) = 0x04fc;
2636 } else {
2637 MCHBAR16(MIPMC4) = 0x64f8;
2638 MCHBAR16(MIPMC5) = 0x64fc;
2639 MCHBAR16(MIPMC6) = 0x64fc;
2640 }
2641
2642#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002643
2644 reg32 = MCHBAR32(PMCFG);
2645 reg32 &= ~(3 << 17);
2646 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002647 MCHBAR32(PMCFG) = reg32;
2648
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002649 MCHBAR32(PMCFG) |= (1 << 4);
2650
Stefan Reinauer278534d2008-10-29 04:51:07 +00002651 reg32 = MCHBAR32(0xc30);
2652 reg32 &= 0xffffff00;
2653 reg32 |= 0x01;
2654 MCHBAR32(0xc30) = reg32;
2655
2656 MCHBAR32(0xb18) &= ~(1 << 21);
2657}
2658
2659static void sdram_thermal_management(void)
2660{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002661
Stefan Reinauer278534d2008-10-29 04:51:07 +00002662 MCHBAR8(TCO1) = 0x00;
2663 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002664
2665 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2666 * 0x30/0x32.
2667 */
2668
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002669 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002670}
2671
2672static void sdram_save_receive_enable(void)
2673{
2674 int i;
2675 u32 reg32;
2676 u8 values[4];
2677
2678 /* The following values are stored to an unused CMOS
2679 * area and restored instead of recalculated in case
2680 * of an S3 resume.
2681 *
2682 * C0WL0REOST [7:0] -> 8 bit
2683 * C1WL0REOST [7:0] -> 8 bit
2684 * RCVENMT [11:8] [3:0] -> 8 bit
2685 * C0DRT1 [27:24] -> 4 bit
2686 * C1DRT1 [27:24] -> 4 bit
2687 */
2688
2689 values[0] = MCHBAR8(C0WL0REOST);
2690 values[1] = MCHBAR8(C1WL0REOST);
2691
2692 reg32 = MCHBAR32(RCVENMT);
2693 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2694
2695 reg32 = MCHBAR32(C0DRT1);
2696 values[3] = (reg32 >> 24) & 0x0f;
2697 reg32 = MCHBAR32(C1DRT1);
2698 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2699
2700 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002701 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002702 */
2703
2704 for (i=0; i<4; i++)
2705 cmos_write(values[i], 128 + i);
2706}
2707
2708static void sdram_recover_receive_enable(void)
2709{
2710 int i;
2711 u32 reg32;
2712 u8 values[4];
2713
2714 for (i=0; i<4; i++)
2715 values[i] = cmos_read(128 + i);
2716
2717 MCHBAR8(C0WL0REOST) = values[0];
2718 MCHBAR8(C1WL0REOST) = values[1];
2719
2720 reg32 = MCHBAR32(RCVENMT);
2721 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2722 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2723 MCHBAR32(RCVENMT) = reg32;
2724
2725 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2726 reg32 |= (u32)(values[3] & 0x0f) << 24;
2727 MCHBAR32(C0DRT1) = reg32;
2728
2729 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2730 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2731 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002732}
2733
2734#include "rcven.c"
2735
2736static void sdram_program_receive_enable(struct sys_info *sysinfo)
2737{
2738 MCHBAR32(REPC) |= (1 << 0);
2739
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002740 /* enable upper CMOS */
2741 RCBA32(0x3400) = (1 << 2);
2742
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002743 /* Program Receive Enable Timings */
2744 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2745 sdram_recover_receive_enable();
2746 } else {
2747 receive_enable_adjust(sysinfo);
2748 sdram_save_receive_enable();
2749 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002750
2751 MCHBAR32(C0DRC1) |= (1 << 6);
2752 MCHBAR32(C1DRC1) |= (1 << 6);
2753 MCHBAR32(C0DRC1) &= ~(1 << 6);
2754 MCHBAR32(C1DRC1) &= ~(1 << 6);
2755
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002756 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002757}
2758
2759/**
2760 * @brief Enable On-Die Termination for DDR2.
2761 *
2762 */
2763
2764static void sdram_on_die_termination(struct sys_info *sysinfo)
2765{
2766 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002767 0x00024911, 0xe0010000,
2768 0x00049211, 0xe0020000,
2769 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002770 };
2771
2772 u32 reg32;
2773 int cas;
2774
2775 reg32 = MCHBAR32(ODTC);
2776 reg32 &= ~(3 << 16);
2777 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2778 MCHBAR32(ODTC) = reg32;
2779
2780 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2781 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002782 printk(BIOS_DEBUG, "one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002783
Stefan Reinauer278534d2008-10-29 04:51:07 +00002784 reg32 = MCHBAR32(C0ODT);
2785 reg32 &= ~(7 << 28);
2786 MCHBAR32(C0ODT) = reg32;
2787 reg32 = MCHBAR32(C1ODT);
2788 reg32 &= ~(7 << 28);
2789 MCHBAR32(C1ODT) = reg32;
2790 }
2791
2792 cas = sysinfo->cas;
2793
2794 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2795 reg32 |= odt[(cas-3) * 2];
2796 MCHBAR32(C0ODT) = reg32;
2797
2798 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2799 reg32 |= odt[(cas-3) * 2];
2800 MCHBAR32(C1ODT) = reg32;
2801
2802 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2803 reg32 |= odt[((cas-3) * 2) + 1];
2804 MCHBAR32(C0ODT + 4) = reg32;
2805
2806 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2807 reg32 |= odt[((cas-3) * 2) + 1];
2808 MCHBAR32(C1ODT + 4) = reg32;
2809}
2810
2811/**
2812 * @brief Enable clocks to populated sockets
2813 */
2814
2815static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2816{
2817 u8 clocks[2] = { 0, 0 };
2818
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002819#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002820#define CLOCKS_WIDTH 2
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002821#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002822#define CLOCKS_WIDTH 3
2823#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002824 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002825 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002826
2827 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002828 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002829
2830 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002831 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002832
2833 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002834 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002835
Patrick Georgi77d66832010-10-01 08:02:45 +00002836#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002837 /* Usually system firmware turns off system memory clock signals
2838 * to unused SO-DIMM slots to reduce EMI and power consumption.
2839 * However, the Kontron 986LCD-M does not like unused clock
2840 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002841 */
2842
2843 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2844 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002845#endif
2846
2847 MCHBAR8(C0DCLKDIS) = clocks[0];
2848 MCHBAR8(C1DCLKDIS) = clocks[1];
2849}
2850
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002851#define RTT_ODT_NONE 0
2852#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002853#define RTT_ODT_75_OHM (1 << 5)
2854#define RTT_ODT_150_OHM (1 << 9)
2855
2856#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2857
2858#define MRS_CAS_3 (3 << 7)
2859#define MRS_CAS_4 (4 << 7)
2860#define MRS_CAS_5 (5 << 7)
2861
2862#define MRS_TWR_3 (2 << 12)
2863#define MRS_TWR_4 (3 << 12)
2864#define MRS_TWR_5 (4 << 12)
2865
2866#define MRS_BT (1 << 6)
2867
2868#define MRS_BL4 (2 << 3)
2869#define MRS_BL8 (3 << 3)
2870
2871static void sdram_jedec_enable(struct sys_info *sysinfo)
2872{
2873 int i, nonzero;
2874 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2875
2876 for (i = 0, nonzero = -1; i < 8; i++) {
2877 if (sysinfo->banksize[i] == 0) {
2878 continue;
2879 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002880
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002881 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002882 switch (i) {
2883 case 0:
2884 /* Start at address 0 */
2885 bankaddr = 0;
2886 break;
2887 case 4:
2888 if (sysinfo->interleaved) {
2889 bankaddr = 0x40;
2890 break;
2891 }
2892 default:
2893 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002894 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002895 bankaddr += sysinfo->banksize[nonzero] <<
2896 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002897 break;
2898 }
2899 /* No populated bank hit before. Start at address 0 */
2900 bankaddr = 0;
2901 }
2902
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002903 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002904 * for the next offset we have to calculate
2905 */
2906 nonzero = i;
2907
2908 /* Get CAS latency set up */
2909 switch (sysinfo->cas) {
2910 case 5: mrsaddr = MRS_CAS_5; break;
2911 case 4: mrsaddr = MRS_CAS_4; break;
2912 case 3: mrsaddr = MRS_CAS_3; break;
2913 default: die("Jedec Error (CAS).\n");
2914 }
2915
2916 /* Get tWR set */
2917 switch (sysinfo->twr) {
2918 case 5: mrsaddr |= MRS_TWR_5; break;
2919 case 4: mrsaddr |= MRS_TWR_4; break;
2920 case 3: mrsaddr |= MRS_TWR_3; break;
2921 default: die("Jedec Error (tWR).\n");
2922 }
2923
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002924 /* Set "Burst Type" */
2925 mrsaddr |= MRS_BT;
2926
Stefan Reinauer278534d2008-10-29 04:51:07 +00002927 /* Interleaved */
2928 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002929 mrsaddr = mrsaddr << 1;
2930 }
2931
2932 /* Only burst length 8 supported */
2933 mrsaddr |= MRS_BL8;
2934
2935 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002936 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002937 do_ram_command(RAM_COMMAND_NOP);
2938 ram_read32(bankaddr);
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 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002946 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002947 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2948 ram_read32(bankaddr);
2949
2950 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002951 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002952 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2953 ram_read32(bankaddr);
2954
2955 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002956 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002957 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2958 tmpaddr = bankaddr;
2959 if (!sdram_capabilities_dual_channel()) {
2960 tmpaddr |= RTT_ODT_75_OHM;
2961 } else if (sysinfo->interleaved) {
2962 tmpaddr |= (RTT_ODT_150_OHM << 1);
2963 } else {
2964 tmpaddr |= RTT_ODT_150_OHM;
2965 }
2966 ram_read32(tmpaddr);
2967
2968 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002969 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002970 do_ram_command(RAM_COMMAND_MRS);
2971 tmpaddr = bankaddr;
2972 tmpaddr |= mrsaddr;
2973 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002974 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002975 tmpaddr |= (1 << 12);
2976 else
2977 tmpaddr |= (1 << 11);
2978 ram_read32(tmpaddr);
2979
2980 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002981 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002982 do_ram_command(RAM_COMMAND_PRECHARGE);
2983 ram_read32(bankaddr);
2984
2985 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002986 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002987 do_ram_command(RAM_COMMAND_CBR);
2988
2989 /* CBR wants two READs */
2990 ram_read32(bankaddr);
2991 ram_read32(bankaddr);
2992
2993 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002994 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002995 do_ram_command(RAM_COMMAND_MRS);
2996
2997 tmpaddr = bankaddr;
2998 tmpaddr |= mrsaddr;
2999 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003000
Stefan Reinauer278534d2008-10-29 04:51:07 +00003001 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003002 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003003 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003004
Stefan Reinauer278534d2008-10-29 04:51:07 +00003005 tmpaddr = bankaddr;
3006 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003007
Stefan Reinauer278534d2008-10-29 04:51:07 +00003008 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
3009 } else if (sysinfo->interleaved) {
3010 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
3011 } else {
3012 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
3013 }
3014 ram_read32(tmpaddr);
3015
3016 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003017 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003018 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3019
3020 tmpaddr = bankaddr;
3021 if (!sdram_capabilities_dual_channel()) {
3022 tmpaddr |= RTT_ODT_75_OHM;
3023 } else if (sysinfo->interleaved) {
3024 tmpaddr |= (RTT_ODT_150_OHM << 1);
3025 } else {
3026 tmpaddr |= RTT_ODT_150_OHM;
3027 }
3028 ram_read32(tmpaddr);
3029 }
3030}
3031
3032static void sdram_init_complete(void)
3033{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003034 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003035 do_ram_command(RAM_COMMAND_NORMAL);
3036}
3037
3038static void sdram_setup_processor_side(void)
3039{
3040 if (i945_silicon_revision() == 0)
3041 MCHBAR32(FSBPMC3) |= (1 << 2);
3042
3043 MCHBAR8(0xb00) |= 1;
3044
3045 if (i945_silicon_revision() == 0)
3046 MCHBAR32(SLPCTL) |= (1 << 8);
3047}
3048
Stefan Reinauer278534d2008-10-29 04:51:07 +00003049/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003050 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003051 */
Sven Schnelle541269b2011-02-21 09:39:17 +00003052void sdram_initialize(int boot_path, const u8 *spd_addresses)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003053{
3054 struct sys_info sysinfo;
3055 u8 reg8, cas_mask;
3056
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003057 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003058
3059 memset(&sysinfo, 0, sizeof(sysinfo));
3060
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003061 sysinfo.boot_path = boot_path;
Sven Schnelle541269b2011-02-21 09:39:17 +00003062 sysinfo.spd_addresses = spd_addresses;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003063
Stefan Reinauer278534d2008-10-29 04:51:07 +00003064 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3065 sdram_get_dram_configuration(&sysinfo);
3066
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003067 /* If error, do cold boot */
3068 sdram_detect_errors(&sysinfo);
3069
Stefan Reinauer278534d2008-10-29 04:51:07 +00003070 /* Check whether we have stacked DIMMs */
3071 sdram_verify_package_type(&sysinfo);
3072
3073 /* Determine common CAS */
3074 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003075
Stefan Reinauer278534d2008-10-29 04:51:07 +00003076 /* Choose Common Frequency */
3077 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003078
Stefan Reinauer278534d2008-10-29 04:51:07 +00003079 /* Determine smallest common tRAS */
3080 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003081
Stefan Reinauer278534d2008-10-29 04:51:07 +00003082 /* Determine tRP */
3083 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003084
Stefan Reinauer278534d2008-10-29 04:51:07 +00003085 /* Determine tRCD */
3086 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003087
Stefan Reinauer278534d2008-10-29 04:51:07 +00003088 /* Determine smallest refresh period */
3089 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003090
Stefan Reinauer278534d2008-10-29 04:51:07 +00003091 /* Verify all DIMMs support burst length 8 */
3092 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003093
Stefan Reinauer278534d2008-10-29 04:51:07 +00003094 /* determine tWR */
3095 sdram_detect_smallest_tWR(&sysinfo);
3096
3097 /* Determine DIMM size parameters (rows, columns banks) */
3098 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003099
Stefan Reinauer278534d2008-10-29 04:51:07 +00003100 /* determine tRFC */
3101 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003102
Stefan Reinauer278534d2008-10-29 04:51:07 +00003103 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003104 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003105
3106 /* Program Graphics Frequency */
3107 sdram_program_graphics_frequency(&sysinfo);
3108
3109 /* Program System Memory Frequency */
3110 sdram_program_memory_frequency(&sysinfo);
3111
3112 /* Determine Mode of Operation (Interleaved etc) */
3113 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003114
Stefan Reinauer278534d2008-10-29 04:51:07 +00003115 /* Program Clock Crossing values */
3116 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003117
Stefan Reinauer278534d2008-10-29 04:51:07 +00003118 /* Disable fast dispatch */
3119 sdram_disable_fast_dispatch();
3120
3121 /* Enable WIODLL Power Down in ACPI states */
3122 MCHBAR32(C0DMC) |= (1 << 24);
3123 MCHBAR32(C1DMC) |= (1 << 24);
3124
3125 /* Program DRAM Row Boundary/Attribute Registers */
3126
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003127 /* program row size DRB and set TOLUD */
3128 sdram_program_row_boundaries(&sysinfo);
3129
3130 /* program page size DRA */
3131 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003132
3133 /* Program CxBNKARC */
3134 sdram_set_bank_architecture(&sysinfo);
3135
3136 /* Program DRAM Timing and Control registers based on SPD */
3137 sdram_set_timing_and_control(&sysinfo);
3138
3139 /* On-Die Termination Adjustment */
3140 sdram_on_die_termination(&sysinfo);
3141
3142 /* Pre Jedec Initialization */
3143 sdram_pre_jedec_initialization();
3144
3145 /* Perform System Memory IO Initialization */
3146 sdram_initialize_system_memory_io(&sysinfo);
3147
3148 /* Perform System Memory IO Buffer Enable */
3149 sdram_enable_system_memory_io(&sysinfo);
3150
3151 /* Enable System Memory Clocks */
3152 sdram_enable_memory_clocks(&sysinfo);
3153
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003154 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003155 /* Jedec Initialization sequence */
3156 sdram_jedec_enable(&sysinfo);
3157 }
3158
3159 /* Program Power Management Registers */
3160 sdram_power_management(&sysinfo);
3161
3162 /* Post Jedec Init */
3163 sdram_post_jedec_initialization(&sysinfo);
3164
3165 /* Program DRAM Throttling */
3166 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003167
Stefan Reinauer278534d2008-10-29 04:51:07 +00003168 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003169 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003170
3171 /* Program Receive Enable Timings */
3172 sdram_program_receive_enable(&sysinfo);
3173
3174 /* Enable Periodic RCOMP */
3175 sdram_enable_rcomp();
3176
3177 /* Tell ICH7 that we're done */
3178 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3179 reg8 &= ~(1 << 7);
3180 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3181
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003182 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003183
Stefan Reinauer278534d2008-10-29 04:51:07 +00003184 sdram_setup_processor_side();
3185}