linux/arch/arm/kernel/setup.c
<<
>>
Prefs
   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/module.h>
  12#include <linux/kernel.h>
  13#include <linux/stddef.h>
  14#include <linux/ioport.h>
  15#include <linux/delay.h>
  16#include <linux/utsname.h>
  17#include <linux/initrd.h>
  18#include <linux/console.h>
  19#include <linux/bootmem.h>
  20#include <linux/seq_file.h>
  21#include <linux/tty.h>
  22#include <linux/init.h>
  23#include <linux/root_dev.h>
  24#include <linux/cpu.h>
  25#include <linux/interrupt.h>
  26
  27#include <asm/cpu.h>
  28#include <asm/elf.h>
  29#include <asm/hardware.h>
  30#include <asm/io.h>
  31#include <asm/procinfo.h>
  32#include <asm/setup.h>
  33#include <asm/mach-types.h>
  34#include <asm/cacheflush.h>
  35#include <asm/tlbflush.h>
  36
  37#include <asm/mach/arch.h>
  38#include <asm/mach/irq.h>
  39#include <asm/mach/time.h>
  40
  41#ifndef MEM_SIZE
  42#define MEM_SIZE        (16*1024*1024)
  43#endif
  44
  45#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
  46char fpe_type[8];
  47
  48static int __init fpe_setup(char *line)
  49{
  50        memcpy(fpe_type, line, 8);
  51        return 1;
  52}
  53
  54__setup("fpe=", fpe_setup);
  55#endif
  56
  57extern unsigned int mem_fclk_21285;
  58extern void paging_init(struct meminfo *, struct machine_desc *desc);
  59extern void convert_to_tag_list(struct tag *tags);
  60extern void squash_mem_tags(struct tag *tag);
  61extern void reboot_setup(char *str);
  62extern int root_mountflags;
  63extern void _stext, _text, _etext, __data_start, _edata, _end;
  64
  65unsigned int processor_id;
  66unsigned int __machine_arch_type;
  67EXPORT_SYMBOL(__machine_arch_type);
  68
  69unsigned int system_rev;
  70EXPORT_SYMBOL(system_rev);
  71
  72unsigned int system_serial_low;
  73EXPORT_SYMBOL(system_serial_low);
  74
  75unsigned int system_serial_high;
  76EXPORT_SYMBOL(system_serial_high);
  77
  78unsigned int elf_hwcap;
  79EXPORT_SYMBOL(elf_hwcap);
  80
  81
  82#ifdef MULTI_CPU
  83struct processor processor;
  84#endif
  85#ifdef MULTI_TLB
  86struct cpu_tlb_fns cpu_tlb;
  87#endif
  88#ifdef MULTI_USER
  89struct cpu_user_fns cpu_user;
  90#endif
  91#ifdef MULTI_CACHE
  92struct cpu_cache_fns cpu_cache;
  93#endif
  94
  95unsigned char aux_device_present;
  96
  97char elf_platform[ELF_PLATFORM_SIZE];
  98EXPORT_SYMBOL(elf_platform);
  99
 100unsigned long phys_initrd_start __initdata = 0;
 101unsigned long phys_initrd_size __initdata = 0;
 102
 103static struct meminfo meminfo __initdata = { 0, };
 104static const char *cpu_name;
 105static const char *machine_name;
 106static char command_line[COMMAND_LINE_SIZE];
 107
 108static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 109static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 110#define ENDIANNESS ((char)endian_test.l)
 111
 112DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
 113
 114/*
 115 * Standard memory resources
 116 */
 117static struct resource mem_res[] = {
 118        { "Video RAM",   0,     0,     IORESOURCE_MEM                   },
 119        { "Kernel text", 0,     0,     IORESOURCE_MEM                   },
 120        { "Kernel data", 0,     0,     IORESOURCE_MEM                   }
 121};
 122
 123#define video_ram   mem_res[0]
 124#define kernel_code mem_res[1]
 125#define kernel_data mem_res[2]
 126
 127static struct resource io_res[] = {
 128        { "reserved",    0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY },
 129        { "reserved",    0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY },
 130        { "reserved",    0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }
 131};
 132
 133#define lp0 io_res[0]
 134#define lp1 io_res[1]
 135#define lp2 io_res[2]
 136
 137static const char *cache_types[16] = {
 138        "write-through",
 139        "write-back",
 140        "write-back",
 141        "undefined 3",
 142        "undefined 4",
 143        "undefined 5",
 144        "write-back",
 145        "write-back",
 146        "undefined 8",
 147        "undefined 9",
 148        "undefined 10",
 149        "undefined 11",
 150        "undefined 12",
 151        "undefined 13",
 152        "write-back",
 153        "undefined 15",
 154};
 155
 156static const char *cache_clean[16] = {
 157        "not required",
 158        "read-block",
 159        "cp15 c7 ops",
 160        "undefined 3",
 161        "undefined 4",
 162        "undefined 5",
 163        "cp15 c7 ops",
 164        "cp15 c7 ops",
 165        "undefined 8",
 166        "undefined 9",
 167        "undefined 10",
 168        "undefined 11",
 169        "undefined 12",
 170        "undefined 13",
 171        "cp15 c7 ops",
 172        "undefined 15",
 173};
 174
 175static const char *cache_lockdown[16] = {
 176        "not supported",
 177        "not supported",
 178        "not supported",
 179        "undefined 3",
 180        "undefined 4",
 181        "undefined 5",
 182        "format A",
 183        "format B",
 184        "undefined 8",
 185        "undefined 9",
 186        "undefined 10",
 187        "undefined 11",
 188        "undefined 12",
 189        "undefined 13",
 190        "format C",
 191        "undefined 15",
 192};
 193
 194static const char *proc_arch[] = {
 195        "undefined/unknown",
 196        "3",
 197        "4",
 198        "4T",
 199        "5",
 200        "5T",
 201        "5TE",
 202        "5TEJ",
 203        "6TEJ",
 204        "?(10)",
 205        "?(11)",
 206        "?(12)",
 207        "?(13)",
 208        "?(14)",
 209        "?(15)",
 210        "?(16)",
 211        "?(17)",
 212};
 213
 214#define CACHE_TYPE(x)   (((x) >> 25) & 15)
 215#define CACHE_S(x)      ((x) & (1 << 24))
 216#define CACHE_DSIZE(x)  (((x) >> 12) & 4095)    /* only if S=1 */
 217#define CACHE_ISIZE(x)  ((x) & 4095)
 218
 219#define CACHE_SIZE(y)   (((y) >> 6) & 7)
 220#define CACHE_ASSOC(y)  (((y) >> 3) & 7)
 221#define CACHE_M(y)      ((y) & (1 << 2))
 222#define CACHE_LINE(y)   ((y) & 3)
 223
 224static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
 225{
 226        unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
 227
 228        printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n",
 229                cpu, prefix,
 230                mult << (8 + CACHE_SIZE(cache)),
 231                (mult << CACHE_ASSOC(cache)) >> 1,
 232                8 << CACHE_LINE(cache),
 233                1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
 234                        CACHE_LINE(cache)));
 235}
 236
 237static void __init dump_cpu_info(int cpu)
 238{
 239        unsigned int info = read_cpuid(CPUID_CACHETYPE);
 240
 241        if (info != processor_id) {
 242                printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
 243                       cache_types[CACHE_TYPE(info)]);
 244                if (CACHE_S(info)) {
 245                        dump_cache("I cache", cpu, CACHE_ISIZE(info));
 246                        dump_cache("D cache", cpu, CACHE_DSIZE(info));
 247                } else {
 248                        dump_cache("cache", cpu, CACHE_ISIZE(info));
 249                }
 250        }
 251}
 252
 253int cpu_architecture(void)
 254{
 255        int cpu_arch;
 256
 257        if ((processor_id & 0x0000f000) == 0) {
 258                cpu_arch = CPU_ARCH_UNKNOWN;
 259        } else if ((processor_id & 0x0000f000) == 0x00007000) {
 260                cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
 261        } else {
 262                cpu_arch = (processor_id >> 16) & 7;
 263                if (cpu_arch)
 264                        cpu_arch += CPU_ARCH_ARMv3;
 265        }
 266
 267        return cpu_arch;
 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(void);
 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();
 287        if (!list) {
 288                printk("CPU configuration botched (ID %08x), unable "
 289                       "to continue.\n", processor_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)\n",
 309               cpu_name, processor_id, (int)processor_id & 15,
 310               proc_arch[cpu_architecture()]);
 311
 312        dump_cpu_info(smp_processor_id());
 313
 314        sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
 315        sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
 316        elf_hwcap = list->elf_hwcap;
 317
 318        cpu_proc_init();
 319}
 320
 321static struct machine_desc * __init setup_machine(unsigned int nr)
 322{
 323        struct machine_desc *list;
 324
 325        /*
 326         * locate machine in the list of supported machines.
 327         */
 328        list = lookup_machine_type(nr);
 329        if (!list) {
 330                printk("Machine configuration botched (nr %d), unable "
 331                       "to continue.\n", nr);
 332                while (1);
 333        }
 334
 335        printk("Machine: %s\n", list->name);
 336
 337        return list;
 338}
 339
 340static void __init early_initrd(char **p)
 341{
 342        unsigned long start, size;
 343
 344        start = memparse(*p, p);
 345        if (**p == ',') {
 346                size = memparse((*p) + 1, p);
 347
 348                phys_initrd_start = start;
 349                phys_initrd_size = size;
 350        }
 351}
 352__early_param("initrd=", early_initrd);
 353
 354/*
 355 * Pick out the memory size.  We look for mem=size@start,
 356 * where start and size are "size[KkMm]"
 357 */
 358static void __init early_mem(char **p)
 359{
 360        static int usermem __initdata = 0;
 361        unsigned long size, start;
 362
 363        /*
 364         * If the user specifies memory size, we
 365         * blow away any automatically generated
 366         * size.
 367         */
 368        if (usermem == 0) {
 369                usermem = 1;
 370                meminfo.nr_banks = 0;
 371        }
 372
 373        start = PHYS_OFFSET;
 374        size  = memparse(*p, p);
 375        if (**p == '@')
 376                start = memparse(*p + 1, p);
 377
 378        meminfo.bank[meminfo.nr_banks].start = start;
 379        meminfo.bank[meminfo.nr_banks].size  = size;
 380        meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(start);
 381        meminfo.nr_banks += 1;
 382}
 383__early_param("mem=", early_mem);
 384
 385/*
 386 * Initial parsing of the command line.
 387 */
 388static void __init parse_cmdline(char **cmdline_p, char *from)
 389{
 390        char c = ' ', *to = command_line;
 391        int len = 0;
 392
 393        for (;;) {
 394                if (c == ' ') {
 395                        extern struct early_params __early_begin, __early_end;
 396                        struct early_params *p;
 397
 398                        for (p = &__early_begin; p < &__early_end; p++) {
 399                                int len = strlen(p->arg);
 400
 401                                if (memcmp(from, p->arg, len) == 0) {
 402                                        if (to != command_line)
 403                                                to -= 1;
 404                                        from += len;
 405                                        p->fn(&from);
 406
 407                                        while (*from != ' ' && *from != '\0')
 408                                                from++;
 409                                        break;
 410                                }
 411                        }
 412                }
 413                c = *from++;
 414                if (!c)
 415                        break;
 416                if (COMMAND_LINE_SIZE <= ++len)
 417                        break;
 418                *to++ = c;
 419        }
 420        *to = '\0';
 421        *cmdline_p = command_line;
 422}
 423
 424static void __init
 425setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
 426{
 427#ifdef CONFIG_BLK_DEV_RAM
 428        extern int rd_size, rd_image_start, rd_prompt, rd_doload;
 429
 430        rd_image_start = image_start;
 431        rd_prompt = prompt;
 432        rd_doload = doload;
 433
 434        if (rd_sz)
 435                rd_size = rd_sz;
 436#endif
 437}
 438
 439static void __init
 440request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
 441{
 442        struct resource *res;
 443        int i;
 444
 445        kernel_code.start   = virt_to_phys(&_text);
 446        kernel_code.end     = virt_to_phys(&_etext - 1);
 447        kernel_data.start   = virt_to_phys(&__data_start);
 448        kernel_data.end     = virt_to_phys(&_end - 1);
 449
 450        for (i = 0; i < mi->nr_banks; i++) {
 451                unsigned long virt_start, virt_end;
 452
 453                if (mi->bank[i].size == 0)
 454                        continue;
 455
 456                virt_start = __phys_to_virt(mi->bank[i].start);
 457                virt_end   = virt_start + mi->bank[i].size - 1;
 458
 459                res = alloc_bootmem_low(sizeof(*res));
 460                res->name  = "System RAM";
 461                res->start = __virt_to_phys(virt_start);
 462                res->end   = __virt_to_phys(virt_end);
 463                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 464
 465                request_resource(&iomem_resource, res);
 466
 467                if (kernel_code.start >= res->start &&
 468                    kernel_code.end <= res->end)
 469                        request_resource(res, &kernel_code);
 470                if (kernel_data.start >= res->start &&
 471                    kernel_data.end <= res->end)
 472                        request_resource(res, &kernel_data);
 473        }
 474
 475        if (mdesc->video_start) {
 476                video_ram.start = mdesc->video_start;
 477                video_ram.end   = mdesc->video_end;
 478                request_resource(&iomem_resource, &video_ram);
 479        }
 480
 481        /*
 482         * Some machines don't have the possibility of ever
 483         * possessing lp0, lp1 or lp2
 484         */
 485        if (mdesc->reserve_lp0)
 486                request_resource(&ioport_resource, &lp0);
 487        if (mdesc->reserve_lp1)
 488                request_resource(&ioport_resource, &lp1);
 489        if (mdesc->reserve_lp2)
 490                request_resource(&ioport_resource, &lp2);
 491}
 492
 493/*
 494 *  Tag parsing.
 495 *
 496 * This is the new way of passing data to the kernel at boot time.  Rather
 497 * than passing a fixed inflexible structure to the kernel, we pass a list
 498 * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
 499 * tag for the list to be recognised (to distinguish the tagged list from
 500 * a param_struct).  The list is terminated with a zero-length tag (this tag
 501 * is not parsed in any way).
 502 */
 503static int __init parse_tag_core(const struct tag *tag)
 504{
 505        if (tag->hdr.size > 2) {
 506                if ((tag->u.core.flags & 1) == 0)
 507                        root_mountflags &= ~MS_RDONLY;
 508                ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
 509        }
 510        return 0;
 511}
 512
 513__tagtable(ATAG_CORE, parse_tag_core);
 514
 515static int __init parse_tag_mem32(const struct tag *tag)
 516{
 517        if (meminfo.nr_banks >= NR_BANKS) {
 518                printk(KERN_WARNING
 519                       "Ignoring memory bank 0x%08x size %dKB\n",
 520                        tag->u.mem.start, tag->u.mem.size / 1024);
 521                return -EINVAL;
 522        }
 523        meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
 524        meminfo.bank[meminfo.nr_banks].size  = tag->u.mem.size;
 525        meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(tag->u.mem.start);
 526        meminfo.nr_banks += 1;
 527
 528        return 0;
 529}
 530
 531__tagtable(ATAG_MEM, parse_tag_mem32);
 532
 533#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 534struct screen_info screen_info = {
 535 .orig_video_lines      = 30,
 536 .orig_video_cols       = 80,
 537 .orig_video_mode       = 0,
 538 .orig_video_ega_bx     = 0,
 539 .orig_video_isVGA      = 1,
 540 .orig_video_points     = 8
 541};
 542
 543static int __init parse_tag_videotext(const struct tag *tag)
 544{
 545        screen_info.orig_x            = tag->u.videotext.x;
 546        screen_info.orig_y            = tag->u.videotext.y;
 547        screen_info.orig_video_page   = tag->u.videotext.video_page;
 548        screen_info.orig_video_mode   = tag->u.videotext.video_mode;
 549        screen_info.orig_video_cols   = tag->u.videotext.video_cols;
 550        screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
 551        screen_info.orig_video_lines  = tag->u.videotext.video_lines;
 552        screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
 553        screen_info.orig_video_points = tag->u.videotext.video_points;
 554        return 0;
 555}
 556
 557__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
 558#endif
 559
 560static int __init parse_tag_ramdisk(const struct tag *tag)
 561{
 562        setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
 563                      (tag->u.ramdisk.flags & 2) == 0,
 564                      tag->u.ramdisk.start, tag->u.ramdisk.size);
 565        return 0;
 566}
 567
 568__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
 569
 570static int __init parse_tag_initrd(const struct tag *tag)
 571{
 572        printk(KERN_WARNING "ATAG_INITRD is deprecated; "
 573                "please update your bootloader.\n");
 574        phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
 575        phys_initrd_size = tag->u.initrd.size;
 576        return 0;
 577}
 578
 579__tagtable(ATAG_INITRD, parse_tag_initrd);
 580
 581static int __init parse_tag_initrd2(const struct tag *tag)
 582{
 583        phys_initrd_start = tag->u.initrd.start;
 584        phys_initrd_size = tag->u.initrd.size;
 585        return 0;
 586}
 587
 588__tagtable(ATAG_INITRD2, parse_tag_initrd2);
 589
 590static int __init parse_tag_serialnr(const struct tag *tag)
 591{
 592        system_serial_low = tag->u.serialnr.low;
 593        system_serial_high = tag->u.serialnr.high;
 594        return 0;
 595}
 596
 597__tagtable(ATAG_SERIAL, parse_tag_serialnr);
 598
 599static int __init parse_tag_revision(const struct tag *tag)
 600{
 601        system_rev = tag->u.revision.rev;
 602        return 0;
 603}
 604
 605__tagtable(ATAG_REVISION, parse_tag_revision);
 606
 607static int __init parse_tag_cmdline(const struct tag *tag)
 608{
 609        strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
 610        return 0;
 611}
 612
 613__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
 614
 615/*
 616 * Scan the tag table for this tag, and call its parse function.
 617 * The tag table is built by the linker from all the __tagtable
 618 * declarations.
 619 */
 620static int __init parse_tag(const struct tag *tag)
 621{
 622        extern struct tagtable __tagtable_begin, __tagtable_end;
 623        struct tagtable *t;
 624
 625        for (t = &__tagtable_begin; t < &__tagtable_end; t++)
 626                if (tag->hdr.tag == t->tag) {
 627                        t->parse(tag);
 628                        break;
 629                }
 630
 631        return t < &__tagtable_end;
 632}
 633
 634/*
 635 * Parse all tags in the list, checking both the global and architecture
 636 * specific tag tables.
 637 */
 638static void __init parse_tags(const struct tag *t)
 639{
 640        for (; t->hdr.size; t = tag_next(t))
 641                if (!parse_tag(t))
 642                        printk(KERN_WARNING
 643                                "Ignoring unrecognised tag 0x%08x\n",
 644                                t->hdr.tag);
 645}
 646
 647/*
 648 * This holds our defaults.
 649 */
 650static struct init_tags {
 651        struct tag_header hdr1;
 652        struct tag_core   core;
 653        struct tag_header hdr2;
 654        struct tag_mem32  mem;
 655        struct tag_header hdr3;
 656} init_tags __initdata = {
 657        { tag_size(tag_core), ATAG_CORE },
 658        { 1, PAGE_SIZE, 0xff },
 659        { tag_size(tag_mem32), ATAG_MEM },
 660        { MEM_SIZE, PHYS_OFFSET },
 661        { 0, ATAG_NONE }
 662};
 663
 664static void (*init_machine)(void) __initdata;
 665
 666static int __init customize_machine(void)
 667{
 668        /* customizes platform devices, or adds new ones */
 669        if (init_machine)
 670                init_machine();
 671        return 0;
 672}
 673arch_initcall(customize_machine);
 674
 675void __init setup_arch(char **cmdline_p)
 676{
 677        struct tag *tags = (struct tag *)&init_tags;
 678        struct machine_desc *mdesc;
 679        char *from = default_command_line;
 680
 681        setup_processor();
 682        mdesc = setup_machine(machine_arch_type);
 683        machine_name = mdesc->name;
 684
 685        if (mdesc->soft_reboot)
 686                reboot_setup("s");
 687
 688        if (mdesc->param_offset)
 689                tags = phys_to_virt(mdesc->param_offset);
 690
 691        /*
 692         * If we have the old style parameters, convert them to
 693         * a tag list.
 694         */
 695        if (tags->hdr.tag != ATAG_CORE)
 696                convert_to_tag_list(tags);
 697        if (tags->hdr.tag != ATAG_CORE)
 698                tags = (struct tag *)&init_tags;
 699
 700        if (mdesc->fixup)
 701                mdesc->fixup(mdesc, tags, &from, &meminfo);
 702
 703        if (tags->hdr.tag == ATAG_CORE) {
 704                if (meminfo.nr_banks != 0)
 705                        squash_mem_tags(tags);
 706                parse_tags(tags);
 707        }
 708
 709        init_mm.start_code = (unsigned long) &_text;
 710        init_mm.end_code   = (unsigned long) &_etext;
 711        init_mm.end_data   = (unsigned long) &_edata;
 712        init_mm.brk        = (unsigned long) &_end;
 713
 714        memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
 715        saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 716        parse_cmdline(cmdline_p, from);
 717        paging_init(&meminfo, mdesc);
 718        request_standard_resources(&meminfo, mdesc);
 719
 720        /*
 721         * Set up various architecture-specific pointers
 722         */
 723        init_arch_irq = mdesc->init_irq;
 724        system_timer = mdesc->timer;
 725        init_machine = mdesc->init_machine;
 726
 727#ifdef CONFIG_VT
 728#if defined(CONFIG_VGA_CONSOLE)
 729        conswitchp = &vga_con;
 730#elif defined(CONFIG_DUMMY_CONSOLE)
 731        conswitchp = &dummy_con;
 732#endif
 733#endif
 734}
 735
 736
 737static int __init topology_init(void)
 738{
 739        int cpu;
 740
 741        for_each_cpu(cpu)
 742                register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
 743
 744        return 0;
 745}
 746
 747subsys_initcall(topology_init);
 748
 749static const char *hwcap_str[] = {
 750        "swp",
 751        "half",
 752        "thumb",
 753        "26bit",
 754        "fastmult",
 755        "fpa",
 756        "vfp",
 757        "edsp",
 758        "java",
 759        NULL
 760};
 761
 762static void
 763c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
 764{
 765        unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
 766
 767        seq_printf(m, "%s size\t\t: %d\n"
 768                      "%s assoc\t\t: %d\n"
 769                      "%s line length\t: %d\n"
 770                      "%s sets\t\t: %d\n",
 771                type, mult << (8 + CACHE_SIZE(cache)),
 772                type, (mult << CACHE_ASSOC(cache)) >> 1,
 773                type, 8 << CACHE_LINE(cache),
 774                type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
 775                            CACHE_LINE(cache)));
 776}
 777
 778static int c_show(struct seq_file *m, void *v)
 779{
 780        int i;
 781
 782        seq_printf(m, "Processor\t: %s rev %d (%s)\n",
 783                   cpu_name, (int)processor_id & 15, elf_platform);
 784
 785#if defined(CONFIG_SMP)
 786        for_each_online_cpu(i) {
 787                seq_printf(m, "Processor\t: %d\n", i);
 788                seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
 789                           per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
 790                           (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
 791        }
 792#else /* CONFIG_SMP */
 793        seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 794                   loops_per_jiffy / (500000/HZ),
 795                   (loops_per_jiffy / (5000/HZ)) % 100);
 796#endif
 797
 798        /* dump out the processor features */
 799        seq_puts(m, "Features\t: ");
 800
 801        for (i = 0; hwcap_str[i]; i++)
 802                if (elf_hwcap & (1 << i))
 803                        seq_printf(m, "%s ", hwcap_str[i]);
 804
 805        seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
 806        seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
 807
 808        if ((processor_id & 0x0000f000) == 0x00000000) {
 809                /* pre-ARM7 */
 810                seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
 811        } else {
 812                if ((processor_id & 0x0000f000) == 0x00007000) {
 813                        /* ARM7 */
 814                        seq_printf(m, "CPU variant\t: 0x%02x\n",
 815                                   (processor_id >> 16) & 127);
 816                } else {
 817                        /* post-ARM7 */
 818                        seq_printf(m, "CPU variant\t: 0x%x\n",
 819                                   (processor_id >> 20) & 15);
 820                }
 821                seq_printf(m, "CPU part\t: 0x%03x\n",
 822                           (processor_id >> 4) & 0xfff);
 823        }
 824        seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
 825
 826        {
 827                unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
 828                if (cache_info != processor_id) {
 829                        seq_printf(m, "Cache type\t: %s\n"
 830                                      "Cache clean\t: %s\n"
 831                                      "Cache lockdown\t: %s\n"
 832                                      "Cache format\t: %s\n",
 833                                   cache_types[CACHE_TYPE(cache_info)],
 834                                   cache_clean[CACHE_TYPE(cache_info)],
 835                                   cache_lockdown[CACHE_TYPE(cache_info)],
 836                                   CACHE_S(cache_info) ? "Harvard" : "Unified");
 837
 838                        if (CACHE_S(cache_info)) {
 839                                c_show_cache(m, "I", CACHE_ISIZE(cache_info));
 840                                c_show_cache(m, "D", CACHE_DSIZE(cache_info));
 841                        } else {
 842                                c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
 843                        }
 844                }
 845        }
 846
 847        seq_puts(m, "\n");
 848
 849        seq_printf(m, "Hardware\t: %s\n", machine_name);
 850        seq_printf(m, "Revision\t: %04x\n", system_rev);
 851        seq_printf(m, "Serial\t\t: %08x%08x\n",
 852                   system_serial_high, system_serial_low);
 853
 854        return 0;
 855}
 856
 857static void *c_start(struct seq_file *m, loff_t *pos)
 858{
 859        return *pos < 1 ? (void *)1 : NULL;
 860}
 861
 862static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 863{
 864        ++*pos;
 865        return NULL;
 866}
 867
 868static void c_stop(struct seq_file *m, void *v)
 869{
 870}
 871
 872struct seq_operations cpuinfo_op = {
 873        .start  = c_start,
 874        .next   = c_next,
 875        .stop   = c_stop,
 876        .show   = c_show
 877};
 878
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.