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