env: ti: ti_common.env: Fix get_overlaystring for FIT Image
[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 #include <cpu_func.h>
11 #include <stdint.h>
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 #ifdef CONFIG_SYS_CACHELINE_SIZE
16 # define MEMSIZE_CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE
17 #else
18 /* Just use the greatest cache flush alignment requirement I'm aware of */
19 # define MEMSIZE_CACHELINE_SIZE 128
20 #endif
21
22 #ifdef __PPC__
23 /*
24  * At least on G2 PowerPC cores, sequential accesses to non-existent
25  * memory must be synchronized.
26  */
27 # include <asm/io.h>    /* for sync() */
28 #else
29 # define sync()         /* nothing */
30 #endif
31
32 static void dcache_flush_invalidate(volatile long *p)
33 {
34         uintptr_t start, stop;
35         start = ALIGN_DOWN((uintptr_t)p, MEMSIZE_CACHELINE_SIZE);
36         stop = start + MEMSIZE_CACHELINE_SIZE;
37         flush_dcache_range(start, stop);
38         invalidate_dcache_range(start, stop);
39 }
40
41 /*
42  * Check memory range for valid RAM. A simple memory test determines
43  * the actually available RAM size between addresses `base' and
44  * `base + maxsize'.
45  */
46 long get_ram_size(long *base, long maxsize)
47 {
48         volatile long *addr;
49         long           save[BITS_PER_LONG - 1];
50         long           save_base;
51         long           cnt;
52         long           val;
53         long           size;
54         int            i = 0;
55         int            dcache_en = dcache_status();
56
57         for (cnt = (maxsize / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) {
58                 addr = base + cnt;      /* pointer arith! */
59                 sync();
60                 save[i++] = *addr;
61                 sync();
62                 *addr = ~cnt;
63                 if (dcache_en)
64                         dcache_flush_invalidate(addr);
65         }
66
67         addr = base;
68         sync();
69         save_base = *addr;
70         sync();
71         *addr = 0;
72
73         sync();
74         if (dcache_en)
75                 dcache_flush_invalidate(addr);
76
77         if ((val = *addr) != 0) {
78                 /* Restore the original data before leaving the function. */
79                 sync();
80                 *base = save_base;
81                 for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) {
82                         addr  = base + cnt;
83                         sync();
84                         *addr = save[--i];
85                 }
86                 return (0);
87         }
88
89         for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) {
90                 addr = base + cnt;      /* pointer arith! */
91                 val = *addr;
92                 *addr = save[--i];
93                 if (val != ~cnt) {
94                         size = cnt * sizeof(long);
95                         /*
96                          * Restore the original data
97                          * before leaving the function.
98                          */
99                         for (cnt <<= 1;
100                              cnt < maxsize / sizeof(long);
101                              cnt <<= 1) {
102                                 addr  = base + cnt;
103                                 *addr = save[--i];
104                         }
105                         /* warning: don't restore save_base in this case,
106                          * it is already done in the loop because
107                          * base and base+size share the same physical memory
108                          * and *base is saved after *(base+size) modification
109                          * in first loop
110                          */
111                         return (size);
112                 }
113         }
114         *base = save_base;
115
116         return (maxsize);
117 }
118
119 phys_size_t __weak get_effective_memsize(void)
120 {
121         phys_size_t ram_size = gd->ram_size;
122
123 #ifdef CONFIG_MPC85xx
124         /*
125          * Check for overflow and limit ram size to some representable value.
126          * It is required that ram_base + ram_size must be representable by
127          * phys_size_t type and must be aligned by direct access, therefore
128          * calculate it from last 4kB sector which should work as alignment
129          * on any platform.
130          */
131         if (gd->ram_base + ram_size < gd->ram_base)
132                 ram_size = ((phys_size_t)~0xfffULL) - gd->ram_base;
133 #endif
134
135 #ifndef CFG_MAX_MEM_MAPPED
136         return ram_size;
137 #else
138         /* limit stack to what we can reasonable map */
139         return ((ram_size > CFG_MAX_MEM_MAPPED) ?
140                 CFG_MAX_MEM_MAPPED : ram_size);
141 #endif
142 }