blob: eceaaee4eb6247edfdf571472ee4950c4fd7d1fd [file] [log] [blame]
Richard Smithcb8eab42006-07-24 04:25:47 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermann1a9c8922007-04-01 17:24:03 +00003 *
Uwe Hermann1683cef2008-11-27 00:47:07 +00004 * Copyright (C) 2007-2008 Uwe Hermann <uwe@hermann-uwe.de>
Keith Hui59356ca2010-03-06 18:16:25 +00005 * Copyright (C) 2010 Keith Hui <buurin@gmail.com>
Uwe Hermann1a9c8922007-04-01 17:24:03 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Richard Smithcb8eab42006-07-24 04:25:47 +000020 */
21
Uwe Hermann1a9c8922007-04-01 17:24:03 +000022#include <spd.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000023#include <delay.h>
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +000024#include <stdlib.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000025#include "i440bx.h"
Keith Hui59356ca2010-03-06 18:16:25 +000026#include "raminit.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000027
Uwe Hermann1a9c8922007-04-01 17:24:03 +000028/*-----------------------------------------------------------------------------
29Macros and definitions.
30-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +000031
Uwe Hermann1a9c8922007-04-01 17:24:03 +000032/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000033#if CONFIG_DEBUG_RAM_SETUP
Uwe Hermann1a9c8922007-04-01 17:24:03 +000034#define PRINT_DEBUG(x) print_debug(x)
35#define PRINT_DEBUG_HEX8(x) print_debug_hex8(x)
36#define PRINT_DEBUG_HEX16(x) print_debug_hex16(x)
37#define PRINT_DEBUG_HEX32(x) print_debug_hex32(x)
Stefan Reinauer3ac400e2010-03-30 22:12:59 +000038// no dump_pci_device in src/northbridge/intel/i440bx
39// #define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
40#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000041#else
Uwe Hermann941a6f02007-04-30 23:27:27 +000042#define PRINT_DEBUG(x)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000043#define PRINT_DEBUG_HEX8(x)
44#define PRINT_DEBUG_HEX16(x)
45#define PRINT_DEBUG_HEX32(x)
46#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000047#endif
48
Uwe Hermann1683cef2008-11-27 00:47:07 +000049#define NB PCI_DEV(0, 0, 0)
50
Uwe Hermann1a9c8922007-04-01 17:24:03 +000051/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
52#define RAM_COMMAND_NORMAL 0x0
53#define RAM_COMMAND_NOP 0x1
54#define RAM_COMMAND_PRECHARGE 0x2
55#define RAM_COMMAND_MRS 0x3
56#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000057
Uwe Hermann1a9c8922007-04-01 17:24:03 +000058/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
59 * defined in DRAMC[2:0].
60 *
61 * [0] == Normal 15.625 us -> 15.6 us
62 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
63 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
64 * [3] == Extended(2x) 31.3 us -> 31.2 us
65 * [4] == Extended(4x) 62.5 us -> 62.4 us
66 * [5] == Extended(8x) 125 us -> 124.8 us
67 */
68static const uint32_t refresh_rate_map[] = {
69 1, 5, 5, 2, 3, 4
70};
Richard Smithcb8eab42006-07-24 04:25:47 +000071
Uwe Hermann1a9c8922007-04-01 17:24:03 +000072/* Table format: register, bitmask, value. */
73static const long register_values[] = {
74 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000075 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000076 *
77 * [31:24] SDRAM Row Without ECC
78 * 0 = ECC components are populated in this row
79 * 1 = ECC components are not populated in this row
80 * [23:19] Reserved
81 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
82 * Assertion of DRAM data on host bus occurs...
83 * 0 = ...one clock after sampling snoop results (default)
84 * 1 = ...on the same clock the snoop result is being sampled
85 * (this mode is faster by one clock cycle)
86 * [17:17] ECC - EDO static Drive mode
87 * 0 = Normal mode (default)
88 * 1 = ECC signals are always driven
89 * [16:16] IDSEL_REDIRECT
90 * 0 = IDSEL1 is allocated to this bridge (default)
91 * 1 = IDSEL7 is allocated to this bridge
92 * [15:15] WSC# Handshake Disable
93 * 1 = Uni-processor mode
94 * 0 = Dual-processor mode with external IOAPIC (default)
95 * [14:14] Intel Reserved
96 * [13:12] Host/DRAM Frequency
97 * 00 = 100 MHz
98 * 01 = Reserved
99 * 10 = 66 MHz
100 * 11 = Reserved
101 * [11:11] AGP to PCI Access Enable
102 * 1 = Enable
103 * 0 = Disable
104 * [10:10] PCI Agent to Aperture Access Disable
105 * 1 = Disable
106 * 0 = Enable (default)
107 * [09:09] Aperture Access Global Enable
108 * 1 = Enable
109 * 0 = Disable
110 * [08:07] DRAM Data Integrity Mode (DDIM)
111 * 00 = Non-ECC
112 * 01 = EC-only
113 * 10 = ECC Mode
114 * 11 = ECC Mode with hardware scrubbing enabled
115 * [06:06] ECC Diagnostic Mode Enable (EDME)
116 * 1 = Enable
117 * 0 = Normal operation mode (default)
118 * [05:05] MDA Present (MDAP)
119 * Works in conjunction with the VGA_EN bit.
120 * VGA_EN MDAP
121 * 0 x All VGA cycles are sent to PCI
122 * 1 0 All VGA cycles are sent to AGP
123 * 1 1 All VGA cycles are sent to AGP, except for
124 * cycles in the MDA range.
125 * [04:04] Reserved
126 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
127 * 1 = Enable
128 * 0 = Disable
129 * [02:02] In-Order Queue Depth (IOQD)
130 * 1 = In-order queue = maximum
131 * 0 = A7# is sampled asserted (i.e., 0)
132 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000133 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000134 // TODO
Uwe Hermannbc3594732007-06-07 22:16:30 +0000135 NBXCFG + 0, 0x00, 0x0c,
136 // NBXCFG + 1, 0x00, 0xa0,
137 NBXCFG + 1, 0x00, 0x80,
138 NBXCFG + 2, 0x00, 0x00,
139 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000140
141 /* DRAMC - DRAM Control Register
142 * 0x57
143 *
144 * [7:6] Reserved
145 * [5:5] Module Mode Configuration (MMCONFIG)
146 * TODO
147 * [4:3] DRAM Type (DT)
148 * 00 = EDO
149 * 01 = SDRAM
150 * 10 = Registered SDRAM
151 * 11 = Reserved
152 * Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
153 * [2:0] DRAM Refresh Rate (DRR)
154 * 000 = Refresh disabled
155 * 001 = 15.6 us
156 * 010 = 31.2 us
157 * 011 = 62.4 us
158 * 100 = 124.8 us
159 * 101 = 249.6 us
160 * 110 = Reserved
161 * 111 = Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000162 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000163 /* Choose SDRAM (not registered), and disable refresh for now. */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000164 DRAMC, 0x00, 0x08,
Richard Smithcb8eab42006-07-24 04:25:47 +0000165
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000166 /*
167 * PAM[6:0] - Programmable Attribute Map Registers
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000168 * 0x59 - 0x5f
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000169 *
170 * 0x59 [3:0] Reserved
171 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
172 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
173 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
174 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
175 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
176 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
177 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
178 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
179 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
180 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS entension
181 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS entension
182 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS entension
183 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS entension
184 *
185 * Bit assignment:
186 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
187 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
188 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
189 * 11 = Read/Write (all access goes to DRAM)
190 */
Keith Hui59356ca2010-03-06 18:16:25 +0000191
192 /*
193 * Map all legacy regions to RAM (read/write). This is required if
194 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
195 * registers are not set here appropriately, the RAM in that region
196 * will not be accessible, thus a RAM check of it will also fail.
197 *
198 * TODO: This was set in sdram_set_spd_registers().
199 * Test if it still works when set here.
200 */
201 PAM0, 0x00, 0x30,
202 PAM1, 0x00, 0x33,
203 PAM2, 0x00, 0x33,
204 PAM3, 0x00, 0x33,
205 PAM4, 0x00, 0x33,
206 PAM5, 0x00, 0x33,
207 PAM6, 0x00, 0x33,
Richard Smithcb8eab42006-07-24 04:25:47 +0000208
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000209 /* DRB[0:7] - DRAM Row Boundary Registers
210 * 0x60 - 0x67
211 *
212 * An array of 8 byte registers, which hold the ending memory address
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000213 * assigned to each pair of DIMMs, in 8MB granularity.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000214 *
215 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
216 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
217 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
218 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
219 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
220 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
221 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
222 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
223 */
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000224 /* Set the DRBs to zero for now, this will be fixed later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000225 DRB0, 0x00, 0x00,
226 DRB1, 0x00, 0x00,
227 DRB2, 0x00, 0x00,
228 DRB3, 0x00, 0x00,
229 DRB4, 0x00, 0x00,
230 DRB5, 0x00, 0x00,
231 DRB6, 0x00, 0x00,
232 DRB7, 0x00, 0x00,
233
234 /* FDHC - Fixed DRAM Hole Control Register
235 * 0x68
236 *
237 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
238 *
239 * [7:6] Hole Enable (HEN)
240 * 00 = None
241 * 01 = 512 KB - 640 KB (128 KB)
242 * 10 = 15 MB - 16 MB (1 MB)
243 * 11 = Reserved
244 * [5:0] Reserved
245 */
246 /* No memory holes. */
247 FDHC, 0x00, 0x00,
248
249 /* RPS - SDRAM Row Page Size Register
250 * 0x74 - 0x75
251 *
252 * Sets the row page size for SDRAM. For EDO memory, the page
253 * size is fixed at 2 KB.
254 *
255 * [15:0] Page Size (PS)
256 * TODO
257 */
258 // TODO
Uwe Hermannbc3594732007-06-07 22:16:30 +0000259 RPS + 0, 0x00, 0x00,
260 RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000261
262 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000263 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000264 *
265 * [15:10] Reserved
266 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
267 * 00 = Illegal
268 * 01 = Add a clock delay to the lead-off clock count
269 * 10 = Illegal
270 * 11 = Illegal
271 * [07:05] SDRAM Mode Select (SMS)
272 * 000 = Normal SDRAM Operation (default)
273 * 001 = NOP Command Enable
274 * 010 = All Banks Precharge Enable
275 * 011 = Mode Register Set Enable
276 * 100 = CBR Enable
277 * 101 = Reserved
278 * 110 = Reserved
279 * 111 = Reserved
280 * [04:04] SDRAMPWR
281 * 0 = 3 DIMM configuration
282 * 1 = 4 DIMM configuration
283 * [03:03] Leadoff Command Timing (LCT)
284 * 0 = 4 CS# Clock
285 * 1 = 3 CS# Clock
286 * [02:02] CAS# Latency (CL)
287 * 0 = 3 DCLK CAS# latency
288 * 1 = 2 DCLK CAS# latency
289 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
290 * 0 = 3 clocks between a row activate and a read or write cmd.
291 * 1 = 2 clocks between a row activate and a read or write cmd.
292 * [00:00] SDRAM RAS# Precharge (SRP)
293 * 0 = 3 clocks of RAS# precharge
294 * 1 = 2 clocks of RAS# precharge
295 */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000296#if CONFIG_SDRAMPWR_4DIMM
297 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
298#else
299 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots.*/
300#endif
Mats Erik Andersson45db3662008-09-30 04:52:29 +0000301 SDRAMC + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000302
303 /* PGPOL - Paging Policy Register
304 * 0x78 - 0x79
305 *
306 * [15:08] Banks per Row (BPR)
307 * TODO
308 * 0 = 2 banks
309 * 1 = 4 banks
310 * [07:05] Reserved
311 * [04:04] Intel Reserved
312 * [03:00] DRAM Idle Timer (DIT)
313 * 0000 = 0 clocks
314 * 0001 = 2 clocks
315 * 0010 = 4 clocks
316 * 0011 = 8 clocks
317 * 0100 = 10 clocks
318 * 0101 = 12 clocks
319 * 0110 = 16 clocks
320 * 0111 = 32 clocks
321 * 1xxx = Infinite (pages are not closed for idle condition)
322 */
323 // TODO
Uwe Hermannbc3594732007-06-07 22:16:30 +0000324 PGPOL + 0, 0x00, 0x00,
325 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000326
327 /* PMCR - Power Management Control Register
328 * 0x7a
329 *
330 * [07:07] Power Down SDRAM Enable (PDSE)
331 * 1 = Enable
332 * 0 = Disable
333 * [06:06] ACPI Control Register Enable (SCRE)
334 * 1 = Enable
335 * 0 = Disable (default)
336 * [05:05] Suspend Refresh Type (SRT)
337 * 1 = Self refresh mode
338 * 0 = CBR fresh mode
339 * [04:04] Normal Refresh Enable (NREF_EN)
340 * 1 = Enable
341 * 0 = Disable
342 * [03:03] Quick Start Mode (QSTART)
343 * 1 = Quick start mode for the processor is enabled
344 * [02:02] Gated Clock Enable (GCLKEN)
345 * 1 = Enable
346 * 0 = Disable
347 * [01:01] AGP Disable (AGP_DIS)
348 * 1 = Disable
349 * 0 = Enable
350 * [00:00] CPU reset without PCIRST enable (CRst_En)
351 * 1 = Enable
352 * 0 = Disable
353 */
354 /* Enable normal refresh and the gated clock. */
355 // TODO: Only do this later?
356 // PMCR, 0x00, 0x14,
357 // PMCR, 0x00, 0x10,
358 PMCR, 0x00, 0x00,
Keith Hui59356ca2010-03-06 18:16:25 +0000359
360 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
361 SCRR + 1, 0x00, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000362};
363
364/*-----------------------------------------------------------------------------
365SDRAM configuration functions.
366-----------------------------------------------------------------------------*/
367
368/**
369 * Send the specified RAM command to all DIMMs.
370 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000371 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000372 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000373static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000374{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000375 int i, caslatency;
376 u8 dimm_start, dimm_end;
377 u16 reg16;
378 u32 addr, addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000379
380 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000381 reg16 = pci_read_config16(NB, SDRAMC);
382 reg16 &= 0xff1f; /* Clear bits 7-5. */
383 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
384 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000385
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000386 /*
387 * RAM_COMMAND_NORMAL affects only the memory controller and
388 * doesn't need to be "sent" to the DIMMs.
389 */
390 if (command == RAM_COMMAND_NORMAL)
391 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000392
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000393 /* Send the RAM command to each row of memory. */
394 dimm_start = 0;
395 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000396 addr_offset = 0;
397 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000398 if (command == RAM_COMMAND_MRS) {
399 /*
400 * MAA[12:11,9:0] must be inverted when sent to DIMM
401 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
402 */
403 if ((i >= 0 && i <= 3) && caslatency == 3)
404 addr_offset = 0x1d0;
405 if ((i >= 4 && i <= 7) && caslatency == 3)
406 addr_offset = 0x1e28;
407 if ((i >= 0 && i <= 3) && caslatency == 2)
408 addr_offset = 0x150;
409 if ((i >= 4 && i <= 7) && caslatency == 2)
410 addr_offset = 0x1ea8;
411 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000412
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000413 dimm_end = pci_read_config8(NB, DRB + i);
414
415 addr = (dimm_start * 8 * 1024 * 1024) + addr_offset;
416 if (dimm_end > dimm_start) {
417#if 0
418 PRINT_DEBUG(" Sending RAM command 0x");
419 PRINT_DEBUG_HEX16(reg16);
420 PRINT_DEBUG(" to 0x");
421 PRINT_DEBUG_HEX32(addr);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000422 PRINT_DEBUG("\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000423#endif
424
425 read32(addr);
426 }
427
428 /* Set the start of the next DIMM. */
429 dimm_start = dimm_end;
430 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000431}
432
Keith Hui59356ca2010-03-06 18:16:25 +0000433static void set_dram_buffer_strength(void)
434{
Keith Huib48ba662010-03-17 02:15:07 +0000435 /* To give some breathing room for romcc,
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000436 * mbsc0 doubles as drb
Keith Huib48ba662010-03-17 02:15:07 +0000437 * mbsc1 doubles as drb1
438 * mbfs0 doubles as i and reg
Keith Hui59356ca2010-03-06 18:16:25 +0000439 */
Keith Huib48ba662010-03-17 02:15:07 +0000440 uint8_t mbsc0,mbsc1,mbsc3,mbsc4,mbfs0,mbfs2,fsb;
Keith Hui59356ca2010-03-06 18:16:25 +0000441
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000442 /* Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000443 * This determines how to program MBFS and MBSC.
444 */
445 uint8_t dimm03 = 0;
446 uint8_t dimm47 = 0;
447
448 mbsc0 = 0;
449 for (mbfs0 = DRB0; mbfs0 <= DRB7; mbfs0++) {
450 mbsc1 = pci_read_config8(NB, mbfs0);
451 if (mbsc0 != mbsc1) {
452 if (mbfs0 <= DRB3) {
453 dimm03++;
454 } else {
455 dimm47++;
456 }
457 mbsc0 = mbsc1;
458 }
459 }
460
461 /* Algorithm bitmap for programming MBSC[39:0] and MBFS[23:0]
462 *
463 * 440BX datasheet says buffer frequency is independent from bus frequency
464 * and mismatch both ways are possible. This is how it is programmed
465 * in ASUS P2B-LS.
466 *
467 * There are four main conditions to check when programming DRAM buffer
468 * frequency and strength:
469 *
470 * a: >2 rows populated across DIMM0,1
471 * b: >2 rows populated across DIMM2,3
472 * c: >4 rows populated across all DIMM slots
473 * and either one of:
474 * 1: NBXCFG[13] strapped as 100MHz, or
475 * 6: NBXCFG[13] strapped as 66MHz
476 *
477 * CKE0/FENA ----------------------------------------------------------+
478 * CKE1/GCKE -------------------[ MBFS ]------------------------+|
479 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
480 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
481 * DQMB5/CASB5# ---------------------------------------------------+||||
482 * DQMA1/CASA1# --------------------------------------------------+|||||
483 * DQMA5/CASA5# -------------------------------------------------+||||||
484 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
485 * CSA6#/CKE2# -------------------------------------------+|||||||||||||
486 * CSB6#/CKE4# ------------------------------------------+||||||||||||||
487 * CSA7#/CKE3# -----------------------------------------+|||||||||||||||
488 * CSB7#/CKE5# ----------------------------------------+||||||||||||||||
489 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
490 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
491 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
492 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
493 * Reserved ------------------------------------+|||||||||||||||||||||||
494 * ||||||||||||||||||||||||
495 * 3 32 21 10 0 * 2 21 10 0
496 * 9876543210987654321098765432109876543210 * 321098765432109876543210
497 * a 10------------------------1010---------- * -1---------------11----- a
498 *!a 11------------------------1111---------- * -0---------------00----- !a
499 * b --10--------------------------1010------ * --1----------------11--- b
500 *!b --11--------------------------1111------ * --0----------------00--- !b
501 * c ----------------------------------1100-- * ----------------------1- c
502 *!c ----------------------------------1011-- * ----------------------0- !c
503 * 1 ----1010101000000000000000------------00 * ---11111111111111----1-0 1
504 * 6 ----000000000000000000000010101010----00 * ---1111111111111100000-0 6
505 * | | | | | | | | | | ||||||| | | | | | |
506 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
507 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
508 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
509 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
510 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
511 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
512 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
513 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# [ 0=1x;1=2x ]
514 * | | | | | | | | | +--------------------- CSA6#/CKE2#
515 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4#
516 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3#
517 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5#
518 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (2x)
519 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (2x)
520 * | | | +--------------------------------- MD[63:0] #1 (2x)
521 * | | +----------------------------------- MD[63:0] #2 (2x)
522 * | +------------------------------------- MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
523 * +--------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
524 * MBSC[47:40] and MBFS[23] are reserved.
525 *
526 * This algorithm is checked against P2B-LS factory BIOS. It has 4 DIMM slots.
527 * Therefore it assumes a board with 4 slots, and will need testing
528 * on boards with 3 DIMM slots.
529 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000530
Keith Huib48ba662010-03-17 02:15:07 +0000531 mbsc0 = 0x80;
532 mbsc1 = 0x2a;
533 mbfs2 = 0x1f;
534 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
535 fsb = 66;
536 mbsc3 = 0x00;
537 mbsc4 = 0x00;
538 mbfs0 = 0x80;
539 } else {
540 fsb = 100;
541 mbsc3 = 0xa0;
542 mbsc4 = 0x0a;
543 mbfs0 = 0x84;
544 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000545
546 if (dimm03 > 2) {
547 mbsc4 = mbsc4 | 0x80;
Keith Huib48ba662010-03-17 02:15:07 +0000548 mbsc1 = mbsc1 | 0x28;
549 mbfs2 = mbfs2 | 0x40;
550 mbfs0 = mbfs0 | 0x60;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000551 } else {
552 mbsc4 = mbsc4 | 0xc0;
Keith Huib48ba662010-03-17 02:15:07 +0000553 if (fsb == 100) {
554 mbsc1 = mbsc1 | 0x3c;
555 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000556 }
557 if (dimm47 > 2) {
558 mbsc4 = mbsc4 | 0x20;
559 mbsc1 = mbsc1 | 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000560 mbsc0 = mbsc0 | 0x80;
561 mbfs2 = mbfs2 | 0x20;
562 mbfs0 = mbfs0 | 0x18;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000563 } else {
Keith Huib48ba662010-03-17 02:15:07 +0000564 mbsc4 = mbsc4 | 0x30;
565 if (fsb == 100) {
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000566 mbsc1 = mbsc1 | 0x03;
Keith Huib48ba662010-03-17 02:15:07 +0000567 mbsc0 = mbsc0 | 0xc0;
568 }
569 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000570 if ((dimm03 + dimm47) > 4) {
Keith Huib48ba662010-03-17 02:15:07 +0000571 mbsc0 = mbsc0 | 0x30;
572 mbfs0 = mbfs0 | 0x02;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000573 } else {
574 mbsc0 = mbsc0 | 0x2c;
Keith Huib48ba662010-03-17 02:15:07 +0000575 }
576
577 pci_write_config8(NB, MBSC + 0, mbsc0);
578 pci_write_config8(NB, MBSC + 1, mbsc1);
579 pci_write_config8(NB, MBSC + 2, 0x00);
580 pci_write_config8(NB, MBSC + 3, mbsc3);
581 pci_write_config8(NB, MBSC + 4, mbsc4);
582 pci_write_config8(NB, MBFS + 0, mbfs0);
583 pci_write_config8(NB, MBFS + 1, 0xff);
584 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000585}
586
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000587/*-----------------------------------------------------------------------------
588DIMM-independant configuration functions.
589-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000590
Uwe Hermann1683cef2008-11-27 00:47:07 +0000591static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000592{
593 int i, value;
594 uint8_t reg;
595
Uwe Hermann1683cef2008-11-27 00:47:07 +0000596 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000597
598 for (i = 0; i < DIMM_SOCKETS; i++) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000599 value = spd_read_byte(DIMM_SPD_BASE + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000600 if (value < 0)
601 continue;
602 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
603
604 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x");
605 PRINT_DEBUG_HEX8(reg);
606 PRINT_DEBUG(") for DIMM ");
607 PRINT_DEBUG_HEX8(i);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000608 PRINT_DEBUG("\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000609 }
610
Uwe Hermann1683cef2008-11-27 00:47:07 +0000611 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000612}
613
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000614/*-----------------------------------------------------------------------------
615Public interface.
616-----------------------------------------------------------------------------*/
617
Uwe Hermann1683cef2008-11-27 00:47:07 +0000618static void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000619{
620 int i, max;
Uwe Hermannbc3594732007-06-07 22:16:30 +0000621 uint8_t reg;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000622
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000623 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000624 DUMPNORTH();
625
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000626 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000627
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000628 /* Set registers as specified in the register_values[] array. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000629 for (i = 0; i < max; i += 3) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000630 reg = pci_read_config8(NB, register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000631 reg &= register_values[i + 1];
632 reg |= register_values[i + 2] & ~(register_values[i + 1]);
Uwe Hermann1683cef2008-11-27 00:47:07 +0000633 pci_write_config8(NB, register_values[i], reg);
Keith Hui59356ca2010-03-06 18:16:25 +0000634#if 0
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000635 PRINT_DEBUG(" Set register 0x");
Uwe Hermannbc3594732007-06-07 22:16:30 +0000636 PRINT_DEBUG_HEX8(register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000637 PRINT_DEBUG(" to 0x");
Uwe Hermannbc3594732007-06-07 22:16:30 +0000638 PRINT_DEBUG_HEX8(reg);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000639 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000640#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000641 }
642}
643
Keith Hui59356ca2010-03-06 18:16:25 +0000644struct dimm_size {
645 unsigned long side1;
646 unsigned long side2;
647};
648
649static struct dimm_size spd_get_dimm_size(unsigned int device)
650{
651 struct dimm_size sz;
652 int i, module_density, dimm_banks;
653 sz.side1 = 0;
654 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
655 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
656
657 /* Find the size of side1. */
658 /* Find the larger value. The larger value is always side1. */
659 for (i = 512; i >= 0; i >>= 1) {
660 if ((module_density & i) == i) {
661 sz.side1 = i;
662 break;
663 }
664 }
665
666 /* Set to 0 in case it's single sided. */
667 sz.side2 = 0;
668
669 /* Test if it's a dual-sided DIMM. */
670 if (dimm_banks > 1) {
671 /* Test if there's a second value. If so it's asymmetrical. */
672 if (module_density != i) {
673 /*
674 * Find second value, picking up where we left off.
675 * i >>= 1 done initially to make sure we don't get
676 * the same value again.
677 */
678 for (i >>= 1; i >= 0; i >>= 1) {
679 if (module_density == (sz.side1 | i)) {
680 sz.side2 = i;
681 break;
682 }
683 }
684 /* If not, it's symmetrical. */
685 } else {
686 sz.side2 = sz.side1;
687 }
688 }
689
690 /*
691 * SPD byte 31 is the memory size divided by 4 so we
692 * need to muliply by 4 to get the total size.
693 */
694 sz.side1 *= 4;
695 sz.side2 *= 4;
696
Anders Jenbo771b0e42010-04-27 08:45:30 +0000697 /* It is possible to partially use larger then supported
698 * modules by setting them to a supported size.
699 */
700 if(sz.side1 > 128) {
701 PRINT_DEBUG("Side1 was 0x");
702 PRINT_DEBUG_HEX16(sz.side1);
703 PRINT_DEBUG(" but only 128MB will be used.\n");
704 sz.side1 = 128;
705
706 if(sz.side2 > 128) {
707 PRINT_DEBUG("Side2 was 0x");
708 PRINT_DEBUG_HEX16(sz.side2);
709 PRINT_DEBUG(" but only 128MB will be used.\n");
710 sz.side2 = 128;
711 }
712 }
713
Keith Hui59356ca2010-03-06 18:16:25 +0000714 return sz;
715}
716/*
717 * Sets DRAM attributes one DIMM at a time, based on SPD data.
718 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
719 */
720static void set_dram_row_attributes(void)
721{
722 int i, dra, drb, col, width, value, rps, edosd, ecc, nbxecc;
723 u8 bpr; /* Top 8 bits of PGPOL */
724
725 edosd = 0;
726 rps = 0;
727 drb = 0;
728 bpr = 0;
729 nbxecc = 0xff;
730
731 for (i = 0; i < DIMM_SOCKETS; i++) {
732 unsigned int device;
733 device = DIMM_SPD_BASE + i;
734 bpr >>= 2;
735
736 /* First check if a DIMM is actually present. */
737 value = spd_read_byte(device, SPD_MEMORY_TYPE);
738 /* This is 440BX! We do EDO too! */
739 if (value == SPD_MEMORY_TYPE_EDO
740 || value == SPD_MEMORY_TYPE_SDRAM) {
741
742 PRINT_DEBUG("Found ");
743 if (value == SPD_MEMORY_TYPE_EDO) {
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000744 edosd |= 0x02;
745 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
746 edosd |= 0x04;
Keith Hui59356ca2010-03-06 18:16:25 +0000747 }
748 PRINT_DEBUG("DIMM in slot ");
749 PRINT_DEBUG_HEX8(i);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000750 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000751
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000752 if (edosd == 0x06) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000753 print_err("Mixing EDO/SDRAM unsupported!\n");
754 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000755 }
756
757 /* "DRA" is our RPS for the two rows on this DIMM. */
758 dra = 0;
759
760 /* Columns */
761 col = spd_read_byte(device, SPD_NUM_COLUMNS);
762
763 /*
764 * Is this an ECC DIMM? Actually will be a 2 if so.
765 * TODO: Other register than NBXCFG also needs this
766 * ECC information.
767 */
768 ecc = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
769
770 /* Data width */
771 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000772
Keith Hui59356ca2010-03-06 18:16:25 +0000773 /* Exclude error checking data width from page size calculations */
774 if (ecc) {
775 value = spd_read_byte(device,
776 SPD_ERROR_CHECKING_SDRAM_WIDTH);
777 width -= value;
778 /* ### ECC */
779 /* Clear top 2 bits to help set up NBXCFG. */
780 ecc &= 0x3f;
781 } else {
782 /* Without ECC, top 2 bits should be 11. */
783 ecc |= 0xc0;
784 }
785
786 /* Calculate page size in bits. */
787 value = ((1 << col) * width);
788
789 /* Convert to KB. */
790 dra = (value >> 13);
791
792 /* Number of banks of DIMM (single or double sided). */
793 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
794
795 /* Once we have dra, col is done and can be reused.
796 * So it's reused for number of banks.
797 */
798 col = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
799
800 if (value == 1) {
801 /*
802 * Second bank of 1-bank DIMMs "doesn't have
803 * ECC" - or anything.
804 */
805 ecc |= 0x80;
806 if (dra == 2) {
807 dra = 0x0; /* 2KB */
808 } else if (dra == 4) {
809 dra = 0x1; /* 4KB */
810 } else if (dra == 8) {
811 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000812 } else if (dra >= 16) {
813 /* Page sizes larger than supported are
814 * set to 8KB to use module partially.
815 */
816 PRINT_DEBUG("Page size forced to 8KB.\n");
817 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000818 } else {
819 dra = -1;
820 }
821 /*
822 * Sets a flag in PGPOL[BPR] if this DIMM has
823 * 4 banks per row.
824 */
825 if (col == 4)
826 bpr |= 0x40;
827 } else if (value == 2) {
828 if (dra == 2) {
829 dra = 0x0; /* 2KB */
830 } else if (dra == 4) {
831 dra = 0x05; /* 4KB */
832 } else if (dra == 8) {
833 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000834 } else if (dra >= 16) {
835 /* Ditto */
836 PRINT_DEBUG("Page size forced to 8KB.\n");
837 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000838 } else {
839 dra = -1;
840 }
841 /* Ditto */
842 if (col == 4)
843 bpr |= 0xc0;
844 } else {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000845 print_err("# of banks of DIMM unsupported!\n");
846 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000847 }
848 if (dra == -1) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000849 print_err("Page size not supported\n");
850 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000851 }
852
853 /*
854 * 440BX supports asymmetrical dual-sided DIMMs,
855 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000856 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000857 */
858 struct dimm_size sz = spd_get_dimm_size(device);
859 if ((sz.side1 < 8)) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000860 print_err("DIMMs smaller than 8MB per side\n"
861 "are not supported on this NB.\n");
862 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000863 }
Keith Hui59356ca2010-03-06 18:16:25 +0000864
865 /* Divide size by 8 to set up the DRB registers. */
866 drb += (sz.side1 / 8);
867
868 /*
869 * Build the DRB for the next row in MSB so it gets
870 * placed in DRB[n+1] where it belongs when written
871 * as a 16-bit word.
872 */
873 drb &= 0xff;
874 drb |= (drb + (sz.side2 / 8)) << 8;
875 } else {
876#if 0
877 PRINT_DEBUG("No DIMM found in slot ");
878 PRINT_DEBUG_HEX8(i);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000879 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000880#endif
881
882 /* If there's no DIMM in the slot, set dra to 0x00. */
883 dra = 0x00;
884 ecc = 0xc0;
885 /* Still have to propagate DRB over. */
886 drb &= 0xff;
887 drb |= (drb << 8);
888 }
889
890 pci_write_config16(NB, DRB + (2 * i), drb);
891#if 0
892 PRINT_DEBUG("DRB has been set to 0x");
893 PRINT_DEBUG_HEX16(drb);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000894 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000895#endif
896
897 /* Brings the upper DRB back down to be base for
898 * DRB calculations for the next two rows.
899 */
900 drb >>= 8;
901
902 rps |= (dra & 0x0f) << (i * 4);
903 nbxecc = (nbxecc >> 2) | (ecc & 0xc0);
904 }
905
906 /* Set paging policy register. */
907 pci_write_config8(NB, PGPOL + 1, bpr);
908 PRINT_DEBUG("PGPOL[BPR] has been set to 0x");
909 PRINT_DEBUG_HEX8(bpr);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000910 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000911
912 /* Set DRAM row page size register. */
913 pci_write_config16(NB, RPS, rps);
914 PRINT_DEBUG("RPS has been set to 0x");
915 PRINT_DEBUG_HEX16(rps);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000916 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000917
918 /* ### ECC */
919 pci_write_config8(NB, NBXCFG + 3, nbxecc);
920 PRINT_DEBUG("NBXECC[31:24] has been set to 0x");
921 PRINT_DEBUG_HEX8(nbxecc);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000922 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000923
924 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM).
925 * TODO: Registered SDRAM support.
926 */
927 edosd &= 0x07;
928 if (edosd & 0x02) {
929 edosd |= 0x00;
930 } else if (edosd & 0x04) {
931 edosd |= 0x08;
932 }
933 edosd &= 0x18;
934
935 /* edosd is now in the form needed for DRAMC[4:3]. */
936 value = pci_read_config8(NB, DRAMC) & 0xe7;
937 value |= edosd;
938 pci_write_config8(NB, DRAMC, value);
939 PRINT_DEBUG("DRAMC has been set to 0x");
940 PRINT_DEBUG_HEX8(value);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000941 PRINT_DEBUG("\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000942}
943
Uwe Hermann1683cef2008-11-27 00:47:07 +0000944static void sdram_set_spd_registers(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000945{
Keith Hui59356ca2010-03-06 18:16:25 +0000946 /* Setup DRAM row boundary registers and other attributes. */
947 set_dram_row_attributes();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000948
949 /* TODO: Set SDRAMC. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000950 pci_write_config16(NB, SDRAMC, 0x0010); /* SDRAMPWR=1: 4 DIMM config */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000951
Keith Hui59356ca2010-03-06 18:16:25 +0000952 /* TODO */
953 set_dram_buffer_strength();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000954
955 /* TODO: Set PMCR? */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000956 // pci_write_config8(NB, PMCR, 0x14);
957 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000958
959 /* TODO? */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000960 pci_write_config8(NB, DRAMT, 0x03);
Richard Smithcb8eab42006-07-24 04:25:47 +0000961}
962
Uwe Hermann1683cef2008-11-27 00:47:07 +0000963static void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000964{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000965 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000966
Uwe Hermann861f9642007-05-28 14:37:06 +0000967 /* 0. Wait until power/voltages and clocks are stable (200us). */
968 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000969
Uwe Hermann861f9642007-05-28 14:37:06 +0000970 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000971 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000972 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +0000973 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000974
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000975 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000976 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000977 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +0000978 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000979
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000980 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000981 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000982 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000983 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +0000984 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000985 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000986
987 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000988 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000989 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +0000990 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000991
992 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000993 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000994 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +0000995 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000996
997 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000998 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Uwe Hermann1683cef2008-11-27 00:47:07 +0000999 // pci_write_config8(NB, PMCR, 0x10);
1000 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +00001001 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001002
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001003 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001004 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001005}