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