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