1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <console/console.h>
6 #include <device/mmio.h>
8 #if ENV_X86 && CONFIG(SSE2)
9 /* Assembler in lib/ is ugly. */
10 static void write_phys(uintptr_t addr
, u32 value
)
15 : "r" (addr
), "r" (value
) /* inputs */
19 static void phys_memory_barrier(void)
22 asm volatile ("sfence" ::: "memory");
25 static void write_phys(uintptr_t addr
, u32 value
)
27 write32p(addr
, value
);
30 static void phys_memory_barrier(void)
32 asm volatile ("" ::: "memory");
36 static u32
read_phys(uintptr_t addr
)
42 * Rotate ones test pattern that access every bit on a 128bit wide
43 * memory bus. To test most address lines, addresses are scattered
44 * using 256B, 4kB and 64kB increments.
46 * @param idx Index to test pattern (0=<idx<0x400)
47 * @param addr Memory to access on idx
48 * @param value Value to write or read at addr
50 static inline void test_pattern(unsigned short int idx
,
51 unsigned long *addr
, unsigned long *value
)
56 j
= (idx
>> 4) & 0x0f;
59 *value
= 0x01010101 << (j
& 7);
65 * Simple write-read-verify memory test. See console debug output for
66 * any dislocated bytes.
68 * Tests 1MiB of memory starting from start.
70 * @param start System memory offset, aligned to 128bytes
72 static int ram_bitset_nodie(uintptr_t start
)
74 unsigned long addr
, value
, value2
;
75 unsigned short int idx
;
76 unsigned char failed
, failures
;
79 printk(BIOS_DEBUG
, "DRAM bitset write: 0x%08lx\n", start
);
80 for (idx
= 0; idx
< 0x400; idx
+= 4) {
81 test_pattern(idx
, &addr
, &value
);
82 write_phys(start
+ addr
, value
);
85 /* Make sure we don't read before we wrote */
86 phys_memory_barrier();
88 printk(BIOS_DEBUG
, "DRAM bitset verify: 0x%08lx\n", start
);
90 for (idx
= 0; idx
< 0x400; idx
+= 4) {
91 test_pattern(idx
, &addr
, &value
);
92 value2
= read_phys(start
+ addr
);
94 failed
= (value2
!= value
);
96 if (failed
&& !verbose
) {
97 printk(BIOS_ERR
, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n",
98 start
+ addr
, value
, value2
);
101 if ((addr
& 0x0f) == 0)
102 printk(BIOS_DEBUG
, "%08lx wr: %08lx rd:",
103 start
+ addr
, value
);
105 printk(BIOS_DEBUG
, " %08lx!", value2
);
107 printk(BIOS_DEBUG
, " %08lx ", value2
);
108 if ((addr
& 0x0f) == 0xc)
109 printk(BIOS_DEBUG
, "\n");
113 post_code(POSTCODE_RAM_FAILURE
);
114 printk(BIOS_DEBUG
, "\nDRAM did _NOT_ verify!\n");
117 printk(BIOS_DEBUG
, "\nDRAM range verified.\n");
122 void ram_check(uintptr_t start
)
125 * This is much more of a "Is my DRAM properly configured?"
126 * test than a "Is my DRAM faulty?" test. Not all bits
129 printk(BIOS_DEBUG
, "Testing DRAM at: %08lx\n", start
);
130 if (ram_bitset_nodie(start
))
132 printk(BIOS_DEBUG
, "Done.\n");
136 int ram_check_nodie(uintptr_t start
)
140 * This is much more of a "Is my DRAM properly configured?"
141 * test than a "Is my DRAM faulty?" test. Not all bits
144 printk(BIOS_DEBUG
, "Testing DRAM at : %08lx\n", start
);
146 ret
= ram_bitset_nodie(start
);
147 printk(BIOS_DEBUG
, "Done.\n");
151 int ram_check_noprint_nodie(uintptr_t start
)
153 unsigned long addr
, value
, value2
;
154 unsigned short int idx
;
155 unsigned char failed
, failures
;
157 for (idx
= 0; idx
< 0x400; idx
+= 4) {
158 test_pattern(idx
, &addr
, &value
);
159 write_phys(start
+ addr
, value
);
162 /* Make sure we don't read before we wrote */
163 phys_memory_barrier();
166 for (idx
= 0; idx
< 0x400; idx
+= 4) {
167 test_pattern(idx
, &addr
, &value
);
168 value2
= read_phys(start
+ addr
);
170 failed
= (value2
!= value
);
176 /* Assumption is 32-bit addressable UC memory at dst. This also executes
177 * on S3 resume path so target memory must be restored.
179 void quick_ram_check_or_die(uintptr_t dst
)
183 backup
= read_phys(dst
);
184 write_phys(dst
, 0x55555555);
185 phys_memory_barrier();
186 if (read_phys(dst
) != 0x55555555)
188 write_phys(dst
, 0xaaaaaaaa);
189 phys_memory_barrier();
190 if (read_phys(dst
) != 0xaaaaaaaa)
192 write_phys(dst
, 0x00000000);
193 phys_memory_barrier();
194 if (read_phys(dst
) != 0x00000000)
196 write_phys(dst
, 0xffffffff);
197 phys_memory_barrier();
198 if (read_phys(dst
) != 0xffffffff)
201 write_phys(dst
, backup
);
203 post_code(POSTCODE_RAM_FAILURE
);
204 die("RAM INIT FAILURE!\n");
206 phys_memory_barrier();