xref: /openbmc/u-boot/common/memsize.c (revision f9727161)
1 /*
2  * (C) Copyright 2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <config.h>
9 #ifdef __PPC__
10 /*
11  * At least on G2 PowerPC cores, sequential accesses to non-existent
12  * memory must be synchronized.
13  */
14 # include <asm/io.h>	/* for sync() */
15 #else
16 # define sync()		/* nothing */
17 #endif
18 
19 /*
20  * Check memory range for valid RAM. A simple memory test determines
21  * the actually available RAM size between addresses `base' and
22  * `base + maxsize'.
23  */
24 long get_ram_size(long *base, long maxsize)
25 {
26 	volatile long *addr;
27 	long           save[32];
28 	long           cnt;
29 	long           val;
30 	long           size;
31 	int            i = 0;
32 
33 	for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
34 		addr = base + cnt;	/* pointer arith! */
35 		sync ();
36 		save[i++] = *addr;
37 		sync ();
38 		*addr = ~cnt;
39 	}
40 
41 	addr = base;
42 	sync ();
43 	save[i] = *addr;
44 	sync ();
45 	*addr = 0;
46 
47 	sync ();
48 	if ((val = *addr) != 0) {
49 		/* Restore the original data before leaving the function.
50 		 */
51 		sync ();
52 		*addr = save[i];
53 		for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) {
54 			addr  = base + cnt;
55 			sync ();
56 			*addr = save[--i];
57 		}
58 		return (0);
59 	}
60 
61 	for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
62 		addr = base + cnt;	/* pointer arith! */
63 		val = *addr;
64 		*addr = save[--i];
65 		if (val != ~cnt) {
66 			size = cnt * sizeof (long);
67 			/* Restore the original data before leaving the function.
68 			 */
69 			for (cnt <<= 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
70 				addr  = base + cnt;
71 				*addr = save[--i];
72 			}
73 			return (size);
74 		}
75 	}
76 
77 	return (maxsize);
78 }
79