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