mb/google/soraka: Fine-tune USB 2.0 port4
[coreboot.git] / src / lib / ramtest.c
blob2b2c34437b2459e815f5e3761b9d10881385864a
1 #include <stdint.h>
2 #include <lib.h> /* Prototypes */
3 #include <console/console.h>
5 static void write_phys(unsigned long addr, u32 value)
7 // Assembler in lib/ is very ugly. But we properly guarded
8 // it so let's obey this one for now
9 #if IS_ENABLED(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
18 #else
19 volatile unsigned long *ptr;
20 ptr = (void *)addr;
21 *ptr = value;
22 #endif
25 static u32 read_phys(unsigned long addr)
27 volatile unsigned long *ptr;
28 ptr = (void *)addr;
29 return *ptr;
32 static void phys_memory_barrier(void)
34 #if IS_ENABLED(CONFIG_SSE2)
35 // Needed for movnti
36 asm volatile (
37 "sfence"
39 #ifdef __GNUC__ /* ROMCC does not like memory clobbers */
40 : "memory"
41 #endif
43 #else
44 #ifdef __GNUC__ /* ROMCC does not like empty asm statements */
45 asm volatile ("" ::: "memory");
46 #endif
47 #endif
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.
55 * @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
59 static inline void test_pattern(unsigned short int idx,
60 unsigned long *addr, unsigned long *value)
62 uint8_t j, k;
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);
73 /**
74 * Simple write-read-verify memory test. See console debug output for
75 * any dislocated bytes.
77 * @param start System memory offset, aligned to 128bytes
79 static int ram_bitset_nodie(unsigned long start)
81 unsigned long addr, value, value2;
82 unsigned short int idx;
83 unsigned char failed, failures;
84 uint8_t verbose = 0;
86 printk(BIOS_DEBUG, "DRAM bitset write: 0x%08lx\n", start);
87 for (idx = 0; idx < 0x400; idx += 4) {
88 test_pattern(idx, &addr, &value);
89 write_phys(start + addr, value);
92 /* Make sure we don't read before we wrote */
93 phys_memory_barrier();
95 printk(BIOS_DEBUG, "DRAM bitset verify: 0x%08lx\n", start);
96 failures = 0;
97 for (idx = 0; idx < 0x400; idx += 4) {
98 test_pattern(idx, &addr, &value);
99 value2 = read_phys(start + addr);
101 failed = (value2 != value);
102 failures |= failed;
103 if (failed && !verbose) {
104 printk(BIOS_ERR, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n",
105 start + addr, value, value2);
107 if (verbose) {
108 if ((addr & 0x0f) == 0)
109 printk(BIOS_DEBUG, "%08lx wr: %08lx rd:",
110 start + addr, value);
111 if (failed)
112 printk(BIOS_DEBUG, " %08lx!", value2);
113 else
114 printk(BIOS_DEBUG, " %08lx ", value2);
115 if ((addr & 0x0f) == 0xc)
116 printk(BIOS_DEBUG, "\n");
119 if (failures) {
120 post_code(0xea);
121 printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n");
122 return 1;
124 printk(BIOS_DEBUG, "\nDRAM range verified.\n");
125 return 0;
129 void ram_check(unsigned long start, unsigned long stop)
132 * This is much more of a "Is my DRAM properly configured?"
133 * test than a "Is my DRAM faulty?" test. Not all bits
134 * are tested. -Tyson
136 printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start);
137 if (ram_bitset_nodie(start))
138 die("DRAM ERROR");
139 printk(BIOS_DEBUG, "Done.\n");
143 int ram_check_nodie(unsigned long start, unsigned long stop)
145 int ret;
147 * This is much more of a "Is my DRAM properly configured?"
148 * test than a "Is my DRAM faulty?" test. Not all bits
149 * are tested. -Tyson
151 printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start);
153 ret = ram_bitset_nodie(start);
154 printk(BIOS_DEBUG, "Done.\n");
155 return ret;
158 int ram_check_noprint_nodie(unsigned long start, unsigned long stop)
160 unsigned long addr, value, value2;
161 unsigned short int idx;
162 unsigned char failed, failures;
164 for (idx = 0; idx < 0x400; idx += 4) {
165 test_pattern(idx, &addr, &value);
166 write_phys(start + addr, value);
169 /* Make sure we don't read before we wrote */
170 phys_memory_barrier();
172 failures = 0;
173 for (idx = 0; idx < 0x400; idx += 4) {
174 test_pattern(idx, &addr, &value);
175 value2 = read_phys(start + addr);
177 failed = (value2 != value);
178 failures |= failed;
180 return failures;
183 static void __quick_ram_check(uintptr_t dst)
185 int fail = 0;
186 u32 backup;
187 backup = read_phys(dst);
188 write_phys(dst, 0x55555555);
189 phys_memory_barrier();
190 if (read_phys(dst) != 0x55555555)
191 fail = 1;
192 write_phys(dst, 0xaaaaaaaa);
193 phys_memory_barrier();
194 if (read_phys(dst) != 0xaaaaaaaa)
195 fail = 1;
196 write_phys(dst, 0x00000000);
197 phys_memory_barrier();
198 if (read_phys(dst) != 0x00000000)
199 fail = 1;
200 write_phys(dst, 0xffffffff);
201 phys_memory_barrier();
202 if (read_phys(dst) != 0xffffffff)
203 fail = 1;
205 write_phys(dst, backup);
206 if (fail) {
207 post_code(0xea);
208 die("RAM INIT FAILURE!\n");
210 phys_memory_barrier();
213 void quick_ram_check(void)
215 __quick_ram_check(0x100000);