Blackfin: catch hardware errors earlier during booting
[linux-block.git] / arch / blackfin / mm / init.c
CommitLineData
1394f032
BW
1/*
2 * File: arch/blackfin/mm/init.c
3 * Based on:
4 * Author:
5 *
6 * Created:
7 * Description:
8 *
9 * Modified:
321f6e0f 10 * Copyright 2004-2007 Analog Devices Inc.
1394f032
BW
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>
1f83b8f1 32#include <linux/uaccess.h>
1394f032 33#include <asm/bfin-global.h>
8f65873e
GY
34#include <asm/pda.h>
35#include <asm/cplbinit.h>
837ec2d5 36#include <asm/early_printk.h>
1394f032
BW
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 */
52static unsigned long empty_bad_page_table;
53
54static unsigned long empty_bad_page;
55
f82e0a0c 56static unsigned long empty_zero_page;
1394f032 57
f82e0a0c
GY
58#ifndef CONFIG_EXCEPTION_L1_SCRATCH
59#if defined CONFIG_SYSCALL_TAB_L1
60__attribute__((l1_data))
61#endif
62static unsigned long exception_stack[NR_CPUS][1024];
63#endif
8f65873e
GY
64
65struct blackfin_pda cpu_pda[NR_CPUS];
66EXPORT_SYMBOL(cpu_pda);
67
1394f032
BW
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 */
321f6e0f 74void __init paging_init(void)
1394f032
BW
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
e3defffe
AL
104 zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
105 zones_size[ZONE_NORMAL] = 0;
1394f032
BW
106#ifdef CONFIG_HIGHMEM
107 zones_size[ZONE_HIGHMEM] = 0;
108#endif
109 free_area_init(zones_size);
110 }
111}
112
8e2a7694 113asmlinkage void __init init_pda(void)
8f65873e
GY
114{
115 unsigned int cpu = raw_smp_processor_id();
116
837ec2d5
RG
117 early_shadow_stamp();
118
8f65873e
GY
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
f82e0a0c
GY
128#ifdef CONFIG_EXCEPTION_L1_SCRATCH
129 cpu_pda[cpu].ex_stack = (unsigned long *)(L1_SCRATCH_START + \
130 L1_SCRATCH_LENGTH);
131#else
8f65873e 132 cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
f82e0a0c 133#endif
8f65873e 134
8f65873e
GY
135#ifdef CONFIG_SMP
136 cpu_pda[cpu].imask = 0x1f;
137#endif
138}
139
321f6e0f 140void __init mem_init(void)
1394f032
BW
141{
142 unsigned int codek = 0, datak = 0, initk = 0;
ee7883b7 143 unsigned int reservedpages = 0, freepages = 0;
1394f032 144 unsigned long tmp;
1394f032
BW
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);
856783b3 153 printk(KERN_DEBUG "Kernel managed physical pages: %lu\n", num_physpages);
1394f032
BW
154
155 /* This will put all memory onto the freelists. */
156 totalram_pages = free_all_bootmem();
157
ee7883b7
YL
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;
41ba653f 166#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
856783b3 167 reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT;
ee7883b7
YL
168#endif
169
1394f032 170 codek = (_etext - _stext) >> 10;
1394f032 171 initk = (__init_end - __init_begin) >> 10;
ee7883b7 172 datak = ((_ramstart - _rambase) >> 10) - codek - initk;
1394f032 173
1394f032 174 printk(KERN_INFO
ee7883b7 175 "Memory available: %luk/%luk RAM, "
856783b3 176 "(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
ee7883b7 177 (unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
856783b3 178 initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
5d481f49
SZ
179}
180
c051489d 181static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
1394f032 182{
1d189474
MF
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);
1394f032 189 totalram_pages++;
1394f032 190 }
1d189474
MF
191 printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
192}
193
194#ifdef CONFIG_BLK_DEV_INITRD
195void __init free_initrd_mem(unsigned long start, unsigned long end)
196{
b97b8a99 197#ifndef CONFIG_MPU
1d189474 198 free_init_pages("initrd memory", start, end);
b97b8a99 199#endif
1394f032
BW
200}
201#endif
202
c051489d 203void __init_refok free_initmem(void)
1394f032 204{
b97b8a99 205#if defined CONFIG_RAMKERNEL && !defined CONFIG_MPU
1d189474
MF
206 free_init_pages("unused kernel memory",
207 (unsigned long)(&__init_begin),
208 (unsigned long)(&__init_end));
1394f032
BW
209#endif
210}