PageRenderTime 103ms CodeModel.GetById 13ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/arm/kernel/setup.c

https://bitbucket.org/thekraven/iscream_thunderc-2.6.35
C | 997 lines | 748 code | 148 blank | 101 comment | 97 complexity | fccf8b8e52a488adb304c8c9ac346dc8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 *  linux/arch/arm/kernel/setup.c
  3 *
  4 *  Copyright (C) 1995-2001 Russell King
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License version 2 as
  8 * published by the Free Software Foundation.
  9 */
 10#include <linux/module.h>
 11#include <linux/kernel.h>
 12#include <linux/stddef.h>
 13#include <linux/ioport.h>
 14#include <linux/delay.h>
 15#include <linux/utsname.h>
 16#include <linux/initrd.h>
 17#include <linux/console.h>
 18#include <linux/bootmem.h>
 19#include <linux/seq_file.h>
 20#include <linux/screen_info.h>
 21#include <linux/init.h>
 22#include <linux/root_dev.h>
 23#include <linux/cpu.h>
 24#include <linux/interrupt.h>
 25#include <linux/smp.h>
 26#include <linux/fs.h>
 27#include <linux/proc_fs.h>
 28#ifdef CONFIG_MEMORY_HOTPLUG
 29#include <linux/memory_hotplug.h>
 30#endif
 31
 32#include <asm/unified.h>
 33#include <asm/cpu.h>
 34#include <asm/cputype.h>
 35#include <asm/elf.h>
 36#include <asm/procinfo.h>
 37#include <asm/sections.h>
 38#include <asm/setup.h>
 39#include <asm/mach-types.h>
 40#include <asm/cacheflush.h>
 41#include <asm/cachetype.h>
 42#include <asm/tlbflush.h>
 43
 44#include <asm/mach/arch.h>
 45#include <asm/mach/irq.h>
 46#include <asm/mach/time.h>
 47#include <asm/traps.h>
 48#include <asm/unwind.h>
 49
 50#include "compat.h"
 51#include "atags.h"
 52#include "tcm.h"
 53
 54#ifndef MEM_SIZE
 55#define MEM_SIZE	(16*1024*1024)
 56#endif
 57
 58#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
 59char fpe_type[8];
 60
 61static int __init fpe_setup(char *line)
 62{
 63	memcpy(fpe_type, line, 8);
 64	return 1;
 65}
 66
 67__setup("fpe=", fpe_setup);
 68#endif
 69
 70extern void paging_init(struct machine_desc *desc);
 71extern void reboot_setup(char *str);
 72
 73unsigned int processor_id;
 74EXPORT_SYMBOL(processor_id);
 75unsigned int __machine_arch_type;
 76EXPORT_SYMBOL(__machine_arch_type);
 77unsigned int cacheid;
 78EXPORT_SYMBOL(cacheid);
 79
 80unsigned int __atags_pointer __initdata;
 81
 82unsigned int system_rev;
 83EXPORT_SYMBOL(system_rev);
 84
 85unsigned int system_serial_low;
 86EXPORT_SYMBOL(system_serial_low);
 87
 88unsigned int system_serial_high;
 89EXPORT_SYMBOL(system_serial_high);
 90
 91unsigned int elf_hwcap;
 92EXPORT_SYMBOL(elf_hwcap);
 93
 94unsigned int boot_reason;
 95EXPORT_SYMBOL(boot_reason);
 96
 97#ifdef MULTI_CPU
 98struct processor processor;
 99#endif
