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 	phys_size_t ram_size = gd->ram_size;
98 
99 #ifdef CONFIG_MPC85xx
100 	/*
101 	 * Check for overflow and limit ram size to some representable value.
102 	 * It is required that ram_base + ram_size must be representable by
103 	 * phys_size_t type and must be aligned by direct access, therefore
104 	 * calculate it from last 4kB sector which should work as alignment
105 	 * on any platform.
106 	 */
107 	if (gd->ram_base + ram_size < gd->ram_base)
108 		ram_size = ((phys_size_t)~0xfffULL) - gd->ram_base;
109 #endif
110 
111 #ifndef CFG_MAX_MEM_MAPPED
112 	return ram_size;
113 #else
114 	/* limit stack to what we can reasonable map */
115 	return ((ram_size > CFG_MAX_MEM_MAPPED) ?
116 		CFG_MAX_MEM_MAPPED : ram_size);
117 #endif
118 }
119