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
[] = {
18 void *ptr
= (void *) addr
;
21 /* Don't accidentally clober oneself. */
22 if (OVERLAP(addr
, addr
+ sizeof(uint32_t), (uintptr_t)_program
, (uintptr_t) _eprogram
))
25 uint32_t old
= read32(ptr
);
26 for (i
= 0; i
< ARRAY_SIZE(patterns
); i
++) {
27 write32(ptr
, patterns
[i
]);
28 if (read32(ptr
) != patterns
[i
])
33 return i
== ARRAY_SIZE(patterns
);
36 /* - 20 as probe_size is in MiB, - 1 as i is signed */
37 #define MAX_ADDRESSABLE_SPACE (sizeof(size_t) * 8 - 20 - 1)
39 /* Probe an area if it's read/writable. */
40 size_t probe_ramsize(const uintptr_t dram_start
, const size_t probe_size
)
44 size_t discovered
= 0;
46 static size_t saved_result
;
50 /* Find the MSB + 1. */
51 size_t tmp
= probe_size
;
56 /* Limit search to accessible address space */
57 msb
= MIN(msb
, MAX_ADDRESSABLE_SPACE
);
59 /* Compact binary search. */
60 for (i
= msb
; i
>= 0; i
--)
61 if (probe_mb(dram_start
, (discovered
| (1ULL << i
))))
62 discovered
|= (1ULL << i
);
64 saved_result
= discovered
;
65 printk(BIOS_DEBUG
, "RAMDETECT: Found %zu MiB RAM\n", discovered
);