100#ifdef MULTI_TLB
101struct cpu_tlb_fns cpu_tlb;
102#endif
103#ifdef MULTI_USER
104struct cpu_user_fns cpu_user;
105#endif
106#ifdef MULTI_CACHE
107struct cpu_cache_fns cpu_cache;
108#endif
109#ifdef CONFIG_OUTER_CACHE
110struct outer_cache_fns outer_cache;
111EXPORT_SYMBOL(outer_cache);
112#endif
113
114struct stack {
115	u32 irq[3];
116	u32 abt[3];
117	u32 und[3];
118} ____cacheline_aligned;
119
120static struct stack stacks[NR_CPUS];
121
122char elf_platform[ELF_PLATFORM_SIZE];
123EXPORT_SYMBOL(elf_platform);
124
125static const char *cpu_name;
126static const char *machine_name;
127static char __initdata cmd_line[COMMAND_LINE_SIZE];
128
129static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
130static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
131#define ENDIANNESS ((char)endian_test.l)
132
133DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
134
135/*
136 * Standard memory resources
137 */
138static struct resource mem_res[] = {
139	{
140		.name = "Video RAM",
141		.start = 0,
142		.end = 0,
143		.flags = IORESOURCE_MEM
144	},
145	{
146		.name = "Kernel text",
147		.start = 0,
148		.end = 0,
149		.flags = IORESOURCE_MEM
150	},
151	{
152		.name = "Kernel data",
153		.start = 0,
154		.end = 0,
155		.flags = IORESOURCE_MEM
156	}
157};
158
159#define video_ram   mem_res[0]
160#define kernel_code mem_res[1]
161#define kernel_data mem_res[2]
162
163static struct resource io_res[] = {
164	{
165		.name = "reserved",
166		.start = 0x3bc,
167		.end = 0x3be,
168		.flags = IORESOURCE_IO | IORESOURCE_BUSY
169	},
170	{
171		.name = "reserved",
172		.start = 0x378,
173		.end = 0x37f,
174		.flags = IORESOURCE_IO | IORESOURCE_BUSY
175	},
176	{
177		.name = "reserved",
178		.start = 0x278,
179		.end = 0x27f,
180		.flags = IORESOURCE_IO | IORESOURCE_BUSY
181	}
182};
183
184#define lp0 io_res[0]
185#define lp1 io_res[1]
186#define lp2 io_res[2]
187
188static const char *proc_arch[] = {
189	"undefined/unknown",
190	"3",
191	"4",
192	"4T",
193	"5",
194	"5T",
195	"5TE",
196	"5TEJ",
197	"6TEJ",
198	"7",
199	"?(11)",
200	"?(12)",
201	"?(13)",
202	"?(14)",
203	"?(15)",
204	"?(16)",
205	"?(17)",
206};
207
208int cpu_architecture(void)
209{
210	int cpu_arch;
211
212	if ((read_cpuid_id() & 0x0008f000) == 0) {
213		cpu_arch = CPU_ARCH_UNKNOWN;
214	} else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
215		cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
216	} else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
217		cpu_arch = (read_cpuid_id() >> 16) & 7;
218		if (cpu_arch)
219			cpu_arch += CPU_ARCH_ARMv3;
220	} else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
221		unsigned int mmfr0;
222
223		/* Revised CPUID format. Read the Memory Model Feature
224		 * Register 0 and check for VMSAv7 or PMSAv7 */
225		asm("mrc	p15, 0, %0, c0, c1, 4"
226		    : "=r" (mmfr0));
227		if ((mmfr0 & 0x0000000f) == 0x00000003 ||
228		    (mmfr0 & 0x000000f0) == 0x00000030)
229			cpu_arch = CPU_ARCH_ARMv7;
230		else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
231			 (mmfr0 & 0x000000f0) == 0x00000020)
232			cpu_arch = CPU_ARCH_ARMv6;
233		else
234			cpu_arch = CPU_ARCH_UNKNOWN;
235	} else
236		cpu_arch = CPU_ARCH_UNKNOWN;
237
238	return cpu_arch;
239}
240
241static void __init cacheid_init(void)
242{
243	unsigned int cachetype = read_cpuid_cachetype();
244	unsigned int arch = cpu_architecture();
245
246	if (arch >= CPU_ARCH_ARMv6) {
247		if ((cachetype & (7 << 29)) == 4 << 29) {
248			/* ARMv7 register format */
249			cacheid = CACHEID_VIPT_NONALIASING;
250			if ((cachetype & (3 << 14)) == 1 << 14)
251				cacheid |= CACHEID_ASID_TAGGED;
252		} else if (cachetype & (1 << 23))
253			cacheid = CACHEID_VIPT_ALIASING;
254		else
255			cacheid = CACHEID_VIPT_NONALIASING;
256	} else {
257		cacheid = CACHEID_VIVT;
258	}
259
260	printk("CPU: %s data cache, %s instruction cache\n",
261		cache_is_vivt() ? "VIVT" :
262		cache_is_vipt_aliasing() ? "VIPT aliasing" :
263		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
264		cache_is_vivt() ? "VIVT" :
265		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
266		cache_is_vipt_aliasing() ? "VIPT aliasing" :
267		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
268}
269
270/*
271 * These functions re-use the assembly code in head.S, which
272 * already provide the required functionality.
273 */
274extern struct proc_info_list *lookup_processor_type(unsigned int);
275extern struct machine_desc *lookup_machine_type(unsigned int);
276
277static void __init setup_processor(void)
278{
279	struct proc_info_list *list;
280
281	/*
282	 * locate processor in the list of supported processor
283	 * types.  The linker builds this table for us from the
284	 * entries in arch/arm/mm/proc-*.S
285	 */
286	list = lookup_processor_type(read_cpuid_id());
287	if (!list) {
288		printk("CPU configuration botched (ID %08x), unable "
289		       "to continue.\n", read_cpuid_id());
290		while (1);
291	}
292
293	cpu_name = list->cpu_name;
294
295#ifdef MULTI_CPU
296	processor = *list->proc;
297#endif
298#ifdef MULTI_TLB
299	cpu_tlb = *list->tlb;
300#endif
301#ifdef MULTI_USER
302	cpu_user = *list->user;
303#endif
304#ifdef MULTI_CACHE
305	cpu_cache = *list->cache;
306#endif
307
308	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
309	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
310	       proc_arch[cpu_architecture()], cr_alignment);
311
312	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
313	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
314	elf_hwcap = list->elf_hwcap;
315#ifndef CONFIG_ARM_THUMB
316	elf_hwcap &= ~HWCAP_THUMB;
317#endif
318
319	cacheid_init();
320	cpu_proc_init();
321}
322
323/*
324 * cpu_init - initialise one CPU.
325 *
326 * cpu_init sets up the per-CPU stacks.
327 */
328void cpu_init(void)
329{
330	unsigned int cpu = smp_processor_id();
331	struct stack *stk = &stacks[cpu];
332
333	if (cpu >= NR_CPUS) {
334		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
335		BUG();
336	}
337
338	/*
339	 * Define the placement constraint for the inline asm directive below.
340	 * In Thumb-2, msr with an immediate value is not allowed.
341	 */
342#ifdef CONFIG_THUMB2_KERNEL
343#define PLC	"r"
344#else
345#define PLC	"I"
346#endif
347
348	/*
349	 * setup stacks for re-entrant exception handlers
350	 */
351	__asm__ (
352	"msr	cpsr_c, %1\n\t"
353	"add	r14, %0, %2\n\t"
354	"mov	sp, r14\n\t"
355	"msr	cpsr_c, %3\n\t"
356	"add	r14, %0, %4\n\t"
357	"mov	sp, r14\n\t"
358	"msr	cpsr_c, %5\n\t"
359	"add	r14, %0, %6\n\t"
360	"mov	sp, r14\n\t"
361	"msr	cpsr_c, %7"
362	    :
363	    : "r" (stk),
364	      PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
365	      "I" (offsetof(struct stack, irq[0])),
366	      PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
367	      "I" (offsetof(struct stack, abt[0])),
368	      PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
369	      "I" (offsetof(struct stack, und[0])),
370	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
371	    : "r14");
372}
373
374static struct machine_desc * __init setup_machine(unsigned int nr)
375{
376	struct machine_desc *list;
377
378	/*
379	 * locate machine in the list of supported machines.
380	 */
381	list = lookup_machine_type(nr);
382	if (!list) {
383		printk("Machine configuration botched (nr %d), unable "
384		       "to continue.\n", nr);
385		while (1);
386	}
387
388	printk("Machine: %s\n", list->name);
389
390	return list;
391}
392
393static int __init arm_add_memory(unsigned long start, unsigned long size)
394{
395	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
396
397	if (meminfo.nr_banks >= NR_BANKS) {
398		printk(KERN_CRIT "NR_BANKS too low, "
399			"ignoring memory at %#lx\n", start);
400		return -EINVAL;
401	}
402
403	/*
404	 * Ensure that start/size are aligned to a page boundary.
405	 * Size is appropriately rounded down, start is rounded up.
406	 */
407	size -= start & ~PAGE_MASK;
408	bank->start = PAGE_ALIGN(start);
409	bank->size  = size & PAGE_MASK;
410	bank->node  = PHYS_TO_NID(start);
411
412	/*
413	 * Check whether this memory region has non-zero size or
414	 * invalid node number.
415	 */
416	if (bank->size == 0 || bank->node >= MAX_NUMNODES)
417		return -EINVAL;
418
419	meminfo.nr_banks++;
420	return 0;
421}
422
423/*
424 * Pick out the memory size.  We look for mem=size@start,
425 * where start and size are "size[KkMm]"
426 */
427static int __init early_mem(char *p)
428{
429	static int usermem __initdata = 0;
430	unsigned long size, start;
431	char *endp;
432
433	/*
434	 * If the user specifies memory size, we
435	 * blow away any automatically generated
436	 * size.
437	 */
438	if (usermem == 0) {
439		usermem = 1;
440		meminfo.nr_banks = 0;
441	}
442
443	start = PHYS_OFFSET;
444	size  = memparse(p, &endp);
445	if (*endp == '@')
446		start = memparse(endp + 1, NULL);
447
448	arm_add_memory(start, size);
449
450	return 0;
451}
452early_param("mem", early_mem);
453
454#ifdef CONFIG_MEMORY_HOTPLUG
455static void __init early_mem_reserved(char **p)
456{
457	unsigned int start;
458	unsigned int size;
459	unsigned int end;
460	unsigned int h_end;
461
462	start = PHYS_OFFSET;
463	size  = memparse(*p, p);
464	if (**p == '@')
465		start = memparse(*p + 1, p);
466
467	if (movable_reserved_start) {
468		end = start + size;
469		h_end = movable_reserved_start + movable_reserved_size;
470		end = max(end, h_end);
471		movable_reserved_start = min(movable_reserved_start,
472			(unsigned long)start);
473		movable_reserved_size = end - movable_reserved_start;
474	} else {
475		movable_reserved_start = start;
476		movable_reserved_size = size;
477	}
478}
479__early_param("mem_reserved=", early_mem_reserved);
480
481static void __init early_mem_low_power(char **p)
482{
483	unsigned int start;
484	unsigned int size;
485	unsigned int end;
486	unsigned int h_end;
487
488	start = PHYS_OFFSET;
489	size  = memparse(*p, p);
490	if (**p == '@')
491		start = memparse(*p + 1, p);
492
493	if (low_power_memory_start) {
494		end = start + size;
495		h_end = low_power_memory_start + low_power_memory_size;
496		end = max(end, h_end);
497		low_power_memory_start = min(low_power_memory_start,
498			(unsigned long)start);
499		low_power_memory_size = end - low_power_memory_start;
500	} else {
501		low_power_memory_start = start;
502		low_power_memory_size = size;
503	}
504
505	arm_add_memory(start, size);
506}
507__early_param("mem_low_power=", early_mem_low_power);
508#endif
509
510static void __init
511setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
512{
513#ifdef CONFIG_BLK_DEV_RAM
514	extern int rd_size, rd_image_start, rd_prompt, rd_doload;
515
516	rd_image_start = image_start;
517	rd_prompt = prompt;
518	rd_doload = doload;
519
520	if (rd_sz)
521		rd_size = rd_sz;
522#endif
523}
524
525static void __init
526request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
527{
528	struct resource *res;
529	int i;
530
531	kernel_code.start   = virt_to_phys(_text);
532	kernel_code.end     = virt_to_phys(_etext - 1);
533	kernel_data.start   = virt_to_phys(_data);
534	kernel_data.end     = virt_to_phys(_end - 1);
535
536	for (i = 0; i < mi->nr_banks; i++) {
537		if (mi->bank[i].size == 0)
538			continue;
539
540		res = alloc_bootmem_low(sizeof(*res));
541		res->name  = "System RAM";
542		res->start = mi->bank[i].start;
543		res->end   = mi->bank[i].start + mi->bank[i].size - 1;
544		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
545
546		request_resource(&iomem_resource, res);
547
548		if (kernel_code.start >= res->start &&
549		    kernel_code.end <= res->end)
550			request_resource(res, &kernel_code);
551		if (kernel_data.start >= res->start &&
552		    kernel_data.end <= res->end)
553			request_resource(res, &kernel_data);
554	}
555
556	if (mdesc->video_start) {
557		video_ram.start = mdesc->video_start;
558		video_ram.end   = mdesc->video_end;
559		request_resource(&iomem_resource, &video_ram);
560	}
561
562	/*
563	 * Some machines don't have the possibility of ever
564	 * possessing lp0, lp1 or lp2
565	 */
566	if (mdesc->reserve_lp0)
567		request_resource(&ioport_resource, &lp0);
568	if (mdesc->reserve_lp1)
569		request_resource(&ioport_resource, &lp1);
570	if (mdesc->reserve_lp2)
571		request_resource(&ioport_resource, &lp2);
572}
573
574/*
575 *  Tag parsing.
576 *
577 * This is the new way of passing data to the kernel at boot time.  Rather
578 * than passing a fixed inflexible structure to the kernel, we pass a list
579 * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
580 * tag for the list to be recognised (to distinguish the tagged list from
581 * a param_struct).  The list is terminated with a zero-length tag (this tag
582 * is not parsed in any way).
583 */
584static int __init parse_tag_core(const struct tag *tag)
585{
586	if (tag->hdr.size > 2) {
587		if ((tag->u.core.flags & 1) == 0)
588			root_mountflags &= ~MS_RDONLY;
589		ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
590	}
591	return 0;
592}
593
594__tagtable(ATAG_CORE, parse_tag_core);
595
596static int __init parse_tag_mem32(const struct tag *tag)
597{
598	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
599}
600
601__tagtable(ATAG_MEM, parse_tag_mem32);
602
603#ifdef CONFIG_MEMORY_HOTPLUG
604static int __init parse_tag_mem32_reserved(const struct tag *tag)
605{
606	unsigned int start;
607	unsigned int size;
608	unsigned int end;
609	unsigned int h_end;
610
611	start = tag->u.mem.start;
612	size = tag->u.mem.size;
613
614	if (movable_reserved_start) {
615		end = start + size;
616		h_end = movable_reserved_start + movable_reserved_size;
617		end = max(end, h_end);
618		movable_reserved_start = min(movable_reserved_start,
619			(unsigned long)start);
620		movable_reserved_size = end - movable_reserved_start;
621	} else {
622		movable_reserved_start = tag->u.mem.start;
623		movable_reserved_size = tag->u.mem.size;
624	}
625	printk(KERN_ALERT "reserved %lx at %lx for hotplug\n",
626		movable_reserved_size, movable_reserved_start);
627
628	return 0;
629}
630
631__tagtable(ATAG_MEM_RESERVED, parse_tag_mem32_reserved);
632
633static int __init parse_tag_mem32_low_power(const struct tag *tag)
634{
635	unsigned int start;
636	unsigned int size;
637	unsigned int end;
638	unsigned int h_end;
639
640	start = tag->u.mem.start;
641	size = tag->u.mem.size;
642
643	if (low_power_memory_start) {
644		end = start + size;
645		h_end = low_power_memory_start + low_power_memory_size;
646		end = max(end, h_end);
647		low_power_memory_start = min(low_power_memory_start,
648			(unsigned long)start);
649		low_power_memory_size = end - low_power_memory_start;
650	} else {
651		low_power_memory_start = tag->u.mem.start;
652		low_power_memory_size = tag->u.mem.size;
653	}
654	printk(KERN_ALERT "low power memory %lx at %lx\n",
655		low_power_memory_size, low_power_memory_start);
656
657	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
658}
659
660__tagtable(ATAG_MEM_LOW_POWER, parse_tag_mem32_low_power);
661#endif
662
663#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
664struct screen_info screen_info = {
665 .orig_video_lines	= 30,
666 .orig_video_cols	= 80,
667 .orig_video_mode	= 0,
668 .orig_video_ega_bx	= 0,
669 .orig_video_isVGA	= 1,
670 .orig_video_points	= 8
671};
672
673static int __init parse_tag_videotext(const struct tag *tag)
674{
675	screen_info.orig_x            = tag->u.videotext.x;
676	screen_info.orig_y            = tag->u.videotext.y;
677	screen_info.orig_video_page   = tag->u.videotext.video_page;
678	screen_info.orig_video_mode   = tag->u.videotext.video_mode;
679	screen_info.orig_video_cols   = tag->u.videotext.video_cols;
680	screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
681	screen_info.orig_video_lines  = tag->u.videotext.video_lines;
682	screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
683	screen_info.orig_video_points = tag->u.videotext.video_points;
684	return 0;
685}
686
687__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
688#endif
689
690static int __init parse_tag_ramdisk(const struct tag *tag)
691{
692	setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
693		      (tag->u.ramdisk.flags & 2) == 0,
694		      tag->u.ramdisk.start, tag->u.ramdisk.size);
695	return 0;
696}
697
698__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
699
700static int __init parse_tag_serialnr(const struct tag *tag)
701{
702	system_serial_low = tag->u.serialnr.low;
703	system_serial_high = tag->u.serialnr.high;
704	return 0;
705}
706
707__tagtable(ATAG_SERIAL, parse_tag_serialnr);
708
709static int __init parse_tag_revision(const struct tag *tag)
710{
711	system_rev = tag->u.revision.rev;
712	return 0;
713}
714
715__tagtable(ATAG_REVISION, parse_tag_revision);
716
717#ifndef CONFIG_CMDLINE_FORCE
718static int __init parse_tag_cmdline(const struct tag *tag)
719{
720	strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
721	return 0;
722}
723
724__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
725#endif /* CONFIG_CMDLINE_FORCE */
726
727/*
728 * Scan the tag table for this tag, and call its parse function.
729 * The tag table is built by the linker from all the __tagtable
730 * declarations.
731 */
732static int __init parse_tag(const struct tag *tag)
733{
734	extern struct tagtable __tagtable_begin, __tagtable_end;
735	struct tagtable *t;
736
737	for (t = &__tagtable_begin; t < &__tagtable_end; t++)
738		if (tag->hdr.tag == t->tag) {
739			t->parse(tag);
740			break;
741		}
742
743	return t < &__tagtable_end;
744}
745
746/*
747 * Parse all tags in the list, checking both the global and architecture
748 * specific tag tables.
749 */
750static void __init parse_tags(const struct tag *t)
751{
752	for (; t->hdr.size; t = tag_next(t))
753		if (!parse_tag(t))
754			printk(KERN_WARNING
755				"Ignoring unrecognised tag 0x%08x\n",
756				t->hdr.tag);
757}
758
759/*
760 * This holds our defaults.
761 */
762static struct init_tags {
763	struct tag_header hdr1;
764	struct tag_core   core;
765	struct tag_header hdr2;
766	struct tag_mem32  mem;
767	struct tag_header hdr3;
768} init_tags __initdata = {
769	{ tag_size(tag_core), ATAG_CORE },
770	{ 1, PAGE_SIZE, 0xff },
771	{ tag_size(tag_mem32), ATAG_MEM },
772	{ MEM_SIZE, PHYS_OFFSET },
773	{ 0, ATAG_NONE }
774};
775
776static void (*init_machine)(void) __initdata;
777
778static int __init customize_machine(void)
779{
780	/* customizes platform devices, or adds new ones */
781	if (init_machine)
782		init_machine();
783	return 0;
784}
785arch_initcall(customize_machine);
786
787void __init setup_arch(char **cmdline_p)
788{
789	struct tag *tags = (struct tag *)&init_tags;
790	struct machine_desc *mdesc;
791	char *from = default_command_line;
792
793	unwind_init();
794
795	setup_processor();
796	mdesc = setup_machine(machine_arch_type);
797	machine_name = mdesc->name;
798
799	if (mdesc->soft_reboot)
800		reboot_setup("s");
801
802	if (__atags_pointer)
803		tags = phys_to_virt(__atags_pointer);
804	else if (mdesc->boot_params)
805		tags = phys_to_virt(mdesc->boot_params);
806
807	/*
808	 * If we have the old style parameters, convert them to
809	 * a tag list.
810	 */
811	if (tags->hdr.tag != ATAG_CORE)
812		convert_to_tag_list(tags);
813	if (tags->hdr.tag != ATAG_CORE)
814		tags = (struct tag *)&init_tags;
815
816	if (mdesc->fixup)
817		mdesc->fixup(mdesc, tags, &from, &meminfo);
818
819	if (tags->hdr.tag == ATAG_CORE) {
820		if (meminfo.nr_banks != 0)
821			squash_mem_tags(tags);
822		save_atags(tags);
823		parse_tags(tags);
824	}
825
826	init_mm.start_code = (unsigned long) _text;
827	init_mm.end_code   = (unsigned long) _etext;
828	init_mm.end_data   = (unsigned long) _edata;
829	init_mm.brk	   = (unsigned long) _end;
830
831	/* parse_early_param needs a boot_command_line */
832	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
833
834	/* populate cmd_line too for later use, preserving boot_command_line */
835	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
836	*cmdline_p = cmd_line;
837
838	parse_early_param();
839
840	paging_init(mdesc);
841	request_standard_resources(&meminfo, mdesc);
842
843#ifdef CONFIG_SMP
844	smp_init_cpus();
845#endif
846
847	cpu_init();
848	tcm_init();
849
850	/*
851	 * Set up various architecture-specific pointers
852	 */
853	init_arch_irq = mdesc->init_irq;
854	system_timer = mdesc->timer;
855	init_machine = mdesc->init_machine;
856
857#ifdef CONFIG_VT
858#if defined(CONFIG_VGA_CONSOLE)
859	conswitchp = &vga_con;
860#elif defined(CONFIG_DUMMY_CONSOLE)
861	conswitchp = &dummy_con;
862#endif
863#endif
864	early_trap_init();
865}
866
867
868static int __init topology_init(void)
869{
870	int cpu;
871
872	for_each_possible_cpu(cpu) {
873		struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
874		cpuinfo->cpu.hotpluggable = 1;
875		register_cpu(&cpuinfo->cpu, cpu);
876	}
877
878	return 0;
879}
880subsys_initcall(topology_init);
881
882#ifdef CONFIG_HAVE_PROC_CPU
883static int __init proc_cpu_init(void)
884{
885	struct proc_dir_entry *res;
886
887	res = proc_mkdir("cpu", NULL);
888	if (!res)
889		return -ENOMEM;
890	return 0;
891}
892fs_initcall(proc_cpu_init);
893#endif
894
895static const char *hwcap_str[] = {
896	"swp",
897	"half",
898	"thumb",
899	"26bit",
900	"fastmult",
901	"fpa",
902	"vfp",
903	"edsp",
904	"java",
905	"iwmmxt",
906	"crunch",
907	"thumbee",
908	"neon",
909	"vfpv3",
910	"vfpv3d16",
911	NULL
912};
913
914static int c_show(struct seq_file *m, void *v)
915{
916	int i;
917
918	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
919		   cpu_name, read_cpuid_id() & 15, elf_platform);
920
921#if defined(CONFIG_SMP)
922	for_each_online_cpu(i) {
923		/*
924		 * glibc reads /proc/cpuinfo to determine the number of
925		 * online processors, looking for lines beginning with
926		 * "processor".  Give glibc what it expects.
927		 */
928		seq_printf(m, "processor\t: %d\n", i);
929		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
930			   per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
931			   (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
932	}
933#else /* CONFIG_SMP */
934	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
935		   loops_per_jiffy / (500000/HZ),
936		   (loops_per_jiffy / (5000/HZ)) % 100);
937#endif
938
939	/* dump out the processor features */
940	seq_puts(m, "Features\t: ");
941
942	for (i = 0; hwcap_str[i]; i++)
943		if (elf_hwcap & (1 << i))
944			seq_printf(m, "%s ", hwcap_str[i]);
945
946	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
947	seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
948
949	if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
950		/* pre-ARM7 */
951		seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
952	} else {
953		if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
954			/* ARM7 */
955			seq_printf(m, "CPU variant\t: 0x%02x\n",
956				   (read_cpuid_id() >> 16) & 127);
957		} else {
958			/* post-ARM7 */
959			seq_printf(m, "CPU variant\t: 0x%x\n",
960				   (read_cpuid_id() >> 20) & 15);
961		}
962		seq_printf(m, "CPU part\t: 0x%03x\n",
963			   (read_cpuid_id() >> 4) & 0xfff);
964	}
965	seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
966
967	seq_puts(m, "\n");
968
969	seq_printf(m, "Hardware\t: %s\n", machine_name);
970	seq_printf(m, "Revision\t: %04x\n", system_rev);
971	seq_printf(m, "Serial\t\t: %08x%08x\n",
972		   system_serial_high, system_serial_low);
973
974	return 0;
975}
976
977static void *c_start(struct seq_file *m, loff_t *pos)
978{
979	return *pos < 1 ? (void *)1 : NULL;
980}
981
982static void *c_next(struct seq_file *m, void *v, loff_t *pos)
983{
984	++*pos;
985	return NULL;
986}
987
988static void c_stop(struct seq_file *m, void *v)
989{
990}
991
992const struct seq_operations cpuinfo_op = {
993	.start	= c_start,
994	.next	= c_next,
995	.stop	= c_stop,
996	.show	= c_show
997};