1 /* 2 * Carsten Langgaard, carstenl@mips.com 3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. 4 * 5 * This program is free software; you can distribute it and/or modify it 6 * under the terms of the GNU General Public License (Version 2) as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 17 * 18 * PROM library functions for acquiring/using memory descriptors given to 19 * us from the YAMON. 20 */ 21 #include <linux/init.h> 22 #include <linux/mm.h> 23 #include <linux/bootmem.h> 24 #include <linux/pfn.h> 25 #include <linux/string.h> 26 27 #include <asm/bootinfo.h> 28 #include <asm/page.h> 29 #include <asm/sections.h> 30 31 #include <asm/mips-boards/prom.h> 32 33 /*#define DEBUG*/ 34 35 enum yamon_memtypes { 36 yamon_dontuse, 37 yamon_prom, 38 yamon_free, 39 }; 40 static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; 41 42 #ifdef DEBUG 43 static char *mtypes[3] = { 44 "Dont use memory", 45 "YAMON PROM memory", 46 "Free memory", 47 }; 48 #endif 49 50 /* determined physical memory size, not overridden by command line args */ 51 unsigned long physical_memsize = 0L; 52 53 static struct prom_pmemblock * __init prom_getmdesc(void) 54 { 55 char *memsize_str; 56 unsigned int memsize; 57 char *ptr; 58 static char cmdline[COMMAND_LINE_SIZE] __initdata; 59 60 /* otherwise look in the environment */ 61 memsize_str = prom_getenv("memsize"); 62 if (!memsize_str) { 63 printk(KERN_WARNING 64 "memsize not set in boot prom, set to default (32Mb)\n"); 65 physical_memsize = 0x02000000; 66 } else { 67 #ifdef DEBUG 68 pr_debug("prom_memsize = %s\n", memsize_str); 69 #endif 70 physical_memsize = simple_strtol(memsize_str, NULL, 0); 71 } 72 73 #ifdef CONFIG_CPU_BIG_ENDIAN 74 /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last 75 word of physical memory */ 76 physical_memsize -= PAGE_SIZE; 77 #endif 78 79 /* Check the command line for a memsize directive that overrides 80 the physical/default amount */ 81 strcpy(cmdline, arcs_cmdline); 82 ptr = strstr(cmdline, "memsize="); 83 if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) 84 ptr = strstr(ptr, " memsize="); 85 86 if (ptr) 87 memsize = memparse(ptr + 8, &ptr); 88 else 89 memsize = physical_memsize; 90 91 memset(mdesc, 0, sizeof(mdesc)); 92 93 mdesc[0].type = yamon_dontuse; 94 mdesc[0].base = 0x00000000; 95 mdesc[0].size = 0x00001000; 96 97 mdesc[1].type = yamon_prom; 98 mdesc[1].base = 0x00001000; 99 mdesc[1].size = 0x000ef000; 100 101 /* 102 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the 103 * south bridge and PCI access always forwarded to the ISA Bus and 104 * BIOSCS# is always generated. 105 * This mean that this area can't be used as DMA memory for PCI 106 * devices. 107 */ 108 mdesc[2].type = yamon_dontuse; 109 mdesc[2].base = 0x000f0000; 110 mdesc[2].size = 0x00010000; 111 112 mdesc[3].type = yamon_dontuse; 113 mdesc[3].base = 0x00100000; 114 mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base; 115 116 mdesc[4].type = yamon_free; 117 mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); 118 mdesc[4].size = memsize - mdesc[4].base; 119 120 return &mdesc[0]; 121 } 122 123 static int __init prom_memtype_classify(unsigned int type) 124 { 125 switch (type) { 126 case yamon_free: 127 return BOOT_MEM_RAM; 128 case yamon_prom: 129 return BOOT_MEM_ROM_DATA; 130 default: 131 return BOOT_MEM_RESERVED; 132 } 133 } 134 135 void __init prom_meminit(void) 136 { 137 struct prom_pmemblock *p; 138 139 #ifdef DEBUG 140 pr_debug("YAMON MEMORY DESCRIPTOR dump:\n"); 141 p = prom_getmdesc(); 142 while (p->size) { 143 int i = 0; 144 pr_debug("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", 145 i, p, p->base, p->size, mtypes[p->type]); 146 p++; 147 i++; 148 } 149 #endif 150 p = prom_getmdesc(); 151 152 while (p->size) { 153 long type; 154 unsigned long base, size; 155 156 type = prom_memtype_classify(p->type); 157 base = p->base; 158 size = p->size; 159 160 add_memory_region(base, size, type); 161 p++; 162 } 163 } 164 165 void __init prom_free_prom_memory(void) 166 { 167 unsigned long addr; 168 int i; 169 170 for (i = 0; i < boot_mem_map.nr_map; i++) { 171 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) 172 continue; 173 174 addr = boot_mem_map.map[i].addr; 175 free_init_pages("prom memory", 176 addr, addr + boot_mem_map.map[i].size); 177 } 178 } 179