.. | .. |
---|
17 | 17 | #include <linux/types.h> |
---|
18 | 18 | #include <linux/sched.h> |
---|
19 | 19 | #include <linux/mm.h> |
---|
20 | | -#include <linux/bootmem.h> |
---|
| 20 | +#include <linux/memblock.h> |
---|
21 | 21 | #include <linux/swap.h> |
---|
22 | 22 | |
---|
23 | 23 | #include <asm/sgialib.h> |
---|
24 | 24 | #include <asm/page.h> |
---|
25 | | -#include <asm/pgtable.h> |
---|
26 | 25 | #include <asm/bootinfo.h> |
---|
27 | 26 | |
---|
28 | 27 | #undef DEBUG |
---|
| 28 | + |
---|
| 29 | +#define MAX_PROM_MEM 5 |
---|
| 30 | +static phys_addr_t prom_mem_base[MAX_PROM_MEM] __initdata; |
---|
| 31 | +static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata; |
---|
| 32 | +static unsigned int nr_prom_mem __initdata; |
---|
29 | 33 | |
---|
30 | 34 | /* |
---|
31 | 35 | * For ARC firmware memory functions the unit of meassuring memory is always |
---|
.. | .. |
---|
64 | 68 | : arc_mtypes[a.arc] |
---|
65 | 69 | #endif |
---|
66 | 70 | |
---|
| 71 | +enum { |
---|
| 72 | + mem_free, mem_prom_used, mem_reserved |
---|
| 73 | +}; |
---|
| 74 | + |
---|
67 | 75 | static inline int memtype_classify_arcs(union linux_memtypes type) |
---|
68 | 76 | { |
---|
69 | 77 | switch (type.arcs) { |
---|
70 | 78 | case arcs_fcontig: |
---|
71 | 79 | case arcs_free: |
---|
72 | | - return BOOT_MEM_RAM; |
---|
| 80 | + return mem_free; |
---|
73 | 81 | case arcs_atmp: |
---|
74 | | - return BOOT_MEM_ROM_DATA; |
---|
| 82 | + return mem_prom_used; |
---|
75 | 83 | case arcs_eblock: |
---|
76 | 84 | case arcs_rvpage: |
---|
77 | 85 | case arcs_bmem: |
---|
78 | 86 | case arcs_prog: |
---|
79 | 87 | case arcs_aperm: |
---|
80 | | - return BOOT_MEM_RESERVED; |
---|
| 88 | + return mem_reserved; |
---|
81 | 89 | default: |
---|
82 | 90 | BUG(); |
---|
83 | 91 | } |
---|
.. | .. |
---|
89 | 97 | switch (type.arc) { |
---|
90 | 98 | case arc_free: |
---|
91 | 99 | case arc_fcontig: |
---|
92 | | - return BOOT_MEM_RAM; |
---|
| 100 | + return mem_free; |
---|
93 | 101 | case arc_atmp: |
---|
94 | | - return BOOT_MEM_ROM_DATA; |
---|
| 102 | + return mem_prom_used; |
---|
95 | 103 | case arc_eblock: |
---|
96 | 104 | case arc_rvpage: |
---|
97 | 105 | case arc_bmem: |
---|
98 | 106 | case arc_prog: |
---|
99 | 107 | case arc_aperm: |
---|
100 | | - return BOOT_MEM_RESERVED; |
---|
| 108 | + return mem_reserved; |
---|
101 | 109 | default: |
---|
102 | 110 | BUG(); |
---|
103 | 111 | } |
---|
.. | .. |
---|
112 | 120 | return memtype_classify_arc(type); |
---|
113 | 121 | } |
---|
114 | 122 | |
---|
115 | | -void __init prom_meminit(void) |
---|
| 123 | +void __weak __init prom_meminit(void) |
---|
116 | 124 | { |
---|
117 | 125 | struct linux_mdesc *p; |
---|
118 | 126 | |
---|
.. | .. |
---|
129 | 137 | } |
---|
130 | 138 | #endif |
---|
131 | 139 | |
---|
| 140 | + nr_prom_mem = 0; |
---|
132 | 141 | p = PROM_NULL_MDESC; |
---|
133 | 142 | while ((p = ArcGetMemoryDescriptor(p))) { |
---|
134 | 143 | unsigned long base, size; |
---|
.. | .. |
---|
138 | 147 | size = p->pages << ARC_PAGE_SHIFT; |
---|
139 | 148 | type = prom_memtype_classify(p->type); |
---|
140 | 149 | |
---|
141 | | - add_memory_region(base, size, type); |
---|
| 150 | + /* ignore mirrored RAM on IP28/IP30 */ |
---|
| 151 | + if (base < PHYS_OFFSET) |
---|
| 152 | + continue; |
---|
| 153 | + |
---|
| 154 | + memblock_add(base, size); |
---|
| 155 | + |
---|
| 156 | + if (type == mem_reserved) |
---|
| 157 | + memblock_reserve(base, size); |
---|
| 158 | + |
---|
| 159 | + if (type == mem_prom_used) { |
---|
| 160 | + memblock_reserve(base, size); |
---|
| 161 | + if (nr_prom_mem >= 5) { |
---|
| 162 | + pr_err("Too many ROM DATA regions"); |
---|
| 163 | + continue; |
---|
| 164 | + } |
---|
| 165 | + prom_mem_base[nr_prom_mem] = base; |
---|
| 166 | + prom_mem_size[nr_prom_mem] = size; |
---|
| 167 | + nr_prom_mem++; |
---|
| 168 | + } |
---|
142 | 169 | } |
---|
143 | 170 | } |
---|
144 | 171 | |
---|
145 | | -void __init prom_free_prom_memory(void) |
---|
| 172 | +void __weak __init prom_cleanup(void) |
---|
146 | 173 | { |
---|
147 | | - unsigned long addr; |
---|
| 174 | +} |
---|
| 175 | + |
---|
| 176 | +void __weak __init prom_free_prom_memory(void) |
---|
| 177 | +{ |
---|
148 | 178 | int i; |
---|
149 | 179 | |
---|
150 | 180 | if (prom_flags & PROM_FLAG_DONT_FREE_TEMP) |
---|
151 | 181 | return; |
---|
152 | 182 | |
---|
153 | | - for (i = 0; i < boot_mem_map.nr_map; i++) { |
---|
154 | | - if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) |
---|
155 | | - continue; |
---|
156 | | - |
---|
157 | | - addr = boot_mem_map.map[i].addr; |
---|
| 183 | + for (i = 0; i < nr_prom_mem; i++) { |
---|
158 | 184 | free_init_pages("prom memory", |
---|
159 | | - addr, addr + boot_mem_map.map[i].size); |
---|
| 185 | + prom_mem_base[i], prom_mem_base[i] + prom_mem_size[i]); |
---|
160 | 186 | } |
---|
| 187 | + /* |
---|
| 188 | + * at this point it isn't safe to call PROM functions |
---|
| 189 | + * give platforms a way to do PROM cleanups |
---|
| 190 | + */ |
---|
| 191 | + prom_cleanup(); |
---|
161 | 192 | } |
---|