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