memory.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * Carsten Langgaard, carstenl@mips.com
  3. * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
  4. * Portions copyright (C) 2009 Cisco Systems, Inc.
  5. *
  6. * This program is free software; you can distribute it and/or modify it
  7. * under the terms of the GNU General Public License (Version 2) as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  13. * for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  18. *
  19. * Apparently originally from arch/mips/malta-memory.c. Modified to work
  20. * with the PowerTV bootloader.
  21. */
  22. #include <linux/init.h>
  23. #include <linux/mm.h>
  24. #include <linux/bootmem.h>
  25. #include <linux/pfn.h>
  26. #include <linux/string.h>
  27. #include <asm/bootinfo.h>
  28. #include <asm/page.h>
  29. #include <asm/sections.h>
  30. #include <asm/mips-boards/prom.h>
  31. #include <asm/mach-powertv/asic.h>
  32. #include <asm/mach-powertv/ioremap.h>
  33. #include "init.h"
  34. /* Memory constants */
  35. #define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
  36. #define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
  37. #define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */
  38. #define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */
  39. #define RV_SIZE MEBIBYTE(4) /* Size of reset vector */
  40. #define LOW_MEM_END 0x20000000 /* Highest low memory address */
  41. #define BLDR_ALIAS 0x10000000 /* Bootloader address */
  42. #define RV_PHYS 0x1fc00000 /* Reset vector address */
  43. #define LOW_RAM_END RV_PHYS /* End of real RAM in low mem */
  44. /*
  45. * Very low-level conversion from processor physical address to device
  46. * DMA address for the first bank of memory.
  47. */
  48. #define PHYS_TO_DMA(paddr) ((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS))
  49. unsigned long ptv_memsize;
  50. /*
  51. * struct low_mem_reserved - Items in low memory that are reserved
  52. * @start: Physical address of item
  53. * @size: Size, in bytes, of this item
  54. * @is_aliased: True if this is RAM aliased from another location. If false,
  55. * it is something other than aliased RAM and the RAM in the
  56. * unaliased address is still visible outside of low memory.
  57. */
  58. struct low_mem_reserved {
  59. phys_addr_t start;
  60. phys_addr_t size;
  61. bool is_aliased;
  62. };
  63. /*
  64. * Must be in ascending address order
  65. */
  66. struct low_mem_reserved low_mem_reserved[] = {
  67. {BLDR_ALIAS, BLDR_SIZE, true}, /* Bootloader RAM */
  68. {RV_PHYS, RV_SIZE, false}, /* Reset vector */
  69. };
  70. /*
  71. * struct mem_layout - layout of a piece of the system RAM
  72. * @phys: Physical address of the start of this piece of RAM. This is the
  73. * address at which both the processor and I/O devices see the
  74. * RAM.
  75. * @alias: Alias of this piece of memory in order to make it appear in
  76. * the low memory part of the processor's address space. I/O
  77. * devices don't see anything here.
  78. * @size: Size, in bytes, of this piece of RAM
  79. */
  80. struct mem_layout {
  81. phys_addr_t phys;
  82. phys_addr_t alias;
  83. phys_addr_t size;
  84. };
  85. /*
  86. * struct mem_layout_list - list descriptor for layouts of system RAM pieces
  87. * @family: Specifies the family being described
  88. * @n: Number of &struct mem_layout elements
  89. * @layout: Pointer to the list of &mem_layout structures
  90. */
  91. struct mem_layout_list {
  92. enum family_type family;
  93. size_t n;
  94. struct mem_layout *layout;
  95. };
  96. static struct mem_layout f1500_layout[] = {
  97. {0x20000000, 0x10000000, MEBIBYTE(256)},
  98. };
  99. static struct mem_layout f4500_layout[] = {
  100. {0x40000000, 0x10000000, MEBIBYTE(256)},
  101. {0x20000000, 0x20000000, MEBIBYTE(32)},
  102. };
  103. static struct mem_layout f8500_layout[] = {
  104. {0x40000000, 0x10000000, MEBIBYTE(256)},
  105. {0x20000000, 0x20000000, MEBIBYTE(32)},
  106. {0x30000000, 0x30000000, MEBIBYTE(32)},
  107. };
  108. static struct mem_layout fx600_layout[] = {
  109. {0x20000000, 0x10000000, MEBIBYTE(256)},
  110. {0x60000000, 0x60000000, MEBIBYTE(128)},
  111. };
  112. static struct mem_layout_list layout_list[] = {
  113. {FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
  114. {FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
  115. {FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
  116. {FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout},
  117. {FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout},
  118. {FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout},
  119. {FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout},
  120. {FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
  121. {FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
  122. {FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
  123. };
  124. /* If we can't determine the layout, use this */
  125. static struct mem_layout default_layout[] = {
  126. {0x20000000, 0x10000000, MEBIBYTE(128)},
  127. };
  128. /**
  129. * register_non_ram - register low memory not available for RAM usage
  130. */
  131. static __init void register_non_ram(void)
  132. {
  133. int i;
  134. for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
  135. add_memory_region(low_mem_reserved[i].start,
  136. low_mem_reserved[i].size, BOOT_MEM_RESERVED);
  137. }
  138. /**
  139. * get_memsize - get the size of memory as a single bank
  140. */
  141. static phys_addr_t get_memsize(void)
  142. {
  143. static char cmdline[COMMAND_LINE_SIZE] __initdata;
  144. phys_addr_t memsize = 0;
  145. char *memsize_str;
  146. char *ptr;
  147. /* Check the command line first for a memsize directive */
  148. strcpy(cmdline, arcs_cmdline);
  149. ptr = strstr(cmdline, "memsize=");
  150. if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
  151. ptr = strstr(ptr, " memsize=");
  152. if (ptr) {
  153. memsize = memparse(ptr + 8, &ptr);
  154. } else {
  155. /* otherwise look in the environment */
  156. memsize_str = prom_getenv("memsize");
  157. if (memsize_str != NULL) {
  158. pr_info("prom memsize = %s\n", memsize_str);
  159. memsize = simple_strtol(memsize_str, NULL, 0);
  160. }
  161. if (memsize == 0) {
  162. if (_prom_memsize != 0) {
  163. memsize = _prom_memsize;
  164. pr_info("_prom_memsize = 0x%x\n", memsize);
  165. /* add in memory that the bootloader doesn't
  166. * report */
  167. memsize += BLDR_SIZE;
  168. } else {
  169. memsize = DEFAULT_MEMSIZE;
  170. pr_info("Memsize not passed by bootloader, "
  171. "defaulting to 0x%x\n", memsize);
  172. }
  173. }
  174. }
  175. return memsize;
  176. }
  177. /**
  178. * register_low_ram - register an aliased section of RAM
  179. * @p: Alias address of memory
  180. * @n: Number of bytes in this section of memory
  181. *
  182. * Returns the number of bytes registered
  183. *
  184. */
  185. static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
  186. {
  187. phys_addr_t s;
  188. int i;
  189. phys_addr_t orig_n;
  190. orig_n = n;
  191. BUG_ON(p + n > RV_PHYS);
  192. for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
  193. phys_addr_t start;
  194. phys_addr_t size;
  195. start = low_mem_reserved[i].start;
  196. size = low_mem_reserved[i].size;
  197. /* Handle memory before this low memory section */
  198. if (p < start) {
  199. phys_addr_t s;
  200. s = min(n, start - p);
  201. add_memory_region(p, s, BOOT_MEM_RAM);
  202. p += s;
  203. n -= s;
  204. }
  205. /* Handle the low memory section itself. If it's aliased,
  206. * we reduce the number of byes left, but if not, the RAM
  207. * is available elsewhere and we don't reduce the number of
  208. * bytes remaining. */
  209. if (p == start) {
  210. if (low_mem_reserved[i].is_aliased) {
  211. s = min(n, size);
  212. n -= s;
  213. p += s;
  214. } else
  215. p += n;
  216. }
  217. }
  218. return orig_n - n;
  219. }
  220. /*
  221. * register_ram - register real RAM
  222. * @p: Address of memory as seen by devices
  223. * @alias: If the memory is seen at an additional address by the processor,
  224. * this will be the address, otherwise it is the same as @p.
  225. * @n: Number of bytes in this section of memory
  226. */
  227. static __init void register_ram(phys_addr_t p, phys_addr_t alias,
  228. phys_addr_t n)
  229. {
  230. /*
  231. * If some or all of this memory has an alias, break it into the
  232. * aliased and non-aliased portion.
  233. */
  234. if (p != alias) {
  235. phys_addr_t alias_size;
  236. phys_addr_t registered;
  237. alias_size = min(n, LOW_RAM_END - alias);
  238. registered = register_low_ram(alias, alias_size);
  239. ioremap_add_map(alias, p, n);
  240. n -= registered;
  241. p += registered;
  242. }
  243. #ifdef CONFIG_HIGHMEM
  244. if (n != 0) {
  245. add_memory_region(p, n, BOOT_MEM_RAM);
  246. ioremap_add_map(p, p, n);
  247. }
  248. #endif
  249. }
  250. /**
  251. * register_address_space - register things in the address space
  252. * @memsize: Number of bytes of RAM installed
  253. *
  254. * Takes the given number of bytes of RAM and registers as many of the regions,
  255. * or partial regions, as it can. So, the default configuration might have
  256. * two regions with 256 MiB each. If the memsize passed in on the command line
  257. * is 384 MiB, it will register the first region with 256 MiB and the second
  258. * with 128 MiB.
  259. */
  260. static __init void register_address_space(phys_addr_t memsize)
  261. {
  262. int i;
  263. phys_addr_t size;
  264. size_t n;
  265. struct mem_layout *layout;
  266. enum family_type family;
  267. /*
  268. * Register all of the things that aren't available to the kernel as
  269. * memory.
  270. */
  271. register_non_ram();
  272. /* Find the appropriate memory description */
  273. family = platform_get_family();
  274. for (i = 0; i < ARRAY_SIZE(layout_list); i++) {
  275. if (layout_list[i].family == family)
  276. break;
  277. }
  278. if (i == ARRAY_SIZE(layout_list)) {
  279. n = ARRAY_SIZE(default_layout);
  280. layout = default_layout;
  281. } else {
  282. n = layout_list[i].n;
  283. layout = layout_list[i].layout;
  284. }
  285. for (i = 0; memsize != 0 && i < n; i++) {
  286. size = min(memsize, layout[i].size);
  287. register_ram(layout[i].phys, layout[i].alias, size);
  288. memsize -= size;
  289. }
  290. }
  291. void __init prom_meminit(void)
  292. {
  293. ptv_memsize = get_memsize();
  294. register_address_space(ptv_memsize);
  295. }
  296. void __init prom_free_prom_memory(void)
  297. {
  298. unsigned long addr;
  299. int i;
  300. for (i = 0; i < boot_mem_map.nr_map; i++) {
  301. if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
  302. continue;
  303. addr = boot_mem_map.map[i].addr;
  304. free_init_pages("prom memory",
  305. addr, addr + boot_mem_map.map[i].size);
  306. }
  307. }