blob: 28b22ec67580ac0df76a5993cede12c5e35b6259 [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 Hui9aa45e62017-07-20 21:00:56 -04005 * Copyright (C) 2010,2017 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.
Richard Smithcb8eab42006-07-24 04:25:47 +000016 */
17
Uwe Hermann1a9c8922007-04-01 17:24:03 +000018#include <spd.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000019#include <delay.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000020#include <stdint.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020021#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020022#include <device/pci_ops.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000023#include <device/pci_def.h>
24#include <console/console.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
Keith Hui9aa45e62017-07-20 21:00:56 -040028/*
29 * Macros and definitions
30 */
Keith Huidf35cdc2010-09-20 23:41:37 +000031
Uwe Hermann1a9c8922007-04-01 17:24:03 +000032/* Debugging macros. */
Julius Wernercd49cce2019-03-05 16:53:33 -080033#if CONFIG(DEBUG_RAM_SETUP)
Keith Hui09f5a742010-12-23 17:12:03 +000034#define PRINT_DEBUG(x...) printk(BIOS_DEBUG, x)
Keith Huidf35cdc2010-09-20 23:41:37 +000035#define DUMPNORTH() dump_pci_device(NB)
Richard Smithcb8eab42006-07-24 04:25:47 +000036#else
Keith Hui09f5a742010-12-23 17:12:03 +000037#define PRINT_DEBUG(x...)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000038#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000039#endif
40
Uwe Hermann1a9c8922007-04-01 17:24:03 +000041/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
42#define RAM_COMMAND_NORMAL 0x0
43#define RAM_COMMAND_NOP 0x1
44#define RAM_COMMAND_PRECHARGE 0x2
45#define RAM_COMMAND_MRS 0x3
46#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000047
Uwe Hermann1a9c8922007-04-01 17:24:03 +000048/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
49 * defined in DRAMC[2:0].
50 *
51 * [0] == Normal 15.625 us -> 15.6 us
52 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
53 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
54 * [3] == Extended(2x) 31.3 us -> 31.2 us
55 * [4] == Extended(4x) 62.5 us -> 62.4 us
56 * [5] == Extended(8x) 125 us -> 124.8 us
57 */
58static const uint32_t refresh_rate_map[] = {
59 1, 5, 5, 2, 3, 4
60};
Richard Smithcb8eab42006-07-24 04:25:47 +000061
Uwe Hermann1a9c8922007-04-01 17:24:03 +000062/* Table format: register, bitmask, value. */
Keith Huidf35cdc2010-09-20 23:41:37 +000063static const u8 register_values[] = {
Uwe Hermann1a9c8922007-04-01 17:24:03 +000064 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000065 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000066 *
67 * [31:24] SDRAM Row Without ECC
68 * 0 = ECC components are populated in this row
69 * 1 = ECC components are not populated in this row
70 * [23:19] Reserved
71 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
72 * Assertion of DRAM data on host bus occurs...
73 * 0 = ...one clock after sampling snoop results (default)
74 * 1 = ...on the same clock the snoop result is being sampled
75 * (this mode is faster by one clock cycle)
76 * [17:17] ECC - EDO static Drive mode
77 * 0 = Normal mode (default)
78 * 1 = ECC signals are always driven
79 * [16:16] IDSEL_REDIRECT
80 * 0 = IDSEL1 is allocated to this bridge (default)
81 * 1 = IDSEL7 is allocated to this bridge
82 * [15:15] WSC# Handshake Disable
83 * 1 = Uni-processor mode
84 * 0 = Dual-processor mode with external IOAPIC (default)
85 * [14:14] Intel Reserved
86 * [13:12] Host/DRAM Frequency
87 * 00 = 100 MHz
88 * 01 = Reserved
89 * 10 = 66 MHz
90 * 11 = Reserved
91 * [11:11] AGP to PCI Access Enable
92 * 1 = Enable
93 * 0 = Disable
94 * [10:10] PCI Agent to Aperture Access Disable
95 * 1 = Disable
96 * 0 = Enable (default)
97 * [09:09] Aperture Access Global Enable
98 * 1 = Enable
99 * 0 = Disable
100 * [08:07] DRAM Data Integrity Mode (DDIM)
101 * 00 = Non-ECC
102 * 01 = EC-only
103 * 10 = ECC Mode
104 * 11 = ECC Mode with hardware scrubbing enabled
105 * [06:06] ECC Diagnostic Mode Enable (EDME)
106 * 1 = Enable
107 * 0 = Normal operation mode (default)
108 * [05:05] MDA Present (MDAP)
109 * Works in conjunction with the VGA_EN bit.
110 * VGA_EN MDAP
111 * 0 x All VGA cycles are sent to PCI
112 * 1 0 All VGA cycles are sent to AGP
113 * 1 1 All VGA cycles are sent to AGP, except for
114 * cycles in the MDA range.
115 * [04:04] Reserved
116 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
117 * 1 = Enable
118 * 0 = Disable
119 * [02:02] In-Order Queue Depth (IOQD)
120 * 1 = In-order queue = maximum
121 * 0 = A7# is sampled asserted (i.e., 0)
122 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000123 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000124 NBXCFG + 0, 0x00, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000125 // TODO: Bit 15 should be 0 for multiprocessor boards
Uwe Hermannbc3594732007-06-07 22:16:30 +0000126 NBXCFG + 1, 0x00, 0x80,
127 NBXCFG + 2, 0x00, 0x00,
128 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000129
130 /* DRAMC - DRAM Control Register
131 * 0x57
132 *
133 * [7:6] Reserved
134 * [5:5] Module Mode Configuration (MMCONFIG)
Keith Huia8380fc2017-12-04 00:05:56 -0500135 * The combination of SDRAMPWR and this bit (set by an
Keith Huidf35cdc2010-09-20 23:41:37 +0000136 * external strapping option) determine how CKE works.
137 * SDRAMPWR MMCONFIG
Keith Huia8380fc2017-12-04 00:05:56 -0500138 * 0 0 = 3 DIMM, CKE[5:0] driven
139 * X 1 = 3 DIMM, CKE0 only
140 * 1 0 = 4 DIMM, GCKE only
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000141 * [4:3] DRAM Type (DT)
142 * 00 = EDO
143 * 01 = SDRAM
144 * 10 = Registered SDRAM
145 * 11 = Reserved
146 * Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
147 * [2:0] DRAM Refresh Rate (DRR)
148 * 000 = Refresh disabled
149 * 001 = 15.6 us
150 * 010 = 31.2 us
151 * 011 = 62.4 us
152 * 100 = 124.8 us
153 * 101 = 249.6 us
154 * 110 = Reserved
155 * 111 = Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000156 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000157 /* Choose SDRAM (not registered), and disable refresh for now. */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000158 DRAMC, 0x00, 0x08,
Richard Smithcb8eab42006-07-24 04:25:47 +0000159
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000160 /*
161 * PAM[6:0] - Programmable Attribute Map Registers
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000162 * 0x59 - 0x5f
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000163 *
164 * 0x59 [3:0] Reserved
165 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
166 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
167 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
168 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
169 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
170 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
171 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
172 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
173 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
Martin Roth128c1042016-11-18 09:29:03 -0700174 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS extension
175 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS extension
176 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS extension
177 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS extension
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000178 *
179 * Bit assignment:
180 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
181 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
182 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
183 * 11 = Read/Write (all access goes to DRAM)
184 */
Keith Hui59356ca2010-03-06 18:16:25 +0000185
186 /*
187 * Map all legacy regions to RAM (read/write). This is required if
188 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
189 * registers are not set here appropriately, the RAM in that region
190 * will not be accessible, thus a RAM check of it will also fail.
Keith Hui59356ca2010-03-06 18:16:25 +0000191 */
192 PAM0, 0x00, 0x30,
193 PAM1, 0x00, 0x33,
194 PAM2, 0x00, 0x33,
195 PAM3, 0x00, 0x33,
196 PAM4, 0x00, 0x33,
197 PAM5, 0x00, 0x33,
198 PAM6, 0x00, 0x33,
Richard Smithcb8eab42006-07-24 04:25:47 +0000199
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000200 /* DRB[0:7] - DRAM Row Boundary Registers
201 * 0x60 - 0x67
202 *
203 * An array of 8 byte registers, which hold the ending memory address
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000204 * assigned to each pair of DIMMs, in 8MB granularity.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000205 *
206 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
207 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
208 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
209 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
210 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
211 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
212 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
213 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
214 */
Keith Huia8380fc2017-12-04 00:05:56 -0500215 /* DRBs will be set later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000216 DRB0, 0x00, 0x00,
217 DRB1, 0x00, 0x00,
218 DRB2, 0x00, 0x00,
219 DRB3, 0x00, 0x00,
220 DRB4, 0x00, 0x00,
221 DRB5, 0x00, 0x00,
222 DRB6, 0x00, 0x00,
223 DRB7, 0x00, 0x00,
224
225 /* FDHC - Fixed DRAM Hole Control Register
226 * 0x68
227 *
228 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
229 *
230 * [7:6] Hole Enable (HEN)
231 * 00 = None
232 * 01 = 512 KB - 640 KB (128 KB)
233 * 10 = 15 MB - 16 MB (1 MB)
234 * 11 = Reserved
235 * [5:0] Reserved
236 */
237 /* No memory holes. */
238 FDHC, 0x00, 0x00,
239
240 /* RPS - SDRAM Row Page Size Register
241 * 0x74 - 0x75
242 *
243 * Sets the row page size for SDRAM. For EDO memory, the page
244 * size is fixed at 2 KB.
245 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000246 * Bits[1:0] Page Size
247 * 00 2 KB
248 * 01 4 KB
249 * 10 8 KB
250 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400251 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000252 * RPS bits Corresponding DRB register
253 * [01:00] DRB[0], row 0
254 * [03:02] DRB[1], row 1
255 * [05:04] DRB[2], row 2
256 * [07:06] DRB[3], row 3
257 * [09:08] DRB[4], row 4
258 * [11:10] DRB[5], row 5
259 * [13:12] DRB[6], row 6
260 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000261 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000262 /* Power on defaults to 2KB. Will be set later. */
263 // RPS + 0, 0x00, 0x00,
264 // RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000265
266 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000267 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000268 *
269 * [15:10] Reserved
270 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
271 * 00 = Illegal
272 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000273 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000274 * [07:05] SDRAM Mode Select (SMS)
275 * 000 = Normal SDRAM Operation (default)
276 * 001 = NOP Command Enable
277 * 010 = All Banks Precharge Enable
278 * 011 = Mode Register Set Enable
279 * 100 = CBR Enable
280 * 101 = Reserved
281 * 110 = Reserved
282 * 111 = Reserved
283 * [04:04] SDRAMPWR
284 * 0 = 3 DIMM configuration
285 * 1 = 4 DIMM configuration
286 * [03:03] Leadoff Command Timing (LCT)
287 * 0 = 4 CS# Clock
288 * 1 = 3 CS# Clock
289 * [02:02] CAS# Latency (CL)
290 * 0 = 3 DCLK CAS# latency
291 * 1 = 2 DCLK CAS# latency
292 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
293 * 0 = 3 clocks between a row activate and a read or write cmd.
294 * 1 = 2 clocks between a row activate and a read or write cmd.
295 * [00:00] SDRAM RAS# Precharge (SRP)
296 * 0 = 3 clocks of RAS# precharge
297 * 1 = 2 clocks of RAS# precharge
298 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800299#if CONFIG(SDRAMPWR_4DIMM)
Keith Hui9c1e1f02010-03-13 20:16:48 +0000300 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
301#else
Keith Huidf35cdc2010-09-20 23:41:37 +0000302 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000303#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000304
305 /* PGPOL - Paging Policy Register
306 * 0x78 - 0x79
307 *
308 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000309 * Each bit in this field corresponds to one row of the memory
310 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
311 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000312 * 0 = 2 banks
313 * 1 = 4 banks
314 * [07:05] Reserved
315 * [04:04] Intel Reserved
316 * [03:00] DRAM Idle Timer (DIT)
317 * 0000 = 0 clocks
318 * 0001 = 2 clocks
319 * 0010 = 4 clocks
320 * 0011 = 8 clocks
321 * 0100 = 10 clocks
322 * 0101 = 12 clocks
323 * 0110 = 16 clocks
324 * 0111 = 32 clocks
325 * 1xxx = Infinite (pages are not closed for idle condition)
326 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000327 PGPOL + 0, 0x00, 0x00,
328 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000329
330 /* PMCR - Power Management Control Register
331 * 0x7a
332 *
333 * [07:07] Power Down SDRAM Enable (PDSE)
334 * 1 = Enable
335 * 0 = Disable
336 * [06:06] ACPI Control Register Enable (SCRE)
337 * 1 = Enable
338 * 0 = Disable (default)
339 * [05:05] Suspend Refresh Type (SRT)
340 * 1 = Self refresh mode
341 * 0 = CBR fresh mode
342 * [04:04] Normal Refresh Enable (NREF_EN)
343 * 1 = Enable
344 * 0 = Disable
345 * [03:03] Quick Start Mode (QSTART)
346 * 1 = Quick start mode for the processor is enabled
347 * [02:02] Gated Clock Enable (GCLKEN)
348 * 1 = Enable
349 * 0 = Disable
350 * [01:01] AGP Disable (AGP_DIS)
351 * 1 = Disable
352 * 0 = Enable
353 * [00:00] CPU reset without PCIRST enable (CRst_En)
354 * 1 = Enable
355 * 0 = Disable
356 */
357 /* Enable normal refresh and the gated clock. */
358 // TODO: Only do this later?
359 // PMCR, 0x00, 0x14,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000360 PMCR, 0x00, 0x00,
Keith Hui59356ca2010-03-06 18:16:25 +0000361
362 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
363 SCRR + 1, 0x00, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000364};
365
366/*-----------------------------------------------------------------------------
367SDRAM configuration functions.
368-----------------------------------------------------------------------------*/
369
370/**
371 * Send the specified RAM command to all DIMMs.
372 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000373 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000374 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000375static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000376{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000377 int i, caslatency;
378 u8 dimm_start, dimm_end;
379 u16 reg16;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800380 void *addr;
381 u32 addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000382
383 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000384 reg16 = pci_read_config16(NB, SDRAMC);
385 reg16 &= 0xff1f; /* Clear bits 7-5. */
386 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
387 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000388
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000389 /*
390 * RAM_COMMAND_NORMAL affects only the memory controller and
391 * doesn't need to be "sent" to the DIMMs.
392 */
393 if (command == RAM_COMMAND_NORMAL)
394 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000395
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000396 /* Send the RAM command to each row of memory. */
397 dimm_start = 0;
398 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000399 addr_offset = 0;
400 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000401 if (command == RAM_COMMAND_MRS) {
402 /*
403 * MAA[12:11,9:0] must be inverted when sent to DIMM
404 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
405 */
406 if ((i >= 0 && i <= 3) && caslatency == 3)
407 addr_offset = 0x1d0;
408 if ((i >= 4 && i <= 7) && caslatency == 3)
409 addr_offset = 0x1e28;
410 if ((i >= 0 && i <= 3) && caslatency == 2)
411 addr_offset = 0x150;
412 if ((i >= 4 && i <= 7) && caslatency == 2)
413 addr_offset = 0x1ea8;
414 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000415
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000416 dimm_end = pci_read_config8(NB, DRB + i);
417
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800418 addr = (void *)((dimm_start * 8 * 1024 * 1024) + addr_offset);
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000419 if (dimm_end > dimm_start) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000420 read32(addr);
421 }
422
423 /* Set the start of the next DIMM. */
424 dimm_start = dimm_end;
425 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000426}
427
Keith Hui59356ca2010-03-06 18:16:25 +0000428static void set_dram_buffer_strength(void)
429{
Keith Huia8380fc2017-12-04 00:05:56 -0500430 /*
431 * Program MBSC[39:0] and MBFS[23:0].
432 *
433 * The 440BX datasheet says buffer frequency is independent from bus
434 * frequency and mismatch both ways are possible.
435 *
436 * MBSC[47:40] and MBFS[23] are reserved.
Keith Hui59356ca2010-03-06 18:16:25 +0000437 */
438
Keith Huia8380fc2017-12-04 00:05:56 -0500439 unsigned int i, reg, drb;
440 uint8_t mbsc0, mbfs0, mbfs1, mbfs2;
441 uint16_t mbsc1, mbsc3;
442
443 /*
444 * Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000445 * This determines how to program MBFS and MBSC.
446 */
447 uint8_t dimm03 = 0;
448 uint8_t dimm47 = 0;
449
Keith Huia8380fc2017-12-04 00:05:56 -0500450 for (drb = 0, i = DRB0; i <= DRB7; i++) {
451 reg = pci_read_config8(NB, i);
452 if (drb != reg) {
453 if (i <= DRB3)
Keith Huib48ba662010-03-17 02:15:07 +0000454 dimm03++;
Keith Huia8380fc2017-12-04 00:05:56 -0500455 else
Keith Huib48ba662010-03-17 02:15:07 +0000456 dimm47++;
Keith Huia8380fc2017-12-04 00:05:56 -0500457
458 drb = reg;
Keith Huib48ba662010-03-17 02:15:07 +0000459 }
460 }
461
Julius Wernercd49cce2019-03-05 16:53:33 -0800462 if (CONFIG(SDRAMPWR_4DIMM)) {
Keith Huia8380fc2017-12-04 00:05:56 -0500463 /*
464 * For a 4 DIMM board, based on ASUS P2B-LS mainboard.
Keith Huib48ba662010-03-17 02:15:07 +0000465 *
Keith Huia8380fc2017-12-04 00:05:56 -0500466 * There are four main conditions to check when programming
467 * DRAM buffer frequency and strength:
Keith Huib48ba662010-03-17 02:15:07 +0000468 *
469 * a: >2 rows populated across DIMM0,1
470 * b: >2 rows populated across DIMM2,3
471 * c: >4 rows populated across all DIMM slots
472 * and either one of:
473 * 1: NBXCFG[13] strapped as 100MHz, or
474 * 6: NBXCFG[13] strapped as 66MHz
475 *
476 * CKE0/FENA ----------------------------------------------------------+
Keith Huia8380fc2017-12-04 00:05:56 -0500477 * CKE1/GCKE ----------------------[ MBFS ]---------------------+|
478 * DQMA/CASA[764320]# -------------[ 0 = 66MHz ]--------------------+||
479 * DQMB1/CASB1# (Fixed for 66MHz) -[ 1 = 100MHz ]-------------------+|||
480 * DQMB5/CASB5# (Fixed for 66MHz) ---------------------------------+||||
481 * DQMA1/CASA1# (Fixed for 66MHz) --------------------------------+|||||
482 * DQMA5/CASA5# (Fixed for 66MHz) -------------------------------+||||||
483 * CSA[5:0]#,CSB[5:0]# ------------------------------------++++++|||||||
484 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
485 * MECC[7:0] #2/#1 ----------------------------------++|||||||||||||||||
486 * MD[63:0] #2/#1 ---------------------------------++|||||||||||||||||||
487 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
488 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
489 * Reserved ------------------------------------+|||||||||||||||||||||||
490 * ||||||||||||||||||||||||
491 * 3 32 21 10 0 * 2 21 10 0
492 * 9876543210987654321098765432109876543210 * 321098765432109876543210
493 * 10------------------------1010---------- a -1---------------11-----
494 * 11------------------------1111---------- !a -0---------------00-----
495 * --10--------------------------1010------ b --1----------------11---
496 * --11--------------------------1111------ !b --0----------------00---
497 * ----------------------------------1100-- c ----------------------1-
498 * ----------------------------------1011-- !c ----------------------0-
499 * ----1010101000000000000000------------00 1 ---11111111111111----1-0
500 * ----000000000000000000000010101010----00 6 ---1111111111111100000-0
501 * | | | | | | | | | | ||||||| | | | | | |
502 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
503 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
504 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
505 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# (66MHz: 2x)
506 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# (66MHz: 2x)
507 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# (66MHz: 2x)
508 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# (66MHz: 2x)
509 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (1x)
510 * | | | | | | | | | +--------------------- CSA6#/CKE2
511 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
512 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
513 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
514 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1
515 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2
516 * | | | +--------------------------------- MD[63:0] #1
517 * | | +----------------------------------- MD[63:0] #2
518 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
519 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
520 */
521 unsigned int fsb;
522
523 mbsc0 = 0xa0;
524 mbsc1 = 0x002a;
525 mbfs1 = 0xff;
526 mbfs2 = 0x1f;
527 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
528 fsb = 66;
529 mbsc3 = 0xa000;
530 mbfs0 = 0x80;
531 } else {
532 fsb = 100;
533 mbsc3 = 0xaaa0;
534 mbfs0 = 0x84;
535 }
536 if (dimm03 > 2) {
537 mbfs2 |= 0x40;
538 if (fsb == 100)
539 mbfs0 |= 0x60;
540 } else {
541 mbsc3 |= 0xc000;
542 if (fsb == 100)
543 mbsc1 |= 0x003c;
544 }
545 if (dimm47 > 2) {
546 mbfs2 |= 0x20;
547 if (fsb == 100)
548 mbfs0 |= 0x18;
549 } else {
550 mbsc3 |= 0x3000;
551 if (fsb == 100) {
552 mbsc1 |= 0x0003;
553 mbsc0 |= 0xc0;
554 }
555 }
556 if ((dimm03 + dimm47) > 4) {
557 mbsc0 |= 0x30;
558 mbfs0 |= 0x02;
559 } else {
560 mbsc0 |= 0x2c;
561 }
562 } else {
563 /*
564 * For a 3 DIMM board, based on ASUS P2B mainboard.
565 *
566 * There are two main conditions to check when programming DRAM buffer
567 * frequency and strength:
568 *
569 * a: >2 rows populated across DIMM0,1
570 * c: >4 rows populated across all DIMM slots
571 *
572 * CKE0 ---------------------------------------------------------------+
573 * CKE1 ------------------------[ MBFS ]------------------------+|
Keith Huib48ba662010-03-17 02:15:07 +0000574 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
575 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
576 * DQMB5/CASB5# ---------------------------------------------------+||||
577 * DQMA1/CASA1# --------------------------------------------------+|||||
578 * DQMA5/CASA5# -------------------------------------------------+||||||
579 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500580 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
Keith Huib48ba662010-03-17 02:15:07 +0000581 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
582 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
583 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
584 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
585 * Reserved ------------------------------------+|||||||||||||||||||||||
586 * ||||||||||||||||||||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500587 * 3 32 21 10 0 * 2 21 10 0
588 * 9876543210987654321098765432109876543210 * 321098765432109876543210
589 * 10------------------------1111---------- a -1----------------------
590 * 11------------------------1010---------- !a -0----------------------
591 * --110000000010101010111111----1010--1010 * --01111000000000000000-0
592 * ----------------------------------11---- c ----------------------1-
593 * ----------------------------------10---- !c ----------------------0-
594 * | | | | | | | | | | ||||||| | | | | | |
595 * | | | | | | | | | | ||||||| | | | | | +- CKE0
596 * | | | | | | | | | | ||||||| | | | | +--- CKE1
597 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
598 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
599 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
600 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
601 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
602 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (2x)
603 * | | | | | | | | | +--------------------- CSA6#/CKE2
604 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
605 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
606 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
607 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (1x)
608 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (1x)
609 * | | | +--------------------------------- MD[63:0] #1 (1x)
610 * | | +----------------------------------- MD[63:0] #2 (1x)
611 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
612 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
Keith Huib48ba662010-03-17 02:15:07 +0000613 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000614
Keith Huia8380fc2017-12-04 00:05:56 -0500615 mbsc0 = 0xaa;
616 mbsc1 = 0xafea;
617 mbsc3 = 0xb00a;
618 mbfs0 = 0x00;
619 mbfs1 = 0x00;
620 mbfs2 = 0x1e;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000621
Keith Huia8380fc2017-12-04 00:05:56 -0500622 if (dimm03 > 2) {
623 mbsc1 |= 0x003c;
624 mbfs2 |= 0x40;
625 } else {
626 mbsc3 |= 0xc000;
Keith Huib48ba662010-03-17 02:15:07 +0000627 }
Keith Huia8380fc2017-12-04 00:05:56 -0500628 if ((dimm03 + dimm47) > 4) {
629 mbsc0 |= 0x30;
630 mbfs0 |= 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000631 }
632 }
Keith Huib48ba662010-03-17 02:15:07 +0000633
634 pci_write_config8(NB, MBSC + 0, mbsc0);
Keith Huia8380fc2017-12-04 00:05:56 -0500635 pci_write_config16(NB, MBSC + 1, mbsc1);
636 pci_write_config16(NB, MBSC + 3, mbsc3);
637 pci_write_config16(NB, MBFS + 0, mbfs1 << 8 | mbfs0);
Keith Huib48ba662010-03-17 02:15:07 +0000638 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000639}
640
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000641/*-----------------------------------------------------------------------------
Martin Roth128c1042016-11-18 09:29:03 -0700642DIMM-independent configuration functions.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000643-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000644
Uwe Hermann1683cef2008-11-27 00:47:07 +0000645static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000646{
647 int i, value;
648 uint8_t reg;
649
Uwe Hermann1683cef2008-11-27 00:47:07 +0000650 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000651
652 for (i = 0; i < DIMM_SOCKETS; i++) {
Uwe Hermannd773fd32010-11-20 20:23:08 +0000653 value = spd_read_byte(DIMM0 + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000654 if (value < 0)
655 continue;
656 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
657
Keith Hui09f5a742010-12-23 17:12:03 +0000658 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000659 }
660
Uwe Hermann1683cef2008-11-27 00:47:07 +0000661 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000662}
663
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000664/*-----------------------------------------------------------------------------
665Public interface.
666-----------------------------------------------------------------------------*/
667
Uwe Hermann115c5b92010-10-09 17:00:18 +0000668void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000669{
670 int i, max;
Uwe Hermannbc3594732007-06-07 22:16:30 +0000671 uint8_t reg;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000672
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000673 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000674 DUMPNORTH();
675
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000676 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000677
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000678 /* Set registers as specified in the register_values[] array. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000679 for (i = 0; i < max; i += 3) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000680 reg = pci_read_config8(NB, register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000681 reg &= register_values[i + 1];
682 reg |= register_values[i + 2] & ~(register_values[i + 1]);
Uwe Hermann1683cef2008-11-27 00:47:07 +0000683 pci_write_config8(NB, register_values[i], reg);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000684 }
685}
686
Keith Hui59356ca2010-03-06 18:16:25 +0000687struct dimm_size {
Keith Hui09f5a742010-12-23 17:12:03 +0000688 u32 side1;
689 u32 side2;
Keith Hui59356ca2010-03-06 18:16:25 +0000690};
691
692static struct dimm_size spd_get_dimm_size(unsigned int device)
693{
694 struct dimm_size sz;
695 int i, module_density, dimm_banks;
696 sz.side1 = 0;
697 module_density = spd_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
698 dimm_banks = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
699
700 /* Find the size of side1. */
701 /* Find the larger value. The larger value is always side1. */
702 for (i = 512; i >= 0; i >>= 1) {
703 if ((module_density & i) == i) {
704 sz.side1 = i;
705 break;
706 }
707 }
708
709 /* Set to 0 in case it's single sided. */
710 sz.side2 = 0;
711
712 /* Test if it's a dual-sided DIMM. */
713 if (dimm_banks > 1) {
714 /* Test if there's a second value. If so it's asymmetrical. */
715 if (module_density != i) {
716 /*
717 * Find second value, picking up where we left off.
718 * i >>= 1 done initially to make sure we don't get
719 * the same value again.
720 */
721 for (i >>= 1; i >= 0; i >>= 1) {
722 if (module_density == (sz.side1 | i)) {
723 sz.side2 = i;
724 break;
725 }
726 }
727 /* If not, it's symmetrical. */
728 } else {
729 sz.side2 = sz.side1;
730 }
731 }
732
733 /*
734 * SPD byte 31 is the memory size divided by 4 so we
Martin Roth128c1042016-11-18 09:29:03 -0700735 * need to multiply by 4 to get the total size.
Keith Hui59356ca2010-03-06 18:16:25 +0000736 */
737 sz.side1 *= 4;
738 sz.side2 *= 4;
739
Keith Huia8380fc2017-12-04 00:05:56 -0500740 /*
741 * It is possible to partially use larger than supported
Anders Jenbo771b0e42010-04-27 08:45:30 +0000742 * modules by setting them to a supported size.
743 */
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200744 if (sz.side1 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000745 PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
746 sz.side1);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000747 sz.side1 = 128;
748
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200749 if (sz.side2 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000750 PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
751 sz.side2);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000752 sz.side2 = 128;
753 }
754 }
755
Keith Hui59356ca2010-03-06 18:16:25 +0000756 return sz;
757}
758/*
759 * Sets DRAM attributes one DIMM at a time, based on SPD data.
760 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
761 */
762static void set_dram_row_attributes(void)
763{
Keith Huie089a3f2011-08-02 22:28:14 -0400764 int i, dra, drb, col, width, value, rps;
Keith Hui59356ca2010-03-06 18:16:25 +0000765 u8 bpr; /* Top 8 bits of PGPOL */
Keith Huie089a3f2011-08-02 22:28:14 -0400766 u8 nbxecc = 0; /* NBXCFG[31:24] */
767 u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
Keith Hui59356ca2010-03-06 18:16:25 +0000768
Keith Huie089a3f2011-08-02 22:28:14 -0400769 edo = 0;
770 sd = 0;
771 regsd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000772 rps = 0;
773 drb = 0;
774 bpr = 0;
Keith Hui59356ca2010-03-06 18:16:25 +0000775
776 for (i = 0; i < DIMM_SOCKETS; i++) {
777 unsigned int device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000778 device = DIMM0 + i;
Keith Hui59356ca2010-03-06 18:16:25 +0000779 bpr >>= 2;
Keith Huie089a3f2011-08-02 22:28:14 -0400780 nbxecc >>= 2;
Keith Hui59356ca2010-03-06 18:16:25 +0000781
782 /* First check if a DIMM is actually present. */
783 value = spd_read_byte(device, SPD_MEMORY_TYPE);
784 /* This is 440BX! We do EDO too! */
785 if (value == SPD_MEMORY_TYPE_EDO
786 || value == SPD_MEMORY_TYPE_SDRAM) {
787
Keith Hui59356ca2010-03-06 18:16:25 +0000788 if (value == SPD_MEMORY_TYPE_EDO) {
Keith Huie089a3f2011-08-02 22:28:14 -0400789 edo = 1;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000790 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
Keith Huie089a3f2011-08-02 22:28:14 -0400791 sd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000792 }
Keith Hui09f5a742010-12-23 17:12:03 +0000793 PRINT_DEBUG("Found DIMM in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000794
Keith Huie089a3f2011-08-02 22:28:14 -0400795 if (edo && sd) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800796 printk(BIOS_ERR, "Mixing EDO/SDRAM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000797 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000798 }
799
800 /* "DRA" is our RPS for the two rows on this DIMM. */
801 dra = 0;
802
803 /* Columns */
804 col = spd_read_byte(device, SPD_NUM_COLUMNS);
805
806 /*
807 * Is this an ECC DIMM? Actually will be a 2 if so.
808 * TODO: Other register than NBXCFG also needs this
809 * ECC information.
810 */
Keith Huie089a3f2011-08-02 22:28:14 -0400811 value = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000812
813 /* Data width */
814 width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000815
Keith Hui59356ca2010-03-06 18:16:25 +0000816 /* Exclude error checking data width from page size calculations */
Keith Huie089a3f2011-08-02 22:28:14 -0400817 if (value) {
Keith Hui59356ca2010-03-06 18:16:25 +0000818 value = spd_read_byte(device,
819 SPD_ERROR_CHECKING_SDRAM_WIDTH);
820 width -= value;
821 /* ### ECC */
822 /* Clear top 2 bits to help set up NBXCFG. */
Keith Huie089a3f2011-08-02 22:28:14 -0400823 nbxecc &= 0x3f;
Keith Hui59356ca2010-03-06 18:16:25 +0000824 } else {
825 /* Without ECC, top 2 bits should be 11. */
Keith Huie089a3f2011-08-02 22:28:14 -0400826 nbxecc |= 0xc0;
Keith Hui59356ca2010-03-06 18:16:25 +0000827 }
828
Keith Huie089a3f2011-08-02 22:28:14 -0400829 /* If any installed DIMM is *not* registered, this system cannot be
830 * configured for registered SDRAM.
831 * By registered, only the address and control lines need to be, which
832 * we can tell by reading SPD byte 21, bit 1.
833 */
834 value = spd_read_byte(device, SPD_MODULE_ATTRIBUTES);
835
836 PRINT_DEBUG("DIMM is ");
837 if ((value & MODULE_REGISTERED) == 0) {
838 regsd = 0;
839 PRINT_DEBUG("not ");
840 }
841 PRINT_DEBUG("registered\n");
842
Keith Hui59356ca2010-03-06 18:16:25 +0000843 /* Calculate page size in bits. */
844 value = ((1 << col) * width);
845
846 /* Convert to KB. */
847 dra = (value >> 13);
848
849 /* Number of banks of DIMM (single or double sided). */
850 value = spd_read_byte(device, SPD_NUM_DIMM_BANKS);
851
852 /* Once we have dra, col is done and can be reused.
853 * So it's reused for number of banks.
854 */
855 col = spd_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
856
857 if (value == 1) {
858 /*
859 * Second bank of 1-bank DIMMs "doesn't have
860 * ECC" - or anything.
861 */
Keith Hui59356ca2010-03-06 18:16:25 +0000862 if (dra == 2) {
863 dra = 0x0; /* 2KB */
864 } else if (dra == 4) {
865 dra = 0x1; /* 4KB */
866 } else if (dra == 8) {
867 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000868 } else if (dra >= 16) {
869 /* Page sizes larger than supported are
870 * set to 8KB to use module partially.
871 */
872 PRINT_DEBUG("Page size forced to 8KB.\n");
873 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000874 } else {
875 dra = -1;
876 }
877 /*
878 * Sets a flag in PGPOL[BPR] if this DIMM has
879 * 4 banks per row.
880 */
881 if (col == 4)
882 bpr |= 0x40;
883 } else if (value == 2) {
884 if (dra == 2) {
885 dra = 0x0; /* 2KB */
886 } else if (dra == 4) {
887 dra = 0x05; /* 4KB */
888 } else if (dra == 8) {
889 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000890 } else if (dra >= 16) {
891 /* Ditto */
892 PRINT_DEBUG("Page size forced to 8KB.\n");
893 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000894 } else {
895 dra = -1;
896 }
897 /* Ditto */
898 if (col == 4)
899 bpr |= 0xc0;
900 } else {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800901 printk(BIOS_ERR, "# of banks of DIMM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000902 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000903 }
904 if (dra == -1) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800905 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000906 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000907 }
908
909 /*
910 * 440BX supports asymmetrical dual-sided DIMMs,
911 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000912 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000913 */
914 struct dimm_size sz = spd_get_dimm_size(device);
915 if ((sz.side1 < 8)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800916 printk(BIOS_ERR, "DIMMs smaller than 8MB per side\n"
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000917 "are not supported on this NB.\n");
918 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000919 }
Keith Hui59356ca2010-03-06 18:16:25 +0000920
921 /* Divide size by 8 to set up the DRB registers. */
922 drb += (sz.side1 / 8);
923
924 /*
925 * Build the DRB for the next row in MSB so it gets
926 * placed in DRB[n+1] where it belongs when written
927 * as a 16-bit word.
928 */
929 drb &= 0xff;
930 drb |= (drb + (sz.side2 / 8)) << 8;
931 } else {
Keith Hui59356ca2010-03-06 18:16:25 +0000932 /* If there's no DIMM in the slot, set dra to 0x00. */
933 dra = 0x00;
Keith Hui59356ca2010-03-06 18:16:25 +0000934 /* Still have to propagate DRB over. */
935 drb &= 0xff;
936 drb |= (drb << 8);
937 }
938
939 pci_write_config16(NB, DRB + (2 * i), drb);
Keith Hui59356ca2010-03-06 18:16:25 +0000940
941 /* Brings the upper DRB back down to be base for
942 * DRB calculations for the next two rows.
943 */
944 drb >>= 8;
945
946 rps |= (dra & 0x0f) << (i * 4);
Keith Hui59356ca2010-03-06 18:16:25 +0000947 }
948
949 /* Set paging policy register. */
950 pci_write_config8(NB, PGPOL + 1, bpr);
Keith Hui09f5a742010-12-23 17:12:03 +0000951 PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
Keith Hui59356ca2010-03-06 18:16:25 +0000952
953 /* Set DRAM row page size register. */
954 pci_write_config16(NB, RPS, rps);
Keith Hui09f5a742010-12-23 17:12:03 +0000955 PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
Keith Hui59356ca2010-03-06 18:16:25 +0000956
957 /* ### ECC */
958 pci_write_config8(NB, NBXCFG + 3, nbxecc);
Keith Hui09f5a742010-12-23 17:12:03 +0000959 PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
Keith Hui59356ca2010-03-06 18:16:25 +0000960
Keith Huie089a3f2011-08-02 22:28:14 -0400961 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
Keith Hui59356ca2010-03-06 18:16:25 +0000962
Keith Huie089a3f2011-08-02 22:28:14 -0400963 /* i will be used to set DRAMC[4:3]. */
964 if (regsd && sd) {
965 i = 0x10; // Registered SDRAM
966 } else if (sd) {
967 i = 0x08; // SDRAM
968 } else {
969 i = 0; // EDO
970 }
971
Keith Hui59356ca2010-03-06 18:16:25 +0000972 value = pci_read_config8(NB, DRAMC) & 0xe7;
Keith Huie089a3f2011-08-02 22:28:14 -0400973 value |= i;
Keith Hui59356ca2010-03-06 18:16:25 +0000974 pci_write_config8(NB, DRAMC, value);
Keith Hui09f5a742010-12-23 17:12:03 +0000975 PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
Keith Hui59356ca2010-03-06 18:16:25 +0000976}
977
Uwe Hermann115c5b92010-10-09 17:00:18 +0000978void sdram_set_spd_registers(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000979{
Keith Hui59356ca2010-03-06 18:16:25 +0000980 /* Setup DRAM row boundary registers and other attributes. */
981 set_dram_row_attributes();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000982
Keith Huidf35cdc2010-09-20 23:41:37 +0000983 /* Setup DRAM buffer strength. */
Keith Hui59356ca2010-03-06 18:16:25 +0000984 set_dram_buffer_strength();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000985
986 /* TODO: Set PMCR? */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000987 // pci_write_config8(NB, PMCR, 0x14);
988 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000989
Keith Huidf35cdc2010-09-20 23:41:37 +0000990 /* TODO: This is for EDO memory only. */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000991 pci_write_config8(NB, DRAMT, 0x03);
Richard Smithcb8eab42006-07-24 04:25:47 +0000992}
993
Uwe Hermann115c5b92010-10-09 17:00:18 +0000994void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000995{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000996 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000997
Uwe Hermann861f9642007-05-28 14:37:06 +0000998 /* 0. Wait until power/voltages and clocks are stable (200us). */
999 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +00001000
Uwe Hermann861f9642007-05-28 14:37:06 +00001001 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001002 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001003 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +00001004 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +00001005
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001006 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001007 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001008 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +00001009 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001010
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001011 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001012 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001013 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001014 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +00001015 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001016 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001017
1018 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001019 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001020 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +00001021 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001022
1023 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001024 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001025 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +00001026 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001027
1028 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001029 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Uwe Hermann1683cef2008-11-27 00:47:07 +00001030 // pci_write_config8(NB, PMCR, 0x10);
1031 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +00001032 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001033
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001034 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001035 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001036}
Keith Hui078e3242017-07-20 21:14:21 -04001037
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001038/* Implemented under mainboard. */
1039void __weak enable_spd(void) { }
1040void __weak disable_spd(void) { }
1041
Keith Hui078e3242017-07-20 21:14:21 -04001042void sdram_initialize(void)
1043{
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001044 enable_spd();
1045
Keith Hui078e3242017-07-20 21:14:21 -04001046 dump_spd_registers();
1047 sdram_set_registers();
1048 sdram_set_spd_registers();
1049 sdram_enable();
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001050
1051 disable_spd();
Martin Rothe1695e22017-07-24 11:28:50 -06001052}