blob: 08019880b7b3665f8cfe647d0ebbfe908edbaa54 [file] [log] [blame]
Richard Smithcb8eab42006-07-24 04:25:47 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermann1a9c8922007-04-01 17:24:03 +00003 *
Uwe Hermann1683cef2008-11-27 00:47:07 +00004 * Copyright (C) 2007-2008 Uwe Hermann <uwe@hermann-uwe.de>
Keith Hui9aa45e62017-07-20 21:00:56 -04005 * Copyright (C) 2010,2017 Keith Hui <buurin@gmail.com>
Uwe Hermann1a9c8922007-04-01 17:24:03 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Richard Smithcb8eab42006-07-24 04:25:47 +000016 */
17
Uwe Hermann1a9c8922007-04-01 17:24:03 +000018#include <spd.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000019#include <delay.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000020#include <stdint.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020021#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020022#include <device/pci_ops.h>
Uwe Hermann115c5b92010-10-09 17:00:18 +000023#include <device/pci_def.h>
24#include <console/console.h>
Uwe Hermann1a9c8922007-04-01 17:24:03 +000025#include "i440bx.h"
Keith Hui59356ca2010-03-06 18:16:25 +000026#include "raminit.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000027
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +020028#include <southbridge/intel/i82371eb/i82371eb.h>
29
Keith Hui9aa45e62017-07-20 21:00:56 -040030/*
31 * Macros and definitions
32 */
Keith Huidf35cdc2010-09-20 23:41:37 +000033
Uwe Hermann1a9c8922007-04-01 17:24:03 +000034/* Debugging macros. */
Julius Wernercd49cce2019-03-05 16:53:33 -080035#if CONFIG(DEBUG_RAM_SETUP)
Keith Hui09f5a742010-12-23 17:12:03 +000036#define PRINT_DEBUG(x...) printk(BIOS_DEBUG, x)
Keith Huidf35cdc2010-09-20 23:41:37 +000037#define DUMPNORTH() dump_pci_device(NB)
Richard Smithcb8eab42006-07-24 04:25:47 +000038#else
Keith Hui09f5a742010-12-23 17:12:03 +000039#define PRINT_DEBUG(x...)
Uwe Hermann1a9c8922007-04-01 17:24:03 +000040#define DUMPNORTH()
Richard Smithcb8eab42006-07-24 04:25:47 +000041#endif
42
Uwe Hermann1a9c8922007-04-01 17:24:03 +000043/* SDRAMC[7:5] - SDRAM Mode Select (SMS). */
44#define RAM_COMMAND_NORMAL 0x0
45#define RAM_COMMAND_NOP 0x1
46#define RAM_COMMAND_PRECHARGE 0x2
47#define RAM_COMMAND_MRS 0x3
48#define RAM_COMMAND_CBR 0x4
Richard Smithcb8eab42006-07-24 04:25:47 +000049
Uwe Hermann1a9c8922007-04-01 17:24:03 +000050/* Map the JEDEC SPD refresh rates (array index) to 440BX refresh rates as
51 * defined in DRAMC[2:0].
52 *
53 * [0] == Normal 15.625 us -> 15.6 us
54 * [1] == Reduced(.25X) 3.9 us -> 7.8 ns
55 * [2] == Reduced(.5X) 7.8 us -> 7.8 us
56 * [3] == Extended(2x) 31.3 us -> 31.2 us
57 * [4] == Extended(4x) 62.5 us -> 62.4 us
58 * [5] == Extended(8x) 125 us -> 124.8 us
59 */
60static const uint32_t refresh_rate_map[] = {
61 1, 5, 5, 2, 3, 4
62};
Richard Smithcb8eab42006-07-24 04:25:47 +000063
Uwe Hermann1a9c8922007-04-01 17:24:03 +000064/* Table format: register, bitmask, value. */
Keith Huidf35cdc2010-09-20 23:41:37 +000065static const u8 register_values[] = {
Uwe Hermann1a9c8922007-04-01 17:24:03 +000066 /* NBXCFG - NBX Configuration Register
Uwe Hermannf5a6fd22007-05-27 23:31:31 +000067 * 0x50 - 0x53
Uwe Hermann1a9c8922007-04-01 17:24:03 +000068 *
69 * [31:24] SDRAM Row Without ECC
70 * 0 = ECC components are populated in this row
71 * 1 = ECC components are not populated in this row
72 * [23:19] Reserved
73 * [18:18] Host Bus Fast Data Ready Enable (HBFDRE)
74 * Assertion of DRAM data on host bus occurs...
75 * 0 = ...one clock after sampling snoop results (default)
76 * 1 = ...on the same clock the snoop result is being sampled
77 * (this mode is faster by one clock cycle)
78 * [17:17] ECC - EDO static Drive mode
79 * 0 = Normal mode (default)
80 * 1 = ECC signals are always driven
81 * [16:16] IDSEL_REDIRECT
82 * 0 = IDSEL1 is allocated to this bridge (default)
83 * 1 = IDSEL7 is allocated to this bridge
84 * [15:15] WSC# Handshake Disable
85 * 1 = Uni-processor mode
86 * 0 = Dual-processor mode with external IOAPIC (default)
87 * [14:14] Intel Reserved
88 * [13:12] Host/DRAM Frequency
89 * 00 = 100 MHz
90 * 01 = Reserved
91 * 10 = 66 MHz
92 * 11 = Reserved
93 * [11:11] AGP to PCI Access Enable
94 * 1 = Enable
95 * 0 = Disable
96 * [10:10] PCI Agent to Aperture Access Disable
97 * 1 = Disable
98 * 0 = Enable (default)
99 * [09:09] Aperture Access Global Enable
100 * 1 = Enable
101 * 0 = Disable
102 * [08:07] DRAM Data Integrity Mode (DDIM)
103 * 00 = Non-ECC
104 * 01 = EC-only
105 * 10 = ECC Mode
106 * 11 = ECC Mode with hardware scrubbing enabled
107 * [06:06] ECC Diagnostic Mode Enable (EDME)
108 * 1 = Enable
109 * 0 = Normal operation mode (default)
110 * [05:05] MDA Present (MDAP)
111 * Works in conjunction with the VGA_EN bit.
112 * VGA_EN MDAP
113 * 0 x All VGA cycles are sent to PCI
114 * 1 0 All VGA cycles are sent to AGP
115 * 1 1 All VGA cycles are sent to AGP, except for
116 * cycles in the MDA range.
117 * [04:04] Reserved
118 * [03:03] USWC Write Post During I/O Bridge Access Enable (UWPIO)
119 * 1 = Enable
120 * 0 = Disable
121 * [02:02] In-Order Queue Depth (IOQD)
122 * 1 = In-order queue = maximum
123 * 0 = A7# is sampled asserted (i.e., 0)
124 * [01:00] Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000125 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000126 NBXCFG + 0, 0x00, 0x0c,
Keith Huidf35cdc2010-09-20 23:41:37 +0000127 // TODO: Bit 15 should be 0 for multiprocessor boards
Uwe Hermannbc3594732007-06-07 22:16:30 +0000128 NBXCFG + 1, 0x00, 0x80,
129 NBXCFG + 2, 0x00, 0x00,
130 NBXCFG + 3, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000131
132 /* DRAMC - DRAM Control Register
133 * 0x57
134 *
135 * [7:6] Reserved
136 * [5:5] Module Mode Configuration (MMCONFIG)
Keith Huia8380fc2017-12-04 00:05:56 -0500137 * The combination of SDRAMPWR and this bit (set by an
Keith Huidf35cdc2010-09-20 23:41:37 +0000138 * external strapping option) determine how CKE works.
139 * SDRAMPWR MMCONFIG
Keith Huia8380fc2017-12-04 00:05:56 -0500140 * 0 0 = 3 DIMM, CKE[5:0] driven
141 * X 1 = 3 DIMM, CKE0 only
142 * 1 0 = 4 DIMM, GCKE only
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000143 * [4:3] DRAM Type (DT)
144 * 00 = EDO
145 * 01 = SDRAM
146 * 10 = Registered SDRAM
147 * 11 = Reserved
148 * Note: EDO, SDRAM and Registered SDRAM cannot be mixed.
149 * [2:0] DRAM Refresh Rate (DRR)
150 * 000 = Refresh disabled
151 * 001 = 15.6 us
152 * 010 = 31.2 us
153 * 011 = 62.4 us
154 * 100 = 124.8 us
155 * 101 = 249.6 us
156 * 110 = Reserved
157 * 111 = Reserved
Richard Smithcb8eab42006-07-24 04:25:47 +0000158 */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000159 /* Choose SDRAM (not registered), and disable refresh for now. */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000160 DRAMC, 0x00, 0x08,
Richard Smithcb8eab42006-07-24 04:25:47 +0000161
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000162 /*
163 * PAM[6:0] - Programmable Attribute Map Registers
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000164 * 0x59 - 0x5f
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000165 *
166 * 0x59 [3:0] Reserved
167 * 0x59 [5:4] 0xF0000 - 0xFFFFF BIOS area
168 * 0x5a [1:0] 0xC0000 - 0xC3FFF ISA add-on BIOS
169 * 0x5a [5:4] 0xC4000 - 0xC7FFF ISA add-on BIOS
170 * 0x5b [1:0] 0xC8000 - 0xCBFFF ISA add-on BIOS
171 * 0x5b [5:4] 0xCC000 - 0xCFFFF ISA add-on BIOS
172 * 0x5c [1:0] 0xD0000 - 0xD3FFF ISA add-on BIOS
173 * 0x5c [5:4] 0xD4000 - 0xD7FFF ISA add-on BIOS
174 * 0x5d [1:0] 0xD8000 - 0xDBFFF ISA add-on BIOS
175 * 0x5d [5:4] 0xDC000 - 0xDFFFF ISA add-on BIOS
Martin Roth128c1042016-11-18 09:29:03 -0700176 * 0x5e [1:0] 0xE0000 - 0xE3FFF BIOS extension
177 * 0x5e [5:4] 0xE4000 - 0xE7FFF BIOS extension
178 * 0x5f [1:0] 0xE8000 - 0xEBFFF BIOS extension
179 * 0x5f [5:4] 0xEC000 - 0xEFFFF BIOS extension
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000180 *
181 * Bit assignment:
182 * 00 = DRAM Disabled (all access goes to memory mapped I/O space)
183 * 01 = Read Only (Reads to DRAM, writes to memory mapped I/O space)
184 * 10 = Write Only (Writes to DRAM, reads to memory mapped I/O space)
185 * 11 = Read/Write (all access goes to DRAM)
186 */
Keith Hui59356ca2010-03-06 18:16:25 +0000187
188 /*
189 * Map all legacy regions to RAM (read/write). This is required if
190 * you want to use the RAM area from 768 KB - 1 MB. If the PAM
191 * registers are not set here appropriately, the RAM in that region
192 * will not be accessible, thus a RAM check of it will also fail.
Keith Hui59356ca2010-03-06 18:16:25 +0000193 */
194 PAM0, 0x00, 0x30,
195 PAM1, 0x00, 0x33,
196 PAM2, 0x00, 0x33,
197 PAM3, 0x00, 0x33,
198 PAM4, 0x00, 0x33,
199 PAM5, 0x00, 0x33,
200 PAM6, 0x00, 0x33,
Richard Smithcb8eab42006-07-24 04:25:47 +0000201
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000202 /* DRB[0:7] - DRAM Row Boundary Registers
203 * 0x60 - 0x67
204 *
205 * An array of 8 byte registers, which hold the ending memory address
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000206 * assigned to each pair of DIMMs, in 8MB granularity.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000207 *
208 * 0x60 DRB0 = Total memory in row0 (in 8 MB)
209 * 0x61 DRB1 = Total memory in row0+1 (in 8 MB)
210 * 0x62 DRB2 = Total memory in row0+1+2 (in 8 MB)
211 * 0x63 DRB3 = Total memory in row0+1+2+3 (in 8 MB)
212 * 0x64 DRB4 = Total memory in row0+1+2+3+4 (in 8 MB)
213 * 0x65 DRB5 = Total memory in row0+1+2+3+4+5 (in 8 MB)
214 * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB)
215 * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB)
216 */
Keith Huia8380fc2017-12-04 00:05:56 -0500217 /* DRBs will be set later. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000218 DRB0, 0x00, 0x00,
219 DRB1, 0x00, 0x00,
220 DRB2, 0x00, 0x00,
221 DRB3, 0x00, 0x00,
222 DRB4, 0x00, 0x00,
223 DRB5, 0x00, 0x00,
224 DRB6, 0x00, 0x00,
225 DRB7, 0x00, 0x00,
226
227 /* FDHC - Fixed DRAM Hole Control Register
228 * 0x68
229 *
230 * Controls two fixed DRAM holes: 512 KB - 640 KB and 15 MB - 16 MB.
231 *
232 * [7:6] Hole Enable (HEN)
233 * 00 = None
234 * 01 = 512 KB - 640 KB (128 KB)
235 * 10 = 15 MB - 16 MB (1 MB)
236 * 11 = Reserved
237 * [5:0] Reserved
238 */
239 /* No memory holes. */
240 FDHC, 0x00, 0x00,
241
242 /* RPS - SDRAM Row Page Size Register
243 * 0x74 - 0x75
244 *
245 * Sets the row page size for SDRAM. For EDO memory, the page
246 * size is fixed at 2 KB.
247 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000248 * Bits[1:0] Page Size
249 * 00 2 KB
250 * 01 4 KB
251 * 10 8 KB
252 * 11 Reserved
Keith Huie089a3f2011-08-02 22:28:14 -0400253 *
Keith Huidf35cdc2010-09-20 23:41:37 +0000254 * RPS bits Corresponding DRB register
255 * [01:00] DRB[0], row 0
256 * [03:02] DRB[1], row 1
257 * [05:04] DRB[2], row 2
258 * [07:06] DRB[3], row 3
259 * [09:08] DRB[4], row 4
260 * [11:10] DRB[5], row 5
261 * [13:12] DRB[6], row 6
262 * [15:14] DRB[7], row 7
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000263 */
Keith Huidf35cdc2010-09-20 23:41:37 +0000264 /* Power on defaults to 2KB. Will be set later. */
265 // RPS + 0, 0x00, 0x00,
266 // RPS + 1, 0x00, 0x00,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000267
268 /* SDRAMC - SDRAM Control Register
Uwe Hermann7ea18cf2007-05-04 00:51:17 +0000269 * 0x76 - 0x77
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000270 *
271 * [15:10] Reserved
272 * [09:08] Idle/Pipeline DRAM Leadoff Timing (IPDLT)
273 * 00 = Illegal
274 * 01 = Add a clock delay to the lead-off clock count
Keith Huidf35cdc2010-09-20 23:41:37 +0000275 * 1x = Illegal
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000276 * [07:05] SDRAM Mode Select (SMS)
277 * 000 = Normal SDRAM Operation (default)
278 * 001 = NOP Command Enable
279 * 010 = All Banks Precharge Enable
280 * 011 = Mode Register Set Enable
281 * 100 = CBR Enable
282 * 101 = Reserved
283 * 110 = Reserved
284 * 111 = Reserved
285 * [04:04] SDRAMPWR
286 * 0 = 3 DIMM configuration
287 * 1 = 4 DIMM configuration
288 * [03:03] Leadoff Command Timing (LCT)
289 * 0 = 4 CS# Clock
290 * 1 = 3 CS# Clock
291 * [02:02] CAS# Latency (CL)
292 * 0 = 3 DCLK CAS# latency
293 * 1 = 2 DCLK CAS# latency
294 * [01:01] SDRAM RAS# to CAS# Delay (SRCD)
295 * 0 = 3 clocks between a row activate and a read or write cmd.
296 * 1 = 2 clocks between a row activate and a read or write cmd.
297 * [00:00] SDRAM RAS# Precharge (SRP)
298 * 0 = 3 clocks of RAS# precharge
299 * 1 = 2 clocks of RAS# precharge
300 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800301#if CONFIG(SDRAMPWR_4DIMM)
Keith Hui9c1e1f02010-03-13 20:16:48 +0000302 SDRAMC + 0, 0x00, 0x10, /* The board has 4 DIMM slots. */
303#else
Keith Huidf35cdc2010-09-20 23:41:37 +0000304 SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */
Keith Hui9c1e1f02010-03-13 20:16:48 +0000305#endif
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000306
307 /* PGPOL - Paging Policy Register
308 * 0x78 - 0x79
309 *
310 * [15:08] Banks per Row (BPR)
Keith Huidf35cdc2010-09-20 23:41:37 +0000311 * Each bit in this field corresponds to one row of the memory
312 * array. Bit 15 corresponds to row 7 while bit 8 corresponds
313 * to row 0. Bits for empty rows are "don't care".
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000314 * 0 = 2 banks
315 * 1 = 4 banks
316 * [07:05] Reserved
317 * [04:04] Intel Reserved
318 * [03:00] DRAM Idle Timer (DIT)
319 * 0000 = 0 clocks
320 * 0001 = 2 clocks
321 * 0010 = 4 clocks
322 * 0011 = 8 clocks
323 * 0100 = 10 clocks
324 * 0101 = 12 clocks
325 * 0110 = 16 clocks
326 * 0111 = 32 clocks
327 * 1xxx = Infinite (pages are not closed for idle condition)
328 */
Uwe Hermannbc3594732007-06-07 22:16:30 +0000329 PGPOL + 0, 0x00, 0x00,
330 PGPOL + 1, 0x00, 0xff,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000331
332 /* PMCR - Power Management Control Register
333 * 0x7a
334 *
335 * [07:07] Power Down SDRAM Enable (PDSE)
336 * 1 = Enable
337 * 0 = Disable
338 * [06:06] ACPI Control Register Enable (SCRE)
339 * 1 = Enable
340 * 0 = Disable (default)
341 * [05:05] Suspend Refresh Type (SRT)
342 * 1 = Self refresh mode
343 * 0 = CBR fresh mode
344 * [04:04] Normal Refresh Enable (NREF_EN)
345 * 1 = Enable
346 * 0 = Disable
347 * [03:03] Quick Start Mode (QSTART)
348 * 1 = Quick start mode for the processor is enabled
349 * [02:02] Gated Clock Enable (GCLKEN)
350 * 1 = Enable
351 * 0 = Disable
352 * [01:01] AGP Disable (AGP_DIS)
353 * 1 = Disable
354 * 0 = Enable
355 * [00:00] CPU reset without PCIRST enable (CRst_En)
356 * 1 = Enable
357 * 0 = Disable
358 */
359 /* Enable normal refresh and the gated clock. */
360 // TODO: Only do this later?
361 // PMCR, 0x00, 0x14,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000362 PMCR, 0x00, 0x00,
Keith Hui59356ca2010-03-06 18:16:25 +0000363
364 /* Enable SCRR.SRRAEN and let BX choose the SRR. */
365 SCRR + 1, 0x00, 0x10,
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000366};
367
368/*-----------------------------------------------------------------------------
369SDRAM configuration functions.
370-----------------------------------------------------------------------------*/
371
372/**
373 * Send the specified RAM command to all DIMMs.
374 *
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000375 * @param command The RAM command to send to the DIMM(s).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000376 */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000377static void do_ram_command(u32 command)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000378{
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000379 int i, caslatency;
380 u8 dimm_start, dimm_end;
381 u16 reg16;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800382 void *addr;
383 u32 addr_offset;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000384
385 /* Configure the RAM command. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000386 reg16 = pci_read_config16(NB, SDRAMC);
387 reg16 &= 0xff1f; /* Clear bits 7-5. */
388 reg16 |= (u16) (command << 5); /* Write command into bits 7-5. */
389 pci_write_config16(NB, SDRAMC, reg16);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000390
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000391 /*
392 * RAM_COMMAND_NORMAL affects only the memory controller and
393 * doesn't need to be "sent" to the DIMMs.
394 */
395 if (command == RAM_COMMAND_NORMAL)
396 return;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000397
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000398 /* Send the RAM command to each row of memory. */
399 dimm_start = 0;
400 for (i = 0; i < (DIMM_SOCKETS * 2); i++) {
Keith Hui59356ca2010-03-06 18:16:25 +0000401 addr_offset = 0;
402 caslatency = 3; /* TODO: Dynamically get CAS latency later. */
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000403 if (command == RAM_COMMAND_MRS) {
404 /*
405 * MAA[12:11,9:0] must be inverted when sent to DIMM
406 * 2 or 3 (no inversion if sent to DIMM 0 or 1).
407 */
408 if ((i >= 0 && i <= 3) && caslatency == 3)
409 addr_offset = 0x1d0;
410 if ((i >= 4 && i <= 7) && caslatency == 3)
411 addr_offset = 0x1e28;
412 if ((i >= 0 && i <= 3) && caslatency == 2)
413 addr_offset = 0x150;
414 if ((i >= 4 && i <= 7) && caslatency == 2)
415 addr_offset = 0x1ea8;
416 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000417
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000418 dimm_end = pci_read_config8(NB, DRB + i);
419
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800420 addr = (void *)((dimm_start * 8 * 1024 * 1024) + addr_offset);
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000421 if (dimm_end > dimm_start) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +0000422 read32(addr);
423 }
424
425 /* Set the start of the next DIMM. */
426 dimm_start = dimm_end;
427 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000428}
429
Keith Hui59356ca2010-03-06 18:16:25 +0000430static void set_dram_buffer_strength(void)
431{
Keith Huia8380fc2017-12-04 00:05:56 -0500432 /*
433 * Program MBSC[39:0] and MBFS[23:0].
434 *
435 * The 440BX datasheet says buffer frequency is independent from bus
436 * frequency and mismatch both ways are possible.
437 *
438 * MBSC[47:40] and MBFS[23] are reserved.
Keith Hui59356ca2010-03-06 18:16:25 +0000439 */
440
Keith Huia8380fc2017-12-04 00:05:56 -0500441 unsigned int i, reg, drb;
442 uint8_t mbsc0, mbfs0, mbfs1, mbfs2;
443 uint16_t mbsc1, mbsc3;
444
445 /*
446 * Tally how many rows between rows 0-3 and rows 4-7 are populated.
Keith Huib48ba662010-03-17 02:15:07 +0000447 * This determines how to program MBFS and MBSC.
448 */
449 uint8_t dimm03 = 0;
450 uint8_t dimm47 = 0;
451
Keith Huia8380fc2017-12-04 00:05:56 -0500452 for (drb = 0, i = DRB0; i <= DRB7; i++) {
453 reg = pci_read_config8(NB, i);
454 if (drb != reg) {
455 if (i <= DRB3)
Keith Huib48ba662010-03-17 02:15:07 +0000456 dimm03++;
Keith Huia8380fc2017-12-04 00:05:56 -0500457 else
Keith Huib48ba662010-03-17 02:15:07 +0000458 dimm47++;
Keith Huia8380fc2017-12-04 00:05:56 -0500459
460 drb = reg;
Keith Huib48ba662010-03-17 02:15:07 +0000461 }
462 }
463
Julius Wernercd49cce2019-03-05 16:53:33 -0800464 if (CONFIG(SDRAMPWR_4DIMM)) {
Keith Huia8380fc2017-12-04 00:05:56 -0500465 /*
466 * For a 4 DIMM board, based on ASUS P2B-LS mainboard.
Keith Huib48ba662010-03-17 02:15:07 +0000467 *
Keith Huia8380fc2017-12-04 00:05:56 -0500468 * There are four main conditions to check when programming
469 * DRAM buffer frequency and strength:
Keith Huib48ba662010-03-17 02:15:07 +0000470 *
471 * a: >2 rows populated across DIMM0,1
472 * b: >2 rows populated across DIMM2,3
473 * c: >4 rows populated across all DIMM slots
474 * and either one of:
475 * 1: NBXCFG[13] strapped as 100MHz, or
476 * 6: NBXCFG[13] strapped as 66MHz
477 *
478 * CKE0/FENA ----------------------------------------------------------+
Keith Huia8380fc2017-12-04 00:05:56 -0500479 * CKE1/GCKE ----------------------[ MBFS ]---------------------+|
480 * DQMA/CASA[764320]# -------------[ 0 = 66MHz ]--------------------+||
481 * DQMB1/CASB1# (Fixed for 66MHz) -[ 1 = 100MHz ]-------------------+|||
482 * DQMB5/CASB5# (Fixed for 66MHz) ---------------------------------+||||
483 * DQMA1/CASA1# (Fixed for 66MHz) --------------------------------+|||||
484 * DQMA5/CASA5# (Fixed for 66MHz) -------------------------------+||||||
485 * CSA[5:0]#,CSB[5:0]# ------------------------------------++++++|||||||
486 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
487 * MECC[7:0] #2/#1 ----------------------------------++|||||||||||||||||
488 * MD[63:0] #2/#1 ---------------------------------++|||||||||||||||||||
489 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
490 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
491 * Reserved ------------------------------------+|||||||||||||||||||||||
492 * ||||||||||||||||||||||||
493 * 3 32 21 10 0 * 2 21 10 0
494 * 9876543210987654321098765432109876543210 * 321098765432109876543210
495 * 10------------------------1010---------- a -1---------------11-----
496 * 11------------------------1111---------- !a -0---------------00-----
497 * --10--------------------------1010------ b --1----------------11---
498 * --11--------------------------1111------ !b --0----------------00---
499 * ----------------------------------1100-- c ----------------------1-
500 * ----------------------------------1011-- !c ----------------------0-
501 * ----1010101000000000000000------------00 1 ---11111111111111----1-0
502 * ----000000000000000000000010101010----00 6 ---1111111111111100000-0
503 * | | | | | | | | | | ||||||| | | | | | |
504 * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA
505 * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE
506 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
507 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# (66MHz: 2x)
508 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# (66MHz: 2x)
509 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# (66MHz: 2x)
510 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# (66MHz: 2x)
511 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (1x)
512 * | | | | | | | | | +--------------------- CSA6#/CKE2
513 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
514 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
515 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
516 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1
517 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2
518 * | | | +--------------------------------- MD[63:0] #1
519 * | | +----------------------------------- MD[63:0] #2
520 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
521 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
522 */
523 unsigned int fsb;
524
525 mbsc0 = 0xa0;
526 mbsc1 = 0x002a;
527 mbfs1 = 0xff;
528 mbfs2 = 0x1f;
529 if (pci_read_config8(NB, NBXCFG + 1) & 0x30) {
530 fsb = 66;
531 mbsc3 = 0xa000;
532 mbfs0 = 0x80;
533 } else {
534 fsb = 100;
535 mbsc3 = 0xaaa0;
536 mbfs0 = 0x84;
537 }
538 if (dimm03 > 2) {
539 mbfs2 |= 0x40;
540 if (fsb == 100)
541 mbfs0 |= 0x60;
542 } else {
543 mbsc3 |= 0xc000;
544 if (fsb == 100)
545 mbsc1 |= 0x003c;
546 }
547 if (dimm47 > 2) {
548 mbfs2 |= 0x20;
549 if (fsb == 100)
550 mbfs0 |= 0x18;
551 } else {
552 mbsc3 |= 0x3000;
553 if (fsb == 100) {
554 mbsc1 |= 0x0003;
555 mbsc0 |= 0xc0;
556 }
557 }
558 if ((dimm03 + dimm47) > 4) {
559 mbsc0 |= 0x30;
560 mbfs0 |= 0x02;
561 } else {
562 mbsc0 |= 0x2c;
563 }
564 } else {
565 /*
566 * For a 3 DIMM board, based on ASUS P2B mainboard.
567 *
568 * There are two main conditions to check when programming DRAM buffer
569 * frequency and strength:
570 *
571 * a: >2 rows populated across DIMM0,1
572 * c: >4 rows populated across all DIMM slots
573 *
574 * CKE0 ---------------------------------------------------------------+
575 * CKE1 ------------------------[ MBFS ]------------------------+|
Keith Huib48ba662010-03-17 02:15:07 +0000576 * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+||
577 * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+|||
578 * DQMB5/CASB5# ---------------------------------------------------+||||
579 * DQMA1/CASA1# --------------------------------------------------+|||||
580 * DQMA5/CASA5# -------------------------------------------------+||||||
581 * CSA0-5#,CSB0-5# ----------------------------------------++++++|||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500582 * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++|||||||||||||
Keith Huib48ba662010-03-17 02:15:07 +0000583 * MECC[7:0] #2/#1 (100MHz) -------------------------++|||||||||||||||||
584 * MD[63:0] #2/#1 (100MHz) ------------------------++|||||||||||||||||||
585 * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+|||||||||||||||||||||
586 * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+||||||||||||||||||||||
587 * Reserved ------------------------------------+|||||||||||||||||||||||
588 * ||||||||||||||||||||||||
Keith Huia8380fc2017-12-04 00:05:56 -0500589 * 3 32 21 10 0 * 2 21 10 0
590 * 9876543210987654321098765432109876543210 * 321098765432109876543210
591 * 10------------------------1111---------- a -1----------------------
592 * 11------------------------1010---------- !a -0----------------------
593 * --110000000010101010111111----1010--1010 * --01111000000000000000-0
594 * ----------------------------------11---- c ----------------------1-
595 * ----------------------------------10---- !c ----------------------0-
596 * | | | | | | | | | | ||||||| | | | | | |
597 * | | | | | | | | | | ||||||| | | | | | +- CKE0
598 * | | | | | | | | | | ||||||| | | | | +--- CKE1
599 * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]#
600 * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1#
601 * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5#
602 * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1#
603 * | | | | | | | | | | ||||||+------------- DQMA5/CASA5#
604 * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (2x)
605 * | | | | | | | | | +--------------------- CSA6#/CKE2
606 * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4
607 * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3
608 * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5
609 * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (1x)
610 * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (1x)
611 * | | | +--------------------------------- MD[63:0] #1 (1x)
612 * | | +----------------------------------- MD[63:0] #2 (1x)
613 * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB#
614 * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA#
Keith Huib48ba662010-03-17 02:15:07 +0000615 */
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000616
Keith Huia8380fc2017-12-04 00:05:56 -0500617 mbsc0 = 0xaa;
618 mbsc1 = 0xafea;
619 mbsc3 = 0xb00a;
620 mbfs0 = 0x00;
621 mbfs1 = 0x00;
622 mbfs2 = 0x1e;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000623
Keith Huia8380fc2017-12-04 00:05:56 -0500624 if (dimm03 > 2) {
625 mbsc1 |= 0x003c;
626 mbfs2 |= 0x40;
627 } else {
628 mbsc3 |= 0xc000;
Keith Huib48ba662010-03-17 02:15:07 +0000629 }
Keith Huia8380fc2017-12-04 00:05:56 -0500630 if ((dimm03 + dimm47) > 4) {
631 mbsc0 |= 0x30;
632 mbfs0 |= 0x02;
Keith Huib48ba662010-03-17 02:15:07 +0000633 }
634 }
Keith Huib48ba662010-03-17 02:15:07 +0000635
636 pci_write_config8(NB, MBSC + 0, mbsc0);
Keith Huia8380fc2017-12-04 00:05:56 -0500637 pci_write_config16(NB, MBSC + 1, mbsc1);
638 pci_write_config16(NB, MBSC + 3, mbsc3);
639 pci_write_config16(NB, MBFS + 0, mbfs1 << 8 | mbfs0);
Keith Huib48ba662010-03-17 02:15:07 +0000640 pci_write_config8(NB, MBFS + 2, mbfs2);
Keith Hui59356ca2010-03-06 18:16:25 +0000641}
642
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000643/*-----------------------------------------------------------------------------
Martin Roth128c1042016-11-18 09:29:03 -0700644DIMM-independent configuration functions.
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000645-----------------------------------------------------------------------------*/
Richard Smithcb8eab42006-07-24 04:25:47 +0000646
Uwe Hermann1683cef2008-11-27 00:47:07 +0000647static void spd_enable_refresh(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000648{
649 int i, value;
650 uint8_t reg;
651
Uwe Hermann1683cef2008-11-27 00:47:07 +0000652 reg = pci_read_config8(NB, DRAMC);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000653
654 for (i = 0; i < DIMM_SOCKETS; i++) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200655 value = smbus_read_byte(DIMM0 + i, SPD_REFRESH);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000656 if (value < 0)
657 continue;
658 reg = (reg & 0xf8) | refresh_rate_map[(value & 0x7f)];
659
Keith Hui09f5a742010-12-23 17:12:03 +0000660 PRINT_DEBUG(" Enabling refresh (DRAMC = 0x%02x) for DIMM %02x\n", reg, i);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000661 }
662
Uwe Hermann1683cef2008-11-27 00:47:07 +0000663 pci_write_config8(NB, DRAMC, reg);
Richard Smithcb8eab42006-07-24 04:25:47 +0000664}
665
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000666/*-----------------------------------------------------------------------------
667Public interface.
668-----------------------------------------------------------------------------*/
669
Uwe Hermann115c5b92010-10-09 17:00:18 +0000670void sdram_set_registers(void)
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000671{
672 int i, max;
Uwe Hermannbc3594732007-06-07 22:16:30 +0000673 uint8_t reg;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000674
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000675 PRINT_DEBUG("Northbridge prior to SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000676 DUMPNORTH();
677
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +0000678 max = ARRAY_SIZE(register_values);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000679
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000680 /* Set registers as specified in the register_values[] array. */
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000681 for (i = 0; i < max; i += 3) {
Uwe Hermann1683cef2008-11-27 00:47:07 +0000682 reg = pci_read_config8(NB, register_values[i]);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000683 reg &= register_values[i + 1];
684 reg |= register_values[i + 2] & ~(register_values[i + 1]);
Uwe Hermann1683cef2008-11-27 00:47:07 +0000685 pci_write_config8(NB, register_values[i], reg);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000686 }
687}
688
Keith Hui59356ca2010-03-06 18:16:25 +0000689struct dimm_size {
Keith Hui09f5a742010-12-23 17:12:03 +0000690 u32 side1;
691 u32 side2;
Keith Hui59356ca2010-03-06 18:16:25 +0000692};
693
694static struct dimm_size spd_get_dimm_size(unsigned int device)
695{
696 struct dimm_size sz;
697 int i, module_density, dimm_banks;
698 sz.side1 = 0;
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200699 module_density = smbus_read_byte(device, SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
700 dimm_banks = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000701
702 /* Find the size of side1. */
703 /* Find the larger value. The larger value is always side1. */
704 for (i = 512; i >= 0; i >>= 1) {
705 if ((module_density & i) == i) {
706 sz.side1 = i;
707 break;
708 }
709 }
710
711 /* Set to 0 in case it's single sided. */
712 sz.side2 = 0;
713
714 /* Test if it's a dual-sided DIMM. */
715 if (dimm_banks > 1) {
716 /* Test if there's a second value. If so it's asymmetrical. */
717 if (module_density != i) {
718 /*
719 * Find second value, picking up where we left off.
720 * i >>= 1 done initially to make sure we don't get
721 * the same value again.
722 */
723 for (i >>= 1; i >= 0; i >>= 1) {
724 if (module_density == (sz.side1 | i)) {
725 sz.side2 = i;
726 break;
727 }
728 }
729 /* If not, it's symmetrical. */
730 } else {
731 sz.side2 = sz.side1;
732 }
733 }
734
735 /*
736 * SPD byte 31 is the memory size divided by 4 so we
Martin Roth128c1042016-11-18 09:29:03 -0700737 * need to multiply by 4 to get the total size.
Keith Hui59356ca2010-03-06 18:16:25 +0000738 */
739 sz.side1 *= 4;
740 sz.side2 *= 4;
741
Keith Huia8380fc2017-12-04 00:05:56 -0500742 /*
743 * It is possible to partially use larger than supported
Anders Jenbo771b0e42010-04-27 08:45:30 +0000744 * modules by setting them to a supported size.
745 */
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200746 if (sz.side1 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000747 PRINT_DEBUG("Side1 was %dMB but only 128MB will be used.\n",
748 sz.side1);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000749 sz.side1 = 128;
750
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200751 if (sz.side2 > 128) {
Keith Hui09f5a742010-12-23 17:12:03 +0000752 PRINT_DEBUG("Side2 was %dMB but only 128MB will be used.\n",
753 sz.side2);
Anders Jenbo771b0e42010-04-27 08:45:30 +0000754 sz.side2 = 128;
755 }
756 }
757
Keith Hui59356ca2010-03-06 18:16:25 +0000758 return sz;
759}
760/*
761 * Sets DRAM attributes one DIMM at a time, based on SPD data.
762 * Northbridge settings that are set: NBXCFG[31:24], DRB0-DRB7, RPS, DRAMC.
763 */
764static void set_dram_row_attributes(void)
765{
Keith Huie089a3f2011-08-02 22:28:14 -0400766 int i, dra, drb, col, width, value, rps;
Keith Hui59356ca2010-03-06 18:16:25 +0000767 u8 bpr; /* Top 8 bits of PGPOL */
Keith Huie089a3f2011-08-02 22:28:14 -0400768 u8 nbxecc = 0; /* NBXCFG[31:24] */
769 u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */
Keith Hui59356ca2010-03-06 18:16:25 +0000770
Keith Huie089a3f2011-08-02 22:28:14 -0400771 edo = 0;
772 sd = 0;
773 regsd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000774 rps = 0;
775 drb = 0;
776 bpr = 0;
Keith Hui59356ca2010-03-06 18:16:25 +0000777
778 for (i = 0; i < DIMM_SOCKETS; i++) {
779 unsigned int device;
Uwe Hermannd773fd32010-11-20 20:23:08 +0000780 device = DIMM0 + i;
Keith Hui59356ca2010-03-06 18:16:25 +0000781 bpr >>= 2;
Keith Huie089a3f2011-08-02 22:28:14 -0400782 nbxecc >>= 2;
Keith Hui59356ca2010-03-06 18:16:25 +0000783
784 /* First check if a DIMM is actually present. */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200785 value = smbus_read_byte(device, SPD_MEMORY_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000786 /* This is 440BX! We do EDO too! */
787 if (value == SPD_MEMORY_TYPE_EDO
788 || value == SPD_MEMORY_TYPE_SDRAM) {
789
Keith Hui59356ca2010-03-06 18:16:25 +0000790 if (value == SPD_MEMORY_TYPE_EDO) {
Keith Huie089a3f2011-08-02 22:28:14 -0400791 edo = 1;
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000792 } else if (value == SPD_MEMORY_TYPE_SDRAM) {
Keith Huie089a3f2011-08-02 22:28:14 -0400793 sd = 1;
Keith Hui59356ca2010-03-06 18:16:25 +0000794 }
Keith Hui09f5a742010-12-23 17:12:03 +0000795 PRINT_DEBUG("Found DIMM in slot %d\n", i);
Keith Hui59356ca2010-03-06 18:16:25 +0000796
Keith Huie089a3f2011-08-02 22:28:14 -0400797 if (edo && sd) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800798 printk(BIOS_ERR, "Mixing EDO/SDRAM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000799 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000800 }
801
802 /* "DRA" is our RPS for the two rows on this DIMM. */
803 dra = 0;
804
805 /* Columns */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200806 col = smbus_read_byte(device, SPD_NUM_COLUMNS);
Keith Hui59356ca2010-03-06 18:16:25 +0000807
808 /*
809 * Is this an ECC DIMM? Actually will be a 2 if so.
810 * TODO: Other register than NBXCFG also needs this
811 * ECC information.
812 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200813 value = smbus_read_byte(device, SPD_DIMM_CONFIG_TYPE);
Keith Hui59356ca2010-03-06 18:16:25 +0000814
815 /* Data width */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200816 width = smbus_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
Anders Jenbo0e1e8062010-04-27 06:35:31 +0000817
Keith Hui59356ca2010-03-06 18:16:25 +0000818 /* Exclude error checking data width from page size calculations */
Keith Huie089a3f2011-08-02 22:28:14 -0400819 if (value) {
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200820 value = smbus_read_byte(device,
Keith Hui59356ca2010-03-06 18:16:25 +0000821 SPD_ERROR_CHECKING_SDRAM_WIDTH);
822 width -= value;
823 /* ### ECC */
824 /* Clear top 2 bits to help set up NBXCFG. */
Keith Huie089a3f2011-08-02 22:28:14 -0400825 nbxecc &= 0x3f;
Keith Hui59356ca2010-03-06 18:16:25 +0000826 } else {
827 /* Without ECC, top 2 bits should be 11. */
Keith Huie089a3f2011-08-02 22:28:14 -0400828 nbxecc |= 0xc0;
Keith Hui59356ca2010-03-06 18:16:25 +0000829 }
830
Keith Huie089a3f2011-08-02 22:28:14 -0400831 /* If any installed DIMM is *not* registered, this system cannot be
832 * configured for registered SDRAM.
833 * By registered, only the address and control lines need to be, which
834 * we can tell by reading SPD byte 21, bit 1.
835 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200836 value = smbus_read_byte(device, SPD_MODULE_ATTRIBUTES);
Keith Huie089a3f2011-08-02 22:28:14 -0400837
838 PRINT_DEBUG("DIMM is ");
839 if ((value & MODULE_REGISTERED) == 0) {
840 regsd = 0;
841 PRINT_DEBUG("not ");
842 }
843 PRINT_DEBUG("registered\n");
844
Keith Hui59356ca2010-03-06 18:16:25 +0000845 /* Calculate page size in bits. */
846 value = ((1 << col) * width);
847
848 /* Convert to KB. */
849 dra = (value >> 13);
850
851 /* Number of banks of DIMM (single or double sided). */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200852 value = smbus_read_byte(device, SPD_NUM_DIMM_BANKS);
Keith Hui59356ca2010-03-06 18:16:25 +0000853
854 /* Once we have dra, col is done and can be reused.
855 * So it's reused for number of banks.
856 */
Kyösti Mälkki3f882faf2020-01-07 12:10:02 +0200857 col = smbus_read_byte(device, SPD_NUM_BANKS_PER_SDRAM);
Keith Hui59356ca2010-03-06 18:16:25 +0000858
859 if (value == 1) {
860 /*
861 * Second bank of 1-bank DIMMs "doesn't have
862 * ECC" - or anything.
863 */
Keith Hui59356ca2010-03-06 18:16:25 +0000864 if (dra == 2) {
865 dra = 0x0; /* 2KB */
866 } else if (dra == 4) {
867 dra = 0x1; /* 4KB */
868 } else if (dra == 8) {
869 dra = 0x2; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000870 } else if (dra >= 16) {
871 /* Page sizes larger than supported are
872 * set to 8KB to use module partially.
873 */
874 PRINT_DEBUG("Page size forced to 8KB.\n");
875 dra = 0x2; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000876 } else {
877 dra = -1;
878 }
879 /*
880 * Sets a flag in PGPOL[BPR] if this DIMM has
881 * 4 banks per row.
882 */
883 if (col == 4)
884 bpr |= 0x40;
885 } else if (value == 2) {
886 if (dra == 2) {
887 dra = 0x0; /* 2KB */
888 } else if (dra == 4) {
889 dra = 0x05; /* 4KB */
890 } else if (dra == 8) {
891 dra = 0x0a; /* 8KB */
Anders Jenbo771b0e42010-04-27 08:45:30 +0000892 } else if (dra >= 16) {
893 /* Ditto */
894 PRINT_DEBUG("Page size forced to 8KB.\n");
895 dra = 0x0a; /* 8KB */
Keith Hui59356ca2010-03-06 18:16:25 +0000896 } else {
897 dra = -1;
898 }
899 /* Ditto */
900 if (col == 4)
901 bpr |= 0xc0;
902 } else {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800903 printk(BIOS_ERR, "# of banks of DIMM unsupported!\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000904 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000905 }
906 if (dra == -1) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800907 printk(BIOS_ERR, "Page size not supported\n");
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000908 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000909 }
910
911 /*
912 * 440BX supports asymmetrical dual-sided DIMMs,
913 * but can't handle DIMMs smaller than 8MB per
Anders Jenbo771b0e42010-04-27 08:45:30 +0000914 * side.
Keith Hui59356ca2010-03-06 18:16:25 +0000915 */
916 struct dimm_size sz = spd_get_dimm_size(device);
917 if ((sz.side1 < 8)) {
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800918 printk(BIOS_ERR, "DIMMs smaller than 8MB per side\n"
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000919 "are not supported on this NB.\n");
920 die("HALT\n");
Keith Hui59356ca2010-03-06 18:16:25 +0000921 }
Keith Hui59356ca2010-03-06 18:16:25 +0000922
923 /* Divide size by 8 to set up the DRB registers. */
924 drb += (sz.side1 / 8);
925
926 /*
927 * Build the DRB for the next row in MSB so it gets
928 * placed in DRB[n+1] where it belongs when written
929 * as a 16-bit word.
930 */
931 drb &= 0xff;
932 drb |= (drb + (sz.side2 / 8)) << 8;
933 } else {
Keith Hui59356ca2010-03-06 18:16:25 +0000934 /* If there's no DIMM in the slot, set dra to 0x00. */
935 dra = 0x00;
Keith Hui59356ca2010-03-06 18:16:25 +0000936 /* Still have to propagate DRB over. */
937 drb &= 0xff;
938 drb |= (drb << 8);
939 }
940
941 pci_write_config16(NB, DRB + (2 * i), drb);
Keith Hui59356ca2010-03-06 18:16:25 +0000942
943 /* Brings the upper DRB back down to be base for
944 * DRB calculations for the next two rows.
945 */
946 drb >>= 8;
947
948 rps |= (dra & 0x0f) << (i * 4);
Keith Hui59356ca2010-03-06 18:16:25 +0000949 }
950
951 /* Set paging policy register. */
952 pci_write_config8(NB, PGPOL + 1, bpr);
Keith Hui09f5a742010-12-23 17:12:03 +0000953 PRINT_DEBUG("PGPOL[BPR] has been set to 0x%02x\n", bpr);
Keith Hui59356ca2010-03-06 18:16:25 +0000954
955 /* Set DRAM row page size register. */
956 pci_write_config16(NB, RPS, rps);
Keith Hui09f5a742010-12-23 17:12:03 +0000957 PRINT_DEBUG("RPS has been set to 0x%04x\n", rps);
Keith Hui59356ca2010-03-06 18:16:25 +0000958
959 /* ### ECC */
960 pci_write_config8(NB, NBXCFG + 3, nbxecc);
Keith Hui09f5a742010-12-23 17:12:03 +0000961 PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
Keith Hui59356ca2010-03-06 18:16:25 +0000962
Keith Huie089a3f2011-08-02 22:28:14 -0400963 /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
Keith Hui59356ca2010-03-06 18:16:25 +0000964
Keith Huie089a3f2011-08-02 22:28:14 -0400965 /* i will be used to set DRAMC[4:3]. */
966 if (regsd && sd) {
967 i = 0x10; // Registered SDRAM
968 } else if (sd) {
969 i = 0x08; // SDRAM
970 } else {
971 i = 0; // EDO
972 }
973
Keith Hui59356ca2010-03-06 18:16:25 +0000974 value = pci_read_config8(NB, DRAMC) & 0xe7;
Keith Huie089a3f2011-08-02 22:28:14 -0400975 value |= i;
Keith Hui59356ca2010-03-06 18:16:25 +0000976 pci_write_config8(NB, DRAMC, value);
Keith Hui09f5a742010-12-23 17:12:03 +0000977 PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
Keith Hui59356ca2010-03-06 18:16:25 +0000978}
979
Uwe Hermann115c5b92010-10-09 17:00:18 +0000980void sdram_set_spd_registers(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000981{
Keith Hui59356ca2010-03-06 18:16:25 +0000982 /* Setup DRAM row boundary registers and other attributes. */
983 set_dram_row_attributes();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000984
Keith Huidf35cdc2010-09-20 23:41:37 +0000985 /* Setup DRAM buffer strength. */
Keith Hui59356ca2010-03-06 18:16:25 +0000986 set_dram_buffer_strength();
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000987
988 /* TODO: Set PMCR? */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000989 // pci_write_config8(NB, PMCR, 0x14);
990 pci_write_config8(NB, PMCR, 0x10);
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000991
Keith Huidf35cdc2010-09-20 23:41:37 +0000992 /* TODO: This is for EDO memory only. */
Uwe Hermann1683cef2008-11-27 00:47:07 +0000993 pci_write_config8(NB, DRAMT, 0x03);
Richard Smithcb8eab42006-07-24 04:25:47 +0000994}
995
Uwe Hermann115c5b92010-10-09 17:00:18 +0000996void sdram_enable(void)
Richard Smithcb8eab42006-07-24 04:25:47 +0000997{
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000998 int i;
Richard Smithcb8eab42006-07-24 04:25:47 +0000999
Uwe Hermann861f9642007-05-28 14:37:06 +00001000 /* 0. Wait until power/voltages and clocks are stable (200us). */
1001 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +00001002
Uwe Hermann861f9642007-05-28 14:37:06 +00001003 /* 1. Apply NOP. Wait 200 clock cycles (200us should do). */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001004 PRINT_DEBUG("RAM Enable 1: Apply NOP\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001005 do_ram_command(RAM_COMMAND_NOP);
Uwe Hermann861f9642007-05-28 14:37:06 +00001006 udelay(200);
Richard Smithcb8eab42006-07-24 04:25:47 +00001007
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001008 /* 2. Precharge all. Wait tRP. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001009 PRINT_DEBUG("RAM Enable 2: Precharge all\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001010 do_ram_command(RAM_COMMAND_PRECHARGE);
Uwe Hermann861f9642007-05-28 14:37:06 +00001011 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001012
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001013 /* 3. Perform 8 refresh cycles. Wait tRC each time. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001014 PRINT_DEBUG("RAM Enable 3: CBR\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001015 for (i = 0; i < 8; i++) {
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001016 do_ram_command(RAM_COMMAND_CBR);
Uwe Hermann861f9642007-05-28 14:37:06 +00001017 udelay(1);
Richard Smithcb8eab42006-07-24 04:25:47 +00001018 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001019
1020 /* 4. Mode register set. Wait two memory cycles. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001021 PRINT_DEBUG("RAM Enable 4: Mode register set\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001022 do_ram_command(RAM_COMMAND_MRS);
Uwe Hermann861f9642007-05-28 14:37:06 +00001023 udelay(2);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001024
1025 /* 5. Normal operation. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001026 PRINT_DEBUG("RAM Enable 5: Normal operation\n");
Uwe Hermann8b643cea2008-12-09 16:36:12 +00001027 do_ram_command(RAM_COMMAND_NORMAL);
Uwe Hermann861f9642007-05-28 14:37:06 +00001028 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001029
1030 /* 6. Finally enable refresh. */
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001031 PRINT_DEBUG("RAM Enable 6: Enable refresh\n");
Uwe Hermann1683cef2008-11-27 00:47:07 +00001032 // pci_write_config8(NB, PMCR, 0x10);
1033 spd_enable_refresh();
Uwe Hermann861f9642007-05-28 14:37:06 +00001034 udelay(1);
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001035
Stefan Reinauer64ed2b72010-03-31 14:47:43 +00001036 PRINT_DEBUG("Northbridge following SDRAM init:\n");
Uwe Hermann1a9c8922007-04-01 17:24:03 +00001037 DUMPNORTH();
Richard Smithcb8eab42006-07-24 04:25:47 +00001038}
Keith Hui078e3242017-07-20 21:14:21 -04001039
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001040/* Implemented under mainboard. */
1041void __weak enable_spd(void) { }
1042void __weak disable_spd(void) { }
1043
Keith Hui078e3242017-07-20 21:14:21 -04001044void sdram_initialize(void)
1045{
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001046 enable_spd();
1047
Keith Hui078e3242017-07-20 21:14:21 -04001048 dump_spd_registers();
1049 sdram_set_registers();
1050 sdram_set_spd_registers();
1051 sdram_enable();
Kyösti Mälkki93e08c72020-01-07 15:17:48 +02001052
1053 disable_spd();
Martin Rothe1695e22017-07-24 11:28:50 -06001054}