blob: f9ba37b17b9011d87237ffadb9a030a152b4b1ea [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>
Arthur Heymans885c2892016-10-03 17:16:48 +020019#include <device/pci_def.h>
20#include <device/device.h>
Julius Werner7a8a4ab2015-05-22 16:26:40 -070021#include <lib.h>
Edwin Beasanteb50c7d2010-07-06 21:05:04 +000022#include <pc80/mc146818rtc.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000023#include <spd.h>
Patrick Georgid0835952010-10-05 09:07:10 +000024#include <string.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070025#include <arch/io.h>
Patrick Georgi546953c2014-11-29 10:38:17 +010026#include <halt.h>
Alexandru Gagniucaf4bd592014-01-12 15:42:58 -060027#include <lib.h>
Stefan Reinauer278534d2008-10-29 04:51:07 +000028#include "raminit.h"
29#include "i945.h"
Arthur Heymans885c2892016-10-03 17:16:48 +020030#include "chip.h"
Rudolf Marekc4369532010-12-13 19:59:13 +000031#include <cbmem.h>
32
Stefan Reinauer278534d2008-10-29 04:51:07 +000033/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000034#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000035#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Stefan Reinauer278534d2008-10-29 04:51:07 +000036#else
37#define PRINTK_DEBUG(x...)
38#endif
39
Stefan Reinauer278534d2008-10-29 04:51:07 +000040#define RAM_INITIALIZATION_COMPLETE (1 << 19)
41
42#define RAM_COMMAND_SELF_REFRESH (0x0 << 16)
43#define RAM_COMMAND_NOP (0x1 << 16)
44#define RAM_COMMAND_PRECHARGE (0x2 << 16)
45#define RAM_COMMAND_MRS (0x3 << 16)
46#define RAM_COMMAND_EMRS (0x4 << 16)
47#define RAM_COMMAND_CBR (0x6 << 16)
48#define RAM_COMMAND_NORMAL (0x7 << 16)
49
50#define RAM_EMRS_1 (0x0 << 21)
51#define RAM_EMRS_2 (0x1 << 21)
52#define RAM_EMRS_3 (0x2 << 21)
53
Arthur Heymans885c2892016-10-03 17:16:48 +020054#define DEFAULT_PCI_MMIO_SIZE 768
Sven Schnelle541269b2011-02-21 09:39:17 +000055static int get_dimm_spd_address(struct sys_info *sysinfo, int device)
56{
57 if (sysinfo->spd_addresses)
58 return sysinfo->spd_addresses[device];
59 else
60 return DIMM0 + device;
61
62}
63
Patrick Georgid0835952010-10-05 09:07:10 +000064static inline int spd_read_byte(unsigned device, unsigned address)
65{
66 return smbus_read_byte(device, address);
67}
68
Stefan Reinauerbc8613e2010-08-25 18:35:42 +000069static __attribute__((noinline)) void do_ram_command(u32 command)
Stefan Reinauer278534d2008-10-29 04:51:07 +000070{
71 u32 reg32;
72
73 reg32 = MCHBAR32(DCC);
74 reg32 &= ~( (3<<21) | (1<<20) | (1<<19) | (7 << 16) );
75 reg32 |= command;
76
77 /* Also set Init Complete */
78 if (command == RAM_COMMAND_NORMAL)
79 reg32 |= RAM_INITIALIZATION_COMPLETE;
80
81 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
82
83 MCHBAR32(DCC) = reg32; /* This is the actual magic */
84
Stefan Reinauer779b3e32008-11-10 15:43:37 +000085 PRINTK_DEBUG("...done\n");
Stefan Reinauerd058ad12010-08-26 12:43:58 +000086
87 udelay(1);
Stefan Reinauer278534d2008-10-29 04:51:07 +000088}
89
Stefan Reinauer278534d2008-10-29 04:51:07 +000090static void ram_read32(u32 offset)
91{
Elyes HAOUAS15279a92016-07-28 21:05:26 +020092 PRINTK_DEBUG(" RAM read: %08x\n", offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000093
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080094 read32((void *)offset);
Stefan Reinauer278534d2008-10-29 04:51:07 +000095}
96
Uwe Hermann01ce6012010-03-05 10:03:50 +000097#if CONFIG_DEBUG_RAM_SETUP
Stefan Reinauer3c0bfaf2010-12-27 11:34:57 +000098void sdram_dump_mchbar_registers(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000099{
100 int i;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000101 printk(BIOS_DEBUG, "Dumping MCHBAR Registers\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000102
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200103 for (i = 0; i < 0xfff; i+=4) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000104 if (MCHBAR32(i) == 0)
105 continue;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000106 printk(BIOS_DEBUG, "0x%04x: 0x%08x\n", i, MCHBAR32(i));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000107 }
108}
109#endif
110
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000111static int memclk(void)
112{
Elyes HAOUASc9848a82016-10-09 20:24:20 +0200113 int offset = IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM) ? 1 : 0;
114
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000115 switch (((MCHBAR32(CLKCFG) >> 4) & 7) - offset) {
116 case 1: return 400;
117 case 2: return 533;
118 case 3: return 667;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000119 default: printk(BIOS_DEBUG, "memclk: unknown register value %x\n", ((MCHBAR32(CLKCFG) >> 4) & 7) - offset);
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000120 }
121 return -1;
122}
123
Peter Stuge76d91432010-10-01 10:02:33 +0000124static u16 fsbclk(void)
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000125{
Elyes HAOUASc9848a82016-10-09 20:24:20 +0200126 if (IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM)) {
127 switch (MCHBAR32(CLKCFG) & 7) {
128 case 0: return 400;
129 case 1: return 533;
130 case 3: return 667;
131 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
132 }
133 return 0xffff;
134 } else if (IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
135 switch (MCHBAR32(CLKCFG) & 7) {
136 case 0: return 1066;
137 case 1: return 533;
138 case 2: return 800;
139 default: printk(BIOS_DEBUG, "fsbclk: unknown register value %x\n", MCHBAR32(CLKCFG) & 7);
140 }
141 return 0xffff;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000142 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000143}
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000144
Stefan Reinauer278534d2008-10-29 04:51:07 +0000145static int sdram_capabilities_max_supported_memory_frequency(void)
146{
147 u32 reg32;
148
Patrick Georgi77d66832010-10-01 08:02:45 +0000149#if CONFIG_MAXIMUM_SUPPORTED_FREQUENCY
150 return CONFIG_MAXIMUM_SUPPORTED_FREQUENCY;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000151#endif
152
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000153 reg32 = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000154 reg32 &= (7 << 0);
155
156 switch (reg32) {
157 case 4: return 400;
158 case 3: return 533;
159 case 2: return 667;
160 }
161 /* Newer revisions of this chipset rather support faster memory clocks,
162 * so if it's a reserved value, return the fastest memory clock that we
163 * know of and can handle
164 */
165 return 667;
166}
167
168/**
169 * @brief determine whether chipset is capable of dual channel interleaved mode
170 *
171 * @return 1 if interleaving is supported, 0 otherwise
172 */
173static int sdram_capabilities_interleave(void)
174{
175 u32 reg32;
176
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000177 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000178 reg32 >>= 25;
179 reg32 &= 1;
180
181 return (!reg32);
182}
183
184/**
185 * @brief determine whether chipset is capable of two memory channels
186 *
187 * @return 1 if dual channel operation is supported, 0 otherwise
188 */
189static int sdram_capabilities_dual_channel(void)
190{
191 u32 reg32;
192
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000193 reg32 = pci_read_config32(PCI_DEV(0, 0x00,0), 0xe4); /* CAPID0 + 4 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000194 reg32 >>= 24;
195 reg32 &= 1;
196
197 return (!reg32);
198}
199
200static int sdram_capabilities_enhanced_addressing_xor(void)
201{
202 u8 reg8;
203
204 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
205 reg8 &= (1 << 7);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000206
Stefan Reinauer278534d2008-10-29 04:51:07 +0000207 return (!reg8);
208}
209
Stefan Reinauer14e22772010-04-27 06:56:47 +0000210// TODO check if we ever need this function
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000211#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +0000212static int sdram_capabilities_MEM4G_disable(void)
213{
214 u8 reg8;
215
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000216 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000217 reg8 &= (1 << 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000218
Stefan Reinauer278534d2008-10-29 04:51:07 +0000219 return (reg8 != 0);
220}
Stefan Reinauer53b0ea42010-03-22 11:50:52 +0000221#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000222
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000223#define GFX_FREQUENCY_CAP_166MHZ 0x04
224#define GFX_FREQUENCY_CAP_200MHZ 0x03
225#define GFX_FREQUENCY_CAP_250MHZ 0x02
226#define GFX_FREQUENCY_CAP_ALL 0x00
227
228static int sdram_capabilities_core_frequencies(void)
229{
230 u8 reg8;
231
232 reg8 = pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe5); /* CAPID0 + 5 */
233 reg8 &= (1 << 3) | (1 << 2) | (1 << 1);
234 reg8 >>= 1;
235
236 return (reg8);
237}
238
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000239static void sdram_detect_errors(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000240{
241 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000242 u8 do_reset = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000243
244 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000245
Stefan Reinauer278534d2008-10-29 04:51:07 +0000246 if (reg8 & ((1<<7)|(1<<2))) {
247 if (reg8 & (1<<2)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000248 printk(BIOS_DEBUG, "SLP S4# Assertion Width Violation.\n");
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000249 /* Write back clears bit 2 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000250 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauerf98ad3a2010-03-05 18:25:19 +0000251 do_reset = 1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000252
Stefan Reinauer278534d2008-10-29 04:51:07 +0000253 }
254
255 if (reg8 & (1<<7)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000256 printk(BIOS_DEBUG, "DRAM initialization was interrupted.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000257 reg8 &= ~(1<<7);
258 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000259 do_reset = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000260 }
261
262 /* Set SLP_S3# Assertion Stretch Enable */
263 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); /* GEN_PMCON_3 */
264 reg8 |= (1 << 3);
265 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
266
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000267 if (do_reset) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000268 printk(BIOS_DEBUG, "Reset required.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000269 outb(0x00, 0xcf9);
270 outb(0x0e, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +0100271 halt(); /* Wait for reset! */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000272 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000273 }
274
275 /* Set DRAM initialization bit in ICH7 */
276 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
277 reg8 |= (1<<7);
278 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000279
Peter Stuge751508a2012-01-27 22:17:09 +0100280 /* clear self refresh status if check is disabled or not a resume */
Patrick Georgi86a11102013-03-15 14:11:37 +0100281 if (!CONFIG_CHECK_SLFRCS_ON_RESUME || sysinfo->boot_path != BOOT_PATH_RESUME) {
282 MCHBAR8(SLFRCS) |= 3;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000283 } else {
284 /* Validate self refresh config */
285 if (((sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED) ||
286 (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100287 !(MCHBAR8(SLFRCS) & (1<<0))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000288 do_reset = 1;
289 }
290 if (((sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED) ||
291 (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)) &&
Patrick Georgi86a11102013-03-15 14:11:37 +0100292 !(MCHBAR8(SLFRCS) & (1<<1))) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000293 do_reset = 1;
294 }
295 }
296
297 if (do_reset) {
298 printk(BIOS_DEBUG, "Reset required.\n");
299 outb(0x00, 0xcf9);
300 outb(0x0e, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +0100301 halt(); /* Wait for reset! */
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000302 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000303}
Stefan Reinauer278534d2008-10-29 04:51:07 +0000304
305/**
306 * @brief Get generic DIMM parameters.
307 * @param sysinfo Central memory controller information structure
308 *
309 * This function gathers several pieces of information for each system DIMM:
310 * o DIMM width (x8 / x16)
311 * o DIMM sides (single sided / dual sided)
312 *
313 * Also, some non-supported scenarios are detected.
314 */
315
316static void sdram_get_dram_configuration(struct sys_info *sysinfo)
317{
318 u32 dimm_mask = 0;
319 int i;
320
321 /**
322 * i945 supports two DIMMs, in two configurations:
323 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000324 * - single channel with two DIMMs
325 * - dual channel with one DIMM per channel
Stefan Reinauer278534d2008-10-29 04:51:07 +0000326 *
Uwe Hermannd773fd32010-11-20 20:23:08 +0000327 * In practice dual channel mainboards have their SPD at 0x50/0x52
328 * whereas single channel configurations have their SPD at 0x50/0x51.
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000329 *
Stefan Reinauer278534d2008-10-29 04:51:07 +0000330 * The capability register knows a lot about the channel configuration
Uwe Hermannd773fd32010-11-20 20:23:08 +0000331 * but for now we stick with the information we gather via SPD.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000332 */
333
334 if (sdram_capabilities_dual_channel()) {
335 sysinfo->dual_channel = 1;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000336 printk(BIOS_DEBUG, "This mainboard supports Dual Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000337 } else {
338 sysinfo->dual_channel = 0;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000339 printk(BIOS_DEBUG, "This mainboard supports only Single Channel Operation.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000340 }
341
342 /**
343 * Since we only support two DIMMs in total, there is a limited number
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000344 * of combinations. This function returns the type of DIMMs.
Stefan Reinauer278534d2008-10-29 04:51:07 +0000345 * return value:
346 * [0:7] lower DIMM population
347 * [8-15] higher DIMM population
348 * [16] dual channel?
349 *
350 * There are 5 different possible populations for a DIMM socket:
351 * 1. x16 double sided (X16DS)
352 * 2. x8 double sided (X8DS)
353 * 3. x16 single sided (X16SS)
354 * 4. x8 double stacked (X8DDS)
355 * 5. not populated (NC)
356 *
357 * For the return value we start counting at zero.
358 *
359 */
360
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200361 for (i = 0; i<(2 * DIMM_SOCKETS); i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000362 int device = get_dimm_spd_address(sysinfo, i);
363 u8 reg8;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000364
365 /* Initialize the socket information with a sane value */
366 sysinfo->dimm[i] = SYSINFO_DIMM_NOT_POPULATED;
367
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000368 /* Dual Channel not supported, but Channel 1? Bail out */
369 if (!sdram_capabilities_dual_channel() && (i >> 1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000370 continue;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000371
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000372 printk(BIOS_DEBUG, "DDR II Channel %d Socket %d: ", (i >> 1), (i & 1));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000373
374 if (spd_read_byte(device, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR2) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000375 printk(BIOS_DEBUG, "N/A\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000376 continue;
377 }
378
379 reg8 = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
380 if (reg8 == ERROR_SCHEME_ECC)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000381 die("Error: ECC memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000382
383 reg8 = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
384 if (reg8 & MODULE_BUFFERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000385 die("Error: Buffered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000386 if (reg8 & MODULE_REGISTERED)
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000387 die("Error: Registered memory not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000388
389 switch (spd_read_byte(device, SPD_PRIMARY_SDRAM_WIDTH)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000390 case 0x08:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000391 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
392 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000393 printk(BIOS_DEBUG, "x8DDS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000394 sysinfo->dimm[i] = SYSINFO_DIMM_X8DDS;
395 break;
396 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000397 printk(BIOS_DEBUG, "x8DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000398 sysinfo->dimm[i] = SYSINFO_DIMM_X8DS;
399 break;
400 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000401 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000402 }
403 break;
404 case 0x10:
405 switch (spd_read_byte(device, SPD_NUM_DIMM_BANKS) & 0x0f) {
406 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000407 printk(BIOS_DEBUG, "x16DS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000408 sysinfo->dimm[i] = SYSINFO_DIMM_X16DS;
409 break;
410 case 0:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000411 printk(BIOS_DEBUG, "x16SS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000412 sysinfo->dimm[i] = SYSINFO_DIMM_X16SS;
413 break;
414 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000415 printk(BIOS_DEBUG, "Unsupported.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000416 }
417 break;
418 default:
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000419 die("Unsupported DDR-II memory width.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000420 }
421
422 dimm_mask |= (1 << i);
423 }
424
425 if (!dimm_mask) {
Stefan Reinauer779b3e32008-11-10 15:43:37 +0000426 die("No memory installed.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000427 }
428
Stefan Reinauer278534d2008-10-29 04:51:07 +0000429 if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000430 printk(BIOS_INFO, "Channel 0 has no memory populated.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000431 }
432}
433
434/**
435 * @brief determine if any DIMMs are stacked
436 *
437 * @param sysinfo central sysinfo data structure.
438 */
439static void sdram_verify_package_type(struct sys_info * sysinfo)
440{
441 int i;
442
443 /* Assume no stacked DIMMs are available until we find one */
444 sysinfo->package = 0;
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200445 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000446 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
447 continue;
448
449 /* Is the current DIMM a stacked DIMM? */
Sven Schnelle541269b2011-02-21 09:39:17 +0000450 if (spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_NUM_DIMM_BANKS) & (1 << 4))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000451 sysinfo->package = 1;
452 }
453}
454
455static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
456{
457 int i;
458 u8 cas_mask;
459
460 /* Setup CAS mask with all supported CAS Latencies */
461 cas_mask = SPD_CAS_LATENCY_DDR2_3 |
462 SPD_CAS_LATENCY_DDR2_4 |
463 SPD_CAS_LATENCY_DDR2_5;
464
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200465 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000466 if (sysinfo->dimm[i] != SYSINFO_DIMM_NOT_POPULATED)
Sven Schnelle541269b2011-02-21 09:39:17 +0000467 cas_mask &= spd_read_byte(get_dimm_spd_address(sysinfo, i),
468 SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000469 }
470
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200471 if (!cas_mask) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000472 die("No DDR-II modules with accepted CAS latencies found.\n");
473 }
474
475 return cas_mask;
476}
477
478static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
479{
480 int i, j, idx;
481 int lowest_common_cas = 0;
Stefan Reinauerde3206a2010-02-22 06:09:43 +0000482 int max_ram_speed = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000483
484 const u8 ddr2_speeds_table[] = {
485 0x50, 0x60, /* DDR2 400: tCLK = 5.0ns tAC = 0.6ns */
486 0x3d, 0x50, /* DDR2 533: tCLK = 3.75ns tAC = 0.5ns */
487 0x30, 0x45, /* DDR2 667: tCLK = 3.0ns tAC = 0.45ns */
488 };
489
490 const u8 spd_lookup_table[] = {
491 SPD_MIN_CYCLE_TIME_AT_CAS_MAX, SPD_ACCESS_TIME_FROM_CLOCK,
492 SPD_SDRAM_CYCLE_TIME_2ND, SPD_ACCESS_TIME_FROM_CLOCK_2ND,
493 SPD_SDRAM_CYCLE_TIME_3RD, SPD_ACCESS_TIME_FROM_CLOCK_3RD
494 };
495
496 switch (sdram_capabilities_max_supported_memory_frequency()) {
497 case 400: max_ram_speed = 0; break;
498 case 533: max_ram_speed = 1; break;
499 case 667: max_ram_speed = 2; break;
500 }
501
502 sysinfo->memory_frequency = 0;
503 sysinfo->cas = 0;
504
505 if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
506 lowest_common_cas = 3;
507 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
508 lowest_common_cas = 4;
509 } else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
510 lowest_common_cas = 5;
511 }
512 PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
513
514 for (j = max_ram_speed; j>=0; j--) {
515 int freq_cas_mask = cas_mask;
516
517 PRINTK_DEBUG("Probing Speed %d\n", j);
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200518 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Sven Schnelle541269b2011-02-21 09:39:17 +0000519 int device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000520 int current_cas_mask;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000521
Stefan Reinauer278534d2008-10-29 04:51:07 +0000522 PRINTK_DEBUG(" DIMM: %d\n", i);
523 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
524 continue;
525 }
526
Sven Schnelle541269b2011-02-21 09:39:17 +0000527 current_cas_mask = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000528
529 while (current_cas_mask) {
530 int highest_supported_cas = 0, current_cas = 0;
531 PRINTK_DEBUG(" Current CAS mask: %04x; ", current_cas_mask);
532 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
533 highest_supported_cas = 5;
534 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
535 highest_supported_cas = 4;
536 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
537 highest_supported_cas = 3;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000538 } else {
539 die("Invalid max. CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000540 }
541 if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
542 current_cas = 3;
543 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
544 current_cas = 4;
545 } else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
546 current_cas = 5;
Stefan Reinauer2b9070a2010-12-11 22:12:32 +0000547 } else {
548 die("Invalid CAS.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000549 }
550
551 idx = highest_supported_cas - current_cas;
552 PRINTK_DEBUG("idx=%d, ", idx);
Sven Schnelle541269b2011-02-21 09:39:17 +0000553 PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(device, spd_lookup_table[2*idx]));
554 PRINTK_DEBUG("tAC=%x", spd_read_byte(device, spd_lookup_table[(2*idx)+1]));
Stefan Reinauer278534d2008-10-29 04:51:07 +0000555
Sven Schnelle541269b2011-02-21 09:39:17 +0000556 if (spd_read_byte(device, spd_lookup_table[2*idx]) <= ddr2_speeds_table[2*j] &&
557 spd_read_byte(device, spd_lookup_table[(2*idx)+1]) <= ddr2_speeds_table[(2*j)+1]) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000558 PRINTK_DEBUG(": OK\n");
559 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000560 }
561
Stefan Reinauer278534d2008-10-29 04:51:07 +0000562 PRINTK_DEBUG(": Not fast enough!\n");
563
564 current_cas_mask &= ~(1 << (current_cas));
565 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000566
Stefan Reinauer278534d2008-10-29 04:51:07 +0000567 freq_cas_mask &= current_cas_mask;
568 if (!current_cas_mask) {
569 PRINTK_DEBUG(" No valid CAS for this speed on DIMM %d\n", i);
570 break;
571 }
572 }
573 PRINTK_DEBUG(" freq_cas_mask for speed %d: %04x\n", j, freq_cas_mask);
574 if (freq_cas_mask) {
575 switch (j) {
576 case 0: sysinfo->memory_frequency = 400; break;
577 case 1: sysinfo->memory_frequency = 533; break;
578 case 2: sysinfo->memory_frequency = 667; break;
579 }
580 if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
581 sysinfo->cas = 3;
582 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
583 sysinfo->cas = 4;
584 } else if (freq_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
585 sysinfo->cas = 5;
586 }
587 break;
588 }
589 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000590
Stefan Reinauer278534d2008-10-29 04:51:07 +0000591 if (sysinfo->memory_frequency && sysinfo->cas) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000592 printk(BIOS_DEBUG, "Memory will be driven at %dMHz with CAS=%d clocks\n",
Stefan Reinauer278534d2008-10-29 04:51:07 +0000593 sysinfo->memory_frequency, sysinfo->cas);
594 } else {
595 die("Could not find common memory frequency and CAS\n");
596 }
597}
598
599static void sdram_detect_smallest_tRAS(struct sys_info * sysinfo)
600{
601 int i;
602 int tRAS_time;
603 int tRAS_cycles;
604 int freq_multiplier = 0;
605
606 switch (sysinfo->memory_frequency) {
607 case 400: freq_multiplier = 0x14; break; /* 5ns */
608 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
609 case 667: freq_multiplier = 0x0c; break; /* 3ns */
610 }
611
612 tRAS_cycles = 4; /* 4 clocks minimum */
613 tRAS_time = tRAS_cycles * freq_multiplier;
614
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200615 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000616 u8 reg8;
617
618 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
619 continue;
620
Sven Schnelle541269b2011-02-21 09:39:17 +0000621 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000622 if (!reg8) {
623 die("Invalid tRAS value.\n");
624 }
625
626 while ((tRAS_time >> 2) < reg8) {
627 tRAS_time += freq_multiplier;
628 tRAS_cycles++;
629 }
630 }
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200631 if (tRAS_cycles > 0x18) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000632 die("DDR-II Module does not support this frequency (tRAS error)\n");
633 }
634
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000635 printk(BIOS_DEBUG, "tRAS = %d cycles\n", tRAS_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000636 sysinfo->tras = tRAS_cycles;
637}
638
639static void sdram_detect_smallest_tRP(struct sys_info * sysinfo)
640{
641 int i;
642 int tRP_time;
643 int tRP_cycles;
644 int freq_multiplier = 0;
645
646 switch (sysinfo->memory_frequency) {
647 case 400: freq_multiplier = 0x14; break; /* 5ns */
648 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
649 case 667: freq_multiplier = 0x0c; break; /* 3ns */
650 }
651
652 tRP_cycles = 2; /* 2 clocks minimum */
653 tRP_time = tRP_cycles * freq_multiplier;
654
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200655 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000656 u8 reg8;
657
658 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
659 continue;
660
Sven Schnelle541269b2011-02-21 09:39:17 +0000661 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_ROW_PRECHARGE_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000662 if (!reg8) {
663 die("Invalid tRP value.\n");
664 }
665
666 while (tRP_time < reg8) {
667 tRP_time += freq_multiplier;
668 tRP_cycles++;
669 }
670 }
671
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200672 if (tRP_cycles > 6) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000673 die("DDR-II Module does not support this frequency (tRP error)\n");
674 }
675
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000676 printk(BIOS_DEBUG, "tRP = %d cycles\n", tRP_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000677 sysinfo->trp = tRP_cycles;
678}
679
680static void sdram_detect_smallest_tRCD(struct sys_info * sysinfo)
681{
682 int i;
683 int tRCD_time;
684 int tRCD_cycles;
685 int freq_multiplier = 0;
686
687 switch (sysinfo->memory_frequency) {
688 case 400: freq_multiplier = 0x14; break; /* 5ns */
689 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
690 case 667: freq_multiplier = 0x0c; break; /* 3ns */
691 }
692
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000693 tRCD_cycles = 2; /* 2 clocks minimum */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000694 tRCD_time = tRCD_cycles * freq_multiplier;
695
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200696 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000697 u8 reg8;
698
699 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
700 continue;
701
Sven Schnelle541269b2011-02-21 09:39:17 +0000702 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_MIN_RAS_TO_CAS_DELAY);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000703 if (!reg8) {
704 die("Invalid tRCD value.\n");
705 }
706
707 while (tRCD_time < reg8) {
708 tRCD_time += freq_multiplier;
709 tRCD_cycles++;
710 }
711 }
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200712 if (tRCD_cycles > 6) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000713 die("DDR-II Module does not support this frequency (tRCD error)\n");
714 }
715
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000716 printk(BIOS_DEBUG, "tRCD = %d cycles\n", tRCD_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000717 sysinfo->trcd = tRCD_cycles;
718}
719
720static void sdram_detect_smallest_tWR(struct sys_info * sysinfo)
721{
722 int i;
723 int tWR_time;
724 int tWR_cycles;
725 int freq_multiplier = 0;
726
727 switch (sysinfo->memory_frequency) {
728 case 400: freq_multiplier = 0x14; break; /* 5ns */
729 case 533: freq_multiplier = 0x0f; break; /* 3.75ns */
730 case 667: freq_multiplier = 0x0c; break; /* 3ns */
731 }
732
733 tWR_cycles = 2; /* 2 clocks minimum */
734 tWR_time = tWR_cycles * freq_multiplier;
735
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200736 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000737 u8 reg8;
738
739 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
740 continue;
741
Sven Schnelle541269b2011-02-21 09:39:17 +0000742 reg8 = spd_read_byte(get_dimm_spd_address(sysinfo, i), SPD_WRITE_RECOVERY_TIME);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000743 if (!reg8) {
744 die("Invalid tWR value.\n");
745 }
746
747 while (tWR_time < reg8) {
748 tWR_time += freq_multiplier;
749 tWR_cycles++;
750 }
751 }
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200752 if (tWR_cycles > 5) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000753 die("DDR-II Module does not support this frequency (tWR error)\n");
754 }
755
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000756 printk(BIOS_DEBUG, "tWR = %d cycles\n", tWR_cycles);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000757 sysinfo->twr = tWR_cycles;
758}
759
760static void sdram_detect_smallest_tRFC(struct sys_info * sysinfo)
761{
762 int i, index = 0;
763
764 const u8 tRFC_cycles[] = {
765 /* 75 105 127.5 */
766 15, 21, 26, /* DDR2-400 */
767 20, 28, 34, /* DDR2-533 */
768 25, 35, 43 /* DDR2-667 */
769 };
770
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200771 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000772 u8 reg8;
773
774 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
775 continue;
776
777 reg8 = sysinfo->banksize[i*2];
778 switch (reg8) {
779 case 0x04: reg8 = 0; break;
780 case 0x08: reg8 = 1; break;
781 case 0x10: reg8 = 2; break;
782 case 0x20: reg8 = 3; break;
783 }
784
785 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS || sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
786 reg8++;
787
788 if (reg8 > 3) {
789 /* Can this happen? Go back to 127.5ns just to be sure
790 * we don't run out of the array. This may be wrong
791 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000792 printk(BIOS_DEBUG, "DIMM %d is 1Gb x16.. Please report.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000793 reg8 = 3;
794 }
795
796 if (reg8 > index)
797 index = reg8;
798
799 }
800 index--;
801 switch (sysinfo->memory_frequency) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000802 case 667: index += 3; /* Fallthrough */
803 case 533: index += 3; /* Fallthrough */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000804 case 400: break;
805 }
806
807 sysinfo->trfc = tRFC_cycles[index];
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000808 printk(BIOS_DEBUG, "tRFC = %d cycles\n", tRFC_cycles[index]);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000809}
810
Stefan Reinauer278534d2008-10-29 04:51:07 +0000811static void sdram_detect_smallest_refresh(struct sys_info * sysinfo)
812{
813 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000814
Stefan Reinauer278534d2008-10-29 04:51:07 +0000815 sysinfo->refresh = 0;
816
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200817 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000818 int refresh;
819
820 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
821 continue;
822
Sven Schnelle541269b2011-02-21 09:39:17 +0000823 refresh = spd_read_byte(get_dimm_spd_address(sysinfo, i),
824 SPD_REFRESH) & ~(1 << 7);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000825
826 /* 15.6us */
827 if (!refresh)
828 continue;
829
830 /* Refresh is slower than 15.6us, use 15.6us */
831 if (refresh > 2)
832 continue;
833
834 if (refresh == 2) {
835 sysinfo->refresh = 1;
836 break;
837 }
838
839 die("DDR-II module has unsupported refresh value\n");
840 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000841 printk(BIOS_DEBUG, "Refresh: %s\n", sysinfo->refresh?"7.8us":"15.6us");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000842}
843
844static void sdram_verify_burst_length(struct sys_info * sysinfo)
845{
846 int i;
847
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200848 for (i = 0; i < 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +0000849 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
850 continue;
851
Sven Schnelle541269b2011-02-21 09:39:17 +0000852 if (!(spd_read_byte(get_dimm_spd_address(sysinfo, i),
853 SPD_SUPPORTED_BURST_LENGTHS) & SPD_BURST_LENGTH_8))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000854 die("Only DDR-II RAM with burst length 8 is supported by this chipset.\n");
855 }
856}
857
858static void sdram_program_dram_width(struct sys_info * sysinfo)
859{
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200860 u16 c0dramw = 0, c1dramw = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000861 int idx;
862
863 if (sysinfo->dual_channel)
864 idx = 2;
865 else
866 idx = 1;
867
868 switch (sysinfo->dimm[0]) {
869 case 0: c0dramw = 0x0000; break; /* x16DS */
870 case 1: c0dramw = 0x0001; break; /* x8DS */
871 case 2: c0dramw = 0x0000; break; /* x16SS */
872 case 3: c0dramw = 0x0005; break; /* x8DDS */
873 case 4: c0dramw = 0x0000; break; /* NC */
874 }
875
876 switch (sysinfo->dimm[idx]) {
877 case 0: c1dramw = 0x0000; break; /* x16DS */
878 case 1: c1dramw = 0x0010; break; /* x8DS */
879 case 2: c1dramw = 0x0000; break; /* x16SS */
880 case 3: c1dramw = 0x0050; break; /* x8DDS */
881 case 4: c1dramw = 0x0000; break; /* NC */
882 }
883
884 if ( !sdram_capabilities_dual_channel() ) {
885 /* Single Channel */
886 c0dramw |= c1dramw;
887 c1dramw = 0;
888 }
889
890 MCHBAR16(C0DRAMW) = c0dramw;
891 MCHBAR16(C1DRAMW) = c1dramw;
892}
893
894static void sdram_write_slew_rates(u32 offset, const u32 *slew_rate_table)
895{
896 int i;
897
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200898 for (i = 0; i < 16; i++)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000899 MCHBAR32(offset+(i*4)) = slew_rate_table[i];
900}
901
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000902static const u32 dq2030[] = {
903 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
904 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
905 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
906 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
907};
908
909static const u32 dq2330[] = {
910 0x08070706, 0x0a090908, 0x0d0c0b0a, 0x12100f0e,
911 0x1a181614, 0x22201e1c, 0x2a282624, 0x3934302d,
912 0x0a090908, 0x0c0b0b0a, 0x0e0d0d0c, 0x1211100f,
913 0x19171513, 0x211f1d1b, 0x2d292623, 0x3f393531
914};
915
916static const u32 cmd2710[] = {
917 0x07060605, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
918 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
919 0x1110100f, 0x0f0d0b09, 0x19171411, 0x1f1f1d1b,
920 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
921};
922
923static const u32 cmd3210[] = {
924 0x0f0d0b0a, 0x17151311, 0x1f1d1b19, 0x1f1f1f1f,
925 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f,
926 0x18171615, 0x1f1f1c1a, 0x1f1f1f1f, 0x1f1f1f1f,
927 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f, 0x1f1f1f1f
928};
929
930static const u32 clk2030[] = {
931 0x0e0d0d0c, 0x100f0f0e, 0x100f0e0d, 0x15131211,
932 0x1d1b1917, 0x2523211f, 0x2a282927, 0x32302e2c,
933 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120,
934 0x27262524, 0x2d2b2928, 0x3533312f, 0x3d3b3937
935};
936
937static const u32 ctl3215[] = {
938 0x01010000, 0x03020101, 0x07060504, 0x0b0a0908,
939 0x100f0e0d, 0x14131211, 0x18171615, 0x1c1b1a19,
940 0x05040403, 0x07060605, 0x0a090807, 0x0f0d0c0b,
941 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d
942};
943
944static const u32 ctl3220[] = {
945 0x05040403, 0x07060505, 0x0e0c0a08, 0x1a171411,
946 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e,
947 0x09080807, 0x0b0a0a09, 0x0f0d0c0b, 0x1b171311,
948 0x2825221f, 0x35322f2b, 0x3e3e3b38, 0x3e3e3e3e
949};
950
951static const u32 nc[] = {
952 0x00000000, 0x00000000, 0x00000000, 0x00000000,
953 0x00000000, 0x00000000, 0x00000000, 0x00000000,
954 0x00000000, 0x00000000, 0x00000000, 0x00000000,
955 0x00000000, 0x00000000, 0x00000000, 0x00000000
956};
957
958enum {
959 DQ2030,
960 DQ2330,
961 CMD2710,
962 CMD3210,
963 CLK2030,
964 CTL3215,
965 CTL3220,
966 NC,
967};
968
969static const u8 dual_channel_slew_group_lookup[] = {
970 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
971 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
972 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
973 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
974 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
975
976 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
977 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
978 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
979 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
980 DQ2030, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
981
982 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
983 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
984 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
985 DQ2030, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD2710,
986 DQ2030, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
987
988 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
989 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
990 DQ2030, CMD2710, CTL3215, CTL3215, CLK2030, CLK2030, DQ2030, CMD3210,
991 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, DQ2030, CMD2710,
992 DQ2030, CMD2710, CTL3215, NC, CLK2030, NC, NC, NC,
993
994 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
995 NC, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
996 NC, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
997 NC, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD2710
998};
999
1000static const u8 single_channel_slew_group_lookup[] = {
1001 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1002 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1003 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1004 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1005 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1006
1007 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1008 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1009 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1010 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1011 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1012
1013 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1014 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1015 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, DQ2330, CMD3210,
1016 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1017 DQ2330, CMD3210, NC, CTL3215, NC, CLK2030, NC, NC,
1018
1019 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1020 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1021 DQ2330, CMD3210, CTL3215, CTL3215, CLK2030, CLK2030, DQ2330, CMD3210,
1022 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, DQ2330, CMD3210,
1023 DQ2330, CMD3210, CTL3215, NC, CLK2030, NC, NC, NC,
1024
1025 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1026 DQ2330, NC, CTL3215, NC, CLK2030, NC, DQ2030, CMD3210,
1027 DQ2330, NC, NC, CTL3215, NC, CLK2030, DQ2030, CMD3210,
1028 DQ2330, NC, CTL3215, NC, CLK2030, CLK2030, DQ2030, CMD3210
1029};
1030
1031static const u32 *slew_group_lookup(int dual_channel, int index)
1032{
1033 const u8 *slew_group;
1034 /* Dual Channel needs different tables. */
1035 if (dual_channel)
1036 slew_group = dual_channel_slew_group_lookup;
1037 else
1038 slew_group = single_channel_slew_group_lookup;
1039
1040 switch (slew_group[index]) {
1041 case DQ2030: return dq2030;
1042 case DQ2330: return dq2330;
1043 case CMD2710: return cmd2710;
1044 case CMD3210: return cmd3210;
1045 case CLK2030: return clk2030;
1046 case CTL3215: return ctl3215;
1047 case CTL3220: return ctl3220;
1048 case NC: return nc;
1049 }
1050
1051 return nc;
1052}
1053
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001054#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001055/* Strength multiplier tables */
1056static const u8 dual_channel_strength_multiplier[] = {
1057 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1058 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1059 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1060 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1061 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1062 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1063 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1064 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1065 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1066 0x44, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1067 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1068 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1069 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1070 0x44, 0x11, 0x11, 0x11, 0x44, 0x44, 0x44, 0x22,
1071 0x44, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1072 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1073 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1074 0x44, 0x22, 0x11, 0x11, 0x44, 0x44, 0x44, 0x11,
1075 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x44, 0x22,
1076 0x44, 0x22, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1077 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1078 0x00, 0x00, 0x11, 0x00, 0x44, 0x00, 0x44, 0x11,
1079 0x00, 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x11,
1080 0x00, 0x00, 0x11, 0x00, 0x44, 0x44, 0x44, 0x22
1081};
1082
1083static const u8 single_channel_strength_multiplier[] = {
1084 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1085 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1086 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1087 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1088 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1089 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1090 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1091 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1092 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1093 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1094 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1095 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1096 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1097 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1098 0x33, 0x11, 0x00, 0x11, 0x00, 0x44, 0x00, 0x00,
1099 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1100 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1101 0x33, 0x11, 0x11, 0x11, 0x44, 0x44, 0x33, 0x11,
1102 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1103 0x33, 0x11, 0x11, 0x00, 0x44, 0x00, 0x00, 0x00,
1104 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1105 0x33, 0x00, 0x11, 0x00, 0x44, 0x00, 0x33, 0x11,
1106 0x33, 0x00, 0x00, 0x11, 0x00, 0x44, 0x33, 0x11,
1107 0x33, 0x00, 0x11, 0x00, 0x44, 0x44, 0x33, 0x11
1108};
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02001109#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001110static const u8 dual_channel_strength_multiplier[] = {
1111 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1112 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1113 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1114 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1115 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
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, 0x22,
1119 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1120 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1121 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1122 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1123 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1124 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1125 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1126 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1127 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1128 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1129 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33,
1130 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1131 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1132 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1133 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x22,
1134 0x44, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x33
1135};
1136
1137static const u8 single_channel_strength_multiplier[] = {
1138 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1139 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1140 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1141 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1142 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1143 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1144 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1145 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1146 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1147 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1148 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1149 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1150 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1151 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1152 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1153 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1154 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1155 0x44, 0x55, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1156 0x44, 0x88, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1157 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1158 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1159 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1160 0x44, 0x22, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00,
1161 0x44, 0x33, 0x00, 0x00, 0x44, 0x44, 0x44, 0x00
1162};
1163#endif
1164
Stefan Reinauer278534d2008-10-29 04:51:07 +00001165static void sdram_rcomp_buffer_strength_and_slew(struct sys_info *sysinfo)
1166{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001167 const u8 * strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001168 int idx, dual_channel;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001169
1170 /* Set Strength Multipliers */
1171
1172 /* Dual Channel needs different tables. */
1173 if (sdram_capabilities_dual_channel()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001174 printk(BIOS_DEBUG, "Programming Dual Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001175 strength_multiplier = dual_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001176 dual_channel = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001177 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[2];
1178 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001179 printk(BIOS_DEBUG, "Programming Single Channel RCOMP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001180 strength_multiplier = single_channel_strength_multiplier;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001181 dual_channel = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001182 idx = 5 * sysinfo->dimm[0] + sysinfo->dimm[1];
1183 }
1184
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001185 printk(BIOS_DEBUG, "Table Index: %d\n", idx);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001186
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001187 MCHBAR8(G1SC) = strength_multiplier[idx * 8 + 0];
1188 MCHBAR8(G2SC) = strength_multiplier[idx * 8 + 1];
1189 MCHBAR8(G3SC) = strength_multiplier[idx * 8 + 2];
1190 MCHBAR8(G4SC) = strength_multiplier[idx * 8 + 3];
1191 MCHBAR8(G5SC) = strength_multiplier[idx * 8 + 4];
1192 MCHBAR8(G6SC) = strength_multiplier[idx * 8 + 5];
1193 MCHBAR8(G7SC) = strength_multiplier[idx * 8 + 6];
1194 MCHBAR8(G8SC) = strength_multiplier[idx * 8 + 7];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001195
1196 /* Channel 0 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001197 sdram_write_slew_rates(G1SRPUT, slew_group_lookup(dual_channel, idx * 8 + 0));
1198 sdram_write_slew_rates(G2SRPUT, slew_group_lookup(dual_channel, idx * 8 + 1));
1199 if ((slew_group_lookup(dual_channel, idx * 8 + 2) != nc) && (sysinfo->package == SYSINFO_PACKAGE_STACKED)) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001200
Stefan Reinauer278534d2008-10-29 04:51:07 +00001201 sdram_write_slew_rates(G3SRPUT, ctl3220);
1202 } else {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001203 sdram_write_slew_rates(G3SRPUT, slew_group_lookup(dual_channel, idx * 8 + 2));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001204 }
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001205 sdram_write_slew_rates(G4SRPUT, slew_group_lookup(dual_channel, idx * 8 + 3));
1206 sdram_write_slew_rates(G5SRPUT, slew_group_lookup(dual_channel, idx * 8 + 4));
1207 sdram_write_slew_rates(G6SRPUT, slew_group_lookup(dual_channel, idx * 8 + 5));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001208
1209 /* Channel 1 */
1210 if (sysinfo->dual_channel) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001211 sdram_write_slew_rates(G7SRPUT, slew_group_lookup(dual_channel, idx * 8 + 6));
1212 sdram_write_slew_rates(G8SRPUT, slew_group_lookup(dual_channel, idx * 8 + 7));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001213 } else {
1214 sdram_write_slew_rates(G7SRPUT, nc);
1215 sdram_write_slew_rates(G8SRPUT, nc);
1216 }
1217}
1218
1219static void sdram_enable_rcomp(void)
1220{
1221 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001222 /* Enable Global Periodic RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001223 udelay(300);
1224 reg32 = MCHBAR32(GBRCOMPCTL);
1225 reg32 &= ~(1 << 23);
1226 MCHBAR32(GBRCOMPCTL) = reg32;
1227}
1228
1229static void sdram_program_dll_timings(struct sys_info *sysinfo)
1230{
1231 u32 chan0dll = 0, chan1dll = 0;
1232 int i;
1233
Elyes HAOUAS38424982016-08-21 12:01:04 +02001234 printk(BIOS_DEBUG, "Programming DLL Timings...\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001235
Stefan Reinauer278534d2008-10-29 04:51:07 +00001236 MCHBAR16(DQSMT) &= ~( (3 << 12) | (1 << 10) | ( 0xf << 0) );
1237 MCHBAR16(DQSMT) |= (1 << 13) | (0xc << 0);
1238
1239 /* We drive both channels with the same speed */
1240 switch (sysinfo->memory_frequency) {
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001241 case 400: chan0dll = 0x26262626; chan1dll = 0x26262626; break; /* 400MHz */
1242 case 533: chan0dll = 0x22222222; chan1dll = 0x22222222; break; /* 533MHz */
1243 case 667: chan0dll = 0x11111111; chan1dll = 0x11111111; break; /* 667MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001244 }
1245
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001246 for (i = 0; i < 4; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001247 MCHBAR32(C0R0B00DQST + (i * 0x10) + 0) = chan0dll;
1248 MCHBAR32(C0R0B00DQST + (i * 0x10) + 4) = chan0dll;
1249 MCHBAR32(C1R0B00DQST + (i * 0x10) + 0) = chan1dll;
1250 MCHBAR32(C1R0B00DQST + (i * 0x10) + 4) = chan1dll;
1251 }
1252}
1253
1254static void sdram_force_rcomp(void)
1255{
1256 u32 reg32;
1257 u8 reg8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001258
Stefan Reinauer278534d2008-10-29 04:51:07 +00001259 reg32 = MCHBAR32(ODTC);
1260 reg32 |= (1 << 28);
1261 MCHBAR32(ODTC) = reg32;
1262
1263 reg32 = MCHBAR32(SMSRCTL);
1264 reg32 |= (1 << 0);
1265 MCHBAR32(SMSRCTL) = reg32;
1266
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001267 /* Start initial RCOMP */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001268 reg32 = MCHBAR32(GBRCOMPCTL);
1269 reg32 |= (1 << 8);
1270 MCHBAR32(GBRCOMPCTL) = reg32;
1271
1272 reg8 = i945_silicon_revision();
1273 if ((reg8 == 0 && (MCHBAR32(DCC) & (3 << 0)) == 0) || (reg8 == 1)) {
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001274
Stefan Reinauer278534d2008-10-29 04:51:07 +00001275 reg32 = MCHBAR32(GBRCOMPCTL);
1276 reg32 |= (3 << 5);
1277 MCHBAR32(GBRCOMPCTL) = reg32;
1278 }
1279}
1280
1281static void sdram_initialize_system_memory_io(struct sys_info *sysinfo)
1282{
1283 u8 reg8;
1284 u32 reg32;
1285
Elyes HAOUAS38424982016-08-21 12:01:04 +02001286 printk(BIOS_DEBUG, "Initializing System Memory IO...\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001287 /* Enable Data Half Clock Pushout */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001288 reg8 = MCHBAR8(C0HCTC);
1289 reg8 &= ~0x1f;
1290 reg8 |= ( 1 << 0);
1291 MCHBAR8(C0HCTC) = reg8;
1292
1293 reg8 = MCHBAR8(C1HCTC);
1294 reg8 &= ~0x1f;
1295 reg8 |= ( 1 << 0);
1296 MCHBAR8(C1HCTC) = reg8;
1297
Stefan Reinauer278534d2008-10-29 04:51:07 +00001298 MCHBAR16(WDLLBYPMODE) &= ~( (1 << 9) | (1 << 6) | (1 << 4) | (1 << 3) | (1 << 1) );
1299 MCHBAR16(WDLLBYPMODE) |= (1 << 8) | (1 << 7) | (1 << 5) | (1 << 2) | (1 << 0);
1300
1301 MCHBAR8(C0WDLLCMC) = 0;
1302 MCHBAR8(C1WDLLCMC) = 0;
1303
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001304 /* Program RCOMP Settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001305 sdram_program_dram_width(sysinfo);
1306
1307 sdram_rcomp_buffer_strength_and_slew(sysinfo);
1308
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001309 /* Indicate that RCOMP programming is done */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001310 reg32 = MCHBAR32(GBRCOMPCTL);
1311 reg32 &= ~( (1 << 29) | (1 << 26) | (3 << 21) | (3 << 2) );
1312 reg32 |= (3 << 27) | (3 << 0);
1313 MCHBAR32(GBRCOMPCTL) = reg32;
1314
1315 MCHBAR32(GBRCOMPCTL) |= (1 << 10);
1316
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001317 /* Program DLL Timings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001318 sdram_program_dll_timings(sysinfo);
1319
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001320 /* Force RCOMP cycle */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001321 sdram_force_rcomp();
1322}
1323
1324static void sdram_enable_system_memory_io(struct sys_info *sysinfo)
1325{
1326 u32 reg32;
1327
Elyes HAOUAS38424982016-08-21 12:01:04 +02001328 printk(BIOS_DEBUG, "Enabling System Memory IO...\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001329
Stefan Reinauer278534d2008-10-29 04:51:07 +00001330 reg32 = MCHBAR32(RCVENMT);
1331 reg32 &= ~(0x3f << 6);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001332 MCHBAR32(RCVENMT) = reg32; /* [11:6] = 0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001333
1334 reg32 |= (1 << 11) | (1 << 9);
1335 MCHBAR32(RCVENMT) = reg32;
1336
1337 reg32 = MCHBAR32(DRTST);
1338 reg32 |= (1 << 3) | (1 << 2);
1339 MCHBAR32(DRTST) = reg32;
1340
1341 reg32 = MCHBAR32(DRTST);
1342 reg32 |= (1 << 6) | (1 << 4);
1343 MCHBAR32(DRTST) = reg32;
1344
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001345 asm volatile ("nop; nop;" ::: "memory");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001346
1347 reg32 = MCHBAR32(DRTST);
1348
1349 /* Is channel 0 populated? */
1350 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1351 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
1352 reg32 |= (1 << 7) | (1 << 5);
1353 else
1354 reg32 |= (1 << 31);
1355
1356 /* Is channel 1 populated? */
1357 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1358 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
1359 reg32 |= (1 << 9) | (1 << 8);
1360 else
1361 reg32 |= (1 << 30);
1362
1363 MCHBAR32(DRTST) = reg32;
1364
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001365 /* Activate DRAM Channel IO Buffers */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001366 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
1367 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) {
1368 reg32 = MCHBAR32(C0DRC1);
1369 reg32 |= (1 << 8);
1370 MCHBAR32(C0DRC1) = reg32;
1371 }
1372 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED ||
1373 sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED) {
1374 reg32 = MCHBAR32(C1DRC1);
1375 reg32 |= (1 << 8);
1376 MCHBAR32(C1DRC1) = reg32;
1377 }
1378}
1379
1380struct dimm_size {
1381 unsigned long side1;
1382 unsigned long side2;
1383};
1384
Sven Schnelle541269b2011-02-21 09:39:17 +00001385static struct dimm_size sdram_get_dimm_size(struct sys_info *sysinfo, u16 dimmno)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001386{
1387 /* Calculate the log base 2 size of a DIMM in bits */
1388 struct dimm_size sz;
Sven Schnelle541269b2011-02-21 09:39:17 +00001389 int value, low, rows, columns, device;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001390
Sven Schnelle541269b2011-02-21 09:39:17 +00001391 device = get_dimm_spd_address(sysinfo, dimmno);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001392 sz.side1 = 0;
1393 sz.side2 = 0;
1394
1395 rows = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1396 if (rows < 0) goto hw_err;
1397 if ((rows & 0xf) == 0) goto val_err;
1398 sz.side1 += rows & 0xf;
1399
1400 columns = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1401 if (columns < 0) goto hw_err;
1402 if ((columns & 0xf) == 0) goto val_err;
1403 sz.side1 += columns & 0xf;
1404
1405 value = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM); /* banks */
1406 if (value < 0) goto hw_err;
1407 if ((value & 0xff) == 0) goto val_err;
1408 sz.side1 += log2(value & 0xff);
1409
1410 /* Get the module data width and convert it to a power of two */
1411 value = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_MSB); /* (high byte) */
1412 if (value < 0) goto hw_err;
1413 value &= 0xff;
1414 value <<= 8;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001415
Stefan Reinauer278534d2008-10-29 04:51:07 +00001416 low = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* (low byte) */
1417 if (low < 0) goto hw_err;
1418 value = value | (low & 0xff);
1419 if ((value != 72) && (value != 64)) goto val_err;
1420 sz.side1 += log2(value);
1421
1422 /* side 2 */
1423 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS); /* number of physical banks */
1424
1425 if (value < 0) goto hw_err;
1426 value &= 7;
1427 value++;
1428 if (value == 1) goto out;
1429 if (value != 2) goto val_err;
1430
1431 /* Start with the symmetrical case */
1432 sz.side2 = sz.side1;
1433
1434 if ((rows & 0xf0) == 0) goto out; /* If symmetrical we are done */
1435
1436 /* Don't die here, I have not come across any of these to test what
1437 * actually happens.
1438 */
Martin Roth128c1042016-11-18 09:29:03 -07001439 printk(BIOS_ERR, "Asymmetric DIMMs are not supported by this chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001440
1441 sz.side2 -= (rows & 0x0f); /* Subtract out rows on side 1 */
1442 sz.side2 += ((rows >> 4) & 0x0f); /* Add in rows on side 2 */
1443
1444 sz.side2 -= (columns & 0x0f); /* Subtract out columns on side 1 */
1445 sz.side2 += ((columns >> 4) & 0x0f); /* Add in columns on side 2 */
1446
1447 goto out;
1448
1449 val_err:
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001450 die("Bad SPD value\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001451 hw_err:
Elyes HAOUAS15279a92016-07-28 21:05:26 +02001452 /* If a hardware error occurs the spd ROM probably does not exist.
Stefan Reinauer278534d2008-10-29 04:51:07 +00001453 * In this case report that there is no memory
1454 */
1455 sz.side1 = 0;
1456 sz.side2 = 0;
Patrick Georgic5fc7db2012-03-07 15:55:47 +01001457out:
Stefan Reinauer278534d2008-10-29 04:51:07 +00001458 return sz;
1459}
1460
1461static void sdram_detect_dimm_size(struct sys_info * sysinfo)
1462{
1463 int i;
1464
Elyes HAOUAS12df9502016-08-23 21:29:48 +02001465 for (i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001466 struct dimm_size sz;
1467
1468 sysinfo->banksize[i * 2] = 0;
1469 sysinfo->banksize[(i * 2) + 1] = 0;
1470
1471 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1472 continue;
1473
Sven Schnelle541269b2011-02-21 09:39:17 +00001474 sz = sdram_get_dimm_size(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001475
Sven Schnelle541269b2011-02-21 09:39:17 +00001476 sysinfo->banks[i] = spd_read_byte(get_dimm_spd_address(sysinfo, i),
1477 SPD_NUM_BANKS_PER_SDRAM); /* banks */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001478
1479 if (sz.side1 < 30)
1480 die("DDR-II rank size smaller than 128MB is not supported.\n");
1481
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001482 sysinfo->banksize[i * 2] = 1 << (sz.side1 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001483
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001484 printk(BIOS_DEBUG, "DIMM %d side 0 = %d MB\n", i, sysinfo->banksize[i * 2] * 32 );
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001485
Stefan Reinauer278534d2008-10-29 04:51:07 +00001486 if (!sz.side2)
1487 continue;
1488
1489 /* If there is a second side, it has to have at least 128M, too */
1490 if (sz.side2 < 30)
1491 die("DDR-II rank size smaller than 128MB is not supported.\n");
1492
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001493 sysinfo->banksize[(i * 2) + 1] = 1 << (sz.side2 - 28);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001494
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001495 printk(BIOS_DEBUG, "DIMM %d side 1 = %d MB\n", i, sysinfo->banksize[(i * 2) + 1] * 32);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001496 }
1497}
1498
1499static int sdram_program_row_boundaries(struct sys_info *sysinfo)
1500{
1501 int i;
Arthur Heymans885c2892016-10-03 17:16:48 +02001502 int cum0, cum1, tolud, tom, pci_mmio_size;
1503 const struct device *dev;
1504 const struct northbridge_intel_i945_config *cfg = NULL;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001505
Paul Menzel84283bc2014-07-17 08:16:04 +02001506 printk(BIOS_DEBUG, "Setting RAM size...\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001507
1508 cum0 = 0;
Elyes HAOUAS12df9502016-08-23 21:29:48 +02001509 for (i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001510 cum0 += sysinfo->banksize[i];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001511 MCHBAR8(C0DRB0+i) = cum0;
1512 }
1513
1514 /* Assume we continue in Channel 1 where we stopped in Channel 0 */
1515 cum1 = cum0;
1516
1517 /* Exception: Interleaved starts from the beginning */
1518 if (sysinfo->interleaved)
1519 cum1 = 0;
1520
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001521#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00001522 /* Exception: Channel 1 is not populated. C1DRB stays zero */
1523 if (sysinfo->dimm[2] == SYSINFO_DIMM_NOT_POPULATED &&
1524 sysinfo->dimm[3] == SYSINFO_DIMM_NOT_POPULATED)
1525 cum1 = 0;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001526#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00001527
Elyes HAOUAS12df9502016-08-23 21:29:48 +02001528 for (i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001529 cum1 += sysinfo->banksize[i + 4];
Stefan Reinauer278534d2008-10-29 04:51:07 +00001530 MCHBAR8(C1DRB0+i) = cum1;
1531 }
1532
1533 /* Set TOLUD Top Of Low Usable DRAM */
1534 if (sysinfo->interleaved)
1535 tolud = (cum0 + cum1) << 1;
1536 else
1537 tolud = (cum1 ? cum1 : cum0) << 1;
Stefan Reinauer779b3e32008-11-10 15:43:37 +00001538
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001539 /* The TOM register has a different format */
1540 tom = tolud >> 3;
1541
1542 /* Limit the value of TOLUD to leave some space for PCI memory. */
Arthur Heymans885c2892016-10-03 17:16:48 +02001543 dev = dev_find_slot(0, PCI_DEVFN(0, 0));
1544 if (dev)
1545 cfg = dev->chip_info;
1546
1547 /* Don't use pci mmio sizes smaller than 768M */
1548 if (!cfg || cfg->pci_mmio_size <= DEFAULT_PCI_MMIO_SIZE)
1549 pci_mmio_size = DEFAULT_PCI_MMIO_SIZE;
1550 else
1551 pci_mmio_size = cfg->pci_mmio_size;
1552
1553 tolud = MIN(((4096 - pci_mmio_size) / 128) << 3, tolud);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001554
1555 pci_write_config8(PCI_DEV(0,0,0), TOLUD, tolud);
1556
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001557 printk(BIOS_DEBUG, "C0DRB = 0x%08x\n", MCHBAR32(C0DRB0));
1558 printk(BIOS_DEBUG, "C1DRB = 0x%08x\n", MCHBAR32(C1DRB0));
1559 printk(BIOS_DEBUG, "TOLUD = 0x%04x\n", pci_read_config8(PCI_DEV(0,0,0), TOLUD));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001560
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001561 pci_write_config16(PCI_DEV(0,0,0), TOM, tom);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001562
1563 return 0;
1564}
1565
Stefan Reinauer278534d2008-10-29 04:51:07 +00001566static int sdram_set_row_attributes(struct sys_info *sysinfo)
1567{
1568 int i, value;
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001569 u16 dra0 = 0, dra1 = 0, dra = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001570
Elyes HAOUAS38424982016-08-21 12:01:04 +02001571 printk(BIOS_DEBUG, "Setting row attributes...\n");
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001572 for (i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001573 u16 device;
1574 u8 columnsrows;
1575
1576 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
1577 continue;
1578 }
1579
Sven Schnelle541269b2011-02-21 09:39:17 +00001580 device = get_dimm_spd_address(sysinfo, i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001581
1582 value = spd_read_byte(device, SPD_NUM_ROWS); /* rows */
1583 columnsrows = (value & 0x0f);
1584
1585 value = spd_read_byte(device, SPD_NUM_COLUMNS); /* columns */
1586 columnsrows |= (value & 0xf) << 4;
1587
1588 switch (columnsrows) {
1589 case 0x9d: dra = 2; break;
1590 case 0xad: dra = 3; break;
1591 case 0xbd: dra = 4; break;
1592 case 0xae: dra = 3; break;
1593 case 0xbe: dra = 4; break;
1594 default: die("Unsupported Rows/Columns. (DRA)");
1595 }
1596
1597 /* Double Sided DIMMs? */
1598 if (sysinfo->banksize[(2 * i) + 1] != 0) {
1599 dra = (dra << 4) | dra;
1600 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001601
Stefan Reinauer278534d2008-10-29 04:51:07 +00001602 if (i < DIMM_SOCKETS)
1603 dra0 |= (dra << (i*8));
1604 else
1605 dra1 |= (dra << ((i - DIMM_SOCKETS)*8));
1606 }
1607
1608 MCHBAR16(C0DRA0) = dra0;
1609 MCHBAR16(C1DRA0) = dra1;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001610
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001611 printk(BIOS_DEBUG, "C0DRA = 0x%04x\n", dra0);
1612 printk(BIOS_DEBUG, "C1DRA = 0x%04x\n", dra1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001613
1614 return 0;
1615}
1616
1617static void sdram_set_bank_architecture(struct sys_info *sysinfo)
1618{
1619 u32 off32;
1620 int i;
1621
1622 MCHBAR16(C1BNKARC) &= 0xff00;
1623 MCHBAR16(C0BNKARC) &= 0xff00;
1624
1625 off32 = C0BNKARC;
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001626 for (i = 0; i < 2 * DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001627 /* Switch to second channel */
1628 if (i == DIMM_SOCKETS)
1629 off32 = C1BNKARC;
1630
1631 if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED)
1632 continue;
1633
1634 if (sysinfo->banks[i] != 8)
1635 continue;
1636
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001637 printk(BIOS_SPEW, "DIMM%d has 8 banks.\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001638
1639 if (i & 1)
1640 MCHBAR16(off32) |= 0x50;
1641 else
1642 MCHBAR16(off32) |= 0x05;
1643 }
1644}
1645
1646#define REFRESH_7_8US 1
1647#define REFRESH_15_6US 0
1648static void sdram_program_refresh_rate(struct sys_info *sysinfo)
1649{
1650 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001651
Stefan Reinauer278534d2008-10-29 04:51:07 +00001652 if (sysinfo->refresh == REFRESH_7_8US) {
1653 reg32 = (2 << 8); /* Refresh enabled at 7.8us */
1654 } else {
1655 reg32 = (1 << 8); /* Refresh enabled at 15.6us */
1656 }
1657
1658 MCHBAR32(C0DRC0) &= ~(7 << 8);
1659 MCHBAR32(C0DRC0) |= reg32;
1660
1661 MCHBAR32(C1DRC0) &= ~(7 << 8);
1662 MCHBAR32(C1DRC0) |= reg32;
1663}
1664
1665static void sdram_program_cke_tristate(struct sys_info *sysinfo)
1666{
1667 u32 reg32;
1668 int i;
1669
1670 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001671
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001672 for (i = 0; i < 4; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001673 if (sysinfo->banksize[i] == 0) {
1674 reg32 |= (1 << (16 + i));
1675 }
1676 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001677
Stefan Reinauer278534d2008-10-29 04:51:07 +00001678 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001679
Stefan Reinauer278534d2008-10-29 04:51:07 +00001680 reg32 |= (1 << 11);
1681 MCHBAR32(C0DRC1) = reg32;
1682
1683 /* Do we have to do this if we're in Single Channel Mode? */
1684 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001685
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001686 for (i = 4; i < 8; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001687 if (sysinfo->banksize[i] == 0) {
1688 reg32 |= (1 << (12 + i));
1689 }
1690 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001691
Stefan Reinauer278534d2008-10-29 04:51:07 +00001692 reg32 |= (1 << 12);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001693
Stefan Reinauer278534d2008-10-29 04:51:07 +00001694 reg32 |= (1 << 11);
1695 MCHBAR32(C1DRC1) = reg32;
1696}
1697
1698static void sdram_program_odt_tristate(struct sys_info *sysinfo)
1699{
1700 u32 reg32;
1701 int i;
1702
1703 reg32 = MCHBAR32(C0DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001704
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001705 for (i = 0; i < 4; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001706 if (sysinfo->banksize[i] == 0) {
1707 reg32 |= (1 << (24 + i));
1708 }
1709 }
1710 MCHBAR32(C0DRC2) = reg32;
1711
1712 reg32 = MCHBAR32(C1DRC2);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001713
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001714 for (i = 4; i < 8; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001715 if (sysinfo->banksize[i] == 0) {
1716 reg32 |= (1 << (20 + i));
1717 }
1718 }
1719 MCHBAR32(C1DRC2) = reg32;
1720}
1721
1722static void sdram_set_timing_and_control(struct sys_info *sysinfo)
1723{
1724 u32 reg32, off32;
1725 u32 tWTR;
1726 u32 temp_drt;
1727 int i, page_size;
1728
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001729 static const u8 drt0_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001730 /* CL 3, 4, 5 */
Arthur Heymanse1897612016-10-15 23:29:18 +02001731 3, 4, 5, /* FSB533, DDR667/533/400 */
1732 4, 5, 6, /* FSB667, DDR667/533/400 */
1733 5, 6, 7, /* FSB800, DDR400/533 */
1734 6, 7, 8, /* FSB800, DDR667 */
1735 5, 6, 7, /* FSB1066, DDR400 */
1736 7, 8, 9, /* FSB1066, DDR533/DDR667 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001737 };
1738
Edward O'Callaghan2f237c12014-05-25 06:24:39 +10001739 static const u8 cas_table[] = {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001740 2, 1, 0, 3
1741 };
1742
1743 reg32 = MCHBAR32(C0DRC0);
1744 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001745 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001746 MCHBAR32(C0DRC0) = reg32;
1747
1748 reg32 = MCHBAR32(C1DRC0);
1749 reg32 |= (1 << 2); /* Burst Length 8 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001750 reg32 &= ~( (1 << 13) | (1 << 12) );
Stefan Reinauer278534d2008-10-29 04:51:07 +00001751 MCHBAR32(C1DRC0) = reg32;
1752
1753 if (!sysinfo->dual_channel && sysinfo->dimm[1] !=
1754 SYSINFO_DIMM_NOT_POPULATED) {
1755 reg32 = MCHBAR32(C0DRC0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001756 reg32 |= (1 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001757 MCHBAR32(C0DRC0) = reg32;
1758 }
1759
1760 sdram_program_refresh_rate(sysinfo);
1761
1762 sdram_program_cke_tristate(sysinfo);
1763
1764 sdram_program_odt_tristate(sysinfo);
1765
1766 /* Calculate DRT0 */
1767
1768 temp_drt = 0;
1769
1770 /* B2B Write Precharge (same bank) = CL-1 + BL/2 + tWR */
1771 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + sysinfo->twr;
1772 temp_drt |= (reg32 << 28);
1773
1774 /* Write Auto Precharge (same bank) = CL-1 + BL/2 + tWR + tRP */
1775 reg32 += sysinfo->trp;
1776 temp_drt |= (reg32 << 4);
1777
1778 if (sysinfo->memory_frequency == 667) {
1779 tWTR = 3; /* 667MHz */
1780 } else {
1781 tWTR = 2; /* 400 and 533 */
1782 }
1783
1784 /* B2B Write to Read Command Spacing */
1785 reg32 = (sysinfo->cas - 1) + (BURSTLENGTH / 2) + tWTR;
1786 temp_drt |= (reg32 << 24);
1787
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001788 /* CxDRT0 [23:22], [21:20], [19:18] [16] have fixed values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001789 temp_drt |= ( (1 << 22) | (3 << 20) | (1 << 18) | (0 << 16) );
1790
1791 /* Program Write Auto Precharge to Activate */
1792 off32 = 0;
Arthur Heymanse1897612016-10-15 23:29:18 +02001793 switch (sysinfo->fsb_frequency) {
1794 case 533:
1795 off32 = 0;
1796 break;
1797 case 667:
1798 off32 = 3;
1799 break;
1800 case 800:
1801 if (sysinfo->memory_frequency <= 533) {
1802 off32 = 6;
1803 break;
1804 }
1805 off32 = 9;
1806 break;
1807 case 1066:
1808 if (sysinfo->memory_frequency == 400) {
1809 off32 = 12;
1810 break;
1811 }
1812 off32 = 15;
1813 break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001814 }
Arthur Heymanse1897612016-10-15 23:29:18 +02001815
Stefan Reinauer278534d2008-10-29 04:51:07 +00001816 off32 += sysinfo->cas - 3;
1817 reg32 = drt0_table[off32];
1818 temp_drt |= (reg32 << 11);
1819
1820 /* Read Auto Precharge to Activate */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001821
Stefan Reinauer278534d2008-10-29 04:51:07 +00001822 temp_drt |= (8 << 0);
1823
1824 MCHBAR32(C0DRT0) = temp_drt;
1825 MCHBAR32(C1DRT0) = temp_drt;
1826
1827 /* Calculate DRT1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001828
Stefan Reinauer278534d2008-10-29 04:51:07 +00001829 temp_drt = MCHBAR32(C0DRT1) & 0x00020088;
1830
1831 /* DRAM RASB Precharge */
1832 temp_drt |= (sysinfo->trp - 2) << 0;
1833
1834 /* DRAM RASB to CASB Delay */
1835 temp_drt |= (sysinfo->trcd - 2) << 4;
1836
1837 /* CASB Latency */
1838 temp_drt |= (cas_table[sysinfo->cas - 3]) << 8;
1839
1840 /* Refresh Cycle Time */
1841 temp_drt |= (sysinfo->trfc) << 10;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001842
Stefan Reinauer278534d2008-10-29 04:51:07 +00001843 /* Pre-All to Activate Delay */
1844 temp_drt |= (0 << 16);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001845
Stefan Reinauer278534d2008-10-29 04:51:07 +00001846 /* Precharge to Precharge Delay stays at 1 clock */
1847 temp_drt |= (0 << 18);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001848
Stefan Reinauer278534d2008-10-29 04:51:07 +00001849 /* Activate to Precharge Delay */
1850 temp_drt |= (sysinfo->tras << 19);
1851
1852 /* Read to Precharge (tRTP) */
1853 if (sysinfo->memory_frequency == 667) {
1854 temp_drt |= (1 << 28);
1855 } else {
1856 temp_drt |= (0 << 28);
1857 }
1858
1859 /* Determine page size */
1860 reg32 = 0;
1861 page_size = 1; /* Default: 1k pagesize */
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001862 for (i = 0; i< 2*DIMM_SOCKETS; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001863 if (sysinfo->dimm[i] == SYSINFO_DIMM_X16DS ||
1864 sysinfo->dimm[i] == SYSINFO_DIMM_X16SS)
1865 page_size = 2; /* 2k pagesize */
1866 }
1867
1868 if (sysinfo->memory_frequency == 533 && page_size == 2) {
1869 reg32 = 1;
1870 }
1871 if (sysinfo->memory_frequency == 667) {
1872 reg32 = page_size;
1873 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001874
Stefan Reinauer278534d2008-10-29 04:51:07 +00001875 temp_drt |= (reg32 << 30);
1876
1877 MCHBAR32(C0DRT1) = temp_drt;
1878 MCHBAR32(C1DRT1) = temp_drt;
1879
1880 /* Program DRT2 */
1881 reg32 = MCHBAR32(C0DRT2);
1882 reg32 &= ~(1 << 8);
1883 MCHBAR32(C0DRT2) = reg32;
1884
1885 reg32 = MCHBAR32(C1DRT2);
1886 reg32 &= ~(1 << 8);
1887 MCHBAR32(C1DRT2) = reg32;
1888
1889 /* Calculate DRT3 */
1890 temp_drt = MCHBAR32(C0DRT3) & ~0x07ffffff;
1891
1892 /* Get old tRFC value */
1893 reg32 = MCHBAR32(C0DRT1) >> 10;
1894 reg32 &= 0x3f;
1895
1896 /* 788nS - tRFC */
1897 switch (sysinfo->memory_frequency) {
1898 case 400: /* 5nS */
1899 reg32 = ((78800 / 500) - reg32) & 0x1ff;
1900 reg32 |= (0x8c << 16) | (0x0c << 10); /* 1 us */
1901 break;
1902 case 533: /* 3.75nS */
1903 reg32 = ((78800 / 375) - reg32) & 0x1ff;
1904 reg32 |= (0xba << 16) | (0x10 << 10); /* 1 us */
1905 break;
1906 case 667: /* 3nS */
1907 reg32 = ((78800 / 300) - reg32) & 0x1ff;
1908 reg32 |= (0xe9 << 16) | (0x14 << 10); /* 1 us */
1909 break;
1910 }
1911
1912 temp_drt |= reg32;
1913
1914 MCHBAR32(C0DRT3) = temp_drt;
1915 MCHBAR32(C1DRT3) = temp_drt;
1916}
1917
1918static void sdram_set_channel_mode(struct sys_info *sysinfo)
1919{
1920 u32 reg32;
1921
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001922 printk(BIOS_DEBUG, "Setting mode of operation for memory channels...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001923
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001924 if (sdram_capabilities_interleave() &&
Stefan Reinauer278534d2008-10-29 04:51:07 +00001925 ( ( sysinfo->banksize[0] + sysinfo->banksize[1] +
1926 sysinfo->banksize[2] + sysinfo->banksize[3] ) ==
1927 ( sysinfo->banksize[4] + sysinfo->banksize[5] +
1928 sysinfo->banksize[6] + sysinfo->banksize[7] ) ) ) {
1929 /* Both channels equipped with DIMMs of the same size */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001930 sysinfo->interleaved = 1;
1931 } else {
1932 sysinfo->interleaved = 0;
1933 }
1934
1935 reg32 = MCHBAR32(DCC);
1936 reg32 &= ~(7 << 0);
1937
Elyes HAOUAS12df9502016-08-23 21:29:48 +02001938 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00001939 /* Dual Channel Interleaved */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001940 printk(BIOS_DEBUG, "Dual Channel Interleaved.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001941 reg32 |= (1 << 1);
1942 } else if (sysinfo->dimm[0] == SYSINFO_DIMM_NOT_POPULATED &&
1943 sysinfo->dimm[1] == SYSINFO_DIMM_NOT_POPULATED) {
1944 /* Channel 1 only */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001945 printk(BIOS_DEBUG, "Single Channel 1 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001946 reg32 |= (1 << 2);
1947 } else if (sdram_capabilities_dual_channel() && sysinfo->dimm[2] !=
1948 SYSINFO_DIMM_NOT_POPULATED) {
Martin Roth128c1042016-11-18 09:29:03 -07001949 /* Dual Channel Asymmetric */
1950 printk(BIOS_DEBUG, "Dual Channel Asymmetric.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001951 reg32 |= (1 << 0);
1952 } else {
1953 /* All bits 0 means Single Channel 0 operation */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00001954 printk(BIOS_DEBUG, "Single Channel 0 only.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001955 }
1956
Stefan Reinauerbf264e92010-05-14 19:09:20 +00001957 /* Now disable channel XORing */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001958 reg32 |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001959
1960 MCHBAR32(DCC) = reg32;
1961
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02001962 PRINTK_DEBUG("DCC = 0x%08x\n", MCHBAR32(DCC));
Stefan Reinauer278534d2008-10-29 04:51:07 +00001963}
1964
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001965static void sdram_program_pll_settings(struct sys_info *sysinfo)
Stefan Reinauer278534d2008-10-29 04:51:07 +00001966{
Stefan Reinauer278534d2008-10-29 04:51:07 +00001967 MCHBAR32(PLLMON) = 0x80800000;
1968
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001969 sysinfo->fsb_frequency = fsbclk();
Peter Stuge76d91432010-10-01 10:02:33 +00001970 if (sysinfo->fsb_frequency == 0xffff)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00001971 die("Unsupported FSB speed");
Stefan Reinauer278534d2008-10-29 04:51:07 +00001972
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001973 /* Program CPCTL according to FSB speed */
1974 /* Only write the lower byte */
1975 switch (sysinfo->fsb_frequency) {
1976 case 400: MCHBAR8(CPCTL) = 0x90; break; /* FSB400 */
1977 case 533: MCHBAR8(CPCTL) = 0x95; break; /* FSB533 */
1978 case 667: MCHBAR8(CPCTL) = 0x8d; break; /* FSB667 */
1979 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00001980
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001981 MCHBAR16(CPCTL) &= ~(1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00001982
Paul Menzel0ce5ebf2013-10-21 21:22:09 +02001983 MCHBAR16(CPCTL); /* Read back register to activate settings */
Stefan Reinauer278534d2008-10-29 04:51:07 +00001984}
1985
1986static void sdram_program_graphics_frequency(struct sys_info *sysinfo)
1987{
1988 u8 reg8;
1989 u16 reg16;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00001990 u8 freq, second_vco, voltage;
Stefan Reinauer278534d2008-10-29 04:51:07 +00001991
1992#define CRCLK_166MHz 0x00
1993#define CRCLK_200MHz 0x01
1994#define CRCLK_250MHz 0x03
1995#define CRCLK_400MHz 0x05
1996
1997#define CDCLK_200MHz 0x00
1998#define CDCLK_320MHz 0x40
1999
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002000#define VOLTAGE_1_05 0x00
2001#define VOLTAGE_1_50 0x01
2002
Paul Menzeldaf9e502014-07-15 23:49:16 +02002003 printk(BIOS_DEBUG, "Setting Graphics Frequency...\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002004
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002005 printk(BIOS_DEBUG, "FSB: %d MHz ", sysinfo->fsb_frequency);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002006
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002007 voltage = VOLTAGE_1_05;
2008 if (MCHBAR32(DFT_STRAP1) & (1 << 20))
2009 voltage = VOLTAGE_1_50;
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002010 printk(BIOS_DEBUG, "Voltage: %s ", (voltage == VOLTAGE_1_05)?"1.05V":"1.5V");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002011
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002012 /* Gate graphics hardware for frequency change */
2013 reg8 = pci_read_config16(PCI_DEV(0,2,0), GCFC + 1);
2014 reg8 = (1<<3) | (1<<1); /* disable crclk, gate cdclk */
2015 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002016
2017 /* Get graphics frequency capabilities */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002018 reg8 = sdram_capabilities_core_frequencies();
2019
Stefan Reinauer278534d2008-10-29 04:51:07 +00002020 freq = CRCLK_250MHz;
2021 switch (reg8) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002022 case GFX_FREQUENCY_CAP_ALL:
2023 if (voltage == VOLTAGE_1_05)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002024 freq = CRCLK_250MHz;
2025 else
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002026 freq = CRCLK_400MHz; /* 1.5V requires 400MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002027 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002028 case GFX_FREQUENCY_CAP_250MHZ: freq = CRCLK_250MHz; break;
2029 case GFX_FREQUENCY_CAP_200MHZ: freq = CRCLK_200MHz; break;
2030 case GFX_FREQUENCY_CAP_166MHZ: freq = CRCLK_166MHz; break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002031 }
2032
2033 if (freq != CRCLK_400MHz) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002034 /* What chipset are we? Force 166MHz for GMS */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002035 reg8 = (pci_read_config8(PCI_DEV(0, 0x00,0), 0xe7) & 0x70) >> 4;
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002036 if (reg8 == 2)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002037 freq = CRCLK_166MHz;
2038 }
2039
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002040 printk(BIOS_DEBUG, "Render: ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002041 switch (freq) {
Elyes HAOUAS0f92f632014-07-27 19:37:31 +02002042 case CRCLK_166MHz: printk(BIOS_DEBUG, "166MHz"); break;
2043 case CRCLK_200MHz: printk(BIOS_DEBUG, "200MHz"); break;
2044 case CRCLK_250MHz: printk(BIOS_DEBUG, "250MHz"); break;
2045 case CRCLK_400MHz: printk(BIOS_DEBUG, "400MHz"); break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002046 }
2047
Stefan Reinauer278534d2008-10-29 04:51:07 +00002048 if (i945_silicon_revision() == 0) {
2049 sysinfo->mvco4x = 1;
2050 } else {
2051 sysinfo->mvco4x = 0;
2052 }
2053
Stefan Reinauer278534d2008-10-29 04:51:07 +00002054 second_vco = 0;
2055
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002056 if (voltage == VOLTAGE_1_50) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002057 second_vco = 1;
2058 } else if ((i945_silicon_revision() > 0) && (freq == CRCLK_250MHz)) {
2059 u16 mem = sysinfo->memory_frequency;
2060 u16 fsb = sysinfo->fsb_frequency;
2061
2062 if ( (fsb == 667 && mem == 533) ||
2063 (fsb == 533 && mem == 533) ||
2064 (fsb == 533 && mem == 400)) {
2065 second_vco = 1;
2066 }
2067
2068 if (fsb == 667 && mem == 533)
2069 sysinfo->mvco4x = 1;
2070 }
2071
2072 if (second_vco) {
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002073 sysinfo->clkcfg_bit7 = 1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002074 } else {
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002075 sysinfo->clkcfg_bit7 = 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002076 }
2077
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002078 /* Graphics Core Render Clock */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002079 reg16 = pci_read_config16(PCI_DEV(0,2,0), GCFC);
2080 reg16 &= ~( (7 << 0) | (1 << 13) );
2081 reg16 |= freq;
2082 pci_write_config16(PCI_DEV(0,2,0), GCFC, reg16);
2083
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002084 /* Graphics Core Display Clock */
2085 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC);
2086 reg8 &= ~( (1<<7) | (7<<4) );
2087
2088 if (voltage == VOLTAGE_1_05) {
2089 reg8 |= CDCLK_200MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002090 printk(BIOS_DEBUG, " Display: 200MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002091 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002092 reg8 |= CDCLK_320MHz;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002093 printk(BIOS_DEBUG, " Display: 320MHz\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002094 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002095 pci_write_config8(PCI_DEV(0,2,0), GCFC, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002096
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002097 reg8 = pci_read_config8(PCI_DEV(0,2,0), GCFC + 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002098
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002099 reg8 |= (1<<3) | (1<<1);
2100 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2101
2102 reg8 |= 0x0f;
2103 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
2104
2105 /* Ungate core render and display clocks */
2106 reg8 &= 0xf0;
2107 pci_write_config8(PCI_DEV(0,2,0), GCFC + 1, reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002108}
2109
2110static void sdram_program_memory_frequency(struct sys_info *sysinfo)
2111{
2112 u32 clkcfg;
2113 u8 reg8;
Arthur Heymans626f8c82016-10-08 21:37:13 +02002114 u8 offset = IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM) ? 1 : 0;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002115
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002116 printk(BIOS_DEBUG, "Setting Memory Frequency... ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002117
Stefan Reinauer278534d2008-10-29 04:51:07 +00002118 clkcfg = MCHBAR32(CLKCFG);
2119
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002120 printk(BIOS_DEBUG, "CLKCFG = 0x%08x, ", clkcfg);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002121
2122 clkcfg &= ~( (1 << 12) | (1 << 7) | ( 7 << 4) );
2123
2124 if (sysinfo->mvco4x) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002125 printk(BIOS_DEBUG, "MVCO 4x, ");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002126 clkcfg &= ~(1 << 12);
2127 }
2128
2129 if (sysinfo->clkcfg_bit7) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002130 printk(BIOS_DEBUG, "second VCO, ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002131
Stefan Reinauer278534d2008-10-29 04:51:07 +00002132 clkcfg |= (1 << 7);
2133 }
2134
2135 switch (sysinfo->memory_frequency) {
Arthur Heymans626f8c82016-10-08 21:37:13 +02002136 case 400: clkcfg |= ((1 + offset) << 4); break;
2137 case 533: clkcfg |= ((2 + offset) << 4); break;
2138 case 667: clkcfg |= ((3 + offset) << 4); break;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002139 default: die("Target Memory Frequency Error");
2140 }
2141
2142 if (MCHBAR32(CLKCFG) == clkcfg) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002143 printk(BIOS_DEBUG, "ok (unchanged)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002144 return;
2145 }
2146
2147 MCHBAR32(CLKCFG) = clkcfg;
2148
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002149 /* Make sure the following code is in the
Stefan Reinauer278534d2008-10-29 04:51:07 +00002150 * cache before we execute it.
2151 */
2152 goto cache_code;
2153vco_update:
2154 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
2155 reg8 &= ~(1 << 7);
2156 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
2157
Stefan Reinauer278534d2008-10-29 04:51:07 +00002158 clkcfg &= ~(1 << 10);
2159 MCHBAR32(CLKCFG) = clkcfg;
2160 clkcfg |= (1 << 10);
2161 MCHBAR32(CLKCFG) = clkcfg;
2162
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002163 asm volatile (
Stefan Reinauer278534d2008-10-29 04:51:07 +00002164 " movl $0x100, %%ecx\n"
2165 "delay_update:\n"
2166 " nop\n"
2167 " nop\n"
2168 " nop\n"
2169 " nop\n"
2170 " loop delay_update\n"
2171 : /* No outputs */
2172 : /* No inputs */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002173 : "%ecx", "memory"
Stefan Reinauer278534d2008-10-29 04:51:07 +00002174 );
2175
Stefan Reinauer278534d2008-10-29 04:51:07 +00002176 clkcfg &= ~(1 << 10);
2177 MCHBAR32(CLKCFG) = clkcfg;
2178
2179 goto out;
2180cache_code:
2181 goto vco_update;
2182out:
2183
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002184 printk(BIOS_DEBUG, "CLKCFG = 0x%08x, ", MCHBAR32(CLKCFG));
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002185 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002186}
2187
2188static void sdram_program_clock_crossing(void)
2189{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002190 int idx = 0;
2191
2192 /**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002193 * We add the indices according to our clocks from CLKCFG.
Stefan Reinauer278534d2008-10-29 04:51:07 +00002194 */
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002195#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer278534d2008-10-29 04:51:07 +00002196 static const u32 data_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002197 0x00100401, 0x00000000, /* DDR400 FSB400 */
Martin Roth2ed0aa22016-01-05 20:58:58 -07002198 0xffffffff, 0xffffffff, /* nonexistent */
2199 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002200
Stefan Reinauer278534d2008-10-29 04:51:07 +00002201 0x08040120, 0x00000000, /* DDR400 FSB533 */
2202 0x00100401, 0x00000000, /* DDR533 FSB533 */
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002203 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002204
2205 0x04020120, 0x00000010, /* DDR400 FSB667 */
2206 0x10040280, 0x00000040, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002207 0x00100401, 0x00000000, /* DDR667 FSB667 */
2208
Martin Roth2ed0aa22016-01-05 20:58:58 -07002209 0xffffffff, 0xffffffff, /* nonexistent */
2210 0xffffffff, 0xffffffff, /* nonexistent */
2211 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002212
Martin Roth2ed0aa22016-01-05 20:58:58 -07002213 0xffffffff, 0xffffffff, /* nonexistent */
2214 0xffffffff, 0xffffffff, /* nonexistent */
2215 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002216 };
2217
2218 static const u32 command_clock_crossing[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002219 0x04020208, 0x00000000, /* DDR400 FSB400 */
Martin Roth2ed0aa22016-01-05 20:58:58 -07002220 0xffffffff, 0xffffffff, /* nonexistent */
2221 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002222
Stefan Reinauer278534d2008-10-29 04:51:07 +00002223 0x00060108, 0x00000000, /* DDR400 FSB533 */
2224 0x04020108, 0x00000000, /* DDR533 FSB533 */
Martin Roth2ed0aa22016-01-05 20:58:58 -07002225 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002226
2227 0x00040318, 0x00000000, /* DDR400 FSB667 */
2228 0x04020118, 0x00000000, /* DDR533 FSB667 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002229 0x02010804, 0x00000000, /* DDR667 FSB667 */
2230
Martin Roth2ed0aa22016-01-05 20:58:58 -07002231 0xffffffff, 0xffffffff, /* nonexistent */
2232 0xffffffff, 0xffffffff, /* nonexistent */
2233 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002234
Martin Roth2ed0aa22016-01-05 20:58:58 -07002235 0xffffffff, 0xffffffff, /* nonexistent */
2236 0xffffffff, 0xffffffff, /* nonexistent */
2237 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002238 };
2239
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002240#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002241 /* i945 G/P */
2242 static const u32 data_clock_crossing[] = {
Martin Roth2ed0aa22016-01-05 20:58:58 -07002243 0xffffffff, 0xffffffff, /* nonexistent */
2244 0xffffffff, 0xffffffff, /* nonexistent */
2245 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002246
2247 0x10080201, 0x00000000, /* DDR400 FSB533 */
2248 0x00100401, 0x00000000, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002249 0x00010402, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002250
Martin Roth2ed0aa22016-01-05 20:58:58 -07002251 0xffffffff, 0xffffffff, /* nonexistent */
2252 0xffffffff, 0xffffffff, /* nonexistent */
2253 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002254
2255 0x04020108, 0x00000000, /* DDR400 FSB800 */
2256 0x00020108, 0x00000000, /* DDR533 FSB800 */
2257 0x00080201, 0x00000000, /* DDR667 FSB800 */
2258
2259 0x00010402, 0x00000000, /* DDR400 FSB1066 */
2260 0x04020108, 0x00000000, /* DDR533 FSB1066 */
2261 0x08040110, 0x00000000, /* DDR667 FSB1066 */
2262 };
2263
2264 static const u32 command_clock_crossing[] = {
Martin Roth2ed0aa22016-01-05 20:58:58 -07002265 0xffffffff, 0xffffffff, /* nonexistent */
2266 0xffffffff, 0xffffffff, /* nonexistent */
2267 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002268
2269 0x00010800, 0x00000402, /* DDR400 FSB533 */
2270 0x01000400, 0x00000200, /* DDR533 FSB533 */
Patrick Georgi682ea3c2010-04-20 15:52:57 +00002271 0x00020904, 0x00000000, /* DDR667 FSB533 - fake values */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002272
Martin Roth2ed0aa22016-01-05 20:58:58 -07002273 0xffffffff, 0xffffffff, /* nonexistent */
2274 0xffffffff, 0xffffffff, /* nonexistent */
2275 0xffffffff, 0xffffffff, /* nonexistent */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002276
2277 0x02010804, 0x00000000, /* DDR400 FSB800 */
2278 0x00010402, 0x00000000, /* DDR533 FSB800 */
Arthur Heymans8b6df622016-10-16 10:58:01 +02002279 0x04020130, 0x00000008, /* DDR667 FSB800 */
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002280
2281 0x00020904, 0x00000000, /* DDR400 FSB1066 */
2282 0x02010804, 0x00000000, /* DDR533 FSB1066 */
2283 0x180601c0, 0x00000020, /* DDR667 FSB1066 */
2284 };
2285#endif
2286
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002287 printk(BIOS_DEBUG, "Programming Clock Crossing...");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002288
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002289 printk(BIOS_DEBUG, "MEM=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002290 switch (memclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002291 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2292 case 533: printk(BIOS_DEBUG, "533"); idx += 2; break;
2293 case 667: printk(BIOS_DEBUG, "667"); idx += 4; break;
2294 default: printk(BIOS_DEBUG, "RSVD %x", memclk()); return;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002295 }
2296
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002297 printk(BIOS_DEBUG, " FSB=");
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002298 switch (fsbclk()) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002299 case 400: printk(BIOS_DEBUG, "400"); idx += 0; break;
2300 case 533: printk(BIOS_DEBUG, "533"); idx += 6; break;
2301 case 667: printk(BIOS_DEBUG, "667"); idx += 12; break;
2302 case 800: printk(BIOS_DEBUG, "800"); idx += 18; break;
2303 case 1066: printk(BIOS_DEBUG, "1066"); idx += 24; break;
2304 default: printk(BIOS_DEBUG, "RSVD %x\n", fsbclk()); return;
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002305 }
2306
2307 if (command_clock_crossing[idx]==0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002308 printk(BIOS_DEBUG, "Invalid MEM/FSB combination!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002309 }
2310
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002311 MCHBAR32(CCCFT + 0) = command_clock_crossing[idx];
2312 MCHBAR32(CCCFT + 4) = command_clock_crossing[idx + 1];
2313
Stefan Reinauer278534d2008-10-29 04:51:07 +00002314 MCHBAR32(C0DCCFT + 0) = data_clock_crossing[idx];
2315 MCHBAR32(C0DCCFT + 4) = data_clock_crossing[idx + 1];
2316 MCHBAR32(C1DCCFT + 0) = data_clock_crossing[idx];
2317 MCHBAR32(C1DCCFT + 4) = data_clock_crossing[idx + 1];
2318
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002319 printk(BIOS_DEBUG, "... ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002320}
2321
2322static void sdram_disable_fast_dispatch(void)
2323{
2324 u32 reg32;
2325
2326 reg32 = MCHBAR32(FSBPMC3);
2327 reg32 |= (1 << 1);
2328 MCHBAR32(FSBPMC3) = reg32;
2329
2330 reg32 = MCHBAR32(SBTEST);
2331 reg32 |= (3 << 1);
2332 MCHBAR32(SBTEST) = reg32;
2333}
2334
2335static void sdram_pre_jedec_initialization(void)
2336{
2337 u32 reg32;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002338
Stefan Reinauer278534d2008-10-29 04:51:07 +00002339 reg32 = MCHBAR32(WCC);
2340 reg32 &= 0x113ff3ff;
2341 reg32 |= (4 << 29) | (3 << 25) | (1 << 10);
2342 MCHBAR32(WCC) = reg32;
2343
2344 MCHBAR32(SMVREFC) |= (1 << 6);
2345
2346 MCHBAR32(MMARB0) &= ~(3 << 17);
2347 MCHBAR32(MMARB0) |= (1 << 21) | (1 << 16);
2348
2349 MCHBAR32(MMARB1) &= ~(7 << 8);
2350 MCHBAR32(MMARB1) |= (3 << 8);
2351
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002352 /* Adaptive Idle Timer Control */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002353 MCHBAR32(C0AIT) = 0x000006c4;
2354 MCHBAR32(C0AIT+4) = 0x871a066d;
2355
2356 MCHBAR32(C1AIT) = 0x000006c4;
2357 MCHBAR32(C1AIT+4) = 0x871a066d;
2358}
2359
2360#define EA_DUALCHANNEL_XOR_BANK_RANK_MODE (0xd4 << 24)
2361#define EA_DUALCHANNEL_XOR_BANK_MODE (0xf4 << 24)
2362#define EA_DUALCHANNEL_BANK_RANK_MODE (0xc2 << 24)
2363#define EA_DUALCHANNEL_BANK_MODE (0xe2 << 24)
2364#define EA_SINGLECHANNEL_XOR_BANK_RANK_MODE (0x91 << 24)
2365#define EA_SINGLECHANNEL_XOR_BANK_MODE (0xb1 << 24)
2366#define EA_SINGLECHANNEL_BANK_RANK_MODE (0x80 << 24)
2367#define EA_SINGLECHANNEL_BANK_MODE (0xa0 << 24)
2368
2369static void sdram_enhanced_addressing_mode(struct sys_info *sysinfo)
2370{
2371 u32 chan0 = 0, chan1 = 0;
2372 int chan0_dualsided, chan1_dualsided, chan0_populated, chan1_populated;
2373
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002374 chan0_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002375 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002376 chan1_populated = (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED ||
Stefan Reinauer278534d2008-10-29 04:51:07 +00002377 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED);
2378 chan0_dualsided = (sysinfo->banksize[1] || sysinfo->banksize[3]);
2379 chan1_dualsided = (sysinfo->banksize[5] || sysinfo->banksize[7]);
2380
2381 if (sdram_capabilities_enhanced_addressing_xor()) {
2382 if (!sysinfo->interleaved) {
Martin Roth128c1042016-11-18 09:29:03 -07002383 /* Single Channel & Dual Channel Asymmetric */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002384 if (chan0_populated) {
2385 if (chan0_dualsided) {
2386 chan0 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2387 } else {
2388 chan0 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2389 }
2390 }
2391 if (chan1_populated) {
2392 if (chan1_dualsided) {
2393 chan1 = EA_SINGLECHANNEL_XOR_BANK_RANK_MODE;
2394 } else {
2395 chan1 = EA_SINGLECHANNEL_XOR_BANK_MODE;
2396 }
2397 }
2398 } else {
2399 /* Interleaved has always both channels populated */
2400 if (chan0_dualsided) {
2401 chan0 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2402 } else {
2403 chan0 = EA_DUALCHANNEL_XOR_BANK_MODE;
2404 }
2405
2406 if (chan1_dualsided) {
2407 chan1 = EA_DUALCHANNEL_XOR_BANK_RANK_MODE;
2408 } else {
2409 chan1 = EA_DUALCHANNEL_XOR_BANK_MODE;
2410 }
2411 }
2412 } else {
2413 if (!sysinfo->interleaved) {
Martin Roth128c1042016-11-18 09:29:03 -07002414 /* Single Channel & Dual Channel Asymmetric */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002415 if (chan0_populated) {
2416 if (chan0_dualsided) {
2417 chan0 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2418 } else {
2419 chan0 = EA_SINGLECHANNEL_BANK_MODE;
2420 }
2421 }
2422 if (chan1_populated) {
2423 if (chan1_dualsided) {
2424 chan1 = EA_SINGLECHANNEL_BANK_RANK_MODE;
2425 } else {
2426 chan1 = EA_SINGLECHANNEL_BANK_MODE;
2427 }
2428 }
2429 } else {
2430 /* Interleaved has always both channels populated */
2431 if (chan0_dualsided) {
2432 chan0 = EA_DUALCHANNEL_BANK_RANK_MODE;
2433 } else {
2434 chan0 = EA_DUALCHANNEL_BANK_MODE;
2435 }
2436
2437 if (chan1_dualsided) {
2438 chan1 = EA_DUALCHANNEL_BANK_RANK_MODE;
2439 } else {
2440 chan1 = EA_DUALCHANNEL_BANK_MODE;
2441 }
2442 }
2443 }
2444
2445 MCHBAR32(C0DRC1) &= 0x00ffffff;
2446 MCHBAR32(C0DRC1) |= chan0;
2447 MCHBAR32(C1DRC1) &= 0x00ffffff;
2448 MCHBAR32(C1DRC1) |= chan1;
2449}
2450
2451static void sdram_post_jedec_initialization(struct sys_info *sysinfo)
2452{
2453 u32 reg32;
2454
2455 /* Enable Channel XORing for Dual Channel Interleave */
2456 if (sysinfo->interleaved) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002457
Stefan Reinauer278534d2008-10-29 04:51:07 +00002458 reg32 = MCHBAR32(DCC);
Patrick Georgi77d66832010-10-01 08:02:45 +00002459#if CONFIG_CHANNEL_XOR_RANDOMIZATION
Stefan Reinauer278534d2008-10-29 04:51:07 +00002460 reg32 &= ~(1 << 10);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002461 reg32 |= (1 << 9);
2462#else
Stefan Reinauer278534d2008-10-29 04:51:07 +00002463 reg32 &= ~(1 << 9);
Stefan Reinauer30140a52009-03-11 16:20:39 +00002464#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002465 MCHBAR32(DCC) = reg32;
2466 }
2467
2468 /* DRAM mode optimizations */
2469 sdram_enhanced_addressing_mode(sysinfo);
2470
2471 reg32 = MCHBAR32(FSBPMC3);
2472 reg32 &= ~(1 << 1);
2473 MCHBAR32(FSBPMC3) = reg32;
2474
2475 reg32 = MCHBAR32(SBTEST);
2476 reg32 &= ~(1 << 2);
2477 MCHBAR32(SBTEST) = reg32;
2478
2479 reg32 = MCHBAR32(SBOCC);
2480 reg32 &= 0xffbdb6ff;
2481 reg32 |= (0xbdb6 << 8) | (1 << 0);
2482 MCHBAR32(SBOCC) = reg32;
2483}
2484
2485static void sdram_power_management(struct sys_info *sysinfo)
2486{
2487 u8 reg8;
2488 u16 reg16;
2489 u32 reg32;
2490 int integrated_graphics = 1;
2491 int i;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002492
Stefan Reinauer278534d2008-10-29 04:51:07 +00002493 reg32 = MCHBAR32(C0DRT2);
2494 reg32 &= 0xffffff00;
2495 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002496 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002497 MCHBAR32(C0DRT2) = reg32;
2498
2499 reg32 = MCHBAR32(C1DRT2);
2500 reg32 &= 0xffffff00;
2501 /* Idle timer = 8 clocks, CKE idle timer = 16 clocks */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002502 reg32 |= (1 << 5) | (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002503 MCHBAR32(C1DRT2) = reg32;
2504
2505 reg32 = MCHBAR32(C0DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002506
2507 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002508 MCHBAR32(C0DRC1) = reg32;
2509
2510 reg32 = MCHBAR32(C1DRC1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002511
2512 reg32 |= (1 << 12) | (1 << 11);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002513 MCHBAR32(C1DRC1) = reg32;
2514
2515 if (i945_silicon_revision()>1) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002516 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2517 u16 peg_bits = (1 << 5) | (1 << 0);
2518
2519 MCHBAR16(UPMC1) = 0x1010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002520 } else {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002521 /* FIXME bits 5 and 0 only if PCIe graphics is disabled */
2522 u16 peg_bits = (1 << 5) | (1 << 0);
2523
Stefan Reinauer278534d2008-10-29 04:51:07 +00002524 /* Rev 0 and 1 */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002525 MCHBAR16(UPMC1) = 0x0010 | peg_bits;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002526 }
2527
2528 reg16 = MCHBAR16(UPMC2);
2529 reg16 &= 0xfc00;
2530 reg16 |= 0x0100;
2531 MCHBAR16(UPMC2) = reg16;
2532
2533 MCHBAR32(UPMC3) = 0x000f06ff;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002534
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002535 for (i = 0; i < 5; i++) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002536 MCHBAR32(UPMC3) &= ~(1 << 16);
2537 MCHBAR32(UPMC3) |= (1 << 16);
2538 }
2539
2540 MCHBAR32(GIPMC1) = 0x8000000c;
2541
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002542 reg16 = MCHBAR16(CPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002543 reg16 &= ~(7 << 11);
2544 if (i945_silicon_revision()>2) {
2545 reg16 |= (6 << 11);
2546 } else {
2547 reg16 |= (4 << 11);
2548 }
2549 MCHBAR16(CPCTL) = reg16;
2550
Stefan Reinauer30140a52009-03-11 16:20:39 +00002551#if 0
Stefan Reinauer278534d2008-10-29 04:51:07 +00002552 if ((MCHBAR32(ECO) & (1 << 16)) != 0) {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002553#else
2554 if (i945_silicon_revision() != 0) {
2555#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002556 switch (sysinfo->fsb_frequency) {
2557 case 667: MCHBAR32(HGIPMC2) = 0x0d590d59; break;
2558 case 533: MCHBAR32(HGIPMC2) = 0x155b155b; break;
2559 }
2560 } else {
2561 switch (sysinfo->fsb_frequency) {
2562 case 667: MCHBAR32(HGIPMC2) = 0x09c409c4; break;
2563 case 533: MCHBAR32(HGIPMC2) = 0x0fa00fa0; break;
2564 }
2565 }
2566
2567 MCHBAR32(FSBPMC1) = 0x8000000c;
2568
2569 reg32 = MCHBAR32(C2C3TT);
2570 reg32 &= 0xffff0000;
2571 switch (sysinfo->fsb_frequency) {
2572 case 667: reg32 |= 0x0600; break;
2573 case 533: reg32 |= 0x0480; break;
2574 }
2575 MCHBAR32(C2C3TT) = reg32;
2576
2577 reg32 = MCHBAR32(C3C4TT);
2578 reg32 &= 0xffff0000;
2579 switch (sysinfo->fsb_frequency) {
2580 case 667: reg32 |= 0x0b80; break;
2581 case 533: reg32 |= 0x0980; break;
2582 }
2583 MCHBAR32(C3C4TT) = reg32;
2584
2585 if (i945_silicon_revision() == 0) {
2586 MCHBAR32(ECO) &= ~(1 << 16);
2587 } else {
2588 MCHBAR32(ECO) |= (1 << 16);
2589 }
2590
2591#if 0
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002592
Stefan Reinauer278534d2008-10-29 04:51:07 +00002593 if (i945_silicon_revision() == 0) {
2594 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2595 } else {
2596 MCHBAR32(FSBPMC3) |= (1 << 29);
2597 }
2598#endif
2599 MCHBAR32(FSBPMC3) &= ~(1 << 29);
2600
2601 MCHBAR32(FSBPMC3) |= (1 << 21);
2602
2603 MCHBAR32(FSBPMC3) &= ~(1 << 19);
2604
2605 MCHBAR32(FSBPMC3) &= ~(1 << 13);
2606
2607 reg32 = MCHBAR32(FSBPMC4);
2608 reg32 &= ~(3 << 24);
2609 reg32 |= ( 2 << 24);
2610 MCHBAR32(FSBPMC4) = reg32;
2611
2612 MCHBAR32(FSBPMC4) |= (1 << 21);
2613
2614 MCHBAR32(FSBPMC4) |= (1 << 5);
2615
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002616 if ((i945_silicon_revision() < 2) /* || cpuid() = 0x6e8 */ ) {
2617 /* stepping 0 and 1 or CPUID 6e8 */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002618 MCHBAR32(FSBPMC4) &= ~(1 << 4);
2619 } else {
Stefan Reinauer30140a52009-03-11 16:20:39 +00002620 MCHBAR32(FSBPMC4) |= (1 << 4);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002621 }
2622
2623 reg8 = pci_read_config8(PCI_DEV(0,0x0,0), 0xfc);
2624 reg8 |= (1 << 4);
2625 pci_write_config8(PCI_DEV(0, 0x0, 0), 0xfc, reg8);
2626
2627 reg8 = pci_read_config8(PCI_DEV(0,0x2,0), 0xc1);
2628 reg8 |= (1 << 2);
2629 pci_write_config8(PCI_DEV(0, 0x2, 0), 0xc1, reg8);
2630
Stefan Reinauerde3206a2010-02-22 06:09:43 +00002631#ifdef C2_SELF_REFRESH_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002632
Stefan Reinauer278534d2008-10-29 04:51:07 +00002633 if (integrated_graphics) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002634 printk(BIOS_DEBUG, "C2 self-refresh with IGD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002635 MCHBAR16(MIPMC4) = 0x0468;
2636 MCHBAR16(MIPMC5) = 0x046c;
2637 MCHBAR16(MIPMC6) = 0x046c;
2638 } else {
2639 MCHBAR16(MIPMC4) = 0x6468;
2640 MCHBAR16(MIPMC5) = 0x646c;
2641 MCHBAR16(MIPMC6) = 0x646c;
2642 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002643#else
2644 if (integrated_graphics) {
2645 MCHBAR16(MIPMC4) = 0x04f8;
2646 MCHBAR16(MIPMC5) = 0x04fc;
2647 MCHBAR16(MIPMC6) = 0x04fc;
2648 } else {
2649 MCHBAR16(MIPMC4) = 0x64f8;
2650 MCHBAR16(MIPMC5) = 0x64fc;
2651 MCHBAR16(MIPMC6) = 0x64fc;
2652 }
2653
2654#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002655
2656 reg32 = MCHBAR32(PMCFG);
2657 reg32 &= ~(3 << 17);
2658 reg32 |= (2 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002659 MCHBAR32(PMCFG) = reg32;
2660
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002661 MCHBAR32(PMCFG) |= (1 << 4);
2662
Stefan Reinauer278534d2008-10-29 04:51:07 +00002663 reg32 = MCHBAR32(0xc30);
2664 reg32 &= 0xffffff00;
2665 reg32 |= 0x01;
2666 MCHBAR32(0xc30) = reg32;
2667
2668 MCHBAR32(0xb18) &= ~(1 << 21);
2669}
2670
2671static void sdram_thermal_management(void)
2672{
Stefan Reinauer278534d2008-10-29 04:51:07 +00002673
Stefan Reinauer278534d2008-10-29 04:51:07 +00002674 MCHBAR8(TCO1) = 0x00;
2675 MCHBAR8(TCO0) = 0x00;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002676
2677 /* The Thermal Sensors for DIMMs at 0x50, 0x52 are at I2C addr
2678 * 0x30/0x32.
2679 */
2680
Stefan Reinauerbf264e92010-05-14 19:09:20 +00002681 /* TODO This is not implemented yet. Volunteers? */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002682}
2683
2684static void sdram_save_receive_enable(void)
2685{
2686 int i;
2687 u32 reg32;
2688 u8 values[4];
2689
2690 /* The following values are stored to an unused CMOS
2691 * area and restored instead of recalculated in case
2692 * of an S3 resume.
2693 *
2694 * C0WL0REOST [7:0] -> 8 bit
2695 * C1WL0REOST [7:0] -> 8 bit
2696 * RCVENMT [11:8] [3:0] -> 8 bit
2697 * C0DRT1 [27:24] -> 4 bit
2698 * C1DRT1 [27:24] -> 4 bit
2699 */
2700
2701 values[0] = MCHBAR8(C0WL0REOST);
2702 values[1] = MCHBAR8(C1WL0REOST);
2703
2704 reg32 = MCHBAR32(RCVENMT);
2705 values[2] = (u8)((reg32 >> (8 - 4)) & 0xf0) | (reg32 & 0x0f);
2706
2707 reg32 = MCHBAR32(C0DRT1);
2708 values[3] = (reg32 >> 24) & 0x0f;
2709 reg32 = MCHBAR32(C1DRT1);
2710 values[3] |= (reg32 >> (24 - 4)) & 0xf0;
2711
2712 /* coreboot only uses bytes 0 - 127 for its CMOS values so far
Edwin Beasanteb50c7d2010-07-06 21:05:04 +00002713 * so we grab bytes 128 - 131 to save the receive enable values
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002714 */
2715
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002716 for (i = 0; i < 4; i++)
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002717 cmos_write(values[i], 128 + i);
2718}
2719
2720static void sdram_recover_receive_enable(void)
2721{
2722 int i;
2723 u32 reg32;
2724 u8 values[4];
2725
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +02002726 for (i = 0; i < 4; i++)
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002727 values[i] = cmos_read(128 + i);
2728
2729 MCHBAR8(C0WL0REOST) = values[0];
2730 MCHBAR8(C1WL0REOST) = values[1];
2731
2732 reg32 = MCHBAR32(RCVENMT);
2733 reg32 &= ~((0x0f << 8) | (0x0f << 0));
2734 reg32 |= ((u32)(values[2] & 0xf0) << (8 - 4)) | (values[2] & 0x0f);
2735 MCHBAR32(RCVENMT) = reg32;
2736
2737 reg32 = MCHBAR32(C0DRT1) & ~(0x0f << 24);
2738 reg32 |= (u32)(values[3] & 0x0f) << 24;
2739 MCHBAR32(C0DRT1) = reg32;
2740
2741 reg32 = MCHBAR32(C1DRT1) & ~(0x0f << 24);
2742 reg32 |= (u32)(values[3] & 0xf0) << (24 - 4);
2743 MCHBAR32(C1DRT1) = reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002744}
2745
2746#include "rcven.c"
2747
2748static void sdram_program_receive_enable(struct sys_info *sysinfo)
2749{
2750 MCHBAR32(REPC) |= (1 << 0);
2751
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00002752 /* enable upper CMOS */
2753 RCBA32(0x3400) = (1 << 2);
2754
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002755 /* Program Receive Enable Timings */
2756 if (sysinfo->boot_path == BOOT_PATH_RESUME) {
2757 sdram_recover_receive_enable();
2758 } else {
2759 receive_enable_adjust(sysinfo);
2760 sdram_save_receive_enable();
2761 }
Stefan Reinauer278534d2008-10-29 04:51:07 +00002762
2763 MCHBAR32(C0DRC1) |= (1 << 6);
2764 MCHBAR32(C1DRC1) |= (1 << 6);
2765 MCHBAR32(C0DRC1) &= ~(1 << 6);
2766 MCHBAR32(C1DRC1) &= ~(1 << 6);
2767
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002768 MCHBAR32(MIPMC3) |= (0x0f << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002769}
2770
2771/**
2772 * @brief Enable On-Die Termination for DDR2.
2773 *
2774 */
2775
2776static void sdram_on_die_termination(struct sys_info *sysinfo)
2777{
2778 static const u32 odt[] = {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002779 0x00024911, 0xe0010000,
2780 0x00049211, 0xe0020000,
2781 0x0006db11, 0xe0030000,
Stefan Reinauer278534d2008-10-29 04:51:07 +00002782 };
2783
2784 u32 reg32;
2785 int cas;
2786
2787 reg32 = MCHBAR32(ODTC);
2788 reg32 &= ~(3 << 16);
2789 reg32 |= (1 << 14) | (1 << 6) | (2 << 16);
2790 MCHBAR32(ODTC) = reg32;
2791
2792 if ( !(sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED &&
2793 sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED) ) {
Elyes HAOUAS38424982016-08-21 12:01:04 +02002794 printk(BIOS_DEBUG, "one dimm per channel config..\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002795
Stefan Reinauer278534d2008-10-29 04:51:07 +00002796 reg32 = MCHBAR32(C0ODT);
2797 reg32 &= ~(7 << 28);
2798 MCHBAR32(C0ODT) = reg32;
2799 reg32 = MCHBAR32(C1ODT);
2800 reg32 &= ~(7 << 28);
2801 MCHBAR32(C1ODT) = reg32;
2802 }
2803
2804 cas = sysinfo->cas;
2805
2806 reg32 = MCHBAR32(C0ODT) & 0xfff00000;
2807 reg32 |= odt[(cas-3) * 2];
2808 MCHBAR32(C0ODT) = reg32;
2809
2810 reg32 = MCHBAR32(C1ODT) & 0xfff00000;
2811 reg32 |= odt[(cas-3) * 2];
2812 MCHBAR32(C1ODT) = reg32;
2813
2814 reg32 = MCHBAR32(C0ODT + 4) & 0x1fc8ffff;
2815 reg32 |= odt[((cas-3) * 2) + 1];
2816 MCHBAR32(C0ODT + 4) = reg32;
2817
2818 reg32 = MCHBAR32(C1ODT + 4) & 0x1fc8ffff;
2819 reg32 |= odt[((cas-3) * 2) + 1];
2820 MCHBAR32(C1ODT + 4) = reg32;
2821}
2822
2823/**
2824 * @brief Enable clocks to populated sockets
2825 */
2826
2827static void sdram_enable_memory_clocks(struct sys_info *sysinfo)
2828{
2829 u8 clocks[2] = { 0, 0 };
2830
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002831#if CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002832#define CLOCKS_WIDTH 2
Kyösti Mälkkieb5e28f2012-02-24 16:08:18 +02002833#elif CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GC
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002834#define CLOCKS_WIDTH 3
2835#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +00002836 if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002837 clocks[0] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002838
2839 if (sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002840 clocks[0] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002841
2842 if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002843 clocks[1] |= (1 << CLOCKS_WIDTH)-1;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002844
2845 if (sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
Stefan Reinauer24b4df52010-01-17 13:47:35 +00002846 clocks[1] |= ((1 << CLOCKS_WIDTH)-1) << CLOCKS_WIDTH;
Stefan Reinauer278534d2008-10-29 04:51:07 +00002847
Patrick Georgi77d66832010-10-01 08:02:45 +00002848#if CONFIG_OVERRIDE_CLOCK_DISABLE
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002849 /* Usually system firmware turns off system memory clock signals
2850 * to unused SO-DIMM slots to reduce EMI and power consumption.
2851 * However, the Kontron 986LCD-M does not like unused clock
2852 * signals to be disabled.
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002853 */
2854
2855 clocks[0] = 0xf; /* force all clock gate pairs to enable */
2856 clocks[1] = 0xf; /* force all clock gate pairs to enable */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002857#endif
2858
2859 MCHBAR8(C0DCLKDIS) = clocks[0];
2860 MCHBAR8(C1DCLKDIS) = clocks[1];
2861}
2862
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002863#define RTT_ODT_NONE 0
2864#define RTT_ODT_50_OHM ( (1 << 9) | (1 << 5) )
Stefan Reinauer278534d2008-10-29 04:51:07 +00002865#define RTT_ODT_75_OHM (1 << 5)
2866#define RTT_ODT_150_OHM (1 << 9)
2867
2868#define EMRS_OCD_DEFAULT ( (1 << 12) | (1 << 11) | (1 << 10) )
2869
2870#define MRS_CAS_3 (3 << 7)
2871#define MRS_CAS_4 (4 << 7)
2872#define MRS_CAS_5 (5 << 7)
2873
2874#define MRS_TWR_3 (2 << 12)
2875#define MRS_TWR_4 (3 << 12)
2876#define MRS_TWR_5 (4 << 12)
2877
2878#define MRS_BT (1 << 6)
2879
2880#define MRS_BL4 (2 << 3)
2881#define MRS_BL8 (3 << 3)
2882
2883static void sdram_jedec_enable(struct sys_info *sysinfo)
2884{
2885 int i, nonzero;
2886 u32 bankaddr = 0, tmpaddr, mrsaddr = 0;
2887
2888 for (i = 0, nonzero = -1; i < 8; i++) {
2889 if (sysinfo->banksize[i] == 0) {
2890 continue;
2891 }
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002892
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002893 printk(BIOS_DEBUG, "jedec enable sequence: bank %d\n", i);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002894 switch (i) {
2895 case 0:
2896 /* Start at address 0 */
2897 bankaddr = 0;
2898 break;
2899 case 4:
2900 if (sysinfo->interleaved) {
2901 bankaddr = 0x40;
2902 break;
2903 }
2904 default:
2905 if (nonzero != -1) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00002906 printk(BIOS_DEBUG, "bankaddr from bank size of rank %d\n", nonzero);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002907 bankaddr += sysinfo->banksize[nonzero] <<
2908 (sysinfo->interleaved ? 26 : 25);
Stefan Reinauer278534d2008-10-29 04:51:07 +00002909 break;
2910 }
2911 /* No populated bank hit before. Start at address 0 */
2912 bankaddr = 0;
2913 }
2914
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002915 /* We have a bank with a non-zero size.. Remember it
Stefan Reinauer278534d2008-10-29 04:51:07 +00002916 * for the next offset we have to calculate
2917 */
2918 nonzero = i;
2919
2920 /* Get CAS latency set up */
2921 switch (sysinfo->cas) {
2922 case 5: mrsaddr = MRS_CAS_5; break;
2923 case 4: mrsaddr = MRS_CAS_4; break;
2924 case 3: mrsaddr = MRS_CAS_3; break;
2925 default: die("Jedec Error (CAS).\n");
2926 }
2927
2928 /* Get tWR set */
2929 switch (sysinfo->twr) {
2930 case 5: mrsaddr |= MRS_TWR_5; break;
2931 case 4: mrsaddr |= MRS_TWR_4; break;
2932 case 3: mrsaddr |= MRS_TWR_3; break;
2933 default: die("Jedec Error (tWR).\n");
2934 }
2935
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002936 /* Set "Burst Type" */
2937 mrsaddr |= MRS_BT;
2938
Stefan Reinauer278534d2008-10-29 04:51:07 +00002939 /* Interleaved */
2940 if (sysinfo->interleaved) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00002941 mrsaddr = mrsaddr << 1;
2942 }
2943
2944 /* Only burst length 8 supported */
2945 mrsaddr |= MRS_BL8;
2946
2947 /* Apply NOP */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002948 PRINTK_DEBUG("Apply NOP\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002949 do_ram_command(RAM_COMMAND_NOP);
2950 ram_read32(bankaddr);
2951
2952 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002953 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002954 do_ram_command(RAM_COMMAND_PRECHARGE);
2955 ram_read32(bankaddr);
2956
2957 /* Extended Mode Register Set (2) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002958 PRINTK_DEBUG("Extended Mode Register Set(2)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002959 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_2);
2960 ram_read32(bankaddr);
2961
2962 /* Extended Mode Register Set (3) */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002963 PRINTK_DEBUG("Extended Mode Register Set(3)\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002964 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_3);
2965 ram_read32(bankaddr);
2966
2967 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002968 PRINTK_DEBUG("Extended Mode Register Set\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002969 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
2970 tmpaddr = bankaddr;
2971 if (!sdram_capabilities_dual_channel()) {
2972 tmpaddr |= RTT_ODT_75_OHM;
2973 } else if (sysinfo->interleaved) {
2974 tmpaddr |= (RTT_ODT_150_OHM << 1);
2975 } else {
2976 tmpaddr |= RTT_ODT_150_OHM;
2977 }
2978 ram_read32(tmpaddr);
2979
2980 /* Mode Register Set: Reset DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002981 PRINTK_DEBUG("MRS: Reset DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002982 do_ram_command(RAM_COMMAND_MRS);
2983 tmpaddr = bankaddr;
2984 tmpaddr |= mrsaddr;
2985 /* Set DLL reset bit */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00002986 if (sysinfo->interleaved)
Stefan Reinauer278534d2008-10-29 04:51:07 +00002987 tmpaddr |= (1 << 12);
2988 else
2989 tmpaddr |= (1 << 11);
2990 ram_read32(tmpaddr);
2991
2992 /* Precharge all banks */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002993 PRINTK_DEBUG("All Banks Precharge\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002994 do_ram_command(RAM_COMMAND_PRECHARGE);
2995 ram_read32(bankaddr);
2996
2997 /* CAS before RAS Refresh */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00002998 PRINTK_DEBUG("CAS before RAS\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00002999 do_ram_command(RAM_COMMAND_CBR);
3000
3001 /* CBR wants two READs */
3002 ram_read32(bankaddr);
3003 ram_read32(bankaddr);
3004
3005 /* Mode Register Set: Enable DLLs */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003006 PRINTK_DEBUG("MRS: Enable DLLs\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003007 do_ram_command(RAM_COMMAND_MRS);
3008
3009 tmpaddr = bankaddr;
3010 tmpaddr |= mrsaddr;
3011 ram_read32(tmpaddr);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003012
Stefan Reinauer278534d2008-10-29 04:51:07 +00003013 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003014 PRINTK_DEBUG("Extended Mode Register Set: ODT/OCD\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003015 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003016
Stefan Reinauer278534d2008-10-29 04:51:07 +00003017 tmpaddr = bankaddr;
3018 if (!sdram_capabilities_dual_channel()) {
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003019
Stefan Reinauer278534d2008-10-29 04:51:07 +00003020 tmpaddr |= RTT_ODT_75_OHM | EMRS_OCD_DEFAULT;
3021 } else if (sysinfo->interleaved) {
3022 tmpaddr |= ((RTT_ODT_150_OHM | EMRS_OCD_DEFAULT) << 1);
3023 } else {
3024 tmpaddr |= RTT_ODT_150_OHM | EMRS_OCD_DEFAULT;
3025 }
3026 ram_read32(tmpaddr);
3027
3028 /* Extended Mode Register Set */
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003029 PRINTK_DEBUG("Extended Mode Register Set: OCD Exit\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003030 do_ram_command(RAM_COMMAND_EMRS | RAM_EMRS_1);
3031
3032 tmpaddr = bankaddr;
3033 if (!sdram_capabilities_dual_channel()) {
3034 tmpaddr |= RTT_ODT_75_OHM;
3035 } else if (sysinfo->interleaved) {
3036 tmpaddr |= (RTT_ODT_150_OHM << 1);
3037 } else {
3038 tmpaddr |= RTT_ODT_150_OHM;
3039 }
3040 ram_read32(tmpaddr);
3041 }
3042}
3043
3044static void sdram_init_complete(void)
3045{
Stefan Reinauer779b3e32008-11-10 15:43:37 +00003046 PRINTK_DEBUG("Normal Operation\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003047 do_ram_command(RAM_COMMAND_NORMAL);
3048}
3049
3050static void sdram_setup_processor_side(void)
3051{
3052 if (i945_silicon_revision() == 0)
3053 MCHBAR32(FSBPMC3) |= (1 << 2);
3054
3055 MCHBAR8(0xb00) |= 1;
3056
3057 if (i945_silicon_revision() == 0)
3058 MCHBAR32(SLPCTL) |= (1 << 8);
3059}
3060
Stefan Reinauer278534d2008-10-29 04:51:07 +00003061/**
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003062 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
Martin Rothf4cb4122015-01-06 10:27:39 -07003063 * @param spd_addresses pointer to a list of SPD addresses
Stefan Reinauer278534d2008-10-29 04:51:07 +00003064 */
Sven Schnelle541269b2011-02-21 09:39:17 +00003065void sdram_initialize(int boot_path, const u8 *spd_addresses)
Stefan Reinauer278534d2008-10-29 04:51:07 +00003066{
3067 struct sys_info sysinfo;
3068 u8 reg8, cas_mask;
3069
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003070 printk(BIOS_DEBUG, "Setting up RAM controller.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +00003071
3072 memset(&sysinfo, 0, sizeof(sysinfo));
3073
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003074 sysinfo.boot_path = boot_path;
Sven Schnelle541269b2011-02-21 09:39:17 +00003075 sysinfo.spd_addresses = spd_addresses;
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003076
Stefan Reinauer278534d2008-10-29 04:51:07 +00003077 /* Look at the type of DIMMs and verify all DIMMs are x8 or x16 width */
3078 sdram_get_dram_configuration(&sysinfo);
3079
Stefan Reinauerbf264e92010-05-14 19:09:20 +00003080 /* If error, do cold boot */
3081 sdram_detect_errors(&sysinfo);
3082
Stefan Reinauer278534d2008-10-29 04:51:07 +00003083 /* Check whether we have stacked DIMMs */
3084 sdram_verify_package_type(&sysinfo);
3085
3086 /* Determine common CAS */
3087 cas_mask = sdram_possible_cas_latencies(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003088
Stefan Reinauer278534d2008-10-29 04:51:07 +00003089 /* Choose Common Frequency */
3090 sdram_detect_cas_latency_and_ram_speed(&sysinfo, cas_mask);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003091
Stefan Reinauer278534d2008-10-29 04:51:07 +00003092 /* Determine smallest common tRAS */
3093 sdram_detect_smallest_tRAS(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003094
Stefan Reinauer278534d2008-10-29 04:51:07 +00003095 /* Determine tRP */
3096 sdram_detect_smallest_tRP(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003097
Stefan Reinauer278534d2008-10-29 04:51:07 +00003098 /* Determine tRCD */
3099 sdram_detect_smallest_tRCD(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003100
Stefan Reinauer278534d2008-10-29 04:51:07 +00003101 /* Determine smallest refresh period */
3102 sdram_detect_smallest_refresh(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003103
Stefan Reinauer278534d2008-10-29 04:51:07 +00003104 /* Verify all DIMMs support burst length 8 */
3105 sdram_verify_burst_length(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003106
Stefan Reinauer278534d2008-10-29 04:51:07 +00003107 /* determine tWR */
3108 sdram_detect_smallest_tWR(&sysinfo);
3109
3110 /* Determine DIMM size parameters (rows, columns banks) */
3111 sdram_detect_dimm_size(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003112
Stefan Reinauer278534d2008-10-29 04:51:07 +00003113 /* determine tRFC */
3114 sdram_detect_smallest_tRFC(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003115
Stefan Reinauer278534d2008-10-29 04:51:07 +00003116 /* Program PLL settings */
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003117 sdram_program_pll_settings(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003118
Arthur Heymans18537812016-12-28 21:20:45 +01003119 /*
3120 * Program Graphics Frequency
3121 * Set core display and render clock on 945GC to the max
3122 */
3123 if (IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
3124 sdram_program_graphics_frequency(&sysinfo);
3125 else
3126 pci_write_config16(PCI_DEV(0, 2, 0), GCFC, 0x0534);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003127
3128 /* Program System Memory Frequency */
3129 sdram_program_memory_frequency(&sysinfo);
3130
3131 /* Determine Mode of Operation (Interleaved etc) */
3132 sdram_set_channel_mode(&sysinfo);
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003133
Stefan Reinauer278534d2008-10-29 04:51:07 +00003134 /* Program Clock Crossing values */
3135 sdram_program_clock_crossing();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003136
Stefan Reinauer278534d2008-10-29 04:51:07 +00003137 /* Disable fast dispatch */
3138 sdram_disable_fast_dispatch();
3139
3140 /* Enable WIODLL Power Down in ACPI states */
3141 MCHBAR32(C0DMC) |= (1 << 24);
3142 MCHBAR32(C1DMC) |= (1 << 24);
3143
3144 /* Program DRAM Row Boundary/Attribute Registers */
3145
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003146 /* program row size DRB and set TOLUD */
3147 sdram_program_row_boundaries(&sysinfo);
3148
3149 /* program page size DRA */
3150 sdram_set_row_attributes(&sysinfo);
Stefan Reinauer278534d2008-10-29 04:51:07 +00003151
3152 /* Program CxBNKARC */
3153 sdram_set_bank_architecture(&sysinfo);
3154
3155 /* Program DRAM Timing and Control registers based on SPD */
3156 sdram_set_timing_and_control(&sysinfo);
3157
3158 /* On-Die Termination Adjustment */
3159 sdram_on_die_termination(&sysinfo);
3160
3161 /* Pre Jedec Initialization */
3162 sdram_pre_jedec_initialization();
3163
3164 /* Perform System Memory IO Initialization */
3165 sdram_initialize_system_memory_io(&sysinfo);
3166
3167 /* Perform System Memory IO Buffer Enable */
3168 sdram_enable_system_memory_io(&sysinfo);
3169
3170 /* Enable System Memory Clocks */
3171 sdram_enable_memory_clocks(&sysinfo);
3172
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003173 if (boot_path == BOOT_PATH_NORMAL) {
Stefan Reinauer278534d2008-10-29 04:51:07 +00003174 /* Jedec Initialization sequence */
3175 sdram_jedec_enable(&sysinfo);
3176 }
3177
3178 /* Program Power Management Registers */
3179 sdram_power_management(&sysinfo);
3180
3181 /* Post Jedec Init */
3182 sdram_post_jedec_initialization(&sysinfo);
3183
3184 /* Program DRAM Throttling */
3185 sdram_thermal_management();
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003186
Stefan Reinauer278534d2008-10-29 04:51:07 +00003187 /* Normal Operations */
Stefan Reinaueraca6ec62009-10-26 17:12:21 +00003188 sdram_init_complete();
Stefan Reinauer278534d2008-10-29 04:51:07 +00003189
3190 /* Program Receive Enable Timings */
3191 sdram_program_receive_enable(&sysinfo);
3192
3193 /* Enable Periodic RCOMP */
3194 sdram_enable_rcomp();
3195
3196 /* Tell ICH7 that we're done */
3197 reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2);
3198 reg8 &= ~(1 << 7);
3199 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8);
3200
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +00003201 printk(BIOS_DEBUG, "RAM initialization finished.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +00003202
Stefan Reinauer278534d2008-10-29 04:51:07 +00003203 sdram_setup_processor_side();
3204}