2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1995 Linus Torvalds
7 * Copyright (C) 1995 Waldorf Electronics
8 * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Ralf Baechle
9 * Copyright (C) 1996 Stoned Elipot
10 * Copyright (C) 1999 Silicon Graphics, Inc.
11 * Copyright (C) 2002 Maciej W. Rozycki
13 #include <linux/config.h>
14 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/ioport.h>
17 #include <linux/sched.h>
18 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/stddef.h>
22 #include <linux/string.h>
23 #include <linux/unistd.h>
24 #include <linux/ptrace.h>
25 #include <linux/slab.h>
26 #include <linux/user.h>
27 #include <linux/utsname.h>
28 #include <linux/a.out.h>
29 #include <linux/tty.h>
30 #include <linux/bootmem.h>
31 #ifdef CONFIG_BLK_DEV_RAM
32 #include <linux/blk.h>
34 #include <linux/major.h>
35 #include <linux/kdev_t.h>
36 #include <linux/root_dev.h>
38 #include <asm/addrspace.h>
39 #include <asm/bootinfo.h>
41 #include <asm/mipsregs.h>
42 #include <asm/stackframe.h>
43 #include <asm/system.h>
44 #include <asm/sections.h>
45 #include <asm/pgalloc.h>
47 struct cpuinfo_mips cpu_data
[NR_CPUS
];
50 struct screen_info screen_info
;
54 * Set if box has EISA slots.
60 #ifdef CONFIG_BLK_DEV_FD
61 extern struct fd_ops no_fd_ops
;
62 struct fd_ops
*fd_ops
;
65 #ifdef CONFIG_BLK_DEV_IDE
66 extern struct ide_ops no_ide_ops
;
67 struct ide_ops
*ide_ops
;
70 extern void * __rd_start
, * __rd_end
;
72 extern struct rtc_ops no_rtc_ops
;
73 struct rtc_ops
*rtc_ops
;
75 extern struct kbd_ops no_kbd_ops
;
76 struct kbd_ops
*kbd_ops
;
81 * These are initialized so they are in the .data section
83 unsigned long mips_machtype
= MACH_UNKNOWN
;
84 unsigned long mips_machgroup
= MACH_GROUP_UNKNOWN
;
86 struct boot_mem_map boot_mem_map
;
88 unsigned char aux_device_present
;
90 static char command_line
[CL_SIZE
] = { 0, };
91 char saved_command_line
[CL_SIZE
];
92 extern char arcs_cmdline
[CL_SIZE
];
95 * mips_io_port_base is the begin of the address space to which x86 style
96 * I/O ports are mapped.
98 const unsigned long mips_io_port_base
= -1;
99 EXPORT_SYMBOL(mips_io_port_base
);
102 * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped
105 unsigned long isa_slot_offset
;
106 EXPORT_SYMBOL(isa_slot_offset
);
108 extern void SetUpBootInfo(void);
109 extern void load_mmu(void);
110 extern ATTRIB_NORET asmlinkage
void start_kernel(void);
111 extern void prom_init(int, char **, char **, int *);
113 static struct resource code_resource
= { "Kernel code" };
114 static struct resource data_resource
= { "Kernel data" };
116 asmlinkage
void __init
init_arch(int argc
, char **argv
, char **envp
,
119 /* Determine which MIPS variant we are running on. */
122 prom_init(argc
, argv
, envp
, prom_vec
);
127 * Determine the mmu/cache attached to this machine, then flush the
128 * tlb and caches. On the r4xx0 variants this also sets CP0_WIRED to
134 * On IP27, I am seeing the TS bit set when the kernel is loaded.
135 * Maybe because the kernel is in ckseg0 and not xkphys? Clear it
138 clear_c0_status(ST0_BEV
|ST0_TS
|ST0_CU1
|ST0_CU2
|ST0_CU3
);
139 set_c0_status(ST0_CU0
|ST0_KX
|ST0_SX
|ST0_FR
);
144 void __init
add_memory_region(phys_t start
, phys_t size
,
147 int x
= boot_mem_map
.nr_map
;
149 if (x
== BOOT_MEM_MAP_MAX
) {
150 printk("Ooops! Too many entries in the memory map!\n");
154 boot_mem_map
.map
[x
].addr
= start
;
155 boot_mem_map
.map
[x
].size
= size
;
156 boot_mem_map
.map
[x
].type
= type
;
157 boot_mem_map
.nr_map
++;
160 static void __init
print_memory_map(void)
164 for (i
= 0; i
< boot_mem_map
.nr_map
; i
++) {
165 printk(" memory: %016Lx @ %016Lx ",
166 (unsigned long long) boot_mem_map
.map
[i
].size
,
167 (unsigned long long) boot_mem_map
.map
[i
].addr
);
168 switch (boot_mem_map
.map
[i
].type
) {
170 printk("(usable)\n");
172 case BOOT_MEM_ROM_DATA
:
173 printk("(ROM data)\n");
175 case BOOT_MEM_RESERVED
:
176 printk("(reserved)\n");
179 printk("type %lu\n", boot_mem_map
.map
[i
].type
);
185 static inline void parse_cmdline_early(void)
187 char c
= ' ', *to
= command_line
, *from
= saved_command_line
;
188 unsigned long start_at
, mem_size
;
192 printk("Determined physical RAM map:\n");
197 * "mem=XXX[kKmM]" defines a memory region from
198 * 0 to <XXX>, overriding the determined size.
199 * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
200 * <YYY> to <YYY>+<XXX>, overriding the determined size.
202 if (c
== ' ' && !memcmp(from
, "mem=", 4)) {
203 if (to
!= command_line
)
206 * If a user specifies memory size, we
207 * blow away any automatically generated
211 boot_mem_map
.nr_map
= 0;
214 mem_size
= memparse(from
+ 4, &from
);
216 start_at
= memparse(from
+ 1, &from
);
219 add_memory_region(start_at
, mem_size
, BOOT_MEM_RAM
);
224 if (CL_SIZE
<= ++len
)
231 printk("User-defined physical RAM map:\n");
237 #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
238 #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
239 #define PFN_PHYS(x) ((x) << PAGE_SHIFT)
241 static inline void bootmem_init(void)
243 #ifdef CONFIG_BLK_DEV_INITRD
245 unsigned long *initrd_header
;
247 unsigned long bootmap_size
;
248 unsigned long start_pfn
, max_pfn
;
251 #ifdef CONFIG_BLK_DEV_INITRD
252 tmp
= (((unsigned long)&_end
+ PAGE_SIZE
-1) & PAGE_MASK
) - 8;
253 if (tmp
< (unsigned long)&_end
)
255 initrd_header
= (unsigned long *)tmp
;
256 if (initrd_header
[0] == 0x494E5244) {
257 initrd_start
= (unsigned long)&initrd_header
[2];
258 initrd_end
= initrd_start
+ initrd_header
[1];
260 start_pfn
= PFN_UP(CPHYSADDR((&_end
)+(initrd_end
- initrd_start
) + PAGE_SIZE
));
263 * Partially used pages are not usable - thus
264 * we are rounding upwards.
266 start_pfn
= PFN_UP(CPHYSADDR(&_end
));
267 #endif /* CONFIG_BLK_DEV_INITRD */
269 #ifndef CONFIG_SGI_IP27
270 /* Find the highest page frame number we have available. */
272 for (i
= 0; i
< boot_mem_map
.nr_map
; i
++) {
273 unsigned long start
, end
;
275 if (boot_mem_map
.map
[i
].type
!= BOOT_MEM_RAM
)
278 start
= PFN_UP(boot_mem_map
.map
[i
].addr
);
279 end
= PFN_DOWN(boot_mem_map
.map
[i
].addr
280 + boot_mem_map
.map
[i
].size
);
288 /* Initialize the boot-time allocator. */
289 bootmap_size
= init_bootmem(start_pfn
, max_pfn
);
292 * Register fully available low RAM pages with the bootmem allocator.
294 for (i
= 0; i
< boot_mem_map
.nr_map
; i
++) {
295 unsigned long curr_pfn
, last_pfn
, size
;
298 * Reserve usable memory.
300 if (boot_mem_map
.map
[i
].type
!= BOOT_MEM_RAM
)
304 * We are rounding up the start address of usable memory:
306 curr_pfn
= PFN_UP(boot_mem_map
.map
[i
].addr
);
307 if (curr_pfn
>= max_pfn
)
309 if (curr_pfn
< start_pfn
)
310 curr_pfn
= start_pfn
;
313 * ... and at the end of the usable range downwards:
315 last_pfn
= PFN_DOWN(boot_mem_map
.map
[i
].addr
316 + boot_mem_map
.map
[i
].size
);
318 if (last_pfn
> max_pfn
)
322 * ... finally, did all the rounding and playing
323 * around just make the area go away?
325 if (last_pfn
<= curr_pfn
)
328 size
= last_pfn
- curr_pfn
;
329 free_bootmem(PFN_PHYS(curr_pfn
), PFN_PHYS(size
));
332 /* Reserve the bootmap memory. */
333 reserve_bootmem(PFN_PHYS(start_pfn
), bootmap_size
);
336 #ifdef CONFIG_BLK_DEV_INITRD
337 /* Board specific code should have set up initrd_start and initrd_end */
338 ROOT_DEV
= Root_RAM0
;
339 if (&__rd_start
!= &__rd_end
) {
340 initrd_start
= (unsigned long)&__rd_start
;
341 initrd_end
= (unsigned long)&__rd_end
;
343 initrd_below_start_ok
= 1;
345 unsigned long initrd_size
= ((unsigned char *)initrd_end
) - ((unsigned char *)initrd_start
);
346 printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
347 (void *)initrd_start
,
349 /* FIXME: is this right? */
350 #ifndef CONFIG_SGI_IP27
351 if (CPHYSADDR(initrd_end
) > PFN_PHYS(max_pfn
)) {
352 printk("initrd extends beyond end of memory "
353 "(0x%p > 0x%p)\ndisabling initrd\n",
354 (void *)CPHYSADDR(initrd_end
),
355 (void *)PFN_PHYS(max_pfn
));
358 #endif /* !CONFIG_SGI_IP27 */
363 static inline void resource_init(void)
367 code_resource
.start
= virt_to_bus(&_text
);
368 code_resource
.end
= virt_to_bus(&_etext
) - 1;
369 data_resource
.start
= virt_to_bus(&_etext
);
370 data_resource
.end
= virt_to_bus(&_edata
) - 1;
373 * Request address space for all standard RAM.
375 for (i
= 0; i
< boot_mem_map
.nr_map
; i
++) {
376 struct resource
*res
;
378 res
= alloc_bootmem(sizeof(struct resource
));
379 switch (boot_mem_map
.map
[i
].type
) {
381 case BOOT_MEM_ROM_DATA
:
382 res
->name
= "System RAM";
384 case BOOT_MEM_RESERVED
:
386 res
->name
= "reserved";
389 res
->start
= boot_mem_map
.map
[i
].addr
;
390 res
->end
= boot_mem_map
.map
[i
].addr
+
391 boot_mem_map
.map
[i
].size
- 1;
393 res
->flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
394 request_resource(&iomem_resource
, res
);
397 * We don't know which RAM region contains kernel data,
398 * so we try it repeatedly and let the resource manager
401 request_resource(res
, &code_resource
);
402 request_resource(res
, &data_resource
);
411 void __init
setup_arch(char **cmdline_p
)
413 extern void decstation_setup(void);
414 extern void ip22_setup(void);
415 extern void ip27_setup(void);
416 extern void ip32_setup(void);
417 extern void swarm_setup(void);
418 extern void malta_setup(void);
419 extern void momenco_ocelot_setup(void);
420 extern void momenco_ocelot_g_setup(void);
421 extern void momenco_ocelot_c_setup(void);
422 extern void swarm_setup(void);
423 void frame_info_init(void);
426 #ifdef CONFIG_DECSTATION
429 #ifdef CONFIG_SGI_IP22
432 #ifdef CONFIG_SGI_IP27
435 #ifdef CONFIG_SGI_IP32
438 #ifdef CONFIG_SIBYTE_BOARD
441 #ifdef CONFIG_MIPS_MALTA
444 #ifdef CONFIG_MOMENCO_OCELOT
445 case MACH_GROUP_MOMENCO
:
446 momenco_ocelot_setup();
449 #ifdef CONFIG_MOMENCO_OCELOT_G
450 case MACH_GROUP_MOMENCO
:
451 momenco_ocelot_g_setup();
454 #ifdef CONFIG_MOMENCO_OCELOT_C
455 case MACH_GROUP_MOMENCO
:
456 momenco_ocelot_c_setup();
461 strlcpy(command_line
, arcs_cmdline
, sizeof(command_line
));
462 strlcpy(saved_command_line
, command_line
, sizeof(saved_command_line
));
464 *cmdline_p
= command_line
;
466 parse_cmdline_early();
475 int __init
fpu_disable(char *s
)
477 cpu_data
[0].options
&= ~MIPS_CPU_FPU
;
482 __setup("nofpu", fpu_disable
);