mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-24 12:44:23 +08:00
common/memsize.c: Fix get_ram_size() when cache is enabled
Ensure that every write is flushed to memory and afterward reads are
from memory.
Since the algorithm rely on the fact that accessing to not existent
memory lead to write at addr / 2 without this modification accesses
to aliased (not physically present) addresses are cached and
wrong size is returned.
This was discovered while working on a TI AM625 based board
where cache is normally enabled, see commit c02712a748
("arm: mach-k3: Enable dcache in SPL").
Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
This commit is contained in:
parent
a1e225b814
commit
1c64b98c1e
@ -7,9 +7,18 @@
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <cpu_func.h>
|
||||
#include <stdint.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_SYS_CACHELINE_SIZE
|
||||
# define MEMSIZE_CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE
|
||||
#else
|
||||
/* Just use the greatest cache flush alignment requirement I'm aware of */
|
||||
# define MEMSIZE_CACHELINE_SIZE 128
|
||||
#endif
|
||||
|
||||
#ifdef __PPC__
|
||||
/*
|
||||
* At least on G2 PowerPC cores, sequential accesses to non-existent
|
||||
@ -20,6 +29,15 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
# define sync() /* nothing */
|
||||
#endif
|
||||
|
||||
static void dcache_flush_invalidate(volatile long *p)
|
||||
{
|
||||
uintptr_t start, stop;
|
||||
start = ALIGN_DOWN((uintptr_t)p, MEMSIZE_CACHELINE_SIZE);
|
||||
stop = start + MEMSIZE_CACHELINE_SIZE;
|
||||
flush_dcache_range(start, stop);
|
||||
invalidate_dcache_range(start, stop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check memory range for valid RAM. A simple memory test determines
|
||||
* the actually available RAM size between addresses `base' and
|
||||
@ -34,6 +52,7 @@ long get_ram_size(long *base, long maxsize)
|
||||
long val;
|
||||
long size;
|
||||
int i = 0;
|
||||
int dcache_en = dcache_status();
|
||||
|
||||
for (cnt = (maxsize / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
|
||||
addr = base + cnt; /* pointer arith! */
|
||||
@ -41,6 +60,8 @@ long get_ram_size(long *base, long maxsize)
|
||||
save[i++] = *addr;
|
||||
sync();
|
||||
*addr = ~cnt;
|
||||
if (dcache_en)
|
||||
dcache_flush_invalidate(addr);
|
||||
}
|
||||
|
||||
addr = base;
|
||||
@ -50,6 +71,9 @@ long get_ram_size(long *base, long maxsize)
|
||||
*addr = 0;
|
||||
|
||||
sync();
|
||||
if (dcache_en)
|
||||
dcache_flush_invalidate(addr);
|
||||
|
||||
if ((val = *addr) != 0) {
|
||||
/* Restore the original data before leaving the function. */
|
||||
sync();
|
||||
|
Loading…
Reference in New Issue
Block a user