blob: e2db5e70ea6d6804bfeb8189c338493c6656cbff [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 Hermann1a9c8922007-04-01 17:24:03 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Richard Smithcb8eab42006-07-24 04:25:47 +000014 */
15
Uwe Hermann1a9c8922007-04-01 17:24:03 +000016#include <spd.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000017#include <delay.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000018#include <stdint.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020019#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020020#include <device/pci_ops.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000021#include <device/pci_def.h>
22#include <console/console.h>
Keith Huid6f259e2020-01-12 18:38:28 -050023#include <timestamp.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000024#include "i440bx.h"
Keith Hui59356ca2010-03-06 18:16:25 +000025#include "raminit.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000026
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +020027#include <southbridge/intel/i82371eb/i82371eb.h>
28
Keith Hui9aa45e62017-07-20 21:00:56 -040029/*
30 * Macros and definitions
31 */
Keith Huidf35cdc2010-09-20 23:41:37 +000032
Uwe Hermann1a9c8922007-04-01 17:24:03 +000033/* Debugging macros. */
Julius Wernercd49cce2019-03-05 16:53:33 -080034#if CONFIG(DEBUG_RAM_SETUP)
Keith Hui09f5a742010-12-23 17:12:03 +000035#define PRINT_DEBUG(x...) printk(BIOS_DEBUG, x)
Keith Huidf35cdc2010-09-20 23:41:37 +000036#define DUMPNORTH() dump_pci_device(NB)
Richard Smithcb8eab42006-07-24 04:25:47 +000037#else
Keith Hui09f5a742010-12-23 17:12:03 +000038#define PRINT_DEBUG(x...)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000039#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000040#endif
41
Uwe Hermann1a9c8922007-04-01 17:24:03 +000042/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
43#define RAM_COMMAND_NORMAL 0x0
44#define RAM_COMMAND_NOP 0x1
45#define RAM_COMMAND_PRECHARGE 0x2
46#define RAM_COMMAND_MRS 0x3
47#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000048
Uwe Hermann1a9c8922007-04-01 17:24:03 +000049/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
50 * defined in DRAMC[2:0].
51 *
52 * [0] == Normal 15.625 us -> 15.6 us
53 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
54 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
55 * [3] == Extended(2x) 31.3 us -> 31.2 us
56 * [4] == Extended(4x) 62.5 us -> 62.4 us
57 * [5] == Extended(8x) 125 us -> 124.8 us
58 */
59static const uint32_t refresh_rate_map[] = {
60 1, 5, 5, 2, 3, 4
61};
Richard Smithcb8eab42006-07-24 04:25:47 +000062
Uwe Hermann1a9c8922007-04-01 17:24:03 +000063/* Table format: register, bitmask, value. */
Keith Huidf35cdc2010-09-20 23:41:37 +000064static const u8 register_values[] = {
Uwe Hermann1a9c8922007-04-01 17:24:03 +000065 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000066 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000067 *
68 * [31:24] SDRAM Row Without ECC
69 * 0 = ECC components are populated in this row
70 * 1 = ECC components are not populated in this row
71 * [23:19] Reserved
72 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
73 * Assertion of DRAM data on host bus occurs...
74 * 0 = ...one clock after sampling snoop results (default)
75 * 1 = ...on the same clock the snoop result is being sampled
76 * (this mode is faster by one clock cycle)
77 * [17:17] ECC - EDO static Drive mode
78 * 0 = Normal mode (default)
79 * 1 = ECC signals are always driven
80 * [16:16] IDSEL_REDIRECT
81 * 0 = IDSEL1 is allocated to this bridge (default)
82 * 1 = IDSEL7 is allocated to this bridge
83 * [15:15] WSC# Handshake Disable
84 * 1 = Uni-processor mode
85 * 0 = Dual-processor mode with external IOAPIC (default)
86 * [14:14] Intel Reserved
87 * [13:12] Host/DRAM Frequency
88 * 00 = 100 MHz
89 * 01 = Reserved
90 * 10 = 66 MHz
91 * 11 = Reserved
92 * [11:11] AGP to PCI Access Enable
93 * 1 = Enable
94 * 0 = Disable
95 * [10:10] PCI Agent to Aperture Access Disable
96 * 1 = Disable
97 * 0 = Enable (default)
98 * [09:09] Aperture Access Global Enable
99 * 1 = Enable
100 * 0 = Disable
101 * [08:07] DRAM Data Integrity Mode (DDIM)
102 * 00 = Non-ECC
103 * 01 = EC-only
104 * 10 = ECC Mode
105 * 11 = ECC Mode with hardware scrubbing enabled
106 * [06:06] ECC Diagnostic Mode Enable (EDME)
107 * 1 = Enable
108 * 0 = Normal operation mode (default)
109 * [05:05] MDA Present (MDAP)
110 * Works in conjunction with the VGA_EN bit.
111 * VGA_EN MDAP
112 * 0 x All VGA cycles are sent to PCI
113 * 1 0 All VGA cycles are sent to AGP
114 * 1 1 All VGA cycles are sent to AGP, except for
115 * cycles in the MDA range.
116 * [04:04] Reserved
117 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
118 * 1 = Enable
119 * 0 = Disable
120 * [02:02] In-Order Queue Depth (IOQD)
121 * 1 = In-order queue = maximum
122 * 0 = A7# is sampled asserted (i.e., 0)
123 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000124 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000125 NBXCFG + 0, 0x00, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000126 // TODO: Bit 15 should be 0 for multiprocessor boards
Uwe Hermannbc3594732007-06-07 22:16:30 +0000127 NBXCFG + 1, 0x00, 0x80,
128 NBXCFG + 2, 0x00, 0x00,
129 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000130
131 /* DRAMC - DRAM Control Register
132 * 0x57
133 *
134 * [7:6] Reserved
135 * [5:5] Module Mode Configuration (MMCONFIG)
Keith Huia8380fc2017-12-04 00:05:56 -0500136 * The combination of SDRAMPWR and this bit (set by an
Keith Huidf35cdc2010-09-20 23:41:37 +0000137 * external strapping option) determine how CKE works.
138 * SDRAMPWR MMCONFIG
Keith Huia8380fc2017-12-04 00:05:56 -0500139 * 0 0 = 3 DIMM, CKE[5:0] driven
140 * X 1 = 3 DIMM, CKE0 only
141 * 1 0 = 4 DIMM, GCKE only
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000142 * [4:3] DRAM Type (DT)
143 * 00 = EDO
144 * 01 = SDRAM
145 * 10 = Registered SDRAM
146 * 11 = Reserved
147 * Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
148 * [2:0] DRAM Refresh Rate (DRR)
149 * 000 = Refresh disabled
150 * 001 = 15.6 us
151 * 010 = 31.2 us
152 * 011 = 62.4 us
153 * 100 = 124.8 us
154 * 101 = 249.6 us
155 * 110 = Reserved
156 * 111 = Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000157 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000158 /* Choose SDRAM (not registered), and disable refresh for now. */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000159 DRAMC, 0x00, 0x08,
Richard Smithcb8eab42006-07-24 04:25:47 +0000160
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000161 /*
162 * PAM[6:0] - Programmable Attribute Map Registers
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000163 * 0x59 - 0x5f
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000164 *
165 * 0x59 [3:0] Reserved
166 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
167 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
168 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
169 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
170 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
171 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
172 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
173 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
174 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
Martin Roth128c1042016-11-18 09:29:03 -0700175 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS extension
176 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS extension
177 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS extension
178 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS extension
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000179 *
180 * Bit assignment:
181 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
182 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
183 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
184 * 11 = Read/Write (all access goes to DRAM)
185 */
Keith Hui59356ca2010-03-06 18:16:25 +0000186
187 /*
188 * Map all legacy regions to RAM (read/write). This is required if
189 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
190 * registers are not set here appropriately, the RAM in that region
191 * will not be accessible, thus a RAM check of it will also fail.
Keith Hui59356ca2010-03-06 18:16:25 +0000192 */
193 PAM0, 0x00, 0x30,
194 PAM1, 0x00, 0x33,
195 PAM2, 0x00, 0x33,
196 PAM3, 0x00, 0x33,
197 PAM4, 0x00, 0x33,
198 PAM5, 0x00, 0x33,
199 PAM6, 0x00, 0x33,
Richard Smithcb8eab42006-07-24 04:25:47 +0000200
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000201 /* DRB[0:7] - DRAM Row Boundary Registers
202 * 0x60 - 0x67
203 *
204 * An array of 8 byte registers, which hold the ending memory address
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000205 * assigned to each pair of DIMMs, in 8MB granularity.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000206 *
207 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
208 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
209 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
210 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
211 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
212 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
213 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
214 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
215 */
Keith Huia8380fc2017-12-04 00:05:56 -0500216 /* DRBs will be set later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000217 DRB0, 0x00, 0x00,
218 DRB1, 0x00, 0x00,
219 DRB2, 0x00, 0x00,
220 DRB3, 0x00, 0x00,
221 DRB4, 0x00, 0x00,
222 DRB5, 0x00, 0x00,
223 DRB6, 0x00, 0x00,
224 DRB7, 0x00, 0x00,
225
226 /* FDHC - Fixed DRAM Hole Control Register
227 * 0x68
228 *
229 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
230 *
231 * [7:6] Hole Enable (HEN)
232 * 00 = None
233 * 01 = 512 KB - 640 KB (128 KB)
234 * 10 = 15 MB - 16 MB (1 MB)
235 * 11 = Reserved
236 * [5:0] Reserved
237 */
238 /* No memory holes. */
239 FDHC, 0x00, 0x00,
240
241 /* RPS - SDRAM Row Page Size Register
242 * 0x74 - 0x75
243 *
244 * Sets the row page size for SDRAM. For EDO memory, the page
245 * size is fixed at 2 KB.
246 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000247 * Bits[1:0] Page Size
248 * 00 2 KB
249 * 01 4 KB
250 * 10 8 KB
251 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400252 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000253 * RPS bits Corresponding DRB register
254 * [01:00] DRB[0], row 0
255 * [03:02] DRB[1], row 1
256 * [05:04] DRB[2], row 2
257 * [07:06] DRB[3], row 3
258 * [09:08] DRB[4], row 4
259 * [11:10] DRB[5], row 5
260 * [13:12] DRB[6], row 6
261 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000262 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000263 /* Power on defaults to 2KB. Will be set later. */
264 // RPS + 0, 0x00, 0x00,
265 // RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000266
267 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000268 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000269 *
270 * [15:10] Reserved
271 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
272 * 00 = Illegal
273 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000274 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000275 * [07:05] SDRAM Mode Select (SMS)
276 * 000 = Normal SDRAM Operation (default)
277 * 001 = NOP Command Enable
278 * 010 = All Banks Precharge Enable
279 * 011 = Mode Register Set Enable
280 * 100 = CBR Enable
281 * 101 = Reserved
282 * 110 = Reserved
283 * 111 = Reserved
284 * [04:04] SDRAMPWR
285 * 0 = 3 DIMM configuration
286 * 1 = 4 DIMM configuration
287 * [03:03] Leadoff Command Timing (LCT)
288 * 0 = 4 CS# Clock
289 * 1 = 3 CS# Clock
290 * [02:02] CAS# Latency (CL)
291 * 0 = 3 DCLK CAS# latency
292 * 1 = 2 DCLK CAS# latency
293 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
294 * 0 = 3 clocks between a row activate and a read or write cmd.
295 * 1 = 2 clocks between a row activate and a read or write cmd.
296 * [00:00] SDRAM RAS# Precharge (SRP)
297 * 0 = 3 clocks of RAS# precharge
298 * 1 = 2 clocks of RAS# precharge
299 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800300#if CONFIG(SDRAMPWR_4DIMM)
Keith Hui9c1e1f02010-03-13 20:16:48 +0000301 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
302#else
Keith Huidf35cdc2010-09-20 23:41:37 +0000303 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000304#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000305
306 /* PGPOL - Paging Policy Register
307 * 0x78 - 0x79
308 *
309 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000310 * Each bit in this field corresponds to one row of the memory
311 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
312 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000313 * 0 = 2 banks
314 * 1 = 4 banks
315 * [07:05] Reserved
316 * [04:04] Intel Reserved
317 * [03:00] DRAM Idle Timer (DIT)
318 * 0000 = 0 clocks
319 * 0001 = 2 clocks
320 * 0010 = 4 clocks
321 * 0011 = 8 clocks
322 * 0100 = 10 clocks
323 * 0101 = 12 clocks
324 * 0110 = 16 clocks
325 * 0111 = 32 clocks
326 * 1xxx = Infinite (pages are not closed for idle condition)
327 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000328 PGPOL + 0, 0x00, 0x00,
329 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000330
331 /* PMCR - Power Management Control Register
332 * 0x7a
333 *
334 * [07:07] Power Down SDRAM Enable (PDSE)
335 * 1 = Enable
336 * 0 = Disable
337 * [06:06] ACPI Control Register Enable (SCRE)
338 * 1 = Enable
339 * 0 = Disable (default)
340 * [05:05] Suspend Refresh Type (SRT)
341 * 1 = Self refresh mode
342 * 0 = CBR fresh mode
343 * [04:04] Normal Refresh Enable (NREF_EN)
344 * 1 = Enable
345 * 0 = Disable
346 * [03:03] Quick Start Mode (QSTART)
347 * 1 = Quick start mode for the processor is enabled
348 * [02:02] Gated Clock Enable (GCLKEN)
349 * 1 = Enable
350 * 0 = Disable
351 * [01:01] AGP Disable (AGP_DIS)
352 * 1 = Disable
353 * 0 = Enable
354 * [00:00] CPU reset without PCIRST enable (CRst_En)
355 * 1 = Enable
356 * 0 = Disable
357 */
Keith Huie9b3fd12020-01-12 18:41:26 -0500358 /* PMCR will be set later. */
Keith Hui59356ca2010-03-06 18:16:25 +0000359
360 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
361 SCRR + 1, 0x00, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000362};
363
364/*-----------------------------------------------------------------------------
365SDRAM configuration functions.
366-----------------------------------------------------------------------------*/
367
368/**
369 * Send the specified RAM command to all DIMMs.
370 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000371 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000372 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000373static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000374{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000375 int i, caslatency;
376 u8 dimm_start, dimm_end;
377 u16 reg16;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800378 void *addr;
379 u32 addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000380
381 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000382 reg16 = pci_read_config16(NB, SDRAMC);
383 reg16 &= 0xff1f; /* Clear bits 7-5. */
384 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
385 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000386
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000387 /*
388 * RAM_COMMAND_NORMAL affects only the memory controller and
389 * doesn't need to be "sent" to the DIMMs.
390 */
391 if (command == RAM_COMMAND_NORMAL)
392 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000393
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000394 /* Send the RAM command to each row of memory. */
395 dimm_start = 0;
396 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000397 addr_offset = 0;
398 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000399 if (command == RAM_COMMAND_MRS) {
400 /*
401 * MAA[12:11,9:0] must be inverted when sent to DIMM
402 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
403 */
404 if ((i >= 0 && i <= 3) && caslatency == 3)
405 addr_offset = 0x1d0;
406 if ((i >= 4 && i <= 7) && caslatency == 3)
407 addr_offset = 0x1e28;
408 if ((i >= 0 && i <= 3) && caslatency == 2)
409 addr_offset = 0x150;
410 if ((i >= 4 && i <= 7) && caslatency == 2)
411 addr_offset = 0x1ea8;
412 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000413
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000414 dimm_end = pci_read_config8(NB, DRB + i);
415
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800416 addr = (void *)((dimm_start * 8 * 1024 * 1024) + addr_offset);
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000417 if (dimm_end > dimm_start) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000418 read32(addr);
419 }
420
421 /* Set the start of the next DIMM. */
422 dimm_start = dimm_end;
423 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000424}
425
Keith Hui59356ca2010-03-06 18:16:25 +0000426static void set_dram_buffer_strength(void)
427{
Keith Huia8380fc2017-12-04 00:05:56 -0500428 /*
429 * Program MBSC[39:0] and MBFS[23:0].
430 *
431 * The 440BX datasheet says buffer frequency is independent from bus
432 * frequency and mismatch both ways are possible.
433 *
434 * MBSC[47:40] and MBFS[23] are reserved.
Keith Hui59356ca2010-03-06 18:16:25 +0000435 */
436
Keith Huia8380fc2017-12-04 00:05:56 -0500437 unsigned int i, reg, drb;
438 uint8_t mbsc0, mbfs0, mbfs1, mbfs2;
439 uint16_t mbsc1, mbsc3;
440
441 /*
442 * Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000443 * This determines how to program MBFS and MBSC.
444 */
445 uint8_t dimm03 = 0;
446 uint8_t dimm47 = 0;
447
Keith Huia8380fc2017-12-04 00:05:56 -0500448 for (drb = 0, i = DRB0; i <= DRB7; i++) {
449 reg = pci_read_config8(NB, i);
450 if (drb != reg) {
451 if (i <= DRB3)
Keith Huib48ba662010-03-17 02:15:07 +0000452 dimm03++;
Keith Huia8380fc2017-12-04 00:05:56 -0500453 else
Keith Huib48ba662010-03-17 02:15:07 +0000454 dimm47++;
Keith Huia8380fc2017-12-04 00:05:56 -0500455
456 drb = reg;
Keith Huib48ba662010-03-17 02:15:07 +0000457 }
458 }
459
Julius Wernercd49cce2019-03-05 16:53:33 -0800460 if (CONFIG(SDRAMPWR_4DIMM)) {
Keith Huia8380fc2017-12-04 00:05:56 -0500461 /*
462 * For a 4 DIMM board, based on ASUS P2B-LS mainboard.
Keith Huib48ba662010-03-17 02:15:07 +0000463 *
Keith Huia8380fc2017-12-04 00:05:56 -0500464 * There are four main conditions to check when programming
465 * DRAM buffer frequency and strength:
Keith Huib48ba662010-03-17 02:15:07 +0000466 *
467 * a: >2 rows populated across DIMM0,1
468 * b: >2 rows populated across DIMM2,3
469 * c: >4 rows populated across all DIMM slots
470 * and either one of:
471 * 1: NBXCFG[13] strapped as 100MHz, or
472 * 6: NBXCFG[13] strapped as 66MHz
473 *
474 * CKE0/FENA ----------------------------------------------------------+
Keith Huia8380fc2017-12-04 00:05:56 -0500475 * CKE1/GCKE ----------------------[ MBFS ]---------------------+|
476 * DQMA/CASA[764320]# -------------[ 0 = 66MHz ]--------------------+||
477 * DQMB1/CASB1# (Fixed for 66MHz) -[ 1 = 100MHz ]-------------------+|||
478 * DQMB5/CASB5# (Fixed for 66MHz) ---------------------------------+||||
479 * DQMA1/CASA1# (Fixed for 66MHz) --------------------------------+|||||
480 * DQMA5/CASA5# (Fixed for 66MHz) -------------------------------+||||||
481 * CSA[5:0]#,CSB[5:0]# ------------------------------------++++++|||||||
482 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
483 * MECC[7:0] #2/#1 ----------------------------------++|||||||||||||||||
484 * MD[63:0] #2/#1 ---------------------------------++|||||||||||||||||||
485 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
486 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
487 * Reserved ------------------------------------+|||||||||||||||||||||||
488 * ||||||||||||||||||||||||
489 * 3 32 21 10 0 * 2 21 10 0
490 * 9876543210987654321098765432109876543210 * 321098765432109876543210
491 * 10------------------------1010---------- a -1---------------11-----
492 * 11------------------------1111---------- !a -0---------------00-----
493 * --10--------------------------1010------ b --1----------------11---
494 * --11--------------------------1111------ !b --0----------------00---
495 * ----------------------------------1100-- c ----------------------1-
496 * ----------------------------------1011-- !c ----------------------0-
497 * ----1010101000000000000000------------00 1 ---11111111111111----1-0
498 * ----000000000000000000000010101010----00 6 ---1111111111111100000-0
499 * | | | | | | | | | | ||||||| | | | | | |
500 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
501 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
502 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
503 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# (66MHz: 2x)
504 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# (66MHz: 2x)
505 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# (66MHz: 2x)
506 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# (66MHz: 2x)
507 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (1x)
508 * | | | | | | | | | +--------------------- CSA6#/CKE2
509 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
510 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
511 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
512 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1
513 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2
514 * | | | +--------------------------------- MD[63:0] #1
515 * | | +----------------------------------- MD[63:0] #2
516 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
517 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
518 */
519 unsigned int fsb;
520
521 mbsc0 = 0xa0;
522 mbsc1 = 0x002a;
523 mbfs1 = 0xff;
524 mbfs2 = 0x1f;
525 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
526 fsb = 66;
527 mbsc3 = 0xa000;
528 mbfs0 = 0x80;
529 } else {
530 fsb = 100;
531 mbsc3 = 0xaaa0;
532 mbfs0 = 0x84;
533 }
534 if (dimm03 > 2) {
535 mbfs2 |= 0x40;
536 if (fsb == 100)
537 mbfs0 |= 0x60;
538 } else {
539 mbsc3 |= 0xc000;
540 if (fsb == 100)
541 mbsc1 |= 0x003c;
542 }
543 if (dimm47 > 2) {
544 mbfs2 |= 0x20;
545 if (fsb == 100)
546 mbfs0 |= 0x18;
547 } else {
548 mbsc3 |= 0x3000;
549 if (fsb == 100) {
550 mbsc1 |= 0x0003;
551 mbsc0 |= 0xc0;
552 }
553 }
554 if ((dimm03 + dimm47) > 4) {
555 mbsc0 |= 0x30;
556 mbfs0 |= 0x02;
557 } else {
558 mbsc0 |= 0x2c;
559 }
560 } else {
561 /*
562 * For a 3 DIMM board, based on ASUS P2B mainboard.
563 *
564 * There are two main conditions to check when programming DRAM buffer
565 * frequency and strength:
566 *
567 * a: >2 rows populated across DIMM0,1
568 * c: >4 rows populated across all DIMM slots
569 *
570 * CKE0 ---------------------------------------------------------------+
571 * CKE1 ------------------------[ MBFS ]------------------------+|
Keith Huib48ba662010-03-17 02:15:07 +0000572 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
573 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
574 * DQMB5/CASB5# ---------------------------------------------------+||||
575 * DQMA1/CASA1# --------------------------------------------------+|||||
576 * DQMA5/CASA5# -------------------------------------------------+||||||
577 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500578 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
Keith Huib48ba662010-03-17 02:15:07 +0000579 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
580 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
581 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
582 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
583 * Reserved ------------------------------------+|||||||||||||||||||||||
584 * ||||||||||||||||||||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500585 * 3 32 21 10 0 * 2 21 10 0
586 * 9876543210987654321098765432109876543210 * 321098765432109876543210
587 * 10------------------------1111---------- a -1----------------------
588 * 11------------------------1010---------- !a -0----------------------
589 * --110000000010101010111111----1010--1010 * --01111000000000000000-0
590 * ----------------------------------11---- c ----------------------1-
591 * ----------------------------------10---- !c ----------------------0-
592 * | | | | | | | | | | ||||||| | | | | | |
593 * | | | | | | | | | | ||||||| | | | | | +- CKE0
594 * | | | | | | | | | | ||||||| | | | | +--- CKE1
595 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
596 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
597 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
598 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
599 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
600 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (2x)
601 * | | | | | | | | | +--------------------- CSA6#/CKE2
602 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
603 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
604 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
605 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (1x)
606 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (1x)
607 * | | | +--------------------------------- MD[63:0] #1 (1x)
608 * | | +----------------------------------- MD[63:0] #2 (1x)
609 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
610 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
Keith Huib48ba662010-03-17 02:15:07 +0000611 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000612
Keith Huia8380fc2017-12-04 00:05:56 -0500613 mbsc0 = 0xaa;
614 mbsc1 = 0xafea;
615 mbsc3 = 0xb00a;
616 mbfs0 = 0x00;
617 mbfs1 = 0x00;
618 mbfs2 = 0x1e;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000619
Keith Huia8380fc2017-12-04 00:05:56 -0500620 if (dimm03 > 2) {
621 mbsc1 |= 0x003c;
622 mbfs2 |= 0x40;
623 } else {
624 mbsc3 |= 0xc000;
Keith Huib48ba662010-03-17 02:15:07 +0000625 }
Keith Huia8380fc2017-12-04 00:05:56 -0500626 if ((dimm03 + dimm47) > 4) {
627 mbsc0 |= 0x30;
628 mbfs0 |= 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000629 }
630 }
Keith Huib48ba662010-03-17 02:15:07 +0000631
632 pci_write_config8(NB, MBSC + 0, mbsc0);
Keith Huia8380fc2017-12-04 00:05:56 -0500633 pci_write_config16(NB, MBSC + 1, mbsc1);
634 pci_write_config16(NB, MBSC + 3, mbsc3);
635 pci_write_config16(NB, MBFS + 0, mbfs1 << 8 | mbfs0);
Keith Huib48ba662010-03-17 02:15:07 +0000636 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000637}
638
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000639/*-----------------------------------------------------------------------------
Martin Roth128c1042016-11-18 09:29:03 -0700640DIMM-independent configuration functions.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000641-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000642
Uwe Hermann1683cef2008-11-27 00:47:07 +0000643static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000644{
645 int i, value;
646 uint8_t reg;
647
Uwe Hermann1683cef2008-11-27 00:47:07 +0000648 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000649
650 for (i = 0; i < DIMM_SOCKETS; i++) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200651 value = smbus_read_byte(DIMM0 + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000652 if (value < 0)
653 continue;
654 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
655
Keith Hui09f5a742010-12-23 17:12:03 +0000656 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000657 }
658
Uwe Hermann1683cef2008-11-27 00:47:07 +0000659 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000660}
661
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000662/*-----------------------------------------------------------------------------
663Public interface.
664-----------------------------------------------------------------------------*/
665
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200666static void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000667{
668 int i, max;
Uwe Hermannbc3594732007-06-07 22:16:30 +0000669 uint8_t reg;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000670
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000671 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000672 DUMPNORTH();
673
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000674 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000675
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000676 /* Set registers as specified in the register_values[] array. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000677 for (i = 0; i < max; i += 3) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000678 reg = pci_read_config8(NB, register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000679 reg &= register_values[i + 1];
680 reg |= register_values[i + 2] & ~(register_values[i + 1]);
Uwe Hermann1683cef2008-11-27 00:47:07 +0000681 pci_write_config8(NB, register_values[i], reg);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000682 }
683}
684
Keith Hui59356ca2010-03-06 18:16:25 +0000685struct dimm_size {
Keith Hui09f5a742010-12-23 17:12:03 +0000686 u32 side1;
687 u32 side2;
Keith Hui59356ca2010-03-06 18:16:25 +0000688};
689
690static struct dimm_size spd_get_dimm_size(unsigned int device)
691{
692 struct dimm_size sz;
693 int i, module_density, dimm_banks;
694 sz.side1 = 0;
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200695 module_density = smbus_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
696 dimm_banks = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000697
698 /* Find the size of side1. */
699 /* Find the larger value. The larger value is always side1. */
700 for (i = 512; i >= 0; i >>= 1) {
701 if ((module_density & i) == i) {
702 sz.side1 = i;
703 break;
704 }
705 }
706
707 /* Set to 0 in case it's single sided. */
708 sz.side2 = 0;
709
710 /* Test if it's a dual-sided DIMM. */
711 if (dimm_banks > 1) {
712 /* Test if there's a second value. If so it's asymmetrical. */
713 if (module_density != i) {
714 /*
715 * Find second value, picking up where we left off.
716 * i >>= 1 done initially to make sure we don't get
717 * the same value again.
718 */
719 for (i >>= 1; i >= 0; i >>= 1) {
720 if (module_density == (sz.side1 | i)) {
721 sz.side2 = i;
722 break;
723 }
724 }
725 /* If not, it's symmetrical. */
726 } else {
727 sz.side2 = sz.side1;
728 }
729 }
730
731 /*
732 * SPD byte 31 is the memory size divided by 4 so we
Martin Roth128c1042016-11-18 09:29:03 -0700733 * need to multiply by 4 to get the total size.
Keith Hui59356ca2010-03-06 18:16:25 +0000734 */
735 sz.side1 *= 4;
736 sz.side2 *= 4;
737
Keith Huia8380fc2017-12-04 00:05:56 -0500738 /*
739 * It is possible to partially use larger than supported
Anders Jenbo771b0e42010-04-27 08:45:30 +0000740 * modules by setting them to a supported size.
741 */
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200742 if (sz.side1 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000743 PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
744 sz.side1);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000745 sz.side1 = 128;
746
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200747 if (sz.side2 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000748 PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
749 sz.side2);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000750 sz.side2 = 128;
751 }
752 }
753
Keith Hui59356ca2010-03-06 18:16:25 +0000754 return sz;
755}
756/*
757 * Sets DRAM attributes one DIMM at a time, based on SPD data.
758 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
759 */
760static void set_dram_row_attributes(void)
761{
Keith Huie089a3f2011-08-02 22:28:14 -0400762 int i, dra, drb, col, width, value, rps;
Keith Hui59356ca2010-03-06 18:16:25 +0000763 u8 bpr; /* Top 8 bits of PGPOL */
Keith Huie089a3f2011-08-02 22:28:14 -0400764 u8 nbxecc = 0; /* NBXCFG[31:24] */
765 u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
Keith Hui59356ca2010-03-06 18:16:25 +0000766
Keith Huie089a3f2011-08-02 22:28:14 -0400767 edo = 0;
768 sd = 0;
769 regsd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000770 rps = 0;
771 drb = 0;
772 bpr = 0;
Keith Hui59356ca2010-03-06 18:16:25 +0000773
774 for (i = 0; i < DIMM_SOCKETS; i++) {
775 unsigned int device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000776 device = DIMM0 + i;
Keith Hui59356ca2010-03-06 18:16:25 +0000777 bpr >>= 2;
Keith Huie089a3f2011-08-02 22:28:14 -0400778 nbxecc >>= 2;
Keith Hui59356ca2010-03-06 18:16:25 +0000779
780 /* First check if a DIMM is actually present. */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200781 value = smbus_read_byte(device, SPD_MEMORY_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000782 /* This is 440BX! We do EDO too! */
783 if (value == SPD_MEMORY_TYPE_EDO
784 || value == SPD_MEMORY_TYPE_SDRAM) {
785
Keith Hui59356ca2010-03-06 18:16:25 +0000786 if (value == SPD_MEMORY_TYPE_EDO) {
Keith Huie089a3f2011-08-02 22:28:14 -0400787 edo = 1;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000788 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
Keith Huie089a3f2011-08-02 22:28:14 -0400789 sd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000790 }
Keith Hui09f5a742010-12-23 17:12:03 +0000791 PRINT_DEBUG("Found DIMM in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000792
Keith Huie089a3f2011-08-02 22:28:14 -0400793 if (edo && sd) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800794 printk(BIOS_ERR, "Mixing EDO/SDRAM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000795 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000796 }
797
798 /* "DRA" is our RPS for the two rows on this DIMM. */
799 dra = 0;
800
801 /* Columns */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200802 col = smbus_read_byte(device, SPD_NUM_COLUMNS);
Keith Hui59356ca2010-03-06 18:16:25 +0000803
804 /*
805 * Is this an ECC DIMM? Actually will be a 2 if so.
806 * TODO: Other register than NBXCFG also needs this
807 * ECC information.
808 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200809 value = smbus_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000810
811 /* Data width */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200812 width = smbus_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000813
Keith Hui59356ca2010-03-06 18:16:25 +0000814 /* Exclude error checking data width from page size calculations */
Keith Huie089a3f2011-08-02 22:28:14 -0400815 if (value) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200816 value = smbus_read_byte(device,
Keith Hui59356ca2010-03-06 18:16:25 +0000817 SPD_ERROR_CHECKING_SDRAM_WIDTH);
818 width -= value;
819 /* ### ECC */
820 /* Clear top 2 bits to help set up NBXCFG. */
Keith Huie089a3f2011-08-02 22:28:14 -0400821 nbxecc &= 0x3f;
Keith Hui59356ca2010-03-06 18:16:25 +0000822 } else {
823 /* Without ECC, top 2 bits should be 11. */
Keith Huie089a3f2011-08-02 22:28:14 -0400824 nbxecc |= 0xc0;
Keith Hui59356ca2010-03-06 18:16:25 +0000825 }
826
Keith Huie089a3f2011-08-02 22:28:14 -0400827 /* If any installed DIMM is *not* registered, this system cannot be
828 * configured for registered SDRAM.
829 * By registered, only the address and control lines need to be, which
830 * we can tell by reading SPD byte 21, bit 1.
831 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200832 value = smbus_read_byte(device, SPD_MODULE_ATTRIBUTES);
Keith Huie089a3f2011-08-02 22:28:14 -0400833
834 PRINT_DEBUG("DIMM is ");
835 if ((value & MODULE_REGISTERED) == 0) {
836 regsd = 0;
837 PRINT_DEBUG("not ");
838 }
839 PRINT_DEBUG("registered\n");
840
Keith Hui59356ca2010-03-06 18:16:25 +0000841 /* Calculate page size in bits. */
842 value = ((1 << col) * width);
843
844 /* Convert to KB. */
845 dra = (value >> 13);
846
847 /* Number of banks of DIMM (single or double sided). */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200848 value = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000849
850 /* Once we have dra, col is done and can be reused.
851 * So it's reused for number of banks.
852 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200853 col = smbus_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
Keith Hui59356ca2010-03-06 18:16:25 +0000854
855 if (value == 1) {
856 /*
857 * Second bank of 1-bank DIMMs "doesn't have
858 * ECC" - or anything.
859 */
Keith Hui59356ca2010-03-06 18:16:25 +0000860 if (dra == 2) {
861 dra = 0x0; /* 2KB */
862 } else if (dra == 4) {
863 dra = 0x1; /* 4KB */
864 } else if (dra == 8) {
865 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000866 } else if (dra >= 16) {
867 /* Page sizes larger than supported are
868 * set to 8KB to use module partially.
869 */
870 PRINT_DEBUG("Page size forced to 8KB.\n");
871 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000872 } else {
873 dra = -1;
874 }
875 /*
876 * Sets a flag in PGPOL[BPR] if this DIMM has
877 * 4 banks per row.
878 */
879 if (col == 4)
880 bpr |= 0x40;
881 } else if (value == 2) {
882 if (dra == 2) {
883 dra = 0x0; /* 2KB */
884 } else if (dra == 4) {
885 dra = 0x05; /* 4KB */
886 } else if (dra == 8) {
887 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000888 } else if (dra >= 16) {
889 /* Ditto */
890 PRINT_DEBUG("Page size forced to 8KB.\n");
891 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000892 } else {
893 dra = -1;
894 }
895 /* Ditto */
896 if (col == 4)
897 bpr |= 0xc0;
898 } else {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800899 printk(BIOS_ERR, "# of banks of DIMM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000900 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000901 }
902 if (dra == -1) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800903 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000904 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000905 }
906
907 /*
908 * 440BX supports asymmetrical dual-sided DIMMs,
909 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000910 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000911 */
912 struct dimm_size sz = spd_get_dimm_size(device);
913 if ((sz.side1 < 8)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800914 printk(BIOS_ERR, "DIMMs smaller than 8MB per side\n"
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000915 "are not supported on this NB.\n");
916 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000917 }
Keith Hui59356ca2010-03-06 18:16:25 +0000918
919 /* Divide size by 8 to set up the DRB registers. */
920 drb += (sz.side1 / 8);
921
922 /*
923 * Build the DRB for the next row in MSB so it gets
924 * placed in DRB[n+1] where it belongs when written
925 * as a 16-bit word.
926 */
927 drb &= 0xff;
928 drb |= (drb + (sz.side2 / 8)) << 8;
929 } else {
Keith Hui59356ca2010-03-06 18:16:25 +0000930 /* If there's no DIMM in the slot, set dra to 0x00. */
931 dra = 0x00;
Keith Hui59356ca2010-03-06 18:16:25 +0000932 /* Still have to propagate DRB over. */
933 drb &= 0xff;
934 drb |= (drb << 8);
935 }
936
937 pci_write_config16(NB, DRB + (2 * i), drb);
Keith Hui59356ca2010-03-06 18:16:25 +0000938
939 /* Brings the upper DRB back down to be base for
940 * DRB calculations for the next two rows.
941 */
942 drb >>= 8;
943
944 rps |= (dra & 0x0f) << (i * 4);
Keith Hui59356ca2010-03-06 18:16:25 +0000945 }
946
947 /* Set paging policy register. */
948 pci_write_config8(NB, PGPOL + 1, bpr);
Keith Hui09f5a742010-12-23 17:12:03 +0000949 PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
Keith Hui59356ca2010-03-06 18:16:25 +0000950
951 /* Set DRAM row page size register. */
952 pci_write_config16(NB, RPS, rps);
Keith Hui09f5a742010-12-23 17:12:03 +0000953 PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
Keith Hui59356ca2010-03-06 18:16:25 +0000954
955 /* ### ECC */
956 pci_write_config8(NB, NBXCFG + 3, nbxecc);
Keith Hui09f5a742010-12-23 17:12:03 +0000957 PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
Keith Hui59356ca2010-03-06 18:16:25 +0000958
Keith Huie089a3f2011-08-02 22:28:14 -0400959 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
Keith Hui59356ca2010-03-06 18:16:25 +0000960
Keith Huie089a3f2011-08-02 22:28:14 -0400961 /* i will be used to set DRAMC[4:3]. */
962 if (regsd && sd) {
963 i = 0x10; // Registered SDRAM
964 } else if (sd) {
965 i = 0x08; // SDRAM
966 } else {
967 i = 0; // EDO
968 }
969
Keith Hui59356ca2010-03-06 18:16:25 +0000970 value = pci_read_config8(NB, DRAMC) & 0xe7;
Keith Huie089a3f2011-08-02 22:28:14 -0400971 value |= i;
Keith Hui59356ca2010-03-06 18:16:25 +0000972 pci_write_config8(NB, DRAMC, value);
Keith Hui09f5a742010-12-23 17:12:03 +0000973 PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
Keith Hui59356ca2010-03-06 18:16:25 +0000974}
975
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200976static void sdram_set_spd_registers(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000977{
Keith Hui59356ca2010-03-06 18:16:25 +0000978 /* Setup DRAM row boundary registers and other attributes. */
979 set_dram_row_attributes();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000980
Keith Huidf35cdc2010-09-20 23:41:37 +0000981 /* Setup DRAM buffer strength. */
Keith Hui59356ca2010-03-06 18:16:25 +0000982 set_dram_buffer_strength();
Richard Smithcb8eab42006-07-24 04:25:47 +0000983}
984
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200985static void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000986{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000987 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000988
Uwe Hermann861f9642007-05-28 14:37:06 +0000989 /* 0. Wait until power/voltages and clocks are stable (200us). */
990 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000991
Uwe Hermann861f9642007-05-28 14:37:06 +0000992 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000993 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000994 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +0000995 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000996
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000997 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000998 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000999 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +00001000 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001001
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001002 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001003 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001004 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001005 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +00001006 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001007 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001008
1009 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001010 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001011 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +00001012 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001013
1014 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001015 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001016 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +00001017 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001018
1019 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001020 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Keith Huie9b3fd12020-01-12 18:41:26 -05001021 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1683cef2008-11-27 00:47:07 +00001022 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +00001023 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001024
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001025 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001026 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001027}
Keith Hui078e3242017-07-20 21:14:21 -04001028
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001029/* Implemented under mainboard. */
1030void __weak enable_spd(void) { }
1031void __weak disable_spd(void) { }
1032
Keith Hui078e3242017-07-20 21:14:21 -04001033void sdram_initialize(void)
1034{
Keith Huid6f259e2020-01-12 18:38:28 -05001035 timestamp_add_now(TS_BEFORE_INITRAM);
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001036 enable_spd();
1037
Keith Hui078e3242017-07-20 21:14:21 -04001038 dump_spd_registers();
1039 sdram_set_registers();
1040 sdram_set_spd_registers();
1041 sdram_enable();
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001042
1043 disable_spd();
Keith Huid6f259e2020-01-12 18:38:28 -05001044 timestamp_add_now(TS_AFTER_INITRAM);
Martin Rothe1695e22017-07-24 11:28:50 -06001045}