874 lines · 19.7 KB · C
RawDownload
/* *  linux/arch/arm/kernel/setup.c * *  Copyright (C) 1995-2001 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/stddef.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/utsname.h>#include <linux/initrd.h>#include <linux/console.h>#include <linux/bootmem.h>#include <linux/seq_file.h>#include <linux/screen_info.h>#include <linux/init.h>#include <linux/root_dev.h>#include <linux/cpu.h>#include <linux/interrupt.h>#include <linux/smp.h>#include <linux/fs.h> #include <asm/cpu.h>#include <asm/cputype.h>#include <asm/elf.h>#include <asm/procinfo.h>#include <asm/sections.h>#include <asm/setup.h>#include <asm/mach-types.h>#include <asm/cacheflush.h>#include <asm/cachetype.h>#include <asm/tlbflush.h> #include <asm/mach/arch.h>#include <asm/mach/irq.h>#include <asm/mach/time.h>#include <asm/traps.h>#include <asm/unwind.h> #include "compat.h"#include "atags.h" #ifndef MEM_SIZE#define MEM_SIZE	(16*1024*1024)#endif #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)char fpe_type[8]; static int __init fpe_setup(char *line){	memcpy(fpe_type, line, 8);	return 1;} __setup("fpe=", fpe_setup);#endif extern void paging_init(struct machine_desc *desc);extern void reboot_setup(char *str); unsigned int processor_id;EXPORT_SYMBOL(processor_id);unsigned int __machine_arch_type;EXPORT_SYMBOL(__machine_arch_type);unsigned int cacheid;EXPORT_SYMBOL(cacheid); unsigned int __atags_pointer __initdata; unsigned int system_rev;EXPORT_SYMBOL(system_rev); unsigned int system_serial_low;EXPORT_SYMBOL(system_serial_low); unsigned int system_serial_high;EXPORT_SYMBOL(system_serial_high); unsigned int elf_hwcap;EXPORT_SYMBOL(elf_hwcap);  #ifdef MULTI_CPUstruct processor processor;#endif#ifdef MULTI_TLBstruct cpu_tlb_fns cpu_tlb;#endif#ifdef MULTI_USERstruct cpu_user_fns cpu_user;#endif#ifdef MULTI_CACHEstruct cpu_cache_fns cpu_cache;#endif#ifdef CONFIG_OUTER_CACHEstruct outer_cache_fns outer_cache;#endif struct stack {	u32 irq[3];	u32 abt[3];	u32 und[3];} ____cacheline_aligned; static struct stack stacks[NR_CPUS]; char elf_platform[ELF_PLATFORM_SIZE];EXPORT_SYMBOL(elf_platform); static const char *cpu_name;static const char *machine_name;static char __initdata command_line[COMMAND_LINE_SIZE]; static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };#define ENDIANNESS ((char)endian_test.l) DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data); /* * Standard memory resources */static struct resource mem_res[] = {	{		.name = "Video RAM",		.start = 0,		.end = 0,		.flags = IORESOURCE_MEM	},	{		.name = "Kernel text",		.start = 0,		.end = 0,		.flags = IORESOURCE_MEM	},	{		.name = "Kernel data",		.start = 0,		.end = 0,		.flags = IORESOURCE_MEM	}}; #define video_ram   mem_res[0]#define kernel_code mem_res[1]#define kernel_data mem_res[2] static struct resource io_res[] = {	{		.name = "reserved",		.start = 0x3bc,		.end = 0x3be,		.flags = IORESOURCE_IO | IORESOURCE_BUSY	},	{		.name = "reserved",		.start = 0x378,		.end = 0x37f,		.flags = IORESOURCE_IO | IORESOURCE_BUSY	},	{		.name = "reserved",		.start = 0x278,		.end = 0x27f,		.flags = IORESOURCE_IO | IORESOURCE_BUSY	}}; #define lp0 io_res[0]#define lp1 io_res[1]#define lp2 io_res[2] static const char *proc_arch[] = {	"undefined/unknown",	"3",	"4",	"4T",	"5",	"5T",	"5TE",	"5TEJ",	"6TEJ",	"7",	"?(11)",	"?(12)",	"?(13)",	"?(14)",	"?(15)",	"?(16)",	"?(17)",}; int cpu_architecture(void){	int cpu_arch; 	if ((read_cpuid_id() & 0x0008f000) == 0) {		cpu_arch = CPU_ARCH_UNKNOWN;	} else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {		cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;	} else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {		cpu_arch = (read_cpuid_id() >> 16) & 7;		if (cpu_arch)			cpu_arch += CPU_ARCH_ARMv3;	} else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {		unsigned int mmfr0; 		/* Revised CPUID format. Read the Memory Model Feature		 * Register 0 and check for VMSAv7 or PMSAv7 */		asm("mrc	p15, 0, %0, c0, c1, 4"		    : "=r" (mmfr0));		if ((mmfr0 & 0x0000000f) == 0x00000003 ||		    (mmfr0 & 0x000000f0) == 0x00000030)			cpu_arch = CPU_ARCH_ARMv7;		else if ((mmfr0 & 0x0000000f) == 0x00000002 ||			 (mmfr0 & 0x000000f0) == 0x00000020)			cpu_arch = CPU_ARCH_ARMv6;		else			cpu_arch = CPU_ARCH_UNKNOWN;	} else		cpu_arch = CPU_ARCH_UNKNOWN; 	return cpu_arch;} static void __init cacheid_init(void){	unsigned int cachetype = read_cpuid_cachetype();	unsigned int arch = cpu_architecture(); 	if (arch >= CPU_ARCH_ARMv6) {		if ((cachetype & (7 << 29)) == 4 << 29) {			/* ARMv7 register format */			cacheid = CACHEID_VIPT_NONALIASING;			if ((cachetype & (3 << 14)) == 1 << 14)				cacheid |= CACHEID_ASID_TAGGED;		} else if (cachetype & (1 << 23))			cacheid = CACHEID_VIPT_ALIASING;		else			cacheid = CACHEID_VIPT_NONALIASING;	} else {		cacheid = CACHEID_VIVT;	} 	printk("CPU: %s data cache, %s instruction cache\n",		cache_is_vivt() ? "VIVT" :		cache_is_vipt_aliasing() ? "VIPT aliasing" :		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",		cache_is_vivt() ? "VIVT" :		icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :		cache_is_vipt_aliasing() ? "VIPT aliasing" :		cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");} /* * These functions re-use the assembly code in head.S, which * already provide the required functionality. */extern struct proc_info_list *lookup_processor_type(unsigned int);extern struct machine_desc *lookup_machine_type(unsigned int); static void __init setup_processor(void){	struct proc_info_list *list; 	/*	 * locate processor in the list of supported processor	 * types.  The linker builds this table for us from the	 * entries in arch/arm/mm/proc-*.S	 */	list = lookup_processor_type(read_cpuid_id());	if (!list) {		printk("CPU configuration botched (ID %08x), unable "		       "to continue.\n", read_cpuid_id());		while (1);	} 	cpu_name = list->cpu_name; #ifdef MULTI_CPU	processor = *list->proc;#endif#ifdef MULTI_TLB	cpu_tlb = *list->tlb;#endif#ifdef MULTI_USER	cpu_user = *list->user;#endif#ifdef MULTI_CACHE	cpu_cache = *list->cache;#endif 	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,	       proc_arch[cpu_architecture()], cr_alignment); 	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);	elf_hwcap = list->elf_hwcap;#ifndef CONFIG_ARM_THUMB	elf_hwcap &= ~HWCAP_THUMB;#endif 	cacheid_init();	cpu_proc_init();} /* * cpu_init - initialise one CPU. * * cpu_init sets up the per-CPU stacks. */void cpu_init(void){	unsigned int cpu = smp_processor_id();	struct stack *stk = &stacks[cpu]; 	if (cpu >= NR_CPUS) {		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);		BUG();	} 	/*	 * setup stacks for re-entrant exception handlers	 */	__asm__ (	"msr	cpsr_c, %1\n\t"	"add	sp, %0, %2\n\t"	"msr	cpsr_c, %3\n\t"	"add	sp, %0, %4\n\t"	"msr	cpsr_c, %5\n\t"	"add	sp, %0, %6\n\t"	"msr	cpsr_c, %7"	    :	    : "r" (stk),	      "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),	      "I" (offsetof(struct stack, irq[0])),	      "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),	      "I" (offsetof(struct stack, abt[0])),	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),	      "I" (offsetof(struct stack, und[0])),	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)	    : "r14");} static struct machine_desc * __init setup_machine(unsigned int nr){	struct machine_desc *list; 	/*	 * locate machine in the list of supported machines.	 */	list = lookup_machine_type(nr);	if (!list) {		printk("Machine configuration botched (nr %d), unable "		       "to continue.\n", nr);		while (1);	} 	printk("Machine: %s\n", list->name); 	return list;} static int __init arm_add_memory(unsigned long start, unsigned long size){	struct membank *bank = &meminfo.bank[meminfo.nr_banks]; 	if (meminfo.nr_banks >= NR_BANKS) {		printk(KERN_CRIT "NR_BANKS too low, "			"ignoring memory at %#lx\n", start);		return -EINVAL;	} 	/*	 * Ensure that start/size are aligned to a page boundary.	 * Size is appropriately rounded down, start is rounded up.	 */	size -= start & ~PAGE_MASK;	bank->start = PAGE_ALIGN(start);	bank->size  = size & PAGE_MASK;	bank->node  = PHYS_TO_NID(start); 	/*	 * Check whether this memory region has non-zero size or	 * invalid node number.	 */	if (bank->size == 0 || bank->node >= MAX_NUMNODES)		return -EINVAL; 	meminfo.nr_banks++;	return 0;} /* * Pick out the memory size.  We look for mem=size@start, * where start and size are "size[KkMm]" */static void __init early_mem(char **p){	static int usermem __initdata = 0;	unsigned long size, start; 	/*	 * If the user specifies memory size, we	 * blow away any automatically generated	 * size.	 */	if (usermem == 0) {		usermem = 1;		meminfo.nr_banks = 0;	} 	start = PHYS_OFFSET;	size  = memparse(*p, p);	if (**p == '@')		start = memparse(*p + 1, p); 	arm_add_memory(start, size);}__early_param("mem=", early_mem); /* * Initial parsing of the command line. */static void __init parse_cmdline(char **cmdline_p, char *from){	char c = ' ', *to = command_line;	int len = 0; 	for (;;) {		if (c == ' ') {			extern struct early_params __early_begin, __early_end;			struct early_params *p; 			for (p = &__early_begin; p < &__early_end; p++) {				int arglen = strlen(p->arg); 				if (memcmp(from, p->arg, arglen) == 0) {					if (to != command_line)						to -= 1;					from += arglen;					p->fn(&from); 					while (*from != ' ' && *from != '\0')						from++;					break;				}			}		}		c = *from++;		if (!c)			break;		if (COMMAND_LINE_SIZE <= ++len)			break;		*to++ = c;	}	*to = '\0';	*cmdline_p = command_line;} static void __initsetup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz){#ifdef CONFIG_BLK_DEV_RAM	extern int rd_size, rd_image_start, rd_prompt, rd_doload; 	rd_image_start = image_start;	rd_prompt = prompt;	rd_doload = doload; 	if (rd_sz)		rd_size = rd_sz;#endif} static void __initrequest_standard_resources(struct meminfo *mi, struct machine_desc *mdesc){	struct resource *res;	int i; 	kernel_code.start   = virt_to_phys(_text);	kernel_code.end     = virt_to_phys(_etext - 1);	kernel_data.start   = virt_to_phys(_data);	kernel_data.end     = virt_to_phys(_end - 1); 	for (i = 0; i < mi->nr_banks; i++) {		if (mi->bank[i].size == 0)			continue; 		res = alloc_bootmem_low(sizeof(*res));		res->name  = "System RAM";		res->start = mi->bank[i].start;

Lines 1–500 of 874.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t