diff options
Diffstat (limited to 'arch/avr32')
-rw-r--r-- | arch/avr32/kernel/setup.c | 238 | ||||
-rw-r--r-- | arch/avr32/mm/init.c | 238 |
2 files changed, 238 insertions, 238 deletions
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index a1a7c3c3f522..53a1ff0cb05c 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c | |||
@@ -8,12 +8,14 @@ | |||
8 | 8 | ||
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/initrd.h> | ||
11 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
12 | #include <linux/console.h> | 13 | #include <linux/console.h> |
13 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
14 | #include <linux/bootmem.h> | 15 | #include <linux/bootmem.h> |
15 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/pfn.h> | ||
17 | #include <linux/root_dev.h> | 19 | #include <linux/root_dev.h> |
18 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
@@ -260,6 +262,242 @@ static void __init parse_tags(struct tag *t) | |||
260 | t->hdr.tag); | 262 | t->hdr.tag); |
261 | } | 263 | } |
262 | 264 | ||
265 | static void __init print_memory_map(const char *what, | ||
266 | struct tag_mem_range *mem) | ||
267 | { | ||
268 | printk ("%s:\n", what); | ||
269 | for (; mem; mem = mem->next) { | ||
270 | printk (" %08lx - %08lx\n", | ||
271 | (unsigned long)mem->addr, | ||
272 | (unsigned long)(mem->addr + mem->size)); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | #define MAX_LOWMEM HIGHMEM_START | ||
277 | #define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM) | ||
278 | |||
279 | /* | ||
280 | * Sort a list of memory regions in-place by ascending address. | ||
281 | * | ||
282 | * We're using bubble sort because we only have singly linked lists | ||
283 | * with few elements. | ||
284 | */ | ||
285 | static void __init sort_mem_list(struct tag_mem_range **pmem) | ||
286 | { | ||
287 | int done; | ||
288 | struct tag_mem_range **a, **b; | ||
289 | |||
290 | if (!*pmem) | ||
291 | return; | ||
292 | |||
293 | do { | ||
294 | done = 1; | ||
295 | a = pmem, b = &(*pmem)->next; | ||
296 | while (*b) { | ||
297 | if ((*a)->addr > (*b)->addr) { | ||
298 | struct tag_mem_range *tmp; | ||
299 | tmp = (*b)->next; | ||
300 | (*b)->next = *a; | ||
301 | *a = *b; | ||
302 | *b = tmp; | ||
303 | done = 0; | ||
304 | } | ||
305 | a = &(*a)->next; | ||
306 | b = &(*a)->next; | ||
307 | } | ||
308 | } while (!done); | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Find a free memory region large enough for storing the | ||
313 | * bootmem bitmap. | ||
314 | */ | ||
315 | static unsigned long __init | ||
316 | find_bootmap_pfn(const struct tag_mem_range *mem) | ||
317 | { | ||
318 | unsigned long bootmap_pages, bootmap_len; | ||
319 | unsigned long node_pages = PFN_UP(mem->size); | ||
320 | unsigned long bootmap_addr = mem->addr; | ||
321 | struct tag_mem_range *reserved = mem_reserved; | ||
322 | struct tag_mem_range *ramdisk = mem_ramdisk; | ||
323 | unsigned long kern_start = __pa(_stext); | ||
324 | unsigned long kern_end = __pa(_end); | ||
325 | |||
326 | bootmap_pages = bootmem_bootmap_pages(node_pages); | ||
327 | bootmap_len = bootmap_pages << PAGE_SHIFT; | ||
328 | |||
329 | /* | ||
330 | * Find a large enough region without reserved pages for | ||
331 | * storing the bootmem bitmap. We can take advantage of the | ||
332 | * fact that all lists have been sorted. | ||
333 | * | ||
334 | * We have to check explicitly reserved regions as well as the | ||
335 | * kernel image and any RAMDISK images... | ||
336 | * | ||
337 | * Oh, and we have to make sure we don't overwrite the taglist | ||
338 | * since we're going to use it until the bootmem allocator is | ||
339 | * fully up and running. | ||
340 | */ | ||
341 | while (1) { | ||
342 | if ((bootmap_addr < kern_end) && | ||
343 | ((bootmap_addr + bootmap_len) > kern_start)) | ||
344 | bootmap_addr = kern_end; | ||
345 | |||
346 | while (reserved && | ||
347 | (bootmap_addr >= (reserved->addr + reserved->size))) | ||
348 | reserved = reserved->next; | ||
349 | |||
350 | if (reserved && | ||
351 | ((bootmap_addr + bootmap_len) >= reserved->addr)) { | ||
352 | bootmap_addr = reserved->addr + reserved->size; | ||
353 | continue; | ||
354 | } | ||
355 | |||
356 | while (ramdisk && | ||
357 | (bootmap_addr >= (ramdisk->addr + ramdisk->size))) | ||
358 | ramdisk = ramdisk->next; | ||
359 | |||
360 | if (!ramdisk || | ||
361 | ((bootmap_addr + bootmap_len) < ramdisk->addr)) | ||
362 | break; | ||
363 | |||
364 | bootmap_addr = ramdisk->addr + ramdisk->size; | ||
365 | } | ||
366 | |||
367 | if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size)) | ||
368 | return ~0UL; | ||
369 | |||
370 | return PFN_UP(bootmap_addr); | ||
371 | } | ||
372 | |||
373 | static void __init setup_bootmem(void) | ||
374 | { | ||
375 | unsigned bootmap_size; | ||
376 | unsigned long first_pfn, bootmap_pfn, pages; | ||
377 | unsigned long max_pfn, max_low_pfn; | ||
378 | unsigned long kern_start = __pa(_stext); | ||
379 | unsigned long kern_end = __pa(_end); | ||
380 | unsigned node = 0; | ||
381 | struct tag_mem_range *bank, *res; | ||
382 | |||
383 | sort_mem_list(&mem_phys); | ||
384 | sort_mem_list(&mem_reserved); | ||
385 | |||
386 | print_memory_map("Physical memory", mem_phys); | ||
387 | print_memory_map("Reserved memory", mem_reserved); | ||
388 | |||
389 | nodes_clear(node_online_map); | ||
390 | |||
391 | if (mem_ramdisk) { | ||
392 | #ifdef CONFIG_BLK_DEV_INITRD | ||
393 | initrd_start = (unsigned long)__va(mem_ramdisk->addr); | ||
394 | initrd_end = initrd_start + mem_ramdisk->size; | ||
395 | |||
396 | print_memory_map("RAMDISK images", mem_ramdisk); | ||
397 | if (mem_ramdisk->next) | ||
398 | printk(KERN_WARNING | ||
399 | "Warning: Only the first RAMDISK image " | ||
400 | "will be used\n"); | ||
401 | sort_mem_list(&mem_ramdisk); | ||
402 | #else | ||
403 | printk(KERN_WARNING "RAM disk image present, but " | ||
404 | "no initrd support in kernel!\n"); | ||
405 | #endif | ||
406 | } | ||
407 | |||
408 | if (mem_phys->next) | ||
409 | printk(KERN_WARNING "Only using first memory bank\n"); | ||
410 | |||
411 | for (bank = mem_phys; bank; bank = NULL) { | ||
412 | first_pfn = PFN_UP(bank->addr); | ||
413 | max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size); | ||
414 | bootmap_pfn = find_bootmap_pfn(bank); | ||
415 | if (bootmap_pfn > max_pfn) | ||
416 | panic("No space for bootmem bitmap!\n"); | ||
417 | |||
418 | if (max_low_pfn > MAX_LOWMEM_PFN) { | ||
419 | max_low_pfn = MAX_LOWMEM_PFN; | ||
420 | #ifndef CONFIG_HIGHMEM | ||
421 | /* | ||
422 | * Lowmem is memory that can be addressed | ||
423 | * directly through P1/P2 | ||
424 | */ | ||
425 | printk(KERN_WARNING | ||
426 | "Node %u: Only %ld MiB of memory will be used.\n", | ||
427 | node, MAX_LOWMEM >> 20); | ||
428 | printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); | ||
429 | #else | ||
430 | #error HIGHMEM is not supported by AVR32 yet | ||
431 | #endif | ||
432 | } | ||
433 | |||
434 | /* Initialize the boot-time allocator with low memory only. */ | ||
435 | bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn, | ||
436 | first_pfn, max_low_pfn); | ||
437 | |||
438 | printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n", | ||
439 | node, NODE_DATA(node)->bdata, | ||
440 | NODE_DATA(node)->bdata->node_bootmem_map); | ||
441 | |||
442 | /* | ||
443 | * Register fully available RAM pages with the bootmem | ||
444 | * allocator. | ||
445 | */ | ||
446 | pages = max_low_pfn - first_pfn; | ||
447 | free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn), | ||
448 | PFN_PHYS(pages)); | ||
449 | |||
450 | /* | ||
451 | * Reserve space for the kernel image (if present in | ||
452 | * this node)... | ||
453 | */ | ||
454 | if ((kern_start >= PFN_PHYS(first_pfn)) && | ||
455 | (kern_start < PFN_PHYS(max_pfn))) { | ||
456 | printk("Node %u: Kernel image %08lx - %08lx\n", | ||
457 | node, kern_start, kern_end); | ||
458 | reserve_bootmem_node(NODE_DATA(node), kern_start, | ||
459 | kern_end - kern_start); | ||
460 | } | ||
461 | |||
462 | /* ...the bootmem bitmap... */ | ||
463 | reserve_bootmem_node(NODE_DATA(node), | ||
464 | PFN_PHYS(bootmap_pfn), | ||
465 | bootmap_size); | ||
466 | |||
467 | /* ...any RAMDISK images... */ | ||
468 | for (res = mem_ramdisk; res; res = res->next) { | ||
469 | if (res->addr > PFN_PHYS(max_pfn)) | ||
470 | break; | ||
471 | |||
472 | if (res->addr >= PFN_PHYS(first_pfn)) { | ||
473 | printk("Node %u: RAMDISK %08lx - %08lx\n", | ||
474 | node, | ||
475 | (unsigned long)res->addr, | ||
476 | (unsigned long)(res->addr + res->size)); | ||
477 | reserve_bootmem_node(NODE_DATA(node), | ||
478 | res->addr, res->size); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | /* ...and any other reserved regions. */ | ||
483 | for (res = mem_reserved; res; res = res->next) { | ||
484 | if (res->addr > PFN_PHYS(max_pfn)) | ||
485 | break; | ||
486 | |||
487 | if (res->addr >= PFN_PHYS(first_pfn)) { | ||
488 | printk("Node %u: Reserved %08lx - %08lx\n", | ||
489 | node, | ||
490 | (unsigned long)res->addr, | ||
491 | (unsigned long)(res->addr + res->size)); | ||
492 | reserve_bootmem_node(NODE_DATA(node), | ||
493 | res->addr, res->size); | ||
494 | } | ||
495 | } | ||
496 | |||
497 | node_set_online(node); | ||
498 | } | ||
499 | } | ||
500 | |||
263 | void __init setup_arch (char **cmdline_p) | 501 | void __init setup_arch (char **cmdline_p) |
264 | { | 502 | { |
265 | struct clk *cpu_clk; | 503 | struct clk *cpu_clk; |
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c index 70da6894acc1..82cf70854b90 100644 --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c | |||
@@ -10,11 +10,9 @@ | |||
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/swap.h> | 11 | #include <linux/swap.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/initrd.h> | ||
14 | #include <linux/mmzone.h> | 13 | #include <linux/mmzone.h> |
15 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
16 | #include <linux/pagemap.h> | 15 | #include <linux/pagemap.h> |
17 | #include <linux/pfn.h> | ||
18 | #include <linux/nodemask.h> | 16 | #include <linux/nodemask.h> |
19 | 17 | ||
20 | #include <asm/page.h> | 18 | #include <asm/page.h> |
@@ -78,242 +76,6 @@ void show_mem(void) | |||
78 | printk ("%d pages swap cached\n", cached); | 76 | printk ("%d pages swap cached\n", cached); |
79 | } | 77 | } |
80 | 78 | ||
81 | static void __init print_memory_map(const char *what, | ||
82 | struct tag_mem_range *mem) | ||
83 | { | ||
84 | printk ("%s:\n", what); | ||
85 | for (; mem; mem = mem->next) { | ||
86 | printk (" %08lx - %08lx\n", | ||
87 | (unsigned long)mem->addr, | ||
88 | (unsigned long)(mem->addr + mem->size)); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #define MAX_LOWMEM HIGHMEM_START | ||
93 | #define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM) | ||
94 | |||
95 | /* | ||
96 | * Sort a list of memory regions in-place by ascending address. | ||
97 | * | ||
98 | * We're using bubble sort because we only have singly linked lists | ||
99 | * with few elements. | ||
100 | */ | ||
101 | static void __init sort_mem_list(struct tag_mem_range **pmem) | ||
102 | { | ||
103 | int done; | ||
104 | struct tag_mem_range **a, **b; | ||
105 | |||
106 | if (!*pmem) | ||
107 | return; | ||
108 | |||
109 | do { | ||
110 | done = 1; | ||
111 | a = pmem, b = &(*pmem)->next; | ||
112 | while (*b) { | ||
113 | if ((*a)->addr > (*b)->addr) { | ||
114 | struct tag_mem_range *tmp; | ||
115 | tmp = (*b)->next; | ||
116 | (*b)->next = *a; | ||
117 | *a = *b; | ||
118 | *b = tmp; | ||
119 | done = 0; | ||
120 | } | ||
121 | a = &(*a)->next; | ||
122 | b = &(*a)->next; | ||
123 | } | ||
124 | } while (!done); | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Find a free memory region large enough for storing the | ||
129 | * bootmem bitmap. | ||
130 | */ | ||
131 | static unsigned long __init | ||
132 | find_bootmap_pfn(const struct tag_mem_range *mem) | ||
133 | { | ||
134 | unsigned long bootmap_pages, bootmap_len; | ||
135 | unsigned long node_pages = PFN_UP(mem->size); | ||
136 | unsigned long bootmap_addr = mem->addr; | ||
137 | struct tag_mem_range *reserved = mem_reserved; | ||
138 | struct tag_mem_range *ramdisk = mem_ramdisk; | ||
139 | unsigned long kern_start = virt_to_phys(_stext); | ||
140 | unsigned long kern_end = virt_to_phys(_end); | ||
141 | |||
142 | bootmap_pages = bootmem_bootmap_pages(node_pages); | ||
143 | bootmap_len = bootmap_pages << PAGE_SHIFT; | ||
144 | |||
145 | /* | ||
146 | * Find a large enough region without reserved pages for | ||
147 | * storing the bootmem bitmap. We can take advantage of the | ||
148 | * fact that all lists have been sorted. | ||
149 | * | ||
150 | * We have to check explicitly reserved regions as well as the | ||
151 | * kernel image and any RAMDISK images... | ||
152 | * | ||
153 | * Oh, and we have to make sure we don't overwrite the taglist | ||
154 | * since we're going to use it until the bootmem allocator is | ||
155 | * fully up and running. | ||
156 | */ | ||
157 | while (1) { | ||
158 | if ((bootmap_addr < kern_end) && | ||
159 | ((bootmap_addr + bootmap_len) > kern_start)) | ||
160 | bootmap_addr = kern_end; | ||
161 | |||
162 | while (reserved && | ||
163 | (bootmap_addr >= (reserved->addr + reserved->size))) | ||
164 | reserved = reserved->next; | ||
165 | |||
166 | if (reserved && | ||
167 | ((bootmap_addr + bootmap_len) >= reserved->addr)) { | ||
168 | bootmap_addr = reserved->addr + reserved->size; | ||
169 | continue; | ||
170 | } | ||
171 | |||
172 | while (ramdisk && | ||
173 | (bootmap_addr >= (ramdisk->addr + ramdisk->size))) | ||
174 | ramdisk = ramdisk->next; | ||
175 | |||
176 | if (!ramdisk || | ||
177 | ((bootmap_addr + bootmap_len) < ramdisk->addr)) | ||
178 | break; | ||
179 | |||
180 | bootmap_addr = ramdisk->addr + ramdisk->size; | ||
181 | } | ||
182 | |||
183 | if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size)) | ||
184 | return ~0UL; | ||
185 | |||
186 | return PFN_UP(bootmap_addr); | ||
187 | } | ||
188 | |||
189 | void __init setup_bootmem(void) | ||
190 | { | ||
191 | unsigned bootmap_size; | ||
192 | unsigned long first_pfn, bootmap_pfn, pages; | ||
193 | unsigned long max_pfn, max_low_pfn; | ||
194 | unsigned long kern_start = virt_to_phys(_stext); | ||
195 | unsigned long kern_end = virt_to_phys(_end); | ||
196 | unsigned node = 0; | ||
197 | struct tag_mem_range *bank, *res; | ||
198 | |||
199 | sort_mem_list(&mem_phys); | ||
200 | sort_mem_list(&mem_reserved); | ||
201 | |||
202 | print_memory_map("Physical memory", mem_phys); | ||
203 | print_memory_map("Reserved memory", mem_reserved); | ||
204 | |||
205 | nodes_clear(node_online_map); | ||
206 | |||
207 | if (mem_ramdisk) { | ||
208 | #ifdef CONFIG_BLK_DEV_INITRD | ||
209 | initrd_start = (unsigned long)__va(mem_ramdisk->addr); | ||
210 | initrd_end = initrd_start + mem_ramdisk->size; | ||
211 | |||
212 | print_memory_map("RAMDISK images", mem_ramdisk); | ||
213 | if (mem_ramdisk->next) | ||
214 | printk(KERN_WARNING | ||
215 | "Warning: Only the first RAMDISK image " | ||
216 | "will be used\n"); | ||
217 | sort_mem_list(&mem_ramdisk); | ||
218 | #else | ||
219 | printk(KERN_WARNING "RAM disk image present, but " | ||
220 | "no initrd support in kernel!\n"); | ||
221 | #endif | ||
222 | } | ||
223 | |||
224 | if (mem_phys->next) | ||
225 | printk(KERN_WARNING "Only using first memory bank\n"); | ||
226 | |||
227 | for (bank = mem_phys; bank; bank = NULL) { | ||
228 | first_pfn = PFN_UP(bank->addr); | ||
229 | max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size); | ||
230 | bootmap_pfn = find_bootmap_pfn(bank); | ||
231 | if (bootmap_pfn > max_pfn) | ||
232 | panic("No space for bootmem bitmap!\n"); | ||
233 | |||
234 | if (max_low_pfn > MAX_LOWMEM_PFN) { | ||
235 | max_low_pfn = MAX_LOWMEM_PFN; | ||
236 | #ifndef CONFIG_HIGHMEM | ||
237 | /* | ||
238 | * Lowmem is memory that can be addressed | ||
239 | * directly through P1/P2 | ||
240 | */ | ||
241 | printk(KERN_WARNING | ||
242 | "Node %u: Only %ld MiB of memory will be used.\n", | ||
243 | node, MAX_LOWMEM >> 20); | ||
244 | printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); | ||
245 | #else | ||
246 | #error HIGHMEM is not supported by AVR32 yet | ||
247 | #endif | ||
248 | } | ||
249 | |||
250 | /* Initialize the boot-time allocator with low memory only. */ | ||
251 | bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn, | ||
252 | first_pfn, max_low_pfn); | ||
253 | |||
254 | printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n", | ||
255 | node, NODE_DATA(node)->bdata, | ||
256 | NODE_DATA(node)->bdata->node_bootmem_map); | ||
257 | |||
258 | /* | ||
259 | * Register fully available RAM pages with the bootmem | ||
260 | * allocator. | ||
261 | */ | ||
262 | pages = max_low_pfn - first_pfn; | ||
263 | free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn), | ||
264 | PFN_PHYS(pages)); | ||
265 | |||
266 | /* | ||
267 | * Reserve space for the kernel image (if present in | ||
268 | * this node)... | ||
269 | */ | ||
270 | if ((kern_start >= PFN_PHYS(first_pfn)) && | ||
271 | (kern_start < PFN_PHYS(max_pfn))) { | ||
272 | printk("Node %u: Kernel image %08lx - %08lx\n", | ||
273 | node, kern_start, kern_end); | ||
274 | reserve_bootmem_node(NODE_DATA(node), kern_start, | ||
275 | kern_end - kern_start); | ||
276 | } | ||
277 | |||
278 | /* ...the bootmem bitmap... */ | ||
279 | reserve_bootmem_node(NODE_DATA(node), | ||
280 | PFN_PHYS(bootmap_pfn), | ||
281 | bootmap_size); | ||
282 | |||
283 | /* ...any RAMDISK images... */ | ||
284 | for (res = mem_ramdisk; res; res = res->next) { | ||
285 | if (res->addr > PFN_PHYS(max_pfn)) | ||
286 | break; | ||
287 | |||
288 | if (res->addr >= PFN_PHYS(first_pfn)) { | ||
289 | printk("Node %u: RAMDISK %08lx - %08lx\n", | ||
290 | node, | ||
291 | (unsigned long)res->addr, | ||
292 | (unsigned long)(res->addr + res->size)); | ||
293 | reserve_bootmem_node(NODE_DATA(node), | ||
294 | res->addr, res->size); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* ...and any other reserved regions. */ | ||
299 | for (res = mem_reserved; res; res = res->next) { | ||
300 | if (res->addr > PFN_PHYS(max_pfn)) | ||
301 | break; | ||
302 | |||
303 | if (res->addr >= PFN_PHYS(first_pfn)) { | ||
304 | printk("Node %u: Reserved %08lx - %08lx\n", | ||
305 | node, | ||
306 | (unsigned long)res->addr, | ||
307 | (unsigned long)(res->addr + res->size)); | ||
308 | reserve_bootmem_node(NODE_DATA(node), | ||
309 | res->addr, res->size); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | node_set_online(node); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /* | 79 | /* |
318 | * paging_init() sets up the page tables | 80 | * paging_init() sets up the page tables |
319 | * | 81 | * |