blob: 20efdea8cdb21dfc31f51cff5cfc8238f1b8aad3 [file] [log] [blame]
Corey Osgoodbd3f93e2008-02-21 00:56:14 +00001/*
2 * This file is part of the coreboot project.
3 *
Aaron Lwefcb2a312008-05-19 12:17:43 +00004 * Copyright (C) 2008 VIA Technologies, Inc.
5 * (Written by Aaron Lwe <aaron.lwe@gmail.com> for VIA)
Corey Osgoodbd3f93e2008-02-21 00:56:14 +00006 * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <spd.h>
24#include <sdram_mode.h>
25#include <delay.h>
26#include "cn700.h"
27
28//#define DEBUG_RAM_SETUP 1
29
30#ifdef DEBUG_RAM_SETUP
31#define PRINT_DEBUG_MEM(x) print_debug(x)
32#define PRINT_DEBUG_MEM_HEX8(x) print_debug_hex8(x)
33#define PRINT_DEBUG_MEM_HEX16(x) print_debug_hex16(x)
34#define PRINT_DEBUG_MEM_HEX32(x) print_debug_hex32(x)
35#define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
36#else
37#define PRINT_DEBUG_MEM(x)
38#define PRINT_DEBUG_MEM_HEX8(x)
39#define PRINT_DEBUG_MEM_HEX16(x)
40#define PRINT_DEBUG_MEM_HEX32(x)
41#define DUMPNORTH()
42#endif
43
Aaron Lwefcb2a312008-05-19 12:17:43 +000044static void do_ram_command(device_t dev, u8 command)
Corey Osgoodbd3f93e2008-02-21 00:56:14 +000045{
46 u8 reg;
47
48 /* TODO: Support for multiple DIMMs. */
49
50 reg = pci_read_config8(dev, DRAM_MISC_CTL);
51 reg &= 0xf8; /* Clear bits 2-0. */
52 reg |= command;
53 pci_write_config8(dev, DRAM_MISC_CTL, reg);
54
55 PRINT_DEBUG_MEM(" Sending RAM command 0x");
56 PRINT_DEBUG_MEM_HEX8(reg);
57 PRINT_DEBUG_MEM(" to 0x");
58 PRINT_DEBUG_MEM_HEX32(0 + addr_offset);
59 PRINT_DEBUG_MEM("\r\n");
Corey Osgoodbd3f93e2008-02-21 00:56:14 +000060}
61
Corey Osgoodbd3f93e2008-02-21 00:56:14 +000062/**
63 * Configure the bus between the cpu and the northbridge. This might be able to
64 * be moved to post-ram code in the future. For the most part, these registers
65 * should not be messed around with. These are too complex to explain short of
66 * copying the datasheets into the comments, but most of these values are from
67 * the BIOS Porting Guide, so they should work on any board. If they don't,
68 * try the values from your factory BIOS.
69 *
70 * TODO: Changing the DRAM frequency doesn't work (hard lockup)
71 *
72 * @param dev The northbridge's CPU Host Interface (D0F2)
73 */
74static void c7_cpu_setup(device_t dev)
75{
76 /* Host bus interface registers (D0F2 0x50-0x67) */
77 /* Request phase control */
78 pci_write_config8(dev, 0x50, 0x88);
79 /* CPU Interface Control */
80 pci_write_config8(dev, 0x51, 0x7a);
81 pci_write_config8(dev, 0x52, 0x6f);
82 /* Arbitration */
83 pci_write_config8(dev, 0x53, 0x88);
84 /* Miscellaneous Control */
Aaron Lwefcb2a312008-05-19 12:17:43 +000085 pci_write_config8(dev, 0x54, 0x1e);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +000086 pci_write_config8(dev, 0x55, 0x16);
87 /* Write Policy */
88 pci_write_config8(dev, 0x56, 0x01);
89 /* Miscellaneous Control */
90 /* DRAM Operating Frequency (Bits 7:5)
91 * 000 : 100MHz 001 : 133MHz
92 * 010 : 166MHz 011 : 200MHz
93 * 100 : 266MHz 101 : 333MHz
94 * 110/111 : Reserved */
Corey Osgoodbd3f93e2008-02-21 00:56:14 +000095 /* CPU Miscellaneous Control */
Aaron Lwefcb2a312008-05-19 12:17:43 +000096 pci_write_config8(dev, 0x59, 0x44);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +000097 /* Write Policy */
98 pci_write_config8(dev, 0x5d, 0xb2);
99 /* Bandwidth Timer */
100 pci_write_config8(dev, 0x5e, 0x88);
101 /* CPU Miscellaneous Control */
102 pci_write_config8(dev, 0x5f, 0xc7);
103
104 /* Line DRDY# Timing Control */
105 pci_write_config8(dev, 0x60, 0xff);
106 pci_write_config8(dev, 0x61, 0xff);
107 pci_write_config8(dev, 0x62, 0x0f);
108 /* QW DRDY# Timing Control */
109 pci_write_config8(dev, 0x63, 0xff);
110 pci_write_config8(dev, 0x64, 0xff);
111 pci_write_config8(dev, 0x65, 0x0f);
112 /* Read Line Burst DRDY# Timing Control */
113 pci_write_config8(dev, 0x66, 0xff);
Aaron Lwefcb2a312008-05-19 12:17:43 +0000114 pci_write_config8(dev, 0x67, 0x30);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000115
116 /* Host Bus IO Circuit (See datasheet) */
117 /* Host Address Pullup/down Driving */
Aaron Lwefcb2a312008-05-19 12:17:43 +0000118 pci_write_config8(dev, 0x70, 0x11);
119 pci_write_config8(dev, 0x71, 0x11);
120 pci_write_config8(dev, 0x72, 0x11);
121 pci_write_config8(dev, 0x73, 0x11);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000122 /* Miscellaneous Control */
Aaron Lwefcb2a312008-05-19 12:17:43 +0000123 pci_write_config8(dev, 0x74, 0x35);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000124 /* AGTL+ I/O Circuit */
125 pci_write_config8(dev, 0x75, 0x28);
126 /* AGTL+ Compensation Status */
127 pci_write_config8(dev, 0x76, 0x74);
128 /* AGTL+ Auto Compensation Offest */
129 pci_write_config8(dev, 0x77, 0x00);
130 /* Host FSB CKG Control */
131 pci_write_config8(dev, 0x78, 0x0a);
132 /* Address/Address Clock Output Delay Control */
133 pci_write_config8(dev, 0x79, 0xaa);
134 /* Address Strobe Input Delay Control */
135 pci_write_config8(dev, 0x7a, 0x24);
Aaron Lwefcb2a312008-05-19 12:17:43 +0000136 // Address CKG Rising/Falling Time Control
137 pci_write_config8(dev, 0x7b, 0xaa);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000138 /* Address CKG Clock Rising/Falling Time Control */
139 pci_write_config8(dev, 0x7c, 0x00);
140 /* Undefined (can't remember why I did this) */
Aaron Lwefcb2a312008-05-19 12:17:43 +0000141 pci_write_config8(dev, 0x7d, 0x6d);
142 pci_write_config8(dev, 0x7e, 0x00);
143 pci_write_config8(dev, 0x7f, 0x00);
144 pci_write_config8(dev, 0x80, 0x1b);
145 pci_write_config8(dev, 0x81, 0x0a);
146 pci_write_config8(dev, 0x82, 0x0a);
147 pci_write_config8(dev, 0x83, 0x0a);
148}
149
150/**
151 * Set up dram size according to spd data. Eventually, DRAM timings should be
152 * done in a similar manner.
153 *
154 * @param ctrl The northbridge devices and spd addresses.
155 */
156static void sdram_set_size(const struct mem_controller *ctrl)
157{
158 u8 density, ranks, result, col;
159
160 ranks = spd_read_byte(ctrl->channel0[0], SPD_NUM_DIMM_BANKS);
161 ranks = (ranks & 0x07) + 1;
162 density = spd_read_byte(ctrl->channel0[0], SPD_DENSITY_OF_EACH_ROW_ON_MODULE);
163 switch (density)
164 {
165 case 0x80:
166 result = 0x08; /* 512MB / 64MB = 0x08 */
167 break;
168 case 0x40:
169 result = 0x04;
170 break;
171 case 0x20:
172 result = 0x02;
173 break;
174 case 0x10:
175 result = 0xff; /* 16GB */
176 break;
177 case 0x08:
178 result = 0xff; /* 8GB */
179 break;
180 case 0x04:
181 result = 0xff; /* 4GB */
182 break;
183 case 0x02:
184 result = 0x20; /* 2GB */
185 break;
186 case 0x01:
187 result = 0x10; /* 1GB */
188 break;
189 }
190
191 if (result == 0xff)
192 die("dram module size too big, not supported by cn700\r\n");
193
194 pci_write_config8(ctrl->d0f3, 0x40, result);
195 pci_write_config8(ctrl->d0f3, 0x48, 0x00);
196 if (ranks == 2) {
197 pci_write_config8(ctrl->d0f3, 0x41, result * ranks);
198 pci_write_config8(ctrl->d0f3, 0x49, result);
199 }
200 /* size mirror */
201 pci_write_config8(ctrl->d0f7, 0xe5, (result * ranks) << 2);
202 pci_write_config8(ctrl->d0f7, 0x57, (result * ranks) << 2);
203 /* Low Top Address */
204 pci_write_config8(ctrl->d0f3, 0x84, 0x00);
205 pci_write_config8(ctrl->d0f3, 0x85, (result * ranks) << 2);
206 pci_write_config8(ctrl->d0f3, 0x88, (result * ranks) << 2);
207
208 /* Physical-Virtual Mapping */
209 if (ranks == 2)
210 pci_write_config8(ctrl->d0f3, 0x54, 1 << 7 | 0 << 4 | 1 << 3 | 1 << 0);
211 if (ranks == 1)
212 pci_write_config8(ctrl->d0f3, 0x54, 1 << 7 | 0 << 4);
213 pci_write_config8(ctrl->d0f3, 0x55, 0x00);
214 /* virtual rank interleave, disable */
215 pci_write_config32(ctrl->d0f3, 0x58, 0x00);
216
217 /* MA Map Type */
218 result = spd_read_byte(ctrl->channel0[0], SPD_NUM_BANKS_PER_SDRAM);
219 if (result == 8) {
220 col = spd_read_byte(ctrl->channel0[0], SPD_NUM_COLUMNS);
221 switch (col)
222 {
223 case 10:
224 pci_write_config8(ctrl->d0f3, 0x50, 0xa0);
225 break;
226 case 11:
227 pci_write_config8(ctrl->d0f3, 0x50, 0xc0);
228 break;
229 case 12:
230 pci_write_config8(ctrl->d0f3, 0x50, 0xe0);
231 break;
232 }
233 }
234 else if (result == 4) {
235 col = spd_read_byte(ctrl->channel0[0], SPD_NUM_COLUMNS);
236 switch (col)
237 {
238 case 9:
239 pci_write_config8(ctrl->d0f3, 0x50, 0x00);
240 break;
241 case 10:
242 pci_write_config8(ctrl->d0f3, 0x50, 0x20);
243 break;
244 case 11:
245 pci_write_config8(ctrl->d0f3, 0x50, 0x40);
246 break;
247 case 12:
248 pci_write_config8(ctrl->d0f3, 0x50, 0x60);
249 break;
250 }
251 }
252 pci_write_config8(ctrl->d0f3, 0x51, 0x00);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000253}
254
255/**
256 * Set up various ram and other control registers statically. Some of these may
257 * not be needed, other should be done with spd info, but that's a project for
258 * the future
259 */
260static void sdram_set_registers(const struct mem_controller *ctrl)
261{
Aaron Lwefcb2a312008-05-19 12:17:43 +0000262 u8 reg;
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000263
Aaron Lwefcb2a312008-05-19 12:17:43 +0000264 /* Set WR=5 */
265 pci_write_config8(ctrl->d0f3, 0x61, 0xe0);
266 /* Set CAS=4 */
267 pci_write_config8(ctrl->d0f3, 0x62, 0xfa);
268 /* dram timing-3 */
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000269 pci_write_config8(ctrl->d0f3, 0x63, 0xca);
Aaron Lwefcb2a312008-05-19 12:17:43 +0000270 /* dram timing-4 */
271 pci_write_config8(ctrl->d0f3, 0x64, 0xcc);
272 /* DIMM command / Address Selection */
273 pci_write_config8(ctrl->d0f3, 0x67, 0x00);
274 /* Disable cross bank/multi page mode */
275 pci_write_config8(ctrl->d0f3, 0x69, 0x00);
276 /* disable refresh now */
277 pci_write_config8(ctrl->d0f3, 0x6a, 0x00);
278
279 /* frequency 100MHZ */
280 pci_write_config8(ctrl->d0f3, 0x90, 0x00);
281 pci_write_config8(ctrl->d0f2, 0x57, 0x18);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000282 /* Allow manual dll reset */
283 pci_write_config8(ctrl->d0f3, 0x6b, 0x10);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000284
Aaron Lwefcb2a312008-05-19 12:17:43 +0000285 /* Bank/Rank Interleave Address Select */
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000286 pci_write_config8(ctrl->d0f3, 0x52, 0x33);
287 pci_write_config8(ctrl->d0f3, 0x53, 0x3f);
288
Aaron Lwefcb2a312008-05-19 12:17:43 +0000289 /* Set to DDR2 sdram, BL=8 (0xc8, 0xc0 for bl=4) */
290 pci_write_config8(ctrl->d0f3, 0x6c, 0xc8);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000291
Aaron Lwefcb2a312008-05-19 12:17:43 +0000292 /* DRAM Bus Turn-Around Setting */
293 pci_write_config8(ctrl->d0f3, 0x60, 0x03);
294 /* DRAM Arbitration Control */
295 pci_write_config8(ctrl->d0f3, 0x66, 0x80);
296 /* DQS Tuning: testing on a couple different boards has shown this is
297 * static, or close enough that it can be. Which is good, because the
298 * tuning function used too many registers
299 */
300 /* DQS Output Delay for CHannel A */
301 pci_write_config8(ctrl->d0f3, 0x70, 0x00);
302 /* MD Output Delay for Channel A */
303 pci_write_config8(ctrl->d0f3, 0x71, 0x01);
304 pci_write_config8(ctrl->d0f3, 0x73, 0x01);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000305
Aaron Lwefcb2a312008-05-19 12:17:43 +0000306 /* dram arbitration timer */
307 pci_write_config8(ctrl->d0f3, 0x65, 0xd9);
308
309 /* dram signal timing control */
310 pci_write_config8(ctrl->d0f3, 0x74, 0x01);
311 pci_write_config8(ctrl->d0f3, 0x75, 0x01);
312 pci_write_config8(ctrl->d0f3, 0x76, 0x06);
313 pci_write_config8(ctrl->d0f3, 0x77, 0x92);
314 pci_write_config8(ctrl->d0f3, 0x78, 0x83);
315 pci_write_config8(ctrl->d0f3, 0x79, 0x83);
316 pci_write_config8(ctrl->d0f3, 0x7a, 0x00);
317 pci_write_config8(ctrl->d0f3, 0x7b, 0x10);
318
319 /* dram clocking control */
320 pci_write_config8(ctrl->d0f3, 0x91, 0x01);
321 /* CS/CKE Clock Phase Control */
322 pci_write_config8(ctrl->d0f3, 0x92, 0x02);
323 /* SCMD/MA Clock Phase Control */
324 pci_write_config8(ctrl->d0f3, 0x93, 0x02);
325 /* DCLKO Feedback Mode Output Control */
326 pci_write_config8(ctrl->d0f3, 0x94, 0x00);
327 pci_write_config8(ctrl->d0f3, 0x9d, 0x0f);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000328
Aaron Lwefcb2a312008-05-19 12:17:43 +0000329 /* SDRAM ODT Control */
330 pci_write_config8(ctrl->d0f3, 0xda, 0x80);
331 /* Channel A DQ/DQS CKG Output Delay Control */
332 pci_write_config8(ctrl->d0f3, 0xdc, 0x54);
333 /* Channel A DQ/DQS CKG Output Delay Control */
334 pci_write_config8(ctrl->d0f3, 0xdd, 0x55);
335 /* odt lookup table */
336 pci_write_config8(ctrl->d0f3, 0xd8, 0x01);
337 pci_write_config8(ctrl->d0f3, 0xd9, 0x0a);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000338
Aaron Lwefcb2a312008-05-19 12:17:43 +0000339 /* ddr sdram control */
340 pci_write_config8(ctrl->d0f3, 0x6d, 0xc0);
341 pci_write_config8(ctrl->d0f3, 0x6f, 0x41);
342
343 /* DQ/DQS Strength Control */
344 pci_write_config8(ctrl->d0f3, 0xd0, 0xaa);
345
346 /* Compensation Control */
347 pci_write_config8(ctrl->d0f3, 0xd3, 0x01); /*enable auto compensation*/
348 /* ODT (some are set with driving select above) */
349 pci_write_config8(ctrl->d0f3, 0xd4, 0x80);
350 pci_write_config8(ctrl->d0f3, 0xd5, 0x8a);
351 /* Memory Pads Driving and Range Select */
352 pci_write_config8(ctrl->d0f3, 0xd6, 0xaa);
353
354 pci_write_config8(ctrl->d0f3, 0xe0, 0xee);
355 pci_write_config8(ctrl->d0f3, 0xe2, 0xac);
356 pci_write_config8(ctrl->d0f3, 0xe4, 0x66);
357 pci_write_config8(ctrl->d0f3, 0xe6, 0x33);
358 pci_write_config8(ctrl->d0f3, 0xe8, 0x86);
359 /* DQS / DQ CKG Duty Cycle Control */
360 pci_write_config8(ctrl->d0f3, 0xec, 0x00);
361 /* MCLK Output Duty Control */
362 pci_write_config8(ctrl->d0f3, 0xee, 0x00);
363 /* DQS CKG Input Delay Control */
364 pci_write_config8(ctrl->d0f3, 0xef, 0x10);
365
366 /* dram duty control */
367 pci_write_config8(ctrl->d0f3, 0xed, 0x10);
368
Bari Arid4759d02008-09-01 01:48:07 +0000369 /* SMM and APIC decoding, we do not use SMM */
Aaron Lwefcb2a312008-05-19 12:17:43 +0000370 reg = 0x29;
371 pci_write_config8(ctrl->d0f3, 0x86, reg);
372 /* SMM and APIC decoding mirror */
373 pci_write_config8(ctrl->d0f7, 0xe6, reg);
374
375 /* dram module configuration */
376 pci_write_config8(ctrl->d0f3, 0x6e, 0x89);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000377}
378
Aaron Lwefcb2a312008-05-19 12:17:43 +0000379static void sdram_set_post(const struct mem_controller *ctrl)
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000380{
Aaron Lwefcb2a312008-05-19 12:17:43 +0000381 device_t dev = ctrl->d0f3;
382 /* Enable multipage mode. */
383 pci_write_config8(dev, 0x69, 0x03);
384
385 /* Enable refresh. */
386 pci_write_config8(dev, 0x6a, 0x32);
387
388 // vga device
389 pci_write_config16(dev, 0xa0, (1 <<15));
390 pci_write_config16(dev, 0xa4, 0x0010);
391
392}
393
394static void sdram_enable(device_t dev, unsigned long rank_address)
395{
396 u8 i;
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000397
398 /* 1. Apply NOP. */
399 PRINT_DEBUG_MEM("RAM Enable 1: Apply NOP\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000400 do_ram_command(dev, RAM_COMMAND_NOP);
401 udelay(100);
402 read32(rank_address + 0x10);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000403
404 /* 2. Precharge all. */
Aaron Lwefcb2a312008-05-19 12:17:43 +0000405 udelay(400);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000406 PRINT_DEBUG_MEM("RAM Enable 2: Precharge all\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000407 do_ram_command(dev, RAM_COMMAND_PRECHARGE);
408 read32(rank_address + 0x10);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000409
410 /* 3. Mode register set. */
411 PRINT_DEBUG_MEM("RAM Enable 4: Mode register set\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000412 do_ram_command(dev, RAM_COMMAND_MRS);
413 read32(rank_address + 0x120000);// EMRS DLL Enable
414 read32(rank_address + 0x800); // MRS DLL Reset
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000415
416 /* 4. Precharge all again. */
417 PRINT_DEBUG_MEM("RAM Enable 2: Precharge all\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000418 do_ram_command(dev, RAM_COMMAND_PRECHARGE);
419 read32(rank_address + 0x0);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000420
421 /* 5. Perform 8 refresh cycles. Wait tRC each time. */
422 PRINT_DEBUG_MEM("RAM Enable 3: CBR\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000423 do_ram_command(dev, RAM_COMMAND_CBR);
424 for(i = 0; i < 8; i++) {
425 read32(rank_address + 0x20);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000426 udelay(100);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000427 }
428
429 /* 6. Mode register set. */
430 PRINT_DEBUG_MEM("RAM Enable 4: Mode register set\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000431 //safe value for now, BL=8, WR=5, CAS=4
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000432 /* (E)MRS values are from the BPG. No direct explanation is given, but
433 * they should somehow conform to the JEDEC DDR2 SDRAM Specification
434 * (JESD79-2C). */
Aaron Lwefcb2a312008-05-19 12:17:43 +0000435 do_ram_command(dev, RAM_COMMAND_MRS);
436 read32(rank_address + 0x002258); // MRS command
437 read32(rank_address + 0x121c20); // EMRS OCD Default
438 read32(rank_address + 0x120020); // EMRS OCD Calibration Mode Exit
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000439
440 /* 8. Normal operation */
441 PRINT_DEBUG_MEM("RAM Enable 5: Normal operation\r\n");
Aaron Lwefcb2a312008-05-19 12:17:43 +0000442 do_ram_command(dev, RAM_COMMAND_NORMAL);
443 read32(rank_address + 0x30);
Corey Osgoodbd3f93e2008-02-21 00:56:14 +0000444}
Aaron Lwefcb2a312008-05-19 12:17:43 +0000445
446/*
447 * Support one dimm with up to 2 ranks
448 */
449static void ddr_ram_setup(const struct mem_controller *ctrl)
450{
451 u8 reg;
452
453 c7_cpu_setup(ctrl->d0f2);
454 sdram_set_registers(ctrl);
455 sdram_set_size(ctrl);
456 sdram_enable(ctrl->d0f3, 0);
457 reg = pci_read_config8(ctrl->d0f3, 0x41);
458 if (reg != 0)
459 sdram_enable(ctrl->d0f3, pci_read_config8(ctrl->d0f3, 0x40) << 26);
460 sdram_set_post(ctrl);
461}
462