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 memmory", 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 cmdline[CL_SIZE], *ptr; 58 59 /* otherwise look in the environment */ 60 memsize_str = prom_getenv("memsize"); 61 if (!memsize_str) { 62 printk(KERN_WARNING 63 "memsize not set in boot prom, set to default (32Mb)\n"); 64 physical_memsize = 0x02000000; 65 } else { 66 #ifdef DEBUG 67 pr_debug("prom_memsize = %s\n", memsize_str); 68 #endif 69 physical_memsize = simple_strtol(memsize_str, NULL, 0); 70 } 71 72 #ifdef CONFIG_CPU_BIG_ENDIAN 73 /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last 74 word of physical memory */ 75 physical_memsize -= PAGE_SIZE; 76 #endif 77 78 /* Check the command line for a memsize directive that overrides 79 the physical/default amount */ 80 strcpy(cmdline, arcs_cmdline); 81 ptr = strstr(cmdline, "memsize="); 82 if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) 83 ptr = strstr(ptr, " memsize="); 84 85 if (ptr) 86 memsize = memparse(ptr + 8, &ptr); 87 else 88 memsize = physical_memsize; 89 90 memset(mdesc, 0, sizeof(mdesc)); 91 92 mdesc[0].type = yamon_dontuse; 93 mdesc[0].base = 0x00000000; 94 mdesc[0].size = 0x00001000; 95 96 mdesc[1].type = yamon_prom; 97 mdesc[1].base = 0x00001000; 98 mdesc[1].size = 0x000ef000; 99 100 /* 101 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the 102 * south bridge and PCI access always forwarded to the ISA Bus and 103 * BIOSCS# is always generated. 104 * This mean that this area can't be used as DMA memory for PCI 105 * devices. 106 */ 107 mdesc[2].type = yamon_dontuse; 108 mdesc[2].base = 0x000f0000; 109 mdesc[2].size = 0x00010000; 110 111 mdesc[3].type = yamon_dontuse; 112 mdesc[3].base = 0x00100000; 113 mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base; 114 115 mdesc[4].type = yamon_free; 116 mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); 117 mdesc[4].size = memsize - mdesc[4].base; 118 119 return &mdesc[0]; 120 } 121 122 static int __init prom_memtype_classify(unsigned int type) 123 { 124 switch (type) { 125 case yamon_free: 126 return BOOT_MEM_RAM; 127 case yamon_prom: 128 return BOOT_MEM_ROM_DATA; 129 default: 130 return BOOT_MEM_RESERVED; 131 } 132 } 133 134 void __init prom_meminit(void) 135 { 136 struct prom_pmemblock *p; 137 138 #ifdef DEBUG 139 pr_debug("YAMON MEMORY DESCRIPTOR dump:\n"); 140 p = prom_getmdesc(); 141 while (p->size) { 142 int i = 0; 143 pr_debug("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", 144 i, p, p->base, p->size, mtypes[p->type]); 145 p++; 146 i++; 147 } 148 #endif 149 p = prom_getmdesc(); 150 151 while (p->size) { 152 long type; 153 unsigned long base, size; 154 155 type = prom_memtype_classify(p->type); 156 base = p->base; 157 size = p->size; 158 159 add_memory_region(base, size, type); 160 p++; 161 } 162 } 163 164 void __init prom_free_prom_memory(void) 165 { 166 unsigned long addr; 167 int i; 168 169 for (i = 0; i < boot_mem_map.nr_map; i++) { 170 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) 171 continue; 172 173 addr = boot_mem_map.map[i].addr; 174 free_init_pages("prom memory", 175 addr, addr + boot_mem_map.map[i].size); 176 } 177 } 178