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 35enum yamon_memtypes { 36 yamon_dontuse, 37 yamon_prom, 38 yamon_free, 39}; 40struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; 41 42#ifdef DEBUG 43static 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 */ 51unsigned long physical_memsize = 0L; 52 53struct 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#ifdef CONFIG_MIPS_MALTA 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#else 112 mdesc[2].type = yamon_prom; 113 mdesc[2].base = 0x000f0000; 114 mdesc[2].size = 0x00010000; 115#endif 116 117 mdesc[3].type = yamon_dontuse; 118 mdesc[3].base = 0x00100000; 119 mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base; 120 121 mdesc[4].type = yamon_free; 122 mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); 123 mdesc[4].size = memsize - mdesc[4].base; 124 125 return &mdesc[0]; 126} 127 128static int __init prom_memtype_classify (unsigned int type) 129{ 130 switch (type) { 131 case yamon_free: 132 return BOOT_MEM_RAM; 133 case yamon_prom: 134 return BOOT_MEM_ROM_DATA; 135 default: 136 return BOOT_MEM_RESERVED; 137 } 138} 139 140void __init prom_meminit(void) 141{ 142 struct prom_pmemblock *p; 143 144#ifdef DEBUG 145 pr_debug("YAMON MEMORY DESCRIPTOR dump:\n"); 146 p = prom_getmdesc(); 147 while (p->size) { 148 int i = 0; 149 pr_debug("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", 150 i, p, p->base, p->size, mtypes[p->type]); 151 p++; 152 i++; 153 } 154#endif 155 p = prom_getmdesc(); 156 157 while (p->size) { 158 long type; 159 unsigned long base, size; 160 161 type = prom_memtype_classify (p->type); 162 base = p->base; 163 size = p->size; 164 165 add_memory_region(base, size, type); 166 p++; 167 } 168} 169 170void __init prom_free_prom_memory(void) 171{ 172 unsigned long addr; 173 int i; 174 175 for (i = 0; i < boot_mem_map.nr_map; i++) { 176 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) 177 continue; 178 179 addr = boot_mem_map.map[i].addr; 180 free_init_pages("prom memory", 181 addr, addr + boot_mem_map.map[i].size); 182 } 183} 184