blob: 9c3629b9a689420edb42a34e3d7611c9650fbe57 [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
2 * File: arch/blackfin/mm/init.c
3 * Based on:
4 * Author:
5 *
6 * Created:
7 * Description:
8 *
9 * Modified:
Mike Frysinger321f6e02007-06-11 15:31:30 +080010 * Copyright 2004-2007 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -070011 *
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>
Mike Frysinger1f83b8f2007-07-12 22:58:21 +080032#include <linux/uaccess.h>
Bryan Wu1394f032007-05-06 14:50:22 -070033#include <asm/bfin-global.h>
Graf Yang8f658732008-11-18 17:48:22 +080034#include <asm/pda.h>
35#include <asm/cplbinit.h>
Bryan Wu1394f032007-05-06 14:50:22 -070036#include "blackfin_sram.h"
37
38/*
39 * BAD_PAGE is the page that is used for page faults when linux
40 * is out-of-memory. Older versions of linux just did a
41 * do_exit(), but using this instead means there is less risk
42 * for a process dying in kernel mode, possibly leaving a inode
43 * unused etc..
44 *
45 * BAD_PAGETABLE is the accompanying page-table: it is initialized
46 * to point to BAD_PAGE entries.
47 *
48 * ZERO_PAGE is a special page that is used for zero-initialized
49 * data and COW.
50 */
51static unsigned long empty_bad_page_table;
52
53static unsigned long empty_bad_page;
54
55unsigned long empty_zero_page;
56
Graf Yang8f658732008-11-18 17:48:22 +080057extern unsigned long exception_stack[NR_CPUS][1024];
58
59struct blackfin_pda cpu_pda[NR_CPUS];
60EXPORT_SYMBOL(cpu_pda);
61
Bryan Wu1394f032007-05-06 14:50:22 -070062/*
63 * paging_init() continues the virtual memory environment setup which
64 * was begun by the code in arch/head.S.
65 * The parameters are pointers to where to stick the starting and ending
66 * addresses of available kernel virtual memory.
67 */
Mike Frysinger321f6e02007-06-11 15:31:30 +080068void __init paging_init(void)
Bryan Wu1394f032007-05-06 14:50:22 -070069{
70 /*
71 * make sure start_mem is page aligned, otherwise bootmem and
72 * page_alloc get different views og the world
73 */
74 unsigned long end_mem = memory_end & PAGE_MASK;
75
76 pr_debug("start_mem is %#lx virtual_end is %#lx\n", PAGE_ALIGN(memory_start), end_mem);
77
78 /*
79 * initialize the bad page table and bad page to point
80 * to a couple of allocated pages
81 */
82 empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
83 empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
84 empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
85 memset((void *)empty_zero_page, 0, PAGE_SIZE);
86
87 /*
88 * Set up SFC/DFC registers (user data space)
89 */
90 set_fs(KERNEL_DS);
91
92 pr_debug("free_area_init -> start_mem is %#lx virtual_end is %#lx\n",
93 PAGE_ALIGN(memory_start), end_mem);
94
95 {
96 unsigned long zones_size[MAX_NR_ZONES] = { 0, };
97
Aubrey Lie3defff2007-05-21 18:09:11 +080098 zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
99 zones_size[ZONE_NORMAL] = 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700100#ifdef CONFIG_HIGHMEM
101 zones_size[ZONE_HIGHMEM] = 0;
102#endif
103 free_area_init(zones_size);
104 }
105}
106
Mike Frysinger8e2a7692009-03-05 18:45:07 +0800107asmlinkage void __init init_pda(void)
Graf Yang8f658732008-11-18 17:48:22 +0800108{
109 unsigned int cpu = raw_smp_processor_id();
110
111 /* Initialize the PDA fields holding references to other parts
112 of the memory. The content of such memory is still
113 undefined at the time of the call, we are only setting up
114 valid pointers to it. */
115 memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu]));
116
117 cpu_pda[0].next = &cpu_pda[1];
118 cpu_pda[1].next = &cpu_pda[0];
119
120 cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
121
Graf Yang8f658732008-11-18 17:48:22 +0800122#ifdef CONFIG_SMP
123 cpu_pda[cpu].imask = 0x1f;
124#endif
125}
126
127void __cpuinit reserve_pda(void)
128{
129 printk(KERN_INFO "PDA for CPU%u reserved at %p\n", smp_processor_id(),
130 &cpu_pda[smp_processor_id()]);
131}
132
Mike Frysinger321f6e02007-06-11 15:31:30 +0800133void __init mem_init(void)
Bryan Wu1394f032007-05-06 14:50:22 -0700134{
135 unsigned int codek = 0, datak = 0, initk = 0;
Yi Liee7883b2008-01-27 19:56:17 +0800136 unsigned int reservedpages = 0, freepages = 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700137 unsigned long tmp;
Bryan Wu1394f032007-05-06 14:50:22 -0700138 unsigned long start_mem = memory_start;
139 unsigned long end_mem = memory_end;
140
141 end_mem &= PAGE_MASK;
142 high_memory = (void *)end_mem;
143
144 start_mem = PAGE_ALIGN(start_mem);
145 max_mapnr = num_physpages = MAP_NR(high_memory);
Yi Li856783b2008-02-09 02:26:01 +0800146 printk(KERN_DEBUG "Kernel managed physical pages: %lu\n", num_physpages);
Bryan Wu1394f032007-05-06 14:50:22 -0700147
148 /* This will put all memory onto the freelists. */
149 totalram_pages = free_all_bootmem();
150
Yi Liee7883b2008-01-27 19:56:17 +0800151 reservedpages = 0;
152 for (tmp = 0; tmp < max_mapnr; tmp++)
153 if (PageReserved(pfn_to_page(tmp)))
154 reservedpages++;
155 freepages = max_mapnr - reservedpages;
Bryan Wu1394f032007-05-06 14:50:22 -0700156
Yi Liee7883b2008-01-27 19:56:17 +0800157 /* do not count in kernel image between _rambase and _ramstart */
158 reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT;
159#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263)
Yi Li856783b2008-02-09 02:26:01 +0800160 reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT;
Yi Liee7883b2008-01-27 19:56:17 +0800161#endif
162
163 codek = (_etext - _stext) >> 10;
164 initk = (__init_end - __init_begin) >> 10;
165 datak = ((_ramstart - _rambase) >> 10) - codek - initk;
166
Bryan Wu1394f032007-05-06 14:50:22 -0700167 printk(KERN_INFO
Yi Liee7883b2008-01-27 19:56:17 +0800168 "Memory available: %luk/%luk RAM, "
Yi Li856783b2008-02-09 02:26:01 +0800169 "(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
Yi Liee7883b2008-01-27 19:56:17 +0800170 (unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
Yi Li856783b2008-02-09 02:26:01 +0800171 initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
Sonic Zhang5d481f42008-07-19 14:51:31 +0800172}
173
174static int __init sram_init(void)
175{
Bryan Wu1394f032007-05-06 14:50:22 -0700176 /* Initialize the blackfin L1 Memory. */
Sonic Zhang5d481f42008-07-19 14:51:31 +0800177 bfin_sram_init();
Bryan Wu1394f032007-05-06 14:50:22 -0700178
Graf Yang8f658732008-11-18 17:48:22 +0800179 /* Reserve the PDA space for the boot CPU right after we
180 * initialized the scratch memory allocator.
181 */
182 reserve_pda();
Sonic Zhang5d481f42008-07-19 14:51:31 +0800183 return 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700184}
Sonic Zhang5d481f42008-07-19 14:51:31 +0800185pure_initcall(sram_init);
Bryan Wu1394f032007-05-06 14:50:22 -0700186
Bryan Wuc0514892008-02-29 12:02:10 +0800187static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
Mike Frysinger1d189472007-07-12 12:32:00 +0800188{
189 unsigned long addr;
190 /* next to check that the page we free is not a partial page */
191 for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
192 ClearPageReserved(virt_to_page(addr));
193 init_page_count(virt_to_page(addr));
194 free_page(addr);
195 totalram_pages++;
196 }
197 printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
198}
199
Bryan Wu1394f032007-05-06 14:50:22 -0700200#ifdef CONFIG_BLK_DEV_INITRD
Mike Frysinger321f6e02007-06-11 15:31:30 +0800201void __init free_initrd_mem(unsigned long start, unsigned long end)
Bryan Wu1394f032007-05-06 14:50:22 -0700202{
Bernd Schmidtb97b8a92008-01-27 18:39:16 +0800203#ifndef CONFIG_MPU
Mike Frysinger1d189472007-07-12 12:32:00 +0800204 free_init_pages("initrd memory", start, end);
Bernd Schmidtb97b8a92008-01-27 18:39:16 +0800205#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700206}
207#endif
208
Bryan Wuc0514892008-02-29 12:02:10 +0800209void __init_refok free_initmem(void)
Bryan Wu1394f032007-05-06 14:50:22 -0700210{
Bernd Schmidtb97b8a92008-01-27 18:39:16 +0800211#if defined CONFIG_RAMKERNEL && !defined CONFIG_MPU
Mike Frysinger1d189472007-07-12 12:32:00 +0800212 free_init_pages("unused kernel memory",
213 (unsigned long)(&__init_begin),
214 (unsigned long)(&__init_end));
Bryan Wu1394f032007-05-06 14:50:22 -0700215#endif
216}