blob: 03c4aa7d78ecdac7f12ae450571697183d80a5a2 [file] [log] [blame]
Patrick Georgid0835952010-10-05 09:07:10 +00001#include <stdint.h>
Myles Watson34261952010-03-19 02:33:40 +00002#include <lib.h> /* Prototypes */
Patrick Georgid0835952010-10-05 09:07:10 +00003#include <console/console.h>
Myles Watson34261952010-03-19 02:33:40 +00004
Stefan Reinauere0d607a2010-03-28 21:31:30 +00005static void write_phys(unsigned long addr, u32 value)
Eric Biederman8ca8d762003-04-22 19:02:15 +00006{
Stefan Reinauera7acc512010-02-25 13:40:49 +00007 // Assembler in lib/ is very ugly. But we properly guarded
8 // it so let's obey this one for now
9#if CONFIG_SSE2
Eric Biederman8d9c1232003-06-17 08:42:17 +000010 asm volatile(
11 "movnti %1, (%0)"
12 : /* outputs */
13 : "r" (addr), "r" (value) /* inputs */
Stefan Reinauere0d607a2010-03-28 21:31:30 +000014#ifndef __GNUC__ /* GCC does not like empty clobbers? */
Eric Biederman8d9c1232003-06-17 08:42:17 +000015 : /* clobbers */
Stefan Reinauer76712932004-05-27 11:13:24 +000016#endif
Eric Biederman8d9c1232003-06-17 08:42:17 +000017 );
18#else
Eric Biederman52685572003-05-19 19:16:21 +000019 volatile unsigned long *ptr;
Eric Biederman8ca8d762003-04-22 19:02:15 +000020 ptr = (void *)addr;
21 *ptr = value;
Eric Biederman8d9c1232003-06-17 08:42:17 +000022#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +000023}
24
Stefan Reinauere0d607a2010-03-28 21:31:30 +000025static u32 read_phys(unsigned long addr)
Eric Biederman8ca8d762003-04-22 19:02:15 +000026{
Eric Biederman52685572003-05-19 19:16:21 +000027 volatile unsigned long *ptr;
Eric Biederman8ca8d762003-04-22 19:02:15 +000028 ptr = (void *)addr;
29 return *ptr;
30}
31
Stefan Reinauere0d607a2010-03-28 21:31:30 +000032static 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
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010050/**
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 *
Martin Roth5f066b22015-01-04 16:47:39 -070055 * @param idx Index to test pattern (0=<idx<0x400)
56 * @param addr Memory to access on idx
57 * @param value Value to write or read at addr
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010058 */
59static inline void test_pattern(unsigned short int idx,
60 unsigned long *addr, unsigned long *value)
Eric Biederman8ca8d762003-04-22 19:02:15 +000061{
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010062 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);
Eric Biederman8ca8d762003-04-22 19:02:15 +000071}
72
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010073/**
74 * Simple write-read-verify memory test. See console debug output for
75 * any dislocated bytes.
76 *
Martin Roth5f066b22015-01-04 16:47:39 -070077 * @param start System memory offset, aligned to 128bytes
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010078 */
79static int ram_bitset_nodie(unsigned long start)
Eric Biederman8ca8d762003-04-22 19:02:15 +000080{
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010081 unsigned long addr, value, value2;
82 unsigned short int idx;
83 unsigned char failed, failures;
84 uint8_t verbose = 0;
85
Kyösti Mälkki481814d2011-10-28 16:15:47 +030086#if !defined(__ROMCC__)
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010087 printk(BIOS_DEBUG, "DRAM bitset write: 0x%08lx\n", start);
Stefan Reinauer48b85fc2008-08-01 12:12:37 +000088#else
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010089 print_debug("DRAM bitset write: 0x");
Eric Biederman8ca8d762003-04-22 19:02:15 +000090 print_debug_hex32(start);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +000091 print_debug("\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +000092#endif
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +010093 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
Kyösti Mälkki481814d2011-10-28 16:15:47 +0300101#if !defined(__ROMCC__)
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100102 printk(BIOS_DEBUG, "DRAM bitset verify: 0x%08lx\n", start);
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000103#else
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100104 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");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000126#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000127 }
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100128 if (verbose) {
Kyösti Mälkki481814d2011-10-28 16:15:47 +0300129#if !defined(__ROMCC__)
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100130 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");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000139#else
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100140 if ((addr & 0x0f) == 0) {
141 print_dbg_hex32(start + addr);
142 print_dbg(" wr: ");
143 print_dbg_hex32(value);
144 print_dbg(" rd: ");
Richard Smithffb7d8a2006-04-01 04:10:44 +0000145 }
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100146 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
Eric Biederman8ca8d762003-04-22 19:02:15 +0000154 }
155 }
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100156 if (failures) {
157 post_code(0xea);
Kyösti Mälkki481814d2011-10-28 16:15:47 +0300158#if !defined(__ROMCC__)
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000159 printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000160#else
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000161 print_debug("\nDRAM did _NOT_ verify!\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000162#endif
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100163 return 1;
Richard Smithffb7d8a2006-04-01 04:10:44 +0000164 }
165 else {
Kyösti Mälkki481814d2011-10-28 16:15:47 +0300166#if !defined(__ROMCC__)
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000167 printk(BIOS_DEBUG, "\nDRAM range verified.\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000168#else
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000169 print_debug("\nDRAM range verified.\n");
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100170 return 0;
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000171#endif
Richard Smithffb7d8a2006-04-01 04:10:44 +0000172 }
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100173 return 0;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000174}
175
176
Eric Biederman8d9c1232003-06-17 08:42:17 +0000177void ram_check(unsigned long start, unsigned long stop)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000178{
Eric Biederman8ca8d762003-04-22 19:02:15 +0000179 /*
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 */
Kyösti Mälkki481814d2011-10-28 16:15:47 +0300184#if !defined(__ROMCC__)
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100185 printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start);
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000186#else
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100187 print_debug("Testing DRAM at: ");
Ronald G. Minnichbfdc5622004-03-22 04:24:29 +0000188 print_debug_hex32(start);
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000189 print_debug("\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000190#endif
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100191 if (ram_bitset_nodie(start))
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100192 die("DRAM ERROR");
Kyösti Mälkki481814d2011-10-28 16:15:47 +0300193#if !defined(__ROMCC__)
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000194 printk(BIOS_DEBUG, "Done.\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000195#else
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000196 print_debug("Done.\n");
Stefan Reinauer48b85fc2008-08-01 12:12:37 +0000197#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000198}
199
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100200
201int 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__)
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100210 printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start);
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100211#else
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100212 print_debug("Testing DRAM at : ");
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100213 print_debug_hex32(start);
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100214 print_debug("\n");
215#endif
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100216
Kyösti Mälkkie77b9a02012-03-17 08:09:14 +0100217 ret = ram_bitset_nodie(start);
Sven Schnelle3ad8c542011-12-02 16:23:06 +0100218#if !defined(__ROMCC__)
219 printk(BIOS_DEBUG, "Done.\n");
220#else
221 print_debug("Done.\n");
222#endif
223 return ret;
224}
225
Alexandru Gagniuc5239ba22013-06-08 11:32:36 -0500226int ram_check_noprint_nodie(unsigned long start, unsigned long stop)
227{
228 unsigned long addr, value, value2;
229 unsigned short int idx;
230 unsigned char failed, failures;
231
232 for (idx=0; idx<0x400; idx+=4) {
233 test_pattern(idx, &addr, &value);
234 write_phys(start + addr, value);
235 }
236
237 /* Make sure we don't read before we wrote */
238 phys_memory_barrier();
239
240 failures = 0;
241 for (idx=0; idx<0x400; idx+=4) {
242 test_pattern(idx, &addr, &value);
243 value2 = read_phys(start + addr);
244
245 failed = (value2 != value);
246 failures |= failed;
247 }
248 return failures;
249}
250
Stefan Reinauere0d607a2010-03-28 21:31:30 +0000251void quick_ram_check(void)
252{
253 int fail = 0;
254 u32 backup;
255 backup = read_phys(CONFIG_RAMBASE);
256 write_phys(CONFIG_RAMBASE, 0x55555555);
257 phys_memory_barrier();
258 if (read_phys(CONFIG_RAMBASE) != 0x55555555)
259 fail=1;
260 write_phys(CONFIG_RAMBASE, 0xaaaaaaaa);
261 phys_memory_barrier();
262 if (read_phys(CONFIG_RAMBASE) != 0xaaaaaaaa)
263 fail=1;
264 write_phys(CONFIG_RAMBASE, 0x00000000);
265 phys_memory_barrier();
266 if (read_phys(CONFIG_RAMBASE) != 0x00000000)
267 fail=1;
268 write_phys(CONFIG_RAMBASE, 0xffffffff);
269 phys_memory_barrier();
270 if (read_phys(CONFIG_RAMBASE) != 0xffffffff)
271 fail=1;
272
273 write_phys(CONFIG_RAMBASE, backup);
274 if (fail) {
275 post_code(0xea);
276 die("RAM INIT FAILURE!\n");
277 }
278 phys_memory_barrier();
279}