blob: 478a9c8b70c7e6f297d308f19d19660f3c6d017b [file] [log] [blame]
Stefan Reinauer278534d2008-10-29 04:51:07 +00001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer71a3d962009-07-21 21:44:24 +00004 * Copyright (C) 2007-2009 coresystems GmbH
Stefan Reinauer278534d2008-10-29 04:51:07 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
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>
26#include <arch/romcc_io.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000027#include "raminit.h"
28#include "i945.h"
Rudolf Marekc4369532010-12-13 19:59:13 +000029#include <cbmem.h>
30
Stefan Reinauer259a39f2010-12-16 23:24:27 +000031struct cbmem_entry *get_cbmem_toc(void)
32{
Rudolf Marekc4369532010-12-13 19:59:13 +000033 return (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
34}
Stefan Reinauer278534d2008-10-29 04:51:07 +000035
Stefan Reinauer278534d2008-10-29 04:51:07 +000036/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000037#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000038#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Stefan Reinauer278534d2008-10-29 04:51:07 +000039#else
40#define PRINTK_DEBUG(x...)
41#endif
42
Stefan Reinauer278534d2008-10-29 04:51:07 +000043#define RAM_INITIALIZATION_COMPLETE (1 << 19)
44
45#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
46#define RAM_COMMAND_NOP (0x1 << 16)
47#define RAM_COMMAND_PRECHARGE (0x2 << 16)
48#define RAM_COMMAND_MRS (0x3 << 16)
49#define RAM_COMMAND_EMRS (0x4 << 16)
50#define RAM_COMMAND_CBR (0x6 << 16)
51#define RAM_COMMAND_NORMAL (0x7 << 16)
52
53#define RAM_EMRS_1 (0x0 << 21)
54#define RAM_EMRS_2 (0x1 << 21)
55#define RAM_EMRS_3 (0x2 << 21)
56
Sven Schnelle541269b2011-02-21 09:39:17 +000057static int get_dimm_spd_address(struct sys_info *sysinfo, int device)
58{
59 if (sysinfo->spd_addresses)
60 return sysinfo->spd_addresses[device];
61 else
62 return DIMM0 + device;
63
64}
65
Patrick Georgid0835952010-10-05 09:07:10 +000066static inline int spd_read_byte(unsigned device, unsigned address)
67{
68 return smbus_read_byte(device, address);
69}
70
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000071static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000072{
73 u32 reg32;
74
75 reg32 = MCHBAR32(DCC);
76 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
77 reg32 |= command;
78
79 /* Also set Init Complete */
80 if (command == RAM_COMMAND_NORMAL)
81 reg32 |= RAM_INITIALIZATION_COMPLETE;
82
83 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
84
85 MCHBAR32(DCC) = reg32; /* This is the actual magic */
86
Stefan Reinauer779b3e32008-11-10 15:43:37 +000087 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000088
89 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000090}
91
Stefan Reinauer278534d2008-10-29 04:51:07 +000092static void ram_read32(u32 offset)
93{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000094 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000095
96 read32(offset);
97}
98
Uwe Hermann01ce6012010-03-05 10:03:50 +000099#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer3c0bfaf2010-12-27 11:34:57 +0000100void sdram_dump_mchbar_registers(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000101{
102 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000103 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000104
105 for (i=0; i<0xfff; i+=4) {
106 if (MCHBAR32(i) == 0)
107 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000108 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000109 }
110}
111#endif
112
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000113static int memclk(void)
114{
115 int offset = 0;
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200116#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000117 offset++;
118#endif
119 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
120 case 1: return 400;
121 case 2: return 533;
122 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000123 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000124 }
125 return -1;
126}
127
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200128#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Peter Stuge76d91432010-10-01 10:02:33 +0000129static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000130{
131 switch (MCHBAR32(CLKCFG) & 7) {
132 case 0: return 400;
133 case 1: return 533;
134 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000135 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000136 }
Peter Stuge76d91432010-10-01 10:02:33 +0000137 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000138}
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200139#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Peter Stuge76d91432010-10-01 10:02:33 +0000140static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000141{
142 switch (MCHBAR32(CLKCFG) & 7) {
143 case 0: return 1066;
144 case 1: return 533;
145 case 2: return 800;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000146 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000147 }
Peter Stuge76d91432010-10-01 10:02:33 +0000148 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000149}
150#endif
151
Stefan Reinauer278534d2008-10-29 04:51:07 +0000152static int sdram_capabilities_max_supported_memory_frequency(void)
153{
154 u32 reg32;
155
Patrick Georgi77d66832010-10-01 08:02:45 +0000156#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
157 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000158#endif
159
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000160 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000161 reg32 &= (7 << 0);
162
163 switch (reg32) {
164 case 4: return 400;
165 case 3: return 533;
166 case 2: return 667;
167 }
168 /* Newer revisions of this chipset rather support faster memory clocks,
169 * so if it's a reserved value, return the fastest memory clock that we
170 * know of and can handle
171 */
172 return 667;
173}
174
175/**
176 * @brief determine whether chipset is capable of dual channel interleaved mode
177 *
178 * @return 1 if interleaving is supported, 0 otherwise
179 */
180static int sdram_capabilities_interleave(void)
181{
182 u32 reg32;
183
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000184 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000185 reg32 >>= 25;
186 reg32 &= 1;
187
188 return (!reg32);
189}
190
191/**
192 * @brief determine whether chipset is capable of two memory channels
193 *
194 * @return 1 if dual channel operation is supported, 0 otherwise
195 */
196static int sdram_capabilities_dual_channel(void)
197{
198 u32 reg32;
199
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000200 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000201 reg32 >>= 24;
202 reg32 &= 1;
203
204 return (!reg32);
205}
206
207static int sdram_capabilities_enhanced_addressing_xor(void)
208{
209 u8 reg8;
210
211 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
212 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000213
Stefan Reinauer278534d2008-10-29 04:51:07 +0000214 return (!reg8);
215}
216
217static int sdram_capabilities_two_dimms_per_channel(void)
218{
219 u8 reg8;
220
221 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
222 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000223
Stefan Reinauer278534d2008-10-29 04:51:07 +0000224 return (reg8 != 0);
225}
226
Stefan Reinauer14e22772010-04-27 06:56:47 +0000227// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000228#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000229static int sdram_capabilities_MEM4G_disable(void)
230{
231 u8 reg8;
232
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000233 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000234 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000235
Stefan Reinauer278534d2008-10-29 04:51:07 +0000236 return (reg8 != 0);
237}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000238#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000239
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000240#define GFX_FREQUENCY_CAP_166MHZ 0x04
241#define GFX_FREQUENCY_CAP_200MHZ 0x03
242#define GFX_FREQUENCY_CAP_250MHZ 0x02
243#define GFX_FREQUENCY_CAP_ALL 0x00
244
245static int sdram_capabilities_core_frequencies(void)
246{
247 u8 reg8;
248
249 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
250 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
251 reg8 >>= 1;
252
253 return (reg8);
254}
255
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000256static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000257{
258 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000259 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000260
261 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000262
Stefan Reinauer278534d2008-10-29 04:51:07 +0000263 if (reg8 & ((1<<7)|(1<<2))) {
264 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000265 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000266 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000267 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000268 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000269
Stefan Reinauer278534d2008-10-29 04:51:07 +0000270 }
271
272 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000273 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000274 reg8 &= ~(1<<7);
275 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000276 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000277 }
278
279 /* Set SLP_S3# Assertion Stretch Enable */
280 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
281 reg8 |= (1 << 3);
282 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
283
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000284 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000285 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000286 outb(0x00, 0xcf9);
287 outb(0x0e, 0xcf9);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000288 for (;;) asm("hlt"); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000289 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000290 }
291
292 /* Set DRAM initialization bit in ICH7 */
293 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
294 reg8 |= (1<<7);
295 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000296
Peter Stuge751508a2012-01-27 22:17:09 +0100297 /* clear self refresh status if check is disabled or not a resume */
298 if (!CONFIG_CHECK_SLFRCS_ON_RESUME || sysinfo->boot_path != 2) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000299 MCHBAR8(0xf14) |= 3;
300 } else {
301 /* Validate self refresh config */
302 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
303 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
304 !(MCHBAR8(0xf14) & (1<<0))) {
305 do_reset = 1;
306 }
307 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
308 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
309 !(MCHBAR8(0xf14) & (1<<1))) {
310 do_reset = 1;
311 }
312 }
313
314 if (do_reset) {
315 printk(BIOS_DEBUG, "Reset required.\n");
316 outb(0x00, 0xcf9);
317 outb(0x0e, 0xcf9);
318 for (;;) asm("hlt"); /* Wait for reset! */
319 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000320}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000321
322/**
323 * @brief Get generic DIMM parameters.
324 * @param sysinfo Central memory controller information structure
325 *
326 * This function gathers several pieces of information for each system DIMM:
327 * o DIMM width (x8 / x16)
328 * o DIMM sides (single sided / dual sided)
329 *
330 * Also, some non-supported scenarios are detected.
331 */
332
333static void sdram_get_dram_configuration(struct sys_info *sysinfo)
334{
335 u32 dimm_mask = 0;
336 int i;
337
338 /**
339 * i945 supports two DIMMs, in two configurations:
340 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000341 * - single channel with two DIMMs
342 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000343 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000344 * In practice dual channel mainboards have their SPD at 0x50/0x52
345 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000346 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000347 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000348 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000349 */
350
351 if (sdram_capabilities_dual_channel()) {
352 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000353 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000354 } else {
355 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000356 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000357 }
358
359 /**
360 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000361 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000362 * return value:
363 * [0:7] lower DIMM population
364 * [8-15] higher DIMM population
365 * [16] dual channel?
366 *
367 * There are 5 different possible populations for a DIMM socket:
368 * 1. x16 double sided (X16DS)
369 * 2. x8 double sided (X8DS)
370 * 3. x16 single sided (X16SS)
371 * 4. x8 double stacked (X8DDS)
372 * 5. not populated (NC)
373 *
374 * For the return value we start counting at zero.
375 *
376 */
377
378 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000379 int device = get_dimm_spd_address(sysinfo, i);
380 u8 reg8;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000381
382 /* Initialize the socket information with a sane value */
383 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
384
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000385 /* Dual Channel not supported, but Channel 1? Bail out */
386 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000387 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000388
389 /* Two DIMMs per channel not supported, but odd DIMM number? */
390 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000391 continue;
392
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000393 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000394
395 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000396 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000397 continue;
398 }
399
400 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
401 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000402 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403
404 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
405 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000406 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000407 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000408 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000409
410 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000411 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000412 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
413 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000414 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000415 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
416 break;
417 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000418 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000419 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
420 break;
421 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000422 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000423 }
424 break;
425 case 0x10:
426 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
427 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000428 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000429 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
430 break;
431 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000432 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000433 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
434 break;
435 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000436 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000437 }
438 break;
439 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000440 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000441 }
442
443 dimm_mask |= (1 << i);
444 }
445
446 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000447 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000448 }
449
Stefan Reinauer278534d2008-10-29 04:51:07 +0000450 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000451 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000452 }
453}
454
455/**
456 * @brief determine if any DIMMs are stacked
457 *
458 * @param sysinfo central sysinfo data structure.
459 */
460static void sdram_verify_package_type(struct sys_info * sysinfo)
461{
462 int i;
463
464 /* Assume no stacked DIMMs are available until we find one */
465 sysinfo->package = 0;
466 for (i=0; i<2*DIMM_SOCKETS; i++) {
467 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
468 continue;
469
470 /* Is the current DIMM a stacked DIMM? */
Sven Schnelle541269b2011-02-21 09:39:17 +0000471 if (spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000472 sysinfo->package = 1;
473 }
474}
475
476static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
477{
478 int i;
479 u8 cas_mask;
480
481 /* Setup CAS mask with all supported CAS Latencies */
482 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
483 SPD_CAS_LATENCY_DDR2_4 |
484 SPD_CAS_LATENCY_DDR2_5;
485
486 for (i=0; i<2*DIMM_SOCKETS; i++) {
487 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Sven Schnelle541269b2011-02-21 09:39:17 +0000488 cas_mask &= spd_read_byte(get_dimm_spd_address(sysinfo, i),
489 SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000490 }
491
492 if(!cas_mask) {
493 die("No DDR-II modules with accepted CAS latencies found.\n");
494 }
495
496 return cas_mask;
497}
498
499static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
500{
501 int i, j, idx;
502 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000503 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000504
505 const u8 ddr2_speeds_table[] = {
506 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
507 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
508 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
509 };
510
511 const u8 spd_lookup_table[] = {
512 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
513 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
514 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
515 };
516
517 switch (sdram_capabilities_max_supported_memory_frequency()) {
518 case 400: max_ram_speed = 0; break;
519 case 533: max_ram_speed = 1; break;
520 case 667: max_ram_speed = 2; break;
521 }
522
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000523 if (fsbclk() == 533)
524 max_ram_speed = 1;
525
Stefan Reinauer278534d2008-10-29 04:51:07 +0000526 sysinfo->memory_frequency = 0;
527 sysinfo->cas = 0;
528
529 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
530 lowest_common_cas = 3;
531 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
532 lowest_common_cas = 4;
533 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
534 lowest_common_cas = 5;
535 }
536 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
537
538 for (j = max_ram_speed; j>=0; j--) {
539 int freq_cas_mask = cas_mask;
540
541 PRINTK_DEBUG("Probing Speed %d\n", j);
542 for (i=0; i<2*DIMM_SOCKETS; i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000543 int device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000544 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000545
Stefan Reinauer278534d2008-10-29 04:51:07 +0000546 PRINTK_DEBUG(" DIMM: %d\n", i);
547 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
548 continue;
549 }
550
Sven Schnelle541269b2011-02-21 09:39:17 +0000551 current_cas_mask = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000552
553 while (current_cas_mask) {
554 int highest_supported_cas = 0, current_cas = 0;
555 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
556 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
557 highest_supported_cas = 5;
558 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
559 highest_supported_cas = 4;
560 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
561 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000562 } else {
563 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000564 }
565 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
566 current_cas = 3;
567 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
568 current_cas = 4;
569 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
570 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000571 } else {
572 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000573 }
574
575 idx = highest_supported_cas - current_cas;
576 PRINTK_DEBUG("idx=%d, ", idx);
Sven Schnelle541269b2011-02-21 09:39:17 +0000577 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(device, spd_lookup_table[2*idx]));
578 PRINTK_DEBUG("tAC=%x", spd_read_byte(device, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000579
Sven Schnelle541269b2011-02-21 09:39:17 +0000580 if (spd_read_byte(device, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
581 spd_read_byte(device, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000582 PRINTK_DEBUG(": OK\n");
583 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000584 }
585
Stefan Reinauer278534d2008-10-29 04:51:07 +0000586 PRINTK_DEBUG(": Not fast enough!\n");
587
588 current_cas_mask &= ~(1 << (current_cas));
589 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000590
Stefan Reinauer278534d2008-10-29 04:51:07 +0000591 freq_cas_mask &= current_cas_mask;
592 if (!current_cas_mask) {
593 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
594 break;
595 }
596 }
597 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
598 if (freq_cas_mask) {
599 switch (j) {
600 case 0: sysinfo->memory_frequency = 400; break;
601 case 1: sysinfo->memory_frequency = 533; break;
602 case 2: sysinfo->memory_frequency = 667; break;
603 }
604 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
605 sysinfo->cas = 3;
606 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
607 sysinfo->cas = 4;
608 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
609 sysinfo->cas = 5;
610 }
611 break;
612 }
613 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000614
Stefan Reinauer278534d2008-10-29 04:51:07 +0000615 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000616 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000617 sysinfo->memory_frequency, sysinfo->cas);
618 } else {
619 die("Could not find common memory frequency and CAS\n");
620 }
621}
622
623static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
624{
625 int i;
626 int tRAS_time;
627 int tRAS_cycles;
628 int freq_multiplier = 0;
629
630 switch (sysinfo->memory_frequency) {
631 case 400: freq_multiplier = 0x14; break; /* 5ns */
632 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
633 case 667: freq_multiplier = 0x0c; break; /* 3ns */
634 }
635
636 tRAS_cycles = 4; /* 4 clocks minimum */
637 tRAS_time = tRAS_cycles * freq_multiplier;
638
639 for (i=0; i<2*DIMM_SOCKETS; i++) {
640 u8 reg8;
641
642 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
643 continue;
644
Sven Schnelle541269b2011-02-21 09:39:17 +0000645 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000646 if (!reg8) {
647 die("Invalid tRAS value.\n");
648 }
649
650 while ((tRAS_time >> 2) < reg8) {
651 tRAS_time += freq_multiplier;
652 tRAS_cycles++;
653 }
654 }
655 if(tRAS_cycles > 0x18) {
656 die("DDR-II Module does not support this frequency (tRAS error)\n");
657 }
658
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000659 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000660 sysinfo->tras = tRAS_cycles;
661}
662
663static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
664{
665 int i;
666 int tRP_time;
667 int tRP_cycles;
668 int freq_multiplier = 0;
669
670 switch (sysinfo->memory_frequency) {
671 case 400: freq_multiplier = 0x14; break; /* 5ns */
672 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
673 case 667: freq_multiplier = 0x0c; break; /* 3ns */
674 }
675
676 tRP_cycles = 2; /* 2 clocks minimum */
677 tRP_time = tRP_cycles * freq_multiplier;
678
679 for (i=0; i<2*DIMM_SOCKETS; i++) {
680 u8 reg8;
681
682 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
683 continue;
684
Sven Schnelle541269b2011-02-21 09:39:17 +0000685 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000686 if (!reg8) {
687 die("Invalid tRP value.\n");
688 }
689
690 while (tRP_time < reg8) {
691 tRP_time += freq_multiplier;
692 tRP_cycles++;
693 }
694 }
695
696 if(tRP_cycles > 6) {
697 die("DDR-II Module does not support this frequency (tRP error)\n");
698 }
699
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000700 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000701 sysinfo->trp = tRP_cycles;
702}
703
704static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
705{
706 int i;
707 int tRCD_time;
708 int tRCD_cycles;
709 int freq_multiplier = 0;
710
711 switch (sysinfo->memory_frequency) {
712 case 400: freq_multiplier = 0x14; break; /* 5ns */
713 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
714 case 667: freq_multiplier = 0x0c; break; /* 3ns */
715 }
716
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000717 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000718 tRCD_time = tRCD_cycles * freq_multiplier;
719
720 for (i=0; i<2*DIMM_SOCKETS; i++) {
721 u8 reg8;
722
723 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
724 continue;
725
Sven Schnelle541269b2011-02-21 09:39:17 +0000726 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000727 if (!reg8) {
728 die("Invalid tRCD value.\n");
729 }
730
731 while (tRCD_time < reg8) {
732 tRCD_time += freq_multiplier;
733 tRCD_cycles++;
734 }
735 }
736 if(tRCD_cycles > 6) {
737 die("DDR-II Module does not support this frequency (tRCD error)\n");
738 }
739
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000740 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000741 sysinfo->trcd = tRCD_cycles;
742}
743
744static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
745{
746 int i;
747 int tWR_time;
748 int tWR_cycles;
749 int freq_multiplier = 0;
750
751 switch (sysinfo->memory_frequency) {
752 case 400: freq_multiplier = 0x14; break; /* 5ns */
753 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
754 case 667: freq_multiplier = 0x0c; break; /* 3ns */
755 }
756
757 tWR_cycles = 2; /* 2 clocks minimum */
758 tWR_time = tWR_cycles * freq_multiplier;
759
760 for (i=0; i<2*DIMM_SOCKETS; i++) {
761 u8 reg8;
762
763 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
764 continue;
765
Sven Schnelle541269b2011-02-21 09:39:17 +0000766 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000767 if (!reg8) {
768 die("Invalid tWR value.\n");
769 }
770
771 while (tWR_time < reg8) {
772 tWR_time += freq_multiplier;
773 tWR_cycles++;
774 }
775 }
776 if(tWR_cycles > 5) {
777 die("DDR-II Module does not support this frequency (tWR error)\n");
778 }
779
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000780 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000781 sysinfo->twr = tWR_cycles;
782}
783
784static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
785{
786 int i, index = 0;
787
788 const u8 tRFC_cycles[] = {
789 /* 75 105 127.5 */
790 15, 21, 26, /* DDR2-400 */
791 20, 28, 34, /* DDR2-533 */
792 25, 35, 43 /* DDR2-667 */
793 };
794
795 for (i=0; i<2*DIMM_SOCKETS; i++) {
796 u8 reg8;
797
798 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
799 continue;
800
801 reg8 = sysinfo->banksize[i*2];
802 switch (reg8) {
803 case 0x04: reg8 = 0; break;
804 case 0x08: reg8 = 1; break;
805 case 0x10: reg8 = 2; break;
806 case 0x20: reg8 = 3; break;
807 }
808
809 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
810 reg8++;
811
812 if (reg8 > 3) {
813 /* Can this happen? Go back to 127.5ns just to be sure
814 * we don't run out of the array. This may be wrong
815 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000816 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000817 reg8 = 3;
818 }
819
820 if (reg8 > index)
821 index = reg8;
822
823 }
824 index--;
825 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000826 case 667: index += 3; /* Fallthrough */
827 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000828 case 400: break;
829 }
830
831 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000832 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000833}
834
Stefan Reinauer278534d2008-10-29 04:51:07 +0000835static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
836{
837 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000838
Stefan Reinauer278534d2008-10-29 04:51:07 +0000839 sysinfo->refresh = 0;
840
841 for (i=0; i<2*DIMM_SOCKETS; i++) {
842 int refresh;
843
844 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
845 continue;
846
Sven Schnelle541269b2011-02-21 09:39:17 +0000847 refresh = spd_read_byte(get_dimm_spd_address(sysinfo, i),
848 SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000849
850 /* 15.6us */
851 if (!refresh)
852 continue;
853
854 /* Refresh is slower than 15.6us, use 15.6us */
855 if (refresh > 2)
856 continue;
857
858 if (refresh == 2) {
859 sysinfo->refresh = 1;
860 break;
861 }
862
863 die("DDR-II module has unsupported refresh value\n");
864 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000865 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000866}
867
868static void sdram_verify_burst_length(struct sys_info * sysinfo)
869{
870 int i;
871
872 for (i=0; i<2*DIMM_SOCKETS; i++) {
873 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
874 continue;
875
Sven Schnelle541269b2011-02-21 09:39:17 +0000876 if (!(spd_read_byte(get_dimm_spd_address(sysinfo, i),
877 SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000878 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
879 }
880}
881
882static void sdram_program_dram_width(struct sys_info * sysinfo)
883{
884 u16 c0dramw=0, c1dramw=0;
885 int idx;
886
887 if (sysinfo->dual_channel)
888 idx = 2;
889 else
890 idx = 1;
891
892 switch (sysinfo->dimm[0]) {
893 case 0: c0dramw = 0x0000; break; /* x16DS */
894 case 1: c0dramw = 0x0001; break; /* x8DS */
895 case 2: c0dramw = 0x0000; break; /* x16SS */
896 case 3: c0dramw = 0x0005; break; /* x8DDS */
897 case 4: c0dramw = 0x0000; break; /* NC */
898 }
899
900 switch (sysinfo->dimm[idx]) {
901 case 0: c1dramw = 0x0000; break; /* x16DS */
902 case 1: c1dramw = 0x0010; break; /* x8DS */
903 case 2: c1dramw = 0x0000; break; /* x16SS */
904 case 3: c1dramw = 0x0050; break; /* x8DDS */
905 case 4: c1dramw = 0x0000; break; /* NC */
906 }
907
908 if ( !sdram_capabilities_dual_channel() ) {
909 /* Single Channel */
910 c0dramw |= c1dramw;
911 c1dramw = 0;
912 }
913
914 MCHBAR16(C0DRAMW) = c0dramw;
915 MCHBAR16(C1DRAMW) = c1dramw;
916}
917
918static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
919{
920 int i;
921
922 for (i=0; i<16; i++)
923 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
924}
925
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000926static const u32 dq2030[] = {
927 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
928 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
929 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
930 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
931};
932
933static const u32 dq2330[] = {
934 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
935 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
936 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
937 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
938};
939
940static const u32 cmd2710[] = {
941 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
942 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
943 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
944 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
945};
946
947static const u32 cmd3210[] = {
948 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
949 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
950 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
951 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
952};
953
954static const u32 clk2030[] = {
955 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
956 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
957 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
958 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
959};
960
961static const u32 ctl3215[] = {
962 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
963 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
964 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
965 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
966};
967
968static const u32 ctl3220[] = {
969 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
970 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
971 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
972 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
973};
974
975static const u32 nc[] = {
976 0x00000000, 0x00000000, 0x00000000, 0x00000000,
977 0x00000000, 0x00000000, 0x00000000, 0x00000000,
978 0x00000000, 0x00000000, 0x00000000, 0x00000000,
979 0x00000000, 0x00000000, 0x00000000, 0x00000000
980};
981
982enum {
983 DQ2030,
984 DQ2330,
985 CMD2710,
986 CMD3210,
987 CLK2030,
988 CTL3215,
989 CTL3220,
990 NC,
991};
992
993static const u8 dual_channel_slew_group_lookup[] = {
994 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
995 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
996 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
997 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
998 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
999
1000 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1001 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1002 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1003 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1004 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1005
1006 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1007 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1008 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1009 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
1010 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1011
1012 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1013 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1014 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1015 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1016 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
1017
1018 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1019 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1020 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1021 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
1022};
1023
1024static const u8 single_channel_slew_group_lookup[] = {
1025 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1026 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1027 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1028 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1029 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1030
1031 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1032 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1033 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1034 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1035 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1036
1037 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1038 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1039 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1040 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1041 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1042
1043 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1044 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1045 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1046 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1047 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1048
1049 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1050 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1051 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1052 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1053};
1054
1055static const u32 *slew_group_lookup(int dual_channel, int index)
1056{
1057 const u8 *slew_group;
1058 /* Dual Channel needs different tables. */
1059 if (dual_channel)
1060 slew_group = dual_channel_slew_group_lookup;
1061 else
1062 slew_group = single_channel_slew_group_lookup;
1063
1064 switch (slew_group[index]) {
1065 case DQ2030: return dq2030;
1066 case DQ2330: return dq2330;
1067 case CMD2710: return cmd2710;
1068 case CMD3210: return cmd3210;
1069 case CLK2030: return clk2030;
1070 case CTL3215: return ctl3215;
1071 case CTL3220: return ctl3220;
1072 case NC: return nc;
1073 }
1074
1075 return nc;
1076}
1077
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001078#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001079/* Strength multiplier tables */
1080static const u8 dual_channel_strength_multiplier[] = {
1081 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1082 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1083 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1084 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1085 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1086 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1087 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1088 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1089 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1090 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1091 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1092 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1093 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1094 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1095 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1096 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1097 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1098 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1099 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1100 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1102 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1103 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1104 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1105};
1106
1107static const u8 single_channel_strength_multiplier[] = {
1108 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1109 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1110 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1111 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1112 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1113 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1114 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1115 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1116 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1117 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1118 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1119 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1120 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1121 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1122 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1123 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1124 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1125 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1126 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1127 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1128 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1129 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1130 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1131 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1132};
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001133#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001134static const u8 dual_channel_strength_multiplier[] = {
1135 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1136 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1137 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1138 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1139 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1140 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1141 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1142 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1143 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1144 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1145 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1146 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1147 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1148 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1149 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1150 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1151 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1152 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1153 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1154 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1155 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1156 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1157 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1158 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1159};
1160
1161static const u8 single_channel_strength_multiplier[] = {
1162 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1163 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1164 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1165 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1166 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1167 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1168 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1169 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1170 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1171 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1172 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1173 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1174 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1175 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1176 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1177 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1178 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1179 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1180 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1181 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1182 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1183 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1184 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1185 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1186};
1187#endif
1188
Stefan Reinauer278534d2008-10-29 04:51:07 +00001189static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1190{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001191 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001192 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001193
1194 /* Set Strength Multipliers */
1195
1196 /* Dual Channel needs different tables. */
1197 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001198 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001199 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001200 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001201 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1202 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001203 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001204 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001205 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001206 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1207 }
1208
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001209 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001210
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001211 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1212 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1213 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1214 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1215 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1216 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1217 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1218 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001219
1220 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001221 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1222 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1223 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001224
Stefan Reinauer278534d2008-10-29 04:51:07 +00001225 sdram_write_slew_rates(G3SRPUT, ctl3220);
1226 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001227 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001228 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001229 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1230 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1231 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001232
1233 /* Channel 1 */
1234 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001235 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1236 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001237 } else {
1238 sdram_write_slew_rates(G7SRPUT, nc);
1239 sdram_write_slew_rates(G8SRPUT, nc);
1240 }
1241}
1242
1243static void sdram_enable_rcomp(void)
1244{
1245 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001246 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001247 udelay(300);
1248 reg32 = MCHBAR32(GBRCOMPCTL);
1249 reg32 &= ~(1 << 23);
1250 MCHBAR32(GBRCOMPCTL) = reg32;
1251}
1252
1253static void sdram_program_dll_timings(struct sys_info *sysinfo)
1254{
1255 u32 chan0dll = 0, chan1dll = 0;
1256 int i;
1257
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001258 printk(BIOS_DEBUG, "Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001259
Stefan Reinauer278534d2008-10-29 04:51:07 +00001260 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1261 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1262
1263 /* We drive both channels with the same speed */
1264 switch (sysinfo->memory_frequency) {
1265 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1266 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1267 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1268 }
1269
1270 for (i=0; i < 4; i++) {
1271 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1272 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1273 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1274 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1275 }
1276}
1277
1278static void sdram_force_rcomp(void)
1279{
1280 u32 reg32;
1281 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001282
Stefan Reinauer278534d2008-10-29 04:51:07 +00001283 reg32 = MCHBAR32(ODTC);
1284 reg32 |= (1 << 28);
1285 MCHBAR32(ODTC) = reg32;
1286
1287 reg32 = MCHBAR32(SMSRCTL);
1288 reg32 |= (1 << 0);
1289 MCHBAR32(SMSRCTL) = reg32;
1290
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001291 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001292 reg32 = MCHBAR32(GBRCOMPCTL);
1293 reg32 |= (1 << 8);
1294 MCHBAR32(GBRCOMPCTL) = reg32;
1295
1296 reg8 = i945_silicon_revision();
1297 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001298
Stefan Reinauer278534d2008-10-29 04:51:07 +00001299 reg32 = MCHBAR32(GBRCOMPCTL);
1300 reg32 |= (3 << 5);
1301 MCHBAR32(GBRCOMPCTL) = reg32;
1302 }
1303}
1304
1305static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1306{
1307 u8 reg8;
1308 u32 reg32;
1309
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001310 printk(BIOS_DEBUG, "Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001311 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001312 reg8 = MCHBAR8(C0HCTC);
1313 reg8 &= ~0x1f;
1314 reg8 |= ( 1 << 0);
1315 MCHBAR8(C0HCTC) = reg8;
1316
1317 reg8 = MCHBAR8(C1HCTC);
1318 reg8 &= ~0x1f;
1319 reg8 |= ( 1 << 0);
1320 MCHBAR8(C1HCTC) = reg8;
1321
Stefan Reinauer278534d2008-10-29 04:51:07 +00001322 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1323 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1324
1325 MCHBAR8(C0WDLLCMC) = 0;
1326 MCHBAR8(C1WDLLCMC) = 0;
1327
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001328 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001329 sdram_program_dram_width(sysinfo);
1330
1331 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1332
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001333 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001334 reg32 = MCHBAR32(GBRCOMPCTL);
1335 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1336 reg32 |= (3 << 27) | (3 << 0);
1337 MCHBAR32(GBRCOMPCTL) = reg32;
1338
1339 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1340
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001341 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001342 sdram_program_dll_timings(sysinfo);
1343
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001344 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001345 sdram_force_rcomp();
1346}
1347
1348static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1349{
1350 u32 reg32;
1351
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001352 printk(BIOS_DEBUG, "Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001353
Stefan Reinauer278534d2008-10-29 04:51:07 +00001354 reg32 = MCHBAR32(RCVENMT);
1355 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001356 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001357
1358 reg32 |= (1 << 11) | (1 << 9);
1359 MCHBAR32(RCVENMT) = reg32;
1360
1361 reg32 = MCHBAR32(DRTST);
1362 reg32 |= (1 << 3) | (1 << 2);
1363 MCHBAR32(DRTST) = reg32;
1364
1365 reg32 = MCHBAR32(DRTST);
1366 reg32 |= (1 << 6) | (1 << 4);
1367 MCHBAR32(DRTST) = reg32;
1368
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001369 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001370
1371 reg32 = MCHBAR32(DRTST);
1372
1373 /* Is channel 0 populated? */
1374 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1375 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1376 reg32 |= (1 << 7) | (1 << 5);
1377 else
1378 reg32 |= (1 << 31);
1379
1380 /* Is channel 1 populated? */
1381 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1382 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1383 reg32 |= (1 << 9) | (1 << 8);
1384 else
1385 reg32 |= (1 << 30);
1386
1387 MCHBAR32(DRTST) = reg32;
1388
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001389 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001390 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1391 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1392 reg32 = MCHBAR32(C0DRC1);
1393 reg32 |= (1 << 8);
1394 MCHBAR32(C0DRC1) = reg32;
1395 }
1396 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1397 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1398 reg32 = MCHBAR32(C1DRC1);
1399 reg32 |= (1 << 8);
1400 MCHBAR32(C1DRC1) = reg32;
1401 }
1402}
1403
1404struct dimm_size {
1405 unsigned long side1;
1406 unsigned long side2;
1407};
1408
Sven Schnelle541269b2011-02-21 09:39:17 +00001409static struct dimm_size sdram_get_dimm_size(struct sys_info *sysinfo, u16 dimmno)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001410{
1411 /* Calculate the log base 2 size of a DIMM in bits */
1412 struct dimm_size sz;
Sven Schnelle541269b2011-02-21 09:39:17 +00001413 int value, low, rows, columns, device;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001414
Sven Schnelle541269b2011-02-21 09:39:17 +00001415 device = get_dimm_spd_address(sysinfo, dimmno);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001416 sz.side1 = 0;
1417 sz.side2 = 0;
1418
1419 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1420 if (rows < 0) goto hw_err;
1421 if ((rows & 0xf) == 0) goto val_err;
1422 sz.side1 += rows & 0xf;
1423
1424 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1425 if (columns < 0) goto hw_err;
1426 if ((columns & 0xf) == 0) goto val_err;
1427 sz.side1 += columns & 0xf;
1428
1429 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1430 if (value < 0) goto hw_err;
1431 if ((value & 0xff) == 0) goto val_err;
1432 sz.side1 += log2(value & 0xff);
1433
1434 /* Get the module data width and convert it to a power of two */
1435 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1436 if (value < 0) goto hw_err;
1437 value &= 0xff;
1438 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001439
Stefan Reinauer278534d2008-10-29 04:51:07 +00001440 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1441 if (low < 0) goto hw_err;
1442 value = value | (low & 0xff);
1443 if ((value != 72) && (value != 64)) goto val_err;
1444 sz.side1 += log2(value);
1445
1446 /* side 2 */
1447 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1448
1449 if (value < 0) goto hw_err;
1450 value &= 7;
1451 value++;
1452 if (value == 1) goto out;
1453 if (value != 2) goto val_err;
1454
1455 /* Start with the symmetrical case */
1456 sz.side2 = sz.side1;
1457
1458 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1459
1460 /* Don't die here, I have not come across any of these to test what
1461 * actually happens.
1462 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001463 printk(BIOS_ERR, "Assymetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001464
1465 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1466 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1467
1468 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1469 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1470
1471 goto out;
1472
1473 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001474 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001475 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001476 /* If a hardware error occurs the spd rom probably does not exist.
1477 * In this case report that there is no memory
1478 */
1479 sz.side1 = 0;
1480 sz.side2 = 0;
Patrick Georgic5fc7db2012-03-07 15:55:47 +01001481out:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001482 return sz;
1483}
1484
1485static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1486{
1487 int i;
1488
1489 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1490 struct dimm_size sz;
1491
1492 sysinfo->banksize[i * 2] = 0;
1493 sysinfo->banksize[(i * 2) + 1] = 0;
1494
1495 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1496 continue;
1497
Sven Schnelle541269b2011-02-21 09:39:17 +00001498 sz = sdram_get_dimm_size(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001499
Sven Schnelle541269b2011-02-21 09:39:17 +00001500 sysinfo->banks[i] = spd_read_byte(get_dimm_spd_address(sysinfo, i),
1501 SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001502
1503 if (sz.side1 < 30)
1504 die("DDR-II rank size smaller than 128MB is not supported.\n");
1505
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001506 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001507
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001508 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001509
Stefan Reinauer278534d2008-10-29 04:51:07 +00001510 if (!sz.side2)
1511 continue;
1512
1513 /* If there is a second side, it has to have at least 128M, too */
1514 if (sz.side2 < 30)
1515 die("DDR-II rank size smaller than 128MB is not supported.\n");
1516
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001517 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001518
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001519 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001520 }
1521}
1522
1523static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1524{
1525 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001526 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001527
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001528 printk(BIOS_DEBUG, "Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001529
1530 cum0 = 0;
1531 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001532 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001533 MCHBAR8(C0DRB0+i) = cum0;
1534 }
1535
1536 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1537 cum1 = cum0;
1538
1539 /* Exception: Interleaved starts from the beginning */
1540 if (sysinfo->interleaved)
1541 cum1 = 0;
1542
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001543#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001544 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1545 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1546 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1547 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001548#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001549
1550 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001551 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001552 MCHBAR8(C1DRB0+i) = cum1;
1553 }
1554
1555 /* Set TOLUD Top Of Low Usable DRAM */
1556 if (sysinfo->interleaved)
1557 tolud = (cum0 + cum1) << 1;
1558 else
1559 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001560
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001561 /* The TOM register has a different format */
1562 tom = tolud >> 3;
1563
1564 /* Limit the value of TOLUD to leave some space for PCI memory. */
1565 if (tolud > 0xd0)
1566 tolud = 0xd0; /* 3.25GB : 0.75GB */
1567
1568 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1569
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001570 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1571 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1572 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001573
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001574 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001575
1576 return 0;
1577}
1578
Stefan Reinauer278534d2008-10-29 04:51:07 +00001579static int sdram_set_row_attributes(struct sys_info *sysinfo)
1580{
1581 int i, value;
1582 u16 dra0=0, dra1=0, dra = 0;
1583
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001584 printk(BIOS_DEBUG, "Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001585 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1586 u16 device;
1587 u8 columnsrows;
1588
1589 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1590 continue;
1591 }
1592
Sven Schnelle541269b2011-02-21 09:39:17 +00001593 device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001594
1595 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1596 columnsrows = (value & 0x0f);
1597
1598 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1599 columnsrows |= (value & 0xf) << 4;
1600
1601 switch (columnsrows) {
1602 case 0x9d: dra = 2; break;
1603 case 0xad: dra = 3; break;
1604 case 0xbd: dra = 4; break;
1605 case 0xae: dra = 3; break;
1606 case 0xbe: dra = 4; break;
1607 default: die("Unsupported Rows/Columns. (DRA)");
1608 }
1609
1610 /* Double Sided DIMMs? */
1611 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1612 dra = (dra << 4) | dra;
1613 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001614
Stefan Reinauer278534d2008-10-29 04:51:07 +00001615 if (i < DIMM_SOCKETS)
1616 dra0 |= (dra << (i*8));
1617 else
1618 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1619 }
1620
1621 MCHBAR16(C0DRA0) = dra0;
1622 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001623
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001624 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1625 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001626
1627 return 0;
1628}
1629
1630static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1631{
1632 u32 off32;
1633 int i;
1634
1635 MCHBAR16(C1BNKARC) &= 0xff00;
1636 MCHBAR16(C0BNKARC) &= 0xff00;
1637
1638 off32 = C0BNKARC;
1639 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1640 /* Switch to second channel */
1641 if (i == DIMM_SOCKETS)
1642 off32 = C1BNKARC;
1643
1644 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1645 continue;
1646
1647 if (sysinfo->banks[i] != 8)
1648 continue;
1649
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001650 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001651
1652 if (i & 1)
1653 MCHBAR16(off32) |= 0x50;
1654 else
1655 MCHBAR16(off32) |= 0x05;
1656 }
1657}
1658
1659#define REFRESH_7_8US 1
1660#define REFRESH_15_6US 0
1661static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1662{
1663 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001664
Stefan Reinauer278534d2008-10-29 04:51:07 +00001665 if (sysinfo->refresh == REFRESH_7_8US) {
1666 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1667 } else {
1668 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1669 }
1670
1671 MCHBAR32(C0DRC0) &= ~(7 << 8);
1672 MCHBAR32(C0DRC0) |= reg32;
1673
1674 MCHBAR32(C1DRC0) &= ~(7 << 8);
1675 MCHBAR32(C1DRC0) |= reg32;
1676}
1677
1678static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1679{
1680 u32 reg32;
1681 int i;
1682
1683 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001684
Stefan Reinauer278534d2008-10-29 04:51:07 +00001685 for (i=0; i < 4; i++) {
1686 if (sysinfo->banksize[i] == 0) {
1687 reg32 |= (1 << (16 + i));
1688 }
1689 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001690
Stefan Reinauer278534d2008-10-29 04:51:07 +00001691 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001692
Stefan Reinauer278534d2008-10-29 04:51:07 +00001693 reg32 |= (1 << 11);
1694 MCHBAR32(C0DRC1) = reg32;
1695
1696 /* Do we have to do this if we're in Single Channel Mode? */
1697 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001698
Stefan Reinauer278534d2008-10-29 04:51:07 +00001699 for (i=4; i < 8; i++) {
1700 if (sysinfo->banksize[i] == 0) {
1701 reg32 |= (1 << (12 + i));
1702 }
1703 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001704
Stefan Reinauer278534d2008-10-29 04:51:07 +00001705 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001706
Stefan Reinauer278534d2008-10-29 04:51:07 +00001707 reg32 |= (1 << 11);
1708 MCHBAR32(C1DRC1) = reg32;
1709}
1710
1711static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1712{
1713 u32 reg32;
1714 int i;
1715
1716 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001717
Stefan Reinauer278534d2008-10-29 04:51:07 +00001718 for (i=0; i < 4; i++) {
1719 if (sysinfo->banksize[i] == 0) {
1720 reg32 |= (1 << (24 + i));
1721 }
1722 }
1723 MCHBAR32(C0DRC2) = reg32;
1724
1725 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001726
Stefan Reinauer278534d2008-10-29 04:51:07 +00001727 for (i=4; i < 8; i++) {
1728 if (sysinfo->banksize[i] == 0) {
1729 reg32 |= (1 << (20 + i));
1730 }
1731 }
1732 MCHBAR32(C1DRC2) = reg32;
1733}
1734
1735static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1736{
1737 u32 reg32, off32;
1738 u32 tWTR;
1739 u32 temp_drt;
1740 int i, page_size;
1741
1742 static const u8 const drt0_table[] = {
1743 /* CL 3, 4, 5 */
1744 3, 4, 5, /* FSB533/400, DDR533/400 */
1745 4, 5, 6, /* FSB667, DDR533/400 */
1746 4, 5, 6, /* FSB667, DDR667 */
1747 };
1748
1749 static const u8 const cas_table[] = {
1750 2, 1, 0, 3
1751 };
1752
1753 reg32 = MCHBAR32(C0DRC0);
1754 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001755 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001756 MCHBAR32(C0DRC0) = reg32;
1757
1758 reg32 = MCHBAR32(C1DRC0);
1759 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001760 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001761 MCHBAR32(C1DRC0) = reg32;
1762
1763 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1764 SYSINFO_DIMM_NOT_POPULATED) {
1765 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001766 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001767 MCHBAR32(C0DRC0) = reg32;
1768 }
1769
1770 sdram_program_refresh_rate(sysinfo);
1771
1772 sdram_program_cke_tristate(sysinfo);
1773
1774 sdram_program_odt_tristate(sysinfo);
1775
1776 /* Calculate DRT0 */
1777
1778 temp_drt = 0;
1779
1780 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1781 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1782 temp_drt |= (reg32 << 28);
1783
1784 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1785 reg32 += sysinfo->trp;
1786 temp_drt |= (reg32 << 4);
1787
1788 if (sysinfo->memory_frequency == 667) {
1789 tWTR = 3; /* 667MHz */
1790 } else {
1791 tWTR = 2; /* 400 and 533 */
1792 }
1793
1794 /* B2B Write to Read Command Spacing */
1795 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1796 temp_drt |= (reg32 << 24);
1797
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001798 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001799 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1800
1801 /* Program Write Auto Precharge to Activate */
1802 off32 = 0;
1803 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1804 off32 += 3;
1805 }
1806 if (sysinfo->memory_frequency == 667) {
1807 off32 += 3;
1808 }
1809 off32 += sysinfo->cas - 3;
1810 reg32 = drt0_table[off32];
1811 temp_drt |= (reg32 << 11);
1812
1813 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001814
Stefan Reinauer278534d2008-10-29 04:51:07 +00001815 temp_drt |= (8 << 0);
1816
1817 MCHBAR32(C0DRT0) = temp_drt;
1818 MCHBAR32(C1DRT0) = temp_drt;
1819
1820 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001821
Stefan Reinauer278534d2008-10-29 04:51:07 +00001822 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1823
1824 /* DRAM RASB Precharge */
1825 temp_drt |= (sysinfo->trp - 2) << 0;
1826
1827 /* DRAM RASB to CASB Delay */
1828 temp_drt |= (sysinfo->trcd - 2) << 4;
1829
1830 /* CASB Latency */
1831 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1832
1833 /* Refresh Cycle Time */
1834 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001835
Stefan Reinauer278534d2008-10-29 04:51:07 +00001836 /* Pre-All to Activate Delay */
1837 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001838
Stefan Reinauer278534d2008-10-29 04:51:07 +00001839 /* Precharge to Precharge Delay stays at 1 clock */
1840 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001841
Stefan Reinauer278534d2008-10-29 04:51:07 +00001842 /* Activate to Precharge Delay */
1843 temp_drt |= (sysinfo->tras << 19);
1844
1845 /* Read to Precharge (tRTP) */
1846 if (sysinfo->memory_frequency == 667) {
1847 temp_drt |= (1 << 28);
1848 } else {
1849 temp_drt |= (0 << 28);
1850 }
1851
1852 /* Determine page size */
1853 reg32 = 0;
1854 page_size = 1; /* Default: 1k pagesize */
1855 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1856 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1857 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1858 page_size = 2; /* 2k pagesize */
1859 }
1860
1861 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1862 reg32 = 1;
1863 }
1864 if (sysinfo->memory_frequency == 667) {
1865 reg32 = page_size;
1866 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001867
Stefan Reinauer278534d2008-10-29 04:51:07 +00001868 temp_drt |= (reg32 << 30);
1869
1870 MCHBAR32(C0DRT1) = temp_drt;
1871 MCHBAR32(C1DRT1) = temp_drt;
1872
1873 /* Program DRT2 */
1874 reg32 = MCHBAR32(C0DRT2);
1875 reg32 &= ~(1 << 8);
1876 MCHBAR32(C0DRT2) = reg32;
1877
1878 reg32 = MCHBAR32(C1DRT2);
1879 reg32 &= ~(1 << 8);
1880 MCHBAR32(C1DRT2) = reg32;
1881
1882 /* Calculate DRT3 */
1883 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1884
1885 /* Get old tRFC value */
1886 reg32 = MCHBAR32(C0DRT1) >> 10;
1887 reg32 &= 0x3f;
1888
1889 /* 788nS - tRFC */
1890 switch (sysinfo->memory_frequency) {
1891 case 400: /* 5nS */
1892 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1893 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1894 break;
1895 case 533: /* 3.75nS */
1896 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1897 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1898 break;
1899 case 667: /* 3nS */
1900 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1901 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1902 break;
1903 }
1904
1905 temp_drt |= reg32;
1906
1907 MCHBAR32(C0DRT3) = temp_drt;
1908 MCHBAR32(C1DRT3) = temp_drt;
1909}
1910
1911static void sdram_set_channel_mode(struct sys_info *sysinfo)
1912{
1913 u32 reg32;
1914
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001915 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001916
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001917 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001918 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1919 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1920 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1921 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1922 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001923 sysinfo->interleaved = 1;
1924 } else {
1925 sysinfo->interleaved = 0;
1926 }
1927
1928 reg32 = MCHBAR32(DCC);
1929 reg32 &= ~(7 << 0);
1930
1931 if(sysinfo->interleaved) {
1932 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001933 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001934 reg32 |= (1 << 1);
1935 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1936 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1937 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001938 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001939 reg32 |= (1 << 2);
1940 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1941 SYSINFO_DIMM_NOT_POPULATED) {
1942 /* Dual Channel Assymetric */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001943 printk(BIOS_DEBUG, "Dual Channel Assymetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001944 reg32 |= (1 << 0);
1945 } else {
1946 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001947 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001948 }
1949
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001950 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001951 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001952
1953 MCHBAR32(DCC) = reg32;
1954
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001955 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001956}
1957
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001958static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001959{
1960 volatile u16 reg16;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001961
1962 MCHBAR32(PLLMON) = 0x80800000;
1963
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001964 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001965 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001966 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001967
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001968 /* Program CPCTL according to FSB speed */
1969 /* Only write the lower byte */
1970 switch (sysinfo->fsb_frequency) {
1971 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1972 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1973 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1974 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001975
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001976 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001977
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001978 reg16 = MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001979}
1980
1981static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1982{
1983 u8 reg8;
1984 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001985 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001986
1987#define CRCLK_166MHz 0x00
1988#define CRCLK_200MHz 0x01
1989#define CRCLK_250MHz 0x03
1990#define CRCLK_400MHz 0x05
1991
1992#define CDCLK_200MHz 0x00
1993#define CDCLK_320MHz 0x40
1994
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001995#define VOLTAGE_1_05 0x00
1996#define VOLTAGE_1_50 0x01
1997
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001998 printk(BIOS_DEBUG, "Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001999
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002000 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002001
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002002 voltage = VOLTAGE_1_05;
2003 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
2004 voltage = VOLTAGE_1_50;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002005 printk(BIOS_DEBUG, "Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002006
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002007 /* Gate graphics hardware for frequency change */
2008 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
2009 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
2010 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002011
2012 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002013 reg8 = sdram_capabilities_core_frequencies();
2014
Stefan Reinauer278534d2008-10-29 04:51:07 +00002015 freq = CRCLK_250MHz;
2016 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002017 case GFX_FREQUENCY_CAP_ALL:
2018 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002019 freq = CRCLK_250MHz;
2020 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002021 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002022 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002023 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2024 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2025 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002026 }
2027
2028 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002029 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002030 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
2031 if (reg8==2)
2032 freq = CRCLK_166MHz;
2033 }
2034
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002035 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002036 switch (freq) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002037 case CRCLK_166MHz: printk(BIOS_DEBUG, "166Mhz"); break;
2038 case CRCLK_200MHz: printk(BIOS_DEBUG, "200Mhz"); break;
2039 case CRCLK_250MHz: printk(BIOS_DEBUG, "250Mhz"); break;
2040 case CRCLK_400MHz: printk(BIOS_DEBUG, "400Mhz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002041 }
2042
Stefan Reinauer278534d2008-10-29 04:51:07 +00002043 if (i945_silicon_revision() == 0) {
2044 sysinfo->mvco4x = 1;
2045 } else {
2046 sysinfo->mvco4x = 0;
2047 }
2048
Stefan Reinauer278534d2008-10-29 04:51:07 +00002049 second_vco = 0;
2050
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002051 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002052 second_vco = 1;
2053 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2054 u16 mem = sysinfo->memory_frequency;
2055 u16 fsb = sysinfo->fsb_frequency;
2056
2057 if ( (fsb == 667 && mem == 533) ||
2058 (fsb == 533 && mem == 533) ||
2059 (fsb == 533 && mem == 400)) {
2060 second_vco = 1;
2061 }
2062
2063 if (fsb == 667 && mem == 533)
2064 sysinfo->mvco4x = 1;
2065 }
2066
2067 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002068 sysinfo->clkcfg_bit7=1;
2069 } else {
2070 sysinfo->clkcfg_bit7=0;
2071 }
2072
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002073 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002074 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2075 reg16 &= ~( (7 << 0) | (1 << 13) );
2076 reg16 |= freq;
2077 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2078
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002079 /* Graphics Core Display Clock */
2080 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2081 reg8 &= ~( (1<<7) | (7<<4) );
2082
2083 if (voltage == VOLTAGE_1_05) {
2084 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002085 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002086 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002087 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002088 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002089 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002090 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002091
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002092 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002093
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002094 reg8 |= (1<<3) | (1<<1);
2095 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2096
2097 reg8 |= 0x0f;
2098 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2099
2100 /* Ungate core render and display clocks */
2101 reg8 &= 0xf0;
2102 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002103}
2104
2105static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2106{
2107 u32 clkcfg;
2108 u8 reg8;
2109
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002110 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002111
Stefan Reinauer278534d2008-10-29 04:51:07 +00002112 clkcfg = MCHBAR32(CLKCFG);
2113
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002114 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002115
2116 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2117
2118 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002119 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002120 clkcfg &= ~(1 << 12);
2121 }
2122
2123 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002124 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002125
Stefan Reinauer278534d2008-10-29 04:51:07 +00002126 clkcfg |= (1 << 7);
2127 }
2128
2129 switch (sysinfo->memory_frequency) {
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002130 case 400: clkcfg |= (2 << 4); break;
2131 case 533: clkcfg |= (3 << 4); break;
2132 case 667: clkcfg |= (4 << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002133 default: die("Target Memory Frequency Error");
2134 }
2135
2136 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002137 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002138 return;
2139 }
2140
2141 MCHBAR32(CLKCFG) = clkcfg;
2142
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002143 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002144 * cache before we execute it.
2145 */
2146 goto cache_code;
2147vco_update:
2148 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2149 reg8 &= ~(1 << 7);
2150 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2151
Stefan Reinauer278534d2008-10-29 04:51:07 +00002152 clkcfg &= ~(1 << 10);
2153 MCHBAR32(CLKCFG) = clkcfg;
2154 clkcfg |= (1 << 10);
2155 MCHBAR32(CLKCFG) = clkcfg;
2156
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002157 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002158 " movl $0x100, %%ecx\n"
2159 "delay_update:\n"
2160 " nop\n"
2161 " nop\n"
2162 " nop\n"
2163 " nop\n"
2164 " loop delay_update\n"
2165 : /* No outputs */
2166 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002167 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002168 );
2169
Stefan Reinauer278534d2008-10-29 04:51:07 +00002170 clkcfg &= ~(1 << 10);
2171 MCHBAR32(CLKCFG) = clkcfg;
2172
2173 goto out;
2174cache_code:
2175 goto vco_update;
2176out:
2177
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002178 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
2179 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002180}
2181
2182static void sdram_program_clock_crossing(void)
2183{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002184 int idx = 0;
2185
2186 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002187 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002188 */
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002189#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002190 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002191 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002192 0xffffffff, 0xffffffff, /* nonexistant */
2193 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002194
Stefan Reinauer278534d2008-10-29 04:51:07 +00002195 0x08040120, 0x00000000, /* DDR400 FSB533 */
2196 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002197 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002198
2199 0x04020120, 0x00000010, /* DDR400 FSB667 */
2200 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002201 0x00100401, 0x00000000, /* DDR667 FSB667 */
2202
2203 0xffffffff, 0xffffffff, /* nonexistant */
2204 0xffffffff, 0xffffffff, /* nonexistant */
2205 0xffffffff, 0xffffffff, /* nonexistant */
2206
2207 0xffffffff, 0xffffffff, /* nonexistant */
2208 0xffffffff, 0xffffffff, /* nonexistant */
2209 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002210 };
2211
2212 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002213 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002214 0xffffffff, 0xffffffff, /* nonexistant */
2215 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002216
Stefan Reinauer278534d2008-10-29 04:51:07 +00002217 0x00060108, 0x00000000, /* DDR400 FSB533 */
2218 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002219 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002220
2221 0x00040318, 0x00000000, /* DDR400 FSB667 */
2222 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002223 0x02010804, 0x00000000, /* DDR667 FSB667 */
2224
2225 0xffffffff, 0xffffffff, /* nonexistant */
2226 0xffffffff, 0xffffffff, /* nonexistant */
2227 0xffffffff, 0xffffffff, /* nonexistant */
2228
2229 0xffffffff, 0xffffffff, /* nonexistant */
2230 0xffffffff, 0xffffffff, /* nonexistant */
2231 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002232 };
2233
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002234#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002235 /* i945 G/P */
2236 static const u32 data_clock_crossing[] = {
2237 0xffffffff, 0xffffffff, /* nonexistant */
2238 0xffffffff, 0xffffffff, /* nonexistant */
2239 0xffffffff, 0xffffffff, /* nonexistant */
2240
2241 0x10080201, 0x00000000, /* DDR400 FSB533 */
2242 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002243 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002244
2245 0xffffffff, 0xffffffff, /* nonexistant */
2246 0xffffffff, 0xffffffff, /* nonexistant */
2247 0xffffffff, 0xffffffff, /* nonexistant */
2248
2249 0x04020108, 0x00000000, /* DDR400 FSB800 */
2250 0x00020108, 0x00000000, /* DDR533 FSB800 */
2251 0x00080201, 0x00000000, /* DDR667 FSB800 */
2252
2253 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2254 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2255 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2256 };
2257
2258 static const u32 command_clock_crossing[] = {
2259 0xffffffff, 0xffffffff, /* nonexistant */
2260 0xffffffff, 0xffffffff, /* nonexistant */
2261 0xffffffff, 0xffffffff, /* nonexistant */
2262
2263 0x00010800, 0x00000402, /* DDR400 FSB533 */
2264 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002265 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002266
2267 0xffffffff, 0xffffffff, /* nonexistant */
2268 0xffffffff, 0xffffffff, /* nonexistant */
2269 0xffffffff, 0xffffffff, /* nonexistant */
2270
2271 0x02010804, 0x00000000, /* DDR400 FSB800 */
2272 0x00010402, 0x00000000, /* DDR533 FSB800 */
2273 0x04020180, 0x00000008, /* DDR667 FSB800 */
2274
2275 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2276 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2277 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2278 };
2279#endif
2280
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002281 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002282
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002283 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002284 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002285 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2286 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2287 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2288 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002289 }
2290
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002291 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002292 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002293 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2294 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2295 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2296 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2297 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2298 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002299 }
2300
2301 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002302 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002303 }
2304
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002305 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2306 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2307
Stefan Reinauer278534d2008-10-29 04:51:07 +00002308 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2309 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2310 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2311 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2312
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002313 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002314}
2315
2316static void sdram_disable_fast_dispatch(void)
2317{
2318 u32 reg32;
2319
2320 reg32 = MCHBAR32(FSBPMC3);
2321 reg32 |= (1 << 1);
2322 MCHBAR32(FSBPMC3) = reg32;
2323
2324 reg32 = MCHBAR32(SBTEST);
2325 reg32 |= (3 << 1);
2326 MCHBAR32(SBTEST) = reg32;
2327}
2328
2329static void sdram_pre_jedec_initialization(void)
2330{
2331 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002332
Stefan Reinauer278534d2008-10-29 04:51:07 +00002333 reg32 = MCHBAR32(WCC);
2334 reg32 &= 0x113ff3ff;
2335 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2336 MCHBAR32(WCC) = reg32;
2337
2338 MCHBAR32(SMVREFC) |= (1 << 6);
2339
2340 MCHBAR32(MMARB0) &= ~(3 << 17);
2341 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2342
2343 MCHBAR32(MMARB1) &= ~(7 << 8);
2344 MCHBAR32(MMARB1) |= (3 << 8);
2345
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002346 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002347 MCHBAR32(C0AIT) = 0x000006c4;
2348 MCHBAR32(C0AIT+4) = 0x871a066d;
2349
2350 MCHBAR32(C1AIT) = 0x000006c4;
2351 MCHBAR32(C1AIT+4) = 0x871a066d;
2352}
2353
2354#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2355#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2356#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2357#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2358#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2359#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2360#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2361#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2362
2363static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2364{
2365 u32 chan0 = 0, chan1 = 0;
2366 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2367
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002368 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002369 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002370 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002371 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2372 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2373 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2374
2375 if (sdram_capabilities_enhanced_addressing_xor()) {
2376 if (!sysinfo->interleaved) {
2377 /* Single Channel & Dual Channel Assymetric */
2378 if (chan0_populated) {
2379 if (chan0_dualsided) {
2380 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2381 } else {
2382 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2383 }
2384 }
2385 if (chan1_populated) {
2386 if (chan1_dualsided) {
2387 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2388 } else {
2389 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2390 }
2391 }
2392 } else {
2393 /* Interleaved has always both channels populated */
2394 if (chan0_dualsided) {
2395 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2396 } else {
2397 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2398 }
2399
2400 if (chan1_dualsided) {
2401 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2402 } else {
2403 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2404 }
2405 }
2406 } else {
2407 if (!sysinfo->interleaved) {
2408 /* Single Channel & Dual Channel Assymetric */
2409 if (chan0_populated) {
2410 if (chan0_dualsided) {
2411 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2412 } else {
2413 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2414 }
2415 }
2416 if (chan1_populated) {
2417 if (chan1_dualsided) {
2418 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2419 } else {
2420 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2421 }
2422 }
2423 } else {
2424 /* Interleaved has always both channels populated */
2425 if (chan0_dualsided) {
2426 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2427 } else {
2428 chan0 = EA_DUALCHANNEL_BANK_MODE;
2429 }
2430
2431 if (chan1_dualsided) {
2432 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2433 } else {
2434 chan1 = EA_DUALCHANNEL_BANK_MODE;
2435 }
2436 }
2437 }
2438
2439 MCHBAR32(C0DRC1) &= 0x00ffffff;
2440 MCHBAR32(C0DRC1) |= chan0;
2441 MCHBAR32(C1DRC1) &= 0x00ffffff;
2442 MCHBAR32(C1DRC1) |= chan1;
2443}
2444
2445static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2446{
2447 u32 reg32;
2448
2449 /* Enable Channel XORing for Dual Channel Interleave */
2450 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002451
Stefan Reinauer278534d2008-10-29 04:51:07 +00002452 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002453#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002454 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002455 reg32 |= (1 << 9);
2456#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002457 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002458#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002459 MCHBAR32(DCC) = reg32;
2460 }
2461
2462 /* DRAM mode optimizations */
2463 sdram_enhanced_addressing_mode(sysinfo);
2464
2465 reg32 = MCHBAR32(FSBPMC3);
2466 reg32 &= ~(1 << 1);
2467 MCHBAR32(FSBPMC3) = reg32;
2468
2469 reg32 = MCHBAR32(SBTEST);
2470 reg32 &= ~(1 << 2);
2471 MCHBAR32(SBTEST) = reg32;
2472
2473 reg32 = MCHBAR32(SBOCC);
2474 reg32 &= 0xffbdb6ff;
2475 reg32 |= (0xbdb6 << 8) | (1 << 0);
2476 MCHBAR32(SBOCC) = reg32;
2477}
2478
2479static void sdram_power_management(struct sys_info *sysinfo)
2480{
2481 u8 reg8;
2482 u16 reg16;
2483 u32 reg32;
2484 int integrated_graphics = 1;
2485 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002486
Stefan Reinauer278534d2008-10-29 04:51:07 +00002487 reg32 = MCHBAR32(C0DRT2);
2488 reg32 &= 0xffffff00;
2489 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002490 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002491 MCHBAR32(C0DRT2) = reg32;
2492
2493 reg32 = MCHBAR32(C1DRT2);
2494 reg32 &= 0xffffff00;
2495 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002496 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002497 MCHBAR32(C1DRT2) = reg32;
2498
2499 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002500
2501 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002502 MCHBAR32(C0DRC1) = reg32;
2503
2504 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002505
2506 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002507 MCHBAR32(C1DRC1) = reg32;
2508
2509 if (i945_silicon_revision()>1) {
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
2513 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002514 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002515 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2516 u16 peg_bits = (1 << 5) | (1 << 0);
2517
Stefan Reinauer278534d2008-10-29 04:51:07 +00002518 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002519 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002520 }
2521
2522 reg16 = MCHBAR16(UPMC2);
2523 reg16 &= 0xfc00;
2524 reg16 |= 0x0100;
2525 MCHBAR16(UPMC2) = reg16;
2526
2527 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002528
Stefan Reinauer278534d2008-10-29 04:51:07 +00002529 for (i=0; i<5; i++) {
2530 MCHBAR32(UPMC3) &= ~(1 << 16);
2531 MCHBAR32(UPMC3) |= (1 << 16);
2532 }
2533
2534 MCHBAR32(GIPMC1) = 0x8000000c;
2535
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002536 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002537 reg16 &= ~(7 << 11);
2538 if (i945_silicon_revision()>2) {
2539 reg16 |= (6 << 11);
2540 } else {
2541 reg16 |= (4 << 11);
2542 }
2543 MCHBAR16(CPCTL) = reg16;
2544
Stefan Reinauer30140a52009-03-11 16:20:39 +00002545#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002546 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002547#else
2548 if (i945_silicon_revision() != 0) {
2549#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002550 switch (sysinfo->fsb_frequency) {
2551 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2552 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2553 }
2554 } else {
2555 switch (sysinfo->fsb_frequency) {
2556 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2557 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2558 }
2559 }
2560
2561 MCHBAR32(FSBPMC1) = 0x8000000c;
2562
2563 reg32 = MCHBAR32(C2C3TT);
2564 reg32 &= 0xffff0000;
2565 switch (sysinfo->fsb_frequency) {
2566 case 667: reg32 |= 0x0600; break;
2567 case 533: reg32 |= 0x0480; break;
2568 }
2569 MCHBAR32(C2C3TT) = reg32;
2570
2571 reg32 = MCHBAR32(C3C4TT);
2572 reg32 &= 0xffff0000;
2573 switch (sysinfo->fsb_frequency) {
2574 case 667: reg32 |= 0x0b80; break;
2575 case 533: reg32 |= 0x0980; break;
2576 }
2577 MCHBAR32(C3C4TT) = reg32;
2578
2579 if (i945_silicon_revision() == 0) {
2580 MCHBAR32(ECO) &= ~(1 << 16);
2581 } else {
2582 MCHBAR32(ECO) |= (1 << 16);
2583 }
2584
2585#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002586
Stefan Reinauer278534d2008-10-29 04:51:07 +00002587 if (i945_silicon_revision() == 0) {
2588 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2589 } else {
2590 MCHBAR32(FSBPMC3) |= (1 << 29);
2591 }
2592#endif
2593 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2594
2595 MCHBAR32(FSBPMC3) |= (1 << 21);
2596
2597 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2598
2599 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2600
2601 reg32 = MCHBAR32(FSBPMC4);
2602 reg32 &= ~(3 << 24);
2603 reg32 |= ( 2 << 24);
2604 MCHBAR32(FSBPMC4) = reg32;
2605
2606 MCHBAR32(FSBPMC4) |= (1 << 21);
2607
2608 MCHBAR32(FSBPMC4) |= (1 << 5);
2609
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002610 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2611 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002612 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2613 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002614 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002615 }
2616
2617 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2618 reg8 |= (1 << 4);
2619 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2620
2621 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2622 reg8 |= (1 << 2);
2623 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2624
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002625#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002626
Stefan Reinauer278534d2008-10-29 04:51:07 +00002627 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002628 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002629 MCHBAR16(MIPMC4) = 0x0468;
2630 MCHBAR16(MIPMC5) = 0x046c;
2631 MCHBAR16(MIPMC6) = 0x046c;
2632 } else {
2633 MCHBAR16(MIPMC4) = 0x6468;
2634 MCHBAR16(MIPMC5) = 0x646c;
2635 MCHBAR16(MIPMC6) = 0x646c;
2636 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002637#else
2638 if (integrated_graphics) {
2639 MCHBAR16(MIPMC4) = 0x04f8;
2640 MCHBAR16(MIPMC5) = 0x04fc;
2641 MCHBAR16(MIPMC6) = 0x04fc;
2642 } else {
2643 MCHBAR16(MIPMC4) = 0x64f8;
2644 MCHBAR16(MIPMC5) = 0x64fc;
2645 MCHBAR16(MIPMC6) = 0x64fc;
2646 }
2647
2648#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002649
2650 reg32 = MCHBAR32(PMCFG);
2651 reg32 &= ~(3 << 17);
2652 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002653 MCHBAR32(PMCFG) = reg32;
2654
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002655 MCHBAR32(PMCFG) |= (1 << 4);
2656
Stefan Reinauer278534d2008-10-29 04:51:07 +00002657 reg32 = MCHBAR32(0xc30);
2658 reg32 &= 0xffffff00;
2659 reg32 |= 0x01;
2660 MCHBAR32(0xc30) = reg32;
2661
2662 MCHBAR32(0xb18) &= ~(1 << 21);
2663}
2664
2665static void sdram_thermal_management(void)
2666{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002667
Stefan Reinauer278534d2008-10-29 04:51:07 +00002668 MCHBAR8(TCO1) = 0x00;
2669 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002670
2671 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2672 * 0x30/0x32.
2673 */
2674
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002675 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002676}
2677
2678static void sdram_save_receive_enable(void)
2679{
2680 int i;
2681 u32 reg32;
2682 u8 values[4];
2683
2684 /* The following values are stored to an unused CMOS
2685 * area and restored instead of recalculated in case
2686 * of an S3 resume.
2687 *
2688 * C0WL0REOST [7:0] -> 8 bit
2689 * C1WL0REOST [7:0] -> 8 bit
2690 * RCVENMT [11:8] [3:0] -> 8 bit
2691 * C0DRT1 [27:24] -> 4 bit
2692 * C1DRT1 [27:24] -> 4 bit
2693 */
2694
2695 values[0] = MCHBAR8(C0WL0REOST);
2696 values[1] = MCHBAR8(C1WL0REOST);
2697
2698 reg32 = MCHBAR32(RCVENMT);
2699 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2700
2701 reg32 = MCHBAR32(C0DRT1);
2702 values[3] = (reg32 >> 24) & 0x0f;
2703 reg32 = MCHBAR32(C1DRT1);
2704 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2705
2706 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002707 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002708 */
2709
2710 for (i=0; i<4; i++)
2711 cmos_write(values[i], 128 + i);
2712}
2713
2714static void sdram_recover_receive_enable(void)
2715{
2716 int i;
2717 u32 reg32;
2718 u8 values[4];
2719
2720 for (i=0; i<4; i++)
2721 values[i] = cmos_read(128 + i);
2722
2723 MCHBAR8(C0WL0REOST) = values[0];
2724 MCHBAR8(C1WL0REOST) = values[1];
2725
2726 reg32 = MCHBAR32(RCVENMT);
2727 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2728 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2729 MCHBAR32(RCVENMT) = reg32;
2730
2731 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2732 reg32 |= (u32)(values[3] & 0x0f) << 24;
2733 MCHBAR32(C0DRT1) = reg32;
2734
2735 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2736 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2737 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002738}
2739
2740#include "rcven.c"
2741
2742static void sdram_program_receive_enable(struct sys_info *sysinfo)
2743{
2744 MCHBAR32(REPC) |= (1 << 0);
2745
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002746 /* enable upper CMOS */
2747 RCBA32(0x3400) = (1 << 2);
2748
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002749 /* Program Receive Enable Timings */
2750 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2751 sdram_recover_receive_enable();
2752 } else {
2753 receive_enable_adjust(sysinfo);
2754 sdram_save_receive_enable();
2755 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002756
2757 MCHBAR32(C0DRC1) |= (1 << 6);
2758 MCHBAR32(C1DRC1) |= (1 << 6);
2759 MCHBAR32(C0DRC1) &= ~(1 << 6);
2760 MCHBAR32(C1DRC1) &= ~(1 << 6);
2761
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002762 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002763}
2764
2765/**
2766 * @brief Enable On-Die Termination for DDR2.
2767 *
2768 */
2769
2770static void sdram_on_die_termination(struct sys_info *sysinfo)
2771{
2772 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002773 0x00024911, 0xe0010000,
2774 0x00049211, 0xe0020000,
2775 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002776 };
2777
2778 u32 reg32;
2779 int cas;
2780
2781 reg32 = MCHBAR32(ODTC);
2782 reg32 &= ~(3 << 16);
2783 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2784 MCHBAR32(ODTC) = reg32;
2785
2786 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2787 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002788 printk(BIOS_DEBUG, "one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002789
Stefan Reinauer278534d2008-10-29 04:51:07 +00002790 reg32 = MCHBAR32(C0ODT);
2791 reg32 &= ~(7 << 28);
2792 MCHBAR32(C0ODT) = reg32;
2793 reg32 = MCHBAR32(C1ODT);
2794 reg32 &= ~(7 << 28);
2795 MCHBAR32(C1ODT) = reg32;
2796 }
2797
2798 cas = sysinfo->cas;
2799
2800 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2801 reg32 |= odt[(cas-3) * 2];
2802 MCHBAR32(C0ODT) = reg32;
2803
2804 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2805 reg32 |= odt[(cas-3) * 2];
2806 MCHBAR32(C1ODT) = reg32;
2807
2808 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2809 reg32 |= odt[((cas-3) * 2) + 1];
2810 MCHBAR32(C0ODT + 4) = reg32;
2811
2812 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2813 reg32 |= odt[((cas-3) * 2) + 1];
2814 MCHBAR32(C1ODT + 4) = reg32;
2815}
2816
2817/**
2818 * @brief Enable clocks to populated sockets
2819 */
2820
2821static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2822{
2823 u8 clocks[2] = { 0, 0 };
2824
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002825#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002826#define CLOCKS_WIDTH 2
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002827#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002828#define CLOCKS_WIDTH 3
2829#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002830 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002831 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002832
2833 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002834 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002835
2836 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002837 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002838
2839 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002840 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002841
Patrick Georgi77d66832010-10-01 08:02:45 +00002842#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002843 /* Usually system firmware turns off system memory clock signals
2844 * to unused SO-DIMM slots to reduce EMI and power consumption.
2845 * However, the Kontron 986LCD-M does not like unused clock
2846 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002847 */
2848
2849 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2850 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002851#endif
2852
2853 MCHBAR8(C0DCLKDIS) = clocks[0];
2854 MCHBAR8(C1DCLKDIS) = clocks[1];
2855}
2856
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002857#define RTT_ODT_NONE 0
2858#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002859#define RTT_ODT_75_OHM (1 << 5)
2860#define RTT_ODT_150_OHM (1 << 9)
2861
2862#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2863
2864#define MRS_CAS_3 (3 << 7)
2865#define MRS_CAS_4 (4 << 7)
2866#define MRS_CAS_5 (5 << 7)
2867
2868#define MRS_TWR_3 (2 << 12)
2869#define MRS_TWR_4 (3 << 12)
2870#define MRS_TWR_5 (4 << 12)
2871
2872#define MRS_BT (1 << 6)
2873
2874#define MRS_BL4 (2 << 3)
2875#define MRS_BL8 (3 << 3)
2876
2877static void sdram_jedec_enable(struct sys_info *sysinfo)
2878{
2879 int i, nonzero;
2880 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2881
2882 for (i = 0, nonzero = -1; i < 8; i++) {
2883 if (sysinfo->banksize[i] == 0) {
2884 continue;
2885 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002886
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002887 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002888 switch (i) {
2889 case 0:
2890 /* Start at address 0 */
2891 bankaddr = 0;
2892 break;
2893 case 4:
2894 if (sysinfo->interleaved) {
2895 bankaddr = 0x40;
2896 break;
2897 }
2898 default:
2899 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002900 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002901 bankaddr += sysinfo->banksize[nonzero] <<
2902 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002903 break;
2904 }
2905 /* No populated bank hit before. Start at address 0 */
2906 bankaddr = 0;
2907 }
2908
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002909 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002910 * for the next offset we have to calculate
2911 */
2912 nonzero = i;
2913
2914 /* Get CAS latency set up */
2915 switch (sysinfo->cas) {
2916 case 5: mrsaddr = MRS_CAS_5; break;
2917 case 4: mrsaddr = MRS_CAS_4; break;
2918 case 3: mrsaddr = MRS_CAS_3; break;
2919 default: die("Jedec Error (CAS).\n");
2920 }
2921
2922 /* Get tWR set */
2923 switch (sysinfo->twr) {
2924 case 5: mrsaddr |= MRS_TWR_5; break;
2925 case 4: mrsaddr |= MRS_TWR_4; break;
2926 case 3: mrsaddr |= MRS_TWR_3; break;
2927 default: die("Jedec Error (tWR).\n");
2928 }
2929
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002930 /* Set "Burst Type" */
2931 mrsaddr |= MRS_BT;
2932
Stefan Reinauer278534d2008-10-29 04:51:07 +00002933 /* Interleaved */
2934 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002935 mrsaddr = mrsaddr << 1;
2936 }
2937
2938 /* Only burst length 8 supported */
2939 mrsaddr |= MRS_BL8;
2940
2941 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002942 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002943 do_ram_command(RAM_COMMAND_NOP);
2944 ram_read32(bankaddr);
2945
2946 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002947 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002948 do_ram_command(RAM_COMMAND_PRECHARGE);
2949 ram_read32(bankaddr);
2950
2951 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002952 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002953 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2954 ram_read32(bankaddr);
2955
2956 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002957 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002958 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2959 ram_read32(bankaddr);
2960
2961 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002962 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002963 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2964 tmpaddr = bankaddr;
2965 if (!sdram_capabilities_dual_channel()) {
2966 tmpaddr |= RTT_ODT_75_OHM;
2967 } else if (sysinfo->interleaved) {
2968 tmpaddr |= (RTT_ODT_150_OHM << 1);
2969 } else {
2970 tmpaddr |= RTT_ODT_150_OHM;
2971 }
2972 ram_read32(tmpaddr);
2973
2974 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002975 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002976 do_ram_command(RAM_COMMAND_MRS);
2977 tmpaddr = bankaddr;
2978 tmpaddr |= mrsaddr;
2979 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002980 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002981 tmpaddr |= (1 << 12);
2982 else
2983 tmpaddr |= (1 << 11);
2984 ram_read32(tmpaddr);
2985
2986 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002987 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002988 do_ram_command(RAM_COMMAND_PRECHARGE);
2989 ram_read32(bankaddr);
2990
2991 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002992 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002993 do_ram_command(RAM_COMMAND_CBR);
2994
2995 /* CBR wants two READs */
2996 ram_read32(bankaddr);
2997 ram_read32(bankaddr);
2998
2999 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003000 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003001 do_ram_command(RAM_COMMAND_MRS);
3002
3003 tmpaddr = bankaddr;
3004 tmpaddr |= mrsaddr;
3005 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003006
Stefan Reinauer278534d2008-10-29 04:51:07 +00003007 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003008 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003009 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003010
Stefan Reinauer278534d2008-10-29 04:51:07 +00003011 tmpaddr = bankaddr;
3012 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003013
Stefan Reinauer278534d2008-10-29 04:51:07 +00003014 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
3015 } else if (sysinfo->interleaved) {
3016 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
3017 } else {
3018 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
3019 }
3020 ram_read32(tmpaddr);
3021
3022 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003023 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003024 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3025
3026 tmpaddr = bankaddr;
3027 if (!sdram_capabilities_dual_channel()) {
3028 tmpaddr |= RTT_ODT_75_OHM;
3029 } else if (sysinfo->interleaved) {
3030 tmpaddr |= (RTT_ODT_150_OHM << 1);
3031 } else {
3032 tmpaddr |= RTT_ODT_150_OHM;
3033 }
3034 ram_read32(tmpaddr);
3035 }
3036}
3037
3038static void sdram_init_complete(void)
3039{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003040 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003041 do_ram_command(RAM_COMMAND_NORMAL);
3042}
3043
3044static void sdram_setup_processor_side(void)
3045{
3046 if (i945_silicon_revision() == 0)
3047 MCHBAR32(FSBPMC3) |= (1 << 2);
3048
3049 MCHBAR8(0xb00) |= 1;
3050
3051 if (i945_silicon_revision() == 0)
3052 MCHBAR32(SLPCTL) |= (1 << 8);
3053}
3054
Stefan Reinauer278534d2008-10-29 04:51:07 +00003055/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003056 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003057 */
Sven Schnelle541269b2011-02-21 09:39:17 +00003058void sdram_initialize(int boot_path, const u8 *spd_addresses)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003059{
3060 struct sys_info sysinfo;
3061 u8 reg8, cas_mask;
3062
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003063 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003064
3065 memset(&sysinfo, 0, sizeof(sysinfo));
3066
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003067 sysinfo.boot_path = boot_path;
Sven Schnelle541269b2011-02-21 09:39:17 +00003068 sysinfo.spd_addresses = spd_addresses;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003069
Stefan Reinauer278534d2008-10-29 04:51:07 +00003070 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3071 sdram_get_dram_configuration(&sysinfo);
3072
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003073 /* If error, do cold boot */
3074 sdram_detect_errors(&sysinfo);
3075
Stefan Reinauer278534d2008-10-29 04:51:07 +00003076 /* Check whether we have stacked DIMMs */
3077 sdram_verify_package_type(&sysinfo);
3078
3079 /* Determine common CAS */
3080 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003081
Stefan Reinauer278534d2008-10-29 04:51:07 +00003082 /* Choose Common Frequency */
3083 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003084
Stefan Reinauer278534d2008-10-29 04:51:07 +00003085 /* Determine smallest common tRAS */
3086 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003087
Stefan Reinauer278534d2008-10-29 04:51:07 +00003088 /* Determine tRP */
3089 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003090
Stefan Reinauer278534d2008-10-29 04:51:07 +00003091 /* Determine tRCD */
3092 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003093
Stefan Reinauer278534d2008-10-29 04:51:07 +00003094 /* Determine smallest refresh period */
3095 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003096
Stefan Reinauer278534d2008-10-29 04:51:07 +00003097 /* Verify all DIMMs support burst length 8 */
3098 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003099
Stefan Reinauer278534d2008-10-29 04:51:07 +00003100 /* determine tWR */
3101 sdram_detect_smallest_tWR(&sysinfo);
3102
3103 /* Determine DIMM size parameters (rows, columns banks) */
3104 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003105
Stefan Reinauer278534d2008-10-29 04:51:07 +00003106 /* determine tRFC */
3107 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003108
Stefan Reinauer278534d2008-10-29 04:51:07 +00003109 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003110 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003111
3112 /* Program Graphics Frequency */
3113 sdram_program_graphics_frequency(&sysinfo);
3114
3115 /* Program System Memory Frequency */
3116 sdram_program_memory_frequency(&sysinfo);
3117
3118 /* Determine Mode of Operation (Interleaved etc) */
3119 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003120
Stefan Reinauer278534d2008-10-29 04:51:07 +00003121 /* Program Clock Crossing values */
3122 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003123
Stefan Reinauer278534d2008-10-29 04:51:07 +00003124 /* Disable fast dispatch */
3125 sdram_disable_fast_dispatch();
3126
3127 /* Enable WIODLL Power Down in ACPI states */
3128 MCHBAR32(C0DMC) |= (1 << 24);
3129 MCHBAR32(C1DMC) |= (1 << 24);
3130
3131 /* Program DRAM Row Boundary/Attribute Registers */
3132
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003133 /* program row size DRB and set TOLUD */
3134 sdram_program_row_boundaries(&sysinfo);
3135
3136 /* program page size DRA */
3137 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003138
3139 /* Program CxBNKARC */
3140 sdram_set_bank_architecture(&sysinfo);
3141
3142 /* Program DRAM Timing and Control registers based on SPD */
3143 sdram_set_timing_and_control(&sysinfo);
3144
3145 /* On-Die Termination Adjustment */
3146 sdram_on_die_termination(&sysinfo);
3147
3148 /* Pre Jedec Initialization */
3149 sdram_pre_jedec_initialization();
3150
3151 /* Perform System Memory IO Initialization */
3152 sdram_initialize_system_memory_io(&sysinfo);
3153
3154 /* Perform System Memory IO Buffer Enable */
3155 sdram_enable_system_memory_io(&sysinfo);
3156
3157 /* Enable System Memory Clocks */
3158 sdram_enable_memory_clocks(&sysinfo);
3159
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003160 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003161 /* Jedec Initialization sequence */
3162 sdram_jedec_enable(&sysinfo);
3163 }
3164
3165 /* Program Power Management Registers */
3166 sdram_power_management(&sysinfo);
3167
3168 /* Post Jedec Init */
3169 sdram_post_jedec_initialization(&sysinfo);
3170
3171 /* Program DRAM Throttling */
3172 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003173
Stefan Reinauer278534d2008-10-29 04:51:07 +00003174 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003175 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003176
3177 /* Program Receive Enable Timings */
3178 sdram_program_receive_enable(&sysinfo);
3179
3180 /* Enable Periodic RCOMP */
3181 sdram_enable_rcomp();
3182
3183 /* Tell ICH7 that we're done */
3184 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3185 reg8 &= ~(1 << 7);
3186 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3187
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003188 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003189
Stefan Reinauer278534d2008-10-29 04:51:07 +00003190 sdram_setup_processor_side();
3191}
3192
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003193unsigned long get_top_of_ram(void)
3194{
Sven Schnelle148a4f52011-04-10 07:41:56 +00003195 u32 tom;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003196
Sven Schnelle148a4f52011-04-10 07:41:56 +00003197 if (pci_read_config8(PCI_DEV(0, 0x0, 0), DEVEN) & ((1 << 4) | (1 << 3))) {
3198 /* IGD enabled, get top of Memory from BSM register */
3199 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
3200 } else {
3201 tom = (pci_read_config8(PCI_DEV(0,0,0), TOLUD) & 0xf7) << 24;
3202 }
3203
3204 /* if TSEG enabled subtract size */
3205 switch(pci_read_config8(PCI_DEV(0, 0, 0), ESMRAM)) {
3206 case 0x01:
3207 /* 1MB TSEG */
3208 tom -= 0x10000;
3209 break;
3210 case 0x03:
3211 /* 2MB TSEG */
3212 tom -= 0x20000;
3213 break;
3214 case 0x05:
3215 /* 8MB TSEG */
3216 tom -= 0x80000;
3217 break;
3218 default:
3219 /* TSEG either disabled or invalid */
3220 break;
3221 }
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003222 return (unsigned long) tom;
3223}
3224