ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / v850 / kernel / setup.c
1 /*
2  * arch/v850/kernel/setup.c -- Arch-dependent initialization functions
3  *
4  *  Copyright (C) 2001,02,03  NEC Electronics Corporation
5  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
6  *
7  * This file is subject to the terms and conditions of the GNU General
8  * Public License.  See the file COPYING in the main directory of this
9  * archive for more details.
10  *
11  * Written by Miles Bader <miles@gnu.org>
12  */
13
14 #include <linux/mm.h>
15 #include <linux/bootmem.h>
16 #include <linux/swap.h>         /* we don't have swap, but for nr_free_pages */
17 #include <linux/irq.h>
18 #include <linux/reboot.h>
19 #include <linux/personality.h>
20 #include <linux/major.h>
21 #include <linux/root_dev.h>
22 #include <linux/mtd/mtd.h>
23
24 #include <asm/irq.h>
25
26 #include "mach.h"
27
28 /* These symbols are all defined in the linker map to delineate various
29    statically allocated regions of memory.  */
30
31 extern char _intv_start, _intv_end;
32 /* `kram' is only used if the kernel uses part of normal user RAM.  */
33 extern char _kram_start __attribute__ ((__weak__));
34 extern char _kram_end __attribute__ ((__weak__));
35 extern char _init_start, _init_end;
36 extern char _bootmap;
37 extern char _stext, _etext, _sdata, _edata, _sbss, _ebss;
38 /* Many platforms use an embedded root image.  */
39 extern char _root_fs_image_start __attribute__ ((__weak__));
40 extern char _root_fs_image_end __attribute__ ((__weak__));
41
42
43 char command_line[512];
44 char saved_command_line[512];
45
46 /* Memory not used by the kernel.  */
47 static unsigned long total_ram_pages;
48
49 /* System RAM.  */
50 static unsigned long ram_start = 0, ram_len = 0;
51
52
53 #define ADDR_TO_PAGE_UP(x)   ((((unsigned long)x) + PAGE_SIZE-1) >> PAGE_SHIFT)
54 #define ADDR_TO_PAGE(x)      (((unsigned long)x) >> PAGE_SHIFT)
55 #define PAGE_TO_ADDR(x)      (((unsigned long)x) << PAGE_SHIFT)
56
57 static void init_mem_alloc (unsigned long ram_start, unsigned long ram_len);
58
59 void set_mem_root (void *addr, size_t len, char *cmd_line);
60
61
62 void __init setup_arch (char **cmdline)
63 {
64         /* Keep a copy of command line */
65         *cmdline = command_line;
66         memcpy (saved_command_line, command_line, sizeof saved_command_line);
67         saved_command_line[sizeof saved_command_line - 1] = '\0';
68
69         console_verbose ();
70
71         init_mm.start_code = (unsigned long) &_stext;
72         init_mm.end_code = (unsigned long) &_etext;
73         init_mm.end_data = (unsigned long) &_edata;
74         init_mm.brk = (unsigned long) &_kram_end;
75
76         /* Find out what mem this machine has.  */
77         mach_get_physical_ram (&ram_start, &ram_len);
78         /* ... and tell the kernel about it.  */
79         init_mem_alloc (ram_start, ram_len);
80
81         printk (KERN_INFO "CPU: %s\nPlatform: %s\n",
82                 CPU_MODEL_LONG, PLATFORM_LONG);
83
84         /* do machine-specific setups.  */
85         mach_setup (cmdline);
86
87 #ifdef CONFIG_MTD
88         if (!ROOT_DEV && &_root_fs_image_end > &_root_fs_image_start)
89                 set_mem_root (&_root_fs_image_start,
90                               &_root_fs_image_end - &_root_fs_image_start,
91                               *cmdline);
92 #endif
93 }
94
95 void __init trap_init (void)
96 {
97 }
98
99 #ifdef CONFIG_MTD
100 /* Set the root filesystem to be the given memory region.
101    Some parameter may be appended to CMD_LINE.  */
102 void set_mem_root (void *addr, size_t len, char *cmd_line)
103 {
104         /* The only way to pass info to the MTD slram driver is via
105            the command line.  */
106         if (*cmd_line) {
107                 cmd_line += strlen (cmd_line);
108                 *cmd_line++ = ' ';
109         }
110         sprintf (cmd_line, "slram=root,0x%x,+0x%x", (u32)addr, (u32)len);
111
112         ROOT_DEV = MKDEV (MTD_BLOCK_MAJOR, 0);
113 }
114 #endif
115
116 \f
117 static void irq_nop (unsigned irq) { }
118 static unsigned irq_zero (unsigned irq) { return 0; }
119
120 static void nmi_end (unsigned irq)
121 {
122         if (irq != IRQ_NMI (0)) {
123                 printk (KERN_CRIT "NMI %d is unrecoverable; restarting...",
124                         irq - IRQ_NMI (0));
125                 machine_restart (0);
126         }
127 }
128
129 static struct hw_interrupt_type nmi_irq_type = {
130         "NMI",
131         irq_zero,               /* startup */
132         irq_nop,                /* shutdown */
133         irq_nop,                /* enable */
134         irq_nop,                /* disable */
135         irq_nop,                /* ack */
136         nmi_end,                /* end */
137 };
138
139 void __init init_IRQ (void)
140 {
141         init_irq_handlers (0, NUM_MACH_IRQS, 1, 0);
142         init_irq_handlers (IRQ_NMI (0), NUM_NMIS, 1, &nmi_irq_type);
143         mach_init_irqs ();
144 }
145
146 \f
147 void __init mem_init (void)
148 {
149         max_mapnr = MAP_NR (ram_start + ram_len);
150
151         num_physpages = ADDR_TO_PAGE (ram_len);
152
153         total_ram_pages = free_all_bootmem ();
154
155         printk (KERN_INFO
156                 "Memory: %luK/%luK available"
157                 " (%luK kernel code, %luK data)\n",
158                 PAGE_TO_ADDR (nr_free_pages()) / 1024,
159                 ram_len / 1024,
160                 ((unsigned long)&_etext - (unsigned long)&_stext) / 1024,
161                 ((unsigned long)&_ebss - (unsigned long)&_sdata) / 1024);
162 }
163
164 void free_initmem (void)
165 {
166         unsigned long ram_end = ram_start + ram_len;
167         unsigned long start = PAGE_ALIGN ((unsigned long)(&_init_start));
168
169         if (start >= ram_start && start < ram_end) {
170                 unsigned long addr;
171                 unsigned long end = PAGE_ALIGN ((unsigned long)(&_init_end));
172
173                 if (end > ram_end)
174                         end = ram_end;
175
176                 printk("Freeing unused kernel memory: %ldK freed\n",
177                        (end - start) / 1024);
178
179                 for (addr = start; addr < end; addr += PAGE_SIZE) {
180                         struct page *page = virt_to_page (addr);
181                         ClearPageReserved (page);
182                         set_page_count (page, 1);
183                         __free_page (page);
184                         total_ram_pages++;
185                 }
186         }
187 }
188
189 \f
190 /* Initialize the `bootmem allocator'.  RAM_START and RAM_LEN identify
191    what RAM may be used.  */
192 static void __init
193 init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
194 {
195         /* The part of the kernel that's in the same managed RAM space
196            used for general allocation.  */
197         unsigned long kram_start = (unsigned long)&_kram_start;
198         unsigned long kram_end = (unsigned long)&_kram_end;
199         /* End of the managed RAM space.  */
200         unsigned long ram_end = ram_start + ram_len;
201         /* Address range of the interrupt vector table.  */
202         unsigned long intv_start = (unsigned long)&_intv_start;
203         unsigned long intv_end = (unsigned long)&_intv_end;
204         /* True if the interrupt vectors are in the managed RAM area.  */
205         int intv_in_ram = (intv_end > ram_start && intv_start < ram_end);
206         /* True if the interrupt vectors are inside the kernel's RAM.  */
207         int intv_in_kram = (intv_end > kram_start && intv_start < kram_end);
208         /* A pointer to an optional function that reserves platform-specific
209            memory regions.  We declare the pointer `volatile' to avoid gcc
210            turning the call into a static call (the problem is that since
211            it's a weak symbol, a static call may end up trying to reference
212            the location 0x0, which is not always reachable).  */
213         void (*volatile mrb) (void) = mach_reserve_bootmem;
214         /* The bootmem allocator's allocation bitmap.  */
215         unsigned long bootmap = (unsigned long)&_bootmap;
216         unsigned long bootmap_len;
217
218         /* Round bootmap location up to next page.  */
219         bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap));
220
221         /* Initialize bootmem allocator.  */
222         bootmap_len = init_bootmem_node (NODE_DATA (0),
223                                          ADDR_TO_PAGE (bootmap),
224                                          ADDR_TO_PAGE (PAGE_OFFSET),
225                                          ADDR_TO_PAGE (ram_end));
226
227         /* Now make the RAM actually allocatable (it starts out `reserved'). */
228         free_bootmem (ram_start, ram_len);
229
230         if (kram_end > kram_start)
231                 /* Reserve the RAM part of the kernel's address space, so it
232                    doesn't get allocated.  */
233                 reserve_bootmem (kram_start, kram_end - kram_start);
234         
235         if (intv_in_ram && !intv_in_kram)
236                 /* Reserve the interrupt vector space.  */
237                 reserve_bootmem (intv_start, intv_end - intv_start);
238
239         if (bootmap >= ram_start && bootmap < ram_end)
240                 /* Reserve the bootmap space.  */
241                 reserve_bootmem (bootmap, bootmap_len);
242
243         /* Reserve the memory used by the root filesystem image if it's
244            in RAM.  */
245         if (&_root_fs_image_end > &_root_fs_image_start
246             && (unsigned long)&_root_fs_image_start >= ram_start
247             && (unsigned long)&_root_fs_image_start < ram_end)
248                 reserve_bootmem ((unsigned long)&_root_fs_image_start,
249                                  &_root_fs_image_end - &_root_fs_image_start);
250
251         /* Let the platform-dependent code reserve some too.  */
252         if (mrb)
253                 (*mrb) ();
254 }
255
256 /* Tell the kernel about what RAM it may use for memory allocation.  */
257 static void __init
258 init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
259 {
260         unsigned i;
261         unsigned long zones_size[MAX_NR_ZONES];
262
263         init_bootmem_alloc (ram_start, ram_len);
264
265         for (i = 0; i < MAX_NR_ZONES; i++)
266                 zones_size[i] = 0;
267
268         /* We stuff all the memory into one area, which includes the
269            initial gap from PAGE_OFFSET to ram_start.  */
270         zones_size[ZONE_DMA]
271                 = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
272
273         /* The allocator is very picky about the address of the first
274            allocatable page -- it must be at least as aligned as the
275            maximum allocation -- so try to detect cases where it will get
276            confused and signal them at compile time (this is a common
277            problem when porting to a new platform with ).  There is a
278            similar runtime check in free_area_init_core.  */
279 #if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
280 #error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
281 #endif
282
283         free_area_init_node (0, NODE_DATA(0), 0, zones_size,
284                              ADDR_TO_PAGE (PAGE_OFFSET), 0);
285         mem_map = NODE_DATA(0)->node_mem_map;
286 }