1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <device/mmio.h>
7 #include <console/console.h>
9 #define OVERLAP(a, b, s, e) ((b) > (s) && (a) < (e))
11 int __weak
probe_mb(const uintptr_t dram_start
, const uintptr_t size
)
13 uintptr_t addr
= dram_start
+ (size
* MiB
) - sizeof(uint32_t);
14 static const uint32_t patterns
[] = {0x55aa55aa, 0x12345678};
15 void *ptr
= (void *)addr
;
18 /* Don't accidentally clobber oneself. */
19 if (OVERLAP(addr
, addr
+ sizeof(uint32_t), (uintptr_t)_program
, (uintptr_t)_eprogram
))
22 uint32_t old
= read32(ptr
);
23 for (i
= 0; i
< ARRAY_SIZE(patterns
); i
++) {
24 write32(ptr
, patterns
[i
]);
25 if (read32(ptr
) != patterns
[i
])
30 return i
== ARRAY_SIZE(patterns
);
33 /* - 20 as probe_size is in MiB, - 1 as i is signed */
34 #define MAX_ADDRESSABLE_SPACE (sizeof(size_t) * 8 - 20 - 1)
36 /* Probe an area if it's read/writable. */
37 size_t probe_ramsize(const uintptr_t dram_start
, const size_t probe_size
)
41 size_t discovered
= 0;
43 static size_t saved_result
;
47 /* Find the MSB + 1. */
48 size_t tmp
= probe_size
;
53 /* Limit search to accessible address space */
54 msb
= MIN(msb
, MAX_ADDRESSABLE_SPACE
);
56 /* Compact binary search. */
57 for (i
= msb
; i
>= 0; i
--) {
58 if ((discovered
| (1ULL << i
)) > probe_size
)
60 if (probe_mb(dram_start
, (discovered
| (1ULL << i
))))
61 discovered
|= (1ULL << i
);
64 saved_result
= discovered
;
65 printk(BIOS_DEBUG
, "RAMDETECT: Found %zu MiB RAM\n", discovered
);