| .. | .. |
|---|
| 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 | } |
|---|