blob: 59a31deacfd6bfb10407337c13dd9e1bc502d1f6 [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.
Stefan Reinauer278534d2008-10-29 04:51:07 +000014 */
15
Patrick Georgid0835952010-10-05 09:07:10 +000016#include <console/console.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000017#include <cpu/x86/mtrr.h>
18#include <cpu/x86/cache.h>
Julius Werner7a8a4ab2015-05-22 16:26:40 -070019#include <lib.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000020#include <pc80/mc146818rtc.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000021#include <spd.h>
Patrick Georgid0835952010-10-05 09:07:10 +000022#include <string.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070023#include <arch/io.h>
Patrick Georgi546953c2014-11-29 10:38:17 +010024#include <halt.h>
Alexandru Gagniucaf4bd592014-01-12 15:42:58 -060025#include <lib.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000026#include "raminit.h"
27#include "i945.h"
Rudolf Marekc4369532010-12-13 19:59:13 +000028#include <cbmem.h>
29
Stefan Reinauer278534d2008-10-29 04:51:07 +000030/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000031#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000032#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Stefan Reinauer278534d2008-10-29 04:51:07 +000033#else
34#define PRINTK_DEBUG(x...)
35#endif
36
Stefan Reinauer278534d2008-10-29 04:51:07 +000037#define RAM_INITIALIZATION_COMPLETE (1 << 19)
38
39#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
40#define RAM_COMMAND_NOP (0x1 << 16)
41#define RAM_COMMAND_PRECHARGE (0x2 << 16)
42#define RAM_COMMAND_MRS (0x3 << 16)
43#define RAM_COMMAND_EMRS (0x4 << 16)
44#define RAM_COMMAND_CBR (0x6 << 16)
45#define RAM_COMMAND_NORMAL (0x7 << 16)
46
47#define RAM_EMRS_1 (0x0 << 21)
48#define RAM_EMRS_2 (0x1 << 21)
49#define RAM_EMRS_3 (0x2 << 21)
50
Sven Schnelle541269b2011-02-21 09:39:17 +000051static int get_dimm_spd_address(struct sys_info *sysinfo, int device)
52{
53 if (sysinfo->spd_addresses)
54 return sysinfo->spd_addresses[device];
55 else
56 return DIMM0 + device;
57
58}
59
Patrick Georgid0835952010-10-05 09:07:10 +000060static inline int spd_read_byte(unsigned device, unsigned address)
61{
62 return smbus_read_byte(device, address);
63}
64
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000065static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000066{
67 u32 reg32;
68
69 reg32 = MCHBAR32(DCC);
70 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
71 reg32 |= command;
72
73 /* Also set Init Complete */
74 if (command == RAM_COMMAND_NORMAL)
75 reg32 |= RAM_INITIALIZATION_COMPLETE;
76
77 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
78
79 MCHBAR32(DCC) = reg32; /* This is the actual magic */
80
Stefan Reinauer779b3e32008-11-10 15:43:37 +000081 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000082
83 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000084}
85
Stefan Reinauer278534d2008-10-29 04:51:07 +000086static void ram_read32(u32 offset)
87{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000088 PRINTK_DEBUG(" ram read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000089
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080090 read32((void *)offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000091}
92
Uwe Hermann01ce6012010-03-05 10:03:50 +000093#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer3c0bfaf2010-12-27 11:34:57 +000094void sdram_dump_mchbar_registers(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000095{
96 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000097 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000098
99 for (i=0; i<0xfff; i+=4) {
100 if (MCHBAR32(i) == 0)
101 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000102 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000103 }
104}
105#endif
106
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000107static int memclk(void)
108{
109 int offset = 0;
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200110#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000111 offset++;
112#endif
113 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
114 case 1: return 400;
115 case 2: return 533;
116 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000117 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000118 }
119 return -1;
120}
121
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200122#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Peter Stuge76d91432010-10-01 10:02:33 +0000123static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000124{
125 switch (MCHBAR32(CLKCFG) & 7) {
126 case 0: return 400;
127 case 1: return 533;
128 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000129 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000130 }
Peter Stuge76d91432010-10-01 10:02:33 +0000131 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000132}
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +0200133#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Peter Stuge76d91432010-10-01 10:02:33 +0000134static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000135{
136 switch (MCHBAR32(CLKCFG) & 7) {
137 case 0: return 1066;
138 case 1: return 533;
139 case 2: return 800;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000140 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000141 }
Peter Stuge76d91432010-10-01 10:02:33 +0000142 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000143}
144#endif
145
Stefan Reinauer278534d2008-10-29 04:51:07 +0000146static int sdram_capabilities_max_supported_memory_frequency(void)
147{
148 u32 reg32;
149
Patrick Georgi77d66832010-10-01 08:02:45 +0000150#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
151 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000152#endif
153
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000154 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000155 reg32 &= (7 << 0);
156
157 switch (reg32) {
158 case 4: return 400;
159 case 3: return 533;
160 case 2: return 667;
161 }
162 /* Newer revisions of this chipset rather support faster memory clocks,
163 * so if it's a reserved value, return the fastest memory clock that we
164 * know of and can handle
165 */
166 return 667;
167}
168
169/**
170 * @brief determine whether chipset is capable of dual channel interleaved mode
171 *
172 * @return 1 if interleaving is supported, 0 otherwise
173 */
174static int sdram_capabilities_interleave(void)
175{
176 u32 reg32;
177
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000178 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000179 reg32 >>= 25;
180 reg32 &= 1;
181
182 return (!reg32);
183}
184
185/**
186 * @brief determine whether chipset is capable of two memory channels
187 *
188 * @return 1 if dual channel operation is supported, 0 otherwise
189 */
190static int sdram_capabilities_dual_channel(void)
191{
192 u32 reg32;
193
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000194 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000195 reg32 >>= 24;
196 reg32 &= 1;
197
198 return (!reg32);
199}
200
201static int sdram_capabilities_enhanced_addressing_xor(void)
202{
203 u8 reg8;
204
205 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
206 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000207
Stefan Reinauer278534d2008-10-29 04:51:07 +0000208 return (!reg8);
209}
210
Stefan Reinauer14e22772010-04-27 06:56:47 +0000211// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000212#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000213static int sdram_capabilities_MEM4G_disable(void)
214{
215 u8 reg8;
216
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000217 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000218 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000219
Stefan Reinauer278534d2008-10-29 04:51:07 +0000220 return (reg8 != 0);
221}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000222#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000223
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000224#define GFX_FREQUENCY_CAP_166MHZ 0x04
225#define GFX_FREQUENCY_CAP_200MHZ 0x03
226#define GFX_FREQUENCY_CAP_250MHZ 0x02
227#define GFX_FREQUENCY_CAP_ALL 0x00
228
229static int sdram_capabilities_core_frequencies(void)
230{
231 u8 reg8;
232
233 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
234 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
235 reg8 >>= 1;
236
237 return (reg8);
238}
239
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000240static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000241{
242 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000243 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000244
245 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000246
Stefan Reinauer278534d2008-10-29 04:51:07 +0000247 if (reg8 & ((1<<7)|(1<<2))) {
248 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000249 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000250 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000251 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000252 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000253
Stefan Reinauer278534d2008-10-29 04:51:07 +0000254 }
255
256 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000257 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000258 reg8 &= ~(1<<7);
259 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000260 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000261 }
262
263 /* Set SLP_S3# Assertion Stretch Enable */
264 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
265 reg8 |= (1 << 3);
266 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
267
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000268 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000269 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000270 outb(0x00, 0xcf9);
271 outb(0x0e, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +0100272 halt(); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000273 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000274 }
275
276 /* Set DRAM initialization bit in ICH7 */
277 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
278 reg8 |= (1<<7);
279 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000280
Peter Stuge751508a2012-01-27 22:17:09 +0100281 /* clear self refresh status if check is disabled or not a resume */
Patrick Georgi86a11102013-03-15 14:11:37 +0100282 if (!CONFIG_CHECK_SLFRCS_ON_RESUME || sysinfo->boot_path != BOOT_PATH_RESUME) {
283 MCHBAR8(SLFRCS) |= 3;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000284 } else {
285 /* Validate self refresh config */
286 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
287 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100288 !(MCHBAR8(SLFRCS) & (1<<0))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000289 do_reset = 1;
290 }
291 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
292 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100293 !(MCHBAR8(SLFRCS) & (1<<1))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000294 do_reset = 1;
295 }
296 }
297
298 if (do_reset) {
299 printk(BIOS_DEBUG, "Reset required.\n");
300 outb(0x00, 0xcf9);
301 outb(0x0e, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +0100302 halt(); /* Wait for reset! */
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000303 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000304}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000305
306/**
307 * @brief Get generic DIMM parameters.
308 * @param sysinfo Central memory controller information structure
309 *
310 * This function gathers several pieces of information for each system DIMM:
311 * o DIMM width (x8 / x16)
312 * o DIMM sides (single sided / dual sided)
313 *
314 * Also, some non-supported scenarios are detected.
315 */
316
317static void sdram_get_dram_configuration(struct sys_info *sysinfo)
318{
319 u32 dimm_mask = 0;
320 int i;
321
322 /**
323 * i945 supports two DIMMs, in two configurations:
324 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000325 * - single channel with two DIMMs
326 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000327 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000328 * In practice dual channel mainboards have their SPD at 0x50/0x52
329 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000330 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000331 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000332 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000333 */
334
335 if (sdram_capabilities_dual_channel()) {
336 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000337 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000338 } else {
339 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000340 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000341 }
342
343 /**
344 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000345 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000346 * return value:
347 * [0:7] lower DIMM population
348 * [8-15] higher DIMM population
349 * [16] dual channel?
350 *
351 * There are 5 different possible populations for a DIMM socket:
352 * 1. x16 double sided (X16DS)
353 * 2. x8 double sided (X8DS)
354 * 3. x16 single sided (X16SS)
355 * 4. x8 double stacked (X8DDS)
356 * 5. not populated (NC)
357 *
358 * For the return value we start counting at zero.
359 *
360 */
361
362 for (i=0; i<(2 * DIMM_SOCKETS); i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000363 int device = get_dimm_spd_address(sysinfo, i);
364 u8 reg8;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000365
366 /* Initialize the socket information with a sane value */
367 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
368
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000369 /* Dual Channel not supported, but Channel 1? Bail out */
370 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000371 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000372
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000373 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000374
375 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000376 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000377 continue;
378 }
379
380 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
381 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000382 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000383
384 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
385 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000386 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000387 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000388 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000389
390 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000391 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000392 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
393 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000394 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000395 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
396 break;
397 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000398 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
400 break;
401 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000402 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403 }
404 break;
405 case 0x10:
406 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
407 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000408 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000409 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
410 break;
411 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000412 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000413 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
414 break;
415 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000416 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000417 }
418 break;
419 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000420 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000421 }
422
423 dimm_mask |= (1 << i);
424 }
425
426 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000427 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000428 }
429
Stefan Reinauer278534d2008-10-29 04:51:07 +0000430 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000431 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000432 }
433}
434
435/**
436 * @brief determine if any DIMMs are stacked
437 *
438 * @param sysinfo central sysinfo data structure.
439 */
440static void sdram_verify_package_type(struct sys_info * sysinfo)
441{
442 int i;
443
444 /* Assume no stacked DIMMs are available until we find one */
445 sysinfo->package = 0;
446 for (i=0; i<2*DIMM_SOCKETS; i++) {
447 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
448 continue;
449
450 /* Is the current DIMM a stacked DIMM? */
Sven Schnelle541269b2011-02-21 09:39:17 +0000451 if (spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000452 sysinfo->package = 1;
453 }
454}
455
456static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
457{
458 int i;
459 u8 cas_mask;
460
461 /* Setup CAS mask with all supported CAS Latencies */
462 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
463 SPD_CAS_LATENCY_DDR2_4 |
464 SPD_CAS_LATENCY_DDR2_5;
465
466 for (i=0; i<2*DIMM_SOCKETS; i++) {
467 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Sven Schnelle541269b2011-02-21 09:39:17 +0000468 cas_mask &= spd_read_byte(get_dimm_spd_address(sysinfo, i),
469 SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000470 }
471
472 if(!cas_mask) {
473 die("No DDR-II modules with accepted CAS latencies found.\n");
474 }
475
476 return cas_mask;
477}
478
479static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
480{
481 int i, j, idx;
482 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000483 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000484
485 const u8 ddr2_speeds_table[] = {
486 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
487 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
488 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
489 };
490
491 const u8 spd_lookup_table[] = {
492 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
493 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
494 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
495 };
496
497 switch (sdram_capabilities_max_supported_memory_frequency()) {
498 case 400: max_ram_speed = 0; break;
499 case 533: max_ram_speed = 1; break;
500 case 667: max_ram_speed = 2; break;
501 }
502
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000503 if (fsbclk() == 533)
504 max_ram_speed = 1;
505
Stefan Reinauer278534d2008-10-29 04:51:07 +0000506 sysinfo->memory_frequency = 0;
507 sysinfo->cas = 0;
508
509 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
510 lowest_common_cas = 3;
511 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
512 lowest_common_cas = 4;
513 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
514 lowest_common_cas = 5;
515 }
516 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
517
518 for (j = max_ram_speed; j>=0; j--) {
519 int freq_cas_mask = cas_mask;
520
521 PRINTK_DEBUG("Probing Speed %d\n", j);
522 for (i=0; i<2*DIMM_SOCKETS; i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000523 int device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000524 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000525
Stefan Reinauer278534d2008-10-29 04:51:07 +0000526 PRINTK_DEBUG(" DIMM: %d\n", i);
527 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
528 continue;
529 }
530
Sven Schnelle541269b2011-02-21 09:39:17 +0000531 current_cas_mask = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000532
533 while (current_cas_mask) {
534 int highest_supported_cas = 0, current_cas = 0;
535 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
536 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
537 highest_supported_cas = 5;
538 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
539 highest_supported_cas = 4;
540 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
541 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000542 } else {
543 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000544 }
545 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
546 current_cas = 3;
547 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
548 current_cas = 4;
549 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
550 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000551 } else {
552 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000553 }
554
555 idx = highest_supported_cas - current_cas;
556 PRINTK_DEBUG("idx=%d, ", idx);
Sven Schnelle541269b2011-02-21 09:39:17 +0000557 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(device, spd_lookup_table[2*idx]));
558 PRINTK_DEBUG("tAC=%x", spd_read_byte(device, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000559
Sven Schnelle541269b2011-02-21 09:39:17 +0000560 if (spd_read_byte(device, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
561 spd_read_byte(device, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000562 PRINTK_DEBUG(": OK\n");
563 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000564 }
565
Stefan Reinauer278534d2008-10-29 04:51:07 +0000566 PRINTK_DEBUG(": Not fast enough!\n");
567
568 current_cas_mask &= ~(1 << (current_cas));
569 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000570
Stefan Reinauer278534d2008-10-29 04:51:07 +0000571 freq_cas_mask &= current_cas_mask;
572 if (!current_cas_mask) {
573 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
574 break;
575 }
576 }
577 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
578 if (freq_cas_mask) {
579 switch (j) {
580 case 0: sysinfo->memory_frequency = 400; break;
581 case 1: sysinfo->memory_frequency = 533; break;
582 case 2: sysinfo->memory_frequency = 667; break;
583 }
584 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
585 sysinfo->cas = 3;
586 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
587 sysinfo->cas = 4;
588 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
589 sysinfo->cas = 5;
590 }
591 break;
592 }
593 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000594
Stefan Reinauer278534d2008-10-29 04:51:07 +0000595 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000596 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000597 sysinfo->memory_frequency, sysinfo->cas);
598 } else {
599 die("Could not find common memory frequency and CAS\n");
600 }
601}
602
603static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
604{
605 int i;
606 int tRAS_time;
607 int tRAS_cycles;
608 int freq_multiplier = 0;
609
610 switch (sysinfo->memory_frequency) {
611 case 400: freq_multiplier = 0x14; break; /* 5ns */
612 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
613 case 667: freq_multiplier = 0x0c; break; /* 3ns */
614 }
615
616 tRAS_cycles = 4; /* 4 clocks minimum */
617 tRAS_time = tRAS_cycles * freq_multiplier;
618
619 for (i=0; i<2*DIMM_SOCKETS; i++) {
620 u8 reg8;
621
622 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
623 continue;
624
Sven Schnelle541269b2011-02-21 09:39:17 +0000625 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000626 if (!reg8) {
627 die("Invalid tRAS value.\n");
628 }
629
630 while ((tRAS_time >> 2) < reg8) {
631 tRAS_time += freq_multiplier;
632 tRAS_cycles++;
633 }
634 }
635 if(tRAS_cycles > 0x18) {
636 die("DDR-II Module does not support this frequency (tRAS error)\n");
637 }
638
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000639 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000640 sysinfo->tras = tRAS_cycles;
641}
642
643static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
644{
645 int i;
646 int tRP_time;
647 int tRP_cycles;
648 int freq_multiplier = 0;
649
650 switch (sysinfo->memory_frequency) {
651 case 400: freq_multiplier = 0x14; break; /* 5ns */
652 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
653 case 667: freq_multiplier = 0x0c; break; /* 3ns */
654 }
655
656 tRP_cycles = 2; /* 2 clocks minimum */
657 tRP_time = tRP_cycles * freq_multiplier;
658
659 for (i=0; i<2*DIMM_SOCKETS; i++) {
660 u8 reg8;
661
662 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
663 continue;
664
Sven Schnelle541269b2011-02-21 09:39:17 +0000665 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000666 if (!reg8) {
667 die("Invalid tRP value.\n");
668 }
669
670 while (tRP_time < reg8) {
671 tRP_time += freq_multiplier;
672 tRP_cycles++;
673 }
674 }
675
676 if(tRP_cycles > 6) {
677 die("DDR-II Module does not support this frequency (tRP error)\n");
678 }
679
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000680 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000681 sysinfo->trp = tRP_cycles;
682}
683
684static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
685{
686 int i;
687 int tRCD_time;
688 int tRCD_cycles;
689 int freq_multiplier = 0;
690
691 switch (sysinfo->memory_frequency) {
692 case 400: freq_multiplier = 0x14; break; /* 5ns */
693 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
694 case 667: freq_multiplier = 0x0c; break; /* 3ns */
695 }
696
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000697 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000698 tRCD_time = tRCD_cycles * freq_multiplier;
699
700 for (i=0; i<2*DIMM_SOCKETS; i++) {
701 u8 reg8;
702
703 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
704 continue;
705
Sven Schnelle541269b2011-02-21 09:39:17 +0000706 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000707 if (!reg8) {
708 die("Invalid tRCD value.\n");
709 }
710
711 while (tRCD_time < reg8) {
712 tRCD_time += freq_multiplier;
713 tRCD_cycles++;
714 }
715 }
716 if(tRCD_cycles > 6) {
717 die("DDR-II Module does not support this frequency (tRCD error)\n");
718 }
719
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000720 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000721 sysinfo->trcd = tRCD_cycles;
722}
723
724static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
725{
726 int i;
727 int tWR_time;
728 int tWR_cycles;
729 int freq_multiplier = 0;
730
731 switch (sysinfo->memory_frequency) {
732 case 400: freq_multiplier = 0x14; break; /* 5ns */
733 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
734 case 667: freq_multiplier = 0x0c; break; /* 3ns */
735 }
736
737 tWR_cycles = 2; /* 2 clocks minimum */
738 tWR_time = tWR_cycles * freq_multiplier;
739
740 for (i=0; i<2*DIMM_SOCKETS; i++) {
741 u8 reg8;
742
743 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
744 continue;
745
Sven Schnelle541269b2011-02-21 09:39:17 +0000746 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000747 if (!reg8) {
748 die("Invalid tWR value.\n");
749 }
750
751 while (tWR_time < reg8) {
752 tWR_time += freq_multiplier;
753 tWR_cycles++;
754 }
755 }
756 if(tWR_cycles > 5) {
757 die("DDR-II Module does not support this frequency (tWR error)\n");
758 }
759
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000760 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000761 sysinfo->twr = tWR_cycles;
762}
763
764static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
765{
766 int i, index = 0;
767
768 const u8 tRFC_cycles[] = {
769 /* 75 105 127.5 */
770 15, 21, 26, /* DDR2-400 */
771 20, 28, 34, /* DDR2-533 */
772 25, 35, 43 /* DDR2-667 */
773 };
774
775 for (i=0; i<2*DIMM_SOCKETS; i++) {
776 u8 reg8;
777
778 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
779 continue;
780
781 reg8 = sysinfo->banksize[i*2];
782 switch (reg8) {
783 case 0x04: reg8 = 0; break;
784 case 0x08: reg8 = 1; break;
785 case 0x10: reg8 = 2; break;
786 case 0x20: reg8 = 3; break;
787 }
788
789 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
790 reg8++;
791
792 if (reg8 > 3) {
793 /* Can this happen? Go back to 127.5ns just to be sure
794 * we don't run out of the array. This may be wrong
795 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000796 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000797 reg8 = 3;
798 }
799
800 if (reg8 > index)
801 index = reg8;
802
803 }
804 index--;
805 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000806 case 667: index += 3; /* Fallthrough */
807 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000808 case 400: break;
809 }
810
811 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000812 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000813}
814
Stefan Reinauer278534d2008-10-29 04:51:07 +0000815static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
816{
817 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000818
Stefan Reinauer278534d2008-10-29 04:51:07 +0000819 sysinfo->refresh = 0;
820
821 for (i=0; i<2*DIMM_SOCKETS; i++) {
822 int refresh;
823
824 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
825 continue;
826
Sven Schnelle541269b2011-02-21 09:39:17 +0000827 refresh = spd_read_byte(get_dimm_spd_address(sysinfo, i),
828 SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000829
830 /* 15.6us */
831 if (!refresh)
832 continue;
833
834 /* Refresh is slower than 15.6us, use 15.6us */
835 if (refresh > 2)
836 continue;
837
838 if (refresh == 2) {
839 sysinfo->refresh = 1;
840 break;
841 }
842
843 die("DDR-II module has unsupported refresh value\n");
844 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000845 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000846}
847
848static void sdram_verify_burst_length(struct sys_info * sysinfo)
849{
850 int i;
851
852 for (i=0; i<2*DIMM_SOCKETS; i++) {
853 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
854 continue;
855
Sven Schnelle541269b2011-02-21 09:39:17 +0000856 if (!(spd_read_byte(get_dimm_spd_address(sysinfo, i),
857 SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000858 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
859 }
860}
861
862static void sdram_program_dram_width(struct sys_info * sysinfo)
863{
864 u16 c0dramw=0, c1dramw=0;
865 int idx;
866
867 if (sysinfo->dual_channel)
868 idx = 2;
869 else
870 idx = 1;
871
872 switch (sysinfo->dimm[0]) {
873 case 0: c0dramw = 0x0000; break; /* x16DS */
874 case 1: c0dramw = 0x0001; break; /* x8DS */
875 case 2: c0dramw = 0x0000; break; /* x16SS */
876 case 3: c0dramw = 0x0005; break; /* x8DDS */
877 case 4: c0dramw = 0x0000; break; /* NC */
878 }
879
880 switch (sysinfo->dimm[idx]) {
881 case 0: c1dramw = 0x0000; break; /* x16DS */
882 case 1: c1dramw = 0x0010; break; /* x8DS */
883 case 2: c1dramw = 0x0000; break; /* x16SS */
884 case 3: c1dramw = 0x0050; break; /* x8DDS */
885 case 4: c1dramw = 0x0000; break; /* NC */
886 }
887
888 if ( !sdram_capabilities_dual_channel() ) {
889 /* Single Channel */
890 c0dramw |= c1dramw;
891 c1dramw = 0;
892 }
893
894 MCHBAR16(C0DRAMW) = c0dramw;
895 MCHBAR16(C1DRAMW) = c1dramw;
896}
897
898static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
899{
900 int i;
901
902 for (i=0; i<16; i++)
903 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
904}
905
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000906static const u32 dq2030[] = {
907 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
908 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
909 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
910 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
911};
912
913static const u32 dq2330[] = {
914 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
915 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
916 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
917 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
918};
919
920static const u32 cmd2710[] = {
921 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
922 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
923 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
924 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
925};
926
927static const u32 cmd3210[] = {
928 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
929 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
930 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
931 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
932};
933
934static const u32 clk2030[] = {
935 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
936 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
937 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
938 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
939};
940
941static const u32 ctl3215[] = {
942 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
943 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
944 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
945 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
946};
947
948static const u32 ctl3220[] = {
949 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
950 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
951 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
952 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
953};
954
955static const u32 nc[] = {
956 0x00000000, 0x00000000, 0x00000000, 0x00000000,
957 0x00000000, 0x00000000, 0x00000000, 0x00000000,
958 0x00000000, 0x00000000, 0x00000000, 0x00000000,
959 0x00000000, 0x00000000, 0x00000000, 0x00000000
960};
961
962enum {
963 DQ2030,
964 DQ2330,
965 CMD2710,
966 CMD3210,
967 CLK2030,
968 CTL3215,
969 CTL3220,
970 NC,
971};
972
973static const u8 dual_channel_slew_group_lookup[] = {
974 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
975 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
976 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
977 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
978 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
979
980 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
981 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
982 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
983 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
984 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
985
986 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
987 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
988 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
989 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
990 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
991
992 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
993 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
994 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
995 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
996 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
997
998 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
999 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1000 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1001 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
1002};
1003
1004static const u8 single_channel_slew_group_lookup[] = {
1005 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1006 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1007 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1008 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1009 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1010
1011 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1012 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1013 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1014 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1015 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1016
1017 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1018 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1019 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1020 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1021 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1022
1023 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1024 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1025 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1026 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1027 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1028
1029 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1030 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1031 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1032 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1033};
1034
1035static const u32 *slew_group_lookup(int dual_channel, int index)
1036{
1037 const u8 *slew_group;
1038 /* Dual Channel needs different tables. */
1039 if (dual_channel)
1040 slew_group = dual_channel_slew_group_lookup;
1041 else
1042 slew_group = single_channel_slew_group_lookup;
1043
1044 switch (slew_group[index]) {
1045 case DQ2030: return dq2030;
1046 case DQ2330: return dq2330;
1047 case CMD2710: return cmd2710;
1048 case CMD3210: return cmd3210;
1049 case CLK2030: return clk2030;
1050 case CTL3215: return ctl3215;
1051 case CTL3220: return ctl3220;
1052 case NC: return nc;
1053 }
1054
1055 return nc;
1056}
1057
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001058#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001059/* Strength multiplier tables */
1060static const u8 dual_channel_strength_multiplier[] = {
1061 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1062 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1063 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1064 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1065 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1066 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1067 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1068 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1069 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1070 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1071 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1072 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1073 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1074 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1075 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1076 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1077 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1078 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1079 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1080 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1082 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1083 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1084 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1085};
1086
1087static const u8 single_channel_strength_multiplier[] = {
1088 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1089 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1090 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1091 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1092 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1093 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1094 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1095 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1096 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1097 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1098 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1099 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1100 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1101 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1102 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1103 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1104 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1105 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1106 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1107 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1108 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1109 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1110 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1111 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1112};
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001113#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001114static const u8 dual_channel_strength_multiplier[] = {
1115 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1116 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1117 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1118 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1119 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1120 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
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, 0x33,
1124 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1125 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
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, 0x33,
1129 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1130 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1131 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1132 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1133 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1134 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1135 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1136 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1137 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1138 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1139};
1140
1141static const u8 single_channel_strength_multiplier[] = {
1142 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1143 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1144 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1145 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1146 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1147 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1148 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1149 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1150 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1151 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1152 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1153 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1154 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1155 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1156 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1157 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1158 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1159 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1160 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1161 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1162 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1163 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1164 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1165 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1166};
1167#endif
1168
Stefan Reinauer278534d2008-10-29 04:51:07 +00001169static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1170{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001171 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001172 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001173
1174 /* Set Strength Multipliers */
1175
1176 /* Dual Channel needs different tables. */
1177 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001178 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001179 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001180 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001181 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1182 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001183 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001184 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001185 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001186 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1187 }
1188
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001189 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001190
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001191 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1192 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1193 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1194 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1195 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1196 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1197 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1198 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001199
1200 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001201 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1202 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1203 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001204
Stefan Reinauer278534d2008-10-29 04:51:07 +00001205 sdram_write_slew_rates(G3SRPUT, ctl3220);
1206 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001207 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001208 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001209 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1210 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1211 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001212
1213 /* Channel 1 */
1214 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001215 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1216 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001217 } else {
1218 sdram_write_slew_rates(G7SRPUT, nc);
1219 sdram_write_slew_rates(G8SRPUT, nc);
1220 }
1221}
1222
1223static void sdram_enable_rcomp(void)
1224{
1225 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001226 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001227 udelay(300);
1228 reg32 = MCHBAR32(GBRCOMPCTL);
1229 reg32 &= ~(1 << 23);
1230 MCHBAR32(GBRCOMPCTL) = reg32;
1231}
1232
1233static void sdram_program_dll_timings(struct sys_info *sysinfo)
1234{
1235 u32 chan0dll = 0, chan1dll = 0;
1236 int i;
1237
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001238 printk(BIOS_DEBUG, "Programming DLL Timings... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001239
Stefan Reinauer278534d2008-10-29 04:51:07 +00001240 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1241 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1242
1243 /* We drive both channels with the same speed */
1244 switch (sysinfo->memory_frequency) {
1245 case 400: chan0dll = 0x26262626; chan1dll=0x26262626; break; /* 400MHz */
1246 case 533: chan0dll = 0x22222222; chan1dll=0x22222222; break; /* 533MHz */
1247 case 667: chan0dll = 0x11111111; chan1dll=0x11111111; break; /* 667MHz */
1248 }
1249
1250 for (i=0; i < 4; i++) {
1251 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1252 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1253 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1254 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1255 }
1256}
1257
1258static void sdram_force_rcomp(void)
1259{
1260 u32 reg32;
1261 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001262
Stefan Reinauer278534d2008-10-29 04:51:07 +00001263 reg32 = MCHBAR32(ODTC);
1264 reg32 |= (1 << 28);
1265 MCHBAR32(ODTC) = reg32;
1266
1267 reg32 = MCHBAR32(SMSRCTL);
1268 reg32 |= (1 << 0);
1269 MCHBAR32(SMSRCTL) = reg32;
1270
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001271 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001272 reg32 = MCHBAR32(GBRCOMPCTL);
1273 reg32 |= (1 << 8);
1274 MCHBAR32(GBRCOMPCTL) = reg32;
1275
1276 reg8 = i945_silicon_revision();
1277 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001278
Stefan Reinauer278534d2008-10-29 04:51:07 +00001279 reg32 = MCHBAR32(GBRCOMPCTL);
1280 reg32 |= (3 << 5);
1281 MCHBAR32(GBRCOMPCTL) = reg32;
1282 }
1283}
1284
1285static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1286{
1287 u8 reg8;
1288 u32 reg32;
1289
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001290 printk(BIOS_DEBUG, "Initializing System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001291 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001292 reg8 = MCHBAR8(C0HCTC);
1293 reg8 &= ~0x1f;
1294 reg8 |= ( 1 << 0);
1295 MCHBAR8(C0HCTC) = reg8;
1296
1297 reg8 = MCHBAR8(C1HCTC);
1298 reg8 &= ~0x1f;
1299 reg8 |= ( 1 << 0);
1300 MCHBAR8(C1HCTC) = reg8;
1301
Stefan Reinauer278534d2008-10-29 04:51:07 +00001302 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1303 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1304
1305 MCHBAR8(C0WDLLCMC) = 0;
1306 MCHBAR8(C1WDLLCMC) = 0;
1307
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001308 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001309 sdram_program_dram_width(sysinfo);
1310
1311 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1312
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001313 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001314 reg32 = MCHBAR32(GBRCOMPCTL);
1315 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1316 reg32 |= (3 << 27) | (3 << 0);
1317 MCHBAR32(GBRCOMPCTL) = reg32;
1318
1319 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1320
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001321 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001322 sdram_program_dll_timings(sysinfo);
1323
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001324 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001325 sdram_force_rcomp();
1326}
1327
1328static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1329{
1330 u32 reg32;
1331
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001332 printk(BIOS_DEBUG, "Enabling System Memory IO... \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001333
Stefan Reinauer278534d2008-10-29 04:51:07 +00001334 reg32 = MCHBAR32(RCVENMT);
1335 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001336 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001337
1338 reg32 |= (1 << 11) | (1 << 9);
1339 MCHBAR32(RCVENMT) = reg32;
1340
1341 reg32 = MCHBAR32(DRTST);
1342 reg32 |= (1 << 3) | (1 << 2);
1343 MCHBAR32(DRTST) = reg32;
1344
1345 reg32 = MCHBAR32(DRTST);
1346 reg32 |= (1 << 6) | (1 << 4);
1347 MCHBAR32(DRTST) = reg32;
1348
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001349 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001350
1351 reg32 = MCHBAR32(DRTST);
1352
1353 /* Is channel 0 populated? */
1354 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1355 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1356 reg32 |= (1 << 7) | (1 << 5);
1357 else
1358 reg32 |= (1 << 31);
1359
1360 /* Is channel 1 populated? */
1361 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1362 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1363 reg32 |= (1 << 9) | (1 << 8);
1364 else
1365 reg32 |= (1 << 30);
1366
1367 MCHBAR32(DRTST) = reg32;
1368
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001369 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001370 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1371 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1372 reg32 = MCHBAR32(C0DRC1);
1373 reg32 |= (1 << 8);
1374 MCHBAR32(C0DRC1) = reg32;
1375 }
1376 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1377 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1378 reg32 = MCHBAR32(C1DRC1);
1379 reg32 |= (1 << 8);
1380 MCHBAR32(C1DRC1) = reg32;
1381 }
1382}
1383
1384struct dimm_size {
1385 unsigned long side1;
1386 unsigned long side2;
1387};
1388
Sven Schnelle541269b2011-02-21 09:39:17 +00001389static struct dimm_size sdram_get_dimm_size(struct sys_info *sysinfo, u16 dimmno)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001390{
1391 /* Calculate the log base 2 size of a DIMM in bits */
1392 struct dimm_size sz;
Sven Schnelle541269b2011-02-21 09:39:17 +00001393 int value, low, rows, columns, device;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001394
Sven Schnelle541269b2011-02-21 09:39:17 +00001395 device = get_dimm_spd_address(sysinfo, dimmno);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001396 sz.side1 = 0;
1397 sz.side2 = 0;
1398
1399 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1400 if (rows < 0) goto hw_err;
1401 if ((rows & 0xf) == 0) goto val_err;
1402 sz.side1 += rows & 0xf;
1403
1404 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1405 if (columns < 0) goto hw_err;
1406 if ((columns & 0xf) == 0) goto val_err;
1407 sz.side1 += columns & 0xf;
1408
1409 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1410 if (value < 0) goto hw_err;
1411 if ((value & 0xff) == 0) goto val_err;
1412 sz.side1 += log2(value & 0xff);
1413
1414 /* Get the module data width and convert it to a power of two */
1415 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1416 if (value < 0) goto hw_err;
1417 value &= 0xff;
1418 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001419
Stefan Reinauer278534d2008-10-29 04:51:07 +00001420 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1421 if (low < 0) goto hw_err;
1422 value = value | (low & 0xff);
1423 if ((value != 72) && (value != 64)) goto val_err;
1424 sz.side1 += log2(value);
1425
1426 /* side 2 */
1427 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1428
1429 if (value < 0) goto hw_err;
1430 value &= 7;
1431 value++;
1432 if (value == 1) goto out;
1433 if (value != 2) goto val_err;
1434
1435 /* Start with the symmetrical case */
1436 sz.side2 = sz.side1;
1437
1438 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1439
1440 /* Don't die here, I have not come across any of these to test what
1441 * actually happens.
1442 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001443 printk(BIOS_ERR, "Assymetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001444
1445 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1446 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1447
1448 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1449 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1450
1451 goto out;
1452
1453 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001454 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001455 hw_err:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001456 /* If a hardware error occurs the spd rom probably does not exist.
1457 * In this case report that there is no memory
1458 */
1459 sz.side1 = 0;
1460 sz.side2 = 0;
Patrick Georgic5fc7db2012-03-07 15:55:47 +01001461out:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001462 return sz;
1463}
1464
1465static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1466{
1467 int i;
1468
1469 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
1470 struct dimm_size sz;
1471
1472 sysinfo->banksize[i * 2] = 0;
1473 sysinfo->banksize[(i * 2) + 1] = 0;
1474
1475 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1476 continue;
1477
Sven Schnelle541269b2011-02-21 09:39:17 +00001478 sz = sdram_get_dimm_size(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001479
Sven Schnelle541269b2011-02-21 09:39:17 +00001480 sysinfo->banks[i] = spd_read_byte(get_dimm_spd_address(sysinfo, i),
1481 SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001482
1483 if (sz.side1 < 30)
1484 die("DDR-II rank size smaller than 128MB is not supported.\n");
1485
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001486 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001487
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001488 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001489
Stefan Reinauer278534d2008-10-29 04:51:07 +00001490 if (!sz.side2)
1491 continue;
1492
1493 /* If there is a second side, it has to have at least 128M, too */
1494 if (sz.side2 < 30)
1495 die("DDR-II rank size smaller than 128MB is not supported.\n");
1496
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001497 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001498
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001499 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001500 }
1501}
1502
1503static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1504{
1505 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001506 int cum0, cum1, tolud, tom;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001507
Paul Menzel84283bc2014-07-17 08:16:04 +02001508 printk(BIOS_DEBUG, "Setting RAM size...\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001509
1510 cum0 = 0;
1511 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001512 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001513 MCHBAR8(C0DRB0+i) = cum0;
1514 }
1515
1516 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1517 cum1 = cum0;
1518
1519 /* Exception: Interleaved starts from the beginning */
1520 if (sysinfo->interleaved)
1521 cum1 = 0;
1522
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001523#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001524 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1525 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1526 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1527 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001528#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001529
1530 for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001531 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001532 MCHBAR8(C1DRB0+i) = cum1;
1533 }
1534
1535 /* Set TOLUD Top Of Low Usable DRAM */
1536 if (sysinfo->interleaved)
1537 tolud = (cum0 + cum1) << 1;
1538 else
1539 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001540
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001541 /* The TOM register has a different format */
1542 tom = tolud >> 3;
1543
1544 /* Limit the value of TOLUD to leave some space for PCI memory. */
1545 if (tolud > 0xd0)
1546 tolud = 0xd0; /* 3.25GB : 0.75GB */
1547
1548 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1549
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001550 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1551 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1552 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001553
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001554 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001555
1556 return 0;
1557}
1558
Stefan Reinauer278534d2008-10-29 04:51:07 +00001559static int sdram_set_row_attributes(struct sys_info *sysinfo)
1560{
1561 int i, value;
1562 u16 dra0=0, dra1=0, dra = 0;
1563
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001564 printk(BIOS_DEBUG, "Setting row attributes... \n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001565 for(i=0; i < 2 * DIMM_SOCKETS; i++) {
1566 u16 device;
1567 u8 columnsrows;
1568
1569 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1570 continue;
1571 }
1572
Sven Schnelle541269b2011-02-21 09:39:17 +00001573 device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001574
1575 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1576 columnsrows = (value & 0x0f);
1577
1578 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1579 columnsrows |= (value & 0xf) << 4;
1580
1581 switch (columnsrows) {
1582 case 0x9d: dra = 2; break;
1583 case 0xad: dra = 3; break;
1584 case 0xbd: dra = 4; break;
1585 case 0xae: dra = 3; break;
1586 case 0xbe: dra = 4; break;
1587 default: die("Unsupported Rows/Columns. (DRA)");
1588 }
1589
1590 /* Double Sided DIMMs? */
1591 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1592 dra = (dra << 4) | dra;
1593 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001594
Stefan Reinauer278534d2008-10-29 04:51:07 +00001595 if (i < DIMM_SOCKETS)
1596 dra0 |= (dra << (i*8));
1597 else
1598 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1599 }
1600
1601 MCHBAR16(C0DRA0) = dra0;
1602 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001603
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001604 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1605 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001606
1607 return 0;
1608}
1609
1610static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1611{
1612 u32 off32;
1613 int i;
1614
1615 MCHBAR16(C1BNKARC) &= 0xff00;
1616 MCHBAR16(C0BNKARC) &= 0xff00;
1617
1618 off32 = C0BNKARC;
1619 for (i=0; i < 2 * DIMM_SOCKETS; i++) {
1620 /* Switch to second channel */
1621 if (i == DIMM_SOCKETS)
1622 off32 = C1BNKARC;
1623
1624 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1625 continue;
1626
1627 if (sysinfo->banks[i] != 8)
1628 continue;
1629
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001630 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001631
1632 if (i & 1)
1633 MCHBAR16(off32) |= 0x50;
1634 else
1635 MCHBAR16(off32) |= 0x05;
1636 }
1637}
1638
1639#define REFRESH_7_8US 1
1640#define REFRESH_15_6US 0
1641static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1642{
1643 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001644
Stefan Reinauer278534d2008-10-29 04:51:07 +00001645 if (sysinfo->refresh == REFRESH_7_8US) {
1646 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1647 } else {
1648 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1649 }
1650
1651 MCHBAR32(C0DRC0) &= ~(7 << 8);
1652 MCHBAR32(C0DRC0) |= reg32;
1653
1654 MCHBAR32(C1DRC0) &= ~(7 << 8);
1655 MCHBAR32(C1DRC0) |= reg32;
1656}
1657
1658static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1659{
1660 u32 reg32;
1661 int i;
1662
1663 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001664
Stefan Reinauer278534d2008-10-29 04:51:07 +00001665 for (i=0; i < 4; i++) {
1666 if (sysinfo->banksize[i] == 0) {
1667 reg32 |= (1 << (16 + i));
1668 }
1669 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001670
Stefan Reinauer278534d2008-10-29 04:51:07 +00001671 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001672
Stefan Reinauer278534d2008-10-29 04:51:07 +00001673 reg32 |= (1 << 11);
1674 MCHBAR32(C0DRC1) = reg32;
1675
1676 /* Do we have to do this if we're in Single Channel Mode? */
1677 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001678
Stefan Reinauer278534d2008-10-29 04:51:07 +00001679 for (i=4; i < 8; i++) {
1680 if (sysinfo->banksize[i] == 0) {
1681 reg32 |= (1 << (12 + i));
1682 }
1683 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001684
Stefan Reinauer278534d2008-10-29 04:51:07 +00001685 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001686
Stefan Reinauer278534d2008-10-29 04:51:07 +00001687 reg32 |= (1 << 11);
1688 MCHBAR32(C1DRC1) = reg32;
1689}
1690
1691static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1692{
1693 u32 reg32;
1694 int i;
1695
1696 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001697
Stefan Reinauer278534d2008-10-29 04:51:07 +00001698 for (i=0; i < 4; i++) {
1699 if (sysinfo->banksize[i] == 0) {
1700 reg32 |= (1 << (24 + i));
1701 }
1702 }
1703 MCHBAR32(C0DRC2) = reg32;
1704
1705 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001706
Stefan Reinauer278534d2008-10-29 04:51:07 +00001707 for (i=4; i < 8; i++) {
1708 if (sysinfo->banksize[i] == 0) {
1709 reg32 |= (1 << (20 + i));
1710 }
1711 }
1712 MCHBAR32(C1DRC2) = reg32;
1713}
1714
1715static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1716{
1717 u32 reg32, off32;
1718 u32 tWTR;
1719 u32 temp_drt;
1720 int i, page_size;
1721
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001722 static const u8 drt0_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001723 /* CL 3, 4, 5 */
1724 3, 4, 5, /* FSB533/400, DDR533/400 */
1725 4, 5, 6, /* FSB667, DDR533/400 */
1726 4, 5, 6, /* FSB667, DDR667 */
1727 };
1728
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001729 static const u8 cas_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001730 2, 1, 0, 3
1731 };
1732
1733 reg32 = MCHBAR32(C0DRC0);
1734 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001735 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001736 MCHBAR32(C0DRC0) = reg32;
1737
1738 reg32 = MCHBAR32(C1DRC0);
1739 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001740 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001741 MCHBAR32(C1DRC0) = reg32;
1742
1743 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1744 SYSINFO_DIMM_NOT_POPULATED) {
1745 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001746 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001747 MCHBAR32(C0DRC0) = reg32;
1748 }
1749
1750 sdram_program_refresh_rate(sysinfo);
1751
1752 sdram_program_cke_tristate(sysinfo);
1753
1754 sdram_program_odt_tristate(sysinfo);
1755
1756 /* Calculate DRT0 */
1757
1758 temp_drt = 0;
1759
1760 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1761 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1762 temp_drt |= (reg32 << 28);
1763
1764 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1765 reg32 += sysinfo->trp;
1766 temp_drt |= (reg32 << 4);
1767
1768 if (sysinfo->memory_frequency == 667) {
1769 tWTR = 3; /* 667MHz */
1770 } else {
1771 tWTR = 2; /* 400 and 533 */
1772 }
1773
1774 /* B2B Write to Read Command Spacing */
1775 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1776 temp_drt |= (reg32 << 24);
1777
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001778 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001779 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1780
1781 /* Program Write Auto Precharge to Activate */
1782 off32 = 0;
1783 if (sysinfo->fsb_frequency == 667) { /* 667MHz FSB */
1784 off32 += 3;
1785 }
1786 if (sysinfo->memory_frequency == 667) {
1787 off32 += 3;
1788 }
1789 off32 += sysinfo->cas - 3;
1790 reg32 = drt0_table[off32];
1791 temp_drt |= (reg32 << 11);
1792
1793 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001794
Stefan Reinauer278534d2008-10-29 04:51:07 +00001795 temp_drt |= (8 << 0);
1796
1797 MCHBAR32(C0DRT0) = temp_drt;
1798 MCHBAR32(C1DRT0) = temp_drt;
1799
1800 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001801
Stefan Reinauer278534d2008-10-29 04:51:07 +00001802 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1803
1804 /* DRAM RASB Precharge */
1805 temp_drt |= (sysinfo->trp - 2) << 0;
1806
1807 /* DRAM RASB to CASB Delay */
1808 temp_drt |= (sysinfo->trcd - 2) << 4;
1809
1810 /* CASB Latency */
1811 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1812
1813 /* Refresh Cycle Time */
1814 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001815
Stefan Reinauer278534d2008-10-29 04:51:07 +00001816 /* Pre-All to Activate Delay */
1817 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001818
Stefan Reinauer278534d2008-10-29 04:51:07 +00001819 /* Precharge to Precharge Delay stays at 1 clock */
1820 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001821
Stefan Reinauer278534d2008-10-29 04:51:07 +00001822 /* Activate to Precharge Delay */
1823 temp_drt |= (sysinfo->tras << 19);
1824
1825 /* Read to Precharge (tRTP) */
1826 if (sysinfo->memory_frequency == 667) {
1827 temp_drt |= (1 << 28);
1828 } else {
1829 temp_drt |= (0 << 28);
1830 }
1831
1832 /* Determine page size */
1833 reg32 = 0;
1834 page_size = 1; /* Default: 1k pagesize */
1835 for (i=0; i< 2*DIMM_SOCKETS; i++) {
1836 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1837 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1838 page_size = 2; /* 2k pagesize */
1839 }
1840
1841 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1842 reg32 = 1;
1843 }
1844 if (sysinfo->memory_frequency == 667) {
1845 reg32 = page_size;
1846 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001847
Stefan Reinauer278534d2008-10-29 04:51:07 +00001848 temp_drt |= (reg32 << 30);
1849
1850 MCHBAR32(C0DRT1) = temp_drt;
1851 MCHBAR32(C1DRT1) = temp_drt;
1852
1853 /* Program DRT2 */
1854 reg32 = MCHBAR32(C0DRT2);
1855 reg32 &= ~(1 << 8);
1856 MCHBAR32(C0DRT2) = reg32;
1857
1858 reg32 = MCHBAR32(C1DRT2);
1859 reg32 &= ~(1 << 8);
1860 MCHBAR32(C1DRT2) = reg32;
1861
1862 /* Calculate DRT3 */
1863 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1864
1865 /* Get old tRFC value */
1866 reg32 = MCHBAR32(C0DRT1) >> 10;
1867 reg32 &= 0x3f;
1868
1869 /* 788nS - tRFC */
1870 switch (sysinfo->memory_frequency) {
1871 case 400: /* 5nS */
1872 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1873 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1874 break;
1875 case 533: /* 3.75nS */
1876 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1877 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1878 break;
1879 case 667: /* 3nS */
1880 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1881 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1882 break;
1883 }
1884
1885 temp_drt |= reg32;
1886
1887 MCHBAR32(C0DRT3) = temp_drt;
1888 MCHBAR32(C1DRT3) = temp_drt;
1889}
1890
1891static void sdram_set_channel_mode(struct sys_info *sysinfo)
1892{
1893 u32 reg32;
1894
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001895 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001896
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001897 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001898 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1899 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1900 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1901 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1902 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001903 sysinfo->interleaved = 1;
1904 } else {
1905 sysinfo->interleaved = 0;
1906 }
1907
1908 reg32 = MCHBAR32(DCC);
1909 reg32 &= ~(7 << 0);
1910
1911 if(sysinfo->interleaved) {
1912 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001913 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001914 reg32 |= (1 << 1);
1915 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1916 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1917 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001918 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001919 reg32 |= (1 << 2);
1920 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1921 SYSINFO_DIMM_NOT_POPULATED) {
1922 /* Dual Channel Assymetric */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001923 printk(BIOS_DEBUG, "Dual Channel Assymetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001924 reg32 |= (1 << 0);
1925 } else {
1926 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001927 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001928 }
1929
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001930 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001931 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001932
1933 MCHBAR32(DCC) = reg32;
1934
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001935 PRINTK_DEBUG("DCC=0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001936}
1937
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001938static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001939{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001940 MCHBAR32(PLLMON) = 0x80800000;
1941
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001942 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001943 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001944 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001945
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001946 /* Program CPCTL according to FSB speed */
1947 /* Only write the lower byte */
1948 switch (sysinfo->fsb_frequency) {
1949 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1950 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1951 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1952 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001953
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001954 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001955
Paul Menzel0ce5ebf2013-10-21 21:22:09 +02001956 MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001957}
1958
1959static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1960{
1961 u8 reg8;
1962 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001963 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001964
1965#define CRCLK_166MHz 0x00
1966#define CRCLK_200MHz 0x01
1967#define CRCLK_250MHz 0x03
1968#define CRCLK_400MHz 0x05
1969
1970#define CDCLK_200MHz 0x00
1971#define CDCLK_320MHz 0x40
1972
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001973#define VOLTAGE_1_05 0x00
1974#define VOLTAGE_1_50 0x01
1975
Paul Menzeldaf9e502014-07-15 23:49:16 +02001976 printk(BIOS_DEBUG, "Setting Graphics Frequency...\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001977
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001978 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001979
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001980 voltage = VOLTAGE_1_05;
1981 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
1982 voltage = VOLTAGE_1_50;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001983 printk(BIOS_DEBUG, "Voltage: %s ", (voltage==VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001984
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001985 /* Gate graphics hardware for frequency change */
1986 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
1987 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
1988 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001989
1990 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001991 reg8 = sdram_capabilities_core_frequencies();
1992
Stefan Reinauer278534d2008-10-29 04:51:07 +00001993 freq = CRCLK_250MHz;
1994 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001995 case GFX_FREQUENCY_CAP_ALL:
1996 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001997 freq = CRCLK_250MHz;
1998 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001999 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002000 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002001 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2002 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2003 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002004 }
2005
2006 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002007 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002008 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
2009 if (reg8==2)
2010 freq = CRCLK_166MHz;
2011 }
2012
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002013 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002014 switch (freq) {
Elyes HAOUAS0f92f632014-07-27 19:37:31 +02002015 case CRCLK_166MHz: printk(BIOS_DEBUG, "166MHz"); break;
2016 case CRCLK_200MHz: printk(BIOS_DEBUG, "200MHz"); break;
2017 case CRCLK_250MHz: printk(BIOS_DEBUG, "250MHz"); break;
2018 case CRCLK_400MHz: printk(BIOS_DEBUG, "400MHz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002019 }
2020
Stefan Reinauer278534d2008-10-29 04:51:07 +00002021 if (i945_silicon_revision() == 0) {
2022 sysinfo->mvco4x = 1;
2023 } else {
2024 sysinfo->mvco4x = 0;
2025 }
2026
Stefan Reinauer278534d2008-10-29 04:51:07 +00002027 second_vco = 0;
2028
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002029 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002030 second_vco = 1;
2031 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2032 u16 mem = sysinfo->memory_frequency;
2033 u16 fsb = sysinfo->fsb_frequency;
2034
2035 if ( (fsb == 667 && mem == 533) ||
2036 (fsb == 533 && mem == 533) ||
2037 (fsb == 533 && mem == 400)) {
2038 second_vco = 1;
2039 }
2040
2041 if (fsb == 667 && mem == 533)
2042 sysinfo->mvco4x = 1;
2043 }
2044
2045 if (second_vco) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002046 sysinfo->clkcfg_bit7=1;
2047 } else {
2048 sysinfo->clkcfg_bit7=0;
2049 }
2050
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002051 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002052 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2053 reg16 &= ~( (7 << 0) | (1 << 13) );
2054 reg16 |= freq;
2055 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2056
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002057 /* Graphics Core Display Clock */
2058 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2059 reg8 &= ~( (1<<7) | (7<<4) );
2060
2061 if (voltage == VOLTAGE_1_05) {
2062 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002063 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002064 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002065 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002066 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002067 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002068 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002069
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002070 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002071
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002072 reg8 |= (1<<3) | (1<<1);
2073 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2074
2075 reg8 |= 0x0f;
2076 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2077
2078 /* Ungate core render and display clocks */
2079 reg8 &= 0xf0;
2080 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002081}
2082
2083static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2084{
2085 u32 clkcfg;
2086 u8 reg8;
2087
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002088 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002089
Stefan Reinauer278534d2008-10-29 04:51:07 +00002090 clkcfg = MCHBAR32(CLKCFG);
2091
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002092 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002093
2094 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2095
2096 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002097 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002098 clkcfg &= ~(1 << 12);
2099 }
2100
2101 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002102 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002103
Stefan Reinauer278534d2008-10-29 04:51:07 +00002104 clkcfg |= (1 << 7);
2105 }
2106
2107 switch (sysinfo->memory_frequency) {
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002108 case 400: clkcfg |= (2 << 4); break;
2109 case 533: clkcfg |= (3 << 4); break;
2110 case 667: clkcfg |= (4 << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002111 default: die("Target Memory Frequency Error");
2112 }
2113
2114 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002115 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002116 return;
2117 }
2118
2119 MCHBAR32(CLKCFG) = clkcfg;
2120
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002121 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002122 * cache before we execute it.
2123 */
2124 goto cache_code;
2125vco_update:
2126 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2127 reg8 &= ~(1 << 7);
2128 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2129
Stefan Reinauer278534d2008-10-29 04:51:07 +00002130 clkcfg &= ~(1 << 10);
2131 MCHBAR32(CLKCFG) = clkcfg;
2132 clkcfg |= (1 << 10);
2133 MCHBAR32(CLKCFG) = clkcfg;
2134
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002135 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002136 " movl $0x100, %%ecx\n"
2137 "delay_update:\n"
2138 " nop\n"
2139 " nop\n"
2140 " nop\n"
2141 " nop\n"
2142 " loop delay_update\n"
2143 : /* No outputs */
2144 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002145 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002146 );
2147
Stefan Reinauer278534d2008-10-29 04:51:07 +00002148 clkcfg &= ~(1 << 10);
2149 MCHBAR32(CLKCFG) = clkcfg;
2150
2151 goto out;
2152cache_code:
2153 goto vco_update;
2154out:
2155
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002156 printk(BIOS_DEBUG, "CLKCFG=0x%08x, ", MCHBAR32(CLKCFG));
2157 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002158}
2159
2160static void sdram_program_clock_crossing(void)
2161{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002162 int idx = 0;
2163
2164 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002165 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002166 */
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002167#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002168 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002169 0x00100401, 0x00000000, /* DDR400 FSB400 */
Martin Roth2ed0aa22016-01-05 20:58:58 -07002170 0xffffffff, 0xffffffff, /* nonexistent */
2171 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002172
Stefan Reinauer278534d2008-10-29 04:51:07 +00002173 0x08040120, 0x00000000, /* DDR400 FSB533 */
2174 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002175 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002176
2177 0x04020120, 0x00000010, /* DDR400 FSB667 */
2178 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002179 0x00100401, 0x00000000, /* DDR667 FSB667 */
2180
Martin Roth2ed0aa22016-01-05 20:58:58 -07002181 0xffffffff, 0xffffffff, /* nonexistent */
2182 0xffffffff, 0xffffffff, /* nonexistent */
2183 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002184
Martin Roth2ed0aa22016-01-05 20:58:58 -07002185 0xffffffff, 0xffffffff, /* nonexistent */
2186 0xffffffff, 0xffffffff, /* nonexistent */
2187 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002188 };
2189
2190 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002191 0x04020208, 0x00000000, /* DDR400 FSB400 */
Martin Roth2ed0aa22016-01-05 20:58:58 -07002192 0xffffffff, 0xffffffff, /* nonexistent */
2193 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002194
Stefan Reinauer278534d2008-10-29 04:51:07 +00002195 0x00060108, 0x00000000, /* DDR400 FSB533 */
2196 0x04020108, 0x00000000, /* DDR533 FSB533 */
Martin Roth2ed0aa22016-01-05 20:58:58 -07002197 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002198
2199 0x00040318, 0x00000000, /* DDR400 FSB667 */
2200 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002201 0x02010804, 0x00000000, /* DDR667 FSB667 */
2202
Martin Roth2ed0aa22016-01-05 20:58:58 -07002203 0xffffffff, 0xffffffff, /* nonexistent */
2204 0xffffffff, 0xffffffff, /* nonexistent */
2205 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002206
Martin Roth2ed0aa22016-01-05 20:58:58 -07002207 0xffffffff, 0xffffffff, /* nonexistent */
2208 0xffffffff, 0xffffffff, /* nonexistent */
2209 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002210 };
2211
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002212#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002213 /* i945 G/P */
2214 static const u32 data_clock_crossing[] = {
Martin Roth2ed0aa22016-01-05 20:58:58 -07002215 0xffffffff, 0xffffffff, /* nonexistent */
2216 0xffffffff, 0xffffffff, /* nonexistent */
2217 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002218
2219 0x10080201, 0x00000000, /* DDR400 FSB533 */
2220 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002221 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002222
Martin Roth2ed0aa22016-01-05 20:58:58 -07002223 0xffffffff, 0xffffffff, /* nonexistent */
2224 0xffffffff, 0xffffffff, /* nonexistent */
2225 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002226
2227 0x04020108, 0x00000000, /* DDR400 FSB800 */
2228 0x00020108, 0x00000000, /* DDR533 FSB800 */
2229 0x00080201, 0x00000000, /* DDR667 FSB800 */
2230
2231 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2232 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2233 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2234 };
2235
2236 static const u32 command_clock_crossing[] = {
Martin Roth2ed0aa22016-01-05 20:58:58 -07002237 0xffffffff, 0xffffffff, /* nonexistent */
2238 0xffffffff, 0xffffffff, /* nonexistent */
2239 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002240
2241 0x00010800, 0x00000402, /* DDR400 FSB533 */
2242 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002243 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002244
Martin Roth2ed0aa22016-01-05 20:58:58 -07002245 0xffffffff, 0xffffffff, /* nonexistent */
2246 0xffffffff, 0xffffffff, /* nonexistent */
2247 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002248
2249 0x02010804, 0x00000000, /* DDR400 FSB800 */
2250 0x00010402, 0x00000000, /* DDR533 FSB800 */
2251 0x04020180, 0x00000008, /* DDR667 FSB800 */
2252
2253 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2254 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2255 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2256 };
2257#endif
2258
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002259 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002260
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002261 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002262 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002263 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2264 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2265 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2266 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002267 }
2268
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002269 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002270 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002271 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2272 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2273 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2274 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2275 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2276 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002277 }
2278
2279 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002280 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002281 }
2282
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002283 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2284 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2285
Stefan Reinauer278534d2008-10-29 04:51:07 +00002286 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2287 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2288 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2289 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2290
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002291 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002292}
2293
2294static void sdram_disable_fast_dispatch(void)
2295{
2296 u32 reg32;
2297
2298 reg32 = MCHBAR32(FSBPMC3);
2299 reg32 |= (1 << 1);
2300 MCHBAR32(FSBPMC3) = reg32;
2301
2302 reg32 = MCHBAR32(SBTEST);
2303 reg32 |= (3 << 1);
2304 MCHBAR32(SBTEST) = reg32;
2305}
2306
2307static void sdram_pre_jedec_initialization(void)
2308{
2309 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002310
Stefan Reinauer278534d2008-10-29 04:51:07 +00002311 reg32 = MCHBAR32(WCC);
2312 reg32 &= 0x113ff3ff;
2313 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2314 MCHBAR32(WCC) = reg32;
2315
2316 MCHBAR32(SMVREFC) |= (1 << 6);
2317
2318 MCHBAR32(MMARB0) &= ~(3 << 17);
2319 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2320
2321 MCHBAR32(MMARB1) &= ~(7 << 8);
2322 MCHBAR32(MMARB1) |= (3 << 8);
2323
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002324 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002325 MCHBAR32(C0AIT) = 0x000006c4;
2326 MCHBAR32(C0AIT+4) = 0x871a066d;
2327
2328 MCHBAR32(C1AIT) = 0x000006c4;
2329 MCHBAR32(C1AIT+4) = 0x871a066d;
2330}
2331
2332#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2333#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2334#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2335#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2336#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2337#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2338#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2339#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2340
2341static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2342{
2343 u32 chan0 = 0, chan1 = 0;
2344 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2345
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002346 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002347 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002348 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002349 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2350 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2351 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2352
2353 if (sdram_capabilities_enhanced_addressing_xor()) {
2354 if (!sysinfo->interleaved) {
2355 /* Single Channel & Dual Channel Assymetric */
2356 if (chan0_populated) {
2357 if (chan0_dualsided) {
2358 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2359 } else {
2360 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2361 }
2362 }
2363 if (chan1_populated) {
2364 if (chan1_dualsided) {
2365 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2366 } else {
2367 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2368 }
2369 }
2370 } else {
2371 /* Interleaved has always both channels populated */
2372 if (chan0_dualsided) {
2373 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2374 } else {
2375 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2376 }
2377
2378 if (chan1_dualsided) {
2379 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2380 } else {
2381 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2382 }
2383 }
2384 } else {
2385 if (!sysinfo->interleaved) {
2386 /* Single Channel & Dual Channel Assymetric */
2387 if (chan0_populated) {
2388 if (chan0_dualsided) {
2389 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2390 } else {
2391 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2392 }
2393 }
2394 if (chan1_populated) {
2395 if (chan1_dualsided) {
2396 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2397 } else {
2398 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2399 }
2400 }
2401 } else {
2402 /* Interleaved has always both channels populated */
2403 if (chan0_dualsided) {
2404 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2405 } else {
2406 chan0 = EA_DUALCHANNEL_BANK_MODE;
2407 }
2408
2409 if (chan1_dualsided) {
2410 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2411 } else {
2412 chan1 = EA_DUALCHANNEL_BANK_MODE;
2413 }
2414 }
2415 }
2416
2417 MCHBAR32(C0DRC1) &= 0x00ffffff;
2418 MCHBAR32(C0DRC1) |= chan0;
2419 MCHBAR32(C1DRC1) &= 0x00ffffff;
2420 MCHBAR32(C1DRC1) |= chan1;
2421}
2422
2423static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2424{
2425 u32 reg32;
2426
2427 /* Enable Channel XORing for Dual Channel Interleave */
2428 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002429
Stefan Reinauer278534d2008-10-29 04:51:07 +00002430 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002431#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002432 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002433 reg32 |= (1 << 9);
2434#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002435 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002436#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002437 MCHBAR32(DCC) = reg32;
2438 }
2439
2440 /* DRAM mode optimizations */
2441 sdram_enhanced_addressing_mode(sysinfo);
2442
2443 reg32 = MCHBAR32(FSBPMC3);
2444 reg32 &= ~(1 << 1);
2445 MCHBAR32(FSBPMC3) = reg32;
2446
2447 reg32 = MCHBAR32(SBTEST);
2448 reg32 &= ~(1 << 2);
2449 MCHBAR32(SBTEST) = reg32;
2450
2451 reg32 = MCHBAR32(SBOCC);
2452 reg32 &= 0xffbdb6ff;
2453 reg32 |= (0xbdb6 << 8) | (1 << 0);
2454 MCHBAR32(SBOCC) = reg32;
2455}
2456
2457static void sdram_power_management(struct sys_info *sysinfo)
2458{
2459 u8 reg8;
2460 u16 reg16;
2461 u32 reg32;
2462 int integrated_graphics = 1;
2463 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002464
Stefan Reinauer278534d2008-10-29 04:51:07 +00002465 reg32 = MCHBAR32(C0DRT2);
2466 reg32 &= 0xffffff00;
2467 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002468 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002469 MCHBAR32(C0DRT2) = reg32;
2470
2471 reg32 = MCHBAR32(C1DRT2);
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(C1DRT2) = reg32;
2476
2477 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002478
2479 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002480 MCHBAR32(C0DRC1) = reg32;
2481
2482 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002483
2484 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002485 MCHBAR32(C1DRC1) = reg32;
2486
2487 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002488 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2489 u16 peg_bits = (1 << 5) | (1 << 0);
2490
2491 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002492 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002493 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2494 u16 peg_bits = (1 << 5) | (1 << 0);
2495
Stefan Reinauer278534d2008-10-29 04:51:07 +00002496 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002497 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002498 }
2499
2500 reg16 = MCHBAR16(UPMC2);
2501 reg16 &= 0xfc00;
2502 reg16 |= 0x0100;
2503 MCHBAR16(UPMC2) = reg16;
2504
2505 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002506
Stefan Reinauer278534d2008-10-29 04:51:07 +00002507 for (i=0; i<5; i++) {
2508 MCHBAR32(UPMC3) &= ~(1 << 16);
2509 MCHBAR32(UPMC3) |= (1 << 16);
2510 }
2511
2512 MCHBAR32(GIPMC1) = 0x8000000c;
2513
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002514 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002515 reg16 &= ~(7 << 11);
2516 if (i945_silicon_revision()>2) {
2517 reg16 |= (6 << 11);
2518 } else {
2519 reg16 |= (4 << 11);
2520 }
2521 MCHBAR16(CPCTL) = reg16;
2522
Stefan Reinauer30140a52009-03-11 16:20:39 +00002523#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002524 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002525#else
2526 if (i945_silicon_revision() != 0) {
2527#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002528 switch (sysinfo->fsb_frequency) {
2529 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2530 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2531 }
2532 } else {
2533 switch (sysinfo->fsb_frequency) {
2534 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2535 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2536 }
2537 }
2538
2539 MCHBAR32(FSBPMC1) = 0x8000000c;
2540
2541 reg32 = MCHBAR32(C2C3TT);
2542 reg32 &= 0xffff0000;
2543 switch (sysinfo->fsb_frequency) {
2544 case 667: reg32 |= 0x0600; break;
2545 case 533: reg32 |= 0x0480; break;
2546 }
2547 MCHBAR32(C2C3TT) = reg32;
2548
2549 reg32 = MCHBAR32(C3C4TT);
2550 reg32 &= 0xffff0000;
2551 switch (sysinfo->fsb_frequency) {
2552 case 667: reg32 |= 0x0b80; break;
2553 case 533: reg32 |= 0x0980; break;
2554 }
2555 MCHBAR32(C3C4TT) = reg32;
2556
2557 if (i945_silicon_revision() == 0) {
2558 MCHBAR32(ECO) &= ~(1 << 16);
2559 } else {
2560 MCHBAR32(ECO) |= (1 << 16);
2561 }
2562
2563#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002564
Stefan Reinauer278534d2008-10-29 04:51:07 +00002565 if (i945_silicon_revision() == 0) {
2566 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2567 } else {
2568 MCHBAR32(FSBPMC3) |= (1 << 29);
2569 }
2570#endif
2571 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2572
2573 MCHBAR32(FSBPMC3) |= (1 << 21);
2574
2575 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2576
2577 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2578
2579 reg32 = MCHBAR32(FSBPMC4);
2580 reg32 &= ~(3 << 24);
2581 reg32 |= ( 2 << 24);
2582 MCHBAR32(FSBPMC4) = reg32;
2583
2584 MCHBAR32(FSBPMC4) |= (1 << 21);
2585
2586 MCHBAR32(FSBPMC4) |= (1 << 5);
2587
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002588 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2589 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002590 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2591 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002592 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002593 }
2594
2595 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2596 reg8 |= (1 << 4);
2597 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2598
2599 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2600 reg8 |= (1 << 2);
2601 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2602
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002603#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002604
Stefan Reinauer278534d2008-10-29 04:51:07 +00002605 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002606 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002607 MCHBAR16(MIPMC4) = 0x0468;
2608 MCHBAR16(MIPMC5) = 0x046c;
2609 MCHBAR16(MIPMC6) = 0x046c;
2610 } else {
2611 MCHBAR16(MIPMC4) = 0x6468;
2612 MCHBAR16(MIPMC5) = 0x646c;
2613 MCHBAR16(MIPMC6) = 0x646c;
2614 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002615#else
2616 if (integrated_graphics) {
2617 MCHBAR16(MIPMC4) = 0x04f8;
2618 MCHBAR16(MIPMC5) = 0x04fc;
2619 MCHBAR16(MIPMC6) = 0x04fc;
2620 } else {
2621 MCHBAR16(MIPMC4) = 0x64f8;
2622 MCHBAR16(MIPMC5) = 0x64fc;
2623 MCHBAR16(MIPMC6) = 0x64fc;
2624 }
2625
2626#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002627
2628 reg32 = MCHBAR32(PMCFG);
2629 reg32 &= ~(3 << 17);
2630 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002631 MCHBAR32(PMCFG) = reg32;
2632
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002633 MCHBAR32(PMCFG) |= (1 << 4);
2634
Stefan Reinauer278534d2008-10-29 04:51:07 +00002635 reg32 = MCHBAR32(0xc30);
2636 reg32 &= 0xffffff00;
2637 reg32 |= 0x01;
2638 MCHBAR32(0xc30) = reg32;
2639
2640 MCHBAR32(0xb18) &= ~(1 << 21);
2641}
2642
2643static void sdram_thermal_management(void)
2644{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002645
Stefan Reinauer278534d2008-10-29 04:51:07 +00002646 MCHBAR8(TCO1) = 0x00;
2647 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002648
2649 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2650 * 0x30/0x32.
2651 */
2652
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002653 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002654}
2655
2656static void sdram_save_receive_enable(void)
2657{
2658 int i;
2659 u32 reg32;
2660 u8 values[4];
2661
2662 /* The following values are stored to an unused CMOS
2663 * area and restored instead of recalculated in case
2664 * of an S3 resume.
2665 *
2666 * C0WL0REOST [7:0] -> 8 bit
2667 * C1WL0REOST [7:0] -> 8 bit
2668 * RCVENMT [11:8] [3:0] -> 8 bit
2669 * C0DRT1 [27:24] -> 4 bit
2670 * C1DRT1 [27:24] -> 4 bit
2671 */
2672
2673 values[0] = MCHBAR8(C0WL0REOST);
2674 values[1] = MCHBAR8(C1WL0REOST);
2675
2676 reg32 = MCHBAR32(RCVENMT);
2677 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2678
2679 reg32 = MCHBAR32(C0DRT1);
2680 values[3] = (reg32 >> 24) & 0x0f;
2681 reg32 = MCHBAR32(C1DRT1);
2682 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2683
2684 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002685 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002686 */
2687
2688 for (i=0; i<4; i++)
2689 cmos_write(values[i], 128 + i);
2690}
2691
2692static void sdram_recover_receive_enable(void)
2693{
2694 int i;
2695 u32 reg32;
2696 u8 values[4];
2697
2698 for (i=0; i<4; i++)
2699 values[i] = cmos_read(128 + i);
2700
2701 MCHBAR8(C0WL0REOST) = values[0];
2702 MCHBAR8(C1WL0REOST) = values[1];
2703
2704 reg32 = MCHBAR32(RCVENMT);
2705 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2706 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2707 MCHBAR32(RCVENMT) = reg32;
2708
2709 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2710 reg32 |= (u32)(values[3] & 0x0f) << 24;
2711 MCHBAR32(C0DRT1) = reg32;
2712
2713 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2714 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2715 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002716}
2717
2718#include "rcven.c"
2719
2720static void sdram_program_receive_enable(struct sys_info *sysinfo)
2721{
2722 MCHBAR32(REPC) |= (1 << 0);
2723
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002724 /* enable upper CMOS */
2725 RCBA32(0x3400) = (1 << 2);
2726
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002727 /* Program Receive Enable Timings */
2728 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2729 sdram_recover_receive_enable();
2730 } else {
2731 receive_enable_adjust(sysinfo);
2732 sdram_save_receive_enable();
2733 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002734
2735 MCHBAR32(C0DRC1) |= (1 << 6);
2736 MCHBAR32(C1DRC1) |= (1 << 6);
2737 MCHBAR32(C0DRC1) &= ~(1 << 6);
2738 MCHBAR32(C1DRC1) &= ~(1 << 6);
2739
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002740 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002741}
2742
2743/**
2744 * @brief Enable On-Die Termination for DDR2.
2745 *
2746 */
2747
2748static void sdram_on_die_termination(struct sys_info *sysinfo)
2749{
2750 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002751 0x00024911, 0xe0010000,
2752 0x00049211, 0xe0020000,
2753 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002754 };
2755
2756 u32 reg32;
2757 int cas;
2758
2759 reg32 = MCHBAR32(ODTC);
2760 reg32 &= ~(3 << 16);
2761 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2762 MCHBAR32(ODTC) = reg32;
2763
2764 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2765 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002766 printk(BIOS_DEBUG, "one dimm per channel config.. \n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002767
Stefan Reinauer278534d2008-10-29 04:51:07 +00002768 reg32 = MCHBAR32(C0ODT);
2769 reg32 &= ~(7 << 28);
2770 MCHBAR32(C0ODT) = reg32;
2771 reg32 = MCHBAR32(C1ODT);
2772 reg32 &= ~(7 << 28);
2773 MCHBAR32(C1ODT) = reg32;
2774 }
2775
2776 cas = sysinfo->cas;
2777
2778 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2779 reg32 |= odt[(cas-3) * 2];
2780 MCHBAR32(C0ODT) = reg32;
2781
2782 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2783 reg32 |= odt[(cas-3) * 2];
2784 MCHBAR32(C1ODT) = reg32;
2785
2786 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2787 reg32 |= odt[((cas-3) * 2) + 1];
2788 MCHBAR32(C0ODT + 4) = reg32;
2789
2790 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2791 reg32 |= odt[((cas-3) * 2) + 1];
2792 MCHBAR32(C1ODT + 4) = reg32;
2793}
2794
2795/**
2796 * @brief Enable clocks to populated sockets
2797 */
2798
2799static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2800{
2801 u8 clocks[2] = { 0, 0 };
2802
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002803#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002804#define CLOCKS_WIDTH 2
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002805#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002806#define CLOCKS_WIDTH 3
2807#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002808 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002809 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002810
2811 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002812 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002813
2814 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002815 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002816
2817 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002818 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002819
Patrick Georgi77d66832010-10-01 08:02:45 +00002820#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002821 /* Usually system firmware turns off system memory clock signals
2822 * to unused SO-DIMM slots to reduce EMI and power consumption.
2823 * However, the Kontron 986LCD-M does not like unused clock
2824 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002825 */
2826
2827 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2828 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002829#endif
2830
2831 MCHBAR8(C0DCLKDIS) = clocks[0];
2832 MCHBAR8(C1DCLKDIS) = clocks[1];
2833}
2834
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002835#define RTT_ODT_NONE 0
2836#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002837#define RTT_ODT_75_OHM (1 << 5)
2838#define RTT_ODT_150_OHM (1 << 9)
2839
2840#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2841
2842#define MRS_CAS_3 (3 << 7)
2843#define MRS_CAS_4 (4 << 7)
2844#define MRS_CAS_5 (5 << 7)
2845
2846#define MRS_TWR_3 (2 << 12)
2847#define MRS_TWR_4 (3 << 12)
2848#define MRS_TWR_5 (4 << 12)
2849
2850#define MRS_BT (1 << 6)
2851
2852#define MRS_BL4 (2 << 3)
2853#define MRS_BL8 (3 << 3)
2854
2855static void sdram_jedec_enable(struct sys_info *sysinfo)
2856{
2857 int i, nonzero;
2858 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2859
2860 for (i = 0, nonzero = -1; i < 8; i++) {
2861 if (sysinfo->banksize[i] == 0) {
2862 continue;
2863 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002864
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002865 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002866 switch (i) {
2867 case 0:
2868 /* Start at address 0 */
2869 bankaddr = 0;
2870 break;
2871 case 4:
2872 if (sysinfo->interleaved) {
2873 bankaddr = 0x40;
2874 break;
2875 }
2876 default:
2877 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002878 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002879 bankaddr += sysinfo->banksize[nonzero] <<
2880 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002881 break;
2882 }
2883 /* No populated bank hit before. Start at address 0 */
2884 bankaddr = 0;
2885 }
2886
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002887 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002888 * for the next offset we have to calculate
2889 */
2890 nonzero = i;
2891
2892 /* Get CAS latency set up */
2893 switch (sysinfo->cas) {
2894 case 5: mrsaddr = MRS_CAS_5; break;
2895 case 4: mrsaddr = MRS_CAS_4; break;
2896 case 3: mrsaddr = MRS_CAS_3; break;
2897 default: die("Jedec Error (CAS).\n");
2898 }
2899
2900 /* Get tWR set */
2901 switch (sysinfo->twr) {
2902 case 5: mrsaddr |= MRS_TWR_5; break;
2903 case 4: mrsaddr |= MRS_TWR_4; break;
2904 case 3: mrsaddr |= MRS_TWR_3; break;
2905 default: die("Jedec Error (tWR).\n");
2906 }
2907
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002908 /* Set "Burst Type" */
2909 mrsaddr |= MRS_BT;
2910
Stefan Reinauer278534d2008-10-29 04:51:07 +00002911 /* Interleaved */
2912 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002913 mrsaddr = mrsaddr << 1;
2914 }
2915
2916 /* Only burst length 8 supported */
2917 mrsaddr |= MRS_BL8;
2918
2919 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002920 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002921 do_ram_command(RAM_COMMAND_NOP);
2922 ram_read32(bankaddr);
2923
2924 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002925 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002926 do_ram_command(RAM_COMMAND_PRECHARGE);
2927 ram_read32(bankaddr);
2928
2929 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002930 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002931 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2932 ram_read32(bankaddr);
2933
2934 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002935 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002936 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2937 ram_read32(bankaddr);
2938
2939 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002940 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002941 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2942 tmpaddr = bankaddr;
2943 if (!sdram_capabilities_dual_channel()) {
2944 tmpaddr |= RTT_ODT_75_OHM;
2945 } else if (sysinfo->interleaved) {
2946 tmpaddr |= (RTT_ODT_150_OHM << 1);
2947 } else {
2948 tmpaddr |= RTT_ODT_150_OHM;
2949 }
2950 ram_read32(tmpaddr);
2951
2952 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002953 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002954 do_ram_command(RAM_COMMAND_MRS);
2955 tmpaddr = bankaddr;
2956 tmpaddr |= mrsaddr;
2957 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002958 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002959 tmpaddr |= (1 << 12);
2960 else
2961 tmpaddr |= (1 << 11);
2962 ram_read32(tmpaddr);
2963
2964 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002965 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002966 do_ram_command(RAM_COMMAND_PRECHARGE);
2967 ram_read32(bankaddr);
2968
2969 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002970 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002971 do_ram_command(RAM_COMMAND_CBR);
2972
2973 /* CBR wants two READs */
2974 ram_read32(bankaddr);
2975 ram_read32(bankaddr);
2976
2977 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002978 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002979 do_ram_command(RAM_COMMAND_MRS);
2980
2981 tmpaddr = bankaddr;
2982 tmpaddr |= mrsaddr;
2983 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002984
Stefan Reinauer278534d2008-10-29 04:51:07 +00002985 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002986 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002987 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002988
Stefan Reinauer278534d2008-10-29 04:51:07 +00002989 tmpaddr = bankaddr;
2990 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002991
Stefan Reinauer278534d2008-10-29 04:51:07 +00002992 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
2993 } else if (sysinfo->interleaved) {
2994 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
2995 } else {
2996 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
2997 }
2998 ram_read32(tmpaddr);
2999
3000 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003001 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003002 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3003
3004 tmpaddr = bankaddr;
3005 if (!sdram_capabilities_dual_channel()) {
3006 tmpaddr |= RTT_ODT_75_OHM;
3007 } else if (sysinfo->interleaved) {
3008 tmpaddr |= (RTT_ODT_150_OHM << 1);
3009 } else {
3010 tmpaddr |= RTT_ODT_150_OHM;
3011 }
3012 ram_read32(tmpaddr);
3013 }
3014}
3015
3016static void sdram_init_complete(void)
3017{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003018 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003019 do_ram_command(RAM_COMMAND_NORMAL);
3020}
3021
3022static void sdram_setup_processor_side(void)
3023{
3024 if (i945_silicon_revision() == 0)
3025 MCHBAR32(FSBPMC3) |= (1 << 2);
3026
3027 MCHBAR8(0xb00) |= 1;
3028
3029 if (i945_silicon_revision() == 0)
3030 MCHBAR32(SLPCTL) |= (1 << 8);
3031}
3032
Stefan Reinauer278534d2008-10-29 04:51:07 +00003033/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003034 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Martin Rothf4cb4122015-01-06 10:27:39 -07003035 * @param spd_addresses pointer to a list of SPD addresses
Stefan Reinauer278534d2008-10-29 04:51:07 +00003036 */
Sven Schnelle541269b2011-02-21 09:39:17 +00003037void sdram_initialize(int boot_path, const u8 *spd_addresses)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003038{
3039 struct sys_info sysinfo;
3040 u8 reg8, cas_mask;
3041
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003042 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003043
3044 memset(&sysinfo, 0, sizeof(sysinfo));
3045
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003046 sysinfo.boot_path = boot_path;
Sven Schnelle541269b2011-02-21 09:39:17 +00003047 sysinfo.spd_addresses = spd_addresses;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003048
Stefan Reinauer278534d2008-10-29 04:51:07 +00003049 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3050 sdram_get_dram_configuration(&sysinfo);
3051
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003052 /* If error, do cold boot */
3053 sdram_detect_errors(&sysinfo);
3054
Stefan Reinauer278534d2008-10-29 04:51:07 +00003055 /* Check whether we have stacked DIMMs */
3056 sdram_verify_package_type(&sysinfo);
3057
3058 /* Determine common CAS */
3059 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003060
Stefan Reinauer278534d2008-10-29 04:51:07 +00003061 /* Choose Common Frequency */
3062 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003063
Stefan Reinauer278534d2008-10-29 04:51:07 +00003064 /* Determine smallest common tRAS */
3065 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003066
Stefan Reinauer278534d2008-10-29 04:51:07 +00003067 /* Determine tRP */
3068 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003069
Stefan Reinauer278534d2008-10-29 04:51:07 +00003070 /* Determine tRCD */
3071 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003072
Stefan Reinauer278534d2008-10-29 04:51:07 +00003073 /* Determine smallest refresh period */
3074 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003075
Stefan Reinauer278534d2008-10-29 04:51:07 +00003076 /* Verify all DIMMs support burst length 8 */
3077 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003078
Stefan Reinauer278534d2008-10-29 04:51:07 +00003079 /* determine tWR */
3080 sdram_detect_smallest_tWR(&sysinfo);
3081
3082 /* Determine DIMM size parameters (rows, columns banks) */
3083 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003084
Stefan Reinauer278534d2008-10-29 04:51:07 +00003085 /* determine tRFC */
3086 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003087
Stefan Reinauer278534d2008-10-29 04:51:07 +00003088 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003089 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003090
3091 /* Program Graphics Frequency */
3092 sdram_program_graphics_frequency(&sysinfo);
3093
3094 /* Program System Memory Frequency */
3095 sdram_program_memory_frequency(&sysinfo);
3096
3097 /* Determine Mode of Operation (Interleaved etc) */
3098 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003099
Stefan Reinauer278534d2008-10-29 04:51:07 +00003100 /* Program Clock Crossing values */
3101 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003102
Stefan Reinauer278534d2008-10-29 04:51:07 +00003103 /* Disable fast dispatch */
3104 sdram_disable_fast_dispatch();
3105
3106 /* Enable WIODLL Power Down in ACPI states */
3107 MCHBAR32(C0DMC) |= (1 << 24);
3108 MCHBAR32(C1DMC) |= (1 << 24);
3109
3110 /* Program DRAM Row Boundary/Attribute Registers */
3111
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003112 /* program row size DRB and set TOLUD */
3113 sdram_program_row_boundaries(&sysinfo);
3114
3115 /* program page size DRA */
3116 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003117
3118 /* Program CxBNKARC */
3119 sdram_set_bank_architecture(&sysinfo);
3120
3121 /* Program DRAM Timing and Control registers based on SPD */
3122 sdram_set_timing_and_control(&sysinfo);
3123
3124 /* On-Die Termination Adjustment */
3125 sdram_on_die_termination(&sysinfo);
3126
3127 /* Pre Jedec Initialization */
3128 sdram_pre_jedec_initialization();
3129
3130 /* Perform System Memory IO Initialization */
3131 sdram_initialize_system_memory_io(&sysinfo);
3132
3133 /* Perform System Memory IO Buffer Enable */
3134 sdram_enable_system_memory_io(&sysinfo);
3135
3136 /* Enable System Memory Clocks */
3137 sdram_enable_memory_clocks(&sysinfo);
3138
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003139 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003140 /* Jedec Initialization sequence */
3141 sdram_jedec_enable(&sysinfo);
3142 }
3143
3144 /* Program Power Management Registers */
3145 sdram_power_management(&sysinfo);
3146
3147 /* Post Jedec Init */
3148 sdram_post_jedec_initialization(&sysinfo);
3149
3150 /* Program DRAM Throttling */
3151 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003152
Stefan Reinauer278534d2008-10-29 04:51:07 +00003153 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003154 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003155
3156 /* Program Receive Enable Timings */
3157 sdram_program_receive_enable(&sysinfo);
3158
3159 /* Enable Periodic RCOMP */
3160 sdram_enable_rcomp();
3161
3162 /* Tell ICH7 that we're done */
3163 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3164 reg8 &= ~(1 << 7);
3165 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3166
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003167 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003168
Stefan Reinauer278534d2008-10-29 04:51:07 +00003169 sdram_setup_processor_side();
3170}