Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * memory.c: memory initialisation code. | |
4 | * | |
5 | * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine | |
6 | * Copyright (C) 2000, 2002 Maciej W. Rozycki | |
7 | */ | |
1da177e4 LT |
8 | #include <linux/init.h> |
9 | #include <linux/kernel.h> | |
10 | #include <linux/mm.h> | |
57c8a661 | 11 | #include <linux/memblock.h> |
1da177e4 LT |
12 | #include <linux/types.h> |
13 | ||
14 | #include <asm/addrspace.h> | |
15 | #include <asm/bootinfo.h> | |
16 | #include <asm/dec/machtype.h> | |
17 | #include <asm/dec/prom.h> | |
18 | #include <asm/page.h> | |
19 | #include <asm/sections.h> | |
20 | ||
21 | ||
982f6ffe | 22 | volatile unsigned long mem_err; /* So we know an error occurred */ |
1da177e4 LT |
23 | |
24 | /* | |
25 | * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen | |
07217d75 | 26 | * off the end of real memory. Only suitable for the 2100/3100's (PMAX). |
1da177e4 LT |
27 | */ |
28 | ||
29 | #define CHUNK_SIZE 0x400000 | |
30 | ||
31 | static inline void pmax_setup_memory_region(void) | |
32 | { | |
33 | volatile unsigned char *memory_page, dummy; | |
34 | char old_handler[0x80]; | |
35 | extern char genexcept_early; | |
36 | ||
37 | /* Install exception handler */ | |
3bd4c902 MR |
38 | memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80); |
39 | memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80); | |
1da177e4 LT |
40 | |
41 | /* read unmapped and uncached (KSEG1) | |
42 | * DECstations have at least 4MB RAM | |
43 | * Assume less than 480MB of RAM, as this is max for 5000/2xx | |
44 | * FIXME this should be replaced by the first free page! | |
45 | */ | |
3bd4c902 MR |
46 | for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE; |
47 | mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000; | |
a3dddd56 | 48 | memory_page += CHUNK_SIZE) { |
1da177e4 LT |
49 | dummy = *memory_page; |
50 | } | |
3bd4c902 | 51 | memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80); |
1da177e4 | 52 | |
3bd4c902 | 53 | add_memory_region(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE, |
1da177e4 LT |
54 | BOOT_MEM_RAM); |
55 | } | |
56 | ||
57 | /* | |
58 | * Use the REX prom calls to get hold of the memory bitmap, and thence | |
59 | * determine memory size. | |
60 | */ | |
61 | static inline void rex_setup_memory_region(void) | |
62 | { | |
63 | int i, bitmap_size; | |
64 | unsigned long mem_start = 0, mem_size = 0; | |
65 | memmap *bm; | |
66 | ||
67 | /* some free 64k */ | |
3bd4c902 | 68 | bm = (memmap *)CKSEG0ADDR(0x28000); |
1da177e4 LT |
69 | |
70 | bitmap_size = rex_getbitmap(bm); | |
71 | ||
72 | for (i = 0; i < bitmap_size; i++) { | |
73 | /* FIXME: very simplistically only add full sets of pages */ | |
74 | if (bm->bitmap[i] == 0xff) | |
75 | mem_size += (8 * bm->pagesize); | |
76 | else if (!mem_size) | |
77 | mem_start += (8 * bm->pagesize); | |
78 | else { | |
79 | add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); | |
80 | mem_start += mem_size + (8 * bm->pagesize); | |
81 | mem_size = 0; | |
82 | } | |
83 | } | |
84 | if (mem_size) | |
85 | add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); | |
86 | } | |
87 | ||
88 | void __init prom_meminit(u32 magic) | |
89 | { | |
90 | if (!prom_is_rex(magic)) | |
91 | pmax_setup_memory_region(); | |
92 | else | |
93 | rex_setup_memory_region(); | |
94 | } | |
95 | ||
c44e8d5e | 96 | void __init prom_free_prom_memory(void) |
1da177e4 | 97 | { |
c44e8d5e | 98 | unsigned long end; |
1da177e4 LT |
99 | |
100 | /* | |
101 | * Free everything below the kernel itself but leave | |
102 | * the first page reserved for the exception handlers. | |
103 | */ | |
104 | ||
baf69e27 | 105 | #if IS_ENABLED(CONFIG_DECLANCE) |
1da177e4 LT |
106 | /* |
107 | * Leave 128 KB reserved for Lance memory for | |
108 | * IOASIC DECstations. | |
109 | * | |
110 | * XXX: save this address for use in dec_lance.c? | |
111 | */ | |
112 | if (IOASIC) | |
113 | end = __pa(&_text) - 0x00020000; | |
114 | else | |
115 | #endif | |
116 | end = __pa(&_text); | |
117 | ||
c44e8d5e | 118 | free_init_pages("unused PROM memory", PAGE_SIZE, end); |
1da177e4 | 119 | } |