2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
5 * Copyright (C) 2010 Nils Jacobs
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.
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.
17 #include <cpu/amd/gx2def.h>
20 static const unsigned char NumColAddr
[] = {
21 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x07,
22 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
25 static void __attribute__((noreturn
)) hcf(void)
27 printk(BIOS_EMERG
, "DIE\n");
28 /* this guarantees we flush the UART fifos (if any) and also
29 * ensures that things, in general, keep going so no debug output
33 printk(BIOS_EMERG
, (0));
36 static void auto_size_dimm(unsigned int dimm
)
38 uint32_t dimm_setting
;
45 printk(BIOS_DEBUG
, "Check present\n");
46 /* Check that we have a dimm */
47 if (spd_read_byte(dimm
, SPD_MEMORY_TYPE
) == 0xFF) {
51 printk(BIOS_DEBUG
, "MODBANKS\n");
52 /* 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
)) {
56 printk(BIOS_EMERG
, "Number of module banks not compatible\n");
57 post_code(ERROR_BANK_SET
);
60 dimm_setting
|= (spd_byte
>> 1) << CF07_UPPER_D0_MB_SHIFT
;
62 printk(BIOS_DEBUG
, "FIELDBANKS\n");
63 /* 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
)) {
67 printk(BIOS_EMERG
, "Number of device banks not compatible\n");
68 post_code(ERROR_BANK_SET
);
71 dimm_setting
|= (spd_byte
>> 2) << CF07_UPPER_D0_CB_SHIFT
;
73 printk(BIOS_DEBUG
, "SPDNUMROWS\n");
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
82 if ((spd_read_byte(dimm
, SPD_NUM_ROWS
) & 0xF0)
83 || (spd_read_byte(dimm
, SPD_NUM_COLUMNS
) & 0xF0)) {
84 printk(BIOS_EMERG
, "Asymmetric DIMM not compatible\n");
85 post_code(ERROR_UNSUPPORTED_DIMM
);
89 printk(BIOS_DEBUG
, "SPDBANKDENSITY\n");
90 dimm_size
= spd_read_byte(dimm
, SPD_BANK_DENSITY
);
91 printk(BIOS_DEBUG
, "DIMMSIZE\n");
92 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 */
95 /* Module Density * Module Banks */
96 dimm_size
<<= (dimm_setting
>> CF07_UPPER_D0_MB_SHIFT
) & 1; /* shift to multiply by # DIMM banks */
97 printk(BIOS_DEBUG
, "BEFORT CTZ\n");
98 dimm_size
= __builtin_ctz(dimm_size
);
99 printk(BIOS_DEBUG
, "TEST DIMM SIZE>7\n");
100 if (dimm_size
> 7) { /* 7 is 512MB only support 512MB per DIMM */
101 printk(BIOS_EMERG
, "Only support up to 512MB per DIMM\n");
102 post_code(ERROR_DENSITY_DIMM
);
105 dimm_setting
|= dimm_size
<< CF07_UPPER_D0_SZ_SHIFT
;
106 printk(BIOS_DEBUG
, "PAGESIZE\n");
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)
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
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)
127 * (AP = autoprecharge bit)
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.
135 spd_byte
= NumColAddr
[spd_read_byte(dimm
, SPD_NUM_COLUMNS
) & 0xF];
136 printk(BIOS_DEBUG
, "MAXCOLADDR\n");
137 if (spd_byte
> MAX_COL_ADDR
) {
138 printk(BIOS_EMERG
, "DIMM page size not compatible\n");
139 post_code(ERROR_SET_PAGE
);
142 printk(BIOS_DEBUG
, ">11address test\n");
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 */
147 dimm_setting
|= spd_byte
<< CF07_UPPER_D0_PSZ_SHIFT
; /* 0=1k,1=2k,2=4k,etc */
149 printk(BIOS_DEBUG
, "RDMSR CF07\n");
150 msr
= rdmsr(MC_CF07_DATA
);
151 printk(BIOS_DEBUG
, "WRMSR CF07\n");
153 msr
.hi
&= 0xFFFF0000;
154 msr
.hi
|= dimm_setting
;
156 msr
.hi
&= 0x0000FFFF;
157 msr
.hi
|= dimm_setting
<< 16;
159 wrmsr(MC_CF07_DATA
, msr
);
160 printk(BIOS_DEBUG
, "ALL DONE\n");
163 static void checkDDRMax(void)
165 uint8_t spd_byte0
, spd_byte1
;
168 /* PC133 identifier */
169 spd_byte0
= spd_read_byte(DIMM0
, SPD_MIN_CYCLE_TIME_AT_CAS_MAX
);
170 if (spd_byte0
== 0xFF) {
173 spd_byte1
= spd_read_byte(DIMM1
, SPD_MIN_CYCLE_TIME_AT_CAS_MAX
);
174 if (spd_byte1
== 0xFF) {
178 /* Use the slowest DIMM */
179 if (spd_byte0
< spd_byte1
) {
180 spd_byte0
= spd_byte1
;
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));
186 /* current speed > max speed? */
187 if (GeodeLinkSpeed() > speed
) {
188 printk(BIOS_EMERG
, "DIMM overclocked. Check GeodeLink Speed\n");
189 post_code(POST_PLL_MEM_FAIL
);
194 const uint16_t REF_RATE
[] = { 15, 3, 7, 31, 62, 125 }; /* ns */
196 static void set_refresh_rate(void)
198 uint8_t spd_byte0
, spd_byte1
;
199 uint16_t rate0
, rate1
;
202 spd_byte0
= spd_read_byte(DIMM0
, SPD_REFRESH
);
207 rate0
= REF_RATE
[spd_byte0
];
209 spd_byte1
= spd_read_byte(DIMM1
, SPD_REFRESH
);
214 rate1
= REF_RATE
[spd_byte1
];
216 /* Use the faster rate (lowest number) */
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
);
227 const uint8_t CASDDR
[] = { 5, 5, 2, 6, 0 }; /* 1(1.5), 1.5, 2, 2.5, 0 */
229 static u8
getcasmap(u32 dimm
, u16 glspeed
)
232 u8 spd_byte
, casmap
, casmap_shift
=0;
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
);
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
);
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 */
252 } /* SPD_SDRAM_CYCLE_TIME_3RD (-1) !=0 */
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 */
267 static void setCAS(void)
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
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.
285 * Exit: Set fastest CAS Latency based on GeodeLink speed and SPD information.
286 * Destroys: We really use everything !
289 uint8_t spd_byte
, casmap0
, casmap1
;
292 glspeed
= GeodeLinkSpeed();
294 casmap0
= getcasmap(DIMM0
, glspeed
);
295 casmap1
= getcasmap(DIMM1
, glspeed
);
297 /* CAS_LAT MAP COMPARE */
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
)];
305 printk(BIOS_EMERG
, "DIMM CAS Latencies not compatible\n");
306 post_code(ERROR_DIFF_DIMMS
);
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
);
316 static void set_latencies(void)
318 uint32_t memspeed
, dimm_setting
;
319 uint8_t spd_byte0
, spd_byte1
;
322 memspeed
= GeodeLinkSpeed() / 2;
327 spd_byte0
= spd_read_byte(DIMM0
, SPD_tRAS
);
328 if (spd_byte0
== 0xFF) {
331 spd_byte1
= spd_read_byte(DIMM1
, SPD_tRAS
);
332 if (spd_byte1
== 0xFF) {
335 if (spd_byte0
< spd_byte1
) {
336 spd_byte0
= spd_byte1
;
338 /* (ns/(1/MHz) = (us*MHZ)/1000 = clocks/1000 = clocks) */
339 spd_byte1
= (spd_byte0
* memspeed
) / 1000;
340 if (((spd_byte0
* memspeed
) % 1000)) {
346 dimm_setting
|= spd_byte1
<< CF8F_LOWER_ACT2PRE_SHIFT
;
349 spd_byte0
= spd_read_byte(DIMM0
, SPD_tRP
);
350 if (spd_byte0
== 0xFF) {
353 spd_byte1
= spd_read_byte(DIMM1
, SPD_tRP
);
354 if (spd_byte1
== 0xFF) {
357 if (spd_byte0
< spd_byte1
) {
358 spd_byte0
= spd_byte1
;
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)) {
365 dimm_setting
|= spd_byte1
<< CF8F_LOWER_PRE2ACT_SHIFT
;
368 spd_byte0
= spd_read_byte(DIMM0
, SPD_tRCD
);
369 if (spd_byte0
== 0xFF) {
372 spd_byte1
= spd_read_byte(DIMM1
, SPD_tRCD
);
373 if (spd_byte1
== 0xFF) {
376 if (spd_byte0
< spd_byte1
) {
377 spd_byte0
= spd_byte1
;
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)) {
384 dimm_setting
|= spd_byte1
<< CF8F_LOWER_ACT2CMD_SHIFT
;
387 spd_byte0
= spd_read_byte(DIMM0
, SPD_tRRD
);
388 if (spd_byte0
== 0xFF) {
391 spd_byte1
= spd_read_byte(DIMM1
, SPD_tRRD
);
392 if (spd_byte1
== 0xFF) {
395 if (spd_byte0
< spd_byte1
) {
396 spd_byte0
= spd_byte1
;
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)) {
403 dimm_setting
|= spd_byte1
<< CF8F_LOWER_ACT2ACT_SHIFT
;
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
;
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
);
419 static void set_extended_mode_registers(void)
421 uint8_t spd_byte0
, spd_byte1
;
423 spd_byte0
= spd_read_byte(DIMM0
, SPD_DEVICE_ATTRIBUTES_GENERAL
);
424 if (spd_byte0
== 0xFF) {
427 spd_byte1
= spd_read_byte(DIMM1
, SPD_DEVICE_ATTRIBUTES_GENERAL
);
428 if (spd_byte1
== 0xFF) {
431 spd_byte1
&= spd_byte0
;
433 msr
= rdmsr(MC_CF07_DATA
);
434 if (spd_byte1
& 1) { /* Drive Strength Control */
435 msr
.lo
|= CF07_LOWER_EMR_DRV_SET
;
437 if (spd_byte1
& 2) { /* FET Control */
438 msr
.lo
|= CF07_LOWER_EMR_QFC_SET
;
440 wrmsr(MC_CF07_DATA
, msr
);
443 static void sdram_set_registers(const struct mem_controller
*ctrl
)
448 /* Set Refresh Staggering */
449 msrnum
= MC_CF07_DATA
;
452 msr
.lo
|= 0x0; /* set refresh to 4SDRAM clocks */
456 static void sdram_set_spd_registers(const struct mem_controller
*ctrl
)
460 printk(BIOS_DEBUG
, "sdram_set_spd_register\n");
461 post_code(POST_MEM_SETUP
); /* post_70h */
463 spd_byte
= spd_read_byte(DIMM0
, SPD_MODULE_ATTRIBUTES
);
464 printk(BIOS_DEBUG
, "Check DIMM 0\n");
465 /* Check DIMM is not Register and not Buffered DIMMs. */
466 if ((spd_byte
!= 0xFF) && (spd_byte
& 3)) {
467 printk(BIOS_EMERG
, "DIMM0 NOT COMPATIBLE\n");
468 post_code(ERROR_UNSUPPORTED_DIMM
);
471 printk(BIOS_DEBUG
, "Check DIMM 1\n");
472 spd_byte
= spd_read_byte(DIMM1
, SPD_MODULE_ATTRIBUTES
);
473 if ((spd_byte
!= 0xFF) && (spd_byte
& 3)) {
474 printk(BIOS_EMERG
, "DIMM1 NOT COMPATIBLE\n");
475 post_code(ERROR_UNSUPPORTED_DIMM
);
479 post_code(POST_MEM_SETUP2
); /* post_72h */
480 printk(BIOS_DEBUG
, "Check DDR MAX\n");
482 /* Check that the memory is not overclocked. */
486 post_code(POST_MEM_SETUP3
); /* post_73h */
487 printk(BIOS_DEBUG
, "AUTOSIZE DIMM 0\n");
488 auto_size_dimm(DIMM0
);
489 post_code(POST_MEM_SETUP4
); /* post_74h */
490 printk(BIOS_DEBUG
, "AUTOSIZE DIMM 1\n");
491 auto_size_dimm(DIMM1
);
493 /* Set CAS latency */
494 printk(BIOS_DEBUG
, "set cas latency\n");
495 post_code(POST_MEM_SETUP5
); /* post_75h */
498 /* Set all the other latencies here (tRAS, tRP....) */
499 printk(BIOS_DEBUG
, "set all latency\n");
502 /* Set Extended Mode Registers */
503 printk(BIOS_DEBUG
, "set emrs\n");
504 set_extended_mode_registers();
506 printk(BIOS_DEBUG
, "set ref rate\n");
507 /* Set Memory Refresh Rate */
511 /* Section 6.1.3, LX processor databooks, BIOS Initialization Sequence
512 * Section 4.1.4, GX/CS5535 GeodeROM Porting guide */
513 static void sdram_enable(int controllers
, const struct mem_controller
*ctrl
)
518 /* 2. clock gating for PMode */
519 msr
= rdmsr(MC_GLD_MSR_PM
);
522 wrmsr(MC_GLD_MSR_PM
, msr
);
523 /* undocmented bits in GX, in LX there are
524 * 8 bits in PM1_UP_DLY */
525 msr
= rdmsr(MC_CF1017_DATA
);
527 wrmsr(MC_CF1017_DATA
, msr
);
528 printk(BIOS_DEBUG
, "sdram_enable step 2\n");
530 /* 3. release CKE mask to enable CKE */
531 msr
= rdmsr(MC_CFCLK_DBUG
);
532 msr
.lo
&= ~(0x03 << 8);
533 wrmsr(MC_CFCLK_DBUG
, msr
);
534 printk(BIOS_DEBUG
, "sdram_enable step 3\n");
536 /* 4. set and clear REF_TST 16 times, more shouldn't hurt
537 * why this is before EMRS and MRS ? */
538 for (i
= 0; i
< 19; i
++) {
539 msr
= rdmsr(MC_CF07_DATA
);
540 msr
.lo
|= (0x01 << 3);
541 wrmsr(MC_CF07_DATA
, msr
);
542 msr
.lo
&= ~(0x01 << 3);
543 wrmsr(MC_CF07_DATA
, msr
);
545 printk(BIOS_DEBUG
, "sdram_enable step 4\n");
547 /* 6. enable DLL, load Extended Mode Register by set and clear PROG_DRAM */
548 msr
= rdmsr(MC_CF07_DATA
);
549 msr
.lo
|= ((0x01 << 28) | 0x01);
550 wrmsr(MC_CF07_DATA
, msr
);
551 msr
.lo
&= ~((0x01 << 28) | 0x01);
552 wrmsr(MC_CF07_DATA
, msr
);
553 printk(BIOS_DEBUG
, "sdram_enable step 6\n");
555 /* 7. Reset DLL, Bit 27 is undocumented in GX datasheet,
556 * it is documented in LX datasheet */
557 /* load Mode Register by set and clear PROG_DRAM */
558 msr
= rdmsr(MC_CF07_DATA
);
559 msr
.lo
|= ((0x01 << 27) | 0x01);
560 wrmsr(MC_CF07_DATA
, msr
);
561 msr
.lo
&= ~((0x01 << 27) | 0x01);
562 wrmsr(MC_CF07_DATA
, msr
);
563 printk(BIOS_DEBUG
, "sdram_enable step 7\n");
565 /* 8. load Mode Register by set and clear PROG_DRAM */
566 msr
= rdmsr(MC_CF07_DATA
);
568 wrmsr(MC_CF07_DATA
, msr
);
570 wrmsr(MC_CF07_DATA
, msr
);
571 printk(BIOS_DEBUG
, "sdram_enable step 8\n");
573 /* wait 200 SDCLKs */
574 for (i
= 0; i
< 200; i
++)
578 msr
= rdmsr(MC_CF_RDSYNC
);
580 /* 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
582 * cause errors. The fix is to just set it to 0x310. Tested on 3 boards
583 * with 3 different type of dram -- Hynix, PSC, infineon.
584 * I am leaving this comment here so that at some future time nobody is tempted
585 * to mess with this setting -- RGM, 9/2006
589 wrmsr(MC_CF_RDSYNC
, msr
);
591 /* set delay control */
592 msr
= rdmsr(GLCP_DELAY_CONTROLS
);
595 wrmsr(GLCP_DELAY_CONTROLS
, msr
);
597 /* The RAM dll needs a write to lock on so generate a few dummy writes */
598 /* Note: The descriptor needs to be enabled to point at memory */
599 volatile unsigned long *ptr
;
600 for (i
= 0; i
< 5; i
++) {
602 *ptr
= (unsigned long)i
;
605 printk(BIOS_INFO
, "RAM DLL lock\n");