Merge master.kernel.org:/home/rmk/linux-2.6-mmc
[linux-2.6] / arch / mips / arc / memory.c
1 /*
2  * memory.c: PROM library functions for acquiring/using memory descriptors
3  *           given to us from the ARCS firmware.
4  *
5  * Copyright (C) 1996 by David S. Miller
6  * Copyright (C) 1999, 2000, 2001 by Ralf Baechle
7  * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
8  *
9  * PROM library functions for acquiring/using memory descriptors given to us
10  * from the ARCS firmware.  This is only used when CONFIG_ARC_MEMORY is set
11  * because on some machines like SGI IP27 the ARC memory configuration data
12  * completly bogus and alternate easier to use mechanisms are available.
13  */
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/sched.h>
18 #include <linux/mm.h>
19 #include <linux/bootmem.h>
20 #include <linux/swap.h>
21
22 #include <asm/sgialib.h>
23 #include <asm/page.h>
24 #include <asm/pgtable.h>
25 #include <asm/bootinfo.h>
26
27 #undef DEBUG
28
29 /*
30  * For ARC firmware memory functions the unit of meassuring memory is always
31  * a 4k page of memory
32  */
33 #define ARC_PAGE_SHIFT  12
34
35 struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current)
36 {
37         return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
38 }
39
40 #ifdef DEBUG /* convenient for debugging */
41 static char *arcs_mtypes[8] = {
42         "Exception Block",
43         "ARCS Romvec Page",
44         "Free/Contig RAM",
45         "Generic Free RAM",
46         "Bad Memory",
47         "Standalone Program Pages",
48         "ARCS Temp Storage Area",
49         "ARCS Permanent Storage Area"
50 };
51
52 static char *arc_mtypes[8] = {
53         "Exception Block",
54         "SystemParameterBlock",
55         "FreeMemory",
56         "Bad Memory",
57         "LoadedProgram",
58         "FirmwareTemporary",
59         "FirmwarePermanent",
60         "FreeContiguous"
61 };
62 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \
63                                                 : arc_mtypes[a.arc]
64 #endif
65
66 static inline int memtype_classify_arcs (union linux_memtypes type)
67 {
68         switch (type.arcs) {
69         case arcs_fcontig:
70         case arcs_free:
71                 return BOOT_MEM_RAM;
72         case arcs_atmp:
73                 return BOOT_MEM_ROM_DATA;
74         case arcs_eblock:
75         case arcs_rvpage:
76         case arcs_bmem:
77         case arcs_prog:
78         case arcs_aperm:
79                 return BOOT_MEM_RESERVED;
80         default:
81                 BUG();
82         }
83         while(1);                               /* Nuke warning.  */
84 }
85
86 static inline int memtype_classify_arc (union linux_memtypes type)
87 {
88         switch (type.arc) {
89         case arc_free:
90         case arc_fcontig:
91                 return BOOT_MEM_RAM;
92         case arc_atmp:
93                 return BOOT_MEM_ROM_DATA;
94         case arc_eblock:
95         case arc_rvpage:
96         case arc_bmem:
97         case arc_prog:
98         case arc_aperm:
99                 return BOOT_MEM_RESERVED;
100         default:
101                 BUG();
102         }
103         while(1);                               /* Nuke warning.  */
104 }
105
106 static int __init prom_memtype_classify (union linux_memtypes type)
107 {
108         if (prom_flags & PROM_FLAG_ARCS)        /* SGI is ``different'' ... */
109                 return memtype_classify_arcs(type);
110
111         return memtype_classify_arc(type);
112 }
113
114 void __init prom_meminit(void)
115 {
116         struct linux_mdesc *p;
117
118 #ifdef DEBUG
119         int i = 0;
120
121         prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
122         p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
123         while(p) {
124                 prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
125                             i, p, p->base, p->pages, mtypes(p->type));
126                 p = ArcGetMemoryDescriptor(p);
127                 i++;
128         }
129 #endif
130
131         p = PROM_NULL_MDESC;
132         while ((p = ArcGetMemoryDescriptor(p))) {
133                 unsigned long base, size;
134                 long type;
135
136                 base = p->base << ARC_PAGE_SHIFT;
137                 size = p->pages << ARC_PAGE_SHIFT;
138                 type = prom_memtype_classify(p->type);
139
140                 add_memory_region(base, size, type);
141         }
142 }
143
144 unsigned long __init prom_free_prom_memory(void)
145 {
146         unsigned long freed = 0;
147         unsigned long addr;
148         int i;
149
150         if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
151                 return 0;
152
153         for (i = 0; i < boot_mem_map.nr_map; i++) {
154                 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
155                         continue;
156
157                 addr = boot_mem_map.map[i].addr;
158                 while (addr < boot_mem_map.map[i].addr
159                               + boot_mem_map.map[i].size) {
160                         ClearPageReserved(virt_to_page(__va(addr)));
161                         init_page_count(virt_to_page(__va(addr)));
162                         free_page((unsigned long)__va(addr));
163                         addr += PAGE_SIZE;
164                         freed += PAGE_SIZE;
165                 }
166         }
167         printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10);
168
169         return freed;
170 }