Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
49bffbdc SH |
2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
1da177e4 LT |
5 | * |
6 | * PROM library functions for acquiring/using memory descriptors given to | |
7 | * us from the YAMON. | |
49bffbdc SH |
8 | * |
9 | * Copyright (C) 1999,2000,2012 MIPS Technologies, Inc. | |
10 | * All rights reserved. | |
11 | * Authors: Carsten Langgaard <carstenl@mips.com> | |
12 | * Steven J. Hill <sjhill@mips.com> | |
1da177e4 | 13 | */ |
1da177e4 | 14 | #include <linux/init.h> |
1da177e4 | 15 | #include <linux/bootmem.h> |
e01402b1 | 16 | #include <linux/string.h> |
1da177e4 LT |
17 | |
18 | #include <asm/bootinfo.h> | |
3a551e25 | 19 | #include <asm/maar.h> |
9c1f1257 | 20 | #include <asm/sections.h> |
b431f09d | 21 | #include <asm/fw/fw.h> |
1da177e4 | 22 | |
b431f09d | 23 | static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS]; |
1da177e4 | 24 | |
70342287 | 25 | /* determined physical memory size, not overridden by command line args */ |
e1a4e469 RB |
26 | unsigned long physical_memsize = 0L; |
27 | ||
e6ca4e5b | 28 | fw_memblock_t * __init fw_getmdesc(int eva) |
1da177e4 | 29 | { |
acd8bc1a | 30 | char *memsize_str, *ememsize_str = NULL, *ptr; |
f8647b50 | 31 | unsigned long memsize = 0, ememsize = 0; |
7580c9c3 | 32 | static char cmdline[COMMAND_LINE_SIZE] __initdata; |
49bffbdc | 33 | int tmp; |
1da177e4 | 34 | |
e1a4e469 | 35 | /* otherwise look in the environment */ |
e6ca4e5b | 36 | |
b431f09d | 37 | memsize_str = fw_getenv("memsize"); |
e6ca4e5b MC |
38 | if (memsize_str) |
39 | tmp = kstrtol(memsize_str, 0, &memsize); | |
40 | if (eva) { | |
41 | /* Look for ememsize for EVA */ | |
42 | ememsize_str = fw_getenv("ememsize"); | |
43 | if (ememsize_str) | |
44 | tmp = kstrtol(ememsize_str, 0, &ememsize); | |
45 | } | |
46 | if (!memsize && !ememsize) { | |
49bffbdc | 47 | pr_warn("memsize not set in YAMON, set to default (32Mb)\n"); |
e1a4e469 RB |
48 | physical_memsize = 0x02000000; |
49 | } else { | |
e6ca4e5b MC |
50 | /* If ememsize is set, then set physical_memsize to that */ |
51 | physical_memsize = ememsize ? : memsize; | |
1da177e4 | 52 | } |
73499682 EO |
53 | |
54 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
e1a4e469 RB |
55 | /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last |
56 | word of physical memory */ | |
57 | physical_memsize -= PAGE_SIZE; | |
73499682 EO |
58 | #endif |
59 | ||
e1a4e469 RB |
60 | /* Check the command line for a memsize directive that overrides |
61 | the physical/default amount */ | |
62 | strcpy(cmdline, arcs_cmdline); | |
63 | ptr = strstr(cmdline, "memsize="); | |
64 | if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) | |
65 | ptr = strstr(ptr, " memsize="); | |
e6ca4e5b MC |
66 | /* And now look for ememsize */ |
67 | if (eva) { | |
68 | ptr = strstr(cmdline, "ememsize="); | |
69 | if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) | |
70 | ptr = strstr(ptr, " ememsize="); | |
71 | } | |
e1a4e469 RB |
72 | |
73 | if (ptr) | |
e6ca4e5b | 74 | memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr); |
e1a4e469 RB |
75 | else |
76 | memsize = physical_memsize; | |
77 | ||
e6ca4e5b MC |
78 | /* Last 64K for HIGHMEM arithmetics */ |
79 | if (memsize > 0x7fff0000) | |
80 | memsize = 0x7fff0000; | |
81 | ||
1da177e4 LT |
82 | memset(mdesc, 0, sizeof(mdesc)); |
83 | ||
b431f09d | 84 | mdesc[0].type = fw_dontuse; |
3bdd8e6e | 85 | mdesc[0].base = PHYS_OFFSET; |
1da177e4 LT |
86 | mdesc[0].size = 0x00001000; |
87 | ||
b431f09d | 88 | mdesc[1].type = fw_code; |
3bdd8e6e | 89 | mdesc[1].base = mdesc[0].base + 0x00001000UL; |
1da177e4 LT |
90 | mdesc[1].size = 0x000ef000; |
91 | ||
1da177e4 LT |
92 | /* |
93 | * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the | |
94 | * south bridge and PCI access always forwarded to the ISA Bus and | |
95 | * BIOSCS# is always generated. | |
96 | * This mean that this area can't be used as DMA memory for PCI | |
97 | * devices. | |
98 | */ | |
b431f09d | 99 | mdesc[2].type = fw_dontuse; |
3bdd8e6e | 100 | mdesc[2].base = mdesc[0].base + 0x000f0000UL; |
1da177e4 | 101 | mdesc[2].size = 0x00010000; |
1da177e4 | 102 | |
b431f09d | 103 | mdesc[3].type = fw_dontuse; |
3bdd8e6e | 104 | mdesc[3].base = mdesc[0].base + 0x00100000UL; |
49bffbdc | 105 | mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - |
3bdd8e6e | 106 | 0x00100000UL; |
1da177e4 | 107 | |
b431f09d | 108 | mdesc[4].type = fw_free; |
3bdd8e6e MC |
109 | mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end)); |
110 | mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base); | |
1da177e4 LT |
111 | |
112 | return &mdesc[0]; | |
113 | } | |
114 | ||
d1965c06 MC |
115 | static void free_init_pages_eva_malta(void *begin, void *end) |
116 | { | |
117 | free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin), | |
118 | __pa_symbol((unsigned long *)end)); | |
119 | } | |
120 | ||
b431f09d | 121 | static int __init fw_memtype_classify(unsigned int type) |
1da177e4 LT |
122 | { |
123 | switch (type) { | |
b431f09d | 124 | case fw_free: |
1da177e4 | 125 | return BOOT_MEM_RAM; |
b431f09d | 126 | case fw_code: |
1da177e4 LT |
127 | return BOOT_MEM_ROM_DATA; |
128 | default: | |
129 | return BOOT_MEM_RESERVED; | |
130 | } | |
131 | } | |
132 | ||
b431f09d | 133 | void __init fw_meminit(void) |
1da177e4 | 134 | { |
b431f09d | 135 | fw_memblock_t *p; |
1da177e4 | 136 | |
e6ca4e5b | 137 | p = fw_getmdesc(config_enabled(CONFIG_EVA)); |
d1965c06 MC |
138 | free_init_pages_eva = (config_enabled(CONFIG_EVA) ? |
139 | free_init_pages_eva_malta : NULL); | |
1da177e4 LT |
140 | |
141 | while (p->size) { | |
142 | long type; | |
143 | unsigned long base, size; | |
144 | ||
b431f09d | 145 | type = fw_memtype_classify(p->type); |
1da177e4 LT |
146 | base = p->base; |
147 | size = p->size; | |
148 | ||
149 | add_memory_region(base, size, type); | |
70342287 | 150 | p++; |
1da177e4 LT |
151 | } |
152 | } | |
153 | ||
c44e8d5e | 154 | void __init prom_free_prom_memory(void) |
1da177e4 | 155 | { |
1da177e4 LT |
156 | unsigned long addr; |
157 | int i; | |
158 | ||
159 | for (i = 0; i < boot_mem_map.nr_map; i++) { | |
160 | if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) | |
161 | continue; | |
162 | ||
c44e8d5e | 163 | addr = boot_mem_map.map[i].addr; |
49bffbdc | 164 | free_init_pages("YAMON memory", |
c44e8d5e | 165 | addr, addr + boot_mem_map.map[i].size); |
1da177e4 | 166 | } |
1da177e4 | 167 | } |
3a551e25 PB |
168 | |
169 | unsigned platform_maar_init(unsigned num_pairs) | |
170 | { | |
171 | phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1; | |
172 | struct maar_config cfg[] = { | |
173 | /* DRAM preceding I/O */ | |
174 | { 0x00000000, 0x0fffffff, MIPS_MAAR_S }, | |
175 | ||
176 | /* DRAM following I/O */ | |
177 | { 0x20000000, mem_end, MIPS_MAAR_S }, | |
178 | ||
179 | /* DRAM alias in upper half of physical */ | |
180 | { 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S }, | |
181 | }; | |
182 | unsigned i, num_cfg = ARRAY_SIZE(cfg); | |
183 | ||
184 | /* If DRAM fits before I/O, drop the region following it */ | |
185 | if (physical_memsize <= 0x10000000) { | |
186 | num_cfg--; | |
187 | for (i = 1; i < num_cfg; i++) | |
188 | cfg[i] = cfg[i + 1]; | |
189 | } | |
190 | ||
191 | return maar_config(cfg, num_cfg, num_pairs); | |
192 | } |