memsize.c 3.3 KB

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