xref: /openbmc/u-boot/common/memsize.c (revision 67a2616af18bbb38905b90ed1c6b66659671e1da)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2c83bf6a2Swdenk /*
3c83bf6a2Swdenk  * (C) Copyright 2004
4c83bf6a2Swdenk  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5c83bf6a2Swdenk  */
6c83bf6a2Swdenk 
7e3866163SYork Sun #include <common.h>
8e3866163SYork Sun 
9e3866163SYork Sun DECLARE_GLOBAL_DATA_PTR;
10e3866163SYork Sun 
1191650b3eSWolfgang Denk #ifdef __PPC__
1291650b3eSWolfgang Denk /*
1391650b3eSWolfgang Denk  * At least on G2 PowerPC cores, sequential accesses to non-existent
1491650b3eSWolfgang Denk  * memory must be synchronized.
1591650b3eSWolfgang Denk  */
1691650b3eSWolfgang Denk # include <asm/io.h>	/* for sync() */
1791650b3eSWolfgang Denk #else
1891650b3eSWolfgang Denk # define sync()		/* nothing */
1991650b3eSWolfgang Denk #endif
20c83bf6a2Swdenk 
21c83bf6a2Swdenk /*
22c83bf6a2Swdenk  * Check memory range for valid RAM. A simple memory test determines
23c83bf6a2Swdenk  * the actually available RAM size between addresses `base' and
24c83bf6a2Swdenk  * `base + maxsize'.
25c83bf6a2Swdenk  */
get_ram_size(long * base,long maxsize)26a55d23ccSAlbert ARIBAUD long get_ram_size(long *base, long maxsize)
27c83bf6a2Swdenk {
28c83bf6a2Swdenk 	volatile long *addr;
29*67a2616aSTien Fong Chee 	long           save[BITS_PER_LONG - 1];
30c5da05cdSPatrick Delaunay 	long           save_base;
31c83bf6a2Swdenk 	long           cnt;
32c83bf6a2Swdenk 	long           val;
33c83bf6a2Swdenk 	long           size;
34c83bf6a2Swdenk 	int            i = 0;
35c83bf6a2Swdenk 
36cc8d698fSHans de Goede 	for (cnt = (maxsize / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
37c83bf6a2Swdenk 		addr = base + cnt;	/* pointer arith! */
3891650b3eSWolfgang Denk 		sync();
39cc8d698fSHans de Goede 		save[i++] = *addr;
40cc8d698fSHans de Goede 		sync();
41cc8d698fSHans de Goede 		*addr = ~cnt;
42cc8d698fSHans de Goede 	}
43cc8d698fSHans de Goede 
44cc8d698fSHans de Goede 	addr = base;
45cc8d698fSHans de Goede 	sync();
46c5da05cdSPatrick Delaunay 	save_base = *addr;
4791650b3eSWolfgang Denk 	sync();
48c83bf6a2Swdenk 	*addr = 0;
49c83bf6a2Swdenk 
508e7cba04SEddy Petrișor 	sync();
51cc8d698fSHans de Goede 	if ((val = *addr) != 0) {
52cc8d698fSHans de Goede 		/* Restore the original data before leaving the function. */
53cc8d698fSHans de Goede 		sync();
54c5da05cdSPatrick Delaunay 		*base = save_base;
55cc8d698fSHans de Goede 		for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) {
56cc8d698fSHans de Goede 			addr  = base + cnt;
57cc8d698fSHans de Goede 			sync();
58cc8d698fSHans de Goede 			*addr = save[--i];
59cc8d698fSHans de Goede 		}
60cc8d698fSHans de Goede 		return (0);
61cc8d698fSHans de Goede 	}
62cc8d698fSHans de Goede 
63cc8d698fSHans de Goede 	for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) {
64c83bf6a2Swdenk 		addr = base + cnt;	/* pointer arith! */
65c83bf6a2Swdenk 		val = *addr;
66cc8d698fSHans de Goede 		*addr = save[--i];
67cc8d698fSHans de Goede 		if (val != ~cnt) {
68c83bf6a2Swdenk 			size = cnt * sizeof(long);
6995099feeSWolfgang Denk 			/*
7095099feeSWolfgang Denk 			 * Restore the original data
7195099feeSWolfgang Denk 			 * before leaving the function.
72c83bf6a2Swdenk 			 */
7395099feeSWolfgang Denk 			for (cnt <<= 1;
7495099feeSWolfgang Denk 			     cnt < maxsize / sizeof(long);
7595099feeSWolfgang Denk 			     cnt <<= 1) {
76c83bf6a2Swdenk 				addr  = base + cnt;
77cc8d698fSHans de Goede 				*addr = save[--i];
78c83bf6a2Swdenk 			}
79218da804SPatrick Delaunay 			/* warning: don't restore save_base in this case,
80218da804SPatrick Delaunay 			 * it is already done in the loop because
81218da804SPatrick Delaunay 			 * base and base+size share the same physical memory
82218da804SPatrick Delaunay 			 * and *base is saved after *(base+size) modification
83218da804SPatrick Delaunay 			 * in first loop
84218da804SPatrick Delaunay 			 */
85c83bf6a2Swdenk 			return (size);
86c83bf6a2Swdenk 		}
87cc8d698fSHans de Goede 	}
88218da804SPatrick Delaunay 	*base = save_base;
89c83bf6a2Swdenk 
90c83bf6a2Swdenk 	return (maxsize);
91c83bf6a2Swdenk }
92e3866163SYork Sun 
get_effective_memsize(void)93e3866163SYork Sun phys_size_t __weak get_effective_memsize(void)
94e3866163SYork Sun {
95e3866163SYork Sun #ifndef CONFIG_VERY_BIG_RAM
96e3866163SYork Sun 	return gd->ram_size;
97e3866163SYork Sun #else
98e3866163SYork Sun 	/* limit stack to what we can reasonable map */
99e3866163SYork Sun 	return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ?
100e3866163SYork Sun 		CONFIG_MAX_MEM_MAPPED : gd->ram_size);
101e3866163SYork Sun #endif
102e3866163SYork Sun }
103