blob: 0a6011286bbe8da6a3155e0de98a72b9504d3261 [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>
Patrick Georgi546953c2014-11-29 10:38:17 +010027#include <halt.h>
Alexandru Gagniucaf4bd592014-01-12 15:42:58 -060028#include <lib.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000029#include "raminit.h"
30#include "i945.h"
Rudolf Marekc4369532010-12-13 19:59:13 +000031#include <cbmem.h>
32
Stefan Reinauer278534d2008-10-29 04:51:07 +000033/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000034#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000035#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Stefan Reinauer278534d2008-10-29 04:51:07 +000036#else
37#define PRINTK_DEBUG(x...)
38#endif
39
Stefan Reinauer278534d2008-10-29 04:51:07 +000040#define RAM_INITIALIZATION_COMPLETE (1 << 19)
41
42#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
43#define RAM_COMMAND_NOP (0x1 << 16)
44#define RAM_COMMAND_PRECHARGE (0x2 << 16)
45#define RAM_COMMAND_MRS (0x3 << 16)
46#define RAM_COMMAND_EMRS (0x4 << 16)
47#define RAM_COMMAND_CBR (0x6 << 16)
48#define RAM_COMMAND_NORMAL (0x7 << 16)
49
50#define RAM_EMRS_1 (0x0 << 21)
51#define RAM_EMRS_2 (0x1 << 21)
52#define RAM_EMRS_3 (0x2 << 21)
53
Sven Schnelle541269b2011-02-21 09:39:17 +000054static int get_dimm_spd_address(struct sys_info *sysinfo, int device)
55{
56 if (sysinfo->spd_addresses)
57 return sysinfo->spd_addresses[device];
58 else
59 return DIMM0 + device;
60
61}
62
Patrick Georgid0835952010-10-05 09:07:10 +000063static inline int spd_read_byte(unsigned device, unsigned address)
64{
65 return smbus_read_byte(device, address);
66}
67
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000068static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000069{
70 u32 reg32;
71
72 reg32 = MCHBAR32(DCC);
73 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
74 reg32 |= command;
75
76 /* Also set Init Complete */
77 if (command == RAM_COMMAND_NORMAL)
78 reg32 |= RAM_INITIALIZATION_COMPLETE;
79
80 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
81
82 MCHBAR32(DCC) = reg32; /* This is the actual magic */
83
Stefan Reinauer779b3e32008-11-10 15:43:37 +000084 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000085
86 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000087}
88
Stefan Reinauer278534d2008-10-29 04:51:07 +000089static void ram_read32(u32 offset)
90{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000091 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000092
93 read32(offset);
94}
95
Uwe Hermann01ce6012010-03-05 10:03:50 +000096#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer3c0bfaf2010-12-27 11:34:57 +000097void sdram_dump_mchbar_registers(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000098{
99 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000100 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000101
102 for (i=0; i<0xfff; i+=4) {
103 if (MCHBAR32(i) == 0)
104 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000105 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000106 }
107}
108#endif
109
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000110static int memclk(void)
111{
112 int offset = 0;
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200113#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000114 offset++;
115#endif
116 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
117 case 1: return 400;
118 case 2: return 533;
119 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000120 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000121 }
122 return -1;
123}
124
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200125#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Peter Stuge76d91432010-10-01 10:02:33 +0000126static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000127{
128 switch (MCHBAR32(CLKCFG) & 7) {
129 case 0: return 400;
130 case 1: return 533;
131 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000132 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000133 }
Peter Stuge76d91432010-10-01 10:02:33 +0000134 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000135}
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200136#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Peter Stuge76d91432010-10-01 10:02:33 +0000137static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000138{
139 switch (MCHBAR32(CLKCFG) & 7) {
140 case 0: return 1066;
141 case 1: return 533;
142 case 2: return 800;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000143 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000144 }
Peter Stuge76d91432010-10-01 10:02:33 +0000145 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000146}
147#endif
148
Stefan Reinauer278534d2008-10-29 04:51:07 +0000149static int sdram_capabilities_max_supported_memory_frequency(void)
150{
151 u32 reg32;
152
Patrick Georgi77d66832010-10-01 08:02:45 +0000153#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
154 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000155#endif
156
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000157 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000158 reg32 &= (7 << 0);
159
160 switch (reg32) {
161 case 4: return 400;
162 case 3: return 533;
163 case 2: return 667;
164 }
165 /* Newer revisions of this chipset rather support faster memory clocks,
166 * so if it's a reserved value, return the fastest memory clock that we
167 * know of and can handle
168 */
169 return 667;
170}
171
172/**
173 * @brief determine whether chipset is capable of dual channel interleaved mode
174 *
175 * @return 1 if interleaving is supported, 0 otherwise
176 */
177static int sdram_capabilities_interleave(void)
178{
179 u32 reg32;
180
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000181 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000182 reg32 >>= 25;
183 reg32 &= 1;
184
185 return (!reg32);
186}
187
188/**
189 * @brief determine whether chipset is capable of two memory channels
190 *
191 * @return 1 if dual channel operation is supported, 0 otherwise
192 */
193static int sdram_capabilities_dual_channel(void)
194{
195 u32 reg32;
196
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000197 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000198 reg32 >>= 24;
199 reg32 &= 1;
200
201 return (!reg32);
202}
203
204static int sdram_capabilities_enhanced_addressing_xor(void)
205{
206 u8 reg8;
207
208 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
209 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000210
Stefan Reinauer278534d2008-10-29 04:51:07 +0000211 return (!reg8);
212}
213
214static int sdram_capabilities_two_dimms_per_channel(void)
215{
216 u8 reg8;
217
218 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
219 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000220
Stefan Reinauer278534d2008-10-29 04:51:07 +0000221 return (reg8 != 0);
222}
223
Stefan Reinauer14e22772010-04-27 06:56:47 +0000224// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000225#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000226static int sdram_capabilities_MEM4G_disable(void)
227{
228 u8 reg8;
229
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000230 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000231 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000232
Stefan Reinauer278534d2008-10-29 04:51:07 +0000233 return (reg8 != 0);
234}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000235#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000236
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000237#define GFX_FREQUENCY_CAP_166MHZ 0x04
238#define GFX_FREQUENCY_CAP_200MHZ 0x03
239#define GFX_FREQUENCY_CAP_250MHZ 0x02
240#define GFX_FREQUENCY_CAP_ALL 0x00
241
242static int sdram_capabilities_core_frequencies(void)
243{
244 u8 reg8;
245
246 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
247 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
248 reg8 >>= 1;
249
250 return (reg8);
251}
252
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000253static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000254{
255 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000256 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000257
258 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000259
Stefan Reinauer278534d2008-10-29 04:51:07 +0000260 if (reg8 & ((1<<7)|(1<<2))) {
261 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000262 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000263 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000264 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000265 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000266
Stefan Reinauer278534d2008-10-29 04:51:07 +0000267 }
268
269 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000270 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000271 reg8 &= ~(1<<7);
272 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000273 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000274 }
275
276 /* Set SLP_S3# Assertion Stretch Enable */
277 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
278 reg8 |= (1 << 3);
279 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
280
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000281 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000282 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000283 outb(0x00, 0xcf9);
284 outb(0x0e, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +0100285 halt(); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000286 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000287 }
288
289 /* Set DRAM initialization bit in ICH7 */
290 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
291 reg8 |= (1<<7);
292 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000293
Peter Stuge751508a2012-01-27 22:17:09 +0100294 /* clear self refresh status if check is disabled or not a resume */
Patrick Georgi86a11102013-03-15 14:11:37 +0100295 if (!CONFIG_CHECK_SLFRCS_ON_RESUME || sysinfo->boot_path != BOOT_PATH_RESUME) {
296 MCHBAR8(SLFRCS) |= 3;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000297 } else {
298 /* Validate self refresh config */
299 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
300 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100301 !(MCHBAR8(SLFRCS) & (1<<0))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000302 do_reset = 1;
303 }
304 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
305 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100306 !(MCHBAR8(SLFRCS) & (1<<1))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000307 do_reset = 1;
308 }
309 }
310
311 if (do_reset) {
312 printk(BIOS_DEBUG, "Reset required.\n");
313 outb(0x00, 0xcf9);
314 outb(0x0e, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +0100315 halt(); /* Wait for reset! */
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000316 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000317}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000318
319/**
320 * @brief Get generic DIMM parameters.
321 * @param sysinfo Central memory controller information structure
322 *
323 * This function gathers several pieces of information for each system DIMM:
324 * o DIMM width (x8 / x16)
325 * o DIMM sides (single sided / dual sided)
326 *
327 * Also, some non-supported scenarios are detected.
328 */
329
330static void sdram_get_dram_configuration(struct sys_info *sysinfo)
331{
332 u32 dimm_mask = 0;
333 int i;
334
335 /**
336 * i945 supports two DIMMs, in two configurations:
337 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000338 * - single channel with two DIMMs
339 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000340 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000341 * In practice dual channel mainboards have their SPD at 0x50/0x52
342 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000343 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000344 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000345 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000346 */
347
348 if (sdram_capabilities_dual_channel()) {
349 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000350 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000351 } else {
352 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000353 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000354 }
355
356 /**
357 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000358 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000359 * return value:
360 * [0:7] lower DIMM population
361 * [8-15] higher DIMM population
362 * [16] dual channel?
363 *
364 * There are 5 different possible populations for a DIMM socket:
365 * 1. x16 double sided (X16DS)
366 * 2. x8 double sided (X8DS)
367 * 3. x16 single sided (X16SS)
368 * 4. x8 double stacked (X8DDS)
369 * 5. not populated (NC)
370 *
371 * For the return value we start counting at zero.
372 *
373 */
374
375 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000376 int device = get_dimm_spd_address(sysinfo, i);
377 u8 reg8;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000378
379 /* Initialize the socket information with a sane value */
380 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
381
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000382 /* Dual Channel not supported, but Channel 1? Bail out */
383 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000384 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000385
386 /* Two DIMMs per channel not supported, but odd DIMM number? */
387 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000388 continue;
389
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000390 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000391
392 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000393 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000394 continue;
395 }
396
397 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
398 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000399 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000400
401 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
402 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000403 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000404 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000405 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000406
407 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000408 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000409 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
410 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000411 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000412 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
413 break;
414 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000415 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000416 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
417 break;
418 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000419 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000420 }
421 break;
422 case 0x10:
423 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
424 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000425 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000426 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
427 break;
428 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000429 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000430 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
431 break;
432 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000433 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000434 }
435 break;
436 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000437 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000438 }
439
440 dimm_mask |= (1 << i);
441 }
442
443 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000444 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000445 }
446
Stefan Reinauer278534d2008-10-29 04:51:07 +0000447 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000448 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000449 }
450}
451
452/**
453 * @brief determine if any DIMMs are stacked
454 *
455 * @param sysinfo central sysinfo data structure.
456 */
457static void sdram_verify_package_type(struct sys_info * sysinfo)
458{
459 int i;
460
461 /* Assume no stacked DIMMs are available until we find one */
462 sysinfo->package = 0;
463 for (i=0; i<2*DIMM_SOCKETS; i++) {
464 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
465 continue;
466
467 /* Is the current DIMM a stacked DIMM? */
Sven Schnelle541269b2011-02-21 09:39:17 +0000468 if (spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000469 sysinfo->package = 1;
470 }
471}
472
473static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
474{
475 int i;
476 u8 cas_mask;
477
478 /* Setup CAS mask with all supported CAS Latencies */
479 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
480 SPD_CAS_LATENCY_DDR2_4 |
481 SPD_CAS_LATENCY_DDR2_5;
482
483 for (i=0; i<2*DIMM_SOCKETS; i++) {
484 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Sven Schnelle541269b2011-02-21 09:39:17 +0000485 cas_mask &= spd_read_byte(get_dimm_spd_address(sysinfo, i),
486 SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000487 }
488
489 if(!cas_mask) {
490 die("No DDR-II modules with accepted CAS latencies found.\n");
491 }
492
493 return cas_mask;
494}
495
496static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
497{
498 int i, j, idx;
499 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000500 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000501
502 const u8 ddr2_speeds_table[] = {
503 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
504 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
505 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
506 };
507
508 const u8 spd_lookup_table[] = {
509 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
510 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
511 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
512 };
513
514 switch (sdram_capabilities_max_supported_memory_frequency()) {
515 case 400: max_ram_speed = 0; break;
516 case 533: max_ram_speed = 1; break;
517 case 667: max_ram_speed = 2; break;
518 }
519
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000520 if (fsbclk() == 533)
521 max_ram_speed = 1;
522
Stefan Reinauer278534d2008-10-29 04:51:07 +0000523 sysinfo->memory_frequency = 0;
524 sysinfo->cas = 0;
525
526 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
527 lowest_common_cas = 3;
528 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
529 lowest_common_cas = 4;
530 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
531 lowest_common_cas = 5;
532 }
533 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
534
535 for (j = max_ram_speed; j>=0; j--) {
536 int freq_cas_mask = cas_mask;
537
538 PRINTK_DEBUG("Probing Speed %d\n", j);
539 for (i=0; i<2*DIMM_SOCKETS; i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000540 int device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000541 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000542
Stefan Reinauer278534d2008-10-29 04:51:07 +0000543 PRINTK_DEBUG(" DIMM: %d\n", i);
544 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
545 continue;
546 }
547
Sven Schnelle541269b2011-02-21 09:39:17 +0000548 current_cas_mask = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000549
550 while (current_cas_mask) {
551 int highest_supported_cas = 0, current_cas = 0;
552 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
553 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
554 highest_supported_cas = 5;
555 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
556 highest_supported_cas = 4;
557 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
558 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000559 } else {
560 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000561 }
562 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
563 current_cas = 3;
564 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
565 current_cas = 4;
566 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
567 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000568 } else {
569 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000570 }
571
572 idx = highest_supported_cas - current_cas;
573 PRINTK_DEBUG("idx=%d, ", idx);
Sven Schnelle541269b2011-02-21 09:39:17 +0000574 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(device, spd_lookup_table[2*idx]));
575 PRINTK_DEBUG("tAC=%x", spd_read_byte(device, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000576
Sven Schnelle541269b2011-02-21 09:39:17 +0000577 if (spd_read_byte(device, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
578 spd_read_byte(device, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000579 PRINTK_DEBUG(": OK\n");
580 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000581 }
582
Stefan Reinauer278534d2008-10-29 04:51:07 +0000583 PRINTK_DEBUG(": Not fast enough!\n");
584
585 current_cas_mask &= ~(1 << (current_cas));
586 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000587
Stefan Reinauer278534d2008-10-29 04:51:07 +0000588 freq_cas_mask &= current_cas_mask;
589 if (!current_cas_mask) {
590 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
591 break;
592 }
593 }
594 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
595 if (freq_cas_mask) {
596 switch (j) {
597 case 0: sysinfo->memory_frequency = 400; break;
598 case 1: sysinfo->memory_frequency = 533; break;
599 case 2: sysinfo->memory_frequency = 667; break;
600 }
601 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
602 sysinfo->cas = 3;
603 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
604 sysinfo->cas = 4;
605 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
606 sysinfo->cas = 5;
607 }
608 break;
609 }
610 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000611
Stefan Reinauer278534d2008-10-29 04:51:07 +0000612 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000613 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000614 sysinfo->memory_frequency, sysinfo->cas);
615 } else {
616 die("Could not find common memory frequency and CAS\n");
617 }
618}
619
620static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
621{
622 int i;
623 int tRAS_time;
624 int tRAS_cycles;
625 int freq_multiplier = 0;
626
627 switch (sysinfo->memory_frequency) {
628 case 400: freq_multiplier = 0x14; break; /* 5ns */
629 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
630 case 667: freq_multiplier = 0x0c; break; /* 3ns */
631 }
632
633 tRAS_cycles = 4; /* 4 clocks minimum */
634 tRAS_time = tRAS_cycles * freq_multiplier;
635
636 for (i=0; i<2*DIMM_SOCKETS; i++) {
637 u8 reg8;
638
639 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
640 continue;
641
Sven Schnelle541269b2011-02-21 09:39:17 +0000642 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000643 if (!reg8) {
644 die("Invalid tRAS value.\n");
645 }
646
647 while ((tRAS_time >> 2) < reg8) {
648 tRAS_time += freq_multiplier;
649 tRAS_cycles++;
650 }
651 }
652 if(tRAS_cycles > 0x18) {
653 die("DDR-II Module does not support this frequency (tRAS error)\n");
654 }
655
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000656 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000657 sysinfo->tras = tRAS_cycles;
658}
659
660static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
661{
662 int i;
663 int tRP_time;
664 int tRP_cycles;
665 int freq_multiplier = 0;
666
667 switch (sysinfo->memory_frequency) {
668 case 400: freq_multiplier = 0x14; break; /* 5ns */
669 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
670 case 667: freq_multiplier = 0x0c; break; /* 3ns */
671 }
672
673 tRP_cycles = 2; /* 2 clocks minimum */
674 tRP_time = tRP_cycles * freq_multiplier;
675
676 for (i=0; i<2*DIMM_SOCKETS; i++) {
677 u8 reg8;
678
679 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
680 continue;
681
Sven Schnelle541269b2011-02-21 09:39:17 +0000682 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000683 if (!reg8) {
684 die("Invalid tRP value.\n");
685 }
686
687 while (tRP_time < reg8) {
688 tRP_time += freq_multiplier;
689 tRP_cycles++;
690 }
691 }
692
693 if(tRP_cycles > 6) {
694 die("DDR-II Module does not support this frequency (tRP error)\n");
695 }
696
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000697 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000698 sysinfo->trp = tRP_cycles;
699}
700
701static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
702{
703 int i;
704 int tRCD_time;
705 int tRCD_cycles;
706 int freq_multiplier = 0;
707
708 switch (sysinfo->memory_frequency) {
709 case 400: freq_multiplier = 0x14; break; /* 5ns */
710 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
711 case 667: freq_multiplier = 0x0c; break; /* 3ns */
712 }
713
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000714 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000715 tRCD_time = tRCD_cycles * freq_multiplier;
716
717 for (i=0; i<2*DIMM_SOCKETS; i++) {
718 u8 reg8;
719
720 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
721 continue;
722
Sven Schnelle541269b2011-02-21 09:39:17 +0000723 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000724 if (!reg8) {
725 die("Invalid tRCD value.\n");
726 }
727
728 while (tRCD_time < reg8) {
729 tRCD_time += freq_multiplier;
730 tRCD_cycles++;
731 }
732 }
733 if(tRCD_cycles > 6) {
734 die("DDR-II Module does not support this frequency (tRCD error)\n");
735 }
736
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000737 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000738 sysinfo->trcd = tRCD_cycles;
739}
740
741static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
742{
743 int i;
744 int tWR_time;
745 int tWR_cycles;
746 int freq_multiplier = 0;
747
748 switch (sysinfo->memory_frequency) {
749 case 400: freq_multiplier = 0x14; break; /* 5ns */
750 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
751 case 667: freq_multiplier = 0x0c; break; /* 3ns */
752 }
753
754 tWR_cycles = 2; /* 2 clocks minimum */
755 tWR_time = tWR_cycles * freq_multiplier;
756
757 for (i=0; i<2*DIMM_SOCKETS; i++) {
758 u8 reg8;
759
760 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
761 continue;
762
Sven Schnelle541269b2011-02-21 09:39:17 +0000763 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000764 if (!reg8) {
765 die("Invalid tWR value.\n");
766 }
767
768 while (tWR_time < reg8) {
769 tWR_time += freq_multiplier;
770 tWR_cycles++;
771 }
772 }
773 if(tWR_cycles > 5) {
774 die("DDR-II Module does not support this frequency (tWR error)\n");
775 }
776
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000777 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000778 sysinfo->twr = tWR_cycles;
779}
780
781static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
782{
783 int i, index = 0;
784
785 const u8 tRFC_cycles[] = {
786 /* 75 105 127.5 */
787 15, 21, 26, /* DDR2-400 */
788 20, 28, 34, /* DDR2-533 */
789 25, 35, 43 /* DDR2-667 */
790 };
791
792 for (i=0; i<2*DIMM_SOCKETS; i++) {
793 u8 reg8;
794
795 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
796 continue;
797
798 reg8 = sysinfo->banksize[i*2];
799 switch (reg8) {
800 case 0x04: reg8 = 0; break;
801 case 0x08: reg8 = 1; break;
802 case 0x10: reg8 = 2; break;
803 case 0x20: reg8 = 3; break;
804 }
805
806 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
807 reg8++;
808
809 if (reg8 > 3) {
810 /* Can this happen? Go back to 127.5ns just to be sure
811 * we don't run out of the array. This may be wrong
812 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000813 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000814 reg8 = 3;
815 }
816
817 if (reg8 > index)
818 index = reg8;
819
820 }
821 index--;
822 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000823 case 667: index += 3; /* Fallthrough */
824 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000825 case 400: break;
826 }
827
828 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000829 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000830}
831
Stefan Reinauer278534d2008-10-29 04:51:07 +0000832static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
833{
834 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000835
Stefan Reinauer278534d2008-10-29 04:51:07 +0000836 sysinfo->refresh = 0;
837
838 for (i=0; i<2*DIMM_SOCKETS; i++) {
839 int refresh;
840
841 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
842 continue;
843
Sven Schnelle541269b2011-02-21 09:39:17 +0000844 refresh = spd_read_byte(get_dimm_spd_address(sysinfo, i),
845 SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000846
847 /* 15.6us */
848 if (!refresh)
849 continue;
850
851 /* Refresh is slower than 15.6us, use 15.6us */
852 if (refresh > 2)
853 continue;
854
855 if (refresh == 2) {
856 sysinfo->refresh = 1;
857 break;
858 }
859
860 die("DDR-II module has unsupported refresh value\n");
861 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000862 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000863}
864
865static void sdram_verify_burst_length(struct sys_info * sysinfo)
866{
867 int i;
868
869 for (i=0; i<2*DIMM_SOCKETS; i++) {
870 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
871 continue;
872
Sven Schnelle541269b2011-02-21 09:39:17 +0000873 if (!(spd_read_byte(get_dimm_spd_address(sysinfo, i),
874 SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000875 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
876 }
877}
878
879static void sdram_program_dram_width(struct sys_info * sysinfo)
880{
881 u16 c0dramw=0, c1dramw=0;
882 int idx;
883
884 if (sysinfo->dual_channel)
885 idx = 2;
886 else
887 idx = 1;
888
889 switch (sysinfo->dimm[0]) {
890 case 0: c0dramw = 0x0000; break; /* x16DS */
891 case 1: c0dramw = 0x0001; break; /* x8DS */
892 case 2: c0dramw = 0x0000; break; /* x16SS */
893 case 3: c0dramw = 0x0005; break; /* x8DDS */
894 case 4: c0dramw = 0x0000; break; /* NC */
895 }
896
897 switch (sysinfo->dimm[idx]) {
898 case 0: c1dramw = 0x0000; break; /* x16DS */
899 case 1: c1dramw = 0x0010; break; /* x8DS */
900 case 2: c1dramw = 0x0000; break; /* x16SS */
901 case 3: c1dramw = 0x0050; break; /* x8DDS */
902 case 4: c1dramw = 0x0000; break; /* NC */
903 }
904
905 if ( !sdram_capabilities_dual_channel() ) {
906 /* Single Channel */
907 c0dramw |= c1dramw;
908 c1dramw = 0;
909 }
910
911 MCHBAR16(C0DRAMW) = c0dramw;
912 MCHBAR16(C1DRAMW) = c1dramw;
913}
914
915static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
916{
917 int i;
918
919 for (i=0; i<16; i++)
920 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
921}
922
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000923static const u32 dq2030[] = {
924 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
925 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
926 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
927 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
928};
929
930static const u32 dq2330[] = {
931 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
932 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
933 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
934 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
935};
936
937static const u32 cmd2710[] = {
938 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
939 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
940 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
941 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
942};
943
944static const u32 cmd3210[] = {
945 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
946 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
947 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
948 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
949};
950
951static const u32 clk2030[] = {
952 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
953 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
954 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
955 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
956};
957
958static const u32 ctl3215[] = {
959 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
960 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
961 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
962 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
963};
964
965static const u32 ctl3220[] = {
966 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
967 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
968 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
969 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
970};
971
972static const u32 nc[] = {
973 0x00000000, 0x00000000, 0x00000000, 0x00000000,
974 0x00000000, 0x00000000, 0x00000000, 0x00000000,
975 0x00000000, 0x00000000, 0x00000000, 0x00000000,
976 0x00000000, 0x00000000, 0x00000000, 0x00000000
977};
978
979enum {
980 DQ2030,
981 DQ2330,
982 CMD2710,
983 CMD3210,
984 CLK2030,
985 CTL3215,
986 CTL3220,
987 NC,
988};
989
990static const u8 dual_channel_slew_group_lookup[] = {
991 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
992 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
993 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
994 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
995 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
996
997 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
998 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
999 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1000 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1001 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1002
1003 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1004 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1005 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1006 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
1007 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1008
1009 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1010 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1011 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1012 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1013 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
1014
1015 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1016 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1017 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1018 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
1019};
1020
1021static const u8 single_channel_slew_group_lookup[] = {
1022 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1023 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1024 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1025 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1026 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1027
1028 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1029 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1030 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1031 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1032 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1033
1034 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1035 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1036 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1037 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1038 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1039
1040 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1041 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1042 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1043 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1044 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1045
1046 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1047 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1048 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1049 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1050};
1051
1052static const u32 *slew_group_lookup(int dual_channel, int index)
1053{
1054 const u8 *slew_group;
1055 /* Dual Channel needs different tables. */
1056 if (dual_channel)
1057 slew_group = dual_channel_slew_group_lookup;
1058 else
1059 slew_group = single_channel_slew_group_lookup;
1060
1061 switch (slew_group[index]) {
1062 case DQ2030: return dq2030;
1063 case DQ2330: return dq2330;
1064 case CMD2710: return cmd2710;
1065 case CMD3210: return cmd3210;
1066 case CLK2030: return clk2030;
1067 case CTL3215: return ctl3215;
1068 case CTL3220: return ctl3220;
1069 case NC: return nc;
1070 }
1071
1072 return nc;
1073}
1074
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001075#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001076/* Strength multiplier tables */
1077static const u8 dual_channel_strength_multiplier[] = {
1078 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1079 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1080 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1081 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1082 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1083 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1084 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1085 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1086 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1087 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1088 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1089 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1090 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1091 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1092 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1093 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1094 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1095 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1096 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1097 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1099 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1100 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1101 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1102};
1103
1104static const u8 single_channel_strength_multiplier[] = {
1105 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1106 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1107 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1108 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1109 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1110 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1111 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1112 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1113 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1114 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1115 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1116 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1117 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1118 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1119 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1120 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1121 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1122 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1123 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1124 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1125 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1126 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1127 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1128 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1129};
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001130#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001131static const u8 dual_channel_strength_multiplier[] = {
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, 0x22,
1135 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1136 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
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, 0x22,
1140 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1141 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
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, 0x22,
1145 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1146 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
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, 0x22,
1150 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1151 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
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, 0x22,
1155 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1156};
1157
1158static const u8 single_channel_strength_multiplier[] = {
1159 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1160 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1161 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1162 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1163 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1164 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1165 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1166 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1167 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1168 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1169 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1170 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1171 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1172 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1173 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1174 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1175 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1176 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1177 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1178 0x44, 0x33, 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, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1182 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1183};
1184#endif
1185
Stefan Reinauer278534d2008-10-29 04:51:07 +00001186static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1187{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001188 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001189 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001190
1191 /* Set Strength Multipliers */
1192
1193 /* Dual Channel needs different tables. */
1194 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001195 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001196 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001197 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001198 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1199 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001200 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001201 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001202 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001203 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1204 }
1205
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001206 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001207
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001208 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1209 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1210 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1211 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1212 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1213 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1214 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1215 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001216
1217 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001218 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1219 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1220 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001221
Stefan Reinauer278534d2008-10-29 04:51:07 +00001222 sdram_write_slew_rates(G3SRPUT, ctl3220);
1223 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001224 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001225 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001226 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1227 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1228 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001229
1230 /* Channel 1 */
1231 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001232 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1233 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001234 } else {
1235 sdram_write_slew_rates(G7SRPUT, nc);
1236 sdram_write_slew_rates(G8SRPUT, nc);
1237 }
1238}
1239
1240static void sdram_enable_rcomp(void)
1241{
1242 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001243 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001244 udelay(300);
1245 reg32 = MCHBAR32(GBRCOMPCTL);
1246 reg32 &= ~(1 << 23);
1247 MCHBAR32(GBRCOMPCTL) = reg32;
1248}
1249
1250static void sdram_program_dll_timings(struct sys_info *sysinfo)
1251{
1252 u32 chan0dll = 0, chan1dll = 0;
1253 int i;
1254
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001255 printk(BIOS_DEBUG, "Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001256
Stefan Reinauer278534d2008-10-29 04:51:07 +00001257 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1258 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1259
1260 /* We drive both channels with the same speed */
1261 switch (sysinfo->memory_frequency) {
1262 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1263 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1264 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1265 }
1266
1267 for (i=0; i < 4; i++) {
1268 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1269 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1270 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1271 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1272 }
1273}
1274
1275static void sdram_force_rcomp(void)
1276{
1277 u32 reg32;
1278 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001279
Stefan Reinauer278534d2008-10-29 04:51:07 +00001280 reg32 = MCHBAR32(ODTC);
1281 reg32 |= (1 << 28);
1282 MCHBAR32(ODTC) = reg32;
1283
1284 reg32 = MCHBAR32(SMSRCTL);
1285 reg32 |= (1 << 0);
1286 MCHBAR32(SMSRCTL) = reg32;
1287
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001288 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001289 reg32 = MCHBAR32(GBRCOMPCTL);
1290 reg32 |= (1 << 8);
1291 MCHBAR32(GBRCOMPCTL) = reg32;
1292
1293 reg8 = i945_silicon_revision();
1294 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001295
Stefan Reinauer278534d2008-10-29 04:51:07 +00001296 reg32 = MCHBAR32(GBRCOMPCTL);
1297 reg32 |= (3 << 5);
1298 MCHBAR32(GBRCOMPCTL) = reg32;
1299 }
1300}
1301
1302static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1303{
1304 u8 reg8;
1305 u32 reg32;
1306
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001307 printk(BIOS_DEBUG, "Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001308 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001309 reg8 = MCHBAR8(C0HCTC);
1310 reg8 &= ~0x1f;
1311 reg8 |= ( 1 << 0);
1312 MCHBAR8(C0HCTC) = reg8;
1313
1314 reg8 = MCHBAR8(C1HCTC);
1315 reg8 &= ~0x1f;
1316 reg8 |= ( 1 << 0);
1317 MCHBAR8(C1HCTC) = reg8;
1318
Stefan Reinauer278534d2008-10-29 04:51:07 +00001319 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1320 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1321
1322 MCHBAR8(C0WDLLCMC) = 0;
1323 MCHBAR8(C1WDLLCMC) = 0;
1324
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001325 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001326 sdram_program_dram_width(sysinfo);
1327
1328 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1329
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001330 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001331 reg32 = MCHBAR32(GBRCOMPCTL);
1332 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1333 reg32 |= (3 << 27) | (3 << 0);
1334 MCHBAR32(GBRCOMPCTL) = reg32;
1335
1336 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1337
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001338 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001339 sdram_program_dll_timings(sysinfo);
1340
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001341 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001342 sdram_force_rcomp();
1343}
1344
1345static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1346{
1347 u32 reg32;
1348
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001349 printk(BIOS_DEBUG, "Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001350
Stefan Reinauer278534d2008-10-29 04:51:07 +00001351 reg32 = MCHBAR32(RCVENMT);
1352 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001353 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001354
1355 reg32 |= (1 << 11) | (1 << 9);
1356 MCHBAR32(RCVENMT) = reg32;
1357
1358 reg32 = MCHBAR32(DRTST);
1359 reg32 |= (1 << 3) | (1 << 2);
1360 MCHBAR32(DRTST) = reg32;
1361
1362 reg32 = MCHBAR32(DRTST);
1363 reg32 |= (1 << 6) | (1 << 4);
1364 MCHBAR32(DRTST) = reg32;
1365
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001366 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001367
1368 reg32 = MCHBAR32(DRTST);
1369
1370 /* Is channel 0 populated? */
1371 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1372 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1373 reg32 |= (1 << 7) | (1 << 5);
1374 else
1375 reg32 |= (1 << 31);
1376
1377 /* Is channel 1 populated? */
1378 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1379 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1380 reg32 |= (1 << 9) | (1 << 8);
1381 else
1382 reg32 |= (1 << 30);
1383
1384 MCHBAR32(DRTST) = reg32;
1385
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001386 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001387 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1388 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1389 reg32 = MCHBAR32(C0DRC1);
1390 reg32 |= (1 << 8);
1391 MCHBAR32(C0DRC1) = reg32;
1392 }
1393 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1394 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1395 reg32 = MCHBAR32(C1DRC1);
1396 reg32 |= (1 << 8);
1397 MCHBAR32(C1DRC1) = reg32;
1398 }
1399}
1400
1401struct dimm_size {
1402 unsigned long side1;
1403 unsigned long side2;
1404};
1405
Sven Schnelle541269b2011-02-21 09:39:17 +00001406static struct dimm_size sdram_get_dimm_size(struct sys_info *sysinfo, u16 dimmno)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001407{
1408 /* Calculate the log base 2 size of a DIMM in bits */
1409 struct dimm_size sz;
Sven Schnelle541269b2011-02-21 09:39:17 +00001410 int value, low, rows, columns, device;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001411
Sven Schnelle541269b2011-02-21 09:39:17 +00001412 device = get_dimm_spd_address(sysinfo, dimmno);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001413 sz.side1 = 0;
1414 sz.side2 = 0;
1415
1416 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1417 if (rows < 0) goto hw_err;
1418 if ((rows & 0xf) == 0) goto val_err;
1419 sz.side1 += rows & 0xf;
1420
1421 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1422 if (columns < 0) goto hw_err;
1423 if ((columns & 0xf) == 0) goto val_err;
1424 sz.side1 += columns & 0xf;
1425
1426 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1427 if (value < 0) goto hw_err;
1428 if ((value & 0xff) == 0) goto val_err;
1429 sz.side1 += log2(value & 0xff);
1430
1431 /* Get the module data width and convert it to a power of two */
1432 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1433 if (value < 0) goto hw_err;
1434 value &= 0xff;
1435 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001436
Stefan Reinauer278534d2008-10-29 04:51:07 +00001437 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1438 if (low < 0) goto hw_err;
1439 value = value | (low & 0xff);
1440 if ((value != 72) && (value != 64)) goto val_err;
1441 sz.side1 += log2(value);
1442
1443 /* side 2 */
1444 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1445
1446 if (value < 0) goto hw_err;
1447 value &= 7;
1448 value++;
1449 if (value == 1) goto out;
1450 if (value != 2) goto val_err;
1451
1452 /* Start with the symmetrical case */
1453 sz.side2 = sz.side1;
1454
1455 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1456
1457 /* Don't die here, I have not come across any of these to test what
1458 * actually happens.
1459 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001460 printk(BIOS_ERR, "Assymetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001461
1462 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1463 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1464
1465 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1466 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1467
1468 goto out;
1469
1470 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001471 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001472 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001473 /* If a hardware error occurs the spd rom probably does not exist.
1474 * In this case report that there is no memory
1475 */
1476 sz.side1 = 0;
1477 sz.side2 = 0;
Patrick Georgic5fc7db2012-03-07 15:55:47 +01001478out:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001479 return sz;
1480}
1481
1482static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1483{
1484 int i;
1485
1486 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1487 struct dimm_size sz;
1488
1489 sysinfo->banksize[i * 2] = 0;
1490 sysinfo->banksize[(i * 2) + 1] = 0;
1491
1492 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1493 continue;
1494
Sven Schnelle541269b2011-02-21 09:39:17 +00001495 sz = sdram_get_dimm_size(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001496
Sven Schnelle541269b2011-02-21 09:39:17 +00001497 sysinfo->banks[i] = spd_read_byte(get_dimm_spd_address(sysinfo, i),
1498 SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001499
1500 if (sz.side1 < 30)
1501 die("DDR-II rank size smaller than 128MB is not supported.\n");
1502
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001503 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001504
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001505 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001506
Stefan Reinauer278534d2008-10-29 04:51:07 +00001507 if (!sz.side2)
1508 continue;
1509
1510 /* If there is a second side, it has to have at least 128M, too */
1511 if (sz.side2 < 30)
1512 die("DDR-II rank size smaller than 128MB is not supported.\n");
1513
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001514 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001515
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001516 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001517 }
1518}
1519
1520static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1521{
1522 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001523 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001524
Paul Menzel84283bc2014-07-17 08:16:04 +02001525 printk(BIOS_DEBUG, "Setting RAM size...\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001526
1527 cum0 = 0;
1528 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001529 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001530 MCHBAR8(C0DRB0+i) = cum0;
1531 }
1532
1533 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1534 cum1 = cum0;
1535
1536 /* Exception: Interleaved starts from the beginning */
1537 if (sysinfo->interleaved)
1538 cum1 = 0;
1539
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001540#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001541 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1542 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1543 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1544 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001545#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001546
1547 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001548 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001549 MCHBAR8(C1DRB0+i) = cum1;
1550 }
1551
1552 /* Set TOLUD Top Of Low Usable DRAM */
1553 if (sysinfo->interleaved)
1554 tolud = (cum0 + cum1) << 1;
1555 else
1556 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001557
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001558 /* The TOM register has a different format */
1559 tom = tolud >> 3;
1560
1561 /* Limit the value of TOLUD to leave some space for PCI memory. */
1562 if (tolud > 0xd0)
1563 tolud = 0xd0; /* 3.25GB : 0.75GB */
1564
1565 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1566
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001567 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1568 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1569 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001570
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001571 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001572
1573 return 0;
1574}
1575
Stefan Reinauer278534d2008-10-29 04:51:07 +00001576static int sdram_set_row_attributes(struct sys_info *sysinfo)
1577{
1578 int i, value;
1579 u16 dra0=0, dra1=0, dra = 0;
1580
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001581 printk(BIOS_DEBUG, "Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001582 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1583 u16 device;
1584 u8 columnsrows;
1585
1586 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1587 continue;
1588 }
1589
Sven Schnelle541269b2011-02-21 09:39:17 +00001590 device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001591
1592 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1593 columnsrows = (value & 0x0f);
1594
1595 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1596 columnsrows |= (value & 0xf) << 4;
1597
1598 switch (columnsrows) {
1599 case 0x9d: dra = 2; break;
1600 case 0xad: dra = 3; break;
1601 case 0xbd: dra = 4; break;
1602 case 0xae: dra = 3; break;
1603 case 0xbe: dra = 4; break;
1604 default: die("Unsupported Rows/Columns. (DRA)");
1605 }
1606
1607 /* Double Sided DIMMs? */
1608 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1609 dra = (dra << 4) | dra;
1610 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001611
Stefan Reinauer278534d2008-10-29 04:51:07 +00001612 if (i < DIMM_SOCKETS)
1613 dra0 |= (dra << (i*8));
1614 else
1615 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1616 }
1617
1618 MCHBAR16(C0DRA0) = dra0;
1619 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001620
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001621 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1622 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001623
1624 return 0;
1625}
1626
1627static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1628{
1629 u32 off32;
1630 int i;
1631
1632 MCHBAR16(C1BNKARC) &= 0xff00;
1633 MCHBAR16(C0BNKARC) &= 0xff00;
1634
1635 off32 = C0BNKARC;
1636 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1637 /* Switch to second channel */
1638 if (i == DIMM_SOCKETS)
1639 off32 = C1BNKARC;
1640
1641 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1642 continue;
1643
1644 if (sysinfo->banks[i] != 8)
1645 continue;
1646
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001647 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001648
1649 if (i & 1)
1650 MCHBAR16(off32) |= 0x50;
1651 else
1652 MCHBAR16(off32) |= 0x05;
1653 }
1654}
1655
1656#define REFRESH_7_8US 1
1657#define REFRESH_15_6US 0
1658static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1659{
1660 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001661
Stefan Reinauer278534d2008-10-29 04:51:07 +00001662 if (sysinfo->refresh == REFRESH_7_8US) {
1663 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1664 } else {
1665 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1666 }
1667
1668 MCHBAR32(C0DRC0) &= ~(7 << 8);
1669 MCHBAR32(C0DRC0) |= reg32;
1670
1671 MCHBAR32(C1DRC0) &= ~(7 << 8);
1672 MCHBAR32(C1DRC0) |= reg32;
1673}
1674
1675static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1676{
1677 u32 reg32;
1678 int i;
1679
1680 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001681
Stefan Reinauer278534d2008-10-29 04:51:07 +00001682 for (i=0; i < 4; i++) {
1683 if (sysinfo->banksize[i] == 0) {
1684 reg32 |= (1 << (16 + i));
1685 }
1686 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001687
Stefan Reinauer278534d2008-10-29 04:51:07 +00001688 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001689
Stefan Reinauer278534d2008-10-29 04:51:07 +00001690 reg32 |= (1 << 11);
1691 MCHBAR32(C0DRC1) = reg32;
1692
1693 /* Do we have to do this if we're in Single Channel Mode? */
1694 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001695
Stefan Reinauer278534d2008-10-29 04:51:07 +00001696 for (i=4; i < 8; i++) {
1697 if (sysinfo->banksize[i] == 0) {
1698 reg32 |= (1 << (12 + i));
1699 }
1700 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001701
Stefan Reinauer278534d2008-10-29 04:51:07 +00001702 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001703
Stefan Reinauer278534d2008-10-29 04:51:07 +00001704 reg32 |= (1 << 11);
1705 MCHBAR32(C1DRC1) = reg32;
1706}
1707
1708static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1709{
1710 u32 reg32;
1711 int i;
1712
1713 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001714
Stefan Reinauer278534d2008-10-29 04:51:07 +00001715 for (i=0; i < 4; i++) {
1716 if (sysinfo->banksize[i] == 0) {
1717 reg32 |= (1 << (24 + i));
1718 }
1719 }
1720 MCHBAR32(C0DRC2) = reg32;
1721
1722 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001723
Stefan Reinauer278534d2008-10-29 04:51:07 +00001724 for (i=4; i < 8; i++) {
1725 if (sysinfo->banksize[i] == 0) {
1726 reg32 |= (1 << (20 + i));
1727 }
1728 }
1729 MCHBAR32(C1DRC2) = reg32;
1730}
1731
1732static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1733{
1734 u32 reg32, off32;
1735 u32 tWTR;
1736 u32 temp_drt;
1737 int i, page_size;
1738
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001739 static const u8 drt0_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001740 /* CL 3, 4, 5 */
1741 3, 4, 5, /* FSB533/400, DDR533/400 */
1742 4, 5, 6, /* FSB667, DDR533/400 */
1743 4, 5, 6, /* FSB667, DDR667 */
1744 };
1745
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001746 static const u8 cas_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001747 2, 1, 0, 3
1748 };
1749
1750 reg32 = MCHBAR32(C0DRC0);
1751 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001752 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001753 MCHBAR32(C0DRC0) = reg32;
1754
1755 reg32 = MCHBAR32(C1DRC0);
1756 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001757 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001758 MCHBAR32(C1DRC0) = reg32;
1759
1760 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1761 SYSINFO_DIMM_NOT_POPULATED) {
1762 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001763 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001764 MCHBAR32(C0DRC0) = reg32;
1765 }
1766
1767 sdram_program_refresh_rate(sysinfo);
1768
1769 sdram_program_cke_tristate(sysinfo);
1770
1771 sdram_program_odt_tristate(sysinfo);
1772
1773 /* Calculate DRT0 */
1774
1775 temp_drt = 0;
1776
1777 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1778 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1779 temp_drt |= (reg32 << 28);
1780
1781 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1782 reg32 += sysinfo->trp;
1783 temp_drt |= (reg32 << 4);
1784
1785 if (sysinfo->memory_frequency == 667) {
1786 tWTR = 3; /* 667MHz */
1787 } else {
1788 tWTR = 2; /* 400 and 533 */
1789 }
1790
1791 /* B2B Write to Read Command Spacing */
1792 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1793 temp_drt |= (reg32 << 24);
1794
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001795 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001796 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1797
1798 /* Program Write Auto Precharge to Activate */
1799 off32 = 0;
1800 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1801 off32 += 3;
1802 }
1803 if (sysinfo->memory_frequency == 667) {
1804 off32 += 3;
1805 }
1806 off32 += sysinfo->cas - 3;
1807 reg32 = drt0_table[off32];
1808 temp_drt |= (reg32 << 11);
1809
1810 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001811
Stefan Reinauer278534d2008-10-29 04:51:07 +00001812 temp_drt |= (8 << 0);
1813
1814 MCHBAR32(C0DRT0) = temp_drt;
1815 MCHBAR32(C1DRT0) = temp_drt;
1816
1817 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001818
Stefan Reinauer278534d2008-10-29 04:51:07 +00001819 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1820
1821 /* DRAM RASB Precharge */
1822 temp_drt |= (sysinfo->trp - 2) << 0;
1823
1824 /* DRAM RASB to CASB Delay */
1825 temp_drt |= (sysinfo->trcd - 2) << 4;
1826
1827 /* CASB Latency */
1828 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1829
1830 /* Refresh Cycle Time */
1831 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001832
Stefan Reinauer278534d2008-10-29 04:51:07 +00001833 /* Pre-All to Activate Delay */
1834 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001835
Stefan Reinauer278534d2008-10-29 04:51:07 +00001836 /* Precharge to Precharge Delay stays at 1 clock */
1837 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001838
Stefan Reinauer278534d2008-10-29 04:51:07 +00001839 /* Activate to Precharge Delay */
1840 temp_drt |= (sysinfo->tras << 19);
1841
1842 /* Read to Precharge (tRTP) */
1843 if (sysinfo->memory_frequency == 667) {
1844 temp_drt |= (1 << 28);
1845 } else {
1846 temp_drt |= (0 << 28);
1847 }
1848
1849 /* Determine page size */
1850 reg32 = 0;
1851 page_size = 1; /* Default: 1k pagesize */
1852 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1853 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1854 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1855 page_size = 2; /* 2k pagesize */
1856 }
1857
1858 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1859 reg32 = 1;
1860 }
1861 if (sysinfo->memory_frequency == 667) {
1862 reg32 = page_size;
1863 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001864
Stefan Reinauer278534d2008-10-29 04:51:07 +00001865 temp_drt |= (reg32 << 30);
1866
1867 MCHBAR32(C0DRT1) = temp_drt;
1868 MCHBAR32(C1DRT1) = temp_drt;
1869
1870 /* Program DRT2 */
1871 reg32 = MCHBAR32(C0DRT2);
1872 reg32 &= ~(1 << 8);
1873 MCHBAR32(C0DRT2) = reg32;
1874
1875 reg32 = MCHBAR32(C1DRT2);
1876 reg32 &= ~(1 << 8);
1877 MCHBAR32(C1DRT2) = reg32;
1878
1879 /* Calculate DRT3 */
1880 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1881
1882 /* Get old tRFC value */
1883 reg32 = MCHBAR32(C0DRT1) >> 10;
1884 reg32 &= 0x3f;
1885
1886 /* 788nS - tRFC */
1887 switch (sysinfo->memory_frequency) {
1888 case 400: /* 5nS */
1889 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1890 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1891 break;
1892 case 533: /* 3.75nS */
1893 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1894 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1895 break;
1896 case 667: /* 3nS */
1897 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1898 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1899 break;
1900 }
1901
1902 temp_drt |= reg32;
1903
1904 MCHBAR32(C0DRT3) = temp_drt;
1905 MCHBAR32(C1DRT3) = temp_drt;
1906}
1907
1908static void sdram_set_channel_mode(struct sys_info *sysinfo)
1909{
1910 u32 reg32;
1911
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001912 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001913
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001914 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001915 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1916 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1917 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1918 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1919 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001920 sysinfo->interleaved = 1;
1921 } else {
1922 sysinfo->interleaved = 0;
1923 }
1924
1925 reg32 = MCHBAR32(DCC);
1926 reg32 &= ~(7 << 0);
1927
1928 if(sysinfo->interleaved) {
1929 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001930 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001931 reg32 |= (1 << 1);
1932 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1933 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1934 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001935 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001936 reg32 |= (1 << 2);
1937 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1938 SYSINFO_DIMM_NOT_POPULATED) {
1939 /* Dual Channel Assymetric */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001940 printk(BIOS_DEBUG, "Dual Channel Assymetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001941 reg32 |= (1 << 0);
1942 } else {
1943 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001944 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001945 }
1946
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001947 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001948 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001949
1950 MCHBAR32(DCC) = reg32;
1951
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001952 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001953}
1954
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001955static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001956{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001957 MCHBAR32(PLLMON) = 0x80800000;
1958
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001959 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001960 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001961 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001962
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001963 /* Program CPCTL according to FSB speed */
1964 /* Only write the lower byte */
1965 switch (sysinfo->fsb_frequency) {
1966 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1967 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1968 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1969 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001970
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001971 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001972
Paul Menzel0ce5ebf2013-10-21 21:22:09 +02001973 MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001974}
1975
1976static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1977{
1978 u8 reg8;
1979 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001980 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001981
1982#define CRCLK_166MHz 0x00
1983#define CRCLK_200MHz 0x01
1984#define CRCLK_250MHz 0x03
1985#define CRCLK_400MHz 0x05
1986
1987#define CDCLK_200MHz 0x00
1988#define CDCLK_320MHz 0x40
1989
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001990#define VOLTAGE_1_05 0x00
1991#define VOLTAGE_1_50 0x01
1992
Paul Menzeldaf9e502014-07-15 23:49:16 +02001993 printk(BIOS_DEBUG, "Setting Graphics Frequency...\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001994
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001995 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001996
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001997 voltage = VOLTAGE_1_05;
1998 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1999 voltage = VOLTAGE_1_50;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002000 printk(BIOS_DEBUG, "Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002001
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002002 /* Gate graphics hardware for frequency change */
2003 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
2004 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
2005 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002006
2007 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002008 reg8 = sdram_capabilities_core_frequencies();
2009
Stefan Reinauer278534d2008-10-29 04:51:07 +00002010 freq = CRCLK_250MHz;
2011 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002012 case GFX_FREQUENCY_CAP_ALL:
2013 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002014 freq = CRCLK_250MHz;
2015 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002016 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002017 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002018 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2019 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2020 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002021 }
2022
2023 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002024 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002025 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
2026 if (reg8==2)
2027 freq = CRCLK_166MHz;
2028 }
2029
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002030 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002031 switch (freq) {
Elyes HAOUAS0f92f632014-07-27 19:37:31 +02002032 case CRCLK_166MHz: printk(BIOS_DEBUG, "166MHz"); break;
2033 case CRCLK_200MHz: printk(BIOS_DEBUG, "200MHz"); break;
2034 case CRCLK_250MHz: printk(BIOS_DEBUG, "250MHz"); break;
2035 case CRCLK_400MHz: printk(BIOS_DEBUG, "400MHz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002036 }
2037
Stefan Reinauer278534d2008-10-29 04:51:07 +00002038 if (i945_silicon_revision() == 0) {
2039 sysinfo->mvco4x = 1;
2040 } else {
2041 sysinfo->mvco4x = 0;
2042 }
2043
Stefan Reinauer278534d2008-10-29 04:51:07 +00002044 second_vco = 0;
2045
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002046 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002047 second_vco = 1;
2048 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2049 u16 mem = sysinfo->memory_frequency;
2050 u16 fsb = sysinfo->fsb_frequency;
2051
2052 if ( (fsb == 667 && mem == 533) ||
2053 (fsb == 533 && mem == 533) ||
2054 (fsb == 533 && mem == 400)) {
2055 second_vco = 1;
2056 }
2057
2058 if (fsb == 667 && mem == 533)
2059 sysinfo->mvco4x = 1;
2060 }
2061
2062 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002063 sysinfo->clkcfg_bit7=1;
2064 } else {
2065 sysinfo->clkcfg_bit7=0;
2066 }
2067
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002068 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002069 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2070 reg16 &= ~( (7 << 0) | (1 << 13) );
2071 reg16 |= freq;
2072 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2073
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002074 /* Graphics Core Display Clock */
2075 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2076 reg8 &= ~( (1<<7) | (7<<4) );
2077
2078 if (voltage == VOLTAGE_1_05) {
2079 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002080 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002081 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002082 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002083 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002084 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002085 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002086
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002087 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002088
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002089 reg8 |= (1<<3) | (1<<1);
2090 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2091
2092 reg8 |= 0x0f;
2093 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2094
2095 /* Ungate core render and display clocks */
2096 reg8 &= 0xf0;
2097 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002098}
2099
2100static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2101{
2102 u32 clkcfg;
2103 u8 reg8;
2104
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002105 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002106
Stefan Reinauer278534d2008-10-29 04:51:07 +00002107 clkcfg = MCHBAR32(CLKCFG);
2108
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002109 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002110
2111 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2112
2113 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002114 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002115 clkcfg &= ~(1 << 12);
2116 }
2117
2118 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002119 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002120
Stefan Reinauer278534d2008-10-29 04:51:07 +00002121 clkcfg |= (1 << 7);
2122 }
2123
2124 switch (sysinfo->memory_frequency) {
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002125 case 400: clkcfg |= (2 << 4); break;
2126 case 533: clkcfg |= (3 << 4); break;
2127 case 667: clkcfg |= (4 << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002128 default: die("Target Memory Frequency Error");
2129 }
2130
2131 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002132 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002133 return;
2134 }
2135
2136 MCHBAR32(CLKCFG) = clkcfg;
2137
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002138 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002139 * cache before we execute it.
2140 */
2141 goto cache_code;
2142vco_update:
2143 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2144 reg8 &= ~(1 << 7);
2145 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2146
Stefan Reinauer278534d2008-10-29 04:51:07 +00002147 clkcfg &= ~(1 << 10);
2148 MCHBAR32(CLKCFG) = clkcfg;
2149 clkcfg |= (1 << 10);
2150 MCHBAR32(CLKCFG) = clkcfg;
2151
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002152 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002153 " movl $0x100, %%ecx\n"
2154 "delay_update:\n"
2155 " nop\n"
2156 " nop\n"
2157 " nop\n"
2158 " nop\n"
2159 " loop delay_update\n"
2160 : /* No outputs */
2161 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002162 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002163 );
2164
Stefan Reinauer278534d2008-10-29 04:51:07 +00002165 clkcfg &= ~(1 << 10);
2166 MCHBAR32(CLKCFG) = clkcfg;
2167
2168 goto out;
2169cache_code:
2170 goto vco_update;
2171out:
2172
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002173 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
2174 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002175}
2176
2177static void sdram_program_clock_crossing(void)
2178{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002179 int idx = 0;
2180
2181 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002182 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002183 */
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002184#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002185 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002186 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002187 0xffffffff, 0xffffffff, /* nonexistant */
2188 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002189
Stefan Reinauer278534d2008-10-29 04:51:07 +00002190 0x08040120, 0x00000000, /* DDR400 FSB533 */
2191 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002192 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002193
2194 0x04020120, 0x00000010, /* DDR400 FSB667 */
2195 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002196 0x00100401, 0x00000000, /* DDR667 FSB667 */
2197
2198 0xffffffff, 0xffffffff, /* nonexistant */
2199 0xffffffff, 0xffffffff, /* nonexistant */
2200 0xffffffff, 0xffffffff, /* nonexistant */
2201
2202 0xffffffff, 0xffffffff, /* nonexistant */
2203 0xffffffff, 0xffffffff, /* nonexistant */
2204 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002205 };
2206
2207 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002208 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002209 0xffffffff, 0xffffffff, /* nonexistant */
2210 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002211
Stefan Reinauer278534d2008-10-29 04:51:07 +00002212 0x00060108, 0x00000000, /* DDR400 FSB533 */
2213 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002214 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002215
2216 0x00040318, 0x00000000, /* DDR400 FSB667 */
2217 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002218 0x02010804, 0x00000000, /* DDR667 FSB667 */
2219
2220 0xffffffff, 0xffffffff, /* nonexistant */
2221 0xffffffff, 0xffffffff, /* nonexistant */
2222 0xffffffff, 0xffffffff, /* nonexistant */
2223
2224 0xffffffff, 0xffffffff, /* nonexistant */
2225 0xffffffff, 0xffffffff, /* nonexistant */
2226 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002227 };
2228
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002229#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002230 /* i945 G/P */
2231 static const u32 data_clock_crossing[] = {
2232 0xffffffff, 0xffffffff, /* nonexistant */
2233 0xffffffff, 0xffffffff, /* nonexistant */
2234 0xffffffff, 0xffffffff, /* nonexistant */
2235
2236 0x10080201, 0x00000000, /* DDR400 FSB533 */
2237 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002238 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002239
2240 0xffffffff, 0xffffffff, /* nonexistant */
2241 0xffffffff, 0xffffffff, /* nonexistant */
2242 0xffffffff, 0xffffffff, /* nonexistant */
2243
2244 0x04020108, 0x00000000, /* DDR400 FSB800 */
2245 0x00020108, 0x00000000, /* DDR533 FSB800 */
2246 0x00080201, 0x00000000, /* DDR667 FSB800 */
2247
2248 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2249 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2250 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2251 };
2252
2253 static const u32 command_clock_crossing[] = {
2254 0xffffffff, 0xffffffff, /* nonexistant */
2255 0xffffffff, 0xffffffff, /* nonexistant */
2256 0xffffffff, 0xffffffff, /* nonexistant */
2257
2258 0x00010800, 0x00000402, /* DDR400 FSB533 */
2259 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002260 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002261
2262 0xffffffff, 0xffffffff, /* nonexistant */
2263 0xffffffff, 0xffffffff, /* nonexistant */
2264 0xffffffff, 0xffffffff, /* nonexistant */
2265
2266 0x02010804, 0x00000000, /* DDR400 FSB800 */
2267 0x00010402, 0x00000000, /* DDR533 FSB800 */
2268 0x04020180, 0x00000008, /* DDR667 FSB800 */
2269
2270 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2271 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2272 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2273 };
2274#endif
2275
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002276 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002277
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002278 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002279 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002280 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2281 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2282 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2283 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002284 }
2285
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002286 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002287 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002288 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2289 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2290 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2291 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2292 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2293 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002294 }
2295
2296 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002297 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002298 }
2299
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002300 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2301 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2302
Stefan Reinauer278534d2008-10-29 04:51:07 +00002303 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2304 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2305 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2306 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2307
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002308 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002309}
2310
2311static void sdram_disable_fast_dispatch(void)
2312{
2313 u32 reg32;
2314
2315 reg32 = MCHBAR32(FSBPMC3);
2316 reg32 |= (1 << 1);
2317 MCHBAR32(FSBPMC3) = reg32;
2318
2319 reg32 = MCHBAR32(SBTEST);
2320 reg32 |= (3 << 1);
2321 MCHBAR32(SBTEST) = reg32;
2322}
2323
2324static void sdram_pre_jedec_initialization(void)
2325{
2326 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002327
Stefan Reinauer278534d2008-10-29 04:51:07 +00002328 reg32 = MCHBAR32(WCC);
2329 reg32 &= 0x113ff3ff;
2330 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2331 MCHBAR32(WCC) = reg32;
2332
2333 MCHBAR32(SMVREFC) |= (1 << 6);
2334
2335 MCHBAR32(MMARB0) &= ~(3 << 17);
2336 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2337
2338 MCHBAR32(MMARB1) &= ~(7 << 8);
2339 MCHBAR32(MMARB1) |= (3 << 8);
2340
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002341 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002342 MCHBAR32(C0AIT) = 0x000006c4;
2343 MCHBAR32(C0AIT+4) = 0x871a066d;
2344
2345 MCHBAR32(C1AIT) = 0x000006c4;
2346 MCHBAR32(C1AIT+4) = 0x871a066d;
2347}
2348
2349#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2350#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2351#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2352#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2353#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2354#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2355#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2356#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2357
2358static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2359{
2360 u32 chan0 = 0, chan1 = 0;
2361 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2362
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002363 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002364 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002365 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002366 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2367 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2368 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2369
2370 if (sdram_capabilities_enhanced_addressing_xor()) {
2371 if (!sysinfo->interleaved) {
2372 /* Single Channel & Dual Channel Assymetric */
2373 if (chan0_populated) {
2374 if (chan0_dualsided) {
2375 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2376 } else {
2377 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2378 }
2379 }
2380 if (chan1_populated) {
2381 if (chan1_dualsided) {
2382 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2383 } else {
2384 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2385 }
2386 }
2387 } else {
2388 /* Interleaved has always both channels populated */
2389 if (chan0_dualsided) {
2390 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2391 } else {
2392 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2393 }
2394
2395 if (chan1_dualsided) {
2396 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2397 } else {
2398 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2399 }
2400 }
2401 } else {
2402 if (!sysinfo->interleaved) {
2403 /* Single Channel & Dual Channel Assymetric */
2404 if (chan0_populated) {
2405 if (chan0_dualsided) {
2406 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2407 } else {
2408 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2409 }
2410 }
2411 if (chan1_populated) {
2412 if (chan1_dualsided) {
2413 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2414 } else {
2415 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2416 }
2417 }
2418 } else {
2419 /* Interleaved has always both channels populated */
2420 if (chan0_dualsided) {
2421 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2422 } else {
2423 chan0 = EA_DUALCHANNEL_BANK_MODE;
2424 }
2425
2426 if (chan1_dualsided) {
2427 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2428 } else {
2429 chan1 = EA_DUALCHANNEL_BANK_MODE;
2430 }
2431 }
2432 }
2433
2434 MCHBAR32(C0DRC1) &= 0x00ffffff;
2435 MCHBAR32(C0DRC1) |= chan0;
2436 MCHBAR32(C1DRC1) &= 0x00ffffff;
2437 MCHBAR32(C1DRC1) |= chan1;
2438}
2439
2440static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2441{
2442 u32 reg32;
2443
2444 /* Enable Channel XORing for Dual Channel Interleave */
2445 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002446
Stefan Reinauer278534d2008-10-29 04:51:07 +00002447 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002448#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002449 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002450 reg32 |= (1 << 9);
2451#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002452 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002453#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002454 MCHBAR32(DCC) = reg32;
2455 }
2456
2457 /* DRAM mode optimizations */
2458 sdram_enhanced_addressing_mode(sysinfo);
2459
2460 reg32 = MCHBAR32(FSBPMC3);
2461 reg32 &= ~(1 << 1);
2462 MCHBAR32(FSBPMC3) = reg32;
2463
2464 reg32 = MCHBAR32(SBTEST);
2465 reg32 &= ~(1 << 2);
2466 MCHBAR32(SBTEST) = reg32;
2467
2468 reg32 = MCHBAR32(SBOCC);
2469 reg32 &= 0xffbdb6ff;
2470 reg32 |= (0xbdb6 << 8) | (1 << 0);
2471 MCHBAR32(SBOCC) = reg32;
2472}
2473
2474static void sdram_power_management(struct sys_info *sysinfo)
2475{
2476 u8 reg8;
2477 u16 reg16;
2478 u32 reg32;
2479 int integrated_graphics = 1;
2480 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002481
Stefan Reinauer278534d2008-10-29 04:51:07 +00002482 reg32 = MCHBAR32(C0DRT2);
2483 reg32 &= 0xffffff00;
2484 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002485 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002486 MCHBAR32(C0DRT2) = reg32;
2487
2488 reg32 = MCHBAR32(C1DRT2);
2489 reg32 &= 0xffffff00;
2490 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002491 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002492 MCHBAR32(C1DRT2) = reg32;
2493
2494 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002495
2496 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002497 MCHBAR32(C0DRC1) = reg32;
2498
2499 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002500
2501 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002502 MCHBAR32(C1DRC1) = reg32;
2503
2504 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002505 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2506 u16 peg_bits = (1 << 5) | (1 << 0);
2507
2508 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002509 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002510 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2511 u16 peg_bits = (1 << 5) | (1 << 0);
2512
Stefan Reinauer278534d2008-10-29 04:51:07 +00002513 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002514 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002515 }
2516
2517 reg16 = MCHBAR16(UPMC2);
2518 reg16 &= 0xfc00;
2519 reg16 |= 0x0100;
2520 MCHBAR16(UPMC2) = reg16;
2521
2522 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002523
Stefan Reinauer278534d2008-10-29 04:51:07 +00002524 for (i=0; i<5; i++) {
2525 MCHBAR32(UPMC3) &= ~(1 << 16);
2526 MCHBAR32(UPMC3) |= (1 << 16);
2527 }
2528
2529 MCHBAR32(GIPMC1) = 0x8000000c;
2530
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002531 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002532 reg16 &= ~(7 << 11);
2533 if (i945_silicon_revision()>2) {
2534 reg16 |= (6 << 11);
2535 } else {
2536 reg16 |= (4 << 11);
2537 }
2538 MCHBAR16(CPCTL) = reg16;
2539
Stefan Reinauer30140a52009-03-11 16:20:39 +00002540#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002541 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002542#else
2543 if (i945_silicon_revision() != 0) {
2544#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002545 switch (sysinfo->fsb_frequency) {
2546 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2547 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2548 }
2549 } else {
2550 switch (sysinfo->fsb_frequency) {
2551 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2552 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2553 }
2554 }
2555
2556 MCHBAR32(FSBPMC1) = 0x8000000c;
2557
2558 reg32 = MCHBAR32(C2C3TT);
2559 reg32 &= 0xffff0000;
2560 switch (sysinfo->fsb_frequency) {
2561 case 667: reg32 |= 0x0600; break;
2562 case 533: reg32 |= 0x0480; break;
2563 }
2564 MCHBAR32(C2C3TT) = reg32;
2565
2566 reg32 = MCHBAR32(C3C4TT);
2567 reg32 &= 0xffff0000;
2568 switch (sysinfo->fsb_frequency) {
2569 case 667: reg32 |= 0x0b80; break;
2570 case 533: reg32 |= 0x0980; break;
2571 }
2572 MCHBAR32(C3C4TT) = reg32;
2573
2574 if (i945_silicon_revision() == 0) {
2575 MCHBAR32(ECO) &= ~(1 << 16);
2576 } else {
2577 MCHBAR32(ECO) |= (1 << 16);
2578 }
2579
2580#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002581
Stefan Reinauer278534d2008-10-29 04:51:07 +00002582 if (i945_silicon_revision() == 0) {
2583 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2584 } else {
2585 MCHBAR32(FSBPMC3) |= (1 << 29);
2586 }
2587#endif
2588 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2589
2590 MCHBAR32(FSBPMC3) |= (1 << 21);
2591
2592 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2593
2594 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2595
2596 reg32 = MCHBAR32(FSBPMC4);
2597 reg32 &= ~(3 << 24);
2598 reg32 |= ( 2 << 24);
2599 MCHBAR32(FSBPMC4) = reg32;
2600
2601 MCHBAR32(FSBPMC4) |= (1 << 21);
2602
2603 MCHBAR32(FSBPMC4) |= (1 << 5);
2604
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002605 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2606 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002607 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2608 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002609 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002610 }
2611
2612 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2613 reg8 |= (1 << 4);
2614 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2615
2616 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2617 reg8 |= (1 << 2);
2618 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2619
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002620#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002621
Stefan Reinauer278534d2008-10-29 04:51:07 +00002622 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002623 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002624 MCHBAR16(MIPMC4) = 0x0468;
2625 MCHBAR16(MIPMC5) = 0x046c;
2626 MCHBAR16(MIPMC6) = 0x046c;
2627 } else {
2628 MCHBAR16(MIPMC4) = 0x6468;
2629 MCHBAR16(MIPMC5) = 0x646c;
2630 MCHBAR16(MIPMC6) = 0x646c;
2631 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002632#else
2633 if (integrated_graphics) {
2634 MCHBAR16(MIPMC4) = 0x04f8;
2635 MCHBAR16(MIPMC5) = 0x04fc;
2636 MCHBAR16(MIPMC6) = 0x04fc;
2637 } else {
2638 MCHBAR16(MIPMC4) = 0x64f8;
2639 MCHBAR16(MIPMC5) = 0x64fc;
2640 MCHBAR16(MIPMC6) = 0x64fc;
2641 }
2642
2643#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002644
2645 reg32 = MCHBAR32(PMCFG);
2646 reg32 &= ~(3 << 17);
2647 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002648 MCHBAR32(PMCFG) = reg32;
2649
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002650 MCHBAR32(PMCFG) |= (1 << 4);
2651
Stefan Reinauer278534d2008-10-29 04:51:07 +00002652 reg32 = MCHBAR32(0xc30);
2653 reg32 &= 0xffffff00;
2654 reg32 |= 0x01;
2655 MCHBAR32(0xc30) = reg32;
2656
2657 MCHBAR32(0xb18) &= ~(1 << 21);
2658}
2659
2660static void sdram_thermal_management(void)
2661{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002662
Stefan Reinauer278534d2008-10-29 04:51:07 +00002663 MCHBAR8(TCO1) = 0x00;
2664 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002665
2666 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2667 * 0x30/0x32.
2668 */
2669
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002670 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002671}
2672
2673static void sdram_save_receive_enable(void)
2674{
2675 int i;
2676 u32 reg32;
2677 u8 values[4];
2678
2679 /* The following values are stored to an unused CMOS
2680 * area and restored instead of recalculated in case
2681 * of an S3 resume.
2682 *
2683 * C0WL0REOST [7:0] -> 8 bit
2684 * C1WL0REOST [7:0] -> 8 bit
2685 * RCVENMT [11:8] [3:0] -> 8 bit
2686 * C0DRT1 [27:24] -> 4 bit
2687 * C1DRT1 [27:24] -> 4 bit
2688 */
2689
2690 values[0] = MCHBAR8(C0WL0REOST);
2691 values[1] = MCHBAR8(C1WL0REOST);
2692
2693 reg32 = MCHBAR32(RCVENMT);
2694 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2695
2696 reg32 = MCHBAR32(C0DRT1);
2697 values[3] = (reg32 >> 24) & 0x0f;
2698 reg32 = MCHBAR32(C1DRT1);
2699 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2700
2701 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002702 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002703 */
2704
2705 for (i=0; i<4; i++)
2706 cmos_write(values[i], 128 + i);
2707}
2708
2709static void sdram_recover_receive_enable(void)
2710{
2711 int i;
2712 u32 reg32;
2713 u8 values[4];
2714
2715 for (i=0; i<4; i++)
2716 values[i] = cmos_read(128 + i);
2717
2718 MCHBAR8(C0WL0REOST) = values[0];
2719 MCHBAR8(C1WL0REOST) = values[1];
2720
2721 reg32 = MCHBAR32(RCVENMT);
2722 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2723 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2724 MCHBAR32(RCVENMT) = reg32;
2725
2726 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2727 reg32 |= (u32)(values[3] & 0x0f) << 24;
2728 MCHBAR32(C0DRT1) = reg32;
2729
2730 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2731 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2732 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002733}
2734
2735#include "rcven.c"
2736
2737static void sdram_program_receive_enable(struct sys_info *sysinfo)
2738{
2739 MCHBAR32(REPC) |= (1 << 0);
2740
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002741 /* enable upper CMOS */
2742 RCBA32(0x3400) = (1 << 2);
2743
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002744 /* Program Receive Enable Timings */
2745 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2746 sdram_recover_receive_enable();
2747 } else {
2748 receive_enable_adjust(sysinfo);
2749 sdram_save_receive_enable();
2750 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002751
2752 MCHBAR32(C0DRC1) |= (1 << 6);
2753 MCHBAR32(C1DRC1) |= (1 << 6);
2754 MCHBAR32(C0DRC1) &= ~(1 << 6);
2755 MCHBAR32(C1DRC1) &= ~(1 << 6);
2756
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002757 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002758}
2759
2760/**
2761 * @brief Enable On-Die Termination for DDR2.
2762 *
2763 */
2764
2765static void sdram_on_die_termination(struct sys_info *sysinfo)
2766{
2767 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002768 0x00024911, 0xe0010000,
2769 0x00049211, 0xe0020000,
2770 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002771 };
2772
2773 u32 reg32;
2774 int cas;
2775
2776 reg32 = MCHBAR32(ODTC);
2777 reg32 &= ~(3 << 16);
2778 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2779 MCHBAR32(ODTC) = reg32;
2780
2781 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2782 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002783 printk(BIOS_DEBUG, "one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002784
Stefan Reinauer278534d2008-10-29 04:51:07 +00002785 reg32 = MCHBAR32(C0ODT);
2786 reg32 &= ~(7 << 28);
2787 MCHBAR32(C0ODT) = reg32;
2788 reg32 = MCHBAR32(C1ODT);
2789 reg32 &= ~(7 << 28);
2790 MCHBAR32(C1ODT) = reg32;
2791 }
2792
2793 cas = sysinfo->cas;
2794
2795 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2796 reg32 |= odt[(cas-3) * 2];
2797 MCHBAR32(C0ODT) = reg32;
2798
2799 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2800 reg32 |= odt[(cas-3) * 2];
2801 MCHBAR32(C1ODT) = reg32;
2802
2803 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2804 reg32 |= odt[((cas-3) * 2) + 1];
2805 MCHBAR32(C0ODT + 4) = reg32;
2806
2807 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2808 reg32 |= odt[((cas-3) * 2) + 1];
2809 MCHBAR32(C1ODT + 4) = reg32;
2810}
2811
2812/**
2813 * @brief Enable clocks to populated sockets
2814 */
2815
2816static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2817{
2818 u8 clocks[2] = { 0, 0 };
2819
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002820#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002821#define CLOCKS_WIDTH 2
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002822#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002823#define CLOCKS_WIDTH 3
2824#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002825 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002826 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002827
2828 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002829 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002830
2831 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002832 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002833
2834 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002835 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002836
Patrick Georgi77d66832010-10-01 08:02:45 +00002837#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002838 /* Usually system firmware turns off system memory clock signals
2839 * to unused SO-DIMM slots to reduce EMI and power consumption.
2840 * However, the Kontron 986LCD-M does not like unused clock
2841 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002842 */
2843
2844 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2845 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002846#endif
2847
2848 MCHBAR8(C0DCLKDIS) = clocks[0];
2849 MCHBAR8(C1DCLKDIS) = clocks[1];
2850}
2851
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002852#define RTT_ODT_NONE 0
2853#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002854#define RTT_ODT_75_OHM (1 << 5)
2855#define RTT_ODT_150_OHM (1 << 9)
2856
2857#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2858
2859#define MRS_CAS_3 (3 << 7)
2860#define MRS_CAS_4 (4 << 7)
2861#define MRS_CAS_5 (5 << 7)
2862
2863#define MRS_TWR_3 (2 << 12)
2864#define MRS_TWR_4 (3 << 12)
2865#define MRS_TWR_5 (4 << 12)
2866
2867#define MRS_BT (1 << 6)
2868
2869#define MRS_BL4 (2 << 3)
2870#define MRS_BL8 (3 << 3)
2871
2872static void sdram_jedec_enable(struct sys_info *sysinfo)
2873{
2874 int i, nonzero;
2875 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2876
2877 for (i = 0, nonzero = -1; i < 8; i++) {
2878 if (sysinfo->banksize[i] == 0) {
2879 continue;
2880 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002881
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002882 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002883 switch (i) {
2884 case 0:
2885 /* Start at address 0 */
2886 bankaddr = 0;
2887 break;
2888 case 4:
2889 if (sysinfo->interleaved) {
2890 bankaddr = 0x40;
2891 break;
2892 }
2893 default:
2894 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002895 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002896 bankaddr += sysinfo->banksize[nonzero] <<
2897 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002898 break;
2899 }
2900 /* No populated bank hit before. Start at address 0 */
2901 bankaddr = 0;
2902 }
2903
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002904 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002905 * for the next offset we have to calculate
2906 */
2907 nonzero = i;
2908
2909 /* Get CAS latency set up */
2910 switch (sysinfo->cas) {
2911 case 5: mrsaddr = MRS_CAS_5; break;
2912 case 4: mrsaddr = MRS_CAS_4; break;
2913 case 3: mrsaddr = MRS_CAS_3; break;
2914 default: die("Jedec Error (CAS).\n");
2915 }
2916
2917 /* Get tWR set */
2918 switch (sysinfo->twr) {
2919 case 5: mrsaddr |= MRS_TWR_5; break;
2920 case 4: mrsaddr |= MRS_TWR_4; break;
2921 case 3: mrsaddr |= MRS_TWR_3; break;
2922 default: die("Jedec Error (tWR).\n");
2923 }
2924
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002925 /* Set "Burst Type" */
2926 mrsaddr |= MRS_BT;
2927
Stefan Reinauer278534d2008-10-29 04:51:07 +00002928 /* Interleaved */
2929 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002930 mrsaddr = mrsaddr << 1;
2931 }
2932
2933 /* Only burst length 8 supported */
2934 mrsaddr |= MRS_BL8;
2935
2936 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002937 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002938 do_ram_command(RAM_COMMAND_NOP);
2939 ram_read32(bankaddr);
2940
2941 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002942 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002943 do_ram_command(RAM_COMMAND_PRECHARGE);
2944 ram_read32(bankaddr);
2945
2946 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002947 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002948 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2949 ram_read32(bankaddr);
2950
2951 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002952 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002953 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2954 ram_read32(bankaddr);
2955
2956 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002957 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002958 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2959 tmpaddr = bankaddr;
2960 if (!sdram_capabilities_dual_channel()) {
2961 tmpaddr |= RTT_ODT_75_OHM;
2962 } else if (sysinfo->interleaved) {
2963 tmpaddr |= (RTT_ODT_150_OHM << 1);
2964 } else {
2965 tmpaddr |= RTT_ODT_150_OHM;
2966 }
2967 ram_read32(tmpaddr);
2968
2969 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002970 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002971 do_ram_command(RAM_COMMAND_MRS);
2972 tmpaddr = bankaddr;
2973 tmpaddr |= mrsaddr;
2974 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002975 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002976 tmpaddr |= (1 << 12);
2977 else
2978 tmpaddr |= (1 << 11);
2979 ram_read32(tmpaddr);
2980
2981 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002982 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002983 do_ram_command(RAM_COMMAND_PRECHARGE);
2984 ram_read32(bankaddr);
2985
2986 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002987 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002988 do_ram_command(RAM_COMMAND_CBR);
2989
2990 /* CBR wants two READs */
2991 ram_read32(bankaddr);
2992 ram_read32(bankaddr);
2993
2994 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002995 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002996 do_ram_command(RAM_COMMAND_MRS);
2997
2998 tmpaddr = bankaddr;
2999 tmpaddr |= mrsaddr;
3000 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003001
Stefan Reinauer278534d2008-10-29 04:51:07 +00003002 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003003 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003004 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003005
Stefan Reinauer278534d2008-10-29 04:51:07 +00003006 tmpaddr = bankaddr;
3007 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003008
Stefan Reinauer278534d2008-10-29 04:51:07 +00003009 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
3010 } else if (sysinfo->interleaved) {
3011 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
3012 } else {
3013 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
3014 }
3015 ram_read32(tmpaddr);
3016
3017 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003018 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003019 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3020
3021 tmpaddr = bankaddr;
3022 if (!sdram_capabilities_dual_channel()) {
3023 tmpaddr |= RTT_ODT_75_OHM;
3024 } else if (sysinfo->interleaved) {
3025 tmpaddr |= (RTT_ODT_150_OHM << 1);
3026 } else {
3027 tmpaddr |= RTT_ODT_150_OHM;
3028 }
3029 ram_read32(tmpaddr);
3030 }
3031}
3032
3033static void sdram_init_complete(void)
3034{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003035 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003036 do_ram_command(RAM_COMMAND_NORMAL);
3037}
3038
3039static void sdram_setup_processor_side(void)
3040{
3041 if (i945_silicon_revision() == 0)
3042 MCHBAR32(FSBPMC3) |= (1 << 2);
3043
3044 MCHBAR8(0xb00) |= 1;
3045
3046 if (i945_silicon_revision() == 0)
3047 MCHBAR32(SLPCTL) |= (1 << 8);
3048}
3049
Stefan Reinauer278534d2008-10-29 04:51:07 +00003050/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003051 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Martin Rothf4cb4122015-01-06 10:27:39 -07003052 * @param spd_addresses pointer to a list of SPD addresses
Stefan Reinauer278534d2008-10-29 04:51:07 +00003053 */
Sven Schnelle541269b2011-02-21 09:39:17 +00003054void sdram_initialize(int boot_path, const u8 *spd_addresses)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003055{
3056 struct sys_info sysinfo;
3057 u8 reg8, cas_mask;
3058
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003059 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003060
3061 memset(&sysinfo, 0, sizeof(sysinfo));
3062
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003063 sysinfo.boot_path = boot_path;
Sven Schnelle541269b2011-02-21 09:39:17 +00003064 sysinfo.spd_addresses = spd_addresses;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003065
Stefan Reinauer278534d2008-10-29 04:51:07 +00003066 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3067 sdram_get_dram_configuration(&sysinfo);
3068
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003069 /* If error, do cold boot */
3070 sdram_detect_errors(&sysinfo);
3071
Stefan Reinauer278534d2008-10-29 04:51:07 +00003072 /* Check whether we have stacked DIMMs */
3073 sdram_verify_package_type(&sysinfo);
3074
3075 /* Determine common CAS */
3076 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003077
Stefan Reinauer278534d2008-10-29 04:51:07 +00003078 /* Choose Common Frequency */
3079 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003080
Stefan Reinauer278534d2008-10-29 04:51:07 +00003081 /* Determine smallest common tRAS */
3082 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003083
Stefan Reinauer278534d2008-10-29 04:51:07 +00003084 /* Determine tRP */
3085 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003086
Stefan Reinauer278534d2008-10-29 04:51:07 +00003087 /* Determine tRCD */
3088 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003089
Stefan Reinauer278534d2008-10-29 04:51:07 +00003090 /* Determine smallest refresh period */
3091 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003092
Stefan Reinauer278534d2008-10-29 04:51:07 +00003093 /* Verify all DIMMs support burst length 8 */
3094 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003095
Stefan Reinauer278534d2008-10-29 04:51:07 +00003096 /* determine tWR */
3097 sdram_detect_smallest_tWR(&sysinfo);
3098
3099 /* Determine DIMM size parameters (rows, columns banks) */
3100 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003101
Stefan Reinauer278534d2008-10-29 04:51:07 +00003102 /* determine tRFC */
3103 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003104
Stefan Reinauer278534d2008-10-29 04:51:07 +00003105 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003106 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003107
3108 /* Program Graphics Frequency */
3109 sdram_program_graphics_frequency(&sysinfo);
3110
3111 /* Program System Memory Frequency */
3112 sdram_program_memory_frequency(&sysinfo);
3113
3114 /* Determine Mode of Operation (Interleaved etc) */
3115 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003116
Stefan Reinauer278534d2008-10-29 04:51:07 +00003117 /* Program Clock Crossing values */
3118 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003119
Stefan Reinauer278534d2008-10-29 04:51:07 +00003120 /* Disable fast dispatch */
3121 sdram_disable_fast_dispatch();
3122
3123 /* Enable WIODLL Power Down in ACPI states */
3124 MCHBAR32(C0DMC) |= (1 << 24);
3125 MCHBAR32(C1DMC) |= (1 << 24);
3126
3127 /* Program DRAM Row Boundary/Attribute Registers */
3128
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003129 /* program row size DRB and set TOLUD */
3130 sdram_program_row_boundaries(&sysinfo);
3131
3132 /* program page size DRA */
3133 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003134
3135 /* Program CxBNKARC */
3136 sdram_set_bank_architecture(&sysinfo);
3137
3138 /* Program DRAM Timing and Control registers based on SPD */
3139 sdram_set_timing_and_control(&sysinfo);
3140
3141 /* On-Die Termination Adjustment */
3142 sdram_on_die_termination(&sysinfo);
3143
3144 /* Pre Jedec Initialization */
3145 sdram_pre_jedec_initialization();
3146
3147 /* Perform System Memory IO Initialization */
3148 sdram_initialize_system_memory_io(&sysinfo);
3149
3150 /* Perform System Memory IO Buffer Enable */
3151 sdram_enable_system_memory_io(&sysinfo);
3152
3153 /* Enable System Memory Clocks */
3154 sdram_enable_memory_clocks(&sysinfo);
3155
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003156 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003157 /* Jedec Initialization sequence */
3158 sdram_jedec_enable(&sysinfo);
3159 }
3160
3161 /* Program Power Management Registers */
3162 sdram_power_management(&sysinfo);
3163
3164 /* Post Jedec Init */
3165 sdram_post_jedec_initialization(&sysinfo);
3166
3167 /* Program DRAM Throttling */
3168 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003169
Stefan Reinauer278534d2008-10-29 04:51:07 +00003170 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003171 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003172
3173 /* Program Receive Enable Timings */
3174 sdram_program_receive_enable(&sysinfo);
3175
3176 /* Enable Periodic RCOMP */
3177 sdram_enable_rcomp();
3178
3179 /* Tell ICH7 that we're done */
3180 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3181 reg8 &= ~(1 << 7);
3182 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3183
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003184 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003185
Stefan Reinauer278534d2008-10-29 04:51:07 +00003186 sdram_setup_processor_side();
3187}