Add constants for fast path resume copying
[coreboot.git] / src / lib / ramtest.c
1 #include <stdint.h>
2 #include <lib.h> /* Prototypes */
3 #include <console/console.h>
4
5 static void write_phys(unsigned long addr, u32 value)
6 {
7         // Assembler in lib/ is very ugly. But we properly guarded
8         // it so let's obey this one for now
9 #if CONFIG_SSE2
10         asm volatile(
11                 "movnti %1, (%0)"
12                 : /* outputs */
13                 : "r" (addr), "r" (value) /* inputs */
14 #ifndef __GNUC__ /* GCC does not like empty clobbers? */
15                 : /* clobbers */
16 #endif
17                 );
18 #else
19         volatile unsigned long *ptr;
20         ptr = (void *)addr;
21         *ptr = value;
22 #endif
23 }
24
25 static u32 read_phys(unsigned long addr)
26 {
27         volatile unsigned long *ptr;
28         ptr = (void *)addr;
29         return *ptr;
30 }
31
32 static void phys_memory_barrier(void)
33 {
34 #if CONFIG_SSE2
35         // Needed for movnti
36         asm volatile (
37                 "sfence"
38                 ::
39 #ifdef __GNUC__ /* ROMCC does not like memory clobbers */
40                 : "memory"
41 #endif
42         );
43 #else
44 #ifdef __GNUC__ /* ROMCC does not like empty asm statements */
45         asm volatile ("" ::: "memory");
46 #endif
47 #endif
48 }
49
50 /**
51  * Rotate ones test pattern that access every bit on a 128bit wide
52  * memory bus. To test most address lines, addresses are scattered
53  * using 256B, 4kB and 64kB increments.
54  *
55  * @idx         Index to test pattern (0=<idx<0x400)
56  * @addr        Memory to access on @idx
57  * @value       Value to write or read at @addr
58  */
59 static inline void test_pattern(unsigned short int idx,
60         unsigned long *addr, unsigned long *value)
61 {
62         uint8_t j, k;
63
64         k = (idx >> 8) + 1;
65         j = (idx >> 4) & 0x0f;
66         *addr = idx & 0x0f;
67         *addr |= j << (4*k);
68         *value = 0x01010101 << (j & 7);
69         if (j & 8)
70                 *value = ~(*value);
71 }
72
73 /**
74  * Simple write-read-verify memory test. See console debug output for
75  * any dislocated bytes.
76  *
77  * @start   System memory offset, aligned to 128bytes
78  */
79 static int ram_bitset_nodie(unsigned long start)
80 {
81         unsigned long addr, value, value2;
82         unsigned short int idx;
83         unsigned char failed, failures;
84         uint8_t verbose = 0;
85
86 #if !defined(__ROMCC__)
87         printk(BIOS_DEBUG, "DRAM bitset write: 0x%08lx\n", start);
88 #else
89         print_debug("DRAM bitset write: 0x");
90         print_debug_hex32(start);
91         print_debug("\n");
92 #endif
93         for (idx=0; idx<0x400; idx+=4) {
94                 test_pattern(idx, &addr, &value);
95                 write_phys(start + addr, value);
96         }
97
98         /* Make sure we don't read before we wrote */
99         phys_memory_barrier();
100
101 #if !defined(__ROMCC__)
102         printk(BIOS_DEBUG, "DRAM bitset verify: 0x%08lx\n", start);
103 #else
104         print_debug("DRAM bitset verify: 0x");
105         print_debug_hex32(start);
106         print_debug("\n");
107 #endif
108         failures = 0;
109         for (idx=0; idx<0x400; idx+=4) {
110                 test_pattern(idx, &addr, &value);
111                 value2 = read_phys(start + addr);
112
113                 failed = (value2 != value);
114                 failures |= failed;
115                 if  (failed && !verbose) {
116 #if !defined(__ROMCC__)
117                         printk(BIOS_ERR, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n",
118                                  start + addr, value, value2);
119 #else
120                         print_err_hex32(start + addr);
121                         print_err(" wr: 0x");
122                         print_err_hex32(value);
123                         print_err(" rd: 0x");
124                         print_err_hex32(value2);
125                         print_err(" FAIL\n");
126 #endif
127                 }
128                 if (verbose) {
129 #if !defined(__ROMCC__)
130                         if ((addr & 0x0f) == 0)
131                                 printk(BIOS_DEBUG, "%08lx wr: %08lx rd:",
132                                         start + addr, value);
133                         if (failed)
134                                 printk(BIOS_DEBUG, " %08lx!", value2);
135                         else
136                                 printk(BIOS_DEBUG, " %08lx ", value2);
137                         if ((addr & 0x0f) == 0xc)
138                                 printk(BIOS_DEBUG, "\n");
139 #else
140                         if ((addr & 0x0f) == 0) {
141                                 print_dbg_hex32(start + addr);
142                                 print_dbg(" wr: ");
143                                 print_dbg_hex32(value);
144                                 print_dbg(" rd: ");
145                         }
146                         print_dbg_hex32(value2);
147                         if (failed)
148                                 print_dbg("! ");
149                         else
150                                 print_dbg("  ");
151                         if ((addr & 0x0f) == 0xc)
152                                 print_dbg("\n");
153 #endif
154                 }
155         }
156         if (failures) {
157                 post_code(0xea);
158 #if !defined(__ROMCC__)
159                 printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n");
160 #else
161                 print_debug("\nDRAM did _NOT_ verify!\n");
162 #endif
163                 return 1;
164         }
165         else {
166 #if !defined(__ROMCC__)
167                 printk(BIOS_DEBUG, "\nDRAM range verified.\n");
168 #else
169                 print_debug("\nDRAM range verified.\n");
170                 return 0;
171 #endif
172         }
173         return 0;
174 }
175
176
177 void ram_check(unsigned long start, unsigned long stop)
178 {
179         /*
180          * This is much more of a "Is my DRAM properly configured?"
181          * test than a "Is my DRAM faulty?" test.  Not all bits
182          * are tested.   -Tyson
183          */
184 #if !defined(__ROMCC__)
185         printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start);
186 #else
187         print_debug("Testing DRAM at: ");
188         print_debug_hex32(start);
189         print_debug("\n");
190 #endif
191         if (ram_bitset_nodie(start))
192                 die("DRAM ERROR");
193 #if !defined(__ROMCC__)
194         printk(BIOS_DEBUG, "Done.\n");
195 #else
196         print_debug("Done.\n");
197 #endif
198 }
199
200
201 int ram_check_nodie(unsigned long start, unsigned long stop)
202 {
203         int ret;
204         /*
205          * This is much more of a "Is my DRAM properly configured?"
206          * test than a "Is my DRAM faulty?" test.  Not all bits
207          * are tested.   -Tyson
208          */
209 #if !defined(__ROMCC__)
210         printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start);
211 #else
212         print_debug("Testing DRAM at : ");
213         print_debug_hex32(start);
214         print_debug("\n");
215 #endif
216
217         ret = ram_bitset_nodie(start);
218 #if !defined(__ROMCC__)
219         printk(BIOS_DEBUG, "Done.\n");
220 #else
221         print_debug("Done.\n");
222 #endif
223         return ret;
224 }
225
226 void quick_ram_check(void)
227 {
228         int fail = 0;
229         u32 backup;
230         backup = read_phys(CONFIG_RAMBASE);
231         write_phys(CONFIG_RAMBASE, 0x55555555);
232         phys_memory_barrier();
233         if (read_phys(CONFIG_RAMBASE) != 0x55555555)
234                 fail=1;
235         write_phys(CONFIG_RAMBASE, 0xaaaaaaaa);
236         phys_memory_barrier();
237         if (read_phys(CONFIG_RAMBASE) != 0xaaaaaaaa)
238                 fail=1;
239         write_phys(CONFIG_RAMBASE, 0x00000000);
240         phys_memory_barrier();
241         if (read_phys(CONFIG_RAMBASE) != 0x00000000)
242                 fail=1;
243         write_phys(CONFIG_RAMBASE, 0xffffffff);
244         phys_memory_barrier();
245         if (read_phys(CONFIG_RAMBASE) != 0xffffffff)
246                 fail=1;
247
248         write_phys(CONFIG_RAMBASE, backup);
249         if (fail) {
250                 post_code(0xea);
251                 die("RAM INIT FAILURE!\n");
252         }
253         phys_memory_barrier();
254 }