blob: 7472cc994ba3813ee44cf2b843c67775a942b347 [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
Paul Menzela46a7122013-02-23 18:37:27 +010019 * 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>
Uwe Hermann115c5b92010-10-09 17:00:18 +000024#include <stdint.h>
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +000025#include <stdlib.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000026#include <arch/io.h>
27#include <arch/romcc_io.h>
28#include <device/pci_def.h>
29#include <console/console.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000030#include "i440bx.h"
Keith Hui59356ca2010-03-06 18:16:25 +000031#include "raminit.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000032
Uwe Hermann1a9c8922007-04-01 17:24:03 +000033/*-----------------------------------------------------------------------------
34Macros and definitions.
35-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +000036
Keith Huidf35cdc2010-09-20 23:41:37 +000037#define NB PCI_DEV(0, 0, 0)
38
Uwe Hermann1a9c8922007-04-01 17:24:03 +000039/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000040#if CONFIG_DEBUG_RAM_SETUP
Keith Hui09f5a742010-12-23 17:12:03 +000041#define PRINT_DEBUG(x...) printk(BIOS_DEBUG, x)
Keith Huidf35cdc2010-09-20 23:41:37 +000042#define DUMPNORTH() dump_pci_device(NB)
Richard Smithcb8eab42006-07-24 04:25:47 +000043#else
Keith Hui09f5a742010-12-23 17:12:03 +000044#define PRINT_DEBUG(x...)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000045#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000046#endif
47
Uwe Hermann1a9c8922007-04-01 17:24:03 +000048/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
49#define RAM_COMMAND_NORMAL 0x0
50#define RAM_COMMAND_NOP 0x1
51#define RAM_COMMAND_PRECHARGE 0x2
52#define RAM_COMMAND_MRS 0x3
53#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000054
Uwe Hermann1a9c8922007-04-01 17:24:03 +000055/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
56 * defined in DRAMC[2:0].
57 *
58 * [0] == Normal 15.625 us -> 15.6 us
59 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
60 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
61 * [3] == Extended(2x) 31.3 us -> 31.2 us
62 * [4] == Extended(4x) 62.5 us -> 62.4 us
63 * [5] == Extended(8x) 125 us -> 124.8 us
64 */
65static const uint32_t refresh_rate_map[] = {
66 1, 5, 5, 2, 3, 4
67};
Richard Smithcb8eab42006-07-24 04:25:47 +000068
Uwe Hermann1a9c8922007-04-01 17:24:03 +000069/* Table format: register, bitmask, value. */
Keith Huidf35cdc2010-09-20 23:41:37 +000070static const u8 register_values[] = {
Uwe Hermann1a9c8922007-04-01 17:24:03 +000071 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000072 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000073 *
74 * [31:24] SDRAM Row Without ECC
75 * 0 = ECC components are populated in this row
76 * 1 = ECC components are not populated in this row
77 * [23:19] Reserved
78 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
79 * Assertion of DRAM data on host bus occurs...
80 * 0 = ...one clock after sampling snoop results (default)
81 * 1 = ...on the same clock the snoop result is being sampled
82 * (this mode is faster by one clock cycle)
83 * [17:17] ECC - EDO static Drive mode
84 * 0 = Normal mode (default)
85 * 1 = ECC signals are always driven
86 * [16:16] IDSEL_REDIRECT
87 * 0 = IDSEL1 is allocated to this bridge (default)
88 * 1 = IDSEL7 is allocated to this bridge
89 * [15:15] WSC# Handshake Disable
90 * 1 = Uni-processor mode
91 * 0 = Dual-processor mode with external IOAPIC (default)
92 * [14:14] Intel Reserved
93 * [13:12] Host/DRAM Frequency
94 * 00 = 100 MHz
95 * 01 = Reserved
96 * 10 = 66 MHz
97 * 11 = Reserved
98 * [11:11] AGP to PCI Access Enable
99 * 1 = Enable
100 * 0 = Disable
101 * [10:10] PCI Agent to Aperture Access Disable
102 * 1 = Disable
103 * 0 = Enable (default)
104 * [09:09] Aperture Access Global Enable
105 * 1 = Enable
106 * 0 = Disable
107 * [08:07] DRAM Data Integrity Mode (DDIM)
108 * 00 = Non-ECC
109 * 01 = EC-only
110 * 10 = ECC Mode
111 * 11 = ECC Mode with hardware scrubbing enabled
112 * [06:06] ECC Diagnostic Mode Enable (EDME)
113 * 1 = Enable
114 * 0 = Normal operation mode (default)
115 * [05:05] MDA Present (MDAP)
116 * Works in conjunction with the VGA_EN bit.
117 * VGA_EN MDAP
118 * 0 x All VGA cycles are sent to PCI
119 * 1 0 All VGA cycles are sent to AGP
120 * 1 1 All VGA cycles are sent to AGP, except for
121 * cycles in the MDA range.
122 * [04:04] Reserved
123 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
124 * 1 = Enable
125 * 0 = Disable
126 * [02:02] In-Order Queue Depth (IOQD)
127 * 1 = In-order queue = maximum
128 * 0 = A7# is sampled asserted (i.e., 0)
129 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000130 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000131 NBXCFG + 0, 0x00, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000132 // TODO: Bit 15 should be 0 for multiprocessor boards
Uwe Hermannbc3594732007-06-07 22:16:30 +0000133 NBXCFG + 1, 0x00, 0x80,
134 NBXCFG + 2, 0x00, 0x00,
135 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000136
137 /* DRAMC - DRAM Control Register
138 * 0x57
139 *
140 * [7:6] Reserved
141 * [5:5] Module Mode Configuration (MMCONFIG)
Keith Huidf35cdc2010-09-20 23:41:37 +0000142 * The combination of SDRAMPWR and this bit (which is set by an
143 * external strapping option) determine how CKE works.
144 * SDRAMPWR MMCONFIG
145 * 0 0 = 3 DIMM, CKE0[5:0] driven
146 * X 1 = 3 DIMM, CKE0 only
147 * 1 0 = 4 DIMM, GCKE only
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000148 * [4:3] DRAM Type (DT)
149 * 00 = EDO
150 * 01 = SDRAM
151 * 10 = Registered SDRAM
152 * 11 = Reserved
153 * Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
154 * [2:0] DRAM Refresh Rate (DRR)
155 * 000 = Refresh disabled
156 * 001 = 15.6 us
157 * 010 = 31.2 us
158 * 011 = 62.4 us
159 * 100 = 124.8 us
160 * 101 = 249.6 us
161 * 110 = Reserved
162 * 111 = Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000163 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000164 /* Choose SDRAM (not registered), and disable refresh for now. */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000165 DRAMC, 0x00, 0x08,
Richard Smithcb8eab42006-07-24 04:25:47 +0000166
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000167 /*
168 * PAM[6:0] - Programmable Attribute Map Registers
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000169 * 0x59 - 0x5f
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000170 *
171 * 0x59 [3:0] Reserved
172 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
173 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
174 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
175 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
176 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
177 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
178 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
179 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
180 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
181 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS entension
182 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS entension
183 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS entension
184 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS entension
185 *
186 * Bit assignment:
187 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
188 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
189 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
190 * 11 = Read/Write (all access goes to DRAM)
191 */
Keith Hui59356ca2010-03-06 18:16:25 +0000192
193 /*
194 * Map all legacy regions to RAM (read/write). This is required if
195 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
196 * registers are not set here appropriately, the RAM in that region
197 * will not be accessible, thus a RAM check of it will also fail.
198 *
199 * TODO: This was set in sdram_set_spd_registers().
200 * Test if it still works when set here.
201 */
202 PAM0, 0x00, 0x30,
203 PAM1, 0x00, 0x33,
204 PAM2, 0x00, 0x33,
205 PAM3, 0x00, 0x33,
206 PAM4, 0x00, 0x33,
207 PAM5, 0x00, 0x33,
208 PAM6, 0x00, 0x33,
Richard Smithcb8eab42006-07-24 04:25:47 +0000209
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000210 /* DRB[0:7] - DRAM Row Boundary Registers
211 * 0x60 - 0x67
212 *
213 * An array of 8 byte registers, which hold the ending memory address
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000214 * assigned to each pair of DIMMs, in 8MB granularity.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000215 *
216 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
217 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
218 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
219 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
220 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
221 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
222 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
223 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
224 */
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000225 /* Set the DRBs to zero for now, this will be fixed later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000226 DRB0, 0x00, 0x00,
227 DRB1, 0x00, 0x00,
228 DRB2, 0x00, 0x00,
229 DRB3, 0x00, 0x00,
230 DRB4, 0x00, 0x00,
231 DRB5, 0x00, 0x00,
232 DRB6, 0x00, 0x00,
233 DRB7, 0x00, 0x00,
234
235 /* FDHC - Fixed DRAM Hole Control Register
236 * 0x68
237 *
238 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
239 *
240 * [7:6] Hole Enable (HEN)
241 * 00 = None
242 * 01 = 512 KB - 640 KB (128 KB)
243 * 10 = 15 MB - 16 MB (1 MB)
244 * 11 = Reserved
245 * [5:0] Reserved
246 */
247 /* No memory holes. */
248 FDHC, 0x00, 0x00,
249
250 /* RPS - SDRAM Row Page Size Register
251 * 0x74 - 0x75
252 *
253 * Sets the row page size for SDRAM. For EDO memory, the page
254 * size is fixed at 2 KB.
255 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000256 * Bits[1:0] Page Size
257 * 00 2 KB
258 * 01 4 KB
259 * 10 8 KB
260 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400261 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000262 * RPS bits Corresponding DRB register
263 * [01:00] DRB[0], row 0
264 * [03:02] DRB[1], row 1
265 * [05:04] DRB[2], row 2
266 * [07:06] DRB[3], row 3
267 * [09:08] DRB[4], row 4
268 * [11:10] DRB[5], row 5
269 * [13:12] DRB[6], row 6
270 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000271 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000272 /* Power on defaults to 2KB. Will be set later. */
273 // RPS + 0, 0x00, 0x00,
274 // RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000275
276 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000277 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000278 *
279 * [15:10] Reserved
280 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
281 * 00 = Illegal
282 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000283 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000284 * [07:05] SDRAM Mode Select (SMS)
285 * 000 = Normal SDRAM Operation (default)
286 * 001 = NOP Command Enable
287 * 010 = All Banks Precharge Enable
288 * 011 = Mode Register Set Enable
289 * 100 = CBR Enable
290 * 101 = Reserved
291 * 110 = Reserved
292 * 111 = Reserved
293 * [04:04] SDRAMPWR
294 * 0 = 3 DIMM configuration
295 * 1 = 4 DIMM configuration
296 * [03:03] Leadoff Command Timing (LCT)
297 * 0 = 4 CS# Clock
298 * 1 = 3 CS# Clock
299 * [02:02] CAS# Latency (CL)
300 * 0 = 3 DCLK CAS# latency
301 * 1 = 2 DCLK CAS# latency
302 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
303 * 0 = 3 clocks between a row activate and a read or write cmd.
304 * 1 = 2 clocks between a row activate and a read or write cmd.
305 * [00:00] SDRAM RAS# Precharge (SRP)
306 * 0 = 3 clocks of RAS# precharge
307 * 1 = 2 clocks of RAS# precharge
308 */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000309#if CONFIG_SDRAMPWR_4DIMM
310 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
311#else
Keith Huidf35cdc2010-09-20 23:41:37 +0000312 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000313#endif
Mats Erik Andersson45db3662008-09-30 04:52:29 +0000314 SDRAMC + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000315
316 /* PGPOL - Paging Policy Register
317 * 0x78 - 0x79
318 *
319 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000320 * Each bit in this field corresponds to one row of the memory
321 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
322 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000323 * 0 = 2 banks
324 * 1 = 4 banks
325 * [07:05] Reserved
326 * [04:04] Intel Reserved
327 * [03:00] DRAM Idle Timer (DIT)
328 * 0000 = 0 clocks
329 * 0001 = 2 clocks
330 * 0010 = 4 clocks
331 * 0011 = 8 clocks
332 * 0100 = 10 clocks
333 * 0101 = 12 clocks
334 * 0110 = 16 clocks
335 * 0111 = 32 clocks
336 * 1xxx = Infinite (pages are not closed for idle condition)
337 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000338 PGPOL + 0, 0x00, 0x00,
339 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000340
341 /* PMCR - Power Management Control Register
342 * 0x7a
343 *
344 * [07:07] Power Down SDRAM Enable (PDSE)
345 * 1 = Enable
346 * 0 = Disable
347 * [06:06] ACPI Control Register Enable (SCRE)
348 * 1 = Enable
349 * 0 = Disable (default)
350 * [05:05] Suspend Refresh Type (SRT)
351 * 1 = Self refresh mode
352 * 0 = CBR fresh mode
353 * [04:04] Normal Refresh Enable (NREF_EN)
354 * 1 = Enable
355 * 0 = Disable
356 * [03:03] Quick Start Mode (QSTART)
357 * 1 = Quick start mode for the processor is enabled
358 * [02:02] Gated Clock Enable (GCLKEN)
359 * 1 = Enable
360 * 0 = Disable
361 * [01:01] AGP Disable (AGP_DIS)
362 * 1 = Disable
363 * 0 = Enable
364 * [00:00] CPU reset without PCIRST enable (CRst_En)
365 * 1 = Enable
366 * 0 = Disable
367 */
368 /* Enable normal refresh and the gated clock. */
369 // TODO: Only do this later?
370 // PMCR, 0x00, 0x14,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000371 PMCR, 0x00, 0x00,
Keith Hui59356ca2010-03-06 18:16:25 +0000372
373 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
374 SCRR + 1, 0x00, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000375};
376
377/*-----------------------------------------------------------------------------
378SDRAM configuration functions.
379-----------------------------------------------------------------------------*/
380
381/**
382 * Send the specified RAM command to all DIMMs.
383 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000384 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000385 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000386static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000387{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000388 int i, caslatency;
389 u8 dimm_start, dimm_end;
390 u16 reg16;
391 u32 addr, addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000392
393 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000394 reg16 = pci_read_config16(NB, SDRAMC);
395 reg16 &= 0xff1f; /* Clear bits 7-5. */
396 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
397 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000398
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000399 /*
400 * RAM_COMMAND_NORMAL affects only the memory controller and
401 * doesn't need to be "sent" to the DIMMs.
402 */
403 if (command == RAM_COMMAND_NORMAL)
404 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000405
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000406 /* Send the RAM command to each row of memory. */
407 dimm_start = 0;
408 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000409 addr_offset = 0;
410 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000411 if (command == RAM_COMMAND_MRS) {
412 /*
413 * MAA[12:11,9:0] must be inverted when sent to DIMM
414 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
415 */
416 if ((i >= 0 && i <= 3) && caslatency == 3)
417 addr_offset = 0x1d0;
418 if ((i >= 4 && i <= 7) && caslatency == 3)
419 addr_offset = 0x1e28;
420 if ((i >= 0 && i <= 3) && caslatency == 2)
421 addr_offset = 0x150;
422 if ((i >= 4 && i <= 7) && caslatency == 2)
423 addr_offset = 0x1ea8;
424 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000425
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000426 dimm_end = pci_read_config8(NB, DRB + i);
427
428 addr = (dimm_start * 8 * 1024 * 1024) + addr_offset;
429 if (dimm_end > dimm_start) {
430#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000431 PRINT_DEBUG(" Sending RAM command 0x%04x to 0x%08x\n",
432 reg16, addr);
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000433#endif
434
435 read32(addr);
436 }
437
438 /* Set the start of the next DIMM. */
439 dimm_start = dimm_end;
440 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000441}
442
Keith Hui59356ca2010-03-06 18:16:25 +0000443static void set_dram_buffer_strength(void)
444{
Keith Huib48ba662010-03-17 02:15:07 +0000445 /* To give some breathing room for romcc,
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000446 * mbsc0 doubles as drb
Keith Huib48ba662010-03-17 02:15:07 +0000447 * mbsc1 doubles as drb1
448 * mbfs0 doubles as i and reg
Keith Hui59356ca2010-03-06 18:16:25 +0000449 */
Keith Huib48ba662010-03-17 02:15:07 +0000450 uint8_t mbsc0,mbsc1,mbsc3,mbsc4,mbfs0,mbfs2,fsb;
Keith Hui59356ca2010-03-06 18:16:25 +0000451
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000452 /* Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000453 * This determines how to program MBFS and MBSC.
454 */
455 uint8_t dimm03 = 0;
456 uint8_t dimm47 = 0;
457
458 mbsc0 = 0;
459 for (mbfs0 = DRB0; mbfs0 <= DRB7; mbfs0++) {
460 mbsc1 = pci_read_config8(NB, mbfs0);
461 if (mbsc0 != mbsc1) {
462 if (mbfs0 <= DRB3) {
463 dimm03++;
464 } else {
465 dimm47++;
466 }
467 mbsc0 = mbsc1;
468 }
469 }
470
Keith Huidf35cdc2010-09-20 23:41:37 +0000471 /* Algorithm bitmap for programming MBSC[39:0] and MBFS[23:0].
Keith Huib48ba662010-03-17 02:15:07 +0000472 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000473 * The 440BX datasheet says buffer frequency is independent from bus
474 * frequency and mismatch both ways are possible. This is how it is
475 * programmed in the ASUS P2B-LS mainboard.
Keith Huib48ba662010-03-17 02:15:07 +0000476 *
477 * There are four main conditions to check when programming DRAM buffer
478 * frequency and strength:
479 *
480 * a: >2 rows populated across DIMM0,1
481 * b: >2 rows populated across DIMM2,3
482 * c: >4 rows populated across all DIMM slots
483 * and either one of:
484 * 1: NBXCFG[13] strapped as 100MHz, or
485 * 6: NBXCFG[13] strapped as 66MHz
486 *
487 * CKE0/FENA ----------------------------------------------------------+
488 * CKE1/GCKE -------------------[ MBFS ]------------------------+|
489 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
490 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
491 * DQMB5/CASB5# ---------------------------------------------------+||||
492 * DQMA1/CASA1# --------------------------------------------------+|||||
493 * DQMA5/CASA5# -------------------------------------------------+||||||
494 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
495 * CSA6#/CKE2# -------------------------------------------+|||||||||||||
496 * CSB6#/CKE4# ------------------------------------------+||||||||||||||
497 * CSA7#/CKE3# -----------------------------------------+|||||||||||||||
498 * CSB7#/CKE5# ----------------------------------------+||||||||||||||||
499 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
500 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
501 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
502 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
503 * Reserved ------------------------------------+|||||||||||||||||||||||
504 * ||||||||||||||||||||||||
505 * 3 32 21 10 0 * 2 21 10 0
506 * 9876543210987654321098765432109876543210 * 321098765432109876543210
507 * a 10------------------------1010---------- * -1---------------11----- a
508 *!a 11------------------------1111---------- * -0---------------00----- !a
509 * b --10--------------------------1010------ * --1----------------11--- b
510 *!b --11--------------------------1111------ * --0----------------00--- !b
511 * c ----------------------------------1100-- * ----------------------1- c
512 *!c ----------------------------------1011-- * ----------------------0- !c
513 * 1 ----1010101000000000000000------------00 * ---11111111111111----1-0 1
514 * 6 ----000000000000000000000010101010----00 * ---1111111111111100000-0 6
515 * | | | | | | | | | | ||||||| | | | | | |
516 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
517 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
518 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
519 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
520 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
521 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
522 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
523 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# [ 0=1x;1=2x ]
524 * | | | | | | | | | +--------------------- CSA6#/CKE2#
525 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4#
526 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3#
527 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5#
528 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (2x)
529 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (2x)
530 * | | | +--------------------------------- MD[63:0] #1 (2x)
531 * | | +----------------------------------- MD[63:0] #2 (2x)
532 * | +------------------------------------- MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
533 * +--------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
534 * MBSC[47:40] and MBFS[23] are reserved.
535 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000536 * This algorithm is checked against the ASUS P2B-LS (which has
537 * 4 DIMM slots) factory BIOS.
Keith Huib48ba662010-03-17 02:15:07 +0000538 * Therefore it assumes a board with 4 slots, and will need testing
539 * on boards with 3 DIMM slots.
540 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000541
Keith Huib48ba662010-03-17 02:15:07 +0000542 mbsc0 = 0x80;
543 mbsc1 = 0x2a;
544 mbfs2 = 0x1f;
545 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
546 fsb = 66;
547 mbsc3 = 0x00;
548 mbsc4 = 0x00;
549 mbfs0 = 0x80;
550 } else {
551 fsb = 100;
552 mbsc3 = 0xa0;
553 mbsc4 = 0x0a;
554 mbfs0 = 0x84;
555 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000556
557 if (dimm03 > 2) {
558 mbsc4 = mbsc4 | 0x80;
Keith Huib48ba662010-03-17 02:15:07 +0000559 mbsc1 = mbsc1 | 0x28;
560 mbfs2 = mbfs2 | 0x40;
561 mbfs0 = mbfs0 | 0x60;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000562 } else {
563 mbsc4 = mbsc4 | 0xc0;
Keith Huib48ba662010-03-17 02:15:07 +0000564 if (fsb == 100) {
565 mbsc1 = mbsc1 | 0x3c;
566 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000567 }
568 if (dimm47 > 2) {
569 mbsc4 = mbsc4 | 0x20;
570 mbsc1 = mbsc1 | 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000571 mbsc0 = mbsc0 | 0x80;
572 mbfs2 = mbfs2 | 0x20;
573 mbfs0 = mbfs0 | 0x18;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000574 } else {
Keith Huib48ba662010-03-17 02:15:07 +0000575 mbsc4 = mbsc4 | 0x30;
576 if (fsb == 100) {
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000577 mbsc1 = mbsc1 | 0x03;
Keith Huib48ba662010-03-17 02:15:07 +0000578 mbsc0 = mbsc0 | 0xc0;
579 }
580 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000581 if ((dimm03 + dimm47) > 4) {
Keith Huib48ba662010-03-17 02:15:07 +0000582 mbsc0 = mbsc0 | 0x30;
583 mbfs0 = mbfs0 | 0x02;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000584 } else {
585 mbsc0 = mbsc0 | 0x2c;
Keith Huib48ba662010-03-17 02:15:07 +0000586 }
587
588 pci_write_config8(NB, MBSC + 0, mbsc0);
589 pci_write_config8(NB, MBSC + 1, mbsc1);
590 pci_write_config8(NB, MBSC + 2, 0x00);
591 pci_write_config8(NB, MBSC + 3, mbsc3);
592 pci_write_config8(NB, MBSC + 4, mbsc4);
593 pci_write_config8(NB, MBFS + 0, mbfs0);
594 pci_write_config8(NB, MBFS + 1, 0xff);
595 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000596}
597
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000598/*-----------------------------------------------------------------------------
599DIMM-independant configuration functions.
600-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000601
Uwe Hermann1683cef2008-11-27 00:47:07 +0000602static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000603{
604 int i, value;
605 uint8_t reg;
606
Uwe Hermann1683cef2008-11-27 00:47:07 +0000607 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000608
609 for (i = 0; i < DIMM_SOCKETS; i++) {
Uwe Hermannd773fd32010-11-20 20:23:08 +0000610 value = spd_read_byte(DIMM0 + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000611 if (value < 0)
612 continue;
613 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
614
Keith Hui09f5a742010-12-23 17:12:03 +0000615 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000616 }
617
Uwe Hermann1683cef2008-11-27 00:47:07 +0000618 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000619}
620
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000621/*-----------------------------------------------------------------------------
622Public interface.
623-----------------------------------------------------------------------------*/
624
Uwe Hermann115c5b92010-10-09 17:00:18 +0000625void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000626{
627 int i, max;
Uwe Hermannbc3594732007-06-07 22:16:30 +0000628 uint8_t reg;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000629
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000630 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000631 DUMPNORTH();
632
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000633 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000634
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000635 /* Set registers as specified in the register_values[] array. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000636 for (i = 0; i < max; i += 3) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000637 reg = pci_read_config8(NB, register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000638 reg &= register_values[i + 1];
639 reg |= register_values[i + 2] & ~(register_values[i + 1]);
Uwe Hermann1683cef2008-11-27 00:47:07 +0000640 pci_write_config8(NB, register_values[i], reg);
Keith Hui59356ca2010-03-06 18:16:25 +0000641#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000642 PRINT_DEBUG(" Set register 0x%02x to 0x%02x\n",
643 register_values[i], reg);
Keith Hui59356ca2010-03-06 18:16:25 +0000644#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000645 }
646}
647
Keith Hui59356ca2010-03-06 18:16:25 +0000648struct dimm_size {
Keith Hui09f5a742010-12-23 17:12:03 +0000649 u32 side1;
650 u32 side2;
Keith Hui59356ca2010-03-06 18:16:25 +0000651};
652
653static struct dimm_size spd_get_dimm_size(unsigned int device)
654{
655 struct dimm_size sz;
656 int i, module_density, dimm_banks;
657 sz.side1 = 0;
658 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
659 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
660
661 /* Find the size of side1. */
662 /* Find the larger value. The larger value is always side1. */
663 for (i = 512; i >= 0; i >>= 1) {
664 if ((module_density & i) == i) {
665 sz.side1 = i;
666 break;
667 }
668 }
669
670 /* Set to 0 in case it's single sided. */
671 sz.side2 = 0;
672
673 /* Test if it's a dual-sided DIMM. */
674 if (dimm_banks > 1) {
675 /* Test if there's a second value. If so it's asymmetrical. */
676 if (module_density != i) {
677 /*
678 * Find second value, picking up where we left off.
679 * i >>= 1 done initially to make sure we don't get
680 * the same value again.
681 */
682 for (i >>= 1; i >= 0; i >>= 1) {
683 if (module_density == (sz.side1 | i)) {
684 sz.side2 = i;
685 break;
686 }
687 }
688 /* If not, it's symmetrical. */
689 } else {
690 sz.side2 = sz.side1;
691 }
692 }
693
694 /*
695 * SPD byte 31 is the memory size divided by 4 so we
696 * need to muliply by 4 to get the total size.
697 */
698 sz.side1 *= 4;
699 sz.side2 *= 4;
700
Anders Jenbo771b0e42010-04-27 08:45:30 +0000701 /* It is possible to partially use larger then supported
702 * modules by setting them to a supported size.
703 */
704 if(sz.side1 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000705 PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
706 sz.side1);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000707 sz.side1 = 128;
708
709 if(sz.side2 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000710 PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
711 sz.side2);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000712 sz.side2 = 128;
713 }
714 }
715
Keith Hui59356ca2010-03-06 18:16:25 +0000716 return sz;
717}
718/*
719 * Sets DRAM attributes one DIMM at a time, based on SPD data.
720 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
721 */
722static void set_dram_row_attributes(void)
723{
Keith Huie089a3f2011-08-02 22:28:14 -0400724 int i, dra, drb, col, width, value, rps;
Keith Hui59356ca2010-03-06 18:16:25 +0000725 u8 bpr; /* Top 8 bits of PGPOL */
Keith Huie089a3f2011-08-02 22:28:14 -0400726 u8 nbxecc = 0; /* NBXCFG[31:24] */
727 u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
Keith Hui59356ca2010-03-06 18:16:25 +0000728
Keith Huie089a3f2011-08-02 22:28:14 -0400729 edo = 0;
730 sd = 0;
731 regsd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000732 rps = 0;
733 drb = 0;
734 bpr = 0;
Keith Hui59356ca2010-03-06 18:16:25 +0000735
736 for (i = 0; i < DIMM_SOCKETS; i++) {
737 unsigned int device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000738 device = DIMM0 + i;
Keith Hui59356ca2010-03-06 18:16:25 +0000739 bpr >>= 2;
Keith Huie089a3f2011-08-02 22:28:14 -0400740 nbxecc >>= 2;
Keith Hui59356ca2010-03-06 18:16:25 +0000741
742 /* First check if a DIMM is actually present. */
743 value = spd_read_byte(device, SPD_MEMORY_TYPE);
744 /* This is 440BX! We do EDO too! */
745 if (value == SPD_MEMORY_TYPE_EDO
746 || value == SPD_MEMORY_TYPE_SDRAM) {
747
Keith Hui59356ca2010-03-06 18:16:25 +0000748 if (value == SPD_MEMORY_TYPE_EDO) {
Keith Huie089a3f2011-08-02 22:28:14 -0400749 edo = 1;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000750 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
Keith Huie089a3f2011-08-02 22:28:14 -0400751 sd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000752 }
Keith Hui09f5a742010-12-23 17:12:03 +0000753 PRINT_DEBUG("Found DIMM in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000754
Keith Huie089a3f2011-08-02 22:28:14 -0400755 if (edo && sd) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000756 print_err("Mixing EDO/SDRAM unsupported!\n");
757 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000758 }
759
760 /* "DRA" is our RPS for the two rows on this DIMM. */
761 dra = 0;
762
763 /* Columns */
764 col = spd_read_byte(device, SPD_NUM_COLUMNS);
765
766 /*
767 * Is this an ECC DIMM? Actually will be a 2 if so.
768 * TODO: Other register than NBXCFG also needs this
769 * ECC information.
770 */
Keith Huie089a3f2011-08-02 22:28:14 -0400771 value = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000772
773 /* Data width */
774 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000775
Keith Hui59356ca2010-03-06 18:16:25 +0000776 /* Exclude error checking data width from page size calculations */
Keith Huie089a3f2011-08-02 22:28:14 -0400777 if (value) {
Keith Hui59356ca2010-03-06 18:16:25 +0000778 value = spd_read_byte(device,
779 SPD_ERROR_CHECKING_SDRAM_WIDTH);
780 width -= value;
781 /* ### ECC */
782 /* Clear top 2 bits to help set up NBXCFG. */
Keith Huie089a3f2011-08-02 22:28:14 -0400783 nbxecc &= 0x3f;
Keith Hui59356ca2010-03-06 18:16:25 +0000784 } else {
785 /* Without ECC, top 2 bits should be 11. */
Keith Huie089a3f2011-08-02 22:28:14 -0400786 nbxecc |= 0xc0;
Keith Hui59356ca2010-03-06 18:16:25 +0000787 }
788
Keith Huie089a3f2011-08-02 22:28:14 -0400789 /* If any installed DIMM is *not* registered, this system cannot be
790 * configured for registered SDRAM.
791 * By registered, only the address and control lines need to be, which
792 * we can tell by reading SPD byte 21, bit 1.
793 */
794 value = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
795
796 PRINT_DEBUG("DIMM is ");
797 if ((value & MODULE_REGISTERED) == 0) {
798 regsd = 0;
799 PRINT_DEBUG("not ");
800 }
801 PRINT_DEBUG("registered\n");
802
Keith Hui59356ca2010-03-06 18:16:25 +0000803 /* Calculate page size in bits. */
804 value = ((1 << col) * width);
805
806 /* Convert to KB. */
807 dra = (value >> 13);
808
809 /* Number of banks of DIMM (single or double sided). */
810 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
811
812 /* Once we have dra, col is done and can be reused.
813 * So it's reused for number of banks.
814 */
815 col = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
816
817 if (value == 1) {
818 /*
819 * Second bank of 1-bank DIMMs "doesn't have
820 * ECC" - or anything.
821 */
Keith Hui59356ca2010-03-06 18:16:25 +0000822 if (dra == 2) {
823 dra = 0x0; /* 2KB */
824 } else if (dra == 4) {
825 dra = 0x1; /* 4KB */
826 } else if (dra == 8) {
827 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000828 } else if (dra >= 16) {
829 /* Page sizes larger than supported are
830 * set to 8KB to use module partially.
831 */
832 PRINT_DEBUG("Page size forced to 8KB.\n");
833 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000834 } else {
835 dra = -1;
836 }
837 /*
838 * Sets a flag in PGPOL[BPR] if this DIMM has
839 * 4 banks per row.
840 */
841 if (col == 4)
842 bpr |= 0x40;
843 } else if (value == 2) {
844 if (dra == 2) {
845 dra = 0x0; /* 2KB */
846 } else if (dra == 4) {
847 dra = 0x05; /* 4KB */
848 } else if (dra == 8) {
849 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000850 } else if (dra >= 16) {
851 /* Ditto */
852 PRINT_DEBUG("Page size forced to 8KB.\n");
853 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000854 } else {
855 dra = -1;
856 }
857 /* Ditto */
858 if (col == 4)
859 bpr |= 0xc0;
860 } else {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000861 print_err("# of banks of DIMM unsupported!\n");
862 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000863 }
864 if (dra == -1) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000865 print_err("Page size not supported\n");
866 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000867 }
868
869 /*
870 * 440BX supports asymmetrical dual-sided DIMMs,
871 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000872 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000873 */
874 struct dimm_size sz = spd_get_dimm_size(device);
875 if ((sz.side1 < 8)) {
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000876 print_err("DIMMs smaller than 8MB per side\n"
877 "are not supported on this NB.\n");
878 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000879 }
Keith Hui59356ca2010-03-06 18:16:25 +0000880
881 /* Divide size by 8 to set up the DRB registers. */
882 drb += (sz.side1 / 8);
883
884 /*
885 * Build the DRB for the next row in MSB so it gets
886 * placed in DRB[n+1] where it belongs when written
887 * as a 16-bit word.
888 */
889 drb &= 0xff;
890 drb |= (drb + (sz.side2 / 8)) << 8;
891 } else {
892#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000893 PRINT_DEBUG("No DIMM found in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000894#endif
895
896 /* If there's no DIMM in the slot, set dra to 0x00. */
897 dra = 0x00;
Keith Hui59356ca2010-03-06 18:16:25 +0000898 /* Still have to propagate DRB over. */
899 drb &= 0xff;
900 drb |= (drb << 8);
901 }
902
903 pci_write_config16(NB, DRB + (2 * i), drb);
904#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000905 PRINT_DEBUG("DRB has been set to 0x%04x\n", drb);
Keith Hui59356ca2010-03-06 18:16:25 +0000906#endif
907
908 /* Brings the upper DRB back down to be base for
909 * DRB calculations for the next two rows.
910 */
911 drb >>= 8;
912
913 rps |= (dra & 0x0f) << (i * 4);
Keith Hui59356ca2010-03-06 18:16:25 +0000914 }
915
916 /* Set paging policy register. */
917 pci_write_config8(NB, PGPOL + 1, bpr);
Keith Hui09f5a742010-12-23 17:12:03 +0000918 PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
Keith Hui59356ca2010-03-06 18:16:25 +0000919
920 /* Set DRAM row page size register. */
921 pci_write_config16(NB, RPS, rps);
Keith Hui09f5a742010-12-23 17:12:03 +0000922 PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
Keith Hui59356ca2010-03-06 18:16:25 +0000923
924 /* ### ECC */
925 pci_write_config8(NB, NBXCFG + 3, nbxecc);
Keith Hui09f5a742010-12-23 17:12:03 +0000926 PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
Keith Hui59356ca2010-03-06 18:16:25 +0000927
Keith Huie089a3f2011-08-02 22:28:14 -0400928 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
Keith Hui59356ca2010-03-06 18:16:25 +0000929
Keith Huie089a3f2011-08-02 22:28:14 -0400930 /* i will be used to set DRAMC[4:3]. */
931 if (regsd && sd) {
932 i = 0x10; // Registered SDRAM
933 } else if (sd) {
934 i = 0x08; // SDRAM
935 } else {
936 i = 0; // EDO
937 }
938
Keith Hui59356ca2010-03-06 18:16:25 +0000939 value = pci_read_config8(NB, DRAMC) & 0xe7;
Keith Huie089a3f2011-08-02 22:28:14 -0400940 value |= i;
Keith Hui59356ca2010-03-06 18:16:25 +0000941 pci_write_config8(NB, DRAMC, value);
Keith Hui09f5a742010-12-23 17:12:03 +0000942 PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
Keith Hui59356ca2010-03-06 18:16:25 +0000943}
944
Uwe Hermann115c5b92010-10-09 17:00:18 +0000945void sdram_set_spd_registers(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000946{
Keith Hui59356ca2010-03-06 18:16:25 +0000947 /* Setup DRAM row boundary registers and other attributes. */
948 set_dram_row_attributes();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000949
Keith Huidf35cdc2010-09-20 23:41:37 +0000950 /* Setup DRAM buffer strength. */
Keith Hui59356ca2010-03-06 18:16:25 +0000951 set_dram_buffer_strength();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000952
953 /* TODO: Set PMCR? */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000954 // pci_write_config8(NB, PMCR, 0x14);
955 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000956
Keith Huidf35cdc2010-09-20 23:41:37 +0000957 /* TODO: This is for EDO memory only. */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000958 pci_write_config8(NB, DRAMT, 0x03);
Richard Smithcb8eab42006-07-24 04:25:47 +0000959}
960
Uwe Hermann115c5b92010-10-09 17:00:18 +0000961void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000962{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000963 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000964
Uwe Hermann861f9642007-05-28 14:37:06 +0000965 /* 0. Wait until power/voltages and clocks are stable (200us). */
966 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000967
Uwe Hermann861f9642007-05-28 14:37:06 +0000968 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000969 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000970 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +0000971 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000972
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000973 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000974 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000975 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +0000976 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000977
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000978 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000979 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000980 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000981 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +0000982 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000983 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000984
985 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000986 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000987 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +0000988 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000989
990 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000991 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000992 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +0000993 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000994
995 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000996 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Uwe Hermann1683cef2008-11-27 00:47:07 +0000997 // pci_write_config8(NB, PMCR, 0x10);
998 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +0000999 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001000
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001001 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001002 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001003}