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/config.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/blk.h>
17 #include <linux/console.h>
18 #include <linux/bootmem.h>
19 #include <linux/seq_file.h>
20 #include <linux/list.h>
21 #include <linux/timer.h>
22 #include <linux/init.h>
23 
24 #include <asm/elf.h>
25 #include <asm/hardware.h>
26 #include <asm/io.h>
27 #include <asm/procinfo.h>
28 #include <asm/setup.h>
29 #include <asm/mach-types.h>
30 
31 #include <asm/mach/arch.h>
32 #include <asm/mach/irq.h>
33 
34 #ifndef MEM_SIZE
35 #define MEM_SIZE	(16*1024*1024)
36 #endif
37 
38 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
39 char fpe_type[8];
40 
fpe_setup(char * line)41 static int __init fpe_setup(char *line)
42 {
43 	memcpy(fpe_type, line, 8);
44 	return 1;
45 }
46 
47 __setup("fpe=", fpe_setup);
48 #endif
49 
50 extern unsigned int mem_fclk_21285;
51 extern void paging_init(struct meminfo *, struct machine_desc *desc);
52 extern void convert_to_tag_list(struct tag *tags);
53 extern void squash_mem_tags(struct tag *tag);
54 extern void bootmem_init(struct meminfo *);
55 extern void reboot_setup(char *str);
56 extern int root_mountflags;
57 extern int _stext, _text, _etext, _edata, _end;
58 
59 unsigned int processor_id;
60 unsigned int __machine_arch_type;
61 unsigned int system_rev;
62 unsigned int system_serial_low;
63 unsigned int system_serial_high;
64 unsigned int elf_hwcap;
65 
66 #ifdef MULTI_CPU
67 struct processor processor;
68 #endif
69 
70 unsigned char aux_device_present;
71 char elf_platform[ELF_PLATFORM_SIZE];
72 char saved_command_line[COMMAND_LINE_SIZE];
73 unsigned long phys_initrd_start __initdata = 0;
74 unsigned long phys_initrd_size __initdata = 0;
75 
76 static struct meminfo meminfo __initdata = { 0, };
77 static const char *cpu_name;
78 static const char *machine_name;
79 static char command_line[COMMAND_LINE_SIZE];
80 
81 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
82 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
83 #define ENDIANNESS ((char)endian_test.l)
84 
85 /*
86  * Standard memory resources
87  */
88 static struct resource mem_res[] = {
89 	{ "Video RAM",   0,     0,     IORESOURCE_MEM			},
90 	{ "Kernel code", 0,     0,     IORESOURCE_MEM			},
91 	{ "Kernel data", 0,     0,     IORESOURCE_MEM			}
92 };
93 
94 #define video_ram   mem_res[0]
95 #define kernel_code mem_res[1]
96 #define kernel_data mem_res[2]
97 
98 static struct resource io_res[] = {
99 	{ "reserved",    0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY },
100 	{ "reserved",    0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY },
101 	{ "reserved",    0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }
102 };
103 
104 #define lp0 io_res[0]
105 #define lp1 io_res[1]
106 #define lp2 io_res[2]
107 
setup_processor(void)108 static void __init setup_processor(void)
109 {
110 	extern struct proc_info_list __proc_info_begin, __proc_info_end;
111 	struct proc_info_list *list;
112 
113 	/*
114 	 * locate processor in the list of supported processor
115 	 * types.  The linker builds this table for us from the
116 	 * entries in arch/arm/mm/proc-*.S
117 	 */
118 	for (list = &__proc_info_begin; list < &__proc_info_end ; list++)
119 		if ((processor_id & list->cpu_mask) == list->cpu_val)
120 			break;
121 
122 	/*
123 	 * If processor type is unrecognised, then we
124 	 * can do nothing...
125 	 */
126 	if (list >= &__proc_info_end) {
127 		printk("CPU configuration botched (ID %08x), unable "
128 		       "to continue.\n", processor_id);
129 		while (1);
130 	}
131 
132 	cpu_name = list->info->cpu_name;
133 
134 #ifdef MULTI_CPU
135 	processor = *list->proc;
136 #endif
137 
138 	printk("CPU: %s revision %d\n", cpu_name, (int)processor_id & 15);
139 
140 	sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
141 	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
142 	elf_hwcap = list->elf_hwcap;
143 
144 	cpu_proc_init();
145 }
146 
setup_machine(unsigned int nr)147 static struct machine_desc * __init setup_machine(unsigned int nr)
148 {
149 	extern struct machine_desc __arch_info_begin, __arch_info_end;
150 	struct machine_desc *list;
151 
152 	/*
153 	 * locate architecture in the list of supported architectures.
154 	 */
155 	for (list = &__arch_info_begin; list < &__arch_info_end; list++)
156 		if (list->nr == nr)
157 			break;
158 
159 	/*
160 	 * If the architecture type is not recognised, then we
161 	 * can co nothing...
162 	 */
163 	if (list >= &__arch_info_end) {
164 		printk("Architecture configuration botched (nr %d), unable "
165 		       "to continue.\n", nr);
166 		while (1);
167 	}
168 
169 	printk("Machine: %s\n", list->name);
170 
171 	return list;
172 }
173 
174 /*
175  * Initial parsing of the command line.  We need to pick out the
176  * memory size.  We look for mem=size@start, where start and size
177  * are "size[KkMm]"
178  */
179 static void __init
parse_cmdline(struct meminfo * mi,char ** cmdline_p,char * from)180 parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from)
181 {
182 	char c = ' ', *to = command_line;
183 	int usermem = 0, len = 0;
184 
185 	for (;;) {
186 		if (c == ' ' && !memcmp(from, "mem=", 4)) {
187 			unsigned long size, start;
188 
189 			if (to != command_line)
190 				to -= 1;
191 
192 			/*
193 			 * If the user specifies memory size, we
194 			 * blow away any automatically generated
195 			 * size.
196 			 */
197 			if (usermem == 0) {
198 				usermem = 1;
199 				mi->nr_banks = 0;
200 			}
201 
202 			start = PHYS_OFFSET;
203 			size  = memparse(from + 4, &from);
204 			if (*from == '@')
205 				start = memparse(from + 1, &from);
206 
207 			mi->bank[mi->nr_banks].start = start;
208 			mi->bank[mi->nr_banks].size  = size;
209 			mi->bank[mi->nr_banks].node  = PHYS_TO_NID(start);
210 			mi->nr_banks += 1;
211 		} else if (c == ' ' && !memcmp(from, "initrd=", 7)) {
212 			unsigned long start, size;
213 
214 			/*
215 			 * Remove space character
216 			 */
217 			if (to != command_line)
218 				to -= 1;
219 
220 			start = memparse(from + 7, &from);
221 			if (*from == ',') {
222 				size = memparse(from + 1, &from);
223 
224 				phys_initrd_start = start;
225 				phys_initrd_size = size;
226 			}
227 		}
228 		c = *from++;
229 		if (!c)
230 			break;
231 		if (COMMAND_LINE_SIZE <= ++len)
232 			break;
233 		*to++ = c;
234 	}
235 	*to = '\0';
236 	*cmdline_p = command_line;
237 }
238 
239 void __init
setup_ramdisk(int doload,int prompt,int image_start,unsigned int rd_sz)240 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
241 {
242 #ifdef CONFIG_BLK_DEV_RAM
243 	extern int rd_size, rd_image_start, rd_prompt, rd_doload;
244 
245 	rd_image_start = image_start;
246 	rd_prompt = prompt;
247 	rd_doload = doload;
248 
249 	if (rd_sz)
250 		rd_size = rd_sz;
251 #endif
252 }
253 
254 /*
255  * initial ram disk
256  */
setup_initrd(unsigned int start,unsigned int size)257 void __init setup_initrd(unsigned int start, unsigned int size)
258 {
259 #ifdef CONFIG_BLK_DEV_INITRD
260 	if (start == 0)
261 		size = 0;
262 	phys_initrd_start = __virt_to_phys(start);
263 	phys_initrd_size = size;
264 #endif
265 }
266 
267 static void __init
request_standard_resources(struct meminfo * mi,struct machine_desc * mdesc)268 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
269 {
270 	struct resource *res;
271 	int i;
272 
273 	kernel_code.start  = __virt_to_phys(init_mm.start_code);
274 	kernel_code.end    = __virt_to_phys(init_mm.end_code - 1);
275 	kernel_data.start  = __virt_to_phys(init_mm.end_code);
276 	kernel_data.end    = __virt_to_phys(init_mm.brk - 1);
277 
278 	for (i = 0; i < mi->nr_banks; i++) {
279 		unsigned long virt_start, virt_end;
280 
281 		if (mi->bank[i].size == 0)
282 			continue;
283 
284 		virt_start = __phys_to_virt(mi->bank[i].start);
285 		virt_end   = virt_start + mi->bank[i].size - 1;
286 
287 		res = alloc_bootmem_low(sizeof(*res));
288 		res->name  = "System RAM";
289 		res->start = __virt_to_phys(virt_start);
290 		res->end   = __virt_to_phys(virt_end);
291 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
292 
293 		request_resource(&iomem_resource, res);
294 
295 		if (kernel_code.start >= res->start &&
296 		    kernel_code.end <= res->end)
297 			request_resource(res, &kernel_code);
298 		if (kernel_data.start >= res->start &&
299 		    kernel_data.end <= res->end)
300 			request_resource(res, &kernel_data);
301 	}
302 
303 	if (mdesc->video_start) {
304 		video_ram.start = mdesc->video_start;
305 		video_ram.end   = mdesc->video_end;
306 		request_resource(&iomem_resource, &video_ram);
307 	}
308 
309 	/*
310 	 * Some machines don't have the possibility of ever
311 	 * possessing lp0, lp1 or lp2
312 	 */
313 	if (mdesc->reserve_lp0)
314 		request_resource(&ioport_resource, &lp0);
315 	if (mdesc->reserve_lp1)
316 		request_resource(&ioport_resource, &lp1);
317 	if (mdesc->reserve_lp2)
318 		request_resource(&ioport_resource, &lp2);
319 }
320 
321 /*
322  *  Tag parsing.
323  *
324  * This is the new way of passing data to the kernel at boot time.  Rather
325  * than passing a fixed inflexible structure to the kernel, we pass a list
326  * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
327  * tag for the list to be recognised (to distinguish the tagged list from
328  * a param_struct).  The list is terminated with a zero-length tag (this tag
329  * is not parsed in any way).
330  */
parse_tag_core(const struct tag * tag)331 static int __init parse_tag_core(const struct tag *tag)
332 {
333 	if (tag->hdr.size > 2) {
334 		if ((tag->u.core.flags & 1) == 0)
335 			root_mountflags &= ~MS_RDONLY;
336 		ROOT_DEV = to_kdev_t(tag->u.core.rootdev);
337 	}
338 	return 0;
339 }
340 
341 __tagtable(ATAG_CORE, parse_tag_core);
342 
parse_tag_mem32(const struct tag * tag)343 static int __init parse_tag_mem32(const struct tag *tag)
344 {
345 	if (meminfo.nr_banks >= NR_BANKS) {
346 		printk(KERN_WARNING
347 		       "Ignoring memory bank 0x%08x size %dKB\n",
348 			tag->u.mem.start, tag->u.mem.size / 1024);
349 		return -EINVAL;
350 	}
351 	meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
352 	meminfo.bank[meminfo.nr_banks].size  = tag->u.mem.size;
353 	meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(tag->u.mem.start);
354 	meminfo.nr_banks += 1;
355 
356 	return 0;
357 }
358 
359 __tagtable(ATAG_MEM, parse_tag_mem32);
360 
361 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
362 struct screen_info screen_info = {
363  .orig_video_lines	= 30,
364  .orig_video_cols	= 80,
365  .orig_video_mode	= 0,
366  .orig_video_ega_bx	= 0,
367  .orig_video_isVGA	= 1,
368  .orig_video_points	= 8
369 };
370 
parse_tag_videotext(const struct tag * tag)371 static int __init parse_tag_videotext(const struct tag *tag)
372 {
373 	screen_info.orig_x            = tag->u.videotext.x;
374 	screen_info.orig_y            = tag->u.videotext.y;
375 	screen_info.orig_video_page   = tag->u.videotext.video_page;
376 	screen_info.orig_video_mode   = tag->u.videotext.video_mode;
377 	screen_info.orig_video_cols   = tag->u.videotext.video_cols;
378 	screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
379 	screen_info.orig_video_lines  = tag->u.videotext.video_lines;
380 	screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
381 	screen_info.orig_video_points = tag->u.videotext.video_points;
382 	return 0;
383 }
384 
385 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
386 #endif
387 
parse_tag_ramdisk(const struct tag * tag)388 static int __init parse_tag_ramdisk(const struct tag *tag)
389 {
390 	setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
391 		      (tag->u.ramdisk.flags & 2) == 0,
392 		      tag->u.ramdisk.start, tag->u.ramdisk.size);
393 	return 0;
394 }
395 
396 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
397 
parse_tag_initrd(const struct tag * tag)398 static int __init parse_tag_initrd(const struct tag *tag)
399 {
400 	phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
401 	phys_initrd_size = tag->u.initrd.size;
402 	return 0;
403 }
404 
405 __tagtable(ATAG_INITRD, parse_tag_initrd);
406 
parse_tag_initrd2(const struct tag * tag)407 static int __init parse_tag_initrd2(const struct tag *tag)
408 {
409 	phys_initrd_start = tag->u.initrd.start;
410 	phys_initrd_size = tag->u.initrd.size;
411 	return 0;
412 }
413 
414 __tagtable(ATAG_INITRD2, parse_tag_initrd2);
415 
parse_tag_serialnr(const struct tag * tag)416 static int __init parse_tag_serialnr(const struct tag *tag)
417 {
418 	system_serial_low = tag->u.serialnr.low;
419 	system_serial_high = tag->u.serialnr.high;
420 	return 0;
421 }
422 
423 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
424 
parse_tag_revision(const struct tag * tag)425 static int __init parse_tag_revision(const struct tag *tag)
426 {
427 	system_rev = tag->u.revision.rev;
428 	return 0;
429 }
430 
431 __tagtable(ATAG_REVISION, parse_tag_revision);
432 
parse_tag_cmdline(const struct tag * tag)433 static int __init parse_tag_cmdline(const struct tag *tag)
434 {
435 	strncpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
436 	default_command_line[COMMAND_LINE_SIZE - 1] = '\0';
437 	return 0;
438 }
439 
440 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
441 
442 /*
443  * Scan the tag table for this tag, and call its parse function.
444  * The tag table is built by the linker from all the __tagtable
445  * declarations.
446  */
parse_tag(const struct tag * tag)447 static int __init parse_tag(const struct tag *tag)
448 {
449 	extern struct tagtable __tagtable_begin, __tagtable_end;
450 	struct tagtable *t;
451 
452 	for (t = &__tagtable_begin; t < &__tagtable_end; t++)
453 		if (tag->hdr.tag == t->tag) {
454 			t->parse(tag);
455 			break;
456 		}
457 
458 	return t < &__tagtable_end;
459 }
460 
461 /*
462  * Parse all tags in the list, checking both the global and architecture
463  * specific tag tables.
464  */
parse_tags(const struct tag * t)465 static void __init parse_tags(const struct tag *t)
466 {
467 	for (; t->hdr.size; t = tag_next(t))
468 		if (!parse_tag(t))
469 			printk(KERN_WARNING
470 				"Ignoring unrecognised tag 0x%08x\n",
471 				t->hdr.tag);
472 }
473 
474 static struct init_tags {
475 	struct tag_header hdr1;
476 	struct tag_core   core;
477 	struct tag_header hdr2;
478 	struct tag_mem32  mem;
479 	struct tag_header hdr3;
480 } init_tags __initdata = {
481 	{ tag_size(tag_core), ATAG_CORE },
482 	{ 1, PAGE_SIZE, 0xff },
483 	{ tag_size(tag_mem32), ATAG_MEM },
484 	{ MEM_SIZE, PHYS_OFFSET },
485 	{ 0, ATAG_NONE }
486 };
487 
setup_arch(char ** cmdline_p)488 void __init setup_arch(char **cmdline_p)
489 {
490 	struct tag *tags = (struct tag *)&init_tags;
491 	struct machine_desc *mdesc;
492 	char *from = default_command_line;
493 
494 	ROOT_DEV = MKDEV(0, 255);
495 
496 	setup_processor();
497 	mdesc = setup_machine(machine_arch_type);
498 	machine_name = mdesc->name;
499 
500 	if (mdesc->soft_reboot)
501 		reboot_setup("s");
502 
503 	if (mdesc->param_offset)
504 		tags = phys_to_virt(mdesc->param_offset);
505 
506 	/*
507 	 * Do the machine-specific fixups before we parse the
508 	 * parameters or tags.
509 	 */
510 	if (mdesc->fixup)
511 		mdesc->fixup(mdesc, (struct param_struct *)tags,
512 			     &from, &meminfo);
513 
514 	/*
515 	 * If we have the old style parameters, convert them to
516 	 * a tag list.
517 	 */
518 	if (tags->hdr.tag != ATAG_CORE)
519 		convert_to_tag_list(tags);
520 
521 	if (tags->hdr.tag == ATAG_CORE) {
522 		if (meminfo.nr_banks != 0)
523 			squash_mem_tags(tags);
524 		parse_tags(tags);
525 	}
526 
527 	if (meminfo.nr_banks == 0) {
528 		meminfo.nr_banks      = 1;
529 		meminfo.bank[0].start = PHYS_OFFSET;
530 		meminfo.bank[0].size  = MEM_SIZE;
531 	}
532 
533 	init_mm.start_code = (unsigned long) &_text;
534 	init_mm.end_code   = (unsigned long) &_etext;
535 	init_mm.end_data   = (unsigned long) &_edata;
536 	init_mm.brk	   = (unsigned long) &_end;
537 
538 	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
539 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
540 	parse_cmdline(&meminfo, cmdline_p, from);
541 	bootmem_init(&meminfo);
542 	paging_init(&meminfo, mdesc);
543 	request_standard_resources(&meminfo, mdesc);
544 
545 	/*
546 	 * Set up various architecture-specific pointers
547 	 */
548 	init_arch_irq = mdesc->init_irq;
549 
550 #ifdef CONFIG_VT
551 #if defined(CONFIG_VGA_CONSOLE)
552 	conswitchp = &vga_con;
553 #elif defined(CONFIG_DUMMY_CONSOLE)
554 	conswitchp = &dummy_con;
555 #endif
556 #endif
557 }
558 
559 static const char *hwcap_str[] = {
560 	"swp",
561 	"half",
562 	"thumb",
563 	"26bit",
564 	"fastmult",
565 	"fpa",
566 	"vfp",
567 	"edsp",
568 	NULL
569 };
570 
c_show(struct seq_file * m,void * v)571 static int c_show(struct seq_file *m, void *v)
572 {
573 	int i;
574 
575 	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
576 		   cpu_name, (int)processor_id & 15, elf_platform);
577 
578 	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
579 		   loops_per_jiffy / (500000/HZ),
580 		   (loops_per_jiffy / (5000/HZ)) % 100);
581 
582 	/* dump out the processor features */
583 	seq_puts(m, "Features\t: ");
584 
585 	for (i = 0; hwcap_str[i]; i++)
586 		if (elf_hwcap & (1 << i))
587 			seq_printf(m, "%s ", hwcap_str[i]);
588 
589 	seq_puts(m, "\n\n");
590 
591 	seq_printf(m, "Hardware\t: %s\n", machine_name);
592 	seq_printf(m, "Revision\t: %04x\n", system_rev);
593 	seq_printf(m, "Serial\t\t: %08x%08x\n",
594 		   system_serial_high, system_serial_low);
595 
596 	return 0;
597 }
598 
c_start(struct seq_file * m,loff_t * pos)599 static void *c_start(struct seq_file *m, loff_t *pos)
600 {
601 	return *pos < 1 ? (void *)1 : NULL;
602 }
603 
c_next(struct seq_file * m,void * v,loff_t * pos)604 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
605 {
606 	++*pos;
607 	return NULL;
608 }
609 
c_stop(struct seq_file * m,void * v)610 static void c_stop(struct seq_file *m, void *v)
611 {
612 }
613 
614 struct seq_operations cpuinfo_op = {
615 	.start	= c_start,
616 	.next	= c_next,
617 	.stop	= c_stop,
618 	.show	= c_show
619 };
620