blob: f191abe13e8cde0422daa861646a6685be7c6bd2 [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>
Uwe Hermann115c5b92010-10-09 17:00:18 +000027#include <device/pci_def.h>
28#include <console/console.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000029#include "i440bx.h"
Keith Hui59356ca2010-03-06 18:16:25 +000030#include "raminit.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000031
Uwe Hermann1a9c8922007-04-01 17:24:03 +000032/*-----------------------------------------------------------------------------
33Macros and definitions.
34-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +000035
Keith Huidf35cdc2010-09-20 23:41:37 +000036#define NB PCI_DEV(0, 0, 0)
37
Uwe Hermann1a9c8922007-04-01 17:24:03 +000038/* Debugging macros. */
Uwe Hermann01ce6012010-03-05 10:03:50 +000039#if CONFIG_DEBUG_RAM_SETUP
Keith Hui09f5a742010-12-23 17:12:03 +000040#define PRINT_DEBUG(x...) printk(BIOS_DEBUG, x)
Keith Huidf35cdc2010-09-20 23:41:37 +000041#define DUMPNORTH() dump_pci_device(NB)
Richard Smithcb8eab42006-07-24 04:25:47 +000042#else
Keith Hui09f5a742010-12-23 17:12:03 +000043#define PRINT_DEBUG(x...)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000044#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000045#endif
46
Uwe Hermann1a9c8922007-04-01 17:24:03 +000047/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
48#define RAM_COMMAND_NORMAL 0x0
49#define RAM_COMMAND_NOP 0x1
50#define RAM_COMMAND_PRECHARGE 0x2
51#define RAM_COMMAND_MRS 0x3
52#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000053
Uwe Hermann1a9c8922007-04-01 17:24:03 +000054/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
55 * defined in DRAMC[2:0].
56 *
57 * [0] == Normal 15.625 us -> 15.6 us
58 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
59 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
60 * [3] == Extended(2x) 31.3 us -> 31.2 us
61 * [4] == Extended(4x) 62.5 us -> 62.4 us
62 * [5] == Extended(8x) 125 us -> 124.8 us
63 */
64static const uint32_t refresh_rate_map[] = {
65 1, 5, 5, 2, 3, 4
66};
Richard Smithcb8eab42006-07-24 04:25:47 +000067
Uwe Hermann1a9c8922007-04-01 17:24:03 +000068/* Table format: register, bitmask, value. */
Keith Huidf35cdc2010-09-20 23:41:37 +000069static const u8 register_values[] = {
Uwe Hermann1a9c8922007-04-01 17:24:03 +000070 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000071 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000072 *
73 * [31:24] SDRAM Row Without ECC
74 * 0 = ECC components are populated in this row
75 * 1 = ECC components are not populated in this row
76 * [23:19] Reserved
77 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
78 * Assertion of DRAM data on host bus occurs...
79 * 0 = ...one clock after sampling snoop results (default)
80 * 1 = ...on the same clock the snoop result is being sampled
81 * (this mode is faster by one clock cycle)
82 * [17:17] ECC - EDO static Drive mode
83 * 0 = Normal mode (default)
84 * 1 = ECC signals are always driven
85 * [16:16] IDSEL_REDIRECT
86 * 0 = IDSEL1 is allocated to this bridge (default)
87 * 1 = IDSEL7 is allocated to this bridge
88 * [15:15] WSC# Handshake Disable
89 * 1 = Uni-processor mode
90 * 0 = Dual-processor mode with external IOAPIC (default)
91 * [14:14] Intel Reserved
92 * [13:12] Host/DRAM Frequency
93 * 00 = 100 MHz
94 * 01 = Reserved
95 * 10 = 66 MHz
96 * 11 = Reserved
97 * [11:11] AGP to PCI Access Enable
98 * 1 = Enable
99 * 0 = Disable
100 * [10:10] PCI Agent to Aperture Access Disable
101 * 1 = Disable
102 * 0 = Enable (default)
103 * [09:09] Aperture Access Global Enable
104 * 1 = Enable
105 * 0 = Disable
106 * [08:07] DRAM Data Integrity Mode (DDIM)
107 * 00 = Non-ECC
108 * 01 = EC-only
109 * 10 = ECC Mode
110 * 11 = ECC Mode with hardware scrubbing enabled
111 * [06:06] ECC Diagnostic Mode Enable (EDME)
112 * 1 = Enable
113 * 0 = Normal operation mode (default)
114 * [05:05] MDA Present (MDAP)
115 * Works in conjunction with the VGA_EN bit.
116 * VGA_EN MDAP
117 * 0 x All VGA cycles are sent to PCI
118 * 1 0 All VGA cycles are sent to AGP
119 * 1 1 All VGA cycles are sent to AGP, except for
120 * cycles in the MDA range.
121 * [04:04] Reserved
122 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
123 * 1 = Enable
124 * 0 = Disable
125 * [02:02] In-Order Queue Depth (IOQD)
126 * 1 = In-order queue = maximum
127 * 0 = A7# is sampled asserted (i.e., 0)
128 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000129 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000130 NBXCFG + 0, 0x00, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000131 // TODO: Bit 15 should be 0 for multiprocessor boards
Uwe Hermannbc3594732007-06-07 22:16:30 +0000132 NBXCFG + 1, 0x00, 0x80,
133 NBXCFG + 2, 0x00, 0x00,
134 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000135
136 /* DRAMC - DRAM Control Register
137 * 0x57
138 *
139 * [7:6] Reserved
140 * [5:5] Module Mode Configuration (MMCONFIG)
Keith Huidf35cdc2010-09-20 23:41:37 +0000141 * The combination of SDRAMPWR and this bit (which is set by an
142 * external strapping option) determine how CKE works.
143 * SDRAMPWR MMCONFIG
144 * 0 0 = 3 DIMM, CKE0[5:0] driven
145 * X 1 = 3 DIMM, CKE0 only
146 * 1 0 = 4 DIMM, GCKE only
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000147 * [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 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000255 * Bits[1:0] Page Size
256 * 00 2 KB
257 * 01 4 KB
258 * 10 8 KB
259 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400260 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000261 * RPS bits Corresponding DRB register
262 * [01:00] DRB[0], row 0
263 * [03:02] DRB[1], row 1
264 * [05:04] DRB[2], row 2
265 * [07:06] DRB[3], row 3
266 * [09:08] DRB[4], row 4
267 * [11:10] DRB[5], row 5
268 * [13:12] DRB[6], row 6
269 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000270 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000271 /* Power on defaults to 2KB. Will be set later. */
272 // RPS + 0, 0x00, 0x00,
273 // RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000274
275 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000276 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000277 *
278 * [15:10] Reserved
279 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
280 * 00 = Illegal
281 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000282 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000283 * [07:05] SDRAM Mode Select (SMS)
284 * 000 = Normal SDRAM Operation (default)
285 * 001 = NOP Command Enable
286 * 010 = All Banks Precharge Enable
287 * 011 = Mode Register Set Enable
288 * 100 = CBR Enable
289 * 101 = Reserved
290 * 110 = Reserved
291 * 111 = Reserved
292 * [04:04] SDRAMPWR
293 * 0 = 3 DIMM configuration
294 * 1 = 4 DIMM configuration
295 * [03:03] Leadoff Command Timing (LCT)
296 * 0 = 4 CS# Clock
297 * 1 = 3 CS# Clock
298 * [02:02] CAS# Latency (CL)
299 * 0 = 3 DCLK CAS# latency
300 * 1 = 2 DCLK CAS# latency
301 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
302 * 0 = 3 clocks between a row activate and a read or write cmd.
303 * 1 = 2 clocks between a row activate and a read or write cmd.
304 * [00:00] SDRAM RAS# Precharge (SRP)
305 * 0 = 3 clocks of RAS# precharge
306 * 1 = 2 clocks of RAS# precharge
307 */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000308#if CONFIG_SDRAMPWR_4DIMM
309 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
310#else
Keith Huidf35cdc2010-09-20 23:41:37 +0000311 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000312#endif
Mats Erik Andersson45db3662008-09-30 04:52:29 +0000313 SDRAMC + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000314
315 /* PGPOL - Paging Policy Register
316 * 0x78 - 0x79
317 *
318 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000319 * Each bit in this field corresponds to one row of the memory
320 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
321 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000322 * 0 = 2 banks
323 * 1 = 4 banks
324 * [07:05] Reserved
325 * [04:04] Intel Reserved
326 * [03:00] DRAM Idle Timer (DIT)
327 * 0000 = 0 clocks
328 * 0001 = 2 clocks
329 * 0010 = 4 clocks
330 * 0011 = 8 clocks
331 * 0100 = 10 clocks
332 * 0101 = 12 clocks
333 * 0110 = 16 clocks
334 * 0111 = 32 clocks
335 * 1xxx = Infinite (pages are not closed for idle condition)
336 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000337 PGPOL + 0, 0x00, 0x00,
338 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000339
340 /* PMCR - Power Management Control Register
341 * 0x7a
342 *
343 * [07:07] Power Down SDRAM Enable (PDSE)
344 * 1 = Enable
345 * 0 = Disable
346 * [06:06] ACPI Control Register Enable (SCRE)
347 * 1 = Enable
348 * 0 = Disable (default)
349 * [05:05] Suspend Refresh Type (SRT)
350 * 1 = Self refresh mode
351 * 0 = CBR fresh mode
352 * [04:04] Normal Refresh Enable (NREF_EN)
353 * 1 = Enable
354 * 0 = Disable
355 * [03:03] Quick Start Mode (QSTART)
356 * 1 = Quick start mode for the processor is enabled
357 * [02:02] Gated Clock Enable (GCLKEN)
358 * 1 = Enable
359 * 0 = Disable
360 * [01:01] AGP Disable (AGP_DIS)
361 * 1 = Disable
362 * 0 = Enable
363 * [00:00] CPU reset without PCIRST enable (CRst_En)
364 * 1 = Enable
365 * 0 = Disable
366 */
367 /* Enable normal refresh and the gated clock. */
368 // TODO: Only do this later?
369 // PMCR, 0x00, 0x14,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000370 PMCR, 0x00, 0x00,
Keith Hui59356ca2010-03-06 18:16:25 +0000371
372 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
373 SCRR + 1, 0x00, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000374};
375
376/*-----------------------------------------------------------------------------
377SDRAM configuration functions.
378-----------------------------------------------------------------------------*/
379
380/**
381 * Send the specified RAM command to all DIMMs.
382 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000383 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000384 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000385static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000386{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000387 int i, caslatency;
388 u8 dimm_start, dimm_end;
389 u16 reg16;
390 u32 addr, addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000391
392 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000393 reg16 = pci_read_config16(NB, SDRAMC);
394 reg16 &= 0xff1f; /* Clear bits 7-5. */
395 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
396 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000397
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000398 /*
399 * RAM_COMMAND_NORMAL affects only the memory controller and
400 * doesn't need to be "sent" to the DIMMs.
401 */
402 if (command == RAM_COMMAND_NORMAL)
403 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000404
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000405 /* Send the RAM command to each row of memory. */
406 dimm_start = 0;
407 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000408 addr_offset = 0;
409 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000410 if (command == RAM_COMMAND_MRS) {
411 /*
412 * MAA[12:11,9:0] must be inverted when sent to DIMM
413 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
414 */
415 if ((i >= 0 && i <= 3) && caslatency == 3)
416 addr_offset = 0x1d0;
417 if ((i >= 4 && i <= 7) && caslatency == 3)
418 addr_offset = 0x1e28;
419 if ((i >= 0 && i <= 3) && caslatency == 2)
420 addr_offset = 0x150;
421 if ((i >= 4 && i <= 7) && caslatency == 2)
422 addr_offset = 0x1ea8;
423 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000424
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000425 dimm_end = pci_read_config8(NB, DRB + i);
426
427 addr = (dimm_start * 8 * 1024 * 1024) + addr_offset;
428 if (dimm_end > dimm_start) {
429#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000430 PRINT_DEBUG(" Sending RAM command 0x%04x to 0x%08x\n",
431 reg16, addr);
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000432#endif
433
434 read32(addr);
435 }
436
437 /* Set the start of the next DIMM. */
438 dimm_start = dimm_end;
439 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000440}
441
Keith Hui59356ca2010-03-06 18:16:25 +0000442static void set_dram_buffer_strength(void)
443{
Keith Huib48ba662010-03-17 02:15:07 +0000444 /* To give some breathing room for romcc,
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000445 * mbsc0 doubles as drb
Keith Huib48ba662010-03-17 02:15:07 +0000446 * mbsc1 doubles as drb1
447 * mbfs0 doubles as i and reg
Keith Hui59356ca2010-03-06 18:16:25 +0000448 */
Keith Huib48ba662010-03-17 02:15:07 +0000449 uint8_t mbsc0,mbsc1,mbsc3,mbsc4,mbfs0,mbfs2,fsb;
Keith Hui59356ca2010-03-06 18:16:25 +0000450
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000451 /* Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000452 * This determines how to program MBFS and MBSC.
453 */
454 uint8_t dimm03 = 0;
455 uint8_t dimm47 = 0;
456
457 mbsc0 = 0;
458 for (mbfs0 = DRB0; mbfs0 <= DRB7; mbfs0++) {
459 mbsc1 = pci_read_config8(NB, mbfs0);
460 if (mbsc0 != mbsc1) {
461 if (mbfs0 <= DRB3) {
462 dimm03++;
463 } else {
464 dimm47++;
465 }
466 mbsc0 = mbsc1;
467 }
468 }
469
Keith Huidf35cdc2010-09-20 23:41:37 +0000470 /* Algorithm bitmap for programming MBSC[39:0] and MBFS[23:0].
Keith Huib48ba662010-03-17 02:15:07 +0000471 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000472 * The 440BX datasheet says buffer frequency is independent from bus
473 * frequency and mismatch both ways are possible. This is how it is
474 * programmed in the ASUS P2B-LS mainboard.
Keith Huib48ba662010-03-17 02:15:07 +0000475 *
476 * There are four main conditions to check when programming DRAM buffer
477 * frequency and strength:
478 *
479 * a: >2 rows populated across DIMM0,1
480 * b: >2 rows populated across DIMM2,3
481 * c: >4 rows populated across all DIMM slots
482 * and either one of:
483 * 1: NBXCFG[13] strapped as 100MHz, or
484 * 6: NBXCFG[13] strapped as 66MHz
485 *
486 * CKE0/FENA ----------------------------------------------------------+
487 * CKE1/GCKE -------------------[ MBFS ]------------------------+|
488 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
489 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
490 * DQMB5/CASB5# ---------------------------------------------------+||||
491 * DQMA1/CASA1# --------------------------------------------------+|||||
492 * DQMA5/CASA5# -------------------------------------------------+||||||
493 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
494 * CSA6#/CKE2# -------------------------------------------+|||||||||||||
495 * CSB6#/CKE4# ------------------------------------------+||||||||||||||
496 * CSA7#/CKE3# -----------------------------------------+|||||||||||||||
497 * CSB7#/CKE5# ----------------------------------------+||||||||||||||||
498 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
499 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
500 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
501 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
502 * Reserved ------------------------------------+|||||||||||||||||||||||
503 * ||||||||||||||||||||||||
504 * 3 32 21 10 0 * 2 21 10 0
505 * 9876543210987654321098765432109876543210 * 321098765432109876543210
506 * a 10------------------------1010---------- * -1---------------11----- a
507 *!a 11------------------------1111---------- * -0---------------00----- !a
508 * b --10--------------------------1010------ * --1----------------11--- b
509 *!b --11--------------------------1111------ * --0----------------00--- !b
510 * c ----------------------------------1100-- * ----------------------1- c
511 *!c ----------------------------------1011-- * ----------------------0- !c
512 * 1 ----1010101000000000000000------------00 * ---11111111111111----1-0 1
513 * 6 ----000000000000000000000010101010----00 * ---1111111111111100000-0 6
514 * | | | | | | | | | | ||||||| | | | | | |
515 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
516 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
517 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
518 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
519 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
520 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
521 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
522 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# [ 0=1x;1=2x ]
523 * | | | | | | | | | +--------------------- CSA6#/CKE2#
524 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4#
525 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3#
526 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5#
527 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (2x)
528 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (2x)
529 * | | | +--------------------------------- MD[63:0] #1 (2x)
530 * | | +----------------------------------- MD[63:0] #2 (2x)
531 * | +------------------------------------- MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
532 * +--------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
533 * MBSC[47:40] and MBFS[23] are reserved.
534 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000535 * This algorithm is checked against the ASUS P2B-LS (which has
536 * 4 DIMM slots) factory BIOS.
Keith Huib48ba662010-03-17 02:15:07 +0000537 * Therefore it assumes a board with 4 slots, and will need testing
538 * on boards with 3 DIMM slots.
539 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000540
Keith Huib48ba662010-03-17 02:15:07 +0000541 mbsc0 = 0x80;
542 mbsc1 = 0x2a;
543 mbfs2 = 0x1f;
544 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
545 fsb = 66;
546 mbsc3 = 0x00;
547 mbsc4 = 0x00;
548 mbfs0 = 0x80;
549 } else {
550 fsb = 100;
551 mbsc3 = 0xa0;
552 mbsc4 = 0x0a;
553 mbfs0 = 0x84;
554 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000555
556 if (dimm03 > 2) {
557 mbsc4 = mbsc4 | 0x80;
Keith Huib48ba662010-03-17 02:15:07 +0000558 mbsc1 = mbsc1 | 0x28;
559 mbfs2 = mbfs2 | 0x40;
560 mbfs0 = mbfs0 | 0x60;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000561 } else {
562 mbsc4 = mbsc4 | 0xc0;
Keith Huib48ba662010-03-17 02:15:07 +0000563 if (fsb == 100) {
564 mbsc1 = mbsc1 | 0x3c;
565 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000566 }
567 if (dimm47 > 2) {
568 mbsc4 = mbsc4 | 0x20;
569 mbsc1 = mbsc1 | 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000570 mbsc0 = mbsc0 | 0x80;
571 mbfs2 = mbfs2 | 0x20;
572 mbfs0 = mbfs0 | 0x18;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000573 } else {
Keith Huib48ba662010-03-17 02:15:07 +0000574 mbsc4 = mbsc4 | 0x30;
575 if (fsb == 100) {
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000576 mbsc1 = mbsc1 | 0x03;
Keith Huib48ba662010-03-17 02:15:07 +0000577 mbsc0 = mbsc0 | 0xc0;
578 }
579 }
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000580 if ((dimm03 + dimm47) > 4) {
Keith Huib48ba662010-03-17 02:15:07 +0000581 mbsc0 = mbsc0 | 0x30;
582 mbfs0 = mbfs0 | 0x02;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000583 } else {
584 mbsc0 = mbsc0 | 0x2c;
Keith Huib48ba662010-03-17 02:15:07 +0000585 }
586
587 pci_write_config8(NB, MBSC + 0, mbsc0);
588 pci_write_config8(NB, MBSC + 1, mbsc1);
589 pci_write_config8(NB, MBSC + 2, 0x00);
590 pci_write_config8(NB, MBSC + 3, mbsc3);
591 pci_write_config8(NB, MBSC + 4, mbsc4);
592 pci_write_config8(NB, MBFS + 0, mbfs0);
593 pci_write_config8(NB, MBFS + 1, 0xff);
594 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000595}
596
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000597/*-----------------------------------------------------------------------------
598DIMM-independant configuration functions.
599-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000600
Uwe Hermann1683cef2008-11-27 00:47:07 +0000601static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000602{
603 int i, value;
604 uint8_t reg;
605
Uwe Hermann1683cef2008-11-27 00:47:07 +0000606 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000607
608 for (i = 0; i < DIMM_SOCKETS; i++) {
Uwe Hermannd773fd32010-11-20 20:23:08 +0000609 value = spd_read_byte(DIMM0 + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000610 if (value < 0)
611 continue;
612 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
613
Keith Hui09f5a742010-12-23 17:12:03 +0000614 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000615 }
616
Uwe Hermann1683cef2008-11-27 00:47:07 +0000617 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000618}
619
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000620/*-----------------------------------------------------------------------------
621Public interface.
622-----------------------------------------------------------------------------*/
623
Uwe Hermann115c5b92010-10-09 17:00:18 +0000624void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000625{
626 int i, max;
Uwe Hermannbc3594732007-06-07 22:16:30 +0000627 uint8_t reg;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000628
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000629 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000630 DUMPNORTH();
631
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000632 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000633
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000634 /* Set registers as specified in the register_values[] array. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000635 for (i = 0; i < max; i += 3) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000636 reg = pci_read_config8(NB, register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000637 reg &= register_values[i + 1];
638 reg |= register_values[i + 2] & ~(register_values[i + 1]);
Uwe Hermann1683cef2008-11-27 00:47:07 +0000639 pci_write_config8(NB, register_values[i], reg);
Keith Hui59356ca2010-03-06 18:16:25 +0000640#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000641 PRINT_DEBUG(" Set register 0x%02x to 0x%02x\n",
642 register_values[i], reg);
Keith Hui59356ca2010-03-06 18:16:25 +0000643#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000644 }
645}
646
Keith Hui59356ca2010-03-06 18:16:25 +0000647struct dimm_size {
Keith Hui09f5a742010-12-23 17:12:03 +0000648 u32 side1;
649 u32 side2;
Keith Hui59356ca2010-03-06 18:16:25 +0000650};
651
652static struct dimm_size spd_get_dimm_size(unsigned int device)
653{
654 struct dimm_size sz;
655 int i, module_density, dimm_banks;
656 sz.side1 = 0;
657 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
658 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
659
660 /* Find the size of side1. */
661 /* Find the larger value. The larger value is always side1. */
662 for (i = 512; i >= 0; i >>= 1) {
663 if ((module_density & i) == i) {
664 sz.side1 = i;
665 break;
666 }
667 }
668
669 /* Set to 0 in case it's single sided. */
670 sz.side2 = 0;
671
672 /* Test if it's a dual-sided DIMM. */
673 if (dimm_banks > 1) {
674 /* Test if there's a second value. If so it's asymmetrical. */
675 if (module_density != i) {
676 /*
677 * Find second value, picking up where we left off.
678 * i >>= 1 done initially to make sure we don't get
679 * the same value again.
680 */
681 for (i >>= 1; i >= 0; i >>= 1) {
682 if (module_density == (sz.side1 | i)) {
683 sz.side2 = i;
684 break;
685 }
686 }
687 /* If not, it's symmetrical. */
688 } else {
689 sz.side2 = sz.side1;
690 }
691 }
692
693 /*
694 * SPD byte 31 is the memory size divided by 4 so we
695 * need to muliply by 4 to get the total size.
696 */
697 sz.side1 *= 4;
698 sz.side2 *= 4;
699
Anders Jenbo771b0e42010-04-27 08:45:30 +0000700 /* It is possible to partially use larger then supported
701 * modules by setting them to a supported size.
702 */
703 if(sz.side1 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000704 PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
705 sz.side1);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000706 sz.side1 = 128;
707
708 if(sz.side2 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000709 PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
710 sz.side2);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000711 sz.side2 = 128;
712 }
713 }
714
Keith Hui59356ca2010-03-06 18:16:25 +0000715 return sz;
716}
717/*
718 * Sets DRAM attributes one DIMM at a time, based on SPD data.
719 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
720 */
721static void set_dram_row_attributes(void)
722{
Keith Huie089a3f2011-08-02 22:28:14 -0400723 int i, dra, drb, col, width, value, rps;
Keith Hui59356ca2010-03-06 18:16:25 +0000724 u8 bpr; /* Top 8 bits of PGPOL */
Keith Huie089a3f2011-08-02 22:28:14 -0400725 u8 nbxecc = 0; /* NBXCFG[31:24] */
726 u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
Keith Hui59356ca2010-03-06 18:16:25 +0000727
Keith Huie089a3f2011-08-02 22:28:14 -0400728 edo = 0;
729 sd = 0;
730 regsd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000731 rps = 0;
732 drb = 0;
733 bpr = 0;
Keith Hui59356ca2010-03-06 18:16:25 +0000734
735 for (i = 0; i < DIMM_SOCKETS; i++) {
736 unsigned int device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000737 device = DIMM0 + i;
Keith Hui59356ca2010-03-06 18:16:25 +0000738 bpr >>= 2;
Keith Huie089a3f2011-08-02 22:28:14 -0400739 nbxecc >>= 2;
Keith Hui59356ca2010-03-06 18:16:25 +0000740
741 /* First check if a DIMM is actually present. */
742 value = spd_read_byte(device, SPD_MEMORY_TYPE);
743 /* This is 440BX! We do EDO too! */
744 if (value == SPD_MEMORY_TYPE_EDO
745 || value == SPD_MEMORY_TYPE_SDRAM) {
746
Keith Hui59356ca2010-03-06 18:16:25 +0000747 if (value == SPD_MEMORY_TYPE_EDO) {
Keith Huie089a3f2011-08-02 22:28:14 -0400748 edo = 1;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000749 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
Keith Huie089a3f2011-08-02 22:28:14 -0400750 sd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000751 }
Keith Hui09f5a742010-12-23 17:12:03 +0000752 PRINT_DEBUG("Found DIMM in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000753
Keith Huie089a3f2011-08-02 22:28:14 -0400754 if (edo && sd) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800755 printk(BIOS_ERR, "Mixing EDO/SDRAM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000756 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000757 }
758
759 /* "DRA" is our RPS for the two rows on this DIMM. */
760 dra = 0;
761
762 /* Columns */
763 col = spd_read_byte(device, SPD_NUM_COLUMNS);
764
765 /*
766 * Is this an ECC DIMM? Actually will be a 2 if so.
767 * TODO: Other register than NBXCFG also needs this
768 * ECC information.
769 */
Keith Huie089a3f2011-08-02 22:28:14 -0400770 value = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000771
772 /* Data width */
773 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000774
Keith Hui59356ca2010-03-06 18:16:25 +0000775 /* Exclude error checking data width from page size calculations */
Keith Huie089a3f2011-08-02 22:28:14 -0400776 if (value) {
Keith Hui59356ca2010-03-06 18:16:25 +0000777 value = spd_read_byte(device,
778 SPD_ERROR_CHECKING_SDRAM_WIDTH);
779 width -= value;
780 /* ### ECC */
781 /* Clear top 2 bits to help set up NBXCFG. */
Keith Huie089a3f2011-08-02 22:28:14 -0400782 nbxecc &= 0x3f;
Keith Hui59356ca2010-03-06 18:16:25 +0000783 } else {
784 /* Without ECC, top 2 bits should be 11. */
Keith Huie089a3f2011-08-02 22:28:14 -0400785 nbxecc |= 0xc0;
Keith Hui59356ca2010-03-06 18:16:25 +0000786 }
787
Keith Huie089a3f2011-08-02 22:28:14 -0400788 /* If any installed DIMM is *not* registered, this system cannot be
789 * configured for registered SDRAM.
790 * By registered, only the address and control lines need to be, which
791 * we can tell by reading SPD byte 21, bit 1.
792 */
793 value = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
794
795 PRINT_DEBUG("DIMM is ");
796 if ((value & MODULE_REGISTERED) == 0) {
797 regsd = 0;
798 PRINT_DEBUG("not ");
799 }
800 PRINT_DEBUG("registered\n");
801
Keith Hui59356ca2010-03-06 18:16:25 +0000802 /* Calculate page size in bits. */
803 value = ((1 << col) * width);
804
805 /* Convert to KB. */
806 dra = (value >> 13);
807
808 /* Number of banks of DIMM (single or double sided). */
809 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
810
811 /* Once we have dra, col is done and can be reused.
812 * So it's reused for number of banks.
813 */
814 col = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
815
816 if (value == 1) {
817 /*
818 * Second bank of 1-bank DIMMs "doesn't have
819 * ECC" - or anything.
820 */
Keith Hui59356ca2010-03-06 18:16:25 +0000821 if (dra == 2) {
822 dra = 0x0; /* 2KB */
823 } else if (dra == 4) {
824 dra = 0x1; /* 4KB */
825 } else if (dra == 8) {
826 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000827 } else if (dra >= 16) {
828 /* Page sizes larger than supported are
829 * set to 8KB to use module partially.
830 */
831 PRINT_DEBUG("Page size forced to 8KB.\n");
832 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000833 } else {
834 dra = -1;
835 }
836 /*
837 * Sets a flag in PGPOL[BPR] if this DIMM has
838 * 4 banks per row.
839 */
840 if (col == 4)
841 bpr |= 0x40;
842 } else if (value == 2) {
843 if (dra == 2) {
844 dra = 0x0; /* 2KB */
845 } else if (dra == 4) {
846 dra = 0x05; /* 4KB */
847 } else if (dra == 8) {
848 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000849 } else if (dra >= 16) {
850 /* Ditto */
851 PRINT_DEBUG("Page size forced to 8KB.\n");
852 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000853 } else {
854 dra = -1;
855 }
856 /* Ditto */
857 if (col == 4)
858 bpr |= 0xc0;
859 } else {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800860 printk(BIOS_ERR, "# of banks of DIMM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000861 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000862 }
863 if (dra == -1) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800864 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000865 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000866 }
867
868 /*
869 * 440BX supports asymmetrical dual-sided DIMMs,
870 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000871 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000872 */
873 struct dimm_size sz = spd_get_dimm_size(device);
874 if ((sz.side1 < 8)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800875 printk(BIOS_ERR, "DIMMs smaller than 8MB per side\n"
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000876 "are not supported on this NB.\n");
877 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000878 }
Keith Hui59356ca2010-03-06 18:16:25 +0000879
880 /* Divide size by 8 to set up the DRB registers. */
881 drb += (sz.side1 / 8);
882
883 /*
884 * Build the DRB for the next row in MSB so it gets
885 * placed in DRB[n+1] where it belongs when written
886 * as a 16-bit word.
887 */
888 drb &= 0xff;
889 drb |= (drb + (sz.side2 / 8)) << 8;
890 } else {
891#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000892 PRINT_DEBUG("No DIMM found in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000893#endif
894
895 /* If there's no DIMM in the slot, set dra to 0x00. */
896 dra = 0x00;
Keith Hui59356ca2010-03-06 18:16:25 +0000897 /* Still have to propagate DRB over. */
898 drb &= 0xff;
899 drb |= (drb << 8);
900 }
901
902 pci_write_config16(NB, DRB + (2 * i), drb);
903#if 0
Stefan Reinauerfc01e5e2010-12-27 14:31:05 +0000904 PRINT_DEBUG("DRB has been set to 0x%04x\n", drb);
Keith Hui59356ca2010-03-06 18:16:25 +0000905#endif
906
907 /* Brings the upper DRB back down to be base for
908 * DRB calculations for the next two rows.
909 */
910 drb >>= 8;
911
912 rps |= (dra & 0x0f) << (i * 4);
Keith Hui59356ca2010-03-06 18:16:25 +0000913 }
914
915 /* Set paging policy register. */
916 pci_write_config8(NB, PGPOL + 1, bpr);
Keith Hui09f5a742010-12-23 17:12:03 +0000917 PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
Keith Hui59356ca2010-03-06 18:16:25 +0000918
919 /* Set DRAM row page size register. */
920 pci_write_config16(NB, RPS, rps);
Keith Hui09f5a742010-12-23 17:12:03 +0000921 PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
Keith Hui59356ca2010-03-06 18:16:25 +0000922
923 /* ### ECC */
924 pci_write_config8(NB, NBXCFG + 3, nbxecc);
Keith Hui09f5a742010-12-23 17:12:03 +0000925 PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
Keith Hui59356ca2010-03-06 18:16:25 +0000926
Keith Huie089a3f2011-08-02 22:28:14 -0400927 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
Keith Hui59356ca2010-03-06 18:16:25 +0000928
Keith Huie089a3f2011-08-02 22:28:14 -0400929 /* i will be used to set DRAMC[4:3]. */
930 if (regsd && sd) {
931 i = 0x10; // Registered SDRAM
932 } else if (sd) {
933 i = 0x08; // SDRAM
934 } else {
935 i = 0; // EDO
936 }
937
Keith Hui59356ca2010-03-06 18:16:25 +0000938 value = pci_read_config8(NB, DRAMC) & 0xe7;
Keith Huie089a3f2011-08-02 22:28:14 -0400939 value |= i;
Keith Hui59356ca2010-03-06 18:16:25 +0000940 pci_write_config8(NB, DRAMC, value);
Keith Hui09f5a742010-12-23 17:12:03 +0000941 PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
Keith Hui59356ca2010-03-06 18:16:25 +0000942}
943
Uwe Hermann115c5b92010-10-09 17:00:18 +0000944void 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
Keith Huidf35cdc2010-09-20 23:41:37 +0000949 /* Setup DRAM buffer strength. */
Keith Hui59356ca2010-03-06 18:16:25 +0000950 set_dram_buffer_strength();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000951
952 /* TODO: Set PMCR? */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000953 // pci_write_config8(NB, PMCR, 0x14);
954 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000955
Keith Huidf35cdc2010-09-20 23:41:37 +0000956 /* TODO: This is for EDO memory only. */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000957 pci_write_config8(NB, DRAMT, 0x03);
Richard Smithcb8eab42006-07-24 04:25:47 +0000958}
959
Uwe Hermann115c5b92010-10-09 17:00:18 +0000960void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000961{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000962 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000963
Uwe Hermann861f9642007-05-28 14:37:06 +0000964 /* 0. Wait until power/voltages and clocks are stable (200us). */
965 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000966
Uwe Hermann861f9642007-05-28 14:37:06 +0000967 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000968 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000969 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +0000970 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000971
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000972 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000973 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000974 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +0000975 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000976
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000977 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000978 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000979 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000980 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +0000981 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000982 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000983
984 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000985 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000986 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +0000987 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000988
989 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000990 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000991 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +0000992 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000993
994 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000995 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Uwe Hermann1683cef2008-11-27 00:47:07 +0000996 // pci_write_config8(NB, PMCR, 0x10);
997 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +0000998 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000999
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001000 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001001 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001002}