blob: 6915d7882bf18e0001176b431024486a4d119294 [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
Patrick Georgid0835952010-10-05 09:07:10 +000057static inline int spd_read_byte(unsigned device, unsigned address)
58{
59 return smbus_read_byte(device, address);
60}
61
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000062static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000063{
64 u32 reg32;
65
66 reg32 = MCHBAR32(DCC);
67 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
68 reg32 |= command;
69
70 /* Also set Init Complete */
71 if (command == RAM_COMMAND_NORMAL)
72 reg32 |= RAM_INITIALIZATION_COMPLETE;
73
74 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
75
76 MCHBAR32(DCC) = reg32; /* This is the actual magic */
77
Stefan Reinauer779b3e32008-11-10 15:43:37 +000078 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000079
80 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000081}
82
Stefan Reinauer278534d2008-10-29 04:51:07 +000083static void ram_read32(u32 offset)
84{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000085 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000086
87 read32(offset);
88}
89
Uwe Hermann01ce6012010-03-05 10:03:50 +000090#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer278534d2008-10-29 04:51:07 +000091static void sdram_dump_mchbar_registers(void)
92{
93 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000094 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000095
96 for (i=0; i<0xfff; i+=4) {
97 if (MCHBAR32(i) == 0)
98 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000099 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000100 }
101}
102#endif
103
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000104static int memclk(void)
105{
106 int offset = 0;
Peter Stugee4bc0f62010-10-01 09:13:18 +0000107#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000108 offset++;
109#endif
110 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
111 case 1: return 400;
112 case 2: return 533;
113 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000114 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000115 }
116 return -1;
117}
118
Peter Stugee4bc0f62010-10-01 09:13:18 +0000119#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Peter Stuge76d91432010-10-01 10:02:33 +0000120static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000121{
122 switch (MCHBAR32(CLKCFG) & 7) {
123 case 0: return 400;
124 case 1: return 533;
125 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000126 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000127 }
Peter Stuge76d91432010-10-01 10:02:33 +0000128 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000129}
Peter Stugee4bc0f62010-10-01 09:13:18 +0000130#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Peter Stuge76d91432010-10-01 10:02:33 +0000131static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000132{
133 switch (MCHBAR32(CLKCFG) & 7) {
134 case 0: return 1066;
135 case 1: return 533;
136 case 2: return 800;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000137 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000138 }
Peter Stuge76d91432010-10-01 10:02:33 +0000139 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000140}
141#endif
142
Stefan Reinauer278534d2008-10-29 04:51:07 +0000143static int sdram_capabilities_max_supported_memory_frequency(void)
144{
145 u32 reg32;
146
Patrick Georgi77d66832010-10-01 08:02:45 +0000147#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
148 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000149#endif
150
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000151 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000152 reg32 &= (7 << 0);
153
154 switch (reg32) {
155 case 4: return 400;
156 case 3: return 533;
157 case 2: return 667;
158 }
159 /* Newer revisions of this chipset rather support faster memory clocks,
160 * so if it's a reserved value, return the fastest memory clock that we
161 * know of and can handle
162 */
163 return 667;
164}
165
166/**
167 * @brief determine whether chipset is capable of dual channel interleaved mode
168 *
169 * @return 1 if interleaving is supported, 0 otherwise
170 */
171static int sdram_capabilities_interleave(void)
172{
173 u32 reg32;
174
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000175 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000176 reg32 >>= 25;
177 reg32 &= 1;
178
179 return (!reg32);
180}
181
182/**
183 * @brief determine whether chipset is capable of two memory channels
184 *
185 * @return 1 if dual channel operation is supported, 0 otherwise
186 */
187static int sdram_capabilities_dual_channel(void)
188{
189 u32 reg32;
190
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000191 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000192 reg32 >>= 24;
193 reg32 &= 1;
194
195 return (!reg32);
196}
197
198static int sdram_capabilities_enhanced_addressing_xor(void)
199{
200 u8 reg8;
201
202 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
203 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000204
Stefan Reinauer278534d2008-10-29 04:51:07 +0000205 return (!reg8);
206}
207
208static int sdram_capabilities_two_dimms_per_channel(void)
209{
210 u8 reg8;
211
212 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe8); /* CAPID0 + 8 */
213 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000214
Stefan Reinauer278534d2008-10-29 04:51:07 +0000215 return (reg8 != 0);
216}
217
Stefan Reinauer14e22772010-04-27 06:56:47 +0000218// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000219#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000220static int sdram_capabilities_MEM4G_disable(void)
221{
222 u8 reg8;
223
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000224 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000225 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000226
Stefan Reinauer278534d2008-10-29 04:51:07 +0000227 return (reg8 != 0);
228}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000229#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000230
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000231#define GFX_FREQUENCY_CAP_166MHZ 0x04
232#define GFX_FREQUENCY_CAP_200MHZ 0x03
233#define GFX_FREQUENCY_CAP_250MHZ 0x02
234#define GFX_FREQUENCY_CAP_ALL 0x00
235
236static int sdram_capabilities_core_frequencies(void)
237{
238 u8 reg8;
239
240 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
241 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
242 reg8 >>= 1;
243
244 return (reg8);
245}
246
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000247static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000248{
249 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000250 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000251
252 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000253
Stefan Reinauer278534d2008-10-29 04:51:07 +0000254 if (reg8 & ((1<<7)|(1<<2))) {
255 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000256 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000257 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000258 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000259 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000260
Stefan Reinauer278534d2008-10-29 04:51:07 +0000261 }
262
263 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000264 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000265 reg8 &= ~(1<<7);
266 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000267 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000268 }
269
270 /* Set SLP_S3# Assertion Stretch Enable */
271 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
272 reg8 |= (1 << 3);
273 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
274
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000275 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000276 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000277 outb(0x00, 0xcf9);
278 outb(0x0e, 0xcf9);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000279 for (;;) asm("hlt"); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000280 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000281 }
282
283 /* Set DRAM initialization bit in ICH7 */
284 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
285 reg8 |= (1<<7);
286 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000287
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000288 /* clear self refresh if not wake-up from suspend */
289 if (sysinfo->boot_path != 2) {
290 MCHBAR8(0xf14) |= 3;
291 } else {
292 /* Validate self refresh config */
293 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
294 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
295 !(MCHBAR8(0xf14) & (1<<0))) {
296 do_reset = 1;
297 }
298 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
299 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
300 !(MCHBAR8(0xf14) & (1<<1))) {
301 do_reset = 1;
302 }
303 }
304
305 if (do_reset) {
306 printk(BIOS_DEBUG, "Reset required.\n");
307 outb(0x00, 0xcf9);
308 outb(0x0e, 0xcf9);
309 for (;;) asm("hlt"); /* Wait for reset! */
310 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000311}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000312
313/**
314 * @brief Get generic DIMM parameters.
315 * @param sysinfo Central memory controller information structure
316 *
317 * This function gathers several pieces of information for each system DIMM:
318 * o DIMM width (x8 / x16)
319 * o DIMM sides (single sided / dual sided)
320 *
321 * Also, some non-supported scenarios are detected.
322 */
323
324static void sdram_get_dram_configuration(struct sys_info *sysinfo)
325{
326 u32 dimm_mask = 0;
327 int i;
328
329 /**
330 * i945 supports two DIMMs, in two configurations:
331 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000332 * - single channel with two DIMMs
333 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000334 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000335 * In practice dual channel mainboards have their SPD at 0x50/0x52
336 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000337 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000338 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000339 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000340 */
341
342 if (sdram_capabilities_dual_channel()) {
343 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000344 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000345 } else {
346 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000347 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000348 }
349
350 /**
351 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000352 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000353 * return value:
354 * [0:7] lower DIMM population
355 * [8-15] higher DIMM population
356 * [16] dual channel?
357 *
358 * There are 5 different possible populations for a DIMM socket:
359 * 1. x16 double sided (X16DS)
360 * 2. x8 double sided (X8DS)
361 * 3. x16 single sided (X16SS)
362 * 4. x8 double stacked (X8DDS)
363 * 5. not populated (NC)
364 *
365 * For the return value we start counting at zero.
366 *
367 */
368
369 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
Uwe Hermannd773fd32010-11-20 20:23:08 +0000370 u8 reg8, device = DIMM0 + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000371
372 /* Initialize the socket information with a sane value */
373 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
374
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000375 /* Dual Channel not supported, but Channel 1? Bail out */
376 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000377 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000378
379 /* Two DIMMs per channel not supported, but odd DIMM number? */
380 if (!sdram_capabilities_two_dimms_per_channel() && (i& 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000381 continue;
382
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000383 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000384
385 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000386 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000387 continue;
388 }
389
390 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
391 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000392 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000393
394 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
395 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000396 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000397 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000398 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399
400 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000401 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000402 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
403 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000404 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000405 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
406 break;
407 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000408 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000409 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
410 break;
411 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000412 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000413 }
414 break;
415 case 0x10:
416 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
417 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000418 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000419 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
420 break;
421 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000422 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000423 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
424 break;
425 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000426 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000427 }
428 break;
429 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000430 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000431 }
432
433 dimm_mask |= (1 << i);
434 }
435
436 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000437 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000438 }
439
Stefan Reinauer278534d2008-10-29 04:51:07 +0000440 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000441 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000442 }
443}
444
445/**
446 * @brief determine if any DIMMs are stacked
447 *
448 * @param sysinfo central sysinfo data structure.
449 */
450static void sdram_verify_package_type(struct sys_info * sysinfo)
451{
452 int i;
453
454 /* Assume no stacked DIMMs are available until we find one */
455 sysinfo->package = 0;
456 for (i=0; i<2*DIMM_SOCKETS; i++) {
457 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
458 continue;
459
460 /* Is the current DIMM a stacked DIMM? */
Uwe Hermannd773fd32010-11-20 20:23:08 +0000461 if (spd_read_byte(DIMM0 + i, SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000462 sysinfo->package = 1;
463 }
464}
465
466static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
467{
468 int i;
469 u8 cas_mask;
470
471 /* Setup CAS mask with all supported CAS Latencies */
472 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
473 SPD_CAS_LATENCY_DDR2_4 |
474 SPD_CAS_LATENCY_DDR2_5;
475
476 for (i=0; i<2*DIMM_SOCKETS; i++) {
477 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Uwe Hermannd773fd32010-11-20 20:23:08 +0000478 cas_mask &= spd_read_byte(DIMM0 + i, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000479 }
480
481 if(!cas_mask) {
482 die("No DDR-II modules with accepted CAS latencies found.\n");
483 }
484
485 return cas_mask;
486}
487
488static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
489{
490 int i, j, idx;
491 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000492 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000493
494 const u8 ddr2_speeds_table[] = {
495 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
496 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
497 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
498 };
499
500 const u8 spd_lookup_table[] = {
501 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
502 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
503 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
504 };
505
506 switch (sdram_capabilities_max_supported_memory_frequency()) {
507 case 400: max_ram_speed = 0; break;
508 case 533: max_ram_speed = 1; break;
509 case 667: max_ram_speed = 2; break;
510 }
511
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000512 if (fsbclk() == 533)
513 max_ram_speed = 1;
514
Stefan Reinauer278534d2008-10-29 04:51:07 +0000515 sysinfo->memory_frequency = 0;
516 sysinfo->cas = 0;
517
518 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
519 lowest_common_cas = 3;
520 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
521 lowest_common_cas = 4;
522 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
523 lowest_common_cas = 5;
524 }
525 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
526
527 for (j = max_ram_speed; j>=0; j--) {
528 int freq_cas_mask = cas_mask;
529
530 PRINTK_DEBUG("Probing Speed %d\n", j);
531 for (i=0; i<2*DIMM_SOCKETS; i++) {
532 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000533
Stefan Reinauer278534d2008-10-29 04:51:07 +0000534 PRINTK_DEBUG(" DIMM: %d\n", i);
535 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
536 continue;
537 }
538
Uwe Hermannd773fd32010-11-20 20:23:08 +0000539 current_cas_mask = spd_read_byte(DIMM0 + i, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000540
541 while (current_cas_mask) {
542 int highest_supported_cas = 0, current_cas = 0;
543 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
544 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
545 highest_supported_cas = 5;
546 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
547 highest_supported_cas = 4;
548 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
549 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000550 } else {
551 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000552 }
553 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
554 current_cas = 3;
555 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
556 current_cas = 4;
557 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
558 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000559 } else {
560 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000561 }
562
563 idx = highest_supported_cas - current_cas;
564 PRINTK_DEBUG("idx=%d, ", idx);
Uwe Hermannd773fd32010-11-20 20:23:08 +0000565 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(DIMM0 + i, spd_lookup_table[2*idx]));
566 PRINTK_DEBUG("tAC=%x", spd_read_byte(DIMM0 + i, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000567
Uwe Hermannd773fd32010-11-20 20:23:08 +0000568 if (spd_read_byte(DIMM0 + i, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
569 spd_read_byte(DIMM0 + i, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000570 PRINTK_DEBUG(": OK\n");
571 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000572 }
573
Stefan Reinauer278534d2008-10-29 04:51:07 +0000574 PRINTK_DEBUG(": Not fast enough!\n");
575
576 current_cas_mask &= ~(1 << (current_cas));
577 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000578
Stefan Reinauer278534d2008-10-29 04:51:07 +0000579 freq_cas_mask &= current_cas_mask;
580 if (!current_cas_mask) {
581 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
582 break;
583 }
584 }
585 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
586 if (freq_cas_mask) {
587 switch (j) {
588 case 0: sysinfo->memory_frequency = 400; break;
589 case 1: sysinfo->memory_frequency = 533; break;
590 case 2: sysinfo->memory_frequency = 667; break;
591 }
592 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
593 sysinfo->cas = 3;
594 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
595 sysinfo->cas = 4;
596 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
597 sysinfo->cas = 5;
598 }
599 break;
600 }
601 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000602
Stefan Reinauer278534d2008-10-29 04:51:07 +0000603 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000604 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000605 sysinfo->memory_frequency, sysinfo->cas);
606 } else {
607 die("Could not find common memory frequency and CAS\n");
608 }
609}
610
611static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
612{
613 int i;
614 int tRAS_time;
615 int tRAS_cycles;
616 int freq_multiplier = 0;
617
618 switch (sysinfo->memory_frequency) {
619 case 400: freq_multiplier = 0x14; break; /* 5ns */
620 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
621 case 667: freq_multiplier = 0x0c; break; /* 3ns */
622 }
623
624 tRAS_cycles = 4; /* 4 clocks minimum */
625 tRAS_time = tRAS_cycles * freq_multiplier;
626
627 for (i=0; i<2*DIMM_SOCKETS; i++) {
628 u8 reg8;
629
630 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
631 continue;
632
Uwe Hermannd773fd32010-11-20 20:23:08 +0000633 reg8 = spd_read_byte(DIMM0 + i, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000634 if (!reg8) {
635 die("Invalid tRAS value.\n");
636 }
637
638 while ((tRAS_time >> 2) < reg8) {
639 tRAS_time += freq_multiplier;
640 tRAS_cycles++;
641 }
642 }
643 if(tRAS_cycles > 0x18) {
644 die("DDR-II Module does not support this frequency (tRAS error)\n");
645 }
646
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000647 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000648 sysinfo->tras = tRAS_cycles;
649}
650
651static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
652{
653 int i;
654 int tRP_time;
655 int tRP_cycles;
656 int freq_multiplier = 0;
657
658 switch (sysinfo->memory_frequency) {
659 case 400: freq_multiplier = 0x14; break; /* 5ns */
660 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
661 case 667: freq_multiplier = 0x0c; break; /* 3ns */
662 }
663
664 tRP_cycles = 2; /* 2 clocks minimum */
665 tRP_time = tRP_cycles * freq_multiplier;
666
667 for (i=0; i<2*DIMM_SOCKETS; i++) {
668 u8 reg8;
669
670 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
671 continue;
672
Uwe Hermannd773fd32010-11-20 20:23:08 +0000673 reg8 = spd_read_byte(DIMM0 + i, SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000674 if (!reg8) {
675 die("Invalid tRP value.\n");
676 }
677
678 while (tRP_time < reg8) {
679 tRP_time += freq_multiplier;
680 tRP_cycles++;
681 }
682 }
683
684 if(tRP_cycles > 6) {
685 die("DDR-II Module does not support this frequency (tRP error)\n");
686 }
687
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000688 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000689 sysinfo->trp = tRP_cycles;
690}
691
692static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
693{
694 int i;
695 int tRCD_time;
696 int tRCD_cycles;
697 int freq_multiplier = 0;
698
699 switch (sysinfo->memory_frequency) {
700 case 400: freq_multiplier = 0x14; break; /* 5ns */
701 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
702 case 667: freq_multiplier = 0x0c; break; /* 3ns */
703 }
704
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000705 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000706 tRCD_time = tRCD_cycles * freq_multiplier;
707
708 for (i=0; i<2*DIMM_SOCKETS; i++) {
709 u8 reg8;
710
711 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
712 continue;
713
Uwe Hermannd773fd32010-11-20 20:23:08 +0000714 reg8 = spd_read_byte(DIMM0 + i, SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000715 if (!reg8) {
716 die("Invalid tRCD value.\n");
717 }
718
719 while (tRCD_time < reg8) {
720 tRCD_time += freq_multiplier;
721 tRCD_cycles++;
722 }
723 }
724 if(tRCD_cycles > 6) {
725 die("DDR-II Module does not support this frequency (tRCD error)\n");
726 }
727
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000728 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000729 sysinfo->trcd = tRCD_cycles;
730}
731
732static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
733{
734 int i;
735 int tWR_time;
736 int tWR_cycles;
737 int freq_multiplier = 0;
738
739 switch (sysinfo->memory_frequency) {
740 case 400: freq_multiplier = 0x14; break; /* 5ns */
741 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
742 case 667: freq_multiplier = 0x0c; break; /* 3ns */
743 }
744
745 tWR_cycles = 2; /* 2 clocks minimum */
746 tWR_time = tWR_cycles * freq_multiplier;
747
748 for (i=0; i<2*DIMM_SOCKETS; i++) {
749 u8 reg8;
750
751 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
752 continue;
753
Uwe Hermannd773fd32010-11-20 20:23:08 +0000754 reg8 = spd_read_byte(DIMM0 + i, SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000755 if (!reg8) {
756 die("Invalid tWR value.\n");
757 }
758
759 while (tWR_time < reg8) {
760 tWR_time += freq_multiplier;
761 tWR_cycles++;
762 }
763 }
764 if(tWR_cycles > 5) {
765 die("DDR-II Module does not support this frequency (tWR error)\n");
766 }
767
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000768 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000769 sysinfo->twr = tWR_cycles;
770}
771
772static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
773{
774 int i, index = 0;
775
776 const u8 tRFC_cycles[] = {
777 /* 75 105 127.5 */
778 15, 21, 26, /* DDR2-400 */
779 20, 28, 34, /* DDR2-533 */
780 25, 35, 43 /* DDR2-667 */
781 };
782
783 for (i=0; i<2*DIMM_SOCKETS; i++) {
784 u8 reg8;
785
786 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
787 continue;
788
789 reg8 = sysinfo->banksize[i*2];
790 switch (reg8) {
791 case 0x04: reg8 = 0; break;
792 case 0x08: reg8 = 1; break;
793 case 0x10: reg8 = 2; break;
794 case 0x20: reg8 = 3; break;
795 }
796
797 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
798 reg8++;
799
800 if (reg8 > 3) {
801 /* Can this happen? Go back to 127.5ns just to be sure
802 * we don't run out of the array. This may be wrong
803 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000804 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000805 reg8 = 3;
806 }
807
808 if (reg8 > index)
809 index = reg8;
810
811 }
812 index--;
813 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000814 case 667: index += 3; /* Fallthrough */
815 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000816 case 400: break;
817 }
818
819 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000820 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000821}
822
Stefan Reinauer278534d2008-10-29 04:51:07 +0000823static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
824{
825 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000826
Stefan Reinauer278534d2008-10-29 04:51:07 +0000827 sysinfo->refresh = 0;
828
829 for (i=0; i<2*DIMM_SOCKETS; i++) {
830 int refresh;
831
832 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
833 continue;
834
Uwe Hermannd773fd32010-11-20 20:23:08 +0000835 refresh = spd_read_byte(DIMM0 + i, SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000836
837 /* 15.6us */
838 if (!refresh)
839 continue;
840
841 /* Refresh is slower than 15.6us, use 15.6us */
842 if (refresh > 2)
843 continue;
844
845 if (refresh == 2) {
846 sysinfo->refresh = 1;
847 break;
848 }
849
850 die("DDR-II module has unsupported refresh value\n");
851 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000852 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000853}
854
855static void sdram_verify_burst_length(struct sys_info * sysinfo)
856{
857 int i;
858
859 for (i=0; i<2*DIMM_SOCKETS; i++) {
860 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
861 continue;
862
Uwe Hermannd773fd32010-11-20 20:23:08 +0000863 if (!(spd_read_byte(DIMM0 + i, SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000864 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
865 }
866}
867
868static void sdram_program_dram_width(struct sys_info * sysinfo)
869{
870 u16 c0dramw=0, c1dramw=0;
871 int idx;
872
873 if (sysinfo->dual_channel)
874 idx = 2;
875 else
876 idx = 1;
877
878 switch (sysinfo->dimm[0]) {
879 case 0: c0dramw = 0x0000; break; /* x16DS */
880 case 1: c0dramw = 0x0001; break; /* x8DS */
881 case 2: c0dramw = 0x0000; break; /* x16SS */
882 case 3: c0dramw = 0x0005; break; /* x8DDS */
883 case 4: c0dramw = 0x0000; break; /* NC */
884 }
885
886 switch (sysinfo->dimm[idx]) {
887 case 0: c1dramw = 0x0000; break; /* x16DS */
888 case 1: c1dramw = 0x0010; break; /* x8DS */
889 case 2: c1dramw = 0x0000; break; /* x16SS */
890 case 3: c1dramw = 0x0050; break; /* x8DDS */
891 case 4: c1dramw = 0x0000; break; /* NC */
892 }
893
894 if ( !sdram_capabilities_dual_channel() ) {
895 /* Single Channel */
896 c0dramw |= c1dramw;
897 c1dramw = 0;
898 }
899
900 MCHBAR16(C0DRAMW) = c0dramw;
901 MCHBAR16(C1DRAMW) = c1dramw;
902}
903
904static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
905{
906 int i;
907
908 for (i=0; i<16; i++)
909 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
910}
911
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000912static const u32 dq2030[] = {
913 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
914 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
915 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
916 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
917};
918
919static const u32 dq2330[] = {
920 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
921 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
922 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
923 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
924};
925
926static const u32 cmd2710[] = {
927 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
928 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
929 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
930 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
931};
932
933static const u32 cmd3210[] = {
934 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
935 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
936 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
937 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
938};
939
940static const u32 clk2030[] = {
941 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
942 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
943 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
944 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
945};
946
947static const u32 ctl3215[] = {
948 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
949 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
950 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
951 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
952};
953
954static const u32 ctl3220[] = {
955 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
956 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
957 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
958 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
959};
960
961static const u32 nc[] = {
962 0x00000000, 0x00000000, 0x00000000, 0x00000000,
963 0x00000000, 0x00000000, 0x00000000, 0x00000000,
964 0x00000000, 0x00000000, 0x00000000, 0x00000000,
965 0x00000000, 0x00000000, 0x00000000, 0x00000000
966};
967
968enum {
969 DQ2030,
970 DQ2330,
971 CMD2710,
972 CMD3210,
973 CLK2030,
974 CTL3215,
975 CTL3220,
976 NC,
977};
978
979static const u8 dual_channel_slew_group_lookup[] = {
980 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
981 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
982 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
983 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
984 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
985
986 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
987 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
988 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
989 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
990 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
991
992 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
993 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
994 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
995 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
996 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
997
998 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
999 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1000 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
1001 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
1002 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
1003
1004 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1005 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1006 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1007 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
1008};
1009
1010static const u8 single_channel_slew_group_lookup[] = {
1011 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1012 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1013 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1014 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1015 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1016
1017 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1018 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1019 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1020 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1021 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1022
1023 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1024 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1025 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1026 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1027 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1028
1029 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1030 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1031 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1032 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1033 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1034
1035 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1036 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1037 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1038 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1039};
1040
1041static const u32 *slew_group_lookup(int dual_channel, int index)
1042{
1043 const u8 *slew_group;
1044 /* Dual Channel needs different tables. */
1045 if (dual_channel)
1046 slew_group = dual_channel_slew_group_lookup;
1047 else
1048 slew_group = single_channel_slew_group_lookup;
1049
1050 switch (slew_group[index]) {
1051 case DQ2030: return dq2030;
1052 case DQ2330: return dq2330;
1053 case CMD2710: return cmd2710;
1054 case CMD3210: return cmd3210;
1055 case CLK2030: return clk2030;
1056 case CTL3215: return ctl3215;
1057 case CTL3220: return ctl3220;
1058 case NC: return nc;
1059 }
1060
1061 return nc;
1062}
1063
Peter Stugee4bc0f62010-10-01 09:13:18 +00001064#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001065/* Strength multiplier tables */
1066static const u8 dual_channel_strength_multiplier[] = {
1067 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1068 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1069 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1070 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1071 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1072 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1073 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1074 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1075 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1076 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1077 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1078 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1079 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1080 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1081 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1082 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1083 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1084 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1085 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1086 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1088 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1089 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1090 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1091};
1092
1093static const u8 single_channel_strength_multiplier[] = {
1094 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1095 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1096 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1097 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1098 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1099 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1100 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1101 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1102 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1103 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1104 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1105 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1106 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1107 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1108 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1109 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1110 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1111 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1112 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1113 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1114 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1115 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1116 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1117 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1118};
Peter Stugee4bc0f62010-10-01 09:13:18 +00001119#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001120static const u8 dual_channel_strength_multiplier[] = {
1121 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1122 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1123 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1124 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1125 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1126 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1127 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1128 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1129 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1130 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1131 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1132 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1133 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1134 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1135 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1136 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1137 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1138 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1139 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1140 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1141 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1142 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1143 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1144 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1145};
1146
1147static const u8 single_channel_strength_multiplier[] = {
1148 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1149 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1150 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1151 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1152 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1153 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1154 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1155 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1156 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1157 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1158 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1159 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1160 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1161 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1162 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1163 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1164 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1165 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1166 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1167 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1168 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1169 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1170 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1171 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1172};
1173#endif
1174
Stefan Reinauer278534d2008-10-29 04:51:07 +00001175static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1176{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001177 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001178 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001179
1180 /* Set Strength Multipliers */
1181
1182 /* Dual Channel needs different tables. */
1183 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001184 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001185 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001186 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001187 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1188 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001189 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001190 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001191 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001192 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1193 }
1194
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001195 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001196
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001197 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1198 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1199 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1200 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1201 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1202 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1203 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1204 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001205
1206 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001207 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1208 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1209 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001210
Stefan Reinauer278534d2008-10-29 04:51:07 +00001211 sdram_write_slew_rates(G3SRPUT, ctl3220);
1212 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001213 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001214 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001215 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1216 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1217 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001218
1219 /* Channel 1 */
1220 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001221 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1222 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001223 } else {
1224 sdram_write_slew_rates(G7SRPUT, nc);
1225 sdram_write_slew_rates(G8SRPUT, nc);
1226 }
1227}
1228
1229static void sdram_enable_rcomp(void)
1230{
1231 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001232 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001233 udelay(300);
1234 reg32 = MCHBAR32(GBRCOMPCTL);
1235 reg32 &= ~(1 << 23);
1236 MCHBAR32(GBRCOMPCTL) = reg32;
1237}
1238
1239static void sdram_program_dll_timings(struct sys_info *sysinfo)
1240{
1241 u32 chan0dll = 0, chan1dll = 0;
1242 int i;
1243
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001244 printk(BIOS_DEBUG, "Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001245
Stefan Reinauer278534d2008-10-29 04:51:07 +00001246 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1247 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1248
1249 /* We drive both channels with the same speed */
1250 switch (sysinfo->memory_frequency) {
1251 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1252 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1253 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1254 }
1255
1256 for (i=0; i < 4; i++) {
1257 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1258 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1259 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1260 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1261 }
1262}
1263
1264static void sdram_force_rcomp(void)
1265{
1266 u32 reg32;
1267 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001268
Stefan Reinauer278534d2008-10-29 04:51:07 +00001269 reg32 = MCHBAR32(ODTC);
1270 reg32 |= (1 << 28);
1271 MCHBAR32(ODTC) = reg32;
1272
1273 reg32 = MCHBAR32(SMSRCTL);
1274 reg32 |= (1 << 0);
1275 MCHBAR32(SMSRCTL) = reg32;
1276
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001277 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001278 reg32 = MCHBAR32(GBRCOMPCTL);
1279 reg32 |= (1 << 8);
1280 MCHBAR32(GBRCOMPCTL) = reg32;
1281
1282 reg8 = i945_silicon_revision();
1283 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001284
Stefan Reinauer278534d2008-10-29 04:51:07 +00001285 reg32 = MCHBAR32(GBRCOMPCTL);
1286 reg32 |= (3 << 5);
1287 MCHBAR32(GBRCOMPCTL) = reg32;
1288 }
1289}
1290
1291static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1292{
1293 u8 reg8;
1294 u32 reg32;
1295
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001296 printk(BIOS_DEBUG, "Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001297 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001298 reg8 = MCHBAR8(C0HCTC);
1299 reg8 &= ~0x1f;
1300 reg8 |= ( 1 << 0);
1301 MCHBAR8(C0HCTC) = reg8;
1302
1303 reg8 = MCHBAR8(C1HCTC);
1304 reg8 &= ~0x1f;
1305 reg8 |= ( 1 << 0);
1306 MCHBAR8(C1HCTC) = reg8;
1307
Stefan Reinauer278534d2008-10-29 04:51:07 +00001308 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1309 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1310
1311 MCHBAR8(C0WDLLCMC) = 0;
1312 MCHBAR8(C1WDLLCMC) = 0;
1313
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001314 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001315 sdram_program_dram_width(sysinfo);
1316
1317 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1318
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001319 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001320 reg32 = MCHBAR32(GBRCOMPCTL);
1321 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1322 reg32 |= (3 << 27) | (3 << 0);
1323 MCHBAR32(GBRCOMPCTL) = reg32;
1324
1325 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1326
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001327 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001328 sdram_program_dll_timings(sysinfo);
1329
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001330 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001331 sdram_force_rcomp();
1332}
1333
1334static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1335{
1336 u32 reg32;
1337
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001338 printk(BIOS_DEBUG, "Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001339
Stefan Reinauer278534d2008-10-29 04:51:07 +00001340 reg32 = MCHBAR32(RCVENMT);
1341 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001342 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001343
1344 reg32 |= (1 << 11) | (1 << 9);
1345 MCHBAR32(RCVENMT) = reg32;
1346
1347 reg32 = MCHBAR32(DRTST);
1348 reg32 |= (1 << 3) | (1 << 2);
1349 MCHBAR32(DRTST) = reg32;
1350
1351 reg32 = MCHBAR32(DRTST);
1352 reg32 |= (1 << 6) | (1 << 4);
1353 MCHBAR32(DRTST) = reg32;
1354
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001355 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001356
1357 reg32 = MCHBAR32(DRTST);
1358
1359 /* Is channel 0 populated? */
1360 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1361 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1362 reg32 |= (1 << 7) | (1 << 5);
1363 else
1364 reg32 |= (1 << 31);
1365
1366 /* Is channel 1 populated? */
1367 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1368 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1369 reg32 |= (1 << 9) | (1 << 8);
1370 else
1371 reg32 |= (1 << 30);
1372
1373 MCHBAR32(DRTST) = reg32;
1374
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001375 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001376 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1377 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1378 reg32 = MCHBAR32(C0DRC1);
1379 reg32 |= (1 << 8);
1380 MCHBAR32(C0DRC1) = reg32;
1381 }
1382 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1383 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1384 reg32 = MCHBAR32(C1DRC1);
1385 reg32 |= (1 << 8);
1386 MCHBAR32(C1DRC1) = reg32;
1387 }
1388}
1389
1390struct dimm_size {
1391 unsigned long side1;
1392 unsigned long side2;
1393};
1394
1395static struct dimm_size sdram_get_dimm_size(u16 device)
1396{
1397 /* Calculate the log base 2 size of a DIMM in bits */
1398 struct dimm_size sz;
1399 int value, low, rows, columns;
1400
1401 sz.side1 = 0;
1402 sz.side2 = 0;
1403
1404 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1405 if (rows < 0) goto hw_err;
1406 if ((rows & 0xf) == 0) goto val_err;
1407 sz.side1 += rows & 0xf;
1408
1409 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1410 if (columns < 0) goto hw_err;
1411 if ((columns & 0xf) == 0) goto val_err;
1412 sz.side1 += columns & 0xf;
1413
1414 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1415 if (value < 0) goto hw_err;
1416 if ((value & 0xff) == 0) goto val_err;
1417 sz.side1 += log2(value & 0xff);
1418
1419 /* Get the module data width and convert it to a power of two */
1420 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1421 if (value < 0) goto hw_err;
1422 value &= 0xff;
1423 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001424
Stefan Reinauer278534d2008-10-29 04:51:07 +00001425 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1426 if (low < 0) goto hw_err;
1427 value = value | (low & 0xff);
1428 if ((value != 72) && (value != 64)) goto val_err;
1429 sz.side1 += log2(value);
1430
1431 /* side 2 */
1432 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1433
1434 if (value < 0) goto hw_err;
1435 value &= 7;
1436 value++;
1437 if (value == 1) goto out;
1438 if (value != 2) goto val_err;
1439
1440 /* Start with the symmetrical case */
1441 sz.side2 = sz.side1;
1442
1443 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1444
1445 /* Don't die here, I have not come across any of these to test what
1446 * actually happens.
1447 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001448 printk(BIOS_ERR, "Assymetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001449
1450 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1451 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1452
1453 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1454 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1455
1456 goto out;
1457
1458 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001459 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001460 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001461 /* If a hardware error occurs the spd rom probably does not exist.
1462 * In this case report that there is no memory
1463 */
1464 sz.side1 = 0;
1465 sz.side2 = 0;
1466 out:
1467 return sz;
1468}
1469
1470static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1471{
1472 int i;
1473
1474 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1475 struct dimm_size sz;
1476
1477 sysinfo->banksize[i * 2] = 0;
1478 sysinfo->banksize[(i * 2) + 1] = 0;
1479
1480 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1481 continue;
1482
Uwe Hermannd773fd32010-11-20 20:23:08 +00001483 sz = sdram_get_dimm_size(DIMM0 + i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001484
Uwe Hermannd773fd32010-11-20 20:23:08 +00001485 sysinfo->banks[i] = spd_read_byte(DIMM0 + i, SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001486
1487 if (sz.side1 < 30)
1488 die("DDR-II rank size smaller than 128MB is not supported.\n");
1489
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001490 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001491
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001492 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001493
Stefan Reinauer278534d2008-10-29 04:51:07 +00001494 if (!sz.side2)
1495 continue;
1496
1497 /* If there is a second side, it has to have at least 128M, too */
1498 if (sz.side2 < 30)
1499 die("DDR-II rank size smaller than 128MB is not supported.\n");
1500
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001501 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001502
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001503 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001504 }
1505}
1506
1507static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1508{
1509 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001510 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001511
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001512 printk(BIOS_DEBUG, "Setting RAM size... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001513
1514 cum0 = 0;
1515 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001516 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001517 MCHBAR8(C0DRB0+i) = cum0;
1518 }
1519
1520 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1521 cum1 = cum0;
1522
1523 /* Exception: Interleaved starts from the beginning */
1524 if (sysinfo->interleaved)
1525 cum1 = 0;
1526
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001527#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001528 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1529 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1530 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1531 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001532#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001533
1534 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001535 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001536 MCHBAR8(C1DRB0+i) = cum1;
1537 }
1538
1539 /* Set TOLUD Top Of Low Usable DRAM */
1540 if (sysinfo->interleaved)
1541 tolud = (cum0 + cum1) << 1;
1542 else
1543 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001544
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001545 /* The TOM register has a different format */
1546 tom = tolud >> 3;
1547
1548 /* Limit the value of TOLUD to leave some space for PCI memory. */
1549 if (tolud > 0xd0)
1550 tolud = 0xd0; /* 3.25GB : 0.75GB */
1551
1552 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1553
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001554 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1555 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1556 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001557
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001558 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001559
1560 return 0;
1561}
1562
Stefan Reinauer278534d2008-10-29 04:51:07 +00001563static int sdram_set_row_attributes(struct sys_info *sysinfo)
1564{
1565 int i, value;
1566 u16 dra0=0, dra1=0, dra = 0;
1567
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001568 printk(BIOS_DEBUG, "Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001569 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1570 u16 device;
1571 u8 columnsrows;
1572
1573 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1574 continue;
1575 }
1576
Uwe Hermannd773fd32010-11-20 20:23:08 +00001577 device = DIMM0 + i;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001578
1579 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1580 columnsrows = (value & 0x0f);
1581
1582 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1583 columnsrows |= (value & 0xf) << 4;
1584
1585 switch (columnsrows) {
1586 case 0x9d: dra = 2; break;
1587 case 0xad: dra = 3; break;
1588 case 0xbd: dra = 4; break;
1589 case 0xae: dra = 3; break;
1590 case 0xbe: dra = 4; break;
1591 default: die("Unsupported Rows/Columns. (DRA)");
1592 }
1593
1594 /* Double Sided DIMMs? */
1595 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1596 dra = (dra << 4) | dra;
1597 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001598
Stefan Reinauer278534d2008-10-29 04:51:07 +00001599 if (i < DIMM_SOCKETS)
1600 dra0 |= (dra << (i*8));
1601 else
1602 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1603 }
1604
1605 MCHBAR16(C0DRA0) = dra0;
1606 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001607
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001608 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1609 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001610
1611 return 0;
1612}
1613
1614static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1615{
1616 u32 off32;
1617 int i;
1618
1619 MCHBAR16(C1BNKARC) &= 0xff00;
1620 MCHBAR16(C0BNKARC) &= 0xff00;
1621
1622 off32 = C0BNKARC;
1623 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1624 /* Switch to second channel */
1625 if (i == DIMM_SOCKETS)
1626 off32 = C1BNKARC;
1627
1628 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1629 continue;
1630
1631 if (sysinfo->banks[i] != 8)
1632 continue;
1633
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001634 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001635
1636 if (i & 1)
1637 MCHBAR16(off32) |= 0x50;
1638 else
1639 MCHBAR16(off32) |= 0x05;
1640 }
1641}
1642
1643#define REFRESH_7_8US 1
1644#define REFRESH_15_6US 0
1645static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1646{
1647 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001648
Stefan Reinauer278534d2008-10-29 04:51:07 +00001649 if (sysinfo->refresh == REFRESH_7_8US) {
1650 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1651 } else {
1652 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1653 }
1654
1655 MCHBAR32(C0DRC0) &= ~(7 << 8);
1656 MCHBAR32(C0DRC0) |= reg32;
1657
1658 MCHBAR32(C1DRC0) &= ~(7 << 8);
1659 MCHBAR32(C1DRC0) |= reg32;
1660}
1661
1662static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1663{
1664 u32 reg32;
1665 int i;
1666
1667 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001668
Stefan Reinauer278534d2008-10-29 04:51:07 +00001669 for (i=0; i < 4; i++) {
1670 if (sysinfo->banksize[i] == 0) {
1671 reg32 |= (1 << (16 + i));
1672 }
1673 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001674
Stefan Reinauer278534d2008-10-29 04:51:07 +00001675 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001676
Stefan Reinauer278534d2008-10-29 04:51:07 +00001677 reg32 |= (1 << 11);
1678 MCHBAR32(C0DRC1) = reg32;
1679
1680 /* Do we have to do this if we're in Single Channel Mode? */
1681 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001682
Stefan Reinauer278534d2008-10-29 04:51:07 +00001683 for (i=4; i < 8; i++) {
1684 if (sysinfo->banksize[i] == 0) {
1685 reg32 |= (1 << (12 + i));
1686 }
1687 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001688
Stefan Reinauer278534d2008-10-29 04:51:07 +00001689 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001690
Stefan Reinauer278534d2008-10-29 04:51:07 +00001691 reg32 |= (1 << 11);
1692 MCHBAR32(C1DRC1) = reg32;
1693}
1694
1695static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1696{
1697 u32 reg32;
1698 int i;
1699
1700 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001701
Stefan Reinauer278534d2008-10-29 04:51:07 +00001702 for (i=0; i < 4; i++) {
1703 if (sysinfo->banksize[i] == 0) {
1704 reg32 |= (1 << (24 + i));
1705 }
1706 }
1707 MCHBAR32(C0DRC2) = reg32;
1708
1709 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001710
Stefan Reinauer278534d2008-10-29 04:51:07 +00001711 for (i=4; i < 8; i++) {
1712 if (sysinfo->banksize[i] == 0) {
1713 reg32 |= (1 << (20 + i));
1714 }
1715 }
1716 MCHBAR32(C1DRC2) = reg32;
1717}
1718
1719static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1720{
1721 u32 reg32, off32;
1722 u32 tWTR;
1723 u32 temp_drt;
1724 int i, page_size;
1725
1726 static const u8 const drt0_table[] = {
1727 /* CL 3, 4, 5 */
1728 3, 4, 5, /* FSB533/400, DDR533/400 */
1729 4, 5, 6, /* FSB667, DDR533/400 */
1730 4, 5, 6, /* FSB667, DDR667 */
1731 };
1732
1733 static const u8 const cas_table[] = {
1734 2, 1, 0, 3
1735 };
1736
1737 reg32 = MCHBAR32(C0DRC0);
1738 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001739 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001740 MCHBAR32(C0DRC0) = reg32;
1741
1742 reg32 = MCHBAR32(C1DRC0);
1743 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001744 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001745 MCHBAR32(C1DRC0) = reg32;
1746
1747 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1748 SYSINFO_DIMM_NOT_POPULATED) {
1749 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001750 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001751 MCHBAR32(C0DRC0) = reg32;
1752 }
1753
1754 sdram_program_refresh_rate(sysinfo);
1755
1756 sdram_program_cke_tristate(sysinfo);
1757
1758 sdram_program_odt_tristate(sysinfo);
1759
1760 /* Calculate DRT0 */
1761
1762 temp_drt = 0;
1763
1764 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1765 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1766 temp_drt |= (reg32 << 28);
1767
1768 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1769 reg32 += sysinfo->trp;
1770 temp_drt |= (reg32 << 4);
1771
1772 if (sysinfo->memory_frequency == 667) {
1773 tWTR = 3; /* 667MHz */
1774 } else {
1775 tWTR = 2; /* 400 and 533 */
1776 }
1777
1778 /* B2B Write to Read Command Spacing */
1779 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1780 temp_drt |= (reg32 << 24);
1781
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001782 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001783 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1784
1785 /* Program Write Auto Precharge to Activate */
1786 off32 = 0;
1787 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1788 off32 += 3;
1789 }
1790 if (sysinfo->memory_frequency == 667) {
1791 off32 += 3;
1792 }
1793 off32 += sysinfo->cas - 3;
1794 reg32 = drt0_table[off32];
1795 temp_drt |= (reg32 << 11);
1796
1797 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001798
Stefan Reinauer278534d2008-10-29 04:51:07 +00001799 temp_drt |= (8 << 0);
1800
1801 MCHBAR32(C0DRT0) = temp_drt;
1802 MCHBAR32(C1DRT0) = temp_drt;
1803
1804 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001805
Stefan Reinauer278534d2008-10-29 04:51:07 +00001806 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1807
1808 /* DRAM RASB Precharge */
1809 temp_drt |= (sysinfo->trp - 2) << 0;
1810
1811 /* DRAM RASB to CASB Delay */
1812 temp_drt |= (sysinfo->trcd - 2) << 4;
1813
1814 /* CASB Latency */
1815 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1816
1817 /* Refresh Cycle Time */
1818 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001819
Stefan Reinauer278534d2008-10-29 04:51:07 +00001820 /* Pre-All to Activate Delay */
1821 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001822
Stefan Reinauer278534d2008-10-29 04:51:07 +00001823 /* Precharge to Precharge Delay stays at 1 clock */
1824 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001825
Stefan Reinauer278534d2008-10-29 04:51:07 +00001826 /* Activate to Precharge Delay */
1827 temp_drt |= (sysinfo->tras << 19);
1828
1829 /* Read to Precharge (tRTP) */
1830 if (sysinfo->memory_frequency == 667) {
1831 temp_drt |= (1 << 28);
1832 } else {
1833 temp_drt |= (0 << 28);
1834 }
1835
1836 /* Determine page size */
1837 reg32 = 0;
1838 page_size = 1; /* Default: 1k pagesize */
1839 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1840 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1841 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1842 page_size = 2; /* 2k pagesize */
1843 }
1844
1845 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1846 reg32 = 1;
1847 }
1848 if (sysinfo->memory_frequency == 667) {
1849 reg32 = page_size;
1850 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001851
Stefan Reinauer278534d2008-10-29 04:51:07 +00001852 temp_drt |= (reg32 << 30);
1853
1854 MCHBAR32(C0DRT1) = temp_drt;
1855 MCHBAR32(C1DRT1) = temp_drt;
1856
1857 /* Program DRT2 */
1858 reg32 = MCHBAR32(C0DRT2);
1859 reg32 &= ~(1 << 8);
1860 MCHBAR32(C0DRT2) = reg32;
1861
1862 reg32 = MCHBAR32(C1DRT2);
1863 reg32 &= ~(1 << 8);
1864 MCHBAR32(C1DRT2) = reg32;
1865
1866 /* Calculate DRT3 */
1867 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1868
1869 /* Get old tRFC value */
1870 reg32 = MCHBAR32(C0DRT1) >> 10;
1871 reg32 &= 0x3f;
1872
1873 /* 788nS - tRFC */
1874 switch (sysinfo->memory_frequency) {
1875 case 400: /* 5nS */
1876 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1877 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1878 break;
1879 case 533: /* 3.75nS */
1880 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1881 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1882 break;
1883 case 667: /* 3nS */
1884 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1885 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1886 break;
1887 }
1888
1889 temp_drt |= reg32;
1890
1891 MCHBAR32(C0DRT3) = temp_drt;
1892 MCHBAR32(C1DRT3) = temp_drt;
1893}
1894
1895static void sdram_set_channel_mode(struct sys_info *sysinfo)
1896{
1897 u32 reg32;
1898
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001899 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001900
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001901 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001902 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1903 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1904 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1905 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1906 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001907 sysinfo->interleaved = 1;
1908 } else {
1909 sysinfo->interleaved = 0;
1910 }
1911
1912 reg32 = MCHBAR32(DCC);
1913 reg32 &= ~(7 << 0);
1914
1915 if(sysinfo->interleaved) {
1916 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001917 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001918 reg32 |= (1 << 1);
1919 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1920 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1921 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001922 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001923 reg32 |= (1 << 2);
1924 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1925 SYSINFO_DIMM_NOT_POPULATED) {
1926 /* Dual Channel Assymetric */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001927 printk(BIOS_DEBUG, "Dual Channel Assymetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001928 reg32 |= (1 << 0);
1929 } else {
1930 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001931 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001932 }
1933
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001934 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001935 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001936
1937 MCHBAR32(DCC) = reg32;
1938
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001939 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001940}
1941
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001942static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001943{
1944 volatile u16 reg16;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001945
1946 MCHBAR32(PLLMON) = 0x80800000;
1947
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001948 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001949 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001950 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001951
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001952 /* Program CPCTL according to FSB speed */
1953 /* Only write the lower byte */
1954 switch (sysinfo->fsb_frequency) {
1955 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1956 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1957 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1958 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001959
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001960 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001961
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001962 reg16 = MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001963}
1964
1965static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1966{
1967 u8 reg8;
1968 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001969 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001970
1971#define CRCLK_166MHz 0x00
1972#define CRCLK_200MHz 0x01
1973#define CRCLK_250MHz 0x03
1974#define CRCLK_400MHz 0x05
1975
1976#define CDCLK_200MHz 0x00
1977#define CDCLK_320MHz 0x40
1978
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001979#define VOLTAGE_1_05 0x00
1980#define VOLTAGE_1_50 0x01
1981
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001982 printk(BIOS_DEBUG, "Setting Graphics Frequency... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001983
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001984 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001985
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001986 voltage = VOLTAGE_1_05;
1987 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1988 voltage = VOLTAGE_1_50;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001989 printk(BIOS_DEBUG, "Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001990
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001991 /* Gate graphics hardware for frequency change */
1992 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
1993 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
1994 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001995
1996 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001997 reg8 = sdram_capabilities_core_frequencies();
1998
Stefan Reinauer278534d2008-10-29 04:51:07 +00001999 freq = CRCLK_250MHz;
2000 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002001 case GFX_FREQUENCY_CAP_ALL:
2002 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002003 freq = CRCLK_250MHz;
2004 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002005 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002006 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002007 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2008 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2009 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002010 }
2011
2012 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002013 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002014 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
2015 if (reg8==2)
2016 freq = CRCLK_166MHz;
2017 }
2018
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002019 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002020 switch (freq) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002021 case CRCLK_166MHz: printk(BIOS_DEBUG, "166Mhz"); break;
2022 case CRCLK_200MHz: printk(BIOS_DEBUG, "200Mhz"); break;
2023 case CRCLK_250MHz: printk(BIOS_DEBUG, "250Mhz"); break;
2024 case CRCLK_400MHz: printk(BIOS_DEBUG, "400Mhz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002025 }
2026
Stefan Reinauer278534d2008-10-29 04:51:07 +00002027 if (i945_silicon_revision() == 0) {
2028 sysinfo->mvco4x = 1;
2029 } else {
2030 sysinfo->mvco4x = 0;
2031 }
2032
Stefan Reinauer278534d2008-10-29 04:51:07 +00002033 second_vco = 0;
2034
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002035 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002036 second_vco = 1;
2037 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2038 u16 mem = sysinfo->memory_frequency;
2039 u16 fsb = sysinfo->fsb_frequency;
2040
2041 if ( (fsb == 667 && mem == 533) ||
2042 (fsb == 533 && mem == 533) ||
2043 (fsb == 533 && mem == 400)) {
2044 second_vco = 1;
2045 }
2046
2047 if (fsb == 667 && mem == 533)
2048 sysinfo->mvco4x = 1;
2049 }
2050
2051 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002052 sysinfo->clkcfg_bit7=1;
2053 } else {
2054 sysinfo->clkcfg_bit7=0;
2055 }
2056
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002057 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002058 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2059 reg16 &= ~( (7 << 0) | (1 << 13) );
2060 reg16 |= freq;
2061 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2062
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002063 /* Graphics Core Display Clock */
2064 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2065 reg8 &= ~( (1<<7) | (7<<4) );
2066
2067 if (voltage == VOLTAGE_1_05) {
2068 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002069 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002070 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002071 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002072 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002073 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002074 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002075
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002076 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002077
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002078 reg8 |= (1<<3) | (1<<1);
2079 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2080
2081 reg8 |= 0x0f;
2082 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2083
2084 /* Ungate core render and display clocks */
2085 reg8 &= 0xf0;
2086 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002087}
2088
2089static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2090{
2091 u32 clkcfg;
2092 u8 reg8;
2093
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002094 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002095
Stefan Reinauer278534d2008-10-29 04:51:07 +00002096 clkcfg = MCHBAR32(CLKCFG);
2097
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002098 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002099
2100 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2101
2102 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002103 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002104 clkcfg &= ~(1 << 12);
2105 }
2106
2107 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002108 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002109
Stefan Reinauer278534d2008-10-29 04:51:07 +00002110 clkcfg |= (1 << 7);
2111 }
2112
2113 switch (sysinfo->memory_frequency) {
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002114 case 400: clkcfg |= (2 << 4); break;
2115 case 533: clkcfg |= (3 << 4); break;
2116 case 667: clkcfg |= (4 << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002117 default: die("Target Memory Frequency Error");
2118 }
2119
2120 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002121 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002122 return;
2123 }
2124
2125 MCHBAR32(CLKCFG) = clkcfg;
2126
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002127 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002128 * cache before we execute it.
2129 */
2130 goto cache_code;
2131vco_update:
2132 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2133 reg8 &= ~(1 << 7);
2134 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2135
Stefan Reinauer278534d2008-10-29 04:51:07 +00002136 clkcfg &= ~(1 << 10);
2137 MCHBAR32(CLKCFG) = clkcfg;
2138 clkcfg |= (1 << 10);
2139 MCHBAR32(CLKCFG) = clkcfg;
2140
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002141 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002142 " movl $0x100, %%ecx\n"
2143 "delay_update:\n"
2144 " nop\n"
2145 " nop\n"
2146 " nop\n"
2147 " nop\n"
2148 " loop delay_update\n"
2149 : /* No outputs */
2150 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002151 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002152 );
2153
Stefan Reinauer278534d2008-10-29 04:51:07 +00002154 clkcfg &= ~(1 << 10);
2155 MCHBAR32(CLKCFG) = clkcfg;
2156
2157 goto out;
2158cache_code:
2159 goto vco_update;
2160out:
2161
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002162 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
2163 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002164}
2165
2166static void sdram_program_clock_crossing(void)
2167{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002168 int idx = 0;
2169
2170 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002171 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002172 */
Peter Stugee4bc0f62010-10-01 09:13:18 +00002173#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002174 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002175 0x00100401, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002176 0xffffffff, 0xffffffff, /* nonexistant */
2177 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002178
Stefan Reinauer278534d2008-10-29 04:51:07 +00002179 0x08040120, 0x00000000, /* DDR400 FSB533 */
2180 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002181 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002182
2183 0x04020120, 0x00000010, /* DDR400 FSB667 */
2184 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002185 0x00100401, 0x00000000, /* DDR667 FSB667 */
2186
2187 0xffffffff, 0xffffffff, /* nonexistant */
2188 0xffffffff, 0xffffffff, /* nonexistant */
2189 0xffffffff, 0xffffffff, /* nonexistant */
2190
2191 0xffffffff, 0xffffffff, /* nonexistant */
2192 0xffffffff, 0xffffffff, /* nonexistant */
2193 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002194 };
2195
2196 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002197 0x04020208, 0x00000000, /* DDR400 FSB400 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002198 0xffffffff, 0xffffffff, /* nonexistant */
2199 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002200
Stefan Reinauer278534d2008-10-29 04:51:07 +00002201 0x00060108, 0x00000000, /* DDR400 FSB533 */
2202 0x04020108, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002203 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002204
2205 0x00040318, 0x00000000, /* DDR400 FSB667 */
2206 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002207 0x02010804, 0x00000000, /* DDR667 FSB667 */
2208
2209 0xffffffff, 0xffffffff, /* nonexistant */
2210 0xffffffff, 0xffffffff, /* nonexistant */
2211 0xffffffff, 0xffffffff, /* nonexistant */
2212
2213 0xffffffff, 0xffffffff, /* nonexistant */
2214 0xffffffff, 0xffffffff, /* nonexistant */
2215 0xffffffff, 0xffffffff, /* nonexistant */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002216 };
2217
Peter Stugee4bc0f62010-10-01 09:13:18 +00002218#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002219 /* i945 G/P */
2220 static const u32 data_clock_crossing[] = {
2221 0xffffffff, 0xffffffff, /* nonexistant */
2222 0xffffffff, 0xffffffff, /* nonexistant */
2223 0xffffffff, 0xffffffff, /* nonexistant */
2224
2225 0x10080201, 0x00000000, /* DDR400 FSB533 */
2226 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002227 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002228
2229 0xffffffff, 0xffffffff, /* nonexistant */
2230 0xffffffff, 0xffffffff, /* nonexistant */
2231 0xffffffff, 0xffffffff, /* nonexistant */
2232
2233 0x04020108, 0x00000000, /* DDR400 FSB800 */
2234 0x00020108, 0x00000000, /* DDR533 FSB800 */
2235 0x00080201, 0x00000000, /* DDR667 FSB800 */
2236
2237 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2238 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2239 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2240 };
2241
2242 static const u32 command_clock_crossing[] = {
2243 0xffffffff, 0xffffffff, /* nonexistant */
2244 0xffffffff, 0xffffffff, /* nonexistant */
2245 0xffffffff, 0xffffffff, /* nonexistant */
2246
2247 0x00010800, 0x00000402, /* DDR400 FSB533 */
2248 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002249 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002250
2251 0xffffffff, 0xffffffff, /* nonexistant */
2252 0xffffffff, 0xffffffff, /* nonexistant */
2253 0xffffffff, 0xffffffff, /* nonexistant */
2254
2255 0x02010804, 0x00000000, /* DDR400 FSB800 */
2256 0x00010402, 0x00000000, /* DDR533 FSB800 */
2257 0x04020180, 0x00000008, /* DDR667 FSB800 */
2258
2259 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2260 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2261 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2262 };
2263#endif
2264
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002265 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002266
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002267 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002268 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002269 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2270 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2271 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2272 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002273 }
2274
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002275 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002276 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002277 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2278 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2279 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2280 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2281 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2282 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002283 }
2284
2285 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002286 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002287 }
2288
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002289 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2290 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2291
Stefan Reinauer278534d2008-10-29 04:51:07 +00002292 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2293 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2294 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2295 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2296
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002297 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002298}
2299
2300static void sdram_disable_fast_dispatch(void)
2301{
2302 u32 reg32;
2303
2304 reg32 = MCHBAR32(FSBPMC3);
2305 reg32 |= (1 << 1);
2306 MCHBAR32(FSBPMC3) = reg32;
2307
2308 reg32 = MCHBAR32(SBTEST);
2309 reg32 |= (3 << 1);
2310 MCHBAR32(SBTEST) = reg32;
2311}
2312
2313static void sdram_pre_jedec_initialization(void)
2314{
2315 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002316
Stefan Reinauer278534d2008-10-29 04:51:07 +00002317 reg32 = MCHBAR32(WCC);
2318 reg32 &= 0x113ff3ff;
2319 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2320 MCHBAR32(WCC) = reg32;
2321
2322 MCHBAR32(SMVREFC) |= (1 << 6);
2323
2324 MCHBAR32(MMARB0) &= ~(3 << 17);
2325 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2326
2327 MCHBAR32(MMARB1) &= ~(7 << 8);
2328 MCHBAR32(MMARB1) |= (3 << 8);
2329
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002330 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002331 MCHBAR32(C0AIT) = 0x000006c4;
2332 MCHBAR32(C0AIT+4) = 0x871a066d;
2333
2334 MCHBAR32(C1AIT) = 0x000006c4;
2335 MCHBAR32(C1AIT+4) = 0x871a066d;
2336}
2337
2338#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2339#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2340#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2341#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2342#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2343#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2344#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2345#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2346
2347static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2348{
2349 u32 chan0 = 0, chan1 = 0;
2350 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2351
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002352 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002353 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002354 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002355 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2356 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2357 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2358
2359 if (sdram_capabilities_enhanced_addressing_xor()) {
2360 if (!sysinfo->interleaved) {
2361 /* Single Channel & Dual Channel Assymetric */
2362 if (chan0_populated) {
2363 if (chan0_dualsided) {
2364 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2365 } else {
2366 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2367 }
2368 }
2369 if (chan1_populated) {
2370 if (chan1_dualsided) {
2371 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2372 } else {
2373 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2374 }
2375 }
2376 } else {
2377 /* Interleaved has always both channels populated */
2378 if (chan0_dualsided) {
2379 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2380 } else {
2381 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2382 }
2383
2384 if (chan1_dualsided) {
2385 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2386 } else {
2387 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2388 }
2389 }
2390 } else {
2391 if (!sysinfo->interleaved) {
2392 /* Single Channel & Dual Channel Assymetric */
2393 if (chan0_populated) {
2394 if (chan0_dualsided) {
2395 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2396 } else {
2397 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2398 }
2399 }
2400 if (chan1_populated) {
2401 if (chan1_dualsided) {
2402 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2403 } else {
2404 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2405 }
2406 }
2407 } else {
2408 /* Interleaved has always both channels populated */
2409 if (chan0_dualsided) {
2410 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2411 } else {
2412 chan0 = EA_DUALCHANNEL_BANK_MODE;
2413 }
2414
2415 if (chan1_dualsided) {
2416 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2417 } else {
2418 chan1 = EA_DUALCHANNEL_BANK_MODE;
2419 }
2420 }
2421 }
2422
2423 MCHBAR32(C0DRC1) &= 0x00ffffff;
2424 MCHBAR32(C0DRC1) |= chan0;
2425 MCHBAR32(C1DRC1) &= 0x00ffffff;
2426 MCHBAR32(C1DRC1) |= chan1;
2427}
2428
2429static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2430{
2431 u32 reg32;
2432
2433 /* Enable Channel XORing for Dual Channel Interleave */
2434 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002435
Stefan Reinauer278534d2008-10-29 04:51:07 +00002436 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002437#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002438 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002439 reg32 |= (1 << 9);
2440#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002441 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002442#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002443 MCHBAR32(DCC) = reg32;
2444 }
2445
2446 /* DRAM mode optimizations */
2447 sdram_enhanced_addressing_mode(sysinfo);
2448
2449 reg32 = MCHBAR32(FSBPMC3);
2450 reg32 &= ~(1 << 1);
2451 MCHBAR32(FSBPMC3) = reg32;
2452
2453 reg32 = MCHBAR32(SBTEST);
2454 reg32 &= ~(1 << 2);
2455 MCHBAR32(SBTEST) = reg32;
2456
2457 reg32 = MCHBAR32(SBOCC);
2458 reg32 &= 0xffbdb6ff;
2459 reg32 |= (0xbdb6 << 8) | (1 << 0);
2460 MCHBAR32(SBOCC) = reg32;
2461}
2462
2463static void sdram_power_management(struct sys_info *sysinfo)
2464{
2465 u8 reg8;
2466 u16 reg16;
2467 u32 reg32;
2468 int integrated_graphics = 1;
2469 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002470
Stefan Reinauer278534d2008-10-29 04:51:07 +00002471 reg32 = MCHBAR32(C0DRT2);
2472 reg32 &= 0xffffff00;
2473 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002474 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002475 MCHBAR32(C0DRT2) = reg32;
2476
2477 reg32 = MCHBAR32(C1DRT2);
2478 reg32 &= 0xffffff00;
2479 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002480 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002481 MCHBAR32(C1DRT2) = reg32;
2482
2483 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002484
2485 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002486 MCHBAR32(C0DRC1) = reg32;
2487
2488 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002489
2490 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002491 MCHBAR32(C1DRC1) = reg32;
2492
2493 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002494 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2495 u16 peg_bits = (1 << 5) | (1 << 0);
2496
2497 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002498 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002499 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2500 u16 peg_bits = (1 << 5) | (1 << 0);
2501
Stefan Reinauer278534d2008-10-29 04:51:07 +00002502 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002503 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002504 }
2505
2506 reg16 = MCHBAR16(UPMC2);
2507 reg16 &= 0xfc00;
2508 reg16 |= 0x0100;
2509 MCHBAR16(UPMC2) = reg16;
2510
2511 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002512
Stefan Reinauer278534d2008-10-29 04:51:07 +00002513 for (i=0; i<5; i++) {
2514 MCHBAR32(UPMC3) &= ~(1 << 16);
2515 MCHBAR32(UPMC3) |= (1 << 16);
2516 }
2517
2518 MCHBAR32(GIPMC1) = 0x8000000c;
2519
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002520 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002521 reg16 &= ~(7 << 11);
2522 if (i945_silicon_revision()>2) {
2523 reg16 |= (6 << 11);
2524 } else {
2525 reg16 |= (4 << 11);
2526 }
2527 MCHBAR16(CPCTL) = reg16;
2528
Stefan Reinauer30140a52009-03-11 16:20:39 +00002529#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002530 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002531#else
2532 if (i945_silicon_revision() != 0) {
2533#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002534 switch (sysinfo->fsb_frequency) {
2535 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2536 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2537 }
2538 } else {
2539 switch (sysinfo->fsb_frequency) {
2540 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2541 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2542 }
2543 }
2544
2545 MCHBAR32(FSBPMC1) = 0x8000000c;
2546
2547 reg32 = MCHBAR32(C2C3TT);
2548 reg32 &= 0xffff0000;
2549 switch (sysinfo->fsb_frequency) {
2550 case 667: reg32 |= 0x0600; break;
2551 case 533: reg32 |= 0x0480; break;
2552 }
2553 MCHBAR32(C2C3TT) = reg32;
2554
2555 reg32 = MCHBAR32(C3C4TT);
2556 reg32 &= 0xffff0000;
2557 switch (sysinfo->fsb_frequency) {
2558 case 667: reg32 |= 0x0b80; break;
2559 case 533: reg32 |= 0x0980; break;
2560 }
2561 MCHBAR32(C3C4TT) = reg32;
2562
2563 if (i945_silicon_revision() == 0) {
2564 MCHBAR32(ECO) &= ~(1 << 16);
2565 } else {
2566 MCHBAR32(ECO) |= (1 << 16);
2567 }
2568
2569#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002570
Stefan Reinauer278534d2008-10-29 04:51:07 +00002571 if (i945_silicon_revision() == 0) {
2572 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2573 } else {
2574 MCHBAR32(FSBPMC3) |= (1 << 29);
2575 }
2576#endif
2577 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2578
2579 MCHBAR32(FSBPMC3) |= (1 << 21);
2580
2581 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2582
2583 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2584
2585 reg32 = MCHBAR32(FSBPMC4);
2586 reg32 &= ~(3 << 24);
2587 reg32 |= ( 2 << 24);
2588 MCHBAR32(FSBPMC4) = reg32;
2589
2590 MCHBAR32(FSBPMC4) |= (1 << 21);
2591
2592 MCHBAR32(FSBPMC4) |= (1 << 5);
2593
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002594 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2595 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002596 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2597 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002598 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002599 }
2600
2601 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2602 reg8 |= (1 << 4);
2603 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2604
2605 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2606 reg8 |= (1 << 2);
2607 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2608
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002609#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002610
Stefan Reinauer278534d2008-10-29 04:51:07 +00002611 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002612 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002613 MCHBAR16(MIPMC4) = 0x0468;
2614 MCHBAR16(MIPMC5) = 0x046c;
2615 MCHBAR16(MIPMC6) = 0x046c;
2616 } else {
2617 MCHBAR16(MIPMC4) = 0x6468;
2618 MCHBAR16(MIPMC5) = 0x646c;
2619 MCHBAR16(MIPMC6) = 0x646c;
2620 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002621#else
2622 if (integrated_graphics) {
2623 MCHBAR16(MIPMC4) = 0x04f8;
2624 MCHBAR16(MIPMC5) = 0x04fc;
2625 MCHBAR16(MIPMC6) = 0x04fc;
2626 } else {
2627 MCHBAR16(MIPMC4) = 0x64f8;
2628 MCHBAR16(MIPMC5) = 0x64fc;
2629 MCHBAR16(MIPMC6) = 0x64fc;
2630 }
2631
2632#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002633
2634 reg32 = MCHBAR32(PMCFG);
2635 reg32 &= ~(3 << 17);
2636 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002637 MCHBAR32(PMCFG) = reg32;
2638
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002639 MCHBAR32(PMCFG) |= (1 << 4);
2640
Stefan Reinauer278534d2008-10-29 04:51:07 +00002641 reg32 = MCHBAR32(0xc30);
2642 reg32 &= 0xffffff00;
2643 reg32 |= 0x01;
2644 MCHBAR32(0xc30) = reg32;
2645
2646 MCHBAR32(0xb18) &= ~(1 << 21);
2647}
2648
2649static void sdram_thermal_management(void)
2650{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002651
Stefan Reinauer278534d2008-10-29 04:51:07 +00002652 MCHBAR8(TCO1) = 0x00;
2653 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002654
2655 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2656 * 0x30/0x32.
2657 */
2658
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002659 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002660}
2661
2662static void sdram_save_receive_enable(void)
2663{
2664 int i;
2665 u32 reg32;
2666 u8 values[4];
2667
2668 /* The following values are stored to an unused CMOS
2669 * area and restored instead of recalculated in case
2670 * of an S3 resume.
2671 *
2672 * C0WL0REOST [7:0] -> 8 bit
2673 * C1WL0REOST [7:0] -> 8 bit
2674 * RCVENMT [11:8] [3:0] -> 8 bit
2675 * C0DRT1 [27:24] -> 4 bit
2676 * C1DRT1 [27:24] -> 4 bit
2677 */
2678
2679 values[0] = MCHBAR8(C0WL0REOST);
2680 values[1] = MCHBAR8(C1WL0REOST);
2681
2682 reg32 = MCHBAR32(RCVENMT);
2683 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2684
2685 reg32 = MCHBAR32(C0DRT1);
2686 values[3] = (reg32 >> 24) & 0x0f;
2687 reg32 = MCHBAR32(C1DRT1);
2688 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2689
2690 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002691 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002692 */
2693
2694 for (i=0; i<4; i++)
2695 cmos_write(values[i], 128 + i);
2696}
2697
2698static void sdram_recover_receive_enable(void)
2699{
2700 int i;
2701 u32 reg32;
2702 u8 values[4];
2703
2704 for (i=0; i<4; i++)
2705 values[i] = cmos_read(128 + i);
2706
2707 MCHBAR8(C0WL0REOST) = values[0];
2708 MCHBAR8(C1WL0REOST) = values[1];
2709
2710 reg32 = MCHBAR32(RCVENMT);
2711 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2712 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2713 MCHBAR32(RCVENMT) = reg32;
2714
2715 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2716 reg32 |= (u32)(values[3] & 0x0f) << 24;
2717 MCHBAR32(C0DRT1) = reg32;
2718
2719 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2720 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2721 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002722}
2723
2724#include "rcven.c"
2725
2726static void sdram_program_receive_enable(struct sys_info *sysinfo)
2727{
2728 MCHBAR32(REPC) |= (1 << 0);
2729
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002730 /* enable upper CMOS */
2731 RCBA32(0x3400) = (1 << 2);
2732
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002733 /* Program Receive Enable Timings */
2734 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2735 sdram_recover_receive_enable();
2736 } else {
2737 receive_enable_adjust(sysinfo);
2738 sdram_save_receive_enable();
2739 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002740
2741 MCHBAR32(C0DRC1) |= (1 << 6);
2742 MCHBAR32(C1DRC1) |= (1 << 6);
2743 MCHBAR32(C0DRC1) &= ~(1 << 6);
2744 MCHBAR32(C1DRC1) &= ~(1 << 6);
2745
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002746 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002747}
2748
2749/**
2750 * @brief Enable On-Die Termination for DDR2.
2751 *
2752 */
2753
2754static void sdram_on_die_termination(struct sys_info *sysinfo)
2755{
2756 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002757 0x00024911, 0xe0010000,
2758 0x00049211, 0xe0020000,
2759 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002760 };
2761
2762 u32 reg32;
2763 int cas;
2764
2765 reg32 = MCHBAR32(ODTC);
2766 reg32 &= ~(3 << 16);
2767 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2768 MCHBAR32(ODTC) = reg32;
2769
2770 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2771 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002772 printk(BIOS_DEBUG, "one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002773
Stefan Reinauer278534d2008-10-29 04:51:07 +00002774 reg32 = MCHBAR32(C0ODT);
2775 reg32 &= ~(7 << 28);
2776 MCHBAR32(C0ODT) = reg32;
2777 reg32 = MCHBAR32(C1ODT);
2778 reg32 &= ~(7 << 28);
2779 MCHBAR32(C1ODT) = reg32;
2780 }
2781
2782 cas = sysinfo->cas;
2783
2784 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2785 reg32 |= odt[(cas-3) * 2];
2786 MCHBAR32(C0ODT) = reg32;
2787
2788 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2789 reg32 |= odt[(cas-3) * 2];
2790 MCHBAR32(C1ODT) = reg32;
2791
2792 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2793 reg32 |= odt[((cas-3) * 2) + 1];
2794 MCHBAR32(C0ODT + 4) = reg32;
2795
2796 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2797 reg32 |= odt[((cas-3) * 2) + 1];
2798 MCHBAR32(C1ODT + 4) = reg32;
2799}
2800
2801/**
2802 * @brief Enable clocks to populated sockets
2803 */
2804
2805static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2806{
2807 u8 clocks[2] = { 0, 0 };
2808
Peter Stugee4bc0f62010-10-01 09:13:18 +00002809#if defined(CONFIG_NORTHBRIDGE_INTEL_I945GM)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002810#define CLOCKS_WIDTH 2
Peter Stugee4bc0f62010-10-01 09:13:18 +00002811#elif defined(CONFIG_NORTHBRIDGE_INTEL_I945GC)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002812#define CLOCKS_WIDTH 3
2813#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002814 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002815 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002816
2817 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002818 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002819
2820 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002821 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002822
2823 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002824 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002825
Patrick Georgi77d66832010-10-01 08:02:45 +00002826#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002827 /* Usually system firmware turns off system memory clock signals
2828 * to unused SO-DIMM slots to reduce EMI and power consumption.
2829 * However, the Kontron 986LCD-M does not like unused clock
2830 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002831 */
2832
2833 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2834 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002835#endif
2836
2837 MCHBAR8(C0DCLKDIS) = clocks[0];
2838 MCHBAR8(C1DCLKDIS) = clocks[1];
2839}
2840
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002841#define RTT_ODT_NONE 0
2842#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002843#define RTT_ODT_75_OHM (1 << 5)
2844#define RTT_ODT_150_OHM (1 << 9)
2845
2846#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2847
2848#define MRS_CAS_3 (3 << 7)
2849#define MRS_CAS_4 (4 << 7)
2850#define MRS_CAS_5 (5 << 7)
2851
2852#define MRS_TWR_3 (2 << 12)
2853#define MRS_TWR_4 (3 << 12)
2854#define MRS_TWR_5 (4 << 12)
2855
2856#define MRS_BT (1 << 6)
2857
2858#define MRS_BL4 (2 << 3)
2859#define MRS_BL8 (3 << 3)
2860
2861static void sdram_jedec_enable(struct sys_info *sysinfo)
2862{
2863 int i, nonzero;
2864 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2865
2866 for (i = 0, nonzero = -1; i < 8; i++) {
2867 if (sysinfo->banksize[i] == 0) {
2868 continue;
2869 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002870
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002871 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002872 switch (i) {
2873 case 0:
2874 /* Start at address 0 */
2875 bankaddr = 0;
2876 break;
2877 case 4:
2878 if (sysinfo->interleaved) {
2879 bankaddr = 0x40;
2880 break;
2881 }
2882 default:
2883 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002884 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002885 bankaddr += sysinfo->banksize[nonzero] <<
2886 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002887 break;
2888 }
2889 /* No populated bank hit before. Start at address 0 */
2890 bankaddr = 0;
2891 }
2892
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002893 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002894 * for the next offset we have to calculate
2895 */
2896 nonzero = i;
2897
2898 /* Get CAS latency set up */
2899 switch (sysinfo->cas) {
2900 case 5: mrsaddr = MRS_CAS_5; break;
2901 case 4: mrsaddr = MRS_CAS_4; break;
2902 case 3: mrsaddr = MRS_CAS_3; break;
2903 default: die("Jedec Error (CAS).\n");
2904 }
2905
2906 /* Get tWR set */
2907 switch (sysinfo->twr) {
2908 case 5: mrsaddr |= MRS_TWR_5; break;
2909 case 4: mrsaddr |= MRS_TWR_4; break;
2910 case 3: mrsaddr |= MRS_TWR_3; break;
2911 default: die("Jedec Error (tWR).\n");
2912 }
2913
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002914 /* Set "Burst Type" */
2915 mrsaddr |= MRS_BT;
2916
Stefan Reinauer278534d2008-10-29 04:51:07 +00002917 /* Interleaved */
2918 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002919 mrsaddr = mrsaddr << 1;
2920 }
2921
2922 /* Only burst length 8 supported */
2923 mrsaddr |= MRS_BL8;
2924
2925 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002926 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002927 do_ram_command(RAM_COMMAND_NOP);
2928 ram_read32(bankaddr);
2929
2930 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002931 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002932 do_ram_command(RAM_COMMAND_PRECHARGE);
2933 ram_read32(bankaddr);
2934
2935 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002936 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002937 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2938 ram_read32(bankaddr);
2939
2940 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002941 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002942 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2943 ram_read32(bankaddr);
2944
2945 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002946 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002947 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2948 tmpaddr = bankaddr;
2949 if (!sdram_capabilities_dual_channel()) {
2950 tmpaddr |= RTT_ODT_75_OHM;
2951 } else if (sysinfo->interleaved) {
2952 tmpaddr |= (RTT_ODT_150_OHM << 1);
2953 } else {
2954 tmpaddr |= RTT_ODT_150_OHM;
2955 }
2956 ram_read32(tmpaddr);
2957
2958 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002959 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002960 do_ram_command(RAM_COMMAND_MRS);
2961 tmpaddr = bankaddr;
2962 tmpaddr |= mrsaddr;
2963 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002964 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002965 tmpaddr |= (1 << 12);
2966 else
2967 tmpaddr |= (1 << 11);
2968 ram_read32(tmpaddr);
2969
2970 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002971 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002972 do_ram_command(RAM_COMMAND_PRECHARGE);
2973 ram_read32(bankaddr);
2974
2975 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002976 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002977 do_ram_command(RAM_COMMAND_CBR);
2978
2979 /* CBR wants two READs */
2980 ram_read32(bankaddr);
2981 ram_read32(bankaddr);
2982
2983 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002984 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002985 do_ram_command(RAM_COMMAND_MRS);
2986
2987 tmpaddr = bankaddr;
2988 tmpaddr |= mrsaddr;
2989 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002990
Stefan Reinauer278534d2008-10-29 04:51:07 +00002991 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002992 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002993 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002994
Stefan Reinauer278534d2008-10-29 04:51:07 +00002995 tmpaddr = bankaddr;
2996 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002997
Stefan Reinauer278534d2008-10-29 04:51:07 +00002998 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
2999 } else if (sysinfo->interleaved) {
3000 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
3001 } else {
3002 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
3003 }
3004 ram_read32(tmpaddr);
3005
3006 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003007 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003008 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3009
3010 tmpaddr = bankaddr;
3011 if (!sdram_capabilities_dual_channel()) {
3012 tmpaddr |= RTT_ODT_75_OHM;
3013 } else if (sysinfo->interleaved) {
3014 tmpaddr |= (RTT_ODT_150_OHM << 1);
3015 } else {
3016 tmpaddr |= RTT_ODT_150_OHM;
3017 }
3018 ram_read32(tmpaddr);
3019 }
3020}
3021
3022static void sdram_init_complete(void)
3023{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003024 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003025 do_ram_command(RAM_COMMAND_NORMAL);
3026}
3027
3028static void sdram_setup_processor_side(void)
3029{
3030 if (i945_silicon_revision() == 0)
3031 MCHBAR32(FSBPMC3) |= (1 << 2);
3032
3033 MCHBAR8(0xb00) |= 1;
3034
3035 if (i945_silicon_revision() == 0)
3036 MCHBAR32(SLPCTL) |= (1 << 8);
3037}
3038
Stefan Reinauer278534d2008-10-29 04:51:07 +00003039/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003040 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Stefan Reinauer278534d2008-10-29 04:51:07 +00003041 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003042void sdram_initialize(int boot_path)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003043{
3044 struct sys_info sysinfo;
3045 u8 reg8, cas_mask;
3046
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003047 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003048
3049 memset(&sysinfo, 0, sizeof(sysinfo));
3050
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003051 sysinfo.boot_path = boot_path;
3052
Stefan Reinauer278534d2008-10-29 04:51:07 +00003053 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3054 sdram_get_dram_configuration(&sysinfo);
3055
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003056 /* If error, do cold boot */
3057 sdram_detect_errors(&sysinfo);
3058
Stefan Reinauer278534d2008-10-29 04:51:07 +00003059 /* Check whether we have stacked DIMMs */
3060 sdram_verify_package_type(&sysinfo);
3061
3062 /* Determine common CAS */
3063 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003064
Stefan Reinauer278534d2008-10-29 04:51:07 +00003065 /* Choose Common Frequency */
3066 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003067
Stefan Reinauer278534d2008-10-29 04:51:07 +00003068 /* Determine smallest common tRAS */
3069 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003070
Stefan Reinauer278534d2008-10-29 04:51:07 +00003071 /* Determine tRP */
3072 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003073
Stefan Reinauer278534d2008-10-29 04:51:07 +00003074 /* Determine tRCD */
3075 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003076
Stefan Reinauer278534d2008-10-29 04:51:07 +00003077 /* Determine smallest refresh period */
3078 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003079
Stefan Reinauer278534d2008-10-29 04:51:07 +00003080 /* Verify all DIMMs support burst length 8 */
3081 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003082
Stefan Reinauer278534d2008-10-29 04:51:07 +00003083 /* determine tWR */
3084 sdram_detect_smallest_tWR(&sysinfo);
3085
3086 /* Determine DIMM size parameters (rows, columns banks) */
3087 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003088
Stefan Reinauer278534d2008-10-29 04:51:07 +00003089 /* determine tRFC */
3090 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003091
Stefan Reinauer278534d2008-10-29 04:51:07 +00003092 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003093 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003094
3095 /* Program Graphics Frequency */
3096 sdram_program_graphics_frequency(&sysinfo);
3097
3098 /* Program System Memory Frequency */
3099 sdram_program_memory_frequency(&sysinfo);
3100
3101 /* Determine Mode of Operation (Interleaved etc) */
3102 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003103
Stefan Reinauer278534d2008-10-29 04:51:07 +00003104 /* Program Clock Crossing values */
3105 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003106
Stefan Reinauer278534d2008-10-29 04:51:07 +00003107 /* Disable fast dispatch */
3108 sdram_disable_fast_dispatch();
3109
3110 /* Enable WIODLL Power Down in ACPI states */
3111 MCHBAR32(C0DMC) |= (1 << 24);
3112 MCHBAR32(C1DMC) |= (1 << 24);
3113
3114 /* Program DRAM Row Boundary/Attribute Registers */
3115
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003116 /* program row size DRB and set TOLUD */
3117 sdram_program_row_boundaries(&sysinfo);
3118
3119 /* program page size DRA */
3120 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003121
3122 /* Program CxBNKARC */
3123 sdram_set_bank_architecture(&sysinfo);
3124
3125 /* Program DRAM Timing and Control registers based on SPD */
3126 sdram_set_timing_and_control(&sysinfo);
3127
3128 /* On-Die Termination Adjustment */
3129 sdram_on_die_termination(&sysinfo);
3130
3131 /* Pre Jedec Initialization */
3132 sdram_pre_jedec_initialization();
3133
3134 /* Perform System Memory IO Initialization */
3135 sdram_initialize_system_memory_io(&sysinfo);
3136
3137 /* Perform System Memory IO Buffer Enable */
3138 sdram_enable_system_memory_io(&sysinfo);
3139
3140 /* Enable System Memory Clocks */
3141 sdram_enable_memory_clocks(&sysinfo);
3142
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003143 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003144 /* Jedec Initialization sequence */
3145 sdram_jedec_enable(&sysinfo);
3146 }
3147
3148 /* Program Power Management Registers */
3149 sdram_power_management(&sysinfo);
3150
3151 /* Post Jedec Init */
3152 sdram_post_jedec_initialization(&sysinfo);
3153
3154 /* Program DRAM Throttling */
3155 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003156
Stefan Reinauer278534d2008-10-29 04:51:07 +00003157 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003158 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003159
3160 /* Program Receive Enable Timings */
3161 sdram_program_receive_enable(&sysinfo);
3162
3163 /* Enable Periodic RCOMP */
3164 sdram_enable_rcomp();
3165
3166 /* Tell ICH7 that we're done */
3167 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3168 reg8 &= ~(1 << 7);
3169 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3170
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003171 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003172
Stefan Reinauer278534d2008-10-29 04:51:07 +00003173 sdram_setup_processor_side();
3174}
3175
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003176unsigned long get_top_of_ram(void)
3177{
3178 /* This will not work if TSEG is in place! */
3179 u32 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
3180
3181 return (unsigned long) tom;
3182}
3183