blob: bd92ac1fe846e9f5129ff0b49d26e1505d1a0acf [file] [log] [blame]
Joseph Smith6a1dc862008-03-09 13:24:46 +00001/*
2 * This file is part of the coreboot project.
3 *
Joseph Smithfa742da2010-02-01 22:51:18 +00004 * Copyright (C) 2008-2010 Joseph Smith <joe@settoplinux.org>
Joseph Smith6a1dc862008-03-09 13:24:46 +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; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
Joseph Smith6a1dc862008-03-09 13:24:46 +000016 */
17
18#include <spd.h>
Joseph Smith6a1dc862008-03-09 13:24:46 +000019#include <delay.h>
Uwe Hermann598ba432008-10-12 22:34:08 +000020#include "lib/debug.c"
Joseph Smith6a1dc862008-03-09 13:24:46 +000021#include "i82830.h"
22
23/*-----------------------------------------------------------------------------
24Macros and definitions.
25-----------------------------------------------------------------------------*/
26
Joseph Smith6a1dc862008-03-09 13:24:46 +000027/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000028#if CONFIG_DEBUG_RAM_SETUP
Joseph Smithbdf26a62010-04-11 05:50:08 +000029#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
Joseph Smith6a1dc862008-03-09 13:24:46 +000030#define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
31#else
Joseph Smithbdf26a62010-04-11 05:50:08 +000032#define PRINTK_DEBUG(x...)
Joseph Smith6a1dc862008-03-09 13:24:46 +000033#define DUMPNORTH()
34#endif
35
36/* DRC[10:8] - Refresh Mode Select (RMS).
37 * 0x0 for Refresh Disabled (Self Refresh)
38 * 0x1 for Refresh interval 15.6 us for 133MHz
39 * 0x2 for Refresh interval 7.8 us for 133MHz
Joseph Smith0d7a9962010-03-17 03:18:29 +000040 * 0x7 for Refresh interval 128 Clocks. (Fast Refresh Mode)
Joseph Smith6a1dc862008-03-09 13:24:46 +000041 */
Joseph Smith14669ae2008-06-22 04:22:46 +000042#define RAM_COMMAND_REFRESH 0x1
Joseph Smith6a1dc862008-03-09 13:24:46 +000043
44/* DRC[6:4] - SDRAM Mode Select (SMS). */
45#define RAM_COMMAND_SELF_REFRESH 0x0
46#define RAM_COMMAND_NOP 0x1
47#define RAM_COMMAND_PRECHARGE 0x2
48#define RAM_COMMAND_MRS 0x3
49#define RAM_COMMAND_CBR 0x6
50#define RAM_COMMAND_NORMAL 0x7
51
52/* DRC[29] - Initialization Complete (IC). */
53#define RAM_COMMAND_IC 0x1
54
55/*-----------------------------------------------------------------------------
Joseph Smithfa742da2010-02-01 22:51:18 +000056DIMM-initialization functions.
Joseph Smith6a1dc862008-03-09 13:24:46 +000057-----------------------------------------------------------------------------*/
58
Stefan Reinauer3ac400e2010-03-30 22:12:59 +000059static void do_ram_command(u32 command)
Joseph Smith6a1dc862008-03-09 13:24:46 +000060{
Stefan Reinauer3ac400e2010-03-30 22:12:59 +000061 u32 reg32;
Joseph Smith6a1dc862008-03-09 13:24:46 +000062
63 /* Configure the RAM command. */
Joseph Smithfa742da2010-02-01 22:51:18 +000064 reg32 = pci_read_config32(NORTHBRIDGE, DRC);
Joseph Smith6a1dc862008-03-09 13:24:46 +000065 /* Clear bits 29, 10-8, 6-4. */
66 reg32 &= 0xdffff88f;
67 reg32 |= command << 4;
Joseph Smithbdf26a62010-04-11 05:50:08 +000068 PRINTK_DEBUG(" Sending RAM command 0x%08x", reg32);
Joseph Smithfa742da2010-02-01 22:51:18 +000069 pci_write_config32(NORTHBRIDGE, DRC, reg32);
Joseph Smithfa742da2010-02-01 22:51:18 +000070}
Joseph Smith6a1dc862008-03-09 13:24:46 +000071
Stefan Reinauer3ac400e2010-03-30 22:12:59 +000072static void ram_read32(u8 dimm_start, u32 offset)
Joseph Smithfa742da2010-02-01 22:51:18 +000073{
Stefan Reinauerd93af232010-04-11 18:54:47 +000074 u32 reg32, base_addr = 32 * 1024 * 1024 * dimm_start;
Joseph Smithfa742da2010-02-01 22:51:18 +000075 if (offset == 0x55aa55aa) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080076 reg32 = read32((u32 *)base_addr);
Stefan Reinauerd93af232010-04-11 18:54:47 +000077 PRINTK_DEBUG(" Reading RAM at 0x%08x => 0x%08x\n", base_addr, reg32);
78 PRINTK_DEBUG(" Writing RAM at 0x%08x <= 0x%08x\n", base_addr, offset);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080079 write32((u32 *)base_addr, offset);
80 reg32 = read32((u32 *)base_addr);
Stefan Reinauerd93af232010-04-11 18:54:47 +000081 PRINTK_DEBUG(" Reading RAM at 0x%08x => 0x%08x\n", base_addr, reg32);
Joseph Smithfa742da2010-02-01 22:51:18 +000082 } else {
Stefan Reinauerd93af232010-04-11 18:54:47 +000083 PRINTK_DEBUG(" to 0x%08x\n", base_addr + offset);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080084 read32((u32 *)(base_addr + offset));
Joseph Smithfa742da2010-02-01 22:51:18 +000085 }
86}
87
88static void initialize_dimm_rows(void)
89{
90 int i, row;
Stefan Reinauer3ac400e2010-03-30 22:12:59 +000091 u8 dimm_start, dimm_end;
Joseph Smithfa742da2010-02-01 22:51:18 +000092 unsigned device;
93
Joseph Smith14669ae2008-06-22 04:22:46 +000094 dimm_start = 0;
Joseph Smith6a1dc862008-03-09 13:24:46 +000095
Joseph Smithfa742da2010-02-01 22:51:18 +000096 for (row = 0; row < (DIMM_SOCKETS * 2); row++) {
97
98 switch (row) {
99 case 0:
Uwe Hermannd773fd32010-11-20 20:23:08 +0000100 device = DIMM0;
Joseph Smithfa742da2010-02-01 22:51:18 +0000101 break;
102 case 1:
Uwe Hermannd773fd32010-11-20 20:23:08 +0000103 device = DIMM0;
Joseph Smithfa742da2010-02-01 22:51:18 +0000104 break;
105 case 2:
Uwe Hermannd773fd32010-11-20 20:23:08 +0000106 device = DIMM0 + 1;
Joseph Smithfa742da2010-02-01 22:51:18 +0000107 break;
108 case 3:
Uwe Hermannd773fd32010-11-20 20:23:08 +0000109 device = DIMM0 + 1;
Joseph Smithfa742da2010-02-01 22:51:18 +0000110 break;
111 }
112
113 dimm_end = pci_read_config8(NORTHBRIDGE, DRB + row);
114
Joseph Smith14669ae2008-06-22 04:22:46 +0000115 if (dimm_end > dimm_start) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000116 printk(BIOS_DEBUG, "Initializing SDRAM Row %u\n", row);
Joseph Smithfa742da2010-02-01 22:51:18 +0000117
118 /* NOP command */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000119 PRINTK_DEBUG(" NOP\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000120 do_ram_command(RAM_COMMAND_NOP);
121 ram_read32(dimm_start, 0);
122 udelay(200);
123
124 /* Pre-charge all banks (at least 200 us after NOP) */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000125 PRINTK_DEBUG(" Pre-charging all banks\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000126 do_ram_command(RAM_COMMAND_PRECHARGE);
127 ram_read32(dimm_start, 0);
128 udelay(1);
129
130 /* 8 CBR refreshes (Auto Refresh) */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000131 PRINTK_DEBUG(" 8 CBR refreshes\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000132 for (i = 0; i < 8; i++) {
133 do_ram_command(RAM_COMMAND_CBR);
134 ram_read32(dimm_start, 0);
135 udelay(1);
136 }
137
138 /* MRS command */
139 /* TODO: Set offset 0x1d0 according to DRT values */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000140 PRINTK_DEBUG(" MRS\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000141 do_ram_command(RAM_COMMAND_MRS);
142 ram_read32(dimm_start, 0x1d0);
143 udelay(2);
144
145 /* Set GMCH-M Mode Select bits back to NORMAL operation mode */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000146 PRINTK_DEBUG(" Normal operation mode\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000147 do_ram_command(RAM_COMMAND_NORMAL);
148 ram_read32(dimm_start, 0);
149 udelay(1);
150
151 /* Perform a dummy memory read/write cycle */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000152 PRINTK_DEBUG(" Performing dummy read/write\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000153 ram_read32(dimm_start, 0x55aa55aa);
154 udelay(1);
Joseph Smith14669ae2008-06-22 04:22:46 +0000155 }
156 /* Set the start of the next DIMM. */
157 dimm_start = dimm_end;
Joseph Smith6a1dc862008-03-09 13:24:46 +0000158 }
159}
160
161/*-----------------------------------------------------------------------------
162DIMM-independant configuration functions.
163-----------------------------------------------------------------------------*/
164
165struct dimm_size {
Joseph Smith7488e042010-04-09 11:10:25 +0000166 unsigned int side1;
167 unsigned int side2;
Joseph Smith6a1dc862008-03-09 13:24:46 +0000168};
169
170static struct dimm_size spd_get_dimm_size(unsigned device)
171{
172 struct dimm_size sz;
173 int i, module_density, dimm_banks;
174 sz.side1 = 0;
Joseph Smithfa742da2010-02-01 22:51:18 +0000175 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
176 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000177
178 /* Find the size of side1. */
179 /* Find the larger value. The larger value is always side1. */
180 for (i = 512; i >= 0; i >>= 1) {
181 if ((module_density & i) == i) {
182 sz.side1 = i;
183 break;
184 }
185 }
186
187 /* Set to 0 in case it's single sided. */
188 sz.side2 = 0;
189
190 /* Test if it's a dual-sided DIMM. */
191 if (dimm_banks > 1) {
192 /* Test to see if there's a second value, if so it's asymmetrical. */
193 if (module_density != i) {
194 /* Find the second value, picking up where we left off. */
195 /* i >>= 1 done initially to make sure we don't get the same value again. */
196 for (i >>= 1; i >= 0; i >>= 1) {
197 if (module_density == (sz.side1 | i)) {
198 sz.side2 = i;
199 break;
200 }
201 }
202 /* If not, it's symmetrical */
203 } else {
204 sz.side2 = sz.side1;
205 }
206 }
207
208 /* SPD byte 31 is the memory size divided by 4 so we
209 * need to muliply by 4 to get the total size.
210 */
211 sz.side1 *= 4;
212 sz.side2 *= 4;
213 return sz;
214}
215
Joseph Smithfa742da2010-02-01 22:51:18 +0000216static void set_dram_row_boundaries(void)
Joseph Smith6a1dc862008-03-09 13:24:46 +0000217{
218 int i, value, drb1, drb2;
219
220 for (i = 0; i < DIMM_SOCKETS; i++) {
221 struct dimm_size sz;
222 unsigned device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000223 device = DIMM0 + i;
Joseph Smith6a1dc862008-03-09 13:24:46 +0000224 drb1 = 0;
225 drb2 = 0;
226
227 /* First check if a DIMM is actually present. */
Joseph Smithfa742da2010-02-01 22:51:18 +0000228 if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000229 printk(BIOS_DEBUG, "Found DIMM in slot %u\n", i);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000230 sz = spd_get_dimm_size(device);
Joseph Smithbdf26a62010-04-11 05:50:08 +0000231 printk(BIOS_DEBUG, " DIMM is %uMB on side 1\n", sz.side1);
232 printk(BIOS_DEBUG, " DIMM is %uMB on side 2\n", sz.side2);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000233
Joseph Smithfa742da2010-02-01 22:51:18 +0000234 /* - Memory compatibility checks - */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000235
Joseph Smith6a1dc862008-03-09 13:24:46 +0000236 /* Test for PC133 (i82830 only supports PC133) */
237 /* PC133 SPD9 - cycle time is always 75 */
Joseph Smithfa742da2010-02-01 22:51:18 +0000238 if (spd_read_byte(device, SPD_MIN_CYCLE_TIME_AT_CAS_MAX) != 0x75) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000239 printk(BIOS_ERR, "SPD9 DIMM Is Not PC133 Compatable\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000240 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000241 }
242 /* PC133 SPD10 - access time is always 54 */
Joseph Smithfa742da2010-02-01 22:51:18 +0000243 if (spd_read_byte(device, SPD_ACCESS_TIME_FROM_CLOCK) != 0x54) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000244 printk(BIOS_ERR, "SPD10 DIMM Is Not PC133 Compatable\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000245 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000246 }
247
248 /* The i82830 only supports a symmetrical dual-sided dimms
249 * and can't handle DIMMs smaller than 32MB per
250 * side or larger than 256MB per side.
251 */
252 if ((sz.side2 != 0) && (sz.side1 != sz.side2)) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000253 printk(BIOS_ERR, "This northbridge only supports\n");
254 printk(BIOS_ERR, "symmetrical dual-sided DIMMs\n");
255 printk(BIOS_ERR, "booting as a single-sided DIMM\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000256 sz.side2 = 0;
257 }
258 if ((sz.side1 < 32)) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000259 printk(BIOS_ERR, "DIMMs smaller than 32MB per side\n");
260 printk(BIOS_ERR, "are not supported on this northbridge\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000261 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000262 }
263
264 if ((sz.side1 > 256)) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000265 printk(BIOS_ERR, "DIMMs larger than 256MB per side\n");
266 printk(BIOS_ERR, "are not supported on this northbridge\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000267 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000268 }
Joseph Smithfa742da2010-02-01 22:51:18 +0000269 /* - End Memory compatibility checks - */
Joseph Smith6a1dc862008-03-09 13:24:46 +0000270
271 /* We need to divide size by 32 to set up the
272 * DRB registers.
273 */
274 if (sz.side1)
275 drb1 = sz.side1 / 32;
276 if (sz.side2)
277 drb2 = sz.side2 / 32;
278 } else {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000279 printk(BIOS_DEBUG, "No DIMM found in slot %u\n", i);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000280
281 /* If there's no DIMM in the slot, set value to 0. */
282 drb1 = 0;
283 drb2 = 0;
284 }
285 /* Set the value for DRAM Row Boundary Registers */
286 if (i == 0) {
Joseph Smithfa742da2010-02-01 22:51:18 +0000287 pci_write_config8(NORTHBRIDGE, DRB, drb1);
288 pci_write_config8(NORTHBRIDGE, DRB + 1, drb1 + drb2);
Joseph Smithbdf26a62010-04-11 05:50:08 +0000289 PRINTK_DEBUG(" DRB 0x%02x has been set to 0x%02x\n", DRB, drb1);
290 PRINTK_DEBUG(" DRB1 0x%02x has been set to 0x%02x\n", DRB + 1, drb1 + drb2);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000291 } else if (i == 1) {
Joseph Smithfa742da2010-02-01 22:51:18 +0000292 value = pci_read_config8(NORTHBRIDGE, DRB + 1);
293 pci_write_config8(NORTHBRIDGE, DRB + 2, value + drb1);
294 pci_write_config8(NORTHBRIDGE, DRB + 3, value + drb1 + drb2);
Joseph Smithbdf26a62010-04-11 05:50:08 +0000295 PRINTK_DEBUG(" DRB2 0x%02x has been set to 0x%02x\n", DRB + 2, value + drb1);
296 PRINTK_DEBUG(" DRB3 0x%02x has been set to 0x%02x\n", DRB + 3, value + drb1 + drb2);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000297
298 /* We need to set the highest DRB value to 0x64 and 0x65.
299 * These are supposed to be "Reserved" but memory will
300 * not initialize properly if we don't.
301 */
Joseph Smithfa742da2010-02-01 22:51:18 +0000302 value = pci_read_config8(NORTHBRIDGE, DRB + 3);
303 pci_write_config8(NORTHBRIDGE, DRB + 4, value);
304 pci_write_config8(NORTHBRIDGE, DRB + 5, value);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000305 }
306 }
307}
308
Joseph Smithfa742da2010-02-01 22:51:18 +0000309static void set_dram_row_attributes(void)
Joseph Smith6a1dc862008-03-09 13:24:46 +0000310{
311 int i, dra, col, width, value;
312
313 for (i = 0; i < DIMM_SOCKETS; i++) {
314 unsigned device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000315 device = DIMM0 + i;
Joseph Smith6a1dc862008-03-09 13:24:46 +0000316
317 /* First check if a DIMM is actually present. */
Joseph Smithfa742da2010-02-01 22:51:18 +0000318 if (spd_read_byte(device, SPD_MEMORY_TYPE) == 0x4) {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000319 PRINTK_DEBUG("Found DIMM in slot %u\n", i);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000320
321 dra = 0x00;
322
323 /* columns */
Joseph Smithfa742da2010-02-01 22:51:18 +0000324 col = spd_read_byte(device, SPD_NUM_COLUMNS);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000325
326 /* data width */
Joseph Smithfa742da2010-02-01 22:51:18 +0000327 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000328
329 /* calculate page size in bits */
330 value = ((1 << col) * width);
331
332 /* convert to Kilobytes */
333 dra = ((value / 8) >> 10);
334
335 /* # of banks of DIMM (single or double sided) */
Joseph Smithfa742da2010-02-01 22:51:18 +0000336 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000337
338 if (value == 1) {
Joseph Smith14669ae2008-06-22 04:22:46 +0000339 if (dra == 2) {
340 dra = 0xF0; /* 2KB */
341 } else if (dra == 4) {
342 dra = 0xF1; /* 4KB */
343 } else if (dra == 8) {
344 dra = 0xF2; /* 8KB */
345 } else if (dra == 16) {
346 dra = 0xF3; /* 16KB */
347 } else {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000348 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000349 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000350 }
351 } else if (value == 2) {
Joseph Smith14669ae2008-06-22 04:22:46 +0000352 if (dra == 2) {
353 dra = 0x00; /* 2KB */
354 } else if (dra == 4) {
355 dra = 0x11; /* 4KB */
356 } else if (dra == 8) {
357 dra = 0x22; /* 8KB */
358 } else if (dra == 16) {
359 dra = 0x33; /* 16KB */
360 } else {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000361 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000362 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000363 }
364 } else {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000365 printk(BIOS_ERR, "# of banks of DIMM not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000366 die("HALT\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000367 }
368
369 } else {
Joseph Smithbdf26a62010-04-11 05:50:08 +0000370 PRINTK_DEBUG("No DIMM found in slot %u\n", i);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000371
372 /* If there's no DIMM in the slot, set dra value to 0xFF. */
373 dra = 0xFF;
374 }
375
376 /* Set the value for DRAM Row Attribute Registers */
Joseph Smithfa742da2010-02-01 22:51:18 +0000377 pci_write_config8(NORTHBRIDGE, DRA + i, dra);
Joseph Smithbdf26a62010-04-11 05:50:08 +0000378 PRINTK_DEBUG(" DRA 0x%02x has been set to 0x%02x\n", DRA + i, dra);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000379 }
380}
381
Joseph Smithfa742da2010-02-01 22:51:18 +0000382static void set_dram_timing(void)
Joseph Smith6a1dc862008-03-09 13:24:46 +0000383{
384 /* Set the value for DRAM Timing Register */
385 /* TODO: Configure the value according to SPD values. */
Joseph Smithfa742da2010-02-01 22:51:18 +0000386 pci_write_config32(NORTHBRIDGE, DRT, 0x00000010);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000387}
388
Joseph Smithfa742da2010-02-01 22:51:18 +0000389static void set_dram_buffer_strength(void)
Joseph Smith6a1dc862008-03-09 13:24:46 +0000390{
391 /* TODO: This needs to be set according to the DRAM tech
392 * (x8, x16, or x32). Argh, Intel provides no docs on this!
393 * Currently, it needs to be pulled from the output of
394 * lspci -xxx Rx92
395 */
396
397 /* Set the value for System Memory Buffer Strength Control Registers */
Joseph Smithfa742da2010-02-01 22:51:18 +0000398 pci_write_config32(NORTHBRIDGE, BUFF_SC, 0xFC9B491B);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000399}
400
401/*-----------------------------------------------------------------------------
402Public interface.
403-----------------------------------------------------------------------------*/
404
Joseph Smithfa742da2010-02-01 22:51:18 +0000405static void sdram_set_registers(void)
406{
Joseph Smith77d31ec2010-04-11 16:36:13 +0000407 printk(BIOS_DEBUG, "Setting initial SDRAM registers....\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000408
409 /* Calculate the value for DRT DRAM Timing Register */
410 set_dram_timing();
411
412 /* Setup System Memory Buffer Strength Control Registers */
413 set_dram_buffer_strength();
414
415 /* Setup DRAM Row Boundary Registers */
416 set_dram_row_boundaries();
417
418 /* Setup DRAM Row Attribute Registers */
419 set_dram_row_attributes();
420
Joseph Smith77d31ec2010-04-11 16:36:13 +0000421 printk(BIOS_DEBUG, "Initial SDRAM registers have been set.\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000422}
423
424static void northbridge_set_registers(void)
Joseph Smith6a1dc862008-03-09 13:24:46 +0000425{
Stefan Reinauer3ac400e2010-03-30 22:12:59 +0000426 u16 value;
Joseph Smith6a1dc862008-03-09 13:24:46 +0000427 int igd_memory = 0;
428
Joseph Smith77d31ec2010-04-11 16:36:13 +0000429 printk(BIOS_DEBUG, "Setting initial Nothbridge registers....\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000430
431 /* Set the value for Fixed DRAM Hole Control Register */
432 pci_write_config8(NORTHBRIDGE, FDHC, 0x00);
433
434 /* Set the value for Programable Attribute Map Registers
435 * Ideally, this should be R/W for as many ranges as possible.
436 */
437 pci_write_config8(NORTHBRIDGE, PAM0, 0x30);
438 pci_write_config8(NORTHBRIDGE, PAM1, 0x33);
439 pci_write_config8(NORTHBRIDGE, PAM2, 0x33);
440 pci_write_config8(NORTHBRIDGE, PAM3, 0x33);
441 pci_write_config8(NORTHBRIDGE, PAM4, 0x33);
442 pci_write_config8(NORTHBRIDGE, PAM5, 0x33);
443 pci_write_config8(NORTHBRIDGE, PAM6, 0x33);
444
445 /* Set the value for System Management RAM Control Register */
446 pci_write_config8(NORTHBRIDGE, SMRAM, 0x02);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000447
448 /* Set the value for GMCH Control Register #0 */
Joseph Smithfa742da2010-02-01 22:51:18 +0000449 pci_write_config16(NORTHBRIDGE, GCC0, 0xA072);
450
451 /* Set the value for Aperture Base Configuration Register */
452 pci_write_config32(NORTHBRIDGE, APBASE, 0x00000008);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000453
454 /* Set the value for GMCH Control Register #1 */
455 switch (CONFIG_VIDEO_MB) {
456 case 512: /* 512K of memory */
457 igd_memory = 0x2;
458 break;
459 case 1: /* 1M of memory */
460 igd_memory = 0x3;
461 break;
462 case 8: /* 8M of memory */
463 igd_memory = 0x4;
464 break;
465 default: /* No memory */
Joseph Smithfa742da2010-02-01 22:51:18 +0000466 pci_write_config16(NORTHBRIDGE, GCC1, 0x0002);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000467 igd_memory = 0x0;
468 }
469
Joseph Smithfa742da2010-02-01 22:51:18 +0000470 value = pci_read_config16(NORTHBRIDGE, GCC1);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000471 value |= igd_memory << 4;
Stefan Reinauer800379f2010-03-01 08:34:19 +0000472 value |= 1; // 64MB aperture
Joseph Smithfa742da2010-02-01 22:51:18 +0000473 pci_write_config16(NORTHBRIDGE, GCC1, value);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000474
Joseph Smith77d31ec2010-04-11 16:36:13 +0000475 printk(BIOS_DEBUG, "Initial Northbridge registers have been set.\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000476}
477
Joseph Smithfa742da2010-02-01 22:51:18 +0000478static void sdram_initialize(void)
Joseph Smith6a1dc862008-03-09 13:24:46 +0000479{
Stefan Reinauer3ac400e2010-03-30 22:12:59 +0000480 u32 reg32;
Joseph Smith6a1dc862008-03-09 13:24:46 +0000481
Joseph Smithfa742da2010-02-01 22:51:18 +0000482 /* Setup Initial SDRAM Registers */
483 sdram_set_registers();
484
Joseph Smithbdf26a62010-04-11 05:50:08 +0000485 /* Wait until power/voltages and clocks are stable (200us). */
Joseph Smith6a1dc862008-03-09 13:24:46 +0000486 udelay(200);
487
Joseph Smithfa742da2010-02-01 22:51:18 +0000488 /* Initialize each row of memory one at a time */
489 initialize_dimm_rows();
Joseph Smith6a1dc862008-03-09 13:24:46 +0000490
Joseph Smithfa742da2010-02-01 22:51:18 +0000491 /* Enable Refresh */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000492 PRINTK_DEBUG("Enabling Refresh\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000493 reg32 = pci_read_config32(NORTHBRIDGE, DRC);
494 reg32 |= (RAM_COMMAND_REFRESH << 8);
495 pci_write_config32(NORTHBRIDGE, DRC, reg32);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000496
Joseph Smithfa742da2010-02-01 22:51:18 +0000497 /* Set initialization complete */
Joseph Smithbdf26a62010-04-11 05:50:08 +0000498 PRINTK_DEBUG("Setting initialization complete\n");
Joseph Smithfa742da2010-02-01 22:51:18 +0000499 reg32 = pci_read_config32(NORTHBRIDGE, DRC);
500 reg32 |= (RAM_COMMAND_IC << 29);
501 pci_write_config32(NORTHBRIDGE, DRC, reg32);
Joseph Smith6a1dc862008-03-09 13:24:46 +0000502
Joseph Smithfa742da2010-02-01 22:51:18 +0000503 /* Setup Initial Northbridge Registers */
504 northbridge_set_registers();
Joseph Smith14669ae2008-06-22 04:22:46 +0000505
Joseph Smithbdf26a62010-04-11 05:50:08 +0000506 PRINTK_DEBUG("Northbridge following SDRAM init:\n");
Joseph Smith6a1dc862008-03-09 13:24:46 +0000507 DUMPNORTH();
508}