]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
c83bf6a2 WD |
2 | /* |
3 | * (C) Copyright 2004 | |
4 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
c83bf6a2 WD |
5 | */ |
6 | ||
e3866163 YS |
7 | #include <common.h> |
8 | ||
9 | DECLARE_GLOBAL_DATA_PTR; | |
10 | ||
91650b3e WD |
11 | #ifdef __PPC__ |
12 | /* | |
13 | * At least on G2 PowerPC cores, sequential accesses to non-existent | |
14 | * memory must be synchronized. | |
15 | */ | |
16 | # include <asm/io.h> /* for sync() */ | |
17 | #else | |
18 | # define sync() /* nothing */ | |
19 | #endif | |
c83bf6a2 WD |
20 | |
21 | /* | |
22 | * Check memory range for valid RAM. A simple memory test determines | |
23 | * the actually available RAM size between addresses `base' and | |
24 | * `base + maxsize'. | |
25 | */ | |
a55d23cc | 26 | long get_ram_size(long *base, long maxsize) |
c83bf6a2 WD |
27 | { |
28 | volatile long *addr; | |
67a2616a | 29 | long save[BITS_PER_LONG - 1]; |
c5da05cd | 30 | long save_base; |
c83bf6a2 WD |
31 | long cnt; |
32 | long val; | |
33 | long size; | |
34 | int i = 0; | |
35 | ||
cc8d698f | 36 | for (cnt = (maxsize / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { |
c83bf6a2 | 37 | addr = base + cnt; /* pointer arith! */ |
95099fee | 38 | sync(); |
cc8d698f | 39 | save[i++] = *addr; |
95099fee | 40 | sync(); |
cc8d698f | 41 | *addr = ~cnt; |
c83bf6a2 WD |
42 | } |
43 | ||
cc8d698f HG |
44 | addr = base; |
45 | sync(); | |
c5da05cd | 46 | save_base = *addr; |
cc8d698f HG |
47 | sync(); |
48 | *addr = 0; | |
49 | ||
8e7cba04 | 50 | sync(); |
cc8d698f HG |
51 | if ((val = *addr) != 0) { |
52 | /* Restore the original data before leaving the function. */ | |
53 | sync(); | |
c5da05cd | 54 | *base = save_base; |
cc8d698f HG |
55 | for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) { |
56 | addr = base + cnt; | |
57 | sync(); | |
58 | *addr = save[--i]; | |
59 | } | |
60 | return (0); | |
61 | } | |
62 | ||
63 | for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) { | |
c83bf6a2 WD |
64 | addr = base + cnt; /* pointer arith! */ |
65 | val = *addr; | |
cc8d698f HG |
66 | *addr = save[--i]; |
67 | if (val != ~cnt) { | |
95099fee WD |
68 | size = cnt * sizeof(long); |
69 | /* | |
70 | * Restore the original data | |
71 | * before leaving the function. | |
c83bf6a2 | 72 | */ |
95099fee WD |
73 | for (cnt <<= 1; |
74 | cnt < maxsize / sizeof(long); | |
75 | cnt <<= 1) { | |
c83bf6a2 | 76 | addr = base + cnt; |
cc8d698f | 77 | *addr = save[--i]; |
c83bf6a2 | 78 | } |
218da804 PD |
79 | /* warning: don't restore save_base in this case, |
80 | * it is already done in the loop because | |
81 | * base and base+size share the same physical memory | |
82 | * and *base is saved after *(base+size) modification | |
83 | * in first loop | |
84 | */ | |
c83bf6a2 WD |
85 | return (size); |
86 | } | |
cc8d698f | 87 | } |
218da804 | 88 | *base = save_base; |
c83bf6a2 WD |
89 | |
90 | return (maxsize); | |
91 | } | |
e3866163 YS |
92 | |
93 | phys_size_t __weak get_effective_memsize(void) | |
94 | { | |
95 | #ifndef CONFIG_VERY_BIG_RAM | |
96 | return gd->ram_size; | |
97 | #else | |
98 | /* limit stack to what we can reasonable map */ | |
99 | return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ? | |
100 | CONFIG_MAX_MEM_MAPPED : gd->ram_size); | |
101 | #endif | |
102 | } |