]> bbs.cooldavid.org Git - net-next-2.6.git/blob - arch/blackfin/mm/init.c
Merge branch 'fix/hda' into topic/hda
[net-next-2.6.git] / arch / blackfin / mm / init.c
1 /*
2  * File:         arch/blackfin/mm/init.c
3  * Based on:
4  * Author:
5  *
6  * Created:
7  * Description:
8  *
9  * Modified:
10  *               Copyright 2004-2007 Analog Devices Inc.
11  *
12  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, see the file COPYING, or write
26  * to the Free Software Foundation, Inc.,
27  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29
30 #include <linux/swap.h>
31 #include <linux/bootmem.h>
32 #include <linux/uaccess.h>
33 #include <asm/bfin-global.h>
34 #include <asm/pda.h>
35 #include <asm/cplbinit.h>
36 #include <asm/early_printk.h>
37 #include "blackfin_sram.h"
38
39 /*
40  * BAD_PAGE is the page that is used for page faults when linux
41  * is out-of-memory. Older versions of linux just did a
42  * do_exit(), but using this instead means there is less risk
43  * for a process dying in kernel mode, possibly leaving a inode
44  * unused etc..
45  *
46  * BAD_PAGETABLE is the accompanying page-table: it is initialized
47  * to point to BAD_PAGE entries.
48  *
49  * ZERO_PAGE is a special page that is used for zero-initialized
50  * data and COW.
51  */
52 static unsigned long empty_bad_page_table;
53
54 static unsigned long empty_bad_page;
55
56 static unsigned long empty_zero_page;
57
58 #ifndef CONFIG_EXCEPTION_L1_SCRATCH
59 #if defined CONFIG_SYSCALL_TAB_L1
60 __attribute__((l1_data))
61 #endif
62 static unsigned long exception_stack[NR_CPUS][1024];
63 #endif
64
65 struct blackfin_pda cpu_pda[NR_CPUS];
66 EXPORT_SYMBOL(cpu_pda);
67
68 /*
69  * paging_init() continues the virtual memory environment setup which
70  * was begun by the code in arch/head.S.
71  * The parameters are pointers to where to stick the starting and ending
72  * addresses  of available kernel virtual memory.
73  */
74 void __init paging_init(void)
75 {
76         /*
77          * make sure start_mem is page aligned,  otherwise bootmem and
78          * page_alloc get different views og the world
79          */
80         unsigned long end_mem = memory_end & PAGE_MASK;
81
82         pr_debug("start_mem is %#lx   virtual_end is %#lx\n", PAGE_ALIGN(memory_start), end_mem);
83
84         /*
85          * initialize the bad page table and bad page to point
86          * to a couple of allocated pages
87          */
88         empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
89         empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
90         empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
91         memset((void *)empty_zero_page, 0, PAGE_SIZE);
92
93         /*
94          * Set up SFC/DFC registers (user data space)
95          */
96         set_fs(KERNEL_DS);
97
98         pr_debug("free_area_init -> start_mem is %#lx   virtual_end is %#lx\n",
99                 PAGE_ALIGN(memory_start), end_mem);
100
101         {
102                 unsigned long zones_size[MAX_NR_ZONES] = { 0, };
103
104                 zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
105                 zones_size[ZONE_NORMAL] = 0;
106 #ifdef CONFIG_HIGHMEM
107                 zones_size[ZONE_HIGHMEM] = 0;
108 #endif
109                 free_area_init(zones_size);
110         }
111 }
112
113 asmlinkage void __init init_pda(void)
114 {
115         unsigned int cpu = raw_smp_processor_id();
116
117         early_shadow_stamp();
118
119         /* Initialize the PDA fields holding references to other parts
120            of the memory. The content of such memory is still
121            undefined at the time of the call, we are only setting up
122            valid pointers to it. */
123         memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu]));
124
125         cpu_pda[0].next = &cpu_pda[1];
126         cpu_pda[1].next = &cpu_pda[0];
127
128 #ifdef CONFIG_EXCEPTION_L1_SCRATCH
129         cpu_pda[cpu].ex_stack = (unsigned long *)(L1_SCRATCH_START + \
130                                         L1_SCRATCH_LENGTH);
131 #else
132         cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
133 #endif
134
135 #ifdef CONFIG_SMP
136         cpu_pda[cpu].imask = 0x1f;
137 #endif
138 }
139
140 void __init mem_init(void)
141 {
142         unsigned int codek = 0, datak = 0, initk = 0;
143         unsigned int reservedpages = 0, freepages = 0;
144         unsigned long tmp;
145         unsigned long start_mem = memory_start;
146         unsigned long end_mem = memory_end;
147
148         end_mem &= PAGE_MASK;
149         high_memory = (void *)end_mem;
150
151         start_mem = PAGE_ALIGN(start_mem);
152         max_mapnr = num_physpages = MAP_NR(high_memory);
153         printk(KERN_DEBUG "Kernel managed physical pages: %lu\n", num_physpages);
154
155         /* This will put all memory onto the freelists. */
156         totalram_pages = free_all_bootmem();
157
158         reservedpages = 0;
159         for (tmp = 0; tmp < max_mapnr; tmp++)
160                 if (PageReserved(pfn_to_page(tmp)))
161                         reservedpages++;
162         freepages =  max_mapnr - reservedpages;
163
164         /* do not count in kernel image between _rambase and _ramstart */
165         reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT;
166 #if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
167         reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT;
168 #endif
169
170         codek = (_etext - _stext) >> 10;
171         initk = (__init_end - __init_begin) >> 10;
172         datak = ((_ramstart - _rambase) >> 10) - codek - initk;
173
174         printk(KERN_INFO
175              "Memory available: %luk/%luk RAM, "
176                 "(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
177                 (unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
178                 initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
179 }
180
181 static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
182 {
183         unsigned long addr;
184         /* next to check that the page we free is not a partial page */
185         for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
186                 ClearPageReserved(virt_to_page(addr));
187                 init_page_count(virt_to_page(addr));
188                 free_page(addr);
189                 totalram_pages++;
190         }
191         printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
192 }
193
194 #ifdef CONFIG_BLK_DEV_INITRD
195 void __init free_initrd_mem(unsigned long start, unsigned long end)
196 {
197 #ifndef CONFIG_MPU
198         free_init_pages("initrd memory", start, end);
199 #endif
200 }
201 #endif
202
203 void __init_refok free_initmem(void)
204 {
205 #if defined CONFIG_RAMKERNEL && !defined CONFIG_MPU
206         free_init_pages("unused kernel memory",
207                         (unsigned long)(&__init_begin),
208                         (unsigned long)(&__init_end));
209 #endif
210 }