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