blob: dddcc217f4ee33cf6346370bf65624194b12daf1 [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
Keith Hui8bd784e2020-04-05 14:54:22 -040063/* Table format: register, 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 */
Keith Hui8bd784e2020-04-05 14:54:22 -0400125 NBXCFG + 0, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000126 // TODO: Bit 15 should be 0 for multiprocessor boards
Keith Hui8bd784e2020-04-05 14:54:22 -0400127 NBXCFG + 1, 0x80,
128 NBXCFG + 2, 0x00,
129 NBXCFG + 3, 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. */
Keith Hui8bd784e2020-04-05 14:54:22 -0400159 DRAMC, 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 */
Keith Hui8bd784e2020-04-05 14:54:22 -0400193 PAM0, 0x30,
194 PAM1, 0x33,
195 PAM2, 0x33,
196 PAM3, 0x33,
197 PAM4, 0x33,
198 PAM5, 0x33,
199 PAM6, 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
218 /* FDHC - Fixed DRAM Hole Control Register
219 * 0x68
220 *
221 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
222 *
223 * [7:6] Hole Enable (HEN)
224 * 00 = None
225 * 01 = 512 KB - 640 KB (128 KB)
226 * 10 = 15 MB - 16 MB (1 MB)
227 * 11 = Reserved
228 * [5:0] Reserved
229 */
230 /* No memory holes. */
Keith Hui8bd784e2020-04-05 14:54:22 -0400231 FDHC, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000232
233 /* RPS - SDRAM Row Page Size Register
234 * 0x74 - 0x75
235 *
236 * Sets the row page size for SDRAM. For EDO memory, the page
237 * size is fixed at 2 KB.
238 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000239 * Bits[1:0] Page Size
240 * 00 2 KB
241 * 01 4 KB
242 * 10 8 KB
243 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400244 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000245 * RPS bits Corresponding DRB register
246 * [01:00] DRB[0], row 0
247 * [03:02] DRB[1], row 1
248 * [05:04] DRB[2], row 2
249 * [07:06] DRB[3], row 3
250 * [09:08] DRB[4], row 4
251 * [11:10] DRB[5], row 5
252 * [13:12] DRB[6], row 6
253 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000254 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000255 /* Power on defaults to 2KB. Will be set later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000256
257 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000258 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000259 *
260 * [15:10] Reserved
261 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
262 * 00 = Illegal
263 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000264 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000265 * [07:05] SDRAM Mode Select (SMS)
266 * 000 = Normal SDRAM Operation (default)
267 * 001 = NOP Command Enable
268 * 010 = All Banks Precharge Enable
269 * 011 = Mode Register Set Enable
270 * 100 = CBR Enable
271 * 101 = Reserved
272 * 110 = Reserved
273 * 111 = Reserved
274 * [04:04] SDRAMPWR
275 * 0 = 3 DIMM configuration
276 * 1 = 4 DIMM configuration
277 * [03:03] Leadoff Command Timing (LCT)
278 * 0 = 4 CS# Clock
279 * 1 = 3 CS# Clock
280 * [02:02] CAS# Latency (CL)
281 * 0 = 3 DCLK CAS# latency
282 * 1 = 2 DCLK CAS# latency
283 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
284 * 0 = 3 clocks between a row activate and a read or write cmd.
285 * 1 = 2 clocks between a row activate and a read or write cmd.
286 * [00:00] SDRAM RAS# Precharge (SRP)
287 * 0 = 3 clocks of RAS# precharge
288 * 1 = 2 clocks of RAS# precharge
289 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800290#if CONFIG(SDRAMPWR_4DIMM)
Keith Hui8bd784e2020-04-05 14:54:22 -0400291 SDRAMC, 0x10, /* The board has 4 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000292#else
Keith Hui8bd784e2020-04-05 14:54:22 -0400293 SDRAMC, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000294#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000295
296 /* PGPOL - Paging Policy Register
297 * 0x78 - 0x79
298 *
299 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000300 * Each bit in this field corresponds to one row of the memory
301 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
302 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000303 * 0 = 2 banks
304 * 1 = 4 banks
305 * [07:05] Reserved
306 * [04:04] Intel Reserved
307 * [03:00] DRAM Idle Timer (DIT)
308 * 0000 = 0 clocks
309 * 0001 = 2 clocks
310 * 0010 = 4 clocks
311 * 0011 = 8 clocks
312 * 0100 = 10 clocks
313 * 0101 = 12 clocks
314 * 0110 = 16 clocks
315 * 0111 = 32 clocks
316 * 1xxx = Infinite (pages are not closed for idle condition)
317 */
Keith Hui8bd784e2020-04-05 14:54:22 -0400318 /* PGPOL will be set later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000319
320 /* PMCR - Power Management Control Register
321 * 0x7a
322 *
Keith Hui8bd784e2020-04-05 14:54:22 -0400323 * [7] Power Down SDRAM Enable (PDSE)
324 * 1 = Enable
325 * 0 = Disable
326 * [6] ACPI Control Register Enable (SCRE)
327 * 1 = Enable
328 * 0 = Disable (default)
329 * [5] Suspend Refresh Type (SRT)
330 * 1 = Self refresh mode
331 * 0 = CBR fresh mode
332 * [4] Normal Refresh Enable (NREF_EN)
333 * 1 = Enable
334 * 0 = Disable
335 * [3] Quick Start Mode (QSTART)
336 * 1 = Quick start mode for the processor is enabled
337 * [2] Gated Clock Enable (GCLKEN)
338 * 1 = Enable
339 * 0 = Disable
340 * [1] AGP Disable (AGP_DIS)
341 * 1 = AGP disabled (Hardware strap)
342 * [0] CPU reset without PCIRST enable (CRst_En)
343 * 1 = Enable
344 * 0 = Disable
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000345 */
Keith Huie9b3fd12020-01-12 18:41:26 -0500346 /* PMCR will be set later. */
Keith Hui59356ca2010-03-06 18:16:25 +0000347
348 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
Keith Hui8bd784e2020-04-05 14:54:22 -0400349 SCRR + 1, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000350};
351
352/*-----------------------------------------------------------------------------
353SDRAM configuration functions.
354-----------------------------------------------------------------------------*/
355
356/**
357 * Send the specified RAM command to all DIMMs.
358 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000359 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000360 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000361static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000362{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000363 int i, caslatency;
364 u8 dimm_start, dimm_end;
365 u16 reg16;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800366 void *addr;
367 u32 addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000368
369 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000370 reg16 = pci_read_config16(NB, SDRAMC);
371 reg16 &= 0xff1f; /* Clear bits 7-5. */
372 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
373 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000374
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000375 /*
376 * RAM_COMMAND_NORMAL affects only the memory controller and
377 * doesn't need to be "sent" to the DIMMs.
378 */
379 if (command == RAM_COMMAND_NORMAL)
380 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000381
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000382 /* Send the RAM command to each row of memory. */
383 dimm_start = 0;
384 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000385 addr_offset = 0;
386 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000387 if (command == RAM_COMMAND_MRS) {
388 /*
389 * MAA[12:11,9:0] must be inverted when sent to DIMM
390 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
391 */
392 if ((i >= 0 && i <= 3) && caslatency == 3)
393 addr_offset = 0x1d0;
394 if ((i >= 4 && i <= 7) && caslatency == 3)
395 addr_offset = 0x1e28;
396 if ((i >= 0 && i <= 3) && caslatency == 2)
397 addr_offset = 0x150;
398 if ((i >= 4 && i <= 7) && caslatency == 2)
399 addr_offset = 0x1ea8;
400 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000401
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000402 dimm_end = pci_read_config8(NB, DRB + i);
403
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800404 addr = (void *)((dimm_start * 8 * 1024 * 1024) + addr_offset);
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000405 if (dimm_end > dimm_start) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000406 read32(addr);
407 }
408
409 /* Set the start of the next DIMM. */
410 dimm_start = dimm_end;
411 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000412}
413
Keith Hui59356ca2010-03-06 18:16:25 +0000414static void set_dram_buffer_strength(void)
415{
Keith Huia8380fc2017-12-04 00:05:56 -0500416 /*
417 * Program MBSC[39:0] and MBFS[23:0].
418 *
419 * The 440BX datasheet says buffer frequency is independent from bus
420 * frequency and mismatch both ways are possible.
421 *
422 * MBSC[47:40] and MBFS[23] are reserved.
Keith Hui59356ca2010-03-06 18:16:25 +0000423 */
424
Keith Huia8380fc2017-12-04 00:05:56 -0500425 unsigned int i, reg, drb;
426 uint8_t mbsc0, mbfs0, mbfs1, mbfs2;
427 uint16_t mbsc1, mbsc3;
428
429 /*
430 * Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000431 * This determines how to program MBFS and MBSC.
432 */
433 uint8_t dimm03 = 0;
434 uint8_t dimm47 = 0;
435
Keith Huia8380fc2017-12-04 00:05:56 -0500436 for (drb = 0, i = DRB0; i <= DRB7; i++) {
437 reg = pci_read_config8(NB, i);
438 if (drb != reg) {
439 if (i <= DRB3)
Keith Huib48ba662010-03-17 02:15:07 +0000440 dimm03++;
Keith Huia8380fc2017-12-04 00:05:56 -0500441 else
Keith Huib48ba662010-03-17 02:15:07 +0000442 dimm47++;
Keith Huia8380fc2017-12-04 00:05:56 -0500443
444 drb = reg;
Keith Huib48ba662010-03-17 02:15:07 +0000445 }
446 }
447
Julius Wernercd49cce2019-03-05 16:53:33 -0800448 if (CONFIG(SDRAMPWR_4DIMM)) {
Keith Huia8380fc2017-12-04 00:05:56 -0500449 /*
450 * For a 4 DIMM board, based on ASUS P2B-LS mainboard.
Keith Huib48ba662010-03-17 02:15:07 +0000451 *
Keith Huia8380fc2017-12-04 00:05:56 -0500452 * There are four main conditions to check when programming
453 * DRAM buffer frequency and strength:
Keith Huib48ba662010-03-17 02:15:07 +0000454 *
455 * a: >2 rows populated across DIMM0,1
456 * b: >2 rows populated across DIMM2,3
457 * c: >4 rows populated across all DIMM slots
458 * and either one of:
459 * 1: NBXCFG[13] strapped as 100MHz, or
460 * 6: NBXCFG[13] strapped as 66MHz
461 *
462 * CKE0/FENA ----------------------------------------------------------+
Keith Huia8380fc2017-12-04 00:05:56 -0500463 * CKE1/GCKE ----------------------[ MBFS ]---------------------+|
464 * DQMA/CASA[764320]# -------------[ 0 = 66MHz ]--------------------+||
465 * DQMB1/CASB1# (Fixed for 66MHz) -[ 1 = 100MHz ]-------------------+|||
466 * DQMB5/CASB5# (Fixed for 66MHz) ---------------------------------+||||
467 * DQMA1/CASA1# (Fixed for 66MHz) --------------------------------+|||||
468 * DQMA5/CASA5# (Fixed for 66MHz) -------------------------------+||||||
469 * CSA[5:0]#,CSB[5:0]# ------------------------------------++++++|||||||
470 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
471 * MECC[7:0] #2/#1 ----------------------------------++|||||||||||||||||
472 * MD[63:0] #2/#1 ---------------------------------++|||||||||||||||||||
473 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
474 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
475 * Reserved ------------------------------------+|||||||||||||||||||||||
476 * ||||||||||||||||||||||||
477 * 3 32 21 10 0 * 2 21 10 0
478 * 9876543210987654321098765432109876543210 * 321098765432109876543210
479 * 10------------------------1010---------- a -1---------------11-----
480 * 11------------------------1111---------- !a -0---------------00-----
481 * --10--------------------------1010------ b --1----------------11---
482 * --11--------------------------1111------ !b --0----------------00---
483 * ----------------------------------1100-- c ----------------------1-
484 * ----------------------------------1011-- !c ----------------------0-
485 * ----1010101000000000000000------------00 1 ---11111111111111----1-0
486 * ----000000000000000000000010101010----00 6 ---1111111111111100000-0
487 * | | | | | | | | | | ||||||| | | | | | |
488 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
489 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
490 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
491 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# (66MHz: 2x)
492 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# (66MHz: 2x)
493 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# (66MHz: 2x)
494 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# (66MHz: 2x)
495 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (1x)
496 * | | | | | | | | | +--------------------- CSA6#/CKE2
497 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
498 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
499 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
500 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1
501 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2
502 * | | | +--------------------------------- MD[63:0] #1
503 * | | +----------------------------------- MD[63:0] #2
504 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
505 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
506 */
507 unsigned int fsb;
508
509 mbsc0 = 0xa0;
510 mbsc1 = 0x002a;
511 mbfs1 = 0xff;
512 mbfs2 = 0x1f;
513 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
514 fsb = 66;
515 mbsc3 = 0xa000;
516 mbfs0 = 0x80;
517 } else {
518 fsb = 100;
519 mbsc3 = 0xaaa0;
520 mbfs0 = 0x84;
521 }
522 if (dimm03 > 2) {
523 mbfs2 |= 0x40;
524 if (fsb == 100)
525 mbfs0 |= 0x60;
526 } else {
527 mbsc3 |= 0xc000;
528 if (fsb == 100)
529 mbsc1 |= 0x003c;
530 }
531 if (dimm47 > 2) {
532 mbfs2 |= 0x20;
533 if (fsb == 100)
534 mbfs0 |= 0x18;
535 } else {
536 mbsc3 |= 0x3000;
537 if (fsb == 100) {
538 mbsc1 |= 0x0003;
539 mbsc0 |= 0xc0;
540 }
541 }
542 if ((dimm03 + dimm47) > 4) {
543 mbsc0 |= 0x30;
544 mbfs0 |= 0x02;
545 } else {
546 mbsc0 |= 0x2c;
547 }
548 } else {
549 /*
550 * For a 3 DIMM board, based on ASUS P2B mainboard.
551 *
552 * There are two main conditions to check when programming DRAM buffer
553 * frequency and strength:
554 *
555 * a: >2 rows populated across DIMM0,1
556 * c: >4 rows populated across all DIMM slots
557 *
558 * CKE0 ---------------------------------------------------------------+
559 * CKE1 ------------------------[ MBFS ]------------------------+|
Keith Huib48ba662010-03-17 02:15:07 +0000560 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
561 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
562 * DQMB5/CASB5# ---------------------------------------------------+||||
563 * DQMA1/CASA1# --------------------------------------------------+|||||
564 * DQMA5/CASA5# -------------------------------------------------+||||||
565 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500566 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
Keith Huib48ba662010-03-17 02:15:07 +0000567 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
568 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
569 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
570 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
571 * Reserved ------------------------------------+|||||||||||||||||||||||
572 * ||||||||||||||||||||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500573 * 3 32 21 10 0 * 2 21 10 0
574 * 9876543210987654321098765432109876543210 * 321098765432109876543210
575 * 10------------------------1111---------- a -1----------------------
576 * 11------------------------1010---------- !a -0----------------------
577 * --110000000010101010111111----1010--1010 * --01111000000000000000-0
578 * ----------------------------------11---- c ----------------------1-
579 * ----------------------------------10---- !c ----------------------0-
580 * | | | | | | | | | | ||||||| | | | | | |
581 * | | | | | | | | | | ||||||| | | | | | +- CKE0
582 * | | | | | | | | | | ||||||| | | | | +--- CKE1
583 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
584 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
585 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
586 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
587 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
588 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (2x)
589 * | | | | | | | | | +--------------------- CSA6#/CKE2
590 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
591 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
592 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
593 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (1x)
594 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (1x)
595 * | | | +--------------------------------- MD[63:0] #1 (1x)
596 * | | +----------------------------------- MD[63:0] #2 (1x)
597 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
598 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
Keith Huib48ba662010-03-17 02:15:07 +0000599 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000600
Keith Huia8380fc2017-12-04 00:05:56 -0500601 mbsc0 = 0xaa;
602 mbsc1 = 0xafea;
603 mbsc3 = 0xb00a;
604 mbfs0 = 0x00;
605 mbfs1 = 0x00;
606 mbfs2 = 0x1e;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000607
Keith Huia8380fc2017-12-04 00:05:56 -0500608 if (dimm03 > 2) {
609 mbsc1 |= 0x003c;
610 mbfs2 |= 0x40;
611 } else {
612 mbsc3 |= 0xc000;
Keith Huib48ba662010-03-17 02:15:07 +0000613 }
Keith Huia8380fc2017-12-04 00:05:56 -0500614 if ((dimm03 + dimm47) > 4) {
615 mbsc0 |= 0x30;
616 mbfs0 |= 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000617 }
618 }
Keith Huib48ba662010-03-17 02:15:07 +0000619
620 pci_write_config8(NB, MBSC + 0, mbsc0);
Keith Huia8380fc2017-12-04 00:05:56 -0500621 pci_write_config16(NB, MBSC + 1, mbsc1);
622 pci_write_config16(NB, MBSC + 3, mbsc3);
623 pci_write_config16(NB, MBFS + 0, mbfs1 << 8 | mbfs0);
Keith Huib48ba662010-03-17 02:15:07 +0000624 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000625}
626
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000627/*-----------------------------------------------------------------------------
Martin Roth128c1042016-11-18 09:29:03 -0700628DIMM-independent configuration functions.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000629-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000630
Uwe Hermann1683cef2008-11-27 00:47:07 +0000631static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000632{
633 int i, value;
634 uint8_t reg;
635
Uwe Hermann1683cef2008-11-27 00:47:07 +0000636 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000637
638 for (i = 0; i < DIMM_SOCKETS; i++) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200639 value = smbus_read_byte(DIMM0 + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000640 if (value < 0)
641 continue;
642 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
643
Keith Hui09f5a742010-12-23 17:12:03 +0000644 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000645 }
646
Uwe Hermann1683cef2008-11-27 00:47:07 +0000647 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000648}
649
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000650/*-----------------------------------------------------------------------------
651Public interface.
652-----------------------------------------------------------------------------*/
653
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200654static void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000655{
656 int i, max;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000657
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000658 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000659 DUMPNORTH();
660
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000661 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000662
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000663 /* Set registers as specified in the register_values[] array. */
Keith Hui8bd784e2020-04-05 14:54:22 -0400664 for (i = 0; i < max; i += 2)
665 pci_write_config8(NB, register_values[i], register_values[i + 1]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000666}
667
Keith Hui59356ca2010-03-06 18:16:25 +0000668struct dimm_size {
Keith Hui09f5a742010-12-23 17:12:03 +0000669 u32 side1;
670 u32 side2;
Keith Hui59356ca2010-03-06 18:16:25 +0000671};
672
673static struct dimm_size spd_get_dimm_size(unsigned int device)
674{
675 struct dimm_size sz;
676 int i, module_density, dimm_banks;
677 sz.side1 = 0;
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200678 module_density = smbus_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
679 dimm_banks = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000680
681 /* Find the size of side1. */
682 /* Find the larger value. The larger value is always side1. */
683 for (i = 512; i >= 0; i >>= 1) {
684 if ((module_density & i) == i) {
685 sz.side1 = i;
686 break;
687 }
688 }
689
690 /* Set to 0 in case it's single sided. */
691 sz.side2 = 0;
692
693 /* Test if it's a dual-sided DIMM. */
694 if (dimm_banks > 1) {
695 /* Test if there's a second value. If so it's asymmetrical. */
696 if (module_density != i) {
697 /*
698 * Find second value, picking up where we left off.
699 * i >>= 1 done initially to make sure we don't get
700 * the same value again.
701 */
702 for (i >>= 1; i >= 0; i >>= 1) {
703 if (module_density == (sz.side1 | i)) {
704 sz.side2 = i;
705 break;
706 }
707 }
708 /* If not, it's symmetrical. */
709 } else {
710 sz.side2 = sz.side1;
711 }
712 }
713
714 /*
715 * SPD byte 31 is the memory size divided by 4 so we
Martin Roth128c1042016-11-18 09:29:03 -0700716 * need to multiply by 4 to get the total size.
Keith Hui59356ca2010-03-06 18:16:25 +0000717 */
718 sz.side1 *= 4;
719 sz.side2 *= 4;
720
Keith Huia8380fc2017-12-04 00:05:56 -0500721 /*
722 * It is possible to partially use larger than supported
Anders Jenbo771b0e42010-04-27 08:45:30 +0000723 * modules by setting them to a supported size.
724 */
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200725 if (sz.side1 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000726 PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
727 sz.side1);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000728 sz.side1 = 128;
729
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200730 if (sz.side2 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000731 PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
732 sz.side2);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000733 sz.side2 = 128;
734 }
735 }
736
Keith Hui59356ca2010-03-06 18:16:25 +0000737 return sz;
738}
739/*
740 * Sets DRAM attributes one DIMM at a time, based on SPD data.
741 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
742 */
743static void set_dram_row_attributes(void)
744{
Keith Huie089a3f2011-08-02 22:28:14 -0400745 int i, dra, drb, col, width, value, rps;
Keith Hui59356ca2010-03-06 18:16:25 +0000746 u8 bpr; /* Top 8 bits of PGPOL */
Keith Huie089a3f2011-08-02 22:28:14 -0400747 u8 nbxecc = 0; /* NBXCFG[31:24] */
748 u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
Keith Hui59356ca2010-03-06 18:16:25 +0000749
Keith Huie089a3f2011-08-02 22:28:14 -0400750 edo = 0;
751 sd = 0;
752 regsd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000753 rps = 0;
754 drb = 0;
755 bpr = 0;
Keith Hui59356ca2010-03-06 18:16:25 +0000756
757 for (i = 0; i < DIMM_SOCKETS; i++) {
758 unsigned int device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000759 device = DIMM0 + i;
Keith Hui59356ca2010-03-06 18:16:25 +0000760 bpr >>= 2;
Keith Huie089a3f2011-08-02 22:28:14 -0400761 nbxecc >>= 2;
Keith Hui59356ca2010-03-06 18:16:25 +0000762
763 /* First check if a DIMM is actually present. */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200764 value = smbus_read_byte(device, SPD_MEMORY_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000765 /* This is 440BX! We do EDO too! */
766 if (value == SPD_MEMORY_TYPE_EDO
767 || value == SPD_MEMORY_TYPE_SDRAM) {
768
Keith Hui59356ca2010-03-06 18:16:25 +0000769 if (value == SPD_MEMORY_TYPE_EDO) {
Keith Huie089a3f2011-08-02 22:28:14 -0400770 edo = 1;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000771 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
Keith Huie089a3f2011-08-02 22:28:14 -0400772 sd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000773 }
Keith Hui09f5a742010-12-23 17:12:03 +0000774 PRINT_DEBUG("Found DIMM in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000775
Keith Huie089a3f2011-08-02 22:28:14 -0400776 if (edo && sd) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800777 printk(BIOS_ERR, "Mixing EDO/SDRAM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000778 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000779 }
780
781 /* "DRA" is our RPS for the two rows on this DIMM. */
782 dra = 0;
783
784 /* Columns */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200785 col = smbus_read_byte(device, SPD_NUM_COLUMNS);
Keith Hui59356ca2010-03-06 18:16:25 +0000786
787 /*
788 * Is this an ECC DIMM? Actually will be a 2 if so.
789 * TODO: Other register than NBXCFG also needs this
790 * ECC information.
791 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200792 value = smbus_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000793
794 /* Data width */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200795 width = smbus_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000796
Keith Hui59356ca2010-03-06 18:16:25 +0000797 /* Exclude error checking data width from page size calculations */
Keith Huie089a3f2011-08-02 22:28:14 -0400798 if (value) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200799 value = smbus_read_byte(device,
Keith Hui59356ca2010-03-06 18:16:25 +0000800 SPD_ERROR_CHECKING_SDRAM_WIDTH);
801 width -= value;
802 /* ### ECC */
803 /* Clear top 2 bits to help set up NBXCFG. */
Keith Huie089a3f2011-08-02 22:28:14 -0400804 nbxecc &= 0x3f;
Keith Hui59356ca2010-03-06 18:16:25 +0000805 } else {
806 /* Without ECC, top 2 bits should be 11. */
Keith Huie089a3f2011-08-02 22:28:14 -0400807 nbxecc |= 0xc0;
Keith Hui59356ca2010-03-06 18:16:25 +0000808 }
809
Keith Huie089a3f2011-08-02 22:28:14 -0400810 /* If any installed DIMM is *not* registered, this system cannot be
811 * configured for registered SDRAM.
812 * By registered, only the address and control lines need to be, which
813 * we can tell by reading SPD byte 21, bit 1.
814 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200815 value = smbus_read_byte(device, SPD_MODULE_ATTRIBUTES);
Keith Huie089a3f2011-08-02 22:28:14 -0400816
817 PRINT_DEBUG("DIMM is ");
818 if ((value & MODULE_REGISTERED) == 0) {
819 regsd = 0;
820 PRINT_DEBUG("not ");
821 }
822 PRINT_DEBUG("registered\n");
823
Keith Hui59356ca2010-03-06 18:16:25 +0000824 /* Calculate page size in bits. */
825 value = ((1 << col) * width);
826
827 /* Convert to KB. */
828 dra = (value >> 13);
829
830 /* Number of banks of DIMM (single or double sided). */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200831 value = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000832
833 /* Once we have dra, col is done and can be reused.
834 * So it's reused for number of banks.
835 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200836 col = smbus_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
Keith Hui59356ca2010-03-06 18:16:25 +0000837
838 if (value == 1) {
839 /*
840 * Second bank of 1-bank DIMMs "doesn't have
841 * ECC" - or anything.
842 */
Keith Hui59356ca2010-03-06 18:16:25 +0000843 if (dra == 2) {
844 dra = 0x0; /* 2KB */
845 } else if (dra == 4) {
846 dra = 0x1; /* 4KB */
847 } else if (dra == 8) {
848 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000849 } else if (dra >= 16) {
850 /* Page sizes larger than supported are
851 * set to 8KB to use module partially.
852 */
853 PRINT_DEBUG("Page size forced to 8KB.\n");
854 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000855 } else {
856 dra = -1;
857 }
858 /*
859 * Sets a flag in PGPOL[BPR] if this DIMM has
860 * 4 banks per row.
861 */
862 if (col == 4)
863 bpr |= 0x40;
864 } else if (value == 2) {
865 if (dra == 2) {
866 dra = 0x0; /* 2KB */
867 } else if (dra == 4) {
868 dra = 0x05; /* 4KB */
869 } else if (dra == 8) {
870 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000871 } else if (dra >= 16) {
872 /* Ditto */
873 PRINT_DEBUG("Page size forced to 8KB.\n");
874 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000875 } else {
876 dra = -1;
877 }
878 /* Ditto */
879 if (col == 4)
880 bpr |= 0xc0;
881 } else {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800882 printk(BIOS_ERR, "# of banks of DIMM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000883 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000884 }
885 if (dra == -1) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800886 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000887 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000888 }
889
890 /*
891 * 440BX supports asymmetrical dual-sided DIMMs,
892 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000893 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000894 */
895 struct dimm_size sz = spd_get_dimm_size(device);
896 if ((sz.side1 < 8)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800897 printk(BIOS_ERR, "DIMMs smaller than 8MB per side\n"
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000898 "are not supported on this NB.\n");
899 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000900 }
Keith Hui59356ca2010-03-06 18:16:25 +0000901
902 /* Divide size by 8 to set up the DRB registers. */
903 drb += (sz.side1 / 8);
904
905 /*
906 * Build the DRB for the next row in MSB so it gets
907 * placed in DRB[n+1] where it belongs when written
908 * as a 16-bit word.
909 */
910 drb &= 0xff;
911 drb |= (drb + (sz.side2 / 8)) << 8;
912 } else {
Keith Hui59356ca2010-03-06 18:16:25 +0000913 /* If there's no DIMM in the slot, set dra to 0x00. */
914 dra = 0x00;
Keith Hui59356ca2010-03-06 18:16:25 +0000915 /* Still have to propagate DRB over. */
916 drb &= 0xff;
917 drb |= (drb << 8);
918 }
919
920 pci_write_config16(NB, DRB + (2 * i), drb);
Keith Hui59356ca2010-03-06 18:16:25 +0000921
922 /* Brings the upper DRB back down to be base for
923 * DRB calculations for the next two rows.
924 */
925 drb >>= 8;
926
927 rps |= (dra & 0x0f) << (i * 4);
Keith Hui59356ca2010-03-06 18:16:25 +0000928 }
929
930 /* Set paging policy register. */
931 pci_write_config8(NB, PGPOL + 1, bpr);
Keith Hui09f5a742010-12-23 17:12:03 +0000932 PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
Keith Hui59356ca2010-03-06 18:16:25 +0000933
934 /* Set DRAM row page size register. */
935 pci_write_config16(NB, RPS, rps);
Keith Hui09f5a742010-12-23 17:12:03 +0000936 PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
Keith Hui59356ca2010-03-06 18:16:25 +0000937
938 /* ### ECC */
939 pci_write_config8(NB, NBXCFG + 3, nbxecc);
Keith Hui09f5a742010-12-23 17:12:03 +0000940 PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
Keith Hui59356ca2010-03-06 18:16:25 +0000941
Keith Huie089a3f2011-08-02 22:28:14 -0400942 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
Keith Hui59356ca2010-03-06 18:16:25 +0000943
Keith Huie089a3f2011-08-02 22:28:14 -0400944 /* i will be used to set DRAMC[4:3]. */
945 if (regsd && sd) {
946 i = 0x10; // Registered SDRAM
947 } else if (sd) {
948 i = 0x08; // SDRAM
949 } else {
950 i = 0; // EDO
951 }
952
Keith Hui59356ca2010-03-06 18:16:25 +0000953 value = pci_read_config8(NB, DRAMC) & 0xe7;
Keith Huie089a3f2011-08-02 22:28:14 -0400954 value |= i;
Keith Hui59356ca2010-03-06 18:16:25 +0000955 pci_write_config8(NB, DRAMC, value);
Keith Hui09f5a742010-12-23 17:12:03 +0000956 PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
Keith Hui59356ca2010-03-06 18:16:25 +0000957}
958
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200959static void sdram_set_spd_registers(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000960{
Keith Hui59356ca2010-03-06 18:16:25 +0000961 /* Setup DRAM row boundary registers and other attributes. */
962 set_dram_row_attributes();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000963
Keith Huidf35cdc2010-09-20 23:41:37 +0000964 /* Setup DRAM buffer strength. */
Keith Hui59356ca2010-03-06 18:16:25 +0000965 set_dram_buffer_strength();
Richard Smithcb8eab42006-07-24 04:25:47 +0000966}
967
Kyösti Mälkki7a955752020-01-07 12:18:24 +0200968static void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000969{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000970 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000971
Uwe Hermann861f9642007-05-28 14:37:06 +0000972 /* 0. Wait until power/voltages and clocks are stable (200us). */
973 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000974
Uwe Hermann861f9642007-05-28 14:37:06 +0000975 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000976 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000977 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +0000978 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +0000979
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000980 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000981 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000982 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +0000983 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000984
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000985 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000986 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000987 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000988 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +0000989 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +0000990 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000991
992 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000993 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000994 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +0000995 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000996
997 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000998 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000999 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +00001000 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001001
1002 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001003 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Keith Huie9b3fd12020-01-12 18:41:26 -05001004 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1683cef2008-11-27 00:47:07 +00001005 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +00001006 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001007
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001008 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001009 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001010}
Keith Hui078e3242017-07-20 21:14:21 -04001011
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001012/* Implemented under mainboard. */
1013void __weak enable_spd(void) { }
1014void __weak disable_spd(void) { }
1015
Keith Hui078e3242017-07-20 21:14:21 -04001016void sdram_initialize(void)
1017{
Keith Huid6f259e2020-01-12 18:38:28 -05001018 timestamp_add_now(TS_BEFORE_INITRAM);
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001019 enable_spd();
1020
Keith Hui078e3242017-07-20 21:14:21 -04001021 dump_spd_registers();
1022 sdram_set_registers();
1023 sdram_set_spd_registers();
1024 sdram_enable();
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001025
1026 disable_spd();
Keith Huid6f259e2020-01-12 18:38:28 -05001027 timestamp_add_now(TS_AFTER_INITRAM);
Martin Rothe1695e22017-07-24 11:28:50 -06001028}