Merge https://source.denx.de/u-boot/custodians/u-boot-marvell
[platform/kernel/u-boot.git] / common / memsize.c
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  */
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
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 }