Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[sfrench/cifs-2.6.git] / arch / mips / mips-boards / generic / memory.c
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/config.h>
22 #include <linux/init.h>
23 #include <linux/mm.h>
24 #include <linux/bootmem.h>
25 #include <linux/string.h>
26
27 #include <asm/bootinfo.h>
28 #include <asm/page.h>
29
30 #include <asm/mips-boards/prom.h>
31
32 /*#define DEBUG*/
33
34 enum yamon_memtypes {
35         yamon_dontuse,
36         yamon_prom,
37         yamon_free,
38 };
39 struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
40
41 #ifdef DEBUG
42 static char *mtypes[3] = {
43         "Dont use memory",
44         "YAMON PROM memory",
45         "Free memmory",
46 };
47 #endif
48
49 /* References to section boundaries */
50 extern char _end;
51
52 #define PFN_ALIGN(x)    (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
53
54
55 struct prom_pmemblock * __init prom_getmdesc(void)
56 {
57         char *memsize_str;
58         unsigned int memsize;
59         char cmdline[CL_SIZE], *ptr;
60
61         /* Check the command line first for a memsize directive */
62         strcpy(cmdline, arcs_cmdline);
63         ptr = strstr(cmdline, "memsize=");
64         if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
65                 ptr = strstr(ptr, " memsize=");
66
67         if (ptr) {
68                 memsize = memparse(ptr + 8, &ptr);
69         }
70         else {
71                 /* otherwise look in the environment */
72                 memsize_str = prom_getenv("memsize");
73                 if (!memsize_str) {
74                         prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
75                         memsize = 0x02000000;
76                 } else {
77 #ifdef DEBUG
78                         prom_printf("prom_memsize = %s\n", memsize_str);
79 #endif
80                         memsize = simple_strtol(memsize_str, NULL, 0);
81                 }
82         }
83         memset(mdesc, 0, sizeof(mdesc));
84
85         mdesc[0].type = yamon_dontuse;
86         mdesc[0].base = 0x00000000;
87         mdesc[0].size = 0x00001000;
88
89         mdesc[1].type = yamon_prom;
90         mdesc[1].base = 0x00001000;
91         mdesc[1].size = 0x000ef000;
92
93 #ifdef CONFIG_MIPS_MALTA
94         /*
95          * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
96          * south bridge and PCI access always forwarded to the ISA Bus and
97          * BIOSCS# is always generated.
98          * This mean that this area can't be used as DMA memory for PCI
99          * devices.
100          */
101         mdesc[2].type = yamon_dontuse;
102         mdesc[2].base = 0x000f0000;
103         mdesc[2].size = 0x00010000;
104 #else
105         mdesc[2].type = yamon_prom;
106         mdesc[2].base = 0x000f0000;
107         mdesc[2].size = 0x00010000;
108 #endif
109
110         mdesc[3].type = yamon_dontuse;
111         mdesc[3].base = 0x00100000;
112         mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
113
114         mdesc[4].type = yamon_free;
115         mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
116         mdesc[4].size = memsize - mdesc[4].base;
117
118         return &mdesc[0];
119 }
120
121 static int __init prom_memtype_classify (unsigned int type)
122 {
123         switch (type) {
124         case yamon_free:
125                 return BOOT_MEM_RAM;
126         case yamon_prom:
127                 return BOOT_MEM_ROM_DATA;
128         default:
129                 return BOOT_MEM_RESERVED;
130         }
131 }
132
133 void __init prom_meminit(void)
134 {
135         struct prom_pmemblock *p;
136
137 #ifdef DEBUG
138         prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
139         p = prom_getmdesc();
140         while (p->size) {
141                 int i = 0;
142                 prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
143                             i, p, p->base, p->size, mtypes[p->type]);
144                 p++;
145                 i++;
146         }
147 #endif
148         p = prom_getmdesc();
149
150         while (p->size) {
151                 long type;
152                 unsigned long base, size;
153
154                 type = prom_memtype_classify (p->type);
155                 base = p->base;
156                 size = p->size;
157
158                 add_memory_region(base, size, type);
159                 p++;
160         }
161 }
162
163 unsigned long __init prom_free_prom_memory(void)
164 {
165         unsigned long freed = 0;
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                 while (addr < boot_mem_map.map[i].addr
175                               + boot_mem_map.map[i].size) {
176                         ClearPageReserved(virt_to_page(__va(addr)));
177                         init_page_count(virt_to_page(__va(addr)));
178                         free_page((unsigned long)__va(addr));
179                         addr += PAGE_SIZE;
180                         freed += PAGE_SIZE;
181                 }
182         }
183         printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
184
185         return freed;
186 }