mb/google/brya: Create rull variant
[coreboot2.git] / src / lib / ramtest.c
blob90fc777a25acd11b5360a22431b5d1b81555a82d
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <stdint.h>
4 #include <lib.h>
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)
12 asm volatile (
13 "movnti %1, (%0)"
14 : /* outputs */
15 : "r" (addr), "r" (value) /* inputs */
19 static void phys_memory_barrier(void)
21 // Needed for movnti
22 asm volatile ("sfence" ::: "memory");
24 #else
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");
34 #endif
36 static u32 read_phys(uintptr_t addr)
38 return read32p(addr);
41 /**
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)
53 uint8_t j, k;
55 k = (idx >> 8) + 1;
56 j = (idx >> 4) & 0x0f;
57 *addr = idx & 0x0f;
58 *addr |= j << (4*k);
59 *value = 0x01010101 << (j & 7);
60 if (j & 8)
61 *value = ~(*value);
64 /**
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;
77 uint8_t verbose = 0;
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);
89 failures = 0;
90 for (idx = 0; idx < 0x400; idx += 4) {
91 test_pattern(idx, &addr, &value);
92 value2 = read_phys(start + addr);
94 failed = (value2 != value);
95 failures |= failed;
96 if (failed && !verbose) {
97 printk(BIOS_ERR, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n",
98 start + addr, value, value2);
100 if (verbose) {
101 if ((addr & 0x0f) == 0)
102 printk(BIOS_DEBUG, "%08lx wr: %08lx rd:",
103 start + addr, value);
104 if (failed)
105 printk(BIOS_DEBUG, " %08lx!", value2);
106 else
107 printk(BIOS_DEBUG, " %08lx ", value2);
108 if ((addr & 0x0f) == 0xc)
109 printk(BIOS_DEBUG, "\n");
112 if (failures) {
113 post_code(POSTCODE_RAM_FAILURE);
114 printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n");
115 return 1;
117 printk(BIOS_DEBUG, "\nDRAM range verified.\n");
118 return 0;
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
127 * are tested. -Tyson
129 printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start);
130 if (ram_bitset_nodie(start))
131 die("DRAM ERROR");
132 printk(BIOS_DEBUG, "Done.\n");
136 int ram_check_nodie(uintptr_t start)
138 int ret;
140 * This is much more of a "Is my DRAM properly configured?"
141 * test than a "Is my DRAM faulty?" test. Not all bits
142 * are tested. -Tyson
144 printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start);
146 ret = ram_bitset_nodie(start);
147 printk(BIOS_DEBUG, "Done.\n");
148 return ret;
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();
165 failures = 0;
166 for (idx = 0; idx < 0x400; idx += 4) {
167 test_pattern(idx, &addr, &value);
168 value2 = read_phys(start + addr);
170 failed = (value2 != value);
171 failures |= failed;
173 return failures;
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)
181 int fail = 0;
182 u32 backup;
183 backup = read_phys(dst);
184 write_phys(dst, 0x55555555);
185 phys_memory_barrier();
186 if (read_phys(dst) != 0x55555555)
187 fail = 1;
188 write_phys(dst, 0xaaaaaaaa);
189 phys_memory_barrier();
190 if (read_phys(dst) != 0xaaaaaaaa)
191 fail = 1;
192 write_phys(dst, 0x00000000);
193 phys_memory_barrier();
194 if (read_phys(dst) != 0x00000000)
195 fail = 1;
196 write_phys(dst, 0xffffffff);
197 phys_memory_barrier();
198 if (read_phys(dst) != 0xffffffff)
199 fail = 1;
201 write_phys(dst, backup);
202 if (fail) {
203 post_code(POSTCODE_RAM_FAILURE);
204 die("RAM INIT FAILURE!\n");
206 phys_memory_barrier();