blob: 0a864e864a98a777fc528223539abd386857eda8 [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>
Keith Huid6f259e2020-01-12 18:38:28 -050025#include <timestamp.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000026#include "i440bx.h"
Keith Hui59356ca2010-03-06 18:16:25 +000027#include "raminit.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000028
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +020029#include <southbridge/intel/i82371eb/i82371eb.h>
30
Keith Hui9aa45e62017-07-20 21:00:56 -040031/*
32 * Macros and definitions
33 */
Keith Huidf35cdc2010-09-20 23:41:37 +000034
Uwe Hermann1a9c8922007-04-01 17:24:03 +000035/* Debugging macros. */
Julius Wernercd49cce2019-03-05 16:53:33 -080036#if CONFIG(DEBUG_RAM_SETUP)
Keith Hui09f5a742010-12-23 17:12:03 +000037#define PRINT_DEBUG(x...) printk(BIOS_DEBUG, x)
Keith Huidf35cdc2010-09-20 23:41:37 +000038#define DUMPNORTH() dump_pci_device(NB)
Richard Smithcb8eab42006-07-24 04:25:47 +000039#else
Keith Hui09f5a742010-12-23 17:12:03 +000040#define PRINT_DEBUG(x...)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000041#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000042#endif
43
Uwe Hermann1a9c8922007-04-01 17:24:03 +000044/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
45#define RAM_COMMAND_NORMAL 0x0
46#define RAM_COMMAND_NOP 0x1
47#define RAM_COMMAND_PRECHARGE 0x2
48#define RAM_COMMAND_MRS 0x3
49#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000050
Uwe Hermann1a9c8922007-04-01 17:24:03 +000051/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
52 * defined in DRAMC[2:0].
53 *
54 * [0] == Normal 15.625 us -> 15.6 us
55 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
56 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
57 * [3] == Extended(2x) 31.3 us -> 31.2 us
58 * [4] == Extended(4x) 62.5 us -> 62.4 us
59 * [5] == Extended(8x) 125 us -> 124.8 us
60 */
61static const uint32_t refresh_rate_map[] = {
62 1, 5, 5, 2, 3, 4
63};
Richard Smithcb8eab42006-07-24 04:25:47 +000064
Uwe Hermann1a9c8922007-04-01 17:24:03 +000065/* Table format: register, bitmask, value. */
Keith Huidf35cdc2010-09-20 23:41:37 +000066static const u8 register_values[] = {
Uwe Hermann1a9c8922007-04-01 17:24:03 +000067 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000068 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000069 *
70 * [31:24] SDRAM Row Without ECC
71 * 0 = ECC components are populated in this row
72 * 1 = ECC components are not populated in this row
73 * [23:19] Reserved
74 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
75 * Assertion of DRAM data on host bus occurs...
76 * 0 = ...one clock after sampling snoop results (default)
77 * 1 = ...on the same clock the snoop result is being sampled
78 * (this mode is faster by one clock cycle)
79 * [17:17] ECC - EDO static Drive mode
80 * 0 = Normal mode (default)
81 * 1 = ECC signals are always driven
82 * [16:16] IDSEL_REDIRECT
83 * 0 = IDSEL1 is allocated to this bridge (default)
84 * 1 = IDSEL7 is allocated to this bridge
85 * [15:15] WSC# Handshake Disable
86 * 1 = Uni-processor mode
87 * 0 = Dual-processor mode with external IOAPIC (default)
88 * [14:14] Intel Reserved
89 * [13:12] Host/DRAM Frequency
90 * 00 = 100 MHz
91 * 01 = Reserved
92 * 10 = 66 MHz
93 * 11 = Reserved
94 * [11:11] AGP to PCI Access Enable
95 * 1 = Enable
96 * 0 = Disable
97 * [10:10] PCI Agent to Aperture Access Disable
98 * 1 = Disable
99 * 0 = Enable (default)
100 * [09:09] Aperture Access Global Enable
101 * 1 = Enable
102 * 0 = Disable
103 * [08:07] DRAM Data Integrity Mode (DDIM)
104 * 00 = Non-ECC
105 * 01 = EC-only
106 * 10 = ECC Mode
107 * 11 = ECC Mode with hardware scrubbing enabled
108 * [06:06] ECC Diagnostic Mode Enable (EDME)
109 * 1 = Enable
110 * 0 = Normal operation mode (default)
111 * [05:05] MDA Present (MDAP)
112 * Works in conjunction with the VGA_EN bit.
113 * VGA_EN MDAP
114 * 0 x All VGA cycles are sent to PCI
115 * 1 0 All VGA cycles are sent to AGP
116 * 1 1 All VGA cycles are sent to AGP, except for
117 * cycles in the MDA range.
118 * [04:04] Reserved
119 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
120 * 1 = Enable
121 * 0 = Disable
122 * [02:02] In-Order Queue Depth (IOQD)
123 * 1 = In-order queue = maximum
124 * 0 = A7# is sampled asserted (i.e., 0)
125 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000126 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000127 NBXCFG + 0, 0x00, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000128 // TODO: Bit 15 should be 0 for multiprocessor boards
Uwe Hermannbc3594732007-06-07 22:16:30 +0000129 NBXCFG + 1, 0x00, 0x80,
130 NBXCFG + 2, 0x00, 0x00,
131 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000132
133 /* DRAMC - DRAM Control Register
134 * 0x57
135 *
136 * [7:6] Reserved
137 * [5:5] Module Mode Configuration (MMCONFIG)
Keith Huia8380fc2017-12-04 00:05:56 -0500138 * The combination of SDRAMPWR and this bit (set by an
Keith Huidf35cdc2010-09-20 23:41:37 +0000139 * external strapping option) determine how CKE works.
140 * SDRAMPWR MMCONFIG
Keith Huia8380fc2017-12-04 00:05:56 -0500141 * 0 0 = 3 DIMM, CKE[5:0] driven
142 * X 1 = 3 DIMM, CKE0 only
143 * 1 0 = 4 DIMM, GCKE only
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000144 * [4:3] DRAM Type (DT)
145 * 00 = EDO
146 * 01 = SDRAM
147 * 10 = Registered SDRAM
148 * 11 = Reserved
149 * Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
150 * [2:0] DRAM Refresh Rate (DRR)
151 * 000 = Refresh disabled
152 * 001 = 15.6 us
153 * 010 = 31.2 us
154 * 011 = 62.4 us
155 * 100 = 124.8 us
156 * 101 = 249.6 us
157 * 110 = Reserved
158 * 111 = Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000159 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000160 /* Choose SDRAM (not registered), and disable refresh for now. */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000161 DRAMC, 0x00, 0x08,
Richard Smithcb8eab42006-07-24 04:25:47 +0000162
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000163 /*
164 * PAM[6:0] - Programmable Attribute Map Registers
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000165 * 0x59 - 0x5f
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000166 *
167 * 0x59 [3:0] Reserved
168 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
169 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
170 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
171 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
172 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
173 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
174 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
175 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
176 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
Martin Roth128c1042016-11-18 09:29:03 -0700177 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS extension
178 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS extension
179 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS extension
180 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS extension
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000181 *
182 * Bit assignment:
183 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
184 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
185 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
186 * 11 = Read/Write (all access goes to DRAM)
187 */
Keith Hui59356ca2010-03-06 18:16:25 +0000188
189 /*
190 * Map all legacy regions to RAM (read/write). This is required if
191 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
192 * registers are not set here appropriately, the RAM in that region
193 * will not be accessible, thus a RAM check of it will also fail.
Keith Hui59356ca2010-03-06 18:16:25 +0000194 */
195 PAM0, 0x00, 0x30,
196 PAM1, 0x00, 0x33,
197 PAM2, 0x00, 0x33,
198 PAM3, 0x00, 0x33,
199 PAM4, 0x00, 0x33,
200 PAM5, 0x00, 0x33,
201 PAM6, 0x00, 0x33,
Richard Smithcb8eab42006-07-24 04:25:47 +0000202
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000203 /* DRB[0:7] - DRAM Row Boundary Registers
204 * 0x60 - 0x67
205 *
206 * An array of 8 byte registers, which hold the ending memory address
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000207 * assigned to each pair of DIMMs, in 8MB granularity.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000208 *
209 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
210 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
211 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
212 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
213 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
214 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
215 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
216 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
217 */
Keith Huia8380fc2017-12-04 00:05:56 -0500218 /* DRBs will be set later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000219 DRB0, 0x00, 0x00,
220 DRB1, 0x00, 0x00,
221 DRB2, 0x00, 0x00,
222 DRB3, 0x00, 0x00,
223 DRB4, 0x00, 0x00,
224 DRB5, 0x00, 0x00,
225 DRB6, 0x00, 0x00,
226 DRB7, 0x00, 0x00,
227
228 /* FDHC - Fixed DRAM Hole Control Register
229 * 0x68
230 *
231 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
232 *
233 * [7:6] Hole Enable (HEN)
234 * 00 = None
235 * 01 = 512 KB - 640 KB (128 KB)
236 * 10 = 15 MB - 16 MB (1 MB)
237 * 11 = Reserved
238 * [5:0] Reserved
239 */
240 /* No memory holes. */
241 FDHC, 0x00, 0x00,
242
243 /* RPS - SDRAM Row Page Size Register
244 * 0x74 - 0x75
245 *
246 * Sets the row page size for SDRAM. For EDO memory, the page
247 * size is fixed at 2 KB.
248 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000249 * Bits[1:0] Page Size
250 * 00 2 KB
251 * 01 4 KB
252 * 10 8 KB
253 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400254 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000255 * RPS bits Corresponding DRB register
256 * [01:00] DRB[0], row 0
257 * [03:02] DRB[1], row 1
258 * [05:04] DRB[2], row 2
259 * [07:06] DRB[3], row 3
260 * [09:08] DRB[4], row 4
261 * [11:10] DRB[5], row 5
262 * [13:12] DRB[6], row 6
263 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000264 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000265 /* Power on defaults to 2KB. Will be set later. */
266 // RPS + 0, 0x00, 0x00,
267 // RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000268
269 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000270 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000271 *
272 * [15:10] Reserved
273 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
274 * 00 = Illegal
275 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000276 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000277 * [07:05] SDRAM Mode Select (SMS)
278 * 000 = Normal SDRAM Operation (default)
279 * 001 = NOP Command Enable
280 * 010 = All Banks Precharge Enable
281 * 011 = Mode Register Set Enable
282 * 100 = CBR Enable
283 * 101 = Reserved
284 * 110 = Reserved
285 * 111 = Reserved
286 * [04:04] SDRAMPWR
287 * 0 = 3 DIMM configuration
288 * 1 = 4 DIMM configuration
289 * [03:03] Leadoff Command Timing (LCT)
290 * 0 = 4 CS# Clock
291 * 1 = 3 CS# Clock
292 * [02:02] CAS# Latency (CL)
293 * 0 = 3 DCLK CAS# latency
294 * 1 = 2 DCLK CAS# latency
295 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
296 * 0 = 3 clocks between a row activate and a read or write cmd.
297 * 1 = 2 clocks between a row activate and a read or write cmd.
298 * [00:00] SDRAM RAS# Precharge (SRP)
299 * 0 = 3 clocks of RAS# precharge
300 * 1 = 2 clocks of RAS# precharge
301 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800302#if CONFIG(SDRAMPWR_4DIMM)
Keith Hui9c1e1f02010-03-13 20:16:48 +0000303 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
304#else
Keith Huidf35cdc2010-09-20 23:41:37 +0000305 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000306#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000307
308 /* PGPOL - Paging Policy Register
309 * 0x78 - 0x79
310 *
311 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000312 * Each bit in this field corresponds to one row of the memory
313 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
314 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000315 * 0 = 2 banks
316 * 1 = 4 banks
317 * [07:05] Reserved
318 * [04:04] Intel Reserved
319 * [03:00] DRAM Idle Timer (DIT)
320 * 0000 = 0 clocks
321 * 0001 = 2 clocks
322 * 0010 = 4 clocks
323 * 0011 = 8 clocks
324 * 0100 = 10 clocks
325 * 0101 = 12 clocks
326 * 0110 = 16 clocks
327 * 0111 = 32 clocks
328 * 1xxx = Infinite (pages are not closed for idle condition)
329 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000330 PGPOL + 0, 0x00, 0x00,
331 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000332
333 /* PMCR - Power Management Control Register
334 * 0x7a
335 *
336 * [07:07] Power Down SDRAM Enable (PDSE)
337 * 1 = Enable
338 * 0 = Disable
339 * [06:06] ACPI Control Register Enable (SCRE)
340 * 1 = Enable
341 * 0 = Disable (default)
342 * [05:05] Suspend Refresh Type (SRT)
343 * 1 = Self refresh mode
344 * 0 = CBR fresh mode
345 * [04:04] Normal Refresh Enable (NREF_EN)
346 * 1 = Enable
347 * 0 = Disable
348 * [03:03] Quick Start Mode (QSTART)
349 * 1 = Quick start mode for the processor is enabled
350 * [02:02] Gated Clock Enable (GCLKEN)
351 * 1 = Enable
352 * 0 = Disable
353 * [01:01] AGP Disable (AGP_DIS)
354 * 1 = Disable
355 * 0 = Enable
356 * [00:00] CPU reset without PCIRST enable (CRst_En)
357 * 1 = Enable
358 * 0 = Disable
359 */
Keith Huie9b3fd12020-01-12 18:41:26 -0500360 /* PMCR will be set later. */
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++) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200653 value = smbus_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
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200668static void 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;
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200697 module_density = smbus_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
698 dimm_banks = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000699
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. */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200783 value = smbus_read_byte(device, SPD_MEMORY_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000784 /* 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 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200804 col = smbus_read_byte(device, SPD_NUM_COLUMNS);
Keith Hui59356ca2010-03-06 18:16:25 +0000805
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 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200811 value = smbus_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000812
813 /* Data width */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200814 width = smbus_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) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200818 value = smbus_read_byte(device,
Keith Hui59356ca2010-03-06 18:16:25 +0000819 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 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200834 value = smbus_read_byte(device, SPD_MODULE_ATTRIBUTES);
Keith Huie089a3f2011-08-02 22:28:14 -0400835
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). */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200850 value = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000851
852 /* Once we have dra, col is done and can be reused.
853 * So it's reused for number of banks.
854 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200855 col = smbus_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
Keith Hui59356ca2010-03-06 18:16:25 +0000856
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
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200978static void 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();
Richard Smithcb8eab42006-07-24 04:25:47 +0000985}
986
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200987static void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000988{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000989 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000990
Uwe Hermann861f9642007-05-28 14:37:06 +0000991 /* 0. Wait until power/voltages and clocks are stable (200us). */
992 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000993
Uwe Hermann861f9642007-05-28 14:37:06 +0000994 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000995 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000996 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +0000997 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000998
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000999 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001000 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001001 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +00001002 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001003
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001004 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001005 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001006 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001007 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +00001008 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001009 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001010
1011 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001012 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001013 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +00001014 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001015
1016 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001017 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001018 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +00001019 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001020
1021 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001022 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Keith Huie9b3fd12020-01-12 18:41:26 -05001023 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1683cef2008-11-27 00:47:07 +00001024 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +00001025 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001026
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001027 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001028 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001029}
Keith Hui078e3242017-07-20 21:14:21 -04001030
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001031/* Implemented under mainboard. */
1032void __weak enable_spd(void) { }
1033void __weak disable_spd(void) { }
1034
Keith Hui078e3242017-07-20 21:14:21 -04001035void sdram_initialize(void)
1036{
Keith Huid6f259e2020-01-12 18:38:28 -05001037 timestamp_add_now(TS_BEFORE_INITRAM);
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001038 enable_spd();
1039
Keith Hui078e3242017-07-20 21:14:21 -04001040 dump_spd_registers();
1041 sdram_set_registers();
1042 sdram_set_spd_registers();
1043 sdram_enable();
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001044
1045 disable_spd();
Keith Huid6f259e2020-01-12 18:38:28 -05001046 timestamp_add_now(TS_AFTER_INITRAM);
Martin Rothe1695e22017-07-24 11:28:50 -06001047}