blob: 46ec6b88307da982d6994daf8f2d79bc86fd0d98 [file] [log] [blame]
Nils Jacobs76890dd2010-11-01 15:20:27 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
5 * Copyright (C) 2010 Nils Jacobs
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Nils Jacobs76890dd2010-11-01 15:20:27 +000015 */
16
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +000017#include <cpu/amd/gx2def.h>
Nils Jacobs76890dd2010-11-01 15:20:27 +000018#include <spd.h>
19
20static const unsigned char NumColAddr[] = {
21 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x07,
22 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
23};
24
Edward O'Callaghand2a75232014-06-29 02:27:19 +100025static void __attribute__((noreturn)) hcf(void)
Nils Jacobs76890dd2010-11-01 15:20:27 +000026{
Nils Jacobsa1e2c562010-11-05 00:13:14 +000027 printk(BIOS_EMERG, "DIE\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000028 /* this guarantees we flush the UART fifos (if any) and also
29 * ensures that things, in general, keep going so no debug output
30 * is lost
31 */
32 while (1)
Nils Jacobsa1e2c562010-11-05 00:13:14 +000033 printk(BIOS_EMERG, (0));
Nils Jacobs76890dd2010-11-01 15:20:27 +000034}
35
36static void auto_size_dimm(unsigned int dimm)
37{
38 uint32_t dimm_setting;
39 uint16_t dimm_size;
40 uint8_t spd_byte;
41 msr_t msr;
42
43 dimm_setting = 0;
44
Nils Jacobsa1e2c562010-11-05 00:13:14 +000045 printk(BIOS_DEBUG, "Check present\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000046 /* Check that we have a dimm */
47 if (spd_read_byte(dimm, SPD_MEMORY_TYPE) == 0xFF) {
48 return;
49 }
50
Nils Jacobsa1e2c562010-11-05 00:13:14 +000051 printk(BIOS_DEBUG, "MODBANKS\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000052 /* Field: Module Banks per DIMM */
53 /* EEPROM byte usage: (5) Number of DIMM Banks */
54 spd_byte = spd_read_byte(dimm, SPD_NUM_DIMM_BANKS);
55 if ((MIN_MOD_BANKS > spd_byte) || (spd_byte > MAX_MOD_BANKS)) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +000056 printk(BIOS_EMERG, "Number of module banks not compatible\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000057 post_code(ERROR_BANK_SET);
58 hcf();
59 }
60 dimm_setting |= (spd_byte >> 1) << CF07_UPPER_D0_MB_SHIFT;
Nils Jacobs76890dd2010-11-01 15:20:27 +000061
Nils Jacobsa1e2c562010-11-05 00:13:14 +000062 printk(BIOS_DEBUG, "FIELDBANKS\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000063 /* Field: Banks per SDRAM device */
64 /* EEPROM byte usage: (17) Number of Banks on SDRAM Device */
65 spd_byte = spd_read_byte(dimm, SPD_NUM_BANKS_PER_SDRAM);
66 if ((MIN_DEV_BANKS > spd_byte) || (spd_byte > MAX_DEV_BANKS)) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +000067 printk(BIOS_EMERG, "Number of device banks not compatible\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000068 post_code(ERROR_BANK_SET);
69 hcf();
70 }
71 dimm_setting |= (spd_byte >> 2) << CF07_UPPER_D0_CB_SHIFT;
Nils Jacobs76890dd2010-11-01 15:20:27 +000072
Nils Jacobsa1e2c562010-11-05 00:13:14 +000073 printk(BIOS_DEBUG, "SPDNUMROWS\n");
Nils Jacobs5beac7f2010-11-03 13:19:50 +000074 /* Field: DIMM size
75 * EEPROM byte usage:
76 * (3) Number of Row Addresses
77 * (4) Number of Column Addresses
78 * (5) Number of DIMM Banks
79 * (31) Module Bank Density
80 * Size = Module Density * Module Banks
Nils Jacobs76890dd2010-11-01 15:20:27 +000081 */
82 if ((spd_read_byte(dimm, SPD_NUM_ROWS) & 0xF0)
83 || (spd_read_byte(dimm, SPD_NUM_COLUMNS) & 0xF0)) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +000084 printk(BIOS_EMERG, "Asymmetric DIMM not compatible\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000085 post_code(ERROR_UNSUPPORTED_DIMM);
86 hcf();
87 }
Nils Jacobs76890dd2010-11-01 15:20:27 +000088
Nils Jacobsa1e2c562010-11-05 00:13:14 +000089 printk(BIOS_DEBUG, "SPDBANKDENSITY\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000090 dimm_size = spd_read_byte(dimm, SPD_BANK_DENSITY);
Nils Jacobsa1e2c562010-11-05 00:13:14 +000091 printk(BIOS_DEBUG, "DIMMSIZE\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000092 dimm_size |= (dimm_size << 8); /* align so 1GB(bit0) is bit 8, this is a little weird to get gcc to not optimize this out */
93 dimm_size &= 0x01FC; /* and off 2GB DIMM size : not supported and the 1GB size we just moved up to bit 8 as well as all the extra on top */
94
Nils Jacobs5beac7f2010-11-03 13:19:50 +000095 /* Module Density * Module Banks */
Nils Jacobs76890dd2010-11-01 15:20:27 +000096 dimm_size <<= (dimm_setting >> CF07_UPPER_D0_MB_SHIFT) & 1; /* shift to multiply by # DIMM banks */
Nils Jacobsa1e2c562010-11-05 00:13:14 +000097 printk(BIOS_DEBUG, "BEFORT CTZ\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +000098 dimm_size = __builtin_ctz(dimm_size);
Nils Jacobsa1e2c562010-11-05 00:13:14 +000099 printk(BIOS_DEBUG, "TEST DIMM SIZE>7\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000100 if (dimm_size > 7) { /* 7 is 512MB only support 512MB per DIMM */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000101 printk(BIOS_EMERG, "Only support up to 512MB per DIMM\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000102 post_code(ERROR_DENSITY_DIMM);
103 hcf();
104 }
105 dimm_setting |= dimm_size << CF07_UPPER_D0_SZ_SHIFT;
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000106 printk(BIOS_DEBUG, "PAGESIZE\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000107
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000108/*
109 * Field: PAGE size
110 * EEPROM byte usage: (4) Number of Column Addresses
111 * PageSize = 2^# Column Addresses * Data width in bytes
112 * (should be 8bytes for a normal DIMM)
113 *
114 * But this really works by magic.
115 * If ma[11:0] is the memory address pins, and pa[13:0] is the physical column
116 * address that MC generates, here is how the MC assigns the pa onto the
117 * ma pins:
118 *
119 * ma 11 10 09 08 07 06 05 04 03 02 01 00
120 * ---------------------------------------
121 * pa 09 08 07 06 05 04 03 (7 col addr bits = 1K page size)
122 * pa 10 09 08 07 06 05 04 03 (8 col addr bits = 2K page size)
123 * pa 11 10 09 08 07 06 05 04 03 (9 col addr bits = 4K page size)
124 * pa 12 11 10 09 08 07 06 05 04 03 (10 col addr bits = 8K page size)
125 * pa 13 AP 12 11 10 09 08 07 06 05 04 03 (11 col addr bits = 16K page size)
126 *
127 * (AP = autoprecharge bit)
128 *
129 * Remember that pa[2:0] are zeroed out since it's a 64-bit data bus (8 bytes),
130 * so lower 3 address bits are dont_cares. So from the table above,
131 * it's easier to see what the old code is doing: if for example,
132 * #col_addr_bits=7(06h), it adds 3 to get 10, then does 2^10=1K.
133 */
Nils Jacobs76890dd2010-11-01 15:20:27 +0000134
135 spd_byte = NumColAddr[spd_read_byte(dimm, SPD_NUM_COLUMNS) & 0xF];
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000136 printk(BIOS_DEBUG, "MAXCOLADDR\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000137 if (spd_byte > MAX_COL_ADDR) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000138 printk(BIOS_EMERG, "DIMM page size not compatible\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000139 post_code(ERROR_SET_PAGE);
140 hcf();
141 }
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000142 printk(BIOS_DEBUG, ">11address test\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000143 spd_byte -= 7;
144 if (spd_byte > 4) { /* if the value is above 4 it means >11 col address lines */
145 spd_byte = 7; /* which means >16k so set to disabled */
146 }
147 dimm_setting |= spd_byte << CF07_UPPER_D0_PSZ_SHIFT; /* 0=1k,1=2k,2=4k,etc */
148
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000149 printk(BIOS_DEBUG, "RDMSR CF07\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000150 msr = rdmsr(MC_CF07_DATA);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000151 printk(BIOS_DEBUG, "WRMSR CF07\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000152 if (dimm == DIMM0) {
153 msr.hi &= 0xFFFF0000;
154 msr.hi |= dimm_setting;
155 } else {
156 msr.hi &= 0x0000FFFF;
157 msr.hi |= dimm_setting << 16;
158 }
159 wrmsr(MC_CF07_DATA, msr);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000160 printk(BIOS_DEBUG, "ALL DONE\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000161}
162
163static void checkDDRMax(void)
164{
165 uint8_t spd_byte0, spd_byte1;
166 uint16_t speed;
167
168 /* PC133 identifier */
169 spd_byte0 = spd_read_byte(DIMM0, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
170 if (spd_byte0 == 0xFF) {
171 spd_byte0 = 0;
172 }
173 spd_byte1 = spd_read_byte(DIMM1, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
174 if (spd_byte1 == 0xFF) {
175 spd_byte1 = 0;
176 }
177
178 /* Use the slowest DIMM */
179 if (spd_byte0 < spd_byte1) {
180 spd_byte0 = spd_byte1;
181 }
182
183 /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
184 speed = 20000 / (((spd_byte0 >> 4) * 10) + (spd_byte0 & 0x0F));
185
186 /* current speed > max speed? */
187 if (GeodeLinkSpeed() > speed) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000188 printk(BIOS_EMERG, "DIMM overclocked. Check GeodeLink Speed\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000189 post_code(POST_PLL_MEM_FAIL);
190 hcf();
191 }
192}
193
194const uint16_t REF_RATE[] = { 15, 3, 7, 31, 62, 125 }; /* ns */
195
196static void set_refresh_rate(void)
197{
198 uint8_t spd_byte0, spd_byte1;
199 uint16_t rate0, rate1;
200 msr_t msr;
201
202 spd_byte0 = spd_read_byte(DIMM0, SPD_REFRESH);
203 spd_byte0 &= 0xF;
204 if (spd_byte0 > 5) {
205 spd_byte0 = 5;
206 }
207 rate0 = REF_RATE[spd_byte0];
208
209 spd_byte1 = spd_read_byte(DIMM1, SPD_REFRESH);
210 spd_byte1 &= 0xF;
211 if (spd_byte1 > 5) {
212 spd_byte1 = 5;
213 }
214 rate1 = REF_RATE[spd_byte1];
215
216 /* Use the faster rate (lowest number) */
217 if (rate0 > rate1) {
218 rate0 = rate1;
219 }
220
221 msr = rdmsr(MC_CF07_DATA);
222 msr.lo |= ((rate0 * (GeodeLinkSpeed() / 2)) / 16)
223 << CF07_LOWER_REF_INT_SHIFT;
224 wrmsr(MC_CF07_DATA, msr);
225}
226
227const uint8_t CASDDR[] = { 5, 5, 2, 6, 0 }; /* 1(1.5), 1.5, 2, 2.5, 0 */
228
229static u8 getcasmap(u32 dimm, u16 glspeed)
230{
231 u16 dimm_speed;
232 u8 spd_byte, casmap, casmap_shift=0;
233
234 /************************** DIMM0 **********************************/
235 casmap = spd_read_byte(dimm, SPD_ACCEPTABLE_CAS_LATENCIES);
236 if (casmap != 0xFF) {
237 /* IF -.5 timing is supported, check -.5 timing > GeodeLink */
238 spd_byte = spd_read_byte(dimm, SPD_SDRAM_CYCLE_TIME_2ND);
239 if (spd_byte != 0) {
240 /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
241 dimm_speed = 20000 / (((spd_byte >> 4) * 10) + (spd_byte & 0x0F));
242 if (dimm_speed >= glspeed) {
243 casmap_shift = 1; /* -.5 is a shift of 1 */
244 /* IF -1 timing is supported, check -1 timing > GeodeLink */
245 spd_byte = spd_read_byte(dimm, SPD_SDRAM_CYCLE_TIME_3RD);
246 if (spd_byte != 0) {
247 /* Turn SPD ns time into MHZ. Check what the asm does to this math. */
248 dimm_speed = 20000 / (((spd_byte >> 4) * 10) + (spd_byte & 0x0F));
249 if (dimm_speed >= glspeed) {
250 casmap_shift = 2; /* -1 is a shift of 2 */
251 }
252 } /* SPD_SDRAM_CYCLE_TIME_3RD (-1) !=0 */
253 } else {
254 casmap_shift = 0;
255 }
256 } /* SPD_SDRAM_CYCLE_TIME_2ND (-.5) !=0 */
257 /* set the casmap based on the shift to limit possible CAS settings */
258 spd_byte = 31 - __builtin_clz((uint32_t) casmap);
259 /* just want bits in the lower byte since we have to cast to a 32 */
260 casmap &= 0xFF << (spd_byte - casmap_shift);
261 } else { /* No DIMM */
262 casmap = 0;
263 }
264 return casmap;
265}
266
267static void setCAS(void)
268{
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000269/*
270 * setCAS
271 * EEPROM byte usage: (18) SDRAM device attributes - CAS latency
272 * EEPROM byte usage: (23) SDRAM Minimum Clock Cycle Time @ CLX -.5
273 * EEPROM byte usage: (25) SDRAM Minimum Clock Cycle Time @ CLX -1
274 *
275 * The CAS setting is based on the information provided in each DIMMs SPD.
276 * The speed at which a DIMM can run is described relative to the slowest
277 * CAS the DIMM supports. Each speed for the relative CAS settings is
278 * checked that it is within the GeodeLink speed. If it isn't within the GeodeLink
279 * speed, the CAS setting is removed from the list of good settings for
280 * the DIMM. This is done for both DIMMs and the lists are compared to
281 * find the lowest common CAS latency setting. If there are no CAS settings
282 * in common we out a ERROR_DIFF_DIMMS (78h) to port 80h and halt.
283 *
284 * Entry:
285 * Exit: Set fastest CAS Latency based on GeodeLink speed and SPD information.
286 * Destroys: We really use everything !
287 */
Nils Jacobs76890dd2010-11-01 15:20:27 +0000288 uint16_t glspeed;
289 uint8_t spd_byte, casmap0, casmap1;
290 msr_t msr;
291
292 glspeed = GeodeLinkSpeed();
293
294 casmap0 = getcasmap(DIMM0, glspeed);
295 casmap1 = getcasmap(DIMM1, glspeed);
296
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000297 /* CAS_LAT MAP COMPARE */
Nils Jacobs76890dd2010-11-01 15:20:27 +0000298 if (casmap0 == 0) {
299 spd_byte = CASDDR[__builtin_ctz(casmap1)];
300 } else if (casmap1 == 0) {
301 spd_byte = CASDDR[__builtin_ctz(casmap0)];
302 } else if ((casmap0 &= casmap1)) {
303 spd_byte = CASDDR[__builtin_ctz(casmap0)];
304 } else {
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000305 printk(BIOS_EMERG, "DIMM CAS Latencies not compatible\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000306 post_code(ERROR_DIFF_DIMMS);
307 hcf();
308 }
309
310 msr = rdmsr(MC_CF8F_DATA);
311 msr.lo &= ~(7 << CF8F_LOWER_CAS_LAT_SHIFT);
312 msr.lo |= spd_byte << CF8F_LOWER_CAS_LAT_SHIFT;
313 wrmsr(MC_CF8F_DATA, msr);
314}
315
316static void set_latencies(void)
317{
318 uint32_t memspeed, dimm_setting;
319 uint8_t spd_byte0, spd_byte1;
320 msr_t msr;
321
322 memspeed = GeodeLinkSpeed() / 2;
323 dimm_setting = 0;
324
325 /* MC_CF8F setup */
326 /* tRAS */
327 spd_byte0 = spd_read_byte(DIMM0, SPD_tRAS);
328 if (spd_byte0 == 0xFF) {
329 spd_byte0 = 0;
330 }
331 spd_byte1 = spd_read_byte(DIMM1, SPD_tRAS);
332 if (spd_byte1 == 0xFF) {
333 spd_byte1 = 0;
334 }
335 if (spd_byte0 < spd_byte1) {
336 spd_byte0 = spd_byte1;
337 }
338 /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
339 spd_byte1 = (spd_byte0 * memspeed) / 1000;
340 if (((spd_byte0 * memspeed) % 1000)) {
341 ++spd_byte1;
342 }
343 if (spd_byte1 > 6) {
344 --spd_byte1;
345 }
346 dimm_setting |= spd_byte1 << CF8F_LOWER_ACT2PRE_SHIFT;
347
348 /* tRP */
349 spd_byte0 = spd_read_byte(DIMM0, SPD_tRP);
350 if (spd_byte0 == 0xFF) {
351 spd_byte0 = 0;
352 }
353 spd_byte1 = spd_read_byte(DIMM1, SPD_tRP);
354 if (spd_byte1 == 0xFF) {
355 spd_byte1 = 0;
356 }
357 if (spd_byte0 < spd_byte1) {
358 spd_byte0 = spd_byte1;
359 }
360 /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
361 spd_byte1 = ((spd_byte0 >> 2) * memspeed) / 1000;
362 if ((((spd_byte0 >> 2) * memspeed) % 1000)) {
363 ++spd_byte1;
364 }
365 dimm_setting |= spd_byte1 << CF8F_LOWER_PRE2ACT_SHIFT;
366
367 /* tRCD */
368 spd_byte0 = spd_read_byte(DIMM0, SPD_tRCD);
369 if (spd_byte0 == 0xFF) {
370 spd_byte0 = 0;
371 }
372 spd_byte1 = spd_read_byte(DIMM1, SPD_tRCD);
373 if (spd_byte1 == 0xFF) {
374 spd_byte1 = 0;
375 }
376 if (spd_byte0 < spd_byte1) {
377 spd_byte0 = spd_byte1;
378 }
379 /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
380 spd_byte1 = ((spd_byte0 >> 2) * memspeed) / 1000;
381 if ((((spd_byte0 >> 2) * memspeed) % 1000)) {
382 ++spd_byte1;
383 }
384 dimm_setting |= spd_byte1 << CF8F_LOWER_ACT2CMD_SHIFT;
385
386 /* tRRD */
387 spd_byte0 = spd_read_byte(DIMM0, SPD_tRRD);
388 if (spd_byte0 == 0xFF) {
389 spd_byte0 = 0;
390 }
391 spd_byte1 = spd_read_byte(DIMM1, SPD_tRRD);
392 if (spd_byte1 == 0xFF) {
393 spd_byte1 = 0;
394 }
395 if (spd_byte0 < spd_byte1) {
396 spd_byte0 = spd_byte1;
397 }
398 /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
399 spd_byte1 = ((spd_byte0 >> 2) * memspeed) / 1000;
400 if ((((spd_byte0 >> 2) * memspeed) % 1000)) {
401 ++spd_byte1;
402 }
403 dimm_setting |= spd_byte1 << CF8F_LOWER_ACT2ACT_SHIFT;
404
405 /* tRC = tRP + tRAS */
406 dimm_setting |= (((dimm_setting >> CF8F_LOWER_ACT2PRE_SHIFT) & 0x0F) +
407 ((dimm_setting >> CF8F_LOWER_PRE2ACT_SHIFT) & 0x07))
408 << CF8F_LOWER_REF2ACT_SHIFT;
409
410 msr = rdmsr(MC_CF8F_DATA);
411 msr.lo &= 0xF00000FF;
412 msr.lo |= dimm_setting;
413 msr.hi |= CF8F_UPPER_REORDER_DIS_SET;
414 wrmsr(MC_CF8F_DATA, msr);
415 printk(BIOS_DEBUG, "MSR MC_CF8F_DATA (%08x) value is %08x:%08x\n",
416 MC_CF8F_DATA, msr.hi, msr.lo);
417}
418
419static void set_extended_mode_registers(void)
420{
421 uint8_t spd_byte0, spd_byte1;
422 msr_t msr;
423 spd_byte0 = spd_read_byte(DIMM0, SPD_DEVICE_ATTRIBUTES_GENERAL);
424 if (spd_byte0 == 0xFF) {
425 spd_byte0 = 0;
426 }
427 spd_byte1 = spd_read_byte(DIMM1, SPD_DEVICE_ATTRIBUTES_GENERAL);
428 if (spd_byte1 == 0xFF) {
429 spd_byte1 = 0;
430 }
431 spd_byte1 &= spd_byte0;
432
433 msr = rdmsr(MC_CF07_DATA);
434 if (spd_byte1 & 1) { /* Drive Strength Control */
435 msr.lo |= CF07_LOWER_EMR_DRV_SET;
436 }
437 if (spd_byte1 & 2) { /* FET Control */
438 msr.lo |= CF07_LOWER_EMR_QFC_SET;
439 }
440 wrmsr(MC_CF07_DATA, msr);
441}
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000442
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000443static void sdram_set_registers(const struct mem_controller *ctrl)
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000444{
Nils Jacobs76890dd2010-11-01 15:20:27 +0000445 msr_t msr;
446 uint32_t msrnum;
447
448 /* Set Refresh Staggering */
449 msrnum = MC_CF07_DATA;
450 msr = rdmsr(msrnum);
451 msr.lo &= ~0xC0;
452 msr.lo |= 0x0; /* set refresh to 4SDRAM clocks */
453 wrmsr(msrnum, msr);
Nils Jacobs76890dd2010-11-01 15:20:27 +0000454}
455
456static void sdram_set_spd_registers(const struct mem_controller *ctrl)
457{
458 uint8_t spd_byte;
459
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000460 printk(BIOS_DEBUG, "sdram_set_spd_register\n");
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000461 post_code(POST_MEM_SETUP); /* post_70h */
Nils Jacobs76890dd2010-11-01 15:20:27 +0000462
463 spd_byte = spd_read_byte(DIMM0, SPD_MODULE_ATTRIBUTES);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000464 printk(BIOS_DEBUG, "Check DIMM 0\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000465 /* Check DIMM is not Register and not Buffered DIMMs. */
466 if ((spd_byte != 0xFF) && (spd_byte & 3)) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000467 printk(BIOS_EMERG, "DIMM0 NOT COMPATIBLE\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000468 post_code(ERROR_UNSUPPORTED_DIMM);
469 hcf();
470 }
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000471 printk(BIOS_DEBUG, "Check DIMM 1\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000472 spd_byte = spd_read_byte(DIMM1, SPD_MODULE_ATTRIBUTES);
473 if ((spd_byte != 0xFF) && (spd_byte & 3)) {
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000474 printk(BIOS_EMERG, "DIMM1 NOT COMPATIBLE\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000475 post_code(ERROR_UNSUPPORTED_DIMM);
476 hcf();
477 }
478
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000479 post_code(POST_MEM_SETUP2); /* post_72h */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000480 printk(BIOS_DEBUG, "Check DDR MAX\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000481
482 /* Check that the memory is not overclocked. */
483 checkDDRMax();
484
485 /* Size the DIMMS */
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000486 post_code(POST_MEM_SETUP3); /* post_73h */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000487 printk(BIOS_DEBUG, "AUTOSIZE DIMM 0\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000488 auto_size_dimm(DIMM0);
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000489 post_code(POST_MEM_SETUP4); /* post_74h */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000490 printk(BIOS_DEBUG, "AUTOSIZE DIMM 1\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000491 auto_size_dimm(DIMM1);
492
493 /* Set CAS latency */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000494 printk(BIOS_DEBUG, "set cas latency\n");
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000495 post_code(POST_MEM_SETUP5); /* post_75h */
Nils Jacobs76890dd2010-11-01 15:20:27 +0000496 setCAS();
497
498 /* Set all the other latencies here (tRAS, tRP....) */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000499 printk(BIOS_DEBUG, "set all latency\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000500 set_latencies();
501
502 /* Set Extended Mode Registers */
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000503 printk(BIOS_DEBUG, "set emrs\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000504 set_extended_mode_registers();
505
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000506 printk(BIOS_DEBUG, "set ref rate\n");
Nils Jacobs76890dd2010-11-01 15:20:27 +0000507 /* Set Memory Refresh Rate */
508 set_refresh_rate();
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000509}
510
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000511/* Section 6.1.3, LX processor databooks, BIOS Initialization Sequence
512 * Section 4.1.4, GX/CS5535 GeodeROM Porting guide */
513static void sdram_enable(int controllers, const struct mem_controller *ctrl)
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000514{
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000515 int i;
516 msr_t msr;
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000517
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000518 /* 2. clock gating for PMode */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000519 msr = rdmsr(MC_GLD_MSR_PM);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000520 msr.lo &= ~0x04;
521 msr.lo |= 0x01;
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000522 wrmsr(MC_GLD_MSR_PM, msr);
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000523 /* undocmented bits in GX, in LX there are
524 * 8 bits in PM1_UP_DLY */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000525 msr = rdmsr(MC_CF1017_DATA);
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000526 msr.lo = 0x0101;
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000527 wrmsr(MC_CF1017_DATA, msr);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000528 printk(BIOS_DEBUG, "sdram_enable step 2\n");
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000529
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000530 /* 3. release CKE mask to enable CKE */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000531 msr = rdmsr(MC_CFCLK_DBUG);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000532 msr.lo &= ~(0x03 << 8);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000533 wrmsr(MC_CFCLK_DBUG, msr);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000534 printk(BIOS_DEBUG, "sdram_enable step 3\n");
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000535
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000536 /* 4. set and clear REF_TST 16 times, more shouldn't hurt
537 * why this is before EMRS and MRS ? */
Li-Ta Loc0fe3192006-02-28 23:07:27 +0000538 for (i = 0; i < 19; i++) {
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000539 msr = rdmsr(MC_CF07_DATA);
Li-Ta Loc0fe3192006-02-28 23:07:27 +0000540 msr.lo |= (0x01 << 3);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000541 wrmsr(MC_CF07_DATA, msr);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000542 msr.lo &= ~(0x01 << 3);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000543 wrmsr(MC_CF07_DATA, msr);
Li-Ta Loc0fe3192006-02-28 23:07:27 +0000544 }
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000545 printk(BIOS_DEBUG, "sdram_enable step 4\n");
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000546
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000547 /* 6. enable DLL, load Extended Mode Register by set and clear PROG_DRAM */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000548 msr = rdmsr(MC_CF07_DATA);
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000549 msr.lo |= ((0x01 << 28) | 0x01);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000550 wrmsr(MC_CF07_DATA, msr);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000551 msr.lo &= ~((0x01 << 28) | 0x01);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000552 wrmsr(MC_CF07_DATA, msr);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000553 printk(BIOS_DEBUG, "sdram_enable step 6\n");
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000554
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000555 /* 7. Reset DLL, Bit 27 is undocumented in GX datasheet,
Nils Jacobs5beac7f2010-11-03 13:19:50 +0000556 * it is documented in LX datasheet */
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000557 /* load Mode Register by set and clear PROG_DRAM */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000558 msr = rdmsr(MC_CF07_DATA);
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000559 msr.lo |= ((0x01 << 27) | 0x01);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000560 wrmsr(MC_CF07_DATA, msr);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000561 msr.lo &= ~((0x01 << 27) | 0x01);
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000562 wrmsr(MC_CF07_DATA, msr);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000563 printk(BIOS_DEBUG, "sdram_enable step 7\n");
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000564
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000565 /* 8. load Mode Register by set and clear PROG_DRAM */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000566 msr = rdmsr(MC_CF07_DATA);
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000567 msr.lo |= 0x01;
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000568 wrmsr(MC_CF07_DATA, msr);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000569 msr.lo &= ~0x01;
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000570 wrmsr(MC_CF07_DATA, msr);
Nils Jacobsa1e2c562010-11-05 00:13:14 +0000571 printk(BIOS_DEBUG, "sdram_enable step 8\n");
Li-Ta Lobab94462006-02-28 15:39:25 +0000572
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000573 /* wait 200 SDCLKs */
574 for (i = 0; i < 200; i++)
575 outb(0xaa, 0x80);
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000576
Li-Ta Lo108dd2c2006-02-23 21:39:19 +0000577 /* load RDSYNC */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000578 msr = rdmsr(MC_CF_RDSYNC);
Li-Ta Lo71eae202006-03-13 21:58:43 +0000579 msr.hi = 0x000ff310;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000580 /* the above setting is supposed to be good for "slow" ram. We have found that for
581 * some dram, at some clock rates, e.g. hynix at 366/244, this will actually
Ronald G. Minnich0740c312006-09-18 04:23:23 +0000582 * cause errors. The fix is to just set it to 0x310. Tested on 3 boards
Stefan Reinauer14e22772010-04-27 06:56:47 +0000583 * with 3 different type of dram -- Hynix, PSC, infineon.
Ronald G. Minnich0740c312006-09-18 04:23:23 +0000584 * I am leaving this comment here so that at some future time nobody is tempted
585 * to mess with this setting -- RGM, 9/2006
586 */
587 msr.hi = 0x00000310;
Li-Ta Loc0fe3192006-02-28 23:07:27 +0000588 msr.lo = 0x00000000;
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000589 wrmsr(MC_CF_RDSYNC, msr);
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000590
Li-Ta Loc0fe3192006-02-28 23:07:27 +0000591 /* set delay control */
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000592 msr = rdmsr(GLCP_DELAY_CONTROLS);
Li-Ta Loec9cdc92006-03-02 21:33:01 +0000593 msr.hi = 0x830d415a;
594 msr.lo = 0x8ea0ad6a;
Nils Jacobsfc9fcf72010-11-01 14:18:11 +0000595 wrmsr(GLCP_DELAY_CONTROLS, msr);
Li-Ta Loc0fe3192006-02-28 23:07:27 +0000596
Ronald G. Minnichaefa3d72006-09-13 01:57:47 +0000597 /* The RAM dll needs a write to lock on so generate a few dummy writes */
Nils Jacobse4740702010-07-26 23:46:25 +0000598 /* Note: The descriptor needs to be enabled to point at memory */
Ronald G. Minnichaefa3d72006-09-13 01:57:47 +0000599 volatile unsigned long *ptr;
Nils Jacobse4740702010-07-26 23:46:25 +0000600 for (i = 0; i < 5; i++) {
Ronald G. Minnichaefa3d72006-09-13 01:57:47 +0000601 ptr = (void *)i;
602 *ptr = (unsigned long)i;
603 }
Ronald G. Minnichd3ba4aa2006-05-02 03:07:11 +0000604
Stefan Reinauer65b72ab2015-01-05 12:59:54 -0800605 printk(BIOS_INFO, "RAM DLL lock\n");
Nils Jacobse4740702010-07-26 23:46:25 +0000606
Ronald G. Minnich2bb216a2006-01-27 23:46:30 +0000607